void clPluginHelperAddRemVirtualAddress(const ClCharT *cmd, const ClPluginHelperVirtualIpAddressT *vip) {
    int up = 0;
    if (cmd[0] == 'u')
        up = 1;

    ClPluginHelperVirtualIpAddressT* vipCopy = (ClPluginHelperVirtualIpAddressT*) malloc(sizeof(ClPluginHelperVirtualIpAddressT));
    memcpy(vipCopy, vip, sizeof(ClPluginHelperVirtualIpAddressT));

    /*
     * Ignore configure if IP and dev are already existing on node
     */
    if (_clCheckExistingDevIf(vipCopy->ip, vipCopy->dev))
    {
        clLogInfo("IOC",
                CL_LOG_PLUGIN_HELPER_AREA,
                "Ignored assignment IP address: %s, for device: %s",
                vipCopy->ip,
                vipCopy->dev);
        goto out;
    }

    if (vipCopy->ip && vipCopy->dev && vipCopy->netmask) 
    {
        char execLine[301];
        snprintf(execLine, 300, "%s/virtualIp %s %s %s %s %s ", ASP_BINDIR, cmd, vipCopy->ip, vipCopy->netmask, vipCopy->dev, vipCopy->subnetPrefix);
        clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Executing %s", execLine);
        __attribute__((unused)) ClRcT result = system(execLine);

        if (up) /* If we are coming up, do a gratuitous arp */
        {
            clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Sending gratuitous arps: IP address: %s, device: %s", vipCopy->ip, vipCopy->dev);
            _clPluginHelperSendArp(vipCopy->ip, vipCopy->dev);
            clOsalTaskCreateDetached("arpTask", CL_OSAL_SCHED_OTHER, 0, 0, _clPluginHelperPummelArps, vipCopy);
            vipCopy = NULL; /* freed by the arp thread*/
        } 
        else 
        {
            /* If we are going down, delay a bit so that the machine that takes over will not do so too soon.
             (the assumption being that the machine taking over will not do so until this remove returns)
             */
            clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Removing IP; not sending gratuitous arps");
            /* sleep(1); */
        }
    } 
    else 
    {
        clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Virtual IP work assignment values incorrect: got IP address: %s, device: %s, mask: %s, net prefix: %s", 
                    vipCopy->ip, vipCopy->dev, vipCopy->netmask, vipCopy->subnetPrefix);
    }

out:
    if(vipCopy)
        free(vipCopy);
}
/**
 * get DM Handle from given ClCorMOId
 */
