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
This commit is contained in:
Daniel P. Berrange 2011-03-23 14:30:30 +00:00
parent 83b77fa589
commit 0c97e70b74
2 changed files with 43 additions and 163 deletions

View File

@ -5,36 +5,18 @@
#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/libvirt.h>
#include <libvirt/virterror.h>
# 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);
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 (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;
}
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

View File

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