int main(int argc, char *argv[])
{
    SaAisErrorT rc = SA_AIS_OK;
    SaSelectionObjectT dispatch_fd;
    fd_set read_fds;
    ClRcT ret = CL_OK;

    /* Connect to the SAF cluster */
    initializeAmf();

    /* Do the application specific initialization here. */
    FD_ZERO(&read_fds);

    if ( (rc = saAmfSelectionObjectGet(amfHandle, &dispatch_fd)) != SA_AIS_OK)
        errorExit(rc);
    
    FD_SET(dispatch_fd, &read_fds);
    
    /* Handle the AMF dispatch loop by spawning a thread that does it */
    ret = clOsalTaskCreateDetached("DISPATCH-THREAD", CL_OSAL_SCHED_OTHER, 0, 0, saAmfDispatchThread, NULL);
    if(ret != CL_OK)
    {
        clprintf(CL_LOG_SEV_ERROR, "Dispatch task create failed with rc 0x%x",rc);
        return ret;
    } 
    while (!unblockNow)
    {
        /* csa112: If I am active then I'll publish an event.
           Note, any application can publish and event regardless of
           HA state.  This tutorial simply uses HA state so only
           one of the two processes are publishing.
        */
        
        if (running && ha_state == SA_AMF_HA_ACTIVE)
        {
            csa113Comp_PublishEvent();
        }
    
        sleep(1);  /* Keep the event publish rate reasonable for this tutorial*/
    }
    
    /* Do the application specific finalization here. */
    if ((rc = saEvtChannelClose(evtChannelHandle)) != SA_AIS_OK)
    {
        clprintf(CL_LOG_SEV_ERROR, "Failed [0x%x] to close event channel", rc);
    }

    if ((rc = saEvtFinalize(evtLibHandle)) != SA_AIS_OK)
    {
        clprintf(CL_LOG_SEV_ERROR, "Failed [0x%x] to finalize event library", rc);
    }

    /* Now finalize my connection with the SAF cluster */
    if((rc = saAmfFinalize(amfHandle)) != SA_AIS_OK)
      clprintf (CL_LOG_SEV_ERROR, "AMF finalization error[0x%X]", rc);
    else
      clprintf (CL_LOG_SEV_INFO, "AMF Finalized");   

    return 0;
}
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 clMsgFinalizeBlocker(void)
{
    ClRcT rc = CL_OK;
    SaTimeT timeout = (SaTimeT)(CL_MSG_FIN_BLOCK_TIME * 1000000000LL);
    ClTimerTimeOutT tempTime = {0};

    CL_OSAL_MUTEX_LOCK(&gFinBlockMutex);

    if(gMsgMoveStatus == MSG_MOVE_DONE)
        goto out;

    clLogDebug("FIN", "BLOCK", "Message service finalize will be blocked for [%llu ns].", timeout);

    if(gMsgMoveStatus == MSG_MOVE_FIN_UNINIT)
    {
        rc = clOsalTaskCreateDetached("allClosedQueueMoverThread", CL_OSAL_SCHED_OTHER, CL_OSAL_THREAD_PRI_NOT_APPLICABLE, 0, clMsgClosedQueueMoveThread, NULL);
        if(rc != CL_OK)
        {
            clLogError("FIN", "BLOCK", "Failed to create a Queue mover thread. error code [0x%x].", rc);
            goto error_out;
        }
        clMsgTimeConvert(&tempTime, timeout);

        rc = clOsalCondWait(gFinBlockCond, &gFinBlockMutex, tempTime);
        if(CL_GET_ERROR_CODE(rc) == CL_ERR_TIMEOUT)
        {   
            clLogError("FIN", "BLOCK", "Finalize blocking timed out. Timeout is [%lld ns]. error code [0x%x].", timeout, rc);
        }   
        else if(rc != CL_OK)
        {
            clLogError("FIN", "BLOCK", "Failed at Conditional Wait. error code [0x%x].", rc);
        }
        else
        {
            clLogDebug("FIN", "BLOCK", "Message queues are failed over to [0x%x] node.", gQMoveDestNode);
        }
    }

    gMsgMoveStatus = MSG_MOVE_DONE;

    goto out;

    error_out:
    out:
    CL_OSAL_MUTEX_UNLOCK(&gFinBlockMutex);
     
    return rc;
}
コード例 #4
0
static ClRcT initializeAmf(void)
{
    ClRcT         rc = CL_OK; 
    ClRcT         retCode;
    ClIocPhysicalAddressT notificationForComp = { CL_IOC_BROADCAST_ADDRESS, 0};
    
    clLogCompName = (ClCharT*) "MSG"; /* Override generated eo name with a short name for our server */
    clAppConfigure(&clEoConfig,clEoBasicLibs,clEoClientLibs);
  
    clMsgRegisterWithCpm();
     
    if(gClMsgInit == CL_TRUE)
    {
        rc = CL_MSG_RC(CL_ERR_INITIALIZED);
        clLogError("MSG", "INI", "The Message Service is already initialized. error code [0x%x].", rc);
        goto error_out;
    }
    
    gLocalAddress = clIocLocalAddressGet();
    gLocalPortId = CL_IOC_MSG_PORT;

    /* Initializing a database to maintain client information */
    rc = clHandleDatabaseCreate((void (*)(void*))NULL, &gMsgClientHandleDb);
     
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to initialize the handle database. error code [0x%x].", rc);
        goto error_out;
    }
    
    /* Initializing IDL for server to server and server to client communication. */
    rc = clMsgCommIdlInitialize();
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to initialize the IDL. error code [0x%x].", rc);
        goto error_out_2;
    }
    
    /* Initializing a database for maintaining queues. */
    rc = clMsgQueueInitialize();
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to initialize the queue databases. error code [0x%x].", rc);
        goto error_out_3;
    }
   
    rc = clMsgReceiverDatabaseInit();
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to initialize \"receiver database\". error code [0x%x].", rc);
        goto error_out_4;
    }

    rc = clOsalMutexInit(&gClMsgFinalizeLock);
    CL_ASSERT(rc == CL_OK);
    
    rc = clOsalCondInit(&gClMsgFinalizeCond);
    CL_ASSERT(rc == CL_OK);

    /* Initializing the Group-Information */
    rc = clOsalMutexInit(&gClGroupDbLock);
    CL_ASSERT(rc == CL_OK);

    rc = clCpmNotificationCallbackInstall(notificationForComp, &clMsgNotificationReceiveCallback, NULL, &gMsgNotificationHandle);
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to install the notification callback function. error code [0x%x].", rc);
        goto error_out_5;
    }
   
    /* Initializing the IDL generated code. */
    rc = clMsgIdlClientInstall();
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to install Server Table. error code [0x%x].", rc);
        goto error_out_6;
    }

    rc = clMsgIdlClientTableRegister(CL_IOC_MSG_PORT);
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to register Server Table. error code [0x%x].", rc);
        goto error_out_7;
    }

    rc = clMsgCltClientTableRegister(CL_IOC_MSG_PORT);
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to register Client Table. error code [0x%x].", rc);
        goto error_out_8;
    }

    rc = clMsgCltSrvClientInstall();
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to install Client Server Table. error code [0x%x].", rc);
        goto error_out_9;
    }
  
    rc = clMsgCltSrvClientTableRegister(CL_IOC_MSG_PORT);
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to register Client Server Table. error code [0x%x].", rc);
        goto error_out_10;
    }

    rc = clMsgFinalizeBlockInit();
    if(rc != CL_OK)
    {
        clLogError("MSG", "INI", "Failed to initialize the msg-finalize blocker. error code [0x%x].", rc);
        goto error_out_11;
    }
   
    clMsgDebugCliRegister();

    rc = clOsalTaskCreateDetached("MsgCkptInitAsync", CL_OSAL_SCHED_OTHER, CL_OSAL_THREAD_PRI_NOT_APPLICABLE, 0,
                                 clMsgCachedCkptInitAsync, NULL);
    CL_ASSERT(rc == CL_OK);

    goto out;
