Skip to content

Events

Chapter 9-8
Events

Event is a real-time indication that something interesting has happened. It can be produced from a user program, or from a Domino server program. This chapter defines some event terminologies, discusses several API event functions, ways to generate and to poll a user-defined event notification, and ways to capture the event notifications generated from the Domino server programs.

Event Terminologies

Event: In this User Guide,a signal from one server add-in program to another, usually indicating that something of interest has occurred.

Event Queue: The queue in which the signal is placed and from which the signal is read.

Event Producer: An add-in task that generates the event, placing it on the queue.

Event Consumer: An add-in task that removes the event from the event queue, acting on it as appropriate.

Event Type and Event Severity: Each event is defined as being of a certain "type" - for example, a mail type of event or a security type of event. For a list of valid event type names, see the definition of EVT_xxx in the Reference.Each event is also defined as being of a certain "severity" - for instance, indicating a fatal condition. For a list of valid event severity names, see the definition of SEV_xxx in the Reference.Since each combination of type and severity defines a different kind of event, you can define a large number of distinct events.

Event Function Calls

Several API functions, described below, are specific to events. For demonstrations of their usage, see the discussions of the CONSUME and PRODUCE sample code below.

EventQueueAlloc
EventQueueAlloc allocates memory for an event queue and names the queue. It is called by an event consumer to create a queue to which an event producer may write events.

EventQueueFree
EventQueueFree deallocates the memory associated with a queue, destroying it. An event consumer should call EventQueueFree when the consumer is no longer interested in receiving events from that queue.

EventRegisterEventRequest
An event consumer calls EventRegisterEventRequest to specify to the HCL Domino Server the name of the event queue it will poll, as well as the type and severity of events in which it is interested. You must call EventRegisterEventRequest for each unique combination of event type and event severity in which the consumer is interested.

This function also allows the consumer to specify a user name or database name to associate with each type/severity of event. After an event is consumed, the consumer may call EventGetDestName to retrieve this name and then use it as appropriate -- for instance, mailing a message to the specified user or logging the event in the specified database.

EventDeregisterEventRequest
EventDeregisterEventRequest indicates to the server that an event consumer is no longer interested in events of a certain type and severity. You must call it once for each distinct type/severity combination.

EventQueuePut
An event producer calls EventQueuePut to place an event of a specific type and severity on the specified event queue. An event producer may pass user-defined data specific to this event. For more details on event-specific data, see the definition of EVENT_DATA.

EventQueueGet
An event consumer calls EventQueueGet to check a specified queue for events. The function is usually called in the main AddInIdle loop. If there are no events in the queue, the function returns the error code ERR_EVTQUEUE_EMPTY. If the functions returns NOERROR, it removes an event from the queue, and returns a handle to an EVENT_DATA data structure.

EventGetDestName
An event consumer calls EventGetDestName to retrieve the user name or database name that was specified in the call to EventRegisterEventRequest.


User-Defined Event Notification

User-defined events allow one server add-in task to notify another that something has happened. This section examines some code fragments from the sample programs CONSUME and PRODUCE that demonstrate the functions. The two programs are in the subdirectory samples\server\events.

The CONSUME Sample Program

The sample program CONSUME is an event consumer. It first creates an event queue with the specified name and tells the server to notify it of events of type TYPE_MISC and severity SEV_NORMAL.

    consume.c: Creating an Event Queue and Registering Events

/
*  Create the event queue and specify that we are interested in events
*  of type EVT_MISC and of severity SEV_NORMAL.
/


if (sError = EventQueueAlloc(QueueName))
   return (ERR(sError));
 
if (sError = EventRegisterEventRequest(EVT_MISC,
                                      SEV_NORMAL,
                                      QueueName,
                                      InputDestName))
   return (ERR(sError));



