ClRcT clRmdPrivateDataGet(void **data)
{
    ClOsalTaskDataT *pThreadData = (ClOsalTaskDataT *) data;
    if (!data)
    {
        return CL_RMD_RC(CL_ERR_NULL_POINTER);
    }
    return clOsalTaskDataGet(clRmdPrivateDataKey, pThreadData);
}
ClRcT clDebugResponseDefer(ClRmdResponseContextHandleT *pResponseHandle, ClBufferHandleT *pOutMsgHandle)
{
    ClDebugDeferContextT *deferContext = NULL;
    ClRcT rc;
    ClEoExecutionObjT *pEoObj = NULL;
    ClDebugObjT *pDebugObj = NULL;

    if(!pResponseHandle)
        return CL_DEBUG_RC(CL_ERR_INVALID_PARAMETER);

    rc = clEoMyEoObjectGet(&pEoObj);
    if (CL_OK != rc)
    {
        return rc;
    }

    rc = clEoPrivateDataGet( pEoObj, CL_EO_DEBUG_OBJECT_COOKIE_ID,
                             (void**) &pDebugObj);
    if (CL_OK != rc)
    {
        return rc;
    }
    
    rc = clOsalTaskDataGet(pDebugObj->debugTaskKey, (ClOsalTaskDataT*)&deferContext);
    if(rc != CL_OK || !deferContext)
    {
        clLogError("DEFER", "CLI", "Task data get failed on the debug defer context");
        return rc;
    }
    
    rc = clRmdResponseDefer(pResponseHandle);
    if(rc != CL_OK)
    {
        return rc;
    }
    deferContext->defer = CL_TRUE;
    if(pOutMsgHandle)
        *pOutMsgHandle = deferContext->outMsgHdl;

    return rc;
}
static void clGmsClusterTrackCallbackWrapper (
        CL_IN const ClGmsClusterNotificationBufferT* const notificationBuffer,
        CL_IN const ClUint32T             numberOfMembers,
        CL_IN const ClRcT                 rc)
{
    ClRcT                          error = CL_OK;
    ClGmsHandleT localHandle = CL_HANDLE_INVALID_VALUE;
    ClGmsHandleT *pGmsHandle = NULL;
    SaClmClusterNotificationBufferT *safbuf = NULL;
    SaClmInstanceT      *clmInstance = NULL;
    ClUint32T                       index = 0;
    SaClmClusterTrackDataT          *callbackArg;

    /*
     * Get the handle context in which this callback is invoked,
     * by using thread specific data.
     */
    error = clOsalTaskDataGet(clGmsPrivateDataKey, (ClOsalTaskDataT*)&pGmsHandle);
    if (error != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "clOsalTaskDataGet failed with error 0x%x\n",error);
    }
    localHandle = *pGmsHandle;

    /* Handle checkout */
    error = clHandleCheckout(databaseHandle, localHandle, (void**)&clmInstance);
    if (error != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "localHandle checkout failed with error 0x%x\n",error);
        return;
    }

    /* Convert the notification gotten from GMS into SAF notification */
    safbuf = (SaClmClusterNotificationBufferT*) clHeapAllocate(sizeof(SaClmClusterNotificationBufferT));
    if (safbuf == NULL)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "Cluster Track Callback failed due to no memory");
        goto error_return;
    }

    safbuf->viewNumber = notificationBuffer->viewNumber;
    safbuf->numberOfItems = notificationBuffer->numberOfItems;
    if( safbuf->numberOfItems != 0x0 )
    {
        safbuf->notification = (SaClmClusterNotificationT*)
                               clHeapAllocate(
                                       (safbuf->numberOfItems)
                                       *(sizeof(SaClmClusterNotificationT)));
        if (safbuf->notification == NULL)
        {
            clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                       "Cluster Track Callback failed due to no memory");
            clHeapFree(safbuf);
            goto error_return;
        }

        for (index = 0; index < safbuf->numberOfItems; index++)
        {
            (safbuf->notification[index]).clusterChange =
                (SaClmClusterChangesT) notificationBuffer->notification[index].clusterChange;

            (safbuf->notification[index]).clusterNode.nodeId =
                notificationBuffer->notification[index].clusterNode.nodeId;

            (safbuf->notification[index]).clusterNode.member =
                (SaBoolT) notificationBuffer->notification[index].clusterNode.memberActive;

            safbuf->notification[index].clusterNode.bootTimestamp =
                notificationBuffer->notification[index].clusterNode.bootTimestamp;

            safbuf->notification[index].clusterNode.initialViewNumber =
                notificationBuffer->notification[index].clusterNode.initialViewNumber;

            /* Copy the node name */
            memcpy(&safbuf->notification[index].clusterNode.nodeName,
                   &notificationBuffer->notification[index].clusterNode.nodeName,
                   sizeof(SaNameT));

            /* copy the node ipaddress */
            memcpy(&safbuf->notification[index].clusterNode.nodeAddress,
                   &notificationBuffer->notification[index].clusterNode.nodeIpAddress,
                   sizeof(SaClmNodeAddressT));
        }
    }

    callbackArg = (SaClmClusterTrackDataT*)clHeapAllocate(sizeof(SaClmClusterTrackDataT));
    if (callbackArg == NULL)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "Cluster track callback failed due to no memory");
        clHeapFree(safbuf->notification);
        clHeapFree(safbuf);
        goto error_return;
    }

    callbackArg->notificationBuffer = safbuf;
    callbackArg->numberOfMembers = numberOfMembers;
    callbackArg->rc = _aspErrToAisErr(rc);

    error = clDispatchCbEnqueue(clmInstance->dispatchHandle,
                                CL_GMS_CLIENT_CLUSTER_TRACK_CALLBACK,
                                (void*)callbackArg);
    if (error != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "clDispatchCbEnqueue failed with rc 0x%x",error);
    }