error_out_11:
    retCode = clMsgCltSrvClientTableDeregister();
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to deregister Client Table. error code [0x%x].", retCode);
error_out_10:
    retCode = clMsgCltSrvClientUninstall();
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to destroy the just opened handle database. error code [0x%x].", retCode);
error_out_9:
    retCode = clMsgCltClientTableDeregister();
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to deregister Client Table. error code [0x%x].", retCode);
error_out_8:
    retCode = clMsgIdlClientTableDeregister();
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to deregister Server Table. error code [0x%x].", retCode);
error_out_7:
    retCode = clMsgIdlClientUninstall();
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to destroy the just opened handle database. error code [0x%x].", retCode);
error_out_6:
    retCode = clCpmNotificationCallbackUninstall(&gMsgNotificationHandle);
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to uninstall the notification callback function. error code [0x%x].", retCode);
error_out_5:
    retCode = clOsalMutexDestroy(&gClGroupDbLock);
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to destroy the group db mutex. error code [0x%x].", retCode);

    retCode = clOsalCondDestroy(&gClMsgFinalizeCond);
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to destroy the finalization condition. error code [0x%x].", retCode);

    retCode = clOsalMutexDestroy(&gClMsgFinalizeLock);
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to destroy the finalization mutex. error code [0x%x].", retCode);

    clMsgReceiverDatabaseFin();

