static ClRcT
clLogMasterFileEntryRecover(ClLogMasterEoDataT      *pMasterEoEntry,
                            ClCkptIOVectorElementT  *pIoVector,
                            ClUint32T               *pErrIndex)
{
    ClRcT                rc            = CL_OK;
    ClBufferHandleT      hFileEntryBuf = CL_HANDLE_INVALID_VALUE;
    ClVersionT version = {0};

    CL_LOG_DEBUG_TRACE(("Enter: size %lld", pIoVector->readSize));

    rc = clBufferCreate(&hFileEntryBuf);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clBufferCreate(): rc[0x %x]", rc));
        return rc;
    }

    rc = clBufferNBytesWrite(hFileEntryBuf, (ClUint8T*) pIoVector->dataBuffer, pIoVector->readSize);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clBufferNBytesWrite(): rc[0x %x]", rc));
        CL_LOG_CLEANUP(clBufferDelete(&hFileEntryBuf), CL_OK);
        return rc;
    }

    rc = clXdrUnmarshallClVersionT(hFileEntryBuf, &version);

    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrUnmarshallClVersionT(): rc[%#x]", rc));
        CL_LOG_CLEANUP(clBufferDelete(&hFileEntryBuf), CL_OK);
        return rc;
    }

    switch(CL_VERSION_CODE(version.releaseCode, version.majorVersion, version.minorVersion))
    {
    case CL_VERSION_CODE(CL_RELEASE_VERSION, CL_MAJOR_VERSION, CL_MINOR_VERSION):
    {
        rc = fileEntryRecoverBaseVersion(pMasterEoEntry, hFileEntryBuf);
    }
    break;
    default:
        rc = CL_LOG_RC(CL_ERR_VERSION_MISMATCH);
        clLogError("FILE", "RECOVER", "Version [%d.%d.%d] unsupported",
                   version.releaseCode, version.majorVersion, version.minorVersion);
        break;
    }

    CL_LOG_CLEANUP(clBufferDelete(&hFileEntryBuf), CL_OK);

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
static void gms_confchg_fn (
	enum totem_configuration_type configuration_type,
	unsigned int *member_list, int member_list_entries,
	unsigned int *left_list, int left_list_entries,
	unsigned int *joined_list, int joined_list_entries,
	struct memb_ring_id *ring_id)
{
	int     i = 0;
    char    iface_string[256 * INTERFACE_MAX] = "";
    ClRcT   rc = CL_OK;
    ClUint32T minVersion = CL_VERSION_CODE(5, 0, 0);

	clLog (NOTICE,OPN,AIS, "GMS CONFIGURATION CHANGE");
	clLog (NOTICE,OPN,AIS, "GMS Configuration:");
	for (i = 0; i < member_list_entries; i++) {
		clLog (NOTICE,OPN,AIS, "\t%s", totempg_ifaces_print (member_list[i]));
	}
	clLog(NOTICE,OPN,AIS, "Members Left:");
	for (i = 0; i < left_list_entries; i++) {
		clLog (NOTICE,OPN,AIS, "\t%s", totempg_ifaces_print (left_list[i]));
	}

	clLog(NOTICE,OPN,AIS, "Members Joined:");
	for (i = 0; i < joined_list_entries; i++) {
		clLog (NOTICE,OPN,AIS, "\t%s", totempg_ifaces_print (joined_list[i]));
	}
   
    clNodeCacheMinVersionGet(NULL, &minVersion);
    if(minVersion >= CL_VERSION_CODE(5, 0, 0) && gAspNativeLeaderElection)
    {
        clLog(DBG, OPN, AIS, "Skipping node leave processing since node cache is used to sync cluster views");
        return ;
    }

    for (i = 0; i < left_list_entries; i++) 
    {
        /* Call Cluster Leave for the nodes which are left.
         * To do that we need to translate IP address to gms nodeID
         * NOTE: Currently we are getting the this left_list[i] to
         * the ip address mapping from the get_interface_ip function.
         * This is not quite reliable and may get into issues when using
         * multiple interfaces...
         */
        strncpy(iface_string, get_node_ip(left_list[i]), (256*INTERFACE_MAX)-1);
        clLog(DBG,OPN,AIS, "Invoking cluster leave for node with IP %s",iface_string);
        rc = _clGmsEngineClusterLeaveWrapper(CL_GMS_CLUSTER_ID, iface_string);
    }