ClRcT
moId2DMHandle(ClCorMOIdPtrT path,
              DMObjHandle_h dmh)
{
    ObjTreeNode_h obj;
    CORObject_h dmObj;

    CL_FUNC_ENTER();
    
    if(!path || !dmh)
    {
        CL_FUNC_EXIT();
        return CL_COR_SET_RC(CL_COR_ERR_NULL_PTR);
    }
    memset(dmh,0,sizeof(DMObjHandle_t));
    obj = corMOObjGet(path);
    if(obj)
    {
        ClCorMOServiceIdT svcId=(path)->svcId;
        
        dmObj = obj->data;
        if(svcId!=CL_COR_INVALID_SRVC_ID)
        { 
            dmObj=corMSOObjGet(obj, svcId);
        } 

        if (dmObj != NULL && dmObj->dmObjH.classId != 0)
        {
            (dmh)->classId = dmObj->dmObjH.classId;
            (dmh)->instanceId = dmObj->dmObjH.instanceId;
        }
        else
        {
            clLogInfo("COR", "OBH", 
                    "The Dm object node doesn't exist. rc[0x%x]", CL_COR_SET_RC(CL_COR_INST_ERR_INVALID_MOID));
            return CL_COR_SET_RC(CL_COR_INST_ERR_INVALID_MOID);
        }
    } 
    else
    {
	    clLogInfo("COR", "OBJ", 
                "The object node doesn't exist in the object tree. rc [0x%x]", CL_COR_SET_RC(CL_COR_INST_ERR_INVALID_MOID));
	    return CL_COR_SET_RC(CL_COR_INST_ERR_INVALID_MOID);
    }

    CL_FUNC_EXIT();
    return CL_OK;
}
static ClRcT _clPluginHelperGetLinkName(const ClCharT *xportType, ClCharT *inf) {
    ClCharT net_addr[CL_MAX_FIELD_LENGTH] = "eth0";
    ClCharT *linkName = NULL;
    ClCharT envlinkNameType[CL_MAX_FIELD_LENGTH] = { 0 };
    if (!xportType) {
        return CL_ERR_INVALID_PARAMETER;
    } else {
        snprintf(envlinkNameType, CL_MAX_FIELD_LENGTH, "ASP_%s_LINK_NAME", xportType);
        linkName = getenv(envlinkNameType);
        if (linkName == NULL)
        {
            // try with default LINK_NAME
            linkName = getenv("LINK_NAME");
            if (linkName == NULL)
            {
                clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA,
                        "%s and LINK_NAME environment variable is not exported. Using 'eth0:10' interface as default", envlinkNameType);
            } else {
                clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "LINK_NAME env is exported. Value is %s", linkName);
                net_addr[0] = 0;
                strncat(net_addr, linkName, sizeof(net_addr)-1);
                ClCharT *token = NULL;
                strtok_r(net_addr, ":", &token);
            }
            snprintf(inf, CL_MAX_FIELD_LENGTH, "%s:%d", net_addr, gIocLocalBladeAddress + 10);
        } else {
            clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "%s env is exported. Value is %s", envlinkNameType, linkName);
            snprintf(inf, CL_MAX_FIELD_LENGTH, "%s", linkName);
        }
    }
    return CL_OK;
}
void clLogSvrTerminate(SaInvocationT invocation, const SaNameT *compName)
{
    
    ClRcT            rc           = CL_OK;
    ClLogSvrEoDataT  *pSvrEoEntry = NULL;
    //ClHandleT        hCpm         = CL_HANDLE_INVALID_VALUE;
    CL_LOG_DEBUG_TRACE(("Enter"));
    clLogInfo("SVR", "MAI", "Unregistering with cpm...... [%.*s]\n", compName->length, compName->value);
    gClLogSvrExiting = CL_TRUE;
    rc = clLogSvrEoEntryGet(&pSvrEoEntry, NULL);
    if( CL_OK != rc )
    {
        return ;
    }
    //hCpm = pSvrEoEntry->hCpm;
    saAmfComponentUnregister(amfHandle,compName, NULL);
#if 1
    CL_LOG_CLEANUP(clLogSvrShutdown(), CL_OK);
#endif    
    saAmfResponse(amfHandle, invocation, SA_AIS_OK);

    CL_LOG_DEBUG_TRACE(("Exit"));

    unblockNow = CL_TRUE;
    //(void)hCpm;

}
ClRcT clNodeCacheCapabilitySet(ClIocNodeAddressT nodeAddress, ClUint32T capability, ClUint32T flag)
{
    if(nodeAddress >= CL_IOC_MAX_NODES || !gpClNodeCache)
        return CL_ERR_INVALID_PARAMETER;

    clOsalSemLock(gClNodeCacheSem);
    switch(flag)
    {
    case CL_NODE_CACHE_CAP_ASSIGN:
        CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[nodeAddress].capability = capability;
        break;

    case CL_NODE_CACHE_CAP_AND:
        CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[nodeAddress].capability &= capability;
        break;

    case CL_NODE_CACHE_CAP_MERGE:
        CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[nodeAddress].capability |= capability;
        break;

    case CL_NODE_CACHE_CAP_CLEAR:
        CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[nodeAddress].capability &= ~capability;
        break;

    default:
        break;
    }

    capability = CL_NODE_CACHE_ENTRY_BASE(gpClNodeCache)[nodeAddress].capability;
    clOsalSemUnlock(gClNodeCacheSem);
    clLogInfo("CAP", "SET", "Node cache capability set to [%#x] for node [%d]", capability, nodeAddress);
    return CL_OK;
}
static ClRcT fileEntryRecoverBaseVersion(ClLogMasterEoDataT *pMasterEoEntry,
        ClBufferHandleT hFileEntryBuf)
{
    ClRcT rc = CL_OK;
    ClLogFileKeyT        fileKey       = {{0}};
    ClLogFileKeyT        *pFileKey     = NULL;
    ClLogFileDataT       *pFileData    = NULL;

    rc = clLogMasterFileKeyUnpack(&fileKey, hFileEntryBuf);
    if( CL_OK != rc )
    {
        return rc;
    }
    clLogInfo(CL_LOG_AREA_MASTER, CL_LOG_CTX_CKPT_READ,
              "Recreating files fileName: %.*s fileLocation: %.*s",
              fileKey.fileName.length, fileKey.fileName.pValue,
              fileKey.fileLocation.length, fileKey.fileLocation.pValue);

    rc = clLogFileKeyCreate(&fileKey.fileName, &fileKey.fileLocation,
                            pMasterEoEntry->maxFiles, &pFileKey);
    if( CL_OK != rc )
    {
        clHeapFree(fileKey.fileName.pValue);
        clHeapFree(fileKey.fileLocation.pValue);
        return rc;
    }
    clHeapFree(fileKey.fileName.pValue);
    clHeapFree(fileKey.fileLocation.pValue);

    /* find out the filelocation is available */
    pFileData = (ClLogFileDataT*) clHeapCalloc(1, sizeof(ClLogFileDataT));
    if( NULL == pFileData )
    {
        CL_LOG_DEBUG_ERROR(("clHeapCalloc()"));
        clLogFileKeyDestroy(pFileKey);
        return rc;
    }

    pFileData->nActiveStreams = 0;
    rc = clLogMasterFileDataRecreate(pFileData, hFileEntryBuf);
    if( CL_OK != rc )
    {
        clLogFileKeyDestroy(pFileKey);
        return rc;
    }

    rc = clCntNodeAdd(pMasterEoEntry->hMasterFileTable,
                      (ClCntKeyHandleT) pFileKey,
                      (ClCntDataHandleT) pFileData, NULL);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clCntNodeAdd()"));
        CL_LOG_CLEANUP(clCntDelete(pFileData->hStreamTable), CL_OK); //FIXME
        clHeapFree(pFileData);
        clLogFileKeyDestroy(pFileKey);
        return rc;
    }

    return rc;
}
static void cpmPayload2StandbySC(const ClGmsClusterNotificationBufferT *notificationBuffer,
                                 ClCpmLocalInfoT *pCpmLocalInfo)
{
    ClUint32T rc = CL_OK;

    if(gpClCpm->haState == CL_AMS_HA_STATE_STANDBY)
    {
        clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                     "Payload node already promoted to Deputy. Skipping initialization of controller functions");
        return;
    }

    clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, 
                "Payload node promoted to deputy. Initializing System controller functions on this node.");

    gpClCpm->pCpmConfig->cpmType = CL_CPM_GLOBAL;
    rc = cpmUpdateTL(CL_AMS_HA_STATE_STANDBY);
    if (rc != CL_OK)
    {
        clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL,
                   CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc);
    }
    rc = clAmsStart(&gAms,
                    CL_AMS_INSTANTIATE_MODE_STANDBY);
    gpClCpm->haState = CL_AMS_HA_STATE_STANDBY;
    gpClCpm->activeMasterNodeId = notificationBuffer->leader;
    gpClCpm->deputyNodeId = notificationBuffer->deputy;
    if (CL_OK != rc)
    {
        clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                      "Unable to initialize AMS, "
                      "error = [%#x]", rc);

        cpmSelfShutDown();
        return;
    }
    clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
              "initialization of AMS is successful. ");
    
    if (gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel)
    {
        cpmInitializeStandby();
    }
    
    clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                "Payload to System Controller conversion done");

    return ;
}
ClRcT
clLogFlusherTimerCallback(void  *pData)
{
    ClHandleT  hFlusher = *(ClHandleT *)(ClWordT)pData;

    CL_LOG_DEBUG_TRACE(("Enter"));

    clLogInfo("LOG", "FLS", "Timer expired");

    clLogFlusherCookieHandleDestroy(hFlusher, CL_FALSE);

    clHeapFree(pData);
    
    CL_LOG_DEBUG_TRACE(("Exit"));
    return CL_OK;
}    
static ClRcT _clPluginHelperGetIpNodeAddress(const ClCharT *xportType, ClCharT *hostAddress, ClCharT *networkMask, ClCharT *broadcast, ClUint32T *ipAddressMask, ClCharT *xportSubnetPrefix) {
    ClCharT envSubNetType[CL_MAX_FIELD_LENGTH] = { 0 };
    ClCharT xportSubnet[CL_MAX_FIELD_LENGTH] = { 0 };
    ClCharT *subnetMask = NULL;
    ClCharT *subnetPrefix = NULL;
    ClUint32T CIDR, ipMask, ip, mask;
    if (!xportType) 
    {
        return CL_ERR_INVALID_PARAMETER;
    } 
    else 
    {
        snprintf(envSubNetType, CL_MAX_FIELD_LENGTH, "ASP_%s_SUBNET", xportType);
        subnetMask = getenv(envSubNetType);
        if (subnetMask == NULL) 
        {
            subnetMask = ASP_PLUGIN_SUBNET_DEFAULT;
        }
        subnetPrefix = strrchr(subnetMask, '/');
        if(!subnetPrefix)
        {
            subnetPrefix = ASP_PLUGIN_SUBNET_PREFIX_DEFAULT; 
        }
        else 
        {
            ++subnetPrefix;
        }
        if(! (CIDR = atoi(subnetPrefix) ) )
        {
            clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "%s", subnetMask);
            return CL_ERR_INVALID_PARAMETER;
        }
        xportSubnetPrefix[0] = 0;
        strncat(xportSubnetPrefix, subnetPrefix, CL_MAX_FIELD_LENGTH-1);
        snprintf(xportSubnet, sizeof(xportSubnet), "%s", subnetMask);
        mask = _clPluginHelperBitFillRShift(CIDR);
        _clPluginHelperConvertInternetToHostAddress(&ip, xportSubnet);

        /* network address */
        ipMask = (ip & mask);
        _clPluginHelperConvertHostToInternetAddress(ipMask + gIocLocalBladeAddress, hostAddress);
        _clPluginHelperConvertHostToInternetAddress(mask, networkMask);
        _clPluginHelperConvertHostToInternetAddress(ip | ~mask, broadcast);
        *ipAddressMask = ipMask;
    }
    return CL_OK;
}
static ClRcT _clPluginHelperGetLinkName(const ClCharT *xportType, ClCharT *inf)
{
    ClCharT net_addr[CL_MAX_FIELD_LENGTH] = "eth0";
    ClCharT *linkName = NULL;
    ClCharT envlinkNameType[CL_MAX_FIELD_LENGTH] = { 0 };
    if (!xportType)
    {
        return CL_ERR_INVALID_PARAMETER;
    }
    else
    {
        snprintf(envlinkNameType, CL_MAX_FIELD_LENGTH, "ASP_%s_LINK_NAME", xportType);
        linkName = getenv(envlinkNameType);
        if (linkName == NULL)
        {
            // try with default LINK_NAME
            linkName = getenv("LINK_NAME");
            if (linkName == NULL)
            {
                clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "%s and LINK_NAME environment variable is not exported. Using 'eth0:10' interface as default", envlinkNameType);
            }
            else
            {
                clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "LINK_NAME env is exported. Value is %s", linkName);
                net_addr[0] = 0;
                strncat(net_addr, linkName, sizeof(net_addr)-1);
                ClCharT *token = NULL;
                strtok_r(net_addr, ":", &token);
            }
            /* If we are not using the existing IP addr then we need to use a virtual device to make sure we don't overwrite an already-configured address */
            if (!ASP_UDP_USE_EXISTING_IP)
              snprintf(inf, CL_MAX_FIELD_LENGTH, "%s:%d", net_addr, gIocLocalBladeAddress + 10);
            /* If we ARE using the existing IP, then whatever interfaces LINK_NAME is set to IS that address */
            else snprintf(inf, CL_MAX_FIELD_LENGTH, "%s", net_addr);            
        }
        else
        {
            clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "%s env is exported. Value is %s", envlinkNameType, linkName);
            snprintf(inf, CL_MAX_FIELD_LENGTH, "%s", linkName);
        }
    }
    return CL_OK;
}
SaAisErrorT saCkptFinalize (const SaCkptHandleT ckptHandle)
{
    ClRcT            rc    = CL_OK;
    SaAisErrorT      safRc = SA_AIS_OK;

    rc = clCkptFinalize((ClCkptSvcHdlT)ckptHandle);
    
    /*
     * Translate the clovis error type to SAF error type.
     */
    clErrorTxlate(rc, &safRc);
    
    if(CL_OK != clASPFinalize())
    {
        clLogInfo("CKP", "FIN",
                  "ASP finalize failed, rc[0x%X]", rc);
        return SA_AIS_ERR_LIBRARY;
    }

    return safRc;
}
/*
 * The main parser entry point
 *
*/
ClRcT clParseXML(ClCharT *pPath,const ClCharT *pFileName,ClParserDataT *pData)
{
    ClRcT rc = CL_OK;
    ClParserPtrT root;

    rc = CL_PARSER_RC(CL_ERR_INVALID_PARAMETER);
    if(pFileName == NULL || pData == NULL)
    {
        clLogError(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_XML,"Invalid parameter\n");
        goto out;
    }
    if(pPath == NULL)
    {
        pPath = getenv("ASP_CONFIG");
        if(pPath == NULL)
        {
            clLogError(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_XML,"Please export ASP_CONFIG\n");
            goto out;
        }
    }

    /*Start the parse*/
    root = clParserOpenFile(pPath,pFileName);
    if(root == NULL)
    {
        clLogInfo(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_XML,"Opening xml configuration file [%s] failed",
                                       pFileName);
        goto out;
    }
    rc = clParseChild(NULL,root,pData,NULL);
    CL_PARSER_RESULT(pData,rc,out_free);

    out_free:
    clParserFree(root);

    out:
    return rc;
}
/* ip route configure */
void clPluginHelperAddRouteAddress(const ClCharT *ipAddress, const ClCharT *ifDevName)
{
    FILE *route_file;
    ClUint32T dest;
    ClCharT dummyStr[CL_MAX_NAME_LENGTH];
    ClCharT dummyDev[CL_MAX_FIELD_LENGTH];
    ClUint32T ipMulticast;
    ClBoolT foundDestRoute = CL_FALSE;
    __attribute__((unused)) ClRcT result;

    clPluginHelperConvertInternetToHostAddress(&ipMulticast, ipAddress);

    // open route file to get the route destination
    route_file = fopen("/proc/net/route", "r");

    result = fscanf(route_file, "%[^\n]", dummyStr);

    while (!feof(route_file))
    {
        result = fscanf(route_file, "%s %8X %[^\n]", dummyDev, &dest, dummyStr);       
        if (!(ipMulticast ^ dest))
        {
            foundDestRoute = CL_TRUE;
            break;
        }
    }
    fclose(route_file);

    if (!foundDestRoute)
    {
        char execLine[301];
        snprintf(execLine, 300, "/sbin/ip route add %s dev %s", ipAddress, ifDevName);
        clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Executing %s", execLine);
        result = system(execLine);
    }
}
SaAisErrorT
saClmFinalize (
        const SaClmHandleT clmHandle
        )
{
    ClRcT rc = CL_OK;
    ClHandleT   localHandle = CL_HANDLE_INVALID_VALUE;
    SaClmInstanceT      *clmInstance = NULL;
    
    SA_GMS_CHECK_INIT_COUNT();

    /* Handle checkout */
    localHandle = (ClHandleT)clmHandle;
    rc = clHandleCheckout(databaseHandle, localHandle, (void**)&clmInstance);
    if (rc != CL_OK)
    {
    return _aspErrToAisErr(rc);
}
    CL_ASSERT(clmInstance != NULL);
    
    /* Finalize with GMS */
    rc = clGmsFinalize(localHandle);
    if (rc != CL_OK)
    {
        clLogError("CLM","FIN",
                   "clGmsFinalize failed with rc 0x%x\n",rc);
    }

    /* Deregister with dispatch */
    rc = clDispatchDeregister(clmInstance->dispatchHandle);
    if (rc != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_FINALISE,
                   "clDispatchDeregister failed with rc 0x%x\n",rc);
    }

    /* Checkin the handle */
    if ((clHandleCheckin(databaseHandle, localHandle)) != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_FINALISE,
                    "clHandleCheckin failed");
    }

    /* Destroy the handle */
    if ((clHandleDestroy(databaseHandle, localHandle)) != CL_OK)
    {
        clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_FINALISE,
                   "clHandleDestroy failed");
    }

    SA_GMS_INIT_COUNT_DEC();
    if (isLastFinalize() == CL_TRUE)
    {
        rc = clHandleDatabaseDestroy(databaseHandle);
        if (rc != CL_OK)
        {
            clLogError(GMS_LOG_AREA_CLM,GMS_LOG_CTX_CLM_DB,
                       "clHandleDatabaseDestroy failed with rc 0x%x\n",rc);
        }
    }
    
    if(CL_OK != clASPFinalize())
    {
        clLogInfo("CLM", "FIN",
                  "ASP finalize failed, rc[0x%X]", rc);
        return SA_AIS_ERR_LIBRARY;
    }

    return _aspErrToAisErr(rc);
}
ClRcT 
clLogSvrInitialize(ClUint32T argc,ClCharT   *argv[])
{
    SaAmfCallbacksT     callbacks = {0};
    SaVersionT          version;
    
    ClRcT            rc            = CL_OK;
    ClLogSvrEoDataT  *pSvrEoEntry  = NULL;
    ClBoolT          *pCookie      = NULL;
    ClIocAddressT    invalidAddr   = {{0}};
	
    clLogCompName =(ClCharT*) "LOG"; /* Override generated eo name with a short name for our server */
    gClLogServer = CL_FALSE;  /* Mark me as the log server */

    clLogInfo(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED, "Log Server initialization started...");

    clAppConfigure(&clEoConfig,clEoBasicLibs,clEoClientLibs);

    version.releaseCode  = 'B';
    version.majorVersion = 0x01;
    version.minorVersion = 0x01;

    callbacks.saAmfHealthcheckCallback          = NULL; /* rarely necessary because SAFplus monitors the process */
    callbacks.saAmfComponentTerminateCallback   = clLogSvrTerminate;
    callbacks.saAmfCSISetCallback               = NULL;
    callbacks.saAmfCSIRemoveCallback            = NULL;
    callbacks.saAmfProtectionGroupTrackCallback = NULL;        
    callbacks.saAmfProxiedComponentInstantiateCallback    = NULL;
    callbacks.saAmfProxiedComponentCleanupCallback    = NULL;

    rc = saAmfInitialize(&amfHandle, &callbacks, &version);
    if( SA_AIS_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("saAmfInitialize(): rc[0x %x]", rc));
        return rc;
    }
          

#if defined(CL_DEBUG) && defined(CL_DEBUG_START)
    clLogDebugLevelSet();
