Commit 8305021f authored by Leigh Stoller's avatar Leigh Stoller

Some whacking of the event system. I have implemented the addressing

scheme that we discussed in email. Notifications and subscriptions now
take an "address_tuple" argument (I know, crappy name) that is a
structure that looks like this:

	char		*site;		/* Which Emulab site. God only */
	char		*expt;		/* Project and experiment IDs */
	char		*group;		/* User defined group of nodes */
	char		*host;		/* A specific host */
	char		*objtype;	/* LINK, TRAFGEN, etc ... */
        char		*objname;	/* link0, cbr0, cbr1, etc ... */
        char		*eventtype;	/* START, STOP, UP, DOWN, etc ... */

These can be a specific value, ADDRESSTUPLE_ANY if you are a
subscriber, or ADDRESSTUPLE_ALL if you are a producer. The reason for
the distinction is that you can optimize the match expression with the
extra bit of information, and the above structure can make for a
fairly lengthy match expression, which takes more time of course.
You should use address_tuple_alloc() and address_tuple_free() rather
than allocating them yourself. Note that host above is actually the
ipaddr of control interface. This turns out to be more convenient
since free nodes do not have virtual names.

Also added a new tbgen directly. This directory includes 3 programs in
the making:

tbmevd: Is the Testbed Master Event Daemon, to be run on boss and will
handle TBCONTROL events (reboot, reload, etc). It is just a shell of a
program right now, that takes the events but does not do anything
useful with them. Have not defined what the events are, and what DB
state will be modified.

tbmevc: Is the Testbed Master Event Client (akin to tmcc). It
generates TBCONTROL events which the tbmevd will pick up and do
something useful with. This program is intended to be wrapped by a
perl script that will ask the tmcd for the name of the boss (running
the event daemon).

sample-client: This is a little client to demonstrate how to connect
to the event system and use the address tuple to subscribe to events,
and then how to get information out of notifications.

