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