2018-11-20 10:59:35 +03:00
def __del__ ( self ) - > None :
2009-07-10 15:18:12 +04:00
try :
if self . cb :
libvirtmod . virStreamEventRemoveCallback ( self . _o )
except AttributeError :
2018-11-20 10:34:48 +03:00
pass
2009-07-10 15:18:12 +04:00
2013-08-22 13:16:03 +04:00
if self . _o is not None :
2009-07-10 15:18:12 +04:00
libvirtmod . virStreamFree ( self . _o )
self . _o = None
2018-11-20 10:59:35 +03:00
def _dispatchStreamEventCallback ( self , events : int , cbData : Dict [ str , Any ] ) - > int :
2011-06-14 21:49:22 +04:00
"""
Dispatches events to python user ' s stream event callbacks
"""
cb = cbData [ " cb " ]
opaque = cbData [ " opaque " ]
cb ( self , events , opaque )
return 0
2018-11-20 10:59:35 +03:00
def eventAddCallback ( self , events : int , cb : Callable [ [ ' virStream ' , int , _T ] , None ] , opaque : _T ) - > None :
2011-06-14 21:49:22 +04:00
self . cb = cb
2018-11-20 10:34:48 +03:00
cbData = { " stream " : self , " cb " : cb , " opaque " : opaque }
2011-06-14 21:49:22 +04:00
ret = libvirtmod . virStreamEventAddCallback ( self . _o , events , cbData )
2018-11-20 10:34:48 +03:00
if ret == - 1 :
raise libvirtError ( ' virStreamEventAddCallback() failed ' )
2011-06-15 00:07:43 +04:00
2018-11-20 10:59:35 +03:00
def recvAll ( self , handler : Callable [ [ ' virStream ' , bytes , _T ] , int ] , opaque : _T ) - > None :
2011-06-16 00:54:16 +04:00
""" Receive the entire data stream, sending the data to the
requested data sink . This is simply a convenient alternative
2014-02-13 12:46:19 +04:00
to virStreamRecv , for apps that do blocking - I / O .
2011-06-16 00:54:16 +04:00
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 :
2020-07-03 13:30:00 +03:00
got = self . recv ( virStorageVol . streamBufSize )
2011-06-16 00:54:16 +04:00
if got == - 2 :
raise libvirtError ( " cannot use recvAll with "
" nonblocking stream " )
if len ( got ) == 0 :
break
try :
ret = handler ( self , got , opaque )
2018-11-21 11:50:39 +03:00
if isinstance ( ret , int ) and ret < 0 :
2011-06-16 00:54:16 +04:00
raise RuntimeError ( " recvAll handler returned %d " % ret )
2020-04-27 11:29:24 +03:00
except BaseException :
2011-06-16 00:54:16 +04:00
try :
self . abort ( )
2020-04-27 11:29:24 +03:00
except Exception :
2011-06-16 00:54:16 +04:00
pass
2020-04-27 11:54:33 +03:00
raise
2011-06-16 00:54:16 +04:00
2018-11-20 10:59:35 +03:00
def sendAll ( self , handler : Callable [ [ ' virStream ' , int , _T ] , bytes ] , opaque : _T ) - > None :
2011-06-16 00:54:16 +04:00
"""
Send the entire data stream , reading the data from the
requested data source . This is simply a convenient alternative
2014-02-13 12:46:19 +04:00
to virStreamSend , for apps that do blocking - I / O .
2011-06-16 00:54:16 +04:00
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 :
2020-07-03 13:30:00 +03:00
got = handler ( self , virStorageVol . streamBufSize , opaque )
2020-04-27 11:29:24 +03:00
except BaseException :
2011-06-16 00:54:16 +04:00
try :
self . abort ( )
2020-04-27 11:29:24 +03:00
except Exception :
2011-06-16 00:54:16 +04:00
pass
2020-04-27 11:54:33 +03:00
raise
2011-06-16 00:54:16 +04:00
2017-05-05 17:39:34 +03:00
if not got :
2011-06-16 00:54:16 +04:00
break
ret = self . send ( got )
if ret == - 2 :
2012-02-01 11:00:12 +04:00
raise libvirtError ( " cannot use sendAll with "
2011-06-16 00:54:16 +04:00
" nonblocking stream " )
2018-11-20 10:59:35 +03:00
def recv ( self , nbytes : int ) - > bytes :
2011-10-31 20:11:33 +04:00
""" Reads a series of bytes from the stream. This method may
2011-06-15 00:07:43 +04:00
block the calling application for an arbitrary amount
of time .
Errors are not guaranteed to be reported synchronously
with the call , but may instead be delayed until a
subsequent call .
On success , the received data is returned . On failure , an
exception is raised . If the stream is a NONBLOCK stream and
the request would block , integer - 2 is returned .
"""
ret = libvirtmod . virStreamRecv ( self . _o , nbytes )
2018-11-20 10:34:48 +03:00
if ret is None :
raise libvirtError ( ' virStreamRecv() failed ' )
2011-06-15 00:07:43 +04:00
return ret
2018-11-20 10:59:35 +03:00
def send ( self , data : bytes ) - > int :
2011-06-15 00:07:43 +04:00
""" Write a series of bytes to the stream. This method may
block the calling application for an arbitrary amount
of time . Once an application has finished sending data
it should call virStreamFinish to wait for successful
confirmation from the driver , or detect any error
This method may not be used if a stream source has been
registered
Errors are not guaranteed to be reported synchronously
with the call , but may instead be delayed until a
subsequent call .
"""
2014-01-23 18:24:12 +04:00
ret = libvirtmod . virStreamSend ( self . _o , data )
2018-11-20 10:34:48 +03:00
if ret == - 1 :
raise libvirtError ( ' virStreamSend() failed ' )
2011-06-15 00:07:43 +04:00
return ret
2017-05-22 08:57:26 +03:00
2018-11-20 10:59:35 +03:00
def recvHole ( self , flags : int = 0 ) - > int :
2017-05-22 08:57:26 +03:00
""" This method is used to determine the length in bytes
of the empty space to be created in a stream ' s target
file when uploading or downloading sparsely populated
files . This is the counterpart to sendHole .
"""
ret = libvirtmod . virStreamRecvHole ( self . _o , flags )
2018-11-20 10:34:48 +03:00
if ret is None :
raise libvirtError ( ' virStreamRecvHole() failed ' )
2017-05-22 08:57:26 +03:00
return ret
2018-11-20 10:59:35 +03:00
def sendHole ( self , length : int , flags : int = 0 ) - > int :
2017-05-22 08:57:26 +03:00
""" Rather than transmitting empty file space, this method
directs the stream target to create length bytes of empty
space . This method would be used when uploading or
downloading sparsely populated files to avoid the
needless copy of empty file space .
"""
ret = libvirtmod . virStreamSendHole ( self . _o , length , flags )
2018-11-20 10:34:48 +03:00
if ret == - 1 :
raise libvirtError ( ' virStreamSendHole() failed ' )
2017-05-22 08:57:26 +03:00
return ret
2017-05-22 09:25:23 +03:00
2018-11-20 10:59:35 +03:00
def recvFlags ( self , nbytes : int , flags : int = 0 ) - > Union [ bytes , int ] :
2017-05-22 09:25:23 +03:00
""" Reads a series of bytes from the stream. This method may
block the calling application for an arbitrary amount
of time . This is just like recv except it has flags
argument .
Errors are not guaranteed to be reported synchronously
with the call , but may instead be delayed until a
subsequent call .
On success , the received data is returned . On failure , an
exception is raised . If the stream is a NONBLOCK stream and
the request would block , integer - 2 is returned .
"""
ret = libvirtmod . virStreamRecvFlags ( self . _o , nbytes , flags )
2018-11-20 10:34:48 +03:00
if ret is None :
raise libvirtError ( ' virStreamRecvFlags() failed ' )
2017-05-22 09:25:23 +03:00
return ret
2017-05-22 12:09:46 +03:00
2018-11-20 10:59:35 +03:00
def sparseRecvAll ( self , handler : Callable [ [ ' virStream ' , bytes , _T ] , Union [ bytes , int ] ] , holeHandler : Callable [ [ ' virStream ' , int , _T ] , Optional [ int ] ] , opaque : _T ) - > None :
2017-05-22 12:09:46 +03:00
""" 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 :
2020-07-03 13:30:00 +03:00
want = virStorageVol . streamBufSize
2017-05-22 12:09:46 +03:00
got = self . recvFlags ( want , VIR_STREAM_RECV_STOP_AT_HOLE )
if got == - 2 :
raise libvirtError ( " cannot use sparseRecvAll with "
" nonblocking stream " )
2020-04-20 12:47:33 +03:00
elif got == - 3 :
2017-05-22 12:09:46 +03:00
length = self . recvHole ( )
if length is None :
self . abort ( )
raise RuntimeError ( " recvHole handler failed " )
2018-11-21 11:26:08 +03:00
ret_hole = holeHandler ( self , length , opaque )
2018-11-21 11:50:39 +03:00
if isinstance ( ret_hole , int ) and ret_hole < 0 :
2017-05-22 12:09:46 +03:00
self . abort ( )
2018-11-21 11:26:08 +03:00
raise RuntimeError ( " holeHandler handler returned %d " % ret_hole )
2017-05-22 12:09:46 +03:00
continue
2020-04-20 12:47:33 +03:00
elif isinstance ( got , int ) :
raise ValueError ( got )
elif not isinstance ( got , bytes ) :
raise TypeError ( type ( got ) )
2017-05-22 12:09:46 +03:00
if len ( got ) == 0 :
break
2018-11-21 11:26:08 +03:00
ret_data = handler ( self , got , opaque )
2018-11-21 11:50:39 +03:00
if isinstance ( ret_data , int ) and ret_data < 0 :
2017-05-22 12:09:46 +03:00
self . abort ( )
2018-11-21 11:26:08 +03:00
raise RuntimeError ( " sparseRecvAll handler returned %d " % ret_data )
2017-05-22 12:09:46 +03:00
2018-11-20 10:59:35 +03:00
def sparseSendAll ( self , handler : Callable [ [ ' virStream ' , int , _T ] , Union [ bytes , int ] ] , holeHandler : Callable [ [ ' virStream ' , _T ] , Tuple [ bool , int ] ] , skipHandler : Callable [ [ ' virStream ' , int , _T ] , int ] , opaque : _T ) - > None :
2017-05-22 12:09:46 +03:00
""" 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 )
2018-11-21 11:08:32 +03:00
if not inData and sectionLen > 0 :
2017-05-22 12:09:46 +03:00
if ( self . sendHole ( sectionLen ) < 0 or
skipHandler ( self , sectionLen , opaque ) < 0 ) :
self . abort ( )
continue
2020-07-03 13:30:00 +03:00
want = virStorageVol . streamBufSize
2017-05-22 12:09:46 +03:00
if ( want > sectionLen ) :
want = sectionLen
got = handler ( self , want , opaque )
2018-11-21 11:50:39 +03:00
if isinstance ( got , int ) and got < 0 :
2017-05-22 12:09:46 +03:00
self . abort ( )
2018-05-16 11:24:34 +03:00
raise RuntimeError ( " sparseSendAll handler returned %d " % got )
2017-05-22 12:09:46 +03:00
if not got :
break
2018-11-20 10:59:35 +03:00
assert isinstance ( got , bytes )
2017-05-22 12:09:46 +03:00
ret = self . send ( got )
if ret == - 2 :
raise libvirtError ( " cannot use sparseSendAll with "
" nonblocking stream " )