static void safTerminate(SaInvocationT invocation, const SaNameT *compName)
{
    SaAisErrorT rc = SA_AIS_OK;
    if(gClMsgInit)
    {
        ClBoolT lockStatus = CL_TRUE;
        ClTimerTimeOutT timeout = {.tsSec = 0, .tsMilliSec = 0};
        clOsalMutexLock(&gClMsgFinalizeLock);
        while(gClMsgSvcRefCnt > 0)
        {
            clOsalCondWait(&gClMsgFinalizeCond, &gClMsgFinalizeLock, timeout);
        }
        safMsgFinalize(&lockStatus);
        if(lockStatus)
        {
            clOsalMutexUnlock(&gClMsgFinalizeLock);
        }
    }
    rc = saAmfComponentUnregister(amfHandle, compName, NULL);
    clCpmClientFinalize(amfHandle);
    //clCpmResponse(cpmHandle, invocation, CL_OK);
    saAmfResponse(amfHandle, invocation, SA_AIS_OK);
    
    return;
}


static void clMsgRegisterWithCpm(void)
{
    SaAisErrorT rc = SA_AIS_OK;
    SaAmfCallbacksT    callbacks = {0};
    SaVersionT  version = {0};

    version.releaseCode = 'B';
    version.majorVersion = 0x01;
    version.minorVersion = 0x01;
                                                                                                                             
    callbacks.saAmfHealthcheckCallback = NULL;
    callbacks.saAmfComponentTerminateCallback = safTerminate;
    callbacks.saAmfCSISetCallback = NULL;
    callbacks.saAmfCSIRemoveCallback = NULL;
    callbacks.saAmfProtectionGroupTrackCallback = NULL;
    

    rc = saAmfInitialize(&amfHandle, &callbacks, &version);
    if( rc != SA_AIS_OK)
    {
         clLogError("MSG", "INI", "saAmfInitialize failed with  error code [0x%x].", rc);
         return ;
    }


    rc = saAmfComponentNameGet(amfHandle, &appName);

    rc = saAmfComponentRegister(amfHandle, &appName, NULL);
}
void clPyGlueStart(int block)
{
    ClRcT rc;
    clRunPython("eoApp.Start()");

    if (block)
      {
      ClTimerTimeOutT forever={0};
      rc = clOsalMutexLock(&pyMutex);
      CL_ASSERT(rc==CL_OK); 
      clOsalCondWait (&event,&pyMutex,forever);
      }
}
ClRcT clMsgFinalizeBlocker(void)
{
    ClRcT rc = CL_OK;
    SaTimeT timeout = (SaTimeT)(CL_MSG_FIN_BLOCK_TIME * 1000000000LL);
    ClTimerTimeOutT tempTime = {0};

    CL_OSAL_MUTEX_LOCK(&gFinBlockMutex);

    if(gMsgMoveStatus == MSG_MOVE_DONE)
        goto out;

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

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

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

    gMsgMoveStatus = MSG_MOVE_DONE;

    goto out;

    error_out:
    out:
    CL_OSAL_MUTEX_UNLOCK(&gFinBlockMutex);
     
    return rc;
}
Example #4
0
static void safTerminate(SaInvocationT invocation, const SaNameT *compName)
{
    if(gClMsgInit)
    {
        ClBoolT lockStatus = CL_TRUE;
        ClTimerTimeOutT timeout = { 0, 0};
        clOsalMutexLock(&gClMsgFinalizeLock);
        while(gClMsgSvcRefCnt > 0)
        {
            clOsalCondWait(&gClMsgFinalizeCond, &gClMsgFinalizeLock, timeout);
        }
        safMsgFinalize(&lockStatus);
        if(lockStatus)
        {
            clOsalMutexUnlock(&gClMsgFinalizeLock);
        }
    }
    IGNORE_RETURN(saAmfComponentUnregister(amfHandle, compName, NULL));
    clCpmClientFinalize(amfHandle);
    //clCpmResponse(cpmHandle, invocation, CL_OK);
    saAmfResponse(amfHandle, invocation, SA_AIS_OK);
    
    return;
}
/*
 * To all the application we need to pass 1. Component Name 2. Ioc Address So
 * as of now we have decided that these will be passed as environment variable 
 */
