[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