I went through new code - it very very nice (i'm starting to like C
more and more :)
I think your events implementation provides way for method
registration which i proposed few weeks ago.
It is universal system for registering methods for particular events -
it is on user to define and register methods. In the case of new test
addition, we just add new validation function which will post new type
of event and the rest is provided automaticaly. It simplifies code i
think.
There is ilustration code (however it is pretty piggy - it is meant as
illustration only):
----
/* present handle_event which is proposed for refactoring: */
static void handle_event(Event_T E) {
ASSERT(E);
switch(E->id) {
case EVENT_START: handle_start(E); break;
case EVENT_STOP: handle_stop(E); break;
case EVENT_RESTART: handle_restart(E); break;
}
if(E->id != EVENT_NULL) {
handle_alert_event(E);
/* TODO: handle_exec_event(E); */
}
Event_free(&E);
}
--------------
/* mycommand structure addopts name of the method specified in
configuration, for example:
* method NAME "..."
* and events registration mask from Exec_T which can be removed.
* mycommand structure is transformed to the list
*/
typedef struct mycommand {
char *arg[ARGMAX]; /**< Program with
arguments */
int length; /**< The length of the arguments
array */
int has_uid; /**< TRUE if a new uid is defined for this
Command */
uid_t uid; /**< The user id to switch to when running this
Command */
int has_gid; /**< TRUE if a new gid is defined for this
Command */
gid_t gid; /**< The group id to switch to when running this
Command */
/**********NEW ***********/
char name; /** method name */
unsigned int events; /**< Events triggering this program to be
executed */
struct mycommand *next;
/**********NEW ***********/
} *Command_T;
/* Service_T from monitor.h replaces start+stop method callbacks by
general method list */
typedef struct myservice {
int task; /**< Monitored task
type */
char *name; /**< Service descriptive
name */
char *group; /**< Service group
name */
/* REMOVE: Command_T start;*/ /**< The start
command for the service */
/* REMOVE: Command_T stop;*/ /**< The stop
command for the service */
Command_T methodlist;
.....
}
/* Event_Table adds default method binding (third field) for
automatic registration if the method's name corresponds to event, for
example for:
* EVENT_START ... is by default registered (if exists): 'method
START ....'
* etc.
*/
struct Event_Table {
int id;
char description[STRLEN];
char default_method_name[STRLEN];
} Event_Table[]= {
{EVENT_NULL, "No Event", "void"},
{EVENT_FAILED, "Failed",
"fail"},
{EVENT_START, "Started",
"start"},
{EVENT_STOP, "Stopped", "stop"},
{EVENT_RESTART, "Restarted", "restart"},
{EVENT_CHECKSUM, "Checksum error", "cheksum"},
{EVENT_RESOURCE, "Resource limit matched", "resource"},
{EVENT_TIMEOUT, "Timeout", "timeout"},
{EVENT_TIMESTAMP, "Timestamp error", "timestamp"}};
/* we will go through registered methods and alerts list and do
appropriate action in the case that registered method/alert was found */
static void handle_event(Event_T E) {
ASSERT(E);
if(E->id != EVENT_NULL) {
handle_exec(E);
handle_alert_event(E);
}
Event_free(&E);
}
/* take care for looking for registered method:
* EITHER method registered by default event tag is found
* OR method registered explicitly by event list is found
* OTHERWISE no method is registered for this event => skip
*/
static void handle_exec(Event_T E) {
struct mycommand command = E->source->methodlist;
while(command) {
if( IS(E->default_method_name, E->source->methodlist->name) ||
(E->id&mask == E->source->methodlist->events&mask)) {
spawn(command);
return;
}
command= E->source->methodlist->next;
}
}
---
CONFIGURATION EXAMPLE:
method start "/etc/init.d/foo start" /* automaticaly registered for
start method because of 'start' name */
method stop "/etc/init.d/foo start" /* automaticaly registered for
stop method because of 'stop' name */
method restart "/etc/init.d/foo restart" on { failed resorce } /*
automaticaly registered for restart method by name + additionaly
explicitly named events */
method reload "/etc/init.d/foo reload" on { timestamp } /* registered
just for timestamp event because there's no default event tag 'reload' */
What do you think? Is this way possible?
Cheers,
Martin