From 0c97e70b74434b4baca9bbfc19c14bf7ff2ef304 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 23 Mar 2011 14:30:30 +0000 Subject: [PATCH] Update event loop example programs to demonstrate best practice 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. Also make the python example use a read only connection to avoid authentication prompts * 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 | 177 ++---------------- .../domain-events/events-python/event-test.py | 29 ++- 2 files changed, 43 insertions(+), 163 deletions(-) diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c index 6e3a1604f8..7d05dd83d7 100644 --- a/examples/domain-events/events-c/event-test.c +++ b/examples/domain-events/events-c/event-test.c @@ -5,36 +5,18 @@ #include #include -#if HAVE_SYS_POLL_H -# include -# include -# include +#include +#include -# define VIR_DEBUG0(fmt) printf("%s:%d :: " fmt "\n", \ +#define VIR_DEBUG0(fmt) printf("%s:%d :: " fmt "\n", \ __func__, __LINE__) -# define VIR_DEBUG(fmt, ...) printf("%s:%d: " fmt "\n", \ +#define VIR_DEBUG(fmt, ...) printf("%s:%d: " fmt "\n", \ __func__, __LINE__, __VA_ARGS__) -# define STREQ(a,b) (strcmp(a,b) == 0) - -# ifndef ATTRIBUTE_UNUSED -# 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; +#define STREQ(a,b) (strcmp(a,b) == 0) +#ifndef ATTRIBUTE_UNUSED +# define ATTRIBUTE_UNUSED __attribute__((__unused__)) +#endif /* Prototypes */ const char *eventToString(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 c149ed93b8..df75dce825 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) -- GitLab