NdbConnection.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:68k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <ndb_global.h>
  14. #include <NdbOut.hpp>
  15. #include <NdbConnection.hpp>
  16. #include <NdbOperation.hpp>
  17. #include <NdbScanOperation.hpp>
  18. #include <NdbIndexScanOperation.hpp>
  19. #include <NdbIndexOperation.hpp>
  20. #include "NdbApiSignal.hpp"
  21. #include "TransporterFacade.hpp"
  22. #include "API.hpp"
  23. #include "NdbBlob.hpp"
  24. #include <ndb_limits.h>
  25. #include <signaldata/TcKeyConf.hpp>
  26. #include <signaldata/TcIndx.hpp>
  27. #include <signaldata/TcCommit.hpp>
  28. #include <signaldata/TcKeyFailConf.hpp>
  29. #include <signaldata/TcHbRep.hpp>
  30. /*****************************************************************************
  31. NdbConnection( Ndb* aNdb );
  32. Return Value:  None
  33. Parameters:    aNdb: Pointers to the Ndb object 
  34. Remark:        Creates a connection object. 
  35. *****************************************************************************/
  36. NdbConnection::NdbConnection( Ndb* aNdb ) :
  37.   theSendStatus(NotInit),
  38.   theCallbackFunction(NULL),
  39.   theCallbackObject(NULL),
  40.   theTransArrayIndex(0),
  41.   theStartTransTime(0),
  42.   theErrorLine(0),
  43.   theErrorOperation(NULL),
  44.   theNdb(aNdb),
  45.   theNext(NULL),
  46.   theFirstOpInList(NULL),
  47.   theLastOpInList(NULL),
  48.   theFirstExecOpInList(NULL),
  49.   theLastExecOpInList(NULL),
  50.   theCompletedFirstOp(NULL),
  51.   theCompletedLastOp(NULL),
  52.   theNoOfOpSent(0),
  53.   theNoOfOpCompleted(0),
  54.   theNoOfOpFetched(0),
  55.   theMyRef(0),
  56.   theTCConPtr(0),
  57.   theTransactionId(0),
  58.   theGlobalCheckpointId(0),
  59.   theStatus(NotConnected),
  60.   theCompletionStatus(NotCompleted), 
  61.   theCommitStatus(NotStarted),
  62.   theMagicNumber(0xFE11DC),
  63.   theTransactionIsStarted(false),
  64.   theDBnode(0),
  65.   theReleaseOnClose(false),
  66.   // Scan operations
  67.   m_waitForReply(true),
  68.   m_theFirstScanOperation(NULL),
  69.   m_theLastScanOperation(NULL),
  70.   m_firstExecutedScanOp(NULL),
  71.   // Scan operations
  72.   theScanningOp(NULL),
  73.   theBuddyConPtr(0xFFFFFFFF),
  74.   theBlobFlag(false),
  75.   thePendingBlobOps(0)
  76. {
  77.   theListState = NotInList;
  78.   theError.code = 0;
  79.   theId = theNdb->theImpl->theNdbObjectIdMap.map(this);
  80. #define CHECK_SZ(mask, sz) assert((sizeof(mask)/sizeof(mask[0])) == sz)
  81.   CHECK_SZ(m_db_nodes, NdbNodeBitmask::Size);
  82.   CHECK_SZ(m_failed_db_nodes, NdbNodeBitmask::Size);
  83. }//NdbConnection::NdbConnection()
  84. /*****************************************************************************
  85. ~NdbConnection();
  86. Remark:        Deletes the connection object. 
  87. *****************************************************************************/
  88. NdbConnection::~NdbConnection()
  89. {
  90.   DBUG_ENTER("NdbConnection::~NdbConnection");
  91.   theNdb->theImpl->theNdbObjectIdMap.unmap(theId, this);
  92.   DBUG_VOID_RETURN;
  93. }//NdbConnection::~NdbConnection()
  94. /*****************************************************************************
  95. void init();
  96. Remark:         Initialise connection object for new transaction. 
  97. *****************************************************************************/
  98. void
  99. NdbConnection::init()
  100. {
  101.   theListState            = NotInList;
  102.   theInUseState           = true;
  103.   theTransactionIsStarted = false;
  104.   theNext   = NULL;
  105.   theFirstOpInList   = NULL;
  106.   theLastOpInList   = NULL;
  107.   theScanningOp            = NULL;
  108.   theFirstExecOpInList   = NULL;
  109.   theLastExecOpInList   = NULL;
  110.   theCompletedFirstOp   = NULL;
  111.   theCompletedLastOp   = NULL;
  112.   theGlobalCheckpointId   = 0;
  113.   theCommitStatus         = Started;
  114.   theCompletionStatus     = NotCompleted;
  115.   m_abortOption           = AbortOnError;
  116.   theError.code   = 0;
  117.   theErrorLine   = 0;
  118.   theErrorOperation   = NULL;
  119.   theReleaseOnClose       = false;
  120.   theSimpleState          = true;
  121.   theSendStatus           = InitState;
  122.   theMagicNumber          = 0x37412619;
  123.   // Scan operations
  124.   m_waitForReply            = true;
  125.   m_theFirstScanOperation = NULL;
  126.   m_theLastScanOperation  = NULL;
  127.   m_firstExecutedScanOp   = 0;
  128.   theBuddyConPtr            = 0xFFFFFFFF;
  129.   //
  130.   theBlobFlag = false;
  131.   thePendingBlobOps = 0;
  132. }//NdbConnection::init()
  133. /*****************************************************************************
  134. setOperationErrorCode(int error);
  135. Remark:        Sets an error code on the connection object from an 
  136.                operation object. 
  137. *****************************************************************************/
  138. void
  139. NdbConnection::setOperationErrorCode(int error)
  140. {
  141.   DBUG_ENTER("NdbConnection::setOperationErrorCode");
  142.   setErrorCode(error);
  143.   DBUG_VOID_RETURN;
  144. }
  145. /*****************************************************************************
  146. setOperationErrorCodeAbort(int error);
  147. Remark:        Sets an error code on the connection object from an 
  148.                operation object. 
  149. *****************************************************************************/
  150. void
  151. NdbConnection::setOperationErrorCodeAbort(int error, int abortOption)
  152. {
  153.   DBUG_ENTER("NdbConnection::setOperationErrorCodeAbort");
  154.   if (abortOption == -1)
  155.     abortOption = m_abortOption;
  156.   if (theTransactionIsStarted == false) {
  157.     theCommitStatus = Aborted;
  158.   } else if ((abortOption == AbortOnError) && 
  159.      (theCommitStatus != Committed) &&
  160.              (theCommitStatus != Aborted)) {
  161.     theCommitStatus = NeedAbort;
  162.   }//if
  163.   setErrorCode(error);
  164.   DBUG_VOID_RETURN;
  165. }
  166. /*****************************************************************************
  167. setErrorCode(int anErrorCode);
  168. Remark:        Sets an error indication on the connection object. 
  169. *****************************************************************************/
  170. void
  171. NdbConnection::setErrorCode(int error)
  172. {
  173.   DBUG_ENTER("NdbConnection::setErrorCode");
  174.   DBUG_PRINT("enter", ("error: %d, theError.code: %d", error, theError.code));
  175.   if (theError.code == 0)
  176.     theError.code = error;
  177.   DBUG_VOID_RETURN;
  178. }//NdbConnection::setErrorCode()
  179. int
  180. NdbConnection::restart(){
  181.   DBUG_ENTER("NdbConnection::restart");
  182.   if(theCompletionStatus == CompletedSuccess){
  183.     releaseCompletedOperations();
  184.     Uint64 tTransid = theNdb->theFirstTransId;
  185.     theTransactionId = tTransid;
  186.     if ((tTransid & 0xFFFFFFFF) == 0xFFFFFFFF) {
  187.       theNdb->theFirstTransId = (tTransid >> 32) << 32;
  188.     } else {
  189.       theNdb->theFirstTransId = tTransid + 1;
  190.     }
  191.     theCommitStatus = Started;
  192.     theCompletionStatus = NotCompleted;
  193.     theTransactionIsStarted = false;
  194.     DBUG_RETURN(0);
  195.   }
  196.   DBUG_PRINT("error",("theCompletionStatus != CompletedSuccess"));
  197.   DBUG_RETURN(-1);
  198. }
  199. /*****************************************************************************
  200. void handleExecuteCompletion(void);
  201. Remark:        Handle time-out on a transaction object. 
  202. *****************************************************************************/
  203. void
  204. NdbConnection::handleExecuteCompletion()
  205. {
  206.   
  207.   if (theCompletionStatus == CompletedFailure) {
  208.     NdbOperation* tOpTemp = theFirstExecOpInList;
  209.     while (tOpTemp != NULL) {
  210. /*****************************************************************************
  211.  * Ensure that all executing operations report failed for each 
  212.  *      read attribute when failure occurs. 
  213.  *      We do not want any operations to report both failure and 
  214.  *      success on different read attributes.
  215.  ****************************************************************************/
  216.       tOpTemp->handleFailedAI_ElemLen();
  217.       tOpTemp = tOpTemp->next();
  218.     }//while
  219.     theReturnStatus = ReturnFailure;
  220.   }//if
  221.   /***************************************************************************
  222.    *   Move the NdbOperation objects from the list of executing 
  223.    *      operations to list of completed
  224.    **************************************************************************/
  225.   NdbOperation* tFirstExecOp = theFirstExecOpInList;
  226.   NdbOperation* tLastExecOp = theLastExecOpInList;
  227.   if (tLastExecOp != NULL) {
  228.     tLastExecOp->next(theCompletedFirstOp);
  229.     theCompletedFirstOp = tFirstExecOp;
  230.     if (theCompletedLastOp == NULL)
  231.       theCompletedLastOp = tLastExecOp;
  232.     theFirstExecOpInList = NULL;
  233.     theLastExecOpInList = NULL;
  234.   }//if
  235.   theSendStatus = InitState;
  236.   return;
  237. }//NdbConnection::handleExecuteCompletion()
  238. /*****************************************************************************
  239. int execute(ExecType aTypeOfExec, CommitType aTypeOfCommit, int forceSend);
  240. Return Value:  Return 0 : execute was successful.
  241.                Return -1: In all other case.  
  242. Parameters :   aTypeOfExec: Type of execute.
  243. Remark:        Initialise connection object for new transaction. 
  244. *****************************************************************************/
  245. int 
  246. NdbConnection::execute(ExecType aTypeOfExec, 
  247.        AbortOption abortOption,
  248.        int forceSend)
  249. {
  250.   NdbError savedError= theError;
  251.   DBUG_ENTER("NdbConnection::execute");
  252.   DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", 
  253.        aTypeOfExec, abortOption));
  254.   if (! theBlobFlag)
  255.     DBUG_RETURN(executeNoBlobs(aTypeOfExec, abortOption, forceSend));
  256.   /*
  257.    * execute prepared ops in batches, as requested by blobs
  258.    * - blob error does not terminate execution
  259.    * - blob error sets error on operation
  260.    * - if error on operation skip blob calls
  261.    */
  262.   ExecType tExecType;
  263.   NdbOperation* tPrepOp;
  264.   NdbOperation* tCompletedFirstOp = NULL;
  265.   NdbOperation* tCompletedLastOp = NULL;
  266.   int ret = 0;
  267.   do {
  268.     tExecType = aTypeOfExec;
  269.     tPrepOp = theFirstOpInList;
  270.     while (tPrepOp != NULL) {
  271.       if (tPrepOp->theError.code == 0) {
  272.         bool batch = false;
  273.         NdbBlob* tBlob = tPrepOp->theBlobList;
  274.         while (tBlob != NULL) {
  275.           if (tBlob->preExecute(tExecType, batch) == -1)
  276.   {
  277.             ret = -1;
  278.     if(savedError.code==0)
  279.       savedError= theError;
  280.   }
  281.           tBlob = tBlob->theNext;
  282.         }
  283.         if (batch) {
  284.           // blob asked to execute all up to here now
  285.           tExecType = NoCommit;
  286.           break;
  287.         }
  288.       }
  289.       tPrepOp = tPrepOp->next();
  290.     }
  291.     // save rest of prepared ops if batch
  292.     NdbOperation* tRestOp= 0;
  293.     NdbOperation* tLastOp= 0;
  294.     if (tPrepOp != NULL) {
  295.       tRestOp = tPrepOp->next();
  296.       tPrepOp->next(NULL);
  297.       tLastOp = theLastOpInList;
  298.       theLastOpInList = tPrepOp;
  299.     }
  300.     if (tExecType == Commit) {
  301.       NdbOperation* tOp = theCompletedFirstOp;
  302.       while (tOp != NULL) {
  303.         if (tOp->theError.code == 0) {
  304.           NdbBlob* tBlob = tOp->theBlobList;
  305.           while (tBlob != NULL) {
  306.             if (tBlob->preCommit() == -1)
  307.     {
  308.       ret = -1;
  309.       if(savedError.code==0)
  310. savedError= theError;
  311.     }
  312.             tBlob = tBlob->theNext;
  313.           }
  314.         }
  315.         tOp = tOp->next();
  316.       }
  317.     }
  318.     // completed ops are in unspecified order
  319.     if (theCompletedFirstOp != NULL) {
  320.       if (tCompletedFirstOp == NULL) {
  321.         tCompletedFirstOp = theCompletedFirstOp;
  322.         tCompletedLastOp = theCompletedLastOp;
  323.       } else {
  324.         tCompletedLastOp->next(theCompletedFirstOp);
  325.         tCompletedLastOp = theCompletedLastOp;
  326.       }
  327.       theCompletedFirstOp = NULL;
  328.       theCompletedLastOp = NULL;
  329.     }
  330.     if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
  331.     {
  332.       ret = -1;
  333.       if(savedError.code==0)
  334. savedError= theError;
  335.     }
  336. #ifdef ndb_api_crash_on_complex_blob_abort
  337.     assert(theFirstOpInList == NULL && theLastOpInList == NULL);
  338. #else
  339.     theFirstOpInList = theLastOpInList = NULL;
  340. #endif
  341.     {
  342.       NdbOperation* tOp = theCompletedFirstOp;
  343.       while (tOp != NULL) {
  344.         if (tOp->theError.code == 0) {
  345.           NdbBlob* tBlob = tOp->theBlobList;
  346.           while (tBlob != NULL) {
  347.             // may add new operations if batch
  348.             if (tBlob->postExecute(tExecType) == -1)
  349.     {
  350.               ret = -1;
  351.       if(savedError.code==0)
  352. savedError= theError;
  353.     }
  354.             tBlob = tBlob->theNext;
  355.           }
  356.         }
  357.         tOp = tOp->next();
  358.       }
  359.     }
  360.     // add saved prepared ops if batch
  361.     if (tPrepOp != NULL && tRestOp != NULL) {
  362.       if (theFirstOpInList == NULL)
  363.         theFirstOpInList = tRestOp;
  364.       else
  365.         theLastOpInList->next(tRestOp);
  366.       theLastOpInList = tLastOp;
  367.     }
  368.     assert(theFirstOpInList == NULL || tExecType == NoCommit);
  369.   } while (theFirstOpInList != NULL || tExecType != aTypeOfExec);
  370.   if (tCompletedFirstOp != NULL) {
  371.     tCompletedLastOp->next(theCompletedFirstOp);
  372.     theCompletedFirstOp = tCompletedFirstOp;
  373.     if (theCompletedLastOp == NULL)
  374.       theCompletedLastOp = tCompletedLastOp;
  375.   }
  376. #if ndb_api_count_completed_ops_after_blob_execute
  377.   { NdbOperation* tOp; unsigned n = 0;
  378.     for (tOp = theCompletedFirstOp; tOp != NULL; tOp = tOp->next()) n++;
  379.     ndbout << "completed ops: " << n << endl;
  380.   }
  381. #endif
  382.   if(savedError.code!=0 && theError.code==4350) // Trans already aborted
  383.       theError= savedError;
  384.   DBUG_RETURN(ret);
  385. }
  386. int 
  387. NdbConnection::executeNoBlobs(ExecType aTypeOfExec, 
  388.                               AbortOption abortOption,
  389.                               int forceSend)
  390. {
  391.   DBUG_ENTER("NdbConnection::executeNoBlobs");
  392.   DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", 
  393.        aTypeOfExec, abortOption));
  394. //------------------------------------------------------------------------
  395. // We will start by preparing all operations in the transaction defined
  396. // since last execute or since beginning. If this works ok we will continue
  397. // by calling the poll with wait method. This method will return when
  398. // the NDB kernel has completed its task or when 10 seconds have passed.
  399. // The NdbConnectionCallBack-method will receive the return code of the
  400. // transaction. The normal methods of reading error codes still apply.
  401. //------------------------------------------------------------------------
  402.   Ndb* tNdb = theNdb;
  403.   m_waitForReply = false;
  404.   executeAsynchPrepare(aTypeOfExec, NULL, NULL, abortOption);
  405.   if (m_waitForReply){
  406.     while (1) {
  407.       int noOfComp = tNdb->sendPollNdb((3 * WAITFOR_RESPONSE_TIMEOUT),
  408.                                        1, forceSend);
  409.       if (noOfComp == 0) {
  410.         /** 
  411.          * This timeout situation can occur if NDB crashes.
  412.          */
  413.         ndbout << "This timeout should never occur, execute(..)" << endl;
  414.         setOperationErrorCodeAbort(4012);  // Error code for "Cluster Failure"
  415.         DBUG_RETURN(-1);
  416.       }//if
  417.       /*
  418.        * Check that the completed transactions include this one.  There
  419.        * could be another thread running asynchronously.  Even in pure
  420.        * async case rollback is done synchronously.
  421.        */
  422.       if (theListState != NotInList)
  423.         continue;
  424. #ifdef VM_TRACE
  425.       unsigned anyway = 0;
  426.       for (unsigned i = 0; i < theNdb->theNoOfPreparedTransactions; i++)
  427.         anyway += theNdb->thePreparedTransactionsArray[i] == this;
  428.       for (unsigned i = 0; i < theNdb->theNoOfSentTransactions; i++)
  429.         anyway += theNdb->theSentTransactionsArray[i] == this;
  430.       for (unsigned i = 0; i < theNdb->theNoOfCompletedTransactions; i++)
  431.         anyway += theNdb->theCompletedTransactionsArray[i] == this;
  432.       if (anyway) {
  433.         theNdb->printState("execute %x", this);
  434.         abort();
  435.       }
  436. #endif
  437.       if (theReturnStatus == ReturnFailure) {
  438.         DBUG_RETURN(-1);
  439.       }//if
  440.       break;
  441.     }
  442.   }
  443.   thePendingBlobOps = 0;
  444.   DBUG_RETURN(0);
  445. }//NdbConnection::execute()
  446. /*****************************************************************************
  447. void executeAsynchPrepare(ExecType           aTypeOfExec,
  448.                           NdbAsynchCallback  callBack,
  449.                           void*              anyObject,
  450.                           CommitType         aTypeOfCommit);
  451. Return Value:  No return value
  452. Parameters :   aTypeOfExec:   Type of execute.
  453.                anyObject:     An object provided in the callback method
  454.                callBack:      The callback method
  455.                aTypeOfCommit: What to do when read/updated/deleted records 
  456.                               are missing or inserted records already exist.
  457. Remark:        Prepare a part of a transaction in an asynchronous manner. 
  458. *****************************************************************************/
  459. void 
  460. NdbConnection::executeAsynchPrepare( ExecType           aTypeOfExec,
  461.                                      NdbAsynchCallback  aCallback,
  462.                                      void*              anyObject,
  463.                                      AbortOption abortOption)
  464. {
  465.   DBUG_ENTER("NdbConnection::executeAsynchPrepare");
  466.   DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: %x, anyObject: %x", 
  467.        aTypeOfExec, aCallback, anyObject));
  468.   /**
  469.    * Reset error.code on execute
  470.    */
  471.   if (theError.code != 0)
  472.     DBUG_PRINT("enter", ("Resetting error %d on execute", theError.code));
  473.   theError.code = 0;
  474.   NdbScanOperation* tcOp = m_theFirstScanOperation;
  475.   if (tcOp != 0){
  476.     // Execute any cursor operations
  477.     while (tcOp != NULL) {
  478.       int tReturnCode;
  479.       tReturnCode = tcOp->executeCursor(theDBnode);
  480.       if (tReturnCode == -1) {
  481.         DBUG_VOID_RETURN;
  482.       }//if
  483.       tcOp = (NdbScanOperation*)tcOp->next();
  484.     } // while
  485.     m_theLastScanOperation->next(m_firstExecutedScanOp);
  486.     m_firstExecutedScanOp = m_theFirstScanOperation;
  487.     // Discard cursor operations, since these are also
  488.     // in the complete operations list we do not need
  489.     // to release them.
  490.     m_theFirstScanOperation = m_theLastScanOperation = NULL;
  491.   }
  492.   bool tTransactionIsStarted = theTransactionIsStarted;
  493.   NdbOperation* tLastOp = theLastOpInList;
  494.   Ndb* tNdb = theNdb;
  495.   CommitStatusType tCommitStatus = theCommitStatus;
  496.   Uint32 tnoOfPreparedTransactions = tNdb->theNoOfPreparedTransactions;
  497.   theReturnStatus     = ReturnSuccess;
  498.   theCallbackFunction = aCallback;
  499.   theCallbackObject   = anyObject;
  500.   m_abortOption   = abortOption;
  501.   m_waitForReply = true;
  502.   tNdb->thePreparedTransactionsArray[tnoOfPreparedTransactions] = this;
  503.   theTransArrayIndex = tnoOfPreparedTransactions;
  504.   theListState = InPreparedList;
  505.   tNdb->theNoOfPreparedTransactions = tnoOfPreparedTransactions + 1;
  506.   if ((tCommitStatus != Started) ||
  507.       (aTypeOfExec == Rollback)) {
  508. /*****************************************************************************
  509.  * Rollback have been ordered on a started transaction. Call rollback.
  510.  *      Could also be state problem or previous problem which leads to the 
  511.  *      same action.
  512.  ****************************************************************************/
  513.     if (aTypeOfExec == Rollback) {
  514.       if (theTransactionIsStarted == false || theSimpleState) {
  515. theCommitStatus = Aborted;
  516. theSendStatus = sendCompleted;
  517.       } else {
  518. theSendStatus = sendABORT;
  519.       }
  520.     } else {
  521.       theSendStatus = sendABORTfail;
  522.     }//if
  523.     if (theCommitStatus == Aborted){
  524.       DBUG_PRINT("exit", ("theCommitStatus: Aborted"));
  525.       setErrorCode(4350);
  526.     }
  527.     DBUG_VOID_RETURN;
  528.   }//if
  529.   if (tTransactionIsStarted == true) {
  530.     if (tLastOp != NULL) {
  531.       if (aTypeOfExec == Commit) {
  532. /*****************************************************************************
  533.  * Set commit indicator on last operation when commit has been ordered
  534.  *      and also a number of operations.
  535. ******************************************************************************/
  536.         tLastOp->theCommitIndicator = 1;
  537.       }//if
  538.     } else {
  539.       if (aTypeOfExec == Commit && !theSimpleState) {
  540. /**********************************************************************
  541.  *   A Transaction have been started and no more operations exist. 
  542.  *   We will use the commit method.
  543.  *********************************************************************/
  544.         theSendStatus = sendCOMMITstate;
  545. DBUG_VOID_RETURN;
  546.       } else {
  547. /**********************************************************************
  548.  * We need to put it into the array of completed transactions to 
  549.  * ensure that we report the completion in a proper way. 
  550.  * We cannot do this here since that would endanger the completed
  551.  * transaction array since that is also updated from the receiver 
  552.  * thread and thus we need to do it under mutex lock and thus we 
  553.  * set the sendStatus to ensure that the send method will
  554.  * put it into the completed array.
  555.  **********************************************************************/
  556.         theSendStatus = sendCompleted;
  557. DBUG_VOID_RETURN; // No Commit with no operations is OK
  558.       }//if
  559.     }//if
  560.   } else if (tTransactionIsStarted == false) {
  561.     NdbOperation* tFirstOp = theFirstOpInList;
  562.     if (tLastOp != NULL) {
  563.       tFirstOp->setStartIndicator();
  564.       if (aTypeOfExec == Commit) {
  565.         tLastOp->theCommitIndicator = 1;
  566.       }//if
  567.     } else {
  568.       /***********************************************************************
  569.        *    No operations are defined and we have not started yet. 
  570.        *    Simply return OK. Set commit status if Commit.
  571.        ***********************************************************************/
  572.       if (aTypeOfExec == Commit) {
  573.         theCommitStatus = Committed;
  574.       }//if
  575.       /***********************************************************************
  576.        * We need to put it into the array of completed transactions to
  577.        * ensure that we report the completion in a proper way. We
  578.        * cannot do this here since that would endanger the completed
  579.        * transaction array since that is also updated from the
  580.        * receiver thread and thus we need to do it under mutex lock
  581.        * and thus we set the sendStatus to ensure that the send method
  582.        * will put it into the completed array.
  583.        ***********************************************************************/
  584.       theSendStatus = sendCompleted;
  585.       DBUG_VOID_RETURN;
  586.     }//if
  587.   }
  588.   NdbOperation* tOp = theFirstOpInList;
  589.   theCompletionStatus = NotCompleted;
  590.   while (tOp) {
  591.     int tReturnCode;
  592.     NdbOperation* tNextOp = tOp->next();
  593.     tReturnCode = tOp->prepareSend(theTCConPtr, theTransactionId);
  594.     if (tReturnCode == -1) {
  595.       theSendStatus = sendABORTfail;
  596.       DBUG_VOID_RETURN;
  597.     }//if
  598.     /*************************************************************************
  599.      * Now that we have successfully prepared the send of this operation we 
  600.      * move it to the list of executing operations and remove it from the 
  601.      * list of defined operations.
  602.      ************************************************************************/
  603.     tOp = tNextOp;
  604.   } 
  605.   NdbOperation* tLastOpInList = theLastOpInList;
  606.   NdbOperation* tFirstOpInList = theFirstOpInList;
  607.   theFirstOpInList = NULL;
  608.   theLastOpInList = NULL;
  609.   theFirstExecOpInList = tFirstOpInList;
  610.   theLastExecOpInList = tLastOpInList;
  611.   theCompletionStatus = CompletedSuccess;
  612.   theNoOfOpSent = 0;
  613.   theNoOfOpCompleted = 0;
  614.   theSendStatus = sendOperations;
  615.   NdbNodeBitmask::clear(m_db_nodes);
  616.   NdbNodeBitmask::clear(m_failed_db_nodes);
  617.   DBUG_VOID_RETURN;
  618. }//NdbConnection::executeAsynchPrepare()
  619. void NdbConnection::close()
  620. {
  621.   theNdb->closeTransaction(this);
  622. }
  623. int NdbConnection::refresh(){
  624.   return sendTC_HBREP();
  625. }
  626. /*****************************************************************************
  627. int sendTC_HBREP();
  628. Return Value:  No return value.  
  629. Parameters :   None.
  630. Remark:        Order NDB to refresh the timeout counter of the transaction. 
  631. ******************************************************************************/
  632. int 
  633. NdbConnection::sendTC_HBREP() // Send a TC_HBREP signal;
  634. {
  635.   NdbApiSignal* tSignal;
  636.   Ndb* tNdb = theNdb;
  637.   Uint32 tTransId1, tTransId2;
  638.   tSignal = tNdb->getSignal();
  639.   if (tSignal == NULL) {
  640.     return -1;
  641.   }
  642.   if (tSignal->setSignal(GSN_TC_HBREP) == -1) {
  643.     return -1;
  644.   }
  645.   TcHbRep * const tcHbRep = CAST_PTR(TcHbRep, tSignal->getDataPtrSend());
  646.   
  647.   tcHbRep->apiConnectPtr = theTCConPtr;    
  648.   
  649.   tTransId1 = (Uint32) theTransactionId;
  650.   tTransId2 = (Uint32) (theTransactionId >> 32);
  651.   tcHbRep->transId1      = tTransId1;
  652.   tcHbRep->transId2      = tTransId2;
  653.  
  654.   TransporterFacade *tp = TransporterFacade::instance();
  655.   tp->lock_mutex(); 
  656.   const int res = tp->sendSignal(tSignal,theDBnode);
  657.   tp->unlock_mutex(); 
  658.   tNdb->releaseSignal(tSignal);
  659.   if (res == -1){
  660.     return -1;
  661.   }    
  662.   
  663.   return 0;
  664. }//NdbConnection::sendTC_HBREP()
  665. /*****************************************************************************
  666. int doSend();
  667. Return Value:  Return 0 : send was successful.
  668.                Return -1: In all other case.  
  669. Remark:        Send all operations belonging to this connection.
  670.                The caller of this method has the responsibility to remove the
  671.                object from the prepared transactions array on the Ndb-object.
  672. *****************************************************************************/
  673. int
  674. NdbConnection::doSend()
  675. {
  676.   DBUG_ENTER("NdbConnection::doSend");
  677.   /*
  678.   This method assumes that at least one operation have been defined. This
  679.   is ensured by the caller of this routine (=execute).
  680.   */
  681.   switch(theSendStatus){
  682.   case sendOperations: {
  683.     NdbOperation * tOp = theFirstExecOpInList;
  684.     do {
  685.       NdbOperation* tNextOp = tOp->next();
  686.       const Uint32 lastFlag = ((tNextOp == NULL) ? 1 : 0);
  687.       const int tReturnCode = tOp->doSend(theDBnode, lastFlag);
  688.       if (tReturnCode == -1) {
  689.         theReturnStatus = ReturnFailure;
  690.         break;
  691.       }//if
  692.       tOp = tNextOp;
  693.     } while (tOp != NULL);
  694.     Ndb* tNdb = theNdb;
  695.     theSendStatus = sendTC_OP;
  696.     theTransactionIsStarted = true;
  697.     tNdb->insert_sent_list(this);
  698.     DBUG_RETURN(0);
  699.   }//case
  700.   case sendABORT:
  701.   case sendABORTfail:{
  702.   /***********************************************************************
  703.    * Rollback have been ordered on a not started transaction. 
  704.    * Simply return OK and set abort status.
  705.    ***********************************************************************/
  706.     if (theSendStatus == sendABORTfail) {
  707.       theReturnStatus = ReturnFailure;
  708.     }//if
  709.     if (sendROLLBACK() == 0) {
  710.       DBUG_RETURN(0);
  711.     }//if
  712.     break;
  713.   }//case
  714.   case sendCOMMITstate:
  715.     if (sendCOMMIT() == 0) {
  716.       DBUG_RETURN(0);
  717.     }//if
  718.     break;
  719.   case sendCompleted:
  720.     theNdb->insert_completed_list(this); 
  721.     DBUG_RETURN(0);
  722.   default:
  723.     ndbout << "Inconsistent theSendStatus = "
  724.    << (Uint32) theSendStatus << endl;
  725.     abort();
  726.     break;
  727.   }//switch
  728.   setOperationErrorCodeAbort(4002);
  729.   theReleaseOnClose = true;
  730.   theTransactionIsStarted = false;
  731.   theCommitStatus = Aborted;
  732.   DBUG_RETURN(-1);
  733. }//NdbConnection::doSend()
  734. /**************************************************************************
  735. int sendROLLBACK();
  736. Return Value:  Return -1 if send unsuccessful.  
  737. Parameters :   None.
  738. Remark:        Order NDB to rollback the transaction. 
  739. **************************************************************************/
  740. int 
  741. NdbConnection::sendROLLBACK()      // Send a TCROLLBACKREQ signal;
  742. {
  743.   Ndb* tNdb = theNdb;
  744.   if ((theTransactionIsStarted == true) &&
  745.       (theCommitStatus != Committed) &&
  746.       (theCommitStatus != Aborted)) {
  747. /**************************************************************************
  748.  * The user did not perform any rollback but simply closed the
  749.  *      transaction. We must rollback Ndb since Ndb have been contacted.
  750.  *************************************************************************/
  751.     NdbApiSignal tSignal(tNdb->theMyRef);
  752.     Uint32 tTransId1, tTransId2;
  753.     TransporterFacade *tp = TransporterFacade::instance();
  754.     int   tReturnCode;
  755.     tTransId1 = (Uint32) theTransactionId;
  756.     tTransId2 = (Uint32) (theTransactionId >> 32);
  757.     tSignal.setSignal(GSN_TCROLLBACKREQ);
  758.     tSignal.setData(theTCConPtr, 1);
  759.     tSignal.setData(tTransId1, 2);
  760.     tSignal.setData(tTransId2, 3);
  761.     tReturnCode = tp->sendSignal(&tSignal,theDBnode);
  762.     if (tReturnCode != -1) {
  763.       theSendStatus = sendTC_ROLLBACK;
  764.       tNdb->insert_sent_list(this);
  765.       return 0;
  766.     }//if
  767.    /*********************************************************************
  768.     * It was not possible to abort the transaction towards the NDB kernel
  769.     * and thus we put it into the array of completed transactions that
  770.     * are ready for reporting to the application.
  771.     *********************************************************************/
  772.     return -1;
  773.   } else {
  774.     /*
  775.      It is not necessary to abort the transaction towards the NDB kernel and
  776.      thus we put it into the array of completed transactions that are ready
  777.      for reporting to the application.
  778.      */
  779.     theSendStatus = sendCompleted;
  780.     tNdb->insert_completed_list(this);
  781.     return 0;
  782.     ;
  783.   }//if
  784. }//NdbConnection::sendROLLBACK()
  785. /***************************************************************************
  786. int sendCOMMIT();
  787. Return Value:  Return 0 : send was successful.
  788.                Return -1: In all other case.  
  789. Parameters :   None.
  790. Remark:        Order NDB to commit the transaction. 
  791. ***************************************************************************/
  792. int 
  793. NdbConnection::sendCOMMIT()    // Send a TC_COMMITREQ signal;
  794. {
  795.   NdbApiSignal tSignal(theNdb->theMyRef);
  796.   Uint32 tTransId1, tTransId2;
  797.   TransporterFacade *tp = TransporterFacade::instance(); 
  798.   int   tReturnCode;
  799.   tTransId1 = (Uint32) theTransactionId;
  800.   tTransId2 = (Uint32) (theTransactionId >> 32);
  801.   tSignal.setSignal(GSN_TC_COMMITREQ);
  802.   tSignal.setData(theTCConPtr, 1);
  803.   tSignal.setData(tTransId1, 2);
  804.   tSignal.setData(tTransId2, 3);
  805.       
  806.   tReturnCode = tp->sendSignal(&tSignal,theDBnode);
  807.   if (tReturnCode != -1) {
  808.     theSendStatus = sendTC_COMMIT;
  809.     theNdb->insert_sent_list(this);
  810.     return 0;
  811.   } else {
  812.     return -1;
  813.   }//if
  814. }//NdbConnection::sendCOMMIT()
  815. /******************************************************************************
  816. void release();
  817. Remark:         Release all operations.
  818. ******************************************************************************/
  819. void 
  820. NdbConnection::release(){
  821.   releaseOperations();
  822.   if ( (theTransactionIsStarted == true) &&
  823.        ((theCommitStatus != Committed) &&
  824. (theCommitStatus != Aborted))) {
  825.     /************************************************************************
  826.      * The user did not perform any rollback but simply closed the
  827.      *      transaction. We must rollback Ndb since Ndb have been contacted.
  828.      ************************************************************************/
  829.     execute(Rollback);
  830.   }//if
  831.   theMagicNumber = 0xFE11DC;
  832.   theInUseState = false;
  833. #ifdef VM_TRACE
  834.   if (theListState != NotInList) {
  835.     theNdb->printState("release %x", this);
  836.     abort();
  837.   }
  838. #endif
  839. }//NdbConnection::release()
  840. void
  841. NdbConnection::releaseOps(NdbOperation* tOp){
  842.   while (tOp != NULL) {
  843.     NdbOperation* tmp = tOp;
  844.     tOp->release();
  845.     tOp = tOp->next();
  846.     theNdb->releaseOperation(tmp);
  847.   }//while
  848. }
  849. /******************************************************************************
  850. void releaseOperations();
  851. Remark:         Release all operations.
  852. ******************************************************************************/
  853. void 
  854. NdbConnection::releaseOperations()
  855. {
  856.   // Release any open scans
  857.   releaseScanOperations(m_theFirstScanOperation);
  858.   releaseScanOperations(m_firstExecutedScanOp);
  859.   
  860.   releaseOps(theCompletedFirstOp);
  861.   releaseOps(theFirstOpInList);
  862.   releaseOps(theFirstExecOpInList);
  863.   theCompletedFirstOp = NULL;
  864.   theCompletedLastOp = NULL;
  865.   theFirstOpInList = NULL;
  866.   theFirstExecOpInList = NULL;
  867.   theLastOpInList = NULL;
  868.   theLastExecOpInList = NULL;
  869.   theScanningOp = NULL;
  870.   m_theFirstScanOperation = NULL;
  871.   m_theLastScanOperation = NULL;
  872.   m_firstExecutedScanOp = NULL;
  873. }//NdbConnection::releaseOperations()
  874. void 
  875. NdbConnection::releaseCompletedOperations()
  876. {
  877.   releaseOps(theCompletedFirstOp);
  878.   theCompletedFirstOp = NULL;
  879.   theCompletedLastOp = NULL;
  880. }//NdbConnection::releaseOperations()
  881. /******************************************************************************
  882. void releaseScanOperations();
  883. Remark:         Release all cursor operations. 
  884.                 (NdbScanOperation and NdbIndexOperation)
  885. ******************************************************************************/
  886. void 
  887. NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp)
  888. {
  889.   while(cursorOp != 0){
  890.     NdbIndexScanOperation* next = (NdbIndexScanOperation*)cursorOp->next();
  891.     cursorOp->release();
  892.     theNdb->releaseScanOperation(cursorOp);
  893.     cursorOp = next;
  894.   }
  895. }//NdbConnection::releaseScanOperations()
  896. /*****************************************************************************
  897. void releaseExecutedScanOperation();
  898. Remark:         Release scan op when hupp'ed trans closed (save memory)
  899. ******************************************************************************/
  900. void 
  901. NdbConnection::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
  902. {
  903.   DBUG_ENTER("NdbConnection::releaseExecutedScanOperation");
  904.   DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp))
  905.   // here is one reason to make op lists doubly linked
  906.   if (m_firstExecutedScanOp == cursorOp) {
  907.     m_firstExecutedScanOp = (NdbIndexScanOperation*)cursorOp->theNext;
  908.     cursorOp->release();
  909.     theNdb->releaseScanOperation(cursorOp);
  910.   } else if (m_firstExecutedScanOp != NULL) {
  911.     NdbIndexScanOperation* tOp = m_firstExecutedScanOp;
  912.     while (tOp->theNext != NULL) {
  913.       if (tOp->theNext == cursorOp) {
  914.         tOp->theNext = cursorOp->theNext;
  915.         cursorOp->release();
  916.         theNdb->releaseScanOperation(cursorOp);
  917.         break;
  918.       }
  919.       tOp = (NdbIndexScanOperation*)tOp->theNext;
  920.     }
  921.   }
  922.   DBUG_VOID_RETURN;
  923. }//NdbConnection::releaseExecutedScanOperation()
  924. /*****************************************************************************
  925. NdbOperation* getNdbOperation(const char* aTableName);
  926. Return Value    Return a pointer to a NdbOperation object if getNdbOperation 
  927.                 was succesful.
  928.                 Return NULL : In all other case. 
  929. Parameters:     aTableName : Name of the database table. 
  930. Remark:         Get an operation from NdbOperation idlelist and get the 
  931.                 NdbConnection object 
  932. who was fetch by startTransaction pointing to this  operation  
  933. getOperation will set the theTableId in the NdbOperation object.
  934.                 synchronous
  935. ******************************************************************************/
  936. NdbOperation*
  937. NdbConnection::getNdbOperation(const char* aTableName)
  938. {
  939.   if (theCommitStatus == Started){
  940.     NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
  941.     if (table != 0){
  942.       return getNdbOperation(table);
  943.     } else {
  944.       setErrorCode(theNdb->theDictionary->getNdbError().code);
  945.       return NULL;
  946.     }//if
  947.   }
  948.   setOperationErrorCodeAbort(4114);
  949.   
  950.   return NULL;
  951. }//NdbConnection::getNdbOperation()
  952. /*****************************************************************************
  953. NdbOperation* getNdbOperation(int aTableId);
  954. Return Value    Return a pointer to a NdbOperation object if getNdbOperation 
  955.                 was succesful.
  956.                 Return NULL: In all other case. 
  957. Parameters:     tableId : Id of the database table beeing deleted.
  958. Remark:         Get an operation from NdbOperation object idlelist and 
  959.                 get the NdbConnection object who was fetch by 
  960.                 startTransaction pointing to this operation 
  961.            getOperation will set the theTableId in the NdbOperation 
  962.                 object, synchronous.
  963. *****************************************************************************/
  964. NdbOperation*
  965. NdbConnection::getNdbOperation(const NdbTableImpl * tab, NdbOperation* aNextOp)
  966.   NdbOperation* tOp;
  967.   if (theScanningOp != NULL){
  968.     setErrorCode(4607);
  969.     return NULL;
  970.   }
  971.   
  972.   tOp = theNdb->getOperation();
  973.   if (tOp == NULL)
  974.     goto getNdbOp_error1;
  975.   if (aNextOp == NULL) {
  976.     if (theLastOpInList != NULL) {
  977.        theLastOpInList->next(tOp);
  978.        theLastOpInList = tOp;
  979.     } else {
  980.        theLastOpInList = tOp;
  981.        theFirstOpInList = tOp;
  982.     }//if
  983.     tOp->next(NULL);
  984.   } else {
  985.     // add before the given op
  986.     if (theFirstOpInList == aNextOp) {
  987.       theFirstOpInList = tOp;
  988.     } else {
  989.       NdbOperation* aLoopOp = theFirstOpInList;
  990.       while (aLoopOp != NULL && aLoopOp->next() != aNextOp)
  991.         aLoopOp = aLoopOp->next();
  992.       assert(aLoopOp != NULL);
  993.       aLoopOp->next(tOp);
  994.     }
  995.     tOp->next(aNextOp);
  996.   }
  997.   if (tOp->init(tab, this) != -1) {
  998.     return tOp;
  999.   } else {
  1000.     theNdb->releaseOperation(tOp);
  1001.   }//if
  1002.   return NULL;
  1003.   
  1004.  getNdbOp_error1:
  1005.   setOperationErrorCodeAbort(4000);
  1006.   return NULL;
  1007. }//NdbConnection::getNdbOperation()
  1008. NdbOperation* NdbConnection::getNdbOperation(const NdbDictionary::Table * table)
  1009. {
  1010.   if (table)
  1011.     return getNdbOperation(& NdbTableImpl::getImpl(*table));
  1012.   else
  1013.     return NULL;
  1014. }//NdbConnection::getNdbOperation()
  1015. // NdbScanOperation
  1016. /*****************************************************************************
  1017. NdbScanOperation* getNdbScanOperation(const char* aTableName);
  1018. Return Value    Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
  1019.                 Return NULL : In all other case. 
  1020. Parameters:     aTableName : Name of the database table. 
  1021. Remark:         Get an operation from NdbScanOperation idlelist and get the NdbConnection object 
  1022. who was fetch by startTransaction pointing to this  operation  
  1023. getOperation will set the theTableId in the NdbOperation object.synchronous
  1024. ******************************************************************************/
  1025. NdbScanOperation*
  1026. NdbConnection::getNdbScanOperation(const char* aTableName)
  1027. {
  1028.   if (theCommitStatus == Started){
  1029.     NdbTableImpl* tab = theNdb->theDictionary->getTable(aTableName);
  1030.     if (tab != 0){
  1031.       return getNdbScanOperation(tab);
  1032.     } else {
  1033.       setOperationErrorCodeAbort(theNdb->theDictionary->m_error.code);
  1034.       return NULL;
  1035.     }//if
  1036.   } 
  1037.   
  1038.   setOperationErrorCodeAbort(4114);
  1039.   return NULL;
  1040. }//NdbConnection::getNdbScanOperation()
  1041. /*****************************************************************************
  1042. NdbScanOperation* getNdbScanOperation(const char* anIndexName, const char* aTableName);
  1043. Return Value    Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
  1044.                 Return NULL : In all other case. 
  1045. Parameters:     anIndexName : Name of the index to use. 
  1046.                 aTableName : Name of the database table. 
  1047. Remark:         Get an operation from NdbScanOperation idlelist and get the NdbConnection object 
  1048. who was fetch by startTransaction pointing to this  operation  
  1049. getOperation will set the theTableId in the NdbOperation object.synchronous
  1050. ******************************************************************************/
  1051. NdbIndexScanOperation*
  1052. NdbConnection::getNdbIndexScanOperation(const char* anIndexName, 
  1053. const char* aTableName)
  1054. {
  1055.   NdbIndexImpl* index = 
  1056.     theNdb->theDictionary->getIndex(anIndexName, aTableName);
  1057.   NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
  1058.   return getNdbIndexScanOperation(index, table);
  1059. }
  1060. NdbIndexScanOperation*
  1061. NdbConnection::getNdbIndexScanOperation(const NdbIndexImpl* index,
  1062. const NdbTableImpl* table)
  1063. {
  1064.   if (theCommitStatus == Started){
  1065.     const NdbTableImpl * indexTable = index->getIndexTable();
  1066.     if (indexTable != 0){
  1067.       NdbIndexScanOperation* tOp = 
  1068. getNdbScanOperation((NdbTableImpl *) indexTable);
  1069.       if(tOp)
  1070.       {
  1071. tOp->m_currentTable = table;
  1072. tOp->m_cursor_type = NdbScanOperation::IndexCursor;
  1073.       }
  1074.       return tOp;
  1075.     } else {
  1076.       setOperationErrorCodeAbort(theNdb->theError.code);
  1077.       return NULL;
  1078.     }//if
  1079.   } 
  1080.   
  1081.   setOperationErrorCodeAbort(4114);
  1082.   return NULL;
  1083. }//NdbConnection::getNdbIndexScanOperation()
  1084. NdbIndexScanOperation* 
  1085. NdbConnection::getNdbIndexScanOperation(const NdbDictionary::Index * index,
  1086. const NdbDictionary::Table * table)
  1087. {
  1088.   if (index && table)
  1089.     return getNdbIndexScanOperation(& NdbIndexImpl::getImpl(*index),
  1090.     & NdbTableImpl::getImpl(*table));
  1091.   else
  1092.     return NULL;
  1093. }//NdbConnection::getNdbIndexScanOperation()
  1094. /*****************************************************************************
  1095. NdbScanOperation* getNdbScanOperation(int aTableId);
  1096. Return Value    Return a pointer to a NdbOperation object if getNdbOperation was succesful.
  1097.                 Return NULL: In all other case. 
  1098. Parameters:     tableId : Id of the database table beeing deleted.
  1099. Remark:         Get an operation from NdbScanOperation object idlelist and get the NdbConnection 
  1100.                 object who was fetch by startTransaction pointing to this  operation 
  1101.            getOperation will set the theTableId in the NdbOperation object, synchronous.
  1102. *****************************************************************************/
  1103. NdbIndexScanOperation*
  1104. NdbConnection::getNdbScanOperation(const NdbTableImpl * tab)
  1105.   NdbIndexScanOperation* tOp;
  1106.   
  1107.   tOp = theNdb->getScanOperation();
  1108.   if (tOp == NULL)
  1109.     goto getNdbOp_error1;
  1110.   
  1111.   if (tOp->init(tab, this) != -1) {
  1112.     define_scan_op(tOp);
  1113.     return tOp;
  1114.   } else {
  1115.     theNdb->releaseScanOperation(tOp);
  1116.   }//if
  1117.   return NULL;
  1118. getNdbOp_error1:
  1119.   setOperationErrorCodeAbort(4000);
  1120.   return NULL;
  1121. }//NdbConnection::getNdbScanOperation()
  1122. void
  1123. NdbConnection::remove_list(NdbOperation*& list, NdbOperation* op){
  1124.   NdbOperation* tmp= list;
  1125.   if(tmp == op)
  1126.     list = op->next();
  1127.   else {
  1128.     while(tmp && tmp->next() != op) tmp = tmp->next();
  1129.     if(tmp)
  1130.       tmp->next(op->next());
  1131.   }
  1132.   op->next(NULL);
  1133. }
  1134. void
  1135. NdbConnection::define_scan_op(NdbIndexScanOperation * tOp){
  1136.   // Link scan operation into list of cursor operations
  1137.   if (m_theLastScanOperation == NULL)
  1138.     m_theFirstScanOperation = m_theLastScanOperation = tOp;
  1139.   else {
  1140.     m_theLastScanOperation->next(tOp);
  1141.     m_theLastScanOperation = tOp;
  1142.   }
  1143.   tOp->next(NULL);
  1144. }
  1145. NdbScanOperation* 
  1146. NdbConnection::getNdbScanOperation(const NdbDictionary::Table * table)
  1147. {
  1148.   if (table)
  1149.     return getNdbScanOperation(& NdbTableImpl::getImpl(*table));
  1150.   else
  1151.     return NULL;
  1152. }//NdbConnection::getNdbScanOperation()
  1153. // IndexOperation
  1154. /*****************************************************************************
  1155. NdbIndexOperation* getNdbIndexOperation(const char* anIndexName,
  1156. const char* aTableName);
  1157. Return Value    Return a pointer to a NdbOperation object if getNdbScanOperation was succesful.
  1158.                 Return NULL : In all other case. 
  1159. Parameters:     aTableName : Name of the database table. 
  1160. Remark:         Get an operation from NdbScanOperation idlelist and get the NdbConnection object 
  1161. who was fetch by startTransaction pointing to this  operation  
  1162. getOperation will set the theTableId in the NdbScanOperation object.synchronous
  1163. ******************************************************************************/
  1164. NdbIndexOperation*
  1165. NdbConnection::getNdbIndexOperation(const char* anIndexName, 
  1166.                                     const char* aTableName)
  1167. {
  1168.   if (theCommitStatus == Started) {
  1169.     NdbTableImpl * table = theNdb->theDictionary->getTable(aTableName);
  1170.     NdbIndexImpl * index = theNdb->theDictionary->getIndex(anIndexName,
  1171.    aTableName);
  1172.     if(table != 0 && index != 0){
  1173.       return getNdbIndexOperation(index, table);
  1174.     }
  1175.     
  1176.     if(index == 0){
  1177.       setOperationErrorCodeAbort(4243);
  1178.       return NULL;
  1179.     }
  1180.     // table == 0
  1181.     setOperationErrorCodeAbort(theNdb->theError.code);
  1182.     return NULL;
  1183.   } 
  1184.   
  1185.   setOperationErrorCodeAbort(4114);
  1186.   return 0;
  1187. }//NdbConnection::getNdbIndexOperation()
  1188. /*****************************************************************************
  1189. NdbIndexOperation* getNdbIndexOperation(int anIndexId, int aTableId);
  1190. Return Value    Return a pointer to a NdbIndexOperation object if getNdbIndexOperation was succesful.
  1191.                 Return NULL: In all other case. 
  1192. Parameters:     tableId : Id of the database table beeing deleted.
  1193. Remark:         Get an operation from NdbIndexOperation object idlelist and get the NdbConnection 
  1194.                 object who was fetch by startTransaction pointing to this  operation 
  1195.            getOperation will set the theTableId in the NdbIndexOperation object, synchronous.
  1196. *****************************************************************************/
  1197. NdbIndexOperation*
  1198. NdbConnection::getNdbIndexOperation(const NdbIndexImpl * anIndex, 
  1199.     const NdbTableImpl * aTable,
  1200.                                     NdbOperation* aNextOp)
  1201.   NdbIndexOperation* tOp;
  1202.   
  1203.   tOp = theNdb->getIndexOperation();
  1204.   if (tOp == NULL)
  1205.     goto getNdbOp_error1;
  1206.   if (aNextOp == NULL) {
  1207.     if (theLastOpInList != NULL) {
  1208.        theLastOpInList->next(tOp);
  1209.        theLastOpInList = tOp;
  1210.     } else {
  1211.        theLastOpInList = tOp;
  1212.        theFirstOpInList = tOp;
  1213.     }//if
  1214.     tOp->next(NULL);
  1215.   } else {
  1216.     // add before the given op
  1217.     if (theFirstOpInList == aNextOp) {
  1218.       theFirstOpInList = tOp;
  1219.     } else {
  1220.       NdbOperation* aLoopOp = theFirstOpInList;
  1221.       while (aLoopOp != NULL && aLoopOp->next() != aNextOp)
  1222.         aLoopOp = aLoopOp->next();
  1223.       assert(aLoopOp != NULL);
  1224.       aLoopOp->next(tOp);
  1225.     }
  1226.     tOp->next(aNextOp);
  1227.   }
  1228.   if (tOp->indxInit(anIndex, aTable, this)!= -1) {
  1229.     return tOp;
  1230.   } else {
  1231.     theNdb->releaseOperation(tOp);
  1232.   }//if
  1233.   return NULL;
  1234.   
  1235.  getNdbOp_error1:
  1236.   setOperationErrorCodeAbort(4000);
  1237.   return NULL;
  1238. }//NdbConnection::getNdbIndexOperation()
  1239. NdbIndexOperation* 
  1240. NdbConnection::getNdbIndexOperation(const NdbDictionary::Index * index,
  1241.     const NdbDictionary::Table * table)
  1242. {
  1243.   if (index && table)
  1244.     return getNdbIndexOperation(& NdbIndexImpl::getImpl(*index),
  1245. & NdbTableImpl::getImpl(*table));
  1246.   else
  1247.     return NULL;
  1248. }//NdbConnection::getNdbIndexOperation()
  1249. /*******************************************************************************
  1250. int  receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
  1251. Return Value:  Return 0 : receiveDIHNDBTAMPER was successful.
  1252.                Return -1: In all other case.
  1253. Parameters:    aSignal: The signal object pointer.
  1254. Remark:        Sets theRestartGCI in the NDB object. 
  1255. *******************************************************************************/
  1256. int
  1257. NdbConnection::receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
  1258. {
  1259.   if (theStatus != Connecting) {
  1260.     return -1;
  1261.   } else {
  1262.     theNdb->RestartGCI((Uint32)aSignal->readData(2));
  1263.     theStatus = Connected;
  1264.   }//if
  1265.   return 0;  
  1266. }//NdbConnection::receiveDIHNDBTAMPER()
  1267. /*******************************************************************************
  1268. int  receiveTCSEIZECONF(NdbApiSignal* aSignal);
  1269. Return Value:  Return 0 : receiveTCSEIZECONF was successful.
  1270.                Return -1: In all other case.
  1271. Parameters:    aSignal: The signal object pointer.
  1272. Remark:        Sets TC Connect pointer at reception of TCSEIZECONF. 
  1273. *******************************************************************************/
  1274. int
  1275. NdbConnection::receiveTCSEIZECONF(NdbApiSignal* aSignal)
  1276. {
  1277.   if (theStatus != Connecting)
  1278.   {
  1279.     return -1;
  1280.   } else
  1281.   {
  1282.     theTCConPtr = (Uint32)aSignal->readData(2);
  1283.     theStatus = Connected;
  1284.   }
  1285.   return 0;
  1286. }//NdbConnection::receiveTCSEIZECONF()
  1287. /*******************************************************************************
  1288. int  receiveTCSEIZEREF(NdbApiSignal* aSignal);
  1289. Return Value:  Return 0 : receiveTCSEIZEREF was successful.
  1290.                Return -1: In all other case.
  1291. Parameters:    aSignal: The signal object pointer.
  1292. Remark:        Sets TC Connect pointer. 
  1293. *******************************************************************************/
  1294. int
  1295. NdbConnection::receiveTCSEIZEREF(NdbApiSignal* aSignal)
  1296. {
  1297.   if (theStatus != Connecting)
  1298.   {
  1299.     return -1;
  1300.   } else
  1301.   {
  1302.     theStatus = ConnectFailure;
  1303.     theNdb->theError.code = aSignal->readData(2);
  1304.     return 0;
  1305.   }
  1306. }//NdbConnection::receiveTCSEIZEREF()
  1307. /*******************************************************************************
  1308. int  receiveTCRELEASECONF(NdbApiSignal* aSignal);
  1309. Return Value:  Return 0 : receiveTCRELEASECONF was successful.
  1310.                Return -1: In all other case.
  1311. Parameters:    aSignal: The signal object pointer.
  1312. Remark:         DisConnect TC Connect pointer to NDBAPI. 
  1313. *******************************************************************************/
  1314. int
  1315. NdbConnection::receiveTCRELEASECONF(NdbApiSignal* aSignal)
  1316. {
  1317.   if (theStatus != DisConnecting)
  1318.   {
  1319.     return -1;
  1320.   } else
  1321.   {
  1322.     theStatus = NotConnected;
  1323.   }
  1324.   return 0;
  1325. }//NdbConnection::receiveTCRELEASECONF()
  1326. /*******************************************************************************
  1327. int  receiveTCRELEASEREF(NdbApiSignal* aSignal);
  1328. Return Value:  Return 0 : receiveTCRELEASEREF was successful.
  1329.                Return -1: In all other case.
  1330. Parameters:    aSignal: The signal object pointer.
  1331. Remark:        DisConnect TC Connect pointer to NDBAPI Failure. 
  1332. *******************************************************************************/
  1333. int
  1334. NdbConnection::receiveTCRELEASEREF(NdbApiSignal* aSignal)
  1335. {
  1336.   if (theStatus != DisConnecting) {
  1337.     return -1;
  1338.   } else {
  1339.     theStatus = ConnectFailure;
  1340.     theNdb->theError.code = aSignal->readData(2);
  1341.     return 0;
  1342.   }//if
  1343. }//NdbConnection::receiveTCRELEASEREF()
  1344. /******************************************************************************
  1345. int  receiveTC_COMMITCONF(NdbApiSignal* aSignal);
  1346. Return Value:  Return 0 : receiveTC_COMMITCONF was successful.
  1347.                Return -1: In all other case.
  1348. Parameters:    aSignal: The signal object pointer.
  1349. Remark:        
  1350. ******************************************************************************/
  1351. int
  1352. NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
  1353.   if(checkState_TransId(&commitConf->transId1)){
  1354.     theCommitStatus = Committed;
  1355.     theCompletionStatus = CompletedSuccess;
  1356.     return 0;
  1357.   } else {
  1358. #ifdef NDB_NO_DROPPED_SIGNAL
  1359.     abort();
  1360. #endif
  1361.   }
  1362.   return -1;
  1363. }//NdbConnection::receiveTC_COMMITCONF()
  1364. /******************************************************************************
  1365. int  receiveTC_COMMITREF(NdbApiSignal* aSignal);
  1366. Return Value:  Return 0 : receiveTC_COMMITREF was successful.
  1367.                Return -1: In all other case.
  1368. Parameters:    aSignal: The signal object pointer.
  1369. Remark:        
  1370. ******************************************************************************/
  1371. int
  1372. NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal)
  1373. {
  1374.   const TcCommitRef * ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr());
  1375.   if(checkState_TransId(&ref->transId1)){
  1376.     setOperationErrorCodeAbort(ref->errorCode);
  1377.     theCommitStatus = Aborted;
  1378.     theCompletionStatus = CompletedFailure;
  1379.     return 0;
  1380.   } else {
  1381. #ifdef NDB_NO_DROPPED_SIGNAL
  1382.     abort();
  1383. #endif
  1384.   }
  1385.   return -1;
  1386. }//NdbConnection::receiveTC_COMMITREF()
  1387. /******************************************************************************
  1388. int  receiveTCROLLBACKCONF(NdbApiSignal* aSignal);
  1389. Return Value:  Return 0 : receiveTCROLLBACKCONF was successful.
  1390.                Return -1: In all other case.
  1391. Parameters:    aSignal: The signal object pointer.
  1392. Remark:        
  1393. ******************************************************************************/
  1394. int
  1395. NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
  1396. {
  1397.   if(checkState_TransId(aSignal->getDataPtr() + 1)){
  1398.     theCommitStatus = Aborted;
  1399.     theCompletionStatus = CompletedSuccess;
  1400.     return 0;
  1401.   } else {
  1402. #ifdef NDB_NO_DROPPED_SIGNAL
  1403.     abort();
  1404. #endif
  1405.   }
  1406.   return -1;
  1407. }//NdbConnection::receiveTCROLLBACKCONF()
  1408. /*******************************************************************************
  1409. int  receiveTCROLLBACKREF(NdbApiSignal* aSignal);
  1410. Return Value:  Return 0 : receiveTCROLLBACKREF was successful.
  1411.                Return -1: In all other case.
  1412. Parameters:    aSignal: The signal object pointer.
  1413. Remark:        
  1414. *******************************************************************************/
  1415. int
  1416. NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
  1417. {
  1418.   if(checkState_TransId(aSignal->getDataPtr() + 1)){
  1419.     setOperationErrorCodeAbort(aSignal->readData(4));
  1420.     theCommitStatus = Aborted;
  1421.     theCompletionStatus = CompletedFailure;
  1422.     return 0;
  1423.   } else {
  1424. #ifdef NDB_NO_DROPPED_SIGNAL
  1425.     abort();
  1426. #endif
  1427.   }
  1428.   return -1;
  1429. }//NdbConnection::receiveTCROLLBACKREF()
  1430. /*****************************************************************************
  1431. int receiveTCROLLBACKREP( NdbApiSignal* aSignal)
  1432. Return Value:   Return 0 : send was succesful.
  1433.                 Return -1: In all other case.   
  1434. Parameters:     aSignal: the signal object that contains the 
  1435.                 TCROLLBACKREP signal from TC.
  1436. Remark:         Handles the reception of the ROLLBACKREP signal.
  1437. *****************************************************************************/
  1438. int
  1439. NdbConnection::receiveTCROLLBACKREP( NdbApiSignal* aSignal)
  1440. {
  1441.   /****************************************************************************
  1442. Check that we are expecting signals from this transaction and that it doesn't
  1443. belong to a transaction already completed. Simply ignore messages from other 
  1444. transactions.
  1445.   ****************************************************************************/
  1446.   if(checkState_TransId(aSignal->getDataPtr() + 1)){
  1447.     theError.code = aSignal->readData(4);// Override any previous errors
  1448.     /**********************************************************************/
  1449.     /* A serious error has occured. This could be due to deadlock or */
  1450.     /* lack of resources or simply a programming error in NDB. This  */
  1451.     /* transaction will be aborted. Actually it has already been     */
  1452.     /* and we only need to report completion and return with the     */
  1453.     /* error code to the application.       */
  1454.     /**********************************************************************/
  1455.     theCompletionStatus = CompletedFailure;
  1456.     theCommitStatus = Aborted;
  1457.     return 0;
  1458.   } else {
  1459. #ifdef NDB_NO_DROPPED_SIGNAL
  1460.     abort();
  1461. #endif
  1462.   }
  1463.   return -1;
  1464. }//NdbConnection::receiveTCROLLBACKREP()
  1465. /*******************************************************************************
  1466. int  receiveTCKEYCONF(NdbApiSignal* aSignal, Uint32 long_short_ind);
  1467. Return Value:  Return 0 : receiveTCKEYCONF was successful.
  1468.                Return -1: In all other case.
  1469. Parameters:    aSignal: The signal object pointer.
  1470. Remark:        
  1471. *******************************************************************************/
  1472. int
  1473. NdbConnection::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength)
  1474. {
  1475.   NdbReceiver* tOp;
  1476.   const Uint32 tTemp = keyConf->confInfo;
  1477.   /***************************************************************************
  1478. Check that we are expecting signals from this transaction and that it
  1479. doesn't belong to a transaction already completed. Simply ignore messages
  1480. from other transactions.
  1481.   ***************************************************************************/
  1482.   if(checkState_TransId(&keyConf->transId1)){
  1483.     const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp);
  1484.     const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp);
  1485.     const Uint32* tPtr = (Uint32 *)&keyConf->operations[0];
  1486.     Uint32 tNoComp = theNoOfOpCompleted;
  1487.     for (Uint32 i = 0; i < tNoOfOperations ; i++) {
  1488.       tOp = theNdb->void2rec(theNdb->int2void(*tPtr++));
  1489.       const Uint32 tAttrInfoLen = *tPtr++;
  1490.       if (tOp && tOp->checkMagicNumber()) {
  1491. Uint32 done = tOp->execTCOPCONF(tAttrInfoLen);
  1492. if(tAttrInfoLen > TcKeyConf::SimpleReadBit){
  1493.   Uint32 node = tAttrInfoLen & (~TcKeyConf::SimpleReadBit);
  1494.   NdbNodeBitmask::set(m_db_nodes, node);
  1495.   if(NdbNodeBitmask::get(m_failed_db_nodes, node) && !done)
  1496.   {
  1497.     done = 1;
  1498.     tOp->setErrorCode(4119);
  1499.     theCompletionStatus = CompletedFailure;
  1500.   }     
  1501. }
  1502. tNoComp += done;
  1503.       } else {
  1504.   return -1;
  1505.       }//if
  1506.     }//for
  1507.     Uint32 tNoSent = theNoOfOpSent;
  1508.     theNoOfOpCompleted = tNoComp;
  1509.     Uint32 tGCI    = keyConf->gci;
  1510.     if (tCommitFlag == 1) {
  1511.       theCommitStatus = Committed;
  1512.       theGlobalCheckpointId = tGCI;
  1513.     } else if ((tNoComp >= tNoSent) &&
  1514.                (theLastExecOpInList->theCommitIndicator == 1)){
  1515.       if (m_abortOption == AO_IgnoreError && theError.code != 0){
  1516. /**
  1517.  * There's always a TCKEYCONF when using IgnoreError
  1518.  */
  1519. return -1;
  1520.       }
  1521. /**********************************************************************/
  1522. // We sent the transaction with Commit flag set and received a CONF with
  1523. // no Commit flag set. This is clearly an anomaly.
  1524. /**********************************************************************/
  1525.       theError.code = 4011;
  1526.       theCompletionStatus = CompletedFailure;
  1527.       theCommitStatus = Aborted;
  1528.       return 0;
  1529.     }//if
  1530.     if (tNoComp >= tNoSent) {
  1531.       return 0; // No more operations to wait for
  1532.     }//if
  1533.      // Not completed the reception yet.
  1534.   } else {
  1535. #ifdef NDB_NO_DROPPED_SIGNAL
  1536.     abort();
  1537. #endif
  1538.   }
  1539.   
  1540.   return -1;
  1541. }//NdbConnection::receiveTCKEYCONF()
  1542. /*****************************************************************************
  1543. int receiveTCKEY_FAILCONF( NdbApiSignal* aSignal)
  1544. Return Value:   Return 0 : receive was completed.
  1545.                 Return -1: In all other case.   
  1546. Parameters:     aSignal: the signal object that contains the 
  1547.                 TCKEY_FAILCONF signal from TC.
  1548. Remark:         Handles the reception of the TCKEY_FAILCONF signal.
  1549. *****************************************************************************/
  1550. int
  1551. NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
  1552. {
  1553.   NdbOperation* tOp;
  1554.   /*
  1555.     Check that we are expecting signals from this transaction and that it 
  1556.     doesn't belong  to a transaction already completed. Simply ignore 
  1557.     messages from other transactions.
  1558.   */
  1559.   if(checkState_TransId(&failConf->transId1)){
  1560.     /*
  1561.       A node failure of the TC node occured. The transaction has
  1562.       been committed.
  1563.     */
  1564.     theCommitStatus = Committed;
  1565.     tOp = theFirstExecOpInList;
  1566.     while (tOp != NULL) {
  1567.       /*
  1568.        * Check if the transaction expected read values...
  1569.        * If it did some of them might have gotten lost even if we succeeded
  1570.        * in committing the transaction.
  1571.        */
  1572.       switch(tOp->theOperationType){
  1573.       case NdbOperation::UpdateRequest:
  1574.       case NdbOperation::InsertRequest:
  1575.       case NdbOperation::DeleteRequest:
  1576.       case NdbOperation::WriteRequest:
  1577. tOp = tOp->next();
  1578. break;
  1579.       case NdbOperation::ReadRequest:
  1580.       case NdbOperation::ReadExclusive:
  1581.       case NdbOperation::OpenScanRequest:
  1582.       case NdbOperation::OpenRangeScanRequest:
  1583. theCompletionStatus = CompletedFailure;
  1584. setOperationErrorCodeAbort(4115);
  1585. tOp = NULL;
  1586. break;
  1587.       case NdbOperation::NotDefined:
  1588.       case NdbOperation::NotDefined2:
  1589. assert(false);
  1590. break;
  1591.       }//if
  1592.     }//while   
  1593.     theReleaseOnClose = true;
  1594.     return 0;
  1595.   } else {
  1596. #ifdef VM_TRACE
  1597.     ndbout_c("Recevied TCKEY_FAILCONF wo/ operation");
  1598. #endif
  1599.   }
  1600.   return -1;
  1601. }//NdbConnection::receiveTCKEY_FAILCONF()
  1602. /*************************************************************************
  1603. int receiveTCKEY_FAILREF( NdbApiSignal* aSignal)
  1604. Return Value:   Return 0 : receive was completed.
  1605.                 Return -1: In all other case.   
  1606. Parameters:     aSignal: the signal object that contains the 
  1607.                 TCKEY_FAILREF signal from TC.
  1608. Remark:         Handles the reception of the TCKEY_FAILREF signal.
  1609. **************************************************************************/
  1610. int
  1611. NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
  1612. {
  1613.   /*
  1614.     Check that we are expecting signals from this transaction and
  1615.     that it doesn't belong to a transaction already
  1616.     completed. Simply ignore messages from other transactions.
  1617.   */
  1618.   if(checkState_TransId(aSignal->getDataPtr()+1)){
  1619.     /*
  1620.       We received an indication of that this transaction was aborted due to a
  1621.       node failure.
  1622.     */
  1623.     if (theSendStatus == NdbConnection::sendTC_ROLLBACK) {
  1624.       /*
  1625. We were in the process of sending a rollback anyways. We will
  1626. report it as a success.
  1627.       */
  1628.       theCompletionStatus = NdbConnection::CompletedSuccess;
  1629.     } else {
  1630.       theCompletionStatus = NdbConnection::CompletedFailure;
  1631.       theError.code = 4031;
  1632.     }//if
  1633.     theReleaseOnClose = true;
  1634.     theCommitStatus = NdbConnection::Aborted;
  1635.     return 0;
  1636.   } else {
  1637. #ifdef VM_TRACE
  1638.     ndbout_c("Recevied TCKEY_FAILREF wo/ operation");
  1639. #endif
  1640.   }
  1641.   return -1;
  1642. }//NdbConnection::receiveTCKEY_FAILREF()
  1643. /******************************************************************************
  1644. int  receiveTCINDXCONF(NdbApiSignal* aSignal, Uint32 long_short_ind);
  1645. Return Value:  Return 0 : receiveTCINDXCONF was successful.
  1646.                Return -1: In all other case.
  1647. Parameters:    aSignal: The signal object pointer.
  1648. Remark:        
  1649. ******************************************************************************/
  1650. int
  1651. NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf, 
  1652.  Uint32 aDataLength)
  1653. {
  1654.   if(checkState_TransId(&indxConf->transId1)){
  1655.     const Uint32 tTemp = indxConf->confInfo;
  1656.     const Uint32 tNoOfOperations = TcIndxConf::getNoOfOperations(tTemp);
  1657.     const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp);
  1658.     
  1659.     const Uint32* tPtr = (Uint32 *)&indxConf->operations[0];
  1660.     Uint32 tNoComp = theNoOfOpCompleted;
  1661.     for (Uint32 i = 0; i < tNoOfOperations ; i++) {
  1662.       NdbReceiver* tOp = theNdb->void2rec(theNdb->int2void(*tPtr));
  1663.       tPtr++;
  1664.       const Uint32 tAttrInfoLen = *tPtr;
  1665.       tPtr++;
  1666.       if (tOp && tOp->checkMagicNumber()) {
  1667. tNoComp += tOp->execTCOPCONF(tAttrInfoLen);
  1668.       } else {
  1669. return -1;
  1670.       }//if
  1671.     }//for
  1672.     Uint32 tNoSent = theNoOfOpSent;
  1673.     Uint32 tGCI    = indxConf->gci;
  1674.     theNoOfOpCompleted = tNoComp;
  1675.     if (tCommitFlag == 1) {
  1676.       theCommitStatus = Committed;
  1677.       theGlobalCheckpointId = tGCI;
  1678.     } else if ((tNoComp >= tNoSent) &&
  1679.                (theLastExecOpInList->theCommitIndicator == 1)){
  1680.       /**********************************************************************/
  1681.       // We sent the transaction with Commit flag set and received a CONF with
  1682.       // no Commit flag set. This is clearly an anomaly.
  1683.       /**********************************************************************/
  1684.       theError.code = 4011;
  1685.       theCompletionStatus = NdbConnection::CompletedFailure;
  1686.       theCommitStatus = NdbConnection::Aborted;
  1687.       return 0;
  1688.     }//if
  1689.     if (tNoComp >= tNoSent) {
  1690.       return 0; // No more operations to wait for
  1691.     }//if
  1692.      // Not completed the reception yet.
  1693.   } else {
  1694. #ifdef NDB_NO_DROPPED_SIGNAL
  1695.     abort();
  1696. #endif
  1697.   }
  1698.   return -1;
  1699. }//NdbConnection::receiveTCINDXCONF()
  1700. /*****************************************************************************
  1701. int receiveTCINDXREF( NdbApiSignal* aSignal)
  1702. Return Value:   Return 0 : send was succesful.
  1703.                 Return -1: In all other case.   
  1704. Parameters:     aSignal: the signal object that contains the 
  1705.                 TCINDXREF signal from TC.
  1706. Remark:         Handles the reception of the TCINDXREF signal.
  1707. *****************************************************************************/
  1708. int
  1709. NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
  1710. {
  1711.   if(checkState_TransId(aSignal->getDataPtr()+1)){
  1712.     theError.code = aSignal->readData(4); // Override any previous errors
  1713.     /**********************************************************************/
  1714.     /* A serious error has occured. This could be due to deadlock or */
  1715.     /* lack of resources or simply a programming error in NDB. This  */
  1716.     /* transaction will be aborted. Actually it has already been     */
  1717.     /* and we only need to report completion and return with the     */
  1718.     /* error code to the application.       */
  1719.     /**********************************************************************/
  1720.     theCompletionStatus = NdbConnection::CompletedFailure;
  1721.     theCommitStatus = NdbConnection::Aborted;
  1722.     return 0;
  1723.   } else {
  1724. #ifdef NDB_NO_DROPPED_SIGNAL
  1725.     abort();
  1726. #endif
  1727.   }
  1728.   return -1;
  1729. }//NdbConnection::receiveTCINDXREF()
  1730. /*******************************************************************************
  1731. int OpCompletedFailure();
  1732. Return Value:  Return 0 : OpCompleteSuccess was successful.
  1733.                Return -1: In all other case.
  1734. Parameters:    aErrorCode: The error code.
  1735. Remark:        An operation was completed with failure.
  1736. *******************************************************************************/
  1737. int 
  1738. NdbConnection::OpCompleteFailure(Uint8 abortOption, bool setFailure)
  1739. {
  1740.   Uint32 tNoComp = theNoOfOpCompleted;
  1741.   Uint32 tNoSent = theNoOfOpSent;
  1742.   if (setFailure)
  1743.     theCompletionStatus = NdbConnection::CompletedFailure;
  1744.   tNoComp++;
  1745.   theNoOfOpCompleted = tNoComp;
  1746.   if (tNoComp == tNoSent) {
  1747.     //------------------------------------------------------------------------
  1748.     //If the transaction consists of only simple reads we can set
  1749.     //Commit state Aborted.  Otherwise this simple operation cannot
  1750.     //decide the success of the whole transaction since a simple
  1751.     //operation is not really part of that transaction.
  1752.     //------------------------------------------------------------------------
  1753.     if (abortOption == AO_IgnoreError){
  1754.       /**
  1755.        * There's always a TCKEYCONF when using IgnoreError
  1756.        */
  1757.       return -1;
  1758.     }
  1759.     
  1760.     return 0; // Last operation received
  1761.   } else if (tNoComp > tNoSent) {
  1762.     setOperationErrorCodeAbort(4113); // Too many operations, 
  1763.                                         // stop waiting for more
  1764.     return 0;
  1765.   } else {
  1766.     return -1; // Continue waiting for more signals
  1767.   }//if
  1768. }//NdbConnection::OpCompleteFailure()
  1769. /******************************************************************************
  1770. int OpCompleteSuccess();
  1771. Return Value:  Return 0 : OpCompleteSuccess was successful.
  1772.                Return -1: In all other case.  
  1773. Remark:        An operation was completed with success.
  1774. *******************************************************************************/
  1775. int 
  1776. NdbConnection::OpCompleteSuccess()
  1777. {
  1778.   Uint32 tNoComp = theNoOfOpCompleted;
  1779.   Uint32 tNoSent = theNoOfOpSent;
  1780.   tNoComp++;
  1781.   theNoOfOpCompleted = tNoComp;
  1782.   if (tNoComp == tNoSent) { // Last operation completed
  1783.     return 0;
  1784.   } else if (tNoComp < tNoSent) {
  1785.     return -1; // Continue waiting for more signals
  1786.   } else {
  1787.     setOperationErrorCodeAbort(4113); // Too many operations, 
  1788.                                         // stop waiting for more
  1789.     theCompletionStatus = NdbConnection::CompletedFailure;
  1790.     return 0;
  1791.   }//if
  1792. }//NdbConnection::OpCompleteSuccess()
  1793. /******************************************************************************
  1794.  int            getGCI();
  1795. Remark: Get global checkpoint identity of the transaction
  1796. *******************************************************************************/
  1797. int
  1798. NdbConnection::getGCI()
  1799. {
  1800.   if (theCommitStatus == NdbConnection::Committed) {
  1801.     return theGlobalCheckpointId;
  1802.   }//if
  1803.   return 0;
  1804. }//NdbConnection::getGCI()
  1805. /*******************************************************************************
  1806. Uint64 getTransactionId(void);
  1807. Remark:        Get the transaction identity. 
  1808. *******************************************************************************/
  1809. Uint64
  1810. NdbConnection::getTransactionId()
  1811. {
  1812.   return theTransactionId;
  1813. }//NdbConnection::getTransactionId()
  1814. NdbConnection::CommitStatusType
  1815. NdbConnection::commitStatus()
  1816. {
  1817.   return theCommitStatus;
  1818. }//NdbConnection::commitStatus()
  1819. int 
  1820. NdbConnection::getNdbErrorLine()
  1821. {
  1822.   return theErrorLine;
  1823. }
  1824. NdbOperation*
  1825. NdbConnection::getNdbErrorOperation()
  1826. {
  1827.   return theErrorOperation;
  1828. }//NdbConnection::getNdbErrorOperation()
  1829. const NdbOperation * 
  1830. NdbConnection::getNextCompletedOperation(const NdbOperation * current) const {
  1831.   if(current == 0)
  1832.     return theCompletedFirstOp;
  1833.   return current->theNext;
  1834. }
  1835. #ifdef VM_TRACE
  1836. #define CASE(x) case x: ndbout << " " << #x; break
  1837. void
  1838. NdbConnection::printState()
  1839. {
  1840.   ndbout << "con=" << hex << this << dec;
  1841.   ndbout << " node=" << getConnectedNodeId();
  1842.   switch (theStatus) {
  1843.   CASE(NotConnected);
  1844.   CASE(Connecting);
  1845.   CASE(Connected);
  1846.   CASE(DisConnecting);
  1847.   CASE(ConnectFailure);
  1848.   default: ndbout << (Uint32) theStatus;
  1849.   }
  1850.   switch (theListState) {
  1851.   CASE(NotInList);
  1852.   CASE(InPreparedList);
  1853.   CASE(InSendList);
  1854.   CASE(InCompletedList);
  1855.   default: ndbout << (Uint32) theListState;
  1856.   }
  1857.   switch (theSendStatus) {
  1858.   CASE(NotInit);
  1859.   CASE(InitState);
  1860.   CASE(sendOperations);
  1861.   CASE(sendCompleted);
  1862.   CASE(sendCOMMITstate);
  1863.   CASE(sendABORT);
  1864.   CASE(sendABORTfail);
  1865.   CASE(sendTC_ROLLBACK);
  1866.   CASE(sendTC_COMMIT);
  1867.   CASE(sendTC_OP);
  1868.   default: ndbout << (Uint32) theSendStatus;
  1869.   }
  1870.   switch (theCommitStatus) {
  1871.   CASE(NotStarted);
  1872.   CASE(Started);
  1873.   CASE(Committed);
  1874.   CASE(Aborted);
  1875.   CASE(NeedAbort);
  1876.   default: ndbout << (Uint32) theCommitStatus;
  1877.   }
  1878.   switch (theCompletionStatus) {
  1879.   CASE(NotCompleted);
  1880.   CASE(CompletedSuccess);
  1881.   CASE(CompletedFailure);
  1882.   CASE(DefinitionFailure);
  1883.   default: ndbout << (Uint32) theCompletionStatus;
  1884.   }
  1885.   ndbout << endl;
  1886. }
  1887. #undef CASE
  1888. #endif
  1889. int
  1890. NdbConnection::report_node_failure(Uint32 id){
  1891.   NdbNodeBitmask::set(m_failed_db_nodes, id);
  1892.   if(!NdbNodeBitmask::get(m_db_nodes, id))
  1893.   {
  1894.     return 0;
  1895.   }
  1896.   
  1897.   /**
  1898.    *   Arrived
  1899.    *   TCKEYCONF   TRANSIDAI
  1900.    * 1)   -           -
  1901.    * 2)   -           X
  1902.    * 3)   X           -
  1903.    * 4)   X           X
  1904.    */
  1905.   NdbOperation* tmp = theFirstExecOpInList;
  1906.   const Uint32 len = TcKeyConf::SimpleReadBit | id;
  1907.   Uint32 tNoComp = theNoOfOpCompleted;
  1908.   Uint32 tNoSent = theNoOfOpSent;
  1909.   while(tmp != 0)
  1910.   {
  1911.     if(tmp->theReceiver.m_expected_result_length == len && 
  1912.        tmp->theReceiver.m_received_result_length == 0)
  1913.     {
  1914.       tNoComp++;
  1915.       tmp->theError.code = 4119;
  1916.     }
  1917.     tmp = tmp->next();
  1918.   }
  1919.   theNoOfOpCompleted = tNoComp;
  1920.   if(tNoComp == tNoSent)
  1921.   {
  1922.     theError.code = 4119;
  1923.     theCompletionStatus = NdbConnection::CompletedFailure;    
  1924.     return 1;
  1925.   }
  1926.   return 0;
  1927. }