2 // LuceneFileQueryable.cs
4 // Copyright (C) 2005 Novell, Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
28 // This queryable just takes the LuceneQueryable and adds some sane
29 // default behavior for indexing files.
33 using System
.Collections
;
38 namespace Beagle
.Daemon
{
40 public abstract class LuceneFileQueryable
: LuceneQueryable
{
42 public LuceneFileQueryable (string index_name
, int minor_version
, bool disable_locking
) :
43 base (index_name
, minor_version
, disable_locking
)
46 public LuceneFileQueryable (string index_name
) : this (index_name
, -1, false) { }
48 public LuceneFileQueryable (string index_name
, bool disable_locking
) : this (index_name
, -1, disable_locking
) { }
50 public LuceneFileQueryable (string index_name
, int minor_version
) : this (index_name
, minor_version
, false) { }
52 ///////////////////////////////////////////////////////////////////////////
54 private Hashtable file_references_count
= new Hashtable ();
56 private void IncrementReferenceCount (string path
)
58 if (! file_references_count
.Contains (path
)) {
59 file_references_count
[path
] = 1;
63 file_references_count
[path
] = (int) file_references_count
[path
] + 1;
67 // true : reference left
68 // false: no more reference left
69 private bool DecrementReferenceCount (string path
)
71 if (! file_references_count
.Contains (path
))
72 throw new Exception ("Shared file is not referenced: " + path
);
74 int reference_count
= (int) file_references_count
[path
] - 1;
76 if (reference_count
== 0) {
77 file_references_count
.Remove (path
);
81 file_references_count
[path
] = reference_count
;
85 ///////////////////////////////////////////////////////////////////////////
87 private class CachedFileInfo
{
90 public DateTime Mtime
;
91 public bool Shared
= false;
94 private Hashtable file_info_cache
= UriFu
.NewHashtable ();
96 override protected bool PreAddIndexableHook (Indexable indexable
)
98 // None of this applies for Removes
99 if (indexable
.Type
== IndexableType
.Remove
)
102 CachedFileInfo info
= (CachedFileInfo
) file_info_cache
[indexable
.Uri
];
105 info
= new CachedFileInfo ();
107 info
.Uri
= indexable
.Uri
;
109 if (indexable
.Uri
.IsFile
&& indexable
.IsNonTransient
)
110 info
.Path
= indexable
.Uri
.LocalPath
;
111 else if (indexable
.ContentUri
.IsFile
&& indexable
.IsNonTransient
)
112 info
.Path
= indexable
.ContentUri
.LocalPath
;
113 else if (indexable
.ParentUri
!= null && indexable
.ParentUri
.IsFile
) {
114 info
.Path
= indexable
.ParentUri
.LocalPath
;
116 IncrementReferenceCount (info
.Path
);
119 // The path could be null in certain cases:
120 // * The indexable is a non-file URI and no
121 // parent URI is set.
122 // * The indexable is a child indexable and the
123 // parent URI is not a file URI.
124 if (info
.Path
== null)
128 info
.Mtime
= FileSystem
.GetLastWriteTimeUtc (info
.Path
);
129 } catch (FileNotFoundException ex
) {
130 // If we can't get an mtime for the file, it must
131 // have disappeared out from under us. In that case,
132 // don't bother adding anything.
136 file_info_cache
[info
.Uri
] = info
;
141 override protected void PostAddHook (Indexable indexable
, IndexerAddedReceipt receipt
)
143 // Retrieve our cached info about the file.
145 info
= file_info_cache
[receipt
.Uri
] as CachedFileInfo
;
149 // Yeah, this is ghetto. If it's a file that's shared across multiple
150 // indexables, only tag it with when the last indexable has been indexed.
151 if (info
.Shared
&& DecrementReferenceCount (info
.Path
))
154 // Since we know that the file has been successfully
155 // indexed, update the file attributes accordingly.
156 // Don't set filter information on a file if multiple
157 // indexables has been created from it.
159 attr
= FileAttributesStore
.ReadOrCreate (info
.Path
);
161 attr
.LastWriteTime
= info
.Mtime
;
163 // Don't set filter information on a file if multiple indexables has been
166 attr
.FilterName
= receipt
.FilterName
;
167 attr
.FilterVersion
= receipt
.FilterVersion
;
170 if (! FileAttributesStore
.Write (attr
))
171 Logger
.Log
.Warn ("Couldn't write attributes for {0}", info
.Path
);
173 file_info_cache
.Remove (info
.Uri
);
176 override protected void PostRemoveHook (Indexable indexable
, IndexerRemovedReceipt receipt
)
178 file_info_cache
.Remove (indexable
.Uri
);
181 override protected bool HitIsValid (Uri uri
)
183 // Do the right thing if the Uri is a file.
184 // If the file Uri we need is the ContentUri, this won't work.
189 return FileSystem
.Exists (uri
.LocalPath
);
190 } catch (Exception e
) {
191 Logger
.Log
.Warn ("Exception executing HitIsValid on {0}", uri
.LocalPath
);
196 ///////////////////////////////////////////////////////////////////////////
198 // Convenience functions
200 public bool IsUpToDate (string path
, Filter filter
)
202 return FileAttributesStore
.IsUpToDate (path
, filter
);
205 public bool IsUpToDate (string path
)
207 return FileAttributesStore
.IsUpToDate (path
);