Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/services/console/lib/purk/UrkLogQueryable.cs
diff options
context:
space:
mode:
Diffstat (limited to 'services/console/lib/purk/UrkLogQueryable.cs')
-rw-r--r--services/console/lib/purk/UrkLogQueryable.cs245
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;
+ }
+
+ }
+}
+