Difference between revisions of "Doc:latest/evalguide/csa112"

 
(How to Run csa212 and What to Observe)
 
(8 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
==csa112 Event Subscription==
 
==csa112 Event Subscription==
 +
 +
An event service is an communications mechanism organised around the categories of data rather then senders and receivers.  A "publisher" posts a message to a well-known event channel and all "subscribers" receive the message.  Publishers and subscribers do not need to know who each other are; they need only know the event channel name. 
 +
 +
As the Messaging service is similar to mail, the Event service is similar to a bulletin board.
 +
  
 
===Objective===
 
===Objective===
  
The objective of csa112 is to learn how to use Clovis' event service to subscribe to events and to extract the relevant information from the events received by subscription.
+
The objective of csa112 is to learn how to use the SAFplus Platform event service to subscribe to events and to extract the relevant information from the events received by subscription.
  
 
===What you will learn===
 
===What you will learn===
  
You will learn  
+
You will learn:
 
*how to initialize the event library
 
*how to initialize the event library
 
*how to subscribe to events
 
*how to subscribe to events
 
*how to receive events
 
*how to receive events
 
*how to extract the event data
 
*how to extract the event data
 +
 +
The SAFplus Event service is SA-Forum compliant and this tutorial expects that you will refer to the relevant SA-Forum document for an in-depth description of the APIs used.
  
 
===Code===
 
===Code===
  
One difference to note between this application and previous ones is that this application will not have a main loop in <code>clCompAppInitialize</code>.  Instead we will do our work in callback code.  This means that when we return from <code>clCompAppInitialize</code> we won't exit the application.
+
One difference to note between this application and previous ones is that this application will not have a main loop in <code>initializeAmf</code>.  Instead we will do our work in callback code.  This means that when we return from <code>initializeAmf</code> we won't exit the application.
  
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
  ! style="color:black;background-color:#ffccaa;" align="center"| clCompAppMain.c
+
  ! style="color:black;background-color:#ffccaa;" align="center"| main.c
 
  |-  
 
  |-  
 
  |<code><pre>
 
  |<code><pre>
     ClNameT    evtChannelName = {
+
     SaNameT evtChannelName =
                    sizeof EVENT_CHANNEL_NAME - 1,
+
    {
                    EVENT_CHANNEL_NAME
+
        sizeof EVENT_CHANNEL_NAME -1,
          };
+
        EVENT_CHANNEL_NAME
 
+
    };
     ClEventChannelHandleT   evtChannelHandle = CL_HANDLE_INVALID_VALUE;
+
     ClEventInitHandleT      evtHandle = CL_HANDLE_INVALID_VALUE;
+
     SaEvtChannelHandleT   evtChannelHandle = 0;
 
+
     SaEvtHandleT          evtLibHandle=0;
     static void
+
     SaEvtEventHandleT     eventHandle=0;
     csa112Comp_appEventCallback( ClEventSubscriptionIdT subscriptionId,
+
                                          ClEventHandleT eventHandle,
+
                                          ClSizeT eventDataSize);
+
  
 +
    static void  csa112Comp_appEventCallback( SaEvtSubscriptionIdT subscriptionId,
 +
                                              SaEvtEventHandleT eventHandle,
 +
                                              SaSizeT eventDataSize);
 
   </pre></code>
 
   </pre></code>
 
|}  
 
|}  
Line 40: Line 47:
  
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
  ! style="color:black;background-color:#ffccaa;" align="center"| clCompAppMain.c
+
  ! style="color:black;background-color:#ffccaa;" align="center"| main.c
 
  |-  
 
  |-  
 
  |<code><pre>
 
  |<code><pre>
     ClRcT
+
     void
     clCompAppInitialize(ClUint32T argc,ClCharT *argv[])
