diff --git a/ndb/include/ndbapi/NdbTransaction.hpp b/ndb/include/ndbapi/NdbTransaction.hpp index a6ba6a11c4d..257956d4fc2 100644 --- a/ndb/include/ndbapi/NdbTransaction.hpp +++ b/ndb/include/ndbapi/NdbTransaction.hpp @@ -657,8 +657,11 @@ private: // Release all cursor operations in connection void releaseOps(NdbOperation*); void releaseScanOperations(NdbIndexScanOperation*); + bool releaseScanOperation(NdbIndexScanOperation** listhead, + NdbIndexScanOperation** listtail, + NdbIndexScanOperation* op); void releaseExecutedScanOperation(NdbIndexScanOperation*); - + // Set the transaction identity of the transaction void setTransactionId(Uint64 aTransactionId); diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index c5a0ebbaf60..a644efe9406 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -678,9 +678,27 @@ void NdbScanOperation::close(bool forceSend, bool releaseOp) theNdbCon = NULL; m_transConnection = NULL; - if (releaseOp && tTransCon) { + if (tTransCon) + { NdbIndexScanOperation* tOp = (NdbIndexScanOperation*)this; - tTransCon->releaseExecutedScanOperation(tOp); + + bool ret = true; + if (theStatus != WaitResponse) + { + /** + * Not executed yet + */ + ret = + tTransCon->releaseScanOperation(&tTransCon->m_theFirstScanOperation, + &tTransCon->m_theLastScanOperation, + tOp); + } + else if (releaseOp) + { + ret = tTransCon->releaseScanOperation(&tTransCon->m_firstExecutedScanOp, + 0, tOp); + } + assert(ret); } tCon->theScanningOp = 0; diff --git a/ndb/src/ndbapi/NdbTransaction.cpp b/ndb/src/ndbapi/NdbTransaction.cpp index e82e02067a6..84a7ad568d7 100644 --- a/ndb/src/ndbapi/NdbTransaction.cpp +++ b/ndb/src/ndbapi/NdbTransaction.cpp @@ -978,28 +978,59 @@ void NdbTransaction::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp) { DBUG_ENTER("NdbTransaction::releaseExecutedScanOperation"); - DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp)) - - // here is one reason to make op lists doubly linked - if (m_firstExecutedScanOp == cursorOp) { - m_firstExecutedScanOp = (NdbIndexScanOperation*)cursorOp->theNext; - cursorOp->release(); - theNdb->releaseScanOperation(cursorOp); - } else if (m_firstExecutedScanOp != NULL) { - NdbIndexScanOperation* tOp = m_firstExecutedScanOp; - while (tOp->theNext != NULL) { - if (tOp->theNext == cursorOp) { - tOp->theNext = cursorOp->theNext; - cursorOp->release(); - theNdb->releaseScanOperation(cursorOp); - break; - } - tOp = (NdbIndexScanOperation*)tOp->theNext; - } - } + DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp)); + + releaseScanOperation(&m_firstExecutedScanOp, 0, cursorOp); + DBUG_VOID_RETURN; }//NdbTransaction::releaseExecutedScanOperation() +bool +NdbTransaction::releaseScanOperation(NdbIndexScanOperation** listhead, + NdbIndexScanOperation** listtail, + NdbIndexScanOperation* op) +{ + if (* listhead == op) + { + * listhead = (NdbIndexScanOperation*)op->theNext; + if (listtail && *listtail == op) + { + assert(* listhead == 0); + * listtail = 0; + } + + } + else + { + NdbIndexScanOperation* tmp = * listhead; + while (tmp != NULL) + { + if (tmp->theNext == op) + { + tmp->theNext = (NdbIndexScanOperation*)op->theNext; + if (listtail && *listtail == op) + { + assert(op->theNext == 0); + *listtail = tmp; + } + break; + } + tmp = (NdbIndexScanOperation*)tmp->theNext; + } + if (tmp == NULL) + op = NULL; + } + + if (op != NULL) + { + op->release(); + theNdb->releaseScanOperation(op); + return true; + } + + return false; +} + /***************************************************************************** NdbOperation* getNdbOperation(const char* aTableName);