📄 ndbtransaction.cpp
字号:
theFirstOpInList = tRestOp; else theLastOpInList->next(tRestOp); theLastOpInList = tLastOp; } assert(theFirstOpInList == NULL || tExecType == NoCommit); } while (theFirstOpInList != NULL || tExecType != aTypeOfExec); if (tCompletedFirstOp != NULL) { tCompletedLastOp->next(theCompletedFirstOp); theCompletedFirstOp = tCompletedFirstOp; if (theCompletedLastOp == NULL) theCompletedLastOp = tCompletedLastOp; }#if ndb_api_count_completed_ops_after_blob_execute { NdbOperation* tOp; unsigned n = 0; for (tOp = theCompletedFirstOp; tOp != NULL; tOp = tOp->next()) n++; ndbout << "completed ops: " << n << endl; }#endif if(savedError.code!=0 && theError.code==4350) // Trans already aborted theError= savedError; DBUG_RETURN(ret);}int NdbTransaction::executeNoBlobs(ExecType aTypeOfExec, AbortOption abortOption, int forceSend){ DBUG_ENTER("NdbTransaction::executeNoBlobs"); DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", aTypeOfExec, abortOption));//------------------------------------------------------------------------// We will start by preparing all operations in the transaction defined// since last execute or since beginning. If this works ok we will continue// by calling the poll with wait method. This method will return when// the NDB kernel has completed its task or when 10 seconds have passed.// The NdbTransactionCallBack-method will receive the return code of the// transaction. The normal methods of reading error codes still apply.//------------------------------------------------------------------------ Ndb* tNdb = theNdb; Uint32 timeout = TransporterFacade::instance()->m_waitfor_timeout; m_waitForReply = false; executeAsynchPrepare(aTypeOfExec, NULL, NULL, abortOption); if (m_waitForReply){ while (1) { int noOfComp = tNdb->sendPollNdb(3 * timeout, 1, forceSend); if (noOfComp == 0) { /** * This timeout situation can occur if NDB crashes. */ ndbout << "This timeout should never occur, execute(..)" << endl; setOperationErrorCodeAbort(4012); // Error code for "Cluster Failure" DBUG_RETURN(-1); }//if /* * Check that the completed transactions include this one. There * could be another thread running asynchronously. Even in pure * async case rollback is done synchronously. */ if (theListState != NotInList) continue;#ifdef VM_TRACE unsigned anyway = 0; for (unsigned i = 0; i < theNdb->theNoOfPreparedTransactions; i++) anyway += theNdb->thePreparedTransactionsArray[i] == this; for (unsigned i = 0; i < theNdb->theNoOfSentTransactions; i++) anyway += theNdb->theSentTransactionsArray[i] == this; for (unsigned i = 0; i < theNdb->theNoOfCompletedTransactions; i++) anyway += theNdb->theCompletedTransactionsArray[i] == this; if (anyway) { theNdb->printState("execute %x", this); abort(); }#endif if (theReturnStatus == ReturnFailure) { DBUG_RETURN(-1); }//if break; } } thePendingBlobOps = 0; DBUG_RETURN(0);}//NdbTransaction::execute()/*****************************************************************************void executeAsynchPrepare(ExecType aTypeOfExec, NdbAsynchCallback callBack, void* anyObject, CommitType aTypeOfCommit);Return Value: No return valueParameters : aTypeOfExec: Type of execute. anyObject: An object provided in the callback method callBack: The callback method aTypeOfCommit: What to do when read/updated/deleted records are missing or inserted records already exist.Remark: Prepare a part of a transaction in an asynchronous manner. *****************************************************************************/void NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec, NdbAsynchCallback aCallback, void* anyObject, AbortOption abortOption){ DBUG_ENTER("NdbTransaction::executeAsynchPrepare"); DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: %x, anyObject: %x", aTypeOfExec, aCallback, anyObject)); /** * Reset error.code on execute */ if (theError.code != 0) DBUG_PRINT("enter", ("Resetting error %d on execute", theError.code)); theError.code = 0; NdbScanOperation* tcOp = m_theFirstScanOperation; if (tcOp != 0){ // Execute any cursor operations while (tcOp != NULL) { int tReturnCode; tReturnCode = tcOp->executeCursor(theDBnode); if (tReturnCode == -1) { DBUG_VOID_RETURN; }//if tcOp = (NdbScanOperation*)tcOp->next(); } // while m_theLastScanOperation->next(m_firstExecutedScanOp); m_firstExecutedScanOp = m_theFirstScanOperation; // Discard cursor operations, since these are also // in the complete operations list we do not need // to release them. m_theFirstScanOperation = m_theLastScanOperation = NULL; } bool tTransactionIsStarted = theTransactionIsStarted; NdbOperation* tLastOp = theLastOpInList; Ndb* tNdb = theNdb; CommitStatusType tCommitStatus = theCommitStatus; Uint32 tnoOfPreparedTransactions = tNdb->theNoOfPreparedTransactions; theReturnStatus = ReturnSuccess; theCallbackFunction = aCallback; theCallbackObject = anyObject; m_abortOption = abortOption; m_waitForReply = true; tNdb->thePreparedTransactionsArray[tnoOfPreparedTransactions] = this; theTransArrayIndex = tnoOfPreparedTransactions; theListState = InPreparedList; tNdb->theNoOfPreparedTransactions = tnoOfPreparedTransactions + 1; if ((tCommitStatus != Started) || (aTypeOfExec == Rollback)) {/***************************************************************************** * Rollback have been ordered on a started transaction. Call rollback. * Could also be state problem or previous problem which leads to the * same action. ****************************************************************************/ if (aTypeOfExec == Rollback) { if (theTransactionIsStarted == false || theSimpleState) { theCommitStatus = Aborted; theSendStatus = sendCompleted; } else { theSendStatus = sendABORT; } } else { theSendStatus = sendABORTfail; }//if if (theCommitStatus == Aborted){ DBUG_PRINT("exit", ("theCommitStatus: Aborted")); setErrorCode(4350); } DBUG_VOID_RETURN; }//if if (tTransactionIsStarted == true) { if (tLastOp != NULL) { if (aTypeOfExec == Commit) {/***************************************************************************** * Set commit indicator on last operation when commit has been ordered * and also a number of operations.******************************************************************************/ tLastOp->theCommitIndicator = 1; }//if } else { if (aTypeOfExec == Commit && !theSimpleState) { /********************************************************************** * A Transaction have been started and no more operations exist. * We will use the commit method. *********************************************************************/ theSendStatus = sendCOMMITstate; DBUG_VOID_RETURN; } else { /********************************************************************** * We need to put it into the array of completed transactions to * ensure that we report the completion in a proper way. * We cannot do this here since that would endanger the completed * transaction array since that is also updated from the receiver * thread and thus we need to do it under mutex lock and thus we * set the sendStatus to ensure that the send method will * put it into the completed array. **********************************************************************/ theSendStatus = sendCompleted; DBUG_VOID_RETURN; // No Commit with no operations is OK }//if }//if } else if (tTransactionIsStarted == false) { NdbOperation* tFirstOp = theFirstOpInList; if (tLastOp != NULL) { tFirstOp->setStartIndicator(); if (aTypeOfExec == Commit) { tLastOp->theCommitIndicator = 1; }//if } else { /*********************************************************************** * No operations are defined and we have not started yet. * Simply return OK. Set commit status if Commit. ***********************************************************************/ if (aTypeOfExec == Commit) { theCommitStatus = Committed; }//if /*********************************************************************** * We need to put it into the array of completed transactions to * ensure that we report the completion in a proper way. We * cannot do this here since that would endanger the completed * transaction array since that is also updated from the * receiver thread and thus we need to do it under mutex lock * and thus we set the sendStatus to ensure that the send method * will put it into the completed array. ***********************************************************************/ theSendStatus = sendCompleted; DBUG_VOID_RETURN; }//if } NdbOperation* tOp = theFirstOpInList; theCompletionStatus = NotCompleted; while (tOp) { int tReturnCode; NdbOperation* tNextOp = tOp->next(); tReturnCode = tOp->prepareSend(theTCConPtr, theTransactionId); if (tReturnCode == -1) { theSendStatus = sendABORTfail; DBUG_VOID_RETURN; }//if /************************************************************************* * Now that we have successfully prepared the send of this operation we * move it to the list of executing operations and remove it from the * list of defined operations. ************************************************************************/ tOp = tNextOp; } NdbOperation* tLastOpInList = theLastOpInList; NdbOperation* tFirstOpInList = theFirstOpInList; theFirstOpInList = NULL; theLastOpInList = NULL; theFirstExecOpInList = tFirstOpInList; theLastExecOpInList = tLastOpInList; theCompletionStatus = CompletedSuccess; theNoOfOpSent = 0; theNoOfOpCompleted = 0; theSendStatus = sendOperations; NdbNodeBitmask::clear(m_db_nodes); NdbNodeBitmask::clear(m_failed_db_nodes); DBUG_VOID_RETURN;}//NdbTransaction::executeAsynchPrepare()void NdbTransaction::close(){ theNdb->closeTransaction(this);}int NdbTransaction::refresh(){ return sendTC_HBREP();}/*****************************************************************************int sendTC_HBREP();Return Value: No return value. Parameters : None.Remark: Order NDB to refresh the timeout counter of the transaction. ******************************************************************************/int NdbTransaction::sendTC_HBREP() // Send a TC_HBREP signal;{ NdbApiSignal* tSignal; Ndb* tNdb = theNdb; Uint32 tTransId1, tTransId2; tSignal = tNdb->getSignal(); if (tSignal == NULL) { return -1; } if (tSignal->setSignal(GSN_TC_HBREP) == -1) { return -1; } TcHbRep * const tcHbRep = CAST_PTR(TcHbRep, tSignal->getDataPtrSend()); tcHbRep->apiConnectPtr = theTCConPtr; tTransId1 = (Uint32) theTransactionId; tTransId2 = (Uint32) (theTransactionId >> 32); tcHbRep->transId1 = tTransId1; tcHbRep->transId2 = tTransId2; TransporterFacade *tp = TransporterFacade::instance(); tp->lock_mutex(); const int res = tp->sendSignal(tSignal,theDBnode); tp->unlock_mutex(); tNdb->releaseSignal(tSignal); if (res == -1){ return -1; } return 0;}//NdbTransaction::sendTC_HBREP()/*****************************************************************************int doSend();Return Value: Return 0 : send was successful. Return -1: In all other case. Remark: Send all operations belonging to this connection. The caller of this method has the responsibility to remove the object from the prepared transactions array on the Ndb-object.*****************************************************************************/intNdbTransaction::doSend(){ DBUG_ENTER("NdbTransaction::doSend"); /* This method assumes that at least one operation have been defined. This is ensured by the caller of this routine (=execute). */ switch(theSendStatus){ case sendOperations: { NdbOperation * tOp = theFirstExecOpInList; do { NdbOperation* tNextOp = tOp->next(); const Uint32 lastFlag = ((tNextOp == NULL) ? 1 : 0); const int tReturnCode = tOp->doSend(theDBnode, lastFlag); if (tReturnCode == -1) { theReturnStatus = ReturnFailure; break; }//if tOp = tNextOp; } while (tOp != NULL); Ndb* tNdb = theNdb; theSendStatus = sendTC_OP; theTransactionIsStarted = true; tNdb->insert_sent_list(this); DBUG_RETURN(0); }//case case sendABORT: case sendABORTfail:{ /*********************************************************************** * Rollback have been ordered on a not started transaction. * Simply return OK and set abort status. ***********************************************************************/ if (theSendStatus == sendABORTfail) { theReturnStatus = ReturnFailure; }//if if (sendROLLBACK() == 0) { DBUG_RETURN(0); }//if break; }//case case sendCOMMITstate: if (sendCOMMIT() == 0) { DBUG_RETURN(0); }//if break; case sendCompleted: theNdb->insert_completed_list(this);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -