ClRcT clJobQueueStop(ClJobQueueT* hdl)
{
    ClJobT* jb=0;
    ClRcT rc;

    if( !(hdl->flags & CreatedQueue) ) return CL_JOBQUEUE_RC(CL_ERR_INVALID_STATE);
    JQ_PFX(hdl);

    /* Clear out all pending jobs */
    do{
        ClQueueDataT temp;
        rc = clQueueNodeDelete(hdl->queue, &temp);
        if (CL_GET_ERROR_CODE(rc) != CL_ERR_NOT_EXIST)
        {
            jb = (ClJobT*) temp;
            CL_ASSERT(jb);
            releaseJob(hdl,jb);
        }
    } while (CL_GET_ERROR_CODE(rc) != CL_ERR_NOT_EXIST);

    /* GAS TODO: Let all the tasks finish up */

    hdl->flags &= ~Running;

    rc = CL_OK;

    JQ_SFX(hdl);
    return rc;
}
ClRcT clJobQueuePreIdle(ClPtrT cookie)
{
    ClJobQueueT* hdl =  (ClJobQueueT*) cookie;
    if(! (hdl->flags & Running) ) return CL_JOBQUEUE_RC(CL_ERR_INVALID_STATE);
    JQ_PFX(hdl);
    ClJobT* jb = NULL;
    ClQueueDataT temp = NULL;
    ClRcT rc = clQueueNodeDelete(hdl->queue, &temp);
    if (rc == CL_OK)
    {
        jb = (ClJobT*) temp;
        CL_ASSERT(jb);
        clTaskPoolRun(hdl->pool,jb->job, jb->data);
        releaseJob(hdl,jb);
    }

    JQ_SFX(hdl);
    return CL_OK;  
}
static void*
tsTimerReEnqueue()
{
    ClRcT returnCode = CL_OK;
    /*ClUint32T queueSize = 0;
    ClUint32T i = 0;*/
    TsTimer_t* pUserTimer = NULL;
    ClRcT retCode = 0;

    /* For each of the timers in the reEnqueue Queue, insert into active timer list
     *  and dequeue from the reEnqueue Queue
     */
    while(returnCode == CL_OK) {
        returnCode = clQueueNodeDelete(gActiveTimerQueue.reEnqueueQueue, (ClQueueDataT*)&pUserTimer);
        if(CL_OK != returnCode) {
            break;
        }
        retCode = tsActiveTimerEnqueue (pUserTimer);
    }

    /* EL - This portion and the return code handling is suspicious */
    returnCode = CL_OK;
    return(0);
}
/* Handle destructor function. */
static void clDispatchHandleDestructor(void* cbArgs)
{
    ClRcT   rc = CL_OK;
    ClDispatchDbEntryT* thisDbEntry = NULL;
    ClUint32T   queueSize = 0;
    ClDispatchCbQueueDataT*   queueData = NULL;

    if (cbArgs == NULL)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Handle destructor is called with NULL pointer"));
        return;
    }

    thisDbEntry = (ClDispatchDbEntryT*)cbArgs;

    /* Lock the queue mutex */
    rc = clOsalMutexLock(thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to lock dispatch Mutex in Handle destructor callback"));
        return;
    }

    /*
     * Before deleting the queue you need to flush the queue.
     * Even though clQueueDelete will flush the node, we need
     * handle it explicitly so that we can invoke
     * ClDispatchQueueDestroyCallbackT registered during Register
     * which will deallocate the memory for the callback arguments.
     */
    rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
    if (rc != CL_OK)
    {
        goto proceed_other_functions;
    }

    while (queueSize != 0)
    {
        rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData);
        if (rc != CL_OK)
        {
            goto proceed_other_functions;
        }
        CL_ASSERT(queueData != NULL);

        /* Invoke the queue destroy callback function */
        thisDbEntry->queueDestroyCallback(queueData->callbackType,
                                          queueData->callbackArgs);

        rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
        if (rc != CL_OK)
        {
            goto proceed_other_functions;
        }
    }

proceed_other_functions:
    /* 
     * Delete the queue. This will also flush the queue. So all the
     * pending callbacks will be flushed.
     */
    rc = clQueueDelete(&thisDbEntry->cbQueue);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to delete the queue. Rc = 0x%x",rc));
    }
        
    /* Delete the pipe */
    errno = 0;
    if ((close(thisDbEntry->readFd)) < 0)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to close write fd of the pipe:%s",strerror(errno)));
    }

    errno = 0;
    if ((close(thisDbEntry->writeFd)) < 0)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to close read fd of the pipe:%s",strerror(errno)));
    }


    /* Delete the mutex */
    rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Failed to unlock the dispatch mutex"));
    }
    rc = clOsalMutexDelete(thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Failed to delete the dispatch mutex"));
    }


    return;
}
/*
 * clDispatchCbDispatch will dequeue the pending callback and invokes the
 * service client specific generic callback. The service client should make
 * sure that it handles the invocation of the associated callback.
 */
