[libvirt] [PATCH] Update event loop example programs to demonstrate best practice

Daniel P. Berrange berrange at redhat.com
Wed Mar 23 15:24:02 UTC 2011


The example C event loop code is a nasty hack and not compliant
with the require API semantics. Delete this, so that developers
don't mistakenly copy it. Instead call the new public event loop
APIs.

Update the python event loop example, so that it can optionally
use the public event APIs, as an alternative to the pure python
code. The pure python event code is a good working example, so
don't delete it.

* examples/domain-events/events-c/event-test.c: Replace event
  loop code with use of public APIs
* examples/domain-events/events-python/event-test.py: Allow
  optional use of new public event APIs
---
 examples/domain-events/events-c/event-test.c       |  163 +------------------
 examples/domain-events/events-python/event-test.py |   29 ++++-
 2 files changed, 36 insertions(+), 156 deletions(-)

diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c
index 6e3a160..ee68bb1 100644
--- a/examples/domain-events/events-c/event-test.c
+++ b/examples/domain-events/events-c/event-test.c
@@ -5,10 +5,8 @@
 #include <string.h>
 #include <signal.h>
 
-#if HAVE_SYS_POLL_H
-# include <sys/types.h>
-# include <sys/poll.h>
 # include <libvirt/libvirt.h>
+# include <libvirt/virterror.h>
 
 # define VIR_DEBUG0(fmt) printf("%s:%d :: " fmt "\n", \
         __func__, __LINE__)
@@ -20,22 +18,6 @@
 #  define ATTRIBUTE_UNUSED __attribute__((__unused__))
 # endif
 
-/* handle globals */
-int h_fd = 0;
-virEventHandleType h_event = 0;
-virEventHandleCallback h_cb = NULL;
-virFreeCallback h_ff = NULL;
-void *h_opaque = NULL;
-
-/* timeout globals */
-# define TIMEOUT_MS 1000
-int t_active = 0;
-int t_timeout = -1;
-virEventTimeoutCallback t_cb = NULL;
-virFreeCallback t_ff = NULL;
-void *t_opaque = NULL;
-
-
 /* Prototypes */
 const char *eventToString(int event);
 int myEventAddHandleFunc  (int fd, int event,
@@ -266,94 +248,6 @@ static void myFreeFunc(void *opaque)
 }
 
 
-/* EventImpl Functions */
-int myEventHandleTypeToPollEvent(virEventHandleType events)
-{
-    int ret = 0;
-    if(events & VIR_EVENT_HANDLE_READABLE)
-        ret |= POLLIN;
-    if(events & VIR_EVENT_HANDLE_WRITABLE)
-        ret |= POLLOUT;
-    if(events & VIR_EVENT_HANDLE_ERROR)
-        ret |= POLLERR;
-    if(events & VIR_EVENT_HANDLE_HANGUP)
-        ret |= POLLHUP;
-    return ret;
-}
-
-virEventHandleType myPollEventToEventHandleType(int events)
-{
-    virEventHandleType ret = 0;
-    if(events & POLLIN)
-        ret |= VIR_EVENT_HANDLE_READABLE;
-    if(events & POLLOUT)
-        ret |= VIR_EVENT_HANDLE_WRITABLE;
-    if(events & POLLERR)
-        ret |= VIR_EVENT_HANDLE_ERROR;
-    if(events & POLLHUP)
-        ret |= VIR_EVENT_HANDLE_HANGUP;
-    return ret;
-}
-
-int  myEventAddHandleFunc(int fd, int event,
-                          virEventHandleCallback cb,
-                          void *opaque,
-                          virFreeCallback ff)
-{
-    VIR_DEBUG("Add handle %d %d %p %p", fd, event, cb, opaque);
-    h_fd = fd;
-    h_event = myEventHandleTypeToPollEvent(event);
-    h_cb = cb;
-    h_ff = ff;
-    h_opaque = opaque;
-    return 0;
-}
-
-void myEventUpdateHandleFunc(int fd, int event)
-{
-    VIR_DEBUG("Updated Handle %d %d", fd, event);
-    h_event = myEventHandleTypeToPollEvent(event);
-    return;
-}
-
-int  myEventRemoveHandleFunc(int fd)
-{
-    VIR_DEBUG("Removed Handle %d", fd);
-    h_fd = 0;
-    if (h_ff)
-       (h_ff)(h_opaque);
-    return 0;
-}
-
-int myEventAddTimeoutFunc(int timeout,
-                          virEventTimeoutCallback cb,
-                          void *opaque,
-                          virFreeCallback ff)
-{
-    VIR_DEBUG("Adding Timeout %d %p %p", timeout, cb, opaque);
-    t_active = 1;
-    t_timeout = timeout;
-    t_cb = cb;
-    t_ff = ff;
-    t_opaque = opaque;
-    return 0;
-}
-
-void myEventUpdateTimeoutFunc(int timer ATTRIBUTE_UNUSED, int timeout)
-{
-    /*VIR_DEBUG("Timeout updated %d %d", timer, timeout);*/
-    t_timeout = timeout;
-}
-
-int myEventRemoveTimeoutFunc(int timer)
-{
-   VIR_DEBUG("Timeout removed %d", timer);
-   t_active = 0;
-   if (t_ff)
-       (t_ff)(t_opaque);
-   return 0;
-}
-
 /* main test functions */
 
 void usage(const char *pname)
