return NULL;
}
- if (virEventPollInit() < 0) {
- VIR_ERROR0(_("Failed to initialize event system"));
+ if (virEventRegisterDefaultImpl() < 0) {
virMutexDestroy(&server->lock);
if (virCondDestroy(&server->job) < 0)
{}
# endif
#endif
- virEventRegisterImpl(virEventPollAddHandle,
- virEventPollUpdateHandle,
- virEventPollRemoveHandle,
- virEventPollAddTimeout,
- virEventPollUpdateTimeout,
- virEventPollRemoveTimeout);
-
return server;
}
static int qemudOneLoop(void) {
sig_atomic_t errors;
- if (virEventPollRunOnce() < 0)
+ if (virEventRunDefaultImpl() < 0)
return -1;
/* Check for any signal handling errors and log them. */
virEventUpdateTimeoutFunc updateTimeout,
virEventRemoveTimeoutFunc removeTimeout);
+int virEventRegisterDefaultImpl(void);
+int virEventRunDefaultImpl(void);
+
/*
* Secret manipulation API
*/
VIR_FROM_SYSINFO = 37, /* Error from sysinfo/SMBIOS */
VIR_FROM_STREAMS = 38, /* Error from I/O streams */
VIR_FROM_VMWARE = 39, /* Error from VMware driver */
+ VIR_FROM_EVENT = 40, /* Error from event loop impl */
} virErrorDomain;
src/util/command.c
src/util/conf.c
src/util/dnsmasq.c
+src/util/event_poll.c
src/util/hooks.c
src/util/hostusb.c
src/util/interface.c
# event_poll.h
virEventPollToNativeEvents;
virEventPollFromNativeEvents;
-virEventPollRunOnce;
-virEventPollInit;
-virEventPollRemoveTimeout;
-virEventPollUpdateTimeout;
-virEventPollAddTimeout;
-virEventPollRemoveHandle;
-virEventPollUpdateHandle;
-virEventPollAddHandle;
# fdstream.h
virConnectGetSysinfo;
} LIBVIRT_0.8.6;
+LIBVIRT_0.9.0 {
+ global:
+ virEventRegisterDefaultImpl;
+ virEventRunDefaultImpl;
+} LIBVIRT_0.8.8;
+
# .... define new API here using predicted next version number ....
#include <config.h>
#include "event.h"
+#include "event_poll.h"
+#include "logging.h"
+#include "virterror_internal.h"
#include <stdlib.h>
return removeTimeoutImpl(timer);
}
+
+/*****************************************************
+ *
+ * Below this point are 3 *PUBLIC* APIs for event
+ * loop integration with applications using libvirt.
+ * These API contracts cannot be changed.
+ *
+ *****************************************************/
+
/**
* virEventRegisterImpl:
* @addHandle: the callback to add fd handles
* @updateTimeout: the callback to update a timeout
* @removeTimeout: the callback to remove a timeout
*
- * Registers an event implementation
+ * Registers an event implementation, to allow integration
+ * with an external event loop. Applications would use this
+ * to integrate with the libglib2 event loop, or libevent
+ * or the QT event loop.
+ *
+ * If an application does not need to integrate with an
+ * existing event loop implementation, then the
+ * virEventRegisterDefaultImpl method can be used to setup
+ * the generic libvirt implementation.
*/
void virEventRegisterImpl(virEventAddHandleFunc addHandle,
virEventUpdateHandleFunc updateHandle,
virEventRemoveHandleFunc removeHandle,
virEventAddTimeoutFunc addTimeout,
virEventUpdateTimeoutFunc updateTimeout,
- virEventRemoveTimeoutFunc removeTimeout) {
+ virEventRemoveTimeoutFunc removeTimeout)
+{
+ VIR_DEBUG("addHandle=%p updateHandle=%p removeHandle=%p "
+ "addTimeout=%p updateTimeout=%p removeTimeout=%p",
+ addHandle, updateHandle, removeHandle,
+ addTimeout, updateTimeout, removeTimeout);
+
addHandleImpl = addHandle;
updateHandleImpl = updateHandle;
removeHandleImpl = removeHandle;
updateTimeoutImpl = updateTimeout;
removeTimeoutImpl = removeTimeout;
}
+
+/**
+ * virEventRegisterDefaultImpl:
+ *
+ * Registers a default event implementation based on the
+ * poll() system call. This is a generic implementation
+ * that can be used by any client application which does
+ * not have a need to integrate with an external event
+ * loop impl.
+ *
+ * Once registered, the application can invoke
+ * virEventRunDefaultImpl in a loop to process
+ * events
+ */
+int virEventRegisterDefaultImpl(void)
+{
+ VIR_DEBUG0("");
+
+ virResetLastError();
+
+ if (virEventPollInit() < 0) {
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ virEventRegisterImpl(
+ virEventPollAddHandle,
+ virEventPollUpdateHandle,
+ virEventPollRemoveHandle,
+ virEventPollAddTimeout,
+ virEventPollUpdateTimeout,
+ virEventPollRemoveTimeout
+ );
+
+ return 0;
+}
+
+
+/**
+ * virEventRunDefaultImpl:
+ *
+ * Run one iteration of the event loop. Applications
+ * will generally want to have a thread which invokes
+ * this method in an infinite loop
+ *
+ * static bool quit = false;
+ *
+ * while (!quit) {
+ * if (virEventRunDefaultImpl() < 0)
+ * ...print error...
+ * }
+ */
+int virEventRunDefaultImpl(void)
+{
+ VIR_DEBUG0("");
+ virResetLastError();
+
+ if (virEventPollRunOnce() < 0) {
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ return 0;
+}
#include "memory.h"
#include "util.h"
#include "ignore-value.h"
+#include "virterror_internal.h"
#define EVENT_DEBUG(fmt, ...) VIR_DEBUG(fmt, __VA_ARGS__)
+#define VIR_FROM_THIS VIR_FROM_EVENT
+
+#define virEventError(code, ...) \
+ virReportErrorHelper(NULL, VIR_FROM_EVENT, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
static int virEventPollInterruptLocked(void);
/* State for a single file handle being monitored */
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to get current time"));
return -1;
}
}
/* Setup the poll file handle data structs */
- if (VIR_ALLOC_N(fds, *nfds) < 0)
+ if (VIR_ALLOC_N(fds, *nfds) < 0) {
+ virReportOOMError();
return NULL;
+ }
*nfds = 0;
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
VIR_DEBUG("Dispatch %d", ntimeouts);
if (gettimeofday(&tv, NULL) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to get current time"));
return -1;
}
now = (((unsigned long long)tv.tv_sec)*1000) +
if (errno == EINTR) {
goto retry;
}
+ virReportSystemError(errno, "%s",
+ _("Unable to poll on file handles"));
goto error_unlocked;
}
EVENT_DEBUG("Poll got %d event(s)", ret);
int virEventPollInit(void)
{
if (virMutexInit(&eventLoop.lock) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to initialize mutex"));
return -1;
}
virSetNonBlock(eventLoop.wakeupfd[1]) < 0 ||
virSetCloseExec(eventLoop.wakeupfd[0]) < 0 ||
virSetCloseExec(eventLoop.wakeupfd[1]) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to setup wakeup pipe"));
return -1;
}
if (virEventPollAddHandle(eventLoop.wakeupfd[0],
VIR_EVENT_HANDLE_READABLE,
virEventPollHandleWakeup, NULL, NULL) < 0) {
+ virEventError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to add handle %d to event loop"),
+ eventLoop.wakeupfd[0]);
return -1;
}
case VIR_FROM_STREAMS:
dom = "Streams ";
break;
+ case VIR_FROM_EVENT:
+ dom = "Events ";
+ break;
}
return(dom);
}
# include "virterror_internal.h"
# include "event.h"
-# include "event_poll.h"
/* ie Ctrl-] as per telnet */
# define CTRL_CLOSE_BRACKET '\35'
NULL);
while (!con->quit) {
- if (virEventPollRunOnce() < 0)
+ if (virEventRunDefaultImpl() < 0)
break;
}
/* set up the signals handlers to catch disconnections */
vshSetupSignals();
- virEventRegisterImpl(virEventPollAddHandle,
- virEventPollUpdateHandle,
- virEventPollRemoveHandle,
- virEventPollAddTimeout,
- virEventPollUpdateTimeout,
- virEventPollRemoveTimeout);
- virEventPollInit();
+ if (virEventRegisterDefaultImpl() < 0)
+ return FALSE;
ctl->conn = virConnectOpenAuth(ctl->name,
virConnectAuthPtrDefault,