diff options
Diffstat (limited to 'services/console/lib/purk/UrkLogQueryable.cs')
-rw-r--r-- | services/console/lib/purk/UrkLogQueryable.cs | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/services/console/lib/purk/UrkLogQueryable.cs b/services/console/lib/purk/UrkLogQueryable.cs new file mode 100644 index 0000000..ee0611c --- /dev/null +++ b/services/console/lib/purk/UrkLogQueryable.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; +using System.Threading; + +using Beagle.Daemon; +using Beagle.Util; + +namespace Beagle.Daemon.UrkLogQueryable { + + [QueryableFlavor (Name="UrkLog", Domain=QueryDomain.Local, RequireInotify=false)] + public class UrkLogQueryable : LuceneFileQueryable { + + private static Logger log = Logger.Get ("UrkLogQueryable"); + + private string config_dir, log_dir, icons_dir; + + private int polling_interval_in_seconds = 60; + + //private GaimBuddyListReader list = new GaimBuddyListReader (); + + public UrkLogQueryable () : base ("UrkLogIndex") + { + config_dir = Path.Combine (PathFinder.HomeDir, ".urk"); + log_dir = Path.Combine (config_dir, "logs"); + icons_dir = Path.Combine (config_dir, "icons"); + } + + ///////////////////////////////////////////////// + + private void StartWorker() + { + if (! Directory.Exists (log_dir)) { + GLib.Timeout.Add (60000, new GLib.TimeoutHandler (CheckForExistence)); + return; + } + + log.Info ("Starting urk log backend"); + + Stopwatch stopwatch = new Stopwatch (); + stopwatch.Start (); + + State = QueryableState.Crawling; + Crawl (); + State = QueryableState.Idle; + + if (!Inotify.Enabled) { + Scheduler.Task task = Scheduler.TaskFromHook (new Scheduler.TaskHook (CrawlHook)); + task.Tag = "Crawling ~/.urk/logs to find new logfiles"; + task.Source = this; + ThisScheduler.Add (task); + } + + stopwatch.Stop (); + + log.Info ("urk log backend worker thread done in {0}", stopwatch); + } + + public override void Start () + { + base.Start (); + + ExceptionHandlingThread.Start (new ThreadStart (StartWorker)); + } + + ///////////////////////////////////////////////// + + private void CrawlHook (Scheduler.Task task) + { + Crawl (); + task.Reschedule = true; + task.TriggerTime = DateTime.Now.AddSeconds (polling_interval_in_seconds); + } + + private void Crawl () + { + Inotify.Subscribe (log_dir, OnInotifyNewProtocol, Inotify.EventType.Create); + + // Walk through protocol subdirs + foreach (string proto_dir in DirectoryWalker.GetDirectories (log_dir)) + CrawlProtocolDirectory (proto_dir); + } + + private void CrawlNetworkDirectory (string proto_dir) + { + Inotify.Subscribe (proto_dir, OnInotifyNewTarget, Inotify.EventType.Create); + + // Walk through accounts + foreach (string account_dir in DirectoryWalker.GetDirectories (proto_dir)) + CrawlTargetDirectory (account_dir); + } + + private void CrawlTargetDirectory (string account_dir) + { + Inotify.Subscribe (account_dir, OnInotifyNewRemote, Inotify.EventType.Create); + + // Walk through remote user conversations + foreach (string remote_dir in DirectoryWalker.GetDirectories (account_dir)) + CrawlRemoteDirectory (remote_dir); + } + + private void CrawlRemoteDirectory (string remote_dir) + { + Inotify.Subscribe (remote_dir, OnInotifyNewConversation, Inotify.EventType.CloseWrite); + + foreach (FileInfo file in DirectoryWalker.GetFileInfos (remote_dir)) + if (FileIsInteresting (file.Name)) + IndexLog (file.FullName, Scheduler.Priority.Delayed); + } + + ///////////////////////////////////////////////// + + private bool CheckForExistence () + { + if (!Directory.Exists (log_dir)) + return true; + + this.Start (); + + return false; + } + + private bool FileIsInteresting (string filename) + { + // Filename must be fixed length, see below + if (filename.Length < 21 || filename.Length > 22) + return false; + + // Check match on regex: ^[0-9]{4}-[0-9]{2}-[0-9]{2}\\.[0-9]{6}\\.(txt|html)$ + // e.g. 2005-07-22.161521.txt + // We'd use System.Text.RegularExpressions if they werent so much more expensive + return Char.IsDigit (filename [0]) && Char.IsDigit (filename [1]) + && Char.IsDigit (filename [2]) && Char.IsDigit (filename [3]) + && filename [4] == '-' + && Char.IsDigit (filename [5]) && Char.IsDigit (filename [6]) + && filename [7] == '-' + && Char.IsDigit (filename [8]) && Char.IsDigit (filename [9]) + && filename [10] == '.' + && Char.IsDigit (filename [11]) && Char.IsDigit (filename [12]) + && Char.IsDigit (filename [13]) && Char.IsDigit (filename [14]) + && Char.IsDigit (filename [15]) && Char.IsDigit (filename [16]) + && filename [17] == '.' + && ( (filename [18] == 't' && filename [19] == 'x' && filename [20] == 't') + || (filename [18] == 'h' && filename [19] == 't' && filename [20] == 'm' && filename [21] == 'l') + ); + } + + ///////////////////////////////////////////////// + + private void OnInotifyNewNetwork (Inotify.Watch watch, + string path, string subitem, string srcpath, + Inotify.EventType type) + { + if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0) + return; + + CrawlNetworkDirectory (Path.Combine (path, subitem)); + } + + private void OnInotifyNewTarget (Inotify.Watch watch, + string path, string subitem, string srcpath, + Inotify.EventType type) + { + if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0) + return; + + CrawlTargetDirectory (Path.Combine (path, subitem)); + } + + private void OnInotifyNewRemote (Inotify.Watch watch, + string path, string subitem, string srcpath, + Inotify.EventType type) + { + if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) == 0) + return; + + CrawlRemoteDirectory (Path.Combine (path, subitem)); + } + + private void OnInotifyNewConversation (Inotify.Watch watch, + string path, string subitem, string srcpath, + Inotify.EventType type) + { + if (subitem.Length == 0 || (type & Inotify.EventType.IsDirectory) != 0) + return; + + if (FileIsInteresting (subitem)) + IndexLog (Path.Combine (path, subitem), Scheduler.Priority.Immediate); + } + + ///////////////////////////////////////////////// + + private static Indexable IRCLogToIndexable (string filename) + { + Uri uri = UriFu.PathToFileUri (filename); + Indexable indexable = new Indexable (uri); + indexable.ContentUri = uri; + indexable.Timestamp = File.GetLastWriteTimeUtc (filename); + indexable.MimeType = GaimLog.MimeType; // XXX + indexable.HitType = "IRCLog"; + indexable.CacheContent = false; + + return indexable; + } + + private void IndexLog (string filename, Scheduler.Priority priority) + { + if (! File.Exists (filename)) + return; + + if (IsUpToDate (filename)) + return; + + Indexable indexable = IRCLogToIndexable (filename); + Scheduler.Task task = NewAddTask (indexable); + task.Priority = priority; + task.SubPriority = 0; + ThisScheduler.Add (task); + } + + override protected double RelevancyMultiplier (Hit hit) + { + return HalfLifeMultiplierFromProperty (hit, 0.25, + "fixme:endtime", "fixme:starttime"); + } + + override protected bool HitFilter (Hit hit) + { + /*ImBuddy buddy = list.Search (hit ["fixme:speakingto"]); + + if (buddy != null) { + if (buddy.Alias != "") + hit ["fixme:speakingto_alias"] = buddy.Alias; + + //if (buddy.BuddyIconLocation != "") + // hit ["fixme:speakingto_icon"] = Path.Combine (icons_dir, buddy.BuddyIconLocation); + }*/ + + return true; + } + + } +} + |