mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 03:25:20 +00:00
Introduce virStreamSendHole
This API is used to tell the other side of the stream to skip some bytes in the stream. This can be used to create a sparse file on the receiving side of a stream. It takes @length argument, which says how big the hole is. This skipping is done from the current point of stream. Since our streams are not rewindable like regular files, we don't need @whence argument like seek(2) has. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
65b9cd6797
commit
69a573d010
@ -50,6 +50,10 @@ int virStreamRecvFlags(virStreamPtr st,
|
||||
size_t nbytes,
|
||||
unsigned int flags);
|
||||
|
||||
int virStreamSendHole(virStreamPtr st,
|
||||
long long length,
|
||||
unsigned int flags);
|
||||
|
||||
|
||||
/**
|
||||
* virStreamSourceFunc:
|
||||
|
@ -41,6 +41,11 @@ typedef int
|
||||
size_t nbytes,
|
||||
unsigned int flags);
|
||||
|
||||
typedef int
|
||||
(*virDrvStreamSendHole)(virStreamPtr st,
|
||||
long long length,
|
||||
unsigned int flags);
|
||||
|
||||
typedef int
|
||||
(*virDrvStreamEventAddCallback)(virStreamPtr stream,
|
||||
int events,
|
||||
@ -68,6 +73,7 @@ struct _virStreamDriver {
|
||||
virDrvStreamSend streamSend;
|
||||
virDrvStreamRecv streamRecv;
|
||||
virDrvStreamRecvFlags streamRecvFlags;
|
||||
virDrvStreamSendHole streamSendHole;
|
||||
virDrvStreamEventAddCallback streamEventAddCallback;
|
||||
virDrvStreamEventUpdateCallback streamEventUpdateCallback;
|
||||
virDrvStreamEventRemoveCallback streamEventRemoveCallback;
|
||||
|
@ -344,6 +344,67 @@ virStreamRecvFlags(virStreamPtr stream,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamSendHole:
|
||||
* @stream: pointer to the stream object
|
||||
* @length: number of bytes to skip
|
||||
* @flags: extra flags; not used yet, so callers should always pass 0
|
||||
*
|
||||
* Rather than transmitting empty file space, this API directs
|
||||
* the @stream target to create @length bytes of empty space.
|
||||
* This API would be used when uploading or downloading sparsely
|
||||
* populated files to avoid the needless copy of empty file
|
||||
* space.
|
||||
*
|
||||
* An example using this with a hypothetical file upload API
|
||||
* looks like:
|
||||
*
|
||||
* virStream st;
|
||||
*
|
||||
* while (1) {
|
||||
* char buf[4096];
|
||||
* size_t len;
|
||||
* if (..in hole...) {
|
||||
* ..get hole size...
|
||||
* virStreamSendHole(st, len, 0);
|
||||
* } else {
|
||||
* ...read len bytes...
|
||||
* virStreamSend(st, buf, len);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Returns 0 on success,
|
||||
* -1 error
|
||||
*/
|
||||
int
|
||||
virStreamSendHole(virStreamPtr stream,
|
||||
long long length,
|
||||
unsigned int flags)
|
||||
{
|
||||
VIR_DEBUG("stream=%p, length=%lld flags=%x",
|
||||
stream, length, flags);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
virCheckStreamReturn(stream, -1);
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamSendHole) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamSendHole)(stream, length, flags);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virReportUnsupportedError();
|
||||
|
||||
error:
|
||||
virDispatchError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamSendAll:
|
||||
* @stream: pointer to the stream object
|
||||
|
@ -762,6 +762,7 @@ LIBVIRT_3.1.0 {
|
||||
LIBVIRT_3.4.0 {
|
||||
global:
|
||||
virStreamRecvFlags;
|
||||
virStreamSendHole;
|
||||
} LIBVIRT_3.1.0;
|
||||
|
||||
# .... define new API here using predicted next version number ....
|
||||
|
Loading…
Reference in New Issue
Block a user