#endif
    CL_LOG_DEBUG_TRACE(("Enter"));	

    clLogSvrMutexModeSet();
    
    /* 
     * Here dummy initialization of Idl handle to avoid mutiple database 
     * Initialization & finalization databases. Keeping this handle alive 
     * will avoid this. coz Idl library will delete the handle database if the
     * handle count becomes zero. Mutiple times we are initializing & deleting
     * the handles in our log service usage.
    */
    rc = clLogIdlHandleInitialize(invalidAddr, &shLogDummyIdl);
    if( CL_OK != rc )
    {
        
        return rc;
    }
    rc = clLogSvrCommonDataInit();
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clLogSvrCommonDataInit(): rc[0x %x]", rc));
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        return rc;
    }
    rc = clLogStreamOwnerLocalBootup();
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clLogStreamOwnerLocalInit(): rc[0x %x]", rc));
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        return rc;
    }    
    pCookie = (ClBoolT*) clHeapCalloc(1, sizeof(ClBoolT));
    if( NULL == pCookie )
    {
        CL_LOG_DEBUG_ERROR(("clHeapCalloc()"));
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogStreamOwnerEoDataFree(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        return CL_LOG_RC(CL_ERR_NO_MEMORY);
    }
    *pCookie = CL_FALSE;
    rc = clLogSvrBootup(pCookie);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clLogSvrDataInit(): rc[0x %x]", rc));
        clHeapFree(pCookie);
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        return rc;
    }    
    clLogInfo(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED, 
              "Log server boot type is [%s]", 
              (*pCookie == 1)? "Restart": "Normal");

    rc = clLogSvrEoEntryGet(&pSvrEoEntry, NULL);
    if( CL_OK != rc )
    {
        CL_LOG_CLEANUP(clLogSvrEoDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrEoDataFree(), CL_OK);
        clHeapFree(pCookie);
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogStreamOwnerEoDataFree(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        return rc;
    }
    pSvrEoEntry->hCpm = amfHandle;
    rc = saAmfComponentNameGet(amfHandle, &logServerName);
    if( SA_AIS_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("saAmfComponentNameGet(): rc[0x %x]", rc));
        saAmfFinalize(amfHandle);
        CL_LOG_CLEANUP(clLogSvrEoDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrEoDataFree(), CL_OK);
        clHeapFree(pCookie);
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogStreamOwnerEoDataFree(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        return rc;
    }
    rc = saAmfComponentRegister(amfHandle, &logServerName, NULL);
    if( SA_AIS_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("saAmfComponentRegister(): rc[0x %x]", rc));
        CL_LOG_CLEANUP(clLogSvrEoDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrEoDataFree(), CL_OK);
        clHeapFree(pCookie);
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogStreamOwnerEoDataFree(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        saAmfFinalize(amfHandle);
        return rc;
    }   
    pSvrEoEntry->hTimer = CL_HANDLE_INVALID_VALUE;
    if( CL_FALSE == *pCookie )
    {
        rc = clLogSvrTimerDeleteNStart(pSvrEoEntry, pCookie);
    }
    else
    {
        rc = clLogTimerCallback((void *) pCookie);
    }
    if( CL_OK != rc )
    {
        saAmfComponentUnregister(amfHandle, &logServerName, NULL);
        CL_LOG_CLEANUP(clLogSvrEoDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrEoDataFree(), CL_OK);
        clHeapFree(pCookie);
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogStreamOwnerEoDataFree(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        saAmfFinalize(amfHandle);
        return rc;
    }
    rc = clLogDebugRegister();
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clLogDebugRegister(): rc[0x %x]", rc));
    }
    clLogNotice(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED, 
                "Log Server partially up");

    CL_LOG_DEBUG_TRACE(("Exit"));
    return CL_OK;					    
}
ClRcT clCkptMasterPeerUpdateNoLock(ClIocPortT        portId, 
                                   ClUint32T         flag, 
                                   ClIocNodeAddressT localAddr,
                                   ClUint8T          credential) 
{
    ClRcT              rc           = CL_OK;
    CkptPeerInfoT      *pPeerInfo   = NULL;
    CkptNodeListInfoT  *pPeerInfoDH = NULL;
    ClCntNodeHandleT   nodeHdl      = 0;
    ClCntNodeHandleT   tempHdl      = 0;
    ClHandleT         *pMasterHandle  = NULL;
    
    /*
     * Check whether node/component is coming up or going down.
     */
    if(flag == CL_CKPT_SERVER_UP)
    {
        /*
         * Checkpoint server up scenario.
         */
         clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_ANNOUNCE,
                   "Received welcome message from master, updating the peerlist for [%d]",
                    localAddr);

         /* Reset the replica list for peer being welcomed without knowing the peer is available or not */
         if(localAddr != gCkptSvr->localAddr)
         {
             clLogNotice("PEER", "UPDATE",
                         "Resetting the replica list for the peer [%#x] being welcomed", localAddr);
             clCkptMasterReplicaListUpdateNoLock(localAddr);
         }

        /* 
         * Add an entry to the peer list if not existing.
         * Mark the node as "available" i.e. available for checkpoint 
         * operations like storing replicas etc..
         */
        rc = clCntDataForKeyGet( gCkptSvr->masterInfo.peerList,
                                 (ClPtrT)(ClWordT)localAddr,
                                 (ClCntDataHandleT *)&pPeerInfo);
        if( rc == CL_OK && pPeerInfo != NULL)
        {
            CL_ASSERT(pPeerInfo->ckptList != 0);
            pPeerInfo->credential = credential;
            pPeerInfo->available  = CL_CKPT_NODE_AVAIL;

            if(localAddr != gCkptSvr->localAddr)
            {
                pPeerInfo->replicaCount = 0;
            }
        }
        else
        {
            if( CL_OK !=( rc = _ckptMasterPeerListInfoCreate(localAddr, 
                            credential,0)))
            {
                return rc;
            }
        }        
    }
    else
    {
        /*
         * Node/component down scenario.
         */
        clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                   "Updating the peerAddr [%d] for down notification",
                   localAddr);
        /* 
         * Find the corresponding entry from the peer list.
         */
        if( CL_OK != (rc = clCntDataForKeyGet(gCkptSvr->masterInfo.peerList,
                                             (ClCntKeyHandleT)(ClWordT)localAddr,
                                             (ClCntDataHandleT *) &pPeerInfo)))
        {
            rc = CL_OK;
            goto exitOnError;
        }

        if( flag != CL_CKPT_COMP_DOWN)
        {
            clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN,
                       "Either ckpt server or node down, "
                       "changing active address");
                    
            clCntFirstNodeGet(pPeerInfo->mastHdlList,&nodeHdl);
            tempHdl = 0;
            while(nodeHdl != 0)
            {
                rc = clCntNodeUserKeyGet(pPeerInfo->mastHdlList,nodeHdl,
                                    (ClCntKeyHandleT *)&pMasterHandle);
                if( CL_OK != rc )
                {
                    clLogError(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                            "Not able get the data for node handle rc[0x %x]",
                            rc);
                    goto exitOnError;
                }
                rc = clCntNextNodeGet(pPeerInfo->mastHdlList, nodeHdl, 
                                      &tempHdl);
                /*
                 * Update the active address and inform the clients.
                 */
                if( CL_OK != (rc = _clCkpMastertReplicaAddressUpdate(*pMasterHandle, 
                                                                 localAddr)))
                {
                    return rc;
                }
                nodeHdl = tempHdl;
                tempHdl = 0;
            }
        }
        
        if (flag != CL_CKPT_SVR_DOWN)
        {
            /* 
             * Component down/ node down case.
             * In case of component down close the associated client Hdl.
             * Incase of node down close all client Hdl.
             * Delete the ckpt Hdls from the client handle List.
             */
            clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                  "Closing the opened handles from this slot id [%d]...", 
                   localAddr);
            clCntFirstNodeGet(pPeerInfo->ckptList,&nodeHdl);
            while(nodeHdl != 0)
            {
                rc = clCntNodeUserDataGet(pPeerInfo->ckptList,nodeHdl,
                        (ClCntDataHandleT *)&pPeerInfoDH);
                if( CL_OK != rc )
                {
                    clLogError(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                            "Not able get the data for node handle rc[0x %x]",
                            rc);
                    goto exitOnError;
                }
                clCntNextNodeGet(pPeerInfo->ckptList,nodeHdl,&tempHdl);
                if ( (flag == CL_CKPT_COMP_DOWN && 
                     pPeerInfoDH->appPortNum == portId) || 
                     (flag == CL_CKPT_NODE_DOWN) )
                {
                    /*
                     * Close the checkpoint hdl but dont delete the entry from
                     * masterHdl list.
                     */
                    if(gCkptSvr->masterInfo.masterAddr == 
                                    gCkptSvr->localAddr) 
                    {                                    
                        clLogInfo(CL_CKPT_AREA_MAS_DEP,
                                  CL_CKPT_CTX_PEER_DOWN, 
                                  "Closing the handle [%#llX]...", 
                                  pPeerInfoDH->clientHdl);
                        _clCkptMasterCloseNoLock(pPeerInfoDH->clientHdl, 
                        localAddr, !CL_CKPT_MASTER_HDL); 
                    }    
                }
                nodeHdl = tempHdl;
                tempHdl = 0; 
            }
        }
        else if (flag == CL_CKPT_SVR_DOWN)
        {
            /*
             * Mark the availability of checkpoint server as UNAVAILABLE.
             */
            if(pPeerInfo->credential == CL_CKPT_CREDENTIAL_POSITIVE)
                gCkptSvr->masterInfo.availPeerCount--;
            pPeerInfo->available = CL_CKPT_NODE_UNAVAIL;
        }   

        if(flag == CL_CKPT_NODE_DOWN
           ||
           flag == CL_CKPT_SVR_DOWN)
        {
            
            /*
             * Node down case, delete the entry from master's peer list.
             */
            rc = clCntAllNodesForKeyDelete(gCkptSvr->masterInfo.peerList,
                                (ClPtrT)(ClWordT)localAddr);
             CKPT_ERR_CHECK(CL_CKPT_SVR,CL_LOG_SEV_ERROR,
             (" MasterPeerUpdate failed rc[0x %x]\n",rc),
             rc);

        }
        
        if( flag != CL_CKPT_COMP_DOWN)
        {
            /*
             * Find other nodes to store the replicas of checkpoints for whom
             * this node was storing the replicas.
             */
             if(gCkptSvr->masterInfo.masterAddr == gCkptSvr->localAddr)
             {
                 _ckptCheckpointLoadBalancing();
             }
        }
    }
exitOnError:
    {
        return rc;
    }
}  
ClRcT clSnmpSendSyncRequestToServer (void **my_loop_context, 
        void **my_data_context, 
        netsnmp_variable_list *put_index_data, 
        ClUint32T tableType,
        ClSnmpOpCodeT opCode)
{
    netsnmp_variable_list *vptr = NULL;
    ClInt32T errorCode = 0;
    ClInt32T retVal = 0;
    ClSnmpReqInfoT reqInfo = {0};
    ClUint32T count = 0;
    ClUint32T tblIndex = 0;
    ClCharT *sendData = NULL;
    ClRcT rc = CL_OK;
    ClSnmpOidInfoT *appOidInfo = NULL;

    /*Set my_loop_context to an application specific iterator context.
     * Typically it will be a linked list of values where each node
     * corresponds to a row in the table. But here we are not maintaining any
     * linked list.*/
    /*Actually we can set my_loop_context to NULL pointer also as we are not
     * maintaining a linked list of rows in a table here. All the required
     * things are maintained in COR. And net-SNMP uses the index we set by
     * calling snmp_set_var_value() function for the next index. So just set
     * it to &reqInfo here*/
    *my_loop_context = &gReqInfo;
    *my_data_context = &gReqInfo;

    memset(&reqInfo, 0, sizeof(ClSnmpReqInfoT));

    vptr = put_index_data;

    sendData = (ClCharT*) &reqInfo.index;


    extern ClRcT snmpBuildAppOIDInfo(ClSnmpOidInfoT **);
    rc = snmpBuildAppOIDInfo(&appOidInfo);
    if (rc != CL_OK)
    {
        return rc;
    }
    
    /* Get table entry from appOidInfo[] */
    while (appOidInfo[tblIndex].numAttr != 0)
    {
        if (appOidInfo[tblIndex].tableType == tableType)
        {
            break;
        }
        tblIndex++;
    }

    clLog(CL_LOG_SEV_DEBUG, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "Finding Index Information for OID[%s] with SNMP GET_FIRST[%d]/GET-NEXT[%d] CURRENT[%d]", appOidInfo[tblIndex].oid, CL_SNMP_GET_FIRST, CL_SNMP_GET_NEXT, opCode );

    if (appOidInfo[tblIndex].numAttr == 0)
    {
        /* Table entry not found after entries being exhausted */
        retVal = CL_MED_SET_RC(CL_ERR_NOT_EXIST);
        clLog(CL_LOG_SEV_ERROR, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "appOidInfo don't have necessary index information");
        return retVal;
    }

    if((opCode ==  CL_SNMP_GET_NEXT) || (my_loop_context !=  NULL && (*(ClInt32T*)*my_loop_context)!= 1))
    {
        for(count =0; (count < appOidInfo[tblIndex].numAttr) && sendData; count++)
        {
            /*We are assuming that the ClSnmpReqInfoT structure is
             * properly completed by the application writer and the union part
             * contains all indices*/

            /*Copy the index got from snmp agent*/
            /*COR supports only Integer / array of character types (string).
             * So we are not handling the case for float/bitstring/double etc
             * which are part of the put_index_data->val union*/
            switch(appOidInfo[tblIndex].attr[count].type)
            {
                case CL_SNMP_STRING_ATTR:
                    clLog(CL_LOG_SEV_DEBUG, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "Index Info Input : Possion[%d] AttrType[STRING] Value [%s] Size[%d]",count, vptr->val.string, appOidInfo[tblIndex].attr[count].size);
                    memcpy(sendData, vptr->val.string, (vptr->val_len + 1));
                    /*Add 1 here so that when
                     * vptr->val_len is added after the
                     * switch() it makes up for the
                     * length copied above*/
                    sendData += 1;     
                    break;
                case CL_SNMP_NON_STRING_ATTR:
                    clLog(CL_LOG_SEV_DEBUG, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "Index Info Input : Possion[%d] AttrType[NON-STRING] Value[%d] Size[%d]",count, *(ClUint32T*)vptr->val.integer, appOidInfo[tblIndex].attr[count].size);
                    memcpy(sendData, vptr->val.integer, appOidInfo[tblIndex].attr[count].size);
                    break;
                default:
                    break;
            }
            sendData += appOidInfo[tblIndex].attr[count].size;
            vptr = vptr->next_variable;
        }
    }

    {

        ClUint32T oidLen = strlen(appOidInfo[tblIndex].oid) + 1;
        if( oidLen > sizeof reqInfo.oid)
        {
            return CL_ERR_NO_SPACE;
        }
        else
            strncpy(reqInfo.oid, appOidInfo[tblIndex].oid, oidLen);
    }


    reqInfo.oidLen = strlen(reqInfo.oid);
    reqInfo.opCode = opCode;
    reqInfo.tableType = tableType;
    reqInfo.dataLen = sizeof(reqInfo.index);

    clLogInfo("SNMP", "SUB", "Before calling execute SNMP, oid is [%s]", reqInfo.oid);

    /*Now call clExecuteSnmp which talks to mediation library and fills the
     * index information for the next data or first data based on request
     * opcode*/
    retVal = clExecuteSnmp( &reqInfo,
            &reqInfo.index,
            NULL,
            &errorCode);
    vptr = put_index_data;
    /*Now set the result in vptr*/
    switch (retVal)
    {
        case CL_OK:   /* No errors : successful operation */
            {
                clLog(CL_LOG_SEV_DEBUG, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "Successfully got index information for OID[%s]",appOidInfo[tblIndex].oid);
                put_index_data->val.string = NULL;
                memset(vptr->buf, '\0', sizeof(vptr->buf));

                sendData = (ClCharT*) &reqInfo.index;
                for(count =0; (count < appOidInfo[tblIndex].numAttr) && sendData; count++)
                {
                    switch(appOidInfo[tblIndex].attr[count].type)
                    {
                        case CL_SNMP_STRING_ATTR:
                            clLog(CL_LOG_SEV_DEBUG, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "Index Info Output : Possion[%d] AttrType[STRING] Value[%s] Size[%d] ",count, sendData, appOidInfo[tblIndex].attr[count].size);
                            snmp_set_var_value(vptr, (u_char *) sendData, strlen(sendData) + 1);
                            sendData += 1;
                            break;
                        case CL_SNMP_NON_STRING_ATTR:
                            clLog(CL_LOG_SEV_DEBUG, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "Index Info Output : Possion[%d] AttrType[NON-STRING] Value[%d] Size[%d]",count, *(ClUint32T*)sendData, appOidInfo[tblIndex].attr[count].size);
                            snmp_set_var_value(vptr, (u_char *)sendData, appOidInfo[tblIndex].attr[count].size);
                            break;
                        default:
                            clLog(CL_LOG_SEV_ERROR, CL_SNMP_AREA, CL_SNMP_CTX_SOP, "AttrType is not Supported");
                    }
                    sendData += appOidInfo[tblIndex].attr[count].size;
                    vptr = vptr->next_variable;
                }
                break;
            }
        default:                 /* Failed due to other reasons */
            clLogDebug("SNP", "OPE", "Failed while getting next entry. rc[0x%x]", retVal);
            return retVal;
    }
    return CL_OK;
}
static ClRcT clAmsMgmtGetSUFreeNodes(ClAmsEntityT *sgName,
                                     const ClCharT *prefix,
                                     ClInt32T extraSUs,
                                     ClInt32T extraNodes,
                                     ClAmsEntityT *nodes,
                                     ClInt32T *pNumNodes)
{
    ClRcT rc = CL_OK;
    ClUint32T i;
    ClAmsEntityBufferT suBuffer = {0};
    ClAmsEntityBufferT nodeBuffer = {0};
    ClAmsEntityT *nodeList = NULL;
    ClAmsEntityConfigT *entityConfig = NULL;
    ClAmsSUConfigT suConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
    ClAmsEntityT *controllers = NULL;
    ClAmsEntityT *workers = NULL;
    ClUint32T numControllers = 0;
    ClUint32T numWorkers = 0;
    ClUint32T totalNodes = 0;

    if(!nodes || !pNumNodes)
        return CL_AMS_RC(CL_ERR_INVALID_PARAMETER);

    if(!extraSUs) return rc;

    *pNumNodes = 0;

    rc = clAmsMgmtGetNodeList(gHandle, &nodeBuffer);

    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "Get node list returned [%#x]", rc);
        goto out;
    }        

    /*
     * First try distributing to the extra nodes.
     */
    if(extraNodes > 0)
    {
        for(i = nodeBuffer.count; i < nodeBuffer.count + extraNodes; ++i)
        {
            nodes[i - nodeBuffer.count].type= CL_AMS_ENTITY_TYPE_NODE;
            snprintf((ClCharT*)nodes[i-nodeBuffer.count].name.value, sizeof(nodes[i-nodeBuffer.count].name.value),
                     "%s_Node%d", prefix, i);
            nodes[i-nodeBuffer.count].name.length = strlen((const ClCharT*)nodes[i-nodeBuffer.count].name.value)+1;
            nodes[i-nodeBuffer.count].debugFlags = 1;
        }
        *pNumNodes = extraNodes;
    }

    if(extraSUs <= extraNodes) 
    {
        clHeapFree(nodeBuffer.entity);
        return CL_OK;
    }

    controllers = (ClAmsEntityT*) clHeapCalloc(nodeBuffer.count, sizeof(*controllers));
    workers = (ClAmsEntityT*) clHeapCalloc(nodeBuffer.count, sizeof(*controllers));
    CL_ASSERT(controllers && workers);

    /*
     * Separate controllers and workers as node distribution preference is
     * higher for workers than controllers.
     */
    clOsalMutexLock(gpClCpm->cpmTableMutex);
    for(i = 0 ; i < nodeBuffer.count; ++i)
    {
        ClCpmLT *cpmL = NULL;
        rc = cpmNodeFindLocked(nodeBuffer.entity[i].name.value, &cpmL);
        if(rc != CL_OK)
        {
            /*
             * We skip the controller and worker ordering.
             */
            if(controllers)
            {
                clHeapFree(controllers);
            }
            if(workers)
            {
                clHeapFree(workers);
            }
            controllers = nodeBuffer.entity;
            numControllers = nodeBuffer.count;
            break;
        }
        if(!strcmp(cpmL->classType, "CL_AMS_NODE_CLASS_C"))
        {
            memcpy(workers+numWorkers, nodeBuffer.entity+i, 
                   sizeof(*workers));
            ++numWorkers;
        }
        else
        {
            memcpy(controllers+numControllers, nodeBuffer.entity+i,
                   sizeof(*controllers));
            ++numControllers;
        }
    }
    clOsalMutexUnlock(gpClCpm->cpmTableMutex);

    nodeList = (ClAmsEntityT*) clHeapCalloc(nodeBuffer.count + extraNodes, sizeof(ClAmsEntityT));
    CL_ASSERT(nodeList);
    
    memcpy(nodeList, nodes, sizeof(*nodes)*extraNodes);
    if(workers)
    {
        memcpy(nodeList + extraNodes, workers, 
               sizeof(*workers) * numWorkers);
        clHeapFree(workers);
    }
    if(controllers)
    {
        memcpy(nodeList + extraNodes + numWorkers, controllers,
               sizeof(*controllers) * numControllers);
        clHeapFree(controllers);
    }

    clHeapFree(nodeBuffer.entity);
    extraSUs -= extraNodes;

    for(i = 0; i < (ClUint32T) extraNodes; ++i)
        nodeList[i].debugFlags = 1;

    for(; i < nodeBuffer.count + extraNodes; ++i)
        nodeList[i].debugFlags = 0;
    
    /*
     * Now find nodes that are unmapped to the SUs of this SG
     */
    rc = clAmsMgmtGetSGSUList(gHandle, sgName, &suBuffer);
    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "SG su list returned [%#x]", rc);
        goto out_free;
    }

    for(i = 0; i < suBuffer.count; ++i)
    {
        ClUint32T j;
        rc = clAmsMgmtEntityGetConfig(gHandle, suBuffer.entity+i,
                                      &entityConfig);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "SU get config returned [%#x]", rc);
            goto out_free;
        }
        memcpy(&suConfig, entityConfig, sizeof(suConfig));
        clHeapFree(entityConfig);
        for(j = 0; j < nodeBuffer.count+extraNodes; ++j)
        {
            if(!strncmp((const ClCharT*)nodeList[j].name.value, (const ClCharT*)suConfig.parentNode.entity.name.value,
                        nodeList[j].name.length-1))
            {
                /*
                 * Mark this entry as seen.
                 */
                nodeList[j].debugFlags = 1;
            }
        }
    }

    clLogInfo("AMS", "MIGRATE", "Scanning free node list");
    totalNodes = nodeBuffer.count + extraNodes;
    for(i = 0; (i < totalNodes) && extraSUs ; ++i)
    {
        if(!nodeList[i].debugFlags)
        {
            clLogInfo("AMS", "MIGRATE", "Copying node [%s]", nodeList[i].name.value);
            memcpy(nodes + extraNodes, nodeList+i, sizeof(ClAmsEntityT));
            ++extraNodes;
            --extraSUs;
        }
    }

    /*
     * Distribute the remaining cyclically.
     */
    if(extraSUs && extraNodes)
    {
        ClInt32T index = 0;
        ClInt32T currentNodes = extraNodes;
        while(extraSUs--)
        {
            memcpy(nodes+extraNodes, nodes+index, sizeof(ClAmsEntityT));
            ++index;
            index %= currentNodes;
            ++extraNodes;
        }
    }

    *pNumNodes = extraNodes;
    rc = CL_OK;

    out_free:
    if(suBuffer.entity) clHeapFree(suBuffer.entity);
    if(nodeList) clHeapFree(nodeList);
    
    out:
    return rc;
}                                     
static void cpmMakeSCActiveOrDeputy(const ClGmsClusterNotificationBufferT *notificationBuffer,
                                    ClCpmLocalInfoT *pCpmLocalInfo)
{
    ClUint32T rc = CL_OK;
    ClGmsNodeIdT prevMasterNodeId = gpClCpm->activeMasterNodeId;
    ClBoolT leadershipChanged = notificationBuffer->leadershipChanged;
    
    /*  
     * Check for initial leadership state incase the cluster track from AMF was issued
     * after GMS leader election was done and GMS responded back with a track with a leadership changed
     * set to FALSE for a CURRENT async request from AMF.
     */
    if(leadershipChanged == CL_FALSE && 
       (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId &&
       (ClInt32T) prevMasterNodeId != pCpmLocalInfo->nodeId && 
       gpClCpm->haState == CL_AMS_HA_STATE_NONE)
        leadershipChanged = CL_TRUE;
        
    if (leadershipChanged == CL_TRUE)
    {
        if ( (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId)
        {
            clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                      "Node [%d] has become the leader of the cluster",
                      pCpmLocalInfo->nodeId);

            if(gpClCpm->haState != CL_AMS_HA_STATE_ACTIVE)
            {
                rc = cpmUpdateTL(CL_AMS_HA_STATE_ACTIVE);
                if (rc != CL_OK)
                {
                    clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL,
                               CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc);
                }
            }
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
        }
        else if ((ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId)
        {
            clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                      "Node [%d] has become the deputy of the cluster",
                      pCpmLocalInfo->nodeId);
            /*
             * Deregister the active registration if going from active to standby.
             */
            if(gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE)
            {
                clIocTransparencyDeregister(pCpmLocalInfo->nodeId << CL_CPM_IOC_SLOT_BITS);
            }
            rc = cpmUpdateTL(CL_AMS_HA_STATE_STANDBY);
            if (rc != CL_OK)
            {
                clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL,
                           CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc);
            }
        }

        if ((gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE) && 
            ( (ClInt32T) notificationBuffer->leader != pCpmLocalInfo->nodeId))
        {
            clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                       "Node [%d] is changing HA state from active to standby",
                       pCpmLocalInfo->nodeId);
              
            /*
             * Deregister the entry during a state change.
             */
            if ( (ClInt32T) notificationBuffer->deputy != pCpmLocalInfo->nodeId)
            {
                clIocTransparencyDeregister((pCpmLocalInfo->nodeId) << CL_CPM_IOC_SLOT_BITS);
            }

            /*
             * Inform AMS to become standby and read the checkpoint.
             */
            if ((gpClCpm->cpmToAmsCallback != NULL) && 
                (gpClCpm->cpmToAmsCallback->amsStateChange != NULL))
            {
                clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                           "Informing AMS on node [%d] to change state "
                           "from active to standby...",
                           pCpmLocalInfo->nodeId);

                rc = gpClCpm->cpmToAmsCallback->amsStateChange(CL_AMS_STATE_CHANGE_ACTIVE_TO_STANDBY |
                                                               CL_AMS_STATE_CHANGE_USE_CHECKPOINT);
                if (CL_OK != rc)
                {
                    clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                                 "AMS state change from active to standby "
                                 "returned [%#x]",
                                 rc);
                }

                cpmWriteNodeStatToFile("AMS", CL_NO);

                if(!gClAmsSwitchoverInline)
                {
                    if (((notificationBuffer->numberOfItems == 0) &&
                         (notificationBuffer->notification == NULL)) &&
                        gpClCpm->polling &&
                        (gpClCpm->nodeLeaving == CL_FALSE))
                    {
                        /*
                         * This indicates that leader election API of
                         * GMS was called.  Since this involves
                         * interaction among only system controllers,
                         * we don't need to restart the worker nodes
                         * like in the case of split brain handling.
                         */
                        
                        cpmActive2Standby(CL_NO);
                    }
                    else if (( (ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId) && gpClCpm->polling && (gpClCpm->nodeLeaving == CL_FALSE))
                    {
                        /*
                         * We try and handle a possible split brain
                         * since presently GMS shouldnt be reelecting.
                         * And even if it does, its pretty much
                         * invalid with respect to AMS where you could
                         * land up with 2 actives.
                         */
                     
                        /*
                         * We arent expected to return back.
                         */
                        cpmActive2Standby(CL_NO);
                    }
                }
            }

            /*
             * Bug 4168:
             * Updating the data structure gpClCpm, when the active becomes
             * standby.
             */
            gpClCpm->haState = CL_AMS_HA_STATE_STANDBY;
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
            if(gClAmsSwitchoverInline)
            {
                /*
                 *Re-register with active.
                 */
                clOsalMutexUnlock(&gpClCpm->clusterMutex);
                cpmSwitchoverActive();
                clOsalMutexLock(&gpClCpm->clusterMutex);
            }
        }
        else if ((gpClCpm->haState == CL_AMS_HA_STATE_STANDBY) && 
                 ( (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId))
        {
            rc = cpmStandby2Active(prevMasterNodeId, 
                                   notificationBuffer->deputy);
            if (CL_OK != rc)
            {
                return;
            }
        }
        else if ((gpClCpm->haState == CL_AMS_HA_STATE_NONE) && 
                 ( (ClInt32T) notificationBuffer->leader ==
                  pCpmLocalInfo->nodeId))
        {
            /*
             * Bug 4411:
             * Added the if-else block.
             * Calling the AMS initialize only if both the callback pointers
             * are not NULL.
             * FIXME: This change is sort of workaround for 2.2.
             * Neat solution is to protect gpClCpm structure and fields properly
             */
            if ((gpClCpm->amsToCpmCallback != NULL) &&
                (gpClCpm->cpmToAmsCallback != NULL))
            {
                clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Starting AMS in active mode...");

                rc = clAmsStart(&gAms,CL_AMS_INSTANTIATE_MODE_ACTIVE | CL_AMS_INSTANTIATE_USE_CHECKPOINT);
                /*
                 * Bug 4092:
                 * If the AMS intitialize fails then do the 
                 * self shut down.
                 */
                if (CL_OK != rc)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMF, error = [%#x]", rc);

                    gpClCpm->amsToCpmCallback = NULL;
                    cpmReset(NULL,NULL);
                    return;
                }
            }
            else
            {
                rc = CL_CPM_RC(CL_ERR_NULL_POINTER);
                 
                if (!gpClCpm->polling)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "AMF finalize called before AMF initialize during node shutdown.");
                }
                else
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "Unable to initialize AMF, error = [%#x]", rc);
                     
                    cpmRestart(NULL,NULL);
                }
                return;
            }
             
            gpClCpm->haState = CL_AMS_HA_STATE_ACTIVE;
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
        }
        /*
         * There could be more than 1 standby SC. 
         * Every none HA-state SC except the master is updated to become to standby SC.        
         */
        else if (gpClCpm->haState == CL_AMS_HA_STATE_NONE)
        {
            /*
             * Bug 4411:
             * Added the if-else block.
             * Calling the clAmsStart only if both the callback pointers
             * are not NULL.
             * FIXME: This change is sort of workaround for 2.2.
             * Neat solution is to protect gpClCpm structure and fields properly
             */
            if ((gpClCpm->amsToCpmCallback != NULL) &&
                (gpClCpm->cpmToAmsCallback != NULL))
            {
                clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                           "Starting AMS in standby mode...");

                rc = clAmsStart(&gAms,CL_AMS_INSTANTIATE_MODE_STANDBY);
                /*
                 * Bug 4092:
                 * If the AMS initialize fails then do the 
                 * self shut down.
                 */
                if (CL_OK != rc)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMS, error = [%#x]", rc);

                    gpClCpm->amsToCpmCallback = NULL;
                    cpmRestart(NULL,NULL);
                    return;
                }
            }
            else
            {
                rc = CL_CPM_RC(CL_ERR_NULL_POINTER);
                 
                if (!gpClCpm->polling)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"AMS finalize called before AMS initialize during node shutdown.");
                }
                else
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMS, error = [%#x]", rc);
                    cpmRestart(NULL,NULL);
                }
                return;
            }

            gpClCpm->haState = CL_AMS_HA_STATE_STANDBY;
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
            if(gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel)
            {
                cpmInitializeStandby();
            }
        }
        else
        {
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
        }

        clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_CPM,
                    "HA state of node [%s] with node ID [%d] is [%s], "
                    "Master node is [%d]",
                    pCpmLocalInfo->nodeName,
                    pCpmLocalInfo->nodeId,
                    gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE  ? "Active":
                    gpClCpm->haState == CL_AMS_HA_STATE_STANDBY ? "Standby":
                    "None",
                    gpClCpm->activeMasterNodeId);
    }
    else
    {
        /*
         * Always update the deputy node ID.  It may be that this
         * path is reached because a deputy node failed.
         */
        gpClCpm->deputyNodeId = notificationBuffer->deputy;

        if (CL_CPM_IS_ACTIVE())
        {
            if(notificationBuffer->notification && 
               notificationBuffer->numberOfItems == 1)
            {

                if (CL_GMS_NODE_LEFT ==
                    notificationBuffer->notification->clusterChange)
                {
                    cpmFailoverNode(notificationBuffer->notification->
                                    clusterNode.nodeId, CL_FALSE);
                }
                else
                {
                    clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, 
                                "Ignoring notification of type [%d] for node [%d]",
                                notificationBuffer->notification->clusterChange,
                                notificationBuffer->notification->clusterNode.nodeId);
                }
            }
            else if(notificationBuffer->notification)
            {
                clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, 
                            "Ignoring notification with number of items [%d], first type [%d]",
                            notificationBuffer->numberOfItems,
                            notificationBuffer->notification->clusterChange);
            }
        }
        else if ((gpClCpm->haState == CL_AMS_HA_STATE_NONE) && ( (ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId))
        {
            if(CL_GMS_NODE_JOINED ==
               notificationBuffer->notification->clusterChange)
            {
                cpmStandbyRecover(notificationBuffer);
            }
            else if(gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel)
            {
                cpmStandbyRecover(notificationBuffer);
                cpmInitializeStandby();
            }
        }
    }
    return ;
}
static ClRcT
clLogSvrStreamEntryUnpackNAdd(ClLogSvrEoDataT        *pSvrEoEntry,
                              ClLogSvrCommonEoDataT  *pSvrCommonEoEntry,
                              ClBufferHandleT         msg,
                              ClUint32T               dsId)
{
    ClRcT             rc              = CL_OK;
    SaNameT           streamName      = {0};
    SaNameT           streamScopeNode = {0};
    ClUint32T         compTableSize   = 0;
    ClCntNodeHandleT  hSvrStreamNode   = CL_HANDLE_INVALID_VALUE;
    ClLogStreamKeyT   *pStreamKey     = NULL;
    ClStringT shmName = {0};
    ClStringT fileName = {0};
    ClStringT fileLocation = {0};

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogSvrStreamTableGet(pSvrEoEntry);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clLogSvrStreamTableCreate(): rc[0x %x]\n", rc));
        return rc;
    }
    rc = clXdrUnmarshallSaNameT(msg, &streamName);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrUnmarshallSaNameT(): rc[0x %x]\n", rc));
        return rc;
    }
    CL_LOG_DEBUG_VERBOSE(("streamName: %*s", streamName.length, streamName.value));

    rc = clXdrUnmarshallSaNameT(msg, &streamScopeNode);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrUnmarshallSaNameT(): rc[0x %x]\n", rc));
        return rc;
    }
    CL_LOG_DEBUG_VERBOSE(("streamScopeNode: %*s", streamScopeNode.length, streamScopeNode.value));

    rc = clXdrUnmarshallClStringT(msg, &fileName);
    if(CL_OK != rc)
    {
        CL_LOG_DEBUG_ERROR(("clXdrUnmarshallClStringT(): rc[%#x]\n", rc));
        return rc;
    }
    rc = clXdrUnmarshallClStringT(msg, &fileLocation);
    if(CL_OK != rc)
    {
        CL_LOG_DEBUG_ERROR(("clXdrUnmarshallClStringT(): rc[%#x]\n", rc));
        return rc;
    }

    rc = clXdrUnmarshallClUint32T(msg, &compTableSize);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrUnmarshallClUint32T(): rc[0x %x]\n", rc));
        return rc;
    }
    CL_LOG_DEBUG_VERBOSE(("compSize : %u", compTableSize));

    rc = clLogStreamKeyCreate(&streamName, &streamScopeNode, pSvrCommonEoEntry->maxStreams, &pStreamKey);
    if( CL_OK != rc )
    {
        return rc;
    }
    rc = clLogShmNameCreate(&streamName,&streamScopeNode,&shmName);
    if( CL_OK != rc )
    {
        return rc;
    }

    clLogInfo("LOG","CRT","Recreating log stream [%*s] shared memory [%*s] located at [%*s] from persistent checkpoint",streamName.length,streamName.value,shmName.length,shmName.pValue,streamScopeNode.length, streamScopeNode.value);

    rc = clLogSvrStreamEntryAdd(pSvrEoEntry, pSvrCommonEoEntry, pStreamKey, &shmName, &hSvrStreamNode);
    clHeapFree(shmName.pValue);
    shmName.pValue=NULL;
    shmName.length=0;

    if (CL_ERR_DUPLICATE == CL_GET_ERROR_CODE(rc))    /* But if it is a duplicate stream should we do the items below? (if so we need to load hSvrStreamNode...) */
    {
        return rc;
    }

    if( CL_OK != rc )
    {
        clLogStreamKeyDestroy(pStreamKey);
        return rc;
    }

    rc = clLogSvrCompEntryRecreate(pSvrCommonEoEntry, pSvrEoEntry,hSvrStreamNode, msg, compTableSize);
    if(( CL_OK != rc )&&(CL_ERR_DUPLICATE != CL_GET_ERROR_CODE(rc)))
    {
        CL_LOG_CLEANUP(clCntNodeDelete(pSvrEoEntry->hSvrStreamTable, hSvrStreamNode), CL_OK);
        return rc;
    }

    rc = clLogSvrShmOpenNFlusherCreate(pSvrEoEntry, &streamName, &streamScopeNode, &fileName, &fileLocation, hSvrStreamNode, dsId);
    if (( CL_OK != rc )&&(CL_ERR_DUPLICATE != CL_GET_ERROR_CODE(rc)))
    {
        CL_LOG_DEBUG_ERROR(("clLogSvrShmOpenAndFlusherCreate(): rc[0x %x]\n", rc));
        CL_LOG_CLEANUP(clCntNodeDelete(pSvrEoEntry->hSvrStreamTable, hSvrStreamNode), CL_OK);
    }

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
ClRcT cpmGmsInitialize(void)
{
    ClRcT rc = CL_OK;
    ClTimerTimeOutT timeOut = {0, 0};

    ClGmsCallbacksT cpmGmsCallbacks = { NULL, cpmClusterTrackCallBack, NULL, NULL };
    
    gpClCpm->version.releaseCode = 'B';
    gpClCpm->version.majorVersion = 0x01;
    gpClCpm->version.minorVersion = 0x01;
    rc = clGmsInitialize(&gpClCpm->cpmGmsHdl,
                         &cpmGmsCallbacks,
                         &gpClCpm->version);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                   "Failed to do GMS initialization, error [%#x]",
                   rc);
        gpClCpm->cpmGmsHdl = CL_HANDLE_INVALID_VALUE;
        goto failure;
    }

    rc = clOsalMutexLock(&gpClCpm->cpmGmsMutex);
    CL_CPM_CHECK_1(CL_LOG_SEV_ERROR, CL_CPM_LOG_1_OSAL_MUTEX_LOCK_ERR, rc, rc,
                   CL_LOG_HANDLE_APP);

    rc = clGmsClusterTrack(gpClCpm->cpmGmsHdl, CL_GMS_TRACK_CHANGES_ONLY | CL_GMS_TRACK_CURRENT, NULL);
    if (CL_OK != rc)
    {
        clOsalMutexUnlock(&gpClCpm->cpmGmsMutex);
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                   "The GMS cluster track function failed, error [%#x]",
                   rc);
        goto failure;
    }

    /*
     * Wait for the GMS callback
     */
    retry:
#ifdef VXWORKS_BUILD
    timeOut.tsSec = gpClCpm->cpmGmsTimeout + 20;
#else
    timeOut.tsSec = gpClCpm->cpmGmsTimeout + 60;  /* There is no reason to not wait for a long time.  100% cpu could cause GMS to come up slowly */
#endif
    timeOut.tsMilliSec = 0;

    clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
              "Node [%s] waiting for GMS cluster track callback for [%d.%d] secs",
              gpClCpm->pCpmLocalInfo->nodeName, timeOut.tsSec, timeOut.tsMilliSec);

    rc = clOsalCondWait(&gpClCpm->cpmGmsCondVar,
                        &gpClCpm->cpmGmsMutex,
                        timeOut);
    if (CL_OK != rc)
    {
        if(gpClCpm->trackCallbackInProgress)
        {
            clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                         "GMS cluster track callback in progress. Waiting for it to complete ...");
            goto retry;
        }
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                   "Failed to receive GMS cluster track callback, "
                   "error [%#x].",
                   rc);
        clOsalMutexUnlock(&gpClCpm->cpmGmsMutex);
        goto failure;
    }

    rc = clOsalMutexUnlock(&gpClCpm->cpmGmsMutex);
    CL_CPM_CHECK_1(CL_LOG_SEV_ERROR, CL_CPM_LOG_1_OSAL_MUTEX_UNLOCK_ERR, rc,
                   rc, CL_LOG_HANDLE_APP);

    return CL_OK;

    failure:
    return rc;
}
static ClRcT
clLogMasterStreamTableRecreate(ClLogSvrCommonEoDataT  *pCommonEoEntry,
                               ClBufferHandleT        hFileEntryBuf,
                               ClLogFileDataT         *pFileData)
{
    ClRcT                   rc              = CL_OK;
    ClLogStreamKeyT         streamKey       = {{0}};
    ClLogStreamKeyT         *pStreamKey     = NULL;
    ClLogMasterStreamDataT  *pStreamData    = NULL;
    ClCntNodeHandleT        hStreamNode     = CL_HANDLE_INVALID_VALUE;
    ClUint32T               bitNum          = 0;
    ClLogMasterEoDataT      *pMasterEoEntry = NULL;

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogMasterEoEntryGet(&pMasterEoEntry, &pCommonEoEntry);
    if( CL_OK != rc )
    {
        return rc;
    }

    rc = clXdrUnmarshallSaNameT(hFileEntryBuf, &(streamKey.streamName));
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrMarshallSaNameT(): rc[0x %x]", rc));
        return rc;
    }

    rc = clXdrUnmarshallSaNameT(hFileEntryBuf, &(streamKey.streamScopeNode));
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrMarshallSaNameT(): rc[0x %x]", rc));
        return rc;
    }

    rc = clLogStreamKeyCreate(&streamKey.streamName, &streamKey.streamScopeNode,
                              pCommonEoEntry->maxStreams, &pStreamKey);
    if( CL_OK != rc )
    {
        return rc;
    }

    pStreamData = (ClLogMasterStreamDataT*) clHeapCalloc(1, sizeof(ClLogMasterStreamDataT));
    if( NULL == pStreamData )
    {
        CL_LOG_DEBUG_ERROR(("clHeapCalloc()"));
        clLogStreamKeyDestroy(pStreamKey);
        return rc;
    }

    rc = clXdrUnmarshallClUint64T(hFileEntryBuf, &(pStreamData->streamMcastAddr));
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrMarshallClUint64T(): rc[0x %x]", rc));
        clHeapFree(pStreamData);
        clLogStreamKeyDestroy(pStreamKey);
        return rc;
    }

    rc = clXdrUnmarshallClUint16T(hFileEntryBuf, &(pStreamData->streamId));
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clXdrMarshallClUint16T(): rc[0x %x]", rc));
        clHeapFree(pStreamData);
        clLogStreamKeyDestroy(pStreamKey);
        return rc;
    }

    rc = clCntNodeAddAndNodeGet(pFileData->hStreamTable,
                                (ClCntKeyHandleT) pStreamKey,
                                (ClCntDataHandleT) pStreamData,
                                NULL, &hStreamNode);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clCntNodeAdd(): rc[0x %x]", rc));
        clHeapFree(pStreamData);
        clLogStreamKeyDestroy(pStreamKey);
        return rc;
    }
    /* Find out the partiuclar stream is still valid */
    if( strncmp(gStreamScopeGlobal, (const ClCharT *)pStreamKey->streamScopeNode.value,
                pStreamKey->streamScopeNode.length)
            &&
            CL_FALSE == clLogMasterStreamIsValid(&pStreamKey->streamScopeNode))
    {
        /*
         * marking this as invalid by assigining CL_IOC_RESERVED_ADDRESS
         * so that streamMcastAddr will not be allocated & bit will not be set
         * numActive streams count also will be valid
         */
        pStreamData->streamMcastAddr = CL_IOC_RESERVED_ADDRESS;
        clLogNotice(CL_LOG_AREA_FILE_OWNER, CL_LOG_CTX_FO_INIT,
                    "Invalidating the stream [%.*s:%.*s]",
                    pStreamKey->streamScopeNode.length, pStreamKey->streamScopeNode.value,
                    pStreamKey->streamName.length, pStreamKey->streamName.value);
    }
    if( CL_IOC_RESERVED_ADDRESS != pStreamData->streamMcastAddr )
    {
        bitNum = pStreamData->streamMcastAddr - pMasterEoEntry->startMcastAddr;
        CL_LOG_DEBUG_TRACE(("bitNUm: %d  pStreamData->streamMcastAddr : %lld \n", bitNum,
                            pStreamData->streamMcastAddr));
        rc = clBitmapBitSet(pMasterEoEntry->hAllocedAddrMap, bitNum);
        if( CL_OK != rc )
        {
            CL_LOG_DEBUG_ERROR(("clBitmapBitClear()"));
            CL_LOG_CLEANUP(clCntNodeDelete(pFileData->hStreamTable, hStreamNode), CL_OK);
        }
        pFileData->nActiveStreams++;
        clLogInfo(CL_LOG_AREA_MASTER, CL_LOG_CTX_CKPT_READ,
                  "Active stream [%.*s:%.*s] has been added",
                  pStreamKey->streamScopeNode.length, pStreamKey->streamScopeNode.value,
                  pStreamKey->streamName.length, pStreamKey->streamName.value);
    }
    CL_LOG_DEBUG_TRACE(("Exit"));
    return CL_OK;
}
static ClRcT _clPluginHelperGetIpNodeAddress(const ClCharT *xportType, const ClCharT *devIf, ClCharT *hostAddress, ClCharT *networkMask, ClCharT *broadcast, ClUint32T *ipAddressMask, ClCharT *xportSubnetPrefix)
{
    ClCharT envSubNetType[CL_MAX_FIELD_LENGTH] = { 0 };
    ClCharT xportSubnet[CL_MAX_FIELD_LENGTH] = { 0 };
    ClCharT *subnetMask = NULL;
    ClCharT *subnetPrefix = NULL;
    ClUint32T CIDR, ipMask, ip, mask;
    ClRcT rc;
    
    if (!xportType)
    {
        return CL_ERR_INVALID_PARAMETER;
    } 
    else 
    {
        snprintf(envSubNetType, CL_MAX_FIELD_LENGTH, "ASP_%s_SUBNET", xportType);
        subnetMask = getenv(envSubNetType);
        if (subnetMask == NULL) 
        {
            subnetMask = ASP_PLUGIN_SUBNET_DEFAULT;
        }
        subnetPrefix = strrchr(subnetMask, '/');
        if(!subnetPrefix)
        {
            subnetPrefix = ASP_PLUGIN_SUBNET_PREFIX_DEFAULT; 
        }
        else 
        {
            ++subnetPrefix;
        }
        if(! (CIDR = atoi(subnetPrefix) ) )
        {
            clLogInfo("IOC", CL_LOG_PLUGIN_HELPER_AREA, "%s", subnetMask);
            return CL_ERR_INVALID_PARAMETER;
        }
        xportSubnetPrefix[0] = 0;
        strncat(xportSubnetPrefix, subnetPrefix, CL_MAX_FIELD_LENGTH-1);
        snprintf(xportSubnet, sizeof(xportSubnet), "%s", subnetMask);
        mask = _clPluginHelperBitFillRShift(CIDR);
        _clPluginHelperConvertInternetToHostAddress(&ip, xportSubnet);

        /* network address */
        ipMask = (ip & mask);


        /* Try to get address from devif */
        
        rc = CL_OK+1;  /* start with any error condition, so the if below this one will be taken  */
        if (clParseEnvBoolean("ASP_UDP_USE_EXISTING_IP"))
        {
            rc = _clPluginHelperDevToIpAddress(devIf, hostAddress);
            if (rc == CL_OK) clLogInfo("IOC",CL_LOG_PLUGIN_HELPER_AREA,"Use existing IP address [%s] as this nodes transport address.", hostAddress);
            else clLogError("IOC",CL_LOG_PLUGIN_HELPER_AREA,"Configured to use an existing IP address for message transport.  But address lookup failed on device [%s] error [0x%x]", devIf, rc);
        }
        
        if (rc != CL_OK)
        {
             /* Automatic assignment of IP address */
            _clPluginHelperConvertHostToInternetAddress(ipMask + gIocLocalBladeAddress, hostAddress);
        }

        _clPluginHelperConvertHostToInternetAddress(mask, networkMask);
        _clPluginHelperConvertHostToInternetAddress(ip | ~mask, broadcast);
        *ipAddressMask = ipMask;
    }
    return CL_OK;
}
/*
 * This is the main flusher therad function. This is where the flusher action
 * starts.
 */
