Merging from head
[beagle.git] / beagled / TomboyQueryable / TomboyQueryable.cs
blobc77144c247917e177a48b4ef592bda014230c940
1 //
2 // TomboyQueryable.cs
3 //
4 // Copyright (C) 2004 Christopher Orr
5 // Copyright (C) 2004-2006 Novell, Inc.
6 //
8 //
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.
28 using System;
29 using System.Collections;
30 using System.IO;
31 using System.Threading;
33 using Beagle.Daemon;
34 using Beagle.Util;
36 namespace Beagle.Daemon.TomboyQueryable {
38 [QueryableFlavor (Name="Tomboy", Domain=QueryDomain.Local, RequireInotify=false)]
39 public class TomboyQueryable : LuceneFileQueryable, IIndexableGenerator {
41 string tomboy_dir;
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 ()
51 base.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));
60 return;
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);
69 } else {
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
82 Scheduler.Task task;
83 task = NewAddTask (this);
84 task.Tag = "Crawling Tomboy Notes";
85 task.Source = this;
87 ThisScheduler.Add (task);
89 Logger.Log.Info ("Tomboy backend started");
92 private bool CheckForExistence ()
94 if (!Directory.Exists (tomboy_dir))
95 return true;
97 this.Start ();
99 return false;
102 /////////////////////////////////////////////////
104 // Modified/Created/Deleted event using Inotify
105 private void OnInotifyEvent (Inotify.Watch watch,
106 string path,
107 string subitem,
108 string srcpath,
109 Inotify.EventType type)
111 if (subitem == "")
112 return;
114 if (Path.GetExtension (subitem) != ".note")
115 return;
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);
161 return indexable;
164 private void IndexNote (FileInfo file, Scheduler.Priority priority)
166 if (this.IsUpToDate (file.FullName))
167 return;
169 // Try and parse a Note from the given path
170 Note note = TomboyNote.ParseNote (file);
171 if (note == null)
172 return;
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.
200 string text;
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))
213 return true;
215 return false;
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;
239 if (! file.Exists)
240 return null;
242 if (IsUpToDate (file.FullName))
243 return null;
245 Note note = TomboyNote.ParseNote (file);
247 if (note == null)
248 return null;
250 Indexable indexable = NoteToIndexable (file, note);
252 return indexable;