int virKeepAliveStart(virKeepAlivePtr ka, int interval, unsigned int count) { int ret = -1; time_t delay; int timeout; time_t now; virKeepAliveLock(ka); if (ka->timer >= 0) { VIR_DEBUG("Keepalive messages already enabled"); ret = 0; goto cleanup; } if (interval > 0) { if (ka->interval > 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("keepalive interval already set")); goto cleanup; } ka->interval = interval; ka->count = count; ka->countToDeath = count; } if (ka->interval <= 0) { VIR_DEBUG("Keepalive messages disabled by configuration"); ret = 0; goto cleanup; } PROBE(RPC_KEEPALIVE_START, "ka=%p client=%p interval=%d count=%u", ka, ka->client, interval, count); now = time(NULL); delay = now - ka->lastPacketReceived; if (delay > ka->interval) timeout = 0; else timeout = ka->interval - delay; ka->intervalStart = now - (ka->interval - timeout); ka->timer = virEventAddTimeout(timeout * 1000, virKeepAliveTimer, ka, virKeepAliveTimerFree); if (ka->timer < 0) goto cleanup; /* the timer now has another reference to this object */ ka->refs++; ret = 0; cleanup: virKeepAliveUnlock(ka); return ret; }
static virNetServerClientPtr virNetServerClientNewInternal(unsigned long long id, virNetSocketPtr sock, int auth, #ifdef WITH_GNUTLS virNetTLSContextPtr tls, #endif bool readonly, size_t nrequests_max, long long timestamp) { virNetServerClientPtr client; if (virNetServerClientInitialize() < 0) return NULL; if (!(client = virObjectLockableNew(virNetServerClientClass))) return NULL; client->id = id; client->sock = virObjectRef(sock); client->auth = auth; client->readonly = readonly; #ifdef WITH_GNUTLS client->tlsCtxt = virObjectRef(tls); #endif client->nrequests_max = nrequests_max; client->conn_time = timestamp; client->sockTimer = virEventAddTimeout(-1, virNetServerClientSockTimerFunc, client, NULL); if (client->sockTimer < 0) goto error; /* Prepare one for packet receive */ if (!(client->rx = virNetMessageNew(true))) goto error; client->rx->bufferLength = VIR_NET_MESSAGE_LEN_MAX; if (VIR_ALLOC_N(client->rx->buffer, client->rx->bufferLength) < 0) goto error; client->nrequests = 1; PROBE(RPC_SERVER_CLIENT_NEW, "client=%p sock=%p", client, client->sock); return client; error: virObjectUnref(client); return NULL; }
static virNetServerClientPtr virNetServerClientNewInternal(virNetSocketPtr sock, int auth, bool readonly, size_t nrequests_max, virNetTLSContextPtr tls) { virNetServerClientPtr client; if (virNetServerClientInitialize() < 0) return NULL; if (!(client = virObjectNew(virNetServerClientClass))) return NULL; if (virMutexInit(&client->lock) < 0) { VIR_FREE(client); return NULL; } client->sock = virObjectRef(sock); client->auth = auth; client->readonly = readonly; client->tlsCtxt = virObjectRef(tls); client->nrequests_max = nrequests_max; client->sockTimer = virEventAddTimeout(-1, virNetServerClientSockTimerFunc, client, NULL); if (client->sockTimer < 0) goto error; /* Prepare one for packet receive */ if (!(client->rx = virNetMessageNew(true))) goto error; client->rx->bufferLength = VIR_NET_MESSAGE_LEN_MAX; if (VIR_ALLOC_N(client->rx->buffer, client->rx->bufferLength) < 0) { virReportOOMError(); goto error; } client->nrequests = 1; PROBE(RPC_SERVER_CLIENT_NEW, "client=%p sock=%p", client, client->sock); return client; error: virObjectUnref(client); return NULL; }
void qemuMonitorTestFree(qemuMonitorTestPtr test) { size_t i; int timer = -1; if (!test) return; virMutexLock(&test->lock); if (test->running) { test->quit = true; /* HACK: Add a dummy timeout to break event loop */ timer = virEventAddTimeout(0, qemuMonitorTestFreeTimer, NULL, NULL); } virMutexUnlock(&test->lock); if (test->client) { virNetSocketRemoveIOCallback(test->client); virNetSocketClose(test->client); virObjectUnref(test->client); } virObjectUnref(test->server); if (test->mon) { virObjectUnlock(test->mon); qemuMonitorClose(test->mon); } virObjectUnref(test->vm); virThreadJoin(&test->thread); if (timer != -1) virEventRemoveTimeout(timer); VIR_FREE(test->incoming); VIR_FREE(test->outgoing); for (i = 0 ; i < test->nitems ; i++) qemuMonitorTestItemFree(test->items[i]); VIR_FREE(test->items); if (test->tmpdir && rmdir(test->tmpdir) < 0) VIR_WARN("Failed to remove tempdir: %s", strerror(errno)); VIR_FREE(test->tmpdir); virMutexDestroy(&test->lock); VIR_FREE(test); }
/* * Initialize connection. */ static bool virshInit(vshControl *ctl) { virshControlPtr priv = ctl->privData; /* Since we have the commandline arguments parsed, we need to * reload our initial settings to make debugging and readline * work properly */ vshInitReload(ctl); if (priv->conn) return false; /* set up the library error handler */ virSetErrorFunc(NULL, vshErrorHandler); if (virEventRegisterDefaultImpl() < 0) { vshReportError(ctl); return false; } if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) { vshReportError(ctl); return false; } ctl->eventLoopStarted = true; if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl, NULL)) < 0) { vshReportError(ctl); return false; } if (ctl->connname) { /* Connecting to a named connection must succeed, but we delay * connecting to the default connection until we need it * (since the first command might be 'connect' which allows a * non-default connection, or might be 'help' which needs no * connection). */ if (virshReconnect(ctl, NULL, false, false) < 0) { vshReportError(ctl); return false; } } return true; }
/** * virObjectEventStateRegisterID: * @conn: connection to associate with callback * @state: domain event state * @uuid: uuid of the object for event filtering * @klass: the base event class * @eventID: ID of the event type to register for * @cb: function to invoke when event occurs * @opaque: data blob to pass to @callback * @freecb: callback to free @opaque * @legacy: true if callback is tracked by function instead of callbackID * @callbackID: filled with callback ID * @serverFilter: true if server supports object filtering * * Register the function @cb with connection @conn, from @state, for * events of type @eventID, and return the registration handle in * @callbackID. * * The return value is only important when registering client-side * mirroring of remote events (since the public API is documented to * return the callbackID rather than a count). A return of 1 means * that this is the first use of this type of event, so a remote event * must be enabled; a return larger than 1 means that an existing * remote event can already feed this callback. If @serverFilter is * false, the return count assumes that a single global remote feeds * both generic and per-object callbacks, and that the event queue * will be fed with virObjectEventStateQueue(). If it is true, then * the return count assumes that the remote side is capable of per- * object filtering; the user must call virObjectEventStateSetRemote() * to record the remote id, and queue events with * virObjectEventStateQueueRemote(). * * Returns: the number of callbacks now registered, or -1 on error. */ int virObjectEventStateRegisterID(virConnectPtr conn, virObjectEventStatePtr state, unsigned char *uuid, virObjectEventCallbackFilter filter, void *filter_opaque, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback cb, void *opaque, virFreeCallback freecb, bool legacy, int *callbackID, bool serverFilter) { int ret = -1; virObjectEventStateLock(state); if ((state->callbacks->count == 0) && (state->timer == -1) && (state->timer = virEventAddTimeout(-1, virObjectEventTimer, state, NULL)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("could not initialize domain event timer")); goto cleanup; } ret = virObjectEventCallbackListAddID(conn, state->callbacks, uuid, filter, filter_opaque, klass, eventID, cb, opaque, freecb, legacy, callbackID, serverFilter); if (ret == -1 && state->callbacks->count == 0 && state->timer != -1) { virEventRemoveTimeout(state->timer); state->timer = -1; } cleanup: virObjectEventStateUnlock(state); return ret; }
/** * virObjectEventStateRegisterID: * @conn: connection to associate with callback * @state: domain event state * @key: key of the object for event filtering * @klass: the base event class * @eventID: ID of the event type to register for * @cb: function to invoke when event occurs * @opaque: data blob to pass to @callback * @freecb: callback to free @opaque * @legacy: true if callback is tracked by function instead of callbackID * @callbackID: filled with callback ID * @serverFilter: true if server supports object filtering * * Register the function @cb with connection @conn, from @state, for * events of type @eventID, and return the registration handle in * @callbackID. * * The return value is only important when registering client-side * mirroring of remote events (since the public API is documented to * return the callbackID rather than a count). A return of 1 means * that this is the first use of this type of event, so a remote event * must be enabled; a return larger than 1 means that an existing * remote event can already feed this callback. If @serverFilter is * false, the return count assumes that a single global remote feeds * both generic and per-object callbacks, and that the event queue * will be fed with virObjectEventStateQueue(). If it is true, then * the return count assumes that the remote side is capable of per- * object filtering; the user must call virObjectEventStateSetRemote() * to record the remote id, and queue events with * virObjectEventStateQueueRemote(). * * Returns: the number of callbacks now registered, or -1 on error. */ int virObjectEventStateRegisterID(virConnectPtr conn, virObjectEventStatePtr state, const char *key, virObjectEventCallbackFilter filter, void *filter_opaque, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback cb, void *opaque, virFreeCallback freecb, bool legacy, int *callbackID, bool serverFilter) { int ret = -1; virObjectLock(state); if ((state->callbacks->count == 0) && (state->timer == -1) && (state->timer = virEventAddTimeout(-1, virObjectEventTimer, state, virObjectFreeCallback)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("could not initialize domain event timer")); goto cleanup; } /* event loop has one reference, but we need one more for the * timer's opaque argument */ virObjectRef(state); ret = virObjectEventCallbackListAddID(conn, state->callbacks, key, filter, filter_opaque, klass, eventID, cb, opaque, freecb, legacy, callbackID, serverFilter); if (ret < 0) virObjectEventStateCleanupTimer(state, false); cleanup: virObjectUnlock(state); return ret; }
static virLXCControllerPtr virLXCControllerNew(const char *name) { virLXCControllerPtr ctrl = NULL; virCapsPtr caps = NULL; char *configFile = NULL; if (VIR_ALLOC(ctrl) < 0) goto no_memory; ctrl->timerShutdown = -1; ctrl->firstClient = true; if (!(ctrl->name = strdup(name))) goto no_memory; if ((caps = lxcCapsInit(NULL)) == NULL) goto error; if ((configFile = virDomainConfigFile(LXC_STATE_DIR, ctrl->name)) == NULL) goto error; if ((ctrl->def = virDomainDefParseFile(caps, configFile, 1 << VIR_DOMAIN_VIRT_LXC, 0)) == NULL) goto error; if ((ctrl->timerShutdown = virEventAddTimeout(-1, virLXCControllerQuitTimer, ctrl, NULL)) < 0) goto error; cleanup: VIR_FREE(configFile); virObjectUnref(caps); return ctrl; no_memory: virReportOOMError(); error: virLXCControllerFree(ctrl); ctrl = NULL; goto cleanup; }
/* * Deinitialize virsh */ static bool virshDeinit(vshControl *ctl) { virshControlPtr priv = ctl->privData; vshDeinit(ctl); VIR_FREE(ctl->connname); if (priv->conn) { int ret; virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect); ret = virConnectClose(priv->conn); if (ret < 0) vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); else if (ret > 0) vshError(ctl, "%s", _("One or more references were leaked after " "disconnect from the hypervisor")); } virResetLastError(); if (ctl->eventLoopStarted) { int timer; virMutexLock(&ctl->lock); ctl->quit = true; /* HACK: Add a dummy timeout to break event loop */ timer = virEventAddTimeout(0, virshDeinitTimer, NULL, NULL); virMutexUnlock(&ctl->lock); virThreadJoin(&ctl->eventLoop); if (timer != -1) virEventRemoveTimeout(timer); if (ctl->eventTimerId != -1) virEventRemoveTimeout(ctl->eventTimerId); ctl->eventLoopStarted = false; } virMutexDestroy(&ctl->lock); return true; }
/** * virDomainEventStateNew: * @timeout_cb: virEventTimeoutCallback to call when timer expires * @timeout_opaque: Data for timeout_cb * @timeout_free: Optional virFreeCallback for freeing timeout_opaque * @requireTimer: If true, return an error if registering the timer fails. * This is fatal for drivers that sit behind the daemon * (qemu, lxc), since there should always be a event impl * registered. */ virDomainEventStatePtr virDomainEventStateNew(virEventTimeoutCallback timeout_cb, void *timeout_opaque, virFreeCallback timeout_free, bool requireTimer) { virDomainEventStatePtr state = NULL; if (VIR_ALLOC(state) < 0) { virReportOOMError(); goto error; } if (VIR_ALLOC(state->callbacks) < 0) { virReportOOMError(); goto error; } if (!(state->queue = virDomainEventQueueNew())) { goto error; } if ((state->timer = virEventAddTimeout(-1, timeout_cb, timeout_opaque, timeout_free)) < 0) { if (requireTimer == false) { VIR_DEBUG("virEventAddTimeout failed: No addTimeoutImpl defined. " "continuing without events."); } else { eventReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("could not initialize domain event timer")); goto error; } } return state; error: virDomainEventStateFree(state); return NULL; }
int virNetClientStreamEventAddCallback(virNetClientStreamPtr st, int events, virNetClientStreamEventCallback cb, void *opaque, virFreeCallback ff) { int ret = -1; virObjectLock(st); if (st->cb) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("multiple stream callbacks not supported")); goto cleanup; } virObjectRef(st); if ((st->cbTimer = virEventAddTimeout(-1, virNetClientStreamEventTimer, st, virObjectFreeCallback)) < 0) { virObjectUnref(st); goto cleanup; } st->cb = cb; st->cbOpaque = opaque; st->cbFree = ff; st->cbEvents = events; virNetClientStreamEventTimerUpdate(st); ret = 0; cleanup: virObjectUnlock(st); return ret; }