The main loop of the program calls EventQueueGet to see if an event of this type has occurred. If so, it processes the data returned with the event. Note that the format of the event-specific data is entirely up to the designer of the consumer and producer tasks. In this sample program, the event-specific data is simply a character string containing the date and time that the event was generated. The program reads the character string and logs it. It also calls EventGetDestName to get the name of the user or database that was specified for this event when the event was registered. It doesn't do anything with this name, but a consumer could make use of this name -- for instance, by mailing a message to the specified user or logging the event in the specified database.

    consume.c: Consuming Events in the Event Queue


   while (!AddInIdle())
  {

   /
   
 Check to see if there is an event we're interested in the queue.
     If no events in the queue, don't do anything.
   
/


       sError = EventQueueGet(QueueName, &hEventData);

       if (sError == ERR_EVTQUEUE_EMPTY)
          continue;


       if (sError == NOERROR)
      {

       /
       
 There is an event in the queue.  Lock the handle returned
         to get the EVENT_DATA structure that is returned with the event.
       
 Copy the event-specific data (in this case, a string denoting
         the time the event occurred) into a local buffer, terminate the
       
 string with a NULL, and log an appropriate message.
       
       
 Also, call EventGetDestName to get the user or database name
         assigned to this event by the call to EventRegisterEventRequest.
       
 This program doesn't do anything with the name - the
         function is called for demonstration purposes only.
       
/



           pBuf = OSLockObject(hEventData);
          pEventData = (EVENT_DATA far )pBuf;
          memmove(DataBuf,
                  &pEventData->EventSpecificData,
                  pEventData->EventDataLength);
          DataBuf[pEventData->EventDataLength] = '\0';            


           sprintf(MessageBuf,
                  "CONSUME consumed an event at %s",
                  DataBuf);


           AddInLogMsg(ADDIN_MSG_FMT, MessageBuf);

           bDestNameReturned = EventGetDestName(EVT_MISC,
                                               SEV_NORMAL,
                                               QueueName,
                                               OutputDestName,
                                               sizeof(OutputDestName));


       /

         Here, the event consumer could do something with the name
       
 returned by EventGetDestName. If a database name was specified
         when the event was registered, the consumer could update the
       
 database appropriately.  If a user name was specified during
         registration, the event consumer could send mail to notify
       
 the user that the event occurred.  Such processing is covered
         elsewhere, so it won't be repeated here.
       
/


           OSUnlockObject(hEventData);
          OSMemFree(hEventData);
           
      }
  }


When the consumer no longer wishes to receive notice of a particular event, it calls the function EventDeregisterEventRequest to indicate this to the server. Before terminating, the consumer should also call EventQueueFree in order to free up any memory the system allocated for the queue.

    consume.c: Deregistering Events, Deallocating Event Queue


   
  /
   
 Destroy the event queue.
   */

   sError = EventDeregisterEventRequest(EVT_MISC, SEV_NORMAL, QueueName);    
  EventQueueFree(QueueName);



The PRODUCE Sample Program

The sample program PRODUCE is an event producer. Every minute, it creates an event of type EVT_MISC and severity SEV_NORMAL and places it on the specified event queue. A string containing the current date and time is passed as event-specific data.

    produce.c: Generating Events



    while (!AddInIdle())
   {
       if (AddInMinutesHaveElapsed(1))
       {
       /
        *  If a minute has passed, get the current time and date.  Then
        *  generate an event of type EVT_MISC and severity SEV_NORMAL.
        *  Pass a string containing the time and date as event-specific
        *  data.
       
/
       
           OSCurrentTIMEDATE(&EventTimeDate);
           ConvertTIMEDATEToText(NULL,
                                 NULL,
                                 &EventTimeDate,
                                 EventBuffer,
                                 sizeof(EventBuffer)-1,
                                 &wLen);


            sError = EventQueuePut(szQueueName,
                                  NULL,
                                  EVT_MISC,
                                  SEV_NORMAL,
                                  &EventTimeDate,
                                  TYPE_TEXT,
                                  wLen,
                                  (BYTE far *) EventBuffer);
                                 
           AddInLogMsg(ADDIN_MSG_FMT, "PRODUCE Test: Produced an event!");
       }
   }