Note that I have not created a proper build environment yet, so new
programs should probably go in the event dir for now, and link using
the same approach as in tbgen/GNUmakefile.in.
parent 11e0ea5f
...@@ -1032,10 +1032,11 @@ fi ...@@ -1032,10 +1032,11 @@ fi
if test "$enable_events" = "yes"; then if test "$enable_events" = "yes"; then
elvinfiles="event/GNUmakefile event/lib/GNUmakefile \ eventfiles="event/GNUmakefile event/lib/GNUmakefile \
event/sched/GNUmakefile event/test/GNUmakefile"; event/sched/GNUmakefile event/test/GNUmakefile \
event/tbgen/GNUmakefile event/tbgen/tbmevd.restart";
else else
elvinfiles=""; eventfiles="";
fi fi
# #
...@@ -1072,7 +1073,7 @@ fi ...@@ -1072,7 +1073,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh. # ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:1076: checking for a BSD compatible install" >&5 echo "configure:1077: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
...@@ -1181,7 +1182,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -1181,7 +1182,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \ vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \ rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \
rc.d/cvsupd.sh \ rc.d/cvsupd.sh \
$elvinfiles \ $eventfiles \
apache/GNUmakefile apache/apache.conf " apache/GNUmakefile apache/apache.conf "
# #
......
...@@ -177,10 +177,11 @@ AC_ARG_ENABLE(events, ...@@ -177,10 +177,11 @@ AC_ARG_ENABLE(events,
--disable-events Disable events (requires Elvin libraries)]) --disable-events Disable events (requires Elvin libraries)])
if test "$enable_events" = "yes"; then if test "$enable_events" = "yes"; then
elvinfiles="event/GNUmakefile event/lib/GNUmakefile \ eventfiles="event/GNUmakefile event/lib/GNUmakefile \
event/sched/GNUmakefile event/test/GNUmakefile"; event/sched/GNUmakefile event/test/GNUmakefile \
event/tbgen/GNUmakefile event/tbgen/tbmevd.restart";
else else
elvinfiles=""; eventfiles="";
fi fi
# #
...@@ -260,7 +261,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -260,7 +261,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \ vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \ rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \
rc.d/cvsupd.sh \ rc.d/cvsupd.sh \
$elvinfiles \ $eventfiles \
apache/GNUmakefile apache/apache.conf " apache/GNUmakefile apache/apache.conf "
# #
......
...@@ -8,7 +8,7 @@ SUBDIR = event ...@@ -8,7 +8,7 @@ SUBDIR = event
include $(OBJDIR)/Makeconf include $(OBJDIR)/Makeconf
SUBDIRS = lib sched test SUBDIRS = lib sched tbgen
all: $(SUBDIRS) all: $(SUBDIRS)
...@@ -20,19 +20,23 @@ lib: ...@@ -20,19 +20,23 @@ lib:
sched: sched:
@$(MAKE) -C sched all @$(MAKE) -C sched all
tbgen:
@$(MAKE) -C tbgen all
test: test:
@$(MAKE) -C test all @$(MAKE) -C test all
install: install:
@$(MAKE) -C lib install @$(MAKE) -C lib install
@$(MAKE) -C sched install @$(MAKE) -C sched install
@$(MAKE) -C test install @$(MAKE) -C tbgen install
clean: subdir-clean clean: subdir-clean
subdir-clean: subdir-clean:
@$(MAKE) -C lib clean @$(MAKE) -C lib clean
@$(MAKE) -C sched clean @$(MAKE) -C sched clean
@$(MAKE) -C tbgen clean
@$(MAKE) -C test clean @$(MAKE) -C test clean
distclean: subdir-distclean distclean: subdir-distclean
......
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
* @COPYRIGHT@ * @COPYRIGHT@
*/ */
static char rcsid[] = "$Id: event.c,v 1.11 2002-02-19 17:12:52 stoller Exp $";
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "event.h" #include "event.h"
#undef TRACE
#define TRACE(fmt,...)
static char hostname[MAXHOSTNAMELEN]; static char hostname[MAXHOSTNAMELEN];
...@@ -259,8 +259,6 @@ int ...@@ -259,8 +259,6 @@ int
event_schedule(event_handle_t handle, event_notification_t notification, event_schedule(event_handle_t handle, event_notification_t notification,
struct timeval *time) struct timeval *time)
{ {
event_type_t type;
if (!handle || !notification || !time) { if (!handle || !notification || !time) {
ERROR("invalid parameter\n"); ERROR("invalid parameter\n");
return 0; return 0;
...@@ -269,38 +267,12 @@ event_schedule(event_handle_t handle, event_notification_t notification, ...@@ -269,38 +267,12 @@ event_schedule(event_handle_t handle, event_notification_t notification,
TRACE("scheduling event notification %p to be sent at time (%ld, %ld)\n", TRACE("scheduling event notification %p to be sent at time (%ld, %ld)\n",
notification, time->tv_sec, time->tv_usec); notification, time->tv_sec, time->tv_usec);
/* Change the event type to EVENT_SCHEDULE, saving the old event /*
type in the notification structure so the event scheduler can * Add an attribute that signifies its a scheduler operation.
change it back when the event is scheduled: */ */
if (! event_notification_remove(handle, notification, "SCHEDULER") ||
if (event_notification_get_int32(handle, notification, "type", ! event_notification_put_int32(handle, notification, "SCHEDULER", 1)) {
(int *) &type) ERROR("could not add scheduler attribute to notification %p\n",
== 0)
{
ERROR("could not get old type attribute from notification %p\n",
notification);
return 0;
}
if (event_notification_remove(handle, notification, "type") == 0) {
ERROR("could not remove old type attribute from notification %p\n",
notification);
return 0;
}
if (event_notification_put_int32(handle, notification, "type",
EVENT_SCHEDULE)
== 0)
{
ERROR("could not add new type attribute to notification %p\n",
notification);
return 0;
}
if (event_notification_put_int32(handle, notification, "old_type",
type)
== 0)
{
ERROR("could not add old type attribute to notification %p\n",
notification); notification);
return 0; return 0;
} }
...@@ -332,25 +304,22 @@ event_schedule(event_handle_t handle, event_notification_t notification, ...@@ -332,25 +304,22 @@ event_schedule(event_handle_t handle, event_notification_t notification,
/* /*
* Allocate an event notification. The HOST parameter specifies * Allocate an event notification. The address TUPLE defines who
* the hostname of the node that should receive the notification, * should receive the notification. Returns a pointer to an event
* or EVENT_HOST_ANY if the notification should go to all hosts. * notification structure if the operation is successful, 0 otherwise.
* The TYPE parameter specifies the event type. Returns
* a pointer to an event notification structure if the operation
* is successful, 0 otherwise.
*/ */
event_notification_t event_notification_t
event_notification_alloc(event_handle_t handle, char *host, event_type_t type) event_notification_alloc(event_handle_t handle, address_tuple_t tuple)
{ {
elvin_notification_t notification; elvin_notification_t notification;
if (!handle || !host || !type) { if (!handle || !tuple) {
ERROR("invalid paramater\n"); ERROR("invalid paramater\n");
return NULL; return NULL;
} }
TRACE("allocating notification (host=\"%s\", type=%d)\n", host, type); TRACE("allocating notification (tuple=%p)\n", tuple);
notification = elvin_notification_alloc(handle->status); notification = elvin_notification_alloc(handle->status);
if (notification == NULL) { if (notification == NULL) {
...@@ -360,22 +329,23 @@ event_notification_alloc(event_handle_t handle, char *host, event_type_t type) ...@@ -360,22 +329,23 @@ event_notification_alloc(event_handle_t handle, char *host, event_type_t type)
} }
TRACE("allocated notification %p\n", notification); TRACE("allocated notification %p\n", notification);
#define EVPUT(name, field) \
/* Add hostname to notification: */ ({ \
if (event_notification_put_string(handle, notification, "host", host) char *foo = (tuple->field ? tuple->field : ADDRESSTUPLE_ALL); \
== 0) \
{ event_notification_put_string(handle, notification, name, foo); \
ERROR("could not add host attribute to notification %p\n", })
notification);
return NULL; /* Add the target address stuff to the notification */
} if (!EVPUT("SITE", site) ||
!EVPUT("EXPT", expt) ||
/* Add type to notification: */ !EVPUT("GROUP", group) ||
if (event_notification_put_int32(handle, notification, "type", type) !EVPUT("HOST", host) ||
== 0) !EVPUT("OBJTYPE", objtype) ||
{ !EVPUT("OBJNAME", objname) ||
ERROR("could not add type attribute to notification %p\n", !EVPUT("EVENTTYPE", eventtype) ||
notification); ! event_notification_put_int32(handle, notification, "SCHEDULER", 0)) {
ERROR("could not add attributes to notification %p\n", notification);
return NULL; return NULL;
} }
...@@ -818,38 +788,77 @@ static void notify_callback(elvin_handle_t server, ...@@ -818,38 +788,77 @@ static void notify_callback(elvin_handle_t server,
* *
* void callback(event_handle_t handle, * void callback(event_handle_t handle,
* event_notification_t notification, * event_notification_t notification,
* char *host,
* event_type_t type,
* void *data); * void *data);
* *
* where HANDLE is the handle to the event server, NOTIFICATION is the * where HANDLE is the handle to the event server, NOTIFICATION is the
* event notification, HOST and TYPE are the respective attributes of * event notification, and DATA is the arbitrary pointer passed to
* the event notification, and DATA is the arbitrary pointer passed to
* event_subscribe. Returns a pointer to an event * event_subscribe. Returns a pointer to an event
* subscription structure if the operation is successful, 0 otherwise. * subscription structure if the operation is successful, 0 otherwise.
*/ */
event_subscription_t event_subscription_t
event_subscribe(event_handle_t handle, event_notify_callback_t callback, event_subscribe(event_handle_t handle, event_notify_callback_t callback,
event_type_t type, void *data) address_tuple_t tuple, void *data)
{ {
elvin_subscription_t subscription; elvin_subscription_t subscription;
struct notify_callback_arg *arg; struct notify_callback_arg *arg;
char expression[EXPRESSION_LENGTH]; char expression[EXPRESSION_LENGTH];
int index = 0;
/* XXX: The declaration of expression has to go last, or the /* XXX: The declaration of expression has to go last, or the
local variables on the stack after it get smashed. Check local variables on the stack after it get smashed. Check
Elvin for buffer overruns. */ Elvin for buffer overruns. */
if (!handle || !callback || !type) { if (!handle || !callback || !tuple) {
ERROR("invalid parameter\n"); ERROR("invalid parameter\n");
return NULL; return NULL;
} }
snprintf(expression, EXPRESSION_LENGTH, if (tuple->site) {
"(host == \"*\" || host == \"%s\") && type == %d", index += snprintf(&expression[index], sizeof(expression) - index,
hostname, "SITE == \"%s\" ",
type); tuple->site);
}
if (tuple->expt) {
index += snprintf(&expression[index], sizeof(expression) - index,
"%s EXPT == \"%s\" ",
(index ? "&&" : ""),
tuple->expt);
}
if (tuple->group) {
index += snprintf(&expression[index], sizeof(expression) - index,
"%s GROUP == \"%s\" ",
(index ? "&&" : ""),
tuple->group);
}
if (tuple->host) {
index += snprintf(&expression[index], sizeof(expression) - index,
"%s HOST == \"%s\" ",
(index ? "&&" : ""),
tuple->host);
}
if (tuple->objtype) {
index += snprintf(&expression[index], sizeof(expression) - index,
"%s OBJTYPE == \"%s\" ",
(index ? "&&" : ""),
tuple->objtype);
}
if (tuple->objname) {
index += snprintf(&expression[index], sizeof(expression) - index,
"%s OBJNAME == \"%s\" ",
(index ? "&&" : ""),
tuple->objname);
}
if (tuple->eventtype) {
index += snprintf(&expression[index], sizeof(expression) - index,
"%s EVENTTYPE == \"%s\" ",
(index ? "&&" : ""),
tuple->eventtype);
}
index += snprintf(&expression[index], sizeof(expression) - index,
"%s SCHEDULER == %d ",
(index ? "&&" : ""),
tuple->scheduler);
TRACE("subscribing to event %s\n", expression); TRACE("subscribing to event %s\n", expression);
...@@ -910,8 +919,6 @@ notify_callback(elvin_handle_t server, ...@@ -910,8 +919,6 @@ notify_callback(elvin_handle_t server,
struct notify_callback_arg *arg = (struct notify_callback_arg *) rock; struct notify_callback_arg *arg = (struct notify_callback_arg *) rock;
event_notify_callback_t callback; event_notify_callback_t callback;
void *data; void *data;
char host[MAXHOSTNAMELEN];
event_type_t type;
TRACE("received event notification\n"); TRACE("received event notification\n");
...@@ -921,23 +928,25 @@ notify_callback(elvin_handle_t server, ...@@ -921,23 +928,25 @@ notify_callback(elvin_handle_t server,
handle.server = server; handle.server = server;
handle.status = status; handle.status = status;
if (event_notification_get_string(&handle, notification, "host", callback(&handle, notification, data);
host, MAXHOSTNAMELEN) }
== 0)
{
ERROR("could not get host attribute from notification %p\n",
notification);
return;
}
if (event_notification_get_int32(&handle, notification, "type", /*
(int *) &type) * address tuple alloc and free.
== 0) */
{ address_tuple_t
ERROR("could not get type attribute from notification %p\n", address_tuple_alloc(void)
notification); {
return; address_tuple_t tuple = xmalloc(sizeof(address_tuple));
}
bzero(tuple, sizeof(address_tuple));
return tuple;
}
callback(&handle, notification, host, type, data); int
address_tuple_free(address_tuple_t tuple)
{
free(tuple);
return 1;
} }
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* @COPYRIGHT@ * @COPYRIGHT@
* *
* $Id: event.h,v 1.6 2002-02-19 15:45:24 imurdock Exp $ * $Id: event.h,v 1.7 2002-02-21 17:49:38 stoller Exp $
*/ */
#ifndef __EVENT_H__ #ifndef __EVENT_H__
...@@ -44,6 +44,43 @@ typedef elvin_notification_t event_notification_t; ...@@ -44,6 +44,43 @@ typedef elvin_notification_t event_notification_t;
/* Event subscription: */ /* Event subscription: */
typedef elvin_subscription_t event_subscription_t; typedef elvin_subscription_t event_subscription_t;
/*
* A tuple defines the target of the event, or if you are a subscriber,
* what events you want to subscribe to.
*/
typedef struct {
char *site; /* Which Emulab site. God only */
char *expt; /* Project and experiment IDs */
char *group; /* User defined group of nodes */
char *host; /* A specific host */
char *objtype; /* LINK, TRAFGEN, etc ... */
char *objname; /* link0, cbr0, cbr1, etc ... */
char *eventtype; /* START, STOP, UP, DOWN, etc ... */
int scheduler; /* A dynamic event to schedule */
} address_tuple, *address_tuple_t;
#define ADDRESSTUPLE_ANY NULL
#define ADDRESSTUPLE_ALL "*"
#define OBJECTTYPE_TESTBED "TBCONTROL"
address_tuple_t address_tuple_alloc(void);
int address_tuple_free(address_tuple_t);
#define event_notification_get_site(handle, note, buf, len) \
event_notification_get_string(handle, note, "SITE", buf, len)
#define event_notification_get_expt(handle, note, buf, len) \
event_notification_get_string(handle, note, "EXPT", buf, len)
#define event_notification_get_group(handle, note, buf, len) \
event_notification_get_string(handle, note, "GROUP", buf, len)
#define event_notification_get_host(handle, note, buf, len) \
event_notification_get_string(handle, note, "HOST", buf, len)
#define event_notification_get_objtype(handle, note, buf, len) \
event_notification_get_string(handle, note, "OBJTYPE", buf, len)
#define event_notification_get_objname(handle, note, buf, len) \
event_notification_get_string(handle, note, "OBJNAME", buf, len)
#define event_notification_get_eventtype(handle, note, buf, len) \
event_notification_get_string(handle, note, "EVENTTYPE", buf, len)
/* The "any host" string: */ /* The "any host" string: */
#define EVENT_HOST_ANY "*" #define EVENT_HOST_ANY "*"
...@@ -60,11 +97,10 @@ typedef enum { ...@@ -60,11 +97,10 @@ typedef enum {
and called whenever the specified event is triggered. and called whenever the specified event is triggered.
HANDLE is the handle to the event server, NOTIFICATION is the event HANDLE is the handle to the event server, NOTIFICATION is the event
notification itself, and DATA is an arbitrary value passed to notification itself, and DATA is an arbitrary value passed to
event_subscribe (argument 4). HOST and TYPE are attributes from the event_subscribe (argument 4).
event notification. */ */
typedef void (*event_notify_callback_t)(event_handle_t handle, typedef void (*event_notify_callback_t)(event_handle_t handle,
event_notification_t notification, event_notification_t notification,
char *host, event_type_t type,
void *data); void *data);
/* /*
...@@ -74,8 +110,10 @@ typedef void (*event_notify_callback_t)(event_handle_t handle, ...@@ -74,8 +110,10 @@ typedef void (*event_notify_callback_t)(event_handle_t handle,
#define ERROR(fmt,...) fprintf(stderr, __FUNCTION__ ": " fmt, ## __VA_ARGS__) #define ERROR(fmt,...) fprintf(stderr, __FUNCTION__ ": " fmt, ## __VA_ARGS__)
#ifdef DEBUG #ifdef DEBUG
#define TRACE(fmt,...) printf(__FUNCTION__ ": " fmt, ## __VA_ARGS__) #define TRACE(fmt,...) printf(__FUNCTION__ ": " fmt, ## __VA_ARGS__)
#define DBG(fmt,...) printf(fmt, ## __VA_ARGS__)
#else #else
#define TRACE(fmt,...) #define TRACE(fmt,...)
#define DBG(fmt,...)
#endif /* DEBUG */ #endif /* DEBUG */
/* /*
...@@ -90,7 +128,7 @@ int event_notify(event_handle_t handle, event_notification_t notification); ...@@ -90,7 +128,7 @@ int event_notify(event_handle_t handle, event_notification_t notification);
int event_schedule(event_handle_t handle, event_notification_t notification, int event_schedule(event_handle_t handle, event_notification_t notification,
struct timeval *time); struct timeval *time);
event_notification_t event_notification_alloc(event_handle_t handle, event_notification_t event_notification_alloc(event_handle_t handle,
char *host, event_type_t type); address_tuple_t tuple);
int event_notification_free(event_handle_t handle, int event_notification_free(event_handle_t handle,
event_notification_t notification); event_notification_t notification);
int event_notification_get_double(event_handle_t handle, int event_notification_get_double(event_handle_t handle,
...@@ -127,7 +165,7 @@ int event_notification_remove(event_handle_t handle, ...@@ -127,7 +165,7 @@ int event_notification_remove(event_handle_t handle,
event_notification_t notification, char *name); event_notification_t notification, char *name);
event_subscription_t event_subscribe(event_handle_t handle, event_subscription_t event_subscribe(event_handle_t handle,
event_notify_callback_t callback, event_notify_callback_t callback,
event_type_t type, void *data); address_tuple_t tuple, void *data);
/* util.c */ /* util.c */
void *xmalloc(int size); void *xmalloc(int size);
......
...@@ -9,19 +9,19 @@ all: event-sched ...@@ -9,19 +9,19 @@ all: event-sched
include $(TESTBED_SRCDIR)/GNUmakerules include $(TESTBED_SRCDIR)/GNUmakerules
CFLAGS += -O -g -static -I. -I$(SRCDIR)/../lib -Wall -pthread -DDEBUG CFLAGS += -O -g -I. -I${OBJDIR} -I$(SRCDIR)/../lib -Wall -pthread -DDEBUG
CFLAGS += `elvin-config --cflags vin4mt` CFLAGS += `elvin-config --cflags vin4mt`
LDFLAGS += -pthread -L../lib LDFLAGS += -pthread -L../lib
LIBS += -levent -lcipher LIBS += -levent -lcipher -L/usr/local/lib/mysql -lmysqlclient
LIBS += `elvin-config --libs vin4mt` LIBS += `elvin-config --libs vin4mt`
OBJS = event-sched.o queue.o OBJS = event-sched.o queue.o libdb.o
event-sched: $(OBJS) event-sched: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
$(OBJS): event-sched.h $(OBJS): event-sched.h ../lib/libevent.a
clean: clean:
/bin/rm -f *.o event-sched /bin/rm -f *.o event-sched
...@@ -16,32 +16,79 @@ ...@@ -16,32 +16,79 @@
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <math.h>
#include <ctype.h>
#include "event-sched.h" #include "event-sched.h"
#include "libdb.h"
static void enqueue(event_handle_t handle, event_notification_t notification, static void enqueue(event_handle_t handle,
char *host, event_type_t type, void *data); event_notification_t notification, void *data);
static void dequeue(event_handle_t handle); static void dequeue(event_handle_t handle);
static char *progname;
static char *pid, *eid;
static int get_static_events(event_handle_t handle);
void
usage()
{
fprintf(stderr, "Usage: %s [-s server] [-p port] <pid> <eid>\n",
progname);
exit(-1);
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
address_tuple_t tuple;
event_handle_t handle; event_handle_t handle;
char *server = NULL; char *server = NULL;
char *port = NULL;
char buf[BUFSIZ];
int c; int c;
/* Initialize event queue semaphores: */ /* Initialize event queue semaphores: */
sched_event_init(); sched_event_init();
while ((c = getopt(argc, argv, "s:")) != -1) { while ((c = getopt(argc, argv, "s:p:")) != -1) {
switch (c) { switch (c) {
case 's': case 's':
server = optarg; server = optarg;
break; break;
case 'p':
port = optarg;
break;
default: default:
fprintf(stderr, "Usage: %s [-s SERVER]\n", argv[0]); fprintf(stderr, "Usage: %s [-s SERVER]\n", argv[0]);
return 1; return 1;
} }
} }
argc -= optind;
argv += optind;
if (argc != 2)
usage();
pid = argv[0];
eid = argv[1];
/*
* Set up DB state.
*/
if (!dbinit())
return 1;
/*
* Convert server/port to elvin thing.
*
* XXX This elvin string stuff should be moved down a layer.
*/
if (server) {
snprintf(buf, sizeof(buf), "elvin://%s%s%s",
server,
(port ? ":" : ""),
(port ? port : ""));
server = buf;
}
/* Register with the event system: */ /* Register with the event system: */
handle = event_register(server, 1); handle = event_register(server, 1);
...@@ -50,9 +97,26 @@ main(int argc, char **argv) ...@@ -50,9 +97,26 @@ main(int argc, char **argv)
return 1; return 1;
} }
/* Subscribe to the EVENT_SCHEDULE event, and enqueue events as /*
they arrive: */ * Read the static events list and schedule.
if (event_subscribe(handle, enqueue, EVENT_SCHEDULE, NULL) == NULL) { */
if (!get_static_events(handle)) {
ERROR("could not get static event list\n");
return 1;
}
/*
* Construct an address tuple for event subscription. We set the scheduler
* flag to indicate we want to capture those notifications.
*/
tuple = address_tuple_alloc();
if (tuple == NULL) {
ERROR("could not allocate an address tuple\n");
return 1;
}
tuple->scheduler = 1;