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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
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@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

Attachment: signature.asc
Description: Digital signature

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]
  Powered by Linux