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;
}
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 ;
}
static ClRcT compConfigSet(ClCpmComponentT *comp, 
                           ClUint64T mask,
                           ClCharT *instantiateCommand,
                           ClAmsCompPropertyT property)
{
    ClRcT rc = CL_OK;
                           
    if ((mask == CL_AMS_CONFIG_ATTR_ALL) ||
        (mask & COMP_CONFIG_INSTANTIATE_COMMAND))
    {
        rc = cpmCompParseArgs(comp->compConfig, instantiateCommand, NULL);
        if (rc != CL_OK) goto out;
    }

    if ((mask == CL_AMS_CONFIG_ATTR_ALL) ||
        (mask & COMP_CONFIG_PROPERTY))
    {
        comp->compConfig->compProperty = property;
    }

    clLogNotice("COMP", "CONFIG", "Updated comp config for component [%s]",
                comp->compConfig->compName);

    out:
    return rc;
}
ClRcT
clLogStreamOwnerCheckpointCreate(ClLogSOEoDataT  *pSoEoEntry,
                                 SaNameT         *pCkptName,
                                 ClHandleT       *phCkpt)
{
    ClRcT         rc     = CL_OK;
    ClCkptCheckpointCreationAttributesT  creationAtt    = {0};
    ClCkptOpenFlagsT                     openFlags      = 0;
    ClLogSvrCommonEoDataT                *pCommonEoData = NULL;
    ClUint32T                            sectionSize    = 0;
    ClInt32T                             tries = 0;
    ClIocNodeAddressT                    localAddr = clIocLocalAddressGet();
    static ClTimerTimeOutT delay = { 0,  500};

    CL_LOG_DEBUG_TRACE(("Enter"));
    
    rc = clLogStreamOwnerEoEntryGet(NULL, &pCommonEoData);
    if( CL_OK != rc )
    {
        return rc;
    }

    creationAtt.creationFlags     = CL_CKPT_CHECKPOINT_COLLOCATED | CL_CKPT_ALL_OPEN_ARE_REPLICAS;
    creationAtt.checkpointSize    = pCommonEoData->maxStreams * CL_LOG_SO_SEC_SIZE; 
    creationAtt.retentionDuration = CL_STREAMOWNER_CKPT_RETENTION_DURATION;
    creationAtt.maxSections       = pCommonEoData->maxStreams;
    sectionSize                   = pCommonEoData->maxComponents * sizeof(ClLogCompKeyT); 
    creationAtt.maxSectionSize    = CL_LOG_SO_SEC_SIZE + sectionSize;
    creationAtt.maxSectionIdSize  = CL_LOG_SO_SEC_ID_SIZE;

    openFlags = CL_CKPT_CHECKPOINT_CREATE | CL_CKPT_CHECKPOINT_WRITE | CL_CKPT_CHECKPOINT_READ;

    reopen:
    rc = clCkptCheckpointOpen(pCommonEoData->hSvrCkpt, pCkptName, &creationAtt, openFlags, 5000L, &pSoEoEntry->hCkpt);
    if( rc != CL_OK )
    {
        /*
         * No replica found and we are the only master.
         * Delete and try re-opening the checkpoint
         */
        if(CL_GET_ERROR_CODE(rc) == CL_ERR_NO_RESOURCE &&
           pCommonEoData->masterAddr == localAddr)
        {
            if(tries++ < 1)
            {
                clLogNotice("CKP", "GET", "No replica for log checkpoint."
                            "Deleting ckpt [%.*s] and retrying the ckpt open",
                            pCkptName->length, pCkptName->value);
                clCkptCheckpointDelete(pCommonEoData->hSvrCkpt, pCkptName);
                clOsalTaskDelay(delay);
                goto reopen;
            }
        }
        CL_LOG_DEBUG_ERROR(("clCkptCheckpointOpen(): rc[0x %x]", rc));
    }    

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}    
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;
}
ClRcT clCorAmfMoIdGet(const ClCharT *name,
                      ClAmsEntityTypeT type,
                      ClCorMOIdT *pMoId)
{
    ClAmsEntityT entity = {0};
    ClBufferHandleT msg = 0;
    ClRcT rc = CL_OK;
    ClVersionT version = {'B', 0x1, 0x1};
    ClCharT *data = NULL;
    ClUint32T dataLen = 0;
    ClCorObjectHandleT objHandle;

    if(!name || !pMoId) return CL_COR_SET_RC(CL_ERR_INVALID_PARAMETER);

    if(!mgmtHandle)
    {
        rc = clAmsMgmtInitialize(&mgmtHandle, NULL, &version);
        if(rc != CL_OK) return rc;
    }

    entity.type = type;
    clNameSet(&entity.name, name);
    ++entity.name.length;
    rc = clAmsMgmtEntityUserDataGetKey(mgmtHandle, &entity, &entity.name, &data, &dataLen);
    if(rc != CL_OK)
    {
        clLogError("FLT", "REPAIR", "Entity data get for [%s] returned [%#x]",
                   entity.name.value, rc);
        goto out_free;
    }
    rc = clBufferCreate(&msg);
    CL_ASSERT(rc == CL_OK);
    rc = clBufferNBytesWrite(msg, (ClUint8T*)data, dataLen);
    CL_ASSERT(rc == CL_OK);
    
    rc = VDECL_VER(clXdrUnmarshallClCorMOIdT, 4, 0, 0)(msg, pMoId);
    CL_ASSERT(rc == CL_OK);
    
    clBufferDelete(&msg);

    clLogNotice("COR", "AMF", "MOID for faulty entity [%s] ", entity.name.value);
    clCorMoIdShow(pMoId);
    
    /*
     * Validating moid
     */
    rc = clCorObjectHandleGet(pMoId, &objHandle);
    CL_ASSERT(rc == CL_OK);

    out_free:
    if(msg) clBufferDelete(&msg);
    if(data) clHeapFree(data);

    return rc;
}
ClRcT clAmsDBGetSISUList(ClAmsMgmtDBHandleT db, ClAmsEntityT *entity,
                         ClAmsSISUExtendedRefBufferT *sisuRefBuffer)
{
    ClRcT rc = CL_OK;
    ClAmsSISUExtendedRefBufferT buffer = {0};
    if(!sisuRefBuffer)
        sisuRefBuffer = &buffer;
    rc = clAmsMgmtDBGetSISUList(db, entity, sisuRefBuffer);
    if(rc != CL_OK)
        return rc;
    if(sisuRefBuffer == &buffer)
    {
        clLogNotice("DBA", "READ", "Getting SI [%s] su list", entity->name.value);
        dumpSISURefBuffer(sisuRefBuffer);
        clLogNotice("DBA", "READ", "Done getting SI [%s] su list", entity->name.value);
        if(sisuRefBuffer->entityRef)
            clHeapFree(sisuRefBuffer->entityRef);
    }
    return rc;
}
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);
}
ClRcT clAmsDBGetSUSIList(ClAmsMgmtDBHandleT db, ClAmsEntityT *entity,
                         ClAmsSUSIExtendedRefBufferT *susiRefBuffer)
{
    ClRcT rc = CL_OK;
    ClAmsSUSIExtendedRefBufferT buffer = {0};
    if(!susiRefBuffer)
        susiRefBuffer = &buffer;
    rc = clAmsMgmtDBGetSUAssignedSIsList(db, entity, susiRefBuffer);
    if(rc != CL_OK)
        return rc;
    if(susiRefBuffer == &buffer)
    {
        clLogNotice("DBA", "READ", "Getting SU [%s] si list", entity->name.value);
        dumpSUSIRefBuffer(susiRefBuffer);
        clLogNotice("DBA", "READ", "Done getting SU [%s] si list", entity->name.value);
        if(susiRefBuffer->entityRef)
            clHeapFree(susiRefBuffer->entityRef);
    }
    return rc;
}
static ClRcT _clPluginHelperHostToIp(const ClCharT *myHost, ClUint32T *ip) {
    struct hostent *host = NULL;
    struct hostent hostdata;
    ClCharT buf[129];
    int errnum = 0;

    if (gethostbyname_r(myHost, &hostdata, buf, 128, &host, &errnum) || !host) {
        clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Cannot resolve host string %s", myHost);
        return CL_ERR_LIBRARY;
    }

    *ip = *((ClUint32T*) host->h_addr_list[0]);
    return CL_OK;
}
ClRcT clAmsDBGetCompCSIList(ClAmsMgmtDBHandleT db, ClAmsEntityT *entity,
                            ClAmsCompCSIRefBufferT *csiRefBuffer)
{
    ClAmsCompCSIRefBufferT buffer = {0};
    ClRcT rc = CL_OK;

    if(!csiRefBuffer)
        csiRefBuffer = &buffer;

    rc = clAmsMgmtDBGetCompCSIList(db, entity, csiRefBuffer);
    if(rc != CL_OK)
        return rc;

    if(csiRefBuffer == &buffer)
    {
        clLogNotice("DBA", "READ", "Getting comp csi list");
        dumpCSIRefBuffer(csiRefBuffer);
        clLogNotice("DBA", "READ", "Done getting comp csi list");
        clAmsMgmtFreeCompCSIRefBuffer(csiRefBuffer);
    }

    return rc;
}
static ClRcT _clPluginHelperDevToMac(const ClCharT* dev, char mac[CL_MAC_ADDRESS_LENGTH]) {
    struct ifreq req;

    int sd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&req, 0, sizeof(struct ifreq));
    strcpy(req.ifr_name, dev);
    req.ifr_addr.sa_family = AF_UNSPEC;
    if (ioctl(sd, SIOCGIFHWADDR, &req) == -1) {
        int err = errno;
        clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "No device %s, hwaddr errno: %d", dev, err);
        return CL_ERR_LIBRARY;
    }
    memcpy(mac, &(req.ifr_addr.sa_data), CL_MAC_ADDRESS_LENGTH);

    close(sd);
    return CL_OK;
}
static ClRcT clAmsEntityRecoveryReset(ClAmsEntityT *pEntity,
                                      ClAmsThresholdT *pThreshold)
{
    ClRcT rc = CL_OK;
    ClAmsAdminStateT adminState = gClAmsEntityTriggerRecoveryResetMap[pEntity->type][pThreshold->recovery];

    switch(adminState)
    {
        
    case CL_AMS_ADMIN_STATE_NONE:
        break;

    case CL_AMS_ADMIN_STATE_UNLOCKED:

        if(pEntity->type  == CL_AMS_ENTITY_TYPE_CSI)
            return clAmsCSIRecovery(pEntity, pThreshold);

        if(pEntity->type == CL_AMS_ENTITY_TYPE_COMP 
           || 
           pEntity->type == CL_AMS_ENTITY_TYPE_SU)
            return clAmsCompRecovery(pEntity, pThreshold);

        clAmsMgmtEntityRepaired(gClAmsEntityTriggerMgmtHandle,
                                pEntity);

        clLogNotice("RECOVERY", "RESET",
                    "Unlocking [%s] -> [%.*s]",
                    CL_AMS_STRING_ENTITY_TYPE(pEntity->type),
                    pEntity->name.length-1, pEntity->name.value);

        rc = clAmsMgmtEntityUnlock(gClAmsEntityTriggerMgmtHandle,
                                   pEntity);
        
        if(rc != CL_OK)
        {
            clLogError("RECOVERY", "RESET",
                       "Unlock returned [%#x]", rc);
        }
        break;
    default:;
    }

    return rc;
}
/*
 * Returns ip address on a network interface given its name...
 */
