]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
python: Implement virStreamSend/RecvAll helpers
authorCole Robinson <crobinso@redhat.com>
Wed, 15 Jun 2011 20:54:16 +0000 (16:54 -0400)
committerCole Robinson <crobinso@redhat.com>
Tue, 21 Jun 2011 14:08:47 +0000 (10:08 -0400)
Pure python implementation. The handler callbacks have been altered
a bit compared to the C API: RecvAll doesn't pass length of the data read
since that can be trivially obtained from python string objects, and SendAll
requires the handler to return the string data to send rather than
store the data in a string pointer.

python/generator.py
python/libvirt-override-virStream.py

index 315d3d4beb375513c6df4f37f418b0eb9c2e93d5..7c843d719c7aafa7cc78ec498a206d9247062252 100755 (executable)
@@ -393,8 +393,8 @@ skip_function = (
     'virFreeError', # Only needed if we use virSaveLastError
 
     'virStreamFree', # Overridden in libvirt-override-virStream.py
-    'virStreamRecvAll', # XXX: Can be written in pure python?
-    'virStreamSendAll', # XXX: Can be written in pure python?
+    'virStreamRecvAll', # Pure python libvirt-override-virStream.py
+    'virStreamSendAll', # Pure python libvirt-override-virStream.py
     'virStreamRecv', # overridden in libvirt-override-virStream.py
     'virStreamSend', # overridden in libvirt-override-virStream.py
 
index f8a1d0b584c5a8f7e863339428bb9bc0fa6417a8..82e16488a82f347459d90e528e4e6c839cdc0af4 100644 (file)
         ret = libvirtmod.virStreamEventAddCallback(self._o, events, cbData)
         if ret == -1: raise libvirtError ('virStreamEventAddCallback() failed')
 
+    def recvAll(self, handler, opaque):
+        """Receive the entire data stream, sending the data to the
+        requested data sink. This is simply a convenient alternative
+        to virStreamRecv, for apps that do blocking-I/o.
+
+        A hypothetical handler function looks like:
+
+            def handler(stream, # virStream instance
+                        buf,    # string containing received data
+                        opaque): # extra data passed to recvAll as opaque
+                fd = opaque
+                return os.write(fd, buf)
+        """
+        while True:
+            got = self.recv(1024*64)
+            if got == -2:
+                raise libvirtError("cannot use recvAll with "
+                                   "nonblocking stream")
+            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:
+                try:
+                    self.abort()
+                except:
+                    pass
+                raise e
+
+    def sendAll(self, handler, 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.
+
+        A hypothetical handler function looks like:
+
+            def handler(stream, # virStream instance
+                        nbytes, # int amt of data to read
+                        opaque): # extra data passed to recvAll as opaque
+                fd = opaque
+                return os.read(fd, nbytes)
+        """
+        while True:
+            try:
+                got = handler(self, 1024*64, opaque)
+            except:
+                try:
+                    self.abort()
+                except:
+                    pass
+                raise e
+
+            if got == "":
+                break
+
+            ret = self.send(got)
+            if ret == -2:
+                raise libvirtError("cannot use recvAll with "
+                                   "nonblocking stream")
+
     def recv(self, nbytes):
         """Write a series of bytes to the stream. This method may
         block the calling application for an arbitrary amount