1
0
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:
Daniel P. Berrange 2011-03-02 16:59:54 +00:00
parent 343eaa150b
commit 2ed6cc7bec
11 changed files with 134 additions and 30 deletions

View File

@ -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. */

View File

@ -1768,6 +1768,9 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
virEventUpdateTimeoutFunc updateTimeout,
virEventRemoveTimeoutFunc removeTimeout);
int virEventRegisterDefaultImpl(void);
int virEventRunDefaultImpl(void);
/*
* Secret manipulation API
*/

View File

@ -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;

View File

@ -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

View File

@ -396,14 +396,6 @@ virEventUpdateTimeout;
# event_poll.h
virEventPollToNativeEvents;
virEventPollFromNativeEvents;
virEventPollRunOnce;
virEventPollInit;
virEventPollRemoveTimeout;
virEventPollUpdateTimeout;
virEventPollAddTimeout;
virEventPollRemoveHandle;
virEventPollUpdateHandle;
virEventPollAddHandle;
# fdstream.h

View File

@ -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 ....

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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,