ClRcT clCkptEntryDelete(ClCachedCkptSvcInfoT *serviceInfo, const SaNameT *sectionName)
{
    ClRcT rc = CL_OK;

    SaCkptSectionIdT ckptSectionId = {        /* Section id for checkpoints   */
        sectionName->length,
        (SaUint8T *) sectionName->value
    };
    ClInt32T tries = 0;
    ClTimerTimeOutT delay = { 0, 500 };

    /* Delete section from the ckpt */
    if (clCkptEntryExist(serviceInfo, sectionName) == CL_TRUE)
    {
retry:
        rc = clCkptSectionDelete(serviceInfo->ckptHandle, (ClCkptSectionIdT *)&ckptSectionId);
        if (CL_ERR_TRY_AGAIN == CL_GET_ERROR_CODE(rc))
        {
            if ((++tries < 5) && (clOsalTaskDelay(delay) == CL_OK))
            {
                goto retry;
            }
        }
    }

    return rc;
}
static ClRcT nodeCacheMemberGetExtended(ClIocNodeAddressT node, ClNodeCacheMemberT *pMember,ClUint32T retries, ClUint32T msecDelay, ClBoolT compat)
{
    ClRcT rc = CL_OK;
    ClUint32T i = 0;
    ClTimerTimeOutT delay;
    delay.tsSec = 0;
    delay.tsMilliSec = msecDelay;
    
    clOsalSemLock(gClNodeCacheSem);
    while(i++ <= retries)
    {
        rc = nodeCacheMemberGetFast(node, pMember, compat);
        if(CL_GET_ERROR_CODE(rc) == CL_ERR_NOT_EXIST)
        {
            clOsalSemUnlock(gClNodeCacheSem);
            if(i > retries)
                goto out;
            clOsalTaskDelay(delay);
            delay.tsMilliSec += msecDelay; /* Back off the time as retries increase */
            clOsalSemLock(gClNodeCacheSem);
        }
        else break;
    }
    clOsalSemUnlock(gClNodeCacheSem);

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

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

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

    openFlags = CL_CKPT_CHECKPOINT_CREATE | CL_CKPT_CHECKPOINT_WRITE | CL_CKPT_CHECKPOINT_READ;

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

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}    
int usleep(int usec)
{
    ClTimerTimeOutT delay = {0};
    delay.tsMilliSec = usec/1000;
    if(clOsalTaskDelay(delay) != CL_OK)
        sleep(1);
    return 0;
}
ClRcT clCkptEntryUpdate(ClCachedCkptSvcInfoT *serviceInfo,
                        const ClCachedCkptDataT *sectionData)
{
    ClRcT rc;

    SaCkptSectionIdT ckptSectionId = {        /* Section id for checkpoints   */
        sectionData->sectionName.length,
        (SaUint8T *) sectionData->sectionName.value
    };

    ClUint8T *ckptedData, *copyData;
    ClSizeT ckptedDataSize = sectionData->dataSize + sizeof(ClIocAddressT);
    ClUint32T network_byte_order;
    ClInt32T tries = 0;
    ClTimerTimeOutT delay = { 0,  500 };

    ckptedData = (ClUint8T *) clHeapAllocate(ckptedDataSize);
    if(ckptedData == NULL)
    {
        rc = CL_ERR_NO_MEMORY;
        clLogError("CCK", "UPD", "Failed to allocate memory. error code [0x%x].", rc);
        goto out1;
    }

    /* Marshall section data*/
    copyData = ckptedData;
    network_byte_order = (ClUint32T) htonl((ClUint32T)sectionData->sectionAddress.iocPhyAddress.nodeAddress);
    memcpy(copyData, &network_byte_order, sizeof(ClUint32T));
    copyData = copyData + sizeof(ClUint32T);
    network_byte_order = (ClUint32T) htonl((ClUint32T)sectionData->sectionAddress.iocPhyAddress.portId);
    memcpy(copyData, &network_byte_order, sizeof(ClUint32T));
    copyData = copyData + sizeof(ClUint32T);
    memcpy(copyData, sectionData->data, sectionData->dataSize);

    /* Try to update the section */
retry:
    rc = clCkptSectionOverwrite(serviceInfo->ckptHandle,         /* Checkpoint handle  */
                                (ClCkptSectionIdT *)&ckptSectionId,         /* Section ID         */
                                ckptedData,             /* Initial data       */
                                ckptedDataSize);        /* Size of data       */
    if (CL_ERR_TRY_AGAIN == CL_GET_ERROR_CODE(rc))
    {
        if ((++tries < 5) && (clOsalTaskDelay(delay) == CL_OK))
        {
            goto retry;
        }
    }
    if (rc != CL_OK)
    {
        clLogError("CCK", "UPD", "CkptSectionUpdate failed with rc [0x%x].",rc);
        goto out2;
    }

out2:
    clHeapFree(ckptedData);
out1:
    return rc;
}
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;

}
static void testEvtMainLoop()
{
    /* Main loop: Keep printing and publishing unless we are suspended */
    int i=0;
    SaAisErrorT  saRc = SA_AIS_OK;
    for(int i=0; i< LOOP_COUNT; i++)
    {
        //appPublishEvent();   
        ClEventIdT      eventId         = 0;
        printf("Publishing Event\n");  
        ClCharT buff[40] = {0};
        memset(buff,0,sizeof(buff));
        sprintf(buff,"Event from external application_%d",i);
        saRc = saEvtEventPublish(gTestInfo.eventHandle, (const void*)buff, strlen(buff), &eventId);   
        ClTimerTimeOutT delay;
        delay.tsSec = 0;
        delay.tsMilliSec = 200;
        clOsalTaskDelay(delay);
    }
}    
void nodeCacheWait(void)
{
    unsigned int done = CL_FALSE;
    ClNodeCacheMemberT nodes[64];
    ClUint32T numNodes;
    ClIocNodeAddressT leader;
    ClTimerTimeOutT delay;
    delay.tsSec = 0;
    delay.tsMilliSec = 700;  

    // I need to wait for one SC to tell us about itself for registration and one payload to come up to receive my logs
    // This is specific to this demo.  Your application may need to wait for different nodes...
    while(done != 3)  
    {
        numNodes = 64;

        printf("Nodes in the cluster:\n");
        clNodeCacheViewGet(nodes,&numNodes);
        for (int i = 0; i<numNodes;i++)
        {
            printf("%30s: Address: %d,  Version: %x  Capability: %s\n",nodes[i].name,nodes[i].address,nodes[i].version,Cap2Str(nodes[i].capability));
            if (CL_NODE_CACHE_LEADER_CAPABILITY(nodes[i].capability)) done |=1;
            if ((nodes[i].address != LOCAL_ADDRESS) && (CL_NODE_CACHE_PL_CAPABILITY(nodes[i].capability))) done |=2;
        }
        
#if 0  // GAS why is the node cache leader not being updated?
        ClRcT rc = clNodeCacheLeaderGet(&leader);
        if (rc == CL_OK)
        {
            done = CL_TRUE;            
        }
#endif        
        
        if (done != 3) clOsalTaskDelay(delay);        
    }
    
    
}
int main(int argc, char **argv)
{

    int ioc_address_local = LOCAL_ADDRESS;
    ClRcT rc = CL_OK;
    rc = clExtInitialize(ioc_address_local);
    if (rc != CL_OK)
    {
        printf("Error: failed to Initialize SAFplus libraries\n");
        exit(1);
    }

    nodeCacheWait();

    // Demonstrate logging */
    printf("\n\nOpen a global log stream and write several records to active PY node\n");        
    if ((rc=logInitialize()) == CL_OK)
    {
        printf("log Initialized\n"); 
        logWrite(CL_LOG_SEV_NOTICE,"This is a test of an external app doing logging");
        for(int i=0;i<100;i++)
        {
            ClTimerTimeOutT delay;
            delay.tsSec = 0;
            delay.tsMilliSec = 10; 
            logWrite(CL_LOG_SEV_NOTICE,"external app log %d", i);
            clOsalTaskDelay(delay);            
        }            
    }
    else
    {
        printf("Unable to open log.  Error 0x%x\n",rc);
        return rc;
    }



    //  Open a subscribe event channel and start receiving events.
    printf("\n\nOpen an Event subscription\n");        
    const SaEvtCallbacksT evtCallbacks =
    {
        NULL,
        appEventCallback
    };
    SaVersionT  evtVersion = CL_EVENT_VERSION;
    rc = saEvtInitialize(&evtHandle, &evtCallbacks, &evtVersion);
    if (rc != SA_AIS_OK)
    {
        printf("Failed to init event mechanism [0x%x]\n",rc);
        return rc;
    }

    saNameSet(&evtChannelName,EVENT_CHANNEL_NAME);
    rc = saEvtChannelOpen(evtHandle,&evtChannelName, (SA_EVT_CHANNEL_SUBSCRIBER | SA_EVT_CHANNEL_CREATE), (SaTimeT)SA_TIME_END, &evtChannelHandle);
    if (rc != SA_AIS_OK)
    {
        printf("Failure opening event channel[0x%x] at %ld\n", rc, time(0L));
        goto errorexit;
    }
    rc = saEvtEventSubscribe(evtChannelHandle, NULL, 1);
    if (rc != SA_AIS_OK)
    {
        printf("Failed to subscribe to event channel [0x%x]\n", rc);
        goto errorexit;
    }
    //open a global log stream and write several records
        
    printf("Open a publisher event channel\n");        
    // open a publisher event channel and 
    openPublisherChannel();
    printf("Start publishing events.\nThe PY component on active PY node subscribes to these events and logs them so you can verify receipt by looking in the clock.log.latest and app.lates  on node active PY node .\n");        
    testEvtMainLoop();
    printf("Unsubscribe event chanel.............................\n");        
    rc = saEvtEventUnsubscribe(evtChannelHandle,1);
    if (rc != SA_AIS_OK) 
        printf("Channel unsubscribe result: %d\n", rc);
    printf("Close subscribe event chanel.............................\n");        
    rc = saEvtChannelClose(evtChannelHandle);
    if (rc != SA_AIS_OK) 
        printf("Channel close result: %d\n", rc);
    printf("Close publish event channel.............................\n");        
    rc = saEvtChannelClose(evtChannelHandlePublic);
    if (rc != SA_AIS_OK) 
        printf("Channel close result: %d\n", rc);
    // never inited: printf("Finalize publish event handle.............................\n");        
    //    saEvtFinalize(gTestInfo.evtInitHandle);
    printf("Finalize xubscribe event handle.............................\n");        
    saEvtFinalize(evtHandle);
    openPublisherChannel();
    testEvtMainLoop();
    printf("Close publish event channel.............................\n");        
    rc = saEvtChannelClose(evtChannelHandlePublic);
    if (rc != SA_AIS_OK) 
        printf("Channel close result: %d\n", rc);
    // never inited printf("Finalize publish event handle.............................\n");        
    //   saEvtFinalize(gTestInfo.evtInitHandle);
    
    return 0;
errorexit:
    printf ("Initialization error [0x%x]\n",rc);
}
/*
 * The recovery thread for entity threshold.
 */
