* [PATCH v3 0/3] python: Add non-blocking Xenstore watch bindings
@ 2017-09-22 16:21 Euan Harris
2017-09-22 16:21 ` [PATCH v3 1/3] python: Add binding for xs_fileno() Euan Harris
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Euan Harris @ 2017-09-22 16:21 UTC (permalink / raw)
To: xen-devel; +Cc: Euan Harris, marmarek
Expose xs_fileno() and xs_check_watch() to Python. These functions
make it posible to write event-driven Xenstore clients in Python:
#!/usr/bin/env python
import xen.lowlevel.xs
import sys
import errno
from select import select
import time
# Connect to XenStore and set watch
xsh = xen.lowlevel.xs.xs()
xsh.watch("/foo", "footoken")
xsh.watch("/bar", "bartoken")
# Start polling loop
xsfd = xsh.fileno()
while True:
readable, writable, exceptional = select([xsfd], [], [xsfd], 1.0)
print "%d tick" % time.time()
if readable:
while True:
watch = xsh.check_watch()
if not watch:
break
path, token = watch
print "%d watch fired: path=%s, token=%s" % (time.time(),
path, token)
value = xsh.read("", path)
print "%d read %s = %s" % (time.time(), path, value)
if exceptional:
print "select error"
The polling loop can be simplified further by wrapping the call to
xsh.check_watch() in a generator, but this is easier to do in Python
than in the C bindings.
Euan Harris (3):
python: Add binding for xs_fileno()
python: Extract registered watch search logic from xspy_read_watch()
python: Add binding for non-blocking xs_check_watch()
tools/python/xen/lowlevel/xs/xs.c | 108 ++++++++++++++++++++++++++++++--------
1 file changed, 85 insertions(+), 23 deletions(-)
--
1.8.3.1
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 1/3] python: Add binding for xs_fileno()
2017-09-22 16:21 [PATCH v3 0/3] python: Add non-blocking Xenstore watch bindings Euan Harris
@ 2017-09-22 16:21 ` Euan Harris
2017-09-22 17:50 ` Marek Marczykowski-Górecki
2017-09-22 16:21 ` [PATCH v3 2/3] python: Extract registered watch search logic from xspy_read_watch() Euan Harris
2017-09-22 16:21 ` [PATCH v3 3/3] python: Add binding for non-blocking xs_check_watch() Euan Harris
2 siblings, 1 reply; 6+ messages in thread
From: Euan Harris @ 2017-09-22 16:21 UTC (permalink / raw)
To: xen-devel; +Cc: Euan Harris, marmarek
xs_fileno() returns a file descriptor which receives events when Xenstore
watches fire. Exposing this in the Python bindings is a prerequisite
for writing event-driven clients in Python.
Signed-off-by: Euan Harris <euan.harris@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
Changed since v2:
* Use PyLong_FromLong instead of PyInt_FromLong
---
tools/python/xen/lowlevel/xs/xs.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c
index aba5a20..3a827b0 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -453,6 +453,25 @@ static PyObject *xspy_watch(XsHandle *self, PyObject *args)
}
+#define xspy_fileno_doc "\n" \
+ "Return the FD to poll for notifications when watches fire.\n" \
+ "Returns: [int] file descriptor.\n" \
+ "\n"
+
+static PyObject *xspy_fileno(XsHandle *self)
+{
+ struct xs_handle *xh = xshandle(self);
+ int fd;
+
+ if (!xh)
+ return NULL;
+
+ fd = xs_fileno(xh);
+
+ return PyLong_FromLong(fd);
+}
+
+
#define xspy_read_watch_doc "\n" \
"Read a watch notification.\n" \
"\n" \
@@ -887,6 +906,7 @@ static PyMethodDef xshandle_methods[] = {
XSPY_METH(release_domain, METH_VARARGS),
XSPY_METH(close, METH_NOARGS),
XSPY_METH(get_domain_path, METH_VARARGS),
+ XSPY_METH(fileno, METH_NOARGS),
{ NULL /* Sentinel. */ },
};
--
1.8.3.1
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 2/3] python: Extract registered watch search logic from xspy_read_watch()
2017-09-22 16:21 [PATCH v3 0/3] python: Add non-blocking Xenstore watch bindings Euan Harris
2017-09-22 16:21 ` [PATCH v3 1/3] python: Add binding for xs_fileno() Euan Harris
@ 2017-09-22 16:21 ` Euan Harris
2017-09-22 16:21 ` [PATCH v3 3/3] python: Add binding for non-blocking xs_check_watch() Euan Harris
2 siblings, 0 replies; 6+ messages in thread
From: Euan Harris @ 2017-09-22 16:21 UTC (permalink / raw)
To: xen-devel; +Cc: Euan Harris, marmarek
When a watch fires, xspy_read_watch() checks whether the client has
registered interest in the path which changed and, if so, returns the
path and a client-supplied token. The binding for xs_check_watch()
needs to do the same, so this patch extracts the search code into a
separate function.
Signed-off-by: Euan Harris <euan.harris@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
Changed since v1:
* Remove stray newline
* Fix indentation
---
tools/python/xen/lowlevel/xs/xs.c | 60 ++++++++++++++++++++++++---------------
1 file changed, 37 insertions(+), 23 deletions(-)
diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c
index 3a827b0..e7c3bd0 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -77,6 +77,8 @@ static inline struct xs_handle *xshandle(XsHandle *self)
static void remove_watch(XsHandle *xsh, PyObject *token);
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval);
+
static PyObject *none(bool result);
static int parse_transaction_path(XsHandle *self, PyObject *args,
@@ -484,8 +486,6 @@ static PyObject *xspy_read_watch(XsHandle *self, PyObject *args)
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
char **xsval;
- PyObject *token;
- int i;
unsigned int num;
if (!xh)
@@ -497,29 +497,16 @@ again:
Py_END_ALLOW_THREADS
if (!xsval) {
PyErr_SetFromErrno(xs_error);
- goto exit;
- }
- if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)&token) != 1) {
- xs_set_error(EINVAL);
- goto exit;
- }
- for (i = 0; i < PyList_Size(self->watches); i++) {
- if (token == PyList_GetItem(self->watches, i))
- break;
- }
- if (i == PyList_Size(self->watches)) {
- /* We do not have a registered watch for the one that has just fired.
- Ignore this -- a watch that has been recently deregistered can still
- have watches in transit. This is a blocking method, so go back to
- read again.
- */
- free(xsval);
- goto again;
+ return val;
}
- /* Create tuple (path, token). */
- val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
- exit:
+
+ val = match_watch_by_token(self, xsval);
free(xsval);
+
+ if (!val && errno == EAGAIN) {
+ goto again;
+ }
+
return val;
}
@@ -868,6 +855,33 @@ static int parse_transaction_path(XsHandle *self, PyObject *args,
}
+static PyObject *match_watch_by_token(XsHandle *self, char **xsval)
+{
+ PyObject *token;
+ int i;
+
+ if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)&token) != 1) {
+ xs_set_error(EINVAL);
+ return NULL;
+ }
+ for (i = 0; i < PyList_Size(self->watches); i++) {
+ if (token == PyList_GetItem(self->watches, i))
+ break;
+ }
+ if (i == PyList_Size(self->watches)) {
+ /* We do not have a registered watch for the one that has just fired.
+ Ignore this -- a watch that has been recently deregistered can still
+ have watches in transit.
+ */
+ xs_set_error(EAGAIN);
+ return NULL;
+ }
+
+ /* Create tuple (path, token). */
+ return Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
+}
+
+
static PyObject *none(bool result)
{
if (result) {
--
1.8.3.1
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v3 3/3] python: Add binding for non-blocking xs_check_watch()
2017-09-22 16:21 [PATCH v3 0/3] python: Add non-blocking Xenstore watch bindings Euan Harris
2017-09-22 16:21 ` [PATCH v3 1/3] python: Add binding for xs_fileno() Euan Harris
2017-09-22 16:21 ` [PATCH v3 2/3] python: Extract registered watch search logic from xspy_read_watch() Euan Harris
@ 2017-09-22 16:21 ` Euan Harris
2 siblings, 0 replies; 6+ messages in thread
From: Euan Harris @ 2017-09-22 16:21 UTC (permalink / raw)
To: xen-devel; +Cc: Euan Harris, marmarek
xs_check_watch() checks for watch notifications without blocking.
Together with the binding for xs_fileno(), this makes it possible
to write event-driven clients in Python.
Signed-off-by: Euan Harris <euan.harris@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
tools/python/xen/lowlevel/xs/xs.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c
index e7c3bd0..9a0acfc 100644
--- a/tools/python/xen/lowlevel/xs/xs.c
+++ b/tools/python/xen/lowlevel/xs/xs.c
@@ -474,6 +474,33 @@ static PyObject *xspy_fileno(XsHandle *self)
}
+#define xspy_check_watch_doc "\n" \
+ "Check for watch notifications without blocking.\n" \
+ "\n" \
+ "Returns: [tuple] (path, token).\n" \
+ " None if no watches have fired.\n" \
+ "Raises xen.lowlevel.xs.Error on error.\n" \
+ "\n"
+
+static PyObject *xspy_check_watch(XsHandle *self, PyObject *args)
+{
+ struct xs_handle *xh = xshandle(self);
+ PyObject *val = NULL;
+ char **xsval;
+
+ if (!xh)
+ return NULL;
+
+ xsval = xs_check_watch(xh);
+ if (!xsval) {
+ return none(errno == EAGAIN);
+ }
+
+ val = match_watch_by_token(self, xsval);
+ free(xsval);
+ return val;
+}
+
#define xspy_read_watch_doc "\n" \
"Read a watch notification.\n" \
"\n" \
@@ -911,6 +938,7 @@ static PyMethodDef xshandle_methods[] = {
XSPY_METH(set_permissions, METH_VARARGS),
XSPY_METH(watch, METH_VARARGS),
XSPY_METH(read_watch, METH_NOARGS),
+ XSPY_METH(check_watch, METH_NOARGS),
XSPY_METH(unwatch, METH_VARARGS),
XSPY_METH(transaction_start, METH_NOARGS),
XSPY_METH(transaction_end, METH_VARARGS | METH_KEYWORDS),
--
1.8.3.1
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/3] python: Add binding for xs_fileno()
2017-09-22 16:21 ` [PATCH v3 1/3] python: Add binding for xs_fileno() Euan Harris
@ 2017-09-22 17:50 ` Marek Marczykowski-Górecki
2017-09-25 8:40 ` Wei Liu
0 siblings, 1 reply; 6+ messages in thread
From: Marek Marczykowski-Górecki @ 2017-09-22 17:50 UTC (permalink / raw)
To: Euan Harris; +Cc: xen-devel
[-- Attachment #1.1: Type: text/plain, Size: 2069 bytes --]
On Fri, Sep 22, 2017 at 05:21:12PM +0100, Euan Harris wrote:
> xs_fileno() returns a file descriptor which receives events when Xenstore
> watches fire. Exposing this in the Python bindings is a prerequisite
> for writing event-driven clients in Python.
>
> Signed-off-by: Euan Harris <euan.harris@citrix.com>
> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
> ---
> Changed since v2:
> * Use PyLong_FromLong instead of PyInt_FromLong
> ---
> tools/python/xen/lowlevel/xs/xs.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c
> index aba5a20..3a827b0 100644
> --- a/tools/python/xen/lowlevel/xs/xs.c
> +++ b/tools/python/xen/lowlevel/xs/xs.c
> @@ -453,6 +453,25 @@ static PyObject *xspy_watch(XsHandle *self, PyObject *args)
> }
>
>
> +#define xspy_fileno_doc "\n" \
> + "Return the FD to poll for notifications when watches fire.\n" \
> + "Returns: [int] file descriptor.\n" \
> + "\n"
> +
> +static PyObject *xspy_fileno(XsHandle *self)
> +{
> + struct xs_handle *xh = xshandle(self);
> + int fd;
> +
> + if (!xh)
> + return NULL;
> +
> + fd = xs_fileno(xh);
> +
> + return PyLong_FromLong(fd);
> +}
> +
> +
> #define xspy_read_watch_doc "\n" \
> "Read a watch notification.\n" \
> "\n" \
> @@ -887,6 +906,7 @@ static PyMethodDef xshandle_methods[] = {
> XSPY_METH(release_domain, METH_VARARGS),
> XSPY_METH(close, METH_NOARGS),
> XSPY_METH(get_domain_path, METH_VARARGS),
> + XSPY_METH(fileno, METH_NOARGS),
> { NULL /* Sentinel. */ },
> };
>
--
Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
[-- Attachment #2: Type: text/plain, Size: 127 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/3] python: Add binding for xs_fileno()
2017-09-22 17:50 ` Marek Marczykowski-Górecki
@ 2017-09-25 8:40 ` Wei Liu
0 siblings, 0 replies; 6+ messages in thread
From: Wei Liu @ 2017-09-25 8:40 UTC (permalink / raw)
To: Marek Marczykowski-Górecki; +Cc: xen-devel, Euan Harris, Wei Liu
On Fri, Sep 22, 2017 at 07:50:04PM +0200, Marek Marczykowski-Górecki wrote:
> On Fri, Sep 22, 2017 at 05:21:12PM +0100, Euan Harris wrote:
> > xs_fileno() returns a file descriptor which receives events when Xenstore
> > watches fire. Exposing this in the Python bindings is a prerequisite
> > for writing event-driven clients in Python.
> >
> > Signed-off-by: Euan Harris <euan.harris@citrix.com>
> > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Reviewed-by: Wei Liu <wei.liu2@citrix.com>
>
> Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Thanks for the quick turnaround.
I've queued this series up for applying for 4.10.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-09-25 8:40 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-22 16:21 [PATCH v3 0/3] python: Add non-blocking Xenstore watch bindings Euan Harris
2017-09-22 16:21 ` [PATCH v3 1/3] python: Add binding for xs_fileno() Euan Harris
2017-09-22 17:50 ` Marek Marczykowski-Górecki
2017-09-25 8:40 ` Wei Liu
2017-09-22 16:21 ` [PATCH v3 2/3] python: Extract registered watch search logic from xspy_read_watch() Euan Harris
2017-09-22 16:21 ` [PATCH v3 3/3] python: Add binding for non-blocking xs_check_watch() Euan Harris
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.