+
     initializeAmf(void)
 
     {
 
     {
 
         ....
 
         ....
  
         ClEventCallbacksT  evtCallbacks = {
+
         const SaEvtCallbacksT evtCallbacks =
                          NULL,
+
        {
                          csa112Comp_appEventCallback
+
            NULL, /* Event open callback */
                        };
+
            csa112Comp_appEventCallback /* Event delivery callback */
 
+
        };
 
         ...
 
         ...
  
 
         // publish our event callbacks
 
         // publish our event callbacks
         rc = clEventInitialize(&evtHandle, &evtCallbacks, &evtVersion);
+
         rc = saEvtInitialize(&evtLibHandle, &evtCallbacks, &evtVersion);
 
+
 
         ...
 
         ...
 
   </pre></code>
 
   </pre></code>
 
|}  
 
|}  
  
We initialize the OpenClovis Event Manager with <code>clEventInitialize</code>.  We pass the address of the variable where we want the event handle stored.  We pass the address of our event callback functions structure.  Note that the only event callback function that we specify is <code>csa112Comp_appEventCallback</code>.  We do not specify the other callback which is the Asynchronous channel open callback.  We specify <code>NULL</code> for that field of <code>evtCallbacks</code> because we don't open our event channel asynchronously.:
+
We initialize the OpenClovis Event Manager with <code>saEvtInitialize</code>.  We pass the address of the variable where we want the event handle stored.  We pass the address of our event callback functions structure.  Note that the only event callback function that we specify is <code>csa112Comp_appEventCallback</code>.  We do not specify the other callback which is the Asynchronous channel open callback.  We specify <code>NULL</code> for that field of <code>evtCallbacks</code> because we don't open our event channel asynchronously.:
  
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
  ! style="color:black;background-color:#ffccaa;" align="center"| clCompAppMain.c
+
  ! style="color:black;background-color:#ffccaa;" align="center"| main.c
 
  |-  
 
  |-  
 
  |<code><pre>
 
  |<code><pre>
     ClRcT
+
     void
     clCompAppInitialize(ClUint32T argc, ClCharT *argv[])
+
     initializeAmf(void)
 
     {
 
     {
  
Line 75: Line 81:
  
 
         // Open an event chanel so that we can subscribe to events on that channel
 
         // Open an event chanel so that we can subscribe to events on that channel
         rc = clEventChannelOpen(evtHandle,
+
         rc = saEvtChannelOpen(evtLibHandle, &evtChannelName,  
                &evtChannelName,
+
                              (SA_EVT_CHANNEL_PUBLISHER | SA_EVT_CHANNEL_SUBSCRIBER | SA_EVT_CHANNEL_CREATE),  
                (CL_EVENT_CHANNEL_SUBSCRIBER |
+
                              (SaTimeT)SA_TIME_END, &evtChannelHandle);
                CL_EVENT_GLOBAL_CHANNEL |
+
         if (rc != SA_AIS_OK)
                CL_EVENT_CHANNEL_CREATE),
+
                (ClTimeT)CL_RMD_TIMEOUT_FOREVER,
+
                &evtChannelHandle);
+
         if (rc != CL_OK)
+
 
         {
 
         {
             clprintf(CL_LOG_SEV_ERROR, "csa112\t:Failure opening event channel[0x%x]",
+
             clprintf(CL_LOG_SEV_ERROR, "Failure opening event channel [0x%x] at %ld", rc, time(0L));
                    rc);
+
             errorExit(rc);
             return rc;
+
 
         }
 
         }
 
+
       
         rc = clEventExtSubscribe(evtChannelHandle, EVENT_TYPE, 1, (void*)0);
+
         rc = saEvtEventSubscribe(evtChannelHandle, NULL, 1);
         if (rc != CL_OK)
+
         if (rc != SA_AIS_OK)
 
         {
 
         {
             clprintf(CL_LOG_SEV_ERROR, "Failed to subscribe to event channel [0x%x]",
+
             clprintf(CL_LOG_SEV_ERROR, "Failed to subscribe to event channel [0x%x]",rc);
                    rc);
+
             errorExit(rc);
             return rc;
+
 
         }
 
         }
 
 
   </pre></code>
 
   </pre></code>
 
|}  
 
|}  
  
