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@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:
+ 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)
+ except Exception as e:
+ self.abort()
+ raise e
+
+ 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@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
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@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@redhat.com >https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.