error_return:
    if ((clHandleCheckin(databaseHandle, localHandle)) != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "clHandleCheckin failed");
    }

    return;
}
static void clGmsClusterMemberGetCallbackWrapper (
        CL_IN const ClInvocationT         invocation,
        CL_IN const ClGmsClusterMemberT* const clusterMember,
        CL_IN const ClRcT                 rc)
{
    SaClmClusterNodeT *safNode = NULL;
    ClRcT              error = CL_OK;
    ClGmsHandleT localHandle = CL_HANDLE_INVALID_VALUE;
    ClGmsHandleT *pGmsHandle = NULL;
    SaClmClusterNodeGetDataT   *callbackArg = NULL;
    SaClmInstanceT      *clmInstance = NULL;
    
    /* 
     * Get the handle context in which this callback is invoked,
     * by using thread specific data.
     */
    error = clOsalTaskDataGet(clGmsPrivateDataKey, (ClOsalTaskDataT*)&pGmsHandle);
    if (error != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "clOsalTaskDataGet failed with rc 0x%x\n",error);
    }
    localHandle = *pGmsHandle;

    /* Handle checkout */
    error = clHandleCheckout(databaseHandle, localHandle, (void**)&clmInstance);
    if (error != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "localHandle checkout failed with rc 0x%x\n",error);
        return;
    }

    if ((rc == CL_OK) && (clusterMember != (const void*)NULL))
    {
        /*Allocate memory for safNode*/
        safNode = (SaClmClusterNodeT*) clHeapAllocate(sizeof(SaClmClusterNodeT));
        if (safNode == NULL)
        {
            clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                       "MemberGet Callback invocation faile due to no memory");
            goto error_exit;
        }
        else
        {
            memset (safNode, 0, sizeof(SaClmClusterNodeT));

            /*Get the values of clusterMember into safNode*/
            safNode->nodeId = clusterMember->nodeId;

            safNode->nodeAddress.family = (SaClmNodeAddressFamilyT)clusterMember->nodeIpAddress.family;
            safNode->nodeAddress.length = clusterMember->nodeIpAddress.length;
            memcpy(&safNode->nodeAddress.value,
                    &clusterMember->nodeIpAddress.value,sizeof(SaUint8T)*SA_CLM_MAX_ADDRESS_LENGTH);

            safNode->nodeName.length = clusterMember->nodeName.length;
            memcpy(&safNode->nodeName.value,&clusterMember->nodeName.value,sizeof(SaUint8T)*SA_MAX_NAME_LENGTH);

            safNode->member = (SaBoolT) clusterMember->memberActive;
            safNode->bootTimestamp = clusterMember->bootTimestamp;
            safNode->initialViewNumber = clusterMember->initialViewNumber;
        }
    }

    callbackArg = (SaClmClusterNodeGetDataT*)clHeapAllocate(sizeof(SaClmClusterNodeGetDataT));
    if (callbackArg == NULL)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "MemberGet Callback invocation faile due to no memory");
        if (safNode != NULL)
        {
            clHeapFree(safNode);
        }
        goto error_exit;
    }
    callbackArg->invocation = invocation;
    callbackArg->clusterNode = safNode;
    callbackArg->rc = _aspErrToAisErr(rc);
    
    error = clDispatchCbEnqueue(clmInstance->dispatchHandle,
                                CL_GMS_CLIENT_CLUSTER_MEMBER_GET_CALLBACK,
                                (void*)callbackArg);
    if (error != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "clDispatchCbEnqueue failed with rc 0x%x",error);
    }

error_exit:
    if ((clHandleCheckin(databaseHandle, localHandle)) != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_CALLBACK,
                   "clHandleCheckin failed");
    }

    return;
}