mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
Expose event loop implementation as a public API
Not all applications have an existing event loop they need to integrate with. Forcing them to implement the libvirt event loop integration APIs is an undue burden. This just exposes our simple poll() based implementation for apps to use. So instead of calling virEventRegister(....callbacks...) The app would call virEventRegisterDefaultImpl() And then have a thread somewhere calling static bool quit = false; .... while (!quit) virEventRunDefaultImpl() * daemon/libvirtd.c, tools/console.c, tools/virsh.c: Convert to public event loop APIs * include/libvirt/libvirt.h.in, src/libvirt_private.syms: Add virEventRegisterDefaultImpl and virEventRunDefaultImpl * src/util/event.c: Implement virEventRegisterDefaultImpl and virEventRunDefaultImpl using poll() event loop * src/util/event_poll.c: Add full error reporting * src/util/virterror.c, include/libvirt/virterror.h: Add VIR_FROM_EVENTS
This commit is contained in:
parent
343eaa150b
commit
2ed6cc7bec
@ -893,8 +893,7 @@ static struct qemud_server *qemudInitialize(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (virEventPollInit() < 0) {
|
||||
VIR_ERROR0(_("Failed to initialize event system"));
|
||||
if (virEventRegisterDefaultImpl() < 0) {
|
||||
virMutexDestroy(&server->lock);
|
||||
if (virCondDestroy(&server->job) < 0)
|
||||
{}
|
||||
@ -957,13 +956,6 @@ static struct qemud_server *qemudInitialize(void) {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
virEventRegisterImpl(virEventPollAddHandle,
|
||||
virEventPollUpdateHandle,
|
||||
virEventPollRemoveHandle,
|
||||
virEventPollAddTimeout,
|
||||
virEventPollUpdateTimeout,
|
||||
virEventPollRemoveTimeout);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@ -2283,7 +2275,7 @@ qemudDispatchServerEvent(int watch, int fd, int events, void *opaque) {
|
||||
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. */
|
||||
|
@ -1768,6 +1768,9 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
|
||||
virEventUpdateTimeoutFunc updateTimeout,
|
||||
virEventRemoveTimeoutFunc removeTimeout);
|
||||
|
||||
int virEventRegisterDefaultImpl(void);
|
||||
int virEventRunDefaultImpl(void);
|
||||
|
||||
/*
|
||||
* Secret manipulation API
|
||||
*/
|
||||
|
@ -79,6 +79,7 @@ typedef enum {
|
||||
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;
|
||||
|
||||
|
||||
|
@ -88,6 +88,7 @@ src/util/cgroup.c
|
||||
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
|
||||
|
@ -396,14 +396,6 @@ virEventUpdateTimeout;
|
||||
# event_poll.h
|
||||
virEventPollToNativeEvents;
|
||||
virEventPollFromNativeEvents;
|
||||
virEventPollRunOnce;
|
||||
virEventPollInit;
|
||||
virEventPollRemoveTimeout;
|
||||
virEventPollUpdateTimeout;
|
||||
virEventPollAddTimeout;
|
||||
virEventPollRemoveHandle;
|
||||
virEventPollUpdateHandle;
|
||||
virEventPollAddHandle;
|
||||
|
||||
|
||||
# fdstream.h
|
||||
|
@ -424,4 +424,10 @@ LIBVIRT_0.8.8 {
|
||||
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 ....
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include <config.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "event_poll.h"
|
||||
#include "logging.h"
|
||||
#include "virterror_internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -77,6 +80,15 @@ int virEventRemoveTimeout(int timer) {
|
||||
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
|
||||
@ -86,14 +98,28 @@ int virEventRemoveTimeout(int timer) {
|
||||
* @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;
|
||||
@ -101,3 +127,67 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
|
||||
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;
|
||||
}
|
||||
|
@ -36,9 +36,16 @@
|
||||
#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 */
|
||||
@ -316,6 +323,8 @@ static int virEventPollCalculateTimeout(int *timeout) {
|
||||
struct timeval tv;
|
||||
|
||||
if (gettimeofday(&tv, NULL) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to get current time"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -350,8 +359,10 @@ static struct pollfd *virEventPollMakePollFDs(int *nfds) {
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
@ -393,6 +404,8 @@ static int virEventPollDispatchTimeouts(void) {
|
||||
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) +
|
||||
@ -584,6 +597,8 @@ int virEventPollRunOnce(void) {
|
||||
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);
|
||||
@ -626,6 +641,8 @@ static void virEventPollHandleWakeup(int watch ATTRIBUTE_UNUSED,
|
||||
int virEventPollInit(void)
|
||||
{
|
||||
if (virMutexInit(&eventLoop.lock) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to initialize mutex"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -634,12 +651,17 @@ int virEventPollInit(void)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -200,6 +200,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
|
||||
case VIR_FROM_STREAMS:
|
||||
dom = "Streams ";
|
||||
break;
|
||||
case VIR_FROM_EVENT:
|
||||
dom = "Events ";
|
||||
break;
|
||||
}
|
||||
return(dom);
|
||||
}
|
||||
|
@ -44,7 +44,6 @@
|
||||
# include "virterror_internal.h"
|
||||
|
||||
# include "event.h"
|
||||
# include "event_poll.h"
|
||||
|
||||
/* ie Ctrl-] as per telnet */
|
||||
# define CTRL_CLOSE_BRACKET '\35'
|
||||
@ -350,7 +349,7 @@ int vshRunConsole(virDomainPtr dom, const char *devname)
|
||||
NULL);
|
||||
|
||||
while (!con->quit) {
|
||||
if (virEventPollRunOnce() < 0)
|
||||
if (virEventRunDefaultImpl() < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -11677,13 +11677,8 @@ vshInit(vshControl *ctl)
|
||||
/* 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,
|
||||
|
Loading…
Reference in New Issue
Block a user