Chapter 3. Creating Producer, Subscriber, and Consumer Applications

This chapter covers the following topics:

Creating a Producer Application

Producer applications must include Event Manager application programming interface (API) function calls that create and submit events to the Event Manager.

Figure 3-1 summarizes the steps necessary to create an event and send it to the Event Manager. The text following the figure provides detailed information about each step. Refer to Chapter 2, “Event Manager API”, for specific information about the individual functions.

Figure 3-1. Creating and Submitting an Event from a Producer Application

Creating and Submitting an Event from a Producer Application

  1. Include the Event Manager API header file so that you can access the Event Manager API functions:

    #include <emgrapi.h>

  2. Verify that the Event Manager daemon is available:

    • Use the emgrIsDaemonInstalled() function to verify that the eventmond daemon is installed on the system.

    • Use the emgrIsDaemonStarted() function to verify that the emgr daemon is running so that the producer application can send event data to it.


      Note: This step is optional. These functions work only with the default configuration; if you modify how the Event Manager is installed or configured, these functions may fail.


  3. Use the emgrAllocEvent() function to allocate memory for the event.

  4. Add information to the event:

    Use the emgrAddItemToEvent() function to add a character name-value.

    or

    Use the emgrAddTaggedDataToEvent() or emgrAddDataToEvent() function to add binary data to the event.

    or

    Use the emgrAddTaggedFileToEvent() or emgrAddFileToEvent() function to add a file from the local filesystem.

    Tips:

    Normally, you should use the Tagged version of the commands because tagged data can be accessed faster.

    Be careful with data that you added to an event using the emgrAddTaggedDataToEvent() and emgrAddDataToEvent() functions. The API does not free any passed pointers; you must keep the pointers valid until you send the event information and free memory.


    Note: This step is optional. You can create an event that has no data; however, normally, you should attach data to an event before you send the event to the Event Manager.


  5. Use the emgrSendEvent() or emgrForwardEvent() function to send the event to the Event Manager daemon (eventmond).

  6. Use the emgrFreeEvent() function to free the memory that you allocated for the event.

Example 3-1 shows an example producer that allocates an event, adds several types of data to it, sends the event to Event Manager, and frees the memory allocated to the event.

Example 3-1. Example Producer Code

#include <stdio.h>
#include <string.h>

#include <emgrapi.h>

