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

MySQL数据库

开发平台:

Visual C++

  1. /* ABORT OF ACC AND TUP ALREADY COMPLETED. THIS STATE IS ONLY USED WHEN      */
  2. /* CREATING A NEW FRAGMENT.                                                  */
  3. /* ------------------------------------------------------------------------- */
  4.     continueAbortLab(signal);
  5.     return;
  6.     break;
  7.   case TcConnectionrec::WAIT_TUP_TO_ABORT:
  8.   case TcConnectionrec::ABORT_STOPPED:
  9.   case TcConnectionrec::LOG_ABORT_QUEUED:
  10.   case TcConnectionrec::WAIT_ACC_ABORT:
  11.   case TcConnectionrec::ABORT_QUEUED:
  12.     jam();
  13. /* ------------------------------------------------------------------------- */
  14. /*ABORT IS ALREADY ONGOING DUE TO SOME ERROR. WE HAVE ALREADY SET THE STATE  */
  15. /*OF THE ABORT SO THAT WE KNOW THAT TC EXPECTS A REPORT. WE CAN THUS SIMPLY  */
  16. /*EXIT.                                                                      */
  17. /* ------------------------------------------------------------------------- */
  18.     return;
  19.     break;
  20.   case TcConnectionrec::COMMIT_STOPPED:
  21.   case TcConnectionrec::LOG_COMMIT_QUEUED:
  22.   case TcConnectionrec::COMMIT_QUEUED:
  23.     jam();
  24. /* ------------------------------------------------------------------------- */
  25. /*THIS IS ONLY AN ALLOWED STATE IF A DIRTY WRITE OR SIMPLE READ IS PERFORMED.*/
  26. /*IF WE ARE MERELY CHECKING THE TRANSACTION STATE IT IS ALSO AN ALLOWED STATE*/
  27. /* ------------------------------------------------------------------------- */
  28.     if (regTcPtr->dirtyOp == ZTRUE) {
  29.       jam();
  30. /* ------------------------------------------------------------------------- */
  31. /*COMPLETE THE DIRTY WRITE AND THEN REPORT COMPLETED BACK TO TC. SINCE IT IS */
  32. /*A DIRTY WRITE IT IS ALLOWED TO COMMIT EVEN IF THE TRANSACTION ABORTS.      */
  33. /* ------------------------------------------------------------------------- */
  34.       return;
  35.     }//if
  36.     if (regTcPtr->simpleRead) {
  37.       jam();
  38. /* ------------------------------------------------------------------------- */
  39. /*A SIMPLE READ IS CURRENTLY RELEASING THE LOCKS OR WAITING FOR ACCESS TO    */
  40. /*ACC TO CLEAR THE LOCKS. COMPLETE THIS PROCESS AND THEN RETURN AS NORMAL.   */
  41. /*NO DATA HAS CHANGED DUE TO THIS SIMPLE READ ANYWAY.                        */
  42. /* ------------------------------------------------------------------------- */
  43.       return;
  44.     }//if
  45.     ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
  46.     jam();
  47. /* ------------------------------------------------------------------------- */
  48. /*WE ARE ONLY CHECKING THE STATUS OF THE TRANSACTION. IT IS COMMITTING.      */
  49. /*COMPLETE THE COMMIT LOCALLY AND THEN SEND REPORT OF COMMITTED TO THE NEW TC*/
  50. /* ------------------------------------------------------------------------- */
  51.     return;
  52.     break;
  53.   case TcConnectionrec::COMMITTED:
  54.     jam();
  55.     ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
  56. /* ------------------------------------------------------------------------- */
  57. /*WE ARE CHECKING TRANSACTION STATUS. REPORT COMMITTED AND CONTINUE WITH THE */
  58. /*NEXT OPERATION.                                                            */
  59. /* ------------------------------------------------------------------------- */
  60.     sendLqhTransconf(signal, LqhTransConf::Committed);
  61.     return;
  62.     break;
  63.   default:
  64.     ndbrequire(false);
  65. /* ------------------------------------------------------------------------- */
  66. /*THE STATE WAS NOT AN ALLOWED STATE ON A NORMAL OPERATION. SCANS AND COPY   */
  67. /*FRAGMENT OPERATIONS SHOULD HAVE EXECUTED IN ANOTHER PATH.                  */
  68. /* ------------------------------------------------------------------------- */
  69.     break;
  70.   }//switch
  71.   abortCommonLab(signal);
  72.   return;
  73. }//Dblqh::abortStateHandlerLab()
  74. void Dblqh::abortErrorLab(Signal* signal) 
  75. {
  76.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  77.   TcConnectionrec * const regTcPtr = tcConnectptr.p;
  78.   if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
  79.     jam();
  80.     regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
  81.     regTcPtr->errorCode = terrorCode;
  82.   }//if
  83.   /* -----------------------------------------------------------------------
  84.    *       ACTIVE CREATION IS RESET FOR ALL ERRORS WHICH SHOULD BE HANDLED 
  85.    *       WITH NORMAL ABORT HANDLING.
  86.    * ----------------------------------------------------------------------- */
  87.   regTcPtr->activeCreat = ZFALSE;
  88.   abortCommonLab(signal);
  89.   return;
  90. }//Dblqh::abortErrorLab()
  91. void Dblqh::abortCommonLab(Signal* signal) 
  92. {
  93.   TcConnectionrec * const regTcPtr = tcConnectptr.p;
  94.   const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
  95.   if(regTcPtr->activeCreat != ZTRUE && commitAckMarker != RNIL){
  96.     /**
  97.      * There is no NR ongoing and we have a marker
  98.      */
  99.     jam();
  100. #ifdef MARKER_TRACE
  101.     {
  102.       CommitAckMarkerPtr tmp;
  103.       m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
  104.       ndbout_c("Abo marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2);
  105.     }
  106. #endif
  107.     m_commitAckMarkerHash.release(commitAckMarker);
  108.     regTcPtr->commitAckMarker = RNIL;
  109.   }
  110.   
  111.   fragptr.i = regTcPtr->fragmentptr;
  112.   if (fragptr.i != RNIL) {
  113.     jam();
  114.     ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  115.     switch (fragptr.p->fragStatus) {
  116.     case Fragrecord::FSACTIVE:
  117.     case Fragrecord::CRASH_RECOVERING:
  118.     case Fragrecord::ACTIVE_CREATION:
  119.       jam();
  120.       linkActiveFrag(signal);
  121.       abortContinueAfterBlockedLab(signal, true);
  122.       return;
  123.       break;
  124.     case Fragrecord::BLOCKED:
  125.       jam();
  126.       linkFragQueue(signal);
  127.       regTcPtr->transactionState = TcConnectionrec::ABORT_STOPPED;
  128.       return;
  129.       break;
  130.     case Fragrecord::FREE:
  131.       jam();
  132.     case Fragrecord::DEFINED:
  133.       jam();
  134.     case Fragrecord::REMOVING:
  135.       jam();
  136.     default:
  137.       ndbrequire(false);
  138.       break;
  139.     }//switch
  140.   } else {
  141.     jam();
  142.     continueAbortLab(signal);
  143.   }//if
  144. }//Dblqh::abortCommonLab()
  145. void Dblqh::abortContinueAfterBlockedLab(Signal* signal, bool canBlock) 
  146. {
  147.   /* ------------------------------------------------------------------------
  148.    *       INPUT:          TC_CONNECTPTR           ACTIVE OPERATION RECORD
  149.    * ------------------------------------------------------------------------
  150.    * ------------------------------------------------------------------------
  151.    *       CAN COME HERE AS RESTART AFTER BEING BLOCKED BY A LOCAL CHECKPOINT.
  152.    * ------------------------------------------------------------------------
  153.    *       ALSO AS PART OF A NORMAL ABORT WITHOUT BLOCKING.
  154.    *       WE MUST ABORT TUP BEFORE ACC TO ENSURE THAT NO ONE RACES IN 
  155.    *       AND SEES A STATE IN TUP.
  156.    * ------------------------------------------------------------------------ */
  157.   TcConnectionrec * const regTcPtr = tcConnectptr.p;
  158.   fragptr.i = regTcPtr->fragmentptr;
  159.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  160.   if ((cCommitBlocked == true) &&
  161.       (fragptr.p->fragActiveStatus == ZTRUE) &&
  162.       (canBlock == true) &&
  163.       (regTcPtr->operation != ZREAD)) {
  164.     jam();
  165. /* ------------------------------------------------------------------------- */
  166. // TUP and/or ACC have problems in writing the undo log to disk fast enough.
  167. // We must avoid the abort at this time and try later instead. The fragment
  168. // is also active with a local checkpoint and this commit can generate UNDO
  169. // log records that overflow the UNDO log buffer.
  170. //
  171. // In certain situations it is simply too complex to insert a wait state here
  172. // since ACC is active and we cannot release the operation from the active
  173. // list without causing great complexity.
  174. /* ------------------------------------------------------------------------- */
  175. /*---------------------------------------------------------------------------*/
  176. // We must delay the write of abort info to the log to safe-guard against
  177. // a crash due to lack of log pages. We temporary stop all log writes to this
  178. // log part to ensure that we don't get a buffer explosion in the delayed
  179. // signal buffer instead.
  180. /*---------------------------------------------------------------------------*/
  181.     releaseActiveFrag(signal);
  182.     logPartPtr.i = regTcPtr->hashValue & 3;
  183.     ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
  184.     linkWaitLog(signal, logPartPtr);
  185.     regTcPtr->transactionState = TcConnectionrec::ABORT_QUEUED;
  186.     if (logPartPtr.p->logPartState == LogPartRecord::IDLE) {
  187.       jam();
  188.       logPartPtr.p->logPartState = LogPartRecord::ACTIVE;
  189.     }//if
  190.     return;
  191.   }//if
  192.   signal->theData[0] = regTcPtr->tupConnectrec;
  193.   EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
  194.   regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
  195.   signal->theData[0] = regTcPtr->accConnectrec;
  196.   EXECUTE_DIRECT(DBACC, GSN_ACC_ABORTREQ, signal, 1);
  197.   /* ------------------------------------------------------------------------
  198.    * We need to insert a real-time break by sending ACC_ABORTCONF through the
  199.    * job buffer to ensure that we catch any ACCKEYCONF or TUPKEYCONF or
  200.    * TUPKEYREF that are in the job buffer but not yet processed. Doing 
  201.    * everything without that would race and create a state error when they 
  202.    * are executed.
  203.    * ----------------------------------------------------------------------- */
  204.   return;
  205. }//Dblqh::abortContinueAfterBlockedLab()
  206. /* ******************>> */
  207. /*  ACC_ABORTCONF     > */
  208. /* ******************>> */
  209. void Dblqh::execACC_ABORTCONF(Signal* signal) 
  210. {
  211.   jamEntry();
  212.   tcConnectptr.i = signal->theData[0];
  213.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  214.   TcConnectionrec * const regTcPtr = tcConnectptr.p;
  215.   ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_ACC_ABORT);
  216.   if (regTcPtr->activeCreat == ZTRUE) {
  217.     /* ----------------------------------------------------------------------
  218.      * A NORMAL EVENT DURING CREATION OF A FRAGMENT. WE NOW NEED TO CONTINUE
  219.      * WITH NORMAL COMMIT PROCESSING.
  220.      * ---------------------------------------------------------------------- */
  221.     if (regTcPtr->currTupAiLen == regTcPtr->totReclenAi) {
  222.       jam();
  223.       regTcPtr->abortState = TcConnectionrec::ABORT_IDLE;
  224.       rwConcludedLab(signal);
  225.       return;
  226.     } else {
  227.       ndbrequire(regTcPtr->currTupAiLen < regTcPtr->totReclenAi);
  228.       jam();
  229.       releaseActiveFrag(signal);
  230.       regTcPtr->transactionState = TcConnectionrec::WAIT_AI_AFTER_ABORT;
  231.       return;
  232.     }//if
  233.   }//if
  234.   releaseActiveFrag(signal);
  235.   continueAbortLab(signal);
  236.   return;
  237. }//Dblqh::execACC_ABORTCONF()
  238. void Dblqh::continueAbortLab(Signal* signal) 
  239. {
  240.   TcConnectionrec * const regTcPtr = tcConnectptr.p;
  241.   /* ------------------------------------------------------------------------
  242.    *  AN ERROR OCCURED IN THE ACTIVE CREATION AFTER THE ABORT PHASE. 
  243.    *  WE NEED TO CONTINUE WITH A NORMAL ABORT.
  244.    * ------------------------------------------------------------------------ 
  245.    *       ALSO USED FOR NORMAL CLEAN UP AFTER A NORMAL ABORT.
  246.    * ------------------------------------------------------------------------
  247.    *       ALSO USED WHEN NO FRAGMENT WAS SET UP ON OPERATION.
  248.    * ------------------------------------------------------------------------ */
  249.   if (regTcPtr->logWriteState == TcConnectionrec::WRITTEN) {
  250.     jam();
  251.     /* ----------------------------------------------------------------------
  252.      * I NEED TO INSERT A ABORT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
  253.      * TRANSACTION.
  254.      * ---------------------------------------------------------------------- */
  255.     initLogPointers(signal);
  256.     if (logPartPtr.p->logPartState == LogPartRecord::ACTIVE) {
  257.       jam();
  258.       /* --------------------------------------------------------------------
  259.        * A PREPARE OPERATION IS CURRENTLY WRITING IN THE LOG. 
  260.        * WE MUST WAIT ON OUR TURN TO WRITE THE LOG. 
  261.        * IT IS NECESSARY TO WRITE ONE LOG RECORD COMPLETELY 
  262.        * AT A TIME OTHERWISE WE WILL SCRAMBLE THE LOG.
  263.        * -------------------------------------------------------------------- */
  264.       linkWaitLog(signal, logPartPtr);
  265.       regTcPtr->transactionState = TcConnectionrec::LOG_ABORT_QUEUED;
  266.       return;
  267.     }//if
  268.     if (cnoOfLogPages == 0) {
  269.       jam();
  270. /*---------------------------------------------------------------------------*/
  271. // We must delay the write of commit info to the log to safe-guard against
  272. // a crash due to lack of log pages. We temporary stop all log writes to this
  273. // log part to ensure that we don't get a buffer explosion in the delayed
  274. // signal buffer instead.
  275. /*---------------------------------------------------------------------------*/
  276.       linkWaitLog(signal, logPartPtr);
  277.       regTcPtr->transactionState = TcConnectionrec::LOG_ABORT_QUEUED;
  278.       if (logPartPtr.p->logPartState == LogPartRecord::IDLE) {
  279.         jam();
  280.         logPartPtr.p->logPartState = LogPartRecord::ACTIVE;
  281.       }//if
  282.       return;
  283.     }//if
  284.     writeAbortLog(signal);
  285.     removeLogTcrec(signal);
  286.   } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_STARTED) {
  287.     jam();
  288.   } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN) {
  289.     jam();
  290.     /* ------------------------------------------------------------------
  291.      * IT IS A READ OPERATION OR OTHER OPERATION THAT DO NOT USE THE LOG.
  292.      * ------------------------------------------------------------------ */
  293.     /* ------------------------------------------------------------------
  294.      * THE LOG HAS NOT BEEN WRITTEN SINCE THE LOG FLAG WAS FALSE. 
  295.      * THIS CAN OCCUR WHEN WE ARE STARTING A NEW FRAGMENT.
  296.      * ------------------------------------------------------------------ */
  297.     regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
  298.   } else {
  299.     ndbrequire(regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
  300.     jam();
  301.     /* ----------------------------------------------------------------
  302.      * THE STATE WAS SET TO NOT_WRITTEN BY THE OPERATION BUT LATER 
  303.      * A SCAN OF ALL OPERATION RECORD CHANGED IT INTO NOT_WRITTEN_WAIT. 
  304.      * THIS INDICATES THAT WE ARE WAITING FOR THIS OPERATION TO COMMIT 
  305.      * OR ABORT SO THAT WE CAN FIND THE 
  306.      * STARTING GLOBAL CHECKPOINT OF THIS NEW FRAGMENT.
  307.      * ---------------------------------------------------------------- */
  308.      checkScanTcCompleted(signal);
  309.   }//if
  310.   continueAfterLogAbortWriteLab(signal);
  311.   return;
  312. }//Dblqh::continueAbortLab()
  313. void Dblqh::continueAfterLogAbortWriteLab(Signal* signal) 
  314. {
  315.   TcConnectionrec * const regTcPtr = tcConnectptr.p;
  316.   if (regTcPtr->simpleRead) {
  317.     jam();
  318.     TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
  319.     
  320.     tcKeyRef->connectPtr = regTcPtr->applOprec;
  321.     tcKeyRef->transId[0] = regTcPtr->transid[0];
  322.     tcKeyRef->transId[1] = regTcPtr->transid[1];
  323.     tcKeyRef->errorCode = regTcPtr->errorCode;
  324.     sendSignal(regTcPtr->applRef, 
  325.                GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
  326.     cleanUp(signal);
  327.     return;
  328.   }//if
  329.   if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_LQH) {
  330.     LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtrSend();
  331.     jam();
  332.     lqhKeyRef->userRef = regTcPtr->clientConnectrec;
  333.     lqhKeyRef->connectPtr = regTcPtr->tcOprec;
  334.     lqhKeyRef->errorCode = regTcPtr->errorCode;
  335.     lqhKeyRef->transId1 = regTcPtr->transid[0];
  336.     lqhKeyRef->transId2 = regTcPtr->transid[1];
  337.     sendSignal(regTcPtr->clientBlockref, GSN_LQHKEYREF, signal, 
  338.                LqhKeyRef::SignalLength, JBB);
  339.   } else if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
  340.     jam();
  341.     sendAborted(signal);
  342.   } else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
  343.     jam();
  344.     sendLqhTransconf(signal, LqhTransConf::Aborted);
  345.   } else {
  346.     ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
  347.     jam();
  348.     signal->theData[0] = regTcPtr->reqRef;
  349.     signal->theData[1] = tcConnectptr.i;
  350.     signal->theData[2] = cownNodeid;
  351.     signal->theData[3] = regTcPtr->transid[0];
  352.     signal->theData[4] = regTcPtr->transid[1];
  353.     sendSignal(regTcPtr->reqBlockref, GSN_ABORTCONF, 
  354.                signal, 5, JBB);
  355.   }//if
  356.   cleanUp(signal);
  357. }//Dblqh::continueAfterLogAbortWriteLab()
  358. /* ########################################################################## 
  359.  * #######                       MODULE TO HANDLE TC FAILURE          ####### 
  360.  *
  361.  * ########################################################################## */
  362. /* ************************************************************************>> 
  363.  *  NODE_FAILREP: Node failure report. Sender Ndbcntr. Set status of failed 
  364.  *  node to down and reply with NF_COMPLETEREP to DIH which will report that 
  365.  *  LQH has completed failure handling.
  366.  * ************************************************************************>> */
  367. void Dblqh::execNODE_FAILREP(Signal* signal) 
  368. {
  369.   UintR TfoundNodes = 0;
  370.   UintR TnoOfNodes;
  371.   UintR Tdata[MAX_NDB_NODES];
  372.   Uint32 i;
  373.   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
  374.   TnoOfNodes = nodeFail->noOfNodes;
  375.   UintR index = 0;
  376.   for (i = 1; i < MAX_NDB_NODES; i++) {
  377.     jam();
  378.     if(NodeBitmask::get(nodeFail->theNodes, i)){
  379.       jam();
  380.       Tdata[index] = i;
  381.       index++;
  382.     }//if
  383.   }//for
  384.   lcpPtr.i = 0;
  385.   ptrAss(lcpPtr, lcpRecord);
  386.   
  387.   ndbrequire(index == TnoOfNodes);
  388.   ndbrequire(cnoOfNodes - 1 < MAX_NDB_NODES);
  389.   for (i = 0; i < TnoOfNodes; i++) {
  390.     const Uint32 nodeId = Tdata[i];
  391.     lcpPtr.p->m_EMPTY_LCP_REQ.clear(nodeId);
  392.     
  393.     for (Uint32 j = 0; j < cnoOfNodes; j++) {
  394.       jam();
  395.       if (cnodeData[j] == nodeId){
  396.         jam();
  397.         cnodeStatus[j] = ZNODE_DOWN;
  398.         TfoundNodes++;
  399.       }//if
  400.     }//for
  401.     NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
  402.     nfCompRep->blockNo      = DBLQH;
  403.     nfCompRep->nodeId       = cownNodeid;
  404.     nfCompRep->failedNodeId = Tdata[i];
  405.     sendSignal(DBDIH_REF, GSN_NF_COMPLETEREP, signal, 
  406.        NFCompleteRep::SignalLength, JBB);
  407.   }//for
  408.   ndbrequire(TnoOfNodes == TfoundNodes);
  409. }//Dblqh::execNODE_FAILREP()
  410. /* ************************************************************************>>
  411.  *  LQH_TRANSREQ: Report status of all transactions where TC was coordinated 
  412.  *  by a crashed TC 
  413.  * ************************************************************************>> */
  414. /* ************************************************************************>>
  415.  *  THIS SIGNAL IS RECEIVED AFTER A NODE CRASH. 
  416.  *  THE NODE HAD A TC AND COORDINATED A NUMBER OF TRANSACTIONS. 
  417.  *  NOW THE MASTER NODE IS PICKING UP THOSE TRANSACTIONS
  418.  *  TO COMPLETE THEM. EITHER ABORT THEM OR COMMIT THEM.
  419.  * ************************************************************************>> */
  420. void Dblqh::execLQH_TRANSREQ(Signal* signal) 
  421. {
  422.   jamEntry();
  423.   Uint32 newTcPtr = signal->theData[0];
  424.   BlockReference newTcBlockref = signal->theData[1];
  425.   Uint32 oldNodeId = signal->theData[2];
  426.   tcNodeFailptr.i = oldNodeId;
  427.   ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
  428.   if ((tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_TRUE) ||
  429.       (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK)) {
  430.     jam();
  431.     tcNodeFailptr.p->lastNewTcBlockref = newTcBlockref;
  432.   /* ------------------------------------------------------------------------
  433.    * WE HAVE RECEIVED A SIGNAL SPECIFYING THAT WE NEED TO HANDLE THE FAILURE
  434.    * OF A TC.  NOW WE RECEIVE ANOTHER SIGNAL WITH THE SAME ORDER. THIS CAN
  435.    * OCCUR IF THE NEW TC FAILS. WE MUST BE CAREFUL IN THIS CASE SO THAT WE DO
  436.    * NOT START PARALLEL ACTIVITIES TRYING TO DO THE SAME THING. WE SAVE THE
  437.    * NEW BLOCK REFERENCE TO THE LAST NEW TC IN A VARIABLE AND ASSIGN TO IT TO
  438.    * NEW_TC_BLOCKREF WHEN THE OLD PROCESS RETURNS TO LQH_TRANS_NEXT. IT IS
  439.    * CERTAIN TO COME THERE SINCE THIS IS THE ONLY PATH TO TAKE CARE OF THE
  440.    * NEXT TC CONNECT RECORD. WE SET THE STATUS TO BREAK TO INDICATE TO THE OLD
  441.    * PROCESS WHAT IS HAPPENING.
  442.    * ------------------------------------------------------------------------ */
  443.     tcNodeFailptr.p->lastNewTcRef = newTcPtr;
  444.     tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_BREAK;
  445.     return;
  446.   }//if
  447.   tcNodeFailptr.p->oldNodeId = oldNodeId;
  448.   tcNodeFailptr.p->newTcBlockref = newTcBlockref;
  449.   tcNodeFailptr.p->newTcRef = newTcPtr;
  450.   tcNodeFailptr.p->tcRecNow = 0;
  451.   tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
  452.   signal->theData[0] = ZLQH_TRANS_NEXT;
  453.   signal->theData[1] = tcNodeFailptr.i;
  454.   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  455.   return;
  456. }//Dblqh::execLQH_TRANSREQ()
  457. void Dblqh::lqhTransNextLab(Signal* signal) 
  458. {
  459.   UintR tend;
  460.   UintR tstart;
  461.   UintR guard0;
  462.   if (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK) {
  463.     jam();
  464.     /* ----------------------------------------------------------------------
  465.      *  AN INTERRUPTION TO THIS NODE FAIL HANDLING WAS RECEIVED AND A NEW 
  466.      *  TC HAVE BEEN ASSIGNED TO TAKE OVER THE FAILED TC. PROBABLY THE OLD 
  467.      *  NEW TC HAVE FAILED.
  468.      * ---------------------------------------------------------------------- */
  469.     tcNodeFailptr.p->newTcBlockref = tcNodeFailptr.p->lastNewTcBlockref;
  470.     tcNodeFailptr.p->newTcRef = tcNodeFailptr.p->lastNewTcRef;
  471.     tcNodeFailptr.p->tcRecNow = 0;
  472.     tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
  473.   }//if
  474.   tstart = tcNodeFailptr.p->tcRecNow;
  475.   tend = tstart + 200;
  476.   guard0 = tend;
  477.   for (tcConnectptr.i = tstart; tcConnectptr.i <= guard0; tcConnectptr.i++) {
  478.     jam();
  479.     if (tcConnectptr.i >= ctcConnectrecFileSize) {
  480.       jam();
  481.       /**
  482.        * Finished with scanning operation record
  483.        *
  484.        * now scan markers
  485.        */
  486.       scanMarkers(signal, tcNodeFailptr.i, 0, RNIL);
  487.       return;
  488.     }//if
  489.     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  490.     if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
  491.       if (tcConnectptr.p->transactionState != TcConnectionrec::TC_NOT_CONNECTED) {
  492.         if (tcConnectptr.p->tcScanRec == RNIL) {
  493.           if (refToNode(tcConnectptr.p->tcBlockref) == tcNodeFailptr.p->oldNodeId) {
  494.             if (tcConnectptr.p->operation != ZREAD) {
  495.               jam();
  496.               tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
  497.               tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
  498.               abortStateHandlerLab(signal);
  499.               return;
  500.             } else {
  501.               jam();
  502.               if (tcConnectptr.p->opSimple != ZTRUE) {
  503.                 jam();
  504.                 tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
  505.                 tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
  506.                 abortStateHandlerLab(signal);
  507.                 return;
  508.               }//if
  509.             }//if
  510.           }//if
  511.         } else {
  512.           scanptr.i = tcConnectptr.p->tcScanRec;
  513.   c_scanRecordPool.getPtr(scanptr);
  514.           if (scanptr.p->scanType == ScanRecord::COPY) {
  515.             jam();
  516.             if (scanptr.p->scanNodeId == tcNodeFailptr.p->oldNodeId) {
  517.               jam();
  518.       /* ------------------------------------------------------------
  519.        * THE RECEIVER OF THE COPY HAVE FAILED. 
  520.        * WE HAVE TO CLOSE THE COPY PROCESS. 
  521.        * ------------------------------------------------------------ */
  522.               tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
  523.               tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
  524.               closeCopyRequestLab(signal);
  525.               return;
  526.             }//if
  527.           } else {
  528.             if (scanptr.p->scanType == ScanRecord::SCAN) {
  529.               jam();
  530.               if (refToNode(tcConnectptr.p->tcBlockref) == 
  531.   tcNodeFailptr.p->oldNodeId) {
  532.                 jam();
  533.                 tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
  534.                 tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
  535.                 closeScanRequestLab(signal);
  536.                 return;
  537.               }//if
  538.             } else {
  539.               jam();
  540.       /* ------------------------------------------------------------
  541.        * THIS IS AN ERROR THAT SHOULD NOT OCCUR. WE CRASH THE SYSTEM.
  542.        * ------------------------------------------------------------ */
  543.                systemErrorLab(signal);
  544.                return;
  545.             }//if
  546.           }//if
  547.         }//if
  548.       }//if
  549.     }//if
  550.   }//for
  551.   tcNodeFailptr.p->tcRecNow = tend + 1;
  552.   signal->theData[0] = ZLQH_TRANS_NEXT;
  553.   signal->theData[1] = tcNodeFailptr.i;
  554.   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  555.   return;
  556. }//Dblqh::lqhTransNextLab()
  557. void
  558. Dblqh::scanMarkers(Signal* signal, 
  559.    Uint32 tcNodeFail, 
  560.    Uint32 startBucket, 
  561.    Uint32 i){
  562.   jam();
  563.   
  564.   TcNodeFailRecordPtr tcNodeFailPtr;
  565.   tcNodeFailPtr.i = tcNodeFail;
  566.   ptrCheckGuard(tcNodeFailPtr, ctcNodeFailrecFileSize, tcNodeFailRecord);
  567.   const Uint32 crashedTcNodeId = tcNodeFailPtr.p->oldNodeId;
  568.   
  569.   CommitAckMarkerIterator iter;
  570.   if(i == RNIL){
  571.     m_commitAckMarkerHash.next(startBucket, iter);
  572.   } else {
  573.     jam();
  574.     iter.curr.i = i;
  575.     iter.bucket = startBucket;
  576.     m_commitAckMarkerHash.getPtr(iter.curr);
  577.     m_commitAckMarkerHash.next(iter);
  578.   }
  579.   const Uint32 RT_BREAK = 256;
  580.   for(i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
  581.     jam();
  582.     
  583.     if(iter.curr.i == RNIL){
  584.       /**
  585.        * Done with iteration
  586.        */
  587.       jam();
  588.       
  589.       tcNodeFailPtr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_FALSE;
  590.       signal->theData[0] = tcNodeFailPtr.p->newTcRef;
  591.       signal->theData[1] = cownNodeid;
  592.       signal->theData[2] = LqhTransConf::LastTransConf;
  593.       sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF, 
  594.  signal, 3, JBB);
  595.       return;
  596.     }
  597.     
  598.     if(iter.curr.p->tcNodeId == crashedTcNodeId){
  599.       jam();
  600.       
  601.       /**
  602.        * Found marker belonging to crashed node
  603.        */
  604.       LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
  605.       lqhTransConf->tcRef     = tcNodeFailPtr.p->newTcRef;
  606.       lqhTransConf->lqhNodeId = cownNodeid;
  607.       lqhTransConf->operationStatus = LqhTransConf::Marker;
  608.       lqhTransConf->transId1 = iter.curr.p->transid1;
  609.       lqhTransConf->transId2 = iter.curr.p->transid2;
  610.       lqhTransConf->apiRef   = iter.curr.p->apiRef;
  611.       lqhTransConf->apiOpRec = iter.curr.p->apiOprec;
  612.       sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF, 
  613.  signal, 7, JBB);
  614.       
  615.       signal->theData[0] = ZSCAN_MARKERS;
  616.       signal->theData[1] = tcNodeFailPtr.i;
  617.       signal->theData[2] = iter.bucket;
  618.       signal->theData[3] = iter.curr.i;
  619.       sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
  620.       return;
  621.     }
  622.     
  623.     m_commitAckMarkerHash.next(iter);
  624.   }
  625.   
  626.   signal->theData[0] = ZSCAN_MARKERS;
  627.   signal->theData[1] = tcNodeFailPtr.i;
  628.   signal->theData[2] = iter.bucket;
  629.   signal->theData[3] = RNIL;
  630.   sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
  631. }  
  632. /* #########################################################################
  633.  * #######                       SCAN MODULE                         ####### 
  634.  *
  635.  * #########################################################################
  636.  * -------------------------------------------------------------------------
  637.  * THIS MODULE CONTAINS THE CODE THAT HANDLES A SCAN OF A PARTICULAR FRAGMENT
  638.  * IT OPERATES UNDER THE CONTROL OF TC AND ORDERS ACC TO PERFORM A SCAN OF
  639.  * ALL TUPLES IN THE FRAGMENT. TUP PERFORMS THE NECESSARY SEARCH CONDITIONS
  640.  * TO ENSURE THAT ONLY VALID TUPLES ARE RETURNED TO THE APPLICATION.
  641.  * ------------------------------------------------------------------------- */
  642. void Dblqh::execACC_SCAN_INFO(Signal* signal) 
  643. {
  644.   jamEntry();
  645.   scanptr.i = signal->theData[0];
  646.   c_scanRecordPool.getPtr(scanptr);
  647.   Uint32 length = signal->theData[3];
  648.   ndbrequire(length <= 4);
  649.   accScanInfoEnterLab(signal, &signal->theData[4], length);
  650. }//Dblqh::execACC_SCAN_INFO()
  651. void Dblqh::execACC_SCAN_INFO24(Signal* signal) 
  652. {
  653.   jamEntry();
  654.   scanptr.i = signal->theData[0];
  655.   c_scanRecordPool.getPtr(scanptr);
  656.   Uint32 length = signal->theData[3];
  657.   ndbrequire(length <= 20);
  658.   accScanInfoEnterLab(signal, &signal->theData[4], length);
  659. }//Dblqh::execACC_SCAN_INFO24()
  660. void Dblqh::accScanInfoEnterLab(Signal* signal,
  661.                                 Uint32* dataPtr,
  662.                                 Uint32 length) 
  663. {
  664.   ndbrequire(length != 0);
  665.   if (scanptr.p->scanState == ScanRecord::WAIT_SCAN_KEYINFO) {
  666.     jam();
  667.     if (keyinfoLab(signal, dataPtr, length)) {
  668.       jam();
  669.       nextScanConfLoopLab(signal);
  670.     }//if
  671.   } else {
  672.     ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_COPY_KEYINFO);
  673.     jam();
  674.     if (keyinfoLab(signal, dataPtr, length)) {
  675.       jam();
  676.       copySendTupkeyReqLab(signal);
  677.     }//if
  678.   }//if
  679. }//Dblqh::accScanInfoEnterLab()
  680. /* *************** */
  681. /*  ACC_SCANCONF > */
  682. /* *************** */
  683. void Dblqh::execACC_SCANCONF(Signal* signal) 
  684. {
  685.   AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
  686.   jamEntry();
  687.   scanptr.i = accScanConf->scanPtr;
  688.   c_scanRecordPool.getPtr(scanptr);
  689.   if (scanptr.p->scanState == ScanRecord::WAIT_ACC_SCAN) {
  690.     accScanConfScanLab(signal);
  691.   } else {
  692.     ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_ACC_COPY);
  693.     accScanConfCopyLab(signal);
  694.   }//if
  695. }//Dblqh::execACC_SCANCONF()
  696. /* ************>> */
  697. /*  ACC_SCANREF > */
  698. /* ************>> */
  699. void Dblqh::execACC_SCANREF(Signal* signal) 
  700. {
  701.   jamEntry();
  702.   ndbrequire(false);
  703. }//Dblqh::execACC_SCANREF()
  704. /* ***************>> */
  705. /*  NEXT_SCANCONF  > */
  706. /* ***************>> */
  707. void Dblqh::execNEXT_SCANCONF(Signal* signal) 
  708. {
  709.   NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
  710.   jamEntry();
  711.   scanptr.i = nextScanConf->scanPtr;
  712.   c_scanRecordPool.getPtr(scanptr);
  713.   if (nextScanConf->localKeyLength == 1) {
  714.     jam();
  715.     nextScanConf->localKey[1] = 
  716.                   nextScanConf->localKey[0] & MAX_TUPLES_PER_PAGE;
  717.     nextScanConf->localKey[0] = nextScanConf->localKey[0] >> MAX_TUPLES_BITS;
  718.   }//if
  719.   switch (scanptr.p->scanState) {
  720.   case ScanRecord::WAIT_CLOSE_SCAN:
  721.     jam();
  722.     accScanCloseConfLab(signal);
  723.     break;
  724.   case ScanRecord::WAIT_CLOSE_COPY:
  725.     jam();
  726.     accCopyCloseConfLab(signal);
  727.     break;
  728.   case ScanRecord::WAIT_NEXT_SCAN:               
  729.     jam();     
  730.     nextScanConfScanLab(signal);       
  731.     break;
  732.   case ScanRecord::WAIT_NEXT_SCAN_COPY:
  733.     jam();
  734.     nextScanConfCopyLab(signal);
  735.     break;
  736.   case ScanRecord::WAIT_RELEASE_LOCK:
  737.     jam();
  738.     ndbrequire(signal->length() == 1);
  739.     scanLockReleasedLab(signal);
  740.     break;
  741.   default:
  742.     ndbrequire(false);
  743.   }//switch
  744. }//Dblqh::execNEXT_SCANCONF()
  745. /* ***************> */
  746. /*  NEXT_SCANREF  > */
  747. /* ***************> */
  748. void Dblqh::execNEXT_SCANREF(Signal* signal) 
  749. {
  750.   jamEntry();
  751.   systemErrorLab(signal);
  752.   return;
  753. }//Dblqh::execNEXT_SCANREF()
  754. /* ******************> */
  755. /*  STORED_PROCCONF  > */
  756. /* ******************> */
  757. void Dblqh::execSTORED_PROCCONF(Signal* signal) 
  758. {
  759.   jamEntry();
  760.   tcConnectptr.i = signal->theData[0];
  761.   Uint32 storedProcId = signal->theData[1];
  762.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  763.   scanptr.i = tcConnectptr.p->tcScanRec;
  764.   c_scanRecordPool.getPtr(scanptr);
  765.   switch (scanptr.p->scanState) {
  766.   case ScanRecord::WAIT_STORED_PROC_SCAN:
  767.     jam();
  768.     scanptr.p->scanStoredProcId = storedProcId;
  769.     storedProcConfScanLab(signal);
  770.     break;
  771.   case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
  772.     jam();
  773.     releaseActiveFrag(signal);
  774.     tupScanCloseConfLab(signal);
  775.     break;
  776.   case ScanRecord::WAIT_STORED_PROC_COPY:
  777.     jam();
  778.     scanptr.p->scanStoredProcId = storedProcId;
  779.     storedProcConfCopyLab(signal);
  780.     break;
  781.   case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
  782.     jam();
  783.     releaseActiveFrag(signal);
  784.     tupCopyCloseConfLab(signal);
  785.     break;
  786.   default:
  787.     ndbrequire(false);
  788.   }//switch
  789. }//Dblqh::execSTORED_PROCCONF()
  790. /* ****************** */
  791. /*  STORED_PROCREF  > */
  792. /* ****************** */
  793. void Dblqh::execSTORED_PROCREF(Signal* signal) 
  794. {
  795.   jamEntry();
  796.   tcConnectptr.i = signal->theData[0];
  797.   Uint32 errorCode  = signal->theData[1];
  798.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  799.   scanptr.i = tcConnectptr.p->tcScanRec;
  800.   c_scanRecordPool.getPtr(scanptr);
  801.   switch (scanptr.p->scanState) {
  802.   case ScanRecord::WAIT_STORED_PROC_SCAN:
  803.     jam();
  804.     scanptr.p->scanStoredProcId = signal->theData[2];
  805.     tcConnectptr.p->errorCode = errorCode;
  806.     closeScanLab(signal);
  807.     break;
  808.   default:
  809.     ndbrequire(false);
  810.   }//switch
  811. }//Dblqh::execSTORED_PROCREF()
  812. /* --------------------------------------------------------------------------
  813.  *       ENTER SCAN_NEXTREQ
  814.  * --------------------------------------------------------------------------
  815.  *       PRECONDITION:
  816.  *       TRANSACTION_STATE = SCAN_STATE
  817.  *       SCAN_STATE = WAIT_SCAN_NEXTREQ
  818.  *
  819.  * Case scanLockHold: ZTRUE  = Unlock previous round of 
  820.  *                             scanned row(s) and fetch next set of rows.
  821.  *                    ZFALSE = Fetch new set of rows.
  822.  * Number of rows to read depends on parallelism and how many rows 
  823.  * left to scan in the fragment. SCAN_NEXTREQ can also be sent with 
  824.  * closeFlag == ZTRUE to close the scan.
  825.  * ------------------------------------------------------------------------- */
  826. void Dblqh::execSCAN_NEXTREQ(Signal* signal) 
  827. {
  828.   jamEntry();
  829.   const ScanFragNextReq * const nextReq = 
  830.                                 (ScanFragNextReq*)&signal->theData[0];
  831.   const Uint32 transid1 = nextReq->transId1;
  832.   const Uint32 transid2 = nextReq->transId2;
  833.   const Uint32 senderData = nextReq->senderData;
  834.   if (findTransaction(transid1, transid2, senderData) != ZOK){
  835.     jam();
  836.     DEBUG(senderData << 
  837.   " Received SCAN_NEXTREQ in LQH with close flag when closed");
  838.     ndbrequire(nextReq->closeFlag == ZTRUE);
  839.     return;
  840.   }
  841.   // Crash node if signal sender is same node
  842.   CRASH_INSERTION2(5021, refToNode(signal->senderBlockRef()) == cownNodeid);
  843.   // Crash node if signal sender is NOT same node
  844.   CRASH_INSERTION2(5022, refToNode(signal->senderBlockRef()) != cownNodeid);
  845.   if (ERROR_INSERTED(5023)){
  846.     // Drop signal if sender is same node
  847.     if (refToNode(signal->senderBlockRef()) == cownNodeid) {
  848.       CLEAR_ERROR_INSERT_VALUE;
  849.       return;
  850.     }
  851.   }//if
  852.   if (ERROR_INSERTED(5024)){
  853.     // Drop signal if sender is NOT same node
  854.     if (refToNode(signal->senderBlockRef()) != cownNodeid) {
  855.       CLEAR_ERROR_INSERT_VALUE;
  856.       return;
  857.     }
  858.   }//if
  859.   if (ERROR_INSERTED(5025)){
  860.     // Delay signal if sender is NOT same node
  861.     if (refToNode(signal->senderBlockRef()) != cownNodeid) {
  862.       CLEAR_ERROR_INSERT_VALUE;
  863.       sendSignalWithDelay(cownref, GSN_SCAN_NEXTREQ, signal, 1000,
  864.   signal->length());
  865.       return;
  866.     }
  867.   }//if
  868.   if (ERROR_INSERTED(5030)){
  869.     ndbout << "ERROR 5030" << endl;
  870.     CLEAR_ERROR_INSERT_VALUE;
  871.     // Drop signal
  872.     return;
  873.   }//if
  874.   if(ERROR_INSERTED(5036)){
  875.     return;
  876.   }
  877.   scanptr.i = tcConnectptr.p->tcScanRec;
  878.   ndbrequire(scanptr.i != RNIL);
  879.   c_scanRecordPool.getPtr(scanptr);
  880.   scanptr.p->scanTcWaiting = ZTRUE;
  881.   /* ------------------------------------------------------------------
  882.    * If close flag is set this scan should be closed
  883.    * If we are waiting for SCAN_NEXTREQ set flag to stop scanning and 
  884.    * continue execution else set flags and wait until the scan 
  885.    * completes itself
  886.    * ------------------------------------------------------------------ */
  887.   if (nextReq->closeFlag == ZTRUE){
  888.     jam();
  889.     if(ERROR_INSERTED(5034)){
  890.       CLEAR_ERROR_INSERT_VALUE;
  891.     }
  892.     if(ERROR_INSERTED(5036)){
  893.       CLEAR_ERROR_INSERT_VALUE;
  894.       return;
  895.     }
  896.     closeScanRequestLab(signal);
  897.     return;
  898.   }//if
  899.   fragptr.i = tcConnectptr.p->fragmentptr;
  900.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  901.   /**
  902.    * Change parameters while running
  903.    *   (is currently not supported)
  904.    */
  905.   const Uint32 max_rows = nextReq->batch_size_rows;
  906.   const Uint32 max_bytes = nextReq->batch_size_bytes;
  907.   ndbrequire(scanptr.p->m_max_batch_size_rows == max_rows);
  908.   ndbrequire(scanptr.p->m_max_batch_size_bytes == max_bytes);  
  909.   /* --------------------------------------------------------------------
  910.    * If scanLockHold = TRUE we need to unlock previous round of 
  911.    * scanned records.
  912.    * scanReleaseLocks will set states for this and send a NEXT_SCANREQ.
  913.    * When confirm signal NEXT_SCANCONF arrives we call 
  914.    * continueScanNextReqLab to continue scanning new rows and 
  915.    * acquiring new locks.
  916.    * -------------------------------------------------------------------- */  
  917.   if ((scanptr.p->scanLockHold == ZTRUE) && 
  918.       (scanptr.p->m_curr_batch_size_rows > 0)) {
  919.     jam();
  920.     scanptr.p->scanReleaseCounter = 1;
  921.     scanReleaseLocksLab(signal);
  922.     return;
  923.   }//if
  924.   /* -----------------------------------------------------------------------
  925.    * We end up here when scanLockHold = FALSE or no rows was locked from 
  926.    * previous round. 
  927.    * Simply continue scanning.
  928.    * ----------------------------------------------------------------------- */
  929.   continueScanNextReqLab(signal);
  930. }//Dblqh::execSCAN_NEXTREQ()
  931. void Dblqh::continueScanNextReqLab(Signal* signal) 
  932. {
  933.   if (scanptr.p->scanCompletedStatus == ZTRUE) {
  934.     jam();
  935.     closeScanLab(signal);
  936.     return;
  937.   }//if
  938.   
  939.   if(scanptr.p->m_last_row){
  940.     jam();
  941.     scanptr.p->scanCompletedStatus = ZTRUE;
  942.     scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
  943.     sendScanFragConf(signal, ZFALSE);
  944.     return;
  945.   }
  946.   // Update timer on tcConnectRecord
  947.   tcConnectptr.p->tcTimer = cLqhTimeOutCount;
  948.   init_acc_ptr_list(scanptr.p);
  949.   scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
  950.   scanNextLoopLab(signal);
  951. }//Dblqh::continueScanNextReqLab()
  952. /* -------------------------------------------------------------------------
  953.  *       WE NEED TO RELEASE LOCKS BEFORE CONTINUING
  954.  * ------------------------------------------------------------------------- */
  955. void Dblqh::scanReleaseLocksLab(Signal* signal) 
  956. {
  957.   switch (fragptr.p->fragStatus) {
  958.   case Fragrecord::FSACTIVE:
  959.     jam();
  960.     linkActiveFrag(signal);
  961.     break;
  962.   case Fragrecord::BLOCKED:
  963.     jam();
  964.     linkFragQueue(signal);
  965.     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_RELEASE_STOPPED;
  966.     return;
  967.     break;
  968.   case Fragrecord::FREE:
  969.     jam();
  970.   case Fragrecord::ACTIVE_CREATION:
  971.     jam();
  972.   case Fragrecord::CRASH_RECOVERING:
  973.     jam();
  974.   case Fragrecord::DEFINED:
  975.     jam();
  976.   case Fragrecord::REMOVING:
  977.     jam();
  978.   default:
  979.     ndbrequire(false);
  980.   }//switch
  981.   continueScanReleaseAfterBlockedLab(signal);
  982. }//Dblqh::scanReleaseLocksLab()
  983. void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal) 
  984. {
  985.   scanptr.i = tcConnectptr.p->tcScanRec;
  986.   c_scanRecordPool.getPtr(scanptr);
  987.   scanptr.p->scanState = ScanRecord::WAIT_RELEASE_LOCK;
  988.   signal->theData[0] = scanptr.p->scanAccPtr;
  989.   signal->theData[1]=
  990.     get_acc_ptr_from_scan_record(scanptr.p,
  991.                                 scanptr.p->scanReleaseCounter -1,
  992.                                 false);
  993.   signal->theData[2] = NextScanReq::ZSCAN_COMMIT;
  994.   if (! scanptr.p->rangeScan)
  995.     sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
  996.   else
  997.     sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
  998. }//Dblqh::continueScanReleaseAfterBlockedLab()
  999. /* -------------------------------------------------------------------------
  1000.  *       ENTER SCAN_NEXTREQ
  1001.  * -------------------------------------------------------------------------
  1002.  *       SCAN_NEXT_REQ SIGNAL ARRIVED IN THE MIDDLE OF EXECUTION OF THE SCAN. 
  1003.  *       IT WAS A REQUEST TO CLOSE THE SCAN. WE WILL CLOSE THE SCAN IN A 
  1004.  *       CAREFUL MANNER TO ENSURE THAT NO ERROR OCCURS.
  1005.  * -------------------------------------------------------------------------
  1006.  *       PRECONDITION:
  1007.  *       TRANSACTION_STATE = SCAN_STATE_USED
  1008.  *       TSCAN_COMPLETED = ZTRUE
  1009.  * -------------------------------------------------------------------------
  1010.  *       WE CAN ALSO ARRIVE AT THIS LABEL AFTER A NODE CRASH OF THE SCAN
  1011.  *       COORDINATOR.
  1012.  * ------------------------------------------------------------------------- */
  1013. void Dblqh::closeScanRequestLab(Signal* signal) 
  1014. {
  1015.   DEBUG("transactionState = " << tcConnectptr.p->transactionState);
  1016.   switch (tcConnectptr.p->transactionState) {
  1017.   case TcConnectionrec::SCAN_STATE_USED:
  1018.     DEBUG("scanState = " << scanptr.p->scanState);
  1019.     switch (scanptr.p->scanState) {
  1020.     case ScanRecord::IN_QUEUE:
  1021.       jam();
  1022.       tupScanCloseConfLab(signal);
  1023.       break;
  1024.     case ScanRecord::WAIT_SCAN_KEYINFO:
  1025.     case ScanRecord::WAIT_NEXT_SCAN:
  1026.       jam();
  1027.       /* -------------------------------------------------------------------
  1028.        *  SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
  1029.        * ------------------------------------------------------------------- */
  1030.       scanptr.p->scanCompletedStatus = ZTRUE;
  1031.       break;
  1032.     case ScanRecord::WAIT_ACC_SCAN:
  1033.     case ScanRecord::WAIT_STORED_PROC_SCAN:
  1034.       jam();
  1035.       /* -------------------------------------------------------------------
  1036.        *  WE ARE CURRENTLY STARTING UP THE SCAN. SET COMPLETED STATUS 
  1037.        *  AND WAIT FOR COMPLETION OF STARTUP.
  1038.        * ------------------------------------------------------------------- */
  1039.       scanptr.p->scanCompletedStatus = ZTRUE;
  1040.       break;
  1041.     case ScanRecord::WAIT_CLOSE_SCAN:
  1042.     case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
  1043.       jam();
  1044.       /*empty*/;
  1045.       break;
  1046.       /* -------------------------------------------------------------------
  1047.        *       CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
  1048.        * ------------------------------------------------------------------- */
  1049.     case ScanRecord::WAIT_RELEASE_LOCK:
  1050.       jam();
  1051.       /* -------------------------------------------------------------------
  1052.        *  WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING THIS 
  1053.        *  WE WILL START TO CLOSE THE SCAN.
  1054.        * ------------------------------------------------------------------- */
  1055.       scanptr.p->scanCompletedStatus = ZTRUE;
  1056.       break;
  1057.     case ScanRecord::WAIT_SCAN_NEXTREQ:
  1058.       jam();
  1059.       /* -------------------------------------------------------------------
  1060.        * WE ARE WAITING FOR A SCAN_NEXTREQ FROM SCAN COORDINATOR(TC)
  1061.        * WICH HAVE CRASHED. CLOSE THE SCAN
  1062.        * ------------------------------------------------------------------- */
  1063.       scanptr.p->scanCompletedStatus = ZTRUE;
  1064.       fragptr.i = tcConnectptr.p->fragmentptr;
  1065.       ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  1066.       if (scanptr.p->scanLockHold == ZTRUE) {
  1067. if (scanptr.p->m_curr_batch_size_rows > 0) {
  1068.   jam();
  1069.   scanptr.p->scanReleaseCounter = 1;
  1070.   scanReleaseLocksLab(signal);
  1071.   return;
  1072. }//if
  1073.       }//if
  1074.       closeScanLab(signal);
  1075.       break;
  1076.     default:
  1077.       ndbrequire(false);
  1078.     }//switch
  1079.     break;
  1080.   case TcConnectionrec::WAIT_SCAN_AI:
  1081.     jam();
  1082.     /* ---------------------------------------------------------------------
  1083.      *  WE ARE STILL WAITING FOR THE ATTRIBUTE INFORMATION THAT 
  1084.      *  OBVIOUSLY WILL NOT ARRIVE. WE CAN QUIT IMMEDIATELY HERE.
  1085.      * --------------------------------------------------------------------- */
  1086.     releaseOprec(signal);
  1087.     if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
  1088.       jam();
  1089.       tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
  1090.       ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
  1091.       tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
  1092.       signal->theData[0] = ZLQH_TRANS_NEXT;
  1093.       signal->theData[1] = tcNodeFailptr.i;
  1094.       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  1095.       return;
  1096.     }//if
  1097.     tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
  1098.     scanptr.p->m_curr_batch_size_rows = 0;
  1099.     scanptr.p->m_curr_batch_size_bytes= 0;
  1100.     sendScanFragConf(signal, ZTRUE);
  1101.     abort_scan(signal, scanptr.i, 0);
  1102.     return;
  1103.     break;
  1104.   case TcConnectionrec::SCAN_TUPKEY:
  1105.   case TcConnectionrec::SCAN_FIRST_STOPPED:
  1106.   case TcConnectionrec::SCAN_CHECK_STOPPED:
  1107.   case TcConnectionrec::SCAN_STOPPED:
  1108.     jam();
  1109.     /* ---------------------------------------------------------------------
  1110.      *       SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
  1111.      * --------------------------------------------------------------------- */
  1112.     scanptr.p->scanCompletedStatus = ZTRUE;
  1113.     break;
  1114.   case TcConnectionrec::SCAN_RELEASE_STOPPED:
  1115.     jam();
  1116.     /* ---------------------------------------------------------------------
  1117.      *  WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING 
  1118.      *  THIS WE WILL START TO CLOSE THE SCAN.
  1119.      * --------------------------------------------------------------------- */
  1120.     scanptr.p->scanCompletedStatus = ZTRUE;
  1121.     break;
  1122.   case TcConnectionrec::SCAN_CLOSE_STOPPED:
  1123.     jam();
  1124.     /* ---------------------------------------------------------------------
  1125.      *  CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
  1126.      * --------------------------------------------------------------------- */
  1127.     /*empty*/;
  1128.     break;
  1129.   default:
  1130.     ndbrequire(false);
  1131.   }//switch
  1132. }//Dblqh::closeScanRequestLab()
  1133. /* -------------------------------------------------------------------------
  1134.  *       ENTER NEXT_SCANCONF
  1135.  * -------------------------------------------------------------------------
  1136.  *       PRECONDITION: SCAN_STATE = WAIT_RELEASE_LOCK
  1137.  * ------------------------------------------------------------------------- */
  1138. void Dblqh::scanLockReleasedLab(Signal* signal)
  1139. {
  1140.   tcConnectptr.i = scanptr.p->scanTcrec;
  1141.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);  
  1142.   releaseActiveFrag(signal);
  1143.   if (scanptr.p->scanReleaseCounter == scanptr.p->m_curr_batch_size_rows) {
  1144.     if ((scanptr.p->scanErrorCounter > 0) ||
  1145.         (scanptr.p->scanCompletedStatus == ZTRUE)) {
  1146.       jam();
  1147.       scanptr.p->m_curr_batch_size_rows = 0;
  1148.       scanptr.p->m_curr_batch_size_bytes = 0;
  1149.       closeScanLab(signal);
  1150.     } else if (scanptr.p->check_scan_batch_completed() &&
  1151.                scanptr.p->scanLockHold != ZTRUE) {
  1152.       jam();
  1153.       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
  1154.       sendScanFragConf(signal, ZFALSE);
  1155.     } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) {
  1156.       jam();
  1157.       closeScanLab(signal);
  1158.       return;
  1159.     } else {
  1160.       jam();
  1161.       /*
  1162.        * We came here after releasing locks after 
  1163.        * receiving SCAN_NEXTREQ from TC. We only come here 
  1164.        * when scanHoldLock == ZTRUE
  1165.        */
  1166.       scanptr.p->m_curr_batch_size_rows = 0;
  1167.       scanptr.p->m_curr_batch_size_bytes = 0;
  1168.       continueScanNextReqLab(signal);
  1169.     }//if
  1170.   } else if (scanptr.p->scanReleaseCounter < scanptr.p->m_curr_batch_size_rows) {
  1171.     jam();
  1172.     scanptr.p->scanReleaseCounter++;     
  1173.     scanReleaseLocksLab(signal);
  1174.   } else {
  1175.     jam();
  1176.     /*
  1177.     We come here when we have been scanning for a long time and not been able
  1178.     to find m_max_batch_size_rows records to return. We needed to release
  1179.     the record we didn't want, but now we are returning all found records to
  1180.     the API.
  1181.     */
  1182.     scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
  1183.     sendScanFragConf(signal, ZFALSE);
  1184.   }//if
  1185. }//Dblqh::scanLockReleasedLab()
  1186. bool
  1187. Dblqh::seize_acc_ptr_list(ScanRecord* scanP, Uint32 batch_size)
  1188. {
  1189.   Uint32 i;
  1190.   Uint32 attr_buf_recs= (batch_size + 30) / 32;
  1191.   if (batch_size > 1) {
  1192.     if (c_no_attrinbuf_recs < attr_buf_recs) {
  1193.       jam();
  1194.       return false;
  1195.     }
  1196.     for (i= 1; i <= attr_buf_recs; i++) {
  1197.       scanP->scan_acc_op_ptr[i]= seize_attrinbuf();
  1198.     }
  1199.   }
  1200.   scanP->scan_acc_attr_recs= attr_buf_recs;
  1201.   scanP->scan_acc_index = 0;
  1202.   return true;
  1203. }
  1204. void
  1205. Dblqh::release_acc_ptr_list(ScanRecord* scanP)
  1206. {
  1207.   Uint32 i, attr_buf_recs;
  1208.   attr_buf_recs= scanP->scan_acc_attr_recs;
  1209.   for (i= 1; i <= attr_buf_recs; i++) {
  1210.     release_attrinbuf(scanP->scan_acc_op_ptr[i]);
  1211.   }
  1212.   scanP->scan_acc_attr_recs= 0;
  1213.   scanP->scan_acc_index = 0;
  1214. }
  1215. Uint32
  1216. Dblqh::seize_attrinbuf()
  1217. {
  1218.   AttrbufPtr regAttrPtr;
  1219.   Uint32 ret_attr_buf;
  1220.   ndbrequire(c_no_attrinbuf_recs > 0);
  1221.   c_no_attrinbuf_recs--;
  1222.   ret_attr_buf= cfirstfreeAttrinbuf;
  1223.   regAttrPtr.i= ret_attr_buf;
  1224.   ptrCheckGuard(regAttrPtr, cattrinbufFileSize, attrbuf);
  1225.   cfirstfreeAttrinbuf= regAttrPtr.p->attrbuf[ZINBUF_NEXT];
  1226.   return ret_attr_buf;
  1227. }
  1228. Uint32
  1229. Dblqh::release_attrinbuf(Uint32 attr_buf_i)
  1230. {
  1231.   Uint32 next_buf;
  1232.   AttrbufPtr regAttrPtr;
  1233.   c_no_attrinbuf_recs++;
  1234.   regAttrPtr.i= attr_buf_i;
  1235.   ptrCheckGuard(regAttrPtr, cattrinbufFileSize, attrbuf);
  1236.   next_buf= regAttrPtr.p->attrbuf[ZINBUF_NEXT];
  1237.   regAttrPtr.p->attrbuf[ZINBUF_NEXT]= cfirstfreeAttrinbuf;
  1238.   cfirstfreeAttrinbuf= regAttrPtr.i;
  1239.   return next_buf;
  1240. }
  1241. void
  1242. Dblqh::init_acc_ptr_list(ScanRecord* scanP) 
  1243. {
  1244.   scanP->scan_acc_index = 0;
  1245. }
  1246. Uint32
  1247. Dblqh::get_acc_ptr_from_scan_record(ScanRecord* scanP,
  1248.                                     Uint32 index,
  1249.                                     bool crash_flag)
  1250. {
  1251.   Uint32* acc_ptr;
  1252.   Uint32 attr_buf_rec, attr_buf_index;
  1253.   if (!((index < MAX_PARALLEL_OP_PER_SCAN) &&
  1254.        index < scanP->scan_acc_index)) {
  1255.     ndbrequire(crash_flag);
  1256.     return RNIL;
  1257.   }
  1258.   i_get_acc_ptr(scanP, acc_ptr, index);
  1259.   return *acc_ptr;
  1260. }
  1261. void
  1262. Dblqh::set_acc_ptr_in_scan_record(ScanRecord* scanP,
  1263.                                   Uint32 index, Uint32 acc)
  1264. {
  1265.   Uint32 *acc_ptr;
  1266.   ndbrequire((index == 0 || scanP->scan_acc_index == index) &&
  1267.              (index < MAX_PARALLEL_OP_PER_SCAN));
  1268.   scanP->scan_acc_index= index + 1;
  1269.   i_get_acc_ptr(scanP, acc_ptr, index);
  1270.   *acc_ptr= acc;
  1271. }
  1272. /* -------------------------------------------------------------------------
  1273.  * SCAN_FRAGREQ: Request to start scanning the specified fragment of a table.
  1274.  * ------------------------------------------------------------------------- */
  1275. void Dblqh::execSCAN_FRAGREQ(Signal* signal) 
  1276. {
  1277.   ScanFragReq * const scanFragReq = (ScanFragReq *)&signal->theData[0];
  1278.   ScanFragRef * ref;
  1279.   const Uint32 transid1 = scanFragReq->transId1;
  1280.   const Uint32 transid2 = scanFragReq->transId2;
  1281.   Uint32 errorCode= 0;
  1282.   Uint32 senderData;
  1283.   Uint32 hashIndex;
  1284.   TcConnectionrecPtr nextHashptr;
  1285.   jamEntry();
  1286.   const Uint32 reqinfo = scanFragReq->requestInfo;
  1287.   const Uint32 fragId = (scanFragReq->fragmentNoKeyLen & 0xFFFF);
  1288.   const Uint32 keyLen = (scanFragReq->fragmentNoKeyLen >> 16);
  1289.   tabptr.i = scanFragReq->tableId;
  1290.   const Uint32 max_rows = scanFragReq->batch_size_rows;
  1291.   const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
  1292.   const Uint8 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
  1293.   const Uint8 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
  1294.   
  1295.   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
  1296.   if(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED){
  1297.     senderData = scanFragReq->senderData;
  1298.     goto error_handler_early_1;
  1299.   }
  1300.   
  1301.   if (cfirstfreeTcConrec != RNIL) {
  1302.     seizeTcrec();
  1303.     tcConnectptr.p->clientConnectrec = scanFragReq->senderData;
  1304.     tcConnectptr.p->clientBlockref = signal->senderBlockRef();
  1305.     tcConnectptr.p->savePointId = scanFragReq->savePointId;
  1306.   } else {
  1307.     jam();
  1308.     /* --------------------------------------------------------------------
  1309.      *      NO FREE TC RECORD AVAILABLE, THUS WE CANNOT HANDLE THE REQUEST.
  1310.      * -------------------------------------------------------------------- */
  1311.     errorCode = ZNO_TC_CONNECT_ERROR;
  1312.     senderData = scanFragReq->senderData;
  1313.     goto error_handler_early;
  1314.   }//if
  1315.   /**
  1316.    * A write allways have to get keyinfo
  1317.    */
  1318.   ndbrequire(scanLockMode == 0 || keyinfo);
  1319.   ndbrequire(max_rows > 0 && max_rows <= MAX_PARALLEL_OP_PER_SCAN);
  1320.   if (!getFragmentrec(signal, fragId)) {
  1321.     errorCode = 1231;
  1322.     goto error_handler;
  1323.   }//if
  1324.   // Verify scan type vs table type (both sides are boolean)
  1325.   if (rangeScan != DictTabInfo::isOrderedIndex(fragptr.p->tableType)) {
  1326.     errorCode = 1232;
  1327.     goto error_handler;
  1328.   }//if
  1329.   
  1330.   // 1 scan record is reserved for node recovery
  1331.   if (cscanNoFreeRec < 2) {
  1332.     jam();
  1333.     errorCode = ScanFragRef::ZNO_FREE_SCANREC_ERROR;
  1334.     goto error_handler;
  1335.   }
  1336.   // XXX adjust cmaxAccOps for range scans and remove this comment
  1337.   if ((cbookedAccOps + max_rows) > cmaxAccOps) {
  1338.     jam();
  1339.     errorCode = ScanFragRef::ZSCAN_BOOK_ACC_OP_ERROR;
  1340.     goto error_handler;
  1341.   }//if
  1342.   ndbrequire(c_scanRecordPool.seize(scanptr));
  1343.   initScanTc(signal,
  1344.              transid1,
  1345.              transid2,
  1346.              fragId,
  1347.              ZNIL);
  1348.   tcConnectptr.p->save1 = 4;
  1349.   tcConnectptr.p->primKeyLen = keyLen + 4; // hard coded in execKEYINFO
  1350.   errorCode = initScanrec(scanFragReq);
  1351.   if (errorCode != ZOK) {
  1352.     jam();
  1353.     goto error_handler2;
  1354.   }//if
  1355.   cscanNoFreeRec--;
  1356.   cbookedAccOps += max_rows;
  1357.   hashIndex = (tcConnectptr.p->transid[0] ^ tcConnectptr.p->tcOprec) & 1023;
  1358.   nextHashptr.i = ctransidHash[hashIndex];
  1359.   ctransidHash[hashIndex] = tcConnectptr.i;
  1360.   tcConnectptr.p->prevHashRec = RNIL;
  1361.   tcConnectptr.p->nextHashRec = nextHashptr.i;
  1362.   if (nextHashptr.i != RNIL) {
  1363.     jam();
  1364.     /* ---------------------------------------------------------------------
  1365.      *   ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD 
  1366.      *   IF IT EXISTS
  1367.      * --------------------------------------------------------------------- */
  1368.     ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
  1369.     nextHashptr.p->prevHashRec = tcConnectptr.i;
  1370.   }//if
  1371.   if (scanptr.p->scanAiLength > 0) {
  1372.     jam();
  1373.     tcConnectptr.p->transactionState = TcConnectionrec::WAIT_SCAN_AI;
  1374.     return;
  1375.   }//if
  1376.   continueAfterReceivingAllAiLab(signal);
  1377.   return;
  1378. error_handler2:
  1379.   // no scan number allocated
  1380.   c_scanRecordPool.release(scanptr);
  1381. error_handler:
  1382.   ref = (ScanFragRef*)&signal->theData[0];
  1383.   tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
  1384.   ref->senderData = tcConnectptr.p->clientConnectrec;
  1385.   ref->transId1 = transid1;
  1386.   ref->transId2 = transid2;
  1387.   ref->errorCode = errorCode;
  1388.   sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal, 
  1389.      ScanFragRef::SignalLength, JBB);
  1390.   releaseOprec(signal);
  1391.   releaseTcrec(signal, tcConnectptr);
  1392.   return;
  1393.  error_handler_early_1:
  1394.   if(tabptr.p->tableStatus == Tablerec::NOT_DEFINED){
  1395.     jam();
  1396.     errorCode = ZTABLE_NOT_DEFINED;
  1397.   } else if (tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_ONGOING ||
  1398.      tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE){
  1399.     jam();
  1400.     errorCode = ZDROP_TABLE_IN_PROGRESS;
  1401.   } else {
  1402.     ndbrequire(0);
  1403.   }
  1404.  error_handler_early:
  1405.   ref = (ScanFragRef*)&signal->theData[0];
  1406.   ref->senderData = senderData;
  1407.   ref->transId1 = transid1;
  1408.   ref->transId2 = transid2;
  1409.   ref->errorCode = errorCode;
  1410.   sendSignal(signal->senderBlockRef(), GSN_SCAN_FRAGREF, signal,
  1411.      ScanFragRef::SignalLength, JBB);
  1412. }//Dblqh::execSCAN_FRAGREQ()
  1413. void Dblqh::continueAfterReceivingAllAiLab(Signal* signal) 
  1414. {
  1415.   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
  1416.   if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
  1417.     jam();
  1418.     return;
  1419.   }
  1420.   
  1421.   scanptr.p->scanState = ScanRecord::WAIT_ACC_SCAN;
  1422.   AccScanReq * req = (AccScanReq*)&signal->theData[0];
  1423.   req->senderData = scanptr.i;
  1424.   req->senderRef = cownref;
  1425.   req->tableId = tcConnectptr.p->tableref;
  1426.   req->fragmentNo = tcConnectptr.p->fragmentid;
  1427.   req->requestInfo = 0;
  1428.   AccScanReq::setLockMode(req->requestInfo, scanptr.p->scanLockMode);
  1429.   AccScanReq::setKeyinfoFlag(req->requestInfo, scanptr.p->scanKeyinfoFlag);
  1430.   AccScanReq::setReadCommittedFlag(req->requestInfo, scanptr.p->readCommitted);
  1431.   req->transId1 = tcConnectptr.p->transid[0];
  1432.   req->transId2 = tcConnectptr.p->transid[1];
  1433.   req->savePointId = tcConnectptr.p->savePointId;
  1434.   // always use if-stmt to switch (instead of setting a "scan block ref")
  1435.   if (! scanptr.p->rangeScan)
  1436.     sendSignal(tcConnectptr.p->tcAccBlockref, GSN_ACC_SCANREQ, signal, 
  1437.                AccScanReq::SignalLength, JBB);
  1438.   else
  1439.     sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_ACC_SCANREQ, signal, 
  1440.                AccScanReq::SignalLength, JBB);
  1441. }//Dblqh::continueAfterReceivingAllAiLab()
  1442. void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length) 
  1443. {
  1444.   scanptr.i = tcConnectptr.p->tcScanRec;
  1445.   c_scanRecordPool.getPtr(scanptr);
  1446.   if (saveTupattrbuf(signal, dataPtr, length) == ZOK) {
  1447.     if (tcConnectptr.p->currTupAiLen < scanptr.p->scanAiLength) {
  1448.       jam();
  1449.     } else {
  1450.       jam();
  1451.       ndbrequire(tcConnectptr.p->currTupAiLen == scanptr.p->scanAiLength);
  1452.       continueAfterReceivingAllAiLab(signal);
  1453.     }//if
  1454.     return;
  1455.   }//if
  1456.   abort_scan(signal, scanptr.i, ZGET_ATTRINBUF_ERROR);
  1457. }
  1458. void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
  1459.   jam();
  1460.   scanptr.i = scan_ptr_i;
  1461.   c_scanRecordPool.getPtr(scanptr);
  1462.   fragptr.i = tcConnectptr.p->fragmentptr;
  1463.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  1464.   finishScanrec(signal);
  1465.   releaseScanrec(signal);
  1466.   tcConnectptr.p->transactionState = TcConnectionrec::IDLE;
  1467.   tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
  1468.   if(errcode)
  1469.   {
  1470.     jam();
  1471.     ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
  1472.     ref->senderData = tcConnectptr.p->clientConnectrec;
  1473.     ref->transId1 = tcConnectptr.p->transid[0];
  1474.     ref->transId2 = tcConnectptr.p->transid[1];
  1475.     ref->errorCode = errcode;
  1476.     sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal, 
  1477.        ScanFragRef::SignalLength, JBB);
  1478.   }
  1479.   deleteTransidHash(signal);
  1480.   releaseOprec(signal);
  1481.   releaseTcrec(signal, tcConnectptr);
  1482. }
  1483. /*---------------------------------------------------------------------*/
  1484. /* Send this 'I am alive' signal to TC when it is received from ACC    */
  1485. /* We include the scanPtr.i that comes from ACC in signalData[1], this */
  1486. /* tells TC which fragment record to check for a timeout.              */
  1487. /*---------------------------------------------------------------------*/
  1488. void Dblqh::execSCAN_HBREP(Signal* signal)
  1489. {
  1490.   jamEntry();
  1491.   scanptr.i = signal->theData[0];
  1492.   c_scanRecordPool.getPtr(scanptr);
  1493.   switch(scanptr.p->scanType){
  1494.   case ScanRecord::SCAN:
  1495.     if (scanptr.p->scanTcWaiting == ZTRUE) {
  1496.       jam();
  1497.       tcConnectptr.i = scanptr.p->scanTcrec;  
  1498.       ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  1499.       ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  1500.       const Uint32 transid1  = signal->theData[1];
  1501.       const Uint32 transid2  = signal->theData[2];
  1502.       ndbrequire(transid1 == tcConnectptr.p->transid[0] && 
  1503.  transid2 == tcConnectptr.p->transid[1]);
  1504.       // Update counter on tcConnectPtr
  1505.       if (tcConnectptr.p->tcTimer != 0){
  1506. tcConnectptr.p->tcTimer = cLqhTimeOutCount;
  1507.       } else {
  1508.         jam();
  1509. //ndbout << "SCAN_HBREP when tcTimer was off" << endl;
  1510.       }
  1511.       
  1512.       signal->theData[0] = tcConnectptr.p->clientConnectrec;
  1513.       signal->theData[1] = tcConnectptr.p->transid[0];
  1514.       signal->theData[2] = tcConnectptr.p->transid[1];
  1515.       sendSignal(tcConnectptr.p->clientBlockref,
  1516.                  GSN_SCAN_HBREP, signal, 3, JBB);
  1517.     }//if
  1518.     break;
  1519.   case ScanRecord::COPY:
  1520.     //    ndbout << "Dblqh::execSCAN_HBREP Dropping SCAN_HBREP" << endl;
  1521.     break;
  1522.   default:
  1523.     ndbrequire(false);
  1524.   }
  1525. }
  1526. void Dblqh::sendScanFragRefLateLab(Signal* signal) 
  1527. {
  1528. }//Dblqh::sendScanFragRefLateLab()
  1529. void Dblqh::accScanConfScanLab(Signal* signal) 
  1530. {
  1531.   AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
  1532.   tcConnectptr.i = scanptr.p->scanTcrec;
  1533.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  1534.   /* -----------------------------------------------------------------------
  1535.    *       PRECONDITION: SCAN_STATE = WAIT_ACC_SCAN
  1536.    * ----------------------------------------------------------------------- */
  1537.   if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
  1538.     jam();
  1539.     /* ---------------------------------------------------------------------
  1540.      *       THE FRAGMENT WAS EMPTY.
  1541.      *       REPORT SUCCESSFUL COPYING.
  1542.      * --------------------------------------------------------------------- */
  1543.     tupScanCloseConfLab(signal);
  1544.     return;
  1545.   }//if
  1546.   scanptr.p->scanAccPtr = accScanConf->accPtr;
  1547.   Uint32 boundAiLength = tcConnectptr.p->primKeyLen - 4;
  1548.   if (scanptr.p->rangeScan) {
  1549.     jam();
  1550.     TuxBoundInfo* const req = (TuxBoundInfo*)signal->getDataPtrSend();
  1551.     req->errorCode = RNIL;
  1552.     req->tuxScanPtrI = scanptr.p->scanAccPtr;
  1553.     req->boundAiLength = boundAiLength;
  1554.     if(boundAiLength > 0)
  1555.       sendKeyinfoAcc(signal, TuxBoundInfo::SignalLength);
  1556.     EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO,
  1557.    signal, TuxBoundInfo::SignalLength + boundAiLength);
  1558.     jamEntry();
  1559.     if (req->errorCode != 0) {
  1560.       jam();
  1561.       /*
  1562.        * Cannot use STORED_PROCREF to abort since even the REF
  1563.        * returns a stored proc id.  So record error and continue.
  1564.        * The scan is already Invalid in TUX and returns empty set.
  1565.        */
  1566.       tcConnectptr.p->errorCode = req->errorCode;
  1567.     }
  1568.   }
  1569.   scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
  1570.   signal->theData[0] = tcConnectptr.p->tupConnectrec;
  1571.   signal->theData[1] = tcConnectptr.p->tableref;
  1572.   signal->theData[2] = scanptr.p->scanSchemaVersion;
  1573.   signal->theData[3] = ZSTORED_PROC_SCAN;
  1574.   signal->theData[4] = scanptr.p->scanAiLength;
  1575.   sendSignal(tcConnectptr.p->tcTupBlockref,
  1576.              GSN_STORED_PROCREQ, signal, 5, JBB);
  1577.   signal->theData[0] = tcConnectptr.p->tupConnectrec;
  1578.   AttrbufPtr regAttrinbufptr;
  1579.   regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
  1580.   while (regAttrinbufptr.i != RNIL) {
  1581.     ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
  1582.     jam();
  1583.     Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
  1584.     ndbrequire(dataLen != 0);
  1585.     // first 3 words already set in STORED_PROCREQ
  1586.     MEMCOPY_NO_WORDS(&signal->theData[3],
  1587.                      &regAttrinbufptr.p->attrbuf[0],
  1588.                      dataLen);
  1589.     sendSignal(tcConnectptr.p->tcTupBlockref,
  1590.                GSN_ATTRINFO, signal, dataLen + 3, JBB);
  1591.     regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
  1592.   }//while
  1593.   releaseOprec(signal);
  1594. }//Dblqh::accScanConfScanLab()
  1595. /* -------------------------------------------------------------------------
  1596.  *       ENTER STORED_PROCCONF WITH
  1597.  *         TC_CONNECTPTR,
  1598.  *         TSTORED_PROC_ID
  1599.  * -------------------------------------------------------------------------
  1600.  *       PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_SCAN
  1601.  * ------------------------------------------------------------------------- */
  1602. void Dblqh::storedProcConfScanLab(Signal* signal) 
  1603. {
  1604.   fragptr.i = tcConnectptr.p->fragmentptr;
  1605.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  1606.   if (scanptr.p->scanCompletedStatus == ZTRUE) {
  1607.     jam();
  1608.     // STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
  1609.     closeScanLab(signal);
  1610.     return;
  1611.   }//if
  1612.   switch (fragptr.p->fragStatus) {
  1613.   case Fragrecord::FSACTIVE:
  1614.     jam();
  1615.     linkActiveFrag(signal);
  1616.     break;
  1617.   case Fragrecord::BLOCKED:
  1618.     jam();
  1619.     linkFragQueue(signal);
  1620.     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_FIRST_STOPPED;
  1621.     return;
  1622.     break;
  1623.   case Fragrecord::FREE:  
  1624.     jam();
  1625.   case Fragrecord::ACTIVE_CREATION:
  1626.     jam();
  1627.   case Fragrecord::CRASH_RECOVERING:
  1628.     jam();
  1629.   case Fragrecord::DEFINED:
  1630.     jam();
  1631.   case Fragrecord::REMOVING:
  1632.     jam();
  1633.   default:
  1634.     ndbrequire(false);
  1635.     break;
  1636.   }//switch
  1637.   continueFirstScanAfterBlockedLab(signal);
  1638. }//Dblqh::storedProcConfScanLab()
  1639. void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal) 
  1640. {
  1641.   scanptr.i = tcConnectptr.p->tcScanRec;
  1642.   c_scanRecordPool.getPtr(scanptr);
  1643.   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
  1644.   init_acc_ptr_list(scanptr.p);
  1645.   signal->theData[0] = scanptr.p->scanAccPtr;
  1646.   signal->theData[1] = RNIL;
  1647.   signal->theData[2] = NextScanReq::ZSCAN_NEXT;
  1648.   if (! scanptr.p->rangeScan)
  1649.     sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
  1650.   else
  1651.     sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
  1652.   return;
  1653. }//Dblqh::continueFirstScanAfterBlockedLab()
  1654. /* ------------------------------------------------------------------------- 
  1655.  * When executing a scan we must come up to the surface at times to make 
  1656.  * sure we can quickly start local checkpoints.
  1657.  * ------------------------------------------------------------------------- */
  1658. void Dblqh::execCHECK_LCP_STOP(Signal* signal)
  1659. {
  1660.   jamEntry();
  1661.   scanptr.i = signal->theData[0];
  1662.   c_scanRecordPool.getPtr(scanptr);
  1663.   tcConnectptr.i = scanptr.p->scanTcrec;
  1664.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  1665.   fragptr.i = tcConnectptr.p->fragmentptr;
  1666.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  1667.   if (signal->theData[1] == ZTRUE) {
  1668.     jam();
  1669.     releaseActiveFrag(signal);
  1670.     signal->theData[0] = ZCHECK_LCP_STOP_BLOCKED;
  1671.     signal->theData[1] = scanptr.i;
  1672.     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
  1673.     signal->theData[0] = RNIL;
  1674.     return;
  1675.   }//if
  1676.   if (fragptr.p->fragStatus != Fragrecord::FSACTIVE) {
  1677.     ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED); 
  1678.     releaseActiveFrag(signal);
  1679.     linkFragQueue(signal);
  1680.     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
  1681.     signal->theData[0] = RNIL;
  1682.   }//if
  1683. }//Dblqh::execCHECK_LCP_STOP()
  1684. void Dblqh::checkLcpStopBlockedLab(Signal* signal)
  1685. {
  1686.   switch (fragptr.p->fragStatus) {
  1687.   case Fragrecord::FSACTIVE:
  1688.     jam();
  1689.     linkActiveFrag(signal);
  1690.     continueAfterCheckLcpStopBlocked(signal);
  1691.     break;
  1692.   case Fragrecord::BLOCKED:
  1693.     jam();
  1694.     linkFragQueue(signal);
  1695.     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
  1696.     return;
  1697.     break;
  1698.   case Fragrecord::FREE:
  1699.     jam();
  1700.   case Fragrecord::ACTIVE_CREATION:
  1701.     jam();
  1702.   case Fragrecord::CRASH_RECOVERING:
  1703.     jam();
  1704.   case Fragrecord::DEFINED:
  1705.     jam();
  1706.   case Fragrecord::REMOVING:
  1707.     jam();
  1708.   default:
  1709.     ndbrequire(false);
  1710.   }//switch
  1711. }//Dblqh::checkLcpStopBlockedLab()
  1712. void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
  1713. {
  1714.   scanptr.i = tcConnectptr.p->tcScanRec;
  1715.   c_scanRecordPool.getPtr(scanptr);
  1716.   signal->theData[0] = scanptr.p->scanAccPtr;
  1717.   signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
  1718.   if (! scanptr.p->rangeScan)
  1719.     EXECUTE_DIRECT(DBACC, GSN_ACC_CHECK_SCAN, signal, 2);
  1720.   else
  1721.     EXECUTE_DIRECT(DBTUX, GSN_ACC_CHECK_SCAN, signal, 2);
  1722. }//Dblqh::continueAfterCheckLcpStopBlocked()
  1723. /* -------------------------------------------------------------------------
  1724.  *       ENTER NEXT_SCANCONF
  1725.  * -------------------------------------------------------------------------
  1726.  *       PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN
  1727.  * ------------------------------------------------------------------------- */
  1728. void Dblqh::nextScanConfScanLab(Signal* signal) 
  1729. {
  1730.   NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
  1731.   tcConnectptr.i = scanptr.p->scanTcrec;
  1732.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  1733.   if (nextScanConf->fragId == RNIL) {
  1734.     jam();
  1735.     /* ---------------------------------------------------------------------
  1736.      *       THERE ARE NO MORE TUPLES TO FETCH. IF WE HAVE ANY
  1737.      *       OPERATIONS STILL NEEDING A LOCK WE REPORT TO THE
  1738.      *       APPLICATION AND CLOSE THE SCAN WHEN THE NEXT SCAN
  1739.      *       REQUEST IS RECEIVED. IF WE DO NOT HAVE ANY NEED FOR
  1740.      *       LOCKS WE CAN CLOSE THE SCAN IMMEDIATELY.
  1741.      * --------------------------------------------------------------------- */
  1742.     releaseActiveFrag(signal);
  1743.     /*************************************************************
  1744.      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
  1745.      ************************************************************ */    
  1746.     if (!scanptr.p->scanLockHold)
  1747.     {
  1748.       jam();
  1749.       closeScanLab(signal);
  1750.       return;
  1751.     }
  1752.     if (scanptr.p->scanCompletedStatus == ZTRUE) {
  1753.       if ((scanptr.p->scanLockHold == ZTRUE) && 
  1754.   (scanptr.p->m_curr_batch_size_rows > 0)) {
  1755. jam();
  1756. scanptr.p->scanReleaseCounter = 1;
  1757. scanReleaseLocksLab(signal);
  1758. return;
  1759.       }//if
  1760.       jam();
  1761.       closeScanLab(signal);
  1762.       return;
  1763.     }//if
  1764.     if (scanptr.p->m_curr_batch_size_rows > 0) {
  1765.       jam();
  1766.       scanptr.p->scanCompletedStatus = ZTRUE;
  1767.       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
  1768.       sendScanFragConf(signal, ZFALSE);
  1769.       return;
  1770.     }//if
  1771.     closeScanLab(signal);
  1772.     return;
  1773.   }//if
  1774.   // If accOperationPtr == RNIL no record was returned by ACC
  1775.   if (nextScanConf->accOperationPtr == RNIL) {
  1776.     jam();
  1777.     /*************************************************************
  1778.      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
  1779.      ************************************************************ */    
  1780.     if (scanptr.p->scanCompletedStatus == ZTRUE) {
  1781.       releaseActiveFrag(signal);
  1782.       if ((scanptr.p->scanLockHold == ZTRUE) && 
  1783.   (scanptr.p->m_curr_batch_size_rows > 0)) {
  1784. jam();
  1785. scanptr.p->scanReleaseCounter = 1;
  1786. scanReleaseLocksLab(signal);
  1787. return;
  1788.       }//if
  1789.       jam();
  1790.       closeScanLab(signal);
  1791.       return;
  1792.     }//if
  1793.     if (scanptr.p->m_curr_batch_size_rows > 0) {
  1794.       jam();
  1795.       releaseActiveFrag(signal);
  1796.       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
  1797.       sendScanFragConf(signal, ZFALSE);
  1798.       return;
  1799.     }//if
  1800.     signal->theData[0] = scanptr.p->scanAccPtr;
  1801.     signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
  1802.     if (! scanptr.p->rangeScan)
  1803.       sendSignal(tcConnectptr.p->tcAccBlockref,
  1804.                  GSN_ACC_CHECK_SCAN, signal, 2, JBB);
  1805.     else
  1806.       sendSignal(tcConnectptr.p->tcTuxBlockref,
  1807.                  GSN_ACC_CHECK_SCAN, signal, 2, JBB);
  1808.     return;
  1809.   }//if
  1810.   jam();
  1811.   set_acc_ptr_in_scan_record(scanptr.p,
  1812.                              scanptr.p->m_curr_batch_size_rows,
  1813.                              nextScanConf->accOperationPtr);
  1814.   jam();
  1815.   scanptr.p->scanLocalref[0] = nextScanConf->localKey[0];
  1816.   scanptr.p->scanLocalref[1] = nextScanConf->localKey[1];
  1817.   scanptr.p->scanLocalFragid = nextScanConf->fragId;
  1818.   if (scanptr.p->scanKeyinfoFlag) {
  1819.     jam();
  1820.     tcConnectptr.p->primKeyLen = nextScanConf->keyLength;
  1821.     seizeTupkeybuf(signal);
  1822.     databufptr.p->data[0] = nextScanConf->key[0];
  1823.     databufptr.p->data[1] = nextScanConf->key[1];
  1824.     databufptr.p->data[2] = nextScanConf->key[2];
  1825.     databufptr.p->data[3] = nextScanConf->key[3];
  1826.     if (nextScanConf->keyLength > 4) {
  1827.       jam();
  1828.       tcConnectptr.p->save1 = 4;
  1829.       scanptr.p->scanState = ScanRecord::WAIT_SCAN_KEYINFO;
  1830.       return;
  1831.     }//if
  1832.   }//if
  1833.   jam();
  1834.   nextScanConfLoopLab(signal);
  1835. }//Dblqh::nextScanConfScanLab()
  1836. void Dblqh::nextScanConfLoopLab(Signal* signal) 
  1837. {
  1838.   /* ----------------------------------------------------------------------
  1839.    *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
  1840.    * ---------------------------------------------------------------------- */
  1841.   if (scanptr.p->scanCompletedStatus == ZTRUE) {
  1842.     jam();
  1843.     releaseActiveFrag(signal);
  1844.     releaseOprec(signal);
  1845.     if ((scanptr.p->scanLockHold == ZTRUE) && 
  1846.         (scanptr.p->m_curr_batch_size_rows > 0)) {
  1847.       jam();
  1848.       scanptr.p->scanReleaseCounter = 1;
  1849.       scanReleaseLocksLab(signal);
  1850.       return;
  1851.     }//if
  1852.     closeScanLab(signal);
  1853.     return;
  1854.   }//if
  1855.   jam();
  1856.   Uint32 tableRef;
  1857.   Uint32 tupFragPtr;
  1858.   Uint32 reqinfo = (scanptr.p->scanLockHold == ZFALSE);
  1859.   reqinfo = reqinfo + (tcConnectptr.p->operation << 6);
  1860.   reqinfo = reqinfo + (tcConnectptr.p->opExec << 10);
  1861.   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_TUPKEY;
  1862.   fragptr.i = tcConnectptr.p->fragmentptr;
  1863.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  1864.   if (! scanptr.p->rangeScan) {
  1865.     tableRef = tcConnectptr.p->tableref;
  1866.     if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
  1867.       jam();
  1868.       tupFragPtr = fragptr.p->tupFragptr[0];
  1869.     } else {
  1870.       jam();
  1871.       tupFragPtr = fragptr.p->tupFragptr[1];
  1872.     }//if
  1873.   } else {
  1874.     jam();
  1875.     // for ordered index use primary table
  1876.     FragrecordPtr tFragPtr;
  1877.     tFragPtr.i = fragptr.p->tableFragptr;
  1878.     ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
  1879.     tableRef = tFragPtr.p->tabRef;
  1880.     if (tFragPtr.p->fragId == scanptr.p->scanLocalFragid) {
  1881.       jam();
  1882.       tupFragPtr = tFragPtr.p->tupFragptr[0];
  1883.     } else {
  1884.       jam();
  1885.       tupFragPtr = tFragPtr.p->tupFragptr[1];
  1886.     }//if
  1887.   }
  1888.   {
  1889.     jam();
  1890.     TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend(); 
  1891.     tupKeyReq->connectPtr = tcConnectptr.p->tupConnectrec;
  1892.     tupKeyReq->request = reqinfo;
  1893.     tupKeyReq->tableRef = tableRef;
  1894.     tupKeyReq->fragId = scanptr.p->scanLocalFragid;
  1895.     tupKeyReq->keyRef1 = scanptr.p->scanLocalref[0];
  1896.     tupKeyReq->keyRef2 = scanptr.p->scanLocalref[1];
  1897.     tupKeyReq->attrBufLen = 0;
  1898.     tupKeyReq->opRef = scanptr.p->scanApiOpPtr; 
  1899.     tupKeyReq->applRef = scanptr.p->scanApiBlockref;
  1900.     tupKeyReq->schemaVersion = scanptr.p->scanSchemaVersion;
  1901.     tupKeyReq->storedProcedure = scanptr.p->scanStoredProcId;
  1902.     tupKeyReq->transId1 = tcConnectptr.p->transid[0];
  1903.     tupKeyReq->transId2 = tcConnectptr.p->transid[1];
  1904.     tupKeyReq->fragPtr = tupFragPtr;
  1905.     tupKeyReq->primaryReplica = (tcConnectptr.p->seqNoReplica == 0)?true:false;
  1906.     tupKeyReq->coordinatorTC = tcConnectptr.p->tcBlockref;
  1907.     tupKeyReq->tcOpIndex = tcConnectptr.p->tcOprec;
  1908.     tupKeyReq->savePointId = tcConnectptr.p->savePointId;
  1909.     Uint32 blockNo = refToBlock(tcConnectptr.p->tcTupBlockref);
  1910.     EXECUTE_DIRECT(blockNo, GSN_TUPKEYREQ, signal, 
  1911.                TupKeyReq::SignalLength);
  1912.   }
  1913. }
  1914. /* -------------------------------------------------------------------------
  1915.  *       RECEPTION OF FURTHER KEY INFORMATION WHEN KEY SIZE > 16 BYTES.
  1916.  * -------------------------------------------------------------------------
  1917.  *       PRECONDITION:   SCAN_STATE = WAIT_SCAN_KEYINFO
  1918.  * ------------------------------------------------------------------------- */
  1919. bool Dblqh::keyinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length) 
  1920. {
  1921.   tcConnectptr.i = scanptr.p->scanTcrec;
  1922.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  1923.   Uint32 index = 0;
  1924.   do {
  1925.     jam();
  1926.     seizeTupkeybuf(signal);
  1927.     databufptr.p->data[0] = dataPtr[index];
  1928.     databufptr.p->data[1] = dataPtr[index + 1];
  1929.     databufptr.p->data[2] = dataPtr[index + 2];
  1930.     databufptr.p->data[3] = dataPtr[index + 3];
  1931.     index += 4;
  1932.     tcConnectptr.p->save1 = tcConnectptr.p->save1 + 4;
  1933.     if (tcConnectptr.p->save1 >= tcConnectptr.p->primKeyLen) {
  1934.       jam();
  1935.       return true;
  1936.     }//if
  1937.     if (index >= length) {
  1938.       jam();
  1939.       return false;
  1940.     }//if
  1941.   } while (index < 20);
  1942.   ndbrequire(false);
  1943.   return false;
  1944. }//Dblqh::keyinfoLab()
  1945. /* -------------------------------------------------------------------------
  1946.  *         ENTER TUPKEYCONF
  1947.  * -------------------------------------------------------------------------
  1948.  *       PRECONDITION:   TRANSACTION_STATE = SCAN_TUPKEY
  1949.  * ------------------------------------------------------------------------- */
  1950. void Dblqh::scanTupkeyConfLab(Signal* signal) 
  1951. {
  1952.   const TupKeyConf * conf = (TupKeyConf *)signal->getDataPtr();
  1953.   UintR tdata4 = conf->readLength;
  1954.   UintR tdata5 = conf->lastRow;
  1955.   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
  1956.   scanptr.i = tcConnectptr.p->tcScanRec;
  1957.   releaseActiveFrag(signal);
  1958.   c_scanRecordPool.getPtr(scanptr);
  1959.   if (scanptr.p->scanCompletedStatus == ZTRUE) {
  1960.     /* ---------------------------------------------------------------------
  1961.      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
  1962.      * --------------------------------------------------------------------- */
  1963.     releaseOprec(signal);
  1964.     if ((scanptr.p->scanLockHold == ZTRUE) && 
  1965.         (scanptr.p->m_curr_batch_size_rows > 0)) {
  1966.       jam();
  1967.       scanptr.p->scanReleaseCounter = 1;
  1968.       scanReleaseLocksLab(signal);
  1969.       return;
  1970.     }//if
  1971.     jam();
  1972.     closeScanLab(signal);
  1973.     return;
  1974.   }//if
  1975.   if (scanptr.p->scanKeyinfoFlag) {
  1976.     jam();
  1977.     sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
  1978.     releaseOprec(signal);
  1979.     tdata4 += tcConnectptr.p->primKeyLen;// Inform API about keyinfo len aswell
  1980.   }//if
  1981.   ndbrequire(scanptr.p->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
  1982.   scanptr.p->m_curr_batch_size_bytes+= tdata4;
  1983.   scanptr.p->m_curr_batch_size_rows++;
  1984.   scanptr.p->m_last_row = tdata5;
  1985.   if (scanptr.p->check_scan_batch_completed() | tdata5){
  1986.     if (scanptr.p->scanLockHold == ZTRUE) {
  1987.       jam();
  1988.       scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
  1989.       sendScanFragConf(signal, ZFALSE);
  1990.       return;
  1991.     } else {
  1992.       jam();
  1993.       scanptr.p->scanReleaseCounter = scanptr.p->m_curr_batch_size_rows;
  1994.       scanReleaseLocksLab(signal);
  1995.       return;
  1996.     }
  1997.   } else {
  1998.     if (scanptr.p->scanLockHold == ZTRUE) {
  1999.       jam();
  2000.       scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
  2001.     } else {
  2002.       jam();
  2003.       scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
  2004.     }
  2005.   }
  2006.   scanNextLoopLab(signal);
  2007. }//Dblqh::scanTupkeyConfLab()
  2008. void Dblqh::scanNextLoopLab(Signal* signal) 
  2009. {
  2010.   switch (fragptr.p->fragStatus) {
  2011.   case Fragrecord::FSACTIVE:
  2012.     jam();
  2013.     linkActiveFrag(signal);
  2014.     break;
  2015.   case Fragrecord::BLOCKED:
  2016.     jam();
  2017.     linkFragQueue(signal);
  2018.     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STOPPED;
  2019.     return;
  2020.     break;
  2021.   case Fragrecord::FREE:
  2022.     jam();
  2023.   case Fragrecord::ACTIVE_CREATION:
  2024.     jam();
  2025.   case Fragrecord::CRASH_RECOVERING:
  2026.     jam();
  2027.   case Fragrecord::DEFINED:
  2028.     jam();
  2029.   case Fragrecord::REMOVING:
  2030.     jam();
  2031.   default:
  2032.     ndbrequire(false);
  2033.   }//switch
  2034.   continueScanAfterBlockedLab(signal);
  2035. }//Dblqh::scanNextLoopLab()
  2036. void Dblqh::continueScanAfterBlockedLab(Signal* signal) 
  2037. {
  2038.   scanptr.i = tcConnectptr.p->tcScanRec;
  2039.   c_scanRecordPool.getPtr(scanptr);
  2040.   Uint32 accOpPtr;
  2041.   if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_ABORT) {
  2042.     jam();
  2043.     scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
  2044.     accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
  2045.    scanptr.p->m_curr_batch_size_rows,
  2046.    false);
  2047.     scanptr.p->scan_acc_index--;
  2048.   } else if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_COMMIT) {
  2049.     jam();
  2050.     accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
  2051.    scanptr.p->m_curr_batch_size_rows-1,
  2052.    false);
  2053.   } else {
  2054.     jam();
  2055.     accOpPtr = RNIL; // The value is not used in ACC
  2056.   }//if
  2057.   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
  2058.   signal->theData[0] = scanptr.p->scanAccPtr;
  2059.   signal->theData[1] = accOpPtr;
  2060.   signal->theData[2] = scanptr.p->scanFlag;
  2061.   if (! scanptr.p->rangeScan)
  2062.     sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3,JBB);
  2063.   else
  2064.     sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3,JBB);
  2065. }//Dblqh::continueScanAfterBlockedLab()
  2066. /* -------------------------------------------------------------------------
  2067.  *         ENTER TUPKEYREF WITH
  2068.  *               TC_CONNECTPTR,
  2069.  *               TERROR_CODE
  2070.  * -------------------------------------------------------------------------
  2071.  *       PRECONDITION:   TRANSACTION_STATE = SCAN_TUPKEY
  2072.  * ------------------------------------------------------------------------- */
  2073. void Dblqh::scanTupkeyRefLab(Signal* signal) 
  2074. {
  2075.   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
  2076.   scanptr.i = tcConnectptr.p->tcScanRec;
  2077.   releaseActiveFrag(signal);
  2078.   releaseOprec(signal);
  2079.   c_scanRecordPool.getPtr(scanptr);
  2080.   if (scanptr.p->scanCompletedStatus == ZTRUE) {
  2081.     /* ---------------------------------------------------------------------
  2082.      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
  2083.      * --------------------------------------------------------------------- */
  2084.     if ((scanptr.p->scanLockHold == ZTRUE) && 
  2085.         (scanptr.p->m_curr_batch_size_rows > 0)) {
  2086.       jam();
  2087.       scanptr.p->scanReleaseCounter = 1;
  2088.       scanReleaseLocksLab(signal);
  2089.       return;
  2090.     }//if
  2091.     jam();
  2092.     closeScanLab(signal);
  2093.     return;
  2094.   }//if
  2095.   if ((terrorCode != ZSEARCH_CONDITION_FALSE) &&
  2096.       (terrorCode != ZNO_TUPLE_FOUND) &&
  2097.       (terrorCode >= ZUSER_ERROR_CODE_LIMIT)) {
  2098.     scanptr.p->scanErrorCounter++;
  2099.     tcConnectptr.p->errorCode = terrorCode;
  2100.     if (scanptr.p->scanLockHold == ZTRUE) {
  2101.       jam();
  2102.       scanptr.p->scanReleaseCounter = 1;
  2103.     } else {
  2104.       jam();
  2105.       scanptr.p->m_curr_batch_size_rows++;
  2106.       scanptr.p->scanReleaseCounter = scanptr.p->m_curr_batch_size_rows;
  2107.     }//if
  2108.     /* --------------------------------------------------------------------
  2109.      *       WE NEED TO RELEASE ALL LOCKS CURRENTLY
  2110.      *       HELD BY THIS SCAN.
  2111.      * -------------------------------------------------------------------- */ 
  2112.     scanReleaseLocksLab(signal);
  2113.     return;
  2114.   }//if
  2115.   Uint32 time_passed= tcConnectptr.p->tcTimer - cLqhTimeOutCount;
  2116.   if (scanptr.p->m_curr_batch_size_rows > 0) {
  2117.     if (time_passed > 1) {
  2118.   /* -----------------------------------------------------------------------
  2119.    *  WE NEED TO ENSURE THAT WE DO NOT SEARCH FOR THE NEXT TUPLE FOR A 
  2120.    *  LONG TIME WHILE WE KEEP A LOCK ON A FOUND TUPLE. WE RATHER REPORT 
  2121.    *  THE FOUND TUPLE IF FOUND TUPLES ARE RARE. If more than 10 ms passed we
  2122.    *  send the found tuples to the API.
  2123.    * ----------------------------------------------------------------------- */
  2124.       scanptr.p->scanReleaseCounter = scanptr.p->m_curr_batch_size_rows + 1;
  2125.       scanReleaseLocksLab(signal);
  2126.       return;
  2127.     }
  2128.   } else {
  2129.     if (time_passed > 10) {
  2130.       jam();
  2131.       signal->theData[0]= scanptr.i;
  2132.       signal->theData[1]= tcConnectptr.p->transid[0];
  2133.       signal->theData[2]= tcConnectptr.p->transid[1];
  2134.       execSCAN_HBREP(signal);
  2135.     }
  2136.   }
  2137.   scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_ABORT;
  2138.   scanNextLoopLab(signal);
  2139. }//Dblqh::scanTupkeyRefLab()
  2140. /* -------------------------------------------------------------------------
  2141.  *   THE SCAN HAS BEEN COMPLETED. EITHER BY REACHING THE END OR BY COMMAND 
  2142.  *   FROM THE APPLICATION OR BY SOME SORT OF ERROR CONDITION.                
  2143.  * ------------------------------------------------------------------------- */
  2144. void Dblqh::closeScanLab(Signal* signal) 
  2145. {
  2146.   fragptr.i = tcConnectptr.p->fragmentptr;
  2147.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  2148.   switch (fragptr.p->fragStatus) {
  2149.   case Fragrecord::FSACTIVE:
  2150.     jam();
  2151.     linkActiveFrag(signal);
  2152.     break;
  2153.   case Fragrecord::BLOCKED:
  2154.     jam();
  2155.     linkFragQueue(signal);
  2156.     tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CLOSE_STOPPED;
  2157.     return;
  2158.     break;
  2159.   case Fragrecord::FREE:
  2160.     jam();
  2161.   case Fragrecord::ACTIVE_CREATION:
  2162.     jam();
  2163.   case Fragrecord::CRASH_RECOVERING:
  2164.     jam();
  2165.   case Fragrecord::DEFINED:
  2166.     jam();
  2167.   case Fragrecord::REMOVING:
  2168.     jam();
  2169.   default:
  2170.     ndbrequire(false);
  2171.   }//switch
  2172.   continueCloseScanAfterBlockedLab(signal);
  2173. }//Dblqh::closeScanLab()
  2174. void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal) 
  2175. {
  2176.   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
  2177.   scanptr.i = tcConnectptr.p->tcScanRec;
  2178.   c_scanRecordPool.getPtr(scanptr);
  2179.   scanptr.p->scanState = ScanRecord::WAIT_CLOSE_SCAN;
  2180.   signal->theData[0] = scanptr.p->scanAccPtr;
  2181.   signal->theData[1] = RNIL;
  2182.   signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
  2183.   if (! scanptr.p->rangeScan)
  2184.     sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
  2185.   else
  2186.     sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
  2187. }//Dblqh::continueCloseScanAfterBlockedLab()
  2188. /* ------------------------------------------------------------------------- 
  2189.  *       ENTER NEXT_SCANCONF
  2190.  * -------------------------------------------------------------------------
  2191.  *       PRECONDITION: SCAN_STATE = WAIT_CLOSE_SCAN
  2192.  * ------------------------------------------------------------------------- */
  2193. void Dblqh::accScanCloseConfLab(Signal* signal) 
  2194. {
  2195.   tcConnectptr.i = scanptr.p->scanTcrec;
  2196.   scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
  2197.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  2198.   signal->theData[0] = tcConnectptr.p->tupConnectrec;
  2199.   signal->theData[1] = tcConnectptr.p->tableref;
  2200.   signal->theData[2] = scanptr.p->scanSchemaVersion;
  2201.   signal->theData[3] = ZDELETE_STORED_PROC_ID;
  2202.   signal->theData[4] = scanptr.p->scanStoredProcId;
  2203.   sendSignal(tcConnectptr.p->tcTupBlockref,
  2204.              GSN_STORED_PROCREQ, signal, 5, JBB);
  2205. }//Dblqh::accScanCloseConfLab()
  2206. /* -------------------------------------------------------------------------
  2207.  *       ENTER STORED_PROCCONF WITH
  2208.  * -------------------------------------------------------------------------
  2209.  * PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_SCAN
  2210.  * ------------------------------------------------------------------------- */
  2211. void Dblqh::tupScanCloseConfLab(Signal* signal) 
  2212. {
  2213.   fragptr.i = tcConnectptr.p->fragmentptr;
  2214.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  2215.   if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
  2216.     jam();
  2217.     tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
  2218.     ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
  2219.     tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
  2220.     signal->theData[0] = ZLQH_TRANS_NEXT;
  2221.     signal->theData[1] = tcNodeFailptr.i;
  2222.     sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  2223.   } else if (tcConnectptr.p->errorCode != 0) {
  2224.     jam();
  2225.     ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
  2226.     ref->senderData = tcConnectptr.p->clientConnectrec;
  2227.     ref->transId1 = tcConnectptr.p->transid[0];
  2228.     ref->transId2 = tcConnectptr.p->transid[1];
  2229.     ref->errorCode = tcConnectptr.p->errorCode; 
  2230.     sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal, 
  2231.  ScanFragRef::SignalLength, JBB);
  2232.   } else {
  2233.     jam();
  2234.     sendScanFragConf(signal, ZSCAN_FRAG_CLOSED);
  2235.   }//if
  2236.   finishScanrec(signal);
  2237.   releaseScanrec(signal);
  2238.   tcConnectptr.p->tcScanRec = RNIL;
  2239.   deleteTransidHash(signal);
  2240.   releaseOprec(signal);
  2241.   releaseTcrec(signal, tcConnectptr);
  2242. }//Dblqh::tupScanCloseConfLab()
  2243. /* ========================================================================= 
  2244.  * =======              INITIATE SCAN RECORD                         ======= 
  2245.  *
  2246.  *       SUBROUTINE SHORT NAME = ISC
  2247.  * ========================================================================= */
  2248. Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
  2249. {
  2250.   const Uint32 reqinfo = scanFragReq->requestInfo;
  2251.   const Uint32 max_rows = scanFragReq->batch_size_rows;
  2252.   const Uint32 max_bytes = scanFragReq->batch_size_bytes;
  2253.   const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
  2254.   const Uint32 scanLockHold = ScanFragReq::getHoldLockFlag(reqinfo);
  2255.   const Uint32 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
  2256.   const Uint32 readCommitted = ScanFragReq::getReadCommittedFlag(reqinfo);
  2257.   const Uint32 idx = ScanFragReq::getRangeScanFlag(reqinfo);
  2258.   const Uint32 attrLen = ScanFragReq::getAttrLen(reqinfo);
  2259.   const Uint32 scanPrio = ScanFragReq::getScanPrio(reqinfo);
  2260.   scanptr.p->scanKeyinfoFlag = keyinfo;
  2261.   scanptr.p->scanLockHold = scanLockHold;
  2262.   scanptr.p->scanCompletedStatus = ZFALSE;
  2263.   scanptr.p->scanType = ScanRecord::SCAN;
  2264.   scanptr.p->scanApiBlockref = scanFragReq->resultRef;
  2265.   scanptr.p->scanAiLength = attrLen;
  2266.   scanptr.p->scanTcrec = tcConnectptr.i;
  2267.   scanptr.p->scanSchemaVersion = scanFragReq->schemaVersion;
  2268.   scanptr.p->m_curr_batch_size_rows = 0;
  2269.   scanptr.p->m_curr_batch_size_bytes= 0;
  2270.   scanptr.p->m_max_batch_size_rows = max_rows;
  2271.   scanptr.p->m_max_batch_size_bytes = max_bytes;
  2272.   scanptr.p->scanErrorCounter = 0;
  2273.   scanptr.p->scanLockMode = scanLockMode;
  2274.   scanptr.p->readCommitted = readCommitted;
  2275.   scanptr.p->rangeScan = idx;
  2276.   scanptr.p->scanState = ScanRecord::SCAN_FREE;
  2277.   scanptr.p->scanFlag = ZFALSE;
  2278.   scanptr.p->scanLocalref[0] = 0;
  2279.   scanptr.p->scanLocalref[1] = 0;
  2280.   scanptr.p->scanLocalFragid = 0;
  2281.   scanptr.p->scanTcWaiting = ZTRUE;
  2282.   scanptr.p->scanNumber = ~0;
  2283.   scanptr.p->scanApiOpPtr = scanFragReq->clientOpPtr;
  2284.   scanptr.p->m_last_row = 0;
  2285.   if (max_rows == 0 || (max_bytes > 0 && max_rows > max_bytes)){
  2286.     jam();
  2287.     return ScanFragRef::ZWRONG_BATCH_SIZE;
  2288.   }
  2289.   if (!seize_acc_ptr_list(scanptr.p, max_rows)){
  2290.     jam();
  2291.     return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
  2292.   }
  2293.   /**
  2294.    * Used for scan take over
  2295.    */
  2296.   FragrecordPtr tFragPtr;
  2297.   tFragPtr.i = fragptr.p->tableFragptr;
  2298.   ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
  2299.   scanptr.p->fragPtrI = fragptr.p->tableFragptr;
  2300.   
  2301.   /**
  2302.    * !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1)  =  1-11
  2303.    *  idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
  2304.    */
  2305.   Uint32 start = (idx ? MAX_PARALLEL_SCANS_PER_FRAG : 1 );
  2306.   Uint32 stop = (idx ? MAX_PARALLEL_INDEX_SCANS_PER_FRAG : MAX_PARALLEL_SCANS_PER_FRAG - 1);
  2307.   stop += start;
  2308.   Uint32 free = tFragPtr.p->m_scanNumberMask.find(start);
  2309.     
  2310.   if(free == Fragrecord::ScanNumberMask::NotFound || free >= stop){
  2311.     jam();
  2312.     
  2313.     if(scanPrio == 0){
  2314.       jam();
  2315.       return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
  2316.     }
  2317.     
  2318.     /**
  2319.      * Put on queue
  2320.      */
  2321.     scanptr.p->scanState = ScanRecord::IN_QUEUE;
  2322.     LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
  2323.       fragptr.p->m_queuedScans);
  2324.     queue.add(scanptr);
  2325.     return ZOK;
  2326.   }
  2327.   
  2328.   scanptr.p->scanNumber = free;
  2329.   tFragPtr.p->m_scanNumberMask.clear(free);// Update mask  
  2330.   
  2331.   LocalDLList<ScanRecord> active(c_scanRecordPool, fragptr.p->m_activeScans);
  2332.   active.add(scanptr);
  2333.   if(scanptr.p->scanKeyinfoFlag){
  2334.     jam();
  2335. #ifdef VM_TRACE
  2336.     ScanRecordPtr tmp;
  2337.     ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p));
  2338. #endif
  2339. #ifdef TRACE_SCAN_TAKEOVER
  2340.     ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d",
  2341.      scanptr.p->scanNumber, scanptr.p->fragPtrI,
  2342.      tabptr.i, scanFragReq->fragmentNo, fragptr.i, fragptr.p->tableFragptr);
  2343. #endif
  2344.     c_scanTakeOverHash.add(scanptr);
  2345.   }
  2346.   init_acc_ptr_list(scanptr.p);
  2347.   return ZOK;
  2348. }
  2349. /* =========================================================================
  2350.  * =======             INITIATE TC RECORD AT SCAN                    =======
  2351.  *
  2352.  *       SUBROUTINE SHORT NAME = IST
  2353.  * ========================================================================= */
  2354. void Dblqh::initScanTc(Signal* signal,
  2355.                        Uint32 transid1,
  2356.                        Uint32 transid2,
  2357.                        Uint32 fragId,
  2358.                        Uint32 nodeId) 
  2359. {
  2360.   tcConnectptr.p->transid[0] = transid1;
  2361.   tcConnectptr.p->transid[1] = transid2;
  2362.   tcConnectptr.p->tcScanRec = scanptr.i;
  2363.   tcConnectptr.p->tableref = tabptr.i;
  2364.   tcConnectptr.p->fragmentid = fragId;
  2365.   tcConnectptr.p->fragmentptr = fragptr.i;
  2366.   tcConnectptr.p->tcOprec = tcConnectptr.p->clientConnectrec;
  2367.   tcConnectptr.p->tcBlockref = tcConnectptr.p->clientBlockref;
  2368.   tcConnectptr.p->errorCode = 0;
  2369.   tcConnectptr.p->reclenAiLqhkey = 0;
  2370.   tcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
  2371.   tcConnectptr.p->nextReplica = nodeId;
  2372.   tcConnectptr.p->currTupAiLen = 0;
  2373.   tcConnectptr.p->opExec = 1;
  2374.   tcConnectptr.p->operation = ZREAD;
  2375.   tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
  2376.   tcConnectptr.p->commitAckMarker = RNIL;
  2377.   tabptr.p->usageCount++;
  2378. }//Dblqh::initScanTc()
  2379. /* ========================================================================= 
  2380.  * =======                       FINISH  SCAN RECORD                 ======= 
  2381.  * 
  2382.  *       REMOVE SCAN RECORD FROM PER FRAGMENT LIST.
  2383.  * ========================================================================= */
  2384. void Dblqh::finishScanrec(Signal* signal)
  2385. {
  2386.   release_acc_ptr_list(scanptr.p);
  2387.   LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
  2388.     fragptr.p->m_queuedScans);
  2389.   
  2390.   if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
  2391.     jam();
  2392.     queue.release(scanptr);
  2393.     return;
  2394.   }
  2395.   if(scanptr.p->scanKeyinfoFlag){
  2396.     jam();
  2397.     ScanRecordPtr tmp;
  2398. #ifdef TRACE_SCAN_TAKEOVER
  2399.     ndbout_c("removing (%d %d)", scanptr.p->scanNumber, scanptr.p->fragPtrI);
  2400. #endif
  2401.     c_scanTakeOverHash.remove(tmp, * scanptr.p);
  2402.     ndbrequire(tmp.p == scanptr.p);
  2403.   }
  2404.   
  2405.   LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
  2406.   scans.release(scanptr);
  2407.   
  2408.   FragrecordPtr tFragPtr;
  2409.   tFragPtr.i = scanptr.p->fragPtrI;
  2410.   ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
  2411.   const Uint32 scanNumber = scanptr.p->scanNumber;
  2412.   ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
  2413.   ScanRecordPtr restart;
  2414.   /**
  2415.    * Start on of queued scans
  2416.    */
  2417.   if(scanNumber == NR_ScanNo || !queue.first(restart)){
  2418.     jam();
  2419.     tFragPtr.p->m_scanNumberMask.set(scanNumber);
  2420.     return;
  2421.   }
  2422.   if(ERROR_INSERTED(5034)){
  2423.     jam();
  2424.     tFragPtr.p->m_scanNumberMask.set(scanNumber);
  2425.     return;
  2426.   }
  2427.   ndbrequire(restart.p->scanState == ScanRecord::IN_QUEUE);
  2428.   ScanRecordPtr tmpScan = scanptr;
  2429.   TcConnectionrecPtr tmpTc = tcConnectptr;
  2430.   
  2431.   tcConnectptr.i = restart.p->scanTcrec;
  2432.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  2433.   restart.p->scanNumber = scanNumber;
  2434.   queue.remove(restart);
  2435.   scans.add(restart);
  2436.   if(restart.p->scanKeyinfoFlag){
  2437.     jam();
  2438. #ifdef VM_TRACE
  2439.     ScanRecordPtr tmp;
  2440.     ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p));
  2441. #endif
  2442.     c_scanTakeOverHash.add(restart);
  2443. #ifdef TRACE_SCAN_TAKEOVER
  2444.     ndbout_c("adding-r (%d %d)", restart.p->scanNumber, restart.p->fragPtrI);
  2445. #endif
  2446.   }
  2447.   restart.p->scanState = ScanRecord::SCAN_FREE; // set in initScanRec
  2448.   if(tcConnectptr.p->transactionState == TcConnectionrec::SCAN_STATE_USED)
  2449.   {
  2450.     jam();
  2451.     scanptr = restart;
  2452.     continueAfterReceivingAllAiLab(signal);  
  2453.   }
  2454.   else
  2455.   {
  2456.     ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_SCAN_AI);
  2457.   }
  2458.   scanptr = tmpScan;
  2459.   tcConnectptr = tmpTc;
  2460. }//Dblqh::finishScanrec()
  2461. /* ========================================================================= 
  2462.  * =======                       RELEASE SCAN RECORD                 ======= 
  2463.  * 
  2464.  *       RELEASE A SCAN RECORD TO THE FREELIST.
  2465.  * ========================================================================= */
  2466. void Dblqh::releaseScanrec(Signal* signal) 
  2467. {
  2468.   scanptr.p->scanState = ScanRecord::SCAN_FREE;
  2469.   scanptr.p->scanType = ScanRecord::ST_IDLE;
  2470.   scanptr.p->scanTcWaiting = ZFALSE;
  2471.   cbookedAccOps -= scanptr.p->m_max_batch_size_rows;
  2472.   cscanNoFreeRec++;
  2473. }//Dblqh::releaseScanrec()
  2474. /* ------------------------------------------------------------------------
  2475.  * -------              SEND KEYINFO20 TO API                       ------- 
  2476.  *
  2477.  * ------------------------------------------------------------------------  */
  2478. void Dblqh::sendKeyinfo20(Signal* signal, 
  2479.   ScanRecord * scanP, 
  2480.   TcConnectionrec * tcConP)
  2481. {
  2482.   ndbrequire(scanP->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
  2483.   KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
  2484.   
  2485.   DatabufPtr TdataBuf;
  2486.   TdataBuf.i = tcConP->firstTupkeybuf;
  2487.   Uint32 keyLen = tcConP->primKeyLen;
  2488.   const Uint32 dataBufSz = cdatabufFileSize;
  2489.   
  2490.   /**
  2491.    * Note that this code requires signal->theData to be big enough for
  2492.    * a entire key
  2493.    */
  2494.   ndbrequire(keyLen * 4 <= sizeof(signal->theData));
  2495.   const BlockReference ref = scanP->scanApiBlockref;
  2496.   const Uint32 scanOp = scanP->m_curr_batch_size_rows;
  2497.   const Uint32 nodeId = refToNode(ref);
  2498.   const bool connectedToNode = getNodeInfo(nodeId).m_connected;
  2499.   const Uint32 type = getNodeInfo(nodeId).m_type;
  2500.   const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP);
  2501.   const bool old_dest = (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
  2502.   const bool longable = true; // TODO is_api && !old_dest;
  2503.   Uint32 * dst = keyInfo->keyData;
  2504.   dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
  2505.   /**
  2506.    * Copy keydata from data buffer into signal
  2507.    * 
  2508.    */
  2509.   for(Uint32 i = 0; i < keyLen; i += 4){ 
  2510.     ptrCheckGuard(TdataBuf, dataBufSz, databuf);
  2511.     * dst++ = TdataBuf.p->data[0];
  2512.     * dst++ = TdataBuf.p->data[1];
  2513.     * dst++ = TdataBuf.p->data[2];
  2514.     * dst++ = TdataBuf.p->data[3];
  2515.     TdataBuf.i = TdataBuf.p->nextDatabuf;
  2516.   }
  2517.   
  2518.   keyInfo->clientOpPtr   = scanP->scanApiOpPtr;
  2519.   keyInfo->keyLen        = keyLen;
  2520.   keyInfo->scanInfo_Node = KeyInfo20::setScanInfo(scanOp,
  2521.                                                   scanP->scanNumber)+
  2522.                                                   (getOwnNodeId() << 20);
  2523.   keyInfo->transId1 = tcConP->transid[0];
  2524.   keyInfo->transId2 = tcConP->transid[1];
  2525.   
  2526.   Uint32 * src = signal->theData+25;
  2527.   if(connectedToNode){
  2528.     jam();
  2529.     
  2530.     if(nodeId != getOwnNodeId()){
  2531.       jam();
  2532.       
  2533.       if(keyLen <= KeyInfo20::DataLength || !longable) {
  2534. while(keyLen > KeyInfo20::DataLength){
  2535.   jam();
  2536.   MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength);
  2537.   sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB);
  2538.   src += KeyInfo20::DataLength;;
  2539.   keyLen -= KeyInfo20::DataLength;
  2540. }
  2541. MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
  2542. sendSignal(ref, GSN_KEYINFO20, signal, 
  2543.    KeyInfo20::HeaderLength+keyLen, JBB);
  2544. return;
  2545.       }
  2546.       
  2547.       LinearSectionPtr ptr[3];
  2548.       ptr[0].p = src;
  2549.       ptr[0].sz = keyLen;
  2550.       sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength, 
  2551.  JBB, ptr, 1);
  2552.       return;
  2553.     }
  2554.     
  2555.     EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal, 
  2556.    KeyInfo20::HeaderLength + keyLen);
  2557.     jamEntry();
  2558.     return;
  2559.   }
  2560.   
  2561.   /** 
  2562.    * If this node does not have a direct connection 
  2563.    * to the receiving node we want to send the signals 
  2564.    * routed via the node that controls this read
  2565.    */
  2566.   Uint32 routeBlockref = tcConP->clientBlockref;
  2567.   
  2568.   if(keyLen < KeyInfo20::DataLength || !longable){
  2569.     jam();
  2570.     
  2571.     while (keyLen > (KeyInfo20::DataLength - 1)) {
  2572.       jam();      
  2573.       MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength - 1);
  2574.       keyInfo->keyData[KeyInfo20::DataLength-1] = ref;
  2575.       sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 25, JBB);
  2576.       src += KeyInfo20::DataLength - 1;
  2577.       keyLen -= KeyInfo20::DataLength - 1;
  2578.     }
  2579.     MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
  2580.     keyInfo->keyData[keyLen] = ref;  
  2581.     sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 
  2582.        KeyInfo20::HeaderLength+keyLen+1, JBB);    
  2583.     return;
  2584.   }
  2585.   keyInfo->keyData[0] = ref;
  2586.   LinearSectionPtr ptr[3];
  2587.   ptr[0].p = src;
  2588.   ptr[0].sz = keyLen;
  2589.   sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 
  2590.      KeyInfo20::HeaderLength+1, JBB, ptr, 1);
  2591.   return;
  2592. }
  2593.   
  2594. /* ------------------------------------------------------------------------
  2595.  * -------        SEND SCAN_FRAGCONF TO TC THAT CONTROLS THE SCAN   ------- 
  2596.  *
  2597.  * ------------------------------------------------------------------------ */
  2598. void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted) 
  2599. {
  2600.   Uint32 completed_ops= scanptr.p->m_curr_batch_size_rows;
  2601.   Uint32 total_len= scanptr.p->m_curr_batch_size_bytes;
  2602.   scanptr.p->scanTcWaiting = ZFALSE;
  2603.   if(ERROR_INSERTED(5037)){
  2604.     CLEAR_ERROR_INSERT_VALUE;
  2605.     return;
  2606.   }
  2607.   ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
  2608.   NodeId tc_node_id= refToNode(tcConnectptr.p->clientBlockref);
  2609.   Uint32 trans_id1= tcConnectptr.p->transid[0];
  2610.   Uint32 trans_id2= tcConnectptr.p->transid[1];
  2611.   conf->senderData = tcConnectptr.p->clientConnectrec;
  2612.   conf->completedOps = completed_ops;
  2613.   conf->fragmentCompleted = scanCompleted;
  2614.   conf->transId1 = trans_id1;
  2615.   conf->transId2 = trans_id2;
  2616.   conf->total_len= total_len;
  2617.   sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGCONF, 
  2618.              signal, ScanFragConf::SignalLength, JBB);
  2619.   
  2620.   if(!scanptr.p->scanLockHold)
  2621.   {
  2622.     jam();
  2623.     scanptr.p->m_curr_batch_size_rows = 0;
  2624.     scanptr.p->m_curr_batch_size_bytes= 0;
  2625.   }
  2626. }//Dblqh::sendScanFragConf()
  2627. /* ######################################################################### */
  2628. /* #######                NODE RECOVERY MODULE                       ####### */
  2629. /*                                                                           */
  2630. /* ######################################################################### */
  2631. /*---------------------------------------------------------------------------*/
  2632. /*                                                                           */
  2633. /*   THIS MODULE IS USED WHEN A NODE HAS FAILED. IT PERFORMS A COPY OF A     */
  2634. /*   FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL   */
  2635. /*   CONNECTIONS TO THE FAILED NODE.                                         */
  2636. /*---------------------------------------------------------------------------*/
  2637. void Dblqh::calculateHash(Signal* signal) 
  2638. {
  2639.   DatabufPtr locDatabufptr;
  2640.   UintR  Ti;
  2641.   UintR  Tdata0;
  2642.   UintR  Tdata1;
  2643.   UintR  Tdata2;
  2644.   UintR  Tdata3;
  2645.   UintR*  Tdata32;
  2646.   Uint64 Tdata[512];
  2647.   Tdata32 = (UintR*)&Tdata[0];
  2648.   Tdata0 = tcConnectptr.p->tupkeyData[0];
  2649.   Tdata1 = tcConnectptr.p->tupkeyData[1];
  2650.   Tdata2 = tcConnectptr.p->tupkeyData[2];
  2651.   Tdata3 = tcConnectptr.p->tupkeyData[3];
  2652.   Tdata32[0] = Tdata0;
  2653.   Tdata32[1] = Tdata1;
  2654.   Tdata32[2] = Tdata2;
  2655.   Tdata32[3] = Tdata3;
  2656.   locDatabufptr.i = tcConnectptr.p->firstTupkeybuf;
  2657.   Ti = 4;
  2658.   while (locDatabufptr.i != RNIL) {
  2659.     ptrCheckGuard(locDatabufptr, cdatabufFileSize, databuf);
  2660.     Tdata0 = locDatabufptr.p->data[0];
  2661.     Tdata1 = locDatabufptr.p->data[1];
  2662.     Tdata2 = locDatabufptr.p->data[2];
  2663.     Tdata3 = locDatabufptr.p->data[3];
  2664.     Tdata32[Ti    ] = Tdata0;
  2665.     Tdata32[Ti + 1] = Tdata1;
  2666.     Tdata32[Ti + 2] = Tdata2;
  2667.     Tdata32[Ti + 3] = Tdata3;
  2668.     locDatabufptr.i = locDatabufptr.p->nextDatabuf;
  2669.     Ti += 4;
  2670.   }//while
  2671.   tcConnectptr.p->hashValue = 
  2672.     md5_hash((Uint64*)&Tdata32[0], (UintR)tcConnectptr.p->primKeyLen);
  2673. }//Dblqh::calculateHash()
  2674. /* *************************************** */
  2675. /*  COPY_FRAGREQ: Start copying a fragment */
  2676. /* *************************************** */
  2677. void Dblqh::execCOPY_FRAGREQ(Signal* signal) 
  2678. {
  2679.   jamEntry();
  2680.   const CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
  2681.   tabptr.i = copyFragReq->tableId;
  2682.   ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
  2683.   const Uint32 fragId = copyFragReq->fragId;
  2684.   const Uint32 copyPtr = copyFragReq->userPtr;
  2685.   const Uint32 userRef = copyFragReq->userRef;
  2686.   const Uint32 nodeId = copyFragReq->nodeId;
  2687.   ndbrequire(cnoActiveCopy < 3);
  2688.   ndbrequire(getFragmentrec(signal, fragId));
  2689.   ndbrequire(fragptr.p->copyFragState == ZIDLE);
  2690.   ndbrequire(cfirstfreeTcConrec != RNIL);
  2691.   ndbrequire(fragptr.p->m_scanNumberMask.get(NR_ScanNo));
  2692.   fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
  2693.   if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
  2694.     jam();
  2695.     /**
  2696.      * Ordered index doesn't need to be copied
  2697.      */
  2698.     CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
  2699.     conf->userPtr = copyPtr;
  2700.     conf->sendingNodeId = cownNodeid;
  2701.     conf->startingNodeId = nodeId;
  2702.     conf->tableId = tabptr.i;
  2703.     conf->fragId = fragId;
  2704.     sendSignal(userRef, GSN_COPY_FRAGCONF, signal,
  2705.        CopyFragConf::SignalLength, JBB);
  2706.     return;
  2707.   }//if
  2708.   
  2709.   LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
  2710.   ndbrequire(scans.seize(scanptr));
  2711. /* ------------------------------------------------------------------------- */
  2712. // We keep track of how many operation records in ACC that has been booked.
  2713. // Copy fragment has records always booked and thus need not book any. The
  2714. // most operations in parallel use is the m_max_batch_size_rows.
  2715. // This variable has to be set-up here since it is used by releaseScanrec
  2716. // to unbook operation records in ACC.
  2717. /* ------------------------------------------------------------------------- */
  2718.   scanptr.p->m_max_batch_size_rows = 0;
  2719.   scanptr.p->rangeScan = 0;
  2720.   seizeTcrec();
  2721.   
  2722.   /**
  2723.    * Remove implicit cast/usage of CopyFragReq
  2724.    */
  2725.   //initCopyrec(signal);
  2726.   scanptr.p->copyPtr = copyPtr;
  2727.   scanptr.p->scanType = ScanRecord::COPY;
  2728.   scanptr.p->scanApiBlockref = userRef;
  2729.   scanptr.p->scanNodeId = nodeId;
  2730.   scanptr.p->scanTcrec = tcConnectptr.i;
  2731.   scanptr.p->scanSchemaVersion = copyFragReq->schemaVersion;
  2732.   scanptr.p->scanCompletedStatus = ZFALSE;
  2733.   scanptr.p->scanErrorCounter = 0;
  2734.   scanptr.p->scanNumber = NR_ScanNo;
  2735.   scanptr.p->scanKeyinfoFlag = 0; // Don't put into hash
  2736.   scanptr.p->fragPtrI = fragptr.i;
  2737.   fragptr.p->m_scanNumberMask.clear(NR_ScanNo);
  2738.   initScanTc(signal,
  2739.              0,
  2740.              (DBLQH << 20) + (cownNodeid << 8),
  2741.              fragId,
  2742.              copyFragReq->nodeId);
  2743.   cactiveCopy[cnoActiveCopy] = fragptr.i;
  2744.   cnoActiveCopy++;
  2745.   tcConnectptr.p->copyCountWords = 0;
  2746.   tcConnectptr.p->tcOprec = tcConnectptr.i;
  2747.   tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
  2748.   scanptr.p->scanState = ScanRecord::WAIT_ACC_COPY;
  2749.   AccScanReq * req = (AccScanReq*)&signal->theData[0];
  2750.   req->senderData = scanptr.i;
  2751.   req->senderRef = cownref;
  2752.   req->tableId = tabptr.i;
  2753.   req->fragmentNo = fragId;
  2754.   req->requestInfo = 0;
  2755.   AccScanReq::setLockMode(req->requestInfo, 0);
  2756.   AccScanReq::setKeyinfoFlag(req->requestInfo, 1);
  2757.   AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
  2758.   req->transId1 = tcConnectptr.p->transid[0];
  2759.   req->transId2 = tcConnectptr.p->transid[1];
  2760.   req->savePointId = tcConnectptr.p->savePointId;
  2761.   sendSignal(tcConnectptr.p->tcAccBlockref, GSN_ACC_SCANREQ, signal, 
  2762.      AccScanReq::SignalLength, JBB);
  2763.   return;
  2764. }//Dblqh::execCOPY_FRAGREQ()
  2765. void Dblqh::accScanConfCopyLab(Signal* signal) 
  2766. {
  2767.   AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
  2768.   tcConnectptr.i = scanptr.p->scanTcrec;
  2769.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  2770. /*--------------------------------------------------------------------------*/
  2771. /*  PRECONDITION: SCAN_STATE = WAIT_ACC_COPY                                */
  2772. /*--------------------------------------------------------------------------*/
  2773.   if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
  2774.     jam();
  2775. /*---------------------------------------------------------------------------*/
  2776. /*   THE FRAGMENT WAS EMPTY.                                                 */
  2777. /*   REPORT SUCCESSFUL COPYING.                                              */
  2778. /*---------------------------------------------------------------------------*/
  2779.     tupCopyCloseConfLab(signal);
  2780.     return;
  2781.   }//if
  2782.   scanptr.p->scanAccPtr = accScanConf->accPtr;
  2783.   scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_COPY;
  2784.   signal->theData[0] = tcConnectptr.p->tupConnectrec;
  2785.   signal->theData[1] = tcConnectptr.p->tableref;
  2786.   signal->theData[2] = scanptr.p->scanSchemaVersion;
  2787.   signal->theData[3] = ZSTORED_PROC_COPY;
  2788. // theData[4] is not used in TUP with ZSTORED_PROC_COPY
  2789.   sendSignal(tcConnectptr.p->tcTupBlockref, GSN_STORED_PROCREQ, signal, 5, JBB);
  2790.   return;
  2791. }//Dblqh::accScanConfCopyLab()
  2792. /*---------------------------------------------------------------------------*/
  2793. /*   ENTER STORED_PROCCONF WITH                                              */
  2794. /*     TC_CONNECTPTR,                                                        */
  2795. /*     TSTORED_PROC_ID                                                       */
  2796. /*---------------------------------------------------------------------------*/
  2797. void Dblqh::storedProcConfCopyLab(Signal* signal) 
  2798. {
  2799. /*---------------------------------------------------------------------------*/
  2800. /*   PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_COPY                        */
  2801. /*---------------------------------------------------------------------------*/
  2802.   fragptr.i = tcConnectptr.p->fragmentptr;
  2803.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  2804.   if (scanptr.p->scanCompletedStatus == ZTRUE) {
  2805.     jam();
  2806. /*---------------------------------------------------------------------------*/
  2807. /*   THE COPY PROCESS HAVE BEEN COMPLETED, MOST LIKELY DUE TO A NODE FAILURE.*/
  2808. /*---------------------------------------------------------------------------*/
  2809.     closeCopyLab(signal);
  2810.     return;
  2811.   }//if
  2812.   scanptr.i = tcConnectptr.p->tcScanRec;
  2813.   c_scanRecordPool.getPtr(scanptr);
  2814.   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
  2815.   switch (fragptr.p->fragStatus) {
  2816.   case Fragrecord::FSACTIVE:
  2817.     jam();
  2818.     linkActiveFrag(signal);
  2819.     break;
  2820.   case Fragrecord::BLOCKED:
  2821.     jam();
  2822.     linkFragQueue(signal);
  2823.     tcConnectptr.p->transactionState = TcConnectionrec::COPY_FIRST_STOPPED;
  2824.     return;
  2825.     break;
  2826.   case Fragrecord::FREE:
  2827.     jam();
  2828.   case Fragrecord::ACTIVE_CREATION:
  2829.     jam();
  2830.   case Fragrecord::CRASH_RECOVERING:
  2831.     jam();
  2832.   case Fragrecord::DEFINED:
  2833.     jam();
  2834.   case Fragrecord::REMOVING:
  2835.     jam();
  2836.   default:
  2837.     jam();
  2838.     systemErrorLab(signal);
  2839.     return;
  2840.     break;
  2841.   }//switch
  2842.   continueFirstCopyAfterBlockedLab(signal);
  2843.   return;
  2844. }//Dblqh::storedProcConfCopyLab()
  2845. void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal) 
  2846. {
  2847.   scanptr.i = tcConnectptr.p->tcScanRec;
  2848.   c_scanRecordPool.getPtr(scanptr);
  2849.   signal->theData[0] = scanptr.p->scanAccPtr;
  2850.   signal->theData[1] = RNIL;
  2851.   signal->theData[2] = NextScanReq::ZSCAN_NEXT;
  2852.   sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
  2853.   return;
  2854. }//Dblqh::continueFirstCopyAfterBlockedLab()
  2855. /*---------------------------------------------------------------------------*/
  2856. /*       ENTER NEXT_SCANCONF WITH                                            */
  2857. /*         SCANPTR,                                                          */
  2858. /*         TFRAGID,                                                          */
  2859. /*         TACC_OPPTR,                                                       */
  2860. /*         TLOCAL_KEY1,                                                      */
  2861. /*         TLOCAL_KEY2,                                                      */
  2862. /*         TKEY_LENGTH,                                                      */
  2863. /*         TKEY1,                                                            */
  2864. /*         TKEY2,                                                            */
  2865. /*         TKEY3,                                                            */
  2866. /*         TKEY4                                                             */
  2867. /*---------------------------------------------------------------------------*/
  2868. /*       PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN_COPY                      */
  2869. /*---------------------------------------------------------------------------*/
  2870. void Dblqh::nextScanConfCopyLab(Signal* signal) 
  2871. {
  2872.   NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
  2873.   tcConnectptr.i = scanptr.p->scanTcrec;
  2874.   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
  2875.   if (nextScanConf->fragId == RNIL) {
  2876.     jam();
  2877. /*---------------------------------------------------------------------------*/
  2878. /*   THERE ARE NO MORE TUPLES TO FETCH. WE NEED TO CLOSE                     */
  2879. /*   THE COPY IN ACC AND DELETE THE STORED PROCEDURE IN TUP                  */
  2880. /*---------------------------------------------------------------------------*/
  2881.     releaseActiveFrag(signal);
  2882.     if (tcConnectptr.p->copyCountWords == 0) {
  2883.       closeCopyLab(signal);
  2884.       return;
  2885.     }//if
  2886. /*---------------------------------------------------------------------------*/
  2887. // Wait until copying is completed also at the starting node before reporting
  2888. // completion. Signal completion through scanCompletedStatus-flag.
  2889. /*---------------------------------------------------------------------------*/
  2890.     scanptr.p->scanCompletedStatus = ZTRUE;
  2891.     return;
  2892.   }//if
  2893.   // If accOperationPtr == RNIL no record was returned by ACC
  2894.   if (nextScanConf->accOperationPtr == RNIL) {
  2895.     jam();
  2896.     signal->theData[0] = scanptr.p->scanAccPtr;
  2897.     signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
  2898.     sendSignal(tcConnectptr.p->tcAccBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
  2899.     return;      
  2900.   }
  2901.   set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
  2902.   initCopyTc(signal);
  2903.   if (tcConnectptr.p->primKeyLen > 4) {
  2904.     jam();
  2905.     tcConnectptr.p->save1 = 4;
  2906.     scanptr.p->scanState = ScanRecord::WAIT_COPY_KEYINFO;
  2907.     return;
  2908.   }//if
  2909.   copySendTupkeyReqLab(signal);
  2910.   return;
  2911. }//Dblqh::nextScanConfCopyLab()
  2912. void Dblqh::copySendTupkeyReqLab(Signal* signal) 
  2913. {
  2914.   Uint32 reqinfo = 0;
  2915.   Uint32 tupFragPtr;
  2916.   reqinfo = reqinfo + (tcConnectptr.p->operation << 6);
  2917.   reqinfo = reqinfo + (tcConnectptr.p->opExec << 10);
  2918.   tcConnectptr.p->transactionState = TcConnectionrec::COPY_TUPKEY;
  2919.   scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
  2920.   fragptr.i = tcConnectptr.p->fragmentptr;
  2921.   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
  2922.   if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
  2923.     jam();
  2924.     tupFragPtr = fragptr.p->tupFragptr[0];
  2925.   } else {
  2926.     jam();
  2927.     tupFragPtr = fragptr.p->tupFragptr[1];
  2928.   }//if
  2929.   {
  2930.     TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend(); 
  2931.     tupKeyReq->connectPtr = tcConnectptr.p->tupConnectrec;
  2932.     tupKeyReq->request = reqinfo;
  2933.     tupKeyReq->tableRef = tcConnectptr.p->tableref;
  2934.     tupKeyReq->fragId = scanptr.p->scanLocalFragid;
  2935.     tupKeyReq->keyRef1 = scanptr.p->scanLocalref[0];
  2936.     tupKeyReq->keyRef2 = scanptr.p->scanLocalref[1];
  2937.     tupKeyReq->attrBufLen = 0;