[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Add python bindings for watches.



# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID 63e226a5e272b4d99461a39e188a20431e10f898
# Parent  99f12399b25a969989af0543da0330601f562f65
Add python bindings for watches.
Uses a watcher thread with per-watch registered callbacks.
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>

diff -r 99f12399b25a -r 63e226a5e272 tools/python/xen/lowlevel/xs/xs.c
--- a/tools/python/xen/lowlevel/xs/xs.c Wed Sep  7 01:03:02 2005
+++ b/tools/python/xen/lowlevel/xs/xs.c Wed Sep  7 12:47:45 2005
@@ -45,6 +45,7 @@
 typedef struct XsHandle {
     PyObject_HEAD;
     struct xs_handle *xh;
+    PyObject *watches;
 } XsHandle;
 
 static inline struct xs_handle *xshandle(PyObject *self)
@@ -355,13 +356,19 @@
        "Raises RuntimeError on error.\n"                               \
        "\n"
 
+/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
+#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
+
 static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwd_spec[] = { "path", "token", NULL };
-    static char *arg_spec = "s|is";
-    char *path = NULL;
-    char *token = "";
-
+    static char *arg_spec = "sO";
+    char *path = NULL;
+    PyObject *token;
+    char token_str[MAX_STRLEN(unsigned long) + 1];
+    int i;
+
+    XsHandle *xsh = (XsHandle *)self;
     struct xs_handle *xh = xshandle(self);
     PyObject *val = NULL;
     int xsval = 0;
@@ -371,8 +378,21 @@
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, 
                                      &path, &token))
         goto exit;
-    xsval = xs_watch(xh, path, token);
-    val = pyvalue_int(xsval);
+    Py_INCREF(token);
+    sprintf(token_str, "%li", (unsigned long)token);
+    xsval = xs_watch(xh, path, token_str);
+    val = pyvalue_int(xsval);
+    if (xsval) {
+       for (i = 0; i < PyList_Size(xsh->watches); i++) {
+           if (PyList_GetItem(xsh->watches, i) == Py_None) {
+               PyList_SetItem(xsh->watches, i, token);
+               break;
+           }
+       }
+       if (i == PyList_Size(xsh->watches))
+           PyList_Append(xsh->watches, token);
+    } else
+       Py_DECREF(token);
  exit:
     return val;
 }
@@ -393,9 +413,12 @@
     static char *kwd_spec[] = { NULL };
     static char *arg_spec = "";
 
+    XsHandle *xsh = (XsHandle *)self;
     struct xs_handle *xh = xshandle(self);
     PyObject *val = NULL;
     char **xsval = NULL;
+    PyObject *token;
+    int i;
 
     if (!xh)
        goto exit;
@@ -403,11 +426,23 @@
         goto exit;
     xsval = xs_read_watch(xh);
     if (!xsval) {
-            val = PyErr_SetFromErrno(PyExc_RuntimeError);
-            goto exit;
+       val = PyErr_SetFromErrno(PyExc_RuntimeError);
+       goto exit;
+    }
+    if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
+       PyErr_SetString(PyExc_RuntimeError, "invalid token");
+       goto exit;
+    }
+    for (i = 0; i < PyList_Size(xsh->watches); i++) {
+       if (token == PyList_GetItem(xsh->watches, i))
+           break;
+    }
+    if (i == PyList_Size(xsh->watches)) {
+       PyErr_SetString(PyExc_RuntimeError, "invalid token");
+       goto exit;
     }
     /* Create tuple (path, token). */
-    val = Py_BuildValue("(ss)", xsval[0], xsval[1]);
+    val = Py_BuildValue("(sO)", xsval[0], token);
  exit:
     if (xsval)
        free(xsval);
@@ -426,8 +461,9 @@
                                        PyObject *kwds)
 {
     static char *kwd_spec[] = { "token", NULL };
-    static char *arg_spec = "s";
-    char *token;
+    static char *arg_spec = "O";
+    PyObject *token;
+    char token_str[MAX_STRLEN(unsigned long) + 1];
 
     struct xs_handle *xh = xshandle(self);
     PyObject *val = NULL;
@@ -437,7 +473,8 @@
        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
         goto exit;
-    xsval = xs_acknowledge_watch(xh, token);
+    sprintf(token_str, "%li", (unsigned long)token);
+    xsval = xs_acknowledge_watch(xh, token_str);
     val = pyvalue_int(xsval);
  exit:
     return val;
@@ -455,10 +492,13 @@
 static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwd_spec[] = { "path", "token", NULL };
-    static char *arg_spec = "s|s";
-    char *path = NULL;
-    char *token = "";
-
+    static char *arg_spec = "sO";
+    char *path = NULL;
+    PyObject *token;
+    char token_str[MAX_STRLEN(unsigned long) + 1];
+    int i;
+
+    XsHandle *xsh = (XsHandle *)self;
     struct xs_handle *xh = xshandle(self);
     PyObject *val = NULL;
     int xsval = 0;
@@ -468,8 +508,16 @@
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
                                     &token))
         goto exit;