Within the above code we open the channel synchronously.  We pass the handle we got back from <code>clEventInitialize</code>, the channel name we defined previously, flags that indicate this process is subscribing to the channel and it's a global channel, and that the channel should be created if it's not already there, a timeout value of "forever", and the address of the location where the channel handle should be stored.  Then, we subscribe to a specific event stream on the event channel.  The <code>EVENT_TYPE</code> constant is defined in <code>common/common.h</code> as 5432.  This value is used by the event publisher when it sends events.  The constant 1 being passed simply identifies this specific subscription on this channel.  This value will be passed to our event delivery callback function.
+
Within the above code we open the channel synchronously.  We pass the handle we got back from <code>saEvtInitialize</code>, the channel name we defined previously, flags that indicate this process is subscribing to the channel and it's a global channel, and that the channel should be created if it's not already there, a timeout value of "forever", and the address of the location where the channel handle should be stored.  Then, we subscribe to a specific event stream on the event channel.  The <code>EVENT_TYPE</code> constant is defined in <code>common/common.h</code> as 5432.  This value is used by the event publisher when it sends events.  The constant 1 being passed simply identifies this specific subscription on this channel.  This value will be passed to our event delivery callback function.
  
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
  ! style="color:black;background-color:#ffccaa;" align="center"| clCompAppMain.c
+
  ! style="color:black;background-color:#ffccaa;" align="center"| main.c
 
  |-  
 
  |-  
 
  |<code><pre>
 
  |<code><pre>
     static void
+
     static void  
     csa112Comp_appEventCallback( ClEventSubscriptionIdT subscriptionId,
+
     csa112Comp_appEventCallback(SaEvtSubscriptionIdT subscriptionId,
                                              ClEventHandleT eventHandle,
+
                                SaEvtEventHandleT eventHandle,  
                                              ClSizeT eventDataSize)
+
                                SaSizeT eventDataSize)
 
     {
 
     {
         ClRcT rc = CL_OK;
+
   
    ClPtrT resTest = NULL;
+
         SaAisErrorT    rc = SA_AIS_OK;
    ClSizeT resSize;
+
        static ClPtrT   resTest = 0;  
    if (running == 0 || ha_state != CL_AMS_HA_STATE_ACTIVE)
+
         clprintf(CL_LOG_SEV_INFO,"We've got an event to receive\n");
    {
+
         goto cleanup;
+
    }
+
    clprintf(CL_LOG_SEV_NOTICE,"We've got an event to receive");
+
  
    resTest = clHeapAllocate(eventDataSize + 1);
+
        if (resTest != 0)
    if (resTest == NULL)
+
        {
    {
+
            clHeapFree((char *)resTest);
        clprintf(CL_LOG_SEV_ERROR, "Failed to allocate space for event");
+
            resTest = 0;
        goto cleanup;
+
         }
    }
+
         resTest = clHeapAllocate(eventDataSize + 1);
    *(((char *)resTest) + eventDataSize) = 0;
+
    resSize = eventDataSize;
+
    rc = clEventDataGet(eventHandle, resTest, &resSize);
+
    if (rc != CL_OK)
+
    {
+
         clprintf(CL_LOG_SEV_ERROR, "Failed to get event data [0x%x]", rc);
+
         clHeapFree(resTest);
+
        goto cleanup;
+
    }
+
  
    clprintf(CL_LOG_SEV_NOTICE,"received event: %s", (char *)resTest);
+
        if (resTest == 0)
 +
        {
 +
            clprintf(CL_LOG_SEV_ERROR, "Failed to allocate space for event");
 +
            return;
 +
        }
 +
        rc = saEvtEventDataGet(eventHandle, resTest, &eventDataSize);
  
    cleanup:
+
        if (rc!= SA_AIS_OK)
    //Free the memory associated with eventHandle
+
        {
    clEventFree(eventHandle);
+
            clprintf(CL_LOG_SEV_ERROR, "Failed to get event data [0x%x]",rc);
 +
            return;
 +
        }
 +
 
 +
        *(((char *)resTest) + eventDataSize) = 0;
 +
        clprintf(CL_LOG_SEV_INFO,"received event: %s\n", (char *)resTest);
 
     }
 
     }
 
   </pre></code>
 
   </pre></code>
 
|}  
 
|}  
  
