From fa47dad041bf9878702724dba9d0ca4152fab928 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Tue, 14 Jun 2011 16:07:43 -0400 Subject: python: Implement virStreamSend/Recv The return values for the python version are different that the C version of virStreamSend: on success we return a string, an error raises an exception, and if the stream would block we return int(-2). We need to do this since strings aren't passed by reference in python. --- generator.py | 9 ++++--- libvirt-override-virStream.py | 35 ++++++++++++++++++++++++ libvirt-override.c | 62 +++++++++++++++++++++++++++++++++++++++++++ typewrappers.c | 14 ++++++++++ typewrappers.h | 1 + 5 files changed, 117 insertions(+), 4 deletions(-) diff --git a/generator.py b/generator.py index cb4d8a4..315d3d4 100755 --- a/generator.py +++ b/generator.py @@ -348,8 +348,6 @@ skip_impl = ( 'virNWFilterGetUUID', 'virNWFilterGetUUIDString', 'virNWFilterLookupByUUID', - 'virStreamRecv', - 'virStreamSend', 'virStoragePoolGetUUID', 'virStoragePoolGetUUIDString', 'virStoragePoolLookupByUUID', @@ -393,9 +391,12 @@ skip_function = ( 'virConnectDomainEventDeregisterAny', # overridden in virConnect.py 'virSaveLastError', # We have our own python error wrapper 'virFreeError', # Only needed if we use virSaveLastError + 'virStreamFree', # Overridden in libvirt-override-virStream.py - 'virStreamRecvAll', - 'virStreamSendAll', + 'virStreamRecvAll', # XXX: Can be written in pure python? + 'virStreamSendAll', # XXX: Can be written in pure python? + 'virStreamRecv', # overridden in libvirt-override-virStream.py + 'virStreamSend', # overridden in libvirt-override-virStream.py # 'Ref' functions have no use for bindings users. "virConnectRef", diff --git a/libvirt-override-virStream.py b/libvirt-override-virStream.py index 56f1df5..f8a1d0b 100644 --- a/libvirt-override-virStream.py +++ b/libvirt-override-virStream.py @@ -24,3 +24,38 @@ cbData = {"stream": self, "cb" : cb, "opaque" : opaque} ret = libvirtmod.virStreamEventAddCallback(self._o, events, cbData) if ret == -1: raise libvirtError ('virStreamEventAddCallback() failed') + + def recv(self, nbytes): + """Write a series of bytes to the stream. This method may + block the calling application for an arbitrary amount + of time. + + Errors are not guaranteed to be reported synchronously + with the call, but may instead be delayed until a + subsequent call. + + On success, the received data is returned. On failure, an + exception is raised. If the stream is a NONBLOCK stream and + the request would block, integer -2 is returned. + """ + ret = libvirtmod.virStreamRecv(self._o, nbytes) + if ret == None: raise libvirtError ('virStreamRecv() failed') + return ret + + def send(self, data): + """Write a series of bytes to the stream. This method may + block the calling application for an arbitrary amount + of time. Once an application has finished sending data + it should call virStreamFinish to wait for successful + confirmation from the driver, or detect any error + + This method may not be used if a stream source has been + registered + + Errors are not guaranteed to be reported synchronously + with the call, but may instead be delayed until a + subsequent call. + """ + ret = libvirtmod.virStreamSend(self._o, data, len(data)) + if ret == -1: raise libvirtError ('virStreamSend() failed') + return ret diff --git a/libvirt-override.c b/libvirt-override.c index 55cb61c..63157b4 100644 --- a/libvirt-override.c +++ b/libvirt-override.c @@ -3697,6 +3697,66 @@ libvirt_virStreamEventAddCallback(PyObject *self ATTRIBUTE_UNUSED, return py_retval; } +static PyObject * +libvirt_virStreamRecv(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) +{ + PyObject *pyobj_stream; + virStreamPtr stream; + char *buf = NULL; + int ret; + int nbytes; + + if (!PyArg_ParseTuple(args, (char *) "Oi:virStreamRecv", + &pyobj_stream, &nbytes)) { + DEBUG("%s failed to parse tuple\n", __FUNCTION__); + return VIR_PY_NONE; + } + stream = PyvirStream_Get(pyobj_stream); + + if ((buf = malloc(nbytes+1 > 0 ? nbytes+1 : 1)) == NULL) + return VIR_PY_NONE; + + LIBVIRT_BEGIN_ALLOW_THREADS; + ret = virStreamRecv(stream, buf, nbytes); + LIBVIRT_END_ALLOW_THREADS; + + buf[ret > -1 ? ret : 0] = '\0'; + DEBUG("StreamRecv ret=%d strlen=%d\n", ret, (int) strlen(buf)); + + if (ret < 0) + return libvirt_intWrap(ret); + return libvirt_charPtrSizeWrap((char *) buf, (Py_ssize_t) ret); +} + +static PyObject * +libvirt_virStreamSend(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) +{ + PyObject *py_retval; + PyObject *pyobj_stream; + virStreamPtr stream; + char *data; + int ret; + int nbytes; + + if (!PyArg_ParseTuple(args, (char *) "Ozi:virStreamRecv", + &pyobj_stream, &data, &nbytes)) { + DEBUG("%s failed to parse tuple\n", __FUNCTION__); + return VIR_PY_INT_FAIL; + } + stream = PyvirStream_Get(pyobj_stream); + + LIBVIRT_BEGIN_ALLOW_THREADS; + ret = virStreamSend(stream, data, nbytes); + LIBVIRT_END_ALLOW_THREADS; + + DEBUG("StreamSend ret=%d\n", ret); + + py_retval = libvirt_intWrap(ret); + return py_retval; +} + /************************************************************************ * * * The registration stuff * @@ -3715,6 +3775,8 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virConnectDomainEventRegisterAny", libvirt_virConnectDomainEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventDeregisterAny", libvirt_virConnectDomainEventDeregisterAny, METH_VARARGS, NULL}, {(char *) "virStreamEventAddCallback", libvirt_virStreamEventAddCallback, METH_VARARGS, NULL}, + {(char *) "virStreamRecv", libvirt_virStreamRecv, METH_VARARGS, NULL}, + {(char *) "virStreamSend", libvirt_virStreamSend, METH_VARARGS, NULL}, {(char *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL}, {(char *) "virDomainGetState", libvirt_virDomainGetState, METH_VARARGS, NULL}, {(char *) "virDomainGetControlInfo", libvirt_virDomainGetControlInfo, METH_VARARGS, NULL}, diff --git a/typewrappers.c b/typewrappers.c index e39d3cd..b5758b4 100644 --- a/typewrappers.c +++ b/typewrappers.c @@ -76,6 +76,20 @@ libvirt_ulonglongWrap(unsigned long long val) return (ret); } +PyObject * +libvirt_charPtrSizeWrap(char *str, Py_ssize_t size) +{ + PyObject *ret; + + if (str == NULL) { + Py_INCREF(Py_None); + return (Py_None); + } + ret = PyString_FromStringAndSize(str, size); + free(str); + return (ret); +} + PyObject * libvirt_charPtrWrap(char *str) { diff --git a/typewrappers.h b/typewrappers.h index cc98110..305d594 100644 --- a/typewrappers.h +++ b/typewrappers.h @@ -156,6 +156,7 @@ PyObject * libvirt_ulongWrap(unsigned long val); PyObject * libvirt_longlongWrap(long long val); PyObject * libvirt_ulonglongWrap(unsigned long long val); PyObject * libvirt_charPtrWrap(char *str); +PyObject * libvirt_charPtrSizeWrap(char *str, Py_ssize_t size); PyObject * libvirt_constcharPtrWrap(const char *str); PyObject * libvirt_charPtrConstWrap(const char *str); PyObject * libvirt_virConnectPtrWrap(virConnectPtr node); -- cgit