error_out_4:
    retCode = clMsgQueueFinalize();
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to finalize the queue databases. error code [0x%x].", retCode);
error_out_3:
    clMsgCommIdlFinalize();
error_out_2:
    retCode = clHandleDatabaseDestroy(gMsgClientHandleDb);
    if(retCode != CL_OK)
        clLogError("MSG", "INI", "Failed to destroy the handle database. error code [0x%x].", retCode);
error_out:
out:
    return rc;  
    
}//end of intializeAmf
int main(int argc, char *argv[])
{
    SaNameT             appName = {0};
    SaAmfCallbacksT     callbacks;
    SaVersionT          version;
    ClIocPortT          iocPort;
    SaAisErrorT         rc = SA_AIS_OK;

    SaSelectionObjectT dispatch_fd;
    fd_set read_fds;
    
    /*
     * Declare other local variables here.
     */

    /*
     * Get the pid for the process and store it in global variable.
     */

    mypid = getpid();

    /*
     * Initialize and register with CPM. 'version' specifies the
     * version of AMF with which this application would like to
     * interface. 'callbacks' is used to register the callbacks this
     * component expects to receive.
     */

    version.releaseCode  = 'B';
    version.majorVersion = 01;
    version.minorVersion = 01;
    
    callbacks.saAmfHealthcheckCallback          = NULL;
    callbacks.saAmfComponentTerminateCallback   = clCompAppTerminate;
    callbacks.saAmfCSISetCallback               = clCompAppAMFCSISet;
    callbacks.saAmfCSIRemoveCallback            = clCompAppAMFCSIRemove;
    callbacks.saAmfProtectionGroupTrackCallback = NULL;
        
    /*
     * Initialize AMF client library.
     */

    if ( (rc = saAmfInitialize(&amfHandle, &callbacks, &version)) != SA_AIS_OK) 
        goto errorexit;

    FD_ZERO(&read_fds);

    /*
     * Get the AMF dispatch FD for the callbacks
     */
    if ( (rc = saAmfSelectionObjectGet(amfHandle, &dispatch_fd)) != SA_AIS_OK)
        goto errorexit;
    
    FD_SET(dispatch_fd, &read_fds);


    /*
     * Do the application specific initialization here.
     */


    /*
     * Now register the component with AMF. At this point it is
     * ready to provide service, i.e. take work assignments.
     */

    if ( (rc = saAmfComponentNameGet(amfHandle, &appName)) != SA_AIS_OK) 
        goto errorexit;
    if ( (rc = saAmfComponentRegister(amfHandle, &appName, NULL)) != SA_AIS_OK) 
        goto errorexit;

    /* Open the log stream as soon as I've registered with AMF */
    clEvalAppLogStreamOpen((ClCharT *)appName.value, &gEvalLogStream);

    /* Handle the AMF dispatch loop by spawning a thread that does it */
    rc = clOsalTaskCreateDetached("DISPATCH-THREAD", CL_OSAL_SCHED_OTHER, 0, 0, saAmfDispatchThread, NULL);
    if(rc != CL_OK)
    {
        clprintf(CL_LOG_SEV_ERROR, "Dispatch task create failed with rc 0x%x",rc);
        return rc;
    }
    
    /*
     * Print out standard information for this component.
     */

    clEoMyEoIocPortGet(&iocPort);
    
    clprintf (CL_LOG_SEV_INFO, "Component [%.*s] : PID [%d]. Initializing\n", appName.length, appName.value, mypid);
    clprintf (CL_LOG_SEV_INFO, "   IOC Address             : 0x%x\n", clIocLocalAddressGet());
    clprintf (CL_LOG_SEV_INFO, "   IOC Port                : 0x%x\n", iocPort);

    /* csa112: initialize the event client library, open the event channel and subscribe to events */
    if (1)
    {
        const SaEvtCallbacksT evtCallbacks =
        {
            NULL,  /* Event open callback */
            csa112Comp_appEventCallback  /* Event delivery callback */
        };
        SaVersionT  evtVersion = {(ClUint8T)'B', 0x1, 0x1};
        
        rc = saEvtInitialize(&evtLibHandle, &evtCallbacks, &evtVersion);
        if (rc != SA_AIS_OK)
        {
            clprintf(CL_LOG_ERROR, "Failed to init event mechanism [0x%x]\n", rc);
            return rc;
        }
            // Open an event chanel so that we can subscribe to events on that channel
        rc = saEvtChannelOpen(evtLibHandle, &evtChannelName, (SA_EVT_CHANNEL_PUBLISHER | SA_EVT_CHANNEL_SUBSCRIBER | SA_EVT_CHANNEL_CREATE), (SaTimeT)SA_TIME_END, &evtChannelHandle);
        if (rc != SA_AIS_OK)
          {
          clprintf(CL_LOG_SEV_ERROR, "Failure opening event channel [0x%x] at %ld", rc, time(0L));
          goto errorexit;
          }
        
      rc = saEvtEventSubscribe(evtChannelHandle, NULL, 1);
      if (rc != SA_AIS_OK)
      {
        clprintf(CL_LOG_SEV_ERROR, "Failed to subscribe to event channel [0x%x]",rc);
        goto errorexit;
      }
    }

    /*csa113: create an event definition to be published */
    if (1)
    {
        SaNameT publisherName;
        clNameSet((ClNameT*) &publisherName,PUBLISHER_NAME);
        
        rc = saEvtEventAllocate(evtChannelHandle, &eventHandle);
        if (rc != SA_AIS_OK)
        {
            clprintf(CL_LOG_SEV_ERROR, "Failed to allocate event [0x%x]\n", rc);
            assert(0);
        }

        rc = saEvtEventAttributesSet(eventHandle, NULL, 1, 0, &publisherName);
        if (rc != SA_AIS_OK)
        {
            clprintf(CL_LOG_ERROR, "Failed to set event attributes [0x%x]\n",rc);
            assert(0);            
        }
    }
    
    
    while (!exiting)
    {
        /* csa112: If I am active then I'll publish an event.
           Note, any application can publish and event regardless of
           HA state.  This tutorial simply uses HA state so only
           one of the two processes are publishing.
        */
        
    if (running && ha_state == SA_AMF_HA_ACTIVE)
    {
        csa113Comp_PublishEvent();
    }
    
    sleep(1);  /* Keep the event publish rate reasonable for this tutorial*/
    }
    
    /*
     * Do the application specific finalization here.
     */

    /* csa112: close the event channel, finalize the event client library */
    if ((rc = saEvtChannelClose(evtChannelHandle)) != SA_AIS_OK)
    {
        clprintf(CL_LOG_ERROR, "Failed [0x%x] to close event channel", rc);
    }

    if ((rc = saEvtFinalize(evtLibHandle)) != SA_AIS_OK)
    {
        clprintf(CL_LOG_ERROR, "Failed [0x%x] to finalize event library", rc);
    }

    if((rc = saAmfFinalize(amfHandle)) != SA_AIS_OK)
	{
        clprintf (CL_LOG_SEV_ERROR, "AMF finalization error[0x%X]", rc);
	}

    clprintf (CL_LOG_SEV_INFO, "AMF Finalized");
    
    return 0;

errorexit:

    clprintf (CL_LOG_SEV_ERROR, "Component [%.*s] : PID [%d]. Initialization error [0x%x]\n",
              appName.length, appName.value, mypid, rc);

    return -1;
}
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;
}
void initializeAmf(void)
{
    SaAmfCallbacksT     callbacks;
    SaVersionT          version;
    ClIocPortT          iocPort;
    SaAisErrorT         rc = SA_AIS_OK;

    /* Get the pid for the process and store it in global variable. */
    mypid = getpid();

    /* SAFplus is fully API compatible with SA-Forum (SAF) definitions.

       This optional call customizes OpenClovis SAFplus Platform extensions
       to the basic SAF services (to use, you would define the parameters as globals).  
       
       If this call is removed, standard SAF services will work just fine. */

    /* clAppConfigure(&clEoConfig,clEoBasicLibs,clEoClientLibs); */

    
    /*
     * Initialize and register with SAFplus AMF. 'version' specifies the
     * version of AMF with which this application would like to
     * interface. 'callbacks' is used to register the callbacks this
     * component expects to receive.
     */
    version.releaseCode  = 'B';
    version.majorVersion = 01;
    version.minorVersion = 01;
    
    callbacks.saAmfHealthcheckCallback          = NULL; /* rarely necessary because SAFplus monitors the process */
    callbacks.saAmfComponentTerminateCallback   = safTerminate;
    callbacks.saAmfCSISetCallback               = safAssignWork;
    callbacks.saAmfCSIRemoveCallback            = safRemoveWork;
    callbacks.saAmfProtectionGroupTrackCallback = NULL;
        
    /* Initialize AMF client library. */
    if ( (rc = saAmfInitialize(&amfHandle, &callbacks, &version)) != SA_AIS_OK)
        errorExit(rc);

    /*
     * Now register the component with AMF. At this point it is
     * ready to provide service, i.e. take work assignments.
     */

    if ( (rc = saAmfComponentNameGet(amfHandle, &appName)) != SA_AIS_OK) 
        errorExit(rc);
    if ( (rc = saAmfComponentRegister(amfHandle, &appName, NULL)) != SA_AIS_OK) 
        errorExit(rc);

    /*
     * Print out standard information for this component.
     */

    clEoMyEoIocPortGet(&iocPort);
    
    clprintf (CL_LOG_SEV_INFO, "Component [%.*s] : PID [%d]. Initializing\n", appName.length, appName.value, mypid);
    clprintf (CL_LOG_SEV_INFO, "   IOC Address             : 0x%x\n", clIocLocalAddressGet());
    clprintf (CL_LOG_SEV_INFO, "   IOC Port                : 0x%x\n", iocPort);

    strncpy(appname, (ClCharT*)appName.value, sizeof(appname)-1);
 
    
    if ((rc = checkpoint_initialize()) != SA_AIS_OK)
    {
        clprintf(CL_LOG_SEV_ERROR,"%s: Failed [0x%x] to initialize checkpoint\n",appname, rc);
        errorExit(rc);
    }
    if ((rc = checkpoint_read_seq(&seq)) != SA_AIS_OK)
    {
        clprintf(CL_LOG_SEV_ERROR,"%s: Failed [0x%x] to read checkpoint\n", appname, rc);
        checkpoint_finalize();
        errorExit(rc);
    }
#ifdef CL_INST
    if ((rc = clDataTapInit(DATA_TAP_DEFAULT_FLAGS, 203)) != CL_OK)
    {
        clprintf(CL_LOG_SEV_ERROR,"%s: Failed [0x%x] to initialize data tap\n", appname, rc);
    }
#endif
    clOsalTaskCreateDetached("testCkpMainLoop", CL_OSAL_SCHED_OTHER, CL_OSAL_THREAD_PRI_NOT_APPLICABLE, 65536, testCkpMainLoop, (void*)appname);
}
コード例 #8
0
static PyObject* initializeAmf(PyObject *self, PyObject *args)
{
    SaNameT             appName = {0};
    SaAmfCallbacksT     callbacks;
    SaVersionT          version;
    ClIocPortT          iocPort;
    ClRcT               rc = SA_AIS_OK;    

    PyEval_InitThreads();    
    PyThreadState* pts = PyThreadState_Get();
    thePythonInterpreter = pts->interp;

    /* Put the EO name received from the environment in the appropriate variable */
    //strncpy(clEoConfig.EOname,getenv("ASP_COMPNAME"),CL_EO_MAX_NAME_LEN-1);
    
    mypid = getpid();

    /*
     * Initialize and register with CPM. 'version' specifies the
     * version of AMF with which this application would like to
     * interface. 'callbacks' is used to register the callbacks this
     * component expects to receive.
     */

    version.releaseCode  = 'B';
    version.majorVersion = 01;
    version.minorVersion = 01;
    
    callbacks.saAmfHealthcheckCallback          = NULL;
    callbacks.saAmfComponentTerminateCallback   = clCompAppTerminate;
    callbacks.saAmfCSISetCallback               = clCompAppAMFCSISet;
    callbacks.saAmfCSIRemoveCallback            = clCompAppAMFCSIRemove;
    callbacks.saAmfProtectionGroupTrackCallback = NULL;
        
    /*
     * Initialize AMF client library.
     */

    if ( (rc = saAmfInitialize(&amfHandle, &callbacks, &version)) != SA_AIS_OK) 
        goto errorexit;

    clprintf (CL_LOG_SEV_INFO, "AmfInitialize successful");

    if (1)
    {
        
    SaSelectionObjectT dispatch_fd;
    fd_set read_fds;

    FD_ZERO(&read_fds);

    /*
     * Get the AMF dispatch FD for the callbacks
     */
    if ( (rc = saAmfSelectionObjectGet(amfHandle, &dispatch_fd)) != SA_AIS_OK)
    {
        clprintf (CL_LOG_SEV_ERROR, "Error getting selection object -- unable to dispatch AMF events");
        return NULL;        
    }
    }
    
    /*
     * Do the application specific initialization here.
     */

    /*
     * ---BEGIN_APPLICATION_CODE---
     */

#if 0
    if (1)
      {
      void (*extensions[])(void) = { init_asp, initasppycustom, 0 };
      clPyGlueInit("clusterMgrApp",extensions);
      }
#endif

    /*
     * ---END_APPLICATION_CODE---
     */

    /*
     * Now register the component with AMF. At this point it is
     * ready to provide service, i.e. take work assignments.
     */

    if ( (rc = saAmfComponentNameGet(amfHandle, &appName)) != SA_AIS_OK) 
        goto errorexit;
    clprintf (CL_LOG_SEV_INFO, "component name get successful");

    if ( (rc = saAmfComponentRegister(amfHandle, &appName, NULL)) != SA_AIS_OK) 
        goto errorexit;
    clprintf (CL_LOG_SEV_INFO, "component register successful");

    /*
     * Print out standard information for this component.
     */

    clEoMyEoIocPortGet(&iocPort);
    
    clprintf (CL_LOG_SEV_INFO, "Component [%s] : PID [%d]. Initializing\n", appName.value, mypid);
    clprintf (CL_LOG_SEV_INFO, "   IOC Address             : 0x%x\n", clIocLocalAddressGet());
    clprintf (CL_LOG_SEV_INFO, "   IOC Port                : 0x%x\n", iocPort);

    /*
     * ---BEGIN_APPLICATION_CODE---
     */
    //clPyGlueStart();
    /*
     * ---END_APPLICATION_CODE---
     */
    rc = clOsalTaskCreateDetached("AmfDispatcher",CL_OSAL_SCHED_OTHER, CL_OSAL_THREAD_PRI_NOT_APPLICABLE, 0, amfDispatcher,NULL);
    

errorexit:

    if (rc != CL_OK)
      {
        char str[256];
        snprintf(str,255,"Component [%s] : PID [%d]. Initialization error [0x%x]\n", appName.value, mypid, rc);
        clprintf (CL_LOG_SEV_ERROR, str);
        //return PyInt_FromLong(rc);
        PyObject* errData = Py_BuildValue("is",rc,str);
        PyErr_SetObject(PyExc_SystemError,errData);
        return NULL;     
      }
    Py_RETURN_NONE;
    }