The event delivery callback function is named <code>csa112Comp_appEventCallback</code>. First it checks that the running variable is not zero and that the High Availability State is <code>CL_AMS_HA_STATE_ACTIVE</code>, otherwise it returns, dropping the event in the bit bucket.  Next it checks whether our incoming data buffer needs to be deallocated.  If there is a buffer, it deallocates it and then allocates enough data to receive the incoming event data.  Then, we extract the data from the event into the newly allocated buffer using <code>clEventDataGet</code>.  Finally, we print the event data we received using <code>clprintf</code> which is another member of Clovis' OS Abstraction Layer.  As its name and usage suggest, it is the OSAL replacement for printf.
+
The event delivery callback function is named <code>csa112Comp_appEventCallback</code>. It checks whether our incoming data buffer needs to be deallocated.  If there is a buffer, it deallocates it and then allocates enough data to receive the incoming event data.  Then, we extract the data from the event into the newly allocated buffer using <code>clEventDataGet</code>.  Finally, we print the event data we received using <code>clprintf</code> which is another member of Clovis' OS Abstraction Layer.  As its name and usage suggest, it is the OSAL replacement for printf.
  
===csa212 SA Forum Compliant Event Subscription===
+
'''Note:'''
  
csa212 demonstrates the usage of SA Forum's Event Service. This sample application does not deviate functionally from csa112. The differences in code are due to using SA Forum data types (structures) and APIs , as presented in the following two tables. (Note we have not repeated data types and APIs covered previously.)
+
Before building the project,copy the common directory which can be found under            <code><eval_dir>/src/app</code> to the working area
 
+
<code><pre># cp -r <eval_dir>/src/app/common  .</pre></code>
{| cellspacing="0" border="1" align="center"
+
|+align="bottom"| '''SA Forum Data Types with the SAFplus Platform equivalent'''
+
|- style="color:black;background-color:#ffffaa;" align="center"
+
!SA Forum Data Types 
+
!OpenClovis Data Types
+
|-
+
|SaEvtHandleT
+
|ClEventInitHandleT
+
|-
+
|SaEvtChannelHandleT
+
|ClEventChannelHandleT
+
|-
+
|SaEvtCallbacksT
+
|ClEventCallbacksT
+
|-
+
|SA_EVT_CHANNEL_SUBSCRIBER
+
|CL_EVENT_CHANNEL_SUBSCRIBER
+
|-
+
|SA_EVT_CHANNEL_CREATE
+
|CL_EVENT_CHANNEL_CREATE
+
|-
+
|SA_TIME_END
+
|CL_RMD_TIMEOUT_FOREVER
+
|}
+
 
+
 
+
 
+
 
+
{| cellspacing="0" border="1" align="center"
+
|+align="bottom"| '''SA Forum APIs with the SAFplus Platform equivalent'''
+
|- style="color:black;background-color:#ffffaa;" align="center"
+
!SA Forum APIs
+
!OpenClovis APIs
+
|-
+
|SaEvtInitialize
+
|ClEventInitialize
+
|-
+
|saEvtChannelOpen
+
|clEventChannelOpen
+
|-
+
|saEvtEventSubscribe
+
|clEventExtSubscribe
+
|-
+
|saEvtEventDataGet
+
|clEventDataGet
+
|-
+
|saEvtChannelClose
+
|clEventChannelClose
+
|-
+
|saEvtFinalize
+
|clEventFinalize
+
|}
+
  
 
===How to Run csa112 and What to Observe===
 
===How to Run csa112 and What to Observe===
  
 
<ol>
 
<ol>
<li>Start example csa112 in the same manner that we have started previous examples, with the SAFplus Platform Console.(Unlock csa212SGI0 instead of csa112SGI0 to run csa212).
+
<li>Start example csa212 in the same manner that we have started previous examples, with the SAFplus Platform Console.(Unlock csa212SGI0 instead of csa112SGI0 to run csa212).
 
<code><pre>
 
<code><pre>
 
  # cd /root/asp/bin
 
  # cd /root/asp/bin
Line 215: Line 159:
 
cli[Test]-> setc 1
 
cli[Test]-> setc 1
 
cli[Test:SCNodeI0]-> setc cpm
 
cli[Test:SCNodeI0]-> setc cpm
cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa112SGI0
+
cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa212SGI0
 
</pre></code>
 
