 |
» |
|
|
 |
Some event subscribers need to monitor events
using a variety of criteria, and then handle in different ways according
to the attributes of the incoming events. For example, the EVM logger
reads a set of filter strings from its configuration file and subscribes
for all the events described in the strings. As each event arrives,
it determines which of the filter strings the event matches in order
to write it to the correct set of logs. You create multiple connections to the EVM daemon
and subscribe on each connection with a separate filter string. However,
this results in connection overhead, and the same event is sent across
two or more of the connections. HP recommends you to take all of the filter strings
and combine them into a single logical string using the OR logical
operator. This combined string is then used to subscribe for all matching
events on a single connection. The combined string can then be discarded,
but the original set of strings must be retained. It can be used to
resubscribe later if the connection has to be re-established, or if
the filter has to change. However, when an event arrives, you need
to know which of the original filter strings it matches, so that you
can decide about how to handle the events. You can use an EVM filter
evaluator to do this. A filter evaluator is an object that can be created,
loaded with a filter string, and then pass series of events to determine
which (if any) of the events match the filter. If you maintain a separate
evaluator for each of the original filter strings, you can apply each
incoming event to each of the evaluators to decide which evaluators
match the event. Example 4-8 demonstrates this technique by using three simple filter strings
and by printing a different message according to which of the filters,
if any, each incoming event matches. The example introduces the following functions: EvmFilterCreate — Establishes
an instance of a filter evaluator and returns a handle. For more information
about this function, see EvmFilterCreate(3) and EvmFilter(5). EvmFilterSet — Passes a
filter string to the filter evaluator to be used in subsequent matches.
For more information about this function, see EvmFilterSet(3) and EvmFilter(5). EvmFilterTest — Compares
a specified event with the filter string that are currently associated
with the filter evaluator. If the event matches the filter string, EvmFilterTest returns EvmTRUE; otherwise,
it returns EvmFALSE. For more information about
this function, see EvmFilterTest(3) and EvmFilter(5). EvmFilterDestroy — Destroys
a filter evaluator, freeing up all associated resources. For more
information about this function, see EvmFilterDestroy(3) and EvmFilter(5).
Example 4-8 Using Filter Evaluators  |
#include <stdio.h>
#include <sys/time.h>
#include <evm/evm.h>
#include<string.h>
void EventCB(EvmConnection_t conn, EvmCallbackArg_t cbarg, EvmCallbackData_t *cbdata);
/* This section of code defines three simple filter strings. The first two filter by name alone,
but the third stringselects events with either of the two names, provided they have a priority of at least 300.*/
#define FILTER_1 "[name *.user]"
#define FILTER_2 "[name *.msg]"
#define FILTER_3 "([name *.msg] | [name *.mark]) & [priority >= 300]"
/*===============================================* Function: main()*===============================================*/
int main()
{ EvmConnection_t conn;
EvmStatus_t status;
int conn_fd;char *filter_string;
status = EvmConnCreate(EvmCONNECTION_LISTEN, EvmRESPONSE_CALLBACK,NULL,EventCB,NULL,&conn);
if (status != EvmERROR_NONE)
{ fprintf(stderr,"Failed to create EVM listening connection\n");
exit(1); }
/* This section of code combines the three filter strings into a single logical expression, surrounding each
substring with parentheses and separating them with the logical OR operator. This will cause the daemon to notify
you of any event that matches at least one of the substrings.*/
filter_string = (char *)malloc(strlen(FILTER_1) + strlen(FILTER_2) + strlen(FILTER_3) + 30);
sprintf(filter_string,"(%s) | (%s) | (%s)",FILTER_1,FILTER_2,FILTER_3);
/* Use the combined string to subscribe for the events, and then, because the string is no longer useful to
you, free its space. If you have to resubscribe for any reason, you can always recombine the substrings.*/
status = EvmConnSubscribe(conn,NULL,filter_string);
if (status != EvmERROR_NONE)
{ fprintf(stderr,"Failed to subscribe for event notification\n");
exit(1); }
free(filter_string);
/* After the evaluators have been established, retain it so that you can use them for all events that you receive
(that is, make them static entities). Alternatively,you could create a new set of evaluators each time you receive
an event, and destroy them as you exit the function. However, retaining them avoids the repeated setup and
teardown overhead.*/
for (;;)
{ status = EvmConnWait(conn,NULL);
if (status != EvmERROR_NONE)
{ fprintf(stderr,"Connection error\n");
exit(1); }
if (EvmConnDispatch(conn) != EvmERROR_NONE)
{ fprintf(stderr,"Connection dispatch error\n");
exit(1); } }}
/*===============================================* Function: EventCB()*===============================================*/
void EventCB(EvmConnection_t conn, EvmCallbackArg_t cbarg, EvmCallbackData_t *cbdata)
{ EvmBoolean_t match;
/* This section of code creates three filter evaluators using EvmFilterCreate() and loads them with the
three filter strings. For clarity, only the return status for the first filter is checked in this example,
but in production code it is important to check it in each case. This code is executed only the first time
we receive an event.*/
static EvmFilter_t f1,f2,f3;
static EvmBoolean_t filters_initialized = EvmFALSE;
if (! filters_initialized)
{ if (EvmFilterCreate(&f1) != EvmERROR_NONE)
{ fprintf(stderr,"Failed to create filter evaluator\n");
exit(1); }
if (EvmFilterSet(f1,FILTER_1) != EvmERROR_NONE)
{ fprintf(stderr,"Failed to set filter evaluator\n");
exit(1); }
EvmFilterCreate(&f2);
EvmFilterSet(f2,FILTER_2);
EvmFilterCreate(&f3);
EvmFilterSet(f3,FILTER_3);
filters_initialized = EvmTRUE; }
/* This section of code tests each incoming event against each of the three filter evaluators established in the
previous section, and prints a different message for each evaluator that is matched by the event. It is quite
possible that some events will match more than one evaluator; in which case, more than one message is printed.*/
switch (cbdata->reason)
{ case EvmREASON_EVENT_DELIVERED: EvmFilterTest(f1,cbdata->event,&match);
if (match)
fprintf(stdout,"Filter 1 event received\n");
EvmFilterTest(f2,cbdata->event,&match);
if (match)
fprintf(stdout,"Filter 2 event received\n");
EvmFilterTest(f3,cbdata->event,&match);
if (match)
fprintf(stdout,"Filter 3 event received\n");
EvmEventDestroy(cbdata->event);
break;
default:
break; }} |
 |
|