ClRcT clNodeCacheLeaderIocSend(ClIocNodeAddressT currentLeader, ClIocAddressT *dstAddr)
{
    ClRcT rc = CL_OK;
    ClIocSendOptionT sendOption = {CL_IOC_HIGH_PRIORITY,0,0,CL_IOC_PERSISTENT_MSG,200 };
    ClIocPhysicalAddressT compAddr = { CL_IOC_BROADCAST_ADDRESS,  CL_IOC_CPM_PORT };
    ClTimerTimeOutT delay = {  0,  200 };
    ClUint32T i = 0;
    ClBufferHandleT message = 0;
    ClEoExecutionObjT *eoObj = NULL;
    ClIocNotificationT notification;
    
    memset(&notification,0,sizeof(ClIocNotificationT));
    notification.protoVersion = htonl(CL_IOC_NOTIFICATION_VERSION);
    notification.id = (ClIocNotificationIdT) htonl(CL_IOC_NODE_ARRIVAL_NOTIFICATION);
    notification.nodeAddress.iocPhyAddress.nodeAddress = htonl(clIocLocalAddressGet());
    notification.nodeAddress.iocPhyAddress.portId = htonl(CL_IOC_GMS_PORT);

    clEoMyEoObjectGet(&eoObj);

    while(!eoObj && i++ <= 3)
    {
        clEoMyEoObjectGet(&eoObj);
        clOsalTaskDelay(delay);
    }

    if(!eoObj)
    {
        clLogWarning("CAP", "ARP", "Could not send current leader update since EO still uninitialized.");
        return CL_ERR_NOT_INITIALIZED;
    }

    clBufferCreate(&message);

    currentLeader = htonl(currentLeader);
    rc = clBufferNBytesWrite(message, (ClUint8T *)&notification, sizeof(ClIocNotificationT));
    rc |= clBufferNBytesWrite(message, (ClUint8T*)&currentLeader, sizeof(currentLeader));
    if (rc != CL_OK)
    {
        clLogError("CAP", "ARP", "clBufferNBytesWrite failed with rc = %#x", rc);
        clBufferDelete(&message);
        return rc;
    }

    rc = clIocSend(eoObj->commObj, message, CL_IOC_PORT_NOTIFICATION_PROTO, dstAddr, &sendOption);

    clBufferDelete(&message);

    return rc;

}
static ClRcT resendMsg(ClRmdRecordSendT  *rec,
                       ClRmdObjT         *pRmdObj,
                       ClEoExecutionObjT *pThis)
{
    ClRcT rc;
    ClIocSendOptionT sndOption = { 0 };

    CL_FUNC_ENTER();
    rec->recType.asyncRec.noOfRetry--;
    RMD_STAT_INC(pRmdObj->rmdStats.nResendRequests);

    sndOption.linkHandle = 0;
    sndOption.msgOption = CL_IOC_PERSISTENT_MSG;
    sndOption.timeout = rec->recType.asyncRec.timeout;
    sndOption.priority = rec->recType.asyncRec.priority;
    if (rec->flags & CL_RMD_CALL_IN_SESSION)
    {
        sndOption.sendType = CL_IOC_SESSION_BASED;
    }
    else
    {
        sndOption.sendType = CL_IOC_NO_SESSION;
    }


    clRmdDumpPkt("sending async req", rec->recType.asyncRec.sndMsgHdl);
    rc = clIocSend((pThis)->commObj,
                   rec->recType.asyncRec.sndMsgHdl,
                   CL_IOC_RMD_ASYNC_REQUEST_PROTO,
                   &rec->recType.asyncRec.destAddr,
                   &sndOption);
    if(rc != CL_OK)
    {
        RMD_STAT_INC(pRmdObj->rmdStats.nFailedResendRequests);
    }

    CL_FUNC_EXIT();
    return rc;
}
/* This function handles msg send request from clients */
static ClRcT clMsgIocRequestHandle(ClEoExecutionObjT *pThis,
                           ClBufferHandleT eoRecvMsg,
                           ClUint8T priority,
                           ClUint8T protoType,
                           ClUint32T length,
                           ClIocPhysicalAddressT srcAddr)
{
    ClRcT          rc = CL_OK;
    ClRcT          ret;
    ClUint32T      sendType;
    ClNameT        pDestination;
    SaMsgMessageT  pMessage;
    ClInt64T       sendTime;
    ClHandleT      senderHandle;
    ClInt64T       timeout;
    ClInt64T       msgId;
    ClUint8T       syncType;

    memset(&(pDestination), 0, sizeof(ClNameT));
    memset(&(pMessage), 0, sizeof(SaMsgMessageT));
    memset(&(senderHandle), 0, sizeof(ClHandleT));

    rc = clXdrUnmarshallClUint32T( eoRecvMsg,&(sendType));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClNameT( eoRecvMsg,&(pDestination));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallSaMsgMessageT_4_0_0( eoRecvMsg,&(pMessage));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClInt64T( eoRecvMsg,&(sendTime));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClHandleT( eoRecvMsg,&(senderHandle));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClInt64T( eoRecvMsg,&(timeout));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClInt64T( eoRecvMsg,&(msgId));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClUint8T( eoRecvMsg,&(syncType));
    if (CL_OK != rc)
    {
        goto out1;
    }

    /* Call remote function */
    ret = VDECL_VER(clMsgMessageReceived, 4, 0, 0)(sendType, &(pDestination), &(pMessage), sendTime, senderHandle, timeout);

    /* Prepare to send return value to the caller */
    ClIocSendOptionT sendOption = { 0 };
    ClBufferHandleT replyMsg = NULL;    
    ClUint8T replyProto = CL_IOC_SAF_MSG_REPLY_PROTO;

    /* Set Ioc send option */
    sendOption.msgOption = CL_IOC_PERSISTENT_MSG;
    sendOption.priority = CL_IOC_DEFAULT_PRIORITY;
    sendOption.timeout = 10000;

    /* Create buffer for input message */
    rc = clBufferCreate(&replyMsg);
    if (CL_OK != rc)
    {
        clDbgResourceLimitExceeded(clDbgMemoryResource, 0, ("Out of memory"));
        goto out1;
    }

    /* Marshall reply data */
    rc = clMsgReplyDataMarshall(replyMsg, ret, msgId, syncType);
    if (CL_OK != rc)
    {
        clDbgCodeError(rc, ("Cannot marshal reply data."));
        goto out2;
    }

    /* Send return value to the caller */
    rc = clIocSend(pThis->commObj, replyMsg, replyProto,(ClIocAddressT *) &srcAddr, &sendOption);
    if (CL_OK != CL_GET_ERROR_CODE(rc))
    {
        clLogError("MSG", "REPLY", "clIocSend(): error code [0x%x].", rc);
    }

out2:
    clBufferDelete(&replyMsg);
out1:
    return rc;
}