@@ -372,7 +266,6 @@ static void stop(int sig)
 
 int main(int argc, char **argv)
 {
-    int sts;
     int callback1ret = -1;
     int callback2ret = -1;
     int callback3ret = -1;
@@ -386,17 +279,12 @@ int main(int argc, char **argv)
 
     action_stop.sa_handler = stop;
 
-    if(argc > 1 && STREQ(argv[1],"--help")) {
+    if (argc > 1 && STREQ(argv[1],"--help")) {
         usage(argv[0]);
         return -1;
     }
 
-    virEventRegisterImpl( myEventAddHandleFunc,
-                          myEventUpdateHandleFunc,
-                          myEventRemoveHandleFunc,
-                          myEventAddTimeoutFunc,
-                          myEventUpdateTimeoutFunc,
-                          myEventRemoveTimeoutFunc);
+    virEventRegisterDefaultImpl();
 
     virConnectPtr dconn = NULL;
     dconn = virConnectOpenReadOnly (argv[1] ? argv[1] : NULL);
@@ -451,38 +339,12 @@ int main(int argc, char **argv)
         (callback5ret != -1) &&
         (callback6ret != -1) &&
         (callback7ret != -1)) {
-        while(run) {
-            struct pollfd pfd = { .fd = h_fd,
-                              .events = h_event,
-                              .revents = 0};
-
-            sts = poll(&pfd, 1, TIMEOUT_MS);
-
-            /* if t_timeout < 0 then t_cb must not be called */
-            if (t_cb && t_active && t_timeout >= 0) {
-                t_cb(t_timeout,t_opaque);
-            }
-
-            if (sts == 0) {
-                /* VIR_DEBUG0("Poll timeout"); */
-                continue;
-            }
-            if (sts < 0 ) {
-                VIR_DEBUG0("Poll failed");
-                continue;
-            }
-            if ( pfd.revents & POLLHUP ) {
-                VIR_DEBUG0("Reset by peer");
-                return -1;
+        while (run) {
+            if (virEventRunDefaultImpl() < 0) {
+                virErrorPtr err = virGetLastError();
+                fprintf(stderr, "Failed to run event loop: %s\n",
+                        err && err->message ? err->message : "Unknown error");
             }
-
-            if(h_cb) {
-                h_cb(0,
-                     h_fd,
-                     myPollEventToEventHandleType(pfd.revents & h_event),
-                     h_opaque);
-            }
-
         }
 
         VIR_DEBUG0("Deregistering event handlers");
@@ -496,17 +358,10 @@ int main(int argc, char **argv)
     }
 
     VIR_DEBUG0("Closing connection");
-    if( dconn && virConnectClose(dconn)<0 ) {
+    if (dconn && virConnectClose(dconn) < 0) {
         printf("error closing\n");
     }
 
     printf("done\n");
     return 0;
 }
-
-#else
-int main(void) {
-    printf("event-test program not available without sys/poll.h support\n");
-    return 1;
-}
-#endif
diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py
index c149ed9..df75dce 100644
--- a/examples/domain-events/events-python/event-test.py
+++ b/examples/domain-events/events-python/event-test.py
@@ -15,6 +15,17 @@ import errno
 import time
 import threading
 
+# For the sake of demonstration, this example program includes
+# an implementation of a pure python event loop. Most applications
+# would be better off just using the default libvirt event loop
+# APIs, instead of implementing this in python. The exception is
+# where an application wants to integrate with an existing 3rd
+# party event loop impl
+#
+# Change this to 'False' to make the demo use the native
+# libvirt event loop impl
+use_pure_python_event_loop = True
+
 do_debug = False
 def debug(msg):
     global do_debug
@@ -392,6 +403,10 @@ def virEventLoopPureRun():
     global eventLoop
     eventLoop.run_loop()
 
+def virEventLoopNativeRun():
+    while True:
+        libvirt.virEventRunDefaultImpl()
+
 # Spawn a background thread to run the event loop
 def virEventLoopPureStart():
     global eventLoopThread
@@ -400,6 +415,13 @@ def virEventLoopPureStart():
     eventLoopThread.setDaemon(True)
     eventLoopThread.start()
 
+def virEventLoopNativeStart():
+    global eventLoopThread
+    libvirt.virEventRegisterDefaultImpl()
+    eventLoopThread = threading.Thread(target=virEventLoopNativeRun, name="libvirtEventLoop")
+    eventLoopThread.setDaemon(True)
+    eventLoopThread.start()
+
 
 ##########################################################################
 # Everything that now follows is a simple demo of domain lifecycle events
@@ -474,9 +496,12 @@ def main():
     print "Using uri:" + uri
 
     # Run a background thread with the event loop
-    virEventLoopPureStart()
+    if use_pure_python_event_loop:
+        virEventLoopPureStart()
+    else:
+        virEventLoopNativeStart()
 
-    vc = libvirt.open(uri)
+    vc = libvirt.openReadOnly(uri)
 
     # Close connection on exit (to test cleanup paths)
     old_exitfunc = getattr(sys, 'exitfunc', None)
-- 
1.7.4




More information about the libvir-list mailing list