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;
}
static ClRcT amsMgmtCCBBatchBufferInitialize(ClAmsMgmtCCBBatchT *batch)
{
    ClRcT rc = CL_OK;

    if(batch->buffer)
    {
        rc |= clBufferDelete(&batch->buffer);
        if(rc != CL_OK)
            goto out;
        batch->buffer = 0;
    }
    rc |= clBufferCreate(&batch->buffer);
    if(rc != CL_OK)
        goto out;
    batch->items = 0;
    batch->version = CL_VERSION_CURRENT;
    clNodeCacheMinVersionGet(NULL, &batch->version);
    rc = clXdrMarshallClUint32T(&batch->version, batch->buffer, 0);
    if(rc != CL_OK)
    {
        goto out_free;
    }
    rc = clBufferWriteOffsetGet(batch->buffer, &batch->itemsOffset);
    if(rc != CL_OK)
    {
        goto out_free;
    }
    rc = clXdrMarshallClUint32T(&batch->items, batch->buffer, 0);
    if(rc != CL_OK)
    {
        goto out_free;
    }
    goto out;

    out_free:
    clBufferDelete(&batch->buffer);
    batch->buffer = 0;
 
    out:
    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 int gms_nodejoin_send (void)
{
    /* For now this function sends only latest version. It needs to be 
     * modified in future when version changes */
    /* Send the join message with given version */
    mar_req_header_t                    header = {0};
	struct VDECL(req_exec_gms_nodejoin) req_exec_gms_nodejoin;
	struct iovec                 req_exec_gms_iovec;
    ClGmsClusterMemberT          thisGmsClusterNode;
	int                          result;
    ClRcT                        rc = CL_OK;
    ClUint32T                    clusterVersion;
    ClBufferHandleT bufferHandle = 0;
    ClUint8T        *message = NULL;
    ClPtrT          temp = NULL;
    ClUint32T       length = 0;

    rc = clNodeCacheMinVersionGet(NULL, &clusterVersion);
    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);
    }

    clLog(DBG,OPN,AIS,
            "This node is sending join message for version %d, %d, %d",
            curVer.releaseCode, curVer.majorVersion, curVer.minorVersion);
    /* 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;

    _clGmsGetThisNodeInfo(&thisGmsClusterNode);

    // node join is send for default cluster group - 0
    req_exec_gms_nodejoin.gmsGroupId     = 0;
    memcpy (&req_exec_gms_nodejoin.specificMessage.gmsClusterNode, &thisGmsClusterNode, sizeof (ClGmsClusterMemberT));
    req_exec_gms_nodejoin.gmsMessageType = CL_GMS_CLUSTER_JOIN_MSG; 

    /* Create a buffer handle and marshall the elements */
    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;
    }

    /* 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(length + sizeof(mar_req_header_t));
    if (temp == NULL)
    {
        clLogError(OPN,AIS, 
                "Failed to allocate memory while sending the message");
        goto buffer_delete_return;
    }

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

    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);

    clLog(DBG,OPN,AIS,
            "Sending node join from this node in sync_process");
    result = totempg_groups_mcast_joined (openais_group_handle, &req_exec_gms_iovec, 1, TOTEMPG_AGREED);

buffer_delete_return:
    if (message != NULL)
        clHeapFree(message);
    if (temp != NULL)
        clHeapFree(temp);
    clBufferDelete(&bufferHandle);
    return result;
}