mirror of
https://gitlab.com/libvirt/libvirt-python.git
synced 2025-07-29 19:41:52 +03:00
virStream: Introduce virStreamSparse{Recv,Send}All
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>
This commit is contained in:
@ -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
|
||||
|
@ -164,3 +164,106 @@
|
||||
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
|
||||
|
||||
ret = handler(self, got, opaque)
|
||||
if type(ret) is int and ret < 0:
|
||||
self.abort()
|
||||
raise RuntimeError("sparseRecvAll handler returned %d" % ret)
|
||||
|
||||
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
|
||||
|
||||
got = handler(self, want, opaque)
|
||||
if type(got) is int and got < 0:
|
||||
self.abort()
|
||||
raise RuntimeError("sparseSendAll handler returned %d" % ret)
|
||||
|
||||
if not got:
|
||||
break
|
||||
|
||||
ret = self.send(got)
|
||||
if ret == -2:
|
||||
raise libvirtError("cannot use sparseSendAll with "
|
||||
"nonblocking stream")
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user