Domino-Generated Event Notification

The EVENTS4.nsf database contains event configurations which the Domino Event Monitor uses when notifying administrators about a specific event. To capture the Domino event notification and direct it into a user-specified queue, you need to specify the relationship between the notification and the queue in the EVENTS4.nsf.

  • Create a new Notification Method
    1. From the Names & Messages (Advanced) \ Notification Methods view of the EVENTS4.nsf, click the New Notification Method action.
    2. Enter the following values in the Event Notification Method form:
      Item Name:Value:
      Method DescriptionAny text, for example: eventMethodTest1
      Method NameThe name of the event queue which the consume program will be polling the notification message from
  • Create a Event Notification and direct the notification to a specific queue
    1. From the Event Notification view of the EVENTS4.nsf, click the New Event Notification action.
    2. From the Basics and Event tabs in the Event Notification form, select appropriate event trigger, and event notification criteria.
    3. From the Action tab in the Event Notification form, choose the new Notification Method just created.
  • Create a consume program to poll the notification
    The name of the message queue specified in this program should be exact the same as the Method Name specified in the EVENTS4.nsf as described above, for example: eventMethodTest1.

      consume.c: To retrieve information from EVENT_DATA


   while (!AddInIdle())
  {

   /
   
 Check to see if there is an event we're interested in the queue.
     If no events in the queue, don't do anything.
   
/


       sError = EventQueueGet(QueueName, &hEventData);

       if (sError == ERR_EVTQUEUE_EMPTY)
          continue;


       if (sError == NOERROR)
      {

           pBuf = OSLockObject ( hEventData );
           pEventData   = (EVENT_DATA ) pBuf;

           /
Acquire ErrorCode from the EVENT_DATA structure. /
           
           errorcode = pEventData->ErrorCode;

           /
Acquire FormatSpecifier from the EVENT_DATA structure. /
           
           formatspecifier = pEventData->FormatSpecifier;

           /
Acquire AddIn name from the EVENT_DATA structure. /

           memmove ( eventAddInData_Buffer,
                 &(pEventData->EventSpecificData),
                 pEventData->AddinNameLength );
           eventAddInData_Buffer [ pEventData->AddinNameLength ] = '\0';

           /
Acquire EventData from the EVENT_DATA structure. /

           memmove ( eventData_Buffer,
                 &(pEventData->EventSpecificData) + pEventData->AddinNameLength,
                 pEventData->EventDataLength - pEventData->AddinNameLength );
           eventData_Buffer[
                 pEventData->EventDataLength-pEventData->AddinNameLength ]='\0';

           /
Acquire OriginatingServerName from the EVENT_DATA structure. /

           memmove ( eventOriginatingServer_Buffer,
                 pEventData->OriginatingServerName,
                 MAXUSERNAME );

           /
Acquire Type from the EVENT_DATA structure. /

           type = pEventData->Type;

           /
Acquire Severity from the EVENT_DATA structure. /

           severity = pEventData->Severity;

           /
Log and Print the alert message. */

           AddInLogMessageText ( SS_ADDIN_LOG,
                                      0,
                                  errorcode,
                                  severity,
                                  type,
                                  (LPSTR) eventAddInData_Buffer,
                                  (LPSTR) eventOriginatingServer_Buffer,
                                  formatspecifier,
                                  (LPSTR) eventData_Buffer );

           OSUnlockObject ( hEventData );
           OSMemFree ( hEventData );
      }
  }

  • Load the Event Monitor (the Event server task )and the consume add-in program
    Please refer to the Server Add-In Tasks chapter (Chapter 4-4) in this manual for more information on loading the consume add-in program and the event program (be sure they are loaded in this order.)