2 using System
.Collections
;
5 using System
.Threading
;
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
));
39 log
.Info ("Starting urk log backend");
41 Stopwatch stopwatch
= new Stopwatch ();
44 State
= QueryableState
.Crawling
;
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";
52 ThisScheduler
.Add (task
);
57 log
.Info ("urk log backend worker thread done in {0}", stopwatch
);
60 public override void Start ()
64 ExceptionHandlingThread
.Start (new ThreadStart (StartWorker
));
67 /////////////////////////////////////////////////
69 private void CrawlHook (Scheduler
.Task task
)
72 task
.Reschedule
= true;
73 task
.TriggerTime
= DateTime
.Now
.AddSeconds (polling_interval_in_seconds
);
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
))
124 private bool FileIsInteresting (string filename
)
126 // Filename must be fixed length, see below
127 if (filename
.Length
< 21 || filename
.Length
> 22)
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)
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)
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)
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)
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;
207 private void IndexLog (string filename
, Scheduler
.Priority priority
)
209 if (! File
.Exists (filename
))
212 if (IsUpToDate (filename
))
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"]);
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);