/**
 * This is a finalization API for transaction agent. This API must be called
 * during finalization of EO.
 */
ClRcT clTxnAgentFinalize()
{
    ClRcT rc = CL_OK;
    ClEoExecutionObjT   *pEOObj;


    CL_FUNC_ENTER();
    /* - Release all allocated memeory 
       FIXME: Check for active transaction, and try to consolidate
    */

    if (clTxnAgntCfg != NULL)
    {
        clTxnDbFini(clTxnAgntCfg->activeTxnMap);

        clCntDelete(clTxnAgntCfg->compServiceMap);
        clTxnMutexDelete(clTxnAgntCfg->actMtx);
        clHeapFree(clTxnAgntCfg);

        clTxnCommIfcFini();

        rc = clEoMyEoObjectGet(&pEOObj);
        clEoClientUninstallTables(pEOObj, 
                                 CL_EO_SERVER_SYM_MOD(gAspFuncTable, TXNAgent));

        clTxnAgntCfg = NULL;
    }
    CL_TXN_RETURN_RC(rc, ("Failed to finalize transaction-agent rc:0x%x\n", rc));
}
ClRcT clLogClientUninstall(void)
{
    ClEoExecutionObjT* pEoObj = NULL;
    ClRcT rc = CL_OK;

    rc = clEoMyEoObjectGet(&pEoObj);
    if (CL_OK != rc)
    {
        return rc;
    }
    rc = clOsalTaskKeyDelete(LogidlSyncKey);
    if (CL_OK != rc)
    {
        return rc;
    }
    rc = clHandleDatabaseDestroy(LogidlDatabaseHdl);
    if (CL_OK != rc)
    {
        return rc;
    }

    clEoClientUninstallTables(pEoObj,CL_EO_SERVER_SYM_MOD(gAspFuncTable,Log));

    return rc;
}
/*
 * This function clean up the information which is it has 
 * 1. Deregister with CPM. 
 * 2. Deregister with debug. 
 * 3. Deregister with CKPT
 * 4. Release the resources like Handle Databases, etc.
 */
ClRcT clEvtFinalize()
{
    ClRcT rc = CL_OK;


    CL_FUNC_ENTER();

    CL_EVT_INIT_DONE_VALIDATION();

    rc = clEoClientUninstallTables(gEvtHead.evtEOId, CL_EO_SERVER_SYM_MOD(gAspFuncTable, EVT));  
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_CRITICAL,
                       ("Event: EO Client Uninstall failed [0x%X]\n\r", rc));
        CL_FUNC_EXIT();
        return rc;
    }

    rc = clEventDebugDeregister(gEvtHead.evtEOId);
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_CRITICAL,
                       ("Event: Debug Deregister failed [0x%X]\n\r", rc));
        CL_FUNC_EXIT();
        return rc;
    }

    /*
     ** Handle Database Cleanup.
     */
    rc = clEvtHandleDatabaseExit();
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_CRITICAL,
                       ("Event: Handle Database Cleanup failed [0x%X]\n\r",
                        rc));
        CL_FUNC_EXIT();
        return rc;
    }

#ifdef CKPT_ENABLED
    /*
     ** Check Pointing Related Cleanup.
     */
    clEvtCkptExit();
    if (rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_CRITICAL,
                       ("Event Ckpt Exit failed [0x%X]\n\r", rc));
        CL_FUNC_EXIT();
        return rc;
    }
