 |
» |
|
|
 |
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 “Using Filter Evaluators” 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 theyhave 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; }} |
|