static ClPtrT clAmsEntityTriggerRecoveryThread(ClPtrT pArg)
{
#define MAX_RECOVERY_MASK (0x3)

    static ClInt32T numRecovery = 0;
    ClTimerTimeOutT timeout = { 0,  0 };
    ClTimerTimeOutT delay =   { 0,  500 };

    static ClAmsListHeadT recoveryList = { 0, CL_LIST_HEAD_INITIALIZER(recoveryList.list) };
    clOsalMutexLock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex);
    while(gClAmsEntityTriggerRecoveryCtrl.running == CL_TRUE)
    {
        ClListHeadT *pNext = NULL;

        while(!gClAmsEntityTriggerRecoveryCtrl.list.numElements)
        {
            numRecovery = 0;
            clOsalCondWait(&gClAmsEntityTriggerRecoveryCtrl.list.cond,
                           &gClAmsEntityTriggerRecoveryCtrl.list.mutex,
                           timeout);
            if(gClAmsEntityTriggerRecoveryCtrl.running == CL_FALSE)
                goto out_drain;
        }
        /*
         * We are here when the recovery list isn't empty.
         * We shove the existing recovery batch into the temp list 
         * and reset the main list to release the lock and go lockless.
         */
        recoveryList.numElements = gClAmsEntityTriggerRecoveryCtrl.list.numElements;
        gClAmsEntityTriggerRecoveryCtrl.list.numElements = 0;
        pNext = gClAmsEntityTriggerRecoveryCtrl.list.list.pNext;
        clListDelInit(&gClAmsEntityTriggerRecoveryCtrl.list.list);
        clListAddTail(pNext, &recoveryList.list);
        clOsalMutexUnlock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex);
        
        while(gClAmsEntityTriggerRecoveryCtrl.running == CL_TRUE
              &&
              recoveryList.numElements > 0
              &&
              !CL_LIST_HEAD_EMPTY(&recoveryList.list))
        {
            ClListHeadT *pFirst = recoveryList.list.pNext;
            ClAmsEntityTriggerT *pEntityTrigger = CL_LIST_ENTRY(pFirst, ClAmsEntityTriggerT, list);
            
            /*
             * Take a break incase you have done some recoveries
             */
            if(numRecovery && !(numRecovery & MAX_RECOVERY_MASK))
            {
                clOsalTaskDelay(delay);
            }
            ++numRecovery;
            numRecovery &= 0xffff;
            /*
             * Unlink the entry from the recovery list.
             */
            clListDel(pFirst);
            clAmsEntityTriggerRecovery(pEntityTrigger);
            clHeapFree(pEntityTrigger);
            --recoveryList.numElements;
        }

        clOsalMutexLock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex);

        if(gClAmsEntityTriggerRecoveryCtrl.running == CL_FALSE)
        {
            goto out_drain;
        }

    }

    /*
     * Drain the entries holding the lock.
     */
    out_drain:
    clAmsListHeadDelete(&recoveryList);
    clAmsListHeadDelete(&gClAmsEntityTriggerRecoveryCtrl.list);
    clOsalMutexUnlock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex);
    
    return NULL;
}
ClRcT
clLogMasterCkptGet(void)
{
    ClRcT                                rc              = CL_OK;
    ClCkptCheckpointCreationAttributesT  ckptAttr        = {0};
    ClCkptOpenFlagsT                     openFlags       = 0;
    ClLogSvrCommonEoDataT                *pCommonEoEntry = NULL;
    ClLogMasterEoDataT                   *pMasterEoEntry = NULL;
    ClTimeT                              timeout         = 5000L;
    ClIocNodeAddressT                    localAddr = clIocLocalAddressGet();
    ClInt32T tries = 0;
    static ClTimerTimeOutT delay = {  0,  100 };

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogMasterEoEntryGet(&pMasterEoEntry, &pCommonEoEntry);
    if( CL_OK != rc )
    {
        return rc;
    }
    ckptAttr.creationFlags     = CL_CKPT_CHECKPOINT_COLLOCATED | CL_CKPT_ALL_OPEN_ARE_REPLICAS;
    ckptAttr.checkpointSize    = pMasterEoEntry->maxFiles * pMasterEoEntry->sectionSize;
    ckptAttr.retentionDuration = CL_LOGMASTER_CKPT_RETENTION_DURATION;
    ckptAttr.maxSections       = pMasterEoEntry->maxFiles;
    ckptAttr.maxSectionSize    = pMasterEoEntry->sectionSize;
    ckptAttr.maxSectionIdSize  = pMasterEoEntry->sectionIdSize;

    //   openFlags = CL_CKPT_CHECKPOINT_WRITE | CL_CKPT_CHECKPOINT_READ;
    //rc = clCkptCheckpointOpen(pCommonEoEntry->hSvrCkpt, &gLogMasterCkptName,
    //                          NULL, openFlags, 0,  &pMasterEoEntry->hCkpt);
    //    if( CL_ERR_NOT_EXIST == CL_GET_ERROR_CODE(rc) )
    //  {
    openFlags = CL_CKPT_CHECKPOINT_CREATE | CL_CKPT_CHECKPOINT_WRITE | CL_CKPT_CHECKPOINT_READ;

reopen:
    rc = clCkptCheckpointOpen(pCommonEoEntry->hSvrCkpt, &gLogMasterCkptName, &ckptAttr,openFlags, timeout, &pMasterEoEntry->hCkpt);
    if( (CL_OK != rc) && (CL_ERR_ALREADY_EXIST != rc) )
    {
        /*
         * 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 && pCommonEoEntry->masterAddr == localAddr)
        {
            if(tries++ < 1)
            {
                clLogNotice("CKP", "GET", "No replica for log checkpoint."
                            "Deleting ckpt [%.*s] and retrying the ckpt open",
                            gLogMasterCkptName.length, gLogMasterCkptName.value);
                clCkptCheckpointDelete(pCommonEoEntry->hSvrCkpt, &gLogMasterCkptName);
                clOsalTaskDelay(delay);
                goto reopen;
            }
        }
        CL_LOG_DEBUG_ERROR(("clCkptCheckpointOpen(): rc[0x%x]", rc));
        return rc;
    }
    //     if( CL_ERR_ALREADY_EXIST != CL_GET_ERROR_CODE(rc))
    {   /* Create default section */
    }
    //    return rc;
    //    }

    if(pCommonEoEntry->masterAddr == localAddr)
    {
        rc = clLogMasterStateRecover(pCommonEoEntry, pMasterEoEntry, CL_FALSE);
        if( CL_OK != rc )
        {
            CL_LOG_CLEANUP(clCkptCheckpointClose(pMasterEoEntry->hCkpt),
                           CL_OK);
        }
    } /* else you are standby so just keep the ckpt opened */

    CL_LOG_DEBUG_TRACE(("Exit: rc[0x%x]", rc));
    return rc;
}
static void*
tsTimerTask (void* pArgument)
{
    ClRcT returnCode = CL_ERR_INVALID_HANDLE;
    ClTimerTimeOutT sleepTime = {0,0};
    ClTimerTypeT type ;
    TsTimer_t* pUserTimer = NULL;

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

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

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

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

        returnCode = clOsalMutexLock (gActiveTimerQueue.timerMutex);

        if (returnCode != CL_OK) {
            continue;
        }

        skewTicksTemp = skew/(iteration+1);

        skew += skewTicksTemp % CL_TIMER_TICK_USECS;

        skewTicksTemp/=CL_TIMER_TICK_USECS;

        skew += diff % CL_TIMER_TICK_USECS;

        skewTicks += skewTicksTemp;

        ++iteration;

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

        currentTime += skewTicks;

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

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

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

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

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

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

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

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

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

                if (type == CL_TIMER_REPETITIVE) {

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

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

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

                }

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

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

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

        tsTimerReEnqueue();

        returnCode = clOsalMutexUnlock (gActiveTimerQueue.timerMutex);

    } /* end of while (1) */

    return (NULL);
}
/**
 * CREATE: This function creates a section in the checkpoint.
 */
