ClRcT
clAmsSAInitialize(
        CL_OUT      ClAmsClientHandleT                      *amsHandle,
        CL_IN       const ClAmsSAClientCallbacksT           *amsClientCallbacks,
        CL_INOUT    ClVersionT                              *version )
{

    ClRcT                                       rc = CL_OK; 
    clAmsClientInitializeRequestT               req;
    clAmsClientInitializeResponseT              *res = NULL;
    struct ams_instance                         *ams_instance = NULL;


    if (amsHandle == NULL || version == NULL)
    {
        return CL_AMS_RC(CL_ERR_NULL_POINTER);
    }
   
    /* 
     * Initialize the library and database 
     */

    if ((rc = check_lib_init())
            != CL_OK)
        goto error;

    /* 
     * Verify the version information 
     */

    if (( rc = clVersionVerify (
                    &version_database,
                    version))
            != CL_OK)
        goto error;

    /* 
     * Create the handle  
     */

    if ((rc = clHandleCreate (
                    handle_database,
                    sizeof(struct ams_instance),
                    amsHandle))
            != CL_OK)
        goto error;

    /* 
     * Check-Out the handle 
     */

    if ((rc = clHandleCheckout(
                    handle_database,
                    *amsHandle,
                    (void *)&ams_instance))
            != CL_OK)
        goto error;


    /* 
     * Initialize instance entry 
     */

    if (amsClientCallbacks) 
    {
        memcpy(&ams_instance->callbacks, amsClientCallbacks, sizeof(ClAmsSAClientCallbacksT));
    } 
    else 
    {
        memset(&ams_instance->callbacks, 0, sizeof(ClAmsSAClientCallbacksT));
    }

     if ( ( rc = clOsalMutexCreate(&ams_instance->response_mutex)) != CL_OK )
         goto error;

    /* 
     * Inform the server 
     */

    req.handle = *amsHandle;
    if ( (rc = cl_ams_client_initialize(
                    &req,
                    &res))
            != CL_OK)
        goto error;

    /* 
     * Decrement handle use count and return 
     */

    if ((rc = clHandleCheckin(
                    handle_database,
                    *amsHandle))
            != CL_OK)
        goto error;
   
    clHeapFree((void*)res);
    res = NULL;
    return CL_OK;

error:

    clHeapFree((void*)res);
    res = NULL;
    return CL_AMS_RC(rc);
}
/*-----------------------------------------------------------------------------
 * Initialize API
 *---------------------------------------------------------------------------*/