ClRcT clPluginHelperDevToIpAddress(const ClCharT *dev, ClCharT *addrStr)
{
    int sd;
    struct ifreq req;
    ClCharT ipAddress[INET_ADDRSTRLEN] = { 0 };
    int rc = 1;

    /* Get a socket handle. */
    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd < 0)
    {
        clLogError("IOC", CL_LOG_PLUGIN_HELPER_AREA, "open socket failed with error [%s]", strerror(errno));
        return rc;
    }

    memset(&req, 0, sizeof(struct ifreq));
    strcpy(req.ifr_name, dev);
    req.ifr_addr.sa_family = PF_UNSPEC;

    if (ioctl(sd, SIOCGIFADDR, &req) == -1)
    {
        clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Operation command failed: [%s]", strerror(errno));
        close(sd);
        return rc;
    }

    struct in_addr *in4_addr = &((struct sockaddr_in*) &((struct ifreq *) &req)->ifr_addr)->sin_addr;
    if (!inet_ntop(PF_INET, (const void *) in4_addr, ipAddress, sizeof(ipAddress)))
    {
        struct in6_addr *in6_addr = &((struct sockaddr_in6*) &((struct ifreq *) &req)->ifr_addr)->sin6_addr;
        if (!inet_ntop(PF_INET6, (const void *) in6_addr, ipAddress, sizeof(ipAddress)))
        {
            goto out;
        }
    }

    /* successful */
    rc = 0;
    strncat(addrStr, ipAddress, sizeof(ipAddress) - 1);

out:
    close(sd);
    return rc;
}
static ClAmsEntityTriggerT *clAmsEntityTriggerCreate(ClAmsEntityT *pEntity,
                                                     ClMetricT *pMetric)
{
    ClAmsEntityTriggerT *pEntityTrigger = NULL;

    if(!pEntity || !pMetric)
        goto out;
    
    if(pMetric->id >= CL_METRIC_MAX)
    {
        clLogError("TRIGGER", "CREATE",
                   "Invalid metric [%#x] for entity [%.*s]",
                   pMetric->id, pEntity->name.length-1, pEntity->name.value);
        goto out;
    }    

    clOsalMutexLock(&gClAmsEntityTriggerList.list.mutex);
    pEntityTrigger = clAmsEntityTriggerFind(pEntity);
    if(!pEntityTrigger)
    {
        clOsalMutexUnlock(&gClAmsEntityTriggerList.list.mutex);
        pEntityTrigger = (ClAmsEntityTriggerT*) clHeapCalloc(1, sizeof(*pEntityTrigger));
        if(!pEntityTrigger)
        {
            clLogError("TRIGGER", "CREATE", "Memory allocation failure");
            goto out;
        }
        memcpy(&pEntityTrigger->entity, pEntity, sizeof(pEntityTrigger->entity));
        clAmsEntityTriggerLoadDefaults(pEntityTrigger, CL_METRIC_ALL);
        clLogNotice("TRIGGER", "CREATE", "Entity [%.*s], Metric [%#x]",
                    pEntity->name.length-1, pEntity->name.value, pMetric->id);
        clOsalMutexLock(&gClAmsEntityTriggerList.list.mutex);
        clAmsEntityTriggerListAdd(pEntityTrigger);
    }

    clAmsEntityTriggerUpdate(pEntityTrigger, pMetric);
    clAmsEntityTriggerCheck(pEntityTrigger, pMetric);

    clOsalMutexUnlock(&gClAmsEntityTriggerList.list.mutex);

    out:
    return pEntityTrigger;
}
static ClRcT _clPluginHelperDevToIfIndex(const ClCharT *dev, int *ifindex) {
    struct ifreq req;

    int sd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&req, 0, sizeof(struct ifreq));
    strcpy(req.ifr_name, dev);
    req.ifr_addr.sa_family = AF_UNSPEC;
    if (ioctl(sd, SIOCGIFINDEX, &req) == -1) {
        int err = errno;
        clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "No device %s, ifindex errno: %d", dev, err);
        *ifindex = 0;
        return CL_ERR_LIBRARY;
    }

    *ifindex = req.ifr_ifindex;

    close(sd);
    return CL_OK;
}
static ClRcT clAmsEntityTriggerUpdate(ClAmsEntityTriggerT *pEntityTrigger,
                                      ClMetricT *pMetric)
{
    ClMetricIdT start = pMetric->id;
    ClMetricIdT end = (ClMetricIdT) (start+1);
    register ClInt32T i;

    if(start == CL_METRIC_ALL)
    {
        start = (ClMetricIdT) (start + 1) ;
        end = CL_METRIC_MAX;
    }

    for(i = start; i < end; ++i)
    {
        pEntityTrigger->thresholds[i].metric.currentThreshold = pMetric->currentThreshold;
        clLogNotice("TRIGGER", "MODIFY", "Entity [%.*s], Threshold [%d]", pEntityTrigger->entity.name.length-1, pEntityTrigger->entity.name.value, pMetric->currentThreshold);
    }

    return CL_OK;
}
static void clAmsMgmtOIExtendedCacheAdd(ClAmsMgmtOIExtendedClassTypeT type,
                                        ClCorInstanceIdT instance, 
                                        ClAmsMgmtOIExtendedEntityConfigT *pConfig,
                                        ClUint32T configSize)
{
    struct hashStruct **table = NULL;
    ClAmsMgmtOIExtendedCacheT *cacheEntry = NULL;
    if(type >= CL_AMS_MGMT_OI_EXTENDED_CLASS_MAX || !pConfig || !configSize)
        return;
    clOsalMutexLock(&gClAmsMgmtOICacheMutex);
    table = gClAmsMgmtOIExtendedCacheTable[type];
    if( (cacheEntry = clAmsMgmtOIExtendedCacheFind(table, instance) ) )
    {
        CL_ASSERT(cacheEntry->pConfig != NULL);
        if(cacheEntry->configSize != configSize)
        {
            clHeapFree(cacheEntry->pConfig);
            cacheEntry->pConfig = clHeapCalloc(1, configSize);
            CL_ASSERT(cacheEntry->pConfig != NULL);
            cacheEntry->configSize = configSize;
        }
        memcpy(cacheEntry->pConfig, pConfig, configSize);
    }
    else
    {
        ClAmsMgmtOIExtendedEntityConfigT *pExtendedConfig = NULL;
        cacheEntry = clHeapCalloc(1, sizeof(*cacheEntry));
        CL_ASSERT(cacheEntry != NULL);
        pExtendedConfig = clHeapCalloc(1, configSize);
        CL_ASSERT(pExtendedConfig != NULL);
        cacheEntry->pConfig = pExtendedConfig;
        cacheEntry->instance = instance;
        memcpy(cacheEntry->pConfig, pConfig, configSize);
        hashAdd(table, entityCacheHashKey(instance), &cacheEntry->hash);
        clLogNotice("AMF", "MGMT", "Added entity [%s], instance [%d] to the extended class [%s]",
                    pConfig->entity.name.value, instance, gClAmsMgmtOIExtendedCacheStrTable[type]);
    }
    clOsalMutexUnlock(&gClAmsMgmtOICacheMutex);
}
static void clAmsMgmtOICacheAdd(ClCorInstanceIdT instance, ClAmsEntityT *entity)
{
    struct hashStruct **table = NULL;
    ClAmsMgmtOICacheT *cacheEntry = NULL;
    if(!entity || entity->type > CL_AMS_ENTITY_TYPE_MAX)
        return;
    clOsalMutexLock(&gClAmsMgmtOICacheMutex);
    table = gClAmsMgmtOICacheTable[entity->type];
    if( (cacheEntry = clAmsMgmtOICacheFind(table, instance, entity) ) )
    {
        memcpy(&cacheEntry->entity, entity, sizeof(cacheEntry->entity));
    }
    else
    {
        cacheEntry = clHeapCalloc(1, sizeof(*cacheEntry));
        CL_ASSERT(cacheEntry != NULL);
        cacheEntry->instance = instance;
        memcpy(&cacheEntry->entity, entity, sizeof(cacheEntry->entity));
        hashAdd(table, entityCacheHashKey(instance), &cacheEntry->hash);
        clLogNotice("AMF", "MGMT", "Added entity [%s], instance [%d] to the cache",
                    entity->name.value, instance);
    }
    clOsalMutexUnlock(&gClAmsMgmtOICacheMutex);
}
static void *clAmsMgmtMigrateListUnlock(void *arg)
{
    ClAmsMgmtMigrateListT *unlockList = (ClAmsMgmtMigrateListT*) arg;
    ClUint32T i;
    ClRcT rc = CL_OK;

    if(!unlockList) return NULL;

#if 0
    /*
     * The user could modify the SI-CSI list for the newly created SI.
     * So we don't want to unlock this SI and have this assigned active to an SU 
     * when running under SG reduction procedure.
     */
    for(i = 0; i < unlockList->si.count; ++i)
    {
        ClAmsEntityT *si = unlockList->si.entity+i;
        clLogNotice("AMS", "MIGRATE", "Unlocking created SI [%s]",
                    si->name.value);
        clAmsMgmtEntityUnlock(gHandle, si);
    }
#endif

    for(i = 0; i < unlockList->node.count; ++i)
    {
        ClAmsEntityT *node = unlockList->node.entity + i;
        clLogNotice("AMS", "MIGRATE", "Unlocking created Node [%s]",
                    node->name.value);
        rc = clAmsMgmtEntityLockAssignment(gHandle, node);
        if(rc == CL_OK)
        {
            rc = clAmsMgmtEntityUnlock(gHandle, node);
        }
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "Node [%s] unlock returned [%#x]", 
                       node->name.value, rc);
        }
    }

#if 0
    for(i = 0; i < unlockList->su.count; ++i)
    {
        ClAmsEntityT *su = unlockList->su.entity + i;
        clLogNotice("AMS", "MIGRATE", "Unlocking created SU [%s]",
                    su->name.value);
        rc = clAmsMgmtEntityLockAssignment(gHandle, su);
        if(rc == CL_OK)
        {
            rc = clAmsMgmtEntityUnlock(gHandle, su);
        }
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "SU [%s] unlock returned [%#x]",
                       su->name.value, rc);
        }
    }
#endif

    clHeapFree(unlockList->si.entity);
    clHeapFree(unlockList->node.entity);
    clHeapFree(unlockList->su.entity);
    clHeapFree(unlockList);

    return NULL;
}
ClRcT cpmNodeAdd(ClCharT *nodeName)
{
    ClRcT rc = CL_OK;
    ClCpmLT *cpm = NULL;
    ClUint16T nodeKey = 0;
    ClCpmSlotInfoT slotInfo = {0};

    if (!nodeName)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM, "NULL pointer passed.");
        goto failure;
    }

    clOsalMutexLock(gpClCpm->cpmTableMutex);
    rc = cpmNodeFindLocked((SaUint8T *)nodeName, &cpm);
    clOsalMutexUnlock(gpClCpm->cpmTableMutex);
    if (cpm)
    {
        clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM, "Node [%s] already exists on this node.", nodeName);
        rc = CL_CPM_RC(CL_ERR_ALREADY_EXIST);
        goto failure;
    }

    cpm = (ClCpmLT*) clHeapAllocate(sizeof(ClCpmLT));
    if (!cpm)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Unable to allocate memory");
        goto failure;
    }

    memset(cpm, 0, sizeof(ClCpmLT));
    
    strncpy(cpm->nodeName, nodeName, strlen(nodeName));
    
    rc = clCksm16bitCompute((ClUint8T *)cpm->nodeName,
                            strlen(cpm->nodeName),
                            &nodeKey);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to compute checksum for node, "
                   "error [%#x]",
                   rc);
        goto failure;
    }

    /* 
     * Filling the CPML with defaults.  
     */

    saNameSet(&cpm->nodeType, nodeName);
    saNameSet(&cpm->nodeIdentifier, nodeName);
    /*
     * Set the class type to CLASS_C.
     */
    strncpy(cpm->classType, "CL_AMS_NODE_CLASS_C", sizeof(cpm->classType)-1);
    /*
     * Get the MOID of the master node. Assuming that node add is
     * only invoked on the master.
     */
    slotInfo.slotId = clIocLocalAddressGet();

    rc = clCpmSlotInfoGet(CL_CPM_SLOT_ID, &slotInfo);
    if(rc == CL_OK)
    {
        rc = cpmCorMoIdToMoIdNameGet(&slotInfo.nodeMoId, &cpm->nodeMoIdStr);
    }
    if(rc != CL_OK)
    {
        if((CL_GET_ERROR_CODE(rc) != CL_IOC_ERR_COMP_UNREACHABLE) && (CL_GET_ERROR_CODE(rc) != CL_ERR_NOT_EXIST) && (CL_GET_ERROR_CODE(rc) != CL_ERR_NOT_SUPPORTED))
        {
            goto failure;
        }
        else
        {
            rc = CL_OK;
            clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM, "COR server not running so cannot discover the Node's MoId");
        }
    }

    clOsalMutexLock(gpClCpm->cpmTableMutex);

    rc = clCntNodeAdd(gpClCpm->cpmTable,
                      (ClCntKeyHandleT)(ClWordT)nodeKey,
                      (ClCntDataHandleT) cpm,
                      NULL);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to add node to the CPM node table, "
                   "error [%#x]",
                   rc);
        clOsalMutexUnlock(gpClCpm->cpmTableMutex);
        goto failure;
    }

    ++gpClCpm->noOfCpm;

    clOsalMutexUnlock(gpClCpm->cpmTableMutex);

    /*
     * Add this to the slotinfo.
     */

    clOsalMutexLock(&gpClCpm->cpmMutex);
    rc = cpmSlotClassAdd(&cpm->nodeType, &cpm->nodeIdentifier, 0);
    clOsalMutexUnlock(&gpClCpm->cpmMutex);

    if(rc != CL_OK)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Node [%s] class add returned [%#x]", cpm->nodeType.value, rc);
    }

    clLogNotice("DYN", "NODE", "Node [%s] added to the cpm table with identity [%.*s]",
                cpm->nodeName, cpm->nodeIdentifier.length, cpm->nodeIdentifier.value);
                
    return CL_OK;

    failure:
    return rc;
}
/*
 * Create objects for the static AMF entities.
 */