-    xsval = xs_unwatch(xh, path, token);
-    val = pyvalue_int(xsval);
+    sprintf(token_str, "%li", (unsigned long)token);
+    xsval = xs_unwatch(xh, path, token_str);
+    val = pyvalue_int(xsval);
+    for (i = 0; i < PyList_Size(xsh->watches); i++) {
+       if (token == PyList_GetItem(xsh->watches, i)) {
+           Py_INCREF(Py_None);
+           PyList_SetItem(xsh->watches, i, Py_None);
+           break;
+       }
+    }
  exit:
     return val;
 }
@@ -612,7 +660,9 @@
 {
     static char *kwd_spec[] = { NULL };
     static char *arg_spec = "";
-
+    int i;
+
+    XsHandle *xsh = (XsHandle *)self;
     struct xs_handle *xh = xshandle(self);
     PyObject *val = NULL;
     int xsval = 1;
@@ -621,8 +671,13 @@
        goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
         goto exit;
+    for (i = 0; i < PyList_Size(xsh->watches); i++) {
+       /* TODO: xs_unwatch watches */
+       Py_INCREF(Py_None);
+       PyList_SetItem(xsh->watches, i, Py_None);
+    }
     xs_daemon_close(xh);
-    ((XsHandle*)self)->xh = NULL;
+    xsh->xh = NULL;
     val = pyvalue_int(xsval);
  exit:
     return val;
@@ -750,20 +805,24 @@
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
                                      &readonly))
-        goto exit;
+       return NULL;
 
     xsh = PyObject_New(XsHandle, &xshandle_type);
     if (!xsh)
+       return NULL;
+    xsh->watches = PyList_New(0);
+    if (!xsh->watches)
        goto exit;
     xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
     if (!xsh->xh) {
-        PyObject_Del(xsh);
-        val = pyvalue_int(0);
+       Py_DECREF(xsh->watches);
         goto exit;
     }
     val = (PyObject *)xsh;
- exit:
-    return val;
+    return val;
+ exit:
+    PyObject_Del(xsh);
+    return NULL;
 }
 
 static PyMethodDef xs_methods[] = {
diff -r 99f12399b25a -r 63e226a5e272 tools/python/xen/xend/xenstore/xswatch.py
--- /dev/null   Wed Sep  7 01:03:02 2005
+++ b/tools/python/xen/xend/xenstore/xswatch.py Wed Sep  7 12:47:45 2005
@@ -0,0 +1,62 @@
+
+import select
+import threading
+from xen.lowlevel import xs
+
+class xswatch:
+
+    watchThread = None
+    threadcond = threading.Condition()
+    xs = None
+    xslock = threading.Lock()
+    watches = []
+    
+    def __init__(self, path, fn, args=(), kwargs={}):
+        self.fn = fn
+        self.args = args
+        self.kwargs = kwargs
+        xswatch.watchStart()
+        xswatch.xslock.acquire()
+        xswatch.xs.watch(path, self)
+        xswatch.xslock.release()
+        xswatch.watches.append(self)
+
+    def watchStart(cls):
+        cls.threadcond.acquire()
+        if cls.watchThread:
+            cls.threadcond.release()
+            return
+        cls.watchThread = threading.Thread(name="Watcher",
+                                           target=cls.watchMain)
+        cls.watchThread.setDaemon(True)
+        cls.watchThread.start()
+        while cls.xs == None:
+            cls.threadcond.wait()
+        cls.threadcond.release()
+
+    watchStart = classmethod(watchStart)
+
+    def watchMain(cls):
+        cls.threadcond.acquire()
+        cls.xs = xs.open()
+        cls.threadcond.notifyAll()
+        cls.threadcond.release()
+        while True:
+            try:
+                (ord, owr, oer) = select.select([ cls.xs ], [], [])
+                cls.xslock.acquire()
+                # reconfirm ready to read with lock
+                (ord, owr, oer) = select.select([ cls.xs ], [], [], 0.001)
+                if not cls.xs in ord:
+                    cls.xslock.release()
+                    continue
+                we = cls.xs.read_watch()
+                watch = we[1]
+                cls.xs.acknowledge_watch(watch)
+                cls.xslock.release()
+            except RuntimeError, ex:
+                print ex
+                raise
+            watch.fn(*watch.args, **watch.kwargs)
+
+    watchMain = classmethod(watchMain)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.