void*
clLogFlusherStart(void  *pData)
{
    ClRcT              rc             = CL_OK;
    ClLogSvrStreamDataT  *pStreamData = (ClLogSvrStreamDataT*) pData;
    ClLogStreamHeaderT   *pHeader     = pStreamData->pStreamHeader;
    ClTimerTimeOutT      timeout      = {0, 0};
    ClOsalTaskIdT        taskId       = CL_HANDLE_INVALID_VALUE;

    clLogDebug(CL_LOG_AREA_SVR, CL_LOG_CTX_BOOTUP,
            "Flusher started for stream [%.*s]", pStreamData->shmName.length, pStreamData->shmName.pValue);
    timeout.tsSec = pHeader->flushInterval / (1000L * 1000L * 1000L);
    timeout.tsMilliSec
        = (pHeader->flushInterval % (1000L * 1000L * 1000L)) / (1000L * 1000L);

    clLogDebug("LOG", "FLS", "timeout: %u sec %u millisec", timeout.tsSec, timeout.tsMilliSec);

    rc = clLogServerStreamMutexLockFlusher(pStreamData);
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "CL_LOG_LOCK(): rc[0x %x]", rc);
        pHeader->streamStatus = CL_LOG_STREAM_THREAD_EXIT;
        return NULL;
    }
    if ((CL_LOG_STREAM_HEADER_STRUCT_ID != pHeader->struct_id) || (CL_LOG_STREAM_HEADER_UPDATE_COMPLETE != pHeader->update_status))
    {/* Stream Header is corrupted so reset Header parameters */
       clLogStreamHeaderReset(pHeader); 
    }
    /*
     * Create a thread for flush interval
     */
    if( CL_LOG_SEM_MODE == clLogLockModeGet() )
    {
        rc = clLogFlushIntervalThreadCreate(pStreamData, &taskId);
        if( CL_OK != rc )
        {
            clLogWarning("SVR", "FLU", "Flusher interval thread create failed"
                    "flushFrequency function will still work..continuing...");
            rc = CL_OK;
            taskId = CL_HANDLE_INVALID_VALUE;
        }
    }

    while( gClLogSvrExiting == CL_FALSE )
    {
        CL_LOG_DEBUG_TRACE(("startIdx in server: %d  startAck  %d \n",
                    pHeader->recordIdx, pHeader->startAck));
        do
        {
            CL_LOG_DEBUG_TRACE(("recordIdx: %u startAck: %u  cnt %d",
                        pHeader->recordIdx, pHeader->startAck, 
                        pStreamData->ackersCount +
                        pStreamData->nonAckersCount));
#ifndef POSIX_BUILD
            rc = clLogServerStreamCondWait(pStreamData,
                                           &pHeader->flushCond,
                                           timeout);
#else
            rc = clLogServerStreamCondWait(pStreamData,
                                           NULL,
                                           timeout);
#endif
            if( gClLogSvrExiting == CL_TRUE 
                    || ( (CL_OK != CL_GET_ERROR_CODE(rc)) && 
                        (CL_ERR_TIMEOUT != CL_GET_ERROR_CODE(rc))) )
            { /* Log service is exiting or Stream is closed so come out of polling loop */
                pHeader->update_status = CL_LOG_STREAM_HEADER_UPDATE_INPROGRESS;
                pHeader->streamStatus = CL_LOG_STREAM_CLOSE;
            }
        }while( (CL_LOG_STREAM_CLOSE != pHeader->streamStatus) &&
                (0 == abs(pHeader->recordIdx - pHeader->startAck)));

        if( gClLogSvrExiting || CL_LOG_STREAM_CLOSE == pHeader->streamStatus )
        {
            clLogInfo("SVR", "FLU", "Stream status: CLOSE...Exiting flusher [%lu] "
                    " [%lu]", (unsigned long)pStreamData->flusherId, (long unsigned int)pthread_self());
            pHeader->streamStatus = CL_LOG_STREAM_THREAD_EXIT;
            pHeader->update_status = CL_LOG_STREAM_HEADER_UPDATE_COMPLETE;
            goto exitFlusher;
        }
        rc = clLogFlusherRecordsFlush(pStreamData);
        if( CL_OK != rc )
        {
            if(pHeader->streamStatus == CL_LOG_STREAM_CLOSE)
            {
                break;
            }
        }    

    }
    pHeader->streamStatus = CL_LOG_STREAM_THREAD_EXIT;