</pre></code>
  
 
Looking at the log file for this example you should see the following.
 
Looking at the log file for this example you should see the following.
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
  ! style="color:black;background-color:#ffffaa;" align="center"| /root/asp/var/log/csa112CompI0Log.latest
+
  ! style="color:black;background-color:#ffffaa;" align="center"| /root/asp/var/log/csa212CompI3Log.latest
 
  |-  
 
  |-  
 
  |<code><pre>
 
  |<code><pre>
Mon Jul 14 21:59:49 2008  (SCNodeI0.24077 : csa112CompEO.---.---.00028 :  INFO)
+
  Fri Oct  1 13:14:16.935 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00001 :  INFO) Component [csa212CompI3] : PID [10366]. Initializing
Component [csa112CompI0] : PID [24077]. Initializing
+
 
Mon Jul 14 21:59:49 2008  (SCNodeI0.24077 : csa112CompEO.---.---.00029 :  INFO)
+
  Fri Oct  1 13:14:16.935 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00002 :  INFO)   IOC Address            : 0x4
    IOC Address            : 0x1
+
 
Mon Jul 14 21:59:49 2008  (SCNodeI0.24077 : csa112CompEO.---.---.00030 :  INFO)
+
  Fri Oct  1 13:14:16.935 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00003 :  INFO)   IOC Port                : 0x80
    IOC Port                : 0x80
+
 
Mon Jul 14 21:59:49 2008  (SCNodeI0.24077 : csa112CompEO.---.---.00037 :  INFO)
+
  Fri Oct  1 13:15:31.389 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00004 :  INFO) Component [csa212CompI3] : PID [10366]. CSI Set Received
csa112: Instantiated as component instance csa112CompI0.
+
 
Mon Jul 14 21:59:49 2008  (SCNodeI0.24077 : csa112CompEO.---.---.00038 :  INFO)
+
 
csa112CompI0: Waiting for CSI assignment...
+
 
</pre></code>
 
</pre></code>
 
|}  
 
|}  
Line 238: Line 181:
 
<li>Now unlock the application with:
 
<li>Now unlock the application with:
 
<code><pre>
 
<code><pre>
cli[Test:SCNodeI0:CPM]-> amsUnlock sg csa112SGI0
+
cli[Test:SCNodeI0:CPM]-> amsUnlock sg csa212SGI0
 
</pre></code>
 
</pre></code>
  
 
At this point you should see the following in the log.
 
At this point you should see the following in the log.
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
 
{| cellspacing="0" cellpadding = "0" border="0" align = "center" width="680"
  ! style="color:black;background-color:#ffffaa;" align="center"| /root/asp/var/log/csa112CompI0Log.latest
+
  ! style="color:black;background-color:#ffffaa;" align="center"| /root/asp/var/log/csa212CompI3Log.latest
 
  |-  
 
  |-  
 
  |<code><pre>
 
  |<code><pre>
Mon Jul 14 22:01:29 2008  (SCNodeI0.24077 : csa112CompEO.---.---.00049 :  INFO)
+
Fri Oct  1 13:15:31.389 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00012 :  INFO) csa212: ACTIVE state requested; activating service
csa112: ACTIVE state requested; activating service
+
 
 +
 
 
</pre></code>
 
</pre></code>
 
|}
 
|}
  
Thats all there is to this example. What you are looking at in the log is the output of our event listener. It doesn't appear very interesting because we have not yet written an event publisher that will give the program something to output. We'll do that in the next example (csa113).
+
Thats all there is to this example. What you are looking at in the log is the output of our event listener. It doesn't appear very interesting because we have not yet written an event publisher that will give the program something to output. We'll do that in the next example (csa213).
  
 
<li>At this point we can shut down our example in the usual fashion.
 
<li>At this point we can shut down our example in the usual fashion.
 
<code><pre>
 
<code><pre>
cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa112SGI0
+
cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa212SGI0
cli[Test:SCNodeI0:CPM]-> amsLockInstantiation sg csa112SGI0
+
cli[Test:SCNodeI0:CPM]-> amsLockInstantiation sg csa212SGI0
 
cli[Test:SCNodeI0:CPM]-> end
 
