ClRcT
clTimerStop (ClTimerHandleT  timerHandle)
{
    /* make sure the timer actually exists */
    ClRcT returnCode = CL_ERR_INVALID_HANDLE;
    TsTimer_t* pUserTimer = NULL;

    CL_FUNC_ENTER();
    pUserTimer = (TsTimer_t*) timerHandle;

    if (pUserTimer == NULL) {
        /* debug message */
        returnCode = CL_TIMER_RC(CL_ERR_INVALID_HANDLE);
        clDbgCodeError(returnCode, ("Bad timer handle"));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    if (pUserTimer->state == TIMER_FREE) {
        returnCode = CL_TIMER_RC(CL_TIMER_ERR_INVALID_TIMER);
        clDbgCodeError(returnCode, ("Attempt to stop a deleted timer."));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    /* if the timer is active, remove it from the active-timers queue */
    if (pUserTimer->state == TIMER_ACTIVE) {
        returnCode = clOsalMutexLock (gActiveTimerQueue.timerMutex);
        if (returnCode != CL_OK) {
            CL_FUNC_EXIT();
            return (returnCode);
        }

        returnCode = tsActiveTimerDequeue (pUserTimer);
        if (returnCode != CL_OK) {
            if(CL_OK != clOsalMutexUnlock (gActiveTimerQueue.timerMutex)) {
                CL_FUNC_EXIT();
                return(returnCode);
            }
            CL_FUNC_EXIT();
            return (returnCode);
        }

        returnCode = clOsalMutexUnlock (gActiveTimerQueue.timerMutex);
        if (returnCode != CL_OK) {
            CL_FUNC_EXIT();
            return (returnCode);
        }
    }

    /* mark the timer as inactive */
    pUserTimer->state = TIMER_INACTIVE;

    CL_FUNC_EXIT();
    return (CL_OK);
}
ClRcT
clTimerDelete (ClTimerHandleT*  pTimerHandle)
{
    TsTimer_t* pUserTimer = NULL;
    ClRcT returnCode = CL_ERR_INVALID_HANDLE;

    CL_FUNC_ENTER();
    if (NULL == pTimerHandle) {
        returnCode = CL_TIMER_RC(CL_ERR_NULL_POINTER);
        clDbgCodeError(returnCode, ("Bad timer handle storage"));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    pUserTimer = (TsTimer_t*) *pTimerHandle;
    if (pUserTimer == NULL) {
        returnCode = CL_TIMER_RC(CL_ERR_INVALID_HANDLE);
        clDbgCodeError(returnCode, ("Bad timer handle"));
        CL_FUNC_EXIT();
        return (returnCode);
    }
    if (pUserTimer->state == TIMER_FREE) {
        returnCode = CL_TIMER_RC(CL_TIMER_ERR_INVALID_TIMER);
        clDbgCodeError(returnCode, ("Double delete of a timer"));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    /* if timer is active, remove it from the active-timers queue */
    returnCode = clTimerStop (*pTimerHandle);

    if (returnCode != CL_OK) {
        CL_DEBUG_PRINT (CL_DEBUG_WARN, ("\nTimer delete failed"));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    /* null out all the values */
    pUserTimer->fpTimeOutAction = NULL;
    pUserTimer->pActionArgument = NULL;
    pUserTimer->state = TIMER_FREE;
    pUserTimer->pNextActiveTimer = NULL; /* valid only for active timers */
    pUserTimer->pPreviousActiveTimer = NULL; /* valid only for active timers */

    /* return timer to the free pool */
    tsFreeTimerReturn (pUserTimer);

    *pTimerHandle = NULL;

    CL_FUNC_EXIT();
    return (CL_OK);
}
Example #3
0
ClRcT
cosPosixSemCreate (ClUint8T* pName, ClUint32T count, ClOsalSemIdT* pSemId)
{
    ClInt32T rc = CL_OK;
    sem_t *pSem = NULL;
    ClInt32T semValue = 0;
    ClInt32T i = 0;
    
    nullChkRet(pSemId);
    nullChkRet(pName);

    CL_FUNC_ENTER();
    if ((count == 0) || count > CL_SEM_MAX_VALUE)
    {
        rc = CL_OSAL_RC(CL_ERR_INVALID_PARAMETER);
        clDbgCodeError(rc, ("Number of semaphores to create (count) [%d] must be between [1] and [%d]", count,  CL_SEM_MAX_VALUE));
        CL_FUNC_EXIT();
        return(rc);
    }

    pSem = sem_open((ClCharT*)pName, O_CREAT, 0777, count);
    if(pSem == SEM_FAILED)
    {
        rc = CL_OSAL_RC(CL_ERR_LIBRARY); 
        clDbgCodeError(rc, ("Failed at sem_open. system error code %d.\n", errno));
        return rc;
    }

    sem_getvalue(pSem, &semValue);

    if (semValue < (ClInt32T)count)
    {
        for (i = semValue; i < (ClInt32T)count; ++i)
        {
            sem_post(pSem);
        }
    }
    else
    {
        for (i = count; i < semValue; ++i)
        {
            sem_wait(pSem);
        }
    }

    *pSemId = *(ClOsalSemIdT*)&pSem;

    CL_FUNC_EXIT();
    return (rc);
}
ClRcT
clTimerTypeGet (ClTimerHandleT timerHandle,
                ClUint32T* pTimerType)
{
    /* make sure the timer actually exists */
    TsTimer_t* pUserTimer = NULL;
    ClRcT returnCode;

    CL_FUNC_ENTER();
    pUserTimer = (TsTimer_t*) timerHandle;
    if (pUserTimer == NULL) {
        /* debug message */
        returnCode = CL_TIMER_RC(CL_ERR_INVALID_HANDLE);
        clDbgCodeError(returnCode, ("Bad timer handle"));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    if (pTimerType == NULL) {
        CL_FUNC_EXIT();
        return (CL_ERR_UNSPECIFIED);
    }

    /* extract the timer-type from the timer */
    *pTimerType = pUserTimer->type;

    CL_FUNC_EXIT();
    return (CL_OK);
}
ClRcT
__cosSysvMutexUnlock (ClOsalMutexIdT mutexId, ClBoolT verbose)
{
    ClRcT rc = CL_OK;
    ClOsalMutexT* pMutex = (ClOsalMutexT*) mutexId;
    static struct sembuf sembuf = {0, 1, SEM_UNDO };
    ClInt32T err = 0;

    CL_FUNC_ENTER();

retry:
    err = semop(pMutex->shared_lock.sem.semId,&sembuf,1);
    if(err < 0)
    {
        if(errno == EINTR)
        {
            goto retry;
        }
        rc = CL_OSAL_RC(CL_ERR_LIBRARY);
        if(verbose)
        {
            clDbgCodeError(rc,("semop unlock returned [%s]\n",strerror(errno)));
        }
    }

    CL_FUNC_EXIT();
    return (rc);
}
/**
 * Delete transaction definition
 */
ClRcT clTxnDefnDelete(
        CL_IN   ClTxnDefnT    *pTxnDefn)
{
    CL_FUNC_ENTER();

    /* Clean-up all other memory allocated with this transaction */

    if (NULL != pTxnDefn)
    {
        CL_DEBUG_PRINT(CL_DEBUG_TRACE, 
            ("Removing transaction definition. txnId:0x%x:0x%x", 
             pTxnDefn->serverTxnId.txnMgrNodeAddress, 
             pTxnDefn->serverTxnId.txnId));
        if(pTxnDefn->jobList)
        {
            //clCntAllNodesDelete(pTxnDefn->jobList); /* This can be removed by giving the destroy callback */
            clCntDelete(pTxnDefn->jobList);
        }
        else
        {
            clDbgCodeError(0,("Where did the jobList go?"));            
        }

        clHeapFree(pTxnDefn);
    }

    CL_FUNC_EXIT();
    return (CL_OK);
}
Example #7
0
ClRcT 
__cosPosixMutexLock (ClOsalMutexIdT mutexId, ClBoolT verbose)
{
    ClRcT rc = CL_OK;
    ClOsalMutexT *pMutex = (ClOsalMutexT*)mutexId;
    ClInt32T err=0;

    if(verbose)
    {
        nullChkRet(pMutex);
    }
    else if(!pMutex)
    {
        return CL_OSAL_RC(CL_ERR_NULL_POINTER);
    }

    CL_FUNC_ENTER();   
retry:
    err = sem_wait(&pMutex->shared_lock.sem.posSem);
    if(err < 0 )
    {
        if(errno == EINTR)
            goto retry;
        rc = CL_OSAL_RC(CL_ERR_LIBRARY);
        if(verbose)
        {
            clDbgCodeError(rc,("sem_wait returned [%s]\n",strerror(errno)));
        }
    }

    CL_FUNC_EXIT();
    return (rc);
}
/**
 * Delete/free transaction-job definition
 */
ClRcT clTxnAppJobDelete(
        CL_IN   ClTxnAppJobDefnT *pTxnAppJob)
{
    CL_FUNC_ENTER();

    if (NULL == pTxnAppJob)
    {
        CL_FUNC_EXIT();
        clDbgCodeError(CL_ERR_NULL_POINTER, ("Null pointer on the job list"));
        return CL_ERR_NULL_POINTER;
    }

    CL_DEBUG_PRINT(CL_DEBUG_TRACE, ("Deleting txn-job %p", (ClPtrT) pTxnAppJob));

    if(pTxnAppJob->compList)
    {
        //clCntAllNodesDelete(pTxnAppJob->compList);
        clCntDelete(pTxnAppJob->compList);
    }

    if (pTxnAppJob->appJobDefn)
        clHeapFree( (ClPtrT) pTxnAppJob->appJobDefn);
    
    memset(pTxnAppJob, 0, sizeof(ClTxnAppJobDefnT));  /* to crash uses after delete */
    clHeapFree(pTxnAppJob);

    return (CL_OK);
}
Example #9
0
ClRcT cosPosixProcessSharedSemInit(ClOsalMutexT *pMutex, ClUint8T *pKey, ClUint32T keyLen, ClInt32T value)
{
    ClRcT rc = CL_OK;
    int err;

    nullChkRet(pKey);
    if(keyLen == 0)
    {
        clDbgCodeError(CL_ERR_INVALID_PARAMETER,("Invalid keylen [%d]\n",keyLen));
        return CL_OSAL_RC(CL_ERR_INVALID_PARAMETER);
    }

    pthread_mutex_lock(&gClSemAccessLock);
    err = sem_init(&pMutex->shared_lock.sem.posSem,1, value);
    if(err < 0)
    {
        pthread_mutex_unlock(&gClSemAccessLock);
        rc = CL_OSAL_RC(CL_ERR_LIBRARY);
        goto out;
    }
    pthread_mutex_unlock(&gClSemAccessLock);
    
    pMutex->shared_lock.sem.numSems = 1;
    rc = CL_OK;

out:
    return rc;
}
ClRcT cosSysvProcessSharedSemInit(ClOsalMutexT *pMutex, ClUint8T *pKey, ClUint32T keyLen, ClInt32T value)
{
    ClInt32T semId = 0;
    ClUint32T semKey = 0;
    ClRcT rc = CL_OK;
    ClUint32T flags = 0666;
    ClInt32T err = 0;

    nullChkRet(pKey);
    if(keyLen == 0)
    {
        clDbgCodeError(CL_ERR_INVALID_PARAMETER,("Invalid keylen [%d]\n",keyLen));
        return CL_OSAL_RC(CL_ERR_INVALID_PARAMETER);
    }

    rc = clCrc32bitCompute(pKey, keyLen, &semKey, NULL);
    CL_ASSERT(rc == CL_OK && semKey );

    pthread_mutex_lock(&gClSemAccessLock);
retry:
    semId = semget(semKey, 1, flags);
    if(semId < 0 )
    {
        if(errno == EINTR)
            goto retry;
        if(errno == ENOENT)
        {
            flags |= IPC_CREAT;
            goto retry;
        }
        pthread_mutex_unlock(&gClSemAccessLock);
        rc = CL_OSAL_RC(CL_ERR_LIBRARY);
        goto out;
    }
    pthread_mutex_unlock(&gClSemAccessLock);
    if( (flags & IPC_CREAT) )
    {
        CosSemCtl_t arg = {0};
        arg.val = value;
retry1:
        err = semctl(semId,0,SETVAL,arg);
        if(err < 0 )
        {
            if(errno == EINTR)
                goto retry1;
            rc = CL_OSAL_RC(CL_ERR_LIBRARY);
            goto out;
        }
    }
    pMutex->shared_lock.sem.semId = semId;
    pMutex->shared_lock.sem.numSems = 1;
    rc = CL_OK;

out:
    return rc;
}
ClRcT
cosSysvSemCreate (ClUint8T* pName, ClUint32T count, ClOsalSemIdT* pSemId)
{
    ClInt32T retCode = CL_OK;
    CosSemCtl_t semArg = {0};
    ClUint32T len = 0;
    ClUint32T key = 0;
    ClInt32T semId = -1;

    nullChkRet(pSemId);
    nullChkRet(pName);

    CL_FUNC_ENTER();
    if ((count == 0) || count > CL_SEM_MAX_VALUE)
    {
        retCode = CL_OSAL_RC(CL_ERR_INVALID_PARAMETER);
        clDbgCodeError(retCode, ("Number of semaphores to create (count) [%d] must be between [1] and [%d]", count,  CL_SEM_MAX_VALUE));
        CL_FUNC_EXIT();
        return(retCode);
    }

    len = (ClUint32T)strlen ((ClCharT*)pName);

#if 0 /* Stone: why this limitation? */
    if(len > 20)
        if(len > 256)
        {
            CL_DEBUG_PRINT (CL_DEBUG_INFO,("Sanity check, semaphore name length is suspiciously long"));
            retCode = CL_OSAL_RC(CL_OSAL_ERR_NAME_TOO_LONG);
            CL_FUNC_EXIT();
            return(retCode);
        }
#endif

    if(len > 256)
    {
        CL_DEBUG_PRINT (CL_DEBUG_INFO,("Sanity check, semaphore name [%s] is suspiciously long",pName));
    }

    retCode = (ClInt32T)clCrc32bitCompute (pName, len, &key, NULL);
    CL_ASSERT(retCode == CL_OK); /* There is no possible error except for pName == NULL, which I've already checked, so don't check the retCode */


    sysErrnoChkRet(semId = semget ((key_t)key, (int)count, IPC_CREAT|0666));

    semArg.val = (int)count;

    /* Initialize all the semaphores to 0.  This should never fail, because I just created the semaphores */
    sysErrnoChkRet(semctl (semId, 0, SETVAL, semArg));

    *pSemId = (ClOsalSemIdT)semId;

    CL_FUNC_EXIT();
    return (CL_OK);
}
Example #12
0
ClRcT
cosPosixMutexValueSet(ClOsalMutexIdT mutexId, ClInt32T value)
{
    ClRcT rc = CL_OSAL_RC(CL_ERR_NOT_SUPPORTED);
    
    CL_FUNC_ENTER();

    clDbgCodeError(rc, ("POSIX semaphores dont support setval operations\n"));

    CL_FUNC_EXIT();
    return rc;
}
ClRcT
cosSysvMutexDestroy (ClOsalMutexT *pMutex)
{
    ClRcT rc = CL_OK;
    ClInt32T err;
    CL_FUNC_ENTER();

    err = semctl(pMutex->shared_lock.sem.semId,0,IPC_RMID,0);
    if(err < 0 )
    {
        rc = CL_OSAL_RC(CL_ERR_LIBRARY);
        clDbgCodeError(CL_ERR_LIBRARY,("semctl returned [%s]\n",strerror(errno)));
    }

    CL_FUNC_EXIT();
    return (rc);
}
Example #14
0
ClRcT 
__cosPosixMutexUnlock (ClOsalMutexIdT mutexId, ClBoolT verbose)
{
    ClRcT rc = CL_OK;
    ClUint32T retCode = 0;
    ClOsalMutexT* pMutex = (ClOsalMutexT*) mutexId;
    ClInt32T err = 0;
   
    CL_FUNC_ENTER();
    
    if (NULL == pMutex)
	{
        retCode = CL_OSAL_RC(CL_ERR_NULL_POINTER);
        if(verbose)
        {
            clLogError(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED,"Mutex Unlock : FAILED, mutex is NULL (used after delete?)");
            clDbgPause();
        }
        CL_FUNC_EXIT();
        return(retCode);
	}

    retry:
    err = sem_post(&pMutex->shared_lock.sem.posSem);
    if(err < 0)
    {
        if(errno == EINTR)
        {
            goto retry;
        }
        rc = CL_OSAL_RC(CL_ERR_LIBRARY);
        if(verbose)
        {
            clDbgCodeError(rc,("sem_post unlock returned [%s]\n",strerror(errno)));
        }
    }

    CL_FUNC_EXIT();
    return (rc);
}
Example #15
0
ClRcT 
cosPosixMutexDestroy (ClOsalMutexT *pMutex)
{
    ClRcT rc = CL_OK;
    ClUint32T retCode = 0;
    CL_FUNC_ENTER();
    if (NULL == pMutex)
	{
        clLogError(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED,"Mutex Destroy failed, mutex is NULL (double delete?)");
        retCode = CL_OSAL_RC(CL_ERR_NULL_POINTER);
        CL_FUNC_EXIT();
        return(retCode);
	}

    ClInt32T err = sem_destroy(&pMutex->shared_lock.sem.posSem);
    if(err < 0 )
    {
        rc = CL_OSAL_RC(CL_ERR_LIBRARY);
        clDbgCodeError(CL_ERR_LIBRARY,("sem_destroy() returned [%s]\n",strerror(errno)));
    }

    CL_FUNC_EXIT();
    return (rc);
}
ClRcT
clHandleCheckin(
                ClHandleDatabaseHandleT databaseHandle,
                ClHandleT handle)
{
    ClRcT          rc        = CL_OK;
    void           *instance = NULL;
    ClHdlDatabaseT *hdbp     = (ClHdlDatabaseT*) databaseHandle;
    ClRcT          ec        = CL_OK;
    ClInt32T       refcount  = 0;

    hdlDbValidityChk(hdbp);
    /* sometimes people want to create the same handle across multiple nodes hdlValidityChk(handle,hdbp); */
    handle = CL_HDL_IDX(handle); /* once we've verified it, we only care about the index */
    /*
     * Decrementing handle to ensure the non-zero handle interface.
     */
    if (CL_HANDLE_INVALID_VALUE == handle--)
    {
        clLogError(CL_HDL_AREA, CL_HDL_CTX_CHECKIN, "Passed handle [%p:%#llX] is invalid", (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE); /* 0 no longer allowed */
    }

    ec = pthread_mutex_lock(&hdbp->mutex);
    if (ec != 0)
    {
        int err = errno;
        clDbgCodeError(CL_HANDLE_RC(CL_ERR_MUTEX_ERROR), ("Handle database mutex lock failed error: %s (%d)", strerror(err), err) );
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR);
    }

    if (handle >= (ClHandleT)hdbp->n_handles)
    {
        pthread_mutex_unlock( &hdbp->mutex);
        clLogError(CL_HDL_AREA, CL_HDL_CTX_CHECKIN,"Passed handle [%p:%#llX] is invalid handle", (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
    }
    refcount = hdbp->handles[handle].ref_count;
    if( (--refcount <= 0) && (hdbp->handles[handle].state != HANDLE_STATE_PENDINGREMOVAL) )
    {
        pthread_mutex_unlock( &hdbp->mutex);
        clLogError(CL_HDL_AREA, CL_HDL_CTX_CHECKIN,  
                "There is no balance between checkout, checkin for handle [%p:%#llX]", 
                (ClPtrT) hdbp, (handle + 1));
        return CL_HANDLE_RC(CL_ERR_INVALID_STATE);
    }

    CL_ASSERT(hdbp->handles[handle].ref_count > 0); // unsigned compare (CID 196 on #1780)
    hdbp->handles[handle].ref_count -= 1;

    if (hdbp->handles[handle].ref_count == 0)
    {
        instance = (hdbp->handles[handle].instance);
        if (hdbp->handle_instance_destructor != NULL)
        {
            hdbp->handle_instance_destructor(instance);
        }
        if (hdbp->handles[handle].flags & HANDLE_ALLOC_FLAG)  /* Clean up the handle if we allocated it */
          clHeapFree(instance);
        
        memset(&hdbp->handles[handle], 0,    /* This also makes entry EMPTY */
                sizeof(ClHdlEntryT));
        CL_ASSERT(hdbp->n_handles_used > 0); //  unsigned compare (CID 196 on #1780)
        hdbp->n_handles_used--;
    }

    ec = pthread_mutex_unlock(&hdbp->mutex);
    if (ec != 0)
    {
        int err = errno;
        clDbgCodeError(CL_HANDLE_RC(CL_ERR_MUTEX_ERROR), ("Handle database mutex unlock failed error: %s (%d)", strerror(err), err) );
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
    }
    /* This check to avoid recursive call from LogClient */
    if( refcount > 0 )
    {
#if 0
        clLogTrace(CL_HDL_AREA, CL_HDL_CTX_CHECKIN, 
                "Checkin for handle [%p:%#llX]", 
                (ClPtrT) hdbp, (handle + 1));
#endif
    }

    return rc;
}
ClRcT
clTimerStart (ClTimerHandleT  timerHandle)
{
    ClRcT returnCode = CL_ERR_INVALID_HANDLE;
    TsTimer_t* pUserTimer = NULL;
    CL_FUNC_ENTER();
    /* make sure the timer actually exists */
    pUserTimer = (TsTimer_t*) timerHandle;
    if (pUserTimer == NULL) {
        /* debug message */
        returnCode = CL_TIMER_RC(CL_ERR_INVALID_HANDLE);
        clDbgCodeError(returnCode, ("Bad timer handle"));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    if (pUserTimer->state == TIMER_FREE) {
        returnCode = CL_TIMER_RC(CL_TIMER_ERR_INVALID_TIMER);
        clDbgCodeError(returnCode, ("Attempt to start deleted timer."));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    if (pUserTimer->fpTimeOutAction == NULL) {
        /* user has probably deleted the timer! otherwise there's some other corruption! */
        returnCode = CL_TIMER_RC(CL_TIMER_ERR_INVALID_TIMER);
        clDbgCodeError(returnCode, ("Attempt to start deleted or corrupt timer."));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    if (pUserTimer->state == TIMER_ACTIVE) {
        returnCode = CL_TIMER_RC(CL_TIMER_ERR_INVALID_TIMER);
        clDbgCodeError(returnCode, ("Attempt to start an already started timer."));
        CL_FUNC_EXIT();
        return (returnCode);
    }

    /* mark timer as active */
    pUserTimer->state = TIMER_ACTIVE;

    returnCode = clOsalMutexLock (gActiveTimerQueue.timerMutex);
    if (returnCode != CL_OK) {
        /* debug message */
        CL_FUNC_EXIT();
        return (returnCode);
    }
    /* put it on the active timer's queue */
    pUserTimer->timestamp = currentTime+pUserTimer->timeInterval;
    pUserTimer->timestamp += skew/(iteration?iteration:1)/CL_TIMER_TICK_USECS;
    returnCode = tsActiveTimerEnqueue (pUserTimer);
    if (returnCode != CL_OK) {
        /* debug message */
        if (CL_OK != clOsalMutexUnlock (gActiveTimerQueue.timerMutex)) {
            CL_FUNC_EXIT();
            return(returnCode);
        }
        CL_FUNC_EXIT();
        return (returnCode);
    }
    returnCode = clOsalMutexUnlock (gActiveTimerQueue.timerMutex);
    if (returnCode != CL_OK) {
        /* debug message */
        CL_FUNC_EXIT();
        return (returnCode);
    }

    CL_FUNC_EXIT();
    return (CL_OK);
}
ClRcT
clHandleDestroy (
    ClHandleDatabaseHandleT databaseHandle,
    ClHandleT handle)
{
    ClHdlDatabaseT *hdbp = (ClHdlDatabaseT*) databaseHandle;
    ClRcT          ec    = CL_OK;

    hdlDbValidityChk(hdbp);
    handle = CL_HDL_IDX(handle); /* once we've verified it, we only care about the index */
    
    /*
     * Decrementing handle to ensure the non-zero handle interface.
     */
    if (CL_HANDLE_INVALID_VALUE == handle--)
    {
        clLogError("HDL", CL_LOG_CONTEXT_UNSPECIFIED, 
                "Passed handle [%p:%#llX] is invalid", (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE); /* 0 no longer allowed */
    }
    /* Verify this particular handle has been already created */
    if( (NULL == hdbp->handles) || (0 == hdbp->n_handles_used) )
    {
        clLogError("HDL", CL_LOG_CONTEXT_UNSPECIFIED, 
                "Invalid attempt to delete the non exiting handle [%p:%#llX]", 
                (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
    }

    ec = pthread_mutex_lock (&hdbp->mutex);
    if (ec != 0)
    {
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR);
    }
    if (handle >= (ClHandleT)hdbp->n_handles)
    {
        ec = pthread_mutex_unlock (&hdbp->mutex);
        if (ec != 0)
        {
            return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
        }
        clLogError("HDL", CL_LOG_CONTEXT_UNSPECIFIED, 
                "Passed handle [%p:%#llX] has not been created", 
                (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
    }
    clDbgResourceNotify(clDbgHandleResource, clDbgRelease, hdbp, handle+1, ("Handle [%p:%#llX] (state: %d, ref: %d) released", (ClPtrT)hdbp, handle+1,hdbp->handles[handle].state,hdbp->handles[handle].ref_count));

    if (HANDLE_STATE_USED == hdbp->handles[handle].state)
    {
        hdbp->handles[handle].state = HANDLE_STATE_PENDINGREMOVAL;

        ec = pthread_mutex_unlock (&hdbp->mutex);
        if (ec != 0)
        {
            return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
        }
        /*
         * Adding 1 to handle to ensure the non-zero handle interface.
         */
        ec = clHandleCheckin (databaseHandle, handle+1);
        return ec;
    }
    else if (HANDLE_STATE_EMPTY == hdbp->handles[handle].state)
    {
        ec = CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
    }
    else if (HANDLE_STATE_PENDINGREMOVAL == hdbp->handles[handle].state)
    {
        ec = pthread_mutex_unlock( &hdbp->mutex);
        if( ec != 0 )
        {
            return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
        }
        clLogWarning(CL_HDL_AREA, CL_HDL_CTX_DESTROY,  
                     "Destroy has been called for this handle [%p:%#llX]" 
                     "returning CL_OK", (ClPtrT) hdbp,
                     (handle + 1));
        return CL_OK;
    }
    else
    {
        clDbgCodeError(CL_ERR_INVALID_HANDLE, 
                       ("Passed handle [%p:%#llX] doesn't have any proper state,"
                       "corrupted code", (ClPtrT) hdbp, (handle + 1)));
        /*
         * Invalid state - this musn't happen!
         */
    }
    if(pthread_mutex_unlock (&hdbp->mutex) != 0)
    {
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
    }

#if 0
    clLogTrace(CL_HDL_AREA, CL_HDL_CTX_DESTROY, 
               "Handle [%p:%#llX] has been deleted successfully", 
               (ClPtrT) hdbp, (handle + 1));
#endif
    return ec;
}
ClRcT
clHandleCheckout(
                 ClHandleDatabaseHandleT databaseHandle,
                 ClHandleT               handleArg,
                 void                    **instance)
{ 
	ClRcT           rc    = CL_OK;
    ClHdlDatabaseT  *hdbp = (ClHdlDatabaseT*)databaseHandle;
    ClHdlStateT     state = HANDLE_STATE_EMPTY;
    ClRcT           ec    = CL_OK;
    ClHandleT       handle;
    hdlDbValidityChk(hdbp);
    /* sometimes people want to create the same handle across multiple nodes hdlValidityChk(handle,hdbp); */
    handle = CL_HDL_IDX(handleArg); /* once we've verified it, we only care about the index */
    nullChkRet(instance);
    /*
     * Decrementing handle to ensure the non-zero handle interface.
     */
    if (CL_HANDLE_INVALID_VALUE == handle--)
    {
        clDbgCodeError(CL_HANDLE_RC(CL_ERR_INVALID_HANDLE), ("Passed Invalid Handle [0x0]"));
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE); /* 0 no longer allowed */
    }

    ec = pthread_mutex_lock (&hdbp->mutex);
    if (ec != 0)
    {
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR);
    }

    if (handle >= (ClHandleT)hdbp->n_handles)
    {
        rc = CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
        pthread_mutex_unlock(&hdbp->mutex);
        clDbgCodeError(rc, ("Passed Invalid Handle [%p:%#llx]", (ClPtrT) hdbp, handleArg));
        return rc;
    }
    
    if ( ( state = hdbp->handles[handle].state ) != HANDLE_STATE_USED)
    {
        pthread_mutex_unlock(&hdbp->mutex);
        if (state == HANDLE_STATE_EMPTY)
        {
            /* In some of our ASP components the assumption made,
             * like checkout handle returns CL_ERR_INVALID_HANDLE 
             * to verify the handle does exist or not.
             * so removing the debug pause
             */
#if 0
            clDbgCodeError(rc, ("Handle [%p:%#llX] is not allocated", (ClPtrT) hdbp, (handle+1)));
#endif
        }
        else if (state == HANDLE_STATE_PENDINGREMOVAL)
        {
            clDbgCodeError(rc, ("Handle [%p:%#llX] is being removed", (ClPtrT) hdbp, handleArg));
        }
        else
        {
            clDbgCodeError(rc, ("Handle [%p:%#llX] invalid state %d", (ClPtrT) hdbp, handleArg, state));
        }

        rc = CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
        clDbgCodeError(rc, ("Handle [%p:%#llX] is invalid", (ClPtrT) hdbp, handleArg));
        return rc;
    }

    *instance = hdbp->handles[handle].instance;

    hdbp->handles[handle].ref_count += 1;

    ec = pthread_mutex_unlock (&hdbp->mutex);
    if (ec != 0)
    {
        clDbgCodeError(CL_HANDLE_RC(CL_ERR_MUTEX_ERROR), ("Mutex unlock failed errno %d", errno));
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
    }
#if 0
    clLogTrace(CL_HDL_AREA, CL_HDL_CTX_CHECKOUT, 
               "Checked out handle [%p:%#llX]", (ClPtrT) hdbp, handleArg);
#endif
    return rc;
}
/* This function handles msg send request from clients */
static ClRcT clMsgIocRequestHandle(ClEoExecutionObjT *pThis,
                           ClBufferHandleT eoRecvMsg,
                           ClUint8T priority,
                           ClUint8T protoType,
                           ClUint32T length,
                           ClIocPhysicalAddressT srcAddr)
{
    ClRcT          rc = CL_OK;
    ClRcT          ret;
    ClUint32T      sendType;
    ClNameT        pDestination;
    SaMsgMessageT  pMessage;
    ClInt64T       sendTime;
    ClHandleT      senderHandle;
    ClInt64T       timeout;
    ClInt64T       msgId;
    ClUint8T       syncType;

    memset(&(pDestination), 0, sizeof(ClNameT));
    memset(&(pMessage), 0, sizeof(SaMsgMessageT));
    memset(&(senderHandle), 0, sizeof(ClHandleT));

    rc = clXdrUnmarshallClUint32T( eoRecvMsg,&(sendType));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClNameT( eoRecvMsg,&(pDestination));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallSaMsgMessageT_4_0_0( eoRecvMsg,&(pMessage));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClInt64T( eoRecvMsg,&(sendTime));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClHandleT( eoRecvMsg,&(senderHandle));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClInt64T( eoRecvMsg,&(timeout));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClInt64T( eoRecvMsg,&(msgId));
    if (CL_OK != rc)
    {
        goto out1;
    }

    rc = clXdrUnmarshallClUint8T( eoRecvMsg,&(syncType));
    if (CL_OK != rc)
    {
        goto out1;
    }

    /* Call remote function */
    ret = VDECL_VER(clMsgMessageReceived, 4, 0, 0)(sendType, &(pDestination), &(pMessage), sendTime, senderHandle, timeout);

    /* Prepare to send return value to the caller */
    ClIocSendOptionT sendOption = { 0 };
    ClBufferHandleT replyMsg = NULL;    
    ClUint8T replyProto = CL_IOC_SAF_MSG_REPLY_PROTO;

    /* Set Ioc send option */
    sendOption.msgOption = CL_IOC_PERSISTENT_MSG;
    sendOption.priority = CL_IOC_DEFAULT_PRIORITY;
    sendOption.timeout = 10000;

    /* Create buffer for input message */
    rc = clBufferCreate(&replyMsg);
    if (CL_OK != rc)
    {
        clDbgResourceLimitExceeded(clDbgMemoryResource, 0, ("Out of memory"));
        goto out1;
    }

    /* Marshall reply data */
    rc = clMsgReplyDataMarshall(replyMsg, ret, msgId, syncType);
    if (CL_OK != rc)
    {
        clDbgCodeError(rc, ("Cannot marshal reply data."));
        goto out2;
    }

    /* Send return value to the caller */
    rc = clIocSend(pThis->commObj, replyMsg, replyProto,(ClIocAddressT *) &srcAddr, &sendOption);
    if (CL_OK != CL_GET_ERROR_CODE(rc))
    {
        clLogError("MSG", "REPLY", "clIocSend(): error code [0x%x].", rc);
    }

out2:
    clBufferDelete(&replyMsg);
out1:
    return rc;
}
ClRcT
clTimerCreate (ClTimerTimeOutT      timeOut,        /* the timeout, in clockticks */
               ClTimerTypeT    type,           /* one shot or repetitive */
               ClTimerContextT timerTaskSpawn, /* whether to spawn off the timer function
                                                 * as a separate task or invoke it in the
                                                 * same context as the timer-task */
               ClTimerCallBackT     fpAction,       /* the function to be called on timeout */
               void*            pActionArgument,/* the argument to the function called on timeout */
               ClTimerHandleT* pTimerHandle)   /* The pointer to the timer handle */
{
    TsTimer_t* pUserTimer = NULL;
    ClRcT errorCode;

    CL_FUNC_ENTER();
    if (fpAction == NULL) {
        errorCode = CL_TIMER_RC(CL_TIMER_ERR_NULL_TIMER_CALLBACK);
        clDbgCodeError(errorCode, ("Timer create failed: Null callback function passed"));
        CL_FUNC_EXIT();
        return (errorCode);
    }

    if (pTimerHandle == NULL) {
        errorCode = CL_TIMER_RC(CL_ERR_NULL_POINTER);
        clDbgCodeError(returnCode, ("Bad timer handle"));
        CL_FUNC_EXIT();
        return (errorCode);
    }

    switch (type) {
    case CL_TIMER_ONE_SHOT:
    case CL_TIMER_REPETITIVE:
        break;
    default:
        errorCode = CL_TIMER_RC(CL_TIMER_ERR_INVALID_TIMER_TYPE);
        clDbgCodeError(errorCode,("Timer create failed: Invalid timer type"));
        CL_FUNC_EXIT();
        return (errorCode);
    }

    switch (timerTaskSpawn) {
    case CL_TIMER_TASK_CONTEXT:
    case CL_TIMER_SEPARATE_CONTEXT:
        break;
    default:
        errorCode = CL_TIMER_RC(CL_TIMER_ERR_INVALID_TIMER_CONTEXT_TYPE);
        clDbgCodeError(errorCode,("Timer create failed: Invalid context type"));
        CL_FUNC_EXIT();
        return (errorCode);
    }

    /* TBD: ensure that user-timeout is more than timer resolution */

    /* allocate a timer from the free pool */
    pUserTimer = tsFreeTimerGet ();

    if (pUserTimer == NULL) {
        /* debug message */
        errorCode = CL_TIMER_RC(CL_ERR_NO_MEMORY);
        CL_DEBUG_PRINT (CL_DEBUG_WARN,
                        ("\nTimer create failed"));
        CL_FUNC_EXIT();
        return (errorCode);
    }

    timeOut.tsSec = timeOut.tsSec + (timeOut.tsMilliSec/1000);
    timeOut.tsMilliSec = timeOut.tsMilliSec % 1000;

    /* fill in the appropriate values */
    pUserTimer->timeOut.tsSec = timeOut.tsSec;
    pUserTimer->timeOut.tsMilliSec = timeOut.tsMilliSec;
    pUserTimer->timeInterval = CL_TIMER_INTERVAL(timeOut);

    pUserTimer->type = type; /* one-shot/repetitive */
    pUserTimer->spawnTask = timerTaskSpawn;
    pUserTimer->fpTimeOutAction = fpAction;
    pUserTimer->pActionArgument = pActionArgument;
    pUserTimer->state = TIMER_INACTIVE; /* active/inactive/free */
    pUserTimer->pNextActiveTimer = NULL; /* valid only for active timers */
    pUserTimer->pPreviousActiveTimer = NULL; /* valid only for active timers */

    /* return handle to the user */
    *pTimerHandle = pUserTimer;

    CL_FUNC_EXIT();
    return (CL_OK);
}