exitFlusher:

    if( CL_HANDLE_INVALID_VALUE != taskId )
    {
        /* Flusher interval thread has been created, so signal to that guy and
         * wait on the variable 
         */
        clLogFlushIntervalThreadJoin(pStreamData, taskId);
        taskId = CL_HANDLE_INVALID_VALUE;
    }
    clLogInfo("SVR", "FLU", "Flusher for stream [%.*s] is exiting..Id [%llu]", 
            pStreamData->shmName.length, pStreamData->shmName.pValue,
            pStreamData->flusherId);
    rc = clLogServerStreamMutexUnlock(pStreamData);
    if( CL_OK != rc )
    {
        clLogError("SVR", "FLU", "Faild to unlock the stream");
    }

    CL_LOG_DEBUG_TRACE(("Exit"));
    return NULL;
}    
ClRcT clLogSvrInitialize(ClUint32T argc,ClCharT   *argv[])
{
    SaAmfCallbacksT     callbacks = {0};
    SaVersionT          version;
    
    ClRcT            rc            = CL_OK;
    ClBoolT          *pCookie      = NULL;
	
    clLogCompName =(ClCharT*) "LOG"; /* Override generated eo name with a short name for our server */
    gClLogServer = CL_FALSE;  /* Mark me as the log server */

    clLogInfo(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED, "Log Server initialization started...");

    clAppConfigure(&clEoConfig,clEoBasicLibs,clEoClientLibs);

    version.releaseCode  = 'B';
    version.majorVersion = 0x01;
    version.minorVersion = 0x01;

    callbacks.saAmfHealthcheckCallback          = NULL; /* rarely necessary because SAFplus monitors the process */
    callbacks.saAmfComponentTerminateCallback   = clLogSvrTerminate;
    callbacks.saAmfCSISetCallback               = NULL;
    callbacks.saAmfCSIRemoveCallback            = NULL;
    callbacks.saAmfProtectionGroupTrackCallback = NULL;        
    callbacks.saAmfProxiedComponentInstantiateCallback    = NULL;
    callbacks.saAmfProxiedComponentCleanupCallback    = NULL;

    rc = saAmfInitialize(&amfHandle, &callbacks, &version);
    if( SA_AIS_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("saAmfInitialize(): rc[0x %x]", rc));
        return rc;
    }
          

    rc = saAmfComponentNameGet(amfHandle, &logServerName);
    if( SA_AIS_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("saAmfComponentNameGet(): rc[0x %x]", rc));
        saAmfFinalize(amfHandle);
        CL_LOG_CLEANUP(clLogSvrEoDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrEoDataFree(), CL_OK);
        clHeapFree(pCookie);
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogStreamOwnerEoDataFree(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        return rc;
    }
    rc = saAmfComponentRegister(amfHandle, &logServerName, NULL);
    if( SA_AIS_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("saAmfComponentRegister(): rc[0x %x]", rc));
        CL_LOG_CLEANUP(clLogSvrEoDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrEoDataFree(), CL_OK);
        clHeapFree(pCookie);
        CL_LOG_CLEANUP(clLogStreamOwnerLocalShutdown(), CL_OK);
        CL_LOG_CLEANUP(clLogStreamOwnerEoDataFree(), CL_OK);
        CL_LOG_CLEANUP(clLogSvrCommonDataFinalize(), CL_OK);
        CL_LOG_CLEANUP(clIdlHandleFinalize(shLogDummyIdl), CL_OK);
        saAmfFinalize(amfHandle);
        return rc;
    }   

    clLogNotice(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED, "Log Server partially up");

    CL_LOG_DEBUG_TRACE(("Exit"));
    return CL_OK;					    
}
static ClRcT
clLogFlusherRecordsFlush(ClLogSvrStreamDataT  *pStreamData)
{    
    ClRcT     rc        = CL_OK;
    ClLogStreamHeaderT     *pHeader           = pStreamData->pStreamHeader;
    ClLogSvrCommonEoDataT  *pSvrCommonEoEntry = NULL;
    ClLogSvrEoDataT        *pSvrEoEntry       = NULL;
    ClUint32T              nFlushableRecords  = 0;
    ClUint32T              nFlushedRecords    = 0;
    ClLogFlushRecordT      flushRecord = {0};

    CL_LOG_DEBUG_TRACE(("Enter"));

    if( (pStreamData->fileOwnerAddr != clIocLocalAddressGet()) && 
        (0 == pStreamData->ackersCount + pStreamData->nonAckersCount) )
    {
        clLogInfo("LOG", "FLS", "No one has registered for the Stream");
        return CL_OK;
    }    

    rc = clLogSvrEoEntryGet(&pSvrEoEntry, &pSvrCommonEoEntry);
    if( CL_OK != rc )
    {
        return rc;
    }            



    CL_LOG_DEBUG_TRACE((" recordIdx: %d startAck : %d \n", pHeader->recordIdx,
                pHeader->startAck));

    if (pHeader->recordIdx < pHeader->startAck)
    {  /* Ring buffer wraparound Case */
        nFlushableRecords = (pHeader->recordIdx + pHeader->maxRecordCount) - pHeader->startAck;
    }
    else
    {
        nFlushableRecords = pHeader->recordIdx - pHeader->startAck;
    }    

    flushRecord.fileName.pValue = (ClCharT*) clHeapCalloc(1, pStreamData->fileName.length+1);
    CL_ASSERT(flushRecord.fileName.pValue != NULL);
    flushRecord.fileName.length = pStreamData->fileName.length;
    memcpy(flushRecord.fileName.pValue, pStreamData->fileName.pValue, flushRecord.fileName.length);
    
    flushRecord.fileLocation.pValue = (ClCharT*) clHeapCalloc(1, pStreamData->fileLocation.length+1);
    CL_ASSERT(flushRecord.fileLocation.pValue != NULL);
    flushRecord.fileLocation.length = pStreamData->fileLocation.length;
    memcpy(flushRecord.fileLocation.pValue, pStreamData->fileLocation.pValue,
           flushRecord.fileLocation.length);

    flushRecord.fileOwnerAddr = pStreamData->fileOwnerAddr;
    flushRecord.seqNum = pStreamData->seqNum;
    flushRecord.multicast = -1;
    flushRecord.recordSize = pHeader->recordSize;

    while( nFlushableRecords > 0 )
    {
        nFlushedRecords = (nFlushableRecords > pSvrEoEntry->maxFlushLimit)
            ? pSvrEoEntry->maxFlushLimit : nFlushableRecords;

        rc = clLogFlusherRecordsGetMcast(pStreamData, nFlushedRecords, &flushRecord);
        if( CL_OK == rc )
        {
            pHeader->update_status = CL_LOG_STREAM_HEADER_UPDATE_INPROGRESS;
            pHeader->startAck += nFlushedRecords;
            pHeader->startAck %= (pHeader->maxRecordCount);
            pStreamData->seqNum += nFlushedRecords;
            nFlushableRecords -= nFlushedRecords;
            CL_LOG_DEBUG_TRACE(("startAck: %u remaining: %u",pHeader->startAck, nFlushableRecords));
            /* FIXME: put the number of overwritten records in log */
            if( 0 != pHeader->numOverwrite )
            {
                pHeader->numDroppedRecords = pHeader->numOverwrite;
                pHeader->numOverwrite = 0;
                CL_LOG_DEBUG_TRACE(("Log buffer full. [%d] records have been dropped", pHeader->numDroppedRecords));
            }
            pHeader->update_status = CL_LOG_STREAM_HEADER_UPDATE_COMPLETE;
        }
        else
        { 
            break;
        }
    }

    rc = clLogServerStreamMutexUnlock(pStreamData);
	if( CL_OK != rc )
    {
        clLogError("SVR", "FLU", "Failed to unlock the stream");
    }

    logRecordsFlush(&flushRecord);
    clLogServerStreamMutexLockFlusher(pStreamData);

    CL_LOG_DEBUG_TRACE(("Exit"));
    return CL_OK;
}    
ClRcT
clAmsGetFaultReport(
        CL_IN  const SaNameT  *compName,
        CL_IN  ClAmsLocalRecoveryT  recommendedRecovery,
        CL_IN  ClUint64T instantiateCookie)
{

    ClRcT  rc = CL_OK;
    ClUint32T  escalation = 0;
    ClAmsEntityRefT  entityRef = {{CL_AMS_ENTITY_TYPE_ENTITY},0,0};

    AMS_FUNC_ENTER (("\n"));

    if(!compName) 
        return CL_AMS_RC(CL_ERR_INVALID_PARAMETER);

    /*
     * First find the name reported by the fault API in the component database
     * If the name is not found in the component database it means that its a node
     * level fault escalation. In this case find the node in the node database.
     */

    memcpy (&entityRef.entity.name, compName, sizeof (SaNameT));
    entityRef.entity.type = CL_AMS_ENTITY_TYPE_COMP; 
    
    AMS_CALL ( clOsalMutexLock(gAms.mutex));

    if ( (rc = clAmsEntityDbFindEntity(&gAms.db.entityDb[CL_AMS_ENTITY_TYPE_COMP],&entityRef)) == CL_OK )
    {
        ClUint64T currentInstantiateCookie = 0;
        ClAmsCompT *comp = (ClAmsCompT*)entityRef.ptr;
        clLogInfo("COMP", "FAILURE", "Processing fault for component [%s], instantiate Cookie [%lld]", comp->config.entity.name.value, instantiateCookie);
        
        currentInstantiateCookie = comp->status.instantiateCookie;
        if(instantiateCookie && instantiateCookie < currentInstantiateCookie)
        {
            clLogInfo("COMP", "FAILURE", 
                      "Ignoring fault for component [%s], instantiation identifier [%lld] "
                      "as component has already been recovered with instantiation identifier [%lld]",
                      comp->config.entity.name.value, instantiateCookie,
                      comp->status.instantiateCookie);
            goto exitfn;
        }
        AMS_CHECK_RC_ERROR ( clAmsPeEntityFaultReport(
                    entityRef.ptr,
                    &recommendedRecovery,
                    &escalation) );

    }

    else
    {

        if ( CL_GET_ERROR_CODE (rc) != CL_ERR_NOT_EXIST )
        {
            clLogWarning("COMP", "FAILURE", "Unable to find component [%s:%d] in AMS database", 
                         compName->value, compName->length);
            goto exitfn;
        }

         /*
          * See if its node level fault escalation
          */

         entityRef.entity.type = CL_AMS_ENTITY_TYPE_NODE;

         AMS_CHECK_RC_ERROR( clAmsEntityDbFindEntity(
                     &gAms.db.entityDb[CL_AMS_ENTITY_TYPE_NODE],
                     &entityRef) ); 
         
         AMS_CHECK_RC_ERROR( clAmsPeEntityFaultReport(
                     entityRef.ptr,
                     &recommendedRecovery,
                     &escalation) );

     }

exitfn:

    AMS_CALL ( clOsalMutexUnlock(gAms.mutex));
    return CL_AMS_RC (rc);

}
static ClRcT
clLogFlusherRecordsFlush(ClLogSvrStreamDataT  *pStreamData)
{    
    ClRcT     rc        = CL_OK;
    ClLogStreamHeaderT     *pHeader           = pStreamData->pStreamHeader;
    ClLogSvrCommonEoDataT  *pSvrCommonEoEntry = NULL;
    ClLogSvrEoDataT        *pSvrEoEntry       = NULL;
    ClUint32T              nFlushableRecords  = 0;
    ClUint32T              nFlushedRecords    = 0;

    CL_LOG_DEBUG_TRACE(("Enter"));

    if( (pStreamData->fileOwnerAddr != clIocLocalAddressGet()) && 
        (0 == pStreamData->ackersCount + pStreamData->nonAckersCount) )
    {
        clLogInfo("LOG", "FLS", "No one has registered for the Stream");
        return CL_OK;
    }    

    rc = clLogSvrEoEntryGet(&pSvrEoEntry, &pSvrCommonEoEntry);
    if( CL_OK != rc )
    {
        return rc;
    }    

    CL_LOG_DEBUG_TRACE((" recordIdx: %d startAck : %d \n", pHeader->recordIdx,
                pHeader->startAck));

    if (pHeader->recordIdx < pHeader->startAck)
    {
        nFlushableRecords = (pHeader->recordIdx + pHeader->maxRecordCount) - pHeader->startAck;
    }
    else
    {
        nFlushableRecords = abs( pHeader->recordIdx - pHeader->startAck );
    }    

    while( nFlushableRecords > 0 )
    {
        nFlushedRecords = (nFlushableRecords > pSvrEoEntry->maxFlushLimit)
            ? pSvrEoEntry->maxFlushLimit : nFlushableRecords;

        rc = clLogFlusherRecordsMcast(pStreamData, nFlushedRecords);
        if( CL_OK == rc )
        {
            pHeader->startAck += nFlushedRecords;
            pHeader->startAck %= (pHeader->maxRecordCount);
            pStreamData->seqNum += nFlushedRecords;
            nFlushableRecords -= nFlushedRecords;
            CL_LOG_DEBUG_TRACE(("startAck: %u remaining: %u",
                        pHeader->startAck, nFlushableRecords));
            /* FIXME: put the number of overwritten records in log */
            if( 0 != pHeader->numOverwrite )
            {
                CL_LOG_DEBUG_TRACE((" %d records have been dropped",
                            pHeader->numOverwrite));
            }
            pHeader->numOverwrite = 0;
        }
        else
        {
            return CL_OK;
        }
    }

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}    
/*-----------------------------------------------------------------------------
 * Initialize API
 *---------------------------------------------------------------------------*/