ClRcT corAmfTreeInitialize(void)
{
    ClRcT rc = CL_OK;

    if(gClAmfMibLoaded)
    {
        rc = corAmfMibTreeInitialize();
    }
    else
    {
        ClVersionT version = {'B', 0x1 , 0x1};
        ClCorMOIdT moId;
        ClAmsEntityBufferT nodeList = {0};
        ClAmsEntityBufferT suList = {0};
        ClAmsEntityBufferT compList = {0};
        ClAmsEntityBufferT sgList = {0};
        ClAmsEntityBufferT siList = {0};
        ClAmsEntityBufferT csiList = {0};
        ClCorClassTypeT classIds[CL_AMS_ENTITY_TYPE_MAX+2] = {0};
        ClCorMOClassPathT sgClassPath;
        ClInt32T i;

        rc = corAmfEntityInitialize();
        if(rc != CL_OK) goto out;

        rc = clAmsMgmtInitialize(&mgmtHandle,  NULL, &version);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "Mgmt initialize returned [%#x]", rc);
            goto out;
        }

        if( (rc = clAmsMgmtGetNodeList(mgmtHandle, &nodeList)) != CL_OK)
        {
            clLogError("COR", "AMF", "Node list returned [%#x]", rc);
            goto out;
        }

        /*
         * Create object heirarchy for nodes/sus/comps. 
         */
        for(i = 0; i < nodeList.count; ++i)
        {
            ClInt32T j;
            ClCorMOClassPathT nodeClassPath;

            rc = clCorMoIdInitialize(&moId);
            CL_ASSERT(rc == CL_OK);

            rc = clCorNodeNameToMoIdGet(nodeList.entity[i].name, &moId);
            if(rc != CL_OK)
            {
                clLogError("COR", "AMF", "Node name to moid get for [%s] failed with [%#x]",
                           nodeList.entity[i].name.value, rc);
                goto out;
            }

            rc = clCorMoClassPathInitialize(&nodeClassPath);
            CL_ASSERT(rc == CL_OK);
        
            rc = clCorMoIdToMoClassPathGet(&moId, &nodeClassPath);
            CL_ASSERT(rc == CL_OK);

            /*
             * Now get nodes su list.
             */
            rc = clAmsMgmtGetNodeSUList(mgmtHandle, &nodeList.entity[i], &suList);
            if(rc != CL_OK)
            {
                clLogError("COR", "AMF", "Node [%s] su list returned [%#x]", 
                           nodeList.entity[i].name.value, rc);
                goto out;
            }

            if(!classIds[CL_AMS_ENTITY_TYPE_SU])
            {
                rc = corAmfEntityClassGet(CL_AMS_ENTITY_TYPE_SU, classIds+CL_AMS_ENTITY_TYPE_SU);
                if(rc != CL_OK)
                {
                    clLogError("COR", "AMF", "Class for entity SU not found");
                    goto out;
                }
            }
        
            if(!classIds[CL_AMS_ENTITY_TYPE_COMP])
            {
                rc = corAmfEntityClassGet(CL_AMS_ENTITY_TYPE_COMP, classIds+CL_AMS_ENTITY_TYPE_COMP);
                if(rc != CL_OK)
                {
                    clLogError("COR", "AMF", "Class for entity comp not found");
                    goto out;
                }
            }

            rc = clCorMoClassPathAppend(&nodeClassPath, classIds[CL_AMS_ENTITY_TYPE_SU]);
            CL_ASSERT(rc == CL_OK);

            rc = corAmfMoClassCreate("AMFSu", &nodeClassPath, NULL);
            if(rc != CL_OK)
            {
                if(CL_GET_ERROR_CODE(rc) != CL_COR_MO_TREE_ERR_FAILED_TO_ADD_NODE)
                    goto out;
            }

            if(CL_GET_ERROR_CODE(rc) != CL_COR_MO_TREE_ERR_FAILED_TO_ADD_NODE)
            {
                rc = clCorMoClassPathAppend(&nodeClassPath, classIds[CL_AMS_ENTITY_TYPE_COMP]);
                CL_ASSERT(rc == CL_OK);
            
                rc = corAmfMoClassCreate("AMFComp", &nodeClassPath, NULL);
                if(rc != CL_OK) goto out;
            }
            else
            {
                rc = CL_OK;
            }

            for(j = 0; j < suList.count; ++j)
            {
                ClInt32T k;
                ClCorMOIdT suMoId;

                memcpy(&suMoId, &moId, sizeof(suMoId));
                rc = clCorMoIdAppend(&suMoId, classIds[CL_AMS_ENTITY_TYPE_SU], j);
                CL_ASSERT(rc == CL_OK);

                rc = corAmfObjectCreate(0, &suList.entity[j], &suMoId);
                if(rc != CL_OK) goto out;

                rc = clAmsMgmtGetSUCompList(mgmtHandle, &suList.entity[j], &compList);
                if(rc != CL_OK)
                {
                    goto out;
                }
            
                for(k = 0; k < compList.count; ++k)
                {
                    ClCorMOIdT compMoId;
   
                    memcpy(&compMoId, &suMoId, sizeof(compMoId));
                    rc = clCorMoIdAppend(&compMoId, classIds[CL_AMS_ENTITY_TYPE_COMP], k);
                    CL_ASSERT(rc == CL_OK);

                    rc = corAmfObjectCreate(0, &compList.entity[k], &compMoId);
                    if(rc != CL_OK) goto out;
                }
                clHeapFree(compList.entity);
                compList.entity = NULL;
            }
            clHeapFree(suList.entity);
            suList.entity = NULL;
        }

        /*
         * Configure object heirarchy for SGs.
         */
        rc = clAmsMgmtGetSGList(mgmtHandle, &sgList);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "SG list returned [%#x]", rc);
            goto out;
        }

        rc = corAmfEntityClassGet(CL_AMS_ENTITY_TYPE_SG, &classIds[CL_AMS_ENTITY_TYPE_SG]);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "SG entity class not found");
            goto out;
        }

        rc = corAmfEntityClassGet(CL_AMS_ENTITY_TYPE_SG, &classIds[CL_AMS_ENTITY_TYPE_SI]);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "SI entity class not found");
            goto out;
        }

        rc = corAmfEntityClassGet(CL_AMS_ENTITY_TYPE_SG, &classIds[CL_AMS_ENTITY_TYPE_CSI]);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "CSI entity class not found");
            goto out;
        }

        rc = clCorMoClassPathInitialize(&sgClassPath);
        CL_ASSERT(rc == CL_OK);
        rc = clCorMoClassPathAppend(&sgClassPath, classIds[CL_AMS_ENTITY_TYPE_SG]);
        CL_ASSERT(rc == CL_OK);

        rc = corAmfMoClassCreate("AMFSg", &sgClassPath, NULL);
        if(rc != CL_OK) goto out;
       
        rc = clCorMoClassPathAppend(&sgClassPath, classIds[CL_AMS_ENTITY_TYPE_SI]);
        CL_ASSERT(rc == CL_OK);
            
        rc = corAmfMoClassCreate("AMFSi", &sgClassPath, NULL);
        if(rc != CL_OK) goto out;

        rc = clCorMoClassPathAppend(&sgClassPath, classIds[CL_AMS_ENTITY_TYPE_CSI]);
        CL_ASSERT(rc == CL_OK);

        rc = corAmfMoClassCreate("AMFCsi", &sgClassPath, NULL);
        if(rc != CL_OK) goto out;

        for(i = 0; i < sgList.count; ++i)
        {
            ClInt32T j;

            rc = clCorMoIdInitialize(&moId);
            CL_ASSERT(rc == CL_OK);
            rc = clCorMoIdAppend(&moId, classIds[CL_AMS_ENTITY_TYPE_SG], i);
            CL_ASSERT(rc == CL_OK);

            rc = corAmfObjectCreate(0, &sgList.entity[i], &moId);
            if(rc != CL_OK) goto out;

            rc = clAmsMgmtGetSGSIList(mgmtHandle, &sgList.entity[i], &siList);
            if(rc != CL_OK)
            {
                clLogError("COR", "AMF", "SI list get for SG [%s] returned [%#x]",
                           sgList.entity[i].name.value, rc);
                goto out;
            }
        
            for(j = 0; j < siList.count; ++j)
            {
                ClInt32T k;
                ClCorMOIdT siMoId;

                memcpy(&siMoId, &moId, sizeof(siMoId));
                rc = clCorMoIdAppend(&siMoId, classIds[CL_AMS_ENTITY_TYPE_SI], j);
                CL_ASSERT(rc == CL_OK);

                rc = corAmfObjectCreate(0, &siList.entity[j], &siMoId);
                if(rc != CL_OK) goto out;

                rc = clAmsMgmtGetSICSIList(mgmtHandle, &siList.entity[j], &csiList);
                if(rc != CL_OK)
                {
                    clLogError("COR", "AMF", "CSI list for SI [%s] returned [%#x]",
                               siList.entity[j].name.value, rc);
                    goto out;
                }

                for(k = 0; k < csiList.count; ++k)
                {
                    ClCorMOIdT csiMoId;
                    memcpy(&csiMoId, &siMoId, sizeof(csiMoId));
                    rc = clCorMoIdAppend(&csiMoId, classIds[CL_AMS_ENTITY_TYPE_CSI], k);
                    CL_ASSERT(rc == CL_OK);
                    rc = corAmfObjectCreate(0, &csiList.entity[k], &csiMoId);
                    if(rc != CL_OK) goto out;
                }
                clHeapFree(csiList.entity);
                csiList.entity = NULL;
            }
            clHeapFree(siList.entity);
            siList.entity = NULL;
        }

        /*
         * We are here when the objects are all created. Do a commit
         */
        rc = corAmfObjectCommit();
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "Object commit returned [%#x]", rc);
            goto out;
        }

        clLogNotice("COR", "AMF", "COR AMF tree successfully initialized");

        out:
        if(nodeList.entity) 
            clHeapFree(nodeList.entity);
        if(suList.entity)   
            clHeapFree(suList.entity);
        if(compList.entity) 
            clHeapFree(compList.entity);
        if(sgList.entity)   
            clHeapFree(sgList.entity);
        if(siList.entity)   
            clHeapFree(siList.entity);
        if(csiList.entity) 
            clHeapFree(csiList.entity);
    }
    return rc;
}
ClRcT corAmfMibTreeInitialize(void)
{
    ClRcT rc = CL_OK;
    ClVersionT version = {'B', 0x1 , 0x1};
    ClCorMOIdT moId;
    ClCorMOIdT chassisMoid;
    ClAmsEntityBufferT nodeList = {0};
    ClAmsEntityBufferT suList = {0};
    ClAmsEntityBufferT compList = {0};
    ClAmsEntityBufferT sgList = {0};
    ClAmsEntityBufferT siList = {0};
    ClAmsEntityBufferT csiList = {0};
    ClCorClassTypeT classIds[CL_AMS_ENTITY_TYPE_MAX+2] = {0};
    ClInt32T chassisId = 0;
    ClNameT entityName = {0};
    ClUint32T i = 0;
    static ClUint32T extendedIndexTable[CL_AMS_MGMT_OI_EXTENDED_CLASS_MAX];

    rc = corAmfEntityInitialize();
    if(rc != CL_OK) goto out;

    rc = clAmsMgmtInitialize(&mgmtHandle,  NULL, &version);
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "Mgmt initialize returned [%#x]", rc);
        goto out;
    }
    
    snprintf(entityName.value, sizeof(entityName.value), "%s:%d", "\\Chassis", chassisId);
    entityName.length = strlen(entityName.value);
    rc = clCorMoIdNameToMoIdGet(&entityName, &chassisMoid);
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "Cor moid get returned [%#x] for name [%s]",
                   rc, entityName.value);
        goto out;
    }

    for(i = 0; i <= CL_AMS_ENTITY_TYPE_MAX; ++i)
    {
        rc = corAmfEntityClassGet(i, classIds + i);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "Entity class for [%s] not found",
                       CL_AMS_STRING_ENTITY_TYPE(i));
            goto out;
        }
    }

    if( (rc = clAmsMgmtGetNodeList(mgmtHandle, &nodeList)) != CL_OK)
    {
        clLogError("COR", "AMF", "Node list returned [%#x]", rc);
        goto out;
    }


    /*
     * Create objects for nodes/sus/comps/sgs/sis/csis
     */
    for(i = 0; i < nodeList.count; ++i)
    {
        memcpy(&moId, &chassisMoid, sizeof(moId));
        clCorMoIdAppend(&moId, classIds[CL_AMS_ENTITY_TYPE_NODE], i);
        rc = corAmfObjectCreate(i, &nodeList.entity[i], &moId);
        if(rc != CL_OK) goto out;
    }

    rc = clAmsMgmtGetSUList(mgmtHandle, &suList);
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "SU list get returned [%#x]", rc);
        goto out;
    }

    for(i = 0; i < suList.count; ++i)
    {
        memcpy(&moId, &chassisMoid, sizeof(moId));
        rc = clCorMoIdAppend(&moId, classIds[CL_AMS_ENTITY_TYPE_SU], i);
        CL_ASSERT(rc == CL_OK);
        rc = corAmfObjectCreate(i, &suList.entity[i], &moId);
        if(rc != CL_OK) goto out;
    }
    
    rc = clAmsMgmtGetCompList(mgmtHandle, &compList);
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "Comp list get returned [%#x]", rc);
        goto out;
    }

    for(i = 0; i < compList.count; ++i)
    {
        memcpy(&moId, &chassisMoid, sizeof(moId));
        rc = clCorMoIdAppend(&moId, classIds[CL_AMS_ENTITY_TYPE_COMP], i);
        CL_ASSERT(rc == CL_OK);
        rc = corAmfObjectCreate(i, &compList.entity[i], &moId);
        if(rc != CL_OK) goto out;
    }

    rc = clAmsMgmtGetSGList(mgmtHandle, &sgList);
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "SG list returned [%#x]", rc);
        goto out;
    }

    for(i = 0; i < sgList.count; ++i)
    {
        ClAmsEntityBufferT rankList = {0};
        memcpy(&moId, &chassisMoid, sizeof(moId));
        rc = clCorMoIdAppend(&moId, classIds[CL_AMS_ENTITY_TYPE_SG], i);
        CL_ASSERT(rc == CL_OK);
        rc = corAmfObjectCreate(i, &sgList.entity[i], &moId);
        if(rc != CL_OK) goto out;
        rc = clAmsMgmtGetSGSIList(mgmtHandle, &sgList.entity[i], &rankList);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "SG [%s] si list returned [%#x]",
                       sgList.entity[i].name.value, rc);
            goto out;
        }
        rc = corAmfExtendedClassObjectCreate("saAmfSGSIRankTable",
                                             &sgList.entity[i],
                                             &chassisMoid,
                                             rankList.count,
                                             &extendedIndexTable[CL_AMS_MGMT_OI_SGSIRANK],
                                             &i);
        if(rankList.entity)
        {
            clHeapFree(rankList.entity);
            rankList.entity = NULL;
            rankList.count = 0;
        }
        
        rc = clAmsMgmtGetSGSUList(mgmtHandle, &sgList.entity[i], &rankList);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "SG [%s] su list returned [%#x]",
                       sgList.entity[i].name.value, rc);
            goto out;
        }
        rc = corAmfExtendedClassObjectCreate("saAmfSGSURankTable",
                                             &sgList.entity[i],
                                             &chassisMoid,
                                             rankList.count,
                                             &extendedIndexTable[CL_AMS_MGMT_OI_SGSURANK],
                                             &i);
        if(rankList.entity)
        {
            clHeapFree(rankList.entity);
            rankList.count = 0;
        }
    }

    rc = clAmsMgmtGetSIList(mgmtHandle, &siList);
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "SI list get returned [%#x]", rc);
        goto out;
    }

    for(i = 0; i < siList.count; ++i)
    {
        ClAmsEntityBufferT list = {0};
        memcpy(&moId, &chassisMoid, sizeof(moId));
        rc = clCorMoIdAppend(&moId, classIds[CL_AMS_ENTITY_TYPE_SI], i);
        CL_ASSERT(rc == CL_OK);
        rc = corAmfObjectCreate(i, &siList.entity[i], &moId);
        if(rc != CL_OK) goto out;
        
        rc = clAmsMgmtGetSIDependenciesList(mgmtHandle, &siList.entity[i],
                                            &list);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "SI [%s] dependencies list returned [%#x]",
                       siList.entity[i].name.value, rc);
            goto out;
        }
        if(list.count)
        {
            rc = corAmfExtendedClassObjectCreate("saAmfSISIDepTable",
                                                 &siList.entity[i],
                                                 &chassisMoid,
                                                 list.count,
                                                 &extendedIndexTable[CL_AMS_MGMT_OI_SISIDEP],
                                                 &i);
        }

        if(list.entity)
        {
            clHeapFree(list.entity);
            list.count = 0;
        }
        rc = clAmsMgmtGetSISURankList(mgmtHandle, &siList.entity[i], &list);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "SI [%s] su rank list returned [%#x]",
                       siList.entity[i].name.value, rc);
            goto out;
        }
        if(list.count)
        {
            rc = corAmfExtendedClassObjectCreate("saAmfSUsperSIRankTable",
                                                 &siList.entity[i],
                                                 &chassisMoid,
                                                 list.count,
                                                 &extendedIndexTable[CL_AMS_MGMT_OI_SUSPERSIRANK],
                                                 &i);
        }
        if(list.entity)
        {
            list.count = 0;
            clHeapFree(list.entity);
        }
    }
    
    rc = clAmsMgmtGetCSIList(mgmtHandle, &csiList);
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "CSI list get returned [%#x]", rc);
        goto out;
    }
    for(i = 0; i < csiList.count; ++i)
    {
        ClAmsCSINVPBufferT buffer = {0};
        ClAmsEntityBufferT list = {0};
        memcpy(&moId, &chassisMoid, sizeof(moId));
        rc = clCorMoIdAppend(&moId, classIds[CL_AMS_ENTITY_TYPE_CSI], i);
        CL_ASSERT(rc == CL_OK);
        rc = corAmfObjectCreate(i, &csiList.entity[i], &moId);
        if(rc != CL_OK) goto out;

        rc = clAmsMgmtGetCSINVPList(mgmtHandle, &csiList.entity[i], &buffer);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "CSI [%s] nvp list returned [%#x]",
                       csiList.entity[i].name.value, rc);
            goto out;
        }
        
        rc = corAmfExtendedClassObjectCreate("saAmfCSINameValueTable",
                                             &csiList.entity[i],
                                             &chassisMoid,
                                             buffer.count,
                                             &extendedIndexTable[CL_AMS_MGMT_OI_CSINAMEVALUE],
                                             &i);
        if(buffer.nvp)
        {
            clHeapFree(buffer.nvp);
        }

        rc = clAmsMgmtGetCSIDependenciesList(mgmtHandle, &csiList.entity[i],
                                             &list);
        if(rc != CL_OK)
        {
            clLogError("COR", "AMF", "CSI [%s] dependencies list returned [%#x]",
                       csiList.entity[i].name.value, rc);
            goto out;
        }
        
        rc = corAmfExtendedClassObjectCreate("saAmfCSICSIDepTable",
                                             &csiList.entity[i],
                                             &chassisMoid,
                                             list.count,
                                             &extendedIndexTable[CL_AMS_MGMT_OI_CSICSIDEP],
                                             &i);
        if(list.entity)
        {
            clHeapFree(list.entity);
        }
    }

    /*
     * We are here when the objects are all created. Do a commit
     */
    rc = corAmfObjectCommit();
    if(rc != CL_OK)
    {
        clLogError("COR", "AMF", "Object commit returned [%#x]", rc);
        goto out;
    }

    clLogNotice("COR", "AMF", "COR AMF tree successfully initialized");

    out:
    if(nodeList.entity) 
        clHeapFree(nodeList.entity);
    if(suList.entity)   
        clHeapFree(suList.entity);
    if(compList.entity) 
        clHeapFree(compList.entity);
    if(sgList.entity)   
        clHeapFree(sgList.entity);
    if(siList.entity)   
        clHeapFree(siList.entity);
    if(csiList.entity) 
        clHeapFree(csiList.entity);
    return rc;
}
ClRcT clAmsMgmtOIInitialize(ClAmsMgmtHandleT *pHandle, 
                            ClRcT (*pClAmsMgmtOIConfigAttributesGet)
                            (ClAmsEntityConfigT*, ClCorAttributeValueListPtrT pAttrList),
                            ClRcT (*pClAmsMgmtOIExtendedConfigAttributesGet)
                            (ClAmsMgmtOIExtendedClassTypeT type, 
                             ClAmsMgmtOIExtendedEntityConfigT *pConfig,
                             ClCorClassTypeT *pClassType,
                             ClCorAttributeValueListT *pAttrList))
{
    ClRcT rc = CL_OK;
    ClAmsMgmtHandleT handle = 0;
    ClAmsEntityBufferT buffer[CL_AMS_ENTITY_TYPE_MAX+2] = {{0}};
    ClVersionT version = {'B', 0x1, 0x1};
    ClCorTxnSessionIdT txnSession = 0;
    ClUint32T i;
    ClCorAddrT appAddress = {0};
    SaNameT chassisInstance = {0};
    ClUint32T chassisId = 0;

    if(!pClAmsMgmtOIConfigAttributesGet)
        return CL_AMS_RC(CL_ERR_INVALID_PARAMETER);

    rc = clOsalMutexInit(&gClAmsMgmtOICacheMutex);
    CL_ASSERT(rc == CL_OK);

    rc = clEoMyEoIocPortGet(&appAddress.portId);
    if(rc != CL_OK) 
        return rc;
    appAddress.nodeAddress = clIocLocalAddressGet();

    rc = clAmsMgmtInitialize(&handle, NULL, &version);
    if(rc != CL_OK)
    {
        return rc;
    }
    snprintf(chassisInstance.value, sizeof(chassisInstance.value),
             "%s:%d", "\\Chassis", chassisId);
    chassisInstance.length = strlen(chassisInstance.value);
    rc = clCorMoIdNameToMoIdGet(&chassisInstance, &gClChassisMoid);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "COR moid get for [%s] returned [%#x]",
                   chassisInstance.value, rc);
        goto out_free;
    }
    rc = clAmsMgmtGetSGList(handle, &buffer[CL_AMS_ENTITY_TYPE_SG]);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "Get SG list returned [%#x]", rc);
        goto out_free;
    }
    rc = clAmsMgmtGetSIList(handle, &buffer[CL_AMS_ENTITY_TYPE_SI]);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "Get SI list returned [%#x]", rc);
        goto out_free;
    }
    rc = clAmsMgmtGetCSIList(handle, &buffer[CL_AMS_ENTITY_TYPE_CSI]);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "Get CSI list returned [%#x]", rc);
        goto out_free;
    }
    rc = clAmsMgmtGetNodeList(handle, &buffer[CL_AMS_ENTITY_TYPE_NODE]);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "Get NODE list returned [%#x]", rc);
        goto out_free;
    }
    rc = clAmsMgmtGetSUList(handle, &buffer[CL_AMS_ENTITY_TYPE_SU]);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "Get SU list returned [%#x]", rc);
        goto out_free;
    }
    rc = clAmsMgmtGetCompList(handle, &buffer[CL_AMS_ENTITY_TYPE_COMP]);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "Get COMP list returned [%#x]", rc);
        goto out_free;
    }
    /*
     * Now fetch the moid for each of the entities and build the cache.
     */
    for(i = 0; i <= CL_AMS_ENTITY_TYPE_MAX; ++i)
    {
        ClAmsEntityBufferT *pBuffer = &buffer[i];
        ClUint32T j;
        if(!pBuffer->count || !pBuffer->entity)
            continue;
        gClAmsMgmtOIIndexTable[i] = pBuffer->count;
        for(j = 0; j < pBuffer->count; ++j)
        {
            ClCorMOIdT moid = {{{0}}};
            rc = clAmsMgmtOIMoIdGet(handle, pBuffer->entity+j, &moid);
            if(rc != CL_OK)
            {
                continue;
            }
            clAmsMgmtOICacheAdd(clCorMoIdToInstanceGet(&moid), pBuffer->entity+j);
            /*
             * Required for instances exceeding the pre-configured limit.
             */
             rc = clCorOIRegister(&moid, &appAddress);
             if(rc != CL_OK)
             {
                 continue;
             }
            rc = clCorPrimaryOISet(&moid, &appAddress);
            if(rc != CL_OK)
            {
                /*
                 * Ignore as it could be already set by the active.
                 */
                continue;
            }
            clAmsMgmtOIConfigAttributeSet(handle, &txnSession, &moid, pBuffer->entity+j, pClAmsMgmtOIConfigAttributesGet);
            clAmsMgmtOIExtendedConfigAttributeSet(handle, &txnSession, pBuffer->entity+j,
                                                  pClAmsMgmtOIExtendedConfigAttributesGet);
        }
    }
    rc = clCorTxnSessionCommit(txnSession);
    if(rc != CL_OK)
    {
        clLogError("AMF", "MGMT", "AMF OI config commit returned [%#x]", rc);
    }
    else
    {
        clLogNotice("AMF", "MGMT", "Entity cache successfully initialized");
        gClAmsMgmtOIInitialized = CL_TRUE;
    }

    out_free:
    for(i = 0; i <= CL_AMS_ENTITY_TYPE_MAX; ++i)
    {
        if(buffer[i].entity) clHeapFree(buffer[i].entity);
        if(rc != CL_OK) clAmsMgmtOICacheDestroy(i);
    }
    if(rc != CL_OK)
    {
        for(i = 0; i < CL_AMS_MGMT_OI_EXTENDED_CLASS_MAX; ++i)
            clAmsMgmtOIExtendedCacheDestroy(i);
    }
    if(rc == CL_OK && pHandle)
        *pHandle = handle;
    else 
        clAmsMgmtFinalize(handle);

    return rc;
}
/**
 * The mode end function which is called after every mode is finished.
 * This is used currently to do bulk get. When the vbcount of the requests
 * is equal to the varcount.
 */