    return;
}
ClRcT
clLogMasterCompTableStateRecover(ClLogMasterEoDataT  *pMasterEoEntry,
                                 ClUint8T            *pBuffer,
                                 ClUint32T           dataSize)
{
    ClRcT            rc       = CL_OK;
    ClBufferHandleT  msg      = CL_HANDLE_INVALID_VALUE;
    ClUint32T versionCode = 0;

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clBufferCreate(&msg);
    if(CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clBufferCreate(): rc[0x %x]", rc));
        return rc;
    }
    rc = clBufferNBytesWrite(msg, pBuffer, dataSize);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clBufferNBytesWrite(): rc[0x %x]", rc));
        CL_LOG_CLEANUP(clBufferDelete(&msg), CL_OK);
        return rc;
    }

    rc = clXdrUnmarshallClUint32T(msg, &versionCode);
    if( CL_OK != rc)
    {
        CL_LOG_DEBUG_ERROR(("clXdrUnmarshallClUint32T(): rc[%#x]", rc));
        CL_LOG_CLEANUP(clBufferDelete(&msg), CL_OK);
        return rc;
    }
    switch(versionCode)
    {

    case CL_VERSION_CODE(CL_RELEASE_VERSION, CL_MAJOR_VERSION, CL_MINOR_VERSION):
    {
        rc = compTableStateRecoverBaseVersion(msg);
    }
    break;

    default:
        clLogError("COMP", "TBL-RECOVER", "Version [%d.%d.%d] is not supported",
                   CL_VERSION_RELEASE(versionCode), CL_VERSION_MAJOR(versionCode),
                   CL_VERSION_MINOR(versionCode));
        rc = CL_LOG_RC(CL_ERR_VERSION_MISMATCH);
    }

    clBufferDelete(&msg);

    return rc;
}
ClRcT
clAmsMgmtCCBBatchCommit(CL_IN ClAmsMgmtCCBBatchHandleT batchHandle)
{
    ClRcT  rc = CL_OK;
    ClAmsMgmtCCBBatchT *batch = (ClAmsMgmtCCBBatchT*)batchHandle;
    ClUint32T saveOffset = 0;

    if(!batch)
        return CL_AMS_RC(CL_ERR_INVALID_PARAMETER);
    if(!batch->buffer)
        return CL_AMS_RC(CL_ERR_NOT_INITIALIZED);

    if(!batch->items)
    {
        clLogWarning("CCB", "COMMIT", "Batch commit tried with no items");
        return CL_OK;
    }
    rc = clBufferWriteOffsetGet(batch->buffer, &saveOffset);
    if(rc != CL_OK)
        goto out;

    rc = clBufferWriteOffsetSet(batch->buffer, batch->itemsOffset, CL_BUFFER_SEEK_SET);
    if(rc != CL_OK)
        goto out;

    /*
     * Update the item count
     */
    rc = clXdrMarshallClUint32T(&batch->items, batch->buffer, 0);
    if(rc != CL_OK)
        goto out;
    
    rc = clBufferWriteOffsetSet(batch->buffer, saveOffset, CL_BUFFER_SEEK_SET);
    if(rc != CL_OK)
        goto out;

    rc = cl_ams_ccb_batch_rmd(CL_AMS_MGMT_CCB_BATCH_COMMIT, batch->buffer, CL_VERSION_CODE(5, 1, 0));
    if(rc != CL_OK)
        goto out;

    /*
     * Clear the buffer for reuse
     */
    rc = amsMgmtCCBBatchBufferInitialize(batch);

    out:
    return rc;
}
static ClRcT nodeCacheMemberGetFast(ClIocNodeAddressT node, ClNodeCacheMemberT *pMember,
                                    ClBoolT compat)
{
    ClRcT rc = CL_OK;

    if(!node || node >= CL_IOC_MAX_NODES || !pMember)
        return CL_ERR_INVALID_PARAMETER;

    if(!gpClNodeCache)
        return CL_ERR_NOT_INITIALIZED;

    if(compat)
    {
        ClUint32T minVersion = CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->minVersion;
        if(minVersion && minVersion < CL_VERSION_CODE(5, 0, 0))
        {
            return CL_ERR_NOT_SUPPORTED;
        }
        if(!gClAspNativeLeaderElection)
        {
            return CL_ERR_NOT_SUPPORTED;
        }
    }

    if(CL_NODE_MAP_TEST(CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->nodeMap, node))
    {
        ClNodeCacheEntryT *entry = &CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[node];
        pMember->address = node;
        pMember->name[0] = 0;
        strncat(pMember->name, entry->nodeName, sizeof(entry->nodeName)-1);
        pMember->version = entry->version;
        pMember->capability = entry->capability;
    }
    else
    {
        rc = CL_ERR_NOT_EXIST;
    }
    return rc;
}
ClRcT
clLogMasterCompDataCheckpoint(ClLogMasterEoDataT   *pMasterEoEntry,
                              ClLogCompDataT       *pCompData)
{
    ClRcT                   rc           = CL_OK;
    ClCkptIOVectorElementT  ioVector[3]  = {{{0}}};
    ClUint32T               numComps     = pMasterEoEntry->numComps;
    ClUint32T               compCnt      = 0;
    ClUint32T               dataSize     = 0;
    ClUint8T                *pDataBuffer = NULL;
    ClUint32T               dataOffset   = 0;
    ClUint32T               errIdx       = 0;
    ClUint32T               versionCode = 0;

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogMasterCompData2BufferGet(pCompData, &pDataBuffer, &dataSize);
    if( CL_OK != rc )
    {
        return rc;
    }

    versionCode = CL_VERSION_CODE(CL_RELEASE_VERSION, CL_MAJOR_VERSION, CL_MINOR_VERSION);
    versionCode = htonl(versionCode);

    ++numComps;
    compCnt                = htonl(numComps);

    ioVector[0].sectionId = gLogMasterCompDataSectionId;
    ioVector[0].dataBuffer = (ClUint8T*)&versionCode;
    ioVector[0].dataSize = sizeof(versionCode);
    ioVector[0].readSize = 0;
    ioVector[0].dataOffset = 0;

    ioVector[1].sectionId  = gLogMasterCompDataSectionId;
    ioVector[1].dataBuffer = (ClUint8T *) &compCnt;
    ioVector[1].dataSize   = sizeof(numComps);
    ioVector[1].readSize   = 0;
    ioVector[1].dataOffset = sizeof(versionCode);

    ioVector[2].sectionId  = gLogMasterCompDataSectionId;
    dataOffset = (pMasterEoEntry->numComps * CL_LOG_COMP_SEC_OFFSET) +
                 sizeof(numComps) + sizeof(versionCode);
    ioVector[2].dataBuffer = pDataBuffer;
    ioVector[2].dataSize   = dataSize;
    ioVector[2].readSize   = 0;
    ioVector[2].dataOffset = dataOffset;

    rc = clCkptCheckpointWrite(pMasterEoEntry->hCkpt, ioVector, 3, &errIdx);
    if( (CL_OK != rc) && (CL_ERR_TRY_AGAIN != CL_GET_ERROR_CODE(rc)) )
    {
        CL_LOG_DEBUG_ERROR(("clkCptCheckpointWrite(): rc[0x %x]", rc));
        clHeapFree(pDataBuffer);
        return rc;
    }
    pMasterEoEntry->numComps = numComps;
    clHeapFree(pDataBuffer);

    CL_LOG_DEBUG_TRACE(("curr Comp Cnt: %d ", numComps));

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
ClRcT
clLogStreamOwnerGlobalCheckpoint(ClLogSOEoDataT         *pSoEoEntry,
                                 SaNameT                *pStreamName,
                                 SaNameT                *pStreamScopeNode,
                                 ClLogStreamOwnerDataT  *pStreamOwnerData)
{
    ClRcT                             rc                      = CL_OK;
    ClBufferHandleT                   msg                     = 
        CL_HANDLE_INVALID_VALUE;
    ClUint32T                         size                    = 0;
    ClAddrT                           pBuffer                 = NULL;
    ClCkptSectionIdT                  secId                   = {0};
    ClCkptSectionCreationAttributesT  secAttr                 = {0};
    ClBoolT                           createdSec              = CL_FALSE;
    ClUint32T                         prefixLen               = 0;
    ClUint32T                         versionCode             = 0;
    CL_LOG_DEBUG_TRACE(("Enter"));

    prefixLen   = strlen(soSecPrefix);
    secId.idLen = pStreamName->length + prefixLen; 
    secId.id    = (ClUint8T*)clHeapCalloc(secId.idLen, sizeof(ClCharT)); 
    if( NULL == secId.id )
    {
        CL_LOG_DEBUG_ERROR(("clHeapCalloc()"));
        return CL_LOG_RC(CL_ERR_NO_MEMORY);
    }    
    memcpy(secId.id, soSecPrefix, prefixLen);
    memcpy(secId.id + prefixLen, pStreamName->value,
           pStreamName->length); 
    if( CL_TRUE == pStreamOwnerData->isNewStream )
    {
        secAttr.sectionId      = &secId;
        secAttr.expirationTime = CL_TIME_END;
        rc = clCkptSectionCreate(pSoEoEntry->hCkpt, &secAttr, 
                                 NULL, 0);
        if( CL_OK != rc )
        {
            CL_LOG_DEBUG_ERROR(("clCkptSectionCreate(): rc[0x %x]", rc));
            clHeapFree(secId.id);
            return rc;
        }    
        pStreamOwnerData->isNewStream = CL_FALSE;
        createdSec = CL_TRUE;
    }    
    rc = clBufferCreate(&msg);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clBufferCreate(): rc[0x %x]", rc));
        if( CL_TRUE == createdSec )
        {
            CL_LOG_CLEANUP(clCkptSectionDelete(pSoEoEntry->hCkpt, &secId), 
                           CL_OK);
        }
        clHeapFree(secId.id);
        return rc;
    } 
    versionCode = CL_VERSION_CODE(CL_RELEASE_VERSION, CL_MAJOR_VERSION, CL_MINOR_VERSION);
    rc = clXdrMarshallClUint32T(&versionCode, msg, 0);
    if(CL_OK != rc)
    {
        CL_LOG_DEBUG_ERROR(("clXdrMarshallClVersionT() rc[%#x]", rc));
        CL_LOG_CLEANUP(clBufferDelete(&msg), CL_OK);
        if(CL_TRUE == createdSec)
        {
            CL_LOG_CLEANUP(clCkptSectionDelete(pSoEoEntry->hCkpt, &secId), CL_OK);
        }
        clHeapFree(secId.id);
        return rc;
    }

    rc = clLogStreamOwnerEntryPack(pStreamName, pStreamScopeNode, 
                                   pStreamOwnerData, msg);
    if( CL_OK != rc )
    {
        CL_LOG_CLEANUP(clBufferDelete(&msg), CL_OK);
        if( CL_TRUE == createdSec )
        {
            CL_LOG_CLEANUP(clCkptSectionDelete(pSoEoEntry->hCkpt, &secId), 
                           CL_OK);
        }
        clHeapFree(secId.id);
        return rc;
    }
    rc = clLogServerSerialiser(0, &pBuffer, &size, msg);
    if( CL_OK != rc )
    {
        CL_LOG_CLEANUP(clBufferDelete(&msg), CL_OK);
        if( CL_TRUE == createdSec )
        {
            CL_LOG_CLEANUP(clCkptSectionDelete(pSoEoEntry->hCkpt, &secId), 
                           CL_OK);
        }
        clHeapFree(secId.id);
        return rc;
    }    
    rc = clCkptSectionOverwrite(pSoEoEntry->hCkpt,
                                &secId,
                                pBuffer, size);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clCkptSectionOverwrite(): rc[0x %x]", rc));
        if( CL_TRUE == createdSec )
        {
            CL_LOG_CLEANUP(clCkptSectionDelete(pSoEoEntry->hCkpt, &secId), 
                           CL_OK);
        }
    }    
    CL_LOG_CLEANUP(clBufferDelete(&msg), CL_OK);
    clHeapFree(pBuffer);
    clHeapFree(secId.id);
   
    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
