4 // Copyright (C) 2004 Christopher Orr
5 // Copyright (C) 2004-2006 Novell, Inc.
9 // Permission is hereby granted, free of charge, to any person obtaining a
10 // copy of this software and associated documentation files (the "Software"),
11 // to deal in the Software without restriction, including without limitation
12 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 // and/or sell copies of the Software, and to permit persons to whom the
14 // Software is furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 // DEALINGS IN THE SOFTWARE.
29 using System
.Collections
;
31 using System
.Threading
;
36 namespace Beagle
.Daemon
.TomboyQueryable
{
38 [QueryableFlavor (Name
="Tomboy", Domain
=QueryDomain
.Local
, RequireInotify
=false)]
39 public class TomboyQueryable
: LuceneFileQueryable
, IIndexableGenerator
{
42 Hashtable note_text_cache
= UriFu
.NewHashtable ();
44 public TomboyQueryable () : base ("TomboyIndex")
46 tomboy_dir
= Path
.Combine (PathFinder
.HomeDir
, ".tomboy");
49 public override void Start ()
53 ExceptionHandlingThread
.Start (new ThreadStart (StartWorker
));
56 private void StartWorker ()
58 if (!Directory
.Exists (tomboy_dir
) ) {
59 GLib
.Timeout
.Add (60000, new GLib
.TimeoutHandler (CheckForExistence
));
63 if (Inotify
.Enabled
) {
64 Inotify
.EventType mask
= Inotify
.EventType
.Delete
|
65 Inotify
.EventType
.MovedTo
|
66 Inotify
.EventType
.MovedFrom
;
68 Inotify
.Subscribe (tomboy_dir
, OnInotifyEvent
, mask
);
70 FileSystemWatcher fsw
= new FileSystemWatcher ();
71 fsw
.Path
= tomboy_dir
;
72 fsw
.Filter
= "*.note";
74 fsw
.Changed
+= new FileSystemEventHandler (OnChanged
);
75 fsw
.Created
+= new FileSystemEventHandler (OnChanged
);
76 fsw
.Deleted
+= new FileSystemEventHandler (OnDeleted
);
78 fsw
.EnableRaisingEvents
= true;
81 // Start our crawler process
83 task
= NewAddTask (this);
84 task
.Tag
= "Crawling Tomboy Notes";
87 ThisScheduler
.Add (task
);
89 Logger
.Log
.Info ("Tomboy backend started");
92 private bool CheckForExistence ()
94 if (!Directory
.Exists (tomboy_dir
))
102 /////////////////////////////////////////////////
104 // Modified/Created/Deleted event using Inotify
105 private void OnInotifyEvent (Inotify
.Watch watch
,
109 Inotify
.EventType type
)
114 if (Path
.GetExtension (subitem
) != ".note")
117 if ((type
& Inotify
.EventType
.MovedTo
) != 0) {
118 IndexNote (new FileInfo (Path
.Combine (path
, subitem
)), Scheduler
.Priority
.Immediate
);
121 if ((type
& Inotify
.EventType
.MovedFrom
) != 0 ||
122 ((type
& Inotify
.EventType
.Delete
) != 0 &&
123 (type
& Inotify
.EventType
.IsDirectory
) == 0))
124 RemoveNote (subitem
);
127 // Modified/Created event using FSW
128 private void OnChanged (object o
, FileSystemEventArgs args
)
130 IndexNote (new FileInfo (args
.FullPath
), Scheduler
.Priority
.Immediate
);
133 // Deleted event using FSW
134 private void OnDeleted (object o
, FileSystemEventArgs args
)
136 RemoveNote (args
.FullPath
);
139 /////////////////////////////////////////////////
141 private Indexable
NoteToIndexable (FileInfo file
, Note note
)
143 Indexable indexable
= new Indexable (note
.Uri
);
145 indexable
.ContentUri
= UriFu
.PathToFileUri (file
.FullName
);
147 indexable
.Timestamp
= note
.timestamp
;
148 indexable
.HitType
= "Note";
149 indexable
.Filtering
= IndexableFiltering
.AlreadyFiltered
;
151 indexable
.AddProperty (Property
.New ("dc:title", note
.subject
));
152 indexable
.AddProperty (Property
.NewUnsearched ("fixme:application","tomboy"));
154 // We remember the note's text so that we can stuff it in
155 // the TextCache later.
156 note_text_cache
[note
.Uri
] = note
.text
;
158 StringReader reader
= new StringReader (note
.text
);
159 indexable
.SetTextReader (reader
);
164 private void IndexNote (FileInfo file
, Scheduler
.Priority priority
)
166 if (this.IsUpToDate (file
.FullName
))
169 // Try and parse a Note from the given path
170 Note note
= TomboyNote
.ParseNote (file
);
174 // A Note was returned; add it to the index
175 Indexable indexable
= NoteToIndexable (file
, note
);
177 Scheduler
.Task task
= NewAddTask (indexable
);
178 task
.Priority
= priority
;
179 task
.SubPriority
= 0;
180 ThisScheduler
.Add (task
);
183 private void RemoveNote (string file
)
185 Uri uri
= Note
.BuildNoteUri (file
, "tomboy");
186 Scheduler
.Task task
= NewRemoveTask (uri
);
187 task
.Priority
= Scheduler
.Priority
.Immediate
;
188 task
.SubPriority
= 0;
189 ThisScheduler
.Add (task
);
192 override protected void PostAddHook (Indexable indexable
, IndexerAddedReceipt receipt
)
194 base.PostAddHook (indexable
, receipt
);
196 // Store the note's text in the text cache.
197 // By doing this in the PostAddHook, we ensure that
198 // the TextCache is not modified until we are
199 // sure that the note was actually indexed.
201 text
= (string) note_text_cache
[receipt
.Uri
];
202 // If text == null, this is equivalent to
203 // calling Delete (receipt.Uri)
204 TextCache
.UserCache
.WriteFromString (receipt
.Uri
, text
);
205 note_text_cache
.Remove (receipt
.Uri
);
208 override protected bool HitIsValid (Uri uri
)
210 string note
= Path
.Combine (tomboy_dir
, uri
.Segments
[1] + ".note");
212 if (File
.Exists (note
))
218 // IIndexableGenerator implementation
219 public string StatusName
{
220 get { return "TomboyQueryable"; }
223 private IEnumerator note_files
= null;
225 public void PostFlushHook () { }
227 public bool HasNextIndexable ()
229 if (note_files
== null)
230 note_files
= DirectoryWalker
.GetFileInfos (tomboy_dir
).GetEnumerator ();
232 return note_files
.MoveNext ();
235 public Indexable
GetNextIndexable ()
237 FileInfo file
= (FileInfo
) note_files
.Current
;
242 if (IsUpToDate (file
.FullName
))
245 Note note
= TomboyNote
.ParseNote (file
);
250 Indexable indexable
= NoteToIndexable (file
, note
);