main()
{
        EmgrEvent_t *e;
        int ret;
        char *err, *val;
        
        /*--- Define data to send ---*/

        char *NAME1 = "HDSIZE", *NAME2 = "MEMSIZE";
        char *VALUE1 = "30GB", *VALUE2 = "256MB";
        int class=123,type=456,version=0;
        char *origin = "syslog";
        char *appname = "unix"; 
        char *databuf;
        int datasz;

        /*---- Initialize the event header and body----*/

        e = emgrAllocEvent(class,type,version,origin,appname);

        /*--- Add data to event---*/

        if(emgrAddItemToEvent(e,NAME1, NULL)!= 0) {
               printf("Error.\n");   
        }

        if(emgrAddItemToEvent(e,NAME2, VALUE2)!= 0) {
               printf("Error.\n");   
        }


        /*--- Add file to event ---*/

        if(ret = emgrAddFileToEvent(e,"/tmp/testfile"))
                printf("\n Failure adding file.\n");

        /*--- Add binary data to event ---*/

        /* NOTE: databuf memory will not be freed by emgrFreeEvent()*/

        if(ret = emgrAddDataToEvent(e,databuf, datasz))
                printf("\n  Failure adding binary data.\n");


        /*--- Send the event to the Event Manager ---*/

        if((err = emgrSendEvent(e,NULL)) != 0) {
                printf("\n Failure sending data: errcode %d\n",ret);


           /*--- Free the memory allocated to the event ---*/

        emgrFreeEvent(e);  
}


Creating a Subscriber Application

Subscriber applications perform the following functions:

  • Creating, updating, and submitting subscription events

  • Creating, updating, and submitting unsubscription events

Subscription events indicate that the Event Manager should send information about a specific event to a specific consumer application. Subscription events specify how the Event Manager should notify the consumer about the event (load a consumer DSO, send event information to an executable application via shared memory, send event information to an executable application via command-line options, or forward the event to a consumer application on another system). Several Event Manager API functions are available to configure how and when the Event Manager should send event information to consumer applications.

Unsubscription events indicate that a consumer no longer needs to receive information about a specific event. When the Event Manager receives an unsubscription event, it stops sending information about the specified event to the specified consumer.

Creating, Modifying, and Submitting Subscription Events

You must subscribe a consumer to an event to enable the consumer application to receive event information from the eventmond daemon. You do this by creating a subscription event and submitting it to the eventmond daemon.

Figure 3-2 summarizes the steps needed to create, modify, and submit subscription events. The text following the figure provides detailed information about each step. Refer to Chapter 2, “Event Manager API”, for specific information about the individual functions.

Figure 3-2. Creating/Updating and Submitting a Subscription Event from a Subscriber Application

Creating/Updating and Submitting a Subscription Event from a Subscriber Application

  1. Include the Event Manager API header file so that you can access the Event Manager API functions:

    #include <emgrapi.h>

  2. Verify that the Event Manager daemon is available:

    • Use the emgrIsDaemonInstalled() function to verify that the eventmond daemon is installed on the system.

    • Use the emgrIsDaemonStarted() function to verify that the eventmond daemon is running so the producer application can send event data to it.


      Note: This step is optional. These functions work only with the default configuration; if you modify how the Event Manager is installed or configured, these functions may fail.


  3. Create or update the subscription event:

    To create a subscription event, perform the following actions:

    • Use the emgrNewSubscribe() function to allocate a new subscription event structure and initialize the event header with data.

    • Perform one of the following actions to subscribe a consumer to the event:

      Use the emgrSubscribeSpecDsoConsumer() function to subscribe events from consumers that are implemented as distributed shared object (DSO) libraries that are called from the Event Manager server.

      or

      Use the emgrSubscribeSpecExecConsumer() function to subscribe events from applications that execute through the fork() or exec() command. (Event parameters pass to the consumer through the command line.)

      or

      Use the emgrSubscribeExecShMemConsumer() function to subscribes events from consumer applications that execute through the fork() or exec() commands and use shared memory. (Event parameters pass to the consumer applications via shared memory handoffs handled by the API layer.)

    To update a subscription event, perform one or more of the following actions:

    • Use the emgrSubscribeSpecPriority() function to add a tagged item to a subscription event to specify an optional event priority filter for subscription matching.

    • Use the emgrSubscribeSpecFacility() function to add a tagged item to a subscription event to specify an optional event facility filter for subscription matching.

    • Use the emgrSubscribeSpecRegexpMap() function to add a tagged item to a subscription event to specify an optional untagged event's class and type mapping before forwarding it to a subscribed consumer.

    • Use the emgrSubscribeSpecTimeFreq() function to add a tagged item to a subscription event that specifies how often (events/second) a matching event should be sent to a matching subscriber.

    • Use the emgrSubscribeSpecCntFreq() function to add a tagged item to a subscription event to specify how often (one out of n events) a matching event should be sent to a matching subscriber.

  4. Use the emgrSendEvent() or emgrRunSubscribe() function to send the event to the Event Manager daemon (eventmond).

  5. Use the emgrFreeEvent() function to free the memory that you allocated for the event.

Examples

The following examples show how to subscribe various types of consumer applications to events.

Example 3-2. Example Code to Subscribe a DSO Consumer

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <string.h>

#include "emgrapi.h"

main() 
{
   int i = 0;

   const char *host = "localhost";
   
   const char *sAppName = "tstApp";
   int         sClass   = 123;
   int         sType    = 345;
   const char *sSource  = NULL;
   const char *sOrigin  = NULL;
   
   const char *sDsoPath = "./libtstdso.so";
   const char *sDsoFunc = "TstDso";
   const char *sDsoPrms = "p1,p2,p3";


   EmgrEvent_t *pSubscrEvent =
   	 emgrNewSubscribe(sAppName, sClass, sType, sSource, sOrigin );

   emgrSubscribeSpecDsoConsumer(pSubscrEvent,
				   sDsoPath, sDsoFunc, sDsoPrms);

   emgrSendEvent(pSubscrEvent, host);

   emgrFreeEvent(pSubscrEvent);
}


Example 3-3. Example Code to Subscribe an Executable Consumer

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <string.h>

#include <emgrapi.h>

main() 
{

   int i = 0;

   const char *host = "localhost";
   
   const char *sAppName = "tstApp";
   int         sClass   = 123;
   int         sType    = 345;
   const char *sSource  = NULL;
   const char *sOrigin  = NULL;
   
   const char *sExecPath = "/bin/ls";
   const char *sExecPrms = "-l";
         

   EmgrEvent_t *pSubscrEvent =
   	 emgrNewSubscribe( sAppName, sClass, sType, sSource, sOrigin );

    emgrSubscribeSpecExecConsumer( pSubscrEvent, sExecPath, sExecPrms);

   emgrSendEvent(pSubscrEvent, host);

   emgrFreeEvent(pSubscrEvent);
}


Example 3-4. Example Code to Subscribe a Shared Memory Consumer

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <string.h>

#include <emgrapi.h>

main() 
{
   int i = 0;
      
   const char *sAppName = "tstApp";
   int         sClass   = 123;
   int         sType    = 345;
   const char *sSource  = "minsk-linux.csd.sgi.com";
   const char *sOrigin  = "tstApp";
   
   const char *sExecPath = "tstShmExec";
   

   EmgrEvent_t *pSubscrEvent = 
	    emgrNewSubscribe(sAppName, sClass, sType, sSource, sOrigin ) ;    
    emgrSubscribeSpecExecShMemConsumer(pSubscrEvent, sExecPath, NULL);

   emgrSendEvent(pSubscrEvent, NULL);

   emgrFreeEvent(pSubscrEvent);
}


Creating, Modifying, and Submitting Unsubscription Events

When a consumer no longer requires information about an event from the Event Manager, you should unsubscribe the event for that consumer. You do this by creating an unsubscription event and sending it to the eventmond daemon.

Figure 3-3 summarizes the steps necessary to create, modify, and submit unsubscription events. The text following the figure provides detailed information about each step. Refer to Chapter 2, “Event Manager API”, for specific information about the individual functions.

Figure 3-3. Creating/Updating and Submitting an Unsubscription Event from a Subscriber Application

Creating/Updating and Submitting an Unsubscription Event from a Subscriber Application

  1. Include the Event Manager API header file so that you can access the Event Manager API functions:

    #include <emgrapi.h>

  2. Verify that the Event Manager daemon is available:

    • Use the emgrIsDaemonInstalled() function to verify that the eventmond daemon is installed on the system

    • Use the emgrIsDaemonStarted() function to verify that the emgr daemon is running so the producer application can send event data to it.


      Note: This step is optional. These functions work only with the default configuration; if you modify how the Event Manager is installed or configured, these functions may fail.


  3. Create/update the unsubscription event:

    To create an unsubscription event, perform the following actions:

    • Use the emgrNewUnsubscribe() function to allocate a new unsubscription event structure and initialize the event header with data.

    • Perform one of the following actions to unsubscribe a consumer from an event:

      Use the emgrSubscribeSpecDsoConsumer() function to unsubscribe events from consumers that are implemented as distributed shared object (DSO) libraries that are called from the Event Manager server.

      or

      Use the emgrSubscribeSpecExecConsumer() function to unsubscribe events from applications that execute through the fork() or exec() command. (Event parameters pass to the consumer through the command line.)

      or

      Use the emgrSubscribeExecShMemConsumer() function to unsubscribe events from consumer applications that execute through the fork() or exec() commands and use shared memory. (Event parameters pass to the consumer applications via shared memory handoffs handled by the API layer.)

    To update an unsubscription event, perform one or more of the following actions:

    • Use the emgrSubscribeSpecPriority() function to add a tagged item to an unsubscription event to specify an optional event priority filter for subscription matching.

    • Use the emgrSubscribeSpecFacility() function to add a tagged item to an unsubscription event to specify an optional event facility filter for subscription matching.

    • Use the emgrSubscribeSpecRegexpMap() function to add a tagged item to an unsubscription event to specify an optional untagged event's class and type mapping before forwarding it to a subscribed consumer.

    • Use the emgrSubscribeSpecTimeFreq() function to add a tagged item to an unsubscription event that specifies how often (events/second) a matching event should be sent to a matching subscriber.

    • Use the emgrSubscribeSpecCntFreq() function to add a tagged item to an unsubscription event to specify how often (1/n) a matching event should be sent to a matching subscriber.

  4. Use the emgrSendEvent() or emgrRunUnsubscribe() function to send the event to the Event Manager daemon (eventmond).

Examples

The unsubscription code must contain the same components as the subscribe code (except that the emgrNewUnsubscribe() function replaces the emgrNewSubscribe() function). The following examples show how to unsubscribe various types of consumer applications from events.

Example 3-5. Example Code to Unsubscribe a DSO Consumer

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <string.h>

#include "emgrapi.h"

main() 
{
   int i = 0;

   const char *host = "localhost";
   
   const char *sAppName = "tstApp";
   int         sClass   = 123;
   int         sType    = 345;
   const char *sSource  = NULL;
   const char *sOrigin  = NULL;
   
   const char *sDsoPath = "./libtstdso.so";
   const char *sDsoFunc = "TstDso";
   const char *sDsoPrms = "p1,p2,p3";

   EmgrEvent_t *pUnsubscrEvent = 
    emgrNewUnsubscribe( sAppName, sClass, sType, sSource, sOrigin );

   emgrSubscribeSpecDsoConsumer( pUnsubscrEvent,
				   sDsoPath, sDsoFunc, sDsoPrms);

   emgrSendEvent(pUnsubscrEvent, host);

   emgrFreeEvent(pUnsubscrEvent);
}


Example 3-6. Example Code to Unsubscribe an Executable Consumer

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <string.h>

#include <emgrapi.h>

main() 
{

  int i = 0;

  const char *host = "localhost";
   
  const char *sAppName = "tstApp";
  int         sClass   = 123;
  int         sType    = 345;
  const char *sSource  = NULL;
  const char *sOrigin  = NULL;
   
  const char *sExecPath = "/bin/ls";
  const char *sExecPrms = "-l";
         

  EmgrEvent_t *pUnsubscrEvent =
  emgrNewUnsubscribe( sAppName, sClass, sType, sSource, sOrigin );

  emgrSubscribeSpecExecConsumer( pUnsubscrEvent, sExecPath, sExecPrms);

  emgrSendEvent(pUnsubscrEvent, host);

  emgrFreeEvent(pUnsubscrEvent);
}


Example 3-7. Example Code to Unsubscribe a Shared Memory Consumer

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <string.h>

#include <emgrapi.h>

main() 
{
  int i = 0;
      
  const char *sAppName = "tstApp";
  int         sClass   = 123;
  int         sType    = 345;
  const char *sSource  = "minsk-linux.csd.sgi.com";
  const char *sOrigin  = "tstApp";
   
  const char *sExecPath = "tstShmExec";
   
  EmgrEvent_t *pUnsubscrEvent = 
  emgrNewUnsubscribe(sAppName, sClass, sType, sSource, sOrigin ) ;    
  emgrSubscribeSpecExecShMemConsumer(pUnsubscrEvent, sExecPath, NULL);

  emgrSendEvent(pUnsubscrEvent, NULL);

  emgrFreeEvent(pUnsubscrEvent);
}


Creating a Consumer Application

When the Event Manager detects an event, it compares the event with the current subscription parameters; if there is a match, the Event Manager executes the proper consumer (using the method specified in the subscription event for the consumer) to send the event to it. Then, the consumer can use API functions to access the event payload (data).

Figure 3-4 summarizes the steps necessary to access the event payload. The text following the figure provides detailed information about each step. Refer to Chapter 2, “Event Manager API”, for specific information about the individual functions.

Figure 3-4. Accessing an Event from a Consumer Application

Accessing an Event from a Consumer Application

  1. Include the Event Manager API header file so that you can access the Event Manager API functions:

    #include <emgrapi.h>

  2. If the consumer is a shared library consumer, the function prototype must use the same format as the following ConsumerEntry_t prototype to enable the Event Manager to call it:

    typedef int ConsumerEntry_t(EmgrEvent_t *event,
    int argc,
    const char *argv[]);

    For example:

    int TstDso(EmgrEvent_t *event,
    int argc,
    char *argv[]);

  3. If the consumer is a shared memory consumer, use the emgrShmInitEvent() or emgrShmCliInitEvent() function to initialize the event structure from shared memory.

  4. Retrieve the data using one of the following methods:

    • If you know the name of the item:

      Use the emgrGetEventItem() function to get the value of the item. You must specify the name of the item as a parameter to the function.

    • If you do not know the name of the item:

      Use the emgrGetFirstEventItem() function to get a (name, value) pair. If there is more than one (name, value) pair, use the emgrGetNextItem() function in a loop to load all of the (name, value) pairs.

  5. Process the event.

Example

The following example shows shared library consumer code that accesses all (name, value) pairs in an event.

Example 3-8. Example Code to Access Event Data from a Shared Library Consumer Application

<#include emgrapi.h>

int TstDso(EmgrEvent_t *event, int argc, char *argv[]) {
   int i;
   const char *name;
   const void *value;
   int type = 0, length = 0;

   printf("consumer_main\n");
   printf("   type=%d;class=%d;version=%d",
	  event->header.evType,event->header.evClass,event->header.version);
   
   printf("   ORIGIN=%s;APPNAME=%s;SOURCE=%s\n",
	  event->origin,event->appname,event->source);

   i = emgrGetFirstEventItem(event, &name, &value, &type, &length);
   while (i == 0) {
      printf("   %s=[%s];\n",name,(char *) value);
      i = emgrGetNextEventItem(event, &name, &value, &type, &length);
   }

   printf("  Number of args: %d\n",argc-1);
   for(i=0; i< argc; i++)
      printf("   arg[%d] = '%s'\n",i,argv[i]);

   return 0;
}

The following example code accesses event data from a shared memory consumer.

Example 3-9. Example Code to Access Event Data from a Shared Memory Consumer

int main(int argc, const char *argv[]) {

   int i = 0;

   for(i = 0; i < argc; i++) {
      printf("Arg[%d] = `%s'\n", i, argv[i]);
   }

   {
      int error = 0;
      EmgrEvent_t *pEvent = emgrShmCliInitEvent( argc, argv, &error);

      if ( pEvent != NULL ) {
	 emgrPrintEvent(pEvent, stdout);

	 emgrFreeEvent(pEvent);
      } else {
	 fprintf(stderr,
		 "Error %d initializing event from the shared memory\n",
		 error);
      }

   }
   return 0;
}