gtk: don't use gtk if there's no display
[urk.git] / UrkLogQueryable.cs
blobee0611c28aea5718007a03ea67c843633399da5b
1 using System;
2 using System.Collections;
3 using System.IO;
4 using System.Text;
5 using System.Threading;
7 using Beagle.Daemon;
8 using Beagle.Util;
10 namespace Beagle.Daemon.UrkLogQueryable {
12 [QueryableFlavor (Name="UrkLog", Domain=QueryDomain.Local, RequireInotify=false)]
13 public class UrkLogQueryable : LuceneFileQueryable {
15 private static Logger log = Logger.Get ("UrkLogQueryable");
17 private string config_dir, log_dir, icons_dir;
19 private int polling_interval_in_seconds = 60;
21 //private GaimBuddyListReader list = new GaimBuddyListReader ();
23 public UrkLogQueryable () : base ("UrkLogIndex")
25 config_dir = Path.Combine (PathFinder.HomeDir, ".urk");
26 log_dir = Path.Combine (config_dir, "logs");
27 icons_dir = Path.Combine (config_dir, "icons");
30 /////////////////////////////////////////////////
32 private void StartWorker()
34 if (! Directory.Exists (log_dir)) {
35 GLib.Timeout.Add (60000, new GLib.TimeoutHandler (CheckForExistence));
36 return;
39 log.Info ("Starting urk log backend");
41 Stopwatch stopwatch = new Stopwatch ();
42 stopwatch.Start ();
44 State = QueryableState.Crawling;
45 Crawl ();
46 State = QueryableState.Idle;
48 if (!Inotify.Enabled) {
49 Scheduler.Task task = Scheduler.TaskFromHook (new Scheduler.TaskHook (CrawlHook));
50 task.Tag = "Crawling ~/.urk/logs to find new logfiles";
51 task.Source = this;
52 ThisScheduler.Add (task);
55 stopwatch.Stop ();
57 log.Info ("urk log backend worker thread done in {0}", stopwatch);
60 public override void Start ()
62 base.Start ();
64 ExceptionHandlingThread.Start (new ThreadStart (StartWorker));
67 /////////////////////////////////////////////////
69 private void CrawlHook (Scheduler.Task task)
71 Crawl ();
72 task.Reschedule = true;
73 task.TriggerTime = DateTime.Now.AddSeconds (polling_interval_in_seconds);
76 private void Crawl ()
78 Inotify.Subscribe (log_dir, OnInotifyNewProtocol, Inotify.EventType.Create);
80 // Walk through protocol subdirs
81 foreach (string proto_dir in DirectoryWalker.GetDirectories (log_dir))
82 CrawlProtocolDirectory (proto_dir);
85 private void CrawlNetworkDirectory (string proto_dir)
87 Inotify.Subscribe (proto_dir, OnInotifyNewTarget, Inotify.EventType.Create);
89 // Walk through accounts
90 foreach (string account_dir in DirectoryWalker.GetDirectories (proto_dir))
91 CrawlTargetDirectory (account_dir);
94 private void CrawlTargetDirectory (string account_dir)
96 Inotify.Subscribe (account_dir, OnInotifyNewRemote, Inotify.EventType.Create);
98 // Walk through remote user conversations
99 foreach (string remote_dir in DirectoryWalker.GetDirectories (account_dir))
100 CrawlRemoteDirectory (remote_dir);
103 private void CrawlRemoteDirectory (string remote_dir)
105 Inotify.Subscribe (remote_dir, OnInotifyNewConversation, Inotify.EventType.CloseWrite);
107 foreach (FileInfo file in DirectoryWalker.GetFileInfos (remote_dir))
108 if (FileIsInteresting (file.Name))
109 IndexLog (file.FullName, Scheduler.Priority.Delayed);
112 /////////////////////////////////////////////////
114 private bool CheckForExistence ()
116 if (!Directory.Exists (log_dir))
117 return true;
119 this.Start ();
121 return false;
124 private bool FileIsInteresting (string filename)
126 // Filename must be fixed length, see below
127 if (filename.Length < 21 || filename.Length > 22)
128 return false;
130 // Check match on regex: ^[0-9]{4}-[0-9]{2}-[0-9]{2}\\.[0-9]{6}\\.(txt|html)$
131 // e.g. 2005-07-22.161521.txt
132 // We'd use System.Text.RegularExpressions if they werent so much more expensive
133 return Char.IsDigit (filename [0]) && Char.IsDigit (filename [1])
134 && Char.IsDigit (filename [2]) && Char.IsDigit (filename [3])
135 && filename [4] == '-'
136 && Char.IsDigit (filename [5]) && Char.IsDigit (filename [6])
137 && filename [7] == '-'
138 && Char.IsDigit (filename [8]) && Char.IsDigit (filename [9])
139 && filename [10] == '.'
140 && Char.IsDigit (filename [11]) && Char.IsDigit (filename [12])
141 && Char.IsDigit (filename [13]) && Char.IsDigit (filename [14])
142 && Char.IsDigit (filename [15]) && Char.IsDigit (filename [16])
143 && filename [17] == '.'
144 && ( (filename [18] == 't' && filename [19] == 'x' && filename [20] == 't')
145 || (filename [18] == 'h' && filename [19] == 't' && filename [20] == 'm' && filename [21] == 'l')
149 /////////////////////////////////////////////////
151 private void OnInotifyNewNetwork (Inotify.Watch watch,
152 string path, string subitem, string srcpath,
153 Inotify.EventType type)
155 if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0)
156 return;
158 CrawlNetworkDirectory (Path.Combine (path, subitem));
161 private void OnInotifyNewTarget (Inotify.Watch watch,
162 string path, string subitem, string srcpath,
163 Inotify.EventType type)
165 if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0)
166 return;
168 CrawlTargetDirectory (Path.Combine (path, subitem));
171 private void OnInotifyNewRemote (Inotify.Watch watch,
172 string path, string subitem, string srcpath,
173 Inotify.EventType type)
175 if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0)
176 return;
178 CrawlRemoteDirectory (Path.Combine (path, subitem));
181 private void OnInotifyNewConversation (Inotify.Watch watch,
182 string path, string subitem, string srcpath,
183 Inotify.EventType type)
185 if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) != 0)
186 return;
188 if (FileIsInteresting (subitem))
189 IndexLog (Path.Combine (path, subitem), Scheduler.Priority.Immediate);
192 /////////////////////////////////////////////////
194 private static Indexable IRCLogToIndexable (string filename)
196 Uri uri = UriFu.PathToFileUri (filename);
197 Indexable indexable = new Indexable (uri);
198 indexable.ContentUri = uri;
199 indexable.Timestamp = File.GetLastWriteTimeUtc (filename);
200 indexable.MimeType = GaimLog.MimeType; // XXX
201 indexable.HitType = "IRCLog";
202 indexable.CacheContent = false;
204 return indexable;
207 private void IndexLog (string filename, Scheduler.Priority priority)
209 if (! File.Exists (filename))
210 return;
212 if (IsUpToDate (filename))
213 return;
215 Indexable indexable = IRCLogToIndexable (filename);
216 Scheduler.Task task = NewAddTask (indexable);
217 task.Priority = priority;
218 task.SubPriority = 0;
219 ThisScheduler.Add (task);
222 override protected double RelevancyMultiplier (Hit hit)
224 return HalfLifeMultiplierFromProperty (hit, 0.25,
225 "fixme:endtime", "fixme:starttime");
228 override protected bool HitFilter (Hit hit)
230 /*ImBuddy buddy = list.Search (hit ["fixme:speakingto"]);
232 if (buddy != null) {
233 if (buddy.Alias != "")
234 hit ["fixme:speakingto_alias"] = buddy.Alias;
236 //if (buddy.BuddyIconLocation != "")
237 // hit ["fixme:speakingto_icon"] = Path.Combine (icons_dir, buddy.BuddyIconLocation);
240 return true;