ClRcT cliEOListShow(ClUint32T argc, ClCharT **argv, ClCharT **retStr)
{
    ClRcT rc = CL_OK;
    ClEoIdT eoId;

    {

        if (argc == ONE_ARGUMENT)
        {
            rc = clCpmExecutionObjectListShow(argc,
                                              clIocLocalAddressGet(),
                                              0,
                                              0,
                                              retStr);
        }
        else
        {
            eoId = (ClEoIdT) cpmCliStrToInt(argv[1]);
            rc = clCpmExecutionObjectListShow(argc,
                                              clIocLocalAddressGet(),
                                              1,
                                              eoId,
                                              retStr);
        }
    }

    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);
}
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;
}    
ClRcT
clNameContextCkptNameUnpack(ClBufferHandleT  inMsg)
{
    ClRcT             rc      = CL_OK;
    ClUint32T         key     = 0;
    ClUint32T         size    = 0;
    ClUint32T         count   = 0;
    ClIocNodeAddressT localAddr = 0;
    ClIocNodeAddressT masterAddr = 0;

    CL_NAME_DEBUG_TRACE(("Enter"));
    rc = clXdrUnmarshallClUint32T(inMsg, &size);
    if( CL_OK != rc )
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("clXdrUnmarshallClUint32T(): rc[0x %x]", rc));
        return rc;
    }    
    clLogDebug("SVR", "CKP", "Num of contexts: %d", size);
    for( count = 0; count < size; count++)
    {    
        rc = clXdrUnmarshallClUint32T(inMsg, &key);
        if( CL_OK != rc )
        {
            return rc;
        }    
        if( (key > CL_NS_DEFAULT_GLOBAL_CONTEXT) && 
            (key < CL_NS_BASE_NODELOCAL_CONTEXT) )
        {
            localAddr = clIocLocalAddressGet();
            rc = clCpmMasterAddressGet(&masterAddr);
            if (rc != CL_OK)
            {
                CL_DEBUG_PRINT(CL_DEBUG_ERROR,("clCpmMasterAddressGet failed with rc 0x%x",rc));
                return rc;
            }

            if( masterAddr == localAddr )
            {
                rc = clNameSvcCtxRecreate(key);
                if( CL_OK != rc )
                {
                    return rc;
                }    
            }    
        }    
        else
        {    
            rc = clNameSvcCtxRecreate(key);
            if( CL_OK != rc )
            {
                return rc;
            }    
        } 
    }
    
    CL_NAME_DEBUG_TRACE(("Exit"));
    return rc;
}    
/*-----------------------------------------------------------------------------
 * Cluster Member Get Async API
 *---------------------------------------------------------------------------*/
ClRcT clGmsClusterMemberGetAsync(
    CL_IN const ClGmsHandleT   gmsHandle,
    CL_IN const ClInvocationT  invocation,
    CL_IN const ClGmsNodeIdT   nodeId)
{
    ClRcT                                rc = CL_OK;
    struct gms_instance                 *gms_instance_ptr = NULL;
    ClGmsClusterMemberGetAsyncRequestT   req = {0};
    ClGmsClusterMemberGetAsyncResponseT *res = NULL;
        
    CL_GMS_SET_CLIENT_VERSION( req );
    rc = clHandleCheckout(gmsHandleDb, gmsHandle, (void**)&gms_instance_ptr);
    if (rc != CL_OK)
    {
        return rc;
    }
    if (gms_instance_ptr == NULL)
    {
        return CL_GMS_RC(CL_ERR_NULL_POINTER);
    }

    if (gms_instance_ptr->callbacks.clGmsClusterMemberGetCallback == NULL)
    {
        rc = CL_GMS_RC(CL_ERR_NO_CALLBACK);
        goto error_checkin;
    }
    
    req.gmsHandle  = gmsHandle;
    req.nodeId     = nodeId;
    req.invocation = invocation;
    req.address.iocPhyAddress.nodeAddress = clIocLocalAddressGet();
    rc = clEoMyEoIocPortGet(&(req.address.iocPhyAddress.portId));
    if (rc != CL_OK)
    {
        goto error_checkin;
    }
    
    clGmsMutexLock(gms_instance_ptr->response_mutex);
    
    rc = cl_gms_cluster_member_get_async_rmd(&req, 0 /* use def. timeout */,
                                             &res);
    if (rc != CL_OK) /* If there was an error, res isn't allocated */
    {
        goto error_unlock_checkin;
    }

error_unlock_checkin:
    clGmsMutexUnlock(gms_instance_ptr->response_mutex);
    
error_checkin:
    if (clHandleCheckin(gmsHandleDb, gmsHandle) != CL_OK)
    {
        clLogError(CLM,NA,
                    "\nclHandleCheckin failed");
    }
    
    return rc;
}
static void __compNotify(ClInt32T wd, const ClCharT *compName, ClIocNotificationIdT notification)
{
    ClTransportNotifyMapT *notify;
    ClInt32T port = -1;
    const ClCharT *s = compName;
    ClIocPhysicalAddressT compAddr;
    if(s && ( s = strrchr(s, '_')))
        port = atoi(s+1);
    if(notification == CL_IOC_COMP_ARRIVAL_NOTIFICATION)
    {
        notify = addNotifyMap(wd, port);
        if(notify)
        {
            compAddr.nodeAddress = clIocLocalAddressGet();
            compAddr.portId = port;
            clIocCompStatusSet(compAddr, CL_IOC_NODE_UP);
            /*
             * Invoke all registrants with the event.
             */
            transportNotifyRegistrants(&compAddr, CL_IOC_NODE_UP);
            clLogDebug("XPORT", "NOTIFY", "Comp arrival marked for port [%#x], id [%s]", port, compName);
        }
    }
    else
    {
        if(delNotifyMap(wd, port) == CL_OK)
        {
            compAddr.nodeAddress = clIocLocalAddressGet();
            compAddr.portId = port;
            if(compName)
            {
                transportNotifyLocRemove(compName);
            }
            clIocCompStatusSet(compAddr, CL_IOC_NODE_DOWN);
            /*
             * Invoke all registrants with the event.
             */
            transportNotifyRegistrants(&compAddr, CL_IOC_NODE_DOWN);
            clLogDebug("XPORT", "NOTIFY", "Comp death marked for port [%#x], id [%s]", port, compName);
        }
    }
}
ClRcT clNodeCacheLeaderIocSend(ClIocNodeAddressT currentLeader, ClIocAddressT *dstAddr)
{
    ClRcT rc = CL_OK;
    ClIocSendOptionT sendOption = {CL_IOC_HIGH_PRIORITY,0,0,CL_IOC_PERSISTENT_MSG,200 };
    ClIocPhysicalAddressT compAddr = { CL_IOC_BROADCAST_ADDRESS,  CL_IOC_CPM_PORT };
    ClTimerTimeOutT delay = {  0,  200 };
    ClUint32T i = 0;
    ClBufferHandleT message = 0;
    ClEoExecutionObjT *eoObj = NULL;
    ClIocNotificationT notification;
    
    memset(&notification,0,sizeof(ClIocNotificationT));
    notification.protoVersion = htonl(CL_IOC_NOTIFICATION_VERSION);
    notification.id = (ClIocNotificationIdT) htonl(CL_IOC_NODE_ARRIVAL_NOTIFICATION);
    notification.nodeAddress.iocPhyAddress.nodeAddress = htonl(clIocLocalAddressGet());
    notification.nodeAddress.iocPhyAddress.portId = htonl(CL_IOC_GMS_PORT);

    clEoMyEoObjectGet(&eoObj);

    while(!eoObj && i++ <= 3)
    {
        clEoMyEoObjectGet(&eoObj);
        clOsalTaskDelay(delay);
    }

    if(!eoObj)
    {
        clLogWarning("CAP", "ARP", "Could not send current leader update since EO still uninitialized.");
        return CL_ERR_NOT_INITIALIZED;
    }

    clBufferCreate(&message);

    currentLeader = htonl(currentLeader);
    rc = clBufferNBytesWrite(message, (ClUint8T *)&notification, sizeof(ClIocNotificationT));
    rc |= clBufferNBytesWrite(message, (ClUint8T*)&currentLeader, sizeof(currentLeader));
    if (rc != CL_OK)
    {
        clLogError("CAP", "ARP", "clBufferNBytesWrite failed with rc = %#x", rc);
        clBufferDelete(&message);
        return rc;
    }

    rc = clIocSend(eoObj->commObj, message, CL_IOC_PORT_NOTIFICATION_PROTO, dstAddr, &sendOption);

    clBufferDelete(&message);

    return rc;

}
/*-----------------------------------------------------------------------------
 * Cluster Track Stop API
 *---------------------------------------------------------------------------*/