ClRcT clGmsInitialize(
    CL_OUT   ClGmsHandleT* const    gmsHandle,
    CL_IN    const ClGmsCallbacksT* const gmsCallbacks,
    CL_INOUT ClVersionT*   const      version)
{
    struct gms_instance *gms_instance_ptr = NULL;
    ClRcT rc = CL_OK;
    ClGmsClientInitRequestT req = {{0}};
    ClGmsClientInitResponseT *res = NULL;

    /* Step 0: Check readiness of library */

    rc = check_lib_init();
    if (rc != CL_OK)
    {
        return CL_GMS_RC(CL_ERR_NOT_INITIALIZED);
    }
    
    /* Step 1: Checking inputs */
    CL_ASSERT(gmsHandle != NULL);
    CL_ASSERT(version != NULL);
#if 0    
    if ((gmsHandle == NULL) || (version == NULL))
    {
        return CL_GMS_RC(CL_ERR_NULL_POINTER);
    }
#endif    

    *gmsHandle = CL_HANDLE_INVALID_VALUE;

    /* Step 2: Verifying version match */
    
    rc = clVersionVerify (&version_database, version);
    if (rc != CL_OK)
    {
        return CL_GMS_RC(CL_ERR_VERSION_MISMATCH); 
    }

    /* Step 3: Obtain unique handle */
    rc = clHandleCreate(gmsHandleDb, sizeof(struct gms_instance), gmsHandle);
    CL_ASSERT(rc == CL_OK);
#if 0    
    if (rc != CL_OK)
    {
        rc = CL_GMS_RC(CL_ERR_NO_RESOURCE);
        goto error_no_destroy;
    }
#endif    
    clLogInfo("GMS","CLT","GMS client handle is [%llX]",*gmsHandle);
    
    rc = clHandleCheckout(gmsHandleDb, *gmsHandle, (void **)&gms_instance_ptr);
    CL_ASSERT(rc == CL_OK);
    CL_ASSERT(gms_instance_ptr != NULL);
#if 0    
    if(rc != CL_OK)
    {
        goto error_destroy;
    }
    if (gms_instance_ptr == NULL)
    {
        clHandleCheckin(gmsHandleDb, *gmsHandle);
        rc = CL_GMS_RC(CL_ERR_NULL_POINTER);
        goto error_destroy;
    }
#endif

    rc = clGmsMutexCreate(&gms_instance_ptr->response_mutex);
    CL_ASSERT(rc == CL_OK);
#if 0    
    if(rc != CL_OK)
    {
        clHandleCheckin(gmsHandleDb, *gmsHandle);
        goto error_destroy;
    }
#endif

    /* Step 4: Negotiate version with the server */
    req.clientVersion.releaseCode = version->releaseCode;
    req.clientVersion.majorVersion= version->majorVersion;
    req.clientVersion.minorVersion= version->minorVersion;

    rc = cl_gms_clientlib_initialize_rmd(&req, 0x0 ,&res );
    if(rc != CL_OK )
    {
        clLogError(GEN,NA,"cl_gms_clientlib_initialize_rmd failed with rc:0x%x ",rc);
        clGmsMutexDelete(gms_instance_ptr->response_mutex);
        gms_instance_ptr->response_mutex = 0;
        clHandleCheckin(gmsHandleDb, *gmsHandle);
        rc = CL_GMS_RC(rc);
        goto error_destroy;
    }
    
    /* Step 5: Initialize instance entry */
    if (gmsCallbacks) 
    {
        memcpy(&gms_instance_ptr->callbacks, gmsCallbacks, sizeof(ClGmsCallbacksT));
    } 
    else 
    {
        memset(&gms_instance_ptr->callbacks, 0, sizeof(ClGmsCallbacksT));
    }

    memset(&gms_instance_ptr->cluster_notification_buffer, 0, sizeof(ClGmsClusterNotificationBufferT));
    memset(&gms_instance_ptr->group_notification_buffer, 0, sizeof(ClGmsGroupNotificationBufferT));

    /* Step 6: Decrement handle use count and return */
    if ((clHandleCheckin(gmsHandleDb, *gmsHandle)) != CL_OK)
    {
        clLogError(GEN,DB, "\nclHandleCheckin failed");
    }
    clHeapFree(res);
    return CL_OK;

    error_destroy:
    clHandleDestroy(gmsHandleDb, *gmsHandle);
    *gmsHandle = CL_HANDLE_INVALID_VALUE;

    //error_no_destroy:
    return rc;
}
/**
 * This is the agent initilaization API called during EO initialization.
 * 
 * Agent acts as intermediate layer during an active transaction. It receives
 * job-definition and commands from transaction manager and takes specific
 * action.
 */
ClRcT clTxnAgentInitialize(CL_IN ClEoExecutionObjT  *appEoObj, 
                           CL_IN ClVersionT         *pTxnVersion)
{
    ClRcT rc = CL_OK;

    CL_FUNC_ENTER();

    if ( (NULL == appEoObj) || (NULL == pTxnVersion) )
    {
        CL_FUNC_EXIT();
        return CL_TXN_RC(CL_ERR_NULL_POINTER);
    }

    /* Do version negotiation  (later part of RC-1 or RC-2) */
    if (clTxnVersionVerify(pTxnVersion) != CL_OK)
    {
        CL_FUNC_EXIT();
        return (CL_TXN_RC(CL_ERR_VERSION_MISMATCH));
    }

    clTxnAgntCfg = (ClTxnAgentCfgT *) clHeapAllocate( sizeof(ClTxnAgentCfgT));
    CL_TXN_NULL_CHECK_RETURN(clTxnAgntCfg, CL_ERR_NO_MEMORY, 
                             ("Failed to allocate memory\n"));
    memset(clTxnAgntCfg, 0, sizeof(ClTxnAgentCfgT));


    /* If possible, instead of statically registring RMD functions, txn-agent 
       could register EO client table here.
    */

    /* Create hash-maps for active-txn component-services */
    rc = clTxnDbInit( &(clTxnAgntCfg->activeTxnMap) );
    CL_TXN_ERR_RET_ON_ERROR(rc, ("Failed to allocate hash-map for active-txn rc:0x%x\n", rc));

    rc = clCntThreadSafeHashtblCreate(CL_TXN_NUM_BUCKETS, 
                            _clTxnCmpServiceKeyCompare, 
                            _clTxnCmpServiceHashFn, 
                            _clTxnCompServiceDelete, _clTxnCompServiceDelete, 
                            CL_CNT_UNIQUE_KEY,
                            (ClCntHandleT *) &clTxnAgntCfg->compServiceMap);
    CL_TXN_ERR_RET_ON_ERROR(rc, ("Failed to allocate hash-map for comp-service rc:0x%x\n", rc));

    clTxnMutexCreateAndLock(&clTxnAgntCfg->actMtx);
    /* No registered service */
    clTxnAgntCfg->agentCapability = CL_TXN_AGENT_NO_SERVICE_REGD;

    clTxnMutexUnlock(clTxnAgntCfg->actMtx);

    clLogInfo("AGT", NULL,
            "Installing function table");
    rc = clEoClientInstallTables(appEoObj, 
                                 CL_EO_SERVER_SYM_MOD(gAspFuncTable, TXNAgent));
    if (CL_OK == rc)
    {
        rc = clTxnCommIfcInit(&(clTxnMgmtVersionSupported[0]));
        if(CL_OK != rc)
        {
            clLogError("AGT", NULL, 
                    "Error in initiazing communication interface, rc [0x%x]", rc);
            clEoClientUninstallTables(appEoObj, 
                                 CL_EO_SERVER_SYM_MOD(gAspFuncTable, TXNAgent));
            return rc;
        }
    }

    if(CL_OK == rc)
    {
        rc = clTxnAgentTableRegister(appEoObj);
        if(CL_OK != rc)
        {
            clLogError("AGT", NULL, 
                    "Error in table registration, rc [0x%x]", rc);
            clEoClientUninstallTables(appEoObj, 
                                 CL_EO_SERVER_SYM_MOD(gAspFuncTable, TXNAgent));
        }
    }

    CL_FUNC_EXIT();
    return (rc);
}