ClRcT clEoInitialize(ClInt32T argc, ClCharT *argv[])
{
    ClRcT rc = CL_OK;

    ClEoExecutionObjT *pThis = NULL;

    ClTimerTimeOutT waitForExit = { 0,  0 };

    clEoProgName = argv[0];
   
    clLog(CL_LOG_SEV_INFO, CL_LOG_AREA, CL_LOG_CTXT_INI, "Process [%s] started. PID [%d]", clEoProgName, (int)getpid());
    
    clEoStaticQueueInit();

    clASPInitialize();
    
    rc = clEoMyEoObjectGet(&pThis);
    if(rc != CL_OK)
    {
        clLog(CL_LOG_SEV_CRITICAL, CL_LOG_AREA, CL_LOG_CTXT_INI, "Exiting : EO my object get failed. error [%x0x].\n", rc);
        exit(1);
    }
        
    /*
     * This should keep track of blocking APP initialize.
     */

    clEoRefInc(pThis);

    /* Call the application's initialize function */
    rc = eoConfig.clEoCreateCallout(argc, argv);
    if (rc != CL_OK)
    {
        clLog(CL_LOG_SEV_CRITICAL, CL_LOG_AREA, CL_LOG_CTXT_INI, "Application initialization failed, error [0x%x]", rc);
        exit(1);
    }

    if(eoConfig.appType == CL_EO_USE_THREAD_FOR_APP)
    {
        clEoUnblock(pThis);
    }

    /*
     * We block on the exit path waiting for a terminate.
     */
    clOsalMutexLock(&pThis->eoMutex);

    while (pThis->refCnt > 0)
    {
        clOsalCondWait(&pThis->eoCond, &pThis->eoMutex, waitForExit);
    }
    clOsalMutexUnlock(&pThis->eoMutex);

    clEoTearDown();
    clLog(CL_LOG_SEV_INFO, CL_LOG_AREA, CL_LOG_CTXT_FIN, "Process [%s] exited normally", argv[0]);

    if (clDbgNoKillComponents)
    {
      clLog(CL_LOG_SEV_CRITICAL, CL_LOG_AREA, CL_LOG_CTXT_FIN,
            "In debug mode and 'clDbgNoKillComponents' is set, so this process will pause, not exit.");
      while(1) sleep(10000); /* Using sleep here instead of Osal because Osal is likely shutdown */
    }
    
    return CL_OK;
}
/*
 * 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 clCkptSvrInitialize(void)
{
    ClRcT             rc         = CL_OK;
    /* Variable related ckptDataBackup feature thats not supported
       ClUint8T          ckptRead   = 0;
    */
    ClTimerTimeOutT   timeOut    = {0}; 
    ClIocNodeAddressT deputy = 0;
    ClIocNodeAddressT master = 0;
    ClBoolT           addressUpdate = CL_FALSE;
    SaNameT           appName    = {0};   
 
    /*
     * Allocate the memory for server control block.
     */
    rc = ckptSvrCbAlloc(&gCkptSvr);
    CKPT_ERR_CHECK(CL_CKPT_SVR,CL_LOG_SEV_ERROR, 
                   ("Checkpoint service CB create failed rc[0x %x]\n", rc), rc); 

    /*
     * Mark server as not ready.
     */
    gCkptSvr->serverUp        = CL_FALSE;
    gCkptSvr->condVarWaiting  = CL_TRUE;    

    /*
     * Create condition variable that indicate the receipt
     * of master and deputy ckpt addresses from gms.
     */
    clOsalCondCreate(&gCkptSvr->condVar);
    clOsalMutexCreate(&gCkptSvr->mutexVar);
    
    gCkptSvr->masterInfo.masterAddr = CL_CKPT_UNINIT_ADDR;
    gCkptSvr->masterInfo.deputyAddr = CL_CKPT_UNINIT_ADDR;
    gCkptSvr->masterInfo.compId     = CL_CKPT_UNINIT_VALUE; 
    gCkptSvr->masterInfo.clientHdlCount = 0;
    gCkptSvr->masterInfo.masterHdlCount = 0; 

    /*
     * Initialize gms to get the master and deputy addresses.
     */
    clOsalMutexLock(&gCkptSvr->ckptClusterSem);
    rc = clCkptMasterAddressesSet();
    master = gCkptSvr->masterInfo.masterAddr;
    deputy = gCkptSvr->masterInfo.deputyAddr;
    clOsalMutexUnlock(&gCkptSvr->ckptClusterSem);

    rc = clEoMyEoObjectGet(&gCkptSvr->eoHdl);
    rc = clEoMyEoIocPortGet(&gCkptSvr->eoPort);
   
    /*
     * Install the ckpt native table.
     */
    rc = clCkptEoClientInstall();
    CL_ASSERT(rc == CL_OK);
    
    rc = clCkptEoClientTableRegister(CL_IOC_CKPT_PORT);
    CL_ASSERT(rc == CL_OK);

    /*
     * Initialize the event client library.
     */
    ckptEventSvcInitialize();
    
    /* 
     * Initialize ckpt lib for persistent memory.
     * Obtain ckptRead flag that will tell whether ckpt server needs to 
     * read data from persistent memory or not.
     */

    /*
      Feature not yet supported see bug 6017 -- Do not forget to uncomment ckptDataBackupFinalize
      rc = ckptDataBackupInitialize(&ckptRead);
    */

    if(rc != CL_OK)
    {
        clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_WARNING, NULL,
                   CL_LOG_MESSAGE_2_LIBRARY_INIT_FAILED, "ckpt", rc);
    }

    if( gCkptSvr->localAddr == master )
    {
        /*
         * The node coming up is master. If deputy exists, syncup with deputy
         * else syncup with persistant memory (if existing).
         */
        rc = clCpmComponentNameGet(gCkptSvr->amfHdl, &appName);
        if(clCpmIsCompRestarted(appName))
        {
            if((deputy != CL_CKPT_UNINIT_ADDR) && ( (ClInt32T) deputy != -1))
            {
                rc = ckptMasterDatabaseSyncup(deputy);
                /*
                 * If deputy server is not reachable then pull info from the 
                 * persistent memory.
                 */
                if(CL_RMD_TIMEOUT_UNREACHABLE_CHECK(rc))
                {
                    clLogNotice(CL_CKPT_AREA_ACTIVE, "DBS", 
                                "Database Syncup with ckpt master failed with RMD timeout error. rc 0x%x",rc);
                    /* This is dead code as the feature is not supported
                       if(ckptRead == 1)
                       {
                       rc = ckptPersistentMemoryRead();
                       }
                    */
                }
            }
        }
        /* This is dead code as the feature is not supported
           else
           {
           if(ckptRead == 1)
           {
           rc = ckptPersistentMemoryRead();
           }
           }
        */
    }
    
    /*TODO:This check is only for seleting the deputy or for what */
    clOsalMutexLock(gCkptSvr->mutexVar);    
    if( (clIocLocalAddressGet() != master) &&
        (gCkptSvr->condVarWaiting == CL_TRUE)     )
    {
        /*
         * Ensure that the node gets the master and deputy addresses before
         * proceeding further.
         */
        timeOut.tsSec            = 5;
        timeOut.tsMilliSec       = 0;
        clOsalCondWait(gCkptSvr->condVar, gCkptSvr->mutexVar, timeOut);
        gCkptSvr->condVarWaiting = CL_FALSE;
        addressUpdate = CL_TRUE;
    }
    clOsalMutexUnlock(gCkptSvr->mutexVar);    

    /*  
     * We double check again incase we had waited for the gms cluster track.
     * but with the right lock sequence below instead of shoving it in the
     * condwait above.
     */
    if(addressUpdate == CL_TRUE)
    {
        clOsalMutexLock(&gCkptSvr->ckptClusterSem);
        master = gCkptSvr->masterInfo.masterAddr;
        deputy = gCkptSvr->masterInfo.deputyAddr;
        clOsalMutexUnlock(&gCkptSvr->ckptClusterSem);
    }
    /* 
     * Announce the arrival to peer in the n/w. Master server announces to 
     * all and other servers announce to master server.
     */
    ckptSvrArrvlAnnounce();
    
    /*
     * If the node coming up is deputy, syncup the metadata and ckpt info 
     * from the master. Treat all SC capable nodes except the master as deputy.
     */
    if(  gCkptSvr->localAddr != master && clCpmIsSCCapable())
    {
        /*
         * Just freezing the deputy till syncup, not to receive any master
         * related calls, this is to ensure that deputy is in full synup with
         * master and any calls from master to update deputy will sleep on the
         * lock.
         */
        CKPT_LOCK(gCkptSvr->masterInfo.ckptMasterDBSem);
        ckptMasterDatabaseSyncup(gCkptSvr->masterInfo.masterAddr);
        CKPT_UNLOCK(gCkptSvr->masterInfo.ckptMasterDBSem);
    }
    
    /* 
     * Server is up.
     */
    gCkptSvr->serverUp = CL_TRUE;
    return rc;
    exitOnError:
    {
        return rc;
    }
}
ClRcT cpmGmsInitialize(void)
{
    ClRcT rc = CL_OK;
    ClTimerTimeOutT timeOut = {0, 0};

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

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

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

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

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

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

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

    return CL_OK;

    failure:
    return rc;
}
static void * 
clLogDeferredHandler(void  *pData)
{
    ClRcT                 rc       = CL_OK;
    ClTimerTimeOutT       timeOut  ={.tsSec = 0, .tsMilliSec = 0};
    ClUint16T             numRecs  = 0;
    ClLogDeferredHeaderT  msg[CL_LOG_MAX_FLUSH_COUNT];
    static ClUint16T      lastReadIdx = 0xFFFF;
    static ClUint16T      lastOverwriteFlag = 0xFFFF;
    static ClUint16T      numNotFlushed     = 0;

    while( gUtilLibInitialized )
    {
        rc = clOsalMutexLock(&gLogMutex);
        if( CL_OK != rc )
        {
            gUtilLibInitialized = CL_FALSE;
            goto threadExit;
        }
        /*
         * Sleep for two seconds, it may be woken up by 
         * writer for flushing.
         * Disable the deferred flusher thread as its obsoleted by other changes to flush to log streams
         * now.
         */
        if(1 /*clLogUtilNumRecordsTBW() <= (2 * CL_LOG_MAX_FLUSH_COUNT)*/)
        {
            //fprintf(stderr, "sleeping....getpid[%d] readIdx [%d] writeIdx [%d]\n", getpid(), readIdx,
              //      writeIdx);
            rc = clOsalCondWait(&gLogCond, &gLogMutex, timeOut);
            if( (CL_OK != rc) && (CL_GET_ERROR_CODE(rc) != CL_ERR_TIMEOUT))
            {
                clOsalMutexUnlock(&gLogMutex);
                gUtilLibInitialized = CL_FALSE;
                goto threadExit;
            }
        }
        if( lastOverwriteFlag != overWriteFlag )
        {
            /* last over write flag is not matching with overWriteFlag, 
             * so readIdx has been modifiedi by writer,
             * so making numNotFlushed to 0
             */
            numNotFlushed = 0;
        }
        if( (numNotFlushed != 0) && (numNotFlushed != numRecs) )
        {
            if( readIdx < numNotFlushed )
            {
                readIdx = CL_LOG_MAX_NUM_MSGS - ( numNotFlushed - readIdx);
            }
            else
            {
                readIdx -= numNotFlushed;
            }
        }
        /* niether everything nor nothing */
        if( (numNotFlushed == 0)  || (lastReadIdx != readIdx) )
        {
            /*
             * if the readIdx has been changed while this thread was
             * not having the lock variable, lastOverwriteFlag has been
             * modified, this means I have to change my buffer.
             */
            clLogNumFlushableRecordsGet(msg, &numRecs, &lastReadIdx,
                    &lastOverwriteFlag); 
            //fprintf(stderr, "msg repopulation, numNotFlushed: [%d] lastReadIdx [%d] readIdx [%d] numRecs [%d]\n",
              //              numNotFlushed, lastReadIdx, readIdx, numRecs);
        }
        numNotFlushed = 0;
        if( gUtilLibInitialized == CL_FALSE )
        {
            clOsalMutexUnlock(&gLogMutex);
            goto threadExit;
        }
        /* unlock it */
        rc = clOsalMutexUnlock(&gLogMutex);
        if( CL_OK != rc )
        {
            gUtilLibInitialized = CL_FALSE;
            goto threadExit;
        }
        /* Do the flushing */
        rc = clLogDoLogWrite(msg, numRecs, &numNotFlushed);
        if( CL_OK != rc )
        {
            goto threadExit;
        }
    }
threadExit:    
    if( CL_OK == rc )
    {
        clLogDoLogWrite(msg, numRecs, &numNotFlushed);
    }
    gUtilLibInitialized = CL_FALSE;
    return NULL;
}

static ClUint16T 
clLogUtilNumRecordsTBW(void)
{
    ClUint16T  numRecs = 0;

    //fprintf(stderr, "readIdx: %d writeIdx: %d\n", readIdx, writeIdx);
    if( (readIdx == writeIdx) && (overWriteFlag == 1))
    {
        numRecs  = CL_LOG_MAX_NUM_MSGS - 1;
    }
    else if( (readIdx <= writeIdx) )
    {
        numRecs  = writeIdx - readIdx;
    }
    else if( (readIdx > writeIdx) && (overWriteFlag == 0) )
    {
        numRecs  = (CL_LOG_MAX_NUM_MSGS - readIdx) + writeIdx;
    }
    else
    {
        fprintf(stderr, "readIdx & writeIdx updation went wrong readIdx [%d] writeIdx [%d] overWriteFlag [%d]\n", 
                    readIdx, writeIdx, overWriteFlag);
        /* Should not occur */
    }
    return numRecs;
}