[libvirt] [PATCH 08/10] python: Add bindings for virEvent*Handle/Timeout
Daniel Veillard
veillard at redhat.com
Mon Jun 20 01:36:23 UTC 2011
On Wed, Jun 15, 2011 at 09:23:17PM -0400, Cole Robinson wrote:
>
> Signed-off-by: Cole Robinson <crobinso at redhat.com>
> ---
> python/generator.py | 11 +--
> python/libvirt-override.c | 192 +++++++++++++++++++++++++++++++++++++------
> python/libvirt-override.py | 54 ++++++++++++
> 3 files changed, 221 insertions(+), 36 deletions(-)
>
> diff --git a/python/generator.py b/python/generator.py
> index 745828b..2777c61 100755
> --- a/python/generator.py
> +++ b/python/generator.py
> @@ -198,7 +198,8 @@ skipped_types = {
> 'virConnectDomainEventIOErrorCallback': "No function types in python",
> 'virConnectDomainEventGraphicsCallback': "No function types in python",
> 'virStreamEventCallback': "No function types in python",
> - 'virEventAddHandleFunc': "No function types in python",
> + 'virEventHandleCallback': "No function types in python",
> + 'virEventTimeoutCallback': "No function types in python",
> }
>
> #######################################################################
> @@ -396,14 +397,6 @@ skip_function = (
> 'virStreamRecv', # overridden in libvirt-override-virStream.py
> 'virStreamSend', # overridden in libvirt-override-virStream.py
>
> - # XXX: Skip for now, some work needed to handle Timeout/Handle callbacks
> - 'virEventAddHandle',
> - 'virEventRemoveHandle',
> - 'virEventUpdateHandle',
> - 'virEventAddTimeout',
> - 'virEventRemoveTimeout',
> - 'virEventUpdateTimeout',
> -
> # 'Ref' functions have no use for bindings users.
> "virConnectRef",
> "virDomainRef",
> diff --git a/python/libvirt-override.c b/python/libvirt-override.c
> index 388c937..b000718 100644
> --- a/python/libvirt-override.c
> +++ b/python/libvirt-override.c
> @@ -59,7 +59,6 @@ static char *py_str(PyObject *obj)
> return PyString_AsString(str);
> }
>
> -
> /************************************************************************
> * *
> * Statistics *
> @@ -2499,6 +2498,30 @@ getLibvirtDomainClassObject (void) {
> Py_INCREF(libvirt_dom_class);
> return libvirt_dom_class;
> }
> +
> +static PyObject *
> +libvirt_lookupPythonFunc(const char *funcname)
> +{
> + PyObject *python_cb;
> +
> + /* Lookup the python callback */
> + python_cb = PyDict_GetItemString(getLibvirtDictObject(), funcname);
> +
> + if (!python_cb) {
> + DEBUG("%s: Error finding %s\n", __FUNCTION__, funcname);
> + PyErr_Print();
> + PyErr_Clear();
> + return NULL;
> + }
> +
> + if (!PyCallable_Check(python_cb)) {
> + DEBUG("%s: %s is not callable\n", __FUNCTION__, funcname);
> + return NULL;
> + }
> +
> + return python_cb;
> +}
> +
> /*******************************************
> * Domain Events
> *******************************************/
> @@ -2684,19 +2707,8 @@ libvirt_virEventAddHandleFunc (int fd,
> LIBVIRT_ENSURE_THREAD_STATE;
>
> /* Lookup the python callback */
> - python_cb = PyDict_GetItemString(getLibvirtDictObject(),
> - "eventInvokeHandleCallback");
> - if(!python_cb) {
> - DEBUG("%s: Error finding eventInvokeHandleCallback\n", __FUNCTION__);
> - PyErr_Print();
> - PyErr_Clear();
> - goto cleanup;
> - }
> - if (!PyCallable_Check(python_cb)) {
> - char *name ATTRIBUTE_UNUSED;
> - name = py_str(python_cb);
> - DEBUG("%s: %s is not callable\n", __FUNCTION__,
> - name ? name : "libvirt.eventInvokeHandleCallback");
> + python_cb = libvirt_lookupPythonFunc("eventInvokeHandleCallback");
> + if (!python_cb) {
> goto cleanup;
> }
> Py_INCREF(python_cb);
> @@ -2801,6 +2813,7 @@ libvirt_virEventRemoveHandleFunc(int watch)
> return retval;
> }
>
> +
> static int
> libvirt_virEventAddTimeoutFunc(int timeout,
> virEventTimeoutCallback cb,
> @@ -2821,19 +2834,8 @@ libvirt_virEventAddTimeoutFunc(int timeout,
> LIBVIRT_ENSURE_THREAD_STATE;
>
> /* Lookup the python callback */
> - python_cb = PyDict_GetItemString(getLibvirtDictObject(),
> - "eventInvokeTimeoutCallback");
> - if(!python_cb) {
> - DEBUG("%s: Error finding eventInvokeTimeoutCallback\n", __FUNCTION__);
> - PyErr_Print();
> - PyErr_Clear();
> - goto cleanup;
> - }
> - if (!PyCallable_Check(python_cb)) {
> - char *name ATTRIBUTE_UNUSED;
> - name = py_str(python_cb);
> - DEBUG("%s: %s is not callable\n", __FUNCTION__,
> - name ? name : "libvirt.eventInvokeTimeoutCallback");
> + python_cb = libvirt_lookupPythonFunc("eventInvokeTimeoutCallback");
> + if (!python_cb) {
> goto cleanup;
> }
> Py_INCREF(python_cb);
> @@ -3051,6 +3053,140 @@ libvirt_virEventInvokeTimeoutCallback(PyObject *self ATTRIBUTE_UNUSED,
> return VIR_PY_INT_SUCCESS;
> }
>
> +static void
> +libvirt_virEventHandleCallback(int watch,
> + int fd,
> + int events,
> + void *opaque)
> +{
> + PyObject *pyobj_cbData = (PyObject *)opaque;
> + PyObject *pyobj_ret;
> + PyObject *python_cb;
> +
> + LIBVIRT_ENSURE_THREAD_STATE;
> +
> + /* Lookup the python callback */
> + python_cb = libvirt_lookupPythonFunc("_dispatchEventHandleCallback");
> + if (!python_cb) {
> + goto cleanup;
> + }
> +
> + Py_INCREF(pyobj_cbData);
> +
> + /* Call the pure python dispatcher */
> + pyobj_ret = PyObject_CallFunction(python_cb,
> + (char *)"iiiO",
> + watch, fd, events, pyobj_cbData);
> +
> + Py_DECREF(pyobj_cbData);
> +
> + if (!pyobj_ret) {
> + DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
> + PyErr_Print();
> + } else {
> + Py_DECREF(pyobj_ret);
> + }
> +
> +cleanup:
> + LIBVIRT_RELEASE_THREAD_STATE;
> +}
> +
> +static PyObject *
> +libvirt_virEventAddHandle(PyObject *self ATTRIBUTE_UNUSED,
> + PyObject *args)
> +{
> + PyObject *py_retval;
> + PyObject *pyobj_cbData;
> + virEventHandleCallback cb = libvirt_virEventHandleCallback;
> + int events;
> + int fd;
> + int ret;
> +
> + if (!PyArg_ParseTuple(args, (char *) "iiO:virEventAddHandle",
> + &fd, &events, &pyobj_cbData)) {
> + DEBUG("%s failed to parse tuple\n", __FUNCTION__);
> + return VIR_PY_INT_FAIL;
> + }
> +
> + Py_INCREF(pyobj_cbData);
> +
> + LIBVIRT_BEGIN_ALLOW_THREADS;
> + ret = virEventAddHandle(fd, events, cb, pyobj_cbData, NULL);
> + LIBVIRT_END_ALLOW_THREADS;
> +
> + if (ret < 0) {
> + Py_DECREF(pyobj_cbData);
> + }
> +
> + py_retval = libvirt_intWrap(ret);
> + return py_retval;
> +}
> +
> +static void
> +libvirt_virEventTimeoutCallback(int timer,
> + void *opaque)
> +{
> + PyObject *pyobj_cbData = (PyObject *)opaque;
> + PyObject *pyobj_ret;
> + PyObject *python_cb;
> +
> + LIBVIRT_ENSURE_THREAD_STATE;
> +
> + /* Lookup the python callback */
> + python_cb = libvirt_lookupPythonFunc("_dispatchEventTimeoutCallback");
> + if (!python_cb) {
> + goto cleanup;
> + }
> +
> + Py_INCREF(pyobj_cbData);
> +
> + /* Call the pure python dispatcher */
> + pyobj_ret = PyObject_CallFunction(python_cb,
> + (char *)"iO",
> + timer, pyobj_cbData);
> +
> + Py_DECREF(pyobj_cbData);
> +
> + if (!pyobj_ret) {
> + DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
> + PyErr_Print();
> + } else {
> + Py_DECREF(pyobj_ret);
> + }
> +
> +cleanup:
> + LIBVIRT_RELEASE_THREAD_STATE;
> +}
> +
> +static PyObject *
> +libvirt_virEventAddTimeout(PyObject *self ATTRIBUTE_UNUSED,
> + PyObject *args)
> +{
> + PyObject *py_retval;
> + PyObject *pyobj_cbData;
> + virEventTimeoutCallback cb = libvirt_virEventTimeoutCallback;
> + int timeout;
> + int ret;
> +
> + if (!PyArg_ParseTuple(args, (char *) "iO:virEventAddTimeout",
> + &timeout, &pyobj_cbData)) {
> + DEBUG("%s failed to parse tuple\n", __FUNCTION__);
> + return VIR_PY_INT_FAIL;
> + }
> +
> + Py_INCREF(pyobj_cbData);
> +
> + LIBVIRT_BEGIN_ALLOW_THREADS;
> + ret = virEventAddTimeout(timeout, cb, pyobj_cbData, NULL);
> + LIBVIRT_END_ALLOW_THREADS;
> +
> + if (ret < 0) {
> + Py_DECREF(pyobj_cbData);
> + }
> +
> + py_retval = libvirt_intWrap(ret);
> + return py_retval;
> +}
>
> static void
> libvirt_virConnectDomainEventFreeFunc(void *opaque)
> @@ -3789,6 +3925,8 @@ static PyMethodDef libvirtMethods[] = {
> {(char *) "virStoragePoolGetUUIDString", libvirt_virStoragePoolGetUUIDString, METH_VARARGS, NULL},
> {(char *) "virStoragePoolLookupByUUID", libvirt_virStoragePoolLookupByUUID, METH_VARARGS, NULL},
> {(char *) "virEventRegisterImpl", libvirt_virEventRegisterImpl, METH_VARARGS, NULL},
> + {(char *) "virEventAddHandle", libvirt_virEventAddHandle, METH_VARARGS, NULL},
> + {(char *) "virEventAddTimeout", libvirt_virEventAddTimeout, METH_VARARGS, NULL},
> {(char *) "virEventInvokeHandleCallback", libvirt_virEventInvokeHandleCallback, METH_VARARGS, NULL},
> {(char *) "virEventInvokeTimeoutCallback", libvirt_virEventInvokeTimeoutCallback, METH_VARARGS, NULL},
> {(char *) "virNodeListDevices", libvirt_virNodeListDevices, METH_VARARGS, NULL},
> diff --git a/python/libvirt-override.py b/python/libvirt-override.py
> index d544a0e..b611ca4 100644
> --- a/python/libvirt-override.py
> +++ b/python/libvirt-override.py
> @@ -131,3 +131,57 @@ def eventInvokeTimeoutCallback (timer, callback, opaque):
> Invoke the Event Impl Timeout Callback in C
> """
> libvirtmod.virEventInvokeTimeoutCallback(timer, callback, opaque);
> +
> +def _dispatchEventHandleCallback(watch, fd, events, cbData):
> + cb = cbData["cb"]
> + opaque = cbData["opaque"]
> +
> + cb(watch, fd, events, opaque)
> + return 0
> +
> +def _dispatchEventTimeoutCallback(timer, cbData):
> + cb = cbData["cb"]
> + opaque = cbData["opaque"]
> +
> + cb(timer, opaque)
> + return 0
> +
> +def virEventAddHandle(fd, events, cb, opaque):
> + """
> + register a callback for monitoring file handle events
> +
> + @fd: file handle to monitor for events
> + @events: bitset of events to watch from virEventHandleType constants
> + @cb: callback to invoke when an event occurs
> + @opaque: user data to pass to callback
> +
> + Example callback prototype is:
> + def cb(watch, # int id of the handle
> + fd, # int file descriptor the event occured on
> + events, # int bitmap of events that have occured
> + opaque): # opaque data passed to eventAddHandle
> + """
> + cbData = {"cb" : cb, "opaque" : opaque}
> + ret = libvirtmod.virEventAddHandle(fd, events, cbData)
> + if ret == -1: raise libvirtError ('virEventAddHandle() failed')
> + return ret
> +
> +def virEventAddTimeout(timeout, cb, opaque):
> + """
> + register a callback for a timer event
> +
> + @timeout: time between events in milliseconds
> + @cb: callback to invoke when an event occurs
> + @opaque: user data to pass to callback
> +
> + Setting timeout to -1 will disable the timer. Setting the timeout
> + to zero will cause it to fire on every event loop iteration.
> +
> + Example callback prototype is:
> + def cb(timer, # int id of the timer
> + opaque): # opaque data passed to eventAddTimeout
> + """
> + cbData = {"cb" : cb, "opaque" : opaque}
> + ret = libvirtmod.virEventAddTimeout(timeout, cbData)
> + if ret == -1: raise libvirtError ('virEventAddTimeout() failed')
> + return ret
> --
> 1.7.4.4
Looks fine, libvirt_lookupPythonFunc() is a nice cleanup. It's a bit
hard to track the Py_DECREF/Py_INCREF, hopefully they are fine in all
cases (errro paths are hard for this),
ACK,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list