[libvirt] [libvirt-python][PATCH v2 3/4] virStream: Introduce virStreamSparse{Recv, Send}All

Martin Kletzander mkletzan at redhat.com
Tue May 23 15:17:05 UTC 2017


On Tue, May 23, 2017 at 04:26:10PM +0200, Michal Privoznik wrote:
>Yet again, our parser is not capable of generating proper
>wrapper. To be fair, this one wold be really tough anyway.
>
>Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>---
> generator.py                  |   2 +
> libvirt-override-virStream.py | 107 ++++++++++++++++++++++++++++++++++++++++++
> sanitytest.py                 |   6 ++-
> 3 files changed, 113 insertions(+), 2 deletions(-)
>
>diff --git a/generator.py b/generator.py
>index 0e07fc8..93d1dc3 100755
>--- a/generator.py
>+++ b/generator.py
>@@ -546,6 +546,8 @@ skip_function = (
>     'virStreamRecvHole', # overridden in libvirt-override-virStream.py
>     'virStreamSendHole', # overridden in libvirt-override-virStream.py
>     'virStreamRecvFlags', # overridden in libvirt-override-virStream.py
>+    'virStreamSparseRecvAll', # overridden in libvirt-override-virStream.py
>+    'virStreamSparseSendAll', # overridden in libvirt-override-virStream.py
>
>     'virConnectUnregisterCloseCallback', # overridden in virConnect.py
>     'virConnectRegisterCloseCallback', # overridden in virConnect.py
>diff --git a/libvirt-override-virStream.py b/libvirt-override-virStream.py
>index 66d2bf6..0ab7815 100644
>--- a/libvirt-override-virStream.py
>+++ b/libvirt-override-virStream.py
>@@ -164,3 +164,110 @@
>         ret = libvirtmod.virStreamRecvFlags(self._o, nbytes, flags)
>         if ret is None: raise libvirtError ('virStreamRecvFlags() failed')
>         return ret
>+
>+    def sparseRecvAll(self, handler, holeHandler, opaque):
>+        """Receive the entire data stream, sending the data to
>+        the requested data sink handler and calling the skip
>+        holeHandler to generate holes for sparse stream targets.
>+        This is simply a convenient alternative to recvFlags, for
>+        apps that do blocking-I/O and want to preserve sparseness.
>+
>+        Hypothetical callbacks can look like this:
>+
>+            def handler(stream, # virStream instance
>+                        buf,    # string containing received data
>+                        opaque): # extra data passed to sparseRecvAll as opaque
>+                fd = opaque
>+                return os.write(fd, buf)
>+
>+            def holeHandler(stream, # virStream instance
>+                            length, # number of bytes to skip
>+                            opaque): # extra data passed to sparseRecvAll as opaque
>+                fd = opaque
>+                cur = os.lseek(fd, length, os.SEEK_CUR)
>+                return os.ftruncate(fd, cur) # take this extra step to
>+                                             # actually allocate the hole
>+        """
>+        while True:
>+            want = 64 * 1024
>+            got = self.recvFlags(want, VIR_STREAM_RECV_STOP_AT_HOLE)
>+            if got == -2:
>+                raise libvirtError("cannot use sparseRecvAll with "
>+                                   "nonblocking stream")
>+            if got == -3:
>+                length = self.recvHole()
>+                if length is None:
>+                    self.abort()
>+                    raise RuntimeError("recvHole handler failed")
>+                ret = holeHandler(self, length, opaque)
>+                if type(ret) is int and ret < 0:
>+                    self.abort()
>+                    raise RuntimeError("holeHandler handler returned %d" % ret)
>+                continue
>+
>+            if len(got) == 0:
>+                break
>+
>+            try:
>+                ret = handler(self, got, opaque)
>+                if type(ret) is int and ret < 0:
>+                    raise RuntimeError("sparseRecvAll handler returned %d" % ret)
>+            except Exception as e:

What exception are you trying to catch here?  Exception means something
went wrong.

>+                self.abort()
>+                raise e
>+
>+    def sparseSendAll(self, handler, holeHandler, skipHandler, opaque):
>+        """Send the entire data stream, reading the data from the
>+        requested data source. This is simply a convenient
>+        alternative to virStreamSend, for apps that do
>+        blocking-I/O and want to preserve sparseness.
>+
>+        Hypothetical callbacks can look like this:
>+
>+            def handler(stream, # virStream instance
>+                        nbytes, # int amt of data to read
>+                        opaque): # extra data passed to sparseSendAll as opaque
>+                fd = opaque
>+                return os.read(fd, nbytes)
>+
>+            def holeHandler(stream, # virStream instance
>+                            opaque): # extra data passed to sparseSendAll as opaque
>+                fd = opaque
>+                cur = os.lseek(fd, 0, os.SEEK_CUR)
>+                # ... find out current section and its boundaries
>+                # and set inData = True/False and sectionLen correspondingly
>+                os.lseek(fd, cur, os.SEEK_SET)
>+                return [inData, sectionLen]
>+
>+            def skipHandler(stream, # virStream instance
>+                            length, # number of bytes to skip
>+                            opaque): # extra data passed to sparseSendAll as opaque
>+                fd = opaque
>+                return os.lseek(fd, length, os.SEEK_CUR)
>+
>+        """
>+        while True:
>+            [inData, sectionLen] = holeHandler(self, opaque)
>+            if (inData == False and sectionLen > 0):
>+                if (self.sendHole(sectionLen) < 0 or
>+                        skipHandler(self, sectionLen, opaque) < 0):
>+                    self.abort()
>+                continue
>+
>+            want = 64 * 1024
>+            if (want > sectionLen):
>+                want = sectionLen
>+
>+            try:
>+                got = handler(self, want, opaque)

Why not the same comparison to < 0?

>+            except Exception as e:
>+                self.abort()
>+                raise e
>+

Again, no need for the exception.

ACK if you change those exceptions to checks for that ret is int < 0

>+            if not got:
>+                break
>+
>+            ret = self.send(got)
>+            if ret == -2:
>+                raise libvirtError("cannot use sparseSendAll with "
>+                                   "nonblocking stream")
>diff --git a/sanitytest.py b/sanitytest.py
>index 7183baa..deec200 100644
>--- a/sanitytest.py
>+++ b/sanitytest.py
>@@ -167,7 +167,8 @@ for cname in wantfunctions:
>     # These aren't functions, they're callback signatures
>     if name in ["virConnectAuthCallbackPtr", "virConnectCloseFunc",
>                 "virStreamSinkFunc", "virStreamSourceFunc", "virStreamEventCallback",
>-                "virEventHandleCallback", "virEventTimeoutCallback", "virFreeCallback"]:
>+                "virEventHandleCallback", "virEventTimeoutCallback", "virFreeCallback",
>+                "virStreamSinkHoleFunc", "virStreamSourceHoleFunc", "virStreamSourceSkipFunc"]:
>         continue
>     if name[0:21] == "virConnectDomainEvent" and name[-8:] == "Callback":
>         continue
>@@ -373,7 +374,8 @@ for name in sorted(finalklassmap):
>
>     # These exist in C and exist in python, but we've got
>     # a pure-python impl so don't check them
>-    if name in ["virStreamRecvAll", "virStreamSendAll"]:
>+    if name in ["virStreamRecvAll", "virStreamSendAll",
>+            "virStreamSparseRecvAll", "virStreamSparseSendAll"]:
>         continue
>
>     try:
>--
>2.13.0
>
>--
>libvir-list mailing list
>libvir-list at redhat.com
>https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20170523/5f514238/attachment-0001.sig>


More information about the libvir-list mailing list