ClRcT clGmsClusterTrackStop(
    CL_IN const ClGmsHandleT gmsHandle)
{
    ClRcT                           rc = CL_OK;
    struct gms_instance            *gms_instance_ptr = NULL;
    ClGmsClusterTrackStopRequestT   req = {0};
    ClGmsClusterTrackStopResponseT *res = NULL;
    
    CL_GMS_SET_CLIENT_VERSION( req );
    rc = clHandleCheckout(gmsHandleDb, gmsHandle, (void**)&gms_instance_ptr);
    if (rc != CL_OK)
    {
        return CL_GMS_RC(CL_ERR_INVALID_HANDLE);
    }
    
    if (gms_instance_ptr == NULL)
    {
        return CL_GMS_RC(CL_ERR_NULL_POINTER);
    }

    req.gmsHandle = gmsHandle;
    req.address.iocPhyAddress.nodeAddress = clIocLocalAddressGet();
    rc = clEoMyEoIocPortGet(&(req.address.iocPhyAddress.portId));
    
    CL_ASSERT(rc == CL_OK); /* Should really never happen */
    
    clGmsMutexLock(gms_instance_ptr->response_mutex);
    
    rc = cl_gms_cluster_track_stop_rmd(&req, 0 /* use def. timeout */, &res);
    if ((rc != CL_OK) || (res == NULL)) /* If there was an error, res isn't allocated */
    {
        goto error_exit;
    }
    
    rc = res->rc;
    
    clHeapFree((void*)res);

error_exit:
    clGmsMutexUnlock(gms_instance_ptr->response_mutex);

    if (clHandleCheckin(gmsHandleDb, gmsHandle) != CL_OK)
    {
        clLogError(CLM,NA,
                   "\nclHandleCheckin failed");
    }

    
    return CL_GMS_RC(rc);
}
ClRcT cliEOSetState(ClUint32T argc, ClCharT **argv, ClCharT **retStr)
{
    ClRcT rc = CL_OK;
    ClEoIdT eoId;
    ClEoStateT state;
    ClCharT tempStr[256];

    if (argc < THREE_ARGUMENT)
    {
        sprintf(tempStr, "%s%s%s", "Usage: EOStateSet <eoId> <state>\n",
                "\teoId[DEC]: Id assigned to an EO\n",
                "\tState[STRING]: SUSPEND/RESUME\n");
        rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER);
        goto done;
    }
    else
    {
        eoId = cpmCliStrToInt(argv[1]);
        
        if (0 == strcmp(argv[2], "SUSPEND"))
            state = CL_EO_STATE_SUSPEND;
        else if (0 == strcmp(argv[2], "RESUME"))
            state = CL_EO_STATE_RESUME;
        else
        {
            sprintf(tempStr, "\n Improper state: State: SUSPEND/RESUME\n");
            rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER);
            goto done;
        }

        rc = clCpmExecutionObjectStateSet(clIocLocalAddressGet(), eoId, state);
        if (rc == CL_OK)
            sprintf(tempStr, "\n State update Successful");
        else
            sprintf(tempStr, "\n State update Failed");
    }

  done:
    *retStr = (ClCharT *) clHeapAllocate(strlen(tempStr) + 1);
    if (*retStr == NULL)
        CL_CPM_CHECK(CL_DEBUG_ERROR, ("\n MAlloc Failed \n"),
                     CL_CPM_RC(CL_ERR_NO_MEMORY));
    strcpy(*retStr, tempStr);

  failure:
    return rc;
}
コード例 #10
0
ClRcT clMsgCommIdlInitialize(void)
{
    ClRcT rc;
    ClRcT retCode;

    gIdlUcastObj.objId = clObjId_ClIdlHandleObjT; 
    gIdlUcastObj.address.addressType = CL_IDL_ADDRESSTYPE_IOC;
    gIdlUcastObj.address.address.iocAddress.iocPhyAddress.nodeAddress = clIocLocalAddressGet();
    gIdlUcastObj.address.address.iocAddress.iocPhyAddress.portId = CL_IOC_MSG_PORT;
    gIdlUcastObj.flags = 0; 
    gIdlUcastObj.options.timeout = CL_RMD_TIMEOUT_FOREVER;
    gIdlUcastObj.options.retries = 3; 
    gIdlUcastObj.options.priority = CL_IOC_DEFAULT_PRIORITY;

    rc = clIdlHandleInitialize(&gIdlUcastObj, &gIdlUcastHandle);
    if(rc != CL_OK)
    {    
        clLogError("MSG", "IDL", "Failed to initialize the the IDL. error code [0x%x].", rc); 
        goto error_out;
    }    

    memcpy(&gIdlBcastObj, &gIdlUcastObj, sizeof(gIdlBcastObj));
    gIdlBcastObj.address.address.iocAddress.iocPhyAddress.nodeAddress = CL_IOC_BROADCAST_ADDRESS;
    gIdlBcastObj.address.address.iocAddress.iocPhyAddress.portId = CL_IOC_MSG_PORT;
    gIdlBcastObj.options.priority = CL_IOC_ORDERED_PRIORITY;
    rc = clIdlHandleInitialize(&gIdlBcastObj, &gIdlBcastHandle);
    if(rc != CL_OK)
    {    
        clLogError("MSG", "IDL", "Failed to initialize the the IDL. error code [0x%x].", rc); 
        goto error_out_1;
    } 

    goto done_out;

error_out_1:
    retCode = clIdlHandleFinalize(gIdlUcastHandle);
    if(retCode != CL_OK)
        clLogError("MSG", "IDL", "Failed to do the finalize the IDL handle. error code [0x%x].", retCode);
error_out:
done_out:
    return rc;
}
ClRcT
clLogClntCompNameChkNCompIdGet(SaNameT    *pCompName,
                               ClUint32T  *pClientId)
{
    ClRcT      rc           = CL_OK;
    ClUint32T  count        = 0;
    ClUint32T  localAddr    = 0;
    ClCharT    *pCompPrefix = NULL;
    ClUint32T  compLen      = 0;

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogCompNamePrefixGet(pCompName, &pCompPrefix);
    if( CL_OK != rc )
    {
        return rc;
    }
    compLen = strlen(pCompPrefix);
    for( count = 0; count < nLogAspComps; count++ )
    {
        if( compLen == strlen(aspCompMap[count].pCompName) )
        {
            if( !(memcmp(pCompPrefix, aspCompMap[count].pCompName, compLen)) )
            {
                localAddr = clIocLocalAddressGet();
                localAddr = localAddr << 16;
                localAddr = localAddr | aspCompMap[count].clntId;
            }
        }
    }
    *pClientId = localAddr;

    clHeapFree(pCompPrefix);
    CL_LOG_DEBUG_TRACE(("Exit: %d", *pClientId));
    return rc;
}
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;
}
/*-----------------------------------------------------------------------------
 * Cluster Join API
 *---------------------------------------------------------------------------*/