static void*
tsTimerTask (void* pArgument)
{
    ClRcT returnCode = CL_ERR_INVALID_HANDLE;
    ClTimerTimeOutT sleepTime = {0,0};
    ClTimerTypeT type ;
    TsTimer_t* pUserTimer = NULL;

    sleepTime.tsSec = 0;
    sleepTime.tsMilliSec = gActiveTimerQueue.tickInMilliSec;

    while (1) {
        /* run forever */
        ClInt64T diff;
        ClUint32T skewTicks;
        ClUint32T skewTicksTemp;
        struct timeval start;
        struct timeval end;
        gettimeofday(&start,NULL);
        returnCode = clOsalTaskDelay (sleepTime);
        gettimeofday(&end,NULL);
        /*
         *  If this ever return CL_OSAL_ERR_OS_ERROR, it means that gOsalFunction
         *  is un-initialized or been finalized. In case of finalized we can
         *  simply return from this thread. Ideally clOsalTaskDelay should
         *  not be used here. a better approach would be pthread_cond_timedwait.
         *  but right now this is the temporary stuff which will work
         */
        if(CL_GET_ERROR_CODE(returnCode) == CL_OSAL_ERR_OS_ERROR &&
                CL_GET_CID(returnCode) == CL_CID_OSAL)
        {
            break;
        }

        diff = clTimerTimeDiff(&start,&end,CL_TIMER_DRIFT_THRESHOLD);

        if(diff < CL_TIMER_TICK_USECS)
        {
            skewTicks = 1;
            diff = 0;
        }
        else
        {
            skewTicks = diff/CL_TIMER_TICK_USECS;
        }

        returnCode = clOsalMutexLock (gActiveTimerQueue.timerMutex);

        if (returnCode != CL_OK) {
            continue;
        }

        skewTicksTemp = skew/(iteration+1);

        skew += skewTicksTemp % CL_TIMER_TICK_USECS;

        skewTicksTemp/=CL_TIMER_TICK_USECS;

        skew += diff % CL_TIMER_TICK_USECS;

        skewTicks += skewTicksTemp;

        ++iteration;

        if(currentTime > currentTime+iteration+skewTicks)
        {
            CL_DEBUG_PRINT(CL_DEBUG_ERROR,("Timer overflow detected.Exiting timer\n"));
            clOsalMutexUnlock(gActiveTimerQueue.timerMutex);
            break;
        }

        currentTime += skewTicks;

        if (gActiveTimerQueue.pFirstTimer == NULL) {
            returnCode = clOsalMutexUnlock (gActiveTimerQueue.timerMutex);
            continue;
        }

        if( (gActiveTimerQueue.pFirstTimer->timestamp > currentTime))
        {

        }
        else {
            gettimeofday(&start,NULL);
            for (pUserTimer = gActiveTimerQueue.pFirstTimer;
                    (pUserTimer != NULL) && (pUserTimer->timestamp <= currentTime);
                    pUserTimer = pUserTimer->pNextActiveTimer) {

                /* first remove the timer from the active queue */
                returnCode = tsActiveTimerDequeue (pUserTimer);

                /* check that the timer we are about to execute is valid */
                if ((pUserTimer->state != TIMER_ACTIVE) ||
                        (pUserTimer->fpTimeOutAction == NULL)) {
                    continue;
                } /* end of check to ensure that the timer we are about to execute is valid */

                if((type = pUserTimer->type) == CL_TIMER_ONE_SHOT)
                {
                    /* make the timer state as inactive if its a one-shot timer */
                    pUserTimer->state = TIMER_INACTIVE;
                }
                switch (pUserTimer->spawnTask) {
                case CL_TIMER_SEPARATE_CONTEXT:
                    /* spawn off a task to run the timer function */
                    returnCode = clOsalTaskCreateDetached ("USER TIMER TASK",
                                                           CL_OSAL_SCHED_OTHER,
                                                           CL_OSAL_THREAD_PRI_NOT_APPLICABLE,
                                                           TIMER_TASK_STACK_SIZE,
                                                           (void* (*) (void*)) pUserTimer->fpTimeOutAction,
                                                           pUserTimer->pActionArgument);

                    if (returnCode != CL_OK) {
                        /* do the appropriate thing here */
                        break;
                    }
                    break;

                case CL_TIMER_TASK_CONTEXT:
                    returnCode = pUserTimer->fpTimeOutAction (pUserTimer->pActionArgument);
                    break;

                default:
                    /* this should never happen! we should have verified this
                     * in create/newTimerActivate
                     */
                    break;
                }

                if (type == CL_TIMER_REPETITIVE) {

                    /* put the current time into this timer's timestamp */
                    pUserTimer->timestamp = currentTime+pUserTimer->timeInterval;

                    /* This timer needs to fire again. So put into re-enqueue Queue */
                    returnCode = clQueueNodeInsert(gActiveTimerQueue.reEnqueueQueue,
                                                   pUserTimer);

                    if (returnCode != CL_OK) {
                        /* do the appropriate thing here */
                        break;
                    }

                }

            } /* end of for (all timers with 0 expiry time) loop */
            gettimeofday(&end,NULL);

            skew += clTimerTimeDiff(&start,&end,CL_TIMER_DRIFT_THRESHOLD);

        } /* end of else: so there are expired timers */

        tsTimerReEnqueue();

        returnCode = clOsalMutexUnlock (gActiveTimerQueue.timerMutex);

    } /* end of while (1) */

    return (NULL);
}