提交 2ed6cc7b 编写于 作者: D Daniel P. Berrange

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
上级 343eaa15
...@@ -893,8 +893,7 @@ static struct qemud_server *qemudInitialize(void) { ...@@ -893,8 +893,7 @@ static struct qemud_server *qemudInitialize(void) {
return NULL; return NULL;
} }
if (virEventPollInit() < 0) { if (virEventRegisterDefaultImpl() < 0) {
VIR_ERROR0(_("Failed to initialize event system"));
virMutexDestroy(&server->lock); virMutexDestroy(&server->lock);
if (virCondDestroy(&server->job) < 0) if (virCondDestroy(&server->job) < 0)
{} {}
...@@ -957,13 +956,6 @@ static struct qemud_server *qemudInitialize(void) { ...@@ -957,13 +956,6 @@ static struct qemud_server *qemudInitialize(void) {
# endif # endif
#endif #endif
virEventRegisterImpl(virEventPollAddHandle,
virEventPollUpdateHandle,
virEventPollRemoveHandle,
virEventPollAddTimeout,
virEventPollUpdateTimeout,
virEventPollRemoveTimeout);
return server; return server;
} }
...@@ -2283,7 +2275,7 @@ qemudDispatchServerEvent(int watch, int fd, int events, void *opaque) { ...@@ -2283,7 +2275,7 @@ qemudDispatchServerEvent(int watch, int fd, int events, void *opaque) {
static int qemudOneLoop(void) { static int qemudOneLoop(void) {
sig_atomic_t errors; sig_atomic_t errors;
if (virEventPollRunOnce() < 0) if (virEventRunDefaultImpl() < 0)
return -1; return -1;
/* Check for any signal handling errors and log them. */ /* Check for any signal handling errors and log them. */
......
...@@ -1768,6 +1768,9 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle, ...@@ -1768,6 +1768,9 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
virEventUpdateTimeoutFunc updateTimeout, virEventUpdateTimeoutFunc updateTimeout,
virEventRemoveTimeoutFunc removeTimeout); virEventRemoveTimeoutFunc removeTimeout);
int virEventRegisterDefaultImpl(void);
int virEventRunDefaultImpl(void);
/* /*
* Secret manipulation API * Secret manipulation API
*/ */
......
...@@ -79,6 +79,7 @@ typedef enum { ...@@ -79,6 +79,7 @@ typedef enum {
VIR_FROM_SYSINFO = 37, /* Error from sysinfo/SMBIOS */ VIR_FROM_SYSINFO = 37, /* Error from sysinfo/SMBIOS */
VIR_FROM_STREAMS = 38, /* Error from I/O streams */ VIR_FROM_STREAMS = 38, /* Error from I/O streams */
VIR_FROM_VMWARE = 39, /* Error from VMware driver */ VIR_FROM_VMWARE = 39, /* Error from VMware driver */
VIR_FROM_EVENT = 40, /* Error from event loop impl */
} virErrorDomain; } virErrorDomain;
......
...@@ -88,6 +88,7 @@ src/util/cgroup.c ...@@ -88,6 +88,7 @@ src/util/cgroup.c
src/util/command.c src/util/command.c
src/util/conf.c src/util/conf.c
src/util/dnsmasq.c src/util/dnsmasq.c
src/util/event_poll.c
src/util/hooks.c src/util/hooks.c
src/util/hostusb.c src/util/hostusb.c
src/util/interface.c src/util/interface.c
......
...@@ -396,14 +396,6 @@ virEventUpdateTimeout; ...@@ -396,14 +396,6 @@ virEventUpdateTimeout;
# event_poll.h # event_poll.h
virEventPollToNativeEvents; virEventPollToNativeEvents;
virEventPollFromNativeEvents; virEventPollFromNativeEvents;
virEventPollRunOnce;
virEventPollInit;
virEventPollRemoveTimeout;
virEventPollUpdateTimeout;
virEventPollAddTimeout;
virEventPollRemoveHandle;
virEventPollUpdateHandle;
virEventPollAddHandle;
# fdstream.h # fdstream.h
......
...@@ -424,4 +424,10 @@ LIBVIRT_0.8.8 { ...@@ -424,4 +424,10 @@ LIBVIRT_0.8.8 {
virConnectGetSysinfo; virConnectGetSysinfo;
} LIBVIRT_0.8.6; } LIBVIRT_0.8.6;
LIBVIRT_0.9.0 {
global:
virEventRegisterDefaultImpl;
virEventRunDefaultImpl;
} LIBVIRT_0.8.8;
# .... define new API here using predicted next version number .... # .... define new API here using predicted next version number ....
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
#include <config.h> #include <config.h>
#include "event.h" #include "event.h"
#include "event_poll.h"
#include "logging.h"
#include "virterror_internal.h"
#include <stdlib.h> #include <stdlib.h>
...@@ -77,6 +80,15 @@ int virEventRemoveTimeout(int timer) { ...@@ -77,6 +80,15 @@ int virEventRemoveTimeout(int timer) {
return removeTimeoutImpl(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: * virEventRegisterImpl:
* @addHandle: the callback to add fd handles * @addHandle: the callback to add fd handles
...@@ -86,14 +98,28 @@ int virEventRemoveTimeout(int timer) { ...@@ -86,14 +98,28 @@ int virEventRemoveTimeout(int timer) {
* @updateTimeout: the callback to update a timeout * @updateTimeout: the callback to update a timeout
* @removeTimeout: the callback to remove 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, void virEventRegisterImpl(virEventAddHandleFunc addHandle,
virEventUpdateHandleFunc updateHandle, virEventUpdateHandleFunc updateHandle,
virEventRemoveHandleFunc removeHandle, virEventRemoveHandleFunc removeHandle,
virEventAddTimeoutFunc addTimeout, virEventAddTimeoutFunc addTimeout,
virEventUpdateTimeoutFunc updateTimeout, 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; addHandleImpl = addHandle;
updateHandleImpl = updateHandle; updateHandleImpl = updateHandle;
removeHandleImpl = removeHandle; removeHandleImpl = removeHandle;
...@@ -101,3 +127,67 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle, ...@@ -101,3 +127,67 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
updateTimeoutImpl = updateTimeout; updateTimeoutImpl = updateTimeout;
removeTimeoutImpl = removeTimeout; 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 @@ ...@@ -36,9 +36,16 @@
#include "memory.h" #include "memory.h"
#include "util.h" #include "util.h"
#include "ignore-value.h" #include "ignore-value.h"
#include "virterror_internal.h"
#define EVENT_DEBUG(fmt, ...) VIR_DEBUG(fmt, __VA_ARGS__) #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); static int virEventPollInterruptLocked(void);
/* State for a single file handle being monitored */ /* State for a single file handle being monitored */
...@@ -316,6 +323,8 @@ static int virEventPollCalculateTimeout(int *timeout) { ...@@ -316,6 +323,8 @@ static int virEventPollCalculateTimeout(int *timeout) {
struct timeval tv; struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) { if (gettimeofday(&tv, NULL) < 0) {
virReportSystemError(errno, "%s",
_("Unable to get current time"));
return -1; return -1;
} }
...@@ -350,8 +359,10 @@ static struct pollfd *virEventPollMakePollFDs(int *nfds) { ...@@ -350,8 +359,10 @@ static struct pollfd *virEventPollMakePollFDs(int *nfds) {
} }
/* Setup the poll file handle data structs */ /* Setup the poll file handle data structs */
if (VIR_ALLOC_N(fds, *nfds) < 0) if (VIR_ALLOC_N(fds, *nfds) < 0) {
virReportOOMError();
return NULL; return NULL;
}
*nfds = 0; *nfds = 0;
for (i = 0 ; i < eventLoop.handlesCount ; i++) { for (i = 0 ; i < eventLoop.handlesCount ; i++) {
...@@ -393,6 +404,8 @@ static int virEventPollDispatchTimeouts(void) { ...@@ -393,6 +404,8 @@ static int virEventPollDispatchTimeouts(void) {
VIR_DEBUG("Dispatch %d", ntimeouts); VIR_DEBUG("Dispatch %d", ntimeouts);
if (gettimeofday(&tv, NULL) < 0) { if (gettimeofday(&tv, NULL) < 0) {
virReportSystemError(errno, "%s",
_("Unable to get current time"));
return -1; return -1;
} }
now = (((unsigned long long)tv.tv_sec)*1000) + now = (((unsigned long long)tv.tv_sec)*1000) +
...@@ -584,6 +597,8 @@ int virEventPollRunOnce(void) { ...@@ -584,6 +597,8 @@ int virEventPollRunOnce(void) {
if (errno == EINTR) { if (errno == EINTR) {
goto retry; goto retry;
} }
virReportSystemError(errno, "%s",
_("Unable to poll on file handles"));
goto error_unlocked; goto error_unlocked;
} }
EVENT_DEBUG("Poll got %d event(s)", ret); EVENT_DEBUG("Poll got %d event(s)", ret);
...@@ -626,6 +641,8 @@ static void virEventPollHandleWakeup(int watch ATTRIBUTE_UNUSED, ...@@ -626,6 +641,8 @@ static void virEventPollHandleWakeup(int watch ATTRIBUTE_UNUSED,
int virEventPollInit(void) int virEventPollInit(void)
{ {
if (virMutexInit(&eventLoop.lock) < 0) { if (virMutexInit(&eventLoop.lock) < 0) {
virReportSystemError(errno, "%s",
_("Unable to initialize mutex"));
return -1; return -1;
} }
...@@ -634,12 +651,17 @@ int virEventPollInit(void) ...@@ -634,12 +651,17 @@ int virEventPollInit(void)
virSetNonBlock(eventLoop.wakeupfd[1]) < 0 || virSetNonBlock(eventLoop.wakeupfd[1]) < 0 ||
virSetCloseExec(eventLoop.wakeupfd[0]) < 0 || virSetCloseExec(eventLoop.wakeupfd[0]) < 0 ||
virSetCloseExec(eventLoop.wakeupfd[1]) < 0) { virSetCloseExec(eventLoop.wakeupfd[1]) < 0) {
virReportSystemError(errno, "%s",
_("Unable to setup wakeup pipe"));
return -1; return -1;
} }
if (virEventPollAddHandle(eventLoop.wakeupfd[0], if (virEventPollAddHandle(eventLoop.wakeupfd[0],
VIR_EVENT_HANDLE_READABLE, VIR_EVENT_HANDLE_READABLE,
virEventPollHandleWakeup, NULL, NULL) < 0) { virEventPollHandleWakeup, NULL, NULL) < 0) {
virEventError(VIR_ERR_INTERNAL_ERROR,
_("Unable to add handle %d to event loop"),
eventLoop.wakeupfd[0]);
return -1; return -1;
} }
......
...@@ -200,6 +200,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { ...@@ -200,6 +200,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_STREAMS: case VIR_FROM_STREAMS:
dom = "Streams "; dom = "Streams ";
break; break;
case VIR_FROM_EVENT:
dom = "Events ";
break;
} }
return(dom); return(dom);
} }
......
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
# include "virterror_internal.h" # include "virterror_internal.h"
# include "event.h" # include "event.h"
# include "event_poll.h"
/* ie Ctrl-] as per telnet */ /* ie Ctrl-] as per telnet */
# define CTRL_CLOSE_BRACKET '\35' # define CTRL_CLOSE_BRACKET '\35'
...@@ -350,7 +349,7 @@ int vshRunConsole(virDomainPtr dom, const char *devname) ...@@ -350,7 +349,7 @@ int vshRunConsole(virDomainPtr dom, const char *devname)
NULL); NULL);
while (!con->quit) { while (!con->quit) {
if (virEventPollRunOnce() < 0) if (virEventRunDefaultImpl() < 0)
break; break;
} }
......
...@@ -11677,13 +11677,8 @@ vshInit(vshControl *ctl) ...@@ -11677,13 +11677,8 @@ vshInit(vshControl *ctl)
/* set up the signals handlers to catch disconnections */ /* set up the signals handlers to catch disconnections */
vshSetupSignals(); vshSetupSignals();
virEventRegisterImpl(virEventPollAddHandle, if (virEventRegisterDefaultImpl() < 0)
virEventPollUpdateHandle, return FALSE;
virEventPollRemoveHandle,
virEventPollAddTimeout,
virEventPollUpdateTimeout,
virEventPollRemoveTimeout);
virEventPollInit();
ctl->conn = virConnectOpenAuth(ctl->name, ctl->conn = virConnectOpenAuth(ctl->name,
virConnectAuthPtrDefault, virConnectAuthPtrDefault,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册