Code Examples.
More...
Code Examples.
The Event Service invovles communincation between pulishers and subscribers and this is accomplished over an event channel. Here we illustrate how a typical subscriber and publisher would look like emphasizing on the various API available with the Event Service.
The example is based on the event generation on a water mark hit in the Execution Object(EO). The event generated has attributes like the EO name, Library ID, Water Mark ID, Water Mark Type and Water Mark Value. The publisher will publish with some specific values for each of these event attributes. A subscriber can choose the particular attributes it is interested in say a particular EO with the name "COR". In our example we have take the NULL filter which ensures delivery of any event generated on water mark hit irrespective of the attributes to the subscriber.
Common defintions: The filter/pattern information should be shared between the subscriber and publisher. These are passed as byte streams to Event Service and it is the responsibility of application to ensure these are endian neurtal by using marshalling (XDR) or some such mechanism. This would make it possible to filter events across different platforms.
typedef enum{
CL_EO_LIB_ID_OSAL,
CL_EO_LIB_ID_MEM,
CL_EO_LIB_ID_HEAP,
CL_EO_LIB_ID_BUFFER,
CL_EO_LIB_ID_TIMER,
CL_EO_LIB_ID_IOC,
CL_EO_LIB_ID_RMD,
CL_EO_LIB_ID_EO,
CL_EO_LIB_ID_RES,
CL_EO_LIB_ID_POOL = CL_EO_LIB_ID_RES,
CL_EO_LIB_ID_CPM,
CL_EO_LIB_ID_MAX
} ClEoLibIdT;
Subscriber Side:
Typical Event Service would provide with three different handles. The user may want to group them up as below:
typedef struct ClSubsEventInfo
{
} ClSubsEventInfoT;
static ClSubsEventInfoT gSubsEventInfo;
If the application chooses to open the channel asynchronously then it needs to register a callback that shall be invoked on the creation of the channel. A typical callback would contain the subcription calls or event publish related calls. This has been illustrated in the publisher later.
void clSubsAsyncChannelOpenCb(ClInvocationT invocation,
{
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
"************* Async Channel Open Callback *************\n");
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
" Channel Handle : %p\n", (ClPtrT)channelHandle);
clOsalPrintf(
"*******************************************************\n");
{
goto failure;
}
CL_EVENT_DEFAULT_SUBS_FILTER, UNIQUE_SUBSCRIPTION_ID,
"User Specified Argument (cookie) for the event delivery callback");
{
goto failure;
}
failure:
return;
}
The subscriber is required to register a callback during the Event Library initialize which is to invoked when an event is delivered. For our example the callback is as follows:
{
ClPtrT pCookie = NULL;
ClPtrT pEventData = NULL;
ClUint8T *pEventPayload = NULL;
if (pEventData == NULL)
{
clOsalPrintf(
"Allocation for event data failed. rc[%#X]\n", rc);
goto failure;
}
{
goto failure;
}
pEventPayload = pEventData;
{
goto failure;
}
&retentionTime, &publisherName,
&publishTime, &eventId);
{
goto failure;
}
clOsalPrintf(
"-------------------------------------------------------\n");
clOsalPrintf(
"!!!!!!!!!!!!!!! Event Delivery Callback !!!!!!!!!!!!!!!\n");
clOsalPrintf(
"-------------------------------------------------------\n");
retentionTime);
CL_WM_HIGH_LIMIT) ? "HIGH" : "LOW");
clOsalPrintf(
"-------------------------------------------------------\n");
failure:
return;
}
Any component that wishes to be a subscriber has to initialize the Event Library with appropriate arguments. The following code snippet shows how Event Library is initialized and set for the subscription. Typically, the following function would reside in the clCompAppInitialize() registered in the clEoConfig structure of an EO. There could be multiple subscriptions depending on the requirement each with a unique subscription id (unique per initialization of Event Library).
static ClRcT clSubsEventLibrayInitialize(
void)
{
{
NULL,
clSubEoEventWaterMarkCb,
};
&version);
{
goto failure;
}
&gSubsEventInfo.channelHandle);
{
goto init_done;
}
CL_EVENT_DEFAULT_SUBS_FILTER, UNIQUE_SUBSCRIPTION_ID,
"User Specified Argument (cookie) for the event delivery callback");
{
goto channel_opened;
}
channel_opened:
init_done:
failure:
return rc;
}
The Event Library is typically finalized from within clCompAppTerminate() registered with the Component Manager (CPM). The following code snippet illustrates the steps involved in finalization of a subscriber.
static ClRcT clSubsEventLibrayFinalize(
void)
{
UNIQUE_SUBSCRIPTION_ID);
{
}
{
}
{
}
}
Publisher Side:
The Publisher would unlike a subscriber allocate events, set their attributes appropriately and publish them as illustrated below:
static ClRcT clPubsTriggerEvent(ClEoLibIdT libId, ClWaterMarkIdT wmId,
ClUint32T wmValue, ClEoWaterMarkFlagT wmFlag)
{
ClNameT publisherName = {
sizeof(CL_EVENT_PUBLISHER_NAME)-1,
CL_EVENT_PUBLISHER_NAME};
0,
patterns
};
&gPubsEventInfo.eventHandle);
{
goto failure;
}
patterns[1].
pPattern = (ClUint8T *)&libId;
patterns[2].
pPattern = (ClUint8T *)&wmId;
patterns[3].
pPattern = (ClUint8T *)&wmFlag;
patterns[4].
pPattern = (ClUint8T *)(&wmValue);
{
goto event_allocated;
}
"Event Payload passed in endian neutral way",
sizeof("Event Payload passed in endian neutral way.")-1,
&eventId);
{
goto event_allocated;
}
event_allocated:
{
}
failure:
return rc;
}
Like in the subscriber the publisher needs to do the Event Library Initialize as suggested before. In publisher we open the channel asynchronously, the callback for which is as below:
void clPubsAsyncChannelOpenCb(ClInvocationT invocation,
{
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
"************* Async Channel Open Callback *************\n");
clOsalPrintf(
"*******************************************************\n");
clOsalPrintf(
" Channel Handle : %p\n", (ClPtrT)channelHandle);
clOsalPrintf(
"*******************************************************\n");
{
clOsalPrintf(
"clEventChannelOpenAsync() failed [%#X]\n",rc);
goto failure;
}
gPubsEventInfo.channelHandle = channelHandle;
rc = clPubsTriggerEvent(CL_EO_LIB_ID_HEAP, CL_WM_HIGH, CL_WM_HIGH_LIMIT,
CL_WM_LOW_LIMIT);
{
goto channel_opened;
}
channel_opened:
failure:
return;
}
Much of the code is similar between the subscriber and publisher as can be seen below. The only difference being a publisher may optionally choose to be a subscriber also in which case it will need to register an event delivery callback. Note that event publish related API that appear in channel open callback above would appear right after the channel open if it were synchrounous. The event can be allocated each time it is published or it can be re-used with special care taken about protection in multi threaded environment when the event handle is shared between the threads.
typedef struct ClPubsEventInfo
{
} ClPubsEventInfoT;
static ClPubsEventInfoT gPubsEventInfo;
static ClRcT clPubsEventLibrayInitialize(
void)
{
{
clPubsAsyncChannelOpenCb,
NULL,
};
ClInvocationT invocation = UNIQUE_INVOCATION_ID;
&evtCallbacks, &version);
{
goto failure;
}
&channelName, evtFlags);
{
goto init_done;
}
init_done:
failure:
return rc;
}
static ClRcT clPubsEventLibrayFinalize(
void)
{
{
}
{
}
}