ClRcT clCachedCkptSectionCreate(ClCachedCkptSvcInfoT *serviceInfo,
                                const ClCachedCkptDataT *sectionData)
{
    ClRcT rc = CL_OK;

    SaCkptSectionIdT ckptSectionId = {        /* Section id for checkpoints   */
        sectionData->sectionName.length,
        (SaUint8T *) sectionData->sectionName.value
    };

    SaCkptSectionCreationAttributesT sectionAttrs= {
        &ckptSectionId,
        CL_TIME_END      /* Setting an infinite time  */
    };

    ClUint8T *ckptedData, *copyData;
    ClSizeT ckptedDataSize = sectionData->dataSize + sizeof(ClIocAddressT);
    ClUint32T network_byte_order;
    ClInt32T tries = 0;
    ClTimerTimeOutT delay = { 0, 500 };

    ckptedData = (ClUint8T *) clHeapAllocate(ckptedDataSize);
    if(ckptedData == NULL)
    {
        rc = CL_ERR_NO_MEMORY;
        clLogError("CCK", "ADD", "Failed to allocate memory. error code [0x%x].", rc);
        goto out1;
    }

    /* Marshall section data */
    copyData = ckptedData;
    network_byte_order = (ClUint32T) htonl((ClUint32T)sectionData->sectionAddress.iocPhyAddress.nodeAddress);
    memcpy(copyData, &network_byte_order, sizeof(ClUint32T));
    copyData = copyData + sizeof(ClUint32T);
    network_byte_order = (ClUint32T) htonl((ClUint32T)sectionData->sectionAddress.iocPhyAddress.portId);
    memcpy(copyData, &network_byte_order, sizeof(ClUint32T));
    copyData = copyData + sizeof(ClUint32T);
    memcpy(copyData, sectionData->data, sectionData->dataSize);

    /* Try to create a section */
retry:
    rc = clCkptSectionCreate(serviceInfo->ckptHandle,    /* Checkpoint handle  */
                             (ClCkptSectionCreationAttributesT *)&sectionAttrs,       /* Section attributes */
                             ckptedData,          /* Initial data       */
                             ckptedDataSize);     /* Size of data       */
    if (CL_ERR_TRY_AGAIN == CL_GET_ERROR_CODE(rc))
    {
        if ((++tries < 5) && (clOsalTaskDelay(delay) == CL_OK))
        {
            goto retry;
        }
    }
    if ((CL_GET_ERROR_CODE(rc) == CL_ERR_ALREADY_EXIST))
    {
        rc = CL_ERR_ALREADY_EXIST;
        goto out2;
    }
    else if (rc != CL_OK)
    {
        clLogError("CCK", "ADD", "CkptSectionCreate failed with rc [0x%x].",rc);
        goto out2;
    }

    /* Add the section data to cache */
    rc = clCacheEntryAdd(serviceInfo, sectionData);

    if (rc != CL_OK)
    {
        clLogError("CCK", "ADD", "CacheEntryAdd failed with rc [0x%x].",rc);
        goto out3;
    }

    goto out2;

out3:
    saCkptSectionDelete(serviceInfo->ckptHandle, &ckptSectionId);
out2:
    clHeapFree(ckptedData);
out1:
    return rc;
}
/**
 * INIT: The below function initializes the checkpoint service client
 * and opens a checkpoint to store data.
 */