cli[Test:SCNodeI0:CPM]-> end
 
cli[Test:SCNodeI0]-> end
 
cli[Test:SCNodeI0]-> end

Latest revision as of 06:39, 17 November 2014

Contents

[edit] csa112 Event Subscription

An event service is an communications mechanism organised around the categories of data rather then senders and receivers. A "publisher" posts a message to a well-known event channel and all "subscribers" receive the message. Publishers and subscribers do not need to know who each other are; they need only know the event channel name.

As the Messaging service is similar to mail, the Event service is similar to a bulletin board.


[edit] Objective

The objective of csa112 is to learn how to use the SAFplus Platform event service to subscribe to events and to extract the relevant information from the events received by subscription.

[edit] What you will learn

You will learn:

  • how to initialize the event library
  • how to subscribe to events
  • how to receive events
  • how to extract the event data

The SAFplus Event service is SA-Forum compliant and this tutorial expects that you will refer to the relevant SA-Forum document for an in-depth description of the APIs used.

[edit] Code

One difference to note between this application and previous ones is that this application will not have a main loop in initializeAmf. Instead we will do our work in callback code. This means that when we return from initializeAmf we won't exit the application.

main.c
    SaNameT evtChannelName =
    {
        sizeof EVENT_CHANNEL_NAME -1,
        EVENT_CHANNEL_NAME
    };
 
    SaEvtChannelHandleT   evtChannelHandle = 0;
    SaEvtHandleT          evtLibHandle=0;
    SaEvtEventHandleT     eventHandle=0;

    static void  csa112Comp_appEventCallback( SaEvtSubscriptionIdT subscriptionId, 
                                              SaEvtEventHandleT eventHandle,
                                              SaSizeT eventDataSize);
  

Here we define variables to hold the payload of our event. Note the initialization of the evtChannelName. The length is set to the length of the EVENT_CHANNEL_NAME string WITHOUT including the null terminator.