ClRcT clGmsInitialize(
    CL_OUT   ClGmsHandleT* const    gmsHandle,
    CL_IN    const ClGmsCallbacksT* const gmsCallbacks,
    CL_INOUT ClVersionT*   const      version)
{
    struct gms_instance *gms_instance_ptr = NULL;
    ClRcT rc = CL_OK;
    ClGmsClientInitRequestT req = {{0}};
    ClGmsClientInitResponseT *res = NULL;

    /* Step 0: Check readiness of library */

    rc = check_lib_init();
    if (rc != CL_OK)
    {
        return CL_GMS_RC(CL_ERR_NOT_INITIALIZED);
    }
    
    /* Step 1: Checking inputs */
    CL_ASSERT(gmsHandle != NULL);
    CL_ASSERT(version != NULL);
#if 0    
    if ((gmsHandle == NULL) || (version == NULL))
    {
        return CL_GMS_RC(CL_ERR_NULL_POINTER);
    }
#endif    

    *gmsHandle = CL_HANDLE_INVALID_VALUE;

    /* Step 2: Verifying version match */
    
    rc = clVersionVerify (&version_database, version);
    if (rc != CL_OK)
    {
        return CL_GMS_RC(CL_ERR_VERSION_MISMATCH); 
    }

    /* Step 3: Obtain unique handle */
    rc = clHandleCreate(gmsHandleDb, sizeof(struct gms_instance), gmsHandle);
    CL_ASSERT(rc == CL_OK);
#if 0    
    if (rc != CL_OK)
    {
        rc = CL_GMS_RC(CL_ERR_NO_RESOURCE);
        goto error_no_destroy;
    }
#endif    
    clLogInfo("GMS","CLT","GMS client handle is [%llX]",*gmsHandle);
    
    rc = clHandleCheckout(gmsHandleDb, *gmsHandle, (void **)&gms_instance_ptr);
    CL_ASSERT(rc == CL_OK);
    CL_ASSERT(gms_instance_ptr != NULL);
#if 0    
    if(rc != CL_OK)
    {
        goto error_destroy;
    }
    if (gms_instance_ptr == NULL)
    {
        clHandleCheckin(gmsHandleDb, *gmsHandle);
        rc = CL_GMS_RC(CL_ERR_NULL_POINTER);
        goto error_destroy;
    }
#endif

    rc = clGmsMutexCreate(&gms_instance_ptr->response_mutex);
    CL_ASSERT(rc == CL_OK);
#if 0    
    if(rc != CL_OK)
    {
        clHandleCheckin(gmsHandleDb, *gmsHandle);
        goto error_destroy;
    }
#endif

    /* Step 4: Negotiate version with the server */
    req.clientVersion.releaseCode = version->releaseCode;
    req.clientVersion.majorVersion= version->majorVersion;
    req.clientVersion.minorVersion= version->minorVersion;

    rc = cl_gms_clientlib_initialize_rmd(&req, 0x0 ,&res );
    if(rc != CL_OK )
    {
        clLogError(GEN,NA,"cl_gms_clientlib_initialize_rmd failed with rc:0x%x ",rc);
        clGmsMutexDelete(gms_instance_ptr->response_mutex);
        gms_instance_ptr->response_mutex = 0;
        clHandleCheckin(gmsHandleDb, *gmsHandle);
        rc = CL_GMS_RC(rc);
        goto error_destroy;
    }
    
    /* Step 5: Initialize instance entry */
    if (gmsCallbacks) 
    {
        memcpy(&gms_instance_ptr->callbacks, gmsCallbacks, sizeof(ClGmsCallbacksT));
    } 
    else 
    {
        memset(&gms_instance_ptr->callbacks, 0, sizeof(ClGmsCallbacksT));
    }

    memset(&gms_instance_ptr->cluster_notification_buffer, 0, sizeof(ClGmsClusterNotificationBufferT));
    memset(&gms_instance_ptr->group_notification_buffer, 0, sizeof(ClGmsGroupNotificationBufferT));

    /* Step 6: Decrement handle use count and return */
    if ((clHandleCheckin(gmsHandleDb, *gmsHandle)) != CL_OK)
    {
        clLogError(GEN,DB, "\nclHandleCheckin failed");
    }
    clHeapFree(res);
    return CL_OK;

    error_destroy:
    clHandleDestroy(gmsHandleDb, *gmsHandle);
    *gmsHandle = CL_HANDLE_INVALID_VALUE;

    //error_no_destroy:
    return rc;
}
ClRcT   clDispatchRegister(
        CL_OUT  ClHandleT*                      pDispatchHandle,
        CL_IN   ClHandleT                       svcInstanceHandle,
        CL_IN   ClDispatchCallbackT             wrapperCallback,
        CL_IN   ClDispatchQueueDestroyCallbackT queueDestroyCallback)
{
    ClRcT   rc = CL_OK;
    ClDispatchDbEntryT* thisDbEntry = NULL;
    ClFdT   fds[2] = {0};

    if (svcInstanceHandle == CL_HANDLE_INVALID_VALUE)
    {
        return CL_ERR_INVALID_PARAMETER;
    }

    if ((wrapperCallback == NULL) || (pDispatchHandle == NULL))
    {
        return CL_ERR_NULL_POINTER;
    }

    CHECK_LIB_INIT;

    /* Create the handle for this initialization of the library */
    rc = clHandleCreate (databaseHandle,
                         sizeof(ClDispatchDbEntryT),
                         pDispatchHandle);
    if (rc != CL_OK)
    {
        return rc;
    }
    CL_ASSERT (*pDispatchHandle != CL_HANDLE_INVALID_VALUE);

    /* Checkout the handle */
    rc = clHandleCheckout(databaseHandle, *pDispatchHandle, (void *)&thisDbEntry);

    if (rc != CL_OK)
    {
        return rc;
    }
    CL_ASSERT (thisDbEntry != NULL);

    /* Store SVC instance handle */
    thisDbEntry->svcInstanceHandle = svcInstanceHandle;
    thisDbEntry->svcCallback = wrapperCallback;
    thisDbEntry->queueDestroyCallback = queueDestroyCallback;

    /* Create the queue */
    rc = clQueueCreate(0x0,
                       clDispatchQueueDequeueCallback,
                       clDispatchQueueDestroyCallback,
                       &thisDbEntry->cbQueue);
    if (rc != CL_OK)
    {
        goto error_return;
    }

    /* Create Mutex to protect the queue */
    rc = clOsalMutexCreate(&thisDbEntry->dispatchMutex);
    if (rc != CL_OK)
    {
        goto error_return;
    }

    errno = 0;
    /* Create the pipe */
    ClInt32T ec = pipe(fds); // since return code for system call can be -ve
    if (ec < 0)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("Unable to create pipe: %s",strerror(errno)));
        rc = CL_ERR_LIBRARY;
        goto error_return;
    }
    /* 
     * Reinitialize rc to CL_OK as it would have changed with
     * above assignment
     */
    rc = CL_OK;

    thisDbEntry->readFd = fds[0];
    thisDbEntry->writeFd = fds[1];

    thisDbEntry->shouldDelete = CL_FALSE;