ClRcT clGmsClusterJoin(
    CL_IN const ClGmsHandleT                        gmsHandle,
    CL_IN const ClGmsClusterManageCallbacksT* const clusterManageCallbacks,
    CL_IN const ClGmsLeadershipCredentialsT         credentials,
    CL_IN const ClTimeT                             timeout,
    CL_IN const ClGmsNodeIdT                        nodeId,
    CL_IN const SaNameT*                      const nodeName)
{
    ClRcT                                rc = CL_OK;
    struct gms_instance                 *gms_instance_ptr = NULL;
    ClGmsClusterJoinRequestT             req = {0};
    ClGmsClusterJoinResponseT           *res = NULL;
    
    clLog(INFO,CLM,NA, "clGmsClusterJoin API is being invoked");
    CL_GMS_SET_CLIENT_VERSION( req );

    if ((nodeName == (const void*)NULL) ||
        (clusterManageCallbacks == (const void*)NULL) ||
        (clusterManageCallbacks->clGmsMemberEjectCallback == NULL))
    {
        return CL_GMS_RC(CL_ERR_NULL_POINTER);
    }
    
    rc = clHandleCheckout(gmsHandleDb, gmsHandle, (void**)&gms_instance_ptr);
    if (rc != CL_OK)
    {
        return rc;
    }

    if (gms_instance_ptr == NULL)
    {
        return CL_GMS_RC(CL_ERR_NULL_POINTER);
    }
    
    memcpy(&(gms_instance_ptr->cluster_manage_callbacks),
           clusterManageCallbacks,
           sizeof(ClGmsClusterManageCallbacksT));
    
    req.gmsHandle   = gmsHandle;
    req.credentials = credentials;
    req.nodeId      = nodeId;
    memcpy(&req.nodeName,nodeName, sizeof(SaNameT));
    req.sync        = CL_TRUE;
    req.address.iocPhyAddress.nodeAddress = clIocLocalAddressGet();
    if (clEoMyEoIocPortGet(&(req.address.iocPhyAddress.portId)) != CL_OK)
    {
        clLogError(CLM,NA,
                   "\nclEoMyEoIocPortGet failed");
    }
    
    clGmsMutexLock(gms_instance_ptr->response_mutex);
    
    clLog(TRACE,CLM,NA, "Sending RMD to GMS server for cluster join");
    rc = cl_gms_cluster_join_rmd(&req, (ClUint32T)(timeout/NS_IN_MS), &res);
    clLog(TRACE,CLM,NA, "clGmsClusterJoin RMD returned");

    
    if( res ) 
    clHeapFree((void*)res);
    
    clGmsMutexUnlock(gms_instance_ptr->response_mutex);
    if (clHandleCheckin(gmsHandleDb, gmsHandle) != CL_OK)
    {
        clLogError(CLM,NA,
                   "\nclHandleCheckin failed");
    }
    return rc;
}
コード例 #14
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
コード例 #15
0
ClRcT
clCompAppInitialize(
    ClUint32T argc,
    ClCharT *argv[])
{
    SaNameT             appName;
    ClCpmCallbacksT     callbacks;
    ClVersionT          version;
    ClIocPortT          iocPort;
    ClRcT               rc = CL_OK;

    /*
     * 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.appHealthCheck                    = NULL;
    callbacks.appTerminate                      = clCompAppTerminate;
    callbacks.appCSISet                         = clCompAppAMFCSISet;
    callbacks.appCSIRmv                         = clCompAppAMFCSIRemove;
    callbacks.appProtectionGroupTrack           = NULL;
        
    /*
     * Get IOC Address, Port and Name. Register with AMF.
     */

    clEoMyEoIocPortGet(&iocPort);

    if ( (rc = clCpmClientInitialize(&cpmHandle, &callbacks, &version)) ) 
        goto errorexit;

    /*
     * If this component will provide a service, register it now.
     */

#if HAS_EO_SERVICES


    rc = clSAFComponent0EO0ClientInstall();

#endif

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

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

    // ...

    /*
     * ---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 = clCpmComponentNameGet(cpmHandle, &appName)) ) 
        goto errorexit;
    if ( (rc = clCpmComponentRegister(cpmHandle, &appName, NULL)) ) 
        goto errorexit;

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

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

    /*
     * This is where the application code starts. If the main thread usage
     * policy is CL_EO_USE_THREAD_FOR_APP, then return from this fn only 
     * after the application terminates. If the main thread usage policy is
     * CL_EO_USE_THREAD_FOR_RECV, then return from this fn after doing the
     * application specific initialization and registration.
     */

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

    // ...

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

    return rc;

errorexit:

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

    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);
    /* Open the log stream as soon as I've registered with AMF */
    clEvalAppLogStreamOpen((ClCharT *)appName.value, &gEvalLogStream);

    /*
     * 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_SEV_ERROR, "Failed to init event mechanism [0x%x]\n", rc);
            return ;
        }
            // 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));
          errorExit(rc);
          }
        
      rc = saEvtEventSubscribe(evtChannelHandle, NULL, 1);
      if (rc != SA_AIS_OK)
      {
        clprintf(CL_LOG_SEV_ERROR, "Failed to subscribe to event channel [0x%x]",rc);
         errorExit(rc);
      }
    }

    /*csa113: create an event definition to be published */
    if (1)
    {
        SaNameT publisherName;
        saNameSet((SaNameT*) &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_SEV_ERROR, "Failed to set event attributes [0x%x]\n",rc);
            assert(0);            
        }
    }
}
ClRcT clCpmCompGet(ClUint32T argc, ClCharT *argv[], ClCharT **retStr)
{
    ClRcT rc = CL_OK;
    ClNameT compName = { 0 };
    ClIocAddressT compAddress;
    ClUint32T compId = 0;
    ClCharT buffer[2048] = "\0";
    ClUint32T length = 0;
    ClIocNodeAddressT nodeAddress;

    if (!strcasecmp("compAddressGet", argv[0]))
    {
        if (argc != THREE_ARGUMENT)
        {
            sprintf(buffer, "%s",
                    "Usage: compAddressGet <CompName> <nodeIocAddress>\n"
                    "\tcompName[STRING] - component Name\n"
                    "\tnodeIocAddress[DEC] - node ioc Address, where the component exist\n");
            rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER);
            goto done;
        }
        strcpy(compName.value, argv[1]);
        compName.length = strlen(argv[1]);
        nodeAddress = (ClIocNodeAddressT) cpmCliStrToInt(argv[2]);
        rc = clCpmComponentAddressGet(nodeAddress, &compName, &compAddress);
        if (rc == CL_OK)
            sprintf(buffer, "Address %d Port %x\n",
                    compAddress.iocPhyAddress.nodeAddress,
                    compAddress.iocPhyAddress.portId);
        else
            sprintf(buffer, "Failed get component Address, rc = 0x%x", rc);
    }
    else if (!strcasecmp("compIdGet", argv[0]))
    {
        if (argc != TWO_ARGUMENT)
        {
            sprintf(buffer, "%s",
                    "Usage: compIdGet <CompName> \n"
                    "\tcompName[STRING] - component Name\n");
            rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER);
           goto done;
        }
        strcpy(compName.value, argv[1]);
        compName.length = strlen(argv[1]);
        rc = clCpmComponentIdGet(0, &compName, &compId);
        if (rc == CL_OK)
            sprintf(buffer, "compId is %d\n", compId);
        else
            sprintf(buffer, "Failed get component Id, rc = 0x%x", rc);
    }
    else if (!strcasecmp("compPIDGet", argv[0]))
    {
        if (argc != TWO_ARGUMENT)
        {
            sprintf(buffer, "%s",
                    "Usage: compPidGet <CompName> \n"
                    "\tcompName[STRING] - component Name\n");
            rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER);
            goto done;
        }
        strcpy(compName.value, argv[1]);
        compName.length = strlen(argv[1]);
        rc = clCpmComponentPIDGet(&compName, &compId);
        if (rc == CL_OK)
            sprintf(buffer, "compPId is %d\n", compId);
        else
            sprintf(buffer, "Failed get component PID, rc = 0x%x", rc);
    }
    else if (!strcasecmp("compTraceGet", argv[0]))
    {
        ClPtrT ppOutMem = NULL;
        ClUint32T segmentSize = 0;
        ClFdT fd = 0;
#ifndef POSIX_BUILD
        ClCharT compShmSegment[CL_MAX_NAME_LENGTH];
        segmentSize = getpagesize();
        if (argc != TWO_ARGUMENT)
        {
            sprintf(buffer, "%s",
                    "Usage: compTraceGet <CompName> \n"
                    "\tcompName[STRING] - component Name \n");
            rc = CL_CPM_RC(CL_ERR_INVALID_PARAMETER);
            goto done;
        }
        strcpy(compName.value, argv[1]);
        snprintf(compShmSegment, sizeof(compShmSegment), "/CL_%s_exception_%d", compName.value, clIocLocalAddressGet());
        rc = clOsalShmOpen(compShmSegment, O_RDONLY, 0777, &fd);
        if(rc == CL_OK)
        {
            rc = clOsalMmap(0, segmentSize, PROT_READ, MAP_PRIVATE, fd, 0, &ppOutMem);
        }
#endif
        if (ppOutMem)
        {
            sprintf(buffer, "%s\n", (ClCharT*)ppOutMem);
            clOsalMunmap(ppOutMem, segmentSize);
            close(fd);
        }
        else
            sprintf(buffer, "%s\n", "Unable to get the component Stack Trace");
    }
  done:
    length = strlen(buffer) + 1;
    *retStr = (ClCharT *) clHeapAllocate(length);
    if (*retStr != NULL)
        strcpy(*retStr, buffer);
    else
        rc = CL_CPM_RC(CL_ERR_NO_MEMORY);

    return rc;
}
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;
}
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);
}
/*-----------------------------------------------------------------------------
 * Cluster Track API
 *---------------------------------------------------------------------------*/
ClRcT clGmsClusterTrack(
    CL_IN    const ClGmsHandleT               gmsHandle,
    CL_IN    const ClUint8T                   trackFlags,
    CL_INOUT ClGmsClusterNotificationBufferT* const notificationBuffer)
{    
    ClRcT                       rc = CL_OK;
    struct gms_instance        *gms_instance_ptr = NULL;
    ClGmsClusterTrackRequestT   req = {0};
    ClGmsClusterTrackResponseT *res = NULL;
    const ClUint8T validFlag = CL_GMS_TRACK_CURRENT | CL_GMS_TRACK_CHANGES |
                            CL_GMS_TRACK_CHANGES_ONLY;
    ClBoolT shouldFreeNotification = CL_TRUE;

    clLog(TRACE,CLM,NA,"clGmsClusterTrack API is invoked");
    if (((trackFlags | validFlag) ^ validFlag) != 0) {
        return CL_GMS_RC(CL_ERR_BAD_FLAG);
    }

    CL_GMS_SET_CLIENT_VERSION( req );
    
    if (((trackFlags & CL_GMS_TRACK_CURRENT) == CL_GMS_TRACK_CURRENT) && /* If current view is requested */
        (notificationBuffer != NULL) &&        /* Buffer is provided */
        (notificationBuffer->notification != NULL) && /* Caller provides array */
        (notificationBuffer->numberOfItems == 0)) /* then size must be given */
    {
        return CL_GMS_RC(CL_ERR_INVALID_PARAMETER);
    }
    
    if (trackFlags == 0) /* at least one flag should be specified */
    {
        return CL_GMS_RC(CL_ERR_BAD_FLAG);
    }
    
    if (((trackFlags & CL_GMS_TRACK_CHANGES) == CL_GMS_TRACK_CHANGES) &&
        ((trackFlags & CL_GMS_TRACK_CHANGES_ONLY) == CL_GMS_TRACK_CHANGES_ONLY)) /* mutually exclusive flags */
    {
        return CL_GMS_RC(CL_ERR_BAD_FLAG);
    }
    
    rc = clHandleCheckout(gmsHandleDb, gmsHandle, (void**)&gms_instance_ptr);
    if (rc != CL_OK)
    {
        return CL_GMS_RC(CL_ERR_INVALID_HANDLE);
    }

    if (gms_instance_ptr == NULL)
    {
        return CL_GMS_RC(CL_ERR_NULL_POINTER);
    }
    
    /* If not a sync call, then clGmsClusterTrackCallbackHandler must be given */
    if (((trackFlags & (CL_GMS_TRACK_CHANGES|CL_GMS_TRACK_CHANGES_ONLY)) != 0) ||
        (((trackFlags & CL_GMS_TRACK_CURRENT) == CL_GMS_TRACK_CURRENT) &&
         (notificationBuffer == NULL)))
    {
        if (gms_instance_ptr->callbacks.clGmsClusterTrackCallback == NULL)
        {
            rc = CL_GMS_RC(CL_ERR_NO_CALLBACK);
            goto error_checkin;
        }
    }
    
    req.gmsHandle  = gmsHandle;
    req.trackFlags = trackFlags;
    req.sync       = CL_FALSE;
    req.address.iocPhyAddress.nodeAddress = clIocLocalAddressGet();
    rc = clEoMyEoIocPortGet(&(req.address.iocPhyAddress.portId));
    
    CL_ASSERT(rc == CL_OK); /* Should really never happen */
    
    clGmsMutexLock(gms_instance_ptr->response_mutex);
    
    if (((trackFlags & CL_GMS_TRACK_CURRENT) == CL_GMS_TRACK_CURRENT) &&
        (notificationBuffer != NULL)) /* Sync response requested */
    {
        /*
         * We need to call the extended track() request which returns with
         * a notification buffer allocated by the XDR layer.
         */
        clLogMultiline(TRACE,CLM,NA,
                "Sending RMD to GMS server for Cluster track with"
                " track flags CL_GMS_TRACK_CURRENT");
        req.sync = CL_TRUE;
        rc = cl_gms_cluster_track_rmd(&req, 0 /* use def. timeout */, &res);
        clLog(TRACE,CLM,NA,"Returned from cluster track RMD");
        if ((rc != CL_OK) || (res == NULL)) /* If there was an error, res isn't allocated */
        {
            switch (CL_GET_ERROR_CODE(rc))
            {
                case CL_ERR_TIMEOUT:    rc = CL_GMS_RC(CL_ERR_TIMEOUT); break;
                case CL_ERR_TRY_AGAIN:  rc = CL_GMS_RC(CL_ERR_TRY_AGAIN); break;
                default:                rc = CL_GMS_RC(CL_ERR_UNSPECIFIED);
            }
            /* FIXME: Need to get back to this! Based on consensus among
             *  engineers.
             */
            goto error_unlock_checkin;
        }

        if (res->rc != CL_OK) /* If other side indicated error, we need
                               * to free the buffer.
                               */
        {
            rc = res->rc;
            goto error_exit;
        }

        /* All fine, need to copy buffer */
        if (notificationBuffer->notification == NULL) /* we provide array */
        {
            memcpy(notificationBuffer, &res->buffer,
                   sizeof(*notificationBuffer)); /* This takes care of array */
            shouldFreeNotification = CL_FALSE;
        }
        else
        { /* caller provided array with fixed given size; we need to copy if
           * there is enough space.
           */
            if (notificationBuffer->numberOfItems >=
                res->buffer.numberOfItems)
            {
                /* Copy array, as much as we can */
                memcpy((void*)notificationBuffer->notification,
                       (void*)res->buffer.notification,
                       res->buffer.numberOfItems *
                          sizeof(ClGmsClusterNotificationT));
            }
            /*
             * Instead of copying the rest of the fields in buffer one-by-one,
             * we do a trick: relink the above array and than copy the entire
             * struck over.  This will keep working even if the buffer struct
             * grows in the future; without change here.
             */
            clHeapFree((void*)res->buffer.notification);
            res->buffer.notification = notificationBuffer->notification;
            memcpy((void*)notificationBuffer, (void*)&res->buffer,
                   sizeof(*notificationBuffer));
            shouldFreeNotification = CL_FALSE;
        }
    }
    else
    {
        clLog(TRACE,CLM,NA, "Sending Async RMD to GMS server for cluster track"); 
        /* No sync response requested, so we call the simple rmd call */
        rc = cl_gms_cluster_track_rmd(&req, 0 /* use def. timeout */, &res);
        clLog(TRACE,CLM,NA, "Cluster track RMD returned");
        /* No sync response requested, so we call the simple rmd call */
        if ((rc != CL_OK) || (res == NULL)) /* If there was an error, res isn't allocated */
        {
            goto error_unlock_checkin;
        }
        
        rc = res->rc;
    }     

error_exit:
    if(shouldFreeNotification == CL_TRUE )
    {
        if (res->buffer.notification != NULL)
          clHeapFree((void*)res->buffer.notification);
    }
    clHeapFree((void*)res);
    
error_unlock_checkin:
    clGmsMutexUnlock(gms_instance_ptr->response_mutex);
    
error_checkin:
    if (clHandleCheckin(gmsHandleDb, gmsHandle) != CL_OK)
    {
        clLog(ERROR,CLM,NA,"clHandleCheckin Failed");
    }
    
    return rc;
}
static void logRecordsFlush(ClLogFlushRecordT *pFlushRecord)
{
    ClRcT rc = CL_OK;
    ClIdlHandleT idlHdl = CL_HANDLE_INVALID_VALUE;
    ClIocNodeAddressT localAddr = clIocLocalAddressGet();
    ClUint32T seqNum = 0;
    ClUint32T i = 0;

    seqNum = pFlushRecord->seqNum;
    if(pFlushRecord->multicast)
    {
        rc = clLogIdlHandleInitialize(pFlushRecord->mcastAddr, &idlHdl);
        if( CL_OK != rc )
        {
            goto out_free;
        }
    }

    for(i = 0; i < pFlushRecord->numBufs; ++i)
    {
        ClUint32T numRecords = pFlushRecord->pBuffs[i].numRecords;
        ClUint8T* pRecord = pFlushRecord->pBuffs[i].pRecord;
        ClUint32T buffLen = pFlushRecord->recordSize * numRecords;
        ClTimerHandleT hTimer = CL_HANDLE_INVALID_VALUE;
        ClHandleT hFlusher = CL_HANDLE_INVALID_VALUE;
        if(pFlushRecord->multicast > 0)
        {
            if(pFlushRecord->ackersCount > 0)
            {
                rc = clLogFlusherCookieHandleCreate(numRecords, &hTimer, &hFlusher);
                if(rc != CL_OK)
                    goto out_free;
            }
            rc = VDECL_VER(clLogClntFileHdlrDataReceiveClientAsync, 4, 0, 0)(idlHdl,
                                                                             pFlushRecord->mcastAddr.iocMulticastAddress,
                                                                             seqNum,
                                                                             localAddr,
                                                                             hFlusher, numRecords,
                                                                             buffLen, pRecord,
                                                                             NULL, 0);
            if(rc != CL_OK)
            {
                if(hFlusher)
                {
                    CL_LOG_CLEANUP(clLogFlusherCookieHandleDestroy(hFlusher, CL_FALSE), CL_OK);
                }
            }
        }
        else
        {
            if(pFlushRecord->fileOwnerAddr == localAddr)
            {
                rc = clLogFileOwnerEntryFindNPersist(&pFlushRecord->fileName,
                                                     &pFlushRecord->fileLocation,
                                                     numRecords, pRecord);
                if(rc != CL_OK)
                {
                    /* 
                     * do nothing
                     */
                }
            }
        }
        seqNum += numRecords;
        clHeapFree(pRecord);
    }

    out_free:
    {
        ClUint32T j;
        for(j = i; j < pFlushRecord->numBufs; ++j)
        {
            if(pFlushRecord->pBuffs[j].pRecord)
                clHeapFree(pFlushRecord->pBuffs[j].pRecord);
        }
    }
    if(idlHdl)
    {
        CL_LOG_CLEANUP(clIdlHandleFinalize(idlHdl), CL_OK);
    }
    if(pFlushRecord->fileLocation.pValue)
    {
        clHeapFree(pFlushRecord->fileLocation.pValue);
        pFlushRecord->fileLocation.pValue = NULL;
        pFlushRecord->fileLocation.length = 0;
    }
    if(pFlushRecord->fileName.pValue)
    {
        clHeapFree(pFlushRecord->fileName.pValue);
        pFlushRecord->fileName.pValue = NULL;
        pFlushRecord->fileName.length = 0;
    }
    if(pFlushRecord->pBuffs)
    {
        clHeapFree(pFlushRecord->pBuffs);
        pFlushRecord->pBuffs = NULL;
    }
}
int main(int argc, char *argv[])
{
    SaNameT             appName = {0};
    SaAmfCallbacksT     callbacks;
    SaVersionT          version;
    ClIocPortT          iocPort;
    SaAisErrorT         rc = SA_AIS_OK;

    SaSelectionObjectT dispatch_fd = 0;
    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;


    /*
     * 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;

    /*
     * Initialize the log stream
     */
    clEvalAppLogStreamOpen((ClCharT*)appName.value, &gEvalLogStream);

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


    /*
     * Block on AMF dispatch file descriptor for callbacks
     */
    do
    {
        struct timeval timeout;
        timeout.tv_sec = 2; timeout.tv_usec = 0;

        FD_ZERO(&read_fds);
        FD_SET(dispatch_fd, &read_fds);

        if( select(dispatch_fd + 1, &read_fds, NULL, NULL, &timeout) < 0)
        {
            if (EINTR == errno)
            {
                continue;
            }
		    clprintf (CL_LOG_SEV_ERROR, "Error in select()");
			perror("");
            break;
        }
        if (FD_ISSET(dispatch_fd,&read_fds)) saAmfDispatch(amfHandle, SA_DISPATCH_ALL);
        
        if (running) clprintf(CL_LOG_SEV_INFO,"csa102: Unthreaded Hello World! %s", show_progress());
        else clprintf(CL_LOG_SEV_INFO,"csa102: idle");        
    }while(!unblockNow);      

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


    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;
}
/*
 * Called with the log server flusher stream lock. held.
 */
