mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
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:
parent
83b77fa589
commit
0c97e70b74
@ -5,10 +5,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.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__)
|
__func__, __LINE__)
|
||||||
@ -20,22 +18,6 @@
|
|||||||
# define ATTRIBUTE_UNUSED __attribute__((__unused__))
|
# define ATTRIBUTE_UNUSED __attribute__((__unused__))
|
||||||
#endif
|
#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 */
|
/* Prototypes */
|
||||||
const char *eventToString(int event);
|
const char *eventToString(int event);
|
||||||
int myEventAddHandleFunc (int fd, 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 */
|
/* main test functions */
|
||||||
|
|
||||||
void usage(const char *pname)
|
void usage(const char *pname)
|
||||||
@ -372,7 +266,6 @@ static void stop(int sig)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int sts;
|
|
||||||
int callback1ret = -1;
|
int callback1ret = -1;
|
||||||
int callback2ret = -1;
|
int callback2ret = -1;
|
||||||
int callback3ret = -1;
|
int callback3ret = -1;
|
||||||
@ -391,12 +284,7 @@ int main(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virEventRegisterImpl( myEventAddHandleFunc,
|
virEventRegisterDefaultImpl();
|
||||||
myEventUpdateHandleFunc,
|
|
||||||
myEventRemoveHandleFunc,
|
|
||||||
myEventAddTimeoutFunc,
|
|
||||||
myEventUpdateTimeoutFunc,
|
|
||||||
myEventRemoveTimeoutFunc);
|
|
||||||
|
|
||||||
virConnectPtr dconn = NULL;
|
virConnectPtr dconn = NULL;
|
||||||
dconn = virConnectOpenReadOnly (argv[1] ? argv[1] : NULL);
|
dconn = virConnectOpenReadOnly (argv[1] ? argv[1] : NULL);
|
||||||
@ -452,37 +340,11 @@ int main(int argc, char **argv)
|
|||||||
(callback6ret != -1) &&
|
(callback6ret != -1) &&
|
||||||
(callback7ret != -1)) {
|
(callback7ret != -1)) {
|
||||||
while (run) {
|
while (run) {
|
||||||
struct pollfd pfd = { .fd = h_fd,
|
if (virEventRunDefaultImpl() < 0) {
|
||||||
.events = h_event,
|
virErrorPtr err = virGetLastError();
|
||||||
.revents = 0};
|
fprintf(stderr, "Failed to run event loop: %s\n",
|
||||||
|
err && err->message ? err->message : "Unknown error");
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(h_cb) {
|
|
||||||
h_cb(0,
|
|
||||||
h_fd,
|
|
||||||
myPollEventToEventHandleType(pfd.revents & h_event),
|
|
||||||
h_opaque);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG0("Deregistering event handlers");
|
VIR_DEBUG0("Deregistering event handlers");
|
||||||
@ -503,10 +365,3 @@ int main(int argc, char **argv)
|
|||||||
printf("done\n");
|
printf("done\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
int main(void) {
|
|
||||||
printf("event-test program not available without sys/poll.h support\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -15,6 +15,17 @@ import errno
|
|||||||
import time
|
import time
|
||||||
import threading
|
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
|
do_debug = False
|
||||||
def debug(msg):
|
def debug(msg):
|
||||||
global do_debug
|
global do_debug
|
||||||
@ -392,6 +403,10 @@ def virEventLoopPureRun():
|
|||||||
global eventLoop
|
global eventLoop
|
||||||
eventLoop.run_loop()
|
eventLoop.run_loop()
|
||||||
|
|
||||||
|
def virEventLoopNativeRun():
|
||||||
|
while True:
|
||||||
|
libvirt.virEventRunDefaultImpl()
|
||||||
|
|
||||||
# Spawn a background thread to run the event loop
|
# Spawn a background thread to run the event loop
|
||||||
def virEventLoopPureStart():
|
def virEventLoopPureStart():
|
||||||
global eventLoopThread
|
global eventLoopThread
|
||||||
@ -400,6 +415,13 @@ def virEventLoopPureStart():
|
|||||||
eventLoopThread.setDaemon(True)
|
eventLoopThread.setDaemon(True)
|
||||||
eventLoopThread.start()
|
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
|
# Everything that now follows is a simple demo of domain lifecycle events
|
||||||
@ -474,9 +496,12 @@ def main():
|
|||||||
print "Using uri:" + uri
|
print "Using uri:" + uri
|
||||||
|
|
||||||
# Run a background thread with the event loop
|
# Run a background thread with the event loop
|
||||||
|
if use_pure_python_event_loop:
|
||||||
virEventLoopPureStart()
|
virEventLoopPureStart()
|
||||||
|
else:
|
||||||
|
virEventLoopNativeStart()
|
||||||
|
|
||||||
vc = libvirt.open(uri)
|
vc = libvirt.openReadOnly(uri)
|
||||||
|
|
||||||
# Close connection on exit (to test cleanup paths)
|
# Close connection on exit (to test cleanup paths)
|
||||||
old_exitfunc = getattr(sys, 'exitfunc', None)
|
old_exitfunc = getattr(sys, 'exitfunc', None)
|
||||||
|
Loading…
Reference in New Issue
Block a user