mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
remote: Use virDomainEventState helpers
One functionality change here is that we no longer force enable the event timeout for every queued event, only enable it for the first event after the queue has been flushed. This is how other drivers have already done it, and I haven't encountered problems in practice. v3: Adjust for new virDomainEventStateNew argument
This commit is contained in:
parent
7405aebe01
commit
4e6e66728f
@ -184,15 +184,7 @@ struct private_data {
|
|||||||
unsigned int bufferLength;
|
unsigned int bufferLength;
|
||||||
unsigned int bufferOffset;
|
unsigned int bufferOffset;
|
||||||
|
|
||||||
/* The list of domain event callbacks */
|
virDomainEventStatePtr domainEventState;
|
||||||
virDomainEventCallbackListPtr callbackList;
|
|
||||||
/* The queue of domain events generated
|
|
||||||
during a call / response rpc */
|
|
||||||
virDomainEventQueuePtr domainEvents;
|
|
||||||
/* Timer for flushing domainEvents queue */
|
|
||||||
int eventFlushTimer;
|
|
||||||
/* Flag if we're in process of dispatching */
|
|
||||||
int domainEventDispatching;
|
|
||||||
|
|
||||||
/* Self-pipe to wakeup threads waiting in poll() */
|
/* Self-pipe to wakeup threads waiting in poll() */
|
||||||
int wakeupSendFD;
|
int wakeupSendFD;
|
||||||
@ -264,6 +256,7 @@ static void make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWF
|
|||||||
static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
|
static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
|
||||||
void remoteDomainEventFired(int watch, int fd, int event, void *data);
|
void remoteDomainEventFired(int watch, int fd, int event, void *data);
|
||||||
void remoteDomainEventQueueFlush(int timer, void *opaque);
|
void remoteDomainEventQueueFlush(int timer, void *opaque);
|
||||||
|
void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event);
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Helper functions for remoteOpen. */
|
/* Helper functions for remoteOpen. */
|
||||||
@ -913,17 +906,6 @@ doRemoteOpen (virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(VIR_ALLOC(priv->callbackList)<0) {
|
|
||||||
virReportOOMError();
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(VIR_ALLOC(priv->domainEvents)<0) {
|
|
||||||
virReportOOMError();
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_DEBUG("Adding Handler for remote events");
|
|
||||||
/* Set up a callback to listen on the socket data */
|
/* Set up a callback to listen on the socket data */
|
||||||
if ((priv->watch = virEventAddHandle(priv->sock,
|
if ((priv->watch = virEventAddHandle(priv->sock,
|
||||||
VIR_EVENT_HANDLE_READABLE,
|
VIR_EVENT_HANDLE_READABLE,
|
||||||
@ -931,18 +913,21 @@ doRemoteOpen (virConnectPtr conn,
|
|||||||
conn, NULL)) < 0) {
|
conn, NULL)) < 0) {
|
||||||
VIR_DEBUG("virEventAddHandle failed: No addHandleImpl defined."
|
VIR_DEBUG("virEventAddHandle failed: No addHandleImpl defined."
|
||||||
" continuing without events.");
|
" continuing without events.");
|
||||||
} else {
|
priv->watch = -1;
|
||||||
|
|
||||||
VIR_DEBUG("Adding Timeout for remote event queue flushing");
|
|
||||||
if ( (priv->eventFlushTimer = virEventAddTimeout(-1,
|
|
||||||
remoteDomainEventQueueFlush,
|
|
||||||
conn, NULL)) < 0) {
|
|
||||||
VIR_DEBUG("virEventAddTimeout failed: No addTimeoutImpl defined. "
|
|
||||||
"continuing without events.");
|
|
||||||
virEventRemoveHandle(priv->watch);
|
|
||||||
priv->watch = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->domainEventState = virDomainEventStateNew(remoteDomainEventQueueFlush,
|
||||||
|
conn,
|
||||||
|
NULL,
|
||||||
|
false);
|
||||||
|
if (!priv->domainEventState) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (priv->domainEventState->timer < 0 && priv->watch != -1) {
|
||||||
|
virEventRemoveHandle(priv->watch);
|
||||||
|
priv->watch = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Successful. */
|
/* Successful. */
|
||||||
retcode = VIR_DRV_OPEN_SUCCESS;
|
retcode = VIR_DRV_OPEN_SUCCESS;
|
||||||
|
|
||||||
@ -1559,12 +1544,13 @@ verify_certificate (virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
static int
|
static int
|
||||||
doRemoteClose (virConnectPtr conn, struct private_data *priv)
|
doRemoteClose (virConnectPtr conn, struct private_data *priv)
|
||||||
{
|
{
|
||||||
if (priv->eventFlushTimer >= 0) {
|
/* Remove timer before closing the connection, to avoid possible
|
||||||
/* Remove timeout */
|
* remoteDomainEventFired with a free'd connection */
|
||||||
virEventRemoveTimeout(priv->eventFlushTimer);
|
if (priv->domainEventState->timer >= 0) {
|
||||||
/* Remove handle for remote events */
|
virEventRemoveTimeout(priv->domainEventState->timer);
|
||||||
virEventRemoveHandle(priv->watch);
|
virEventRemoveHandle(priv->watch);
|
||||||
priv->watch = -1;
|
priv->watch = -1;
|
||||||
|
priv->domainEventState->timer = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_CLOSE,
|
if (call (conn, priv, 0, REMOTE_PROC_CLOSE,
|
||||||
@ -1605,11 +1591,7 @@ retry:
|
|||||||
/* See comment for remoteType. */
|
/* See comment for remoteType. */
|
||||||
VIR_FREE(priv->type);
|
VIR_FREE(priv->type);
|
||||||
|
|
||||||
/* Free callback list */
|
virDomainEventStateFree(priv->domainEventState);
|
||||||
virDomainEventCallbackListFree(priv->callbackList);
|
|
||||||
|
|
||||||
/* Free queued events */
|
|
||||||
virDomainEventQueueFree(priv->domainEvents);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3800,17 +3782,20 @@ static int remoteDomainEventRegister(virConnectPtr conn,
|
|||||||
|
|
||||||
remoteDriverLock(priv);
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
if (priv->eventFlushTimer < 0) {
|
if (priv->domainEventState->timer < 0) {
|
||||||
remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
|
remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (virDomainEventCallbackListAdd(conn, priv->callbackList,
|
|
||||||
|
if (virDomainEventCallbackListAdd(conn, priv->domainEventState->callbacks,
|
||||||
callback, opaque, freecb) < 0) {
|
callback, opaque, freecb) < 0) {
|
||||||
remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
|
remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virDomainEventCallbackListCountID(conn, priv->callbackList, VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 1) {
|
if (virDomainEventCallbackListCountID(conn,
|
||||||
|
priv->domainEventState->callbacks,
|
||||||
|
VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 1) {
|
||||||
/* Tell the server when we are the first callback deregistering */
|
/* Tell the server when we are the first callback deregistering */
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER,
|
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER,
|
||||||
(xdrproc_t) xdr_void, (char *) NULL,
|
(xdrproc_t) xdr_void, (char *) NULL,
|
||||||
@ -3833,21 +3818,14 @@ static int remoteDomainEventDeregister(virConnectPtr conn,
|
|||||||
|
|
||||||
remoteDriverLock(priv);
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
if (priv->domainEventDispatching) {
|
if (virDomainEventStateDeregister(conn,
|
||||||
if (virDomainEventCallbackListMarkDelete(conn, priv->callbackList,
|
priv->domainEventState,
|
||||||
callback) < 0) {
|
callback) < 0)
|
||||||
remoteError(VIR_ERR_RPC, "%s", _("marking cb for deletion"));
|
goto done;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (virDomainEventCallbackListRemove(conn, priv->callbackList,
|
|
||||||
callback) < 0) {
|
|
||||||
remoteError(VIR_ERR_RPC, "%s", _("removing cb from list"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virDomainEventCallbackListCountID(conn, priv->callbackList, VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 0) {
|
if (virDomainEventCallbackListCountID(conn,
|
||||||
|
priv->domainEventState->callbacks,
|
||||||
|
VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 0) {
|
||||||
/* Tell the server when we are the last callback deregistering */
|
/* Tell the server when we are the last callback deregistering */
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER,
|
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER,
|
||||||
(xdrproc_t) xdr_void, (char *) NULL,
|
(xdrproc_t) xdr_void, (char *) NULL,
|
||||||
@ -4723,12 +4701,13 @@ static int remoteDomainEventRegisterAny(virConnectPtr conn,
|
|||||||
|
|
||||||
remoteDriverLock(priv);
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
if (priv->eventFlushTimer < 0) {
|
if (priv->domainEventState->timer < 0) {
|
||||||
remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
|
remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((callbackID = virDomainEventCallbackListAddID(conn, priv->callbackList,
|
if ((callbackID = virDomainEventCallbackListAddID(conn,
|
||||||
|
priv->domainEventState->callbacks,
|
||||||
dom, eventID,
|
dom, eventID,
|
||||||
callback, opaque, freecb)) < 0) {
|
callback, opaque, freecb)) < 0) {
|
||||||
remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
|
remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
|
||||||
@ -4737,13 +4716,17 @@ static int remoteDomainEventRegisterAny(virConnectPtr conn,
|
|||||||
|
|
||||||
/* If this is the first callback for this eventID, we need to enable
|
/* If this is the first callback for this eventID, we need to enable
|
||||||
* events on the server */
|
* events on the server */
|
||||||
if (virDomainEventCallbackListCountID(conn, priv->callbackList, eventID) == 1) {
|
if (virDomainEventCallbackListCountID(conn,
|
||||||
|
priv->domainEventState->callbacks,
|
||||||
|
eventID) == 1) {
|
||||||
args.eventID = eventID;
|
args.eventID = eventID;
|
||||||
|
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY,
|
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY,
|
||||||
(xdrproc_t) xdr_remote_domain_events_register_any_args, (char *) &args,
|
(xdrproc_t) xdr_remote_domain_events_register_any_args, (char *) &args,
|
||||||
(xdrproc_t) xdr_void, (char *)NULL) == -1) {
|
(xdrproc_t) xdr_void, (char *)NULL) == -1) {
|
||||||
virDomainEventCallbackListRemoveID(conn, priv->callbackList, callbackID);
|
virDomainEventCallbackListRemoveID(conn,
|
||||||
|
priv->domainEventState->callbacks,
|
||||||
|
callbackID);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4766,28 +4749,23 @@ static int remoteDomainEventDeregisterAny(virConnectPtr conn,
|
|||||||
|
|
||||||
remoteDriverLock(priv);
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
if ((eventID = virDomainEventCallbackListEventID(conn, priv->callbackList, callbackID)) < 0) {
|
if ((eventID = virDomainEventCallbackListEventID(conn,
|
||||||
|
priv->domainEventState->callbacks,
|
||||||
|
callbackID)) < 0) {
|
||||||
remoteError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
|
remoteError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->domainEventDispatching) {
|
if (virDomainEventStateDeregisterAny(conn,
|
||||||
if (virDomainEventCallbackListMarkDeleteID(conn, priv->callbackList,
|
priv->domainEventState,
|
||||||
callbackID) < 0) {
|
callbackID) < 0)
|
||||||
remoteError(VIR_ERR_RPC, "%s", _("marking cb for deletion"));
|
goto done;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (virDomainEventCallbackListRemoveID(conn, priv->callbackList,
|
|
||||||
callbackID) < 0) {
|
|
||||||
remoteError(VIR_ERR_RPC, "%s", _("removing cb from list"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If that was the last callback for this eventID, we need to disable
|
/* If that was the last callback for this eventID, we need to disable
|
||||||
* events on the server */
|
* events on the server */
|
||||||
if (virDomainEventCallbackListCountID(conn, priv->callbackList, eventID) == 0) {
|
if (virDomainEventCallbackListCountID(conn,
|
||||||
|
priv->domainEventState->callbacks,
|
||||||
|
eventID) == 0) {
|
||||||
args.eventID = eventID;
|
args.eventID = eventID;
|
||||||
|
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY,
|
if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY,
|
||||||
@ -5593,13 +5571,7 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
|
|||||||
if (!event)
|
if (!event)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (virDomainEventQueuePush(priv->domainEvents,
|
remoteDomainEventQueue(priv, event);
|
||||||
event) < 0) {
|
|
||||||
VIR_DEBUG("Error adding event to queue");
|
|
||||||
virDomainEventFree(event);
|
|
||||||
}
|
|
||||||
virEventUpdateTimeout(priv->eventFlushTimer, 0);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6270,31 +6242,22 @@ remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
|
|||||||
{
|
{
|
||||||
virConnectPtr conn = opaque;
|
virConnectPtr conn = opaque;
|
||||||
struct private_data *priv = conn->privateData;
|
struct private_data *priv = conn->privateData;
|
||||||
virDomainEventQueue tempQueue;
|
|
||||||
|
|
||||||
remoteDriverLock(priv);
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
VIR_DEBUG("Event queue flush %p", conn);
|
VIR_DEBUG("Event queue flush %p", conn);
|
||||||
priv->domainEventDispatching = 1;
|
|
||||||
|
|
||||||
/* Copy the queue, so we're reentrant safe */
|
|
||||||
tempQueue.count = priv->domainEvents->count;
|
|
||||||
tempQueue.events = priv->domainEvents->events;
|
|
||||||
priv->domainEvents->count = 0;
|
|
||||||
priv->domainEvents->events = NULL;
|
|
||||||
|
|
||||||
virEventUpdateTimeout(priv->eventFlushTimer, -1);
|
|
||||||
virDomainEventQueueDispatch(&tempQueue, priv->callbackList,
|
|
||||||
remoteDomainEventDispatchFunc, priv);
|
|
||||||
|
|
||||||
/* Purge any deleted callbacks */
|
|
||||||
virDomainEventCallbackListPurgeMarked(priv->callbackList);
|
|
||||||
|
|
||||||
priv->domainEventDispatching = 0;
|
|
||||||
|
|
||||||
|
virDomainEventStateFlush(priv->domainEventState,
|
||||||
|
remoteDomainEventDispatchFunc,
|
||||||
|
priv);
|
||||||
remoteDriverUnlock(priv);
|
remoteDriverUnlock(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event)
|
||||||
|
{
|
||||||
|
virDomainEventStateQueue(priv->domainEventState, event);
|
||||||
|
}
|
||||||
|
|
||||||
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
||||||
* (name, uuid) pair into virDomainPtr or virNetworkPtr object.
|
* (name, uuid) pair into virDomainPtr or virNetworkPtr object.
|
||||||
|
Loading…
Reference in New Issue
Block a user