mirror of
https://gitlab.com/libvirt/libvirt-python.git
synced 2025-08-03 08:21:58 +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
|
'virStreamRecvHole', # overridden in libvirt-override-virStream.py
|
||||||
'virStreamSendHole', # overridden in libvirt-override-virStream.py
|
'virStreamSendHole', # overridden in libvirt-override-virStream.py
|
||||||
'virStreamRecvFlags', # 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
|
'virConnectUnregisterCloseCallback', # overridden in virConnect.py
|
||||||
'virConnectRegisterCloseCallback', # overridden in virConnect.py
|
'virConnectRegisterCloseCallback', # overridden in virConnect.py
|
||||||
|
@ -164,3 +164,106 @@
|
|||||||
ret = libvirtmod.virStreamRecvFlags(self._o, nbytes, flags)
|
ret = libvirtmod.virStreamRecvFlags(self._o, nbytes, flags)
|
||||||
if ret is None: raise libvirtError ('virStreamRecvFlags() failed')
|
if ret is None: raise libvirtError ('virStreamRecvFlags() failed')
|
||||||
return ret
|
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
|
# These aren't functions, they're callback signatures
|
||||||
if name in ["virConnectAuthCallbackPtr", "virConnectCloseFunc",
|
if name in ["virConnectAuthCallbackPtr", "virConnectCloseFunc",
|
||||||
"virStreamSinkFunc", "virStreamSourceFunc", "virStreamEventCallback",
|
"virStreamSinkFunc", "virStreamSourceFunc", "virStreamEventCallback",
|
||||||
"virEventHandleCallback", "virEventTimeoutCallback", "virFreeCallback"]:
|
"virEventHandleCallback", "virEventTimeoutCallback", "virFreeCallback",
|
||||||
|
"virStreamSinkHoleFunc", "virStreamSourceHoleFunc", "virStreamSourceSkipFunc"]:
|
||||||
continue
|
continue
|
||||||
if name[0:21] == "virConnectDomainEvent" and name[-8:] == "Callback":
|
if name[0:21] == "virConnectDomainEvent" and name[-8:] == "Callback":
|
||||||
continue
|
continue
|
||||||
@ -373,7 +374,8 @@ for name in sorted(finalklassmap):
|
|||||||
|
|
||||||
# These exist in C and exist in python, but we've got
|
# These exist in C and exist in python, but we've got
|
||||||
# a pure-python impl so don't check them
|
# a pure-python impl so don't check them
|
||||||
if name in ["virStreamRecvAll", "virStreamSendAll"]:
|
if name in ["virStreamRecvAll", "virStreamSendAll",
|
||||||
|
"virStreamSparseRecvAll", "virStreamSparseSendAll"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
Reference in New Issue
Block a user