]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Expose event loop implementation as a public API
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 2 Mar 2011 16:59:54 +0000 (16:59 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 7 Mar 2011 14:16:13 +0000 (14:16 +0000)
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

daemon/libvirtd.c
include/libvirt/libvirt.h.in
include/libvirt/virterror.h
po/POTFILES.in
src/libvirt_private.syms
src/libvirt_public.syms
src/util/event.c
src/util/event_poll.c
src/util/virterror.c
tools/console.c
tools/virsh.c

index 602edbe37968fadda46d655937dde17122b9370a..452566cc3f87a33aa9b87f01916fae8a8a8a12fa 100644 (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. */
index 5dfb752176e613cbc9f45dda0a27898bc6a9e827..618b350c35d6d2b072dc01d46b34e101d6dcce5f 100644 (file)
@@ -1768,6 +1768,9 @@ void virEventRegisterImpl(virEventAddHandleFunc addHandle,
                           virEventUpdateTimeoutFunc updateTimeout,
                           virEventRemoveTimeoutFunc removeTimeout);
 
+int virEventRegisterDefaultImpl(void);
+int virEventRunDefaultImpl(void);
+
 /*
  * Secret manipulation API
  */
index 5962dbfee5ea6d6a20964107e8062e4e03fc4222..6b8c789541ce89c17b1ec21f0811ecaf807e95c0 100644 (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;
 
 
index 9852f97d7a69660dd7f560b2b459b2a585dd4f0c..1ed276507ea0a1577cdc3296a09c2e8ad4db1ac2 100644 (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
index 07810eacc008f47cc5136e90753f0f3342aa20ab..efcf3c5ec03f5f7fb29c53fd6285abcd5fbdd516 100644 (file)
@@ -396,14 +396,6 @@ virEventUpdateTimeout;
 # event_poll.h
 virEventPollToNativeEvents;
 virEventPollFromNativeEvents;
-virEventPollRunOnce;
-virEventPollInit;
-virEventPollRemoveTimeout;
-virEventPollUpdateTimeout;
-virEventPollAddTimeout;
-virEventPollRemoveHandle;
-virEventPollUpdateHandle;
-virEventPollAddHandle;
 
 
 # fdstream.h
index 1a45be142027cc242bb76877d4865094341ece9c..cca8d085e763e485e68119b436fda7b70ae8ca15 100644 (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 ....
index 680fef91318386ffb37e708f643f5679ee4209fe..0d88b557b62191d6748cde5268eab2f606231f4d 100644 (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;
+}
index 13628409cd9e6dccd4f1551a32c659f30c385ac0..dd83fc34a8698683cc8db838fe68fa1486a8681d 100644 (file)
 #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;
     }
 
index 89bb2a5acaa3cee6ba74a4efea165299a663c36b..aaa37206c2d9fbf968a417a51e97714763d0369e 100644 (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);
 }
index 84c28a3792cb8eb4341426229506ae4420d39f72..b9dd26832d6f9e92d02aa1ff8ff34d7317297b62 100644 (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;
     }
 
index 95bcfcc987d888430963c40a41d2bf2d8ee034ad..f3754d74330c7739c728f76e33b252fcd341dd1a 100644 (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,