4 // Copyright (C) 2004 Christopher Orr
5 // Copyright (C) 2004 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
{
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 // Crawl all of our existing notes to make sure that
82 // everything is up-to-date.
83 Logger
.Log
.Info ("Scanning Tomboy notes...");
85 Stopwatch stopwatch
= new Stopwatch ();
88 DirectoryInfo dir
= new DirectoryInfo (tomboy_dir
);
90 foreach (FileInfo file
in dir
.GetFiles ()) {
91 if (file
.Extension
== ".note") {
92 IndexNote (file
, Scheduler
.Priority
.Delayed
);
98 Logger
.Log
.Info ("Scanned {0} notes in {1}", count
, stopwatch
);
101 private bool CheckForExistence ()
103 if (!Directory
.Exists (tomboy_dir
))
111 /////////////////////////////////////////////////
113 // Modified/Created/Deleted event using Inotify
114 private void OnInotifyEvent (Inotify
.Watch watch
,
118 Inotify
.EventType type
)
123 if (Path
.GetExtension (subitem
) != ".note")
126 if ((type
& Inotify
.EventType
.MovedTo
) != 0) {
127 IndexNote (new FileInfo (Path
.Combine (path
, subitem
)), Scheduler
.Priority
.Immediate
);
130 if ((type
& Inotify
.EventType
.MovedFrom
) != 0 ||
131 ((type
& Inotify
.EventType
.Delete
) != 0 &&
132 (type
& Inotify
.EventType
.IsDirectory
) == 0))
133 RemoveNote (subitem
);
136 // Modified/Created event using FSW
137 private void OnChanged (object o
, FileSystemEventArgs args
)
139 IndexNote (new FileInfo (args
.FullPath
), Scheduler
.Priority
.Immediate
);
142 // Deleted event using FSW
143 private void OnDeleted (object o
, FileSystemEventArgs args
)
145 RemoveNote (args
.FullPath
);
148 /////////////////////////////////////////////////
150 private Indexable
NoteToIndexable (FileInfo file
, Note note
)
152 Indexable indexable
= new Indexable (note
.Uri
);
154 indexable
.ContentUri
= UriFu
.PathToFileUri (file
.FullName
);
156 indexable
.Timestamp
= note
.timestamp
;
157 indexable
.Type
= "Note";
158 indexable
.Filtering
= IndexableFiltering
.AlreadyFiltered
;
160 indexable
.AddProperty (Property
.New ("dc:title", note
.subject
));
162 // We remember the note's text so that we can stuff it in
163 // the TextCache later.
164 note_text_cache
[note
.Uri
] = note
.text
;
166 StringReader reader
= new StringReader (note
.text
);
167 indexable
.SetTextReader (reader
);
172 private void IndexNote (FileInfo file
, Scheduler
.Priority priority
)
174 if (this.IsUpToDate (file
.FullName
))
177 // Try and parse a Note from the given path
178 Note note
= TomboyNote
.ParseNote (file
);
182 // A Note was returned; add it to the index
183 Indexable indexable
= NoteToIndexable (file
, note
);
185 Scheduler
.Task task
= NewAddTask (indexable
);
186 task
.Priority
= priority
;
187 task
.SubPriority
= 0;
188 ThisScheduler
.Add (task
);
192 private void RemoveNote (string file
)
194 Uri uri
= Note
.BuildNoteUri (file
, "tomboy");
195 Scheduler
.Task task
= NewRemoveTask (uri
);
196 task
.Priority
= Scheduler
.Priority
.Immediate
;
197 task
.SubPriority
= 0;
198 ThisScheduler
.Add (task
);
201 override protected void PostAddHook (IndexerAddedReceipt receipt
)
203 base.PostAddHook (receipt
);
205 // Store the note's text in the text cache.
206 // By doing this in the PostAddHook, we ensure that
207 // the TextCache is not modified until we are
208 // sure that the note was actually indexed.
210 text
= (string) note_text_cache
[receipt
.Uri
];
211 // If text == null, this is equivalent to
212 // calling Delete (receipt.Uri)
213 TextCache
.UserCache
.WriteFromString (receipt
.Uri
, text
);
214 note_text_cache
.Remove (receipt
.Uri
);
217 override protected bool HitIsValid (Uri uri
)
219 string note
= Path
.Combine (tomboy_dir
, uri
.Segments
[1] + ".note");
221 if (File
.Exists (note
))