mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Extend xenbus/xenstore client interface to include a transaction
handle on appropriate operations. Next step is to plug this through to the store daemon and get rid of the nasty serialisation mutex for transactions. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
f2b39d8ae1
commit
25517fd2f2
22 files changed
+364
-223
No files matched your search
@@ -80,8 +80,8 @@ static inline PyObject *pyvalue_str(char *val) {
|
||||
|
||||
static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "path", NULL };
|
||||
static char *arg_spec = "s|";
|
||||
static char *kwd_spec[] = { "transaction", "path", NULL };
|
||||
static char *arg_spec = "ss";
|
||||
char *path = NULL;
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
@@ -89,13 +89,19 @@ static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
unsigned int xsval_n = 0;
|
||||
PyObject *val = NULL;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&path))
|
||||
&thstr, &path))
|
||||
goto exit;
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_read(xh, path, &xsval_n);
|
||||
xsval = xs_read(xh, th, path, &xsval_n);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
if (errno == ENOENT) {
|
||||
@@ -123,8 +129,8 @@ static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
|
||||
static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "path", "data", NULL };
|
||||
static char *arg_spec = "ss#";
|
||||
static char *kwd_spec[] = { "transaction", "path", "data", NULL };
|
||||
static char *arg_spec = "sss#";
|
||||
char *path = NULL;
|
||||
char *data = NULL;
|
||||
int data_n = 0;
|
||||
@@ -133,13 +139,19 @@ static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
PyObject *val = NULL;
|
||||
int xsval = 0;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&path, &data, &data_n))
|
||||
&thstr, &path, &data, &data_n))
|
||||
goto exit;
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_write(xh, path, data, data_n);
|
||||
xsval = xs_write(xh, th, path, data, data_n);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
PyErr_SetFromErrno(PyExc_RuntimeError);
|
||||
@@ -162,8 +174,8 @@ static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
|
||||
static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "path", NULL };
|
||||
static char *arg_spec = "s|";
|
||||
static char *kwd_spec[] = { "transaction", "path", NULL };
|
||||
static char *arg_spec = "ss";
|
||||
char *path = NULL;
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
@@ -172,12 +184,20 @@ static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
unsigned int xsval_n = 0;
|
||||
int i;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&thstr, &path))
|
||||
goto exit;
|
||||
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_directory(xh, path, &xsval_n);
|
||||
xsval = xs_directory(xh, th, path, &xsval_n);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
if (errno == ENOENT) {
|
||||
@@ -205,20 +225,27 @@ static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
|
||||
static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "path", NULL };
|
||||
static char *arg_spec = "s|";
|
||||
static char *kwd_spec[] = { "transaction", "path", NULL };
|
||||
static char *arg_spec = "ss";
|
||||
char *path = NULL;
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
PyObject *val = NULL;
|
||||
int xsval = 0;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&thstr, &path))
|
||||
goto exit;
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_mkdir(xh, path);
|
||||
xsval = xs_mkdir(xh, th, path);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
PyErr_SetFromErrno(PyExc_RuntimeError);
|
||||
@@ -240,20 +267,27 @@ static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
|
||||
static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "path", NULL };
|
||||
static char *arg_spec = "s|";
|
||||
static char *kwd_spec[] = { "transaction", "path", NULL };
|
||||
static char *arg_spec = "ss";
|
||||
char *path = NULL;
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
PyObject *val = NULL;
|
||||
int xsval = 0;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&thstr, &path))
|
||||
goto exit;
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_rm(xh, path);
|
||||
xsval = xs_rm(xh, th, path);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval && errno != ENOENT) {
|
||||
PyErr_SetFromErrno(PyExc_RuntimeError);
|
||||
@@ -276,8 +310,8 @@ static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "path", NULL };
|
||||
static char *arg_spec = "s|";
|
||||
static char *kwd_spec[] = { "transaction", "path", NULL };
|
||||
static char *arg_spec = "ss";
|
||||
char *path = NULL;
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
@@ -286,12 +320,19 @@ static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
|
||||
unsigned int perms_n = 0;
|
||||
int i;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&thstr, &path))
|
||||
goto exit;
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
perms = xs_get_permissions(xh, path, &perms_n);
|
||||
perms = xs_get_permissions(xh, th, path, &perms_n);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!perms) {
|
||||
PyErr_SetFromErrno(PyExc_RuntimeError);
|
||||
@@ -321,8 +362,8 @@ static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
|
||||
static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "path", "perms", NULL };
|
||||
static char *arg_spec = "sO";
|
||||
static char *kwd_spec[] = { "transaction", "path", "perms", NULL };
|
||||
static char *arg_spec = "ssO";
|
||||
char *path = NULL;
|
||||
PyObject *perms = NULL;
|
||||
static char *perm_names[] = { "dom", "read", "write", NULL };
|
||||
@@ -335,11 +376,17 @@ static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
|
||||
PyObject *tuple0 = NULL;
|
||||
PyObject *val = NULL;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&path, &perms))
|
||||
&thstr, &path, &perms))
|
||||
goto exit;
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
if (!PyList_Check(perms)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
|
||||
goto exit;
|
||||
@@ -369,7 +416,7 @@ static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
|
||||
xsperms[i].perms |= XS_PERM_WRITE;
|
||||
}
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
|
||||
xsval = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
PyErr_SetFromErrno(PyExc_RuntimeError);
|
||||
@@ -543,9 +590,8 @@ static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
|
||||
#define xspy_transaction_start_doc "\n" \
|
||||
"Start a transaction.\n" \
|
||||
"Only one transaction can be active at a time.\n" \
|
||||
"\n" \
|
||||
"Returns None on success.\n" \
|
||||
"Returns transaction handle on success.\n" \
|
||||
"Raises RuntimeError on error.\n" \
|
||||
"\n"
|
||||
|
||||
@@ -558,21 +604,23 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
PyObject *val = NULL;
|
||||
int xsval = 0;
|
||||
struct xs_transaction_handle *th;
|
||||
char thstr[20];
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
|
||||
goto exit;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_transaction_start(xh);
|
||||
th = xs_transaction_start(xh);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
if (th == NULL) {
|
||||
PyErr_SetFromErrno(PyExc_RuntimeError);
|
||||
goto exit;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
val = Py_None;
|
||||
|
||||
sprintf(thstr, "%lX", (unsigned long)th);
|
||||
val = PyString_FromString(thstr);
|
||||
exit:
|
||||
return val;
|
||||
}
|
||||
@@ -589,20 +637,27 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
|
||||
static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "abort", NULL };
|
||||
static char *arg_spec = "|i";
|
||||
static char *kwd_spec[] = { "transaction", "abort", NULL };
|
||||
static char *arg_spec = "s|i";
|
||||
int abort = 0;
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
PyObject *val = NULL;
|
||||
int xsval = 0;
|
||||
|
||||
struct xs_transaction_handle *th;
|
||||
char *thstr;
|
||||
|
||||
if (!xh)
|
||||
goto exit;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
|
||||
&thstr, &abort))
|
||||
goto exit;
|
||||
|
||||
th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
xsval = xs_transaction_end(xh, abort);
|
||||
xsval = xs_transaction_end(xh, th, abort);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (!xsval) {
|
||||
if (errno == EAGAIN) {
|
||||
|
||||
@@ -14,29 +14,34 @@ from xen.xend.xenstore.xsutil import xshandle
|
||||
class xstransact:
|
||||
|
||||
def __init__(self, path):
|
||||
self.in_transaction = False
|
||||
self.path = path.rstrip("/")
|
||||
xshandle().transaction_start()
|
||||
self.transaction = xshandle().transaction_start()
|
||||
self.in_transaction = True
|
||||
|
||||
def __del__(self):
|
||||
if self.in_transaction:
|
||||
xshandle().transaction_end(True)
|
||||
xshandle().transaction_end(self.transaction, True)
|
||||
|
||||
def commit(self):
|
||||
if not self.in_transaction:
|
||||
raise RuntimeError
|
||||
self.in_transaction = False
|
||||
return xshandle().transaction_end(False)
|
||||
rc = xshandle().transaction_end(self.transaction, False)
|
||||
self.transaction = "0"
|
||||
return rc
|
||||
|
||||
def abort(self):
|
||||
if not self.in_transaction:
|
||||
return True
|
||||
self.in_transaction = False
|
||||
return xshandle().transaction_end(True)
|
||||
rc = xshandle().transaction_end(self.transaction, True)
|
||||
self.transaction = "0"
|
||||
return rc
|
||||
|
||||
def _read(self, key):
|
||||
path = "%s/%s" % (self.path, key)
|
||||
try:
|
||||
return xshandle().read(path)
|
||||
return xshandle().read(self.transaction, path)
|
||||
except RuntimeError, ex:
|
||||
raise RuntimeError(ex.args[0],
|
||||
'%s, while reading %s' % (ex.args[1], path))
|
||||
@@ -50,7 +55,7 @@ class xstransact:
|
||||
instead.
|
||||
"""
|
||||
if len(args) == 0:
|
||||
return xshandle().read(self.path)
|
||||
return xshandle().read(self.transaction, self.path)
|
||||
if len(args) == 1:
|
||||
return self._read(args[0])
|
||||
ret = []
|
||||
@@ -61,7 +66,7 @@ class xstransact:
|
||||
def _write(self, key, data):
|
||||
path = "%s/%s" % (self.path, key)
|
||||
try:
|
||||
xshandle().write(path, data)
|
||||
xshandle().write(self.transaction, path, data)
|
||||
except RuntimeError, ex:
|
||||
raise RuntimeError(ex.args[0],
|
||||
('%s, while writing %s : %s' %
|
||||
@@ -93,7 +98,7 @@ class xstransact:
|
||||
|
||||
def _remove(self, key):
|
||||
path = "%s/%s" % (self.path, key)
|
||||
return xshandle().rm(path)
|
||||
return xshandle().rm(self.transaction, path)
|
||||
|
||||
def remove(self, *args):
|
||||
"""If no arguments are given, remove this transaction's path.
|
||||
@@ -101,14 +106,14 @@ class xstransact:
|
||||
path, and remove each of those instead.
|
||||
"""
|
||||
if len(args) == 0:
|
||||
xshandle().rm(self.path)
|
||||
xshandle().rm(self.transaction, self.path)
|
||||
else:
|
||||
for key in args:
|
||||
self._remove(key)
|
||||
|
||||
def _list(self, key):
|
||||
path = "%s/%s" % (self.path, key)
|
||||
l = xshandle().ls(path)
|
||||
l = xshandle().ls(self.transaction, path)
|
||||
if l:
|
||||
return map(lambda x: key + "/" + x, l)
|
||||
return []
|
||||
@@ -120,7 +125,7 @@ class xstransact:
|
||||
path, and return the cumulative listing of each of those instead.
|
||||
"""
|
||||
if len(args) == 0:
|
||||
ret = xshandle().ls(self.path)
|
||||
ret = xshandle().ls(self.transaction, self.path)
|
||||
if ret is None:
|
||||
return []
|
||||
else:
|
||||
@@ -136,11 +141,11 @@ class xstransact:
|
||||
ret = []
|
||||
for key in keys:
|
||||
new_subdir = subdir + "/" + key
|
||||
l = xshandle().ls(new_subdir)
|
||||
l = xshandle().ls(self.transaction, new_subdir)
|
||||
if l:
|
||||
ret.append([key, self.list_recursive_(new_subdir, l)])
|
||||
else:
|
||||
ret.append([key, xshandle().read(new_subdir)])
|
||||
ret.append([key, xshandle().read(self.transaction, new_subdir)])
|
||||
return ret
|
||||
|
||||
|
||||
|
||||