static ClRcT
clLogFlusherRecordsMcast(ClLogSvrStreamDataT  *pStreamData,
                         ClUint32T            nRecords)
{
    ClRcT      rc       = CL_OK;
    ClLogStreamHeaderT  *pHeader  = pStreamData->pStreamHeader;
    ClUint8T            *pRecords = pStreamData->pStreamRecords;
    ClUint32T           startIdx  = 0;
    ClUint32T           buffLen   = 0;
    ClHandleT           hFlusher  = CL_HANDLE_INVALID_VALUE;     
    ClTimerHandleT      hTimer    = CL_HANDLE_INVALID_VALUE;  
    ClIdlHandleT        hIdlHdl   = CL_HANDLE_INVALID_VALUE;
    ClIocNodeAddressT   localAddr = 0;
    ClUint8T            *pBuffer  = NULL;
    ClUint32T           size      = 0;
    ClUint32T           firstBatch = 0;
    ClUint32T           secondPatch = 0;
    ClBoolT             doMulticast = 
        ( (0 < (pStreamData->ackersCount + pStreamData->nonAckersCount)) &&
          (pHeader->streamMcastAddr.iocMulticastAddress != 0) )? CL_TRUE: CL_FALSE;

    clLogDebug("SVR", "FLU", "Enter: nRecords: %u seqNum: %u fileOwnerAddr:[%d]", nRecords,
            pStreamData->seqNum, pStreamData->fileOwnerAddr);

    if( (pStreamData->ackersCount + pStreamData->nonAckersCount) == 1 && 
        (pStreamData->fileOwnerAddr == clIocLocalAddressGet()) )
    {
        doMulticast = CL_FALSE;
    }
    /* 
     * If some fileowner has registered for this stream, if then multicast,
     * otherwise just send it to local guy 
     */
    if( CL_TRUE == doMulticast )
    {
        rc = clLogIdlHandleInitialize(pHeader->streamMcastAddr, &hIdlHdl);
        if( CL_OK != rc )
        {
            return rc;
        }
        if( pStreamData->ackersCount > 0 )
        {
            rc = clLogFlusherCookieHandleCreate(nRecords, &hTimer, &hFlusher);
            if( CL_OK != rc )
            {
                CL_LOG_CLEANUP(clIdlHandleFinalize(hIdlHdl), CL_OK);
                return rc;
            }
            CL_LOG_DEBUG_TRACE(("hFlusher: %#llX", hFlusher));
        }
    }

    localAddr = clIocLocalAddressGet();
    startIdx = pHeader->startAck % pHeader->maxRecordCount;
    if(nRecords > pHeader->maxRecordCount)
        nRecords = pHeader->maxRecordCount;

    buffLen = nRecords * pHeader->recordSize;
    /*
     * Drop the server stream mutex unlock now and grab it again after file owner writes
     * and before exiting out of the function
     */
    clLogDebug(CL_LOG_AREA_SVR, "FLU", "startIdx: %u maxRec: %u nRecords: %u startIdx: %d recordIdx: %d", startIdx,
                    pHeader->maxRecordCount, nRecords, pHeader->startAck, pHeader->recordIdx);
    if( (startIdx + nRecords) <= pHeader->maxRecordCount )
    {
        pBuffer = pRecords + (startIdx * pHeader->recordSize);
        if( pStreamData->fileOwnerAddr == localAddr ) 
        {
            /* File onwer function which flushes the data into file */
            rc = clLogFileOwnerEntryFindNPersist(&pStreamData->fileName, 
                    &pStreamData->fileLocation, nRecords, pBuffer);
            if( CL_OK != rc )
            {
                return rc;
            }
        }
        if( doMulticast == CL_TRUE )
        {
            rc = VDECL_VER(clLogClntFileHdlrDataReceiveClientAsync, 4, 0, 0)(hIdlHdl, 
                    pHeader->streamMcastAddr.iocMulticastAddress, 
                    pStreamData->seqNum, localAddr, 
                    hFlusher, nRecords, buffLen, pBuffer,
                    NULL, 0);
            CL_LOG_CLEANUP(clIdlHandleFinalize(hIdlHdl), CL_OK);
        }
        CL_LOG_DEBUG_VERBOSE(("Copied from: %p to %u", pRecords + startIdx,
                    nRecords * pHeader->recordSize));
    }
    else
    {
        CL_LOG_DEBUG_TRACE(("startIdx: %u maxRec: %u nRecords: %u", startIdx,
                    pHeader->maxRecordCount, nRecords));
        firstBatch = pHeader->maxRecordCount - startIdx;
        pBuffer = pRecords + (startIdx * pHeader->recordSize);
        secondPatch = nRecords - firstBatch;
        if( pStreamData->fileOwnerAddr == localAddr )
        {
            /*
             *  Make two calls to fileowner function, so that no need to
             *  allocate memory, it just direct copy from shared memory 
             */
            rc = clLogFileOwnerEntryFindNPersist(&pStreamData->fileName, 
                    &pStreamData->fileLocation, firstBatch, pBuffer);
            if( CL_OK != rc )
            {
                return rc;
            }
            rc = clLogFileOwnerEntryFindNPersist(&pStreamData->fileName, 
                    &pStreamData->fileLocation, secondPatch, pRecords);
            if( CL_OK != rc )
            {
                return rc;
            }
        }
        if( doMulticast == CL_TRUE )
        {
            pBuffer = clHeapCalloc(buffLen, sizeof(ClUint8T));
            if( NULL == pBuffer )
            {
                clLogError("LOG", "FLS", "clHeapCalloc() : rc[0x %x]", rc);
                CL_LOG_CLEANUP(clLogFlusherCookieHandleDestroy(hFlusher, CL_FALSE), CL_OK);
                CL_LOG_CLEANUP(clIdlHandleFinalize(hIdlHdl), CL_OK);
                return CL_LOG_RC(CL_ERR_NO_MEMORY);
            }
            size = firstBatch * pHeader->recordSize;
            memcpy(pBuffer, pRecords + (startIdx * pHeader->recordSize), size);
            memcpy(pBuffer + size, pRecords, buffLen - size); 
            rc = VDECL_VER(clLogClntFileHdlrDataReceiveClientAsync, 4, 0, 0)(hIdlHdl, 
                    pHeader->streamMcastAddr.iocMulticastAddress, 
                    pStreamData->seqNum, localAddr, 
                    hFlusher, nRecords, buffLen, pBuffer,
                    NULL, 0);
            clHeapFree(pBuffer);
            CL_LOG_CLEANUP(clIdlHandleFinalize(hIdlHdl), CL_OK);
        }
    }
    if( (doMulticast == CL_TRUE) && (CL_OK != rc) )
    {
        clLogError("LOG", "FLS", "VDECL_VER(clLogClntFileHdlrDataReceiveClientAsync, 4, 0, 0)(): "
                "rc[0x %x]", rc);
        CL_LOG_CLEANUP(clLogFlusherCookieHandleDestroy(hFlusher, CL_FALSE), CL_OK);
        return rc;
    }    

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
static ClRcT
clLogFlusherRecordsGetMcast(ClLogSvrStreamDataT  *pStreamData,
                            ClUint32T            nRecords,
                            ClLogFlushRecordT    *pFlushRecord)
{
    ClRcT      rc       = CL_OK;
    ClLogStreamHeaderT  *pHeader  = pStreamData->pStreamHeader;
    ClUint8T            *pRecords = pStreamData->pStreamRecords;
    ClUint32T           startIdx  = 0;
    ClUint32T           buffLen   = 0;
    ClIocNodeAddressT   localAddr = 0;
    ClUint8T            *pBuffer  = NULL;
    ClUint32T           firstBatch = 0;
    ClBoolT             doMulticast = CL_FALSE;
    ClUint32T           secondBatch = 0;

    if ((CL_LOG_STREAM_HEADER_STRUCT_ID != pHeader->struct_id) || (CL_LOG_STREAM_HEADER_UPDATE_COMPLETE != pHeader->update_status))
    {/* Stream Header is corrupted so reset Header parameters */
       clLogStreamHeaderReset(pHeader); 
    }
    if(pFlushRecord->multicast < 0 )
    {
        doMulticast = ( (0 < (pStreamData->ackersCount + pStreamData->nonAckersCount)) &&
                        (pHeader->streamMcastAddr.iocMulticastAddress != 0) )? CL_TRUE: CL_FALSE;

        if( (pStreamData->ackersCount + pStreamData->nonAckersCount) == 1 && 
            (pStreamData->fileOwnerAddr == clIocLocalAddressGet()) )
        {
            doMulticast = CL_FALSE;
        }
        pFlushRecord->multicast = doMulticast;
        pFlushRecord->mcastAddr = pHeader->streamMcastAddr;
        pFlushRecord->ackersCount = pStreamData->ackersCount;
    }
    else
    {
        doMulticast = (pFlushRecord->multicast ? CL_TRUE : CL_FALSE) ;
    }

    localAddr = clIocLocalAddressGet();
    if((!doMulticast) && (pStreamData->fileOwnerAddr != localAddr))
    { /*Nobody is interested in these records and they are not for me then skip them */
      /*  clLogDebug("SVR", "FLU", "Nobody is Interested in These records, So skipping them");*/
        return rc;
    }

    startIdx = pHeader->startAck % pHeader->maxRecordCount;
    if(nRecords > pHeader->maxRecordCount)
        nRecords = pHeader->maxRecordCount;

    CL_ASSERT(pHeader->recordSize < 4*1024);  // Sanity check the log record size
    buffLen = nRecords * pHeader->recordSize;

    clLogTrace(CL_LOG_AREA_SVR, "FLU", "startIdx: %u maxRec: %u nRecords: %u startIdx: %d recordIdx: %d", startIdx,
               pHeader->maxRecordCount, nRecords, pHeader->startAck, pHeader->recordIdx);
    /* FirstBatch is from startIdx towards maxRecordCount and SecondBatch is from 0 to startIdx 
     * SecondBatch is only valid if number of records are greater than (maxRecordCount - startIdx)
     */
    if ( (startIdx + nRecords) <= pHeader->maxRecordCount )
    {
        firstBatch = nRecords;
        secondBatch = 0;
    }
    else
    {
        firstBatch = pHeader->maxRecordCount - startIdx;
        secondBatch = nRecords + startIdx - pHeader->maxRecordCount;
    }
    /* Computed firstBatch and secondBatch number of records, now verify and flush them */
    pBuffer = pRecords + (startIdx * pHeader->recordSize);

    pFlushRecord->pBuffs = (ClLogFlushBufferT*) clHeapRealloc(pFlushRecord->pBuffs, (pFlushRecord->numBufs+1)*sizeof(*pFlushRecord->pBuffs));
    CL_ASSERT(pFlushRecord->pBuffs != NULL);
    memset(pFlushRecord->pBuffs+pFlushRecord->numBufs, 0, sizeof(*pFlushRecord->pBuffs));
    pFlushRecord->pBuffs[pFlushRecord->numBufs].pRecord = (ClUint8T*) clHeapCalloc(sizeof(ClUint8T), buffLen);
    CL_ASSERT(pFlushRecord->pBuffs[pFlushRecord->numBufs].pRecord != NULL);

    pFlushRecord->pBuffs[pFlushRecord->numBufs].numRecords = 0;
    if (firstBatch)
    {
        clLogVerifyAndFlushRecords(pBuffer, pHeader, pFlushRecord, firstBatch);
    }
    if (secondBatch)
    {
        pBuffer = pRecords;
        clLogVerifyAndFlushRecords(pBuffer, pHeader, pFlushRecord, secondBatch);
    }
    pFlushRecord->numBufs++;

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

    CL_LOG_DEBUG_TRACE(("Enter"));

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

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

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

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

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

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

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

    CL_LOG_DEBUG_TRACE(("Enter"));

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

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



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

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

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

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

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

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

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

    logRecordsFlush(&flushRecord);
    clLogServerStreamMutexLockFlusher(pStreamData);

    CL_LOG_DEBUG_TRACE(("Exit"));
    return CL_OK;
}    
static void clEoQueueStatsDump(void)
{
    register ClInt32T i,j;
    ClCharT *pBuffer = NULL;
    ClUint32T bytes = 0;
    ClUint32T totalBytes=0;
    ClUint32T nbytes=0;
    ClInt32T remaining = 0;

    for(i = 0; i < CL_IOC_MAX_PRIORITIES;++i)
    {
        for(j = 0; j < CL_IOC_NUM_PROTOS;++j)
        {
            ClEoQueueStatsT *pStats = &gClEoQueueStats[i][j];
            ClUint64T avgTime = 0;
            ClUint32T avgQueueSize=0;
            if(pStats->used == CL_FALSE) continue;
            if(!remaining)
            {
                remaining = 1024;
                totalBytes = bytes+remaining;
                totalBytes &= ~1023;
                pBuffer = realloc(pBuffer,totalBytes);
                if(!pBuffer) return;
            }
            avgTime = pStats->totalTime/(pStats->count?pStats->count:1);
            avgQueueSize= pStats->totalQueueSize/(pStats->count ? pStats->count:1);
            nbytes = snprintf(pBuffer+bytes,totalBytes-bytes,
                    "Pri:%d, Proto:%s, Count:%d, MinSize:%d, MaxSize:%d, AvgSize:%d, MinTime:%lld, MaxTime:%lld, AvgTime:%lld\n", i,clEoProtoName((ClUint32T)j),pStats->count,pStats->minQueueSize,pStats->maxQueueSize,avgQueueSize,pStats->minTime,pStats->maxTime,avgTime);
            bytes += nbytes;
            remaining -= nbytes;
            if(remaining < nbytes )
                remaining = 0;
        }
    }
    if(pBuffer)
    {
        ClCharT filename[0xff+1];
        ClCharT *aspLogDir = getenv("ASP_LOGDIR");
        ClIocNodeAddressT nodeAddress = clIocLocalAddressGet();
        snprintf(filename,
                 sizeof(filename),
                 "%s/%s_queue_stats_%d.txt",
                 !aspLogDir ? "/tmp" : aspLogDir,
                 CL_EO_NAME,
                 nodeAddress);
        int fd = open(filename, O_CREAT|O_RDWR|O_APPEND,0666);
        if(fd < 0 )
        {
            perror("open:");
            free(pBuffer);
            return;
        }
        if(write(fd,pBuffer,bytes) != bytes)
        {
            perror("Write:");
        }
        else
        {
            printf(" EO Queue Stats written to %s\n",filename);
        }
        free(pBuffer);
    }
}
コード例 #28
0
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;
}
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;
    callbacks.saAmfProxiedComponentInstantiateCallback    = clProxiedCompInstantiate;
    callbacks.saAmfProxiedComponentCleanupCallback        = clProxiedCompCleanup;

    /*
     * Get IOC Address, Port and Name. Register with AMF.
     */

    clEoMyEoIocPortGet(&iocPort);

    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;

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

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

    /*
     * Block on AMF dispatch file descriptor for callbacks
     */
    do
    {
        if( select(dispatch_fd + 1, &read_fds, NULL, NULL, NULL) < 0)
        {
            clprintf (CL_LOG_SEV_ERROR, "Error in select()");
            perror("");
            break;
        }
        saAmfDispatch(amfHandle, SA_DISPATCH_ALL);
    } while(!unblockNow);

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


    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 PyObject* GetRunningNodeList(PyObject *self, PyObject *args)
{
  char buf[16*1024];
  const int bufLen = sizeof(buf);
  int curLen = 0;
  ClIocNodeAddressT nodeList[CL_IOC_MAX_NODES];
  unsigned int numNodes = CL_IOC_MAX_NODES;
  ClRcT rc;
  unsigned int i;

  for (i=0;i<CL_IOC_MAX_NODES;i++)
    nodeList[i] = i;

  if ((rc = clIocNeighborListGet(&numNodes, nodeList)) != CL_OK)
    {
     char c[100];
     snprintf(c,100,"Error [0x%x] getting nodes", rc);
     //PyErr_SetString(PyExc_SystemError,c);
     PyObject* errData = Py_BuildValue("is",rc,buf);
     PyErr_SetObject(PyExc_SystemError,errData);
     return NULL;
    }
  DbgLog("IocNeighbors: returned: 0x%x Number of Nodes: %d  nodelist: %d %d", rc, numNodes, nodeList[0],nodeList[1]);

#if 0 /* NeighborListGet supposedly returns self */
  nodeList[0] = clIocLocalAddressGet()&CL_IOC_NODE_MASK;
  numNodes++;
#endif

  curLen += snprintf(buf+curLen, bufLen-curLen, "[ ");

  /*
   * Now get node names from ioc address using clCpmSlotGet.
   */

  char* needComma = "";
  for(i = 0; i < numNodes; ++i)
    {
    ClCpmSlotInfoT slotInfo;
    slotInfo.slotId = nodeList[i];
    rc = clCpmSlotGet(CL_CPM_SLOT_ID, &slotInfo);
    if(rc == CL_OK)
      {
          DbgLog("rc: %x, 'slot': %d, 'name': '%.*s'", rc,slotInfo.slotId, slotInfo.nodeName.length, slotInfo.nodeName.value);
       curLen += snprintf(buf+curLen, bufLen-curLen, "%s{ 'slot': %d, 'name': '%.*s' }", needComma,slotInfo.slotId, slotInfo.nodeName.length, slotInfo.nodeName.value);
       needComma = ",";
      }
    else
      {
        clAppLog(CL_LOG_HANDLE_APP, CL_LOG_SEV_ERROR, 10, CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED,
           "Cannot get slot information for slot [%d], Error [0x%x]", nodeList[i], rc);
      }
    }

  curLen += snprintf(buf+curLen, bufLen-curLen, "]");

  
  DbgLog("NumNodes=%d, Slot List=%s", numNodes,buf);
  PyObject* ret = PyRun_String(buf,Py_eval_input,emptyDict,emptyDict);
  return ret;
}