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

Michal Privoznik mprivozn at redhat.com
Mon May 22 10:57:14 UTC 2017


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 | 117 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)

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..568bd9f 100644
--- a/libvirt-override-virStream.py
+++ b/libvirt-override-virStream.py
@@ -164,3 +164,120 @@
         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.
+
+        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")
+                try:
+                   ret = holeHandler(self, length, opaque)
+                except:
+                    self.abort()
+                continue
+
+            if len(got) == 0:
+                break
+
+            try:
+                ret = handler(self, got, opaque)
+                if type(ret) is int and ret < 0:
+                    raise RuntimeError("recvAll handler returned %d" % ret)
+            except Exception:
+                e = sys.exc_info()[1]
+                try:
+                    self.abort()
+                except:
+                    pass
+                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.
+
+        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:
+            try:
+                [inData, sectionLen] = holeHandler(self, opaque)
+                if (inData == False and sectionLen > 0):
+                    self.sendHole(sectionLen)
+                    skipHandler(self, sectionLen, opaque)
+                    continue
+            except:
+                self.abort()
+
+            want = 64 * 1024
+            if (want > sectionLen):
+                want = sectionLen
+
+            try:
+                got = handler(self, want, opaque)
+            except:
+                e = sys.exc_info()[1]
+                try:
+                    self.abort()
+                except:
+                    pass
+                raise e
+
+            if not got:
+                break
+
+            ret = self.send(got)
+            if ret == -2:
+                raise libvirtError("cannot use sendAll with "
+                                   "nonblocking stream")
-- 
2.13.0




More information about the libvir-list mailing list