ClRcT   clDispatchCbDispatch(
        CL_IN   ClHandleT           dispatchHandle,
        CL_IN   ClDispatchFlagsT     dispatchFlag)
{
    ClRcT   rc = CL_OK;
    ClDispatchDbEntryT* thisDbEntry = NULL;
    ClUint32T   queueSize = 0;
    ClDispatchCbQueueDataT*   queueData = NULL;
    ClCharT ch = pipeNotifyChar;

    if ((dispatchFlag != CL_DISPATCH_ONE) &&
            (dispatchFlag != CL_DISPATCH_ALL) &&
            (dispatchFlag != CL_DISPATCH_BLOCKING))
    {
        return CL_ERR_INVALID_PARAMETER;
    }

    CHECK_LIB_INIT;

    rc = clHandleCheckout(databaseHandle, dispatchHandle, (void *)&thisDbEntry);
    if (rc != CL_OK)
    {
        return CL_ERR_INVALID_HANDLE;
    }
    CL_ASSERT(thisDbEntry != NULL);

    /* Lock the mutex */
    rc = clOsalMutexLock(thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        goto error_return;
    }

    if (thisDbEntry->shouldDelete == CL_TRUE)
    {
        rc = CL_ERR_INVALID_HANDLE;
        goto error_unlock_return;
    }

    switch (dispatchFlag)
    {
        case CL_DISPATCH_ONE:
            {
                rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
                if (rc != CL_OK)
                {
                    goto error_unlock_return;
                }

                if (queueSize < 1)
                {
                    /* Dont return any error. So rc = CL_OK */
                    goto error_unlock_return;
                }

                /* Dequeue the node */
                rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData);
                if (rc != CL_OK)
                {
                    goto error_unlock_return;
                }
                CL_ASSERT(queueData != NULL);

                /* Read a character from the pipe */
                errno = 0;
                if ((read(thisDbEntry->readFd, (void*)&ch, 1)) < 1)
                {
                    CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                            ("read error on pipe: %s",strerror(errno)));
                }
                            
                rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex);
                if (rc != CL_OK)
                {
                    goto error_return;
                }

                /* Invoke the generic callback */
                thisDbEntry->svcCallback(thisDbEntry->svcInstanceHandle,
                                         queueData->callbackType,
                                         queueData->callbackArgs);
                clHeapFree(queueData);
            }
            /* Dont do break, as we have already unlocked the mutex */
            goto error_return;
        case CL_DISPATCH_ALL:
            {
                rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
                if (rc != CL_OK)
                {
                    goto error_unlock_return;
                }

                while (queueSize != 0)
                {
                    rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData);
                    if (rc != CL_OK)
                    {
                        goto error_unlock_return;
                    }
                    CL_ASSERT(queueData != NULL);

                    /* Read the byte */
                    errno = 0;
                    if ((read(thisDbEntry->readFd,(void*)&ch,1)) < 1)
                    {
                        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                                ("Read error on the pipe: %s",strerror(errno)));
                    }

                    rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex);
                    if (rc != CL_OK)
                    {
                        goto error_return;
                    }

                    /* Invoke the generic callback */
                    thisDbEntry->svcCallback(thisDbEntry->svcInstanceHandle,
                                             queueData->callbackType,
                                             queueData->callbackArgs);

                    /* Free the queueData */
                    clHeapFree(queueData);

                    /* Get the lock again */
                    rc = clOsalMutexLock(thisDbEntry->dispatchMutex);
                    if (rc != CL_OK)
                    {
                        goto error_return;
                    }

                    if (thisDbEntry->shouldDelete == CL_TRUE)
                    {
                        rc = CL_ERR_INVALID_HANDLE;
                        goto error_unlock_return;
                    }

                    rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
                    if (rc != CL_OK)
                    {
                        goto error_unlock_return;
                    }
                } /* End of while */

            }
            /* Just break, as we need to unlock and return */
            break;
        case CL_DISPATCH_BLOCKING:
            {
                while (1)
                {
                    rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex);
                    if (rc != CL_OK)
                    {
                        goto error_return;
                    }

                    /* Block on the readFd */
                    errno = 0;
                    if ((read(thisDbEntry->readFd,(void*)&ch,1)) < 1)
                    {
                        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                                ("Read error on the pipe: %s",strerror(errno)));
                        /* 
                         * This might be because finalize has been done and write fd
                         * is closed. So return
                         */
                        goto error_return;
                    }

                    rc = clOsalMutexLock(thisDbEntry->dispatchMutex);
                    if (rc != CL_OK)
                    {
                        goto error_return;
                    }

                    if (thisDbEntry->shouldDelete == CL_TRUE)
                    {
                        rc = CL_OK;
                        goto error_unlock_return;
                    }

                    rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize);
                    if (rc != CL_OK)
                    {
                        goto error_unlock_return;
                    }

                    if (queueSize < 1)
                    {
                        /* 
                         * This would happen when read has come out due
                         * to signal
                         */
                        continue;
                    }

                    /* Dequeue the node */
                    rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData);
                    if (rc != CL_OK)
                    {
                        goto error_unlock_return;
                    }
                    CL_ASSERT(queueData != NULL);

                    rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex);
                    if (rc != CL_OK)
                    {
                        goto error_return;
                    }

                    /* Invoke the generic callback */
                    thisDbEntry->svcCallback(thisDbEntry->svcInstanceHandle,
                            queueData->callbackType,
                            queueData->callbackArgs);

                    /* Free the queueData */
                    clHeapFree(queueData);

                    /* Get the lock again */
                    rc = clOsalMutexLock(thisDbEntry->dispatchMutex);
                    if (rc != CL_OK)
                    {
                        goto error_return;
                    }

                    if (thisDbEntry->shouldDelete == CL_TRUE)
                    {
                        rc = CL_ERR_INVALID_HANDLE;
                        goto error_unlock_return;
                    }
                }
                break;
            }
    } /* End of switch */

error_unlock_return:
    if ((clOsalMutexUnlock(thisDbEntry->dispatchMutex)) != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Mutex Unlock failed\n"));
    }

error_return:
    if ((clHandleCheckin(databaseHandle, dispatchHandle)) != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("clHandleCheckin failed"));
    }

    return rc;
}