]> ToastFreeware Gitweb - gregoa/zavai.git/blobdiff - src/core.vala
Merge branch 'master' into gregoa
[gregoa/zavai.git] / src / core.vala
index c8b4047d38fc637bd0a271831e501ca76cd03f2e..6eb4de43e8a32e9c3c1dca964e369f6d7cfe4301 100644 (file)
@@ -42,16 +42,27 @@ public abstract class Service : Object, Resource {
     public bool started {
         get { return _started; }
         set { _started = value; }
-        default = false;
     }
 
     public signal void toggled(bool new_state);
 
-    protected HashMap<string, int> requests;
+    protected class Request
+    {
+        public string requestor;
+        public int count;
+        public Request(string requestor)
+        {
+            this.requestor = requestor;
+            count = 1;
+        }
+    }
+
+    protected List<Request> requests;
 
     construct
     {
-        requests = new HashMap<string, int>(str_hash, str_equal);
+        started = false;
+        requests = null;
         zavai.registry.register(this);
     }
 
@@ -93,11 +104,17 @@ public abstract class Service : Object, Resource {
      */
     public bool request(string id)
     {
-        bool res = (requests.size == 0);
-        if (id in requests)
-            requests[id] = requests[id] + 1;
-        else
-            requests.set(id, 1);
+        bool res = (requests == null);
+        bool got = false;
+        for (weak List<Request> i = requests; i != null; i = i.next)
+            if (i.data.requestor == id)
+            {
+                ++i.data.count;
+                got = true;
+                break;
+            }
+        if (!got)
+            requests.prepend(new Request(id));
         if (res) start();
         return res;
     }
@@ -113,20 +130,161 @@ public abstract class Service : Object, Resource {
      */
     public bool release(string id)
     {
-        if (id in requests)
+        weak List<Request> el = null;
+        for (weak List<Request> i = requests; i != null; i = i.next)
+            if (i.data.requestor == id)
+            {
+                el = i;
+                break;
+            }
+
+        if (el == null)
+            return false;
+
+        --el.data.count;
+        if (el.data.count == 0)
+            requests.delete_link(el);
+
+        if (requests != null)
+            return false;
+
+        stop();
+        return true;
+    }
+}
+
+public abstract class ScriptService : Service
+{
+    protected string script;
+
+    protected bool script_start()
+    {
+        try {
+            zavai.config.find_and_run_script(name, "start");
+            return true;
+        } catch (Error e) {
+            zavai.log.error("Running " + name + " start: " + e.message);
+            return false;
+        }
+    }
+
+    protected bool script_stop()
+    {
+        try {
+            zavai.config.find_and_run_script(name, "stop");
+            return true;
+        } catch (Error e) {
+            zavai.log.error("Running " + name + " stop: " + e.message);
+            return false;
+        }
+    }
+
+    protected bool script_status()
+    {
+        string std_out;
+        string std_err;
+        string script = zavai.config.find_script(name);
+        if (script == null)
         {
-            if (requests[id] > 1)
-                requests[id] = requests[id] - 1;
-            else
-                requests.remove(id);
-        } else {
+            zavai.log.error("Hook " + name + " does not exist");
             return false;
         }
-        if (requests.size > 0)
+        string command = script + " status";
+        try {
+            int res = zavai.config.run_script_sync(command, out std_out, out std_err);
+            if (res != 0)
+            {
+                zavai.log.error("Running " + command + ": " + std_err);
+                return false;
+            }
+        } catch (SpawnError e) {
+            zavai.log.error("Running " + command + ": " + e.message);
             return false;
-        stop();
+        }
+
+        std_out._strip();
+
+        return (std_out == "on");
+    }
+}
+
+public abstract class ScriptMonitorService : Service
+{
+    protected Pid child_pid;
+    protected int child_watch_id;
+
+    ScriptMonitorService()
+    {
+        child_pid = 0;
+        child_watch_id = 0;
+    }
+
+    protected bool script_start()
+    {
+        string script = zavai.config.find_script(name);
+        zavai.log.info("Run program: " + script + " pre");
+        try {
+            // Then run our own script
+            zavai.config.run_script(script + " pre");
+        } catch (Error e) {
+            zavai.log.error("Running " + script + " pre: " + e.message);
+            return false;
+        }
+
+        zavai.log.info("Run program: " + script + " run");
+        string[] args = { script, "run" };
+        try {
+            Process.spawn_async(
+                Environment.get_home_dir(),
+                args,
+                null,
+                SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
+                null,
+                out child_pid);
+        } catch (SpawnError e) {
+            zavai.log.error("Running " + script + " run: " + e.message);
+            return false;
+        }
+
+        // Add a child watch source to know when it ends
+        ChildWatch.add(child_pid, on_child);
+
+        return true;
+    }
+
+    protected bool script_stop()
+    {
+        Posix.kill((Posix.pid_t)child_pid, Posix.SIGTERM);
         return true;
     }
+
+    protected void on_child(Pid pid, int status)
+    {
+        zavai.log.info("Exited");
+        Process.close_pid(pid);
+
+        try {
+            // Then run our own script
+            zavai.config.find_and_run_script(name, "post");
+        } catch (Error e) {
+            zavai.log.error("Running " + name + " post: " + e.message);
+            return;
+        }
+
+        cleanup_after_script_stop();
+
+        base.stop();
+    }
+
+    protected virtual void cleanup_after_script_stop()
+    {
+    }
+
+    /*
+    protected bool script_status()
+    {
+    }
+    */
 }
 
 }