/* Finalize function for Event */
ClRcT corEventFinalize(void)
{

 /* Close all the event channels */
  clEventChannelClose(corEventChannelHandle);
  clEventChannelClose(cpmEventChannelHandle);
  clEventChannelClose(cpmEventNodeChannelHandle);

  return (clEventFinalize(corEventHandle));
}
static ClRcT clMsgEventFinalize(void)
{
    ClRcT rc;

    rc = clEventChannelClose(gCpmChHdl);
    if(rc != CL_OK)
        clLogError("EVT", "FIN", "Failed to close CPM event channel. error code [0x%x]", rc);

    rc = clEventFinalize(gMsgEvtHdl);
    if(rc != CL_OK)
        clLogError("EVT", "FIN", "Failed to finalize event library. error code [0x%x].", rc);

    return rc;
}
static ClRcT clMsgEventInitialize(void)
{
    ClRcT rc, retCode;
    ClVersionT version = CL_EVENT_VERSION;
    ClEventCallbacksT msgEvtCallbacks = { NULL, clMsgEventCallbackFunc };

    ClNameT cpmEvtCh = {0};
    ClEventChannelOpenFlagsT cpmChOpenFlags = CL_EVENT_CHANNEL_SUBSCRIBER | CL_EVENT_GLOBAL_CHANNEL;

    ClUint32T nodeDepPattern = htonl(CL_CPM_NODE_DEPART_PATTERN);
    ClEventFilterT nodeDepFilter[] = {{CL_EVENT_EXACT_FILTER, {0, (ClSizeT)sizeof(nodeDepPattern), (ClUint8T*)&nodeDepPattern}}};
    ClEventFilterArrayT nodeDepFltArray = {sizeof(nodeDepFilter)/sizeof(nodeDepFilter[0]), nodeDepFilter};

    rc = clEventInitialize(&gMsgEvtHdl, &msgEvtCallbacks, &version);
    if(rc != CL_OK)
    {
        clLogError("EVT", "INI", "Failed to initialize the event client. error code [0x%x].", rc);
        goto error_out;
    }

    clNameSet(&cpmEvtCh, CL_CPM_NODE_EVENT_CHANNEL_NAME);

    rc = clEventChannelOpen(gMsgEvtHdl, &cpmEvtCh, cpmChOpenFlags, SA_TIME_MAX, &gCpmChHdl);
    if(rc != CL_OK)
    {
        clLogError("EVT", "INI", "Failed to open event channel. error code [0x%x].", rc);
        goto error_out_1;
    }

    rc = clEventSubscribe(gCpmChHdl, &nodeDepFltArray, 0, NULL);
    if(rc != CL_OK)
    {
        clLogError("EVT", "INI", "Failed to subscribe for node departure event. error code [0x%x].", rc);
        goto error_out_2;
    }

    goto out;

error_out_2:
    retCode = clEventChannelClose(gCpmChHdl);
    if(retCode != CL_OK)
        clLogError("EVT", "INI", "Failed to close CPM event channel. error code [0x%x].", retCode);
error_out_1:
    retCode = clEventFinalize(gMsgEvtHdl);
    if(retCode != CL_OK)
        clLogError("EVT", "INI", "Failed to finalize event library. error code [0x%x].", retCode);
error_out:
out:
    return rc;
}
static ClRcT clSubsEventLibrayInitialize(void)
{
    ClRcT rc = CL_OK;

    ClVersionT version = CL_EVENT_VERSION;    
    ClNameT channelName = {sizeof(CL_EO_EVENT_CHANNEL_NAME)-1, CL_EO_EVENT_CHANNEL_NAME};

    const ClEventCallbacksT evtCallbacks = 
    {
        NULL, // clSubsAsyncChannelOpenCb for Async Channel Open
        clSubEoEventWaterMarkCb,  // Event Delivery Callback
    };
    ClEventChannelOpenFlagsT evtFlags = CL_EVENT_CHANNEL_SUBSCRIBER | CL_EVENT_LOCAL_CHANNEL;

    rc = clEventInitialize(&gSubsEventInfo.initHandle, &evtCallbacks, &version);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventInitialize() failed [%#X]\n",rc);
        goto failure;
    }

    rc = clEventChannelOpen(gSubsEventInfo.initHandle, &channelName, 
            evtFlags, CL_RMD_DEFAULT_TIMEOUT, 
            &gSubsEventInfo.channelHandle);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventChannelOpen() failed [%#X]\n",rc);
        goto init_done;
    }

    rc = clEventSubscribe(gSubsEventInfo.channelHandle, CL_EVENT_DEFAULT_SUBS_FILTER, UNIQUE_SUBSCRIPTION_ID, 
            "User Specified Argument (cookie) for the event delivery callback");
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventSubscribe() failed [%#X]\n",rc);
        goto channel_opened;
    }

    return CL_OK;

channel_opened:
    clEventChannelClose(gSubsEventInfo.channelHandle);

init_done:
    clEventFinalize(gSubsEventInfo.initHandle);

failure:
    return rc;
}
static ClRcT clPubsEventLibrayFinalize(void)
{
    ClRcT rc = CL_OK;

    rc = clEventChannelClose(gPubsEventInfo.channelHandle);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventChannelClose() failed [%#X]\n",rc);
    }

    rc = clEventFinalize(gPubsEventInfo.initHandle);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventFinalize() failed [%#X]\n",rc);
    }

    return CL_OK;
}
void clPubsAsyncChannelOpenCb(ClInvocationT invocation,
        ClEventChannelHandleT channelHandle, ClRcT retCode)
{
    ClRcT rc = CL_OK;

    clOsalPrintf("*******************************************************\n");
    clOsalPrintf("************* Async Channel Open Callback *************\n");
    clOsalPrintf("*******************************************************\n");
    clOsalPrintf("             Invocation        : %#X\n", invocation);
    clOsalPrintf("             Channel Handle    : %#llX\n", channelHandle);
    clOsalPrintf("             API Return Code   : %#X\n", retCode);
    clOsalPrintf("*******************************************************\n");

    /*
     * Check if the Channel Open Asyn was successful
     */
    if(CL_OK != retCode)
    {
        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);
    if(CL_OK != rc)
    {
        clOsalPrintf("Publish trigger failed [%#X]\n",rc);
        goto channel_opened;
    }

channel_opened:
    clEventChannelClose(gPubsEventInfo.channelHandle);

failure:
    return;
}
static ClRcT clSubsEventLibrayFinalize(void)
{
    ClRcT rc = CL_OK;

    rc = clEventUnsubscribe(gSubsEventInfo.channelHandle, UNIQUE_SUBSCRIPTION_ID);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventUnsubscribe() failed [%#X]\n",rc);
    }

    rc = clEventChannelClose(gSubsEventInfo.channelHandle);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventChannelClose() failed [%#X]\n",rc);
    }

    rc = clEventFinalize(gSubsEventInfo.initHandle);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventFinalize() failed [%#X]\n",rc);
    }

    return CL_OK;
}