/** * 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)); }
/** * Internal function to pack/prepare state oa given transaction */ static ClRcT _clTxnServiceCkptTxnPack( CL_IN ClUint32T dataSetId, CL_OUT ClAddrT *ppData, CL_OUT ClUint32T *pDataLen, CL_IN ClPtrT cookie) { ClRcT rc = CL_OK; ClTxnDefnT *pTxnDefn; ClBufferHandleT txnStateBuf; ClUint32T msgLen; CL_FUNC_ENTER(); pTxnDefn = (ClTxnDefnT *) cookie; if (pTxnDefn == NULL) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Null argument")); CL_FUNC_EXIT(); return (CL_ERR_NULL_POINTER); } CL_DEBUG_PRINT(CL_DEBUG_TRACE, ("Packing for data-set 0x%x for txn[0x%x:0x%x]", dataSetId, pTxnDefn->serverTxnId.txnMgrNodeAddress, pTxnDefn->serverTxnId.txnId)); /* Validate between dataSetId and txn-Id */ #if 0 if ( (dataSetId - CL_TXN_CKPT_TXN_DATA_SET_ID_OFFSET) != pTxnId->txnId) { CL_TXN_RETURN_RC(CL_ERR_INVALID_PARAMETER, ("Invalid data-set(0x%x) for transaction-id(0x%x)\n", dataSetId, pTxnId->txnId)); } #endif rc = clBufferCreate (&txnStateBuf); if (CL_OK == rc) { rc = clTxnStreamTxnCfgInfoPack (pTxnDefn, txnStateBuf); *ppData = NULL; *pDataLen = 0; if (CL_OK == rc) { /* Copy the state-information from message-buffer to ppData */ rc = clBufferLengthGet(txnStateBuf, &msgLen); } if (CL_OK == rc) { *pDataLen = msgLen; *ppData = (ClInt8T *) clHeapAllocate(msgLen); if ( *ppData == NULL ) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Failed to allocate memory")); rc = CL_ERR_NO_MEMORY; } } if (CL_OK == rc) { rc = clBufferNBytesRead(txnStateBuf, (ClUint8T *) *ppData, &msgLen); if (CL_OK != rc) { clHeapFree(*ppData); *pDataLen = 0x0; CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Failed to pack/serialize txn-defn[0x%x:0x%x] for ckpt. rc:0x%x", pTxnDefn->serverTxnId.txnMgrNodeAddress, pTxnDefn->serverTxnId.txnId, rc)); rc = CL_GET_ERROR_CODE(rc); } } rc = clBufferDelete(&txnStateBuf); } CL_FUNC_EXIT(); return (rc); }
/** * API to un-register a service with transaction-agent */ ClRcT clTxnAgentServiceUnRegister(CL_IN ClTxnAgentServiceHandleT tHandle) { ClRcT rc = CL_OK; ClUint8T twoPC = 0; ClTxnAgentCompServiceInfoT *pCompService = NULL; CL_FUNC_ENTER(); if (tHandle == 0x0) { CL_FUNC_EXIT(); return CL_TXN_RC(CL_ERR_INVALID_HANDLE); } /* This is a request from service hosted in the component to unregister from the transaction-management. Remove the entry from the data-structure and invalidate the handle FIXME: Before actually deleting it, check to see if this service is part of any active txn or not */ rc = clCntDataForKeyGet(clTxnAgntCfg->compServiceMap, (ClCntKeyHandleT) &(((ClTxnAgentCompServiceInfoT *)tHandle)->serviceType), (ClCntDataHandleT *)&pCompService); if (CL_OK == rc) { ClUint32T srvCount; if (pCompService->serviceCapability == CL_TXN_AGENT_SERVICE_1PC) { twoPC = 0; clTxnAgntCfg->agentCapability &= ~(CL_TXN_AGENT_SERVICE_1PC); } else if(pCompService->serviceCapability == CL_TXN_AGENT_SERVICE_2PC) { twoPC = 1; } rc = clCntAllNodesForKeyDelete(clTxnAgntCfg->compServiceMap, (ClCntKeyHandleT) &(((ClTxnAgentCompServiceInfoT *)tHandle)->serviceType)); if(CL_OK != rc) { clLogError("AGT", NULL, "Failed to delete node from compServiceMap corresponding to service[%d]", ((ClTxnAgentCompServiceInfoT *)tHandle)->serviceType); return rc; } /* Reset agent capability, if necessary */ rc = clCntSizeGet(clTxnAgntCfg->compServiceMap, &srvCount); if ( (CL_OK == rc) && (srvCount == 0x0) ) { clTxnAgntCfg->agentCapability = CL_TXN_AGENT_NO_SERVICE_REGD; } else if ( (CL_OK == rc) && (srvCount == 0x1) && ( (clTxnAgntCfg->agentCapability & CL_TXN_AGENT_SERVICE_1PC) == CL_TXN_AGENT_SERVICE_1PC) ) { clTxnAgntCfg->agentCapability = CL_TXN_AGENT_SERVICE_1PC; } else if ( CL_OK != rc ) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Error while reading number of service registered. rc:0x%x", rc)); } } if(CL_OK == rc) clLogNotice("AGT", "FIN", "Unregistering [%s] service successfull", twoPC ? "2PC":"READ"); CL_TXN_RETURN_RC(rc, ("Failed to unregister component-service rc:0x%x\n", rc)); }
/** * API to register a service with transaction agent */ ClRcT clTxnAgentServiceRegister( CL_IN ClInt32T serviceId, CL_IN ClTxnAgentCallbacksT tCallback, CL_OUT ClTxnAgentServiceHandleT *pHandle) { /* This is registration request from a service hosted in this component. (There could be multiple such services). Store these callbacks in an appropriate data-structure indexed with service-id (identication of service under considered). */ ClRcT rc = CL_OK; ClUint8T serviceCapability = 0xFF; ClTxnAgentCompServiceInfoT *pNewCompService = NULL; CL_FUNC_ENTER(); CL_TXN_NULL_CHECK_RETURN(pHandle, CL_ERR_NULL_POINTER, ("Invalid handle\n")); if (NULL == clTxnAgntCfg) { clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_ERROR, CL_TXN_AGENT_LIB, CL_LOG_MESSAGE_0_COMPONENT_UNINITIALIZED); CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Agent library is not initialized. clTxnAgntCfg is NULL\n")); CL_FUNC_EXIT(); return CL_TXN_RC(CL_ERR_NOT_INITIALIZED); } /* Validate callback function */ if( (tCallback.fpTxnAgentJobPrepare == NULL) && (tCallback.fpTxnAgentJobRollback == NULL) && (tCallback.fpTxnAgentJobCommit != NULL) ) { serviceCapability = CL_TXN_AGENT_SERVICE_1PC; clTxnMutexLock(clTxnAgntCfg->actMtx); /* Check if this is not the first one to declare as 1-PC Capable service */ if ( (clTxnAgntCfg->agentCapability & CL_TXN_AGENT_SERVICE_1PC) == CL_TXN_AGENT_SERVICE_1PC) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Txn-Agent does not allow more than one service of 1-PC Type")); CL_FUNC_EXIT(); clTxnMutexUnlock(clTxnAgntCfg->actMtx); return CL_TXN_RC(CL_ERR_INVALID_PARAMETER); } clTxnMutexUnlock(clTxnAgntCfg->actMtx); } else if ( (tCallback.fpTxnAgentJobPrepare != NULL) && (tCallback.fpTxnAgentJobCommit != NULL) && (tCallback.fpTxnAgentJobRollback != NULL) ) { serviceCapability = CL_TXN_AGENT_SERVICE_2PC; } else { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Invalid parameter - callback function not defined properly")); CL_FUNC_EXIT(); return CL_TXN_RC(CL_ERR_INVALID_PARAMETER); } /* Check if entry already exists or not */ rc = clCntDataForKeyGet( (ClCntHandleT) clTxnAgntCfg->compServiceMap, (ClCntKeyHandleT) &serviceId, (ClCntDataHandleT *) &pNewCompService); if ( CL_OK == rc ) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Component-service already registered\n")); CL_FUNC_EXIT(); return (CL_TXN_RC(CL_ERR_DUPLICATE)); } pNewCompService = (ClTxnAgentCompServiceInfoT *) clHeapAllocate(sizeof(ClTxnAgentCompServiceInfoT)); CL_TXN_NULL_CHECK_RETURN(pNewCompService, CL_ERR_NO_MEMORY, ("Failed to allocate memory\n")); memset(pNewCompService, 0, sizeof(ClTxnAgentCompServiceInfoT)); pNewCompService->serviceType = serviceId; pNewCompService->serviceCapability = serviceCapability; pNewCompService->pCompCallbacks = (ClTxnAgentCallbacksT *) clHeapAllocate(sizeof(ClTxnAgentCallbacksT)); CL_TXN_NULL_CHECK_RETURN(pNewCompService->pCompCallbacks, CL_ERR_NO_MEMORY, ("Failed to allocate memory\n")); memcpy(pNewCompService->pCompCallbacks, &tCallback, sizeof(ClTxnAgentCallbacksT)); /* Put the entry into hash-map with service-id to be the key */ rc = clCntNodeAdd(clTxnAgntCfg->compServiceMap, (ClCntKeyHandleT) &(pNewCompService->serviceType), (ClCntDataHandleT)pNewCompService, NULL); if (CL_OK != rc) { clHeapFree(pNewCompService->pCompCallbacks); clHeapFree(pNewCompService); } else { /* Update agent-cfg */ if (serviceCapability == CL_TXN_AGENT_SERVICE_1PC) { #ifdef CL_TXN_DEBUG CL_DEBUG_PRINT(CL_DEBUG_ERROR,( "Service registered is 1pc\n")); #endif clTxnAgntCfg->agentCapability |= CL_TXN_AGENT_SERVICE_1PC; } else clTxnAgntCfg->agentCapability |= CL_TXN_AGENT_SERVICE_2PC; *pHandle = (ClTxnAgentServiceHandleT )pNewCompService; clLogNotice("AGT", "INI", "Registered [%s] service successfully having serviceId [%d]", (serviceCapability == CL_TXN_AGENT_SERVICE_1PC)?"READ": "2P", serviceId); } CL_TXN_RETURN_RC(rc, ("Failed to register new component-service rc:0x%x\n", rc)); }