[libvirt] [PATCH 08/10] python: Add bindings for virEvent*Handle/Timeout

Cole Robinson crobinso at redhat.com
Thu Jun 16 01:23:17 UTC 2011


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




More information about the libvir-list mailing list