#endif

    CL_FUNC_EXIT();
    return CL_OK;
}
ClRcT clAmsTriggerRmdFinalize(void)
{
    ClRcT rc = CL_OK;
    rc = clEoClientUninstallTables(gAms.eoObject, 
                                   CL_EO_SERVER_SYM_MOD(gAspFuncTable, AMFTrigger));
    if(rc != CL_OK)
    {
        clLogError("TRIGGER", "RMD", "EO client uninstall returned [%#x]", rc);
        goto out;
    }
    out:
    return rc;
}
ClRcT clDebugLibFinalize(void)
{
    ClEoExecutionObjT  *pEoObj    = NULL; 
    ClDebugObjT        *pDebugObj = NULL;
    ClRcT              rc         = CL_OK;

    rc = clEoMyEoObjectGet(&pEoObj);
    if (CL_OK != rc)
    {
        return rc;
    }

    rc = clEoPrivateDataGet( pEoObj, CL_EO_DEBUG_OBJECT_COOKIE_ID,
                             (void**) &pDebugObj);
    if (CL_OK != rc)
    {
        return rc;
    }

    clEoDebugDeregister();

    if( CL_OK != (rc = clHandleDatabaseDestroy(pDebugObj->hDebugFnDB))) 
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clHandleDatabaseDestroy(): "
                       "rc[0x %x]", rc));
    }
    
    clDebugClientTableDeregister(pEoObj);

    if( CL_OK != (rc = clEoClientUninstallTables(pEoObj, CL_EO_SERVER_SYM_MOD(gAspFuncTable, DEBUGCli))) )
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clEoClientUninstall(): rc[0x %x]",
                    rc));
    }

    clHeapFree(pDebugObj);

    return rc;
}
ClRcT clEventClientUninstallTables(ClEoExecutionObjT *pEoObj)
{
    return clEoClientUninstallTables(pEoObj, CL_EO_SERVER_SYM_MOD(gAspCltFuncTable, EVT));
}
void clGmsServerTerminate(SaInvocationT invocation, const SaNameT *compName)
{

    ClRcT   rc = CL_OK;

    gmsGlobalInfo.opState = CL_GMS_STATE_SHUTING_DOWN;

    clLog(CRITICAL,GEN,NA, "Got termination request for component [%.*s]. Started Shutting Down...", compName->length,compName->value);
    
    rc = clEoClientUninstallTables (gmsGlobalInfo.gmsEoObject, CL_EO_SERVER_SYM_MOD(gAspFuncTable, GMS));
    if (rc != CL_OK)
    {
        clLog(ERROR,GEN,NA, "clEoClientUninstall failed with rc = 0x%x", rc);
    }
    /*
     * Unregister with AMF and respond to AMF saying whether the
     * termination was successful or not.
     */
    

    rc = clDebugDeregister(gGmsDebugReg);
    if (rc != CL_OK)
    {
        clLog(ERROR,GEN,NA, "clDebugDeregister failed with rc = 0x%x", rc);
    }

    /* Close the leader election algorithm dl if open */
#ifndef VXWORKS_BUILD 
    if (pluginHandle != NULL)
    {
        dlclose(pluginHandle);
    }
#endif

    if(gClTotemRunning)
    {
        /* We need to invoke openais finalize function instead of signal
         * handler here */
        totempg_finalize();

        /* Waiting for 10ms before invoking exit() */
        usleep(10000);
    }
    clLog(CRITICAL,GEN,NA,
          "GMS server exiting");

    rc = clHandleDatabaseDestroy(contextHandleDatabase);
    if (rc != CL_OK)
    {
        clLog(ERROR,GEN,NA,
                "contextHandleDatabase destroy failed with Rc = 0x%x",rc);
    }
    rc = saAmfComponentUnregister(amfHandle, compName, NULL);
    
    if(rc != SA_AIS_OK) 
    {
        clLog(ERROR,GEN,NA,
              "saAmfComponentUnregister failed with rc = 0x%x", rc);     
    }

    rc = saAmfFinalize(amfHandle);

    if (rc != SA_AIS_OK)
    {
        clLog(ERROR,GEN,NA,
              "saAmfFinalize failed with rc = 0x%x", rc);
    }
    /* Ok tell SAFplus that we handled it properly */
    rc = saAmfResponse(amfHandle, invocation, SA_AIS_OK);
    
    if (rc != SA_AIS_OK)
    {
        clLog(ERROR,GEN,NA,
              "clCpmResponse failed with rc = 0x%x", rc);
    }
    unblockNow = CL_TRUE;
}
/**
 * This is the agent initilaization API called during EO initialization.
 * 
 * Agent acts as intermediate layer during an active transaction. It receives
 * job-definition and commands from transaction manager and takes specific
 * action.
 */
