ia64/xen-unstable

changeset 6673:63e226a5e272

Add python bindings for watches.
Uses a watcher thread with per-watch registered callbacks.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Wed Sep 07 12:47:45 2005 +0000 (2005-09-07)
parents 99f12399b25a
children a75b08af8d19
files tools/python/xen/lowlevel/xs/xs.c tools/python/xen/xend/xenstore/xswatch.py
line diff
     1.1 --- a/tools/python/xen/lowlevel/xs/xs.c	Wed Sep 07 01:03:02 2005 +0000
     1.2 +++ b/tools/python/xen/lowlevel/xs/xs.c	Wed Sep 07 12:47:45 2005 +0000
     1.3 @@ -45,6 +45,7 @@
     1.4  typedef struct XsHandle {
     1.5      PyObject_HEAD;
     1.6      struct xs_handle *xh;
     1.7 +    PyObject *watches;
     1.8  } XsHandle;
     1.9  
    1.10  static inline struct xs_handle *xshandle(PyObject *self)
    1.11 @@ -355,13 +356,19 @@ static PyObject *xspy_set_permissions(Py
    1.12  	"Raises RuntimeError on error.\n"				\
    1.13  	"\n"
    1.14  
    1.15 +/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
    1.16 +#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
    1.17 +
    1.18  static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
    1.19  {
    1.20      static char *kwd_spec[] = { "path", "token", NULL };
    1.21 -    static char *arg_spec = "s|is";
    1.22 +    static char *arg_spec = "sO";
    1.23      char *path = NULL;
    1.24 -    char *token = "";
    1.25 +    PyObject *token;
    1.26 +    char token_str[MAX_STRLEN(unsigned long) + 1];
    1.27 +    int i;
    1.28  
    1.29 +    XsHandle *xsh = (XsHandle *)self;
    1.30      struct xs_handle *xh = xshandle(self);
    1.31      PyObject *val = NULL;
    1.32      int xsval = 0;
    1.33 @@ -371,8 +378,21 @@ static PyObject *xspy_watch(PyObject *se
    1.34      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, 
    1.35                                       &path, &token))
    1.36          goto exit;
    1.37 -    xsval = xs_watch(xh, path, token);
    1.38 +    Py_INCREF(token);
    1.39 +    sprintf(token_str, "%li", (unsigned long)token);
    1.40 +    xsval = xs_watch(xh, path, token_str);
    1.41      val = pyvalue_int(xsval);
    1.42 +    if (xsval) {
    1.43 +	for (i = 0; i < PyList_Size(xsh->watches); i++) {
    1.44 +	    if (PyList_GetItem(xsh->watches, i) == Py_None) {
    1.45 +		PyList_SetItem(xsh->watches, i, token);
    1.46 +		break;
    1.47 +	    }
    1.48 +	}
    1.49 +	if (i == PyList_Size(xsh->watches))
    1.50 +	    PyList_Append(xsh->watches, token);
    1.51 +    } else
    1.52 +	Py_DECREF(token);
    1.53   exit:
    1.54      return val;
    1.55  }
    1.56 @@ -393,9 +413,12 @@ static PyObject *xspy_read_watch(PyObjec
    1.57      static char *kwd_spec[] = { NULL };
    1.58      static char *arg_spec = "";
    1.59  
    1.60 +    XsHandle *xsh = (XsHandle *)self;
    1.61      struct xs_handle *xh = xshandle(self);
    1.62      PyObject *val = NULL;
    1.63      char **xsval = NULL;
    1.64 +    PyObject *token;
    1.65 +    int i;
    1.66  
    1.67      if (!xh)
    1.68  	goto exit;
    1.69 @@ -403,11 +426,23 @@ static PyObject *xspy_read_watch(PyObjec
    1.70          goto exit;
    1.71      xsval = xs_read_watch(xh);
    1.72      if (!xsval) {
    1.73 -            val = PyErr_SetFromErrno(PyExc_RuntimeError);
    1.74 -            goto exit;
    1.75 +	val = PyErr_SetFromErrno(PyExc_RuntimeError);
    1.76 +	goto exit;
    1.77 +    }
    1.78 +    if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
    1.79 +	PyErr_SetString(PyExc_RuntimeError, "invalid token");
    1.80 +	goto exit;
    1.81 +    }
    1.82 +    for (i = 0; i < PyList_Size(xsh->watches); i++) {
    1.83 +	if (token == PyList_GetItem(xsh->watches, i))
    1.84 +	    break;
    1.85 +    }
    1.86 +    if (i == PyList_Size(xsh->watches)) {
    1.87 +	PyErr_SetString(PyExc_RuntimeError, "invalid token");
    1.88 +	goto exit;
    1.89      }
    1.90      /* Create tuple (path, token). */
    1.91 -    val = Py_BuildValue("(ss)", xsval[0], xsval[1]);
    1.92 +    val = Py_BuildValue("(sO)", xsval[0], token);
    1.93   exit:
    1.94      if (xsval)
    1.95  	free(xsval);
    1.96 @@ -426,8 +461,9 @@ static PyObject *xspy_acknowledge_watch(
    1.97  					PyObject *kwds)
    1.98  {
    1.99      static char *kwd_spec[] = { "token", NULL };
   1.100 -    static char *arg_spec = "s";
   1.101 -    char *token;
   1.102 +    static char *arg_spec = "O";
   1.103 +    PyObject *token;
   1.104 +    char token_str[MAX_STRLEN(unsigned long) + 1];
   1.105  
   1.106      struct xs_handle *xh = xshandle(self);
   1.107      PyObject *val = NULL;
   1.108 @@ -437,7 +473,8 @@ static PyObject *xspy_acknowledge_watch(
   1.109  	goto exit;
   1.110      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
   1.111          goto exit;
   1.112 -    xsval = xs_acknowledge_watch(xh, token);
   1.113 +    sprintf(token_str, "%li", (unsigned long)token);
   1.114 +    xsval = xs_acknowledge_watch(xh, token_str);
   1.115      val = pyvalue_int(xsval);
   1.116   exit:
   1.117      return val;
   1.118 @@ -455,10 +492,13 @@ static PyObject *xspy_acknowledge_watch(
   1.119  static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
   1.120  {
   1.121      static char *kwd_spec[] = { "path", "token", NULL };
   1.122 -    static char *arg_spec = "s|s";
   1.123 +    static char *arg_spec = "sO";
   1.124      char *path = NULL;
   1.125 -    char *token = "";
   1.126 +    PyObject *token;
   1.127 +    char token_str[MAX_STRLEN(unsigned long) + 1];
   1.128 +    int i;
   1.129  
   1.130 +    XsHandle *xsh = (XsHandle *)self;
   1.131      struct xs_handle *xh = xshandle(self);
   1.132      PyObject *val = NULL;
   1.133      int xsval = 0;
   1.134 @@ -468,8 +508,16 @@ static PyObject *xspy_unwatch(PyObject *
   1.135      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
   1.136  				     &token))
   1.137          goto exit;
   1.138 -    xsval = xs_unwatch(xh, path, token);
   1.139 +    sprintf(token_str, "%li", (unsigned long)token);
   1.140 +    xsval = xs_unwatch(xh, path, token_str);
   1.141      val = pyvalue_int(xsval);
   1.142 +    for (i = 0; i < PyList_Size(xsh->watches); i++) {
   1.143 +	if (token == PyList_GetItem(xsh->watches, i)) {
   1.144 +	    Py_INCREF(Py_None);
   1.145 +	    PyList_SetItem(xsh->watches, i, Py_None);
   1.146 +	    break;
   1.147 +	}
   1.148 +    }
   1.149   exit:
   1.150      return val;
   1.151  }
   1.152 @@ -612,7 +660,9 @@ static PyObject *xspy_close(PyObject *se
   1.153  {
   1.154      static char *kwd_spec[] = { NULL };
   1.155      static char *arg_spec = "";
   1.156 +    int i;
   1.157  
   1.158 +    XsHandle *xsh = (XsHandle *)self;
   1.159      struct xs_handle *xh = xshandle(self);
   1.160      PyObject *val = NULL;
   1.161      int xsval = 1;
   1.162 @@ -621,8 +671,13 @@ static PyObject *xspy_close(PyObject *se
   1.163  	goto exit;
   1.164      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
   1.165          goto exit;
   1.166 +    for (i = 0; i < PyList_Size(xsh->watches); i++) {
   1.167 +	/* TODO: xs_unwatch watches */
   1.168 +	Py_INCREF(Py_None);
   1.169 +	PyList_SetItem(xsh->watches, i, Py_None);
   1.170 +    }
   1.171      xs_daemon_close(xh);
   1.172 -    ((XsHandle*)self)->xh = NULL;
   1.173 +    xsh->xh = NULL;
   1.174      val = pyvalue_int(xsval);
   1.175   exit:
   1.176      return val;
   1.177 @@ -750,20 +805,24 @@ static PyObject *xshandle_open(PyObject 
   1.178  
   1.179      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.180                                       &readonly))
   1.181 -        goto exit;
   1.182 +	return NULL;
   1.183  
   1.184      xsh = PyObject_New(XsHandle, &xshandle_type);
   1.185      if (!xsh)
   1.186 +	return NULL;
   1.187 +    xsh->watches = PyList_New(0);
   1.188 +    if (!xsh->watches)
   1.189  	goto exit;
   1.190      xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
   1.191      if (!xsh->xh) {
   1.192 -        PyObject_Del(xsh);
   1.193 -        val = pyvalue_int(0);
   1.194 +	Py_DECREF(xsh->watches);
   1.195          goto exit;
   1.196      }
   1.197      val = (PyObject *)xsh;
   1.198 +    return val;
   1.199   exit:
   1.200 -    return val;
   1.201 +    PyObject_Del(xsh);
   1.202 +    return NULL;
   1.203  }
   1.204  
   1.205  static PyMethodDef xs_methods[] = {
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/python/xen/xend/xenstore/xswatch.py	Wed Sep 07 12:47:45 2005 +0000
     2.3 @@ -0,0 +1,62 @@
     2.4 +
     2.5 +import select
     2.6 +import threading
     2.7 +from xen.lowlevel import xs
     2.8 +
     2.9 +class xswatch:
    2.10 +
    2.11 +    watchThread = None
    2.12 +    threadcond = threading.Condition()
    2.13 +    xs = None
    2.14 +    xslock = threading.Lock()
    2.15 +    watches = []
    2.16 +    
    2.17 +    def __init__(self, path, fn, args=(), kwargs={}):
    2.18 +        self.fn = fn
    2.19 +        self.args = args
    2.20 +        self.kwargs = kwargs
    2.21 +        xswatch.watchStart()
    2.22 +        xswatch.xslock.acquire()
    2.23 +        xswatch.xs.watch(path, self)
    2.24 +        xswatch.xslock.release()
    2.25 +        xswatch.watches.append(self)
    2.26 +
    2.27 +    def watchStart(cls):
    2.28 +        cls.threadcond.acquire()
    2.29 +        if cls.watchThread:
    2.30 +            cls.threadcond.release()
    2.31 +            return
    2.32 +        cls.watchThread = threading.Thread(name="Watcher",
    2.33 +                                           target=cls.watchMain)
    2.34 +        cls.watchThread.setDaemon(True)
    2.35 +        cls.watchThread.start()
    2.36 +        while cls.xs == None:
    2.37 +            cls.threadcond.wait()
    2.38 +        cls.threadcond.release()
    2.39 +
    2.40 +    watchStart = classmethod(watchStart)
    2.41 +
    2.42 +    def watchMain(cls):
    2.43 +        cls.threadcond.acquire()
    2.44 +        cls.xs = xs.open()
    2.45 +        cls.threadcond.notifyAll()
    2.46 +        cls.threadcond.release()
    2.47 +        while True:
    2.48 +            try:
    2.49 +                (ord, owr, oer) = select.select([ cls.xs ], [], [])
    2.50 +                cls.xslock.acquire()
    2.51 +                # reconfirm ready to read with lock
    2.52 +                (ord, owr, oer) = select.select([ cls.xs ], [], [], 0.001)
    2.53 +                if not cls.xs in ord:
    2.54 +                    cls.xslock.release()
    2.55 +                    continue
    2.56 +                we = cls.xs.read_watch()
    2.57 +                watch = we[1]
    2.58 +                cls.xs.acknowledge_watch(watch)
    2.59 +                cls.xslock.release()
    2.60 +            except RuntimeError, ex:
    2.61 +                print ex
    2.62 +                raise
    2.63 +            watch.fn(*watch.args, **watch.kwargs)
    2.64 +
    2.65 +    watchMain = classmethod(watchMain)