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

MySQL数据库

开发平台:

Visual C++

  1.      * ourselves vicarious for the failed node.
  2.      *--------------------------------------------------------------*/
  3.             setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
  4.             signal->theData[0] = tcConnectptr.i;
  5.             signal->theData[1] = apiConnectptr.p->transid[0];
  6.             signal->theData[2] = apiConnectptr.p->transid[1];
  7.             signal->theData[3] = hostptr.i;
  8.             signal->theData[4] = ZFALSE;
  9.             sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
  10.           }//if
  11.         }//if
  12.       }//for
  13.     }//if
  14.     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
  15.   } while (1);
  16. }//Dbtc::sendAbortedAfterTimeout()
  17. void Dbtc::reportNodeFailed(Signal* signal, Uint32 nodeId)
  18. {
  19.   DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
  20.   rep->nodeId = nodeId;
  21.   rep->err = DisconnectRep::TcReportNodeFailed;
  22.   sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal, 
  23.      DisconnectRep::SignalLength, JBB);
  24. }//Dbtc::reportNodeFailed()
  25. /*-------------------------------------------------*/
  26. /*      Timeout-loop for scanned fragments.        */
  27. /*-------------------------------------------------*/
  28. void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
  29. {
  30.   ScanFragRecPtr timeOutPtr[8];
  31.   UintR tfragTimer[8];
  32.   UintR texpiredTime[8];
  33.   UintR TloopCount = 0;
  34.   Uint32 TtcTimer = ctcTimer;
  35.   while ((TscanConPtr + 8) < cscanFragrecFileSize) {
  36.     jam();
  37.     timeOutPtr[0].i  = TscanConPtr + 0;
  38.     timeOutPtr[1].i  = TscanConPtr + 1;
  39.     timeOutPtr[2].i  = TscanConPtr + 2;
  40.     timeOutPtr[3].i  = TscanConPtr + 3;
  41.     timeOutPtr[4].i  = TscanConPtr + 4;
  42.     timeOutPtr[5].i  = TscanConPtr + 5;
  43.     timeOutPtr[6].i  = TscanConPtr + 6;
  44.     timeOutPtr[7].i  = TscanConPtr + 7;
  45.     
  46.     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
  47.     c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
  48.     c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
  49.     c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
  50.     c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
  51.     c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
  52.     c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
  53.     c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
  54.     tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
  55.     tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
  56.     tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
  57.     tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
  58.     tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
  59.     tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
  60.     tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
  61.     tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
  62.     texpiredTime[0] = TtcTimer - tfragTimer[0];
  63.     texpiredTime[1] = TtcTimer - tfragTimer[1];
  64.     texpiredTime[2] = TtcTimer - tfragTimer[2];
  65.     texpiredTime[3] = TtcTimer - tfragTimer[3];
  66.     texpiredTime[4] = TtcTimer - tfragTimer[4];
  67.     texpiredTime[5] = TtcTimer - tfragTimer[5];
  68.     texpiredTime[6] = TtcTimer - tfragTimer[6];
  69.     texpiredTime[7] = TtcTimer - tfragTimer[7];
  70.     
  71.     for (Uint32 Ti = 0; Ti < 8; Ti++) {
  72.       jam();
  73.       if (tfragTimer[Ti] != 0) {
  74.         if (texpiredTime[Ti] > ctimeOutValue) {
  75.   jam();
  76.   DEBUG("Fragment timeout found:"<<
  77. " ctimeOutValue=" <<ctimeOutValue
  78. <<", texpiredTime="<<texpiredTime[Ti]<<endl
  79. <<"      tfragTimer="<<tfragTimer[Ti]
  80. <<", ctcTimer="<<ctcTimer);
  81.           timeOutFoundFragLab(signal, TscanConPtr + Ti);
  82.           return;
  83.         }//if
  84.       }//if
  85.     }//for
  86.     TscanConPtr += 8;
  87.     /*----------------------------------------------------------------*/
  88.     /* We split the process up checking 1024 fragmentrecords at a time*/
  89.     /* to maintain real time behaviour.                               */
  90.     /*----------------------------------------------------------------*/
  91.     if (TloopCount++ > 128 ) {
  92.       jam();
  93.       signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
  94.       signal->theData[1] = TscanConPtr;
  95.       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  96.       return;
  97.     }//if
  98.   }//while
  99.   for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
  100.     jam();
  101.     timeOutPtr[0].i = TscanConPtr;
  102.     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
  103.     if (timeOutPtr[0].p->scanFragTimer != 0) {
  104.       texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
  105.       if (texpiredTime[0] > ctimeOutValue) {
  106.         jam();
  107. DEBUG("Fragment timeout found:"<<
  108.       " ctimeOutValue=" <<ctimeOutValue
  109.       <<", texpiredTime="<<texpiredTime[0]<<endl
  110. <<"      tfragTimer="<<tfragTimer[0]
  111. <<", ctcTimer="<<ctcTimer);
  112.         timeOutFoundFragLab(signal, TscanConPtr);
  113.         return;
  114.       }//if
  115.     }//if
  116.   }//for  
  117.   ctimeOutCheckFragActive = TOCS_FALSE;
  118.   return;
  119. }//timeOutLoopStartFragLab()
  120. /*--------------------------------------------------------------------------*/
  121. /*Handle the heartbeat signal from LQH in a scan process                    */
  122. // (Set timer on fragrec.)
  123. /*--------------------------------------------------------------------------*/
  124. void Dbtc::execSCAN_HBREP(Signal* signal)
  125. {
  126.   jamEntry();
  127.   scanFragptr.i = signal->theData[0];  
  128.   c_scan_frag_pool.getPtr(scanFragptr);
  129.   switch (scanFragptr.p->scanFragState){
  130.   case ScanFragRec::LQH_ACTIVE:
  131.     break;
  132.   default:
  133.     DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
  134.     systemErrorLab(signal);
  135.     break;
  136.   }
  137.   ScanRecordPtr scanptr;
  138.   scanptr.i = scanFragptr.p->scanRec;
  139.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  140.   apiConnectptr.i = scanptr.p->scanApiRec;
  141.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  142.   if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
  143. apiConnectptr.p->transid[1] == signal->theData[2])){
  144.     jam();
  145.     /**
  146.      * Send signal back to sender so that the crash occurs there
  147.      */
  148.     // Save original transid
  149.     signal->theData[3] = signal->theData[0];
  150.     signal->theData[4] = signal->theData[1];
  151.     // Set transid to illegal values
  152.     signal->theData[1] = RNIL;
  153.     signal->theData[2] = RNIL;
  154.     
  155.     sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
  156.     DEBUG("SCAN_HBREP with wrong transid("
  157.   <<signal->theData[3]<<", "<<signal->theData[4]<<")");
  158.     return;
  159.   }//if
  160.   // Update timer on ScanFragRec
  161.   if (scanFragptr.p->scanFragTimer != 0){
  162.     updateBuddyTimer(apiConnectptr);
  163.     scanFragptr.p->startFragTimer(ctcTimer);
  164.   } else {
  165.     ndbassert(false);
  166.     DEBUG("SCAN_HBREP when scanFragTimer was turned off");
  167.   }
  168. }//execSCAN_HBREP()
  169. /*--------------------------------------------------------------------------*/
  170. /*      Timeout has occured on a fragment which means a scan has timed out. */
  171. /*      If this is true we have an error in LQH/ACC.                        */
  172. /*--------------------------------------------------------------------------*/
  173. void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
  174. {
  175.   ScanFragRecPtr ptr;
  176.   c_scan_frag_pool.getPtr(ptr, TscanConPtr);
  177.   DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState);
  178.   /*-------------------------------------------------------------------------*/
  179.   // The scan fragment has expired its timeout. Check its state to decide
  180.   // what to do.
  181.   /*-------------------------------------------------------------------------*/
  182.   switch (ptr.p->scanFragState) {
  183.   case ScanFragRec::WAIT_GET_PRIMCONF:
  184.     jam();
  185.     ndbrequire(false);
  186.     break;
  187.   case ScanFragRec::LQH_ACTIVE:{
  188.     jam();
  189.     /**  
  190.      * The LQH expired it's timeout, try to close it
  191.      */    
  192.     Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
  193.     Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
  194.     ScanRecordPtr scanptr;
  195.     scanptr.i = ptr.p->scanRec;
  196.     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  197.     if(connectCount != ptr.p->m_connectCount){
  198.       jam();
  199.       /**
  200.        * The node has died
  201.        */
  202.       ptr.p->scanFragState = ScanFragRec::COMPLETED;
  203.       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  204.       
  205.       run.release(ptr);
  206.       ptr.p->stopFragTimer();
  207.     }
  208.     
  209.     scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
  210.     break;
  211.   }
  212.   case ScanFragRec::DELIVERED:
  213.     jam();
  214.   case ScanFragRec::IDLE:
  215.     jam();
  216.   case ScanFragRec::QUEUED_FOR_DELIVERY:
  217.     jam();
  218.     /*-----------------------------------------------------------------------
  219.      * Should never occur. We will simply report set the timer to zero and
  220.      * continue. In a debug version we should crash here but not in a release
  221.      * version. In a release version we will simply set the time-out to zero.
  222.      *-----------------------------------------------------------------------*/
  223. #ifdef VM_TRACE
  224.     systemErrorLab(signal);
  225. #endif
  226.     scanFragptr.p->stopFragTimer();
  227.     break;
  228.   default:
  229.     jam();
  230.     /*-----------------------------------------------------------------------
  231.      * Non-existent state. Crash.
  232.      *-----------------------------------------------------------------------*/
  233.     systemErrorLab(signal);
  234.     break;
  235.   }//switch
  236.   
  237.   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
  238.   signal->theData[1] = TscanConPtr + 1;
  239.   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  240.   return;  
  241. }//timeOutFoundFragLab()
  242. /*
  243.   4.3.16 GCP_NOMORETRANS  
  244.   ----------------------
  245. */
  246. /*****************************************************************************
  247.  *                         G C P _ N O M O R E T R A N S                    
  248.  *                                                                           
  249.  *  WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF  
  250.  *  THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN 
  251.  *  SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
  252.  *  CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
  253.  *  FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
  254.  *  COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS, 
  255.  *  THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
  256.  *  THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL 
  257.  *  TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.       
  258.  *****************************************************************************/
  259. void Dbtc::execGCP_NOMORETRANS(Signal* signal) 
  260. {
  261.   jamEntry();
  262.   tcheckGcpId = signal->theData[1];
  263.   if (cfirstgcp != RNIL) {
  264.     jam();
  265.                                       /* A GLOBAL CHECKPOINT IS GOING ON */
  266.     gcpPtr.i = cfirstgcp;             /* SET POINTER TO FIRST GCP IN QUEUE*/
  267.     ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
  268.     if (gcpPtr.p->gcpId == tcheckGcpId) {
  269.       jam();
  270.       if (gcpPtr.p->firstApiConnect != RNIL) {
  271.         jam();
  272.         gcpPtr.p->gcpNomoretransRec = ZTRUE;
  273.       } else {
  274.         jam();
  275.         gcpTcfinished(signal);
  276.         unlinkGcp(signal);
  277.       }//if
  278.     } else {
  279.       jam();
  280.       /*------------------------------------------------------------*/
  281.       /*       IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO       */
  282.       /*       RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE  */
  283.       /*       THE GLOBAL CHECKPOINTS IN ORDER.                     */
  284.       /*------------------------------------------------------------*/
  285.       gcpTcfinished(signal);
  286.     }//if
  287.   } else {
  288.     jam();
  289.     gcpTcfinished(signal);
  290.   }//if
  291.   return;
  292. }//Dbtc::execGCP_NOMORETRANS()
  293. /*****************************************************************************/
  294. /*                                                                           */
  295. /*                            TAKE OVER MODULE                               */
  296. /*                                                                           */
  297. /*****************************************************************************/
  298. /*                                                                           */
  299. /*    THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE  */
  300. /*    NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT   */
  301. /*    ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE   */
  302. /*    FAILED.                                                                */
  303. /*                                                                           */
  304. /*    AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
  305. /*    CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
  306. /*    COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED.    */
  307. /*    IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO  */
  308. /*    WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT.            */
  309. /*****************************************************************************/
  310. void Dbtc::execNODE_FAILREP(Signal* signal) 
  311. {
  312.   HostRecordPtr tmpHostptr;
  313.   jamEntry();
  314.   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
  315.   cfailure_nr = nodeFail->failNo;
  316.   const Uint32 tnoOfNodes  = nodeFail->noOfNodes;
  317.   const Uint32 tnewMasterId = nodeFail->masterNodeId;
  318.   
  319.   arrGuard(tnoOfNodes, MAX_NDB_NODES);
  320.   int index = 0;
  321.   for (unsigned i = 1; i< MAX_NDB_NODES; i++) {
  322.     if(NodeBitmask::get(nodeFail->theNodes, i)){
  323.       cdata[index] = i;
  324.       index++;
  325.     }//if
  326.   }//for
  327.   tcNodeFailptr.i = 0;
  328.   ptrAss(tcNodeFailptr, tcFailRecord);
  329.   Uint32 tindex;
  330.   for (tindex = 0; tindex < tnoOfNodes; tindex++) {
  331.     jam();
  332.     hostptr.i = cdata[tindex];
  333.     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  334.     /*------------------------------------------------------------*/
  335.     /*       SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS   */
  336.     /*       FAILED.                                              */
  337.     /*------------------------------------------------------------*/
  338.     hostptr.p->hostStatus = HS_DEAD;
  339.     if (hostptr.p->takeOverStatus == TOS_COMPLETED) {
  340.       jam();
  341.       /*------------------------------------------------------------*/
  342.       /*       A VERY UNUSUAL SITUATION. THE TAKE OVER WAS COMPLETED*/
  343.       /*       EVEN BEFORE WE HEARD ABOUT THE NODE FAILURE REPORT.  */
  344.       /*       HOWEVER UNUSUAL THIS SITUATION IS POSSIBLE.          */
  345.       /*------------------------------------------------------------*/
  346.       /*       RELEASE THE CURRENTLY UNUSED LQH CONNECTIONS. THE    */
  347.       /*       REMAINING WILL BE RELEASED WHEN THE TRANSACTION THAT */
  348.       /*       USED THEM IS COMPLETED.                              */
  349.       /*------------------------------------------------------------*/
  350.       {
  351. NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
  352. nfRep->blockNo      = DBTC;
  353. nfRep->nodeId       = cownNodeid;
  354. nfRep->failedNodeId = hostptr.i;
  355.       }
  356.       sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal, 
  357.  NFCompleteRep::SignalLength, JBB);
  358.     } else {
  359.       ndbrequire(hostptr.p->takeOverStatus == TOS_IDLE);
  360.       hostptr.p->takeOverStatus = TOS_NODE_FAILED;
  361.     }//if
  362.     
  363.     if (tcNodeFailptr.p->failStatus == FS_LISTENING) {
  364.       jam();
  365.       /*------------------------------------------------------------*/
  366.       /*       THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE   */
  367.       /*       FAILURE.                                             */
  368.       /*------------------------------------------------------------*/
  369.       if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
  370. jam();
  371. /*------------------------------------------------------------*/
  372. /*       WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
  373. /*       PROTOCOL FOR TC.                                     */
  374. /*------------------------------------------------------------*/
  375. signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
  376. signal->theData[1] = hostptr.i;
  377. sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  378.       }//if
  379.     }//if
  380.     
  381.   }//for
  382.   const bool masterFailed = (cmasterNodeId != tnewMasterId);
  383.   cmasterNodeId = tnewMasterId;
  384.   if(getOwnNodeId() == cmasterNodeId && masterFailed){
  385.     /**
  386.      * Master has failed and I'm the new master
  387.      */
  388.     jam();
  389.     
  390.     for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
  391.       jam();
  392.       ptrAss(hostptr, hostRecord);
  393.       if (hostptr.p->hostStatus != HS_ALIVE) {
  394. jam();
  395. if (hostptr.p->takeOverStatus == TOS_COMPLETED) {
  396.   jam();
  397.   /*------------------------------------------------------------*/
  398.   /*       SEND TAKE OVER CONFIRMATION TO ALL ALIVE NODES IF    */
  399.   /*       TAKE OVER IS COMPLETED. THIS IS PERFORMED TO ENSURE  */
  400.   /*       THAT ALL NODES AGREE ON THE IDLE STATE OF THE TAKE   */
  401.   /*       OVER. THIS MIGHT BE MISSED IN AN ERROR SITUATION IF  */
  402.   /*       MASTER FAILS AFTER SENDING CONFIRMATION TO NEW       */
  403.   /*       MASTER BUT FAILING BEFORE SENDING TO ANOTHER NODE    */
  404.   /*       WHICH WAS NOT MASTER. IF THIS NODE LATER BECOMES     */
  405.   /*       MASTER IT MIGHT START A NEW TAKE OVER EVEN AFTER THE */
  406.   /*       CRASHED NODE HAVE ALREADY RECOVERED.                 */
  407.   /*------------------------------------------------------------*/
  408.   for(tmpHostptr.i = 1; tmpHostptr.i < MAX_NDB_NODES;tmpHostptr.i++) {
  409.     jam();
  410.     ptrAss(tmpHostptr, hostRecord);
  411.     if (tmpHostptr.p->hostStatus == HS_ALIVE) {
  412.       jam();
  413.       tblockref = calcTcBlockRef(tmpHostptr.i);
  414.       signal->theData[0] = hostptr.i;
  415.       sendSignal(tblockref, GSN_TAKE_OVERTCCONF, signal, 1, JBB);
  416.     }//if
  417.   }//for
  418. }//if
  419.       }//if
  420.     }//for
  421.   }
  422.   if(getOwnNodeId() == cmasterNodeId){
  423.     jam();
  424.     for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
  425.       jam();
  426.       ptrAss(hostptr, hostRecord);
  427.       if (hostptr.p->hostStatus != HS_ALIVE) {
  428.         jam();
  429.         if (hostptr.p->takeOverStatus == TOS_NODE_FAILED) {
  430.           jam();
  431.   /*------------------------------------------------------------*/
  432.   /*       CONCLUDE ALL ACTIVITIES THE FAILED TC DID CONTROL    */
  433.   /*       SINCE WE ARE THE MASTER. THIS COULD HAVE BEEN STARTED*/
  434.   /*       BY A PREVIOUS MASTER BUT HAVE NOT BEEN CONCLUDED YET.*/
  435.   /*------------------------------------------------------------*/
  436.           hostptr.p->takeOverStatus = TOS_ACTIVE;
  437.           signal->theData[0] = hostptr.i;
  438.           sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
  439.         }//if
  440.       }//if
  441.     }//for
  442.   }//if
  443.   for (tindex = 0; tindex < tnoOfNodes; tindex++) {
  444.     jam();
  445.     hostptr.i = cdata[tindex];
  446.     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  447.     /*------------------------------------------------------------*/
  448.     /*       LOOP THROUGH AND ABORT ALL SCANS THAT WHERE          */
  449.     /*       CONTROLLED BY THIS TC AND ACTIVE IN THE FAILED       */
  450.     /*       NODE'S LQH                                           */
  451.     /*------------------------------------------------------------*/
  452.     checkScanActiveInFailedLqh(signal, 0, hostptr.i);
  453.     checkWaitDropTabFailedLqh(signal, hostptr.i, 0); // nodeid, tableid
  454.   }//for
  455. }//Dbtc::execNODE_FAILREP()
  456. void Dbtc::checkScanActiveInFailedLqh(Signal* signal, 
  457.       Uint32 scanPtrI, 
  458.       Uint32 failedNodeId){
  459.   ScanRecordPtr scanptr;
  460.   for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
  461.     jam();
  462.     ptrAss(scanptr, scanRecord);
  463.     bool found = false;
  464.     if (scanptr.p->scanState != ScanRecord::IDLE){
  465.       jam();
  466.       ScanFragRecPtr ptr;
  467.       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  468.       
  469.       for(run.first(ptr); !ptr.isNull(); ){
  470. jam();
  471. ScanFragRecPtr curr = ptr;
  472. run.next(ptr);
  473. if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE && 
  474.     refToNode(curr.p->lqhBlockref) == failedNodeId){
  475.   jam();
  476.   
  477.   run.release(curr);
  478.   curr.p->scanFragState = ScanFragRec::COMPLETED;
  479.   curr.p->stopFragTimer();
  480.   found = true;
  481. }
  482.       }
  483.     }
  484.     if(found){
  485.       jam();
  486.       scanError(signal, scanptr, ZSCAN_LQH_ERROR);   
  487.     }
  488.     // Send CONTINUEB to continue later
  489.     signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
  490.     signal->theData[1] = scanptr.i + 1; // Check next scanptr
  491.     signal->theData[2] = failedNodeId;
  492.     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
  493.     return;
  494.   }//for
  495. }
  496. void
  497. Dbtc::checkScanFragList(Signal* signal,
  498. Uint32 failedNodeId,
  499. ScanRecord * scanP, 
  500. ScanFragList::Head & head){
  501.   
  502.   DEBUG("checkScanActiveInFailedLqh: scanFragError");
  503. }
  504. void Dbtc::execTAKE_OVERTCCONF(Signal* signal) 
  505. {
  506.   jamEntry();
  507.   tfailedNodeId = signal->theData[0];
  508.   hostptr.i = tfailedNodeId;
  509.   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  510.   switch (hostptr.p->takeOverStatus) {
  511.   case TOS_IDLE:
  512.     jam();
  513.     /*------------------------------------------------------------*/
  514.     /*       THIS MESSAGE ARRIVED EVEN BEFORE THE NODE_FAILREP    */
  515.     /*       MESSAGE. THIS IS POSSIBLE IN EXTREME SITUATIONS.     */
  516.     /*       WE SET THE STATE TO TAKE_OVER_COMPLETED AND WAIT     */
  517.     /*       FOR THE NODE_FAILREP MESSAGE.                        */
  518.     /*------------------------------------------------------------*/
  519.     hostptr.p->takeOverStatus = TOS_COMPLETED;
  520.     break;
  521.   case TOS_NODE_FAILED:
  522.   case TOS_ACTIVE:
  523.     jam();
  524.     /*------------------------------------------------------------*/
  525.     /*       WE ARE NOT MASTER AND THE TAKE OVER IS ACTIVE OR WE  */
  526.     /*       ARE MASTER AND THE TAKE OVER IS ACTIVE. IN BOTH      */
  527.     /*       WE SET THE STATE TO TAKE_OVER_COMPLETED.             */
  528.     /*------------------------------------------------------------*/
  529.     /*       RELEASE THE CURRENTLY UNUSED LQH CONNECTIONS. THE    */
  530.     /*       REMAINING WILL BE RELEASED WHEN THE TRANSACTION THAT */
  531.     /*       USED THEM IS COMPLETED.                              */
  532.     /*------------------------------------------------------------*/
  533.     hostptr.p->takeOverStatus = TOS_COMPLETED;
  534.     {
  535.       NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
  536.       nfRep->blockNo      = DBTC;
  537.       nfRep->nodeId       = cownNodeid;
  538.       nfRep->failedNodeId = hostptr.i;
  539.     }
  540.     sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal, 
  541.                NFCompleteRep::SignalLength, JBB);
  542.     break;
  543.   case TOS_COMPLETED:
  544.     jam();
  545.     /*------------------------------------------------------------*/
  546.     /*       WE HAVE ALREADY RECEIVED THE CONF SIGNAL. IT IS MOST */
  547.     /*       LIKELY SENT FROM A NEW MASTER WHICH WASN'T SURE IF   */
  548.     /*       THIS NODE HEARD THE CONF SIGNAL FROM THE OLD MASTER. */
  549.     /*       WE SIMPLY IGNORE THE MESSAGE.                        */
  550.     /*------------------------------------------------------------*/
  551.     /*empty*/;
  552.     break;
  553.   default:
  554.     jam();
  555.     systemErrorLab(signal);
  556.     return;
  557.   }//switch
  558. }//Dbtc::execTAKE_OVERTCCONF()
  559. void Dbtc::execTAKE_OVERTCREQ(Signal* signal) 
  560. {
  561.   jamEntry();
  562.   tfailedNodeId = signal->theData[0];
  563.   tcNodeFailptr.i = 0;
  564.   ptrAss(tcNodeFailptr, tcFailRecord);
  565.   if (tcNodeFailptr.p->failStatus != FS_IDLE) {
  566.     jam();
  567.     /*------------------------------------------------------------*/
  568.     /*       WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
  569.     /*------------------------------------------------------------*/
  570.     /*       IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL      */
  571.     /*       QUEUE THE TAKE OVER AND START IT AS SOON AS THE      */
  572.     /*       PREVIOUS ARE COMPLETED.                              */
  573.     /*------------------------------------------------------------*/
  574.     arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
  575.     tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = tfailedNodeId;
  576.     tcNodeFailptr.p->queueIndex = tcNodeFailptr.p->queueIndex + 1;
  577.     return;
  578.   }//if
  579.   startTakeOverLab(signal);
  580. }//Dbtc::execTAKE_OVERTCREQ()
  581. /*------------------------------------------------------------*/
  582. /*       INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS  */
  583. /*       AND OPERATIONS DURING TC TAKE OVER.                  */
  584. /*------------------------------------------------------------*/
  585. void Dbtc::startTakeOverLab(Signal* signal) 
  586. {
  587.   for (tindex = 0; tindex <= 511; tindex++) {
  588.     ctransidFailHash[tindex] = RNIL;
  589.   }//for
  590.   for (tindex = 0; tindex <= 1023; tindex++) {
  591.     ctcConnectFailHash[tindex] = RNIL;
  592.   }//for
  593.   tcNodeFailptr.p->failStatus = FS_LISTENING;
  594.   tcNodeFailptr.p->takeOverNode = tfailedNodeId;
  595.   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
  596.     jam();
  597.     ptrAss(hostptr, hostRecord);
  598.     if (hostptr.p->hostStatus == HS_ALIVE) {
  599.       jam();
  600.       tblockref = calcLqhBlockRef(hostptr.i);
  601.       hostptr.p->lqhTransStatus = LTS_ACTIVE;
  602.       signal->theData[0] = tcNodeFailptr.i;
  603.       signal->theData[1] = cownref;
  604.       signal->theData[2] = tfailedNodeId;
  605.       sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB);
  606.     }//if
  607.   }//for
  608. }//Dbtc::startTakeOverLab()
  609. /*------------------------------------------------------------*/
  610. /*       A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
  611. /*------------------------------------------------------------*/
  612. void Dbtc::execLQH_TRANSCONF(Signal* signal) 
  613. {
  614.   jamEntry();
  615.   LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
  616.   
  617.   tcNodeFailptr.i = lqhTransConf->tcRef;
  618.   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
  619.   tnodeid = lqhTransConf->lqhNodeId;
  620.   ttransStatus = (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
  621.   ttransid1    = lqhTransConf->transId1;
  622.   ttransid2    = lqhTransConf->transId2;
  623.   ttcOprec     = lqhTransConf->oldTcOpRec;
  624.   treqinfo     = lqhTransConf->requestInfo;
  625.   tgci         = lqhTransConf->gci;
  626.   cnodes[0]    = lqhTransConf->nextNodeId1;
  627.   cnodes[1]    = lqhTransConf->nextNodeId2;
  628.   cnodes[2]    = lqhTransConf->nextNodeId3;
  629.   const Uint32 ref = tapplRef = lqhTransConf->apiRef;
  630.   tapplOprec   = lqhTransConf->apiOpRec;
  631.   const Uint32 tableId = lqhTransConf->tableId;
  632.   if (ttransStatus == LqhTransConf::LastTransConf){
  633.     jam();
  634.     /*------------------------------------------------------------*/
  635.     /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
  636.     /*------------------------------------------------------------*/
  637.     nodeTakeOverCompletedLab(signal);
  638.     return;
  639.   }//if
  640.   if (ttransStatus == LqhTransConf::Marker){
  641.     jam();
  642.     treqinfo = 0;
  643.     LqhTransConf::setMarkerFlag(treqinfo, 1);
  644.   } else {
  645.     TableRecordPtr tabPtr;
  646.     tabPtr.i = tableId;
  647.     ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
  648.     switch((DictTabInfo::TableType)tabPtr.p->tableType){
  649.     case DictTabInfo::SystemTable:
  650.     case DictTabInfo::UserTable:
  651.       break;
  652.     default:
  653.       tapplRef = 0;
  654.       tapplOprec = 0;
  655.     }
  656.   }
  657.   findApiConnectFail(signal);
  658.   if(apiConnectptr.p->ndbapiBlockref == 0 && tapplRef != 0){
  659.     apiConnectptr.p->ndbapiBlockref = ref;
  660.     apiConnectptr.p->ndbapiConnect = tapplOprec;
  661.   }
  662.   
  663.   if (ttransStatus != LqhTransConf::Marker){
  664.     jam();
  665.     findTcConnectFail(signal);
  666.   }
  667. }//Dbtc::execLQH_TRANSCONF()
  668. /*------------------------------------------------------------*/
  669. /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
  670. /*------------------------------------------------------------*/
  671. void Dbtc::nodeTakeOverCompletedLab(Signal* signal) 
  672. {
  673.   Uint32 guard0;
  674.   hostptr.i = tnodeid;
  675.   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  676.   hostptr.p->lqhTransStatus = LTS_IDLE;
  677.   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
  678.     jam();
  679.     ptrAss(hostptr, hostRecord);
  680.     if (hostptr.p->hostStatus == HS_ALIVE) {
  681.       if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
  682.         jam();
  683. /*------------------------------------------------------------*/
  684. /*       NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE    */
  685. /*       TAKE OVER.                                           */
  686. /*------------------------------------------------------------*/
  687.         return;
  688.       }//if
  689.     }//if
  690.   }//for
  691.   /*------------------------------------------------------------*/
  692.   /*       ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
  693.   /*       OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE  */
  694.   /*       ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE       */
  695.   /*       TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN     */
  696.   /*       UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
  697.   /*       TO THE APPLICATION IF THAT IS STILL ALIVE.           */
  698.   /*------------------------------------------------------------*/
  699.   tcNodeFailptr.p->currentHashIndexTakeOver = 0;
  700.   tcNodeFailptr.p->completedTakeOver = 0;
  701.   tcNodeFailptr.p->failStatus = FS_COMPLETING;
  702.   guard0 = cnoParallelTakeOver - 1;
  703.   /*------------------------------------------------------------*/
  704.   /*       WE WILL COMPLETE THE TRANSACTIONS BY STARTING A      */
  705.   /*       NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL    */
  706.   /*       COMPLETE ONE TRANSACTION AT A TIME AND IN THAT       */
  707.   /*       TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
  708.   /*       WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
  709.   /*       IS COMPLETED.                                        */
  710.   /*------------------------------------------------------------*/
  711.   arrGuard(guard0, MAX_NDB_NODES);
  712.   for (tindex = 0; tindex <= guard0; tindex++) {
  713.     jam();
  714.     tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
  715.     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
  716.     signal->theData[1] = tcNodeFailptr.i;
  717.     signal->theData[2] = tindex;
  718.     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
  719.   }//for
  720. }//Dbtc::nodeTakeOverCompletedLab()
  721. /*------------------------------------------------------------*/
  722. /*       COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF    */
  723. /*       TRANSACTIONS TO COMPLETE.                            */
  724. /*------------------------------------------------------------*/
  725. void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd) 
  726. {
  727.   jam();
  728.   while (tcNodeFailptr.p->currentHashIndexTakeOver < 512){
  729.     jam();
  730.     apiConnectptr.i = 
  731.         ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
  732.     if (apiConnectptr.i != RNIL) {
  733.       jam();
  734.       /*------------------------------------------------------------*/
  735.       /*       WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE         */
  736.       /*       COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT   */
  737.       /*       NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS     */
  738.       /*       TRANSACTION.                                         */
  739.       /*------------------------------------------------------------*/
  740.       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  741.       ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] = 
  742.         apiConnectptr.p->nextApiConnect;
  743.       completeTransAtTakeOverDoOne(signal, TtakeOverInd);
  744.       // One transaction taken care of, return from this function
  745.       // and wait for the next CONTINUEB to continue processing
  746.       break;
  747.     } else {
  748.       if (tcNodeFailptr.p->currentHashIndexTakeOver < 511){
  749.         jam();      
  750.         tcNodeFailptr.p->currentHashIndexTakeOver++;
  751.       } else {
  752.         jam();
  753.         completeTransAtTakeOverDoLast(signal, TtakeOverInd); 
  754.         tcNodeFailptr.p->currentHashIndexTakeOver++;
  755.       }//if
  756.     }//if
  757.   }//while
  758. }//Dbtc::completeTransAtTakeOverLab()
  759. void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd) 
  760. {
  761.   Uint32 guard0;
  762.   /*------------------------------------------------------------*/
  763.   /*       THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS     */
  764.   /*       ACTIVITY IS COMPLETED.                               */
  765.   /*------------------------------------------------------------*/
  766.   arrGuard(TtakeOverInd, MAX_NDB_NODES);
  767.   if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
  768.     jam();
  769.     systemErrorLab(signal);
  770.     return;
  771.   }//if
  772.   tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
  773.   tcNodeFailptr.p->completedTakeOver++;
  774.   if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
  775.     jam();
  776.     /*------------------------------------------------------------*/
  777.     /*       WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
  778.     /*       TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL     */
  779.     /*       NODES THAT ARE ALIVE.                                */
  780.     /*------------------------------------------------------------*/
  781.     for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
  782.       jam();
  783.       ptrAss(hostptr, hostRecord);
  784.       if (hostptr.p->hostStatus == HS_ALIVE) {
  785.         jam();
  786.         tblockref = calcTcBlockRef(hostptr.i);
  787.         signal->theData[0] = tcNodeFailptr.p->takeOverNode;
  788.         sendSignal(tblockref, GSN_TAKE_OVERTCCONF, signal, 1, JBB);
  789.       }//if
  790.     }//for
  791.     if (tcNodeFailptr.p->queueIndex > 0) {
  792.       jam();
  793.       /*------------------------------------------------------------*/
  794.       /*       THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START  */
  795.       /*       THE TAKE OVER.                                       */
  796.       /*------------------------------------------------------------*/
  797.       tfailedNodeId = tcNodeFailptr.p->queueList[0];
  798.       guard0 = tcNodeFailptr.p->queueIndex - 1;
  799.       arrGuard(guard0 + 1, MAX_NDB_NODES);
  800.       for (tindex = 0; tindex <= guard0; tindex++) {
  801.         jam();
  802.         tcNodeFailptr.p->queueList[tindex] = 
  803.           tcNodeFailptr.p->queueList[tindex + 1];
  804.       }//for
  805.       tcNodeFailptr.p->queueIndex--;
  806.       startTakeOverLab(signal);
  807.       return;
  808.     } else {
  809.       jam();
  810.       tcNodeFailptr.p->failStatus = FS_IDLE;
  811.     }//if
  812.   }//if
  813.   return;
  814. }//Dbtc::completeTransAtTakeOverDoLast()
  815. void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
  816. {
  817.   apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
  818.   apiConnectptr.p->takeOverInd = TtakeOverInd;
  819.   switch (apiConnectptr.p->apiConnectstate) {
  820.   case CS_FAIL_COMMITTED:
  821.     jam();
  822.     /*------------------------------------------------------------*/
  823.     /*       ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
  824.     /*       HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT  */
  825.     /*       COMMITTED TO THE APPLICATION AND CONTINUE WITH THE   */
  826.     /*       COMPLETE PHASE.                                      */
  827.     /*------------------------------------------------------------*/
  828.     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
  829.     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
  830.     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  831.     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
  832.     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
  833.     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  834.     toCompleteHandlingLab(signal);
  835.     return;
  836.   case CS_FAIL_COMMITTING:
  837.     jam();
  838.     /*------------------------------------------------------------*/
  839.     /*       AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
  840.     /*       PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
  841.     /*       THEN CONTINUE AS AFTER COMMITTED.                    */
  842.     /*------------------------------------------------------------*/
  843.     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
  844.     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  845.     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
  846.     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
  847.     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  848.     toCommitHandlingLab(signal);
  849.     return;
  850.   case CS_FAIL_ABORTING:
  851.   case CS_FAIL_PREPARED:
  852.     jam();
  853.     /*------------------------------------------------------------*/
  854.     /*       WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
  855.     /*       STATE IN THIS VERSION. IN LATER VERSIONS WE WILL     */
  856.     /*       HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT  */
  857.     /*       TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
  858.     /*       HAVE HEARD FROM THE TRANSACTION COORDINATOR.         */
  859.     /*                                                            */
  860.     /*       IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE       */
  861.     /*       PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL  */
  862.     /*       LATER VERSIONS.                                      */
  863.     /*------------------------------------------------------------*/
  864.     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
  865.     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  866.     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
  867.     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
  868.     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  869.     toAbortHandlingLab(signal);
  870.     return;
  871.   case CS_FAIL_ABORTED:
  872.     jam();
  873.     sendTCKEY_FAILREF(signal, apiConnectptr.p);
  874.     
  875.     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
  876.     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
  877.     signal->theData[2] = apiConnectptr.p->takeOverInd;
  878.     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
  879.     releaseTakeOver(signal);
  880.     break;
  881.   case CS_FAIL_COMPLETED:
  882.     jam();
  883.     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
  884.     
  885.     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
  886.     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
  887.     signal->theData[2] = apiConnectptr.p->takeOverInd;
  888.     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
  889.     releaseApiConnectFail(signal);
  890.     break;
  891.   default:
  892.     jam();
  893.     systemErrorLab(signal);
  894.     return;
  895.   }//switch
  896. }//Dbtc::completeTransAtTakeOverDoOne()
  897. void 
  898. Dbtc::sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord * regApiPtr){
  899.   jam();
  900.   const Uint32 ref = regApiPtr->ndbapiBlockref;
  901.   if(ref != 0){
  902.     signal->theData[0] = regApiPtr->ndbapiConnect;
  903.     signal->theData[1] = regApiPtr->transid[0];
  904.     signal->theData[2] = regApiPtr->transid[1];
  905.   
  906.     sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
  907.   }
  908. }
  909. void 
  910. Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
  911.   jam();
  912.   TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
  913.   
  914.   const Uint32 ref = regApiPtr->ndbapiBlockref;
  915.   const Uint32 marker = regApiPtr->commitAckMarker;
  916.   if(ref != 0){
  917.     failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
  918.     failConf->transId1 = regApiPtr->transid[0];
  919.     failConf->transId2 = regApiPtr->transid[1];
  920.     
  921.     sendSignal(regApiPtr->ndbapiBlockref,
  922.        GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB);
  923.   }
  924.   regApiPtr->commitAckMarker = RNIL;
  925. }
  926. /*------------------------------------------------------------*/
  927. /*       THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A   */
  928. /*       NODE FAILURE BEFORE THE COMMIT DECISION.             */
  929. /*------------------------------------------------------------*/
  930. /*       ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID      */
  931. /*------------------------------------------------------------*/
  932. void Dbtc::execABORTCONF(Signal* signal) 
  933. {
  934.   UintR compare_transid1, compare_transid2;
  935.   jamEntry();
  936.   tcConnectptr.i = signal->theData[0];
  937.   tnodeid = signal->theData[2];
  938.   if (ERROR_INSERTED(8045)) {
  939.     CLEAR_ERROR_INSERT_VALUE;
  940.     sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
  941.     return;
  942.   }//if
  943.   if (tcConnectptr.i >= ctcConnectFilesize) {
  944.     errorReport(signal, 5);
  945.     return;
  946.   }//if
  947.   ptrAss(tcConnectptr, tcConnectRecord);
  948.   if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
  949.     warningReport(signal, 16);
  950.     return;
  951.   }//if
  952.   apiConnectptr.i = tcConnectptr.p->apiConnect;
  953.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  954.   if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
  955.     warningReport(signal, 17);
  956.     return;
  957.   }//if
  958.   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
  959.   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
  960.   compare_transid1 = compare_transid1 | compare_transid2;
  961.   if (compare_transid1 != 0) {
  962.     warningReport(signal, 18);
  963.     return;
  964.   }//if
  965.   arrGuard(apiConnectptr.p->currentReplicaNo, 4);
  966.   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
  967.       tnodeid) {
  968.     warningReport(signal, 19);
  969.     return;
  970.   }//if
  971.   tcurrentReplicaNo = (Uint8)Z8NIL;
  972.   tcConnectptr.p->tcConnectstate = OS_ABORTING;
  973.   toAbortHandlingLab(signal);
  974. }//Dbtc::execABORTCONF()
  975. void Dbtc::toAbortHandlingLab(Signal* signal) 
  976. {
  977.   do {
  978.     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
  979.       jam();
  980.       arrGuard(tcurrentReplicaNo, 4);
  981.       const LqhTransConf::OperationStatus stat = 
  982. (LqhTransConf::OperationStatus)
  983. tcConnectptr.p->failData[tcurrentReplicaNo];
  984.       switch(stat){
  985.       case LqhTransConf::InvalidStatus:
  986.       case LqhTransConf::Aborted:
  987.         jam();
  988.         /*empty*/;
  989.         break;
  990.       case LqhTransConf::Prepared:
  991.         jam();
  992.         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
  993.         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  994.         if (hostptr.p->hostStatus == HS_ALIVE) {
  995.           jam();
  996.           tblockref = calcLqhBlockRef(hostptr.i);
  997.           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
  998.           tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
  999.           apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
  1000.           apiConnectptr.p->timeOutCounter = 0;
  1001.           signal->theData[0] = tcConnectptr.i;
  1002.           signal->theData[1] = cownref;
  1003.           signal->theData[2] = apiConnectptr.p->transid[0];
  1004.           signal->theData[3] = apiConnectptr.p->transid[1];
  1005.           signal->theData[4] = apiConnectptr.p->tcBlockref;
  1006.           signal->theData[5] = tcConnectptr.p->tcOprec;
  1007.           sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
  1008.           return;
  1009.         }//if
  1010.         break;
  1011.       default:
  1012.         jam();
  1013.         systemErrorLab(signal);
  1014.         return;
  1015.       }//switch
  1016.     }//if
  1017.     if (apiConnectptr.p->currentReplicaNo > 0) {
  1018.       jam();
  1019.       /*------------------------------------------------------------*/
  1020.       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
  1021.       /*       ABORTED.                                             */
  1022.       /*------------------------------------------------------------*/
  1023.       apiConnectptr.p->currentReplicaNo--;
  1024.       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
  1025.     } else {
  1026.       /*------------------------------------------------------------*/
  1027.       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
  1028.       /*------------------------------------------------------------*/
  1029.       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
  1030.       if (tcConnectptr.i == RNIL) {
  1031. /*------------------------------------------------------------*/
  1032. /*       WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
  1033. /*       THE ABORT STATUS TO THE APPLICATION AND CONTINUE     */
  1034. /*       WITH THE NEXT TRANSACTION.                           */
  1035. /*------------------------------------------------------------*/
  1036.         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
  1037.           jam();
  1038.   sendTCKEY_FAILREF(signal, apiConnectptr.p);
  1039.   const Uint32 marker = apiConnectptr.p->commitAckMarker;
  1040.           if(marker != RNIL){
  1041.     jam();
  1042.             CommitAckMarkerPtr tmp;
  1043.             tmp.i = marker;
  1044.             tmp.p = m_commitAckMarkerHash.getPtr(tmp.i);
  1045.             
  1046.             m_commitAckMarkerHash.release(tmp);
  1047.             apiConnectptr.p->commitAckMarker = RNIL;
  1048.           }
  1049.           
  1050.   /*------------------------------------------------------------*/
  1051.   /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
  1052.   /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
  1053.   /*------------------------------------------------------------*/
  1054.           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
  1055.           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
  1056.           signal->theData[2] = apiConnectptr.p->takeOverInd;
  1057.           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
  1058.           releaseTakeOver(signal);
  1059.         } else {
  1060.           jam();
  1061.           releaseAbortResources(signal);
  1062.         }//if
  1063.         return;
  1064.       }//if
  1065.       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
  1066.       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1067.       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1068.       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1069.     }//if
  1070.   } while (1);
  1071. }//Dbtc::toAbortHandlingLab()
  1072. /*------------------------------------------------------------*/
  1073. /*       THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A  */
  1074. /*       NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE.      */
  1075. /*------------------------------------------------------------*/
  1076. /*       COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID     */
  1077. /*------------------------------------------------------------*/
  1078. void Dbtc::execCOMMITCONF(Signal* signal) 
  1079. {
  1080.   UintR compare_transid1, compare_transid2;
  1081.   jamEntry();
  1082.   tcConnectptr.i = signal->theData[0];
  1083.   tnodeid = signal->theData[1];
  1084.   if (ERROR_INSERTED(8046)) {
  1085.     CLEAR_ERROR_INSERT_VALUE;
  1086.     sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
  1087.     return;
  1088.   }//if
  1089.   if (tcConnectptr.i >= ctcConnectFilesize) {
  1090.     errorReport(signal, 4);
  1091.     return;
  1092.   }//if
  1093.   ptrAss(tcConnectptr, tcConnectRecord);
  1094.   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
  1095.     warningReport(signal, 8);
  1096.     return;
  1097.   }//if
  1098.   apiConnectptr.i = tcConnectptr.p->apiConnect;
  1099.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  1100.   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
  1101.     warningReport(signal, 9);
  1102.     return;
  1103.   }//if
  1104.   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
  1105.   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
  1106.   compare_transid1 = compare_transid1 | compare_transid2;
  1107.   if (compare_transid1 != 0) {
  1108.     warningReport(signal, 10);
  1109.     return;
  1110.   }//if
  1111.   arrGuard(apiConnectptr.p->currentReplicaNo, 4);
  1112.   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
  1113.       tnodeid) {
  1114.     warningReport(signal, 11);
  1115.     return;
  1116.   }//if
  1117.   if (ERROR_INSERTED(8026)) {
  1118.     jam();
  1119.     systemErrorLab(signal);
  1120.   }//if
  1121.   tcurrentReplicaNo = (Uint8)Z8NIL;
  1122.   tcConnectptr.p->tcConnectstate = OS_COMMITTED;
  1123.   toCommitHandlingLab(signal);
  1124. }//Dbtc::execCOMMITCONF()
  1125. void Dbtc::toCommitHandlingLab(Signal* signal) 
  1126. {
  1127.   do {
  1128.     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
  1129.       jam();
  1130.       arrGuard(tcurrentReplicaNo, 4);
  1131.       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
  1132.       case LqhTransConf::InvalidStatus:
  1133.         jam();
  1134.         /*empty*/;
  1135.         break;
  1136.       case LqhTransConf::Committed:
  1137.         jam();
  1138.         /*empty*/;
  1139.         break;
  1140.       case LqhTransConf::Prepared:
  1141.         jam();
  1142.         /*------------------------------------------------------------*/
  1143.         /*       THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR    */
  1144.         /*       COMMIT REQUEST FROM TC.                              */
  1145.         /*------------------------------------------------------------*/
  1146.         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
  1147.         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  1148.         if (hostptr.p->hostStatus == HS_ALIVE) {
  1149.           jam();
  1150.           tblockref = calcLqhBlockRef(hostptr.i);
  1151.           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
  1152.           apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
  1153.           apiConnectptr.p->timeOutCounter = 0;
  1154.           tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
  1155.           signal->theData[0] = tcConnectptr.i;
  1156.           signal->theData[1] = cownref;
  1157.           signal->theData[2] = apiConnectptr.p->globalcheckpointid;
  1158.           signal->theData[3] = apiConnectptr.p->transid[0];
  1159.           signal->theData[4] = apiConnectptr.p->transid[1];
  1160.           signal->theData[5] = apiConnectptr.p->tcBlockref;
  1161.           signal->theData[6] = tcConnectptr.p->tcOprec;
  1162.           sendSignal(tblockref, GSN_COMMITREQ, signal, 7, JBB);
  1163.           return;
  1164.         }//if
  1165.         break;
  1166.       default:
  1167.         jam();
  1168.         systemErrorLab(signal);
  1169.         return;
  1170.         break;
  1171.       }//switch
  1172.     }//if
  1173.     if (apiConnectptr.p->currentReplicaNo > 0) {
  1174.       jam();
  1175.       /*------------------------------------------------------------*/
  1176.       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
  1177.       /*       COMMITTED.                                           */
  1178.       /*------------------------------------------------------------*/
  1179.       apiConnectptr.p->currentReplicaNo--;
  1180.       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
  1181.     } else {
  1182.       /*------------------------------------------------------------*/
  1183.       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
  1184.       /*------------------------------------------------------------*/
  1185.       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
  1186.       if (tcConnectptr.i == RNIL) {
  1187. /*------------------------------------------------------------*/
  1188. /*       WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
  1189. /*       THE COMMIT STATUS TO THE APPLICATION AND CONTINUE    */
  1190. /*       WITH THE COMPLETE PHASE.                             */
  1191. /*------------------------------------------------------------*/
  1192.         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
  1193.           jam();
  1194.   sendTCKEY_FAILCONF(signal, apiConnectptr.p);
  1195. } else {
  1196.           jam();
  1197.           sendApiCommit(signal);
  1198.         }//if
  1199.         apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
  1200.         tcConnectptr.i = apiConnectptr.p->firstTcConnect;
  1201.         ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1202.         tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1203.         apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
  1204.         toCompleteHandlingLab(signal);
  1205.         return;
  1206.       }//if
  1207.       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
  1208.       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1209.       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1210.       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1211.     }//if
  1212.   } while (1);
  1213. }//Dbtc::toCommitHandlingLab()
  1214. /*------------------------------------------------------------*/
  1215. /*       COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE   */
  1216. /*       HAVE FAILED.                                         */
  1217. /*------------------------------------------------------------*/
  1218. /*       THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION   */
  1219. /*------------------------------------------------------------*/
  1220. void Dbtc::execCOMPLETECONF(Signal* signal) 
  1221. {
  1222.   UintR compare_transid1, compare_transid2;
  1223.   jamEntry();
  1224.   tcConnectptr.i = signal->theData[0];
  1225.   tnodeid = signal->theData[1];
  1226.   if (ERROR_INSERTED(8047)) {
  1227.     CLEAR_ERROR_INSERT_VALUE;
  1228.     sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
  1229.     return;
  1230.   }//if
  1231.   if (tcConnectptr.i >= ctcConnectFilesize) {
  1232.     errorReport(signal, 3);
  1233.     return;
  1234.   }//if
  1235.   ptrAss(tcConnectptr, tcConnectRecord);
  1236.   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
  1237.     warningReport(signal, 12);
  1238.     return;
  1239.   }//if
  1240.   apiConnectptr.i = tcConnectptr.p->apiConnect;
  1241.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  1242.   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
  1243.     warningReport(signal, 13);
  1244.     return;
  1245.   }//if
  1246.   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
  1247.   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
  1248.   compare_transid1 = compare_transid1 | compare_transid2;
  1249.   if (compare_transid1 != 0) {
  1250.     warningReport(signal, 14);
  1251.     return;
  1252.   }//if
  1253.   arrGuard(apiConnectptr.p->currentReplicaNo, 4);
  1254.   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
  1255.       tnodeid) {
  1256.     warningReport(signal, 15);
  1257.     return;
  1258.   }//if
  1259.   if (ERROR_INSERTED(8028)) {
  1260.     jam();
  1261.     systemErrorLab(signal);
  1262.   }//if
  1263.   tcConnectptr.p->tcConnectstate = OS_COMPLETED;
  1264.   tcurrentReplicaNo = (Uint8)Z8NIL;
  1265.   toCompleteHandlingLab(signal);
  1266. }//Dbtc::execCOMPLETECONF()
  1267. void Dbtc::toCompleteHandlingLab(Signal* signal) 
  1268. {
  1269.   do {
  1270.     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
  1271.       jam();
  1272.       arrGuard(tcurrentReplicaNo, 4);
  1273.       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
  1274.       case LqhTransConf::InvalidStatus:
  1275.         jam();
  1276.         /*empty*/;
  1277.         break;
  1278.       default:
  1279.         jam();
  1280.         /*------------------------------------------------------------*/
  1281.         /*       THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
  1282.         /*       IT MUST HAVE FAILED.                                 */
  1283.         /*------------------------------------------------------------*/
  1284.         /*------------------------------------------------------------*/
  1285.         /*       SEND COMPLETEREQ TO THE NEXT REPLICA.                */
  1286.         /*------------------------------------------------------------*/
  1287.         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
  1288.         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  1289.         if (hostptr.p->hostStatus == HS_ALIVE) {
  1290.           jam();
  1291.           tblockref = calcLqhBlockRef(hostptr.i);
  1292.           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
  1293.           tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
  1294.           apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
  1295.           apiConnectptr.p->timeOutCounter = 0;
  1296.           tcConnectptr.p->apiConnect = apiConnectptr.i;
  1297.           signal->theData[0] = tcConnectptr.i;
  1298.           signal->theData[1] = cownref;
  1299.           signal->theData[2] = apiConnectptr.p->transid[0];
  1300.           signal->theData[3] = apiConnectptr.p->transid[1];
  1301.           signal->theData[4] = apiConnectptr.p->tcBlockref;
  1302.           signal->theData[5] = tcConnectptr.p->tcOprec;
  1303.           sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
  1304.           return;
  1305.         }//if
  1306.         break;
  1307.       }//switch
  1308.     }//if
  1309.     if (apiConnectptr.p->currentReplicaNo != 0) {
  1310.       jam();
  1311.       /*------------------------------------------------------------*/
  1312.       /*       THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE  */
  1313.       /*       NEED TO CONTINUE WITH THOSE REPLICAS.                */
  1314.       /*------------------------------------------------------------*/
  1315.       apiConnectptr.p->currentReplicaNo--;
  1316.       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
  1317.     } else {
  1318.       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
  1319.       if (tcConnectptr.i == RNIL) {
  1320.         /*------------------------------------------------------------*/
  1321.         /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
  1322.         /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
  1323.         /*------------------------------------------------------------*/
  1324.         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
  1325.           jam();
  1326.           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
  1327.           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
  1328.           signal->theData[2] = apiConnectptr.p->takeOverInd;
  1329.           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
  1330.           releaseTakeOver(signal);
  1331.         } else {
  1332.           jam();
  1333.           releaseTransResources(signal);
  1334.         }//if
  1335.         return;
  1336.       }//if
  1337.       /*------------------------------------------------------------*/
  1338.       /*       WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
  1339.       /*       COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
  1340.       /*       FIRST REPLICA SINCE IT IS THE COMPLETE PHASE.        */
  1341.       /*------------------------------------------------------------*/
  1342.       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
  1343.       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1344.       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1345.       apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
  1346.     }//if
  1347.   } while (1);
  1348. }//Dbtc::toCompleteHandlingLab()
  1349. /*------------------------------------------------------------*/
  1350. /*                                                            */
  1351. /*       FIND THE API CONNECT RECORD FOR THIS TRANSACTION     */
  1352. /*       DURING TAKE OVER FROM A FAILED TC. IF NONE EXISTS    */
  1353. /*       YET THEN SEIZE A NEW API CONNECT RECORD AND LINK IT  */
  1354. /*       INTO THE HASH TABLE.                                 */
  1355. /*------------------------------------------------------------*/
  1356. void Dbtc::findApiConnectFail(Signal* signal) 
  1357. {
  1358.   ApiConnectRecordPtr fafPrevApiConnectptr;
  1359.   ApiConnectRecordPtr fafNextApiConnectptr;
  1360.   UintR tfafHashNumber;
  1361.   tfafHashNumber = ttransid1 & 511;
  1362.   fafPrevApiConnectptr.i = RNIL;
  1363.   ptrNull(fafPrevApiConnectptr);
  1364.   arrGuard(tfafHashNumber, 512);
  1365.   fafNextApiConnectptr.i = ctransidFailHash[tfafHashNumber];
  1366.   ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
  1367. FAF_LOOP:
  1368.   jam();
  1369.   if (fafNextApiConnectptr.i == RNIL) {
  1370.     jam();
  1371.     if (cfirstfreeApiConnectFail == RNIL) {
  1372.       jam();
  1373.       systemErrorLab(signal);
  1374.       return;
  1375.     }//if
  1376.     seizeApiConnectFail(signal);
  1377.     if (fafPrevApiConnectptr.i == RNIL) {
  1378.       jam();
  1379.       ctransidFailHash[tfafHashNumber] = apiConnectptr.i;
  1380.     } else {
  1381.       jam();
  1382.       ptrGuard(fafPrevApiConnectptr);
  1383.       fafPrevApiConnectptr.p->nextApiConnect = apiConnectptr.i;
  1384.     }//if
  1385.     apiConnectptr.p->nextApiConnect = RNIL;
  1386.     initApiConnectFail(signal);
  1387.   } else {
  1388.     jam();
  1389.     fafPrevApiConnectptr.i = fafNextApiConnectptr.i;
  1390.     fafPrevApiConnectptr.p = fafNextApiConnectptr.p;
  1391.     apiConnectptr.i = fafNextApiConnectptr.i;
  1392.     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  1393.     fafNextApiConnectptr.i = apiConnectptr.p->nextApiConnect;
  1394.     ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
  1395.     if ((apiConnectptr.p->transid[1] != ttransid2) ||
  1396.         (apiConnectptr.p->transid[0] != ttransid1)) {
  1397.       goto FAF_LOOP;
  1398.     }//if
  1399.     updateApiStateFail(signal);
  1400.   }//if
  1401. }//Dbtc::findApiConnectFail()
  1402. /*----------------------------------------------------------*/
  1403. /*       FIND THE TC CONNECT AND IF NOT FOUND ALLOCATE A NEW  */
  1404. /*----------------------------------------------------------*/
  1405. void Dbtc::findTcConnectFail(Signal* signal) 
  1406. {
  1407.   UintR tftfHashNumber;
  1408.   tftfHashNumber = (ttransid1 ^ ttcOprec) & 1023;
  1409.   tcConnectptr.i = ctcConnectFailHash[tftfHashNumber];
  1410.   do {
  1411.     if (tcConnectptr.i == RNIL) {
  1412.       jam();
  1413.       if (cfirstfreeTcConnectFail == RNIL) {
  1414.         jam();
  1415.         systemErrorLab(signal);
  1416.         return;
  1417.       }//if
  1418.       seizeTcConnectFail(signal);
  1419.       linkTcInConnectionlist(signal);
  1420.       tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[tftfHashNumber];
  1421.       ctcConnectFailHash[tftfHashNumber] = tcConnectptr.i;
  1422.       initTcConnectFail(signal);
  1423.       return;
  1424.     } else {
  1425.       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1426.       if (tcConnectptr.p->tcOprec != ttcOprec) {
  1427.         jam();  /* FRAGMENTID = TC_OPREC HERE, LOOP ANOTHER TURN */
  1428.         tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
  1429.       } else {
  1430.         updateTcStateFail(signal);
  1431.         return;
  1432.       }//if
  1433.     }//if
  1434.   } while (1);
  1435. }//Dbtc::findTcConnectFail()
  1436. /*----------------------------------------------------------*/
  1437. /*       INITIALISE AN API CONNECT FAIL RECORD              */
  1438. /*----------------------------------------------------------*/
  1439. void Dbtc::initApiConnectFail(Signal* signal) 
  1440. {
  1441.   apiConnectptr.p->transid[0] = ttransid1;
  1442.   apiConnectptr.p->transid[1] = ttransid2;
  1443.   apiConnectptr.p->firstTcConnect = RNIL;
  1444.   apiConnectptr.p->currSavePointId = 0;
  1445.   apiConnectptr.p->lastTcConnect = RNIL;
  1446.   tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
  1447.   apiConnectptr.p->tcBlockref = tblockref;
  1448.   apiConnectptr.p->ndbapiBlockref = 0;
  1449.   apiConnectptr.p->ndbapiConnect = 0;
  1450.   apiConnectptr.p->buddyPtr = RNIL;
  1451.   setApiConTimer(apiConnectptr.i, 0, __LINE__);
  1452.   switch(ttransStatus){
  1453.   case LqhTransConf::Committed:
  1454.     jam();
  1455.     apiConnectptr.p->globalcheckpointid = tgci;
  1456.     apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
  1457.     break;
  1458.   case LqhTransConf::Prepared:
  1459.     jam();
  1460.     apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
  1461.     break;
  1462.   case LqhTransConf::Aborted:
  1463.     jam();
  1464.     apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
  1465.     break;
  1466.   case LqhTransConf::Marker:
  1467.     jam();
  1468.     apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
  1469.     break;
  1470.   default:
  1471.     jam();
  1472.     systemErrorLab(signal);
  1473.   }//if
  1474.   apiConnectptr.p->commitAckMarker = RNIL;
  1475.   if(LqhTransConf::getMarkerFlag(treqinfo)){
  1476.     jam();
  1477.     CommitAckMarkerPtr tmp;
  1478.     m_commitAckMarkerHash.seize(tmp);
  1479.     
  1480.     ndbrequire(tmp.i != RNIL);
  1481.     
  1482.     apiConnectptr.p->commitAckMarker = tmp.i;
  1483.     tmp.p->transid1      = ttransid1;
  1484.     tmp.p->transid2      = ttransid2;
  1485.     tmp.p->apiNodeId     = refToNode(tapplRef);
  1486.     tmp.p->noOfLqhs      = 1;
  1487.     tmp.p->lqhNodeId[0]  = tnodeid;
  1488.     tmp.p->apiConnectPtr = apiConnectptr.i;
  1489.     m_commitAckMarkerHash.add(tmp);
  1490.   } 
  1491. }//Dbtc::initApiConnectFail()
  1492. /*------------------------------------------------------------*/
  1493. /*       INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
  1494. /*       THE TC CONNECT RECORD.                               */
  1495. /*------------------------------------------------------------*/
  1496. void Dbtc::initTcConnectFail(Signal* signal) 
  1497. {
  1498.   tcConnectptr.p->apiConnect = apiConnectptr.i;
  1499.   tcConnectptr.p->tcOprec = ttcOprec;
  1500.   Uint32 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
  1501.   for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
  1502.     tcConnectptr.p->failData[i] = LqhTransConf::InvalidStatus;
  1503.   }//for
  1504.   tcConnectptr.p->tcNodedata[treplicaNo] = tnodeid;
  1505.   tcConnectptr.p->failData[treplicaNo] = ttransStatus;
  1506.   tcConnectptr.p->lastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
  1507.   tcConnectptr.p->dirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
  1508.   
  1509. }//Dbtc::initTcConnectFail()
  1510. /*----------------------------------------------------------*/
  1511. /*       INITIALISE TC NODE FAIL RECORD.                    */
  1512. /*----------------------------------------------------------*/
  1513. void Dbtc::initTcFail(Signal* signal) 
  1514. {
  1515.   tcNodeFailptr.i = 0;
  1516.   ptrAss(tcNodeFailptr, tcFailRecord);
  1517.   tcNodeFailptr.p->queueIndex = 0;
  1518.   tcNodeFailptr.p->failStatus = FS_IDLE;
  1519. }//Dbtc::initTcFail()
  1520. /*----------------------------------------------------------*/
  1521. /*               RELEASE_TAKE_OVER                          */
  1522. /*----------------------------------------------------------*/
  1523. void Dbtc::releaseTakeOver(Signal* signal) 
  1524. {
  1525.   TcConnectRecordPtr rtoNextTcConnectptr;
  1526.   rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
  1527.   do {
  1528.     jam();
  1529.     tcConnectptr.i = rtoNextTcConnectptr.i;
  1530.     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1531.     rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
  1532.     releaseTcConnectFail(signal);
  1533.   } while (rtoNextTcConnectptr.i != RNIL);
  1534.   releaseApiConnectFail(signal);
  1535. }//Dbtc::releaseTakeOver()
  1536. /*---------------------------------------------------------------------------*/
  1537. /*                               SETUP_FAIL_DATA                             */
  1538. /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE      */
  1539. /* FAILURE SITUATIONS.                                                       */
  1540. /*---------------------------------------------------------------------------*/
  1541. void Dbtc::setupFailData(Signal* signal) 
  1542. {
  1543.   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
  1544.   do {
  1545.     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1546.     switch (tcConnectptr.p->tcConnectstate) {
  1547.     case OS_PREPARED:
  1548.     case OS_COMMITTING:
  1549.       jam();
  1550.       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
  1551. jam();
  1552. /*-------------------------------------------------------------------
  1553.  * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH. 
  1554.  * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR 
  1555.  * COMMIT/ABORT DECISION.                 
  1556.  *------------------------------------------------------------------*/
  1557. arrGuard(tindex, 4);
  1558. tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
  1559.       }//for
  1560.       break;
  1561.     case OS_COMMITTED:
  1562.     case OS_COMPLETING:
  1563.       jam();
  1564.       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
  1565. jam();
  1566. /*-------------------------------------------------------------------
  1567.  * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH. 
  1568.  * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR 
  1569.  * COMPLETE MESSAGE.                     
  1570.  *------------------------------------------------------------------*/
  1571. arrGuard(tindex, 4);
  1572. tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
  1573.       }//for
  1574.       break;
  1575.     case OS_COMPLETED:
  1576.       jam();
  1577.       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
  1578. jam();
  1579. /*-------------------------------------------------------------------
  1580.  * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH. 
  1581.  * IN THIS CASE ALL LQH'S ARE COMPLETED.
  1582.  *-------------------------------------------------------------------*/
  1583. arrGuard(tindex, 4);
  1584. tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
  1585.       }//for
  1586.       break;
  1587.     default:
  1588.       jam();
  1589.       sendSystemError(signal);
  1590.       break;
  1591.     }//switch
  1592.     if (tabortInd != ZCOMMIT_SETUP) {
  1593.       jam();
  1594.       for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
  1595.         hostptr.i = tcConnectptr.p->tcNodedata[Ti];
  1596.         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
  1597.         if (hostptr.p->hostStatus != HS_ALIVE) {
  1598.           jam();
  1599.   /*-----------------------------------------------------------------
  1600.    * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION. 
  1601.    *-----------------------------------------------------------------*/
  1602.           tabortInd = ZTRUE;
  1603.         }//if
  1604.       }//for
  1605.     }//if
  1606.     tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
  1607.     tcConnectptr.p->tcOprec = tcConnectptr.i;
  1608.     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
  1609.   } while (tcConnectptr.i != RNIL);
  1610.   apiConnectptr.p->tcBlockref = cownref;
  1611.   apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
  1612.   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
  1613.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  1614.   apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1615.   tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
  1616. }//Dbtc::setupFailData()
  1617. /*----------------------------------------------------------*/
  1618. /*       UPDATE THE STATE OF THE API CONNECT FOR THIS PART.   */
  1619. /*----------------------------------------------------------*/
  1620. void Dbtc::updateApiStateFail(Signal* signal) 
  1621. {
  1622.   if(LqhTransConf::getMarkerFlag(treqinfo)){
  1623.     jam();
  1624.     const Uint32 marker = apiConnectptr.p->commitAckMarker;
  1625.     if(marker == RNIL){
  1626.       jam();
  1627.       CommitAckMarkerPtr tmp;
  1628.       m_commitAckMarkerHash.seize(tmp);
  1629.       ndbrequire(tmp.i != RNIL);
  1630.       
  1631.       apiConnectptr.p->commitAckMarker = tmp.i;
  1632.       tmp.p->transid1      = ttransid1;
  1633.       tmp.p->transid2      = ttransid2;
  1634.       tmp.p->apiNodeId     = refToNode(tapplRef);
  1635.       tmp.p->noOfLqhs      = 1;
  1636.       tmp.p->lqhNodeId[0]  = tnodeid;
  1637.       tmp.p->apiConnectPtr = apiConnectptr.i;
  1638.       m_commitAckMarkerHash.add(tmp);
  1639.     } else {
  1640.       jam();
  1641.       
  1642.       CommitAckMarkerPtr tmp;
  1643.       tmp.i = marker;
  1644.       tmp.p = m_commitAckMarkerHash.getPtr(marker);
  1645.       const Uint32 noOfLqhs = tmp.p->noOfLqhs;
  1646.       ndbrequire(noOfLqhs < MAX_REPLICAS);
  1647.       tmp.p->lqhNodeId[noOfLqhs] = tnodeid;
  1648.       tmp.p->noOfLqhs = (noOfLqhs + 1);
  1649.     }
  1650.   }
  1651.   switch (ttransStatus) {
  1652.   case LqhTransConf::Committed:
  1653.     jam();
  1654.     switch (apiConnectptr.p->apiConnectstate) {
  1655.     case CS_FAIL_COMMITTING:
  1656.     case CS_FAIL_COMMITTED:
  1657.       jam();
  1658.       ndbrequire(tgci == apiConnectptr.p->globalcheckpointid);
  1659.       break;
  1660.     case CS_FAIL_PREPARED:
  1661.       jam();
  1662.       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
  1663.       apiConnectptr.p->globalcheckpointid = tgci;
  1664.       break;
  1665.     case CS_FAIL_COMPLETED:
  1666.       jam();
  1667.       apiConnectptr.p->globalcheckpointid = tgci;
  1668.       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
  1669.       break;
  1670.     default:
  1671.       jam();
  1672.       systemErrorLab(signal);
  1673.       break;
  1674.     }//switch
  1675.     break;
  1676.   case LqhTransConf::Prepared:
  1677.     jam();
  1678.     switch (apiConnectptr.p->apiConnectstate) {
  1679.     case CS_FAIL_COMMITTED:
  1680.       jam();
  1681.       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
  1682.       break;
  1683.     case CS_FAIL_ABORTED:
  1684.       jam();
  1685.       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
  1686.       break;
  1687.     case CS_FAIL_COMMITTING:
  1688.     case CS_FAIL_PREPARED:
  1689.     case CS_FAIL_ABORTING:
  1690.       jam();
  1691.       /*empty*/;
  1692.       break;
  1693.     default:
  1694.       jam();
  1695.       systemErrorLab(signal);
  1696.       break;
  1697.     }//switch
  1698.     break;
  1699.   case LqhTransConf::Aborted:
  1700.     jam();
  1701.     switch (apiConnectptr.p->apiConnectstate) {
  1702.     case CS_FAIL_COMMITTING:
  1703.     case CS_FAIL_COMMITTED:
  1704.       jam();
  1705.       systemErrorLab(signal);
  1706.       break;
  1707.     case CS_FAIL_PREPARED:
  1708.       jam();
  1709.       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
  1710.       break;
  1711.     case CS_FAIL_ABORTING:
  1712.     case CS_FAIL_ABORTED:
  1713.       jam();
  1714.       /*empty*/;
  1715.       break;
  1716.     default:
  1717.       jam();
  1718.       systemErrorLab(signal);
  1719.       break;
  1720.     }//switch
  1721.     break;
  1722.   case LqhTransConf::Marker:
  1723.     jam();
  1724.     break;
  1725.   default:
  1726.     jam();
  1727.     systemErrorLab(signal);
  1728.     break;
  1729.   }//switch
  1730. }//Dbtc::updateApiStateFail()
  1731. /*------------------------------------------------------------*/
  1732. /*               UPDATE_TC_STATE_FAIL                         */
  1733. /*                                                            */
  1734. /*       WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
  1735. /*       WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY      */
  1736. /*       BETWEEN THE DIFFERENT REPLICAS.                      */
  1737. /*------------------------------------------------------------*/
  1738. void Dbtc::updateTcStateFail(Signal* signal) 
  1739. {
  1740.   const Uint8 treplicaNo     = LqhTransConf::getReplicaNo(treqinfo);
  1741.   const Uint8 tlastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
  1742.   const Uint8 tdirtyOp       = LqhTransConf::getDirtyFlag(treqinfo);
  1743.   TcConnectRecord * regTcPtr = tcConnectptr.p;
  1744.   
  1745.   ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
  1746.   ndbrequire(regTcPtr->failData[treplicaNo] == LqhTransConf::InvalidStatus);
  1747.   ndbrequire(regTcPtr->lastReplicaNo == tlastReplicaNo);
  1748.   ndbrequire(regTcPtr->dirtyOp == tdirtyOp);
  1749.   
  1750.   regTcPtr->tcNodedata[treplicaNo] = tnodeid;
  1751.   regTcPtr->failData[treplicaNo] = ttransStatus;  
  1752. }//Dbtc::updateTcStateFail()
  1753. void Dbtc::execTCGETOPSIZEREQ(Signal* signal) 
  1754. {
  1755.   jamEntry();
  1756.   CRASH_INSERTION(8000);
  1757.   UintR Tuserpointer = signal->theData[0];         /* DBDIH POINTER         */
  1758.   BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
  1759.   signal->theData[0] = Tuserpointer;
  1760.   signal->theData[1] = coperationsize;
  1761.   sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
  1762. }//Dbtc::execTCGETOPSIZEREQ()
  1763. void Dbtc::execTC_CLOPSIZEREQ(Signal* signal) 
  1764. {
  1765.   jamEntry();
  1766.   CRASH_INSERTION(8001);
  1767.   tuserpointer = signal->theData[0];
  1768.   tusersblkref = signal->theData[1];
  1769.                                             /* DBDIH BLOCK REFERENCE         */
  1770.   coperationsize = 0;
  1771.   signal->theData[0] = tuserpointer;
  1772.   sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
  1773. }//Dbtc::execTC_CLOPSIZEREQ()
  1774. /* ######################################################################### */
  1775. /* #######                        ERROR MODULE                       ####### */
  1776. /* ######################################################################### */
  1777. void Dbtc::tabStateErrorLab(Signal* signal) 
  1778. {
  1779.   terrorCode = ZSTATE_ERROR;
  1780.   releaseAtErrorLab(signal);
  1781. }//Dbtc::tabStateErrorLab()
  1782. void Dbtc::wrongSchemaVersionErrorLab(Signal* signal) 
  1783. {
  1784.   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
  1785.   TableRecordPtr tabPtr;
  1786.   tabPtr.i = tcKeyReq->tableId;
  1787.   const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
  1788.   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
  1789.   terrorCode = tabPtr.p->getErrorCode(schemVer);
  1790.   
  1791.   abortErrorLab(signal);
  1792. }//Dbtc::wrongSchemaVersionErrorLab()
  1793. void Dbtc::noFreeConnectionErrorLab(Signal* signal) 
  1794. {
  1795.   terrorCode = ZNO_FREE_TC_CONNECTION;
  1796.   abortErrorLab(signal);        /* RECORD. OTHERWISE GOTO ERRORHANDLING  */
  1797. }//Dbtc::noFreeConnectionErrorLab()
  1798. void Dbtc::aiErrorLab(Signal* signal) 
  1799. {
  1800.   terrorCode = ZLENGTH_ERROR;
  1801.   abortErrorLab(signal);
  1802. }//Dbtc::aiErrorLab()
  1803. void Dbtc::seizeAttrbuferrorLab(Signal* signal) 
  1804. {
  1805.   terrorCode = ZGET_ATTRBUF_ERROR;
  1806.   abortErrorLab(signal);
  1807. }//Dbtc::seizeAttrbuferrorLab()
  1808. void Dbtc::seizeDatabuferrorLab(Signal* signal) 
  1809. {
  1810.   terrorCode = ZGET_DATAREC_ERROR;
  1811.   releaseAtErrorLab(signal);
  1812. }//Dbtc::seizeDatabuferrorLab()
  1813. void Dbtc::releaseAtErrorLab(Signal* signal) 
  1814. {
  1815.   ptrGuard(tcConnectptr);
  1816.   tcConnectptr.p->tcConnectstate = OS_ABORTING;
  1817.   /*-------------------------------------------------------------------------*
  1818.    * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A 
  1819.    * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE. 
  1820.    * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH 
  1821.    * TO HANDLE THIS PROBLEM.      
  1822.    * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
  1823.    * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING 
  1824.    * ANY SIGNALS.                              
  1825.    *-------------------------------------------------------------------------*/
  1826.   tcConnectptr.p->noOfNodes = 0;
  1827.   abortErrorLab(signal);
  1828. }//Dbtc::releaseAtErrorLab()
  1829. void Dbtc::warningHandlerLab(Signal* signal) 
  1830. {
  1831.   ndbassert(false);
  1832. }//Dbtc::warningHandlerLab()
  1833. void Dbtc::systemErrorLab(Signal* signal) 
  1834. {
  1835.   progError(0, 0);
  1836. }//Dbtc::systemErrorLab()
  1837. /* ######################################################################### *
  1838.  * #######                        SCAN MODULE                        ####### *
  1839.  * ######################################################################### *
  1840.   The application orders a scan of a table.  We divide the scan into a scan on
  1841.   each fragment.  The scan uses the primary replicas since the scan might be   
  1842.   used for an update in a separate transaction. 
  1843.   Scans are always done as a separate transaction.  Locks from the scan
  1844.   can be overtaken by another transaction.  Scans can never lock the entire
  1845.   table.  Locks are released immediately after the read has been verified 
  1846.   by the application. There is not even an option to leave the locks. 
  1847.   The reason is that this would hurt real-time behaviour too much.
  1848.   -#  The first step in handling a scan of a table is to receive all signals
  1849.       defining the scan. If failures occur during this step we release all 
  1850.       resource and reply with SCAN_TABREF providing the error code. 
  1851.       If system load is too high, the request will not be allowed.   
  1852.    
  1853.   -#  The second step retrieves the number of fragments that exist in the 
  1854.       table. It also ensures that the table actually exist.  After this,
  1855.       the scan is ready to be parallelised.  The idea is that the receiving 
  1856.       process (hereafter called delivery process) will start up a number 
  1857.       of scan processes.  Each of these scan processes will 
  1858.       independently scan one fragment at a time.  The delivery
  1859.       process object is the scan record and the scan process object is 
  1860.       the scan fragment record plus the scan operation record.
  1861.    
  1862.   -#  The third step is thus performed in parallel. In the third step each 
  1863.       scan process retrieves the primary replica of the fragment it will 
  1864.       scan.  Then it starts the scan as soon as the load on that node permits. 
  1865.    
  1866.   The LQH returns either when it retrieved the maximum number of tuples or 
  1867.   when it has retrived at least one tuple and is hindered by a lock to
  1868.   retrieve the next tuple.  This is to ensure that a scan process never 
  1869.   can be involved in a deadlock situation.   
  1870.    
  1871.   When the scan process receives a number of tuples to report to the 
  1872.   application it checks the state of the delivery process. Only one delivery 
  1873.   at a time is handled by the application. Thus if the delivery process 
  1874.   has already sent a number of tuples to the application this set of tuples 
  1875.   are queued.
  1876.    
  1877.   When the application requests the next set of tuples it is immediately
  1878.   delivered if any are queued, otherwise it waits for the next scan
  1879.   process that is ready to deliver.  
  1880.   ERROR HANDLING
  1881.    
  1882.   As already mentioned it is rather easy to handle errors before the scan 
  1883.   processes have started.  In this case it is enough to release the resources 
  1884.   and send SCAN_TAB_REF.
  1885.    
  1886.   If an error occurs in any of the scan processes then we have to stop all 
  1887.   scan processes. We do however only stop the delivery process and ask 
  1888.   the api to order us to close the scan.  The reason is that we can easily 
  1889.   enter into difficult timing problems since the application and this 
  1890.   block is out of synch we will thus always start by report the error to
  1891.   the application and wait for a close request. This error report uses the 
  1892.   SCAN_TABREF signal with a special error code that the api must check for.   
  1893.    
  1894.    
  1895.   CLOSING AN ACTIVE SCAN
  1896.    
  1897.   The application can close a scan for several reasons before it is completed.
  1898.   One reason was mentioned above where an error in a scan process led to a  
  1899.   request to close the scan. Another reason could simply be that the 
  1900.   application found what it looked for and is thus not interested in the 
  1901.   rest of the scan.  
  1902.   IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API. 
  1903.    
  1904.   When a close scan request is received, all scan processes are stopped and all
  1905.   resources belonging to those scan processes are released. Stopping the scan  
  1906.   processes most often includes communication with an LQH where the local scan 
  1907.   is controlled. Finally all resources belonging to the scan is released and 
  1908.   the SCAN_TABCONF is sent with an indication of that the scan is closed.   
  1909.    
  1910.    
  1911.   CLOSING A COMPLETED SCAN  
  1912.    
  1913.   When all scan processes are completed then a report is sent to the 
  1914.   application which indicates that no more tuples can be fetched. 
  1915.   The application will send a close scan and the same action as when 
  1916.   closing an active scan is performed. 
  1917.   In this case it will of course not find any active scan processes. 
  1918.   It will even find all scan processes already released.
  1919.    
  1920.   The reason for requiring the api to close the scan is the same as above. 
  1921.   It is to avoid any timing problems due to that the api and this block 
  1922.   is out of synch.
  1923.    
  1924.   * ######################################################################## */
  1925. void Dbtc::execSCAN_TABREQ(Signal* signal) 
  1926. {
  1927.   const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
  1928.   const Uint32 reqinfo = scanTabReq->requestInfo;
  1929.   const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
  1930.   const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
  1931.   const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
  1932.   const Uint32 transid1 = scanTabReq->transId1;
  1933.   const Uint32 transid2 = scanTabReq->transId2;
  1934.   const Uint32 tmpXX = scanTabReq->buddyConPtr;
  1935.   const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
  1936.   Uint32 currSavePointId = 0;
  1937.   
  1938.   Uint32 scanConcurrency = scanTabReq->getParallelism(reqinfo);
  1939.   Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(reqinfo);
  1940.   Uint32 scanParallel = scanConcurrency;
  1941.   Uint32 errCode;
  1942.   ScanRecordPtr scanptr;
  1943.   jamEntry();
  1944.   SegmentedSectionPtr api_op_ptr;
  1945.   signal->getSection(api_op_ptr, 0);
  1946.   copy(&cdata[0], api_op_ptr);
  1947.   releaseSections(signal);
  1948.   apiConnectptr.i = scanTabReq->apiConnectPtr;
  1949.   tabptr.i = scanTabReq->tableId;
  1950.   if (apiConnectptr.i >= capiConnectFilesize)
  1951.   {
  1952.     jam();
  1953.     warningHandlerLab(signal);
  1954.     return;
  1955.   }//if
  1956.   ptrAss(apiConnectptr, apiConnectRecord);
  1957.   ApiConnectRecord * transP = apiConnectptr.p;
  1958.   if (transP->apiConnectstate != CS_CONNECTED) {
  1959.     jam();
  1960.     // could be left over from TCKEYREQ rollback
  1961.     if (transP->apiConnectstate == CS_ABORTING &&
  1962. transP->abortState == AS_IDLE) {
  1963.       jam();
  1964.     } else if(transP->apiConnectstate == CS_STARTED && 
  1965.       transP->firstTcConnect == RNIL){
  1966.       jam();
  1967.       // left over from simple/dirty read
  1968.     } else {
  1969.       jam();
  1970.       errCode = ZSTATE_ERROR;
  1971.       goto SCAN_TAB_error_no_state_change;
  1972.     }
  1973.   }
  1974.   if(tabptr.i >= ctabrecFilesize)
  1975.   {
  1976.     errCode = ZUNKNOWN_TABLE_ERROR;
  1977.     goto SCAN_TAB_error;
  1978.   }
  1979.   ptrAss(tabptr, tableRecord);
  1980.   if ((aiLength == 0) ||
  1981.       (!tabptr.p->checkTable(schemaVersion)) ||
  1982.       (scanConcurrency == 0) ||
  1983.       (cfirstfreeTcConnect == RNIL) ||
  1984.       (cfirstfreeScanrec == RNIL)) {
  1985.     goto SCAN_error_check;
  1986.   }
  1987.   if (buddyPtr != RNIL) {
  1988.     jam();
  1989.     ApiConnectRecordPtr buddyApiPtr;
  1990.     buddyApiPtr.i = buddyPtr;
  1991.     ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
  1992.     if ((transid1 == buddyApiPtr.p->transid[0]) &&
  1993. (transid2 == buddyApiPtr.p->transid[1])) {
  1994.       jam();
  1995.       
  1996.       if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
  1997. // transaction has been aborted
  1998. jam();
  1999. errCode = buddyApiPtr.p->returncode;
  2000. goto SCAN_TAB_error;
  2001.       }//if
  2002.       currSavePointId = buddyApiPtr.p->currSavePointId;
  2003.       buddyApiPtr.p->currSavePointId++;
  2004.     }
  2005.   }
  2006.   
  2007.   seizeTcConnect(signal);
  2008.   tcConnectptr.p->apiConnect = apiConnectptr.i;
  2009.   tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
  2010.   apiConnectptr.p->lastTcConnect = tcConnectptr.i;
  2011.   seizeCacheRecord(signal);
  2012.   cachePtr.p->keylen = keyLen;
  2013.   cachePtr.p->save1 = 0;
  2014.   scanptr = seizeScanrec(signal);
  2015.   ndbrequire(transP->apiScanRec == RNIL);
  2016.   ndbrequire(scanptr.p->scanApiRec == RNIL);
  2017.   initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag);
  2018.   transP->apiScanRec = scanptr.i;
  2019.   transP->returncode = 0;
  2020.   transP->transid[0] = transid1;
  2021.   transP->transid[1] = transid2;
  2022.   transP->buddyPtr   = buddyPtr;
  2023.   // The scan is started
  2024.   transP->apiConnectstate = CS_START_SCAN;
  2025.   transP->currSavePointId = currSavePointId;
  2026.   /**********************************************************
  2027.   * We start the timer on scanRec to be able to discover a 
  2028.   * timeout in the API the API now is in charge!
  2029.   ***********************************************************/
  2030.   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
  2031.   updateBuddyTimer(apiConnectptr);
  2032.   /***********************************************************
  2033.    * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN 
  2034.    * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO 
  2035.    * IF ANY TO RECEIVE.
  2036.    **********************************************************/
  2037.   scanptr.p->scanState = ScanRecord::WAIT_AI;
  2038.   return;
  2039.  SCAN_error_check:
  2040.   if (aiLength == 0) {
  2041.     jam()
  2042.     errCode = ZSCAN_AI_LEN_ERROR;
  2043.     goto SCAN_TAB_error;
  2044.   }//if
  2045.   if (!tabptr.p->checkTable(schemaVersion)){
  2046.     jam();
  2047.     errCode = tabptr.p->getErrorCode(schemaVersion);
  2048.     goto SCAN_TAB_error;
  2049.   }//if  
  2050.   if (scanConcurrency == 0) {
  2051.     jam();
  2052.     errCode = ZNO_CONCURRENCY_ERROR;
  2053.     goto SCAN_TAB_error;
  2054.   }//if
  2055.   if (cfirstfreeTcConnect == RNIL) {
  2056.     jam();
  2057.     errCode = ZNO_FREE_TC_CONNECTION;
  2058.     goto SCAN_TAB_error;
  2059.   }//if
  2060.   ndbrequire(cfirstfreeScanrec == RNIL);
  2061.   jam();
  2062.   errCode = ZNO_SCANREC_ERROR;
  2063.   goto SCAN_TAB_error;
  2064.  
  2065. SCAN_TAB_error:
  2066.   jam();
  2067.   /**
  2068.    * Prepare for up coming ATTRINFO/KEYINFO
  2069.    */
  2070.   transP->apiConnectstate = CS_ABORTING;
  2071.   transP->abortState = AS_IDLE;
  2072.   transP->transid[0] = transid1;
  2073.   transP->transid[1] = transid2;
  2074.  
  2075. SCAN_TAB_error_no_state_change:
  2076.   
  2077.   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
  2078.   ref->apiConnectPtr = transP->ndbapiConnect;
  2079.   ref->transId1 = transid1;
  2080.   ref->transId2 = transid2;
  2081.   ref->errorCode  = errCode;
  2082.   ref->closeNeeded = 0;
  2083.   sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF, 
  2084.      signal, ScanTabRef::SignalLength, JBB);
  2085.   return;
  2086. }//Dbtc::execSCAN_TABREQ()
  2087. void Dbtc::initScanrec(ScanRecordPtr scanptr,
  2088.        const ScanTabReq * scanTabReq,
  2089.        UintR scanParallel,
  2090.        UintR noOprecPerFrag) 
  2091. {
  2092.   scanptr.p->scanTcrec = tcConnectptr.i;
  2093.   scanptr.p->scanApiRec = apiConnectptr.i;
  2094.   scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
  2095.   scanptr.p->scanKeyLen = scanTabReq->attrLenKeyLen >> 16;
  2096.   scanptr.p->scanTableref = tabptr.i;
  2097.   scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
  2098.   scanptr.p->scanParallel = scanParallel;
  2099.   scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
  2100.   scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
  2101.   scanptr.p->batch_size_rows = noOprecPerFrag;
  2102.   Uint32 tmp = 0;
  2103.   const UintR ri = scanTabReq->requestInfo;
  2104.   ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
  2105.   ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
  2106.   ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
  2107.   ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
  2108.   ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
  2109.   ScanFragReq::setAttrLen(tmp, scanTabReq->attrLenKeyLen & 0xFFFF);
  2110.   
  2111.   scanptr.p->scanRequestInfo = tmp;
  2112.   scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
  2113.   scanptr.p->scanState = ScanRecord::RUNNING;
  2114.   scanptr.p->m_queued_count = 0;
  2115.   ScanFragList list(c_scan_frag_pool, 
  2116.     scanptr.p->m_running_scan_frags);
  2117.   for (Uint32 i = 0; i < scanParallel; i++) {
  2118.     jam();
  2119.     ScanFragRecPtr ptr;
  2120.     ndbrequire(list.seize(ptr));
  2121.     ptr.p->scanRec = scanptr.i;
  2122.     ptr.p->scanFragId = 0;
  2123.     ptr.p->m_apiPtr = cdata[i];
  2124.   }//for
  2125.   (* (ScanTabReq::getRangeScanFlag(ri) ? 
  2126.       &c_counters.c_range_scan_count : 
  2127.       &c_counters.c_scan_count))++;
  2128. }//Dbtc::initScanrec()
  2129. void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode) 
  2130. {
  2131.   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
  2132.   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
  2133.   ref->transId1 = apiConnectptr.p->transid[0];
  2134.   ref->transId2 = apiConnectptr.p->transid[1];
  2135.   ref->errorCode  = errCode;
  2136.   ref->closeNeeded = 0;
  2137.   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF, 
  2138.      signal, ScanTabRef::SignalLength, JBB);
  2139. }//Dbtc::scanTabRefLab()
  2140. /*---------------------------------------------------------------------------*/
  2141. /*                                                                           */
  2142. /*       RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST.                       */
  2143. /*---------------------------------------------------------------------------*/
  2144. void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen) 
  2145. {
  2146.   ScanRecordPtr scanptr;
  2147.   scanptr.i = apiConnectptr.p->apiScanRec;
  2148.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2149.   tcConnectptr.i = scanptr.p->scanTcrec;
  2150.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  2151.   cachePtr.i = apiConnectptr.p->cachePtr;
  2152.   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
  2153.   CacheRecord * const regCachePtr = cachePtr.p;
  2154.   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
  2155.   regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
  2156.   if (regCachePtr->currReclenAi < scanptr.p->scanAiLength) {
  2157.     if (cfirstfreeAttrbuf == RNIL) {
  2158.       goto scanAttrinfo_attrbuf_error;
  2159.     }//if
  2160.     saveAttrbuf(signal);
  2161.   } else {
  2162.     if (regCachePtr->currReclenAi > scanptr.p->scanAiLength) {
  2163.       goto scanAttrinfo_len_error;
  2164.     } else {
  2165.       /* CURR_RECLEN_AI = SCAN_AI_LENGTH */
  2166.       if (cfirstfreeAttrbuf == RNIL) {
  2167.         goto scanAttrinfo_attrbuf2_error;
  2168.       }//if
  2169.       saveAttrbuf(signal);
  2170.       /**************************************************
  2171.        * WE HAVE NOW RECEIVED ALL INFORMATION CONCERNING 
  2172.        * THIS SCAN. WE ARE READY TO START THE ACTUAL 
  2173.        * EXECUTION OF THE SCAN QUERY
  2174.        **************************************************/
  2175.       diFcountReqLab(signal, scanptr);
  2176.       return;
  2177.     }//if
  2178.   }//if
  2179.   return;
  2180. scanAttrinfo_attrbuf_error:
  2181.   jam();
  2182.   abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR);
  2183.   return;
  2184. scanAttrinfo_attrbuf2_error:
  2185.   jam();
  2186.   abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR);
  2187.   return;
  2188. scanAttrinfo_len_error:
  2189.   jam();
  2190.   abortScanLab(signal, scanptr, ZLENGTH_ERROR);
  2191.   return;
  2192. }//Dbtc::scanAttrinfoLab()
  2193. void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
  2194. {
  2195.   /**
  2196.    * Check so that the table is not being dropped
  2197.    */
  2198.   TableRecordPtr tabPtr;
  2199.   tabPtr.i = scanptr.p->scanTableref;
  2200.   tabPtr.p = &tableRecord[tabPtr.i];
  2201.   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
  2202.     ;
  2203.   } else {
  2204.     abortScanLab(signal, scanptr, 
  2205.  tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
  2206.     return;
  2207.   }
  2208.   scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
  2209.   /*************************************************
  2210.    * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED. 
  2211.    * WE MUST FIRST GET THE NUMBER OF  FRAGMENTS IN THE TABLE.
  2212.    ***************************************************/
  2213.   signal->theData[0] = tcConnectptr.p->dihConnectptr;
  2214.   signal->theData[1] = scanptr.p->scanTableref;
  2215.   sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
  2216.   return;
  2217. }//Dbtc::diFcountReqLab()
  2218. /********************************************************************
  2219.  * execDI_FCOUNTCONF
  2220.  *
  2221.  * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE. 
  2222.  * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF 
  2223.  * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS 
  2224.  * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION 
  2225.  * CLOSES THE SCAN.
  2226.  ********************************************************************/
  2227. void Dbtc::execDI_FCOUNTCONF(Signal* signal) 
  2228. {
  2229.   jamEntry();
  2230.   tcConnectptr.i = signal->theData[0];
  2231.   const UintR tfragCount = signal->theData[1];
  2232.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  2233.   apiConnectptr.i = tcConnectptr.p->apiConnect;
  2234.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  2235.   ScanRecordPtr scanptr;
  2236.   scanptr.i = apiConnectptr.p->apiScanRec;
  2237.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2238.   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
  2239.   if (apiConnectptr.p->apiFailState == ZTRUE) {
  2240.     jam();
  2241.     releaseScanResources(scanptr);
  2242.     handleApiFailState(signal, apiConnectptr.i);
  2243.     return;
  2244.   }//if
  2245.   if (tfragCount == 0) {
  2246.     jam();
  2247.     abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR);
  2248.     return;
  2249.   }//if
  2250.   
  2251.   /**
  2252.    * Check so that the table is not being dropped
  2253.    */
  2254.   TableRecordPtr tabPtr;
  2255.   tabPtr.i = scanptr.p->scanTableref;
  2256.   tabPtr.p = &tableRecord[tabPtr.i];
  2257.   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
  2258.     ;
  2259.   } else {
  2260.     abortScanLab(signal, scanptr,
  2261.  tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion));
  2262.     return;
  2263.   }
  2264.   if(scanptr.p->scanParallel > tfragCount){
  2265.     jam();
  2266.     abortScanLab(signal, scanptr, ZTOO_HIGH_CONCURRENCY_ERROR);
  2267.     return;
  2268.   }
  2269.   
  2270.   scanptr.p->scanParallel = tfragCount;
  2271.   scanptr.p->scanNoFrag = tfragCount;
  2272.   scanptr.p->scanNextFragId = 0;
  2273.   scanptr.p->scanState = ScanRecord::RUNNING;
  2274.   setApiConTimer(apiConnectptr.i, 0, __LINE__);
  2275.   updateBuddyTimer(apiConnectptr);
  2276.   
  2277.   ScanFragRecPtr ptr;
  2278.   ScanFragList list(c_scan_frag_pool, 
  2279.     scanptr.p->m_running_scan_frags);
  2280.   for (list.first(ptr); !ptr.isNull(); list.next(ptr)){
  2281.     jam();
  2282.     ptr.p->lqhBlockref = 0;
  2283.     ptr.p->startFragTimer(ctcTimer);
  2284.     ptr.p->scanFragId = scanptr.p->scanNextFragId++;
  2285.     ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
  2286.     ptr.p->startFragTimer(ctcTimer);
  2287.     signal->theData[0] = tcConnectptr.p->dihConnectptr;
  2288.     signal->theData[1] = ptr.i;
  2289.     signal->theData[2] = scanptr.p->scanTableref;
  2290.     signal->theData[3] = ptr.p->scanFragId;
  2291.     sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
  2292.   }//for
  2293. }//Dbtc::execDI_FCOUNTCONF()
  2294. /******************************************************
  2295.  * execDI_FCOUNTREF
  2296.  ******************************************************/
  2297. void Dbtc::execDI_FCOUNTREF(Signal* signal) 
  2298. {
  2299.   jamEntry();
  2300.   tcConnectptr.i = signal->theData[0];
  2301.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  2302.   const Uint32 errCode = signal->theData[1];
  2303.   apiConnectptr.i = tcConnectptr.p->apiConnect;
  2304.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  2305.   ScanRecordPtr scanptr;
  2306.   scanptr.i = apiConnectptr.p->apiScanRec;
  2307.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2308.   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
  2309.   if (apiConnectptr.p->apiFailState == ZTRUE) {
  2310.     jam();
  2311.     releaseScanResources(scanptr);
  2312.     handleApiFailState(signal, apiConnectptr.i);
  2313.     return;
  2314.   }//if
  2315.   abortScanLab(signal, scanptr, errCode);
  2316. }//Dbtc::execDI_FCOUNTREF()
  2317. void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode) 
  2318. {
  2319.   scanTabRefLab(signal, errCode);
  2320.   releaseScanResources(scanptr);
  2321. }//Dbtc::abortScanLab()
  2322. void Dbtc::releaseScanResources(ScanRecordPtr scanPtr)
  2323. {
  2324.   if (apiConnectptr.p->cachePtr != RNIL) {
  2325.     cachePtr.i = apiConnectptr.p->cachePtr;
  2326.     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
  2327.     releaseKeys();
  2328.     releaseAttrinfo();
  2329.   }//if
  2330.   tcConnectptr.i = scanPtr.p->scanTcrec;
  2331.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  2332.   releaseTcCon();
  2333.   ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
  2334.   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
  2335.   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
  2336.   ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
  2337.   ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
  2338.   
  2339.   // link into free list
  2340.   scanPtr.p->nextScan = cfirstfreeScanrec;
  2341.   scanPtr.p->scanState = ScanRecord::IDLE;
  2342.   scanPtr.p->scanTcrec = RNIL;
  2343.   scanPtr.p->scanApiRec = RNIL;
  2344.   cfirstfreeScanrec = scanPtr.i;
  2345.   
  2346.   apiConnectptr.p->apiScanRec = RNIL;
  2347.   apiConnectptr.p->apiConnectstate = CS_CONNECTED;
  2348.   setApiConTimer(apiConnectptr.i, 0, __LINE__);
  2349. }//Dbtc::releaseScanResources()
  2350. /****************************************************************
  2351.  * execDIGETPRIMCONF
  2352.  *
  2353.  * WE HAVE RECEIVED THE PRIMARY NODE OF THIS FRAGMENT. 
  2354.  * WE ARE NOW READY TO ASK  FOR PERMISSION TO LOAD THIS 
  2355.  * SPECIFIC NODE WITH A SCAN OPERATION.
  2356.  ****************************************************************/
  2357. void Dbtc::execDIGETPRIMCONF(Signal* signal) 
  2358. {
  2359.   jamEntry();
  2360.   //  tcConnectptr.i in theData[0] is not used
  2361.   scanFragptr.i = signal->theData[1];
  2362.   c_scan_frag_pool.getPtr(scanFragptr);
  2363.   tnodeid = signal->theData[2];
  2364.   arrGuard(tnodeid, MAX_NDB_NODES);
  2365.   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
  2366.   scanFragptr.p->stopFragTimer();
  2367.   ScanRecordPtr scanptr;
  2368.   scanptr.i = scanFragptr.p->scanRec;
  2369.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2370.   /**
  2371.    * This must be false as select count(*) otherwise
  2372.    *   can "pass" committing on backup fragments and
  2373.    *   get incorrect row count
  2374.    */
  2375.   if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
  2376.   {
  2377.     jam();
  2378.     Uint32 max = 3+signal->theData[6];
  2379.     Uint32 nodeid = getOwnNodeId();
  2380.     for(Uint32 i = 3; i<max; i++)
  2381.       if(signal->theData[i] ==  nodeid)
  2382.       {
  2383. jam();
  2384. tnodeid = nodeid;
  2385. break;
  2386.       }
  2387.   }
  2388.   
  2389.   {
  2390.     /**
  2391.      * Check table
  2392.      */
  2393.     TableRecordPtr tabPtr;
  2394.     tabPtr.i = scanptr.p->scanTableref;
  2395.     ptrAss(tabPtr, tableRecord);
  2396.     Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
  2397.     if(tabPtr.p->checkTable(schemaVersion) == false){
  2398.       jam();
  2399.       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  2400.       
  2401.       run.release(scanFragptr);
  2402.       scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion));
  2403.       return;
  2404.     }
  2405.   }
  2406.   
  2407.   tcConnectptr.i = scanptr.p->scanTcrec;
  2408.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  2409.   apiConnectptr.i = scanptr.p->scanApiRec;
  2410.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  2411.   cachePtr.i = apiConnectptr.p->cachePtr;
  2412.   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
  2413.   switch (scanptr.p->scanState) {
  2414.   case ScanRecord::CLOSING_SCAN:
  2415.     jam();
  2416.     updateBuddyTimer(apiConnectptr);
  2417.     {
  2418.       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  2419.       
  2420.       run.release(scanFragptr);
  2421.     }
  2422.     close_scan_req_send_conf(signal, scanptr);
  2423.     return;
  2424.   default:
  2425.     jam();
  2426.     /*empty*/;
  2427.     break;
  2428.   }//switch
  2429.   Uint32 ref = calcLqhBlockRef(tnodeid);
  2430.   scanFragptr.p->lqhBlockref = ref;
  2431.   scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
  2432.   sendScanFragReq(signal, scanptr.p, scanFragptr.p);
  2433.   if(ERROR_INSERTED(8035))
  2434.     globalTransporterRegistry.performSend();
  2435.   attrbufptr.i = cachePtr.p->firstAttrbuf;
  2436.   while (attrbufptr.i != RNIL) {
  2437.     jam();
  2438.     ptrCheckGuard(attrbufptr, cattrbufFilesize, attrbufRecord);
  2439.     sendAttrinfo(signal,
  2440.                  scanFragptr.i,
  2441.                  attrbufptr.p,
  2442.                  ref);
  2443.     attrbufptr.i = attrbufptr.p->attrbuf[ZINBUF_NEXT];
  2444.     if(ERROR_INSERTED(8035))
  2445.       globalTransporterRegistry.performSend();
  2446.   }//while
  2447.   scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
  2448.   scanFragptr.p->startFragTimer(ctcTimer);
  2449.   updateBuddyTimer(apiConnectptr);
  2450.   /*********************************************
  2451.    * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW 
  2452.    * WAIT FOR THE FIRST SCANNED RECORDS
  2453.    *********************************************/
  2454. }//Dbtc::execDIGETPRIMCONF
  2455. /***************************************************
  2456.  * execDIGETPRIMREF
  2457.  *
  2458.  * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR 
  2459.  * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH 
  2460.  * FINDING A PRIMARY REPLICA OF A CERTAIN FRAGMENT.
  2461.  ***************************************************/
  2462. void Dbtc::execDIGETPRIMREF(Signal* signal) 
  2463. {
  2464.   jamEntry();
  2465.   // tcConnectptr.i in theData[0] is not used.
  2466.   scanFragptr.i = signal->theData[1];
  2467.   const Uint32 errCode = signal->theData[2];
  2468.   c_scan_frag_pool.getPtr(scanFragptr);
  2469.   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
  2470.   ScanRecordPtr scanptr;
  2471.   scanptr.i = scanFragptr.p->scanRec;
  2472.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2473.   ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  2474.   
  2475.   run.release(scanFragptr);
  2476.   scanError(signal, scanptr, errCode);
  2477. }//Dbtc::execDIGETPRIMREF()
  2478. /**
  2479.  * Dbtc::execSCAN_FRAGREF
  2480.  *  Our attempt to scan a fragment was refused
  2481.  *  set error code and close all other fragment 
  2482.  *  scan's belonging to this scan
  2483.  */
  2484. void Dbtc::execSCAN_FRAGREF(Signal* signal) 
  2485. {
  2486.   const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
  2487.   
  2488.   jamEntry();
  2489.   const Uint32 errCode = ref->errorCode;
  2490.   scanFragptr.i = ref->senderData;
  2491.   c_scan_frag_pool.getPtr(scanFragptr);
  2492.   ScanRecordPtr scanptr;
  2493.   scanptr.i = scanFragptr.p->scanRec;
  2494.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2495.   apiConnectptr.i = scanptr.p->scanApiRec;
  2496.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  2497.   Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
  2498.   Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
  2499.   transid1 = transid1 | transid2;
  2500.   if (transid1 != 0) {
  2501.     jam();
  2502.     systemErrorLab(signal);
  2503.   }//if
  2504.   /**
  2505.    * Set errorcode, close connection to this lqh fragment,
  2506.    * stop fragment timer and call scanFragError to start 
  2507.    * close of the other fragment scans
  2508.    */
  2509.   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
  2510.   {
  2511.     scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
  2512.     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  2513.     
  2514.     run.release(scanFragptr);
  2515.     scanFragptr.p->stopFragTimer();
  2516.   }    
  2517.   scanError(signal, scanptr, errCode);
  2518. }//Dbtc::execSCAN_FRAGREF()
  2519. /**
  2520.  * Dbtc::scanError
  2521.  *
  2522.  * Called when an error occurs during
  2523.  */ 
  2524. void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode) 
  2525. {
  2526.   jam();
  2527.   ScanRecord* scanP = scanptr.p;
  2528.   
  2529.   DEBUG("scanError, errorCode = "<< errorCode << 
  2530. ", scanState = " << scanptr.p->scanState);
  2531.   apiConnectptr.i = scanP->scanApiRec;
  2532.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  2533.   ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
  2534.   if(scanP->scanState == ScanRecord::CLOSING_SCAN){
  2535.     jam();
  2536.     close_scan_req_send_conf(signal, scanptr);
  2537.     return;
  2538.   }
  2539.   
  2540.   ndbrequire(scanP->scanState == ScanRecord::RUNNING);
  2541.   
  2542.   /**
  2543.    * Close scan wo/ having received an order to do so
  2544.    */
  2545.   close_scan_req(signal, scanptr, false);
  2546.   
  2547.   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
  2548.   if(apiFail){
  2549.     jam();
  2550.     return;
  2551.   }
  2552.   
  2553.   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
  2554.   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
  2555.   ref->transId1 = apiConnectptr.p->transid[0];
  2556.   ref->transId2 = apiConnectptr.p->transid[1];
  2557.   ref->errorCode  = errorCode;
  2558.   ref->closeNeeded = 1;
  2559.   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF, 
  2560.      signal, ScanTabRef::SignalLength, JBB);
  2561. }//Dbtc::scanError()
  2562. /************************************************************
  2563.  * execSCAN_FRAGCONF
  2564.  *
  2565.  * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS 
  2566.  * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
  2567.  ************************************************************/
  2568. void Dbtc::execSCAN_FRAGCONF(Signal* signal) 
  2569. {
  2570.   Uint32 transid1, transid2, total_len;
  2571.   jamEntry();
  2572.   const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
  2573.   const Uint32 noCompletedOps = conf->completedOps;
  2574.   const Uint32 status = conf->fragmentCompleted;
  2575.   scanFragptr.i = conf->senderData;
  2576.   c_scan_frag_pool.getPtr(scanFragptr);
  2577.   
  2578.   ScanRecordPtr scanptr;
  2579.   scanptr.i = scanFragptr.p->scanRec;
  2580.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2581.   
  2582.   apiConnectptr.i = scanptr.p->scanApiRec;
  2583.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  2584.   transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
  2585.   transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
  2586.   total_len= conf->total_len;
  2587.   transid1 = transid1 | transid2;
  2588.   if (transid1 != 0) {
  2589.     jam();
  2590.     systemErrorLab(signal);
  2591.   }//if
  2592.   
  2593.   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
  2594.   
  2595.   if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
  2596.     jam();
  2597.     if(status == 0){
  2598.       /**
  2599.        * We have started closing = we sent a close -> ignore this
  2600.        */
  2601.       return;
  2602.     } else {
  2603.       jam();
  2604.       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  2605.       
  2606.       run.release(scanFragptr);
  2607.       scanFragptr.p->stopFragTimer();
  2608.       scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
  2609.     }
  2610.     close_scan_req_send_conf(signal, scanptr);
  2611.     return;
  2612.   }
  2613.   if(noCompletedOps == 0 && status != 0 && 
  2614.      scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){
  2615.     /**
  2616.      * Start on next fragment
  2617.      */
  2618.     scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF; 
  2619.     scanFragptr.p->startFragTimer(ctcTimer);
  2620.     tcConnectptr.i = scanptr.p->scanTcrec;
  2621.     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  2622.     scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
  2623.     signal->theData[0] = tcConnectptr.p->dihConnectptr;
  2624.     signal->theData[1] = scanFragptr.i;
  2625.     signal->theData[2] = scanptr.p->scanTableref;
  2626.     signal->theData[3] = scanFragptr.p->scanFragId;
  2627.     sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
  2628.     return;
  2629.   }
  2630.  /* 
  2631.   Uint32 totalLen = 0;
  2632.   for(Uint32 i = 0; i<noCompletedOps; i++){
  2633.     Uint32 tmp = conf->opReturnDataLen[i];
  2634.     totalLen += tmp;
  2635.   }
  2636.  */ 
  2637.   {
  2638.     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
  2639.     ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
  2640.     
  2641.     run.remove(scanFragptr);
  2642.     queued.add(scanFragptr);
  2643.     scanptr.p->m_queued_count++;
  2644.   }
  2645.   scanFragptr.p->m_scan_frag_conf_status = status;
  2646.   scanFragptr.p->m_ops = noCompletedOps;
  2647.   scanFragptr.p->m_totalLen = total_len;
  2648.   scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
  2649.   scanFragptr.p->stopFragTimer();
  2650.   
  2651.   if(scanptr.p->m_queued_count > /** Min */ 0){
  2652.     jam();
  2653.     sendScanTabConf(signal, scanptr);
  2654.   }
  2655. }//Dbtc::execSCAN_FRAGCONF()
  2656. /****************************************************************************
  2657.  * execSCAN_NEXTREQ
  2658.  *
  2659.  * THE APPLICATION HAVE PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
  2660.  * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN. 
  2661.  ****************************************************************************/
  2662. void Dbtc::execSCAN_NEXTREQ(Signal* signal) 
  2663. {
  2664.   const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
  2665.   const UintR transid1 = req->transId1;
  2666.   const UintR transid2 = req->transId2;
  2667.   const UintR stopScan = req->stopScan;
  2668.   jamEntry();
  2669.   apiConnectptr.i = req->apiConnectPtr;
  2670.   if (apiConnectptr.i >= capiConnectFilesize) {
  2671.     jam();
  2672.     warningHandlerLab(signal);
  2673.     return;
  2674.   }//if
  2675.   ptrAss(apiConnectptr, apiConnectRecord);
  2676.   /**
  2677.    * Check transid
  2678.    */
  2679.   const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
  2680.   const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
  2681.   if ((ctransid1 | ctransid2) != 0){
  2682.     ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
  2683.     ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
  2684.     ref->transId1 = transid1;
  2685.     ref->transId2 = transid2;
  2686.     ref->errorCode  = ZSTATE_ERROR;
  2687.     ref->closeNeeded = 0;
  2688.     sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF, 
  2689.        signal, ScanTabRef::SignalLength, JBB);
  2690.     DEBUG("Wrong transid");
  2691.     return;
  2692.   }
  2693.   /**
  2694.    * Check state of API connection
  2695.    */
  2696.   if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
  2697.     jam();
  2698.     if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
  2699.       jam();
  2700.       /*********************************************************************
  2701.        * The application sends a SCAN_NEXTREQ after experiencing a time-out.
  2702.        *  We will send a SCAN_TABREF to indicate a time-out occurred.
  2703.        *********************************************************************/
  2704.       DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
  2705.       ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
  2706.       ndbrequire(false); //B2 indication of strange things going on
  2707.       scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
  2708.       return;
  2709.     }
  2710.     DEBUG("scanTabRefLab: ZSTATE_ERROR");
  2711.     DEBUG("  apiConnectstate="<<apiConnectptr.p->apiConnectstate);
  2712.     ndbrequire(false); //B2 indication of strange things going on
  2713.     scanTabRefLab(signal, ZSTATE_ERROR);
  2714.     return;
  2715.   }//if
  2716.   
  2717.   /*******************************************************
  2718.    * START THE ACTUAL LOGIC OF SCAN_NEXTREQ. 
  2719.    ********************************************************/
  2720.   // Stop the timer that is used to check for timeout in the API 
  2721.   setApiConTimer(apiConnectptr.i, 0, __LINE__);
  2722.   ScanRecordPtr scanptr;
  2723.   scanptr.i = apiConnectptr.p->apiScanRec;
  2724.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2725.   ScanRecord* scanP = scanptr.p;
  2726.   const Uint32 len = signal->getLength() - 4;
  2727.   if (stopScan == ZTRUE) {
  2728.     jam();
  2729.     /*********************************************************************
  2730.      * APPLICATION IS CLOSING THE SCAN.
  2731.      **********************************************************************/
  2732.     close_scan_req(signal, scanptr, true);
  2733.     return;
  2734.   }//if
  2735.   if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
  2736.     jam();
  2737.     /**
  2738.      * The scan is closing (typically due to error)
  2739.      *   but the API hasn't understood it yet
  2740.      *
  2741.      * Wait for API close request
  2742.      */
  2743.     return;
  2744.   }
  2745.   // Copy op ptrs so I dont overwrite them when sending...
  2746.   memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len);
  2747.   ScanFragNextReq tmp;
  2748.   tmp.closeFlag = ZFALSE;
  2749.   tmp.transId1 = apiConnectptr.p->transid[0];
  2750.   tmp.transId2 = apiConnectptr.p->transid[1];
  2751.   tmp.batch_size_rows = scanP->batch_size_rows;
  2752.   tmp.batch_size_bytes = scanP->batch_byte_size;
  2753.   ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
  2754.   ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
  2755.   for(Uint32 i = 0 ; i<len; i++){
  2756.     jam();
  2757.     scanFragptr.i = signal->theData[i+25];
  2758.     c_scan_frag_pool.getPtr(scanFragptr);
  2759.     ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
  2760.     
  2761.     scanFragptr.p->startFragTimer(ctcTimer);
  2762.     scanFragptr.p->m_ops = 0;
  2763.     if(scanFragptr.p->m_scan_frag_conf_status)
  2764.     {
  2765.       /**
  2766.        * last scan was complete
  2767.        */
  2768.       jam();
  2769.       ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
  2770.       scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF; 
  2771.       
  2772.       tcConnectptr.i = scanptr.p->scanTcrec;
  2773.       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  2774.       scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
  2775.       signal->theData[0] = tcConnectptr.p->dihConnectptr;
  2776.       signal->theData[1] = scanFragptr.i;
  2777.       signal->theData[2] = scanptr.p->scanTableref;
  2778.       signal->theData[3] = scanFragptr.p->scanFragId;
  2779.       sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
  2780.     }
  2781.     else
  2782.     {
  2783.       jam();
  2784.       scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
  2785.       ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
  2786.       * req = tmp;
  2787.       req->senderData = scanFragptr.i;
  2788.       sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, 
  2789.  ScanFragNextReq::SignalLength, JBB);
  2790.     }
  2791.     delivered.remove(scanFragptr);
  2792.     running.add(scanFragptr);
  2793.   }//for
  2794.   
  2795. }//Dbtc::execSCAN_NEXTREQ()
  2796. void
  2797. Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
  2798.   ScanRecord* scanP = scanPtr.p;
  2799.   ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);  
  2800.   scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
  2801.   scanPtr.p->m_close_scan_req = req_received;
  2802.   /**
  2803.    * Queue         : Action
  2804.    * ============= : =================
  2805.    * completed     : -
  2806.    * running       : close -> LQH
  2807.    * delivered w/  : close -> LQH
  2808.    * delivered wo/ : move to completed
  2809.    * queued w/     : close -> LQH
  2810.    * queued wo/    : move to completed
  2811.    */
  2812.   
  2813.   ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
  2814.   nextReq->closeFlag = ZTRUE;
  2815.   nextReq->transId1 = apiConnectptr.p->transid[0];
  2816.   nextReq->transId2 = apiConnectptr.p->transid[1];
  2817.   
  2818.   {
  2819.     ScanFragRecPtr ptr;
  2820.     ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
  2821.     ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
  2822.     ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
  2823.     
  2824.     // Close running
  2825.     for(running.first(ptr); !ptr.isNull(); ){
  2826.       ScanFragRecPtr curr = ptr; // Remove while iterating...
  2827.       running.next(ptr);
  2828.       if(curr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF){
  2829. jam();
  2830. continue;
  2831.       }
  2832.       ndbrequire(curr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
  2833.       
  2834.       curr.p->startFragTimer(ctcTimer);
  2835.       curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
  2836.       nextReq->senderData = curr.i;
  2837.       sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, 
  2838.  ScanFragNextReq::SignalLength, JBB);
  2839.     }
  2840.     // Close delivered
  2841.     for(delivered.first(ptr); !ptr.isNull(); ){
  2842.       jam();
  2843.       ScanFragRecPtr curr = ptr; // Remove while iterating...
  2844.       delivered.next(ptr);
  2845.       ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
  2846.       delivered.remove(curr);
  2847.       
  2848.       if(curr.p->m_ops > 0 && curr.p->m_scan_frag_conf_status == 0){
  2849. jam();
  2850. running.add(curr);
  2851. curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
  2852. curr.p->startFragTimer(ctcTimer);
  2853. nextReq->senderData = curr.i;
  2854. sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, 
  2855.    ScanFragNextReq::SignalLength, JBB);
  2856.       } else {
  2857. jam();
  2858. c_scan_frag_pool.release(curr);
  2859. curr.p->scanFragState = ScanFragRec::COMPLETED;
  2860. curr.p->stopFragTimer();
  2861.       }
  2862.     }//for
  2863.     /**
  2864.      * All queued with data should be closed
  2865.      */
  2866.     for(queued.first(ptr); !ptr.isNull(); ){
  2867.       jam();
  2868.       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
  2869.       ScanFragRecPtr curr = ptr; // Remove while iterating...
  2870.       queued.next(ptr);
  2871.       
  2872.       queued.remove(curr); 
  2873.       scanP->m_queued_count--;
  2874.       
  2875.       if(curr.p->m_ops > 0){
  2876. jam();
  2877. running.add(curr);
  2878. curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
  2879. curr.p->startFragTimer(ctcTimer);
  2880. nextReq->senderData = curr.i;
  2881. sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal, 
  2882.    ScanFragNextReq::SignalLength, JBB);
  2883.       } else {
  2884. jam();
  2885. c_scan_frag_pool.release(curr);
  2886. curr.p->scanFragState = ScanFragRec::COMPLETED;
  2887. curr.p->stopFragTimer();
  2888.       }
  2889.     }
  2890.   }
  2891.   close_scan_req_send_conf(signal, scanPtr);
  2892. }
  2893. void
  2894. Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
  2895.   jam();
  2896.   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
  2897.   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
  2898.   //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
  2899. #if 0
  2900.   {
  2901.     ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
  2902.     ScanFragRecPtr ptr;
  2903.     for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
  2904.       ndbrequire(ptr.p->scanFragTimer == 0);
  2905.       ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
  2906.     } 
  2907.   }
  2908. #endif
  2909.   
  2910.   if(!scanPtr.p->m_running_scan_frags.isEmpty()){
  2911.     jam();
  2912.     return;
  2913.   }
  2914.   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
  2915.   
  2916.   if(!scanPtr.p->m_close_scan_req){
  2917.     jam();
  2918.     /**
  2919.      * The API hasn't order closing yet
  2920.      */
  2921.     return;
  2922.   }
  2923.   Uint32 ref = apiConnectptr.p->ndbapiBlockref;
  2924.   if(!apiFail && ref){
  2925.     jam();
  2926.     ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
  2927.     conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
  2928.     conf->requestInfo = ScanTabConf::EndOfData;
  2929.     conf->transId1 = apiConnectptr.p->transid[0];
  2930.     conf->transId2 = apiConnectptr.p->transid[1];
  2931.     sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
  2932.   }
  2933.   
  2934.   releaseScanResources(scanPtr);
  2935.   
  2936.   if(apiFail){
  2937.     jam();
  2938.     /**
  2939.      * API has failed
  2940.      */
  2941.     handleApiFailState(signal, apiConnectptr.i);
  2942.   }
  2943. }
  2944. Dbtc::ScanRecordPtr
  2945. Dbtc::seizeScanrec(Signal* signal) {
  2946.   ScanRecordPtr scanptr;
  2947.   scanptr.i = cfirstfreeScanrec;
  2948.   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
  2949.   cfirstfreeScanrec = scanptr.p->nextScan;
  2950.   scanptr.p->nextScan = RNIL;
  2951.   ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
  2952.   return scanptr;
  2953. }//Dbtc::seizeScanrec()
  2954. void Dbtc::sendScanFragReq(Signal* signal, 
  2955.    ScanRecord* scanP, 
  2956.    ScanFragRec* scanFragP)
  2957. {
  2958.   ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
  2959.   Uint32 requestInfo = scanP->scanRequestInfo;
  2960.   ScanFragReq::setScanPrio(requestInfo, 1);
  2961.   apiConnectptr.i = scanP->scanApiRec;
  2962.   req->tableId = scanP->scanTableref;
  2963.   req->schemaVersion = scanP->scanSchemaVersion;
  2964.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  2965.   req->senderData = scanFragptr.i;
  2966.   req->requestInfo = requestInfo;
  2967.   req->fragmentNoKeyLen = scanFragP->scanFragId | (scanP->scanKeyLen << 16);
  2968.   req->resultRef = apiConnectptr.p->ndbapiBlockref;
  2969.   req->savePointId = apiConnectptr.p->currSavePointId;
  2970.   req->transId1 = apiConnectptr.p->transid[0];
  2971.   req->transId2 = apiConnectptr.p->transid[1];
  2972.   req->clientOpPtr = scanFragP->m_apiPtr;
  2973.   req->batch_size_rows= scanP->batch_size_rows;
  2974.   req->batch_size_bytes= scanP->batch_byte_size;
  2975.   sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
  2976.              ScanFragReq::SignalLength, JBB);
  2977.   if(scanP->scanKeyLen > 0)
  2978.   {
  2979.     tcConnectptr.i = scanFragptr.i;
  2980.     packKeyData000Lab(signal, scanFragP->lqhBlockref, scanP->scanKeyLen);
  2981.   }
  2982.   updateBuddyTimer(apiConnectptr);
  2983.   scanFragP->startFragTimer(ctcTimer);
  2984. }//Dbtc::sendScanFragReq()
  2985. void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
  2986.   jam();
  2987.   Uint32* ops = signal->getDataPtrSend()+4;
  2988.   Uint32 op_count = scanPtr.p->m_queued_count;
  2989.   if(4 + 3 * op_count > 25){
  2990.     jam();
  2991.     ops += 21;
  2992.   }
  2993.   Uint32 left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
  2994.   
  2995.   ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
  2996.   conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
  2997.   conf->requestInfo = op_count;
  2998.   conf->transId1 = apiConnectptr.p->transid[0];
  2999.   conf->transId2 = apiConnectptr.p->transid[1];
  3000.   ScanFragRecPtr ptr;
  3001.   {
  3002.     ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
  3003.     ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
  3004.     for(queued.first(ptr); !ptr.isNull(); ){
  3005.       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
  3006.       ScanFragRecPtr curr = ptr; // Remove while iterating...
  3007.       queued.next(ptr);
  3008.       
  3009.       bool done = curr.p->m_scan_frag_conf_status && --left;
  3010.       * ops++ = curr.p->m_apiPtr;
  3011.       * ops++ = done ? RNIL : curr.i;
  3012.       * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
  3013.       
  3014.       queued.remove(curr); 
  3015.       if(!done){
  3016. delivered.add(curr);
  3017. curr.p->scanFragState = ScanFragRec::DELIVERED;
  3018. curr.p->stopFragTimer();
  3019.       } else {
  3020. c_scan_frag_pool.release(curr);
  3021. curr.p->scanFragState = ScanFragRec::COMPLETED;
  3022. curr.p->stopFragTimer();
  3023.       }
  3024.     }
  3025.   }
  3026.   
  3027.   if(scanPtr.p->m_delivered_scan_frags.isEmpty() && 
  3028.      scanPtr.p->m_running_scan_frags.isEmpty()){
  3029.     conf->requestInfo = op_count | ScanTabConf::EndOfData;    
  3030.     releaseScanResources(scanPtr);
  3031.   }