Index table:name attribute of table:table of ods files. These store the sheet names.
[beagle.git] / bludgeon / Daemon.cs
blob8c3bd0e7d103e84453a99e53f2d2e5615453fe2a
2 using System;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Threading;
7 using Beagle.Util;
9 namespace Bludgeon {
11 static public class Daemon {
13 public delegate void StartedHandler (string daemon_version);
14 public delegate void IdleHandler ();
15 public delegate void VerifiedHandler (bool index_is_sane);
17 static public bool UseHeapBuddy = false;
19 /////////////////////////////////////////////////////////////
21 static Beagle.Query index_listener_query = null;
23 static private void SetupIndexListener ()
25 index_listener_query = new Beagle.Query ();
26 index_listener_query.IsIndexListener = true;
28 index_listener_query.HitsAddedEvent += OnHitsAdded;
29 index_listener_query.HitsSubtractedEvent += OnHitsSubtracted;
31 index_listener_query.SendAsync ();
34 static private void OnHitsAdded (Beagle.HitsAddedResponse response)
36 //Log.Spew ("Added {0} hits!", response.Hits.Count);
37 //foreach (Beagle.Hit hit in response.Hits)
38 //Log.Spew (" {0}", hit.Uri);
41 static private void OnHitsSubtracted (Beagle.HitsSubtractedResponse response)
43 //Log.Spew ("Subtracted {0} uris!", response.Uris.Count);
46 /////////////////////////////////////////////////////////////
48 private class WaitForStartClosure {
50 Process process;
51 StartedHandler started;
52 int failure_count = 0;
54 public WaitForStartClosure (Process process, StartedHandler started)
56 this.process = process;
57 this.started = started;
60 public void Start ()
62 // Wait a little bit before we start pinging the daemon. This is
63 // an attempt to work around a mono crash.
64 //Thread.Sleep (200);
66 Action.Add (50, new GLib.TimeoutHandler (OurTimeoutHandler));
69 private bool OurTimeoutHandler ()
71 #if false
72 // Oops, process.HasExited doesn't work in mono. Grrr.
73 if (process.HasExited) {
74 Log.Failure ("Beagle daemon has terminated unexpectedly - exit code {0}",
75 process.ExitCode);
76 if (started != null)
77 started (null);
78 return false;
80 #endif
82 Beagle.RequestMessage request;
83 request = new Beagle.DaemonInformationRequest ();
85 Beagle.ResponseMessage response = null;
86 try {
87 //Log.Spew ("Pinging daemon!");
88 response = request.Send ();
89 } catch { }
91 if (response == null) {
93 ++failure_count;
94 if (failure_count % 20 == 0)
95 Log.Info ("Ping attempt {0} failed", failure_count);
97 // If we've already tried a bunch of times, just give up.
98 if (failure_count >= 100) {
99 Log.Failure ("Could not contact daemon after {0} pings", failure_count);
100 if (started != null)
101 started (null);
102 return false;
105 return true; // wait a bit, then try again
108 Beagle.DaemonInformationResponse info;
109 info = (Beagle.DaemonInformationResponse) response;
111 Log.Spew ("Successfully pinged daemon (version={0})", info.Version);
113 SetupIndexListener ();
115 if (started != null)
116 started (info.Version);
118 return false; // all done
122 static public void Start (StartedHandler started)
124 Log.Spew ("Starting daemon");
126 string beagled;
127 beagled = Environment.GetEnvironmentVariable ("BEAGLED_COMMAND");
129 string args;
130 args = "--debug-memory --bg --allow-backend files";
132 if (UseHeapBuddy)
133 args += " --heap-buddy";
135 Process p;
136 p = new Process ();
137 p.StartInfo.UseShellExecute = false;
139 p.StartInfo.FileName = beagled;
140 p.StartInfo.Arguments = args;
142 p.StartInfo.EnvironmentVariables ["BEAGLE_HOME"] = Beagle.Util.PathFinder.HomeDir;
143 p.StartInfo.EnvironmentVariables ["BEAGLE_EXERCISE_THE_DOG"] = "1";
144 p.StartInfo.EnvironmentVariables ["BEAGLE_UNDER_BLUDGEON"] = "1";
145 p.StartInfo.EnvironmentVariables ["BEAGLE_HEAP_BUDDY_DIR"] = Path.Combine (Beagle.Util.PathFinder.HomeDir,
146 ".bludgeon");
148 p.Start ();
150 WaitForStartClosure closure;
151 closure = new WaitForStartClosure (p, started);
152 closure.Start ();
155 /////////////////////////////////////////////////////////////
157 private class WaitUntilIdleClosure {
159 IdleHandler idle;
160 int failure_count = 0;
161 int busy_count = 0;
162 bool optimized = false;
163 Stopwatch sw = null;
165 public WaitUntilIdleClosure (IdleHandler idle)
167 this.idle = idle;
170 public void Start ()
172 Action.Add (200, new GLib.TimeoutHandler (OurTimeoutHandler));
175 private bool OurTimeoutHandler ()
177 if (sw == null) {
178 sw = new Stopwatch ();
179 sw.Start ();
182 Beagle.RequestMessage request;
183 request = new Beagle.DaemonInformationRequest ();
185 Beagle.ResponseMessage response = null;
186 try {
187 response = request.Send ();
188 } catch { }
190 if (response == null) {
191 ++failure_count;
192 // FIXME: we should abort if we have too many failures
193 if (failure_count > 9)
194 Log.Info ("Status request attempt {0} failed", failure_count);
195 return true; // wait a bit, then try again
198 string status_str;
199 status_str = ((Beagle.DaemonInformationResponse) response).HumanReadableStatus;
201 if (status_str.IndexOf ("Waiting on empty queue") == -1) {
202 if (busy_count == 0)
203 Log.Spew ("Waiting for daemon to become idle");
204 ++busy_count;
205 if (busy_count % 10 == 0)
206 Log.Spew ("Still waiting for daemon to become idle...");
207 return true; // wait a bit, then try again
210 if (failure_count > 0 || busy_count > 0)
211 Log.Spew ("Daemon is idle after {0}", sw);
212 else
213 Log.Spew ("Daemon is idle");
215 if (! optimized) {
216 Log.Spew ("Requesting index optimization");
217 optimized = true;
218 failure_count = 0;
219 busy_count = 0;
220 sw.Reset ();
222 request = new Beagle.OptimizeIndexesRequest ();
223 try {
224 request.Send ();
225 } catch {
226 Log.Failure ("Optimize request failed");
227 // FIXME: we should probably terminate here, or something
230 return true; // wait for optimize to finish
233 if (idle != null)
234 idle ();
236 return false; // all done
240 static public void WaitUntilIdle (IdleHandler idle)
242 WaitUntilIdleClosure closure;
243 closure = new WaitUntilIdleClosure (idle);
244 closure.Start ();
247 /////////////////////////////////////////////////////////////
249 private class WaitUntilVerifiedClosure {
251 FileSystemObject root;
252 VerifiedHandler verified;
254 public WaitUntilVerifiedClosure (FileSystemObject root,
255 VerifiedHandler verified)
257 this.root = root;
258 this.verified = verified;
261 public void Start ()
263 WaitUntilIdle (OurIdleHandler);
266 private void OurIdleHandler ()
268 bool is_correct;
269 is_correct = SanityCheck.VerifyIndex (root);
270 if (verified != null)
271 verified (is_correct);
275 static public void WaitUntilVerified (FileSystemObject root, VerifiedHandler verified)
277 WaitUntilVerifiedClosure closure;
278 closure = new WaitUntilVerifiedClosure (root, verified);
279 closure.Start ();
282 /////////////////////////////////////////////////////////////
284 static public void Shutdown ()
286 Beagle.RequestMessage request;
287 request = new Beagle.ShutdownRequest ();
289 Log.Spew ("Shutting down daemon");
291 try {
292 request.Send ();
293 } catch {
294 Log.Failure ("beagled shutdown failed");