diff options
Diffstat (limited to 'ndb/src/ndbapi/NdbConnection.cpp')
-rw-r--r-- | ndb/src/ndbapi/NdbConnection.cpp | 717 |
1 files changed, 376 insertions, 341 deletions
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp index ad415b8acbf..9a2995a957e 100644 --- a/ndb/src/ndbapi/NdbConnection.cpp +++ b/ndb/src/ndbapi/NdbConnection.cpp @@ -27,11 +27,12 @@ Description: Interface between TIS and NDB Documentation: Adjust: 971022 UABMNST First version. *****************************************************************************/ -#include "NdbOut.hpp" -#include "NdbConnection.hpp" -#include "NdbOperation.hpp" -#include "NdbScanOperation.hpp" -#include "NdbIndexOperation.hpp" +#include <NdbOut.hpp> +#include <NdbConnection.hpp> +#include <NdbOperation.hpp> +#include <NdbScanOperation.hpp> +#include <NdbIndexScanOperation.hpp> +#include <NdbIndexOperation.hpp> #include "NdbApiSignal.hpp" #include "TransporterFacade.hpp" #include "API.hpp" @@ -80,18 +81,16 @@ NdbConnection::NdbConnection( Ndb* aNdb ) : theTransactionIsStarted(false), theDBnode(0), theReleaseOnClose(false), - // Cursor operations + // Scan operations m_waitForReply(true), - m_theFirstCursorOperation(NULL), - m_theLastCursorOperation(NULL), - m_firstExecutedCursorOp(NULL), + m_theFirstScanOperation(NULL), + m_theLastScanOperation(NULL), + m_firstExecutedScanOp(NULL), // Scan operations - theScanFinished(0), - theCurrentScanRec(NULL), - thePreviousScanRec(NULL), theScanningOp(NULL), theBuddyConPtr(0xFFFFFFFF), - theBlobFlag(false) + theBlobFlag(false), + thePendingBlobOps(0) { theListState = NotInList; theError.code = 0; @@ -119,7 +118,6 @@ NdbConnection::init() theListState = NotInList; theInUseState = true; theTransactionIsStarted = false; - theScanFinished = 0; theNext = NULL; theFirstOpInList = NULL; @@ -130,9 +128,6 @@ NdbConnection::init() theFirstExecOpInList = NULL; theLastExecOpInList = NULL; - theCurrentScanRec = NULL; - thePreviousScanRec = NULL; - theCompletedFirstOp = NULL; theGlobalCheckpointId = 0; @@ -148,14 +143,15 @@ NdbConnection::init() theSimpleState = true; theSendStatus = InitState; theMagicNumber = 0x37412619; - // Cursor operations + // Scan operations m_waitForReply = true; - m_theFirstCursorOperation = NULL; - m_theLastCursorOperation = NULL; - m_firstExecutedCursorOp = 0; + m_theFirstScanOperation = NULL; + m_theLastScanOperation = NULL; + m_firstExecutedScanOp = 0; theBuddyConPtr = 0xFFFFFFFF; // theBlobFlag = false; + thePendingBlobOps = 0; }//NdbConnection::init() /***************************************************************************** @@ -203,6 +199,23 @@ NdbConnection::setErrorCode(int anErrorCode) theError.code = anErrorCode; }//NdbConnection::setErrorCode() +int +NdbConnection::restart(){ + if(theCompletionStatus == CompletedSuccess){ + releaseCompletedOperations(); + Uint64 tTransid = theNdb->theFirstTransId; + theTransactionId = tTransid; + if ((tTransid & 0xFFFFFFFF) == 0xFFFFFFFF) { + theNdb->theFirstTransId = (tTransid >> 32) << 32; + } else { + theNdb->theFirstTransId = tTransid + 1; + } + theCompletionStatus = NotCompleted; + return 0; + } + return -1; +} + /***************************************************************************** void handleExecuteCompletion(void); @@ -258,26 +271,34 @@ NdbConnection::execute(ExecType aTypeOfExec, if (! theBlobFlag) return executeNoBlobs(aTypeOfExec, abortOption, forceSend); - // execute prepared ops in batches, as requested by blobs + /* + * execute prepared ops in batches, as requested by blobs + * - blob error does not terminate execution + * - blob error sets error on operation + * - if error on operation skip blob calls + */ ExecType tExecType; NdbOperation* tPrepOp; + int ret = 0; do { tExecType = aTypeOfExec; tPrepOp = theFirstOpInList; while (tPrepOp != NULL) { - bool batch = false; - NdbBlob* tBlob = tPrepOp->theBlobList; - while (tBlob != NULL) { - if (tBlob->preExecute(tExecType, batch) == -1) - return -1; - tBlob = tBlob->theNext; - } - if (batch) { - // blob asked to execute all up to here now - tExecType = NoCommit; - break; + if (tPrepOp->theError.code == 0) { + bool batch = false; + NdbBlob* tBlob = tPrepOp->theBlobList; + while (tBlob != NULL) { + if (tBlob->preExecute(tExecType, batch) == -1) + ret = -1; + tBlob = tBlob->theNext; + } + if (batch) { + // blob asked to execute all up to here now + tExecType = NoCommit; + break; + } } tPrepOp = tPrepOp->next(); } @@ -293,26 +314,30 @@ NdbConnection::execute(ExecType aTypeOfExec, if (tExecType == Commit) { NdbOperation* tOp = theCompletedFirstOp; while (tOp != NULL) { - NdbBlob* tBlob = tOp->theBlobList; - while (tBlob != NULL) { - if (tBlob->preCommit() == -1) - return -1; - tBlob = tBlob->theNext; + if (tOp->theError.code == 0) { + NdbBlob* tBlob = tOp->theBlobList; + while (tBlob != NULL) { + if (tBlob->preCommit() == -1) + ret = -1; + tBlob = tBlob->theNext; + } } tOp = tOp->next(); } } if (executeNoBlobs(tExecType, abortOption, forceSend) == -1) - return -1; + ret = -1; { NdbOperation* tOp = theCompletedFirstOp; while (tOp != NULL) { - NdbBlob* tBlob = tOp->theBlobList; - while (tBlob != NULL) { - // may add new operations if batch - if (tBlob->postExecute(tExecType) == -1) - return -1; - tBlob = tBlob->theNext; + if (tOp->theError.code == 0) { + NdbBlob* tBlob = tOp->theBlobList; + while (tBlob != NULL) { + // may add new operations if batch + if (tBlob->postExecute(tExecType) == -1) + ret = -1; + tBlob = tBlob->theNext; + } } tOp = tOp->next(); } @@ -327,7 +352,7 @@ NdbConnection::execute(ExecType aTypeOfExec, } } while (theFirstOpInList != NULL || tExecType != aTypeOfExec); - return 0; + return ret; } int @@ -386,6 +411,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec, break; } } + thePendingBlobOps = 0; return 0; }//NdbConnection::execute() @@ -414,7 +440,7 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec, * Reset error.code on execute */ theError.code = 0; - NdbCursorOperation* tcOp = m_theFirstCursorOperation; + NdbScanOperation* tcOp = m_theFirstScanOperation; if (tcOp != 0){ // Execute any cursor operations while (tcOp != NULL) { @@ -423,14 +449,14 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec, if (tReturnCode == -1) { return; }//if - tcOp = (NdbCursorOperation*)tcOp->next(); + tcOp = (NdbScanOperation*)tcOp->next(); } // while - m_theLastCursorOperation->next(m_firstExecutedCursorOp); - m_firstExecutedCursorOp = m_theFirstCursorOperation; + 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_theFirstCursorOperation = m_theLastCursorOperation = NULL; + m_theFirstScanOperation = m_theLastScanOperation = NULL; } bool tTransactionIsStarted = theTransactionIsStarted; @@ -797,17 +823,14 @@ Remark: Release all operations. ******************************************************************************/ void NdbConnection::release(){ - if (theTransactionIsStarted == true && theScanningOp != NULL ) - stopScan(); - releaseOperations(); if ( (theTransactionIsStarted == true) && - ((theCommitStatus != Committed) && - (theCommitStatus != Aborted))) { -/**************************************************************************** - * The user did not perform any rollback but simply closed the - * transaction. We must rollback Ndb since Ndb have been contacted. -******************************************************************************/ + ((theCommitStatus != Committed) && + (theCommitStatus != Aborted))) { + /************************************************************************ + * The user did not perform any rollback but simply closed the + * transaction. We must rollback Ndb since Ndb have been contacted. + ************************************************************************/ execute(Rollback); }//if theMagicNumber = 0xFE11DC; @@ -839,8 +862,8 @@ void NdbConnection::releaseOperations() { // Release any open scans - releaseCursorOperations(m_theFirstCursorOperation); - releaseCursorOperations(m_firstExecutedCursorOp); + releaseScanOperations(m_theFirstScanOperation); + releaseScanOperations(m_firstExecutedScanOp); releaseOps(theCompletedFirstOp); releaseOps(theFirstOpInList); @@ -852,9 +875,9 @@ NdbConnection::releaseOperations() theLastOpInList = NULL; theLastExecOpInList = NULL; theScanningOp = NULL; - m_theFirstCursorOperation = NULL; - m_theLastCursorOperation = NULL; - m_firstExecutedCursorOp = NULL; + m_theFirstScanOperation = NULL; + m_theLastScanOperation = NULL; + m_firstExecutedScanOp = NULL; }//NdbConnection::releaseOperations() void @@ -865,24 +888,21 @@ NdbConnection::releaseCompletedOperations() }//NdbConnection::releaseOperations() /****************************************************************************** -void releaseCursorOperations(); +void releaseScanOperations(); Remark: Release all cursor operations. (NdbScanOperation and NdbIndexOperation) ******************************************************************************/ void -NdbConnection::releaseCursorOperations(NdbCursorOperation* cursorOp) +NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp) { while(cursorOp != 0){ - NdbCursorOperation* next = (NdbCursorOperation*)cursorOp->next(); + NdbIndexScanOperation* next = (NdbIndexScanOperation*)cursorOp->next(); cursorOp->release(); - if (cursorOp->cursorType() == NdbCursorOperation::ScanCursor) - theNdb->releaseScanOperation((NdbScanOperation*)cursorOp); - else - theNdb->releaseOperation(cursorOp); + theNdb->releaseScanOperation(cursorOp); cursorOp = next; } -}//NdbConnection::releaseCursorOperations() +}//NdbConnection::releaseScanOperations() /***************************************************************************** NdbOperation* getNdbOperation(const char* aTableName); @@ -916,45 +936,6 @@ NdbConnection::getNdbOperation(const char* aTableName) }//NdbConnection::getNdbOperation() /***************************************************************************** -NdbOperation* getNdbOperation(const char* anIndexName, const char* aTableName); - -Return Value Return a pointer to a NdbOperation object if getNdbOperation - was succesful. - Return NULL : In all other case. -Parameters: anIndexName : Name of the index to use. - aTableName : Name of the database table. -Remark: Get an operation from NdbOperation idlelist and get the - NdbConnection object - who was fetch by startTransaction pointing to this operation - getOperation will set the theTableId in the NdbOperation object. - synchronous -******************************************************************************/ -NdbOperation* -NdbConnection::getNdbOperation(const char* anIndexName, const char* aTableName) -{ - if ((theError.code == 0) && - (theCommitStatus == Started)){ - NdbIndexImpl* index = - theNdb->theDictionary->getIndex(anIndexName, aTableName); - NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName); - NdbTableImpl* indexTable = - theNdb->theDictionary->getIndexTable(index, table); - if (indexTable != 0){ - return getNdbOperation(indexTable); - } else { - setErrorCode(theNdb->theDictionary->getNdbError().code); - return NULL; - }//if - } else { - if (theError.code == 0) { - setOperationErrorCodeAbort(4114); - }//if - - return NULL; - }//if -}//NdbConnection::getNdbOperation() - -/***************************************************************************** NdbOperation* getNdbOperation(int aTableId); Return Value Return a pointer to a NdbOperation object if getNdbOperation @@ -1014,6 +995,14 @@ NdbConnection::getNdbOperation(NdbTableImpl * tab, NdbOperation* aNextOp) return NULL; }//NdbConnection::getNdbOperation() +NdbOperation* NdbConnection::getNdbOperation(NdbDictionary::Table * table) +{ + if (table) + return getNdbOperation(& NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbOperation() + // NdbScanOperation /***************************************************************************** NdbScanOperation* getNdbScanOperation(const char* aTableName); @@ -1033,7 +1022,7 @@ NdbConnection::getNdbScanOperation(const char* aTableName) if (tab != 0){ return getNdbScanOperation(tab); } else { - setOperationErrorCodeAbort(theNdb->theError.code); + setOperationErrorCodeAbort(theNdb->theDictionary->m_error.code); return NULL; }//if } @@ -1053,17 +1042,29 @@ Remark: Get an operation from NdbScanOperation idlelist and get the NdbC who was fetch by startTransaction pointing to this operation getOperation will set the theTableId in the NdbOperation object.synchronous ******************************************************************************/ -NdbScanOperation* -NdbConnection::getNdbScanOperation(const char* anIndexName, const char* aTableName) +NdbIndexScanOperation* +NdbConnection::getNdbIndexScanOperation(const char* anIndexName, + const char* aTableName) +{ + NdbIndexImpl* index = + theNdb->theDictionary->getIndex(anIndexName, aTableName); + NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName); + + return getNdbIndexScanOperation(index, table); +} + +NdbIndexScanOperation* +NdbConnection::getNdbIndexScanOperation(NdbIndexImpl* index, + NdbTableImpl* table) { if (theCommitStatus == Started){ - NdbIndexImpl* index = - theNdb->theDictionary->getIndex(anIndexName, aTableName); - NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName); - NdbTableImpl* indexTable = - theNdb->theDictionary->getIndexTable(index, table); + const NdbTableImpl * indexTable = index->getIndexTable(); if (indexTable != 0){ - return getNdbScanOperation(indexTable); + NdbIndexScanOperation* tOp = + getNdbScanOperation((NdbTableImpl *) indexTable); + tOp->m_currentTable = table; + if(tOp) tOp->m_cursor_type = NdbScanOperation::IndexCursor; + return tOp; } else { setOperationErrorCodeAbort(theNdb->theError.code); return NULL; @@ -1072,7 +1073,18 @@ NdbConnection::getNdbScanOperation(const char* anIndexName, const char* aTableNa setOperationErrorCodeAbort(4114); return NULL; -}//NdbConnection::getNdbScanOperation() +}//NdbConnection::getNdbIndexScanOperation() + +NdbIndexScanOperation* +NdbConnection::getNdbIndexScanOperation(NdbDictionary::Index * index, + NdbDictionary::Table * table) +{ + if (index && table) + return getNdbIndexScanOperation(& NdbIndexImpl::getImpl(*index), + & NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbIndexScanOperation() /***************************************************************************** NdbScanOperation* getNdbScanOperation(int aTableId); @@ -1084,21 +1096,21 @@ Remark: Get an operation from NdbScanOperation object idlelist and get t object who was fetch by startTransaction pointing to this operation getOperation will set the theTableId in the NdbOperation object, synchronous. *****************************************************************************/ -NdbScanOperation* +NdbIndexScanOperation* NdbConnection::getNdbScanOperation(NdbTableImpl * tab) { - NdbScanOperation* tOp; + NdbIndexScanOperation* tOp; tOp = theNdb->getScanOperation(); if (tOp == NULL) goto getNdbOp_error1; // Link scan operation into list of cursor operations - if (m_theLastCursorOperation == NULL) - m_theFirstCursorOperation = m_theLastCursorOperation = tOp; + if (m_theLastScanOperation == NULL) + m_theFirstScanOperation = m_theLastScanOperation = tOp; else { - m_theLastCursorOperation->next(tOp); - m_theLastCursorOperation = tOp; + m_theLastScanOperation->next(tOp); + m_theLastScanOperation = tOp; } tOp->next(NULL); if (tOp->init(tab, this) != -1) { @@ -1113,6 +1125,14 @@ getNdbOp_error1: return NULL; }//NdbConnection::getNdbScanOperation() +NdbScanOperation* +NdbConnection::getNdbScanOperation(NdbDictionary::Table * table) +{ + if (table) + return getNdbScanOperation(& NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbScanOperation() // IndexOperation @@ -1207,6 +1227,18 @@ NdbConnection::getNdbIndexOperation(NdbIndexImpl * anIndex, return NULL; }//NdbConnection::getNdbIndexOperation() +NdbIndexOperation* +NdbConnection::getNdbIndexOperation(NdbDictionary::Index * index, + NdbDictionary::Table * table) +{ + if (index && table) + return getNdbIndexOperation(& NdbIndexImpl::getImpl(*index), + & NdbTableImpl::getImpl(*table)); + else + return NULL; +}//NdbConnection::getNdbIndexOperation() + + /******************************************************************************* int receiveDIHNDBTAMPER(NdbApiSignal* aSignal) @@ -1323,12 +1355,16 @@ Remark: int NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf) { - if(theStatus != Connected){ - return -1; + if(checkState_TransId(&commitConf->transId1)){ + theCommitStatus = Committed; + theCompletionStatus = CompletedSuccess; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - theCommitStatus = Committed; - theCompletionStatus = CompletedSuccess; - return 0; + return -1; }//NdbConnection::receiveTC_COMMITCONF() /****************************************************************************** @@ -1342,33 +1378,43 @@ Remark: int NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal) { - if(theStatus != Connected){ - return -1; + const TcCommitRef * ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr()); + if(checkState_TransId(&ref->transId1)){ + setOperationErrorCodeAbort(ref->errorCode); + theCommitStatus = Aborted; + theCompletionStatus = CompletedFailure; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - const TcCommitRef * const ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr()); - setOperationErrorCodeAbort(ref->errorCode); - theCommitStatus = Aborted; - theCompletionStatus = CompletedFailure; - return 0; + + return -1; }//NdbConnection::receiveTC_COMMITREF() -/******************************************************************************* +/****************************************************************************** int receiveTCROLLBACKCONF(NdbApiSignal* aSignal); Return Value: Return 0 : receiveTCROLLBACKCONF was successful. Return -1: In all other case. Parameters: aSignal: The signal object pointer. Remark: -*******************************************************************************/ +******************************************************************************/ int NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal) { - if(theStatus != Connected){ - return -1; + if(checkState_TransId(aSignal->getDataPtr() + 1)){ + theCommitStatus = Aborted; + theCompletionStatus = CompletedSuccess; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - theCommitStatus = Aborted; - theCompletionStatus = CompletedSuccess; - return 0; + + return -1; }//NdbConnection::receiveTCROLLBACKCONF() /******************************************************************************* @@ -1382,13 +1428,18 @@ Remark: int NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal) { - if(theStatus != Connected){ - return -1; + if(checkState_TransId(aSignal->getDataPtr() + 1)){ + setOperationErrorCodeAbort(aSignal->readData(4)); + theCommitStatus = Aborted; + theCompletionStatus = CompletedFailure; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif } - setOperationErrorCodeAbort(aSignal->readData(2)); - theCommitStatus = Aborted; - theCompletionStatus = CompletedFailure; - return 0; + + return -1; }//NdbConnection::receiveTCROLLBACKREF() /***************************************************************************** @@ -1403,36 +1454,31 @@ Remark: Handles the reception of the ROLLBACKREP signal. int NdbConnection::receiveTCROLLBACKREP( NdbApiSignal* aSignal) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; - - if (theStatus != Connected) { - return -1; - }//if -/***************************************************************************** + /**************************************************************************** Check that we are expecting signals from this transaction and that it doesn't belong to a transaction already completed. Simply ignore messages from other transactions. -******************************************************************************/ - tTmp1 = aSignal->readData(2); - tTmp2 = aSignal->readData(3); - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if - theError.code = aSignal->readData(4); // Override any previous errors + ****************************************************************************/ + if(checkState_TransId(aSignal->getDataPtr() + 1)){ + theError.code = aSignal->readData(4);// Override any previous errors + + /**********************************************************************/ + /* A serious error has occured. This could be due to deadlock or */ + /* lack of resources or simply a programming error in NDB. This */ + /* transaction will be aborted. Actually it has already been */ + /* and we only need to report completion and return with the */ + /* error code to the application. */ + /**********************************************************************/ + theCompletionStatus = CompletedFailure; + theCommitStatus = Aborted; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } -/**********************************************************************/ -/* A serious error has occured. This could be due to deadlock or */ -/* lack of resources or simply a programming error in NDB. This */ -/* transaction will be aborted. Actually it has already been */ -/* and we only need to report completion and return with the */ -/* error code to the application. */ -/**********************************************************************/ - theCompletionStatus = CompletedFailure; - theCommitStatus = Aborted; - return 0; + return -1; }//NdbConnection::receiveTCROLLBACKREP() /******************************************************************************* @@ -1446,49 +1492,50 @@ Remark: int NdbConnection::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength) { - Uint64 tRecTransId; - NdbOperation* tOp; - Uint32 tConditionFlag; - + NdbReceiver* tOp; const Uint32 tTemp = keyConf->confInfo; - const Uint32 tTmp1 = keyConf->transId1; - const Uint32 tTmp2 = keyConf->transId2; -/****************************************************************************** + /*************************************************************************** Check that we are expecting signals from this transaction and that it doesn't belong to a transaction already completed. Simply ignore messages from other transactions. -******************************************************************************/ - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); + ***************************************************************************/ + if(checkState_TransId(&keyConf->transId1)){ - const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp); - const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); - tConditionFlag = (Uint32)(((aDataLength - 5) >> 1) - tNoOfOperations); - tConditionFlag |= (Uint32)(tNoOfOperations > 10); - tConditionFlag |= (Uint32)(tNoOfOperations <= 0); - tConditionFlag |= (Uint32)(theTransactionId - tRecTransId); - tConditionFlag |= (Uint32)(theStatus - Connected); + const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp); + const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); - if (tConditionFlag == 0) { const Uint32* tPtr = (Uint32 *)&keyConf->operations[0]; + Uint32 tNoComp = theNoOfOpCompleted; for (Uint32 i = 0; i < tNoOfOperations ; i++) { - tOp = theNdb->void2rec_op(theNdb->int2void(*tPtr)); + tOp = theNdb->void2rec(theNdb->int2void(*tPtr)); tPtr++; const Uint32 tAttrInfoLen = *tPtr; tPtr++; - if (tOp && tOp->checkMagicNumber() != -1) { - tOp->TCOPCONF(tAttrInfoLen); + if (tOp && tOp->checkMagicNumber()) { + tNoComp += tOp->execTCOPCONF(tAttrInfoLen); } else { return -1; }//if }//for - Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; + theNoOfOpCompleted = tNoComp; Uint32 tGCI = keyConf->gci; if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ + + + if (m_abortOption == IgnoreError && theError.code != 0){ + /** + * There's always a TCKEYCONF when using IgnoreError + */ +#ifdef VM_TRACE + ndbout_c("Not completing transaction 2"); +#endif + return -1; + } /**********************************************************************/ // We sent the transaction with Commit flag set and received a CONF with // no Commit flag set. This is clearly an anomaly. @@ -1502,7 +1549,12 @@ from other transactions. return 0; // No more operations to wait for }//if // Not completed the reception yet. - }//if + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } + return -1; }//NdbConnection::receiveTCKEYCONF() @@ -1518,50 +1570,50 @@ Remark: Handles the reception of the TCKEY_FAILCONF signal. int NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; NdbOperation* tOp; - if (theStatus != Connected) { - return -1; - }//if /* - Check that we are expecting signals from this transaction and that it - doesn't belong to a transaction already completed. Simply ignore - messages from other transactions. + Check that we are expecting signals from this transaction and that it + doesn't belong to a transaction already completed. Simply ignore + messages from other transactions. */ - tTmp1 = failConf->transId1; - tTmp2 = failConf->transId2; - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if - /* - A node failure of the TC node occured. The transaction has - been committed. - */ - theCommitStatus = Committed; - tOp = theFirstExecOpInList; - while (tOp != NULL) { + if(checkState_TransId(&failConf->transId1)){ /* - Check if the transaction expected read values... - If it did some of them might have gotten lost even if we succeeded - in committing the transaction. + A node failure of the TC node occured. The transaction has + been committed. */ - if (tOp->theAI_ElementLen != 0) { - theCompletionStatus = CompletedFailure; - setOperationErrorCodeAbort(4115); - break; - }//if - if (tOp->theCurrentRecAttr != NULL) { - theCompletionStatus = CompletedFailure; - setOperationErrorCodeAbort(4115); - break; - }//if - tOp = tOp->next(); - }//while - theReleaseOnClose = true; - return 0; + theCommitStatus = Committed; + tOp = theFirstExecOpInList; + while (tOp != NULL) { + /* + * Check if the transaction expected read values... + * If it did some of them might have gotten lost even if we succeeded + * in committing the transaction. + */ + switch(tOp->theOperationType){ + case NdbOperation::UpdateRequest: + case NdbOperation::InsertRequest: + case NdbOperation::DeleteRequest: + case NdbOperation::WriteRequest: + tOp = tOp->next(); + break; + case NdbOperation::ReadRequest: + case NdbOperation::ReadExclusive: + case NdbOperation::OpenScanRequest: + case NdbOperation::OpenRangeScanRequest: + theCompletionStatus = CompletedFailure; + setOperationErrorCodeAbort(4115); + tOp = NULL; + break; + }//if + }//while + theReleaseOnClose = true; + return 0; + } else { +#ifdef VM_TRACE + ndbout_c("Recevied TCKEY_FAILCONF wo/ operation"); +#endif + } + return -1; }//NdbConnection::receiveTCKEY_FAILCONF() /************************************************************************* @@ -1576,111 +1628,94 @@ Remark: Handles the reception of the TCKEY_FAILREF signal. int NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; - - if (theStatus != Connected) { - return -1; - }//if - /* - Check that we are expecting signals from this transaction and - that it doesn't belong to a transaction already - completed. Simply ignore messages from other transactions. - */ - tTmp1 = aSignal->readData(2); - tTmp2 = aSignal->readData(3); - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if /* - We received an indication of that this transaction was aborted due to a - node failure. + Check that we are expecting signals from this transaction and + that it doesn't belong to a transaction already + completed. Simply ignore messages from other transactions. */ - if (theSendStatus == sendTC_ROLLBACK) { + if(checkState_TransId(aSignal->getDataPtr()+1)){ /* - We were in the process of sending a rollback anyways. We will - report it as a success. + We received an indication of that this transaction was aborted due to a + node failure. */ - theCompletionStatus = CompletedSuccess; + if (theSendStatus == NdbConnection::sendTC_ROLLBACK) { + /* + We were in the process of sending a rollback anyways. We will + report it as a success. + */ + theCompletionStatus = NdbConnection::CompletedSuccess; + } else { + theCompletionStatus = NdbConnection::CompletedFailure; + theError.code = 4031; + }//if + theReleaseOnClose = true; + theCommitStatus = NdbConnection::Aborted; + return 0; } else { - theCompletionStatus = CompletedFailure; - theError.code = 4031; - }//if - theReleaseOnClose = true; - theCommitStatus = Aborted; - return 0; +#ifdef VM_TRACE + ndbout_c("Recevied TCKEY_FAILREF wo/ operation"); +#endif + } + return -1; }//NdbConnection::receiveTCKEY_FAILREF() -/******************************************************************************* +/****************************************************************************** int receiveTCINDXCONF(NdbApiSignal* aSignal, Uint32 long_short_ind); Return Value: Return 0 : receiveTCINDXCONF was successful. Return -1: In all other case. Parameters: aSignal: The signal object pointer. Remark: -*******************************************************************************/ +******************************************************************************/ int -NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf, Uint32 aDataLength) +NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf, + Uint32 aDataLength) { - Uint64 tRecTransId; - Uint32 tConditionFlag; - - const Uint32 tTemp = indxConf->confInfo; - const Uint32 tTmp1 = indxConf->transId1; - const Uint32 tTmp2 = indxConf->transId2; -/****************************************************************************** -Check that we are expecting signals from this transaction and that it -doesn't belong to a transaction already completed. Simply ignore messages -from other transactions. -******************************************************************************/ - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - - const Uint32 tNoOfOperations = TcIndxConf::getNoOfOperations(tTemp); - const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); - - tConditionFlag = (Uint32)(((aDataLength - 5) >> 1) - tNoOfOperations); - tConditionFlag |= (Uint32)(tNoOfOperations > 10); - tConditionFlag |= (Uint32)(tNoOfOperations <= 0); - tConditionFlag |= (Uint32)(theTransactionId - tRecTransId); - tConditionFlag |= (Uint32)(theStatus - Connected); - - if (tConditionFlag == 0) { + if(checkState_TransId(&indxConf->transId1)){ + const Uint32 tTemp = indxConf->confInfo; + const Uint32 tNoOfOperations = TcIndxConf::getNoOfOperations(tTemp); + const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp); + const Uint32* tPtr = (Uint32 *)&indxConf->operations[0]; + Uint32 tNoComp = theNoOfOpCompleted; for (Uint32 i = 0; i < tNoOfOperations ; i++) { - NdbIndexOperation* tOp = theNdb->void2rec_iop(theNdb->int2void(*tPtr)); + NdbReceiver* tOp = theNdb->void2rec(theNdb->int2void(*tPtr)); tPtr++; const Uint32 tAttrInfoLen = *tPtr; tPtr++; - if (tOp && tOp->checkMagicNumber() != -1) { - tOp->TCOPCONF(tAttrInfoLen); + if (tOp && tOp->checkMagicNumber()) { + tNoComp += tOp->execTCOPCONF(tAttrInfoLen); } else { return -1; }//if }//for - Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; Uint32 tGCI = indxConf->gci; + theNoOfOpCompleted = tNoComp; if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ -/**********************************************************************/ -// We sent the transaction with Commit flag set and received a CONF with -// no Commit flag set. This is clearly an anomaly. -/**********************************************************************/ + /**********************************************************************/ + // We sent the transaction with Commit flag set and received a CONF with + // no Commit flag set. This is clearly an anomaly. + /**********************************************************************/ theError.code = 4011; - theCompletionStatus = CompletedFailure; - theCommitStatus = Aborted; + theCompletionStatus = NdbConnection::CompletedFailure; + theCommitStatus = NdbConnection::Aborted; return 0; }//if if (tNoComp >= tNoSent) { return 0; // No more operations to wait for }//if // Not completed the reception yet. - }//if + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } + return -1; }//NdbConnection::receiveTCINDXCONF() @@ -1696,36 +1731,26 @@ Remark: Handles the reception of the TCINDXREF signal. int NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal) { - Uint64 tRecTransId, tCurrTransId; - Uint32 tTmp1, tTmp2; - - if (theStatus != Connected) { - return -1; - }//if -/***************************************************************************** -Check that we are expecting signals from this transaction and that it doesn't -belong to a transaction already completed. Simply ignore messages from other -transactions. -******************************************************************************/ - tTmp1 = aSignal->readData(2); - tTmp2 = aSignal->readData(3); - tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32); - tCurrTransId = this->getTransactionId(); - if (tCurrTransId != tRecTransId) { - return -1; - }//if - theError.code = aSignal->readData(4); // Override any previous errors + if(checkState_TransId(aSignal->getDataPtr()+1)){ + theError.code = aSignal->readData(4); // Override any previous errors + + /**********************************************************************/ + /* A serious error has occured. This could be due to deadlock or */ + /* lack of resources or simply a programming error in NDB. This */ + /* transaction will be aborted. Actually it has already been */ + /* and we only need to report completion and return with the */ + /* error code to the application. */ + /**********************************************************************/ + theCompletionStatus = NdbConnection::CompletedFailure; + theCommitStatus = NdbConnection::Aborted; + return 0; + } else { +#ifdef NDB_NO_DROPPED_SIGNAL + abort(); +#endif + } -/**********************************************************************/ -/* A serious error has occured. This could be due to deadlock or */ -/* lack of resources or simply a programming error in NDB. This */ -/* transaction will be aborted. Actually it has already been */ -/* and we only need to report completion and return with the */ -/* error code to the application. */ -/**********************************************************************/ - theCompletionStatus = CompletedFailure; - theCommitStatus = Aborted; - return 0; + return -1; }//NdbConnection::receiveTCINDXREF() /******************************************************************************* @@ -1741,7 +1766,7 @@ NdbConnection::OpCompleteFailure() { Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; - theCompletionStatus = CompletedFailure; + theCompletionStatus = NdbConnection::CompletedFailure; tNoComp++; theNoOfOpCompleted = tNoComp; if (tNoComp == tNoSent) { @@ -1752,8 +1777,18 @@ NdbConnection::OpCompleteFailure() //operation is not really part of that transaction. //------------------------------------------------------------------------ if (theSimpleState == 1) { - theCommitStatus = Aborted; + theCommitStatus = NdbConnection::Aborted; }//if + if (m_abortOption == IgnoreError){ + /** + * There's always a TCKEYCONF when using IgnoreError + */ +#ifdef VM_TRACE + ndbout_c("Not completing transaction"); +#endif + return -1; + } + return 0; // Last operation received } else if (tNoComp > tNoSent) { setOperationErrorCodeAbort(4113); // Too many operations, @@ -1780,7 +1815,7 @@ NdbConnection::OpCompleteSuccess() theNoOfOpCompleted = tNoComp; if (tNoComp == tNoSent) { // Last operation completed if (theSimpleState == 1) { - theCommitStatus = Committed; + theCommitStatus = NdbConnection::Committed; }//if return 0; } else if (tNoComp < tNoSent) { @@ -1788,7 +1823,7 @@ NdbConnection::OpCompleteSuccess() } else { setOperationErrorCodeAbort(4113); // Too many operations, // stop waiting for more - theCompletionStatus = CompletedFailure; + theCompletionStatus = NdbConnection::CompletedFailure; return 0; }//if }//NdbConnection::OpCompleteSuccess() @@ -1801,7 +1836,7 @@ Remark: Get global checkpoint identity of the transaction int NdbConnection::getGCI() { - if (theCommitStatus == Committed) { + if (theCommitStatus == NdbConnection::Committed) { return theGlobalCheckpointId; }//if return 0; |