ia64/xen-unstable

changeset 7899:34d9095e79e3

Simplify the logic of each of the functions here, removing the many bizarre
uses of goto that reduce down to return NULL in any case, breaking the common
code out for returning values based upon the success or failure of an
operation, and the common code that parses transaction and path parameters,
used by xspy_read, xspy_ls, and xspy_mkdir. Break out also the common code
that removes a watch token from the XsHandle watches list.

Use bool rather than int for result values, where this matches the same use
by tools/xenstore/xs.c.

Added missing free in xspy_get_permissions.

Use PySequence_SetItem inside xs_watch, rather than Py_INCREF followed by
PyList_SetItem. If there is no None entry in the watches list, the code goes
on to append to the list using PyList_Append, and that call takes its own
reference rather than stealing one like PyList_SetItem. This means that we
were previously leaking a reference if the list was full and so PyList_Append
was necessary.

Use PySequence_SetItem rather than Py_INCREF/PyList_SetItem also where we are
using assigning Py_None into the list, for neatness.

Remove meaningless pipe from xspy_release_domain's arg_spec.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Nov 17 20:17:50 2005 +0100 (2005-11-17)
parents 80e393599413
children e710b125b4cf
files tools/python/xen/lowlevel/xs/xs.c
line diff
     1.1 --- a/tools/python/xen/lowlevel/xs/xs.c	Thu Nov 17 12:59:58 2005 +0100
     1.2 +++ b/tools/python/xen/lowlevel/xs/xs.c	Thu Nov 17 20:17:50 2005 +0100
     1.3 @@ -21,6 +21,7 @@
     1.4  
     1.5  #include <Python.h>
     1.6  
     1.7 +#include <stdbool.h>
     1.8  #include <stdio.h>
     1.9  #include <stdlib.h>
    1.10  #include <unistd.h>
    1.11 @@ -70,6 +71,17 @@ static inline PyObject *pyvalue_str(char
    1.12              : PyErr_SetFromErrno(PyExc_RuntimeError));
    1.13  }
    1.14  
    1.15 +static void remove_watch(XsHandle *xsh, PyObject *token);
    1.16 +
    1.17 +static PyObject *none(bool result);
    1.18 +
    1.19 +static int parse_transaction_path(PyObject *self, PyObject *args,
    1.20 +                                  PyObject *kwds,
    1.21 +                                  struct xs_handle **xh,
    1.22 +                                  struct xs_transaction_handle **th,
    1.23 +                                  char **path);
    1.24 +
    1.25 +
    1.26  #define xspy_read_doc "\n"			\
    1.27  	"Read data from a path.\n"		\
    1.28  	" path [string]: xenstore path\n"	\
    1.29 @@ -81,43 +93,30 @@ static inline PyObject *pyvalue_str(char
    1.30  
    1.31  static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
    1.32  {
    1.33 -    static char *kwd_spec[] = { "transaction", "path", NULL };
    1.34 -    static char *arg_spec = "ss";
    1.35 -    char *path = NULL;
    1.36 -
    1.37 -    struct xs_handle *xh = xshandle(self);
    1.38 -    char *xsval = NULL;
    1.39 -    unsigned int xsval_n = 0;
    1.40 -    PyObject *val = NULL;
    1.41 -
    1.42 +    struct xs_handle *xh;
    1.43      struct xs_transaction_handle *th;
    1.44 -    char *thstr;
    1.45 +    char *path;
    1.46  
    1.47 -    if (!xh)
    1.48 -        goto exit;
    1.49 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
    1.50 -                                     &thstr, &path))
    1.51 -        goto exit;
    1.52 +    char *xsval;
    1.53 +    unsigned int xsval_n;
    1.54  
    1.55 -    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
    1.56 +    if (!parse_transaction_path(self, args, kwds, &xh, &th, &path))
    1.57 +        return NULL;
    1.58  
    1.59      Py_BEGIN_ALLOW_THREADS
    1.60      xsval = xs_read(xh, th, path, &xsval_n);
    1.61      Py_END_ALLOW_THREADS
    1.62 -    if (!xsval) {
    1.63 -        if (errno == ENOENT) {
    1.64 -            Py_INCREF(Py_None);
    1.65 -            val = Py_None;
    1.66 -        } else
    1.67 -            PyErr_SetFromErrno(PyExc_RuntimeError);
    1.68 -        goto exit;
    1.69 +    if (xsval) {
    1.70 +        PyObject *val = PyString_FromStringAndSize(xsval, xsval_n);
    1.71 +        free(xsval);
    1.72 +        return val;
    1.73      }
    1.74 -    val = PyString_FromStringAndSize(xsval, xsval_n);
    1.75 - exit:
    1.76 -    free(xsval);
    1.77 -    return val;
    1.78 +    else {
    1.79 +        return none(errno == ENOENT);
    1.80 +    }
    1.81  }
    1.82  
    1.83 +
    1.84  #define xspy_write_doc "\n"					\
    1.85  	"Write data to a path.\n"				\
    1.86  	" path   [string] : xenstore path to write to\n."	\
    1.87 @@ -136,33 +135,27 @@ static PyObject *xspy_write(PyObject *se
    1.88      int data_n = 0;
    1.89  
    1.90      struct xs_handle *xh = xshandle(self);
    1.91 -    PyObject *val = NULL;
    1.92 -    int xsval = 0;
    1.93 +    bool result;
    1.94  
    1.95      struct xs_transaction_handle *th;
    1.96      char *thstr;
    1.97  
    1.98      if (!xh)
    1.99 -        goto exit;
   1.100 +        return NULL;
   1.101      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.102                                       &thstr, &path, &data, &data_n))
   1.103 -        goto exit;
   1.104 +        return NULL;
   1.105  
   1.106      th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   1.107  
   1.108      Py_BEGIN_ALLOW_THREADS
   1.109 -    xsval = xs_write(xh, th, path, data, data_n);
   1.110 +    result = xs_write(xh, th, path, data, data_n);
   1.111      Py_END_ALLOW_THREADS
   1.112 -    if (!xsval) {
   1.113 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.114 -        goto exit;
   1.115 -    }
   1.116 -    Py_INCREF(Py_None);
   1.117 -    val = Py_None;
   1.118 - exit:
   1.119 -    return val;
   1.120 +
   1.121 +    return none(result);
   1.122  }
   1.123  
   1.124 +
   1.125  #define xspy_ls_doc "\n"					\
   1.126  	"List a directory.\n"					\
   1.127  	" path [string]: path to list.\n"			\
   1.128 @@ -174,47 +167,34 @@ static PyObject *xspy_write(PyObject *se
   1.129  
   1.130  static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
   1.131  {
   1.132 -    static char *kwd_spec[] = { "transaction", "path", NULL };
   1.133 -    static char *arg_spec = "ss";
   1.134 -    char *path = NULL;
   1.135 -
   1.136 -    struct xs_handle *xh = xshandle(self);
   1.137 -    PyObject *val = NULL;
   1.138 -    char **xsval = NULL;
   1.139 -    unsigned int xsval_n = 0;
   1.140 -    int i;
   1.141 -
   1.142 +    struct xs_handle *xh;
   1.143      struct xs_transaction_handle *th;
   1.144 -    char *thstr;
   1.145 +    char *path;
   1.146  
   1.147 -    if (!xh)
   1.148 -        goto exit;
   1.149 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.150 -                                     &thstr, &path))
   1.151 -        goto exit;
   1.152 +    char **xsval;
   1.153 +    int xsval_n;
   1.154  
   1.155 -
   1.156 -    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   1.157 +    if (!parse_transaction_path(self, args, kwds, &xh, &th, &path))
   1.158 +        return NULL;
   1.159  
   1.160      Py_BEGIN_ALLOW_THREADS
   1.161      xsval = xs_directory(xh, th, path, &xsval_n);
   1.162      Py_END_ALLOW_THREADS
   1.163 -    if (!xsval) {
   1.164 -        if (errno == ENOENT) {
   1.165 -            Py_INCREF(Py_None);
   1.166 -            val = Py_None;
   1.167 -        } else
   1.168 -            PyErr_SetFromErrno(PyExc_RuntimeError);
   1.169 -	goto exit;
   1.170 +
   1.171 +    if (xsval) {
   1.172 +        int i;
   1.173 +        PyObject *val = PyList_New(xsval_n);
   1.174 +        for (i = 0; i < xsval_n; i++)
   1.175 +            PyList_SetItem(val, i, PyString_FromString(xsval[i]));
   1.176 +        free(xsval);
   1.177 +        return val;
   1.178      }
   1.179 -    val = PyList_New(xsval_n);
   1.180 -    for (i = 0; i < xsval_n; i++)
   1.181 -        PyList_SetItem(val, i, PyString_FromString(xsval[i]));
   1.182 -    free(xsval);
   1.183 - exit:
   1.184 -    return val;
   1.185 +    else {
   1.186 +        return none(errno == ENOENT);
   1.187 +    }
   1.188  }
   1.189  
   1.190 +
   1.191  #define xspy_mkdir_doc "\n"					\
   1.192  	"Make a directory.\n"					\
   1.193  	" path [string]: path to directory to create.\n"	\
   1.194 @@ -225,38 +205,23 @@ static PyObject *xspy_ls(PyObject *self,
   1.195  
   1.196  static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
   1.197  {
   1.198 -    static char *kwd_spec[] = { "transaction", "path", NULL };
   1.199 -    static char *arg_spec = "ss";
   1.200 -    char *path = NULL;
   1.201 -
   1.202 -    struct xs_handle *xh = xshandle(self);
   1.203 -    PyObject *val = NULL;
   1.204 -    int xsval = 0;
   1.205 -
   1.206 +    struct xs_handle *xh;
   1.207      struct xs_transaction_handle *th;
   1.208 -    char *thstr;
   1.209 +    char *path;
   1.210  
   1.211 -    if (!xh)
   1.212 -        goto exit;
   1.213 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.214 -                                     &thstr, &path))
   1.215 -        goto exit;
   1.216 +    bool result;
   1.217  
   1.218 -    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   1.219 +    if (!parse_transaction_path(self, args, kwds, &xh, &th, &path))
   1.220 +        return NULL;
   1.221  
   1.222      Py_BEGIN_ALLOW_THREADS
   1.223 -    xsval = xs_mkdir(xh, th, path);
   1.224 +    result = xs_mkdir(xh, th, path);
   1.225      Py_END_ALLOW_THREADS
   1.226 -    if (!xsval) {
   1.227 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.228 -        goto exit;
   1.229 -    }
   1.230 -    Py_INCREF(Py_None);
   1.231 -    val = Py_None;
   1.232 - exit:
   1.233 -    return val;
   1.234 +
   1.235 +    return none(result);
   1.236  }
   1.237  
   1.238 +
   1.239  #define xspy_rm_doc "\n"			\
   1.240  	"Remove a path.\n"			\
   1.241  	" path [string] : path to remove\n"	\
   1.242 @@ -267,38 +232,23 @@ static PyObject *xspy_mkdir(PyObject *se
   1.243  
   1.244  static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
   1.245  {
   1.246 -    static char *kwd_spec[] = { "transaction", "path", NULL };
   1.247 -    static char *arg_spec = "ss";
   1.248 -    char *path = NULL;
   1.249 -
   1.250 -    struct xs_handle *xh = xshandle(self);
   1.251 -    PyObject *val = NULL;
   1.252 -    int xsval = 0;
   1.253 -
   1.254 +    struct xs_handle *xh;
   1.255      struct xs_transaction_handle *th;
   1.256 -    char *thstr;
   1.257 +    char *path;
   1.258  
   1.259 -    if (!xh)
   1.260 -        goto exit;
   1.261 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.262 -                                     &thstr, &path))
   1.263 -        goto exit;
   1.264 +    bool result;
   1.265  
   1.266 -    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   1.267 +    if (!parse_transaction_path(self, args, kwds, &xh, &th, &path))
   1.268 +        return NULL;
   1.269  
   1.270      Py_BEGIN_ALLOW_THREADS
   1.271 -    xsval = xs_rm(xh, th, path);
   1.272 +    result = xs_rm(xh, th, path);
   1.273      Py_END_ALLOW_THREADS
   1.274 -    if (!xsval && errno != ENOENT) {
   1.275 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.276 -        goto exit;
   1.277 -    }
   1.278 -    Py_INCREF(Py_None);
   1.279 -    val = Py_None;
   1.280 - exit:
   1.281 -    return val;
   1.282 +
   1.283 +    return none(result || errno == ENOENT);
   1.284  }
   1.285  
   1.286 +
   1.287  #define xspy_get_permissions_doc "\n"		\
   1.288  	"Get the permissions for a path\n"	\
   1.289  	" path [string]: xenstore path.\n"	\
   1.290 @@ -315,7 +265,6 @@ static PyObject *xspy_get_permissions(Py
   1.291      char *path = NULL;
   1.292  
   1.293      struct xs_handle *xh = xshandle(self);
   1.294 -    PyObject *val = NULL;
   1.295      struct xs_permissions *perms;
   1.296      unsigned int perms_n = 0;
   1.297      int i;
   1.298 @@ -324,30 +273,34 @@ static PyObject *xspy_get_permissions(Py
   1.299      char *thstr;
   1.300  
   1.301      if (!xh)
   1.302 -        goto exit;
   1.303 +        return NULL;
   1.304      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.305                                       &thstr, &path))
   1.306 -        goto exit;
   1.307 +        return NULL;
   1.308  
   1.309      th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   1.310  
   1.311      Py_BEGIN_ALLOW_THREADS
   1.312      perms = xs_get_permissions(xh, th, path, &perms_n);
   1.313      Py_END_ALLOW_THREADS
   1.314 -    if (!perms) {
   1.315 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.316 -        goto exit;
   1.317 +
   1.318 +    if (perms) {
   1.319 +        PyObject *val = PyList_New(perms_n);
   1.320 +        for (i = 0; i < perms_n; i++, perms++) {
   1.321 +            PyObject *p = Py_BuildValue("{s:i,s:i,s:i}",
   1.322 +                                        "dom",  perms->id,
   1.323 +                                        "read", perms->perms & XS_PERM_READ,
   1.324 +                                        "write",perms->perms & XS_PERM_WRITE);
   1.325 +            PyList_SetItem(val, i, p);
   1.326 +        }
   1.327 +
   1.328 +        free(perms);
   1.329 +        return val;
   1.330      }
   1.331 -    val = PyList_New(perms_n);
   1.332 -    for (i = 0; i < perms_n; i++, perms++) {
   1.333 -        PyObject *p = Py_BuildValue("{s:i,s:i,s:i}",
   1.334 -                                    "dom",   perms->id,
   1.335 -                                    "read",  (perms->perms & XS_PERM_READ),
   1.336 -                                    "write",  (perms->perms & XS_PERM_WRITE));
   1.337 -        PyList_SetItem(val, i, p);
   1.338 +    else {
   1.339 +        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.340 +        return NULL;
   1.341      }
   1.342 - exit:
   1.343 -    return val;
   1.344  }
   1.345  
   1.346  #define xspy_set_permissions_doc "\n"		\
   1.347 @@ -370,7 +323,7 @@ static PyObject *xspy_set_permissions(Py
   1.348      static char *perm_spec = "i|iiii";
   1.349  
   1.350      struct xs_handle *xh = xshandle(self);
   1.351 -    int i, xsval;
   1.352 +    int i, result;
   1.353      struct xs_permissions *xsperms = NULL;
   1.354      int xsperms_n = 0;
   1.355      PyObject *tuple0 = NULL;
   1.356 @@ -416,9 +369,9 @@ static PyObject *xspy_set_permissions(Py
   1.357              xsperms[i].perms |= XS_PERM_WRITE;
   1.358      }
   1.359      Py_BEGIN_ALLOW_THREADS
   1.360 -    xsval = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
   1.361 +    result = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
   1.362      Py_END_ALLOW_THREADS
   1.363 -    if (!xsval) {
   1.364 +    if (!result) {
   1.365          PyErr_SetFromErrno(PyExc_RuntimeError);
   1.366          goto exit;
   1.367      }
   1.368 @@ -453,7 +406,7 @@ static PyObject *xspy_watch(PyObject *se
   1.369  
   1.370      XsHandle *xsh = (XsHandle *)self;
   1.371      struct xs_handle *xh = xshandle(self);
   1.372 -    int xsval = 0;
   1.373 +    int result = 0;
   1.374  
   1.375      if (!xh)
   1.376          return NULL;
   1.377 @@ -466,10 +419,9 @@ static PyObject *xspy_watch(PyObject *se
   1.378         races with xs_read_watch.
   1.379      */
   1.380  
   1.381 -    Py_INCREF(token);
   1.382      for (i = 0; i < PyList_Size(xsh->watches); i++) {
   1.383          if (PyList_GetItem(xsh->watches, i) == Py_None) {
   1.384 -            PyList_SetItem(xsh->watches, i, token);
   1.385 +            PySequence_SetItem(xsh->watches, i, token);
   1.386              break;
   1.387          }
   1.388      }
   1.389 @@ -478,24 +430,15 @@ static PyObject *xspy_watch(PyObject *se
   1.390  
   1.391      sprintf(token_str, "%li", (unsigned long)token);
   1.392      Py_BEGIN_ALLOW_THREADS
   1.393 -    xsval = xs_watch(xh, path, token_str);
   1.394 +    result = xs_watch(xh, path, token_str);
   1.395      Py_END_ALLOW_THREADS
   1.396 -    if (!xsval) {
   1.397 -        for (i = 0; i < PyList_Size(xsh->watches); i++) {
   1.398 -            if (PyList_GetItem(xsh->watches, i) == token) {
   1.399 -                Py_INCREF(Py_None);
   1.400 -                PyList_SetItem(xsh->watches, i,  Py_None);
   1.401 -                break;
   1.402 -            }
   1.403 -        }
   1.404 +
   1.405 +    if (!result)
   1.406 +        remove_watch(xsh, token);
   1.407  
   1.408 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.409 -        return NULL;
   1.410 -    }
   1.411 +    return none(result);
   1.412 +}
   1.413  
   1.414 -    Py_INCREF(Py_None);
   1.415 -    return Py_None;
   1.416 -}
   1.417  
   1.418  #define xspy_read_watch_doc "\n"				\
   1.419  	"Read a watch notification.\n"				\
   1.420 @@ -519,9 +462,10 @@ static PyObject *xspy_read_watch(PyObjec
   1.421      unsigned int num;
   1.422  
   1.423      if (!xh)
   1.424 -        goto exit;
   1.425 +        return NULL;
   1.426      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
   1.427 -        goto exit;
   1.428 +        return NULL;
   1.429 +
   1.430  again:
   1.431      Py_BEGIN_ALLOW_THREADS
   1.432      xsval = xs_read_watch(xh, &num);
   1.433 @@ -570,37 +514,25 @@ static PyObject *xspy_unwatch(PyObject *
   1.434      char *path = NULL;
   1.435      PyObject *token;
   1.436      char token_str[MAX_STRLEN(unsigned long) + 1];
   1.437 -    int i;
   1.438  
   1.439      XsHandle *xsh = (XsHandle *)self;
   1.440      struct xs_handle *xh = xshandle(self);
   1.441 -    PyObject *val = NULL;
   1.442 -    int xsval = 0;
   1.443 +    int result = 0;
   1.444  
   1.445      if (!xh)
   1.446 -        goto exit;
   1.447 +        return NULL;
   1.448      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
   1.449                                       &token))
   1.450 -        goto exit;
   1.451 +        return NULL;
   1.452 +
   1.453      sprintf(token_str, "%li", (unsigned long)token);
   1.454      Py_BEGIN_ALLOW_THREADS
   1.455 -    xsval = xs_unwatch(xh, path, token_str);
   1.456 +    result = xs_unwatch(xh, path, token_str);
   1.457      Py_END_ALLOW_THREADS
   1.458 -    if (!xsval)
   1.459 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.460 -    else {
   1.461 -        Py_INCREF(Py_None);
   1.462 -        val = Py_None;
   1.463 -    }
   1.464 -    for (i = 0; i < PyList_Size(xsh->watches); i++) {
   1.465 -        if (token == PyList_GetItem(xsh->watches, i)) {
   1.466 -            Py_INCREF(Py_None);
   1.467 -            PyList_SetItem(xsh->watches, i, Py_None);
   1.468 -            break;
   1.469 -        }
   1.470 -    }
   1.471 - exit:
   1.472 -    return val;
   1.473 +
   1.474 +    remove_watch(xsh, token);
   1.475 +
   1.476 +    return none(result);
   1.477  }
   1.478  
   1.479  #define xspy_transaction_start_doc "\n"				\
   1.480 @@ -618,26 +550,25 @@ static PyObject *xspy_transaction_start(
   1.481      char *path = NULL;
   1.482  
   1.483      struct xs_handle *xh = xshandle(self);
   1.484 -    PyObject *val = NULL;
   1.485      struct xs_transaction_handle *th;
   1.486      char thstr[20];
   1.487  
   1.488      if (!xh)
   1.489 -        goto exit;
   1.490 +        return NULL;
   1.491      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
   1.492 -        goto exit;
   1.493 +        return NULL;
   1.494 +
   1.495      Py_BEGIN_ALLOW_THREADS
   1.496      th = xs_transaction_start(xh);
   1.497      Py_END_ALLOW_THREADS
   1.498 +
   1.499      if (th == NULL) {
   1.500          PyErr_SetFromErrno(PyExc_RuntimeError);
   1.501 -        goto exit;
   1.502 +        return NULL;
   1.503      }
   1.504  
   1.505      sprintf(thstr, "%lX", (unsigned long)th);
   1.506 -    val = PyString_FromString(thstr);
   1.507 - exit:
   1.508 -    return val;
   1.509 +    return PyString_FromString(thstr);
   1.510  }
   1.511  
   1.512  #define xspy_transaction_end_doc "\n"					\
   1.513 @@ -657,38 +588,38 @@ static PyObject *xspy_transaction_end(Py
   1.514      int abort = 0;
   1.515  
   1.516      struct xs_handle *xh = xshandle(self);
   1.517 -    PyObject *val = NULL;
   1.518 -    int xsval = 0;
   1.519 +    bool result;
   1.520  
   1.521      struct xs_transaction_handle *th;
   1.522      char *thstr;
   1.523  
   1.524      if (!xh)
   1.525 -        goto exit;
   1.526 +        return NULL;
   1.527      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.528                                       &thstr, &abort))
   1.529 -        goto exit;
   1.530 +        return NULL;
   1.531  
   1.532      th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   1.533  
   1.534      Py_BEGIN_ALLOW_THREADS
   1.535 -    xsval = xs_transaction_end(xh, th, abort);
   1.536 +    result = xs_transaction_end(xh, th, abort);
   1.537      Py_END_ALLOW_THREADS
   1.538 -    if (!xsval) {
   1.539 -	if (errno == EAGAIN) {
   1.540 -	    Py_INCREF(Py_False);
   1.541 -	    val = Py_False;
   1.542 -	    goto exit;
   1.543 -	}
   1.544 +
   1.545 +    if (result) {
   1.546 +        Py_INCREF(Py_True);
   1.547 +        return Py_True;
   1.548 +    }
   1.549 +    else if (errno == EAGAIN) {
   1.550 +        Py_INCREF(Py_False);
   1.551 +        return Py_False;
   1.552 +    }
   1.553 +    else {
   1.554          PyErr_SetFromErrno(PyExc_RuntimeError);
   1.555 -        goto exit;
   1.556 +        return NULL;
   1.557      }
   1.558 -    Py_INCREF(Py_True);
   1.559 -    val = Py_True;
   1.560 - exit:
   1.561 -    return val;
   1.562  }
   1.563  
   1.564 +
   1.565  #define xspy_introduce_domain_doc "\n"					\
   1.566  	"Tell xenstore about a domain so it can talk to it.\n"		\
   1.567  	" dom  [int]   : domain id\n"					\
   1.568 @@ -709,27 +640,22 @@ static PyObject *xspy_introduce_domain(P
   1.569      unsigned int port = 0;
   1.570  
   1.571      struct xs_handle *xh = xshandle(self);
   1.572 -    PyObject *val = NULL;
   1.573 -    int xsval = 0;
   1.574 +    bool result = 0;
   1.575  
   1.576      if (!xh)
   1.577 -        goto exit;
   1.578 +        return NULL;
   1.579      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.580                                       &dom, &page, &port))
   1.581 -        goto exit;
   1.582 +        return NULL;
   1.583 +
   1.584      Py_BEGIN_ALLOW_THREADS
   1.585 -    xsval = xs_introduce_domain(xh, dom, page, port);
   1.586 +    result = xs_introduce_domain(xh, dom, page, port);
   1.587      Py_END_ALLOW_THREADS
   1.588 -    if (!xsval) {
   1.589 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.590 -        goto exit;
   1.591 -    }
   1.592 -    Py_INCREF(Py_None);
   1.593 -    val = Py_None;
   1.594 - exit:
   1.595 -    return val;
   1.596 +
   1.597 +    return none(result);
   1.598  }
   1.599  
   1.600 +
   1.601  #define xspy_release_domain_doc "\n"					\
   1.602  	"Tell xenstore to release its channel to a domain.\n"		\
   1.603  	"Unless this is done the domain will not be released.\n"	\
   1.604 @@ -743,31 +669,26 @@ static PyObject *xspy_release_domain(PyO
   1.605                                       PyObject *kwds)
   1.606  {
   1.607      static char *kwd_spec[] = { "dom", NULL };
   1.608 -    static char *arg_spec = "i|";
   1.609 +    static char *arg_spec = "i";
   1.610      domid_t dom;
   1.611  
   1.612      struct xs_handle *xh = xshandle(self);
   1.613 -    PyObject *val = NULL;
   1.614 -    int xsval = 0;
   1.615 +    bool result = 0;
   1.616  
   1.617      if (!xh)
   1.618 -        goto exit;
   1.619 +        return NULL;
   1.620      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.621                                       &dom))
   1.622 -        goto exit;
   1.623 +        return NULL;
   1.624 +
   1.625      Py_BEGIN_ALLOW_THREADS
   1.626 -    xsval = xs_release_domain(xh, dom);
   1.627 +    result = xs_release_domain(xh, dom);
   1.628      Py_END_ALLOW_THREADS
   1.629 -    if (!xsval) {
   1.630 -        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.631 -        goto exit;
   1.632 -    }
   1.633 -    Py_INCREF(Py_None);
   1.634 -    val = Py_None;
   1.635 - exit:
   1.636 -    return val;
   1.637 +
   1.638 +    return none(result);
   1.639  }
   1.640  
   1.641 +
   1.642  #define xspy_close_doc "\n"			\
   1.643  	"Close the connection to xenstore.\n"	\
   1.644  	"\n"					\
   1.645 @@ -783,25 +704,25 @@ static PyObject *xspy_close(PyObject *se
   1.646  
   1.647      XsHandle *xsh = (XsHandle *)self;
   1.648      struct xs_handle *xh = xshandle(self);
   1.649 -    PyObject *val = NULL;
   1.650  
   1.651      if (!xh)
   1.652 -        goto exit;
   1.653 +        return NULL;
   1.654      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
   1.655 -        goto exit;
   1.656 +        return NULL;
   1.657 +
   1.658      for (i = 0; i < PyList_Size(xsh->watches); i++) {
   1.659          /* TODO: xs_unwatch watches */
   1.660 -        Py_INCREF(Py_None);
   1.661 -        PyList_SetItem(xsh->watches, i, Py_None);
   1.662 +        PySequence_SetItem(xsh->watches, i, Py_None);
   1.663      }
   1.664 +
   1.665      xs_daemon_close(xh);
   1.666      xsh->xh = NULL;
   1.667 +
   1.668      Py_INCREF(Py_None);
   1.669 -    val = Py_None;
   1.670 - exit:
   1.671 -    return val;
   1.672 +    return Py_None;
   1.673  }
   1.674  
   1.675 +
   1.676  #define xspy_get_domain_path_doc "\n"			\
   1.677  	"Return store path of domain, whether or not the domain exists.\n" \
   1.678  	" domid [int]: domain id\n"			\
   1.679 @@ -819,30 +740,91 @@ static PyObject *xspy_get_domain_path(Py
   1.680  
   1.681      struct xs_handle *xh = xshandle(self);
   1.682      char *xsval = NULL;
   1.683 -    PyObject *val = NULL;
   1.684  
   1.685      if (!xh)
   1.686 -        goto exit;
   1.687 +        return NULL;
   1.688      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.689                                       &domid))
   1.690 -        goto exit;
   1.691 +        return NULL;
   1.692 +
   1.693      Py_BEGIN_ALLOW_THREADS
   1.694      xsval = xs_get_domain_path(xh, domid);
   1.695      Py_END_ALLOW_THREADS
   1.696 -    if (!xsval) {
   1.697 -        if (errno == ENOENT) {
   1.698 -            Py_INCREF(Py_None);
   1.699 -            val = Py_None;
   1.700 -        } else
   1.701 -            PyErr_SetFromErrno(PyExc_RuntimeError);
   1.702 -        goto exit;
   1.703 +
   1.704 +    if (xsval) {
   1.705 +        PyObject *val = PyString_FromString(xsval);
   1.706 +        free(xsval);
   1.707 +        return val;
   1.708 +    }
   1.709 +    else {
   1.710 +        return none(errno == ENOENT);
   1.711 +    }
   1.712 +}
   1.713 +
   1.714 +
   1.715 +/**
   1.716 + * Remove the given token from the watches list belonging to the given
   1.717 + * XsHandle, if present.
   1.718 + */
   1.719 +static void remove_watch(XsHandle *xsh, PyObject *token)
   1.720 +{
   1.721 +    int i;
   1.722 +
   1.723 +    for (i = 0; i < PyList_Size(xsh->watches); i++) {
   1.724 +        if (PyList_GetItem(xsh->watches, i) == token) {
   1.725 +            PySequence_SetItem(xsh->watches, i, Py_None);
   1.726 +            return;
   1.727 +        }
   1.728      }
   1.729 -    val = PyString_FromString(xsval);
   1.730 -    free(xsval);
   1.731 - exit:
   1.732 -    return val;
   1.733  }
   1.734  
   1.735 +
   1.736 +/**
   1.737 + * Parse transaction and path arguments from the given args and kwds,
   1.738 + * convert the given self value to an xs_handle, and return all three by
   1.739 + * reference.
   1.740 + * 
   1.741 + * @return 1 on success, in which case *xh, *th, and *path are valid, or 0 on
   1.742 + * failure.
   1.743 + */
   1.744 +static int parse_transaction_path(PyObject *self, PyObject *args,
   1.745 +                                  PyObject *kwds,
   1.746 +                                  struct xs_handle **xh,
   1.747 +                                  struct xs_transaction_handle **th,
   1.748 +                                  char **path)
   1.749 +{
   1.750 +    static char *arg_spec = "ss";
   1.751 +    static char *kwd_spec[] = { "transaction", "path", NULL };
   1.752 +    char *thstr;
   1.753 +
   1.754 +    *xh = xshandle(self);
   1.755 +
   1.756 +    if (!xh)
   1.757 +        return 0;
   1.758 +
   1.759 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   1.760 +                                     &thstr, path))
   1.761 +        return 0;
   1.762 +
   1.763 +    *th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   1.764 +
   1.765 +    return 1;
   1.766 +}
   1.767 +
   1.768 +
   1.769 +static PyObject *none(bool result)
   1.770 +{
   1.771 +    if (result) {
   1.772 +        Py_INCREF(Py_None);
   1.773 +        return Py_None;
   1.774 +    }
   1.775 +    else {
   1.776 +        PyErr_SetFromErrno(PyExc_RuntimeError);
   1.777 +        return NULL;
   1.778 +    }
   1.779 +}
   1.780 +
   1.781 +
   1.782  #define XSPY_METH(_name) {			\
   1.783      .ml_name  = #_name,				\
   1.784      .ml_meth  = (PyCFunction) xspy_ ## _name,	\
   1.785 @@ -871,9 +853,7 @@ static PyMethodDef xshandle_methods[] = 
   1.786  
   1.787  static PyObject *xshandle_getattr(PyObject *self, char *name)
   1.788  {
   1.789 -    PyObject *val = NULL;
   1.790 -    val = Py_FindMethod(xshandle_methods, self, name);
   1.791 -    return val;
   1.792 +    return Py_FindMethod(xshandle_methods, self, name);
   1.793  }
   1.794  
   1.795  static void xshandle_dealloc(PyObject *self)