# 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
|