Tokenize 001234 as 1234. Include a testing function in NoiseFilter to figure out...
[beagle.git] / beagled / EvolutionMailDriver / EvolutionMailDriver.cs
blob1cee82f37fe3d762971329c147612201e04a8ee2
1 //
2 // EvolutionMailDriver.cs
3 //
4 // Copyright (C) 2004 Novell, Inc.
5 //
6 //
7 //
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 using System;
29 using System.Collections;
30 using System.IO;
31 using System.Threading;
33 using Beagle.Util;
34 using Camel = Beagle.Util.Camel;
36 namespace Beagle.Daemon.EvolutionMailDriver {
38 [QueryableFlavor (Name="EvolutionMail", Domain=QueryDomain.Local, RequireInotify=false)]
39 public class EvolutionMailQueryable : LuceneQueryable {
41 public int polling_interval_in_seconds = 60;
43 private string local_path, imap_path, imap4_path;
45 private MailCrawler crawler;
47 private Hashtable generator_progress = new Hashtable ();
49 // Index versions
50 // 1: Original version, stored all recipient addresses as a
51 // RFC822 string
52 // 2: Stores recipients in separate properties,
53 // filters/indexes all attachments
54 // 3: Make email addresses non-keyword, add sanitized version
55 // for searching for parts of an email address.
56 // 4: Make the flags property mutable, and create a property
57 // change Indexable when they change for IMAP generators.
58 // 5: No need for a separate sanitized version of email addresses.
59 private const int INDEX_VERSION = 5;
61 public EvolutionMailQueryable () : base ("EvolutionMailIndex", INDEX_VERSION)
63 this.local_path = Path.Combine (PathFinder.HomeDir, ".evolution/mail/local");
64 this.imap_path = Path.Combine (PathFinder.HomeDir, ".evolution/mail/imap");
65 this.imap4_path = Path.Combine (PathFinder.HomeDir, ".evolution/mail/imap4");
68 private void CrawlHook (Scheduler.Task task)
70 crawler.Crawl ();
71 task.Reschedule = true;
72 task.TriggerTime = DateTime.Now.AddSeconds (polling_interval_in_seconds);
75 //////////////////////////////////////////////////////////////////////////////////////////////
77 private void StartWorker ()
79 Logger.Log.Info ("Starting Evolution mail backend");
81 Stopwatch stopwatch = new Stopwatch ();
82 stopwatch.Start ();
84 // Check that we have data to index
85 if ((! Directory.Exists (this.local_path)) && (! Directory.Exists (this.imap_path))) {
86 // No mails present, repoll every minute
87 Logger.Log.Warn ("Evolution mail store not found, watching for it.");
88 GLib.Timeout.Add (60000, new GLib.TimeoutHandler (CheckForMailData));
89 return;
92 Logger.Log.Debug ("Starting mail crawl");
93 State = QueryableState.Crawling;
94 crawler = new MailCrawler (this.local_path, this.imap_path, this.imap4_path);
95 crawler.MboxAddedEvent += IndexMbox;
96 crawler.SummaryAddedEvent += IndexSummary;
97 crawler.Crawl ();
98 State = QueryableState.Idle;
99 Logger.Log.Debug ("Mail crawl finished");
101 // If we don't have inotify, we have to poll the file system. Ugh.
102 if (! Inotify.Enabled) {
103 Scheduler.Task task = Scheduler.TaskFromHook (new Scheduler.TaskHook (CrawlHook));
104 task.Tag = "Crawling ~/.evolution to find summary changes";
105 task.Source = this;
106 ThisScheduler.Add (task);
109 stopwatch.Stop ();
110 Logger.Log.Info ("Evolution mail driver worker thread done in {0}",
111 stopwatch);
114 public override void Start ()
116 base.Start ();
118 ExceptionHandlingThread.Start (new ThreadStart (StartWorker));
121 private bool CheckForMailData ()
123 if ((! Directory.Exists (this.local_path)) && (! Directory.Exists (this.imap_path)))
124 return true; // continue polling
126 // Otherwise stop polling and start indexing
127 StartWorker();
128 return false;
131 public string Name {
132 get { return "EvolutionMail"; }
135 public void IndexSummary (FileInfo summaryInfo)
137 // If there's already a task running for this folder,
138 // don't interrupt it.
139 if (ThisScheduler.ContainsByTag (summaryInfo.FullName)) {
140 Logger.Log.Debug ("Not adding task for already running task: {0}", summaryInfo.FullName);
141 return;
144 Logger.Log.Debug ("Will index summary {0}", summaryInfo.FullName);
145 EvolutionMailIndexableGeneratorImap generator = new EvolutionMailIndexableGeneratorImap (this, summaryInfo);
146 Scheduler.Task task;
147 task = NewAddTask (generator);
148 task.Tag = summaryInfo.FullName;
149 // IndexableGenerator tasks default to having priority Scheduler.Priority Generator
150 ThisScheduler.Add (task);
152 SetGeneratorProgress (generator, 0);
155 public void IndexMbox (FileInfo mboxInfo)
157 // If there's already a task running for this mbox,
158 // don't interrupt it.
159 if (ThisScheduler.ContainsByTag (mboxInfo.FullName)) {
160 Logger.Log.Debug ("Not adding task for already running task: {0}", mboxInfo.FullName);
161 return;
164 Logger.Log.Debug ("Will index mbox {0}", mboxInfo.FullName);
165 EvolutionMailIndexableGeneratorMbox generator = new EvolutionMailIndexableGeneratorMbox (this, mboxInfo);
166 Scheduler.Task task;
167 task = NewAddTask (generator);
168 task.Tag = mboxInfo.FullName;
169 // IndexableGenerator tasks default to having priority Scheduler.Priority Generator
170 ThisScheduler.Add (task);
172 SetGeneratorProgress (generator, 0);
175 public static Uri EmailUri (string accountName, string folderName, string uid)
177 return new Uri (String.Format ("email://{0}/{1};uid={2}",
178 accountName, folderName, uid));
181 // An embarrassingly unscientific attempt at getting progress
182 // information from the mail backend as a whole. Unfortunately
183 // the IMAP and mbox backends don't have a common unit of
184 // measurement (IMAP has number of messages, mbox number of
185 // bytes), so we can't get anything really accurate. We could
186 // try to normalize the byte count; that'd do us a little
187 // better.
188 public void SetGeneratorProgress (EvolutionMailIndexableGenerator generator, int percent)
190 this.generator_progress [generator] = percent;
192 int i = 0, total_percent = 0;
193 foreach (int progress in this.generator_progress.Values) {
194 total_percent += progress;
195 i++;
198 Logger.Log.Debug ("Overall percent is {0}", (float) total_percent / i);
200 this.ProgressPercent = total_percent / i;
203 public void RemoveGeneratorProgress (EvolutionMailIndexableGenerator generator)
205 this.generator_progress.Remove (generator);
207 int i = 0, total_percent = 0;
208 foreach (int progress in this.generator_progress.Values) {
209 total_percent += progress;
210 i++;
213 Logger.Log.Debug ("Overall percent is {0}", (float) total_percent / i);
215 this.ProgressPercent = total_percent / i;