ClRcT clTxnAgentInitialize(CL_IN ClEoExecutionObjT  *appEoObj, 
                           CL_IN ClVersionT         *pTxnVersion)
{
    ClRcT rc = CL_OK;

    CL_FUNC_ENTER();

    if ( (NULL == appEoObj) || (NULL == pTxnVersion) )
    {
        CL_FUNC_EXIT();
        return CL_TXN_RC(CL_ERR_NULL_POINTER);
    }

    /* Do version negotiation  (later part of RC-1 or RC-2) */
    if (clTxnVersionVerify(pTxnVersion) != CL_OK)
    {
        CL_FUNC_EXIT();
        return (CL_TXN_RC(CL_ERR_VERSION_MISMATCH));
    }

    clTxnAgntCfg = (ClTxnAgentCfgT *) clHeapAllocate( sizeof(ClTxnAgentCfgT));
    CL_TXN_NULL_CHECK_RETURN(clTxnAgntCfg, CL_ERR_NO_MEMORY, 
                             ("Failed to allocate memory\n"));
    memset(clTxnAgntCfg, 0, sizeof(ClTxnAgentCfgT));


    /* If possible, instead of statically registring RMD functions, txn-agent 
       could register EO client table here.
    */

    /* Create hash-maps for active-txn component-services */
    rc = clTxnDbInit( &(clTxnAgntCfg->activeTxnMap) );
    CL_TXN_ERR_RET_ON_ERROR(rc, ("Failed to allocate hash-map for active-txn rc:0x%x\n", rc));

    rc = clCntThreadSafeHashtblCreate(CL_TXN_NUM_BUCKETS, 
                            _clTxnCmpServiceKeyCompare, 
                            _clTxnCmpServiceHashFn, 
                            _clTxnCompServiceDelete, _clTxnCompServiceDelete, 
                            CL_CNT_UNIQUE_KEY,
                            (ClCntHandleT *) &clTxnAgntCfg->compServiceMap);
    CL_TXN_ERR_RET_ON_ERROR(rc, ("Failed to allocate hash-map for comp-service rc:0x%x\n", rc));

    clTxnMutexCreateAndLock(&clTxnAgntCfg->actMtx);
    /* No registered service */
    clTxnAgntCfg->agentCapability = CL_TXN_AGENT_NO_SERVICE_REGD;

    clTxnMutexUnlock(clTxnAgntCfg->actMtx);

    clLogInfo("AGT", NULL,
            "Installing function table");
    rc = clEoClientInstallTables(appEoObj, 
                                 CL_EO_SERVER_SYM_MOD(gAspFuncTable, TXNAgent));
    if (CL_OK == rc)
    {
        rc = clTxnCommIfcInit(&(clTxnMgmtVersionSupported[0]));
        if(CL_OK != rc)
        {
            clLogError("AGT", NULL, 
                    "Error in initiazing communication interface, rc [0x%x]", rc);
            clEoClientUninstallTables(appEoObj, 
                                 CL_EO_SERVER_SYM_MOD(gAspFuncTable, TXNAgent));
            return rc;
        }
    }

    if(CL_OK == rc)
    {
        rc = clTxnAgentTableRegister(appEoObj);
        if(CL_OK != rc)
        {
            clLogError("AGT", NULL, 
                    "Error in table registration, rc [0x%x]", rc);
            clEoClientUninstallTables(appEoObj, 
                                 CL_EO_SERVER_SYM_MOD(gAspFuncTable, TXNAgent));
        }
    }

    CL_FUNC_EXIT();
    return (rc);
}
ClRcT clDebugLibInitialize(void)
{
    ClEoExecutionObjT  *pEoObj     = NULL;
    ClDebugObjT        *pDebugObj  = NULL;
    ClRcT              rc          = CL_OK;
    ClNameT            compName    = {0};
    
    rc = clEoMyEoObjectGet(&pEoObj);
    if (CL_OK != rc)
    {
        return rc;
    }

    pDebugObj = clHeapCalloc(1, sizeof(ClDebugObjT));
    if (NULL == pDebugObj)
    {
        clLogWrite(CL_LOG_HANDLE_APP,CL_LOG_CRITICAL,CL_DEBUG_LIB_CLIENT,
                   CL_LOG_MESSAGE_0_MEMORY_ALLOCATION_FAILED);
        return CL_DEBUG_RC(CL_ERR_NO_MEMORY);
    }

    rc = clOsalTaskKeyCreate(&pDebugObj->debugTaskKey, NULL);
    if(rc != CL_OK)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Debug task key create returned with [%#x]\n", rc));
        clHeapFree(pDebugObj);
        return CL_DEBUG_RC(CL_GET_ERROR_CODE(rc));
    }

    rc = clHandleDatabaseCreate(NULL, &pDebugObj->hDebugFnDB);
    if( CL_OK != rc )
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clHandleDatabaseCreate(): rc[0x %x]",
                rc));
        clHeapFree(pDebugObj);
        return CL_DEBUG_RC(CL_ERR_NO_MEMORY);
    }

    /* Getting the compName from CPM */
    rc = clCpmComponentNameGet(0, &compName);
    if( CL_OK != rc )
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clCpmComponentNameGet(): rc[0x %x]",
                    rc));
        clLogWrite(CL_LOG_HANDLE_APP,CL_LOG_WARNING,CL_DEBUG_LIB_CLIENT,
                   CL_LOG_MESSAGE_1_INVALID_PARAMETER, 
                   "CompNameGet is not proper");
        return rc;
    }

    pDebugObj->numFunc       = 0;
    /* Assining the compName */
    memset(pDebugObj->compName, '\0', CL_DEBUG_COMP_NAME_LEN);
    if( compName.length < CL_DEBUG_COMP_NAME_LEN )
    {
        memcpy(pDebugObj->compName, compName.value, compName.length);
        pDebugObj->compName[compName.length] = '\0';
    }
    else
    {
        clLogWrite(CL_LOG_HANDLE_APP,CL_LOG_WARNING,CL_DEBUG_LIB_CLIENT,
                   CL_LOG_MESSAGE_1_INVALID_PARAMETER,"CompName is Invalid");
        return CL_DEBUG_RC(CL_ERR_INVALID_PARAMETER);
    }

    /* Assigning compPrompt to DEFAULT */
    memset(pDebugObj->compPrompt, '\0', CL_DEBUG_COMP_PROMPT_LEN);
    strcpy(pDebugObj->compPrompt, "DEFAULT");

    rc = clEoClientInstallTablesWithCookie( pEoObj, 
                                            CL_EO_SERVER_SYM_MOD(gAspFuncTable, DEBUGCli),
                                            pDebugObj);
    if (CL_OK != rc)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clEoClientInstall(): rc[0x %x]", rc));
        clHandleDatabaseDestroy(pDebugObj->hDebugFnDB);
        clHeapFree(pDebugObj);
        return rc;
    }
    rc = clDebugClientTableRegister(pEoObj);
    if(CL_OK != rc)
    {
        clEoClientUninstallTables(pEoObj, 
                                  CL_EO_SERVER_SYM_MOD(gAspFuncTable, DEBUGCli));
        clHandleDatabaseDestroy(pDebugObj->hDebugFnDB);
        clHeapFree(pDebugObj);
        return rc;
    }

    rc = clEoPrivateDataSet(pEoObj, CL_EO_DEBUG_OBJECT_COOKIE_ID, pDebugObj);
    if (CL_OK != rc)
    {
        CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clEoPrivateDataSet(): rc[0x %x]", rc));
        clEoClientUninstallTables(pEoObj, 
                                  CL_EO_SERVER_SYM_MOD(gAspFuncTable, DEBUGCli));
        clHandleDatabaseDestroy(pDebugObj->hDebugFnDB);
        clHeapFree(pDebugObj);
        return rc;
    }
    
    clEoDebugRegister();

    return rc;
}