mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
Add public API definition for data stream handling
* include/libvirt/libvirt.h.in: Public API contract for virStreamPtr object * src/libvirt_public.syms: Export data stream APIs * src/libvirt_private.syms: Export internal helper APIs * src/libvirt.c: Data stream API driver dispatch * src/datatypes.h, src/datatypes.c: Internal helpers for virStreamPtr object * src/driver.h: Define internal driver API for streams * .x-sc_avoid_write: Ignore src/libvirt.c because it trips up on comments including write() * python/Makefile.am: Add libvirt-override-virStream.py * python/generator.py: Add rules for virStreamPtr class * python/typewrappers.h, python/typewrappers.c: Wrapper for virStreamPtr * docs/libvirt-api.xml, docs/libvirt-refs.xml: Regenerate with new APIs
This commit is contained in:
parent
d9e66a62b4
commit
182eba1bc6
@ -1,3 +1,4 @@
|
||||
^src/libvirt\.c$
|
||||
^src/util/util\.c$
|
||||
^src/xen/xend_internal\.c$
|
||||
^daemon/libvirtd.c$
|
||||
|
@ -25,6 +25,7 @@
|
||||
<exports symbol='VIR_EVENT_HANDLE_READABLE' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_SHUTDOWN' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_SCHED_FIELD_UINT' type='enum'/>
|
||||
<exports symbol='VIR_STREAM_NONBLOCK' type='enum'/>
|
||||
<exports symbol='VIR_STORAGE_POOL_BUILDING' type='enum'/>
|
||||
<exports symbol='VIR_CRED_CNONCE' type='enum'/>
|
||||
<exports symbol='VIR_CRED_ECHOPROMPT' type='enum'/>
|
||||
@ -41,13 +42,15 @@
|
||||
<exports symbol='VIR_STORAGE_POOL_BUILD_REPAIR' type='enum'/>
|
||||
<exports symbol='VIR_CRED_LANGUAGE' type='enum'/>
|
||||
<exports symbol='VIR_CRED_NOECHOPROMPT' type='enum'/>
|
||||
<exports symbol='VIR_STREAM_EVENT_ERROR' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_EVENT_UNDEFINED' type='enum'/>
|
||||
<exports symbol='VIR_MIGRATE_LIVE' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_EVENT_STOPPED_DESTROYED' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_EVENT_DEFINED_ADDED' type='enum'/>
|
||||
<exports symbol='VIR_VCPU_BLOCKED' type='enum'/>
|
||||
<exports symbol='VIR_SECRET_USAGE_TYPE_NONE' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_EVENT_STARTED_MIGRATED' type='enum'/>
|
||||
<exports symbol='VIR_VCPU_BLOCKED' type='enum'/>
|
||||
<exports symbol='VIR_STREAM_EVENT_HANGUP' type='enum'/>
|
||||
<exports symbol='VIR_MEMORY_VIRTUAL' type='enum'/>
|
||||
<exports symbol='VIR_CRED_USERNAME' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_EVENT_RESUMED_UNPAUSED' type='enum'/>
|
||||
@ -77,6 +80,7 @@
|
||||
<exports symbol='VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_CRASHED' type='enum'/>
|
||||
<exports symbol='VIR_VCPU_RUNNING' type='enum'/>
|
||||
<exports symbol='VIR_STREAM_EVENT_WRITABLE' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_SCHED_FIELD_DOUBLE' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_SCHED_FIELD_LLONG' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_SCHED_FIELD_BOOLEAN' type='enum'/>
|
||||
@ -90,6 +94,7 @@
|
||||
<exports symbol='VIR_DOMAIN_EVENT_STOPPED_SAVED' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_EVENT_STOPPED_MIGRATED' type='enum'/>
|
||||
<exports symbol='VIR_STORAGE_POOL_INACTIVE' type='enum'/>
|
||||
<exports symbol='VIR_STREAM_EVENT_READABLE' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_XML_SECURE' type='enum'/>
|
||||
<exports symbol='VIR_DOMAIN_EVENT_SUSPENDED' type='enum'/>
|
||||
<exports symbol='virDomainBlockStatsStruct' type='typedef'/>
|
||||
@ -106,9 +111,11 @@
|
||||
<exports symbol='virEventHandleType' type='typedef'/>
|
||||
<exports symbol='virStoragePool' type='typedef'/>
|
||||
<exports symbol='virDomainEventType' type='typedef'/>
|
||||
<exports symbol='virStream' type='typedef'/>
|
||||
<exports symbol='virDomainInterfaceStatsStruct' type='typedef'/>
|
||||
<exports symbol='virStoragePoolInfo' type='typedef'/>
|
||||
<exports symbol='virSecret' type='typedef'/>
|
||||
<exports symbol='virStreamPtr' type='typedef'/>
|
||||
<exports symbol='virDomainState' type='typedef'/>
|
||||
<exports symbol='virDomain' type='typedef'/>
|
||||
<exports symbol='virDomainInterfaceStatsPtr' type='typedef'/>
|
||||
@ -126,11 +133,13 @@
|
||||
<exports symbol='virConnectPtr' type='typedef'/>
|
||||
<exports symbol='virStorageVol' type='typedef'/>
|
||||
<exports symbol='virNodeDevicePtr' type='typedef'/>
|
||||
<exports symbol='virStreamEventType' type='typedef'/>
|
||||
<exports symbol='virInterface' type='typedef'/>
|
||||
<exports symbol='virSchedParameter' type='typedef'/>
|
||||
<exports symbol='virConnectFlags' type='typedef'/>
|
||||
<exports symbol='virDomainEventDefinedDetailType' type='typedef'/>
|
||||
<exports symbol='virInterfacePtr' type='typedef'/>
|
||||
<exports symbol='virStreamFlags' type='typedef'/>
|
||||
<exports symbol='virDomainMemoryFlags' type='typedef'/>
|
||||
<exports symbol='virDomainEventStoppedDetailType' type='typedef'/>
|
||||
<exports symbol='virStorageVolPtr' type='typedef'/>
|
||||
@ -189,6 +198,7 @@
|
||||
<exports symbol='virDomainGetSchedulerParameters' type='function'/>
|
||||
<exports symbol='virDomainLookupByUUIDString' type='function'/>
|
||||
<exports symbol='virConnectNumOfDefinedNetworks' type='function'/>
|
||||
<exports symbol='virStreamRecvAll' type='function'/>
|
||||
<exports symbol='virConnectListStoragePools' type='function'/>
|
||||
<exports symbol='virNetworkGetUUID' type='function'/>
|
||||
<exports symbol='virInterfaceGetXMLDesc' type='function'/>
|
||||
@ -201,6 +211,7 @@
|
||||
<exports symbol='virStoragePoolDefineXML' type='function'/>
|
||||
<exports symbol='virStorageVolLookupByPath' type='function'/>
|
||||
<exports symbol='virStorageVolLookupByName' type='function'/>
|
||||
<exports symbol='virStreamSinkFunc' type='function'/>
|
||||
<exports symbol='virNetworkCreate' type='function'/>
|
||||
<exports symbol='virSecretLookupByUUID' type='function'/>
|
||||
<exports symbol='virDomainSetMaxMemory' type='function'/>
|
||||
@ -208,6 +219,7 @@
|
||||
<exports symbol='virInterfaceDefineXML' type='function'/>
|
||||
<exports symbol='virDomainMigrate' type='function'/>
|
||||
<exports symbol='virDomainSuspend' type='function'/>
|
||||
<exports symbol='virStreamSourceFunc' type='function'/>
|
||||
<exports symbol='virDomainCreateLinux' type='function'/>
|
||||
<exports symbol='virNodeDeviceGetXMLDesc' type='function'/>
|
||||
<exports symbol='virEventUpdateHandleFunc' type='function'/>
|
||||
@ -226,6 +238,7 @@
|
||||
<exports symbol='virNetworkDestroy' type='function'/>
|
||||
<exports symbol='virStoragePoolLookupByName' type='function'/>
|
||||
<exports symbol='virStoragePoolCreateXML' type='function'/>
|
||||
<exports symbol='virStreamFree' type='function'/>
|
||||
<exports symbol='virNetworkGetAutostart' type='function'/>
|
||||
<exports symbol='virNetworkGetBridgeName' type='function'/>
|
||||
<exports symbol='virStorageVolGetXMLDesc' type='function'/>
|
||||
@ -235,6 +248,7 @@
|
||||
<exports symbol='virStorageVolCreateXML' type='function'/>
|
||||
<exports symbol='virDomainSave' type='function'/>
|
||||
<exports symbol='virDomainCreate' type='function'/>
|
||||
<exports symbol='virStreamEventAddCallback' type='function'/>
|
||||
<exports symbol='virConnectListDomains' type='function'/>
|
||||
<exports symbol='virDomainCoreDump' type='function'/>
|
||||
<exports symbol='virDomainSetMemory' type='function'/>
|
||||
@ -244,16 +258,20 @@
|
||||
<exports symbol='virNetworkSetAutostart' type='function'/>
|
||||
<exports symbol='virSecretLookupByUUIDString' type='function'/>
|
||||
<exports symbol='virDomainGetMaxMemory' type='function'/>
|
||||
<exports symbol='virStreamRef' type='function'/>
|
||||
<exports symbol='virStreamAbort' type='function'/>
|
||||
<exports symbol='virStoragePoolFree' type='function'/>
|
||||
<exports symbol='virConnectNumOfDefinedInterfaces' type='function'/>
|
||||
<exports symbol='virFreeCallback' type='function'/>
|
||||
<exports symbol='virNetworkDefineXML' type='function'/>
|
||||
<exports symbol='virNodeDeviceListCaps' type='function'/>
|
||||
<exports symbol='virDomainBlockStats' type='function'/>
|
||||
<exports symbol='virStreamFinish' type='function'/>
|
||||
<exports symbol='virConnectOpenAuth' type='function'/>
|
||||
<exports symbol='virStoragePoolDelete' type='function'/>
|
||||
<exports symbol='virDomainResume' type='function'/>
|
||||
<exports symbol='virStorageVolGetName' type='function'/>
|
||||
<exports symbol='virStreamNew' type='function'/>
|
||||
<exports symbol='virStoragePoolGetAutostart' type='function'/>
|
||||
<exports symbol='virDomainGetAutostart' type='function'/>
|
||||
<exports symbol='virStoragePoolListVolumes' type='function'/>
|
||||
@ -305,9 +323,11 @@
|
||||
<exports symbol='virStorageVolCreateXMLFrom' type='function'/>
|
||||
<exports symbol='virConnectClose' type='function'/>
|
||||
<exports symbol='virDomainReboot' type='function'/>
|
||||
<exports symbol='virStreamEventCallback' type='function'/>
|
||||
<exports symbol='virNetworkGetUUIDString' type='function'/>
|
||||
<exports symbol='virNetworkLookupByName' type='function'/>
|
||||
<exports symbol='virDomainGetMaxVcpus' type='function'/>
|
||||
<exports symbol='virStreamEventUpdateCallback' type='function'/>
|
||||
<exports symbol='virEventHandleCallback' type='function'/>
|
||||
<exports symbol='virDomainGetSchedulerType' type='function'/>
|
||||
<exports symbol='virNodeDeviceReset' type='function'/>
|
||||
@ -337,8 +357,10 @@
|
||||
<exports symbol='virStorageVolGetConnect' type='function'/>
|
||||
<exports symbol='virNodeNumOfDevices' type='function'/>
|
||||
<exports symbol='virStoragePoolDestroy' type='function'/>
|
||||
<exports symbol='virStreamRecv' type='function'/>
|
||||
<exports symbol='virStoragePoolLookupByVolume' type='function'/>
|
||||
<exports symbol='virDomainLookupByUUID' type='function'/>
|
||||
<exports symbol='virStreamSend' type='function'/>
|
||||
<exports symbol='virDomainGetOSType' type='function'/>
|
||||
<exports symbol='virStoragePoolBuild' type='function'/>
|
||||
<exports symbol='virConnectGetMaxVcpus' type='function'/>
|
||||
@ -350,6 +372,8 @@
|
||||
<exports symbol='virNodeDeviceGetParent' type='function'/>
|
||||
<exports symbol='virConnectOpen' type='function'/>
|
||||
<exports symbol='virDomainCreateXML' type='function'/>
|
||||
<exports symbol='virStreamEventRemoveCallback' type='function'/>
|
||||
<exports symbol='virStreamSendAll' type='function'/>
|
||||
<exports symbol='virNodeDeviceRef' type='function'/>
|
||||
<exports symbol='virInterfaceUndefine' type='function'/>
|
||||
<exports symbol='virDomainSetVcpus' type='function'/>
|
||||
@ -710,6 +734,11 @@
|
||||
<enum name='VIR_STORAGE_VOL_DELETE_NORMAL' file='libvirt' value='0' type='virStorageVolDeleteFlags' info='Delete metadata only (fast)'/>
|
||||
<enum name='VIR_STORAGE_VOL_DELETE_ZEROED' file='libvirt' value='1' type='virStorageVolDeleteFlags' info=' Clear all data to zeros (slow)'/>
|
||||
<enum name='VIR_STORAGE_VOL_FILE' file='libvirt' value='0' type='virStorageVolType' info='Regular file based volumes'/>
|
||||
<enum name='VIR_STREAM_EVENT_ERROR' file='libvirt' value='4' type='virStreamEventType'/>
|
||||
<enum name='VIR_STREAM_EVENT_HANGUP' file='libvirt' value='8' type='virStreamEventType'/>
|
||||
<enum name='VIR_STREAM_EVENT_READABLE' file='libvirt' value='1' type='virStreamEventType'/>
|
||||
<enum name='VIR_STREAM_EVENT_WRITABLE' file='libvirt' value='2' type='virStreamEventType'/>
|
||||
<enum name='VIR_STREAM_NONBLOCK' file='libvirt' value='1' type='virStreamFlags'/>
|
||||
<enum name='VIR_VCPU_BLOCKED' file='libvirt' value='2' type='virVcpuState' info=' the virtual CPU is blocked on resource'/>
|
||||
<enum name='VIR_VCPU_OFFLINE' file='libvirt' value='0' type='virVcpuState' info='the virtual CPU is offline'/>
|
||||
<enum name='VIR_VCPU_RUNNING' file='libvirt' value='1' type='virVcpuState' info='the virtual CPU is running'/>
|
||||
@ -881,6 +910,12 @@ see note above'/>
|
||||
<info><![CDATA[a virStorageVolPtr is pointer to a virStorageVol private structure, this is the type used to reference a storage volume in the API.]]></info>
|
||||
</typedef>
|
||||
<typedef name='virStorageVolType' file='libvirt' type='enum'/>
|
||||
<struct name='virStream' file='libvirt' type='struct _virStream'/>
|
||||
<typedef name='virStreamEventType' file='libvirt' type='enum'/>
|
||||
<typedef name='virStreamFlags' file='libvirt' type='enum'/>
|
||||
<typedef name='virStreamPtr' file='libvirt' type='virStream *'>
|
||||
<info><![CDATA[a virStreamPtr is pointer to a virStream private structure, this is the type used to reference a data stream in the API.]]></info>
|
||||
</typedef>
|
||||
<struct name='virVcpuInfo' file='libvirt' type='struct _virVcpuInfo'>
|
||||
<field name='number' type='unsigned int' info=' virtual CPU number'/>
|
||||
<field name='state' type='int' info=' value from virVcpuState'/>
|
||||
@ -2657,5 +2692,289 @@ the reference count.]]></info>
|
||||
<return type='int' info='0 in case of success, -1 in case of failure.'/>
|
||||
<arg name='vol' type='virStorageVolPtr' info='the vol to hold a reference on'/>
|
||||
</function>
|
||||
<function name='virStreamAbort' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Request that the in progress data transfer be cancelled
|
||||
abnormally before the end of the stream has been reached.
|
||||
For output streams this can be used to inform the driver
|
||||
that the stream is being terminated early. For input
|
||||
streams this can be used to inform the driver that it
|
||||
should stop sending data.]]></info>
|
||||
<return type='int' info='0 on success, -1 upon error'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream object'/>
|
||||
</function>
|
||||
<function name='virStreamEventAddCallback' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[]]></info>
|
||||
<return type='int' info=''/>
|
||||
<arg name='stream' type='virStreamPtr' info=''/>
|
||||
<arg name='events' type='int' info=''/>
|
||||
<arg name='cb' type='virStreamEventCallback' info=''/>
|
||||
<arg name='opaque' type='void *' info=''/>
|
||||
<arg name='ff' type='virFreeCallback' info=''/>
|
||||
</function>
|
||||
<functype name='virStreamEventCallback' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Callback for receiving stream events. The callback will
|
||||
be invoked once for each event which is pending.]]></info>
|
||||
<return type='void'/>
|
||||
<arg name='stream' type='virStreamPtr' info='stream on which the event occurred'/>
|
||||
<arg name='events' type='int' info='bitset of events from virEventHandleType constants'/>
|
||||
<arg name='opaque' type='void *' info='user data registered with handle'/>
|
||||
</functype>
|
||||
<function name='virStreamEventRemoveCallback' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[]]></info>
|
||||
<return type='int' info=''/>
|
||||
<arg name='stream' type='virStreamPtr' info=''/>
|
||||
</function>
|
||||
<function name='virStreamEventUpdateCallback' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[]]></info>
|
||||
<return type='int' info=''/>
|
||||
<arg name='stream' type='virStreamPtr' info=''/>
|
||||
<arg name='events' type='int' info=''/>
|
||||
</function>
|
||||
<function name='virStreamFinish' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Indicate that there is no further data is to be transmitted
|
||||
on the stream. For output streams this should be called once
|
||||
all data has been written. For input streams this should be
|
||||
called once virStreamRecv returns end-of-file.
|
||||
|
||||
This method is a synchronization point for all asynchronous
|
||||
errors, so if this returns a success code the application can
|
||||
be sure that all data has been successfully processed.]]></info>
|
||||
<return type='int' info='0 on success, -1 upon error'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream object'/>
|
||||
</function>
|
||||
<function name='virStreamFree' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Decrement the reference count on a stream, releasing
|
||||
the stream object if the reference count has hit zero.
|
||||
|
||||
There must not be a active data transfer in progress
|
||||
when releasing the stream. If a stream needs to be
|
||||
disposed of prior to end of stream being reached, then
|
||||
the virStreamAbort function should be called first.]]></info>
|
||||
<return type='int' info='0 upon success, or -1 on error'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream object'/>
|
||||
</function>
|
||||
<function name='virStreamNew' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Creates a new stream object which can be used to perform
|
||||
streamed I/O with other public API function.
|
||||
|
||||
When no longer needed, a stream object must be released
|
||||
with virStreamFree. If a data stream has been used,
|
||||
then the application must call virStreamFinish or
|
||||
virStreamAbort before free'ing to, in order to notify
|
||||
the driver of termination.
|
||||
|
||||
If a non-blocking data stream is required passed
|
||||
VIR_STREAM_NONBLOCK for flags, otherwise pass 0.]]></info>
|
||||
<return type='virStreamPtr' info='the new stream, or NULL upon error'/>
|
||||
<arg name='conn' type='virConnectPtr' info='pointer to the connection'/>
|
||||
<arg name='flags' type='unsigned int' info='control features of the stream'/>
|
||||
</function>
|
||||
<function name='virStreamRecv' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Write a series of bytes to the stream. This method may
|
||||
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.
|
||||
|
||||
A example using this with a hypothetical file download
|
||||
API looks like
|
||||
|
||||
virStreamPtr st = virStreamNew(conn, 0);
|
||||
int fd = open("demo.iso", O_WRONLY, 0600)
|
||||
|
||||
virConnectDownloadFile(conn, "demo.iso", st);
|
||||
|
||||
while (1) {
|
||||
char buf[1024];
|
||||
int got = virStreamRecv(st, buf, 1024);
|
||||
if (got < 0)
|
||||
break;
|
||||
if (got == 0) {
|
||||
virStreamFinish(st);
|
||||
break;
|
||||
}
|
||||
int offset = 0;
|
||||
while (offset < got) {
|
||||
int sent = write(fd, buf+offset, got-offset)
|
||||
if (sent < 0) {
|
||||
virStreamAbort(st);
|
||||
goto done;
|
||||
}
|
||||
offset += sent;
|
||||
}
|
||||
}
|
||||
if (virStreamFinish(st) < 0)
|
||||
... report an error ....
|
||||
done:
|
||||
virStreamFree(st);
|
||||
close(fd);]]></info>
|
||||
<return type='int' info='the number of bytes read, which may be less than requested. Returns 0 when the end of the stream is reached, at which time the caller should invoke virStreamFinish() to get confirmation of stream completion. Returns -1 upon error, at which time the stream will be marked as aborted, and the caller should now release the stream with virStreamFree. Returns -2 if there is no data pending to be read & the stream is marked as non-blocking.'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream object'/>
|
||||
<arg name='data' type='char *' info='buffer to write to stream'/>
|
||||
<arg name='nbytes' type='size_t' info='size of @data buffer'/>
|
||||
</function>
|
||||
<function name='virStreamRecvAll' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Receive the entire data stream, sending the data to the
|
||||
requested data sink. This is simply a convenient alternative
|
||||
to virStreamRecv, for apps that do blocking-I/o.
|
||||
|
||||
A example using this with a hypothetical file download
|
||||
API looks like
|
||||
|
||||
int mysink(virStreamPtr st, const char *buf, int nbytes, void *opaque) {
|
||||
int *fd = opaque;
|
||||
|
||||
return write(*fd, buf, nbytes);
|
||||
}
|
||||
|
||||
virStreamPtr st = virStreamNew(conn, 0);
|
||||
int fd = open("demo.iso", O_WRONLY)
|
||||
|
||||
virConnectUploadFile(conn, st);
|
||||
if (virStreamRecvAll(st, mysink, &fd) < 0) {
|
||||
...report an error ...
|
||||
goto done;
|
||||
}
|
||||
if (virStreamFinish(st) < 0)
|
||||
...report an error...
|
||||
virStreamFree(st);
|
||||
close(fd);]]></info>
|
||||
<return type='int' info='0 if all the data was succesfully received. The caller should invoke virStreamFinish(st) to flush the stream upon success and then virStreamFree Returns -1 upon any error, with virStreamAbort() already having been called, so the caller need only call virStreamFree()'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream object'/>
|
||||
<arg name='handler' type='virStreamSinkFunc' info='sink callback for writing data to application'/>
|
||||
<arg name='opaque' type='void *' info='application defined data'/>
|
||||
</function>
|
||||
<function name='virStreamRef' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[Increment the reference count on the stream. For each
|
||||
additional call to this method, there shall be a corresponding
|
||||
call to virStreamFree to release the reference count, once
|
||||
the caller no longer needs the reference to this object.]]></info>
|
||||
<return type='int' info='0 in case of success, -1 in case of failure'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream'/>
|
||||
</function>
|
||||
<function name='virStreamSend' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[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 succesful
|
||||
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.
|
||||
|
||||
A example using this with a hypothetical file upload
|
||||
API looks like
|
||||
|
||||
virStreamPtr st = virStreamNew(conn, 0);
|
||||
int fd = open("demo.iso", O_RDONLY)
|
||||
|
||||
virConnectUploadFile(conn, "demo.iso", st);
|
||||
|
||||
while (1) {
|
||||
char buf[1024];
|
||||
int got = read(fd, buf, 1024);
|
||||
if (got < 0) {
|
||||
virStreamAbort(st);
|
||||
break;
|
||||
}
|
||||
if (got == 0) {
|
||||
virStreamFinish(st);
|
||||
break;
|
||||
}
|
||||
int offset = 0;
|
||||
while (offset < got) {
|
||||
int sent = virStreamSend(st, buf+offset, got-offset)
|
||||
if (sent < 0) {
|
||||
virStreamAbort(st);
|
||||
goto done;
|
||||
}
|
||||
offset += sent;
|
||||
}
|
||||
}
|
||||
if (virStreamFinish(st) < 0)
|
||||
... report an error ....
|
||||
done:
|
||||
virStreamFree(st);
|
||||
close(fd);]]></info>
|
||||
<return type='int' info='the number of bytes written, which may be less than requested. Returns -1 upon error, at which time the stream will be marked as aborted, and the caller should now release the stream with virStreamFree. Returns -2 if the outgoing transmit buffers are full & the stream is marked as non-blocking.'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream object'/>
|
||||
<arg name='data' type='const char *' info='buffer to write to stream'/>
|
||||
<arg name='nbytes' type='size_t' info='size of @data buffer'/>
|
||||
</function>
|
||||
<function name='virStreamSendAll' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[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.
|
||||
|
||||
A example using this with a hypothetical file upload
|
||||
API looks like
|
||||
|
||||
int mysource(virStreamPtr st, char *buf, int nbytes, void *opaque) {
|
||||
int *fd = opaque;
|
||||
|
||||
return read(*fd, buf, nbytes);
|
||||
}
|
||||
|
||||
virStreamPtr st = virStreamNew(conn, 0);
|
||||
int fd = open("demo.iso", O_RDONLY)
|
||||
|
||||
virConnectUploadFile(conn, st);
|
||||
if (virStreamSendAll(st, mysource, &fd) < 0) {
|
||||
...report an error ...
|
||||
goto done;
|
||||
}
|
||||
if (virStreamFinish(st) < 0)
|
||||
...report an error...
|
||||
virStreamFree(st);
|
||||
close(fd);]]></info>
|
||||
<return type='int' info='0 if all the data was succesfully sent. The caller should invoke virStreamFinish(st) to flush the stream upon success and then virStreamFree Returns -1 upon any error, with virStreamAbort() already having been called, so the caller need only call virStreamFree()'/>
|
||||
<arg name='stream' type='virStreamPtr' info='pointer to the stream object'/>
|
||||
<arg name='handler' type='virStreamSourceFunc' info='source callback for reading data from application'/>
|
||||
<arg name='opaque' type='void *' info='application defined data'/>
|
||||
</function>
|
||||
<functype name='virStreamSinkFunc' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[The virStreamSinkFunc callback is used together
|
||||
with the virStreamRecvAll function for libvirt to
|
||||
provide the data that has been received.
|
||||
|
||||
The callback will be invoked multiple times,
|
||||
providing data in small chunks. The application
|
||||
should consume up 'nbytes' from the 'data' array
|
||||
of data and then return the number actual number
|
||||
of bytes consumed. The callback will continue to be
|
||||
invoked until it indicates the end of the stream
|
||||
has been reached. A return value of -1 at any time
|
||||
will abort the receive operation]]></info>
|
||||
<return type='int' info='the number of bytes consumed or -1 upon error'/>
|
||||
<arg name='st' type='virStreamPtr' info='the stream object'/>
|
||||
<arg name='data' type='const char *' info='preallocated array to be filled with data'/>
|
||||
<arg name='nbytes' type='size_t' info='size of the data array'/>
|
||||
<arg name='opaque' type='void *' info='optional application provided data'/>
|
||||
</functype>
|
||||
<functype name='virStreamSourceFunc' file='libvirt' module='libvirt'>
|
||||
<info><![CDATA[The virStreamSourceFunc callback is used together
|
||||
with the virStreamSendAll function for libvirt to
|
||||
obtain the data that is to be sent.
|
||||
|
||||
The callback will be invoked multiple times,
|
||||
fetching data in small chunks. The application
|
||||
should fill the 'data' array with upto 'nbytes'
|
||||
of data and then return the number actual number
|
||||
of bytes. The callback will continue to be
|
||||
invoked until it indicates the end of the source
|
||||
has been reached by returning 0. A return value
|
||||
of -1 at any time will abort the send operation]]></info>
|
||||
<return type='int' info='the number of bytes filled, 0 upon end of file, or -1 upon error'/>
|
||||
<arg name='st' type='virStreamPtr' info='the stream object'/>
|
||||
<arg name='data' type='char *' info='preallocated array to be filled with data'/>
|
||||
<arg name='nbytes' type='size_t' info='size of the data array'/>
|
||||
<arg name='opaque' type='void *' info='optional application provided data'/>
|
||||
</functype>
|
||||
</symbols>
|
||||
</api>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -110,6 +110,24 @@ typedef enum {
|
||||
VIR_DOMAIN_NONE = 0
|
||||
} virDomainCreateFlags;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* virStream:
|
||||
*
|
||||
* a virStream is a private structure representing a data stream.
|
||||
*/
|
||||
typedef struct _virStream virStream;
|
||||
|
||||
/**
|
||||
* virStreamPtr:
|
||||
*
|
||||
* a virStreamPtr is pointer to a virStream private structure, this is the
|
||||
* type used to reference a data stream in the API.
|
||||
*/
|
||||
typedef virStream *virStreamPtr;
|
||||
|
||||
|
||||
/**
|
||||
* VIR_SECURITY_LABEL_BUFLEN:
|
||||
*
|
||||
@ -1502,6 +1520,127 @@ int virSecretUndefine (virSecretPtr secret);
|
||||
int virSecretRef (virSecretPtr secret);
|
||||
int virSecretFree (virSecretPtr secret);
|
||||
|
||||
typedef enum {
|
||||
VIR_STREAM_NONBLOCK = (1 << 0),
|
||||
} virStreamFlags;
|
||||
|
||||
virStreamPtr virStreamNew(virConnectPtr conn,
|
||||
unsigned int flags);
|
||||
int virStreamRef(virStreamPtr st);
|
||||
|
||||
int virStreamSend(virStreamPtr st,
|
||||
const char *data,
|
||||
size_t nbytes);
|
||||
|
||||
int virStreamRecv(virStreamPtr st,
|
||||
char *data,
|
||||
size_t nbytes);
|
||||
|
||||
|
||||
/**
|
||||
* virStreamSourceFunc:
|
||||
*
|
||||
* @st: the stream object
|
||||
* @data: preallocated array to be filled with data
|
||||
* @nbytes: size of the data array
|
||||
* @opaque: optional application provided data
|
||||
*
|
||||
* The virStreamSourceFunc callback is used together
|
||||
* with the virStreamSendAll function for libvirt to
|
||||
* obtain the data that is to be sent.
|
||||
*
|
||||
* The callback will be invoked multiple times,
|
||||
* fetching data in small chunks. The application
|
||||
* should fill the 'data' array with upto 'nbytes'
|
||||
* of data and then return the number actual number
|
||||
* of bytes. The callback will continue to be
|
||||
* invoked until it indicates the end of the source
|
||||
* has been reached by returning 0. A return value
|
||||
* of -1 at any time will abort the send operation
|
||||
*
|
||||
* Returns the number of bytes filled, 0 upon end
|
||||
* of file, or -1 upon error
|
||||
*/
|
||||
typedef int (*virStreamSourceFunc)(virStreamPtr st,
|
||||
char *data,
|
||||
size_t nbytes,
|
||||
void *opaque);
|
||||
|
||||
int virStreamSendAll(virStreamPtr st,
|
||||
virStreamSourceFunc handler,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* virStreamSinkFunc:
|
||||
*
|
||||
* @st: the stream object
|
||||
* @data: preallocated array to be filled with data
|
||||
* @nbytes: size of the data array
|
||||
* @opaque: optional application provided data
|
||||
*
|
||||
* The virStreamSinkFunc callback is used together
|
||||
* with the virStreamRecvAll function for libvirt to
|
||||
* provide the data that has been received.
|
||||
*
|
||||
* The callback will be invoked multiple times,
|
||||
* providing data in small chunks. The application
|
||||
* should consume up 'nbytes' from the 'data' array
|
||||
* of data and then return the number actual number
|
||||
* of bytes consumed. The callback will continue to be
|
||||
* invoked until it indicates the end of the stream
|
||||
* has been reached. A return value of -1 at any time
|
||||
* will abort the receive operation
|
||||
*
|
||||
* Returns the number of bytes consumed or -1 upon
|
||||
* error
|
||||
*/
|
||||
typedef int (*virStreamSinkFunc)(virStreamPtr st,
|
||||
const char *data,
|
||||
size_t nbytes,
|
||||
void *opaque);
|
||||
|
||||
int virStreamRecvAll(virStreamPtr st,
|
||||
virStreamSinkFunc handler,
|
||||
void *opaque);
|
||||
|
||||
typedef enum {
|
||||
VIR_STREAM_EVENT_READABLE = (1 << 0),
|
||||
VIR_STREAM_EVENT_WRITABLE = (1 << 1),
|
||||
VIR_STREAM_EVENT_ERROR = (1 << 2),
|
||||
VIR_STREAM_EVENT_HANGUP = (1 << 3),
|
||||
} virStreamEventType;
|
||||
|
||||
|
||||
/**
|
||||
* virStreamEventCallback:
|
||||
*
|
||||
* @stream: stream on which the event occurred
|
||||
* @events: bitset of events from virEventHandleType constants
|
||||
* @opaque: user data registered with handle
|
||||
*
|
||||
* Callback for receiving stream events. The callback will
|
||||
* be invoked once for each event which is pending.
|
||||
*/
|
||||
typedef void (*virStreamEventCallback)(virStreamPtr stream, int events, void *opaque);
|
||||
|
||||
int virStreamEventAddCallback(virStreamPtr stream,
|
||||
int events,
|
||||
virStreamEventCallback cb,
|
||||
void *opaque,
|
||||
virFreeCallback ff);
|
||||
|
||||
int virStreamEventUpdateCallback(virStreamPtr stream,
|
||||
int events);
|
||||
|
||||
int virStreamEventRemoveCallback(virStreamPtr stream);
|
||||
|
||||
|
||||
int virStreamFinish(virStreamPtr st);
|
||||
int virStreamAbort(virStreamPtr st);
|
||||
|
||||
int virStreamFree(virStreamPtr st);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -13,7 +13,9 @@ DOCS_DIR = $(datadir)/doc/libvirt-python-$(LIBVIRT_VERSION)
|
||||
|
||||
DOCS = ${srcdir}/TODO
|
||||
|
||||
CLASSES_EXTRA = libvirt-override-virConnect.py
|
||||
CLASSES_EXTRA = \
|
||||
libvirt-override-virConnect.py \
|
||||
libvirt-override-virStream.py
|
||||
|
||||
EXTRA_DIST = \
|
||||
generator.py \
|
||||
|
@ -282,6 +282,11 @@ py_types = {
|
||||
'const virSecretPtr': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
|
||||
'virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
|
||||
'const virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
|
||||
|
||||
'virStreamPtr': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
|
||||
'const virStreamPtr': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
|
||||
'virStream *': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
|
||||
'const virStream *': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
|
||||
}
|
||||
|
||||
py_return_types = {
|
||||
@ -338,6 +343,8 @@ skip_impl = (
|
||||
'virSecretGetUUID',
|
||||
'virSecretGetUUIDString',
|
||||
'virSecretLookupByUUID',
|
||||
'virStreamRecv',
|
||||
'virStreamSend',
|
||||
'virStoragePoolGetUUID',
|
||||
'virStoragePoolGetUUIDString',
|
||||
'virStoragePoolLookupByUUID',
|
||||
@ -373,6 +380,11 @@ skip_function = (
|
||||
'virConnectDomainEventDeregister', # overridden in virConnect.py
|
||||
'virSaveLastError', # We have our own python error wrapper
|
||||
'virFreeError', # Only needed if we use virSaveLastError
|
||||
'virStreamEventAddCallback',
|
||||
'virStreamRecvAll',
|
||||
'virStreamSendAll',
|
||||
'virStreamRef',
|
||||
'virStreamFree',
|
||||
)
|
||||
|
||||
|
||||
@ -643,6 +655,8 @@ classes_type = {
|
||||
"virNodeDevice *": ("._o", "virNodeDevice(self, _obj=%s)", "virNodeDevice"),
|
||||
"virSecretPtr": ("._o", "virSecret(self, _obj=%s)", "virSecret"),
|
||||
"virSecret *": ("._o", "virSecret(self, _obj=%s)", "virSecret"),
|
||||
"virStreamPtr": ("._o", "virStream(self, _obj=%s)", "virStream"),
|
||||
"virStream *": ("._o", "virStream(self, _obj=%s)", "virStream"),
|
||||
"virConnectPtr": ("._o", "virConnect(_obj=%s)", "virConnect"),
|
||||
"virConnect *": ("._o", "virConnect(_obj=%s)", "virConnect"),
|
||||
}
|
||||
@ -652,7 +666,8 @@ converter_type = {
|
||||
|
||||
primary_classes = ["virDomain", "virNetwork", "virInterface",
|
||||
"virStoragePool", "virStorageVol",
|
||||
"virConnect", "virNodeDevice", "virSecret" ]
|
||||
"virConnect", "virNodeDevice", "virSecret",
|
||||
"virStream"]
|
||||
|
||||
classes_ancestor = {
|
||||
}
|
||||
@ -663,7 +678,9 @@ classes_destructors = {
|
||||
"virStoragePool": "virStoragePoolFree",
|
||||
"virStorageVol": "virStorageVolFree",
|
||||
"virNodeDevice" : "virNodeDeviceFree",
|
||||
"virSecret": "virSecretFree"
|
||||
"virSecret": "virSecretFree",
|
||||
# We hand-craft __del__ for this one
|
||||
#"virStream": "virStreamFree",
|
||||
}
|
||||
|
||||
functions_noexcept = {
|
||||
@ -782,6 +799,11 @@ def nameFixup(name, classe, type, file):
|
||||
elif name[0:9] == 'virSecret':
|
||||
func = name[9:]
|
||||
func = string.lower(func[0:1]) + func[1:]
|
||||
elif name[0:12] == 'virStreamNew':
|
||||
func = "newStream"
|
||||
elif name[0:9] == 'virStream':
|
||||
func = name[9:]
|
||||
func = string.lower(func[0:1]) + func[1:]
|
||||
elif name[0:17] == "virStoragePoolGet":
|
||||
func = name[17:]
|
||||
func = string.lower(func[0:1]) + func[1:]
|
||||
@ -1059,7 +1081,8 @@ def buildWrappers():
|
||||
classes_ancestor[classname]))
|
||||
else:
|
||||
classes.write("class %s:\n" % (classname))
|
||||
if classname in [ "virDomain", "virNetwork", "virInterface", "virStoragePool", "virStorageVol", "virNodeDevice", "virSecret" ]:
|
||||
if classname in [ "virDomain", "virNetwork", "virInterface", "virStoragePool",
|
||||
"virStorageVol", "virNodeDevice", "virSecret","virStream" ]:
|
||||
classes.write(" def __init__(self, conn, _obj=None):\n")
|
||||
else:
|
||||
classes.write(" def __init__(self, _obj=None):\n")
|
||||
@ -1067,7 +1090,8 @@ def buildWrappers():
|
||||
list = reference_keepers[classname]
|
||||
for ref in list:
|
||||
classes.write(" self.%s = None\n" % ref[1])
|
||||
if classname in [ "virDomain", "virNetwork", "virInterface", "virNodeDevice", "virSecret" ]:
|
||||
if classname in [ "virDomain", "virNetwork", "virInterface",
|
||||
"virNodeDevice", "virSecret", "virStream" ]:
|
||||
classes.write(" self._conn = conn\n")
|
||||
elif classname in [ "virStorageVol", "virStoragePool" ]:
|
||||
classes.write(" self._conn = conn\n" + \
|
||||
|
20
python/libvirt-override-virStream.py
Normal file
20
python/libvirt-override-virStream.py
Normal file
@ -0,0 +1,20 @@
|
||||
def __del__(self):
|
||||
try:
|
||||
if self.cb:
|
||||
libvirtmod.virStreamEventRemoveCallback(self._o)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if self._o != None:
|
||||
libvirtmod.virStreamFree(self._o)
|
||||
self._o = None
|
||||
|
||||
def eventAddCallback(self, cb, opaque):
|
||||
""" """
|
||||
try:
|
||||
self.cb = cb
|
||||
self.opaque = opaque
|
||||
ret = libvirtmod.virStreamEventAddCallback(self._o, self)
|
||||
if ret == -1: raise libvirtError ('virStreamEventAddCallback() failed', conn=self._conn)
|
||||
except AttributeError:
|
||||
pass
|
@ -206,6 +206,19 @@ libvirt_virSecretPtrWrap(virSecretPtr node)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libvirt_virStreamPtrWrap(virStreamPtr node)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (node == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
ret = PyCObject_FromVoidPtrAndDesc(node, (char *) "virStreamPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libvirt_virEventHandleCallbackWrap(virEventHandleCallback node)
|
||||
{
|
||||
|
@ -92,6 +92,15 @@ typedef struct {
|
||||
} PyvirSecret_Object;
|
||||
|
||||
|
||||
#define PyvirStream_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyvirStream_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
virStreamPtr obj;
|
||||
} PyvirStream_Object;
|
||||
|
||||
|
||||
#define PyvirEventHandleCallback_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyvirEventHandleCallback_Object *)(v))->obj))
|
||||
|
||||
@ -144,6 +153,7 @@ PyObject * libvirt_virFreeCallbackWrap(virFreeCallback node);
|
||||
PyObject * libvirt_virVoidPtrWrap(void* node);
|
||||
PyObject * libvirt_virNodeDevicePtrWrap(virNodeDevicePtr node);
|
||||
PyObject * libvirt_virSecretPtrWrap(virSecretPtr node);
|
||||
PyObject * libvirt_virStreamPtrWrap(virStreamPtr node);
|
||||
|
||||
|
||||
/* Provide simple macro statement wrappers (adapted from GLib, in turn from Perl):
|
||||
|
@ -1162,6 +1162,7 @@ virUnrefNodeDevice(virNodeDevicePtr dev) {
|
||||
return (refs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virGetSecret:
|
||||
* @conn: the hypervisor connection
|
||||
@ -1297,3 +1298,61 @@ virUnrefSecret(virSecretPtr secret) {
|
||||
virMutexUnlock(&secret->conn->lock);
|
||||
return refs;
|
||||
}
|
||||
|
||||
virStreamPtr virGetStream(virConnectPtr conn) {
|
||||
virStreamPtr ret = NULL;
|
||||
|
||||
virMutexLock(&conn->lock);
|
||||
|
||||
if (VIR_ALLOC(ret) < 0) {
|
||||
virReportOOMError(conn);
|
||||
goto error;
|
||||
}
|
||||
ret->magic = VIR_STREAM_MAGIC;
|
||||
ret->conn = conn;
|
||||
conn->refs++;
|
||||
ret->refs++;
|
||||
virMutexUnlock(&conn->lock);
|
||||
return(ret);
|
||||
|
||||
error:
|
||||
virMutexUnlock(&conn->lock);
|
||||
VIR_FREE(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
virReleaseStream(virStreamPtr st) {
|
||||
virConnectPtr conn = st->conn;
|
||||
DEBUG("release dev %p", st);
|
||||
|
||||
st->magic = -1;
|
||||
VIR_FREE(st);
|
||||
|
||||
DEBUG("unref connection %p %d", conn, conn->refs);
|
||||
conn->refs--;
|
||||
if (conn->refs == 0) {
|
||||
virReleaseConnect(conn);
|
||||
/* Already unlocked mutex */
|
||||
return;
|
||||
}
|
||||
|
||||
virMutexUnlock(&conn->lock);
|
||||
}
|
||||
|
||||
int virUnrefStream(virStreamPtr st) {
|
||||
int refs;
|
||||
|
||||
virMutexLock(&st->conn->lock);
|
||||
DEBUG("unref stream %p %d", st, st->refs);
|
||||
st->refs--;
|
||||
refs = st->refs;
|
||||
if (refs == 0) {
|
||||
virReleaseStream(st);
|
||||
/* Already unlocked mutex */
|
||||
return (0);
|
||||
}
|
||||
|
||||
virMutexUnlock(&st->conn->lock);
|
||||
return (refs);
|
||||
}
|
||||
|
@ -109,6 +109,17 @@
|
||||
#define VIR_IS_CONNECTED_SECRET(obj) (VIR_IS_SECRET(obj) && VIR_IS_CONNECT((obj)->conn))
|
||||
|
||||
|
||||
/**
|
||||
* VIR_STREAM_MAGIC:
|
||||
*
|
||||
* magic value used to protect the API when pointers to stream structures
|
||||
* are passed down by the users.
|
||||
*/
|
||||
#define VIR_STREAM_MAGIC 0x1DEAD666
|
||||
#define VIR_IS_STREAM(obj) ((obj) && (obj)->magic==VIR_STREAM_MAGIC)
|
||||
#define VIR_IS_CONNECTED_STREAM(obj) (VIR_IS_STREAM(obj) && VIR_IS_CONNECT((obj)->conn))
|
||||
|
||||
|
||||
/**
|
||||
* _virConnect:
|
||||
*
|
||||
@ -261,6 +272,25 @@ struct _virSecret {
|
||||
};
|
||||
|
||||
|
||||
typedef int (*virStreamAbortFunc)(virStreamPtr, void *opaque);
|
||||
typedef int (*virStreamFinishFunc)(virStreamPtr, void *opaque);
|
||||
|
||||
/**
|
||||
* _virStream:
|
||||
*
|
||||
* Internal structure associated with an input stream
|
||||
*/
|
||||
struct _virStream {
|
||||
unsigned int magic;
|
||||
virConnectPtr conn;
|
||||
int refs;
|
||||
int flags;
|
||||
|
||||
virStreamDriverPtr driver;
|
||||
void *privateData;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* API for domain/connections (de)allocations and lookups *
|
||||
@ -303,4 +333,7 @@ virSecretPtr virGetSecret(virConnectPtr conn,
|
||||
const char *usageID);
|
||||
int virUnrefSecret(virSecretPtr secret);
|
||||
|
||||
virStreamPtr virGetStream(virConnectPtr conn);
|
||||
int virUnrefStream(virStreamPtr st);
|
||||
|
||||
#endif
|
||||
|
35
src/driver.h
35
src/driver.h
@ -879,6 +879,41 @@ struct _virSecretDriver {
|
||||
virDrvSecretUndefine undefine;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _virStreamDriver virStreamDriver;
|
||||
typedef virStreamDriver *virStreamDriverPtr;
|
||||
|
||||
typedef int (*virDrvStreamSend)(virStreamPtr st,
|
||||
const char *data,
|
||||
size_t nbytes);
|
||||
typedef int (*virDrvStreamRecv)(virStreamPtr st,
|
||||
char *data,
|
||||
size_t nbytes);
|
||||
|
||||
typedef int (*virDrvStreamEventAddCallback)(virStreamPtr stream,
|
||||
int events,
|
||||
virStreamEventCallback cb,
|
||||
void *opaque,
|
||||
virFreeCallback ff);
|
||||
|
||||
typedef int (*virDrvStreamEventUpdateCallback)(virStreamPtr stream,
|
||||
int events);
|
||||
typedef int (*virDrvStreamEventRemoveCallback)(virStreamPtr stream);
|
||||
typedef int (*virDrvStreamFinish)(virStreamPtr st);
|
||||
typedef int (*virDrvStreamAbort)(virStreamPtr st);
|
||||
|
||||
|
||||
struct _virStreamDriver {
|
||||
virDrvStreamSend streamSend;
|
||||
virDrvStreamRecv streamRecv;
|
||||
virDrvStreamEventAddCallback streamAddCallback;
|
||||
virDrvStreamEventUpdateCallback streamUpdateCallback;
|
||||
virDrvStreamEventRemoveCallback streamRemoveCallback;
|
||||
virDrvStreamFinish streamFinish;
|
||||
virDrvStreamAbort streamAbort;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Registration
|
||||
* TODO: also need ways to (des)activate a given driver
|
||||
|
701
src/libvirt.c
701
src/libvirt.c
@ -561,6 +561,10 @@ virLibNodeDeviceError(virNodeDevicePtr dev, virErrorNumber error,
|
||||
errmsg, info, NULL, 0, 0, errmsg, info);
|
||||
}
|
||||
|
||||
#define virLibStreamError(conn, code, fmt...) \
|
||||
virReportErrorHelper(conn, VIR_FROM_NONE, code, __FILE__, \
|
||||
__FUNCTION__, __LINE__, fmt)
|
||||
|
||||
/**
|
||||
* virLibSecretError:
|
||||
* @secret: the secret if available
|
||||
@ -9394,3 +9398,700 @@ virSecretFree(virSecretPtr secret)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamNew:
|
||||
* @conn: pointer to the connection
|
||||
* @flags: control features of the stream
|
||||
*
|
||||
* Creates a new stream object which can be used to perform
|
||||
* streamed I/O with other public API function.
|
||||
*
|
||||
* When no longer needed, a stream object must be released
|
||||
* with virStreamFree. If a data stream has been used,
|
||||
* then the application must call virStreamFinish or
|
||||
* virStreamAbort before free'ing to, in order to notify
|
||||
* the driver of termination.
|
||||
*
|
||||
* If a non-blocking data stream is required passed
|
||||
* VIR_STREAM_NONBLOCK for flags, otherwise pass 0.
|
||||
*
|
||||
* Returns the new stream, or NULL upon error
|
||||
*/
|
||||
virStreamPtr
|
||||
virStreamNew(virConnectPtr conn,
|
||||
unsigned int flags)
|
||||
{
|
||||
virStreamPtr st;
|
||||
|
||||
DEBUG("conn=%p, flags=%u", conn, flags);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECT(conn)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
st = virGetStream(conn);
|
||||
if (st)
|
||||
st->flags = flags;
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamRef:
|
||||
* @stream: pointer to the stream
|
||||
*
|
||||
* Increment the reference count on the stream. For each
|
||||
* additional call to this method, there shall be a corresponding
|
||||
* call to virStreamFree to release the reference count, once
|
||||
* the caller no longer needs the reference to this object.
|
||||
*
|
||||
* Returns 0 in case of success, -1 in case of failure
|
||||
*/
|
||||
int
|
||||
virStreamRef(virStreamPtr stream)
|
||||
{
|
||||
if ((!VIR_IS_CONNECTED_STREAM(stream))) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||
return(-1);
|
||||
}
|
||||
virMutexLock(&stream->conn->lock);
|
||||
DEBUG("stream=%p refs=%d", stream, stream->refs);
|
||||
stream->refs++;
|
||||
virMutexUnlock(&stream->conn->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamSend:
|
||||
* @stream: pointer to the stream object
|
||||
* @data: buffer to write to stream
|
||||
* @nbytes: size of @data buffer
|
||||
*
|
||||
* 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 succesful
|
||||
* 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.
|
||||
*
|
||||
* A example using this with a hypothetical file upload
|
||||
* API looks like
|
||||
*
|
||||
* virStreamPtr st = virStreamNew(conn, 0);
|
||||
* int fd = open("demo.iso", O_RDONLY)
|
||||
*
|
||||
* virConnectUploadFile(conn, "demo.iso", st);
|
||||
*
|
||||
* while (1) {
|
||||
* char buf[1024];
|
||||
* int got = read(fd, buf, 1024);
|
||||
* if (got < 0) {
|
||||
* virStreamAbort(st);
|
||||
* break;
|
||||
* }
|
||||
* if (got == 0) {
|
||||
* virStreamFinish(st);
|
||||
* break;
|
||||
* }
|
||||
* int offset = 0;
|
||||
* while (offset < got) {
|
||||
* int sent = virStreamSend(st, buf+offset, got-offset)
|
||||
* if (sent < 0) {
|
||||
* virStreamAbort(st);
|
||||
* goto done;
|
||||
* }
|
||||
* offset += sent;
|
||||
* }
|
||||
* }
|
||||
* if (virStreamFinish(st) < 0)
|
||||
* ... report an error ....
|
||||
* done:
|
||||
* virStreamFree(st);
|
||||
* close(fd);
|
||||
*
|
||||
* Returns the number of bytes written, which may be less
|
||||
* than requested.
|
||||
*
|
||||
* Returns -1 upon error, at which time the stream will
|
||||
* be marked as aborted, and the caller should now release
|
||||
* the stream with virStreamFree.
|
||||
*
|
||||
* Returns -2 if the outgoing transmit buffers are full &
|
||||
* the stream is marked as non-blocking.
|
||||
*/
|
||||
int virStreamSend(virStreamPtr stream,
|
||||
const char *data,
|
||||
size_t nbytes)
|
||||
{
|
||||
DEBUG("stream=%p, data=%p, nbytes=%zi", stream, data, nbytes);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamSend) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamSend)(stream, data, nbytes);
|
||||
if (ret == -2)
|
||||
return -2;
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError(stream->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamRecv:
|
||||
* @stream: pointer to the stream object
|
||||
* @data: buffer to write to stream
|
||||
* @nbytes: size of @data buffer
|
||||
*
|
||||
* Write a series of bytes to the stream. This method may
|
||||
* 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.
|
||||
*
|
||||
* A example using this with a hypothetical file download
|
||||
* API looks like
|
||||
*
|
||||
* virStreamPtr st = virStreamNew(conn, 0);
|
||||
* int fd = open("demo.iso", O_WRONLY, 0600)
|
||||
*
|
||||
* virConnectDownloadFile(conn, "demo.iso", st);
|
||||
*
|
||||
* while (1) {
|
||||
* char buf[1024];
|
||||
* int got = virStreamRecv(st, buf, 1024);
|
||||
* if (got < 0)
|
||||
* break;
|
||||
* if (got == 0) {
|
||||
* virStreamFinish(st);
|
||||
* break;
|
||||
* }
|
||||
* int offset = 0;
|
||||
* while (offset < got) {
|
||||
* int sent = write(fd, buf+offset, got-offset)
|
||||
* if (sent < 0) {
|
||||
* virStreamAbort(st);
|
||||
* goto done;
|
||||
* }
|
||||
* offset += sent;
|
||||
* }
|
||||
* }
|
||||
* if (virStreamFinish(st) < 0)
|
||||
* ... report an error ....
|
||||
* done:
|
||||
* virStreamFree(st);
|
||||
* close(fd);
|
||||
*
|
||||
*
|
||||
* Returns the number of bytes read, which may be less
|
||||
* than requested.
|
||||
*
|
||||
* Returns 0 when the end of the stream is reached, at
|
||||
* which time the caller should invoke virStreamFinish()
|
||||
* to get confirmation of stream completion.
|
||||
*
|
||||
* Returns -1 upon error, at which time the stream will
|
||||
* be marked as aborted, and the caller should now release
|
||||
* the stream with virStreamFree.
|
||||
*
|
||||
* Returns -2 if there is no data pending to be read & the
|
||||
* stream is marked as non-blocking.
|
||||
*/
|
||||
int virStreamRecv(virStreamPtr stream,
|
||||
char *data,
|
||||
size_t nbytes)
|
||||
{
|
||||
DEBUG("stream=%p, data=%p, nbytes=%zi", stream, data, nbytes);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamRecv) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamRecv)(stream, data, nbytes);
|
||||
if (ret == -2)
|
||||
return -2;
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError(stream->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamSendAll:
|
||||
* @stream: pointer to the stream object
|
||||
* @handler: source callback for reading data from application
|
||||
* @opaque: application defined data
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A example using this with a hypothetical file upload
|
||||
* API looks like
|
||||
*
|
||||
* int mysource(virStreamPtr st, char *buf, int nbytes, void *opaque) {
|
||||
* int *fd = opaque;
|
||||
*
|
||||
* return read(*fd, buf, nbytes);
|
||||
* }
|
||||
*
|
||||
* virStreamPtr st = virStreamNew(conn, 0);
|
||||
* int fd = open("demo.iso", O_RDONLY)
|
||||
*
|
||||
* virConnectUploadFile(conn, st);
|
||||
* if (virStreamSendAll(st, mysource, &fd) < 0) {
|
||||
* ...report an error ...
|
||||
* goto done;
|
||||
* }
|
||||
* if (virStreamFinish(st) < 0)
|
||||
* ...report an error...
|
||||
* virStreamFree(st);
|
||||
* close(fd);
|
||||
*
|
||||
* Returns 0 if all the data was succesfully sent. The caller
|
||||
* should invoke virStreamFinish(st) to flush the stream upon
|
||||
* success and then virStreamFree
|
||||
*
|
||||
* Returns -1 upon any error, with virStreamAbort() already
|
||||
* having been called, so the caller need only call
|
||||
* virStreamFree()
|
||||
*/
|
||||
int virStreamSendAll(virStreamPtr stream,
|
||||
virStreamSourceFunc handler,
|
||||
void *opaque)
|
||||
{
|
||||
char *bytes = NULL;
|
||||
int want = 1024*64;
|
||||
int ret = -1;
|
||||
DEBUG("stream=%p, handler=%p, opaque=%p", stream, handler, opaque);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->flags & VIR_STREAM_NONBLOCK) {
|
||||
virLibConnError(NULL, VIR_ERR_OPERATION_INVALID,
|
||||
_("data sources cannot be used for non-blocking streams"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC_N(bytes, want) < 0) {
|
||||
virReportOOMError(stream->conn);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int got, offset = 0;
|
||||
got = (handler)(stream, bytes, want, opaque);
|
||||
if (got < 0) {
|
||||
virStreamAbort(stream);
|
||||
goto cleanup;
|
||||
}
|
||||
if (got == 0)
|
||||
break;
|
||||
while (offset < got) {
|
||||
int done;
|
||||
done = virStreamSend(stream, bytes + offset, got - offset);
|
||||
if (done < 0)
|
||||
goto cleanup;
|
||||
offset += done;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(bytes);
|
||||
|
||||
/* Copy to connection error object for back compatability */
|
||||
if (ret != 0)
|
||||
virSetConnError(stream->conn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamRecvAll:
|
||||
* @stream: pointer to the stream object
|
||||
* @handler: sink callback for writing data to application
|
||||
* @opaque: application defined data
|
||||
*
|
||||
* Receive the entire data stream, sending the data to the
|
||||
* requested data sink. This is simply a convenient alternative
|
||||
* to virStreamRecv, for apps that do blocking-I/o.
|
||||
*
|
||||
* A example using this with a hypothetical file download
|
||||
* API looks like
|
||||
*
|
||||
* int mysink(virStreamPtr st, const char *buf, int nbytes, void *opaque) {
|
||||
* int *fd = opaque;
|
||||
*
|
||||
* return write(*fd, buf, nbytes);
|
||||
* }
|
||||
*
|
||||
* virStreamPtr st = virStreamNew(conn, 0);
|
||||
* int fd = open("demo.iso", O_WRONLY)
|
||||
*
|
||||
* virConnectUploadFile(conn, st);
|
||||
* if (virStreamRecvAll(st, mysink, &fd) < 0) {
|
||||
* ...report an error ...
|
||||
* goto done;
|
||||
* }
|
||||
* if (virStreamFinish(st) < 0)
|
||||
* ...report an error...
|
||||
* virStreamFree(st);
|
||||
* close(fd);
|
||||
*
|
||||
* Returns 0 if all the data was succesfully received. The caller
|
||||
* should invoke virStreamFinish(st) to flush the stream upon
|
||||
* success and then virStreamFree
|
||||
*
|
||||
* Returns -1 upon any error, with virStreamAbort() already
|
||||
* having been called, so the caller need only call
|
||||
* virStreamFree()
|
||||
*/
|
||||
int virStreamRecvAll(virStreamPtr stream,
|
||||
virStreamSinkFunc handler,
|
||||
void *opaque)
|
||||
{
|
||||
char *bytes = NULL;
|
||||
int want = 1024*64;
|
||||
int ret = -1;
|
||||
DEBUG("stream=%p, handler=%p, opaque=%p", stream, handler, opaque);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->flags & VIR_STREAM_NONBLOCK) {
|
||||
virLibConnError(NULL, VIR_ERR_OPERATION_INVALID,
|
||||
_("data sinks cannot be used for non-blocking streams"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
if (VIR_ALLOC_N(bytes, want) < 0) {
|
||||
virReportOOMError(stream->conn);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int got, offset = 0;
|
||||
got = virStreamRecv(stream, bytes, want);
|
||||
if (got < 0)
|
||||
goto cleanup;
|
||||
if (got == 0)
|
||||
break;
|
||||
while (offset < got) {
|
||||
int done;
|
||||
done = (handler)(stream, bytes + offset, got - offset, opaque);
|
||||
if (done < 0) {
|
||||
virStreamAbort(stream);
|
||||
goto cleanup;
|
||||
}
|
||||
offset += done;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(bytes);
|
||||
|
||||
/* Copy to connection error object for back compatability */
|
||||
if (ret != 0)
|
||||
virSetConnError(stream->conn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamEventAddCallback
|
||||
* @stream: pointer to the stream object
|
||||
* @events: set of events to monitor
|
||||
* @cb: callback to invoke when an event occurs
|
||||
* @opaque: application defined data
|
||||
* @ff: callback to free @opaque data
|
||||
*
|
||||
* Register a callback to be notified when a stream
|
||||
* becomes writable, or readable. This is most commonly
|
||||
* used in conjunction with non-blocking data streams
|
||||
* to integrate into an event loop
|
||||
*
|
||||
* Returns 0 on success, -1 upon error
|
||||
*/
|
||||
int virStreamEventAddCallback(virStreamPtr stream,
|
||||
int events,
|
||||
virStreamEventCallback cb,
|
||||
void *opaque,
|
||||
virFreeCallback ff)
|
||||
{
|
||||
DEBUG("stream=%p, events=%d, cb=%p, opaque=%p, ff=%p", stream, events, cb, opaque, ff);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamAddCallback) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamAddCallback)(stream, events, cb, opaque, ff);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError(stream->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStreamEventUpdateCallback
|
||||
* @stream: pointer to the stream object
|
||||
* @events: set of events to monitor
|
||||
*
|
||||
* Changes the set of events to monitor for a stream. This allows
|
||||
* for event notification to be changed without having to
|
||||
* unregister & register the callback completely. This method
|
||||
* is guarenteed to succeed if a callback is already registered
|
||||
*
|
||||
* Returns 0 on success, -1 if no callback is registered
|
||||
*/
|
||||
int virStreamEventUpdateCallback(virStreamPtr stream,
|
||||
int events)
|
||||
{
|
||||
DEBUG("stream=%p, events=%d", stream, events);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamUpdateCallback) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamUpdateCallback)(stream, events);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError (stream->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virStreamEventRemoveCallback
|
||||
* @stream: pointer to the stream object
|
||||
*
|
||||
* Remove a event callback from the stream
|
||||
*
|
||||
* Returns 0 on success, -1 on error
|
||||
*/
|
||||
int virStreamEventRemoveCallback(virStreamPtr stream)
|
||||
{
|
||||
DEBUG("stream=%p", stream);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamRemoveCallback) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamRemoveCallback)(stream);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError (stream->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virStreamFinish:
|
||||
* @stream: pointer to the stream object
|
||||
*
|
||||
* Indicate that there is no further data is to be transmitted
|
||||
* on the stream. For output streams this should be called once
|
||||
* all data has been written. For input streams this should be
|
||||
* called once virStreamRecv returns end-of-file.
|
||||
*
|
||||
* This method is a synchronization point for all asynchronous
|
||||
* errors, so if this returns a success code the application can
|
||||
* be sure that all data has been successfully processed.
|
||||
*
|
||||
* Returns 0 on success, -1 upon error
|
||||
*/
|
||||
int virStreamFinish(virStreamPtr stream)
|
||||
{
|
||||
DEBUG("stream=%p", stream);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamFinish) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamFinish)(stream);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError (stream->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virStreamAbort:
|
||||
* @stream: pointer to the stream object
|
||||
*
|
||||
* Request that the in progress data transfer be cancelled
|
||||
* abnormally before the end of the stream has been reached.
|
||||
* For output streams this can be used to inform the driver
|
||||
* that the stream is being terminated early. For input
|
||||
* streams this can be used to inform the driver that it
|
||||
* should stop sending data.
|
||||
*
|
||||
* Returns 0 on success, -1 upon error
|
||||
*/
|
||||
int virStreamAbort(virStreamPtr stream)
|
||||
{
|
||||
DEBUG("stream=%p", stream);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream->driver &&
|
||||
stream->driver->streamAbort) {
|
||||
int ret;
|
||||
ret = (stream->driver->streamAbort)(stream);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
}
|
||||
|
||||
virLibConnError (stream->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||
|
||||
error:
|
||||
/* Copy to connection error object for back compatability */
|
||||
virSetConnError(stream->conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virStreamFree:
|
||||
* @stream: pointer to the stream object
|
||||
*
|
||||
* Decrement the reference count on a stream, releasing
|
||||
* the stream object if the reference count has hit zero.
|
||||
*
|
||||
* There must not be a active data transfer in progress
|
||||
* when releasing the stream. If a stream needs to be
|
||||
* disposed of prior to end of stream being reached, then
|
||||
* the virStreamAbort function should be called first.
|
||||
*
|
||||
* Returns 0 upon success, or -1 on error
|
||||
*/
|
||||
int virStreamFree(virStreamPtr stream)
|
||||
{
|
||||
DEBUG("stream=%p", stream);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
if (!VIR_IS_CONNECTED_STREAM(stream)) {
|
||||
virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* XXX Enforce shutdown before free'ing resources ? */
|
||||
|
||||
if (virUnrefStream(stream) < 0)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
@ -78,6 +78,8 @@ virGetNodeDevice;
|
||||
virUnrefDomain;
|
||||
virUnrefConnect;
|
||||
virUnrefSecret;
|
||||
virGetStream;
|
||||
virUnrefStream;
|
||||
|
||||
|
||||
# domain_conf.h
|
||||
|
@ -312,4 +312,20 @@ LIBVIRT_0.7.1 {
|
||||
virSecretFree;
|
||||
} LIBVIRT_0.7.0;
|
||||
|
||||
LIBVIRT_0.7.2 {
|
||||
global:
|
||||
virStreamNew;
|
||||
virStreamRef;
|
||||
virStreamSend;
|
||||
virStreamRecv;
|
||||
virStreamSendAll;
|
||||
virStreamRecvAll;
|
||||
virStreamEventAddCallback;
|
||||
virStreamEventUpdateCallback;
|
||||
virStreamEventRemoveCallback;
|
||||
virStreamFinish;
|
||||
virStreamAbort;
|
||||
virStreamFree;
|
||||
} LIBVIRT_0.7.1;
|
||||
|
||||
# .... define new API here using predicted next version number ....
|
||||
|
Loading…
Reference in New Issue
Block a user