int
clSnmpModeEndCallback(
        netsnmp_mib_handler               *handler,
        netsnmp_handler_registration      *reginfo,
        netsnmp_agent_request_info        *reqinfo,
        netsnmp_request_info              *requests)
{
    ClRcT   rc = CL_SNMP_ERR_NOERROR;
    netsnmp_request_info * request = NULL;
    static ClUint16T noOfOps = 0;

    clLogDebug("SNM","OPE", "Inside MODE-END callback [%s] ...mode [%d]", 
            __FUNCTION__, reqinfo->mode );
    
        switch (reqinfo->mode)
    {
        case MODE_GETBULK:
            clLogDebug("SNM","OPE", "Inside mode BULK-GET");
            break;
        case MODE_GETNEXT:
        case MODE_GET:
            {
                for (request = requests; request != NULL; request = request->next)
                {
                    noOfOps++;
                }

                clLogDebug("SNM","OPE", "Inside mode [%s] vbC[%d] noOfOps [%d]",
                        reqinfo->mode == MODE_GET ? "GET": "GET-NEXT", reqinfo->asp->vbcount, noOfOps);

                if (gErrorHappened == CL_TRUE)
                {
                    noOfOps = 0;
                    clSnmpDataReset();
                    gErrorHappened = CL_FALSE;
                    clLogNotice("SNM","OPE", "Error happened in the validating the request.");
                    netsnmp_request_set_error(requests, CL_SNMP_ERR_NOSUCHNAME);
                    return CL_SNMP_ERR_NOSUCHNAME;
                }
                        
                if (reqinfo->asp->vbcount == noOfOps)
                {
                    clLogDebug("SNP","OPE", "Sending the get request now as the vbCount and varCount are equal.");
                    rc = clSnmpProcessRequest(requests);
                    if (CL_OK != rc)
                        clLogError("SNP","OPE", "Failed while processing the GET request. rc[0x%x]", rc);
  		            noOfOps = 0;
                }
            }
            break;
        case MODE_SET_RESERVE1:
            clLogDebug("SNM","OPE", "Inside mode RESERVE1");
            break;
        case MODE_SET_RESERVE2:
            clLogDebug("SNM","OPE", "Inside mode RESERVE2");
            break;
        case MODE_SET_ACTION:
            clLogDebug("SNM","OPE", "Inside mode ACTION");
            break;
        case MODE_SET_COMMIT:
            clLogDebug("SNM","OPE", "Inside mode COMMIT");
            break;
        case MODE_SET_UNDO:
            clLogDebug("SNM","OPE", "Inside mode UNDO");
            break;
        case MODE_SET_FREE:
            clLogDebug("SNM","OPE", "Inside mode FREE");
            break;
        default:
            clLogDebug("SNM","OPE", "Inside default case");
    }

   return rc;
}
static ClRcT clAmsMgmtSGMigrateMPlusN(ClAmsSGRedundancyModelT model,
                                      ClAmsEntityT *sgName,
                                      const ClCharT *prefix,
                                      ClUint32T numActiveSUs,
                                      ClUint32T numStandbySUs,
                                      ClAmsMgmtMigrateListT *migrateList)
{
    ClUint32T i;
    ClRcT rc = CL_OK;
    ClAmsEntityBufferT siBuffer = {0};
    ClAmsEntityBufferT suBuffer = {0};
    ClAmsEntityBufferT nodeBuffer = {0};
    ClInt32T extraSIs = 0;
    ClInt32T extraSUs = 0;
    ClInt32T extraNodes = 0;
    ClAmsEntityT *nodeList = NULL;
    ClAmsEntityT *nodes = NULL;
    ClAmsEntityT *sus = NULL;
    ClAmsEntityT *comps = NULL;
    ClAmsEntityT *sis =  NULL;
    ClAmsEntityT *csis = NULL;
    ClInt32T numNodes = 0;
    ClAmsEntityConfigT *pSURefComp = NULL;
    ClAmsEntityConfigT *pSGRefSI = NULL;
    ClAmsEntityConfigT *pSIRefCSI = NULL;
    ClAmsEntityConfigT *pSGConfig = NULL;
    ClAmsSGConfigT sgConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
    ClUint32T numSupportedCSITypes = 0;
    SaNameT *pNumSupportedCSITypes = NULL;
    ClAmsMgmtCCBHandleT ccbHandle = 0;
    ClAmsMgmtMigrateListT *unlockList = NULL;

    rc = clAmsMgmtEntityGetConfig(gHandle, sgName, &pSGConfig);
    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "SG [%.*s] config get returned [%#x]",
                   sgName->name.length-1, sgName->name.value, rc);
        goto out;
    }

    memcpy(&sgConfig, pSGConfig, sizeof(sgConfig));
    clHeapFree(pSGConfig);

    /*
     * If scaling down actives, ensure that those many service units are locked.
     */
    if(numActiveSUs < sgConfig.numPrefActiveSUs)
    {
        ClInt32T numShrinkSUs = sgConfig.numPrefActiveSUs - numActiveSUs;
        ClAmsEntityBufferT suList = {0};
        ClInt32T numOutOfServiceSUs = 0;
        rc = clAmsMgmtGetSGSUList(gHandle, sgName, &suList);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "SG [%.*s] su list returned [%#x]",
                       sgName->name.length-1, sgName->name.value, rc);
            goto out;
        }
        for(i = 0; i < suList.count; ++i)
        {
            ClAmsSUConfigT *pSUConfig = NULL;
            rc = clAmsMgmtEntityGetConfig(gHandle, suList.entity+i,
                                          (ClAmsEntityConfigT**)&pSUConfig);
            if(rc != CL_OK)
            {
                clHeapFree(suList.entity);
                clLogError("AMS", "MIGRATE", "SU [%.*s] get config returned [%#x]",
                           suList.entity[i].name.length-1, suList.entity[i].name.value, rc);
                goto out;
            }
            if(pSUConfig->adminState == CL_AMS_ADMIN_STATE_LOCKED_A
               ||
               pSUConfig->adminState == CL_AMS_ADMIN_STATE_LOCKED_I)
            {
                ++numOutOfServiceSUs;
            }
            clHeapFree(pSUConfig);
        }
        clHeapFree(suList.entity);
        if(numOutOfServiceSUs < numShrinkSUs)
        {
            clLogError("AMS", "MIGRATE", "Expected a minimum of [%d] SUs to be out of service to satisfy SG. "
                       "redundancy model shrink. Got [%d] out of service", numShrinkSUs,
                       numOutOfServiceSUs);
            rc = CL_AMS_RC(CL_AMS_ERR_INVALID_ENTITY_STATE);
            goto out;
        }
    }

    rc = clAmsMgmtSGRedundancyModelEstimate(model, sgName, numActiveSUs, numStandbySUs,
                                            &extraSIs, &extraSUs, &extraNodes);

    if(rc != CL_OK)
    {
        goto out;
    }
    
    rc = clAmsMgmtCCBInitialize(gHandle, &ccbHandle);
    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "AMS ccb initialize returned [%#x]", rc);
        goto out;
    }

    /* 
     * Add the existing SI CSI list to the supported list.
     */
    rc = clAmsMgmtGetSGSIList(gHandle, sgName, &siBuffer);
    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "AMS sg si list returned [%#x]", rc);
        goto out;
    }

    if(siBuffer.count)
    {
        rc = clAmsMgmtEntityGetConfig(gHandle, siBuffer.entity,
                                      &pSGRefSI);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "AMS reference si get config returned [%#x]",
                       rc);
            goto out_free;
        }
    }

    for(i = 0; i < siBuffer.count; ++i)
    {
        ClUint32T j; 
        ClAmsEntityBufferT csiBuffer = {CL_AMS_ENTITY_TYPE_ENTITY};
        ClAmsSIConfigT siConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
        ClUint64T mask = 0;
        memcpy(&siConfig.entity, siBuffer.entity+i, 
               sizeof(siConfig.entity));
        mask |= SI_CONFIG_NUM_STANDBY_ASSIGNMENTS;
        siConfig.numStandbyAssignments = numStandbySUs;
        if(numActiveSUs > 1)
            siConfig.numStandbyAssignments = (numStandbySUs+1)&~1;
        siConfig.numStandbyAssignments = CL_MAX(1, siConfig.numStandbyAssignments/
                                                (numActiveSUs?numActiveSUs:1));
        /*
         * Update the num standby assignments.
         */
        rc = clAmsMgmtCCBEntitySetConfig(ccbHandle, &siConfig.entity, mask);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "SI [%.*s] num standby set returned [%#x]",
                       siConfig.entity.name.length-1, siConfig.entity.name.value, rc);
        }

        rc = clAmsMgmtGetSICSIList(gHandle, siBuffer.entity+i,
                                   &csiBuffer);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "AMS get si csi list returned [%#x]", rc);
            goto out_free;
        }
        pNumSupportedCSITypes = (SaNameT*) clHeapRealloc(pNumSupportedCSITypes, (numSupportedCSITypes+csiBuffer.count)*sizeof(SaNameT));
        for(j = 0; j < csiBuffer.count ; ++j)
        {
            ClAmsEntityConfigT *entityConfig = NULL;
            ClAmsCSIConfigT csiConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
            ClUint32T k;

            rc = clAmsMgmtEntityGetConfig(gHandle, csiBuffer.entity+j, &entityConfig);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS csi get config returned [%#x]", rc);
                goto out_free;
            }
            memcpy(&csiConfig, entityConfig, sizeof(csiConfig));
            if(!pSIRefCSI)
            {
                pSIRefCSI = entityConfig;
            }
            else
            {
                clHeapFree(entityConfig);
            }
            /*
             * Search for this csi type in the list to see if its 
             * already present
             */
            for(k = 0; k < numSupportedCSITypes; ++k)
            {
                if(!memcmp(pNumSupportedCSITypes[k].value,
                           csiConfig.type.value,
                           pNumSupportedCSITypes[k].length))
                    break;
            }

            if(k == numSupportedCSITypes)
            {
                memcpy(pNumSupportedCSITypes+numSupportedCSITypes,
                       &csiConfig.type, sizeof(csiConfig.type));
                ++numSupportedCSITypes;
            }
        }

        clHeapFree(csiBuffer.entity);
    }
    
    if(extraSIs)
    {
        sis = (ClAmsEntityT*) clHeapCalloc(extraSIs, sizeof(ClAmsEntityT));
        CL_ASSERT(sis != NULL);
        csis = (ClAmsEntityT*) clHeapCalloc(extraSIs, sizeof(ClAmsEntityT));
        for(i = siBuffer.count; i < siBuffer.count + extraSIs; ++i)
        {
            ClAmsEntityT si ={CL_AMS_ENTITY_TYPE_ENTITY};
            ClAmsEntityT csi = {CL_AMS_ENTITY_TYPE_ENTITY};
            ClUint64T bitMask = 0;
            ClAmsSIConfigT siConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
            ClAmsCSIConfigT csiConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
            si.type = CL_AMS_ENTITY_TYPE_SI;
            snprintf((ClCharT*)si.name.value, sizeof(si.name.value)-1, "%s_%.*s_SI%d", prefix,
                     sgName->name.length-1, (const ClCharT*)sgName->name.value, i);
            clLogNotice("AMS", "MIGRATE", "Creating SI [%s]", si.name.value);
            si.name.length = strlen((const ClCharT*)si.name.value)+1;
            rc = clAmsMgmtCCBEntityCreate(ccbHandle, &si);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS entity create returned [%#x]", rc);
                goto out_free;
            }
            memcpy(&sis[i-siBuffer.count], &si, sizeof(si));
            
            rc = clAmsMgmtCCBSetSGSIList(ccbHandle, sgName, &si);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS set sg silist returned [%#x]", rc);
                goto out_free;
            }

            if(pSGRefSI)
            {
                /*
                 * Set config to the base SI.
                 */
                bitMask = CL_AMS_CONFIG_ATTR_ALL;
                memcpy(&siConfig, pSGRefSI, sizeof(siConfig));
                memcpy(&siConfig.entity, &si, sizeof(siConfig.entity));
                siConfig.numStandbyAssignments = numStandbySUs;
                if(numActiveSUs > 1 )
                    siConfig.numStandbyAssignments = (numStandbySUs+1)&~1;
                siConfig.numStandbyAssignments = CL_MAX(1,siConfig.numStandbyAssignments/
                                                        (numActiveSUs?numActiveSUs:1));
                siConfig.numCSIs = 1;
                siConfig.adminState = CL_AMS_ADMIN_STATE_LOCKED_A;
                rc = clAmsMgmtCCBEntitySetConfig(ccbHandle, &siConfig.entity, bitMask);
                if(rc != CL_OK)
                {
                    clLogError("AMS", "MIGRATE", "AMS entity set config returned [%#x]", rc);
                    goto out_free;
                }
            }

            csi.type = CL_AMS_ENTITY_TYPE_CSI;
            snprintf((ClCharT*)csi.name.value, sizeof(csi.name.value),
                     "%s_CSI%d", (const ClCharT*)si.name.value, i-siBuffer.count);
            csi.name.length = strlen((const ClCharT*)csi.name.value)+1;
            clLogNotice("AMS", "MIGRATE", "Creating CSI [%s]", csi.name.value);
            rc = clAmsMgmtCCBEntityCreate(ccbHandle, &csi);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS csi create returned [%#x]", rc);
                goto out_free;
            }
            memcpy(&csis[i-siBuffer.count], &csi, sizeof(csi));
            rc = clAmsMgmtCCBSetSICSIList(ccbHandle, &si, &csi);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "SET si csi list returned [%#x]", rc);
                goto out_free;
            }
            
            if(pSIRefCSI)
            {
                /*
                 * Load the config. for the base csi type.
                 */
                memcpy(&csiConfig, pSIRefCSI, sizeof(csiConfig));
                memcpy(&csiConfig.entity, &csi, sizeof(csiConfig.entity));
                csiConfig.isProxyCSI = CL_FALSE;
                memcpy(&csiConfig.type, &csiConfig.entity.name, sizeof(csiConfig.type));
                bitMask = CL_AMS_CONFIG_ATTR_ALL;
                rc = clAmsMgmtCCBEntitySetConfig(ccbHandle, &csiConfig.entity, bitMask);
                if(rc != CL_OK)
                {
                    clLogError("AMS", "MIGRATE", "AMS ref csi set config returned [%#x]", rc);
                    goto out_free;
                }
            }
            /*
             * Add this to the supported list.
             */
            pNumSupportedCSITypes = (SaNameT*) clHeapRealloc(pNumSupportedCSITypes, (numSupportedCSITypes+1)*sizeof(SaNameT));
            CL_ASSERT(pNumSupportedCSITypes != NULL);
            memcpy(pNumSupportedCSITypes+numSupportedCSITypes, &csi.name, sizeof(SaNameT));
            ++numSupportedCSITypes;
        }
    }

    if(extraNodes)
    {
        nodes = (ClAmsEntityT*) clHeapCalloc(extraNodes, sizeof(ClAmsEntityT));
        CL_ASSERT(nodes != NULL);

        rc = clAmsMgmtGetNodeList(gHandle, &nodeBuffer);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "AMS get node list returned [%#x]", rc);
            goto out_free;
        }
        for(i = nodeBuffer.count ; i < nodeBuffer.count + extraNodes; ++i)
        {
            ClAmsEntityT node = {CL_AMS_ENTITY_TYPE_ENTITY};
            node.type = CL_AMS_ENTITY_TYPE_NODE;
            snprintf((ClCharT*) node.name.value, sizeof(node.name.value), "%s_Node%d", prefix, i);
            node.name.length = strlen((const ClCharT*) node.name.value) + 1;
            clLogNotice("AMS", "MIGRATE", "Creating node [%s]", node.name.value);
            rc = clAmsMgmtCCBEntityCreate(ccbHandle, &node);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS ccb create returned [%#x]", rc);
                goto out_free;
            }
            memcpy(&nodes[i-nodeBuffer.count], &node, sizeof(node));
        }
    }

    rc = clAmsMgmtGetSGSUList(gHandle, sgName, &suBuffer);
    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "Get SG su list returned [%#x]", rc);
        goto out_free;
    }

    for(i = 0 ; i < suBuffer.count; ++i)
    {
        ClUint32T j;
        ClAmsEntityBufferT compBuffer=
            {
                0
            }
        ;
        rc = clAmsMgmtGetSUCompList(gHandle, &suBuffer.entity[i],
                                    &compBuffer);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "Get SU comp list returned [%#x]", rc);
            goto out_free;
        }
        /*
         * Get the first component properties.
         */
        if(!pSURefComp)
        {
            rc = clAmsMgmtEntityGetConfig(gHandle, compBuffer.entity,
                                          &pSURefComp);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS base comp get config returned [%#x]",
                           rc);
                goto out_free;
            }
        }

        /*
         * Update all config. with supported csi types.
         * and correct comp config whereever appropriate
         */
        for(j = 0; j < compBuffer.count; ++j)
        {
            ClAmsEntityConfigT *entityConfig =NULL;
            ClAmsCompConfigT compConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
            ClUint64T bitMask = 0;
            ClUint32T k ;
            rc = clAmsMgmtEntityGetConfig(gHandle, compBuffer.entity+j,
                                          &entityConfig);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS comp get config returned [%#x]", rc);
                goto out_free;
            }
            memcpy(&compConfig, entityConfig, sizeof(compConfig));
            clHeapFree(entityConfig);
            /*
             * update supported CSI type incase of SI additions.
             */
            if(extraSIs)
            {
                bitMask |= COMP_CONFIG_SUPPORTED_CSI_TYPE;
                compConfig.pSupportedCSITypes = (SaNameT*) clHeapRealloc(compConfig.pSupportedCSITypes, (compConfig.numSupportedCSITypes + extraSIs)* sizeof(SaNameT));
                CL_ASSERT(compConfig.pSupportedCSITypes);
                for(k = compConfig.numSupportedCSITypes; k < compConfig.numSupportedCSITypes + extraSIs; ++k)
                {
                    memcpy(compConfig.pSupportedCSITypes+k, &csis[k-compConfig.numSupportedCSITypes].name, sizeof(SaNameT));
                }
                compConfig.numSupportedCSITypes += extraSIs;
            }
            bitMask |= COMP_CONFIG_NUM_MAX_STANDBY_CSIS;
            /*
             * take active to standby ratio
             */
            compConfig.numMaxStandbyCSIs = numActiveSUs;
            if(numStandbySUs > 1 )
                compConfig.numMaxStandbyCSIs = (numActiveSUs+1)&~1;
            compConfig.numMaxStandbyCSIs = CL_MAX(1, compConfig.numMaxStandbyCSIs/
                                                  (numStandbySUs?numStandbySUs:1));
            rc = clAmsMgmtCCBEntitySetConfig(ccbHandle,
                                             &compConfig.entity,
                                             bitMask);
            clHeapFree(compConfig.pSupportedCSITypes);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS entity set config returned [%#x]", rc);
                goto out_free;
            }
        }
        clHeapFree(compBuffer.entity);
    }

    if(extraSUs)
    {
        sus = (ClAmsEntityT*) clHeapCalloc(extraSUs, sizeof(ClAmsEntityT));
        CL_ASSERT(sus != NULL);
        comps = (ClAmsEntityT*) clHeapCalloc(extraSUs, sizeof(ClAmsEntityT));
        CL_ASSERT(comps != NULL);
        nodeList = (ClAmsEntityT*) clHeapCalloc(extraSUs + extraNodes, sizeof(ClAmsEntityT));
        CL_ASSERT(nodeList != NULL);

        rc = clAmsMgmtGetSUFreeNodes(sgName, prefix, extraSUs, extraNodes, nodeList, &numNodes);

        for(i = suBuffer.count; i < suBuffer.count + extraSUs; ++i)
        {
            ClAmsEntityT su = {CL_AMS_ENTITY_TYPE_ENTITY};
            ClAmsEntityT comp = {CL_AMS_ENTITY_TYPE_ENTITY};
            ClAmsSUConfigT suConfig = 
                {
                    {
                       CL_AMS_ENTITY_TYPE_ENTITY
                    }
                }
            ;
            ClAmsCompConfigT compConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
            ClUint64T bitMask = 0;

            su.type = CL_AMS_ENTITY_TYPE_SU;
            snprintf((ClCharT*)su.name.value, sizeof(su.name.value),
                     "%s_%s_SU%d", prefix, (const ClCharT*)nodeList[i-suBuffer.count].name.value, i);

            su.name.length = strlen((const ClCharT*)su.name.value)+1;
            clLogNotice("AMS", "MIGRATE", "Creating SU [%s]", su.name.value);
            rc = clAmsMgmtCCBEntityCreate(ccbHandle, &su);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "SU create returned [%#x]", rc);
                goto out_free;
            }
            memcpy(&sus[i-suBuffer.count], &su, sizeof(su));
            /*
             * Assign this SU under the parent node and SG
             */
            rc = clAmsMgmtCCBSetNodeSUList(ccbHandle, &nodeList[i-suBuffer.count], &su);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "Node su list set returned [%#x]", rc);
                goto out_free;
            }

            /*
             * Give the parent SG. for this SU
             */
            rc = clAmsMgmtCCBSetSGSUList(ccbHandle, sgName, &su);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "Set SG su list returned [%#x]", rc);
                goto out_free;
            }
            bitMask = SU_CONFIG_NUM_COMPONENTS;
            memcpy(&suConfig.entity, &su, sizeof(suConfig.entity));
            suConfig.numComponents = 1;
            rc = clAmsMgmtCCBEntitySetConfig(ccbHandle, &suConfig.entity, bitMask);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "SU set config returned [%#x]", rc);
                goto out_free;
            }
            
            comp.type = CL_AMS_ENTITY_TYPE_COMP;
            snprintf((ClCharT*) comp.name.value, sizeof(comp.name.value), "%s_Comp%d", su.name.value, i - suBuffer.count);
            comp.name.length = strlen((const ClCharT*) comp.name.value) + 1;
            clLogNotice("AMS", "MIGRATE", "Creating component [%s]",
                        comp.name.value);
            rc = clAmsMgmtCCBEntityCreate(ccbHandle, &comp);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "Comp create returned [%#x]", rc);
                goto out_free;
            }
            memcpy(&comps[i-suBuffer.count], &comp, sizeof(comp));
            rc = clAmsMgmtCCBSetSUCompList(ccbHandle, &su, 
                                           &comp);
            if(rc != CL_OK)
            {
                clLogError("AMS", "MIGRATE", "AMS set su comp list returned [%#x]", rc);
                goto out_free;
            }
            
            if(pSURefComp)
            {
                /*
                 * At this stage, we have created the hierarchy. 
                 * Set the comp property to the base component type and
                 * add the num supported CSI types to be part of every component
                 * added to the SU.
                 */

                bitMask = CL_AMS_CONFIG_ATTR_ALL;
                memcpy(&compConfig, pSURefComp, sizeof(compConfig));
                memcpy(&compConfig.entity, &comp, sizeof(compConfig.entity));
                compConfig.numSupportedCSITypes = numSupportedCSITypes;
                compConfig.pSupportedCSITypes = pNumSupportedCSITypes;
                memcpy(&compConfig.parentSU.entity, &su, sizeof(compConfig.parentSU.entity));
                
                /*
                 * Distribute the standbys based on the active/standby ratio.
                 */
                compConfig.numMaxStandbyCSIs = numActiveSUs;
                if(numStandbySUs > 1 )
                    compConfig.numMaxStandbyCSIs = (numActiveSUs+1)&~1;
                compConfig.numMaxStandbyCSIs = CL_MAX(1, compConfig.numMaxStandbyCSIs/
                                                      (numStandbySUs?numStandbySUs:1));
                rc = clAmsMgmtCCBEntitySetConfig(ccbHandle, &compConfig.entity,
                                                 bitMask);
                if(rc != CL_OK)
                {
                    clLogError("AMS", "MIGRATE", "AMS set config returned [%#x]", rc);
                    goto out_free;
                }
            }
        }
    }

    /*
     * At this stage, we are all set to commit. after updating SG config.
     */
    {
        ClUint64T bitMask = 0;
        bitMask |= SG_CONFIG_REDUNDANCY_MODEL;
        sgConfig.redundancyModel = model;
        sgConfig.numPrefActiveSUs = numActiveSUs;
        bitMask |= SG_CONFIG_NUM_PREF_ACTIVE_SUS;
        sgConfig.numPrefStandbySUs = numStandbySUs;
        bitMask |= SG_CONFIG_NUM_PREF_STANDBY_SUS;
        if(sgConfig.numPrefInserviceSUs < numActiveSUs + numStandbySUs)
        {
            sgConfig.numPrefInserviceSUs = numActiveSUs + numStandbySUs;
            bitMask |= SG_CONFIG_NUM_PREF_INSERVICE_SUS;
        }
        sgConfig.numPrefAssignedSUs = numActiveSUs + numStandbySUs;
        bitMask |= SG_CONFIG_NUM_PREF_ASSIGNED_SUS;
        /*
         * Active standby ratio.
         */
        sgConfig.maxStandbySIsPerSU = numActiveSUs;
        if(numStandbySUs > 1 )
            sgConfig.maxStandbySIsPerSU = (numActiveSUs+1)&~1;
        sgConfig.maxStandbySIsPerSU = CL_MAX(1,sgConfig.maxStandbySIsPerSU/
                                             (numStandbySUs?numStandbySUs:1));
        bitMask |= SG_CONFIG_MAX_STANDBY_SIS_PER_SU;
        rc = clAmsMgmtCCBEntitySetConfig(ccbHandle, &sgConfig.entity, bitMask);
        if(rc != CL_OK)
        {
            clLogError("AMS", "MIGRATE", "AMS sg set config returned [%#x]", rc);
            goto out_free;
        }
    }

    rc = clAmsMgmtCCBCommit(ccbHandle);
    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "AMS database commit returned [%#x]", rc);
    }

    /*
     * Okay, the commit is successful. Now unlock all added entities
     * except SU so that other attributes could be updated before unlocking
     * Do that in a separate thread as there could be pending invocations.
     */
    unlockList = (ClAmsMgmtMigrateListT*) clHeapCalloc(1, sizeof(*unlockList));
    CL_ASSERT(unlockList != NULL);
    unlockList->si.count = extraSIs;
    unlockList->node.count = extraNodes;
    unlockList->su.count = extraSUs;
                                                
    unlockList->si.entity = (ClAmsEntityT*) clHeapCalloc(extraSIs, sizeof(*sis));
    unlockList->node.entity = (ClAmsEntityT*) clHeapCalloc(extraNodes, sizeof(*nodes));
    unlockList->su.entity = (ClAmsEntityT*) clHeapCalloc(extraSUs, sizeof(*sus));

    CL_ASSERT(unlockList->si.entity && unlockList->node.entity && unlockList->su.entity);

    memcpy(unlockList->si.entity, sis, sizeof(*sis)*extraSIs);
    memcpy(unlockList->node.entity, nodes, sizeof(*nodes)*extraNodes);
    memcpy(unlockList->su.entity, sus, sizeof(*sus) * extraSUs);

    clOsalTaskCreateDetached("MIGRATE-UNLOCK-THREAD", CL_OSAL_SCHED_OTHER, 0, 0, 
                             clAmsMgmtMigrateListUnlock, (void*)unlockList);

    /*
     * Return the newly created info. in the migrated list.
     */
    if(migrateList)
    {
        if(extraSIs)
        {
            migrateList->si.count = extraSIs;
            migrateList->si.entity = sis;
            migrateList->csi.count = extraSIs;
            migrateList->csi.entity = csis;
            sis = csis = NULL;
        }

        if(extraNodes)
        {
            migrateList->node.count = extraNodes;
            migrateList->node.entity = nodes;
            nodes = NULL;
        }

        if(extraSUs)
        {
            migrateList->su.count = extraSUs;
            migrateList->su.entity = sus;
            migrateList->comp.count = extraSUs;
            migrateList->comp.entity = comps;
            sus = comps = NULL;
        }
    }

    out_free:

    clAmsMgmtCCBFinalize(ccbHandle);

    if(siBuffer.entity) clHeapFree(siBuffer.entity);
    if(nodeBuffer.entity) clHeapFree(nodeBuffer.entity);
    if(suBuffer.entity) clHeapFree(suBuffer.entity);
    if(nodeList) clHeapFree(nodeList);
    if(nodes) clHeapFree(nodes);
    if(sus) clHeapFree(sus);
    if(comps) clHeapFree(comps);
    if(sis) clHeapFree(sis);
    if(csis) clHeapFree(csis);
    if(pSGRefSI) clHeapFree(pSGRefSI);
    if(pSIRefCSI) clHeapFree(pSIRefCSI);
    if(pSURefComp) clHeapFree(pSURefComp);
    if(pNumSupportedCSITypes) clHeapFree(pNumSupportedCSITypes);

    out:
    return rc;
}
/*
 * Before calling ifconfig, we want to check if interface and ip existing,
 * if so, just ignore the calling command
 */