error_return:
    if ((clHandleCheckin(databaseHandle, *pDispatchHandle)) != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR,
                ("clHandleCheckin failed"));
    }
    return rc;
}
static ClRcT
clLogFlusherCookieHandleCreate(ClUint32T       numRecords,
                               ClTimerHandleT  *phTimer, 
                               ClHandleT       *phFlusher)
{
    ClRcT     rc   = CL_OK;
    ClLogFlushCookieT  *pFlushCookie = NULL;
    ClLogSvrEoDataT    *pSvrEoEntry  = NULL;
    ClTimerTimeOutT    timeout       = {0, 8000L};
    ClHandleT          *pTimerArg    = NULL;

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogSvrEoEntryGet(&pSvrEoEntry, NULL);
    if(  CL_OK != rc )
    {
        return rc;
    }    
    if( CL_FALSE == pSvrEoEntry->logInit )
    {
        clLogError("LOG", "FLS", "Log Service has terminated...");
        return CL_OK;
    }
    CL_LOG_DEBUG_TRACE(("hFlusherDB: %p ", (ClPtrT) pSvrEoEntry->hFlusherDB));

    rc = clHandleCreate(pSvrEoEntry->hFlusherDB, sizeof(ClLogFlushCookieT), 
                        phFlusher);
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "clHandleCreate(): rc[0x %x]", rc);
        return rc;
    }    
    pTimerArg = (ClHandleT*) clHeapCalloc(1, sizeof(ClHandleT));

    if( NULL == pTimerArg )
    {
    	clLogError("LOG", "FLS", "clHeapCalloc() : rc[0x %x]", rc);
        CL_LOG_CLEANUP(clHandleDestroy(pSvrEoEntry->hFlusherDB, *phFlusher),
                       CL_OK);
        return CL_LOG_RC(CL_ERR_NO_MEMORY);
    }

    *pTimerArg = *phFlusher;

    rc = clTimerCreateAndStart(timeout, CL_TIMER_ONE_SHOT, 
                               CL_TIMER_SEPARATE_CONTEXT, 
                               clLogFlusherTimerCallback,
                               (ClPtrT)(ClWordT) pTimerArg, phTimer);
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "clTimerCreate(): rc[0x %x]", rc);
        CL_LOG_CLEANUP(clHandleDestroy(pSvrEoEntry->hFlusherDB, *phFlusher),
                       CL_OK);
        clHeapFree(pTimerArg);
        return rc;
    }    

    rc = clHandleCheckout(pSvrEoEntry->hFlusherDB, *phFlusher, 
            (void **) &pFlushCookie);
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "clHandleCheckout(): rc[0x %x]", rc);
        CL_LOG_CLEANUP(clTimerDelete(phTimer), CL_OK);
        CL_LOG_CLEANUP(clHandleDestroy(pSvrEoEntry->hFlusherDB, *phFlusher),
                CL_OK);
        return rc;
    }    
    pFlushCookie->numRecords = numRecords;
    pFlushCookie->hTimer     = *phTimer;
    rc = clHandleCheckin(pSvrEoEntry->hFlusherDB, *phFlusher);
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "clHandleCheckin(): rc[0x %x]", rc);
        CL_LOG_CLEANUP(clTimerDelete(phTimer), CL_OK);
        CL_LOG_CLEANUP(clHandleDestroy(pSvrEoEntry->hFlusherDB, *phFlusher),
                CL_OK);
    }    

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}    
static ClRcT
clLogFileHdlrHandleCreate(ClLogHandleT       hLog,
                          ClBoolT            isDelete, 
                          ClUint32T          operatingLvl, 
                          ClLogClntFileKeyT  *pFileKey,
                          ClHandleT          *phFile)
{
    ClRcT                   rc            = CL_OK;
    ClBoolT                 entryAdd      = CL_FALSE;
    ClLogClntFileHdlrInfoT  *pData        = NULL;
    ClLogClntEoDataT        *pClntEoEntry = NULL;

    CL_LOG_DEBUG_TRACE(("Enter"));

    rc = clLogClntEoEntryGet(&pClntEoEntry);
    if( CL_OK != rc )
    {
        return rc;
    }

    rc = clHandleCreate(pClntEoEntry->hClntHandleDB, 
                        sizeof(ClLogClntFileHdlrInfoT), phFile);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clHandleCreate(); rc[0x %x]", rc));
        if( CL_TRUE == entryAdd )
        {
            CL_LOG_CLEANUP(clHandleDatabaseDestroy(pClntEoEntry->hClntHandleDB),
                           CL_OK);
        }
        return rc;
    }

    rc = clHandleCheckout(pClntEoEntry->hClntHandleDB, *phFile, 
                          (void **) &pData);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clHandleCheckout(): rc[0x %x]", rc));
        CL_LOG_CLEANUP(clHandleDestroy(pClntEoEntry->hClntHandleDB, *phFile),
                       CL_OK);
        if( CL_TRUE == entryAdd )
        {
            CL_LOG_CLEANUP(clHandleDatabaseDestroy(pClntEoEntry->hClntHandleDB),
                           CL_OK);
        }
        return rc;
    }
    pData->type         = CL_LOG_FILE_HANDLE;
    pData->isDelete     = isDelete;
    pData->startRead    = 0;
    pData->operatingLvl = operatingLvl;
    pData->hLog         = hLog;
    pData->pFileKey     = pFileKey; 

    rc = clHandleCheckin(pClntEoEntry->hClntHandleDB, *phFile);
    if( CL_OK != rc )
    {
        CL_LOG_DEBUG_ERROR(("clHandleCheckin(); rc[0x %x]", rc));
        CL_LOG_CLEANUP(clHandleDestroy(pClntEoEntry->hClntHandleDB, *phFile),
                       CL_OK);
        if( CL_TRUE == entryAdd )
        {
            CL_LOG_CLEANUP(clHandleDatabaseDestroy(pClntEoEntry->hClntHandleDB),
                           CL_OK);
        }
        return rc;
    }

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}
ClRcT clDebugRegister(ClDebugFuncEntryT  *funcArray,
                      ClUint32T          funcArrayLen,
                      ClHandleT          *phDebugReg)/* - by user - needs to be exposed*/
{
    ClRcT              rc          = CL_OK;
    ClDebugObjT        *pDebugObj  = NULL;
    ClUint32T          i           = 0;
    ClEoExecutionObjT  *pEoObj     = NULL; 
    ClDebugFuncGroupT  *pFuncGroup = NULL;

    if ((0 == funcArrayLen) || (NULL == funcArray))
    {
        clLogWrite(CL_LOG_HANDLE_APP,CL_LOG_WARNING,CL_DEBUG_LIB_CLIENT,
                   CL_LOG_MESSAGE_1_INVALID_PARAMETER,"Arguments are Invalid");
        return CL_DEBUG_RC(CL_ERR_INVALID_PARAMETER);
    }

    rc = clEoMyEoObjectGet(&pEoObj);
    if (CL_OK != rc)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clEoMyEoObjectGet(): rc[0x %x]",
                    rc));
        return rc;
    }
    rc = clEoPrivateDataGet( pEoObj,
                             CL_EO_DEBUG_OBJECT_COOKIE_ID,
                             (void**) &pDebugObj);
    if (CL_OK != rc)
    {
        return rc;
    }
    
     /* Detecting dupilcate entries are there or not */
    rc = clDebugDuplicateCommandDetect(pDebugObj, funcArray, funcArrayLen);
    if( CL_OK != rc )
    {
        return rc;
    }

    rc = clHandleCreate(pDebugObj->hDebugFnDB, sizeof(ClDebugFuncGroupT), phDebugReg);
    if( CL_OK != rc )
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clHandleCreate(): rc[0x %x]", rc));
        return rc;
    }

    rc = clHandleCheckout(pDebugObj->hDebugFnDB, *phDebugReg, 
                          (void **) &pFuncGroup);
    if( CL_OK != rc )
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clHandleCheckout(): rc[0x %x]", rc));
        clHandleDestroy(pDebugObj->hDebugFnDB, *phDebugReg);
        return rc;
    }

    pFuncGroup->pFuncDescList = clHeapAllocate(sizeof(ClDebugFuncEntryT) *
                                                         funcArrayLen);
    if (NULL == pFuncGroup->pFuncDescList)
    {
        clLogWrite(CL_LOG_HANDLE_APP,CL_LOG_CRITICAL,CL_DEBUG_LIB_CLIENT,
                   CL_LOG_MESSAGE_0_MEMORY_ALLOCATION_FAILED);
        clHandleCheckin(pDebugObj->hDebugFnDB, *phDebugReg);
        clHandleDestroy(pDebugObj->hDebugFnDB, *phDebugReg);
        return CL_DEBUG_RC(CL_ERR_NO_MEMORY);
    }

    for (i = 0; i < funcArrayLen; i++)
    {
         pFuncGroup->pFuncDescList[i] = funcArray[i];
    }

    pFuncGroup->numFunc = funcArrayLen;
    pDebugObj->numFunc += pFuncGroup->numFunc;
    if( CL_OK != (rc = clHandleCheckin(pDebugObj->hDebugFnDB, *phDebugReg)))
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clHandleCheckin(): rc[0x %x]", rc));
    }

    return CL_OK;
}