ClRcT clCachedCkptInitialize(ClCachedCkptSvcInfoT *serviceInfo,
                             const SaNameT *ckptName,
                             const SaCkptCheckpointCreationAttributesT *ckptAttributes,
                             SaCkptCheckpointOpenFlagsT openFlags,
                             ClUint32T cachSize)
{
    ClRcT			rc = CL_OK;
    SaCkptHandleT		ckptSvcHandle = 0;
    SaCkptCheckpointHandleT	ckptHandle = 0;
    SaVersionT			ckptVersion = {'B', 0x01, 0x01};
    ClTimerTimeOutT		delay = { 0, 500};
    ClInt32T			tries = 0;
    ClCharT cacheName[CL_MAX_NAME_LENGTH];
    ClUint32T                   shmSize = clCachedCkptShmSizeGet(cachSize);
    ClUint32T  *numberOfSections;
    ClUint32T  *sizeOfCache;

    serviceInfo->cachSize = shmSize;

    if(serviceInfo->ckptHandle != CL_HANDLE_INVALID_VALUE)
    {
        clLogWarning("CCK", "INI", "Checkpoint already initialized. Skipping initialization");
        return CL_ERR_ALREADY_EXIST;
    }

    snprintf(cacheName, sizeof(cacheName), "%s_%d", ckptName->value, gIocLocalBladeAddress);

    rc = clOsalSemCreate((ClUint8T*)cacheName, 1, &serviceInfo->cacheSem);
    if(rc != CL_OK)
    {
        ClOsalSemIdT semId = 0;

        if(clOsalSemIdGet((ClUint8T*)cacheName, &semId) != CL_OK)
        {
            clLogError("CCK", "INI", "cache semaphore creation error while fetching semaphore id");
            goto out1;
        }

        if(clOsalSemDelete(semId) != CL_OK)
        {
            clLogError("CCK", "INI", "cache semaphore creation error while deleting old semaphore id");
            goto out1;
        }

        rc = clOsalSemCreate((ClUint8T*)cacheName, 1, &serviceInfo->cacheSem);
    }

    if(ckptAttributes || openFlags)
    {
        if(serviceInfo->ckptSvcHandle == CL_HANDLE_INVALID_VALUE)
        {
            /* Initialize checkpoint service instance */
            do
            {
                rc = clCkptInitialize(&ckptSvcHandle, NULL, (ClVersionT *)&ckptVersion);
            } while(rc != CL_OK && tries++ < 100 && clOsalTaskDelay(delay) == CL_OK);

            if(rc != CL_OK)
            {
                clLogError("CCK", "INI", "Failed to initialize checkpoint service instance. error code [0x%x].", rc);
                goto out2;
            }

            serviceInfo->ckptSvcHandle = ckptSvcHandle;
        }

        /* Create the checkpoint for read and write. */
        do
        {
            rc = clCkptCheckpointOpen(serviceInfo->ckptSvcHandle,
                                      (SaNameT *)ckptName,
                                      (ClCkptCheckpointCreationAttributesT *)ckptAttributes,
                                      openFlags,
                                      0L,
                                      &ckptHandle);
        } while(rc != CL_OK && tries++ < 100 && clOsalTaskDelay(delay) == CL_OK);

        if(rc != CL_OK)
        {
            clLogError("CCK", "INI", "Failed to open checkpoint. error code [0x%x].", rc);
            goto out3;
        }

        serviceInfo->ckptHandle = ckptHandle;
    }

    /* Create shm */

    rc = clOsalShmOpen((ClCharT *)cacheName, CL_CACHED_CKPT_SHM_EXCL_CREATE_FLAGS,
                       CL_CACHED_CKPT_SHM_MODE, &serviceInfo->fd);
    if( CL_ERR_ALREADY_EXIST == CL_GET_ERROR_CODE(rc) )
    {
        rc = clOsalShmOpen((ClCharT *)cacheName, CL_CACHED_CKPT_SHM_OPEN_FLAGS,
                           CL_CACHED_CKPT_SHM_MODE, &serviceInfo->fd);
        if( CL_OK != rc )
        {
            clLogError("CCK", "INI", "Could not open shared memory.");
            goto out4;
        }
    }

    rc = clOsalFtruncate(serviceInfo->fd, shmSize);
    if( CL_OK != rc )
    {
        clLogError("CCK", "INI", "clOsalFtruncate(): error code [0x%x].", rc);
        goto out5;
    }

    rc = clOsalMmap(0, shmSize, CL_CACHED_CKPT_MMAP_PROT_FLAGS,
                    CL_CACHED_CKPT_MMAP_FLAGS, serviceInfo->fd, 0, (void **) &serviceInfo->cache);
    if( CL_OK != rc )
    {
        clLogError("CCK", "INI", "clOsalMmap(): error code [0x%x].", rc);
        goto out5;
    }

    numberOfSections = (ClUint32T *)(serviceInfo->cache);
    sizeOfCache = (ClUint32T *)(numberOfSections + 1);
    *numberOfSections = 0;
    *sizeOfCache = 0;

    clOsalMsync(serviceInfo->cache, shmSize, MS_SYNC);

    goto out1;

out5:
    clOsalShmClose(&serviceInfo->fd);
out4:
    if(serviceInfo->ckptHandle)
    {
        clCkptCheckpointClose(serviceInfo->ckptHandle);
        serviceInfo->ckptHandle =  CL_HANDLE_INVALID_VALUE;
    }
out3:
    if(serviceInfo->ckptSvcHandle)
    {
        clCkptFinalize(serviceInfo->ckptSvcHandle);
        serviceInfo->ckptSvcHandle =  CL_HANDLE_INVALID_VALUE;
    }
out2:
    clOsalSemDelete(serviceInfo->cacheSem);
out1:
    return rc;
}