static ClRcT _clCheckExistingDevIf(const ClCharT *ip, const ClCharT *dev)
{
    int sd = -1;
    int i = 0;
    ClUint32T reqs = 0;
    struct ifconf   ifc = {0};
    struct ifreq    *ifr = NULL;
    ClCharT addrStr[INET_ADDRSTRLEN] = {0};

    /* Get a socket handle. */
    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd < 0) {
        clLogError(
                "IOC",
                CL_LOG_PLUGIN_HELPER_AREA,
                "open socket failed with error [%s]", strerror(errno));
        return (0);
    }

    memset(&ifc, 0, sizeof(ifc));

    /* Query available interfaces. */
    do
    {
        reqs += 5;
        ifc.ifc_len = reqs * sizeof(*ifr);
        ifc.ifc_buf = (char*) realloc(ifc.ifc_buf, sizeof(*ifr) * reqs);
        CL_ASSERT(ifc.ifc_buf != NULL);
        if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) {
            clLogNotice("IOC",
                    CL_LOG_PLUGIN_HELPER_AREA,
                    "Operation command failed: [%s]", strerror(errno));
            goto out;
        }
    } while ((unsigned int )ifc.ifc_len == reqs * sizeof(*ifr));


    /* Iterate through the list of interfaces. */
    ifr = ifc.ifc_req;
    for(i = 0; i < ifc.ifc_len; i += sizeof(*ifr))
    {
//        clLogTrace("IOC",
//                        CL_LOG_PLUGIN_HELPER_AREA,
//                        "Checking interface name [%s]",
//                        ifr->ifr_name);

        /* Checking if match interface name first */
        if (strlen(ifr->ifr_name) == strlen(dev)
                && memcmp(ifr->ifr_name, dev, strlen(dev)) == 0)
        {

            /* Get the address
             * This may seem silly but it seems to be needed on some systems
             */
            if (ioctl(sd, SIOCGIFADDR, ifr) < 0) {
                clLogNotice("IOC",
                        CL_LOG_PLUGIN_HELPER_AREA,
                        "Operation command failed: [%s]", strerror(errno));
                break;
            }

            addrStr[0] = 0;
            struct in_addr *in4_addr = &((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr;
            if(!inet_ntop(PF_INET, (const void *)in4_addr, addrStr, sizeof(addrStr)))
            {
                struct in6_addr *in6_addr = &((struct sockaddr_in6*)&ifr->ifr_addr)->sin6_addr;
                if(!inet_ntop(PF_INET6, (const void*)in6_addr, addrStr, sizeof(addrStr)))
                {
                    goto out;
                }
            }

//            clLogTrace("IOC",
//                            CL_LOG_PLUGIN_HELPER_AREA,
//                            "Checking IP address [%s]",
//                            addrStr);

            if (strlen(addrStr) == strlen(ip)
                    && memcmp(addrStr, ip, strlen(ip)) == 0)
            {
                free(ifc.ifc_buf);
                close(sd);
                return (1);
            }

            /* Ignore other interfaces */
            break;
        }
        ++ifr;
    }

out:
    if (ifc.ifc_buf)
        free(ifc.ifc_buf);
    close(sd);
    return (0);
}
static ClRcT rmdSendTimerFunc(void *pData)
{
    ClCntNodeHandleT    nodeHandle;
    ClRmdRecordSendT    *rec         = NULL;
    ClRcT               rc;
    ClRcT               retCode      = 0;
    ClRmdObjT           *pRmdObject;
    ClRmdAsyncCallbackT fpTempPtr;
    void                *cookie;
    ClBufferHandleT     outMsgHdl;
    ClEoExecutionObjT   *pThis       = NULL;
    ClUint64T           msgId        = (ClUint32T)(ClWordT) pData;

    CL_FUNC_ENTER();
    if (pData == NULL)
    {
        return (CL_RMD_RC(CL_ERR_INVALID_BUFFER));
    }
    rc = clEoMyEoObjectGet(&pThis);

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

    pRmdObject = (ClRmdObjT *) (pThis->rmdObj);
    if (pRmdObject == NULL)
    {
        return (CL_RMD_RC(CL_ERR_INVALID_BUFFER));
    }

    rc = clOsalMutexLock(pRmdObject->semaForSendHashTable);
    CL_ASSERT(rc == CL_OK);
    clLogNotice("CALLBACK", "TASKS","Enter rmdSendTimerFunc 0");
    rc = clCntNodeFind(pRmdObject->sndRecContainerHandle, (ClPtrT)(ClWordT)msgId,
                       &nodeHandle);
    if (rc == CL_OK)
    {
        clLogNotice("CALLBACK", "TASKS","Enter rmdSendTimerFunc 1");

        rc = clCntNodeUserDataGet(pRmdObject->sndRecContainerHandle, nodeHandle,
                                  (ClCntDataHandleT *) &rec);
        if (rc == CL_OK)
        {
            clLogNotice("CALLBACK", "TASKS","Enter rmdSendTimerFunc 2");
            if (rec)
            {
                /*
                 * Disabling retries for ASYNC since we dont want
                 * to land up in duplicate send mess as anyway we have
                 * accounted for the retries while creating the async timer.
                 */
                if (0 && rec->recType.asyncRec.noOfRetry > 0)
                {
                    /*
                     * key is part of record so no need to free just reuse
                     */
                    retCode = resendMsg(rec, pRmdObject, pThis);
                }
                else
                {
                    /*
                     * key is part of record so no need to free, it will be
                     * freed by hash delete callback
                     */
                    RMD_STAT_INC(pRmdObject->rmdStats.nCallTimeouts);
                    retCode = clTimerDeleteAsync(&rec->recType.asyncRec.timerID);
                    if (rec->recType.asyncRec.func)
                    {
                        /*
                         * unlocking it as callback func can make the rmd call
                         */
                        ClBufferHandleT message;

                        fpTempPtr = rec->recType.asyncRec.func;
                        cookie = rec->recType.asyncRec.cookie;
                        outMsgHdl = rec->recType.asyncRec.outMsgHdl;
                        message = rec->recType.asyncRec.sndMsgHdl;
                        clBufferHeaderTrim(message, rec->hdrLen);
                        rc = clCntNodeDelete(pRmdObject->sndRecContainerHandle,
                                             nodeHandle);
                        rc = clOsalMutexUnlock(pRmdObject->
                                               semaForSendHashTable);
                        fpTempPtr((CL_RMD_RC(CL_ERR_TIMEOUT)), cookie, message,
                                  outMsgHdl);
                        clBufferDelete(&(message));
                        rc = clOsalMutexLock(pRmdObject->semaForSendHashTable);
                    }
                }
            }
        }
    }

    rc = clOsalMutexUnlock(pRmdObject->semaForSendHashTable);
    CL_ASSERT(rc == CL_OK);
    CL_FUNC_EXIT();
    return CL_OK;

}
static ClRcT _clPluginHelperSendArp(const ClCharT *host, const ClCharT *dev) {
    int i;
    ClRcT rc = CL_OK;
    ClCharT myMac[CL_MAC_ADDRESS_LENGTH];
    ClUint32T myIp = 0;
    ClPluginHelperEthIpv4ArpPacketT pkt;
    int ifindex = 0;

    _clPluginHelperDevToMac(dev, myMac);
    if ((rc = _clPluginHelperHostToIp(host, &myIp)) != CL_OK)
    {
        return rc;
    }

    _clPluginHelperDevToIfIndex(dev, &ifindex);

    for (i = CL_PLUGIN_HELPER_ARP_REQUEST; i <= CL_PLUGIN_HELPER_ARP_REPLY; i++) {
        memcpy(pkt.myMac, myMac, CL_MAC_ADDRESS_LENGTH);
        memset(pkt.dstMac, 0xFF, CL_MAC_ADDRESS_LENGTH);

        pkt.type = htons(ETHERTYPE_ARP);

        pkt.hrd = htons(CL_PLUGIN_HELPER_ARP_HW_TYPE_ETHERNET);
        pkt.pro = htons(CL_PLUGIN_HELPER_IP_PROTO_TYPE); //htons(ETHERTYPE_IP); //htons(ETH_P_IP); //ArpAddressResolutionType;
        pkt.hln = CL_MAC_ADDRESS_LENGTH; /* ETH_HW_ADDR_LEN; Length in bytes of ethernet address */
        pkt.pln = 4; // IP_ADDR_LEN;
        pkt.op = htons(i); // htons(ARPOP_REQUEST);

        memcpy(pkt.sha, myMac, CL_MAC_ADDRESS_LENGTH);
        memset(pkt.tha, 0xFF, CL_MAC_ADDRESS_LENGTH);
        memcpy(pkt.spa, &myIp, 4);
        memcpy(pkt.tpa, &myIp, 4);

        if (1) {
            int sd;
            struct sockaddr_ll sal;

            bzero(&sal, sizeof(sal));
            sal.sll_family = AF_PACKET;
            sal.sll_protocol = htons(ETH_P_ARP);
            sal.sll_ifindex = ifindex;
            sal.sll_hatype = htons(i);
            sal.sll_pkttype = PACKET_BROADCAST;
            memcpy(sal.sll_addr, myMac, CL_MAC_ADDRESS_LENGTH);
            sal.sll_halen = CL_MAC_ADDRESS_LENGTH;

            if ((sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) < 0) {
                int err = errno;
                clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Cannot create a socket, arp not sent; error %d: %s", err, "");
            } else {
                if (sendto(sd, &pkt, sizeof(pkt), 0, (struct sockaddr *) &sal, sizeof(sal)) < 0) {
                    int err = errno;
                    clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Cannot send the arp packet; error %d: %s", err, "");
                    rc = CL_ERR_LIBRARY;
                }
                clLogNotice("IOC", CL_LOG_PLUGIN_HELPER_AREA, "Gratuitous arp sent: IP %s device %s mac %02x:%02x:%02x:%02x:%02x:%02x", host, dev, myMac[0],
                        myMac[1], myMac[2], myMac[3], myMac[4], myMac[5]);
                shutdown(sd, SHUT_RDWR);
                close(sd);
            }
        }
    }
    return CL_OK;
}
/*
 * Carry out per entity recovery based on the configured recovery.
 */
static ClRcT clAmsEntityRecovery(ClAmsEntityT *pEntity,
                                 ClAmsThresholdT *pThreshold)
{
    ClRcT rc = CL_OK;

    /*
     * Special case for undo on the entity that underwent recovery.
     */
    if(pThreshold->recoveryReset == CL_TRUE)
    {
        return clAmsEntityRecoveryReset(pEntity, pThreshold);
    }

    switch(pEntity->type)
    {
    case CL_AMS_ENTITY_TYPE_SI:
     
        switch(pThreshold->recovery)
        {

        case CL_AMS_ENTITY_RECOVERY_FAILOVER:
        case CL_AMS_ENTITY_RECOVERY_LOCK:
            
            /*
             * Switch work for the SI.
             */
            clLogNotice("TRIGGER", "RECOVERY",
                        "Switching over SI [%.*s] as part of [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value,
                        CL_METRIC_STR(pThreshold->metric.id));
            rc = clAmsMgmtEntityLockAssignment(gClAmsEntityTriggerMgmtHandle,
                                               pEntity);
            if(rc != CL_OK)
            {
                clLogError("TRIGGER", "RECOVERY",
                           "Switching over SI returned [%#x]", rc);
            }
            break;

        default:
            break;
        }
        break;

    case CL_AMS_ENTITY_TYPE_CSI:
        clAmsCSIRecovery(pEntity, pThreshold);
        break;

    case CL_AMS_ENTITY_TYPE_SG:

        switch(pThreshold->recovery)
        {
        case CL_AMS_ENTITY_RECOVERY_FAILOVER:
        case CL_AMS_ENTITY_RECOVERY_LOCK:
            /*
             * Lock work for the SG
             */
            clLogNotice("TRIGGER", "RECOVERY",
                        "Removing work for SG [%.*s] as part of [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value, 
                        CL_METRIC_STR(pThreshold->metric.id));
            rc = clAmsMgmtEntityLockAssignment(gClAmsEntityTriggerMgmtHandle,
                                               pEntity);
            if(rc != CL_OK)
            {
                clLogError("TRIGGER", "RECOVERY",
                           "Removing work for SG returned [%#x]", rc);
            }
            break;

        default:
            break;
        }

        break;

    case CL_AMS_ENTITY_TYPE_NODE:

        switch(pThreshold->recovery)
        {
        case CL_AMS_ENTITY_RECOVERY_LOCK:
            
            clLogNotice("TRIGGER", "RECOVERY",
                        "Switching over work for the node SUs [%.*s] as part of [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value, 
                        CL_METRIC_STR(pThreshold->metric.id));
            rc = clAmsMgmtEntityLockAssignment(gClAmsEntityTriggerMgmtHandle,
                                               pEntity);
            if(rc != CL_OK)
            {
                clLogError("TRIGGER", "RECOVERY",
                           "Switching over work for node returned [%#x]", rc);
            }
            break;

        case CL_AMS_ENTITY_RECOVERY_RESTART:
            
            clLogNotice("TRIGGER", "RECOVERY",
                        "Restarting SUs for node [%.*s] as part of [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value,
                        CL_METRIC_STR(pThreshold->metric.id));

            rc = clAmsMgmtEntityRestart(gClAmsEntityTriggerMgmtHandle,
                                        pEntity);

            if(rc != CL_OK)
            {
                clLogError("TRIGGER", "RECOVERY",
                           "Restart node returned [%#x]", rc);
            }

            break;

        case CL_AMS_ENTITY_RECOVERY_FAILOVER:
            clLogNotice("TRIGGER", "RECOVERY",
                        "Failing over node [%.*s] as part [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value,
                        CL_METRIC_STR(pThreshold->metric.id));
            clAmsTriggerFault(pEntity, CL_AMS_RECOVERY_NODE_FAILOVER);
            break;

        case CL_AMS_ENTITY_RECOVERY_FAILFAST:
            clLogNotice("TRIGGER", "RECOVERY",
                        "Failing over node [%.*s] as part of [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value,
                        CL_METRIC_STR(pThreshold->metric.id));
            clAmsTriggerFault(pEntity, CL_AMS_RECOVERY_NODE_FAILFAST);
            break;

        default:
            break;
        }
        break;

    case CL_AMS_ENTITY_TYPE_SU:

        switch(pThreshold->recovery)
        {
        case CL_AMS_ENTITY_RECOVERY_FAILOVER:
                clLogNotice("TRIGGER", "RECOVERY", 
                            "Failover over work for SU [%.*s] as part of [%s] threshold recovery",
                            pEntity->name.length-1, pEntity->name.value, 
                            CL_METRIC_STR(pThreshold->metric.id));
                clAmsCompRecovery(pEntity, pThreshold);
                break;

        case CL_AMS_ENTITY_RECOVERY_LOCK:
            clLogNotice("TRIGGER", "RECOVERY", 
                        "Switching over work for SU [%.*s] as part of [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value,
                        CL_METRIC_STR(pThreshold->metric.id)
                        );

            rc = clAmsMgmtEntityLockAssignment(gClAmsEntityTriggerMgmtHandle,
                                               pEntity);
            
            if(rc != CL_OK)
            {
                clLogError("TRIGGER", "RECOVERY",
                           "Switching over work for SU returned [%#x]", rc);
            }
            break;

        case CL_AMS_ENTITY_RECOVERY_RESTART:
            
            clLogNotice("TRIGGER", "RECOVERY",
                        "Restarting components in SU [%.*s] as part of [%s] threshold recovery",
                        pEntity->name.length-1, pEntity->name.value, 
                        CL_METRIC_STR(pThreshold->metric.id));
            
            rc = clAmsMgmtEntityRestart(gClAmsEntityTriggerMgmtHandle,
                                        pEntity);
            if(rc != CL_OK)
            {
                clLogError("TRIGGER", "RECOVERY",
                           "Restarting SU returned [%#x]", rc);
            }

            break;

        default:
            break;
        }
        break;
       
    case CL_AMS_ENTITY_TYPE_COMP:
        clAmsCompRecovery(pEntity, pThreshold);
        break;

    default:
        break;
    }

    return rc;
}