ClRcT
clLogStreamOwnerGlobalEntryRecover(ClLogSOEoDataT            *pSoEoEntry,
                                   ClCkptSectionDescriptorT  *pSecDescriptor)
{
    ClRcT                   rc     = CL_OK;
    ClCkptIOVectorElementT  ioVector       = {{0}};
    ClUint32T               errIndex       = 0;
    ClLogSvrCommonEoDataT   *pCommonEoData = NULL;
    ClUint32T               versionCode = 0;

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogStreamOwnerEoEntryGet(NULL, &pCommonEoData);
    if( CL_OK != rc )
    {
        return rc;
    }
    
    ioVector.sectionId  = pSecDescriptor->sectionId; 
    ioVector.dataBuffer = NULL;
    ioVector.dataSize   = 0;
    ioVector.readSize   = 0;
    ioVector.dataOffset = 0;
    rc = clCkptCheckpointRead(pSoEoEntry->hCkpt, &ioVector, 1, &errIndex);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clCkptCheckpointRead(): rc[0x %x]", rc));
        return rc;
    }

    if(ioVector.readSize <= sizeof(versionCode))
    {
        CL_LOG_DEBUG_ERROR(("Global stream recovery failed because of inconsistent ckpt "
                            "data of size [%lld]",
                            ioVector.readSize));
        clHeapFree(ioVector.dataBuffer);
        return CL_LOG_RC(CL_ERR_INVALID_STATE);
    }

    ioVector.readSize -= sizeof(versionCode);
    versionCode = ntohl(*(ClUint32T*)ioVector.dataBuffer);
    switch(versionCode)
    {
    case CL_VERSION_CODE(CL_RELEASE_VERSION, CL_MAJOR_VERSION, CL_MINOR_VERSION):
        {
            rc = clLogSOStreamEntryRecreate(0, 
                                            (ClAddrT)( (ClUint8T*)ioVector.dataBuffer + sizeof(versionCode)),
                                            ioVector.readSize,
                                            CL_HANDLE_INVALID_VALUE);
        }
        break;
    default:
        rc = CL_LOG_RC(CL_ERR_VERSION_MISMATCH);
        clLogError("GLOBAL", "RECOVER", "Version unsupported [%d.%d.%d]",
                   CL_VERSION_RELEASE(versionCode), CL_VERSION_MAJOR(versionCode),
                   CL_VERSION_MINOR(versionCode));
        break;
    }

    clHeapFree(ioVector.dataBuffer);

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}    
int clGmsSendMsg(ClGmsViewMemberT       *memberNodeInfo,
                 ClGmsGroupIdT           groupId, 
                 ClGmsMessageTypeT       msgType,
                 ClGmsMemberEjectReasonT ejectReason,
                 ClUint32T               dataSize,
                 ClPtrT                  dataPtr)
{
    mar_req_header_t        header = {0};
    struct VDECL(req_exec_gms_nodejoin) req_exec_gms_nodejoin = {{0}};
    struct iovec    req_exec_gms_iovec = {0};
    int             result = -1;
    ClRcT           rc = CL_OK;
    ClUint32T       clusterVersion = 0;
    ClBufferHandleT bufferHandle = 0;
    ClUint8T        *message = NULL;
    ClUint32T       length = 0;
    ClPtrT          temp = NULL;

    rc = clNodeCacheMinVersionGet(NULL, &clusterVersion);
    if(clusterVersion >= CL_VERSION_CODE(5, 0, 0) 
       && 
       clAspNativeLeaderElection())
    {
        clLog(DBG, OPN, AIS, 
              "Skipped sending msgtype [%d] since node cache is used to form the cluster view",
              msgType);
        return 0;
    }

    if (rc != CL_OK)
    {
        clLog(ERROR,OPN,AIS,
                "Error while getting version from the version cache. rc 0x%x",rc);

        curVer.releaseCode = CL_RELEASE_VERSION;
        curVer.majorVersion = CL_MAJOR_VERSION;
        curVer.minorVersion = CL_MINOR_VERSION;
    } 
    else 
    {
        curVer.releaseCode = CL_VERSION_RELEASE(clusterVersion);
        curVer.majorVersion = CL_VERSION_MAJOR(clusterVersion);
        curVer.minorVersion = CL_VERSION_MINOR(clusterVersion);
    }

    /* Get the version and send it */
    req_exec_gms_nodejoin.version.releaseCode = curVer.releaseCode;
    req_exec_gms_nodejoin.version.majorVersion = curVer.majorVersion;
    req_exec_gms_nodejoin.version.minorVersion = curVer.minorVersion;

    /* For now we send message without caring about version. Later on
     * we need to change it accordingly */
    
    switch(msgType)
    {
        case CL_GMS_CLUSTER_JOIN_MSG:
        case CL_GMS_CLUSTER_LEAVE_MSG:
        case CL_GMS_CLUSTER_EJECT_MSG:
            clLog(DBG,OPN,AIS,
                    "Sending cluster %s multicast message",
                    msgType == CL_GMS_CLUSTER_JOIN_MSG ? "join":
                    msgType == CL_GMS_CLUSTER_LEAVE_MSG ? "leave" : "eject");
            req_exec_gms_nodejoin.ejectReason = ejectReason;
            memcpy (&req_exec_gms_nodejoin.specificMessage.gmsClusterNode, &memberNodeInfo->clusterMember,
                    sizeof (ClGmsClusterMemberT));
            req_exec_gms_nodejoin.contextHandle = memberNodeInfo->contextHandle;
            break;
        case CL_GMS_GROUP_CREATE_MSG:
        case CL_GMS_GROUP_DESTROY_MSG:
        case CL_GMS_GROUP_JOIN_MSG:
        case CL_GMS_GROUP_LEAVE_MSG:
            clLog(DBG,OPN,AIS,
                    "Sending group %s multicast message",
                    msgType == CL_GMS_GROUP_CREATE_MSG ? "create" : 
                    msgType == CL_GMS_GROUP_DESTROY_MSG ? "destroy" :
                    msgType == CL_GMS_GROUP_JOIN_MSG ? "join" : "leave");
            memcpy (&req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode, 
                    &memberNodeInfo->groupMember,
                    sizeof (ClGmsGroupMemberT));
            memcpy (&req_exec_gms_nodejoin.specificMessage.groupMessage.groupData, 
                    &memberNodeInfo->groupData,
                    sizeof(ClGmsGroupInfoT));
            req_exec_gms_nodejoin.contextHandle = memberNodeInfo->contextHandle;
            break;
        case CL_GMS_COMP_DEATH:
            clLog(DBG,OPN,AIS,
                    "Sending comp death multicast message");
            memcpy (&req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode, 
                    &memberNodeInfo->groupMember,
                    sizeof (ClGmsGroupMemberT));
            req_exec_gms_nodejoin.contextHandle = memberNodeInfo->contextHandle;
            break;
        case CL_GMS_LEADER_ELECT_MSG:
            clLog(DBG,OPN,AIS,
                    "Sending leader elect multicast message");
            memcpy (&req_exec_gms_nodejoin.specificMessage.gmsClusterNode, &memberNodeInfo->clusterMember,
                    sizeof (ClGmsClusterMemberT));
            req_exec_gms_nodejoin.contextHandle = memberNodeInfo->contextHandle;
            break;
        case CL_GMS_SYNC_MESSAGE:
            clLog(DBG,OPN,AIS,
                    "Sending gms synch multicast message");
            req_exec_gms_nodejoin.dataPtr = dataPtr;
            break;
        case CL_GMS_GROUP_MCAST_MSG:
            memcpy (&req_exec_gms_nodejoin.specificMessage.mcastMessage.groupInfo.gmsGroupNode, 
                    &memberNodeInfo->groupMember,
                    sizeof (ClGmsGroupMemberT));
            memcpy (&req_exec_gms_nodejoin.specificMessage.mcastMessage.groupInfo.groupData,
                    &memberNodeInfo->groupData,
                    sizeof(ClGmsGroupInfoT));
            req_exec_gms_nodejoin.contextHandle = memberNodeInfo->contextHandle;
            req_exec_gms_nodejoin.specificMessage.mcastMessage.userDataSize = dataSize;
            req_exec_gms_nodejoin.dataPtr = dataPtr;
            break;
        default:
            clLog(DBG,OPN,AIS,
                    "Requested wrong message to be multicasted. Message type %d",
                    msgType);
            return CL_GMS_RC(CL_ERR_INVALID_PARAMETER);
    }

    req_exec_gms_nodejoin.gmsMessageType = msgType;
    req_exec_gms_nodejoin.gmsGroupId = groupId;

    /* Create a buffer handle and marshall the eliments */
    rc = clBufferCreate(&bufferHandle);
    if (rc != CL_OK)
    {
        clLogError(OPN,AIS,
                "Failed to create buffer while sending message on totem. rc 0x%x",rc);
        return rc;
    }

    rc = marshallReqExecGmsNodeJoin(&req_exec_gms_nodejoin,bufferHandle);
    if (rc != CL_OK)
    {
        clLogError(OPN,AIS,
                "Failed to marshall the data while sending message on totem. rc 0x%x",rc);
        goto buffer_delete_return;
    }

    rc = clBufferLengthGet(bufferHandle, &length);
    if (rc != CL_OK)
    {
        clLogError(OPN,AIS,
                "Failed to get buffer length. rc 0x%x",rc);
        goto buffer_delete_return;
    }

    rc = clBufferFlatten(bufferHandle, &message);
    if (rc != CL_OK)
    {
        clLogError(OPN,AIS,
                "clBufferFlatten failed with rc 0x%x",rc);
        goto buffer_delete_return;
    }

    header.id = SERVICE_ID_MAKE (GMS_SERVICE, MESSAGE_REQ_EXEC_GMS_NODEJOIN);
    header.size = length + sizeof(mar_req_header_t);

    /* We need to prepend the total message length in the beginning of the
     * message so that we can find the length while unmarshalling */
    temp = clHeapAllocate(header.size);
    if (temp == NULL)
    {
        clLogError(OPN,AIS, 
                "Failed to allocate memory while sending the message");
        goto buffer_delete_return;
    }

    memcpy(temp,&header, sizeof(mar_req_header_t));
    memcpy(temp+sizeof(mar_req_header_t), message, length);

    req_exec_gms_iovec.iov_base = temp;
    req_exec_gms_iovec.iov_len = length + sizeof(mar_req_header_t);

    result = totempg_groups_mcast_joined (openais_group_handle, &req_exec_gms_iovec, 1, TOTEMPG_AGREED);

    clLog(DBG,OPN,AIS,
            "Done with sending multicast message of type %d",msgType);

buffer_delete_return:
    if (message != NULL)
        clHeapFree(message);

    if (temp != NULL)
        clHeapFree(temp);

    clBufferDelete(&bufferHandle);
    return result;
}
static void gms_exec_message_handler (
                                      void *message,
                                      unsigned int nodeid)
{
    mar_req_header_t              header = {0};
    struct VDECL(req_exec_gms_nodejoin) req_exec_gms_nodejoin = {{0}};
    ClGmsViewNodeT               *node = NULL;
    ClRcT                         rc = CL_OK;
    ClGmsClusterMemberT           thisGmsClusterNode = {0};
    char                          nodeIp[256 * INTERFACE_MAX] = "";
    int                           isLocalMsg = 0;
    int                           verCode = 0;
    ClBufferHandleT               bufferHandle = NULL;

    /* Get the ip address string for the given nodeId */
    strncpy(nodeIp, get_node_ip(nodeid), (256 * INTERFACE_MAX)-1);
    if (strcmp(nodeIp, totemip_print(this_ip)) == 0)
    {
        isLocalMsg = 1;
    }

    /* Unmarshall the incoming message */
    rc = clBufferCreate(&bufferHandle);
    if (rc != CL_OK)
    {
        clLogError(OPN,AIS,
                   "Failed to create buffer while unmarshalling the received message. rc 0x%x",rc);
        return;
    }

    memcpy(&header, message, sizeof(mar_req_header_t));

    rc = clBufferNBytesWrite(bufferHandle, (ClUint8T *)message+sizeof(mar_req_header_t), header.size-sizeof(mar_req_header_t));
    if (rc != CL_OK)
    {
        clLogError(OPN,AIS,
                   "Failed to retrieve data from buffer. rc 0x%x",rc);
        goto out_delete;
    }

    rc = unmarshallReqExecGmsNodeJoin(bufferHandle, &req_exec_gms_nodejoin);
    if (rc != CL_OK)
    {
        clLogError(OPN,AIS,"Failed to unmarshall the data. rc 0x%x",rc);
        goto out_delete;
    }

    verCode = CL_VERSION_CODE(req_exec_gms_nodejoin.version.releaseCode, 
                              req_exec_gms_nodejoin.version.majorVersion,
                              req_exec_gms_nodejoin.version.minorVersion);
    clLog(DBG,OPN,AIS,
          "Received a %d message from version [%d.%d.%d].",req_exec_gms_nodejoin.gmsMessageType,
          req_exec_gms_nodejoin.version.releaseCode, req_exec_gms_nodejoin.version.majorVersion, 
          req_exec_gms_nodejoin.version.minorVersion);
    /* Verify version */
    if (verCode > CL_VERSION_CODE(curVer.releaseCode, curVer.majorVersion, curVer.minorVersion)) {
        /* I received a message from higher version and it dont know
         * how to decode it. So it discarding it. */
        clLog(NOTICE,OPN,AIS,
              "Version mismatch detected. Discarding the message ");
        goto out_delete;
    }

    // message type & message data
    clLog(DBG,OPN,AIS,"message type %d from groupId %d!\n", req_exec_gms_nodejoin.gmsMessageType, req_exec_gms_nodejoin.gmsGroupId);

    /* This message is from same version. So processing it */
    switch (req_exec_gms_nodejoin.gmsMessageType)
    {
    case CL_GMS_CLUSTER_JOIN_MSG:
        {
            ClUint32T minVersion = CL_VERSION_CODE(5, 0, 0);
            clLog(DBG,OPN,AIS,
                  "Received multicast message for cluster join from ioc node [%#x:%#x]",
                  req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.nodeAddress,
                  req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.portId);
            clNodeCacheMinVersionGet(NULL, &minVersion);
            if(minVersion >= CL_VERSION_CODE(5, 0, 0) && gAspNativeLeaderElection)
            {
                clLog(DBG, OPN, AIS,
                      "Skipping multicast join since node cache view is used to form the cluster ring");
                goto out_delete;
            }
            node = (ClGmsViewNodeT *) clHeapAllocate(sizeof(ClGmsViewNodeT));
            if (node == NULL)
            {
                clLog (ERROR,OPN,AIS, "clHeapAllocate failed");
                goto out_delete;
            }
            else {
                rc = clVersionVerify(
                                     &(gmsGlobalInfo.config.versionsSupported),
                                     &(req_exec_gms_nodejoin.specificMessage.gmsClusterNode.gmsVersion)
                                     );
                ringVersion.releaseCode =
                    req_exec_gms_nodejoin.specificMessage.gmsClusterNode.gmsVersion.releaseCode;
                ringVersion.majorVersion=
                    req_exec_gms_nodejoin.specificMessage.gmsClusterNode.gmsVersion.majorVersion;
                ringVersion.minorVersion=
                    req_exec_gms_nodejoin.specificMessage.gmsClusterNode.gmsVersion.minorVersion;
                if(rc != CL_OK)
                {
                    ringVersionCheckPassed = CL_FALSE;
                    /* copy the ring version */
                    clGmsCsLeave( &joinCs );
                    clLog (ERROR,OPN,AIS,
                           "Server Version Mismatch detected for this join message");
                    break;
                }

                _clGmsGetThisNodeInfo(&thisGmsClusterNode);
                if( thisGmsClusterNode.nodeId !=
                    req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeId)
                {
                    /* TODO This will never happen... */
                    clGmsCsLeave( &joinCs );
                }

                node->viewMember.clusterMember =
                    req_exec_gms_nodejoin.specificMessage.gmsClusterNode;
                /* If this is local join, then update the IP address */
                if (thisGmsClusterNode.nodeId ==
                    req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeId)
                {
                    memcpy(&node->viewMember.clusterMember.nodeIpAddress,
                           &myAddress, sizeof(ClGmsNodeAddressT));
                }

                rc = _clGmsEngineClusterJoin(req_exec_gms_nodejoin.gmsGroupId,
                                             req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeId,
                                             node);
            }
        }
        break;
    case CL_GMS_CLUSTER_EJECT_MSG:
        clLog (DBG,OPN,AIS,
               "Received cluster eject multicast message from ioc node [%#x:%#x]",
               req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.nodeAddress,
               req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.portId);
        /* inform the member about the eject by invoking the ejection
         *  callback registered with the reason UKNOWN */
        /* The below logic is same for the leave as well so we just
         *  fall through the case */
        _clGmsGetThisNodeInfo(&thisGmsClusterNode);
        if( req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeId ==
            thisGmsClusterNode.nodeId)
        {
            rc = _clGmsCallClusterMemberEjectCallBack(
                                                      req_exec_gms_nodejoin.ejectReason);
            if( rc != CL_OK )
            {
                clLog(ERROR,OPN,AIS,"_clGmsCallEjectCallBack failed with"
                      "rc:0x%x",rc);
            }
        }
    case CL_GMS_CLUSTER_LEAVE_MSG:
        clLog(DBG,OPN,AIS,
              "Received cluster leave multicast message from ioc node [%#x:%#x]",
              req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.nodeAddress,
              req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.portId);
        rc = _clGmsEngineClusterLeave(req_exec_gms_nodejoin.gmsGroupId,
                                      req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeId);
        break;
    case CL_GMS_GROUP_CREATE_MSG:
        clLog(DBG,OPN,AIS,
              "Received group create multicast message from ioc node [%#x:%#x]",
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.nodeAddress,
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.portId);

        rc = _clGmsEngineGroupCreate(req_exec_gms_nodejoin.specificMessage.groupMessage.groupData.groupName,
                                     req_exec_gms_nodejoin.specificMessage.groupMessage.groupData.groupParams,
                                     req_exec_gms_nodejoin.contextHandle, isLocalMsg);
        break;
    case CL_GMS_GROUP_DESTROY_MSG:
        clLog(DBG,OPN,AIS,
              "Received group destroy multicast message from ioc node [%#x:%#x]",
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.nodeAddress,
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.portId);

        rc = _clGmsEngineGroupDestroy(req_exec_gms_nodejoin.specificMessage.groupMessage.groupData.groupId,
                                      req_exec_gms_nodejoin.specificMessage.groupMessage.groupData.groupName,
                                      req_exec_gms_nodejoin.contextHandle, isLocalMsg);
        break;
    case CL_GMS_GROUP_JOIN_MSG:
        clLog(DBG,OPN,AIS,
              "Received group join multicast message from ioc node [%#x:%#x]",
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.nodeAddress,
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.portId);

        node = (ClGmsViewNodeT *) clHeapAllocate(sizeof(ClGmsViewNodeT));
        if (!node)
        {
            log_printf (LOG_LEVEL_NOTICE, "clHeapAllocate failed");
            goto out_delete;
        }
        else {
            /* FIXME: Need to verify version */
            memcpy(&node->viewMember.groupMember,&req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode,
                   sizeof(ClGmsGroupMemberT));
            memcpy(&node->viewMember.groupData, &req_exec_gms_nodejoin.specificMessage.groupMessage.groupData,
                   sizeof(ClGmsGroupInfoT));
            rc = _clGmsEngineGroupJoin(req_exec_gms_nodejoin.specificMessage.groupMessage.groupData.groupId,
                                       node, req_exec_gms_nodejoin.contextHandle, isLocalMsg);
        }
        break;
    case CL_GMS_GROUP_LEAVE_MSG:
        clLog(DBG,OPN,AIS,
              "Received group leave multicast message from ioc node [%#x:%#x]",
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.nodeAddress,
              req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberAddress.iocPhyAddress.portId);

        rc = _clGmsEngineGroupLeave(req_exec_gms_nodejoin.specificMessage.groupMessage.groupData.groupId,
                                    req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberId,
                                    req_exec_gms_nodejoin.contextHandle, isLocalMsg);
        break;
    case CL_GMS_COMP_DEATH:
        clLog(DBG,OPN,AIS,
              "Received comp death multicast message");
        rc = _clGmsRemoveMemberOnCompDeath(req_exec_gms_nodejoin.specificMessage.groupMessage.gmsGroupNode.memberId);
        break;
    case CL_GMS_LEADER_ELECT_MSG:
        clLog(DBG,OPN,AIS,
              "Received leader elect multicast message from ioc node [%#x:%#x]",
              req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.nodeAddress,
              req_exec_gms_nodejoin.specificMessage.gmsClusterNode.nodeAddress.iocPhyAddress.portId);
        rc = _clGmsEnginePreferredLeaderElect(req_exec_gms_nodejoin.specificMessage.gmsClusterNode, 
                                              req_exec_gms_nodejoin.contextHandle,
                                              isLocalMsg);
        break;
    case CL_GMS_SYNC_MESSAGE:
        clLog(DBG,OPN,AIS,
              "Received gms synch multicast message");
        rc = _clGmsEngineGroupInfoSync((ClGmsGroupSyncNotificationT *)(req_exec_gms_nodejoin.dataPtr));
        clHeapFree(((ClGmsGroupSyncNotificationT *)req_exec_gms_nodejoin.dataPtr)->groupInfoList);
        clHeapFree(((ClGmsGroupSyncNotificationT *)req_exec_gms_nodejoin.dataPtr)->groupMemberList);
        clHeapFree(req_exec_gms_nodejoin.dataPtr);
        break;

    case CL_GMS_GROUP_MCAST_MSG:
        _clGmsEngineMcastMessageHandler(
                                        &(req_exec_gms_nodejoin.specificMessage.mcastMessage.groupInfo.gmsGroupNode),
                                        &(req_exec_gms_nodejoin.specificMessage.mcastMessage.groupInfo.groupData),
                                        req_exec_gms_nodejoin.specificMessage.mcastMessage.userDataSize,
                                        req_exec_gms_nodejoin.dataPtr);
        break;
    default:
        clLogMultiline(ERROR,OPN,AIS,
                       "Openais GMS wrapper received Message wih invalid [MsgType=%x]. \n"
                       "This could be because of multicast port clashes.",
                       req_exec_gms_nodejoin.gmsMessageType);
        goto out_delete;
    }
    clLog(TRACE,OPN,AIS,
          "Processed the received message. Returning");
    out_delete:
    clBufferDelete(&bufferHandle);
}
static ClRcT nodeCacheViewGetWithFilterFast(ClNodeCacheMemberT *pMembers, 
                                            ClUint32T *pMaxMembers, ClUint32T capFilter,
                                            ClBoolT compat)
{
    ClInt32T i;
    ClInt32T j;
    ClUint32T maxMembers = 0;
    ClUint32T currentMembers = 0;

    if(!pMembers || !pMaxMembers || !(maxMembers = *pMaxMembers))
        return CL_ERR_INVALID_PARAMETER;

    if(!gpClNodeCache)
        return CL_ERR_NOT_INITIALIZED;

    if(compat)
    {
        ClUint32T minVersion = CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->minVersion;
        if(minVersion && minVersion < CL_VERSION_CODE(5, 0, 0))
        {
            *pMaxMembers = 0;
            return CL_OK;
        }
        if(!gClAspNativeLeaderElection)
        {
            *pMaxMembers = 0;
            return CL_OK;
        }
    }

    if(!capFilter) capFilter = ~capFilter;

    for(i = 0; i < CL_NODE_MAP_WORDS; ++i)
    {
        ClUint32T mask = CL_NODE_CACHE_HEADER_BASE(gpClNodeCache)->nodeMap[i];
        if(!mask) continue;
        for(j = 0; j < 32; ++j)
        {
            ClIocNodeAddressT node = (i << 5) + j;
            if( (mask & ( 1 << j)) )
            {
                if((CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[node].capability & capFilter))
                {
                    pMembers[currentMembers].address = node;
                    pMembers[currentMembers].version = CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[node].version;
                    pMembers[currentMembers].capability = CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[node].capability;
                    pMembers[currentMembers].name[0] = 0;
                    strncat(pMembers[currentMembers].name,
                            CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[node].nodeName,
                            sizeof(pMembers[currentMembers].name)-1);

                    if(++currentMembers >= maxMembers)
                        goto out;
                }
            }
        }
    }

    out:
    *pMaxMembers = currentMembers;
    return CL_OK;
}