main.c
    void
    initializeAmf(void)
    {
        ....

        const SaEvtCallbacksT evtCallbacks =
        {
            NULL,  /* Event open callback */
            csa112Comp_appEventCallback  /* Event delivery callback */
        };
        ...

        // publish our event callbacks
        rc = saEvtInitialize(&evtLibHandle, &evtCallbacks, &evtVersion);
        ...
  

We initialize the OpenClovis Event Manager with saEvtInitialize. We pass the address of the variable where we want the event handle stored. We pass the address of our event callback functions structure. Note that the only event callback function that we specify is csa112Comp_appEventCallback. We do not specify the other callback which is the Asynchronous channel open callback. We specify NULL for that field of evtCallbacks because we don't open our event channel asynchronously.:

main.c
    void
    initializeAmf(void)
    {

        ....

        // Open an event chanel so that we can subscribe to events on that channel
        rc = saEvtChannelOpen(evtLibHandle, &evtChannelName, 
                              (SA_EVT_CHANNEL_PUBLISHER | SA_EVT_CHANNEL_SUBSCRIBER | SA_EVT_CHANNEL_CREATE), 
                              (SaTimeT)SA_TIME_END, &evtChannelHandle);
        if (rc != SA_AIS_OK)
        {
            clprintf(CL_LOG_SEV_ERROR, "Failure opening event channel [0x%x] at %ld", rc, time(0L));
            errorExit(rc);
        }
        
        rc = saEvtEventSubscribe(evtChannelHandle, NULL, 1);
        if (rc != SA_AIS_OK)
        {
            clprintf(CL_LOG_SEV_ERROR, "Failed to subscribe to event channel [0x%x]",rc);
            errorExit(rc);
        }
  

Within the above code we open the channel synchronously. We pass the handle we got back from saEvtInitialize, the channel name we defined previously, flags that indicate this process is subscribing to the channel and it's a global channel, and that the channel should be created if it's not already there, a timeout value of "forever", and the address of the location where the channel handle should be stored. Then, we subscribe to a specific event stream on the event channel. The EVENT_TYPE constant is defined in common/common.h as 5432. This value is used by the event publisher when it sends events. The constant 1 being passed simply identifies this specific subscription on this channel. This value will be passed to our event delivery callback function.

main.c
    static void 
    csa112Comp_appEventCallback(SaEvtSubscriptionIdT subscriptionId,
                                SaEvtEventHandleT eventHandle, 
                                SaSizeT eventDataSize)
    {
    
        SaAisErrorT     rc = SA_AIS_OK;
        static ClPtrT   resTest = 0;    
        clprintf(CL_LOG_SEV_INFO,"We've got an event to receive\n");

        if (resTest != 0)
        {
            clHeapFree((char *)resTest);
            resTest = 0;
        }
        resTest = clHeapAllocate(eventDataSize + 1);

        if (resTest == 0)
        {
            clprintf(CL_LOG_SEV_ERROR, "Failed to allocate space for event");
            return;
        }
        rc = saEvtEventDataGet(eventHandle, resTest, &eventDataSize);

        if (rc!= SA_AIS_OK)
        {
            clprintf(CL_LOG_SEV_ERROR, "Failed to get event data [0x%x]",rc);
            return;
        }

        *(((char *)resTest) + eventDataSize) = 0;
        clprintf(CL_LOG_SEV_INFO,"received event: %s\n", (char *)resTest);
    }
  

The event delivery callback function is named csa112Comp_appEventCallback. It checks whether our incoming data buffer needs to be deallocated. If there is a buffer, it deallocates it and then allocates enough data to receive the incoming event data. Then, we extract the data from the event into the newly allocated buffer using clEventDataGet. Finally, we print the event data we received using clprintf which is another member of Clovis' OS Abstraction Layer. As its name and usage suggest, it is the OSAL replacement for printf.

Note:

Before building the project,copy the common directory which can be found under <eval_dir>/src/app to the working area

# cp -r <eval_dir>/src/app/common  .

[edit] How to Run csa112 and What to Observe

  1. Start example csa212 in the same manner that we have started previous examples, with the SAFplus Platform Console.(Unlock csa212SGI0 instead of csa112SGI0 to run csa212).
     # cd /root/asp/bin
     # ./asp_console
    
    
    cli[Test]-> setc 1
    cli[Test:SCNodeI0]-> setc cpm
    cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa212SGI0
    

    Looking at the log file for this example you should see the following.

    /root/asp/var/log/csa212CompI3Log.latest
      Fri Oct  1 13:14:16.935 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00001 :   INFO) Component [csa212CompI3] : PID [10366]. Initializing
    
      Fri Oct  1 13:14:16.935 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00002 :   INFO)    IOC Address             : 0x4
    
      Fri Oct  1 13:14:16.935 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00003 :   INFO)    IOC Port                : 0x80
    
      Fri Oct  1 13:15:31.389 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00004 :   INFO) Component [csa212CompI3] : PID [10366]. CSI Set Received
    
    
    
  2. Now unlock the application with:
    cli[Test:SCNodeI0:CPM]-> amsUnlock sg csa212SGI0
    

    At this point you should see the following in the log.

    /root/asp/var/log/csa212CompI3Log.latest
     Fri Oct  1 13:15:31.389 2010 (PayloadNodeI1.10366 : csa212CompEO.---.---.00012 :   INFO) csa212: ACTIVE state requested; activating service
    
      
    

    Thats all there is to this example. What you are looking at in the log is the output of our event listener. It doesn't appear very interesting because we have not yet written an event publisher that will give the program something to output. We'll do that in the next example (csa213).

  3. At this point we can shut down our example in the usual fashion.
    cli[Test:SCNodeI0:CPM]-> amsLockAssignment sg csa212SGI0
    cli[Test:SCNodeI0:CPM]-> amsLockInstantiation sg csa212SGI0
    cli[Test:SCNodeI0:CPM]-> end
    cli[Test:SCNodeI0]-> end
    cli[Test]-> bye
    

OpenClovis Note.pngWhen running model csa212 you will not see the output described for the the amsLockAssignment and amsUnlock commands.

[edit] Summary and References

We've seen how to create a basic event subscriber application using Clovis' event manager library. For further reading check the Clovis SAFplus Platform API reference guide, specifically the section on the event manager. Also, the header file: clEventExtApi.h should be helpful.