On Wed, Jun 15, 2011 at 09:23:17PM -0400, Cole Robinson wrote: > > Signed-off-by: Cole Robinson <crobinso@xxxxxxxxxx> > --- > 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@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list