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

MySQL数据库

开发平台:

Visual C++

  1.   
  2.   if(4 + 3 * op_count > 25){
  3.     jam();
  4.     LinearSectionPtr ptr[3];
  5.     ptr[0].p = signal->getDataPtrSend()+25;
  6.     ptr[0].sz = 3 * op_count;
  7.     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal, 
  8.        ScanTabConf::SignalLength, JBB, ptr, 1);
  9.   } else {
  10.     jam();
  11.     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal, 
  12.        ScanTabConf::SignalLength + 3 * op_count, JBB);
  13.   }
  14.   scanPtr.p->m_queued_count = 0;
  15. }//Dbtc::sendScanTabConf()
  16. void Dbtc::gcpTcfinished(Signal* signal) 
  17. {
  18.   signal->theData[1] = tcheckGcpId;
  19.   sendSignal(cdihblockref, GSN_GCP_TCFINISHED, signal, 2, JBB);
  20. }//Dbtc::gcpTcfinished()
  21. void Dbtc::initApiConnect(Signal* signal) 
  22. {
  23.   Uint32 tiacTmp;
  24.   Uint32 guard4;
  25.   tiacTmp = capiConnectFilesize / 3;
  26.   ndbrequire(tiacTmp > 0);
  27.   guard4 = tiacTmp + 1;
  28.   for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
  29.     refresh_watch_dog();
  30.     ptrAss(cachePtr, cacheRecord);
  31.     cachePtr.p->firstAttrbuf = RNIL;
  32.     cachePtr.p->lastAttrbuf = RNIL;
  33.     cachePtr.p->firstKeybuf = RNIL;
  34.     cachePtr.p->lastKeybuf = RNIL;
  35.     cachePtr.p->nextCacheRec = cachePtr.i + 1;
  36.   }//for
  37.   cachePtr.i = tiacTmp;
  38.   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
  39.   cachePtr.p->nextCacheRec = RNIL;
  40.   cfirstfreeCacheRec = 0;
  41.   guard4 = tiacTmp - 1;
  42.   for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
  43.     refresh_watch_dog();
  44.     jam();
  45.     ptrAss(apiConnectptr, apiConnectRecord);
  46.     apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
  47.     apiConnectptr.p->apiFailState = ZFALSE;
  48.     setApiConTimer(apiConnectptr.i, 0, __LINE__);
  49.     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
  50.     apiConnectptr.p->cachePtr = RNIL;
  51.     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
  52.     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
  53.     apiConnectptr.p->commitAckMarker = RNIL;
  54.     apiConnectptr.p->firstTcConnect = RNIL;
  55.     apiConnectptr.p->lastTcConnect = RNIL;
  56.     apiConnectptr.p->triggerPending = false;
  57.     apiConnectptr.p->isIndexOp = false;
  58.     apiConnectptr.p->accumulatingIndexOp = RNIL;
  59.     apiConnectptr.p->executingIndexOp = RNIL;
  60.     apiConnectptr.p->buddyPtr = RNIL;
  61.     apiConnectptr.p->currSavePointId = 0;
  62.   }//for
  63.   apiConnectptr.i = tiacTmp - 1;
  64.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  65.   apiConnectptr.p->nextApiConnect = RNIL;
  66.   cfirstfreeApiConnect = 0;
  67.   guard4 = (2 * tiacTmp) - 1;
  68.   for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
  69.     {
  70.       refresh_watch_dog();
  71.       jam();
  72.       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  73.       apiConnectptr.p->apiConnectstate = CS_RESTART;
  74.       apiConnectptr.p->apiFailState = ZFALSE;
  75.       setApiConTimer(apiConnectptr.i, 0, __LINE__);
  76.       apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
  77.       apiConnectptr.p->cachePtr = RNIL;
  78.       apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
  79.       apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
  80.       apiConnectptr.p->commitAckMarker = RNIL;
  81.       apiConnectptr.p->firstTcConnect = RNIL;
  82.       apiConnectptr.p->lastTcConnect = RNIL;
  83.       apiConnectptr.p->triggerPending = false;
  84.       apiConnectptr.p->isIndexOp = false;
  85.       apiConnectptr.p->accumulatingIndexOp = RNIL;
  86.       apiConnectptr.p->executingIndexOp = RNIL;
  87.       apiConnectptr.p->buddyPtr = RNIL;
  88.       apiConnectptr.p->currSavePointId = 0;
  89.     }//for
  90.   apiConnectptr.i = (2 * tiacTmp) - 1;
  91.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  92.   apiConnectptr.p->nextApiConnect = RNIL;
  93.   cfirstfreeApiConnectCopy = tiacTmp;
  94.   guard4 = (3 * tiacTmp) - 1;
  95.   for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4; 
  96.        apiConnectptr.i++) {
  97.     refresh_watch_dog();
  98.     jam();
  99.     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  100.     setApiConTimer(apiConnectptr.i, 0, __LINE__);
  101.     apiConnectptr.p->apiFailState = ZFALSE;
  102.     apiConnectptr.p->apiConnectstate = CS_RESTART;
  103.     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
  104.     apiConnectptr.p->cachePtr = RNIL;
  105.     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
  106.     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
  107.     apiConnectptr.p->commitAckMarker = RNIL;
  108.     apiConnectptr.p->firstTcConnect = RNIL;
  109.     apiConnectptr.p->lastTcConnect = RNIL;
  110.     apiConnectptr.p->triggerPending = false;
  111.     apiConnectptr.p->isIndexOp = false;
  112.     apiConnectptr.p->accumulatingIndexOp = RNIL;
  113.     apiConnectptr.p->executingIndexOp = RNIL;
  114.     apiConnectptr.p->buddyPtr = RNIL;
  115.     apiConnectptr.p->currSavePointId = 0;
  116.   }//for
  117.   apiConnectptr.i = (3 * tiacTmp) - 1;
  118.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  119.   apiConnectptr.p->nextApiConnect = RNIL;
  120.   cfirstfreeApiConnectFail = 2 * tiacTmp;
  121. }//Dbtc::initApiConnect()
  122. void Dbtc::initattrbuf(Signal* signal) 
  123. {
  124.   ndbrequire(cattrbufFilesize > 0);
  125.   for (attrbufptr.i = 0; attrbufptr.i < cattrbufFilesize; attrbufptr.i++) {
  126.     refresh_watch_dog();
  127.     jam();
  128.     ptrAss(attrbufptr, attrbufRecord);
  129.     attrbufptr.p->attrbuf[ZINBUF_NEXT] = attrbufptr.i + 1;  /* NEXT ATTRBUF */
  130.   }//for
  131.   attrbufptr.i = cattrbufFilesize - 1;
  132.   ptrAss(attrbufptr, attrbufRecord);
  133.   attrbufptr.p->attrbuf[ZINBUF_NEXT] = RNIL;    /* NEXT ATTRBUF */
  134.   cfirstfreeAttrbuf = 0;
  135. }//Dbtc::initattrbuf()
  136. void Dbtc::initdatabuf(Signal* signal) 
  137. {
  138.   ndbrequire(cdatabufFilesize > 0);
  139.   for (databufptr.i = 0; databufptr.i < cdatabufFilesize; databufptr.i++) {
  140.     refresh_watch_dog();
  141.     ptrAss(databufptr, databufRecord);
  142.     databufptr.p->nextDatabuf = databufptr.i + 1;
  143.   }//for
  144.   databufptr.i = cdatabufFilesize - 1;
  145.   ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
  146.   databufptr.p->nextDatabuf = RNIL;
  147.   cfirstfreeDatabuf = 0;
  148. }//Dbtc::initdatabuf()
  149. void Dbtc::initgcp(Signal* signal) 
  150. {
  151.   ndbrequire(cgcpFilesize > 0);
  152.   for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
  153.     ptrAss(gcpPtr, gcpRecord);
  154.     gcpPtr.p->nextGcp = gcpPtr.i + 1;
  155.   }//for
  156.   gcpPtr.i = cgcpFilesize - 1;
  157.   ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
  158.   gcpPtr.p->nextGcp = RNIL;
  159.   cfirstfreeGcp = 0;
  160.   cfirstgcp = RNIL;
  161.   clastgcp = RNIL;
  162. }//Dbtc::initgcp()
  163. void Dbtc::inithost(Signal* signal) 
  164. {
  165.   cpackedListIndex = 0;
  166.   ndbrequire(chostFilesize > 0);
  167.   for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
  168.     jam();
  169.     ptrAss(hostptr, hostRecord);
  170.     hostptr.p->hostStatus = HS_DEAD;
  171.     hostptr.p->inPackedList = false;
  172.     hostptr.p->takeOverStatus = TOS_NOT_DEFINED;
  173.     hostptr.p->lqhTransStatus = LTS_IDLE;
  174.     hostptr.p->noOfWordsTCKEYCONF = 0;
  175.     hostptr.p->noOfWordsTCINDXCONF = 0;
  176.     hostptr.p->noOfPackedWordsLqh = 0;
  177.     hostptr.p->hostLqhBlockRef = calcLqhBlockRef(hostptr.i);
  178.   }//for
  179. }//Dbtc::inithost()
  180. void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0, 
  181. Uint32 retRef, Uint32 retData) 
  182. {
  183.   switch (Tdata0) {
  184.   case 0:
  185.     jam();
  186.     initApiConnect(signal);
  187.     break;
  188.   case 1:
  189.     jam();
  190.     initattrbuf(signal);
  191.     break;
  192.   case 2:
  193.     jam();
  194.     initdatabuf(signal);
  195.     break;
  196.   case 3:
  197.     jam();
  198.     initgcp(signal);
  199.     break;
  200.   case 4:
  201.     jam();
  202.     inithost(signal);
  203.     break;
  204.   case 5:
  205.     jam();
  206.     // UNUSED Free to initialise something
  207.     break;
  208.   case 6:
  209.     jam();
  210.     initTable(signal);
  211.     break;
  212.   case 7:
  213.     jam();
  214.     initialiseScanrec(signal);
  215.     break;
  216.   case 8:
  217.     jam();
  218.     initialiseScanOprec(signal);
  219.     break;
  220.   case 9:
  221.     jam();
  222.     initialiseScanFragrec(signal);
  223.     break;
  224.   case 10:
  225.     jam();
  226.     initialiseTcConnect(signal);
  227.     break;
  228.   case 11:
  229.     jam();
  230.     initTcFail(signal);
  231.     {
  232.       ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
  233.       conf->senderRef = reference();
  234.       conf->senderData = retData;
  235.       sendSignal(retRef, GSN_READ_CONFIG_CONF, signal, 
  236.  ReadConfigConf::SignalLength, JBB);
  237.     }
  238.     return;
  239.     break;
  240.   default:
  241.     jam();
  242.     systemErrorLab(signal);
  243.     return;
  244.     break;
  245.   }//switch
  246.   signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
  247.   signal->theData[1] = Tdata0 + 1;
  248.   signal->theData[2] = 0;
  249.   signal->theData[3] = retRef;
  250.   signal->theData[4] = retData;
  251.   sendSignal(DBTC_REF, GSN_CONTINUEB, signal, 5, JBB);
  252. }
  253. /* ========================================================================= */
  254. /* =======                       INITIALISE_SCANREC                  ======= */
  255. /*                                                                           */
  256. /* ========================================================================= */
  257. void Dbtc::initialiseScanrec(Signal* signal) 
  258. {
  259.   ScanRecordPtr scanptr;
  260.   ndbrequire(cscanrecFileSize > 0);
  261.   for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
  262.     refresh_watch_dog();
  263.     jam();
  264.     ptrAss(scanptr, scanRecord);
  265.     new (scanptr.p) ScanRecord();
  266.     scanptr.p->scanState = ScanRecord::IDLE;
  267.     scanptr.p->scanApiRec = RNIL;
  268.     scanptr.p->nextScan = scanptr.i + 1;
  269.   }//for
  270.   scanptr.i = cscanrecFileSize - 1;
  271.   ptrAss(scanptr, scanRecord);
  272.   scanptr.p->nextScan = RNIL;
  273.   cfirstfreeScanrec = 0;
  274. }//Dbtc::initialiseScanrec()
  275. void Dbtc::initialiseScanFragrec(Signal* signal) 
  276. {
  277. }//Dbtc::initialiseScanFragrec()
  278. void Dbtc::initialiseScanOprec(Signal* signal) 
  279. {
  280. }//Dbtc::initialiseScanOprec()
  281. void Dbtc::initTable(Signal* signal) 
  282. {
  283.   ndbrequire(ctabrecFilesize > 0);
  284.   for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
  285.     refresh_watch_dog();
  286.     ptrAss(tabptr, tableRecord);
  287.     tabptr.p->currentSchemaVersion = 0;
  288.     tabptr.p->storedTable = true;
  289.     tabptr.p->tableType = 0;
  290.     tabptr.p->enabled = false;
  291.     tabptr.p->dropping = false;
  292.   }//for
  293. }//Dbtc::initTable()
  294. void Dbtc::initialiseTcConnect(Signal* signal) 
  295. {
  296.   ndbrequire(ctcConnectFilesize >= 2);
  297.   // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
  298.   Uint32 titcTmp = ctcConnectFilesize / 2;
  299.   for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
  300.     refresh_watch_dog();
  301.     jam();
  302.     ptrAss(tcConnectptr, tcConnectRecord);
  303.     tcConnectptr.p->tcConnectstate = OS_RESTART;
  304.     tcConnectptr.p->apiConnect = RNIL;
  305.     tcConnectptr.p->noOfNodes = 0;
  306.     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
  307.   }//for
  308.   tcConnectptr.i = titcTmp - 1;
  309.   ptrAss(tcConnectptr, tcConnectRecord);
  310.   tcConnectptr.p->nextTcConnect = RNIL;
  311.   cfirstfreeTcConnectFail = 0;
  312.   // Place other half in cfirstfreeTcConnect list
  313.   for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize; 
  314.        tcConnectptr.i++) {
  315.     refresh_watch_dog();
  316.     jam();
  317.     ptrAss(tcConnectptr, tcConnectRecord);
  318.     tcConnectptr.p->tcConnectstate = OS_RESTART;
  319.     tcConnectptr.p->apiConnect = RNIL;
  320.     tcConnectptr.p->noOfNodes = 0;
  321.     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
  322.   }//for
  323.   tcConnectptr.i = ctcConnectFilesize - 1;
  324.   ptrAss(tcConnectptr, tcConnectRecord);
  325.   tcConnectptr.p->nextTcConnect = RNIL;
  326.   cfirstfreeTcConnect = titcTmp;
  327.   c_counters.cconcurrentOp = 0;
  328. }//Dbtc::initialiseTcConnect()
  329. /* ------------------------------------------------------------------------- */
  330. /* ----     LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS  */
  331. /*          WAITING FOR COMPLETION.                                          */
  332. /* ------------------------------------------------------------------------- */
  333. void Dbtc::linkGciInGcilist(Signal* signal) 
  334. {
  335.   GcpRecordPtr tmpGcpPointer;
  336.   if (cfirstgcp == RNIL) {
  337.     jam();
  338.     cfirstgcp = gcpPtr.i;
  339.   } else {
  340.     jam();
  341.     tmpGcpPointer.i = clastgcp;
  342.     ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
  343.     tmpGcpPointer.p->nextGcp = gcpPtr.i;
  344.   }//if
  345.   clastgcp = gcpPtr.i;
  346. }//Dbtc::linkGciInGcilist()
  347. /* ------------------------------------------------------------------------- */
  348. /* -------        LINK SECONDARY KEY BUFFER IN OPERATION RECORD      ------- */
  349. /* ------------------------------------------------------------------------- */
  350. void Dbtc::linkKeybuf(Signal* signal) 
  351. {
  352.   seizeDatabuf(signal);
  353.   tmpDatabufptr.i = cachePtr.p->lastKeybuf;
  354.   cachePtr.p->lastKeybuf = databufptr.i;
  355.   if (tmpDatabufptr.i == RNIL) {
  356.     jam();
  357.     cachePtr.p->firstKeybuf = databufptr.i;
  358.   } else {
  359.     jam();
  360.     ptrCheckGuard(tmpDatabufptr, cdatabufFilesize, databufRecord);
  361.     tmpDatabufptr.p->nextDatabuf = databufptr.i;
  362.   }//if
  363. }//Dbtc::linkKeybuf()
  364. /* ------------------------------------------------------------------------- */
  365. /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS  --- */
  366. /* ------------------------------------------------------------------------- */
  367. void Dbtc::linkTcInConnectionlist(Signal* signal) 
  368. {
  369.   /* POINTER FOR THE CONNECT_RECORD */
  370.   TcConnectRecordPtr ltcTcConnectptr;
  371.   tcConnectptr.p->nextTcConnect = RNIL;
  372.   ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
  373.   ptrCheck(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
  374.   apiConnectptr.p->lastTcConnect = tcConnectptr.i;
  375.   if (ltcTcConnectptr.i == RNIL) {
  376.     jam();
  377.     apiConnectptr.p->firstTcConnect = tcConnectptr.i;
  378.   } else {
  379.     jam();
  380.     ptrGuard(ltcTcConnectptr);
  381.     ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
  382.   }//if
  383. }//Dbtc::linkTcInConnectionlist()
  384. /*---------------------------------------------------------------------------*/
  385. /*                    RELEASE_ABORT_RESOURCES                                */
  386. /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
  387. /* SENDS THE ABORT DECISION TO THE APPLICATION.                              */
  388. /*---------------------------------------------------------------------------*/
  389. void Dbtc::releaseAbortResources(Signal* signal) 
  390. {
  391.   TcConnectRecordPtr rarTcConnectptr;
  392.   c_counters.cabortCount++;
  393.   if (apiConnectptr.p->cachePtr != RNIL) {
  394.     cachePtr.i = apiConnectptr.p->cachePtr;
  395.     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
  396.     releaseAttrinfo();
  397.     releaseKeys();
  398.   }//if
  399.   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
  400.   while (tcConnectptr.i != RNIL) {
  401.     jam();
  402.     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  403.     // Clear any markers that were set in CS_RECEIVING state
  404.     clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
  405.     rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
  406.     releaseTcCon();
  407.     tcConnectptr.i = rarTcConnectptr.i;
  408.   }//while
  409.   apiConnectptr.p->firstTcConnect = RNIL;
  410.   apiConnectptr.p->lastTcConnect = RNIL;
  411.   // MASV let state be CS_ABORTING until all 
  412.   // signals in the "air" have been received. Reset to CS_CONNECTED
  413.   // will be done when a TCKEYREQ with start flag is recieved
  414.   // or releaseApiCon is called
  415.   // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
  416.   apiConnectptr.p->apiConnectstate = CS_ABORTING;
  417.   apiConnectptr.p->abortState = AS_IDLE;
  418.   releaseAllSeizedIndexOperations(apiConnectptr.p);
  419.   if(apiConnectptr.p->m_exec_flag || apiConnectptr.p->apiFailState == ZTRUE){
  420.     jam();
  421.     bool ok = false;
  422.     Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
  423.     ReturnSignal ret = apiConnectptr.p->returnsignal;
  424.     apiConnectptr.p->returnsignal = RS_NO_RETURN;
  425.     apiConnectptr.p->m_exec_flag = 0;
  426.     switch(ret){
  427.     case RS_TCROLLBACKCONF:
  428.       jam();
  429.       ok = true;
  430.       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
  431.       signal->theData[1] = apiConnectptr.p->transid[0];
  432.       signal->theData[2] = apiConnectptr.p->transid[1];
  433.       sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
  434.       break;
  435.     case RS_TCROLLBACKREP:{
  436.       jam();
  437.       ok = true;
  438.       TcRollbackRep * const tcRollbackRep = 
  439. (TcRollbackRep *) signal->getDataPtr();
  440.       
  441.       tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
  442.       tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
  443.       tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
  444.       tcRollbackRep->returnCode = apiConnectptr.p->returncode;
  445.       sendSignal(blockRef, GSN_TCROLLBACKREP, signal, 
  446.  TcRollbackRep::SignalLength, JBB);
  447.     }
  448.       break;
  449.     case RS_NO_RETURN:
  450.       jam();
  451.       ok = true;
  452.       break;
  453.     case RS_TCKEYCONF:
  454.     case RS_TC_COMMITCONF:
  455.       break;
  456.     }    
  457.     if(!ok){
  458.       jam();
  459.       ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
  460.       sendSystemError(signal);
  461.     }//if
  462.   }
  463.   setApiConTimer(apiConnectptr.i, 0, 
  464.  100000+c_apiConTimer_line[apiConnectptr.i]);
  465.   if (apiConnectptr.p->apiFailState == ZTRUE) {
  466.     jam();
  467.     handleApiFailState(signal, apiConnectptr.i);
  468.     return;
  469.   }//if
  470. }//Dbtc::releaseAbortResources()
  471. void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr) 
  472. {
  473.   ApiConnectRecordPtr TlocalApiConnectptr;
  474.   TlocalApiConnectptr.i = TapiConnectPtr;
  475.   ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
  476.   TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
  477.   cfirstfreeApiConnect = TlocalApiConnectptr.i;
  478.   setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
  479.   TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
  480.   ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
  481.   TlocalApiConnectptr.p->ndbapiBlockref = 0;
  482. }//Dbtc::releaseApiCon()
  483. void Dbtc::releaseApiConnectFail(Signal* signal) 
  484. {
  485.   apiConnectptr.p->apiConnectstate = CS_RESTART;
  486.   apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
  487.   setApiConTimer(apiConnectptr.i, 0, __LINE__);
  488.   apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
  489.   cfirstfreeApiConnectFail = apiConnectptr.i;
  490. }//Dbtc::releaseApiConnectFail()
  491. void Dbtc::releaseGcp(Signal* signal) 
  492. {
  493.   ptrGuard(gcpPtr);
  494.   gcpPtr.p->nextGcp = cfirstfreeGcp;
  495.   cfirstfreeGcp = gcpPtr.i;
  496. }//Dbtc::releaseGcp()
  497. void Dbtc::releaseKeys() 
  498. {
  499.   UintR Tmp;
  500.   databufptr.i = cachePtr.p->firstKeybuf;
  501.   while (databufptr.i != RNIL) {
  502.     jam();
  503.     ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
  504.     Tmp = databufptr.p->nextDatabuf;
  505.     databufptr.p->nextDatabuf = cfirstfreeDatabuf;
  506.     cfirstfreeDatabuf = databufptr.i;
  507.     databufptr.i = Tmp;
  508.   }//while
  509.   cachePtr.p->firstKeybuf = RNIL;
  510.   cachePtr.p->lastKeybuf = RNIL;
  511. }//Dbtc::releaseKeys()
  512. void Dbtc::releaseTcConnectFail(Signal* signal) 
  513. {
  514.   ptrGuard(tcConnectptr);
  515.   tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
  516.   cfirstfreeTcConnectFail = tcConnectptr.i;
  517. }//Dbtc::releaseTcConnectFail()
  518. void Dbtc::seizeApiConnect(Signal* signal) 
  519. {
  520.   if (cfirstfreeApiConnect != RNIL) {
  521.     jam();
  522.     terrorCode = ZOK;
  523.     apiConnectptr.i = cfirstfreeApiConnect;     /* ASSIGN A FREE RECORD FROM */
  524.     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  525.     cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
  526.     apiConnectptr.p->nextApiConnect = RNIL;
  527.     setApiConTimer(apiConnectptr.i, 0, __LINE__);
  528.     apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
  529.     apiConnectptr.p->triggerPending = false;
  530.     apiConnectptr.p->isIndexOp = false;
  531.   } else {
  532.     jam();
  533.     terrorCode = ZNO_FREE_API_CONNECTION;
  534.   }//if
  535. }//Dbtc::seizeApiConnect()
  536. void Dbtc::seizeApiConnectFail(Signal* signal) 
  537. {
  538.   apiConnectptr.i = cfirstfreeApiConnectFail;
  539.   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  540.   cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
  541. }//Dbtc::seizeApiConnectFail()
  542. void Dbtc::seizeDatabuf(Signal* signal) 
  543. {
  544.   databufptr.i = cfirstfreeDatabuf;
  545.   ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
  546.   cfirstfreeDatabuf = databufptr.p->nextDatabuf;
  547.   databufptr.p->nextDatabuf = RNIL;
  548. }//Dbtc::seizeDatabuf()
  549. void Dbtc::seizeTcConnect(Signal* signal) 
  550. {
  551.   tcConnectptr.i = cfirstfreeTcConnect;
  552.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  553.   cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
  554.   c_counters.cconcurrentOp++;
  555.   tcConnectptr.p->isIndexOp = false;
  556. }//Dbtc::seizeTcConnect()
  557. void Dbtc::seizeTcConnectFail(Signal* signal) 
  558. {
  559.   tcConnectptr.i = cfirstfreeTcConnectFail;
  560.   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
  561.   cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
  562. }//Dbtc::seizeTcConnectFail()
  563. void Dbtc::sendAttrinfo(Signal* signal,
  564.                         UintR TattrinfoPtr,
  565.                         AttrbufRecord * const regAttrPtr,
  566.                         UintR TBref) 
  567. {
  568.   UintR TdataPos;
  569.   UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6, sig7;
  570.   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
  571.   TdataPos = regAttrPtr->attrbuf[ZINBUF_DATA_LEN];
  572.   sig0 = TattrinfoPtr;
  573.   sig1 = regApiPtr->transid[0];
  574.   sig2 = regApiPtr->transid[1];
  575.   signal->theData[0] = sig0;
  576.   signal->theData[1] = sig1;
  577.   signal->theData[2] = sig2;
  578.   sig0 = regAttrPtr->attrbuf[0];
  579.   sig1 = regAttrPtr->attrbuf[1];
  580.   sig2 = regAttrPtr->attrbuf[2];
  581.   sig3 = regAttrPtr->attrbuf[3];
  582.   sig4 = regAttrPtr->attrbuf[4];
  583.   sig5 = regAttrPtr->attrbuf[5];
  584.   sig6 = regAttrPtr->attrbuf[6];
  585.   sig7 = regAttrPtr->attrbuf[7];
  586.   signal->theData[3] = sig0;
  587.   signal->theData[4] = sig1;
  588.   signal->theData[5] = sig2;
  589.   signal->theData[6] = sig3;
  590.   signal->theData[7] = sig4;
  591.   signal->theData[8] = sig5;
  592.   signal->theData[9] = sig6;
  593.   signal->theData[10] = sig7;
  594.   if (TdataPos > 8) {
  595.     sig0 = regAttrPtr->attrbuf[8];
  596.     sig1 = regAttrPtr->attrbuf[9];
  597.     sig2 = regAttrPtr->attrbuf[10];
  598.     sig3 = regAttrPtr->attrbuf[11];
  599.     sig4 = regAttrPtr->attrbuf[12];
  600.     sig5 = regAttrPtr->attrbuf[13];
  601.     sig6 = regAttrPtr->attrbuf[14];
  602.     jam();
  603.     signal->theData[11] = sig0;
  604.     signal->theData[12] = sig1;
  605.     signal->theData[13] = sig2;
  606.     signal->theData[14] = sig3;
  607.     signal->theData[15] = sig4;
  608.     signal->theData[16] = sig5;
  609.     signal->theData[17] = sig6;
  610.     if (TdataPos > 15) {
  611.       sig0 = regAttrPtr->attrbuf[15];
  612.       sig1 = regAttrPtr->attrbuf[16];
  613.       sig2 = regAttrPtr->attrbuf[17];
  614.       sig3 = regAttrPtr->attrbuf[18];
  615.       sig4 = regAttrPtr->attrbuf[19];
  616.       sig5 = regAttrPtr->attrbuf[20];
  617.       sig6 = regAttrPtr->attrbuf[21];
  618.       jam();
  619.       signal->theData[18] = sig0;
  620.       signal->theData[19] = sig1;
  621.       signal->theData[20] = sig2;
  622.       signal->theData[21] = sig3;
  623.       signal->theData[22] = sig4;
  624.       signal->theData[23] = sig5;
  625.       signal->theData[24] = sig6;
  626.     }//if
  627.   }//if
  628.   sendSignal(TBref, GSN_ATTRINFO, signal, TdataPos + 3, JBB);
  629. }//Dbtc::sendAttrinfo()
  630. void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr) 
  631. {
  632.   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
  633.   signal->theData[1] = TapiConPtr;
  634.   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
  635. }//Dbtc::sendContinueTimeOutControl()
  636. void Dbtc::sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len) 
  637. {
  638.   signal->theData[0] = tcConnectptr.i;
  639.   signal->theData[1] = apiConnectptr.p->transid[0];
  640.   signal->theData[2] = apiConnectptr.p->transid[1];
  641.   signal->theData[3] = cdata[0];
  642.   signal->theData[4] = cdata[1];
  643.   signal->theData[5] = cdata[2];
  644.   signal->theData[6] = cdata[3];
  645.   signal->theData[7] = cdata[4];
  646.   signal->theData[8] = cdata[5];
  647.   signal->theData[9] = cdata[6];
  648.   signal->theData[10] = cdata[7];
  649.   signal->theData[11] = cdata[8];
  650.   signal->theData[12] = cdata[9];
  651.   signal->theData[13] = cdata[10];
  652.   signal->theData[14] = cdata[11];
  653.   signal->theData[15] = cdata[12];
  654.   signal->theData[16] = cdata[13];
  655.   signal->theData[17] = cdata[14];
  656.   signal->theData[18] = cdata[15];
  657.   signal->theData[19] = cdata[16];
  658.   signal->theData[20] = cdata[17];
  659.   signal->theData[21] = cdata[18];
  660.   signal->theData[22] = cdata[19];
  661.   sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
  662. }//Dbtc::sendKeyinfo()
  663. void Dbtc::sendSystemError(Signal* signal) 
  664. {
  665.   progError(0, 0);
  666. }//Dbtc::sendSystemError()
  667. /* ========================================================================= */
  668. /* -------             LINK ACTUAL GCP OUT OF LIST                   ------- */
  669. /* ------------------------------------------------------------------------- */
  670. void Dbtc::unlinkGcp(Signal* signal) 
  671. {
  672.   if (cfirstgcp == gcpPtr.i) {
  673.     jam();
  674.     cfirstgcp = gcpPtr.p->nextGcp;
  675.     if (gcpPtr.i == clastgcp) {
  676.       jam();
  677.       clastgcp = RNIL;
  678.     }//if
  679.   } else {
  680.     jam();
  681.     /* -------------------------------------------------------------------- 
  682.      * WE ARE TRYING TO REMOVE A GLOBAL CHECKPOINT WHICH WAS NOT THE OLDEST. 
  683.      * THIS IS A SYSTEM ERROR.                                              
  684.      * ------------------------------------------------------------------- */
  685.     sendSystemError(signal);
  686.   }//if
  687.   gcpPtr.p->nextGcp = cfirstfreeGcp;
  688.   cfirstfreeGcp = gcpPtr.i;
  689. }//Dbtc::unlinkGcp()
  690. void
  691. Dbtc::execDUMP_STATE_ORD(Signal* signal)
  692. {
  693.   DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
  694.   if(signal->theData[0] == DumpStateOrd::CommitAckMarkersSize){
  695.     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
  696.               m_commitAckMarkerPool.getNoOfFree(),
  697.               m_commitAckMarkerPool.getSize());
  698.   }
  699.   if(signal->theData[0] == DumpStateOrd::CommitAckMarkersDump){
  700.     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
  701.               m_commitAckMarkerPool.getNoOfFree(),
  702.               m_commitAckMarkerPool.getSize());
  703.     
  704.     CommitAckMarkerIterator iter;
  705.     for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
  706.         m_commitAckMarkerHash.next(iter)){
  707.       infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
  708.                 " Api: %d Lghs(%d): %d %d %d %d bucket = %d",
  709.                 iter.curr.i,
  710.                 iter.curr.p->transid1,
  711.                 iter.curr.p->transid2,
  712.                 iter.curr.p->apiNodeId,
  713.                 iter.curr.p->noOfLqhs,
  714.                 iter.curr.p->lqhNodeId[0],
  715.                 iter.curr.p->lqhNodeId[1],
  716.                 iter.curr.p->lqhNodeId[2],
  717.                 iter.curr.p->lqhNodeId[3],
  718.                 iter.bucket);
  719.     }
  720.   }
  721.   // Dump all ScanFragRecs
  722.   if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
  723.     Uint32 recordNo = 0;
  724.     if (signal->getLength() == 1)
  725.       infoEvent("TC: Dump all ScanFragRec - size: %d",
  726. cscanFragrecFileSize);
  727.     else if (signal->getLength() == 2)
  728.       recordNo = dumpState->args[1];
  729.     else
  730.       return;
  731.     
  732.     dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
  733.     dumpState->args[1] = recordNo;
  734.     execDUMP_STATE_ORD(signal);
  735.     if (recordNo < cscanFragrecFileSize-1){
  736.       dumpState->args[0] = DumpStateOrd::TcDumpAllScanFragRec;
  737.       dumpState->args[1] = recordNo+1;
  738.       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
  739.     }
  740.   }
  741.   // Dump one ScanFragRec
  742.   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
  743.     Uint32 recordNo = RNIL;
  744.     if (signal->getLength() == 2)
  745.       recordNo = dumpState->args[1];
  746.     else
  747.       return;
  748.     if (recordNo >= cscanFragrecFileSize)
  749.       return;
  750.     ScanFragRecPtr sfp;
  751.     sfp.i = recordNo;
  752.     c_scan_frag_pool.getPtr(sfp);
  753.     infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
  754.       sfp.i,
  755.       sfp.p->scanFragState,
  756.       sfp.p->scanFragId);
  757.     infoEvent(" nodeid=%d, timer=%d",
  758.       refToNode(sfp.p->lqhBlockref),
  759.       sfp.p->scanFragTimer);
  760.   }
  761.   // Dump all ScanRecords
  762.   if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanRec){
  763.     Uint32 recordNo = 0;
  764.     if (signal->getLength() == 1)
  765.       infoEvent("TC: Dump all ScanRecord - size: %d",
  766. cscanrecFileSize);
  767.     else if (signal->getLength() == 2)
  768.       recordNo = dumpState->args[1];
  769.     else
  770.       return;  
  771.     dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
  772.     dumpState->args[1] = recordNo;
  773.     execDUMP_STATE_ORD(signal);
  774.     
  775.     if (recordNo < cscanrecFileSize-1){
  776.       dumpState->args[0] = DumpStateOrd::TcDumpAllScanRec;
  777.       dumpState->args[1] = recordNo+1;
  778.       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
  779.     }
  780.   }
  781.   // Dump all active ScanRecords
  782.   if (dumpState->args[0] == DumpStateOrd::TcDumpAllActiveScanRec){
  783.     Uint32 recordNo = 0;     
  784.     if (signal->getLength() == 1)
  785.       infoEvent("TC: Dump active ScanRecord - size: %d",
  786. cscanrecFileSize);
  787.     else if (signal->getLength() == 2)
  788.       recordNo = dumpState->args[1];
  789.     else
  790.       return;
  791.     ScanRecordPtr sp;
  792.     sp.i = recordNo;
  793.     ptrAss(sp, scanRecord);
  794.     if (sp.p->scanState != ScanRecord::IDLE){
  795.       dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
  796.       dumpState->args[1] = recordNo;
  797.       execDUMP_STATE_ORD(signal);
  798.     }
  799.     if (recordNo < cscanrecFileSize-1){
  800.       dumpState->args[0] = DumpStateOrd::TcDumpAllActiveScanRec;
  801.       dumpState->args[1] = recordNo+1;
  802.       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
  803.     }
  804.   }
  805.   // Dump one ScanRecord
  806.   // and associated ScanFragRec and ApiConnectRecord
  807.   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
  808.     Uint32 recordNo = RNIL;
  809.     if (signal->getLength() == 2)
  810.       recordNo = dumpState->args[1];
  811.     else
  812.       return;
  813.     if (recordNo >= cscanrecFileSize)
  814.       return;
  815.     ScanRecordPtr sp;
  816.     sp.i = recordNo;
  817.     ptrAss(sp, scanRecord);
  818.     infoEvent("Dbtc::ScanRecord[%d]: state=%d"
  819.       "nextfrag=%d, nofrag=%d",
  820.       sp.i,
  821.       sp.p->scanState,
  822.       sp.p->scanNextFragId,
  823.       sp.p->scanNoFrag);
  824.     infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
  825.       sp.p->scanAiLength,
  826.       sp.p->scanParallel,
  827.       sp.p->scanReceivedOperations,
  828.       sp.p->batch_size_rows);
  829.     infoEvent(" schv=%d, tab=%d, sproc=%d",
  830.       sp.p->scanSchemaVersion,
  831.       sp.p->scanTableref,
  832.       sp.p->scanStoredProcId);
  833.     infoEvent(" apiRec=%d, next=%d",
  834.       sp.p->scanApiRec, sp.p->nextScan);
  835.     if (sp.p->scanState != ScanRecord::IDLE){
  836.       // Request dump of ScanFragRec
  837.       ScanFragRecPtr sfptr;
  838. #define DUMP_SFR(x){
  839.       ScanFragList list(c_scan_frag_pool, x);
  840.       for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){
  841. dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; 
  842. dumpState->args[1] = sfptr.i;
  843. execDUMP_STATE_ORD(signal);
  844.       }}
  845.       DUMP_SFR(sp.p->m_running_scan_frags);
  846.       DUMP_SFR(sp.p->m_queued_scan_frags);
  847.       DUMP_SFR(sp.p->m_delivered_scan_frags);
  848.       // Request dump of ApiConnectRecord
  849.       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
  850.       dumpState->args[1] = sp.p->scanApiRec;
  851.       execDUMP_STATE_ORD(signal);      
  852.     }
  853.   }
  854.   // Dump all ApiConnectRecord(s)
  855.   if (dumpState->args[0] == DumpStateOrd::TcDumpAllApiConnectRec){
  856.     Uint32 recordNo = 0;
  857.     if (signal->getLength() == 1)
  858.       infoEvent("TC: Dump all ApiConnectRecord - size: %d",
  859. capiConnectFilesize);
  860.     else if (signal->getLength() == 2)
  861.       recordNo = dumpState->args[1];
  862.     else
  863.       return;
  864.     dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
  865.     dumpState->args[1] = recordNo;
  866.     execDUMP_STATE_ORD(signal);
  867.     
  868.     if (recordNo < capiConnectFilesize-1){
  869.       dumpState->args[0] = DumpStateOrd::TcDumpAllApiConnectRec;
  870.       dumpState->args[1] = recordNo+1;
  871.       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
  872.     }
  873.   }
  874.   // Dump one ApiConnectRecord
  875.   if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
  876.     Uint32 recordNo = RNIL;
  877.     if (signal->getLength() == 2)
  878.       recordNo = dumpState->args[1];
  879.     else
  880.       return;
  881.     if (recordNo >= capiConnectFilesize)
  882.       return;
  883.     ApiConnectRecordPtr ap;
  884.     ap.i = recordNo;
  885.     ptrAss(ap, apiConnectRecord);
  886.     infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
  887.       "apiFailState=%d",
  888.       ap.i,
  889.       ap.p->apiConnectstate,
  890.       ap.p->abortState,
  891.       ap.p->apiFailState);
  892.     infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
  893.       ap.p->transid[0],
  894.       ap.p->transid[1],
  895.       ap.p->ndbapiBlockref,
  896.       ap.p->apiScanRec);
  897.     infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
  898.       "retsig=%d",
  899.       ctcTimer, getApiConTimer(ap.i),
  900.       ap.p->counter,
  901.       ap.p->returncode,
  902.       ap.p->returnsignal);
  903.     infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
  904.       "tckeyrec=%d",
  905.       ap.p->lqhkeyconfrec,
  906.       ap.p->lqhkeyreqrec,
  907.       ap.p->tckeyrec);
  908.     infoEvent(" next=%d ",
  909.       ap.p->nextApiConnect);
  910.   }
  911.   if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
  912.     jam();
  913.     if(signal->getLength() > 1){
  914.       set_timeout_value(signal->theData[1]);
  915.     }
  916.   }
  917.   if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
  918.     jam();
  919.     if(signal->getLength() > 1){
  920.       set_appl_timeout_value(signal->theData[1]);
  921.     }
  922.   }
  923.   if (dumpState->args[0] == DumpStateOrd::StartTcTimer){
  924.     c_counters.c_trans_status = TransCounters::Started;
  925.     c_counters.reset();
  926.   }
  927.   if (dumpState->args[0] == DumpStateOrd::StopTcTimer){
  928.     c_counters.c_trans_status = TransCounters::Off;
  929.     Uint32 len = c_counters.report(signal);
  930.     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
  931.     c_counters.reset();
  932.   }
  933.   
  934.   if (dumpState->args[0] == DumpStateOrd::StartPeriodicTcTimer){
  935.     c_counters.c_trans_status = TransCounters::Timer;
  936.     c_counters.reset();
  937.     signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
  938.     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
  939.   }
  940.   if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
  941.   {
  942.     static int frequency = 1;
  943.     if (signal->getLength() > 1)
  944.       frequency = signal->theData[1];
  945.     else
  946.       if (refToBlock(signal->getSendersBlockRef()) != DBTC)
  947. frequency = 1;
  948.     
  949.     if (frequency)
  950.     {
  951.       dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
  952.       execDUMP_STATE_ORD(signal);
  953.       dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
  954.       
  955.       Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
  956.       sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
  957.     }
  958.   }
  959.   
  960.   if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
  961.   {
  962.     infoEvent("IndexOpCount: pool: %d free: %d", 
  963.       c_theIndexOperationPool.getSize(),
  964.       c_theIndexOperationPool.getNoOfFree());
  965.   }
  966. }//Dbtc::execDUMP_STATE_ORD()
  967. void Dbtc::execSET_VAR_REQ(Signal* signal)
  968. {
  969. #if 0
  970.   SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0];
  971.   ConfigParamId var = setVarReq->variable();
  972.   int val = setVarReq->value();
  973.   switch (var) {
  974.   case TransactionInactiveTime:
  975.     jam();
  976.     set_appl_timeout_value(val);
  977.     break;
  978.   case TransactionDeadlockDetectionTimeout:
  979.     set_timeout_value(val);
  980.     sendSignal(CMVMI_REF, GSN_SET_VAR_CONF, signal, 1, JBB);
  981.     break;
  982.   case NoOfConcurrentProcessesHandleTakeover:
  983.     set_no_parallel_takeover(val);
  984.     sendSignal(CMVMI_REF, GSN_SET_VAR_CONF, signal, 1, JBB);
  985.     break;
  986.   default:
  987.     sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB);
  988.   } // switch
  989. #endif
  990. }
  991. void Dbtc::execABORT_ALL_REQ(Signal* signal)
  992. {
  993.   jamEntry();
  994.   AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
  995.   AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
  996.   
  997.   const Uint32 senderData = req->senderData;
  998.   const BlockReference senderRef = req->senderRef;
  999.   
  1000.   if(getAllowStartTransaction() == true && !getNodeState().getSingleUserMode()){
  1001.     jam();
  1002.     ref->senderData = senderData;
  1003.     ref->errorCode = AbortAllRef::InvalidState;
  1004.     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal, 
  1005.        AbortAllRef::SignalLength, JBB);
  1006.     return;
  1007.   }
  1008.   
  1009.   if(c_abortRec.clientRef != 0){
  1010.     jam();
  1011.     
  1012.     ref->senderData = senderData;
  1013.     ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
  1014.     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal, 
  1015.        AbortAllRef::SignalLength, JBB);
  1016.     return;
  1017.   }
  1018.   if(refToNode(senderRef) != getOwnNodeId()){
  1019.     jam();
  1020.     
  1021.     ref->senderData = senderData;
  1022.     ref->errorCode = AbortAllRef::FunctionNotImplemented;
  1023.     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal, 
  1024.        AbortAllRef::SignalLength, JBB);
  1025.     return;
  1026.   }
  1027.   c_abortRec.clientRef = senderRef;
  1028.   c_abortRec.clientData = senderData;
  1029.   c_abortRec.oldTimeOutValue = ctimeOutValue;
  1030.   
  1031.   ctimeOutValue = 0;
  1032.   const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
  1033.   
  1034.   checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
  1035. }
  1036. void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
  1037. {
  1038.   
  1039.   ndbrequire(c_abortRec.clientRef != 0);
  1040.   
  1041.   if(sleepTime > 0){
  1042.     jam();
  1043.     
  1044.     sleepTime -= 1;
  1045.     signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
  1046.     signal->theData[1] = sleepTime;
  1047.     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
  1048.     return;
  1049.   }
  1050.   AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
  1051.   conf->senderData = c_abortRec.clientData;
  1052.   sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal, 
  1053.      AbortAllConf::SignalLength, JBB);
  1054.   
  1055.   ctimeOutValue = c_abortRec.oldTimeOutValue;
  1056.   c_abortRec.clientRef = 0;
  1057. }
  1058. /* **************************************************************** */
  1059. /* ---------------------------------------------------------------- */
  1060. /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
  1061. /* ---------------------------------------------------------------- */
  1062. /* **************************************************************** */
  1063. void Dbtc::execCREATE_TRIG_REQ(Signal* signal)
  1064. {
  1065.   jamEntry();
  1066.   CreateTrigReq * const createTrigReq = 
  1067.     (CreateTrigReq *)&signal->theData[0];
  1068.   TcDefinedTriggerData* triggerData;
  1069.   DefinedTriggerPtr triggerPtr;
  1070.   BlockReference sender = signal->senderBlockRef();
  1071.   releaseSections(signal);
  1072.   
  1073.   triggerPtr.i = createTrigReq->getTriggerId();
  1074.   if (ERROR_INSERTED(8033) ||
  1075.       !c_theDefinedTriggers.seizeId(triggerPtr, 
  1076.     createTrigReq->getTriggerId())) {
  1077.     jam();
  1078.     CLEAR_ERROR_INSERT_VALUE;
  1079.     // Failed to allocate trigger record
  1080.     CreateTrigRef * const createTrigRef =  
  1081.       (CreateTrigRef *)&signal->theData[0];
  1082.     
  1083.     createTrigRef->setConnectionPtr(createTrigReq->getConnectionPtr());
  1084.     createTrigRef->setErrorCode(CreateTrigRef::TooManyTriggers);
  1085.     sendSignal(sender, GSN_CREATE_TRIG_REF, 
  1086.                signal, CreateTrigRef::SignalLength, JBB);
  1087.     return;
  1088.   }
  1089.   triggerData = triggerPtr.p;
  1090.   triggerData->triggerId = createTrigReq->getTriggerId();
  1091.   triggerData->triggerType = createTrigReq->getTriggerType();
  1092.   triggerData->triggerEvent = createTrigReq->getTriggerEvent();
  1093.   triggerData->attributeMask = createTrigReq->getAttributeMask();
  1094.   if (triggerData->triggerType == TriggerType::SECONDARY_INDEX)
  1095.     triggerData->indexId = createTrigReq->getIndexId();
  1096.   CreateTrigConf * const createTrigConf =  
  1097.     (CreateTrigConf *)&signal->theData[0];
  1098.   
  1099.   createTrigConf->setConnectionPtr(createTrigReq->getConnectionPtr());
  1100.   sendSignal(sender, GSN_CREATE_TRIG_CONF, 
  1101.              signal, CreateTrigConf::SignalLength, JBB);
  1102. }
  1103. void Dbtc::execDROP_TRIG_REQ(Signal* signal)
  1104. {
  1105.   jamEntry();
  1106.   DropTrigReq * const dropTrigReq =  (DropTrigReq *)&signal->theData[0];
  1107.   BlockReference sender = signal->senderBlockRef();
  1108.   if (ERROR_INSERTED(8035) ||
  1109.       (c_theDefinedTriggers.getPtr(dropTrigReq->getTriggerId())) == NULL) {
  1110.     jam();
  1111.     CLEAR_ERROR_INSERT_VALUE;
  1112.     // Failed to find find trigger record
  1113.     DropTrigRef * const dropTrigRef =  (DropTrigRef *)&signal->theData[0];
  1114.     dropTrigRef->setConnectionPtr(dropTrigReq->getConnectionPtr());
  1115.     dropTrigRef->setErrorCode(DropTrigRef::TriggerNotFound);
  1116.     sendSignal(sender, GSN_DROP_TRIG_REF, 
  1117.                signal, DropTrigRef::SignalLength, JBB);
  1118.     return;
  1119.   }
  1120.   // Release trigger record
  1121.   c_theDefinedTriggers.release(dropTrigReq->getTriggerId());
  1122.   DropTrigConf * const dropTrigConf =  (DropTrigConf *)&signal->theData[0];
  1123.   
  1124.   dropTrigConf->setConnectionPtr(dropTrigReq->getConnectionPtr());
  1125.   sendSignal(sender, GSN_DROP_TRIG_CONF, 
  1126.              signal, DropTrigConf::SignalLength, JBB);
  1127. }
  1128. void Dbtc::execCREATE_INDX_REQ(Signal* signal)
  1129. {
  1130.   jamEntry();
  1131.   CreateIndxReq * const createIndxReq =  
  1132.     (CreateIndxReq *)signal->getDataPtr();
  1133.   TcIndexData* indexData;
  1134.   TcIndexDataPtr indexPtr;
  1135.   BlockReference sender = signal->senderBlockRef();
  1136.   
  1137.   if (ERROR_INSERTED(8034) ||
  1138.       !c_theIndexes.seizeId(indexPtr, createIndxReq->getIndexId())) {
  1139.     jam();
  1140.     CLEAR_ERROR_INSERT_VALUE;
  1141.     // Failed to allocate index record
  1142.      CreateIndxRef * const createIndxRef =  
  1143.        (CreateIndxRef *)&signal->theData[0];
  1144.      createIndxRef->setConnectionPtr(createIndxReq->getConnectionPtr());
  1145.      createIndxRef->setErrorCode(CreateIndxRef::TooManyIndexes);
  1146.      releaseSections(signal);
  1147.      sendSignal(sender, GSN_CREATE_INDX_REF, 
  1148.                 signal, CreateIndxRef::SignalLength, JBB);
  1149.      return;
  1150.   }
  1151.   indexData = indexPtr.p;
  1152.   // Indexes always start in state IS_BUILDING
  1153.   // Will become IS_ONLINE in execALTER_INDX_REQ
  1154.   indexData->indexState = IS_BUILDING;
  1155.   indexData->indexId = indexPtr.i;
  1156.   indexData->primaryTableId = createIndxReq->getTableId();
  1157.   // So far need only attribute count
  1158.   SegmentedSectionPtr ssPtr;
  1159.   signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
  1160.   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
  1161.   r0.reset(); // undo implicit first()
  1162.   if (!r0.getWord(&indexData->attributeList.sz) ||
  1163.       !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
  1164.     ndbrequire(false);
  1165.   }
  1166.   indexData->primaryKeyPos = indexData->attributeList.sz;
  1167.   releaseSections(signal);
  1168.   
  1169.   CreateIndxConf * const createIndxConf =  
  1170.     (CreateIndxConf *)&signal->theData[0];
  1171.   createIndxConf->setConnectionPtr(createIndxReq->getConnectionPtr());
  1172.   createIndxConf->setTableId(createIndxReq->getTableId());
  1173.   createIndxConf->setIndexId(createIndxReq->getIndexId());
  1174.   sendSignal(sender, GSN_CREATE_INDX_CONF, 
  1175.              signal, CreateIndxConf::SignalLength, JBB);
  1176. }
  1177. void Dbtc::execALTER_INDX_REQ(Signal* signal)
  1178. {
  1179.   jamEntry();
  1180.   AlterIndxReq * const alterIndxReq =  (AlterIndxReq *)signal->getDataPtr();
  1181.   TcIndexData* indexData;
  1182.   //BlockReference sender = signal->senderBlockRef();
  1183.   BlockReference sender = (BlockReference) alterIndxReq->getUserRef();
  1184.   Uint32 connectionPtr = alterIndxReq->getConnectionPtr();
  1185.   AlterIndxReq::RequestType requestType = alterIndxReq->getRequestType();
  1186.   Uint32 tableId = alterIndxReq->getTableId();
  1187.   Uint32 indexId = alterIndxReq->getIndexId();
  1188.   bool online = (alterIndxReq->getOnline() == 1) ? true : false;
  1189.   if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
  1190.     jam();
  1191.     // Failed to find index record
  1192.     AlterIndxRef * const alterIndxRef =  
  1193.       (AlterIndxRef *)signal->getDataPtrSend();
  1194.     
  1195.     alterIndxRef->setUserRef(reference());
  1196.     alterIndxRef->setConnectionPtr(connectionPtr);
  1197.     alterIndxRef->setRequestType(requestType);
  1198.     alterIndxRef->setTableId(tableId);
  1199.     alterIndxRef->setIndexId(indexId);
  1200.     alterIndxRef->setErrorCode(AlterIndxRef::IndexNotFound);
  1201.     alterIndxRef->setErrorLine(__LINE__);
  1202.     alterIndxRef->setErrorNode(getOwnNodeId());
  1203.     sendSignal(sender, GSN_ALTER_INDX_REF, 
  1204.        signal, AlterIndxRef::SignalLength, JBB);
  1205.     return;
  1206.   }
  1207.   // Found index record, alter it's state  
  1208.   if (online) {
  1209.     jam();
  1210.     indexData->indexState = IS_ONLINE;
  1211.   } else {
  1212.     jam();
  1213.     indexData->indexState = IS_BUILDING;
  1214.   }//if 
  1215.   AlterIndxConf * const alterIndxConf =  
  1216.     (AlterIndxConf *)signal->getDataPtrSend();
  1217.   
  1218.   alterIndxConf->setUserRef(reference());
  1219.   alterIndxConf->setConnectionPtr(connectionPtr);
  1220.   alterIndxConf->setRequestType(requestType);
  1221.   alterIndxConf->setTableId(tableId);
  1222.   alterIndxConf->setIndexId(indexId);
  1223.   sendSignal(sender, GSN_ALTER_INDX_CONF, 
  1224.      signal, AlterIndxConf::SignalLength, JBB);
  1225. }
  1226. void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
  1227. {
  1228.   jamEntry();
  1229.   FireTrigOrd * const fireOrd =  (FireTrigOrd *)signal->getDataPtr();
  1230.   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
  1231.   ApiConnectRecordPtr transPtr;
  1232.   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
  1233.   TcConnectRecordPtr opPtr;
  1234.   /**
  1235.    * TODO
  1236.    * Check transid,
  1237.    * Fix overload i.e invalid word count
  1238.    */
  1239.   TcFiredTriggerData key;
  1240.   key.fireingOperation = fireOrd->getConnectionPtr();
  1241.   key.nodeId = refToNode(signal->getSendersBlockRef());
  1242.   FiredTriggerPtr trigPtr;
  1243.   if(c_firedTriggerHash.find(trigPtr, key)){
  1244.     
  1245.     c_firedTriggerHash.remove(trigPtr);
  1246.     bool ok = trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
  1247.     ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
  1248.     ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
  1249.     if(ok){
  1250.       opPtr.i = key.fireingOperation;
  1251.       ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
  1252.       transPtr.i = opPtr.p->apiConnect;
  1253.       transPtr.p = &localApiConnectRecord[transPtr.i];
  1254.       
  1255.       opPtr.p->noReceivedTriggers++;
  1256.       opPtr.p->triggerExecutionCount++;
  1257.     
  1258.       // Insert fired trigger in execution queue
  1259.       transPtr.p->theFiredTriggers.add(trigPtr);
  1260.       if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
  1261. executeTriggers(signal, &transPtr);
  1262.       }
  1263.       return;
  1264.     }
  1265.     jam();
  1266.     c_theFiredTriggerPool.release(trigPtr);
  1267.   }
  1268.   jam();
  1269.   /**
  1270.    * Failed to find record or invalid word counts
  1271.    */
  1272.   ndbrequire(false);
  1273. }
  1274. void Dbtc::execTRIG_ATTRINFO(Signal* signal)
  1275. {
  1276.   jamEntry();
  1277.   TrigAttrInfo * const trigAttrInfo =  (TrigAttrInfo *)signal->getDataPtr();
  1278.   Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
  1279.   const Uint32 *src = trigAttrInfo->getData();
  1280.   FiredTriggerPtr firedTrigPtr;
  1281.   
  1282.   TcFiredTriggerData key;
  1283.   key.fireingOperation = trigAttrInfo->getConnectionPtr();
  1284.   key.nodeId = refToNode(signal->getSendersBlockRef());
  1285.   if(!c_firedTriggerHash.find(firedTrigPtr, key)){
  1286.     jam();
  1287.     if(!c_firedTriggerHash.seize(firedTrigPtr)){
  1288.       jam();
  1289.       /**
  1290.        * Will be handled when FIRE_TRIG_ORD arrives
  1291.        */
  1292.       ndbout_c("op: %d node: %d failed to seize",
  1293.        key.fireingOperation, key.nodeId);
  1294.       return;
  1295.     }
  1296.     ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
  1297.        firedTrigPtr.p->beforeValues.getSize() == 0 &&
  1298.        firedTrigPtr.p->afterValues.getSize() == 0);
  1299.     
  1300.     firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
  1301.     firedTrigPtr.p->fireingOperation = key.fireingOperation;
  1302.     firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
  1303.     c_firedTriggerHash.add(firedTrigPtr);
  1304.   }
  1305.   
  1306.   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
  1307.   switch (trigAttrInfo->getAttrInfoType()) {
  1308.   case(TrigAttrInfo::PRIMARY_KEY):
  1309.     jam();
  1310.     {
  1311.       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
  1312.       buf.append(src, attrInfoLength);
  1313.     }
  1314.     break;
  1315.   case(TrigAttrInfo::BEFORE_VALUES):
  1316.     jam();
  1317.     {
  1318.       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
  1319.       buf.append(src, attrInfoLength);
  1320.     }
  1321.     break;
  1322.   case(TrigAttrInfo::AFTER_VALUES):
  1323.     jam();
  1324.     {
  1325.       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
  1326.       buf.append(src, attrInfoLength);
  1327.     }
  1328.     break;
  1329.   default:
  1330.     ndbrequire(false);
  1331.   }
  1332. }
  1333. void Dbtc::execDROP_INDX_REQ(Signal* signal)
  1334. {
  1335.   jamEntry();
  1336.   DropIndxReq * const dropIndxReq =  (DropIndxReq *)signal->getDataPtr();
  1337.   TcIndexData* indexData;
  1338.   BlockReference sender = signal->senderBlockRef();
  1339.   
  1340.   if (ERROR_INSERTED(8036) ||
  1341.       (indexData = c_theIndexes.getPtr(dropIndxReq->getIndexId())) == NULL) {
  1342.     jam();
  1343.     CLEAR_ERROR_INSERT_VALUE;
  1344.     // Failed to find index record
  1345.     DropIndxRef * const dropIndxRef =  
  1346.       (DropIndxRef *)signal->getDataPtrSend();
  1347.     dropIndxRef->setConnectionPtr(dropIndxReq->getConnectionPtr());
  1348.     dropIndxRef->setErrorCode(DropIndxRef::IndexNotFound);
  1349.     sendSignal(sender, GSN_DROP_INDX_REF, 
  1350.                signal, DropIndxRef::SignalLength, JBB);
  1351.     return;
  1352.   }
  1353.   // Release index record
  1354.   c_theIndexes.release(dropIndxReq->getIndexId());
  1355.   DropIndxConf * const dropIndxConf =  
  1356.     (DropIndxConf *)signal->getDataPtrSend();
  1357.   dropIndxConf->setConnectionPtr(dropIndxReq->getConnectionPtr());
  1358.   sendSignal(sender, GSN_DROP_INDX_CONF, 
  1359.              signal, DropIndxConf::SignalLength, JBB);
  1360. }
  1361. void Dbtc::execTCINDXREQ(Signal* signal)
  1362. {
  1363.   jamEntry();
  1364.   TcIndxReq * const tcIndxReq =  (TcIndxReq *)signal->getDataPtr();
  1365.   const UintR TapiIndex = tcIndxReq->apiConnectPtr;
  1366.   Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
  1367.   Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
  1368.   Uint32 * dataPtr = &tcIndxReq->scanInfo;
  1369.   Uint32 indexBufSize = 8; // Maximum for index in TCINDXREQ
  1370.   Uint32 attrBufSize = 5;  // Maximum for attrInfo in TCINDXREQ
  1371.   ApiConnectRecordPtr transPtr;
  1372.   transPtr.i = TapiIndex;
  1373.   if (transPtr.i >= capiConnectFilesize) {
  1374.     jam();
  1375.     warningHandlerLab(signal);
  1376.     return;
  1377.   }//if
  1378.   ptrAss(transPtr, apiConnectRecord);
  1379.   ApiConnectRecord * const regApiPtr = transPtr.p;  
  1380.   // Seize index operation
  1381.   TcIndexOperationPtr indexOpPtr;
  1382.   if ((startFlag == 1) &&
  1383.       (regApiPtr->apiConnectstate == CS_CONNECTED ||
  1384.        (regApiPtr->apiConnectstate == CS_STARTED && 
  1385. regApiPtr->firstTcConnect == RNIL)) ||
  1386.       (regApiPtr->apiConnectstate == CS_ABORTING && 
  1387.        regApiPtr->abortState == AS_IDLE)) {
  1388.     jam();
  1389.     // This is a newly started transaction, clean-up
  1390.     releaseAllSeizedIndexOperations(regApiPtr);
  1391.     regApiPtr->transid[0] = tcIndxReq->transId1;
  1392.     regApiPtr->transid[1] = tcIndxReq->transId2;
  1393.   }//if
  1394.   if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
  1395.     jam();
  1396.     // Failed to allocate index operation
  1397.     terrorCode = 288;
  1398.     regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
  1399.     apiConnectptr = transPtr;
  1400.     abortErrorLab(signal);
  1401.     return;
  1402.   }
  1403.   TcIndexOperation* indexOp = indexOpPtr.p;
  1404.   indexOp->indexOpId = indexOpPtr.i;
  1405.   // Save original signal
  1406.   indexOp->tcIndxReq = *tcIndxReq;
  1407.   indexOp->connectionIndex = TapiIndex;
  1408.   regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
  1409.   // If operation is readTupleExclusive or updateTuple then read index 
  1410.   // table with exclusive lock
  1411.   Uint32 indexLength = TcIndxReq::getIndexLength(tcIndxRequestInfo);
  1412.   Uint32 attrLength = tcIndxReq->attrLen;
  1413.   indexOp->expectedKeyInfo = indexLength;
  1414.   Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
  1415.   indexOp->expectedAttrInfo = attrLength;
  1416.   Uint32 includedAttrLength = MIN(attrLength, attrBufSize);
  1417.   if (saveINDXKEYINFO(signal, 
  1418.                       indexOp, 
  1419.                       dataPtr, 
  1420.                       includedIndexLength)) {
  1421.     jam();
  1422.     // We have received all we need
  1423.     readIndexTable(signal, regApiPtr, indexOp);
  1424.     return;
  1425.   }
  1426.   dataPtr += includedIndexLength;
  1427.   if (saveINDXATTRINFO(signal, 
  1428.                        indexOp, 
  1429.                        dataPtr, 
  1430.                        includedAttrLength)) {
  1431.     jam();
  1432.     // We have received all we need
  1433.     readIndexTable(signal, regApiPtr, indexOp);
  1434.     return;
  1435.   }
  1436. }
  1437. void Dbtc::sendTcIndxConf(Signal* signal, UintR TcommitFlag) 
  1438. {
  1439.   HostRecordPtr localHostptr;
  1440.   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
  1441.   const UintR TopWords = (UintR)regApiPtr->tcindxrec;
  1442.   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
  1443.   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
  1444.   const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP);
  1445.   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
  1446.   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL ? 0 : 1);
  1447.   ptrAss(localHostptr, hostRecord);
  1448.   UintR TcurrLen = localHostptr.p->noOfWordsTCINDXCONF;
  1449.   UintR confInfo = 0;
  1450.   TcIndxConf::setNoOfOperations(confInfo, (TopWords >> 1));
  1451.   TcIndxConf::setCommitFlag(confInfo, TcommitFlag == 1);
  1452.   TcIndxConf::setMarkerFlag(confInfo, Tmarker);
  1453.   const UintR TpacketLen = 6 + TopWords;
  1454.   regApiPtr->tcindxrec = 0;
  1455.   if(TcommitFlag || (regApiPtr->lqhkeyreqrec == regApiPtr->lqhkeyconfrec)){
  1456.     jam();
  1457.     regApiPtr->m_exec_flag = 0;
  1458.   }
  1459.   if ((TpacketLen > 25) || !is_api){
  1460.     TcIndxConf * const tcIndxConf = (TcIndxConf *)signal->getDataPtrSend();
  1461.     
  1462.     jam();
  1463.     tcIndxConf->apiConnectPtr = regApiPtr->ndbapiConnect;
  1464.     tcIndxConf->gci = regApiPtr->globalcheckpointid;;
  1465.     tcIndxConf->confInfo = confInfo;
  1466.     tcIndxConf->transId1 = regApiPtr->transid[0];
  1467.     tcIndxConf->transId2 = regApiPtr->transid[1];
  1468.     copyFromToLen(&regApiPtr->tcIndxSendArray[0],
  1469.                   (UintR*)&tcIndxConf->operations,
  1470.                   (UintR)ZTCOPCONF_SIZE);
  1471.     sendSignal(regApiPtr->ndbapiBlockref,
  1472.                GSN_TCINDXCONF, signal, (TpacketLen - 1), JBB);
  1473.     return;
  1474.   } else if (((TcurrLen + TpacketLen) > 25) && (TcurrLen > 0)) {
  1475.     jam();
  1476.     sendPackedTCINDXCONF(signal, localHostptr.p, localHostptr.i);
  1477.     TcurrLen = 0;
  1478.   } else {
  1479.     jam();
  1480.     updatePackedList(signal, localHostptr.p, localHostptr.i);
  1481.   }//if
  1482. // -------------------------------------------------------------------------
  1483. // The header contains the block reference of receiver plus the real signal
  1484. // length - 3, since we have the real signal length plus one additional word
  1485. // for the header we have to do - 4.
  1486. // -------------------------------------------------------------------------
  1487.   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
  1488.   UintR Tpack1 = regApiPtr->ndbapiConnect;
  1489.   UintR Tpack2 = regApiPtr->globalcheckpointid;
  1490.   UintR Tpack3 = confInfo;
  1491.   UintR Tpack4 = regApiPtr->transid[0];
  1492.   UintR Tpack5 = regApiPtr->transid[1];
  1493.   localHostptr.p->noOfWordsTCINDXCONF = TcurrLen + TpacketLen;
  1494.   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 0] = Tpack0;
  1495.   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 1] = Tpack1;
  1496.   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 2] = Tpack2;
  1497.   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 3] = Tpack3;
  1498.   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 4] = Tpack4;
  1499.   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 5] = Tpack5;
  1500.   UintR Ti;
  1501.   for (Ti = 6; Ti < TpacketLen; Ti++) {
  1502.     localHostptr.p->packedWordsTCINDXCONF[TcurrLen + Ti] = 
  1503.           regApiPtr->tcIndxSendArray[Ti - 6];
  1504.   }//for
  1505. }//Dbtc::sendTcIndxConf()
  1506. void Dbtc::execINDXKEYINFO(Signal* signal)
  1507. {
  1508.   jamEntry();
  1509.   Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
  1510.   IndxKeyInfo * const indxKeyInfo =  (IndxKeyInfo *)signal->getDataPtr();
  1511.   const Uint32 *src = indxKeyInfo->getData();
  1512.   const UintR TconnectIndex = indxKeyInfo->connectPtr;
  1513.   ApiConnectRecordPtr transPtr;
  1514.   transPtr.i = TconnectIndex;
  1515.   if (transPtr.i >= capiConnectFilesize) {
  1516.     jam();
  1517.     warningHandlerLab(signal);
  1518.     return;
  1519.   }//if
  1520.   ptrAss(transPtr, apiConnectRecord);
  1521.   ApiConnectRecord * const regApiPtr = transPtr.p;
  1522.   TcIndexOperationPtr indexOpPtr;
  1523.   TcIndexOperation* indexOp;
  1524.   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
  1525.   {
  1526.     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
  1527.     if (saveINDXKEYINFO(signal,
  1528. indexOp, 
  1529. src, 
  1530. keyInfoLength)) {
  1531.       jam();
  1532.       // We have received all we need
  1533.       readIndexTable(signal, regApiPtr, indexOp);
  1534.     }
  1535.   }
  1536. }
  1537. void Dbtc::execINDXATTRINFO(Signal* signal)
  1538. {
  1539.   jamEntry();
  1540.   Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
  1541.   IndxAttrInfo * const indxAttrInfo =  (IndxAttrInfo *)signal->getDataPtr();
  1542.   const Uint32 *src = indxAttrInfo->getData();
  1543.   const UintR TconnectIndex = indxAttrInfo->connectPtr;
  1544.   ApiConnectRecordPtr transPtr;
  1545.   transPtr.i = TconnectIndex;
  1546.   if (transPtr.i >= capiConnectFilesize) {
  1547.     jam();
  1548.     warningHandlerLab(signal);
  1549.     return;
  1550.   }//if
  1551.   ptrAss(transPtr, apiConnectRecord);
  1552.   ApiConnectRecord * const regApiPtr = transPtr.p;  
  1553.   TcIndexOperationPtr indexOpPtr;
  1554.   TcIndexOperation* indexOp;
  1555.   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
  1556.   {
  1557.     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
  1558.     if (saveINDXATTRINFO(signal,
  1559.  indexOp, 
  1560.  src, 
  1561.  attrInfoLength)) {
  1562.       jam();
  1563.       // We have received all we need
  1564.       readIndexTable(signal, regApiPtr, indexOp);
  1565.     }
  1566.   }
  1567. }
  1568. /**
  1569.  * Save signal INDXKEYINFO
  1570.  * Return true if we have received all needed data
  1571.  */
  1572. bool Dbtc::saveINDXKEYINFO(Signal* signal,
  1573.                            TcIndexOperation* indexOp,
  1574.                            const Uint32 *src, 
  1575.                            Uint32 len)
  1576. {
  1577.   if (!indexOp->keyInfo.append(src, len)) {
  1578.     jam();
  1579.     // Failed to seize keyInfo, abort transaction
  1580. #ifdef VM_TRACE
  1581.     ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize keyinfon");
  1582. #endif
  1583.     // Abort transaction
  1584.     apiConnectptr.i = indexOp->connectionIndex;
  1585.     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  1586.     releaseIndexOperation(apiConnectptr.p, indexOp);
  1587.     terrorCode = 4000;
  1588.     abortErrorLab(signal);
  1589.     return false;
  1590.   }
  1591.   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
  1592.     jam();
  1593.     return true;
  1594.   }
  1595.   return false;
  1596. }
  1597. bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
  1598. {
  1599.   return (indexOp->keyInfo.getSize() == indexOp->expectedKeyInfo);
  1600. }
  1601. /**
  1602.  * Save signal INDXATTRINFO
  1603.  * Return true if we have received all needed data
  1604.  */
  1605. bool Dbtc::saveINDXATTRINFO(Signal* signal,
  1606.                             TcIndexOperation* indexOp,
  1607.                             const Uint32 *src, 
  1608.                             Uint32 len)
  1609. {
  1610.   if (!indexOp->attrInfo.append(src, len)) {
  1611.     jam();
  1612. #ifdef VM_TRACE
  1613.     ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize attrInfon");
  1614. #endif
  1615.     apiConnectptr.i = indexOp->connectionIndex;
  1616.     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  1617.     releaseIndexOperation(apiConnectptr.p, indexOp);
  1618.     terrorCode = 4000;
  1619.     abortErrorLab(signal);
  1620.     return false;
  1621.   }
  1622.   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
  1623.     jam();
  1624.     return true;
  1625.   }
  1626.   return false;
  1627. }
  1628. bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
  1629. {
  1630.   return (indexOp->attrInfo.getSize() == indexOp->expectedAttrInfo);
  1631. }
  1632. bool  Dbtc::saveTRANSID_AI(Signal* signal,
  1633.    TcIndexOperation* indexOp, 
  1634.                            const Uint32 *src,
  1635.                            Uint32 len)
  1636. {
  1637.   Uint32 currentTransIdAILength = indexOp->transIdAI.getSize();
  1638.     
  1639.   if (currentTransIdAILength == 0) {
  1640.     jam();
  1641.     // Read first AttributeHeader to get expected size
  1642.     // of the single key attribute expected
  1643.     AttributeHeader* head = (AttributeHeader *) src;
  1644.     indexOp->expectedTransIdAI = head->getHeaderSize() + head->getDataSize();
  1645.   }
  1646.   if (!indexOp->transIdAI.append(src, len)) {
  1647.     jam();
  1648. #ifdef VM_TRACE
  1649.     ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize transIdAIn");
  1650. #endif
  1651.     apiConnectptr.i = indexOp->connectionIndex;
  1652.     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  1653.     releaseIndexOperation(apiConnectptr.p, indexOp);
  1654.     terrorCode = 4000;
  1655.     abortErrorLab(signal);
  1656.     return false;
  1657.   }
  1658.   return true;
  1659. }
  1660. bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
  1661. {
  1662.   return (indexOp->transIdAI.getSize() == indexOp->expectedTransIdAI);
  1663. }
  1664. /**
  1665.  * Receive signal TCINDXCONF
  1666.  * This can be either the return of reading an index table
  1667.  * or performing an index operation
  1668.  */
  1669. void Dbtc::execTCKEYCONF(Signal* signal)
  1670. {
  1671.   TcKeyConf * const tcKeyConf =  (TcKeyConf *)signal->getDataPtr();
  1672.   TcIndexOperationPtr indexOpPtr;
  1673.   jamEntry();
  1674.   indexOpPtr.i = tcKeyConf->apiConnectPtr;
  1675.   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
  1676.   Uint32 confInfo = tcKeyConf->confInfo;
  1677.   /**
  1678.    * Check on TCKEYCONF wheater the the transaction was committed
  1679.    */
  1680.   Uint32 Tcommit = TcKeyConf::getCommitFlag(confInfo);
  1681.   indexOpPtr.p = indexOp;
  1682.   if (!indexOp) {
  1683.     jam();
  1684.     // Missing index operation
  1685.     return;
  1686.   }
  1687.   const UintR TconnectIndex = indexOp->connectionIndex;
  1688.   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
  1689.   apiConnectptr.p = regApiPtr;
  1690.   apiConnectptr.i = TconnectIndex;
  1691.   switch(indexOp->indexOpState) {
  1692.   case(IOS_NOOP): {
  1693.     jam();
  1694.     // Should never happen, abort
  1695.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1696.     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
  1697.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  1698.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  1699.     tcIndxRef->errorCode = 4349;    
  1700.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  1701.        TcIndxRef::SignalLength, JBB);
  1702.     return;
  1703.   }
  1704.   case(IOS_INDEX_ACCESS): {
  1705.     jam();
  1706.     // Wait for TRANSID_AI
  1707.     indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
  1708.     break;
  1709.   }
  1710.   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
  1711.     jam();
  1712.     // Double TCKEYCONF, should never happen, abort
  1713.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1714.     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
  1715.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  1716.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  1717.     tcIndxRef->errorCode = 4349;    
  1718.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  1719.        TcIndxRef::SignalLength, JBB);
  1720.     return;
  1721.   }
  1722.   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {  
  1723.     jam();
  1724.     // Continue with index operation
  1725.     executeIndexOperation(signal, regApiPtr, indexOp);
  1726.     break;
  1727.   }
  1728.   case(IOS_INDEX_OPERATION): {
  1729.     // We are done, send TCINDXCONF
  1730.     jam();    
  1731.     Uint32 Ttcindxrec = regApiPtr->tcindxrec;
  1732.     // Copy reply from TcKeyConf
  1733.     ndbassert(regApiPtr->noIndexOp);
  1734.     regApiPtr->noIndexOp--; // Decrease count
  1735.     regApiPtr->tcIndxSendArray[Ttcindxrec] = indexOp->tcIndxReq.senderData;
  1736.     regApiPtr->tcIndxSendArray[Ttcindxrec + 1] = 
  1737.       tcKeyConf->operations[0].attrInfoLen;
  1738.     regApiPtr->tcindxrec = Ttcindxrec + 2;
  1739.     if (regApiPtr->noIndexOp == 0) {
  1740.       jam();
  1741.       sendTcIndxConf(signal, Tcommit);
  1742.     } else if (regApiPtr->tcindxrec == ZTCOPCONF_SIZE) {
  1743.       jam();
  1744.       sendTcIndxConf(signal, 0);
  1745.     }
  1746.     releaseIndexOperation(regApiPtr, indexOp);
  1747.     break;
  1748.   }
  1749.   }
  1750. }
  1751. void Dbtc::execTCKEYREF(Signal* signal)
  1752. {
  1753.   TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
  1754.   TcIndexOperationPtr indexOpPtr;
  1755.   jamEntry();
  1756.   indexOpPtr.i = tcKeyRef->connectPtr;
  1757.   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
  1758.   indexOpPtr.p = indexOp;
  1759.   if (!indexOp) {
  1760.     jam();    
  1761.     // Missing index operation
  1762.     return;
  1763.   }
  1764.   const UintR TconnectIndex = indexOp->connectionIndex;
  1765.   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
  1766.   Uint32 tcKeyRequestInfo  = indexOp->tcIndxReq.requestInfo;
  1767.   Uint32 commitFlg = TcKeyReq::getCommitFlag(tcKeyRequestInfo);
  1768.   switch(indexOp->indexOpState) {
  1769.   case(IOS_NOOP): {
  1770.     jam();    
  1771.     // Should never happen, abort
  1772.     break;
  1773.   }
  1774.   case(IOS_INDEX_ACCESS):
  1775.   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
  1776.   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
  1777.     jam();    
  1778.     // If we fail index access for a non-read operation during commit 
  1779.     // we abort transaction
  1780.     if (commitFlg == 1) {
  1781.       jam();
  1782.       releaseIndexOperation(regApiPtr, indexOp);
  1783.       apiConnectptr.i = indexOp->connectionIndex;
  1784.       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
  1785.       terrorCode = tcKeyRef->errorCode;
  1786.       abortErrorLab(signal);
  1787.       break;
  1788.     }
  1789.     /**
  1790.      * Increase count as it will be decreased below...
  1791.      *   (and the code is written to handle failing lookup on "real" table
  1792.      *    not lookup on index table)
  1793.      */
  1794.     regApiPtr->noIndexOp++;
  1795.     // else continue
  1796.   }
  1797.   case(IOS_INDEX_OPERATION): {
  1798.     // Send TCINDXREF 
  1799.     
  1800.     jam();
  1801.     TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
  1802.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1803.     
  1804.     ndbassert(regApiPtr->noIndexOp);
  1805.     regApiPtr->noIndexOp--; // Decrease count
  1806.     tcIndxRef->connectPtr = tcIndxReq->senderData;
  1807.     tcIndxRef->transId[0] = tcKeyRef->transId[0];
  1808.     tcIndxRef->transId[1] = tcKeyRef->transId[1];
  1809.     tcIndxRef->errorCode = tcKeyRef->errorCode;
  1810.     sendSignal(regApiPtr->ndbapiBlockref, 
  1811.                GSN_TCINDXREF, signal, TcIndxRef::SignalLength, JBB);
  1812.     return;
  1813.   }
  1814.   }
  1815. }
  1816. void Dbtc::execTRANSID_AI_R(Signal* signal){
  1817.   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
  1818.   Uint32 sigLen = signal->length();
  1819.   Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
  1820.   Uint32 recBlockref = transIdAI->attrData[dataLen];
  1821.   jamEntry();
  1822.   /**
  1823.    * Forward signal to final destination
  1824.    * Truncate last word since that was used to hold the final dest.
  1825.    */
  1826.   sendSignal(recBlockref, GSN_TRANSID_AI,
  1827.      signal, sigLen - 1, JBB);
  1828. }
  1829. void Dbtc::execKEYINFO20_R(Signal* signal){
  1830.   KeyInfo20 * const keyInfo =  (KeyInfo20 *)signal->getDataPtr();
  1831.   Uint32 sigLen = signal->length();
  1832.   Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
  1833.   Uint32 recBlockref = keyInfo->keyData[dataLen];
  1834.   jamEntry();
  1835.   
  1836.   /**
  1837.    * Forward signal to final destination
  1838.    * Truncate last word since that was used to hold the final dest.
  1839.    */
  1840.   sendSignal(recBlockref, GSN_KEYINFO20,
  1841.      signal, sigLen - 1, JBB);
  1842. }
  1843. void Dbtc::execTRANSID_AI(Signal* signal)
  1844. {
  1845.   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
  1846.   jamEntry();
  1847.   TcIndexOperationPtr indexOpPtr;
  1848.   indexOpPtr.i = transIdAI->connectPtr;
  1849.   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
  1850.   indexOpPtr.p = indexOp;
  1851.   if (!indexOp) {
  1852.     jam();
  1853.     // Missing index operation
  1854.   }
  1855.   const UintR TconnectIndex = indexOp->connectionIndex;
  1856.   //  ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
  1857.   ApiConnectRecordPtr transPtr;
  1858.   
  1859.   transPtr.i = TconnectIndex;
  1860.   ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
  1861.   ApiConnectRecord * const regApiPtr = transPtr.p;
  1862.   // Acccumulate attribute data
  1863.   if (!saveTRANSID_AI(signal,
  1864.       indexOp, 
  1865.                       transIdAI->getData(), 
  1866.                       signal->getLength() - TransIdAI::HeaderLength)) {
  1867.     jam();
  1868.     // Failed to allocate space for TransIdAI
  1869.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1870.     
  1871.     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
  1872.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  1873.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  1874.     tcIndxRef->errorCode = 4000;
  1875.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  1876.        TcIndxRef::SignalLength, JBB);
  1877.     return;
  1878.   }
  1879.   switch(indexOp->indexOpState) {
  1880.   case(IOS_NOOP): {
  1881.     jam();
  1882.     // Should never happen, abort
  1883.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1884.     
  1885.     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
  1886.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  1887.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  1888.     tcIndxRef->errorCode = 4349;
  1889.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  1890.        TcIndxRef::SignalLength, JBB);
  1891.     return;
  1892.     break;
  1893.   }
  1894.   case(IOS_INDEX_ACCESS): {
  1895.     jam();
  1896.     // Check if all TRANSID_AI have been received
  1897.     if (receivedAllTRANSID_AI(indexOp)) {
  1898.       jam();
  1899.       // Wait for TRANSID_AI
  1900.       indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
  1901.     }
  1902.     break;
  1903.     }
  1904.   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
  1905.     jam();
  1906. #ifdef VM_TRACE
  1907.     ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for nown");
  1908. #endif
  1909.     /*
  1910.     // Too many TRANSID_AI
  1911.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1912.     
  1913.     tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
  1914.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  1915.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  1916.     tcIndxRef->errorCode = 4349;
  1917.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  1918.                TcIndxRef::SignalLength, JBB);
  1919.     */
  1920.     break;
  1921.   }
  1922.   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): { 
  1923.     jam();
  1924.     // Check if all TRANSID_AI have been received
  1925.     if (receivedAllTRANSID_AI(indexOp)) {
  1926.       jam();
  1927.       // Continue with index operation
  1928.       executeIndexOperation(signal, regApiPtr, indexOp);
  1929.     }
  1930.     // else continue waiting for more TRANSID_AI
  1931.     break;
  1932.   }
  1933.   case(IOS_INDEX_OPERATION): {
  1934.     // Should never receive TRANSID_AI in this state!!
  1935.     jam();    
  1936.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1937.     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
  1938.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  1939.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  1940.     tcIndxRef->errorCode = 4349;
  1941.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  1942.        TcIndxRef::SignalLength, JBB);
  1943.     return;
  1944.   }
  1945.   }
  1946. }
  1947. void Dbtc::execTCROLLBACKREP(Signal* signal)
  1948. {
  1949.   TcRollbackRep* tcRollbackRep =  (TcRollbackRep *)signal->getDataPtr();
  1950.   jamEntry();
  1951.   TcIndexOperationPtr indexOpPtr;
  1952.   indexOpPtr.i = tcRollbackRep->connectPtr;
  1953.   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
  1954.   indexOpPtr.p = indexOp;
  1955.   tcRollbackRep =  (TcRollbackRep *)signal->getDataPtrSend();
  1956.   tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
  1957.   sendSignal(apiConnectptr.p->ndbapiBlockref, 
  1958.      GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
  1959. }
  1960. /**
  1961.  * Read index table with the index attributes as PK
  1962.  */
  1963. void Dbtc::readIndexTable(Signal* signal, 
  1964.   ApiConnectRecord* regApiPtr,
  1965.   TcIndexOperation* indexOp) 
  1966. {
  1967.   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
  1968.   Uint32 dataPos = 0;
  1969.   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
  1970.   Uint32 * dataPtr = &tcKeyReq->scanInfo;
  1971.   Uint32 tcKeyLength = TcKeyReq::StaticLength;
  1972.   Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo; 
  1973.   AttributeBuffer::DataBufferIterator keyIter;
  1974.   Uint32 keyLength = TcKeyReq::getKeyLength(tcKeyRequestInfo);
  1975.   TcIndexData* indexData;
  1976.   Uint32 transId1 = indexOp->tcIndxReq.transId1;
  1977.   Uint32 transId2 = indexOp->tcIndxReq.transId2;
  1978.   const Operation_t opType = 
  1979.     (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
  1980.   // Find index table
  1981.   if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.indexId)) == NULL) {
  1982.     jam();
  1983.     // Failed to find index record
  1984.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  1985.     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
  1986.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  1987.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  1988.     tcIndxRef->errorCode = 4000;    
  1989.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  1990.        TcIndxRef::SignalLength, JBB);
  1991.     return;
  1992.   }
  1993.   tcKeyReq->transId1 = transId1;
  1994.   tcKeyReq->transId2 = transId2;
  1995.   tcKeyReq->tableId = indexData->indexId;
  1996.   tcKeyLength += MIN(keyLength, keyBufSize);
  1997.   tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.indexSchemaVersion;
  1998.   TcKeyReq::setOperationType(tcKeyRequestInfo, 
  1999.      opType == ZREAD ? ZREAD : ZREAD_EX);
  2000.   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
  2001.   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
  2002.   BlockReference originalReceiver = regApiPtr->ndbapiBlockref;
  2003.   regApiPtr->ndbapiBlockref = reference(); // Send result to me
  2004.   tcKeyReq->senderData = indexOp->indexOpId;
  2005.   indexOp->indexOpState = IOS_INDEX_ACCESS;
  2006.   regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
  2007.   regApiPtr->accumulatingIndexOp = RNIL;
  2008.   regApiPtr->isIndexOp = true;
  2009.   Uint32 remainingKey = indexOp->keyInfo.getSize();
  2010.   bool moreKeyData = indexOp->keyInfo.first(keyIter);
  2011.   // *********** KEYINFO in TCKEYREQ ***********
  2012.   while((dataPos < keyBufSize) &&
  2013.         (remainingKey-- != 0)) {
  2014.     *dataPtr++ = *keyIter.data;
  2015.     dataPos++;
  2016.     moreKeyData = indexOp->keyInfo.next(keyIter);
  2017.   }
  2018.   // *********** ATTRINFO in TCKEYREQ ***********  
  2019.   tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
  2020.   AttributeHeader::init(dataPtr, indexData->primaryKeyPos, 0);
  2021.   tcKeyLength++;
  2022.   tcKeyReq->requestInfo = tcKeyRequestInfo;
  2023.   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
  2024.   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
  2025.   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
  2026.  
  2027.   /**
  2028.    * "Fool" TC not to start commiting transaction since it always will
  2029.    *   have one outstanding lqhkeyreq
  2030.    * This is later decreased when the index read is complete
  2031.    */ 
  2032.   regApiPtr->lqhkeyreqrec++;
  2033.   /**
  2034.    * Remember ptr to index read operation
  2035.    *   (used to set correct save point id on index operation later)
  2036.    */
  2037.   indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
  2038.   jamEntry();
  2039.   // *********** KEYINFO ***********
  2040.   if (moreKeyData) {
  2041.     jam();
  2042.     // Send KEYINFO sequence
  2043.     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
  2044.     
  2045.     keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
  2046.     keyInfo->transId[0] = transId1;
  2047.     keyInfo->transId[1] = transId2;
  2048.     dataPtr = (Uint32 *) &keyInfo->keyData;
  2049.     dataPos = 0;
  2050.     while(remainingKey-- != 0) {// If we have not read complete key
  2051.       *dataPtr++ = *keyIter.data;
  2052.       dataPos++;
  2053.       if (dataPos == KeyInfo::DataLength) {
  2054. // Flush KEYINFO
  2055. EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, 
  2056.        KeyInfo::HeaderLength + KeyInfo::DataLength);
  2057.         jamEntry();
  2058. dataPos = 0;
  2059. dataPtr = (Uint32 *) &keyInfo->keyData;
  2060.       }       
  2061.       moreKeyData = indexOp->keyInfo.next(keyIter);
  2062.     }
  2063.     if (dataPos != 0) {
  2064.       // Flush last KEYINFO
  2065.       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2066.      KeyInfo::HeaderLength + dataPos);
  2067.       jamEntry();
  2068.     }
  2069.   }
  2070.   
  2071.   regApiPtr->ndbapiBlockref = originalReceiver; // reset original receiver
  2072. }
  2073. /**
  2074.  * Execute the index operation with the result from
  2075.  * the index table read as PK
  2076.  */
  2077. void Dbtc::executeIndexOperation(Signal* signal, 
  2078.  ApiConnectRecord* regApiPtr,
  2079.  TcIndexOperation* indexOp) {
  2080.   
  2081.   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
  2082.   Uint32 attrBufSize = 5;
  2083.   Uint32 dataPos = 0;
  2084.   TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
  2085.   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
  2086.   Uint32 * dataPtr = &tcKeyReq->scanInfo;
  2087.   Uint32 tcKeyLength = TcKeyReq::StaticLength;
  2088.   Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
  2089.   TcIndexData* indexData;
  2090.   AttributeBuffer::DataBufferIterator attrIter;
  2091.   AttributeBuffer::DataBufferIterator aiIter;
  2092.   bool moreKeyData = indexOp->transIdAI.first(aiIter);
  2093.       
  2094.   // Find index table
  2095.   if ((indexData = c_theIndexes.getPtr(tcIndxReq->indexId)) == NULL) {
  2096.     jam();
  2097.     // Failed to find index record 
  2098.     TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
  2099.     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
  2100.     tcIndxRef->transId[0] = regApiPtr->transid[0];
  2101.     tcIndxRef->transId[1] = regApiPtr->transid[1];
  2102.     tcIndxRef->errorCode = 4349;    
  2103.     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal, 
  2104.        TcIndxRef::SignalLength, JBB);
  2105.     return;
  2106.   }    
  2107.   // Find schema version of primary table
  2108.   TableRecordPtr tabPtr;
  2109.   tabPtr.i = indexData->primaryTableId;
  2110.   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
  2111.   tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
  2112.   tcKeyReq->attrLen = tcIndxReq->attrLen;
  2113.   tcKeyReq->tableId = indexData->primaryTableId;
  2114.   tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
  2115.   tcKeyReq->transId1 = regApiPtr->transid[0];
  2116.   tcKeyReq->transId2 = regApiPtr->transid[1];
  2117.   tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
  2118.   indexOp->indexOpState = IOS_INDEX_OPERATION;
  2119.   regApiPtr->isIndexOp = true;
  2120.   regApiPtr->executingIndexOp = indexOp->indexOpId;;
  2121.   regApiPtr->noIndexOp++; // Increase count
  2122.   // Filter out AttributeHeader:s since this should not be in key
  2123.   AttributeHeader* attrHeader = (AttributeHeader *) aiIter.data;
  2124.     
  2125.   Uint32 headerSize = attrHeader->getHeaderSize();
  2126.   Uint32 keySize = attrHeader->getDataSize();
  2127.   TcKeyReq::setKeyLength(tcKeyRequestInfo, keySize);
  2128.   // Skip header
  2129.   if (headerSize == 1) {
  2130.     jam();
  2131.     moreKeyData = indexOp->transIdAI.next(aiIter);
  2132.   } else {
  2133.     jam();
  2134.     moreKeyData = indexOp->transIdAI.next(aiIter, headerSize - 1);
  2135.   }//if
  2136.   while(// If we have not read complete key
  2137. (keySize != 0) &&
  2138. (dataPos < keyBufSize)) {
  2139.     *dataPtr++ = *aiIter.data;
  2140.     dataPos++;
  2141.     keySize--;
  2142.     moreKeyData = indexOp->transIdAI.next(aiIter);
  2143.   }
  2144.   tcKeyLength += dataPos;
  2145.   Uint32 attributesLength = indexOp->attrInfo.getSize();
  2146.   if (attributesLength <= attrBufSize) {
  2147.     jam();
  2148.     // ATTRINFO fits in TCKEYREQ
  2149.     // Pack ATTRINFO IN TCKEYREQ
  2150.     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, indexOp->attrInfo.getSize());
  2151.     // Insert IndxAttrInfo
  2152.     for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
  2153.         moreAttrData;
  2154.         moreAttrData = indexOp->attrInfo.next(attrIter)) {      
  2155.       *dataPtr++ = *attrIter.data;
  2156.     }
  2157.     tcKeyLength += attributesLength;
  2158.   } else {
  2159.     jam();
  2160.     // No ATTRINFO in TCKEYREQ
  2161.     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
  2162.   }
  2163.   TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
  2164.   TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
  2165.   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
  2166.   tcKeyReq->requestInfo = tcKeyRequestInfo;
  2167.   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
  2168.   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
  2169.   /**
  2170.    * Decrease lqhkeyreqrec to compensate for addition
  2171.    *   during read of index table
  2172.    * I.e. let TC start committing when other operations has completed
  2173.    */
  2174.   regApiPtr->lqhkeyreqrec--;
  2175.   /**
  2176.    * Fix savepoint id -
  2177.    *   fix so that index operation has the same savepoint id
  2178.    *   as the read of the index table (TCINDXREQ)
  2179.    */
  2180.   TcConnectRecordPtr tmp;
  2181.   tmp.i = indexOp->indexReadTcConnect;
  2182.   ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
  2183.   const Uint32 currSavePointId = regApiPtr->currSavePointId;
  2184.   regApiPtr->currSavePointId = tmp.p->savePointId;
  2185.   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
  2186.   regApiPtr->currSavePointId = currSavePointId;
  2187.   
  2188.   jamEntry();
  2189.   // *********** KEYINFO ***********
  2190.   if (moreKeyData) {
  2191.     jam();
  2192.     // Send KEYINFO sequence
  2193.     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
  2194.     
  2195.     keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
  2196.     keyInfo->transId[0] = regApiPtr->transid[0];
  2197.     keyInfo->transId[1] = regApiPtr->transid[1];
  2198.     dataPtr = (Uint32 *) &keyInfo->keyData;
  2199.     dataPos = 0;
  2200.     // Pack any part of a key attribute that did no fit TCKEYREQ
  2201.     while(keySize-- != 0) {// If we have not read complete key
  2202.       *dataPtr++ = *aiIter.data;
  2203.       dataPos++;
  2204.       if (dataPos == KeyInfo::DataLength) {
  2205. // Flush KEYINFO
  2206. EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, 
  2207.        KeyInfo::HeaderLength + KeyInfo::DataLength);
  2208.         jamEntry();
  2209. dataPos = 0;
  2210. dataPtr = (Uint32 *) &keyInfo->keyData;
  2211.       }
  2212.       moreKeyData = indexOp->transIdAI.next(aiIter);
  2213.     }
  2214.     if (dataPos != 0) {
  2215.       // Flush last KEYINFO
  2216.       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2217.      KeyInfo::HeaderLength + dataPos);
  2218.       jamEntry();
  2219.     }
  2220.   }
  2221.   
  2222.   // *********** ATTRINFO ***********
  2223.   if (attributesLength > attrBufSize) {
  2224.     jam();
  2225.     // No ATTRINFO in TcKeyReq
  2226.     TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
  2227.     // Send ATTRINFO sequence
  2228.     AttrInfo * const attrInfo =  (AttrInfo *)signal->getDataPtrSend();
  2229.     Uint32 attrInfoPos = 0;
  2230.     
  2231.     attrInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
  2232.     attrInfo->transId[0] = regApiPtr->transid[0];
  2233.     attrInfo->transId[1] = regApiPtr->transid[1];
  2234.     dataPtr = (Uint32 *) &attrInfo->attrData;
  2235.  
  2236.     // Insert attribute values (insert key values of primary table)
  2237.     for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
  2238.         moreAttrData;
  2239.         moreAttrData = indexOp->attrInfo.next(attrIter)) {      
  2240.       *dataPtr++ = *attrIter.data;
  2241.       attrInfoPos++;
  2242.       if (attrInfoPos == AttrInfo::DataLength) {
  2243.         // Flush ATTRINFO
  2244.         EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
  2245.        AttrInfo::HeaderLength + AttrInfo::DataLength);
  2246.         jamEntry();
  2247.         attrInfoPos = 0;
  2248. dataPtr = (Uint32 *) &attrInfo->attrData;
  2249.       }
  2250.     }
  2251.     if (attrInfoPos != 0) {
  2252.       // Send last ATTRINFO
  2253.       EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal, 
  2254.      AttrInfo::HeaderLength + attrInfoPos);
  2255.       jamEntry();
  2256.     }
  2257.   }
  2258. }
  2259. bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
  2260.        TcIndexOperationPtr& indexOpPtr)
  2261. {
  2262.   return regApiPtr->theSeizedIndexOperations.seize(indexOpPtr);
  2263. }
  2264. void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
  2265.  TcIndexOperation* indexOp)
  2266. {
  2267.   indexOp->indexOpState = IOS_NOOP;
  2268.   indexOp->expectedKeyInfo = 0;
  2269.   indexOp->keyInfo.release();
  2270.   indexOp->expectedAttrInfo = 0;
  2271.   indexOp->attrInfo.release();
  2272.   indexOp->expectedTransIdAI = 0;
  2273.   indexOp->transIdAI.release();
  2274.   regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
  2275. }
  2276. void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
  2277. {
  2278.   TcIndexOperationPtr seizedIndexOpPtr;
  2279.   regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
  2280.   while(seizedIndexOpPtr.i != RNIL) {
  2281.     jam();
  2282.     TcIndexOperation* indexOp = seizedIndexOpPtr.p;
  2283.     indexOp->indexOpState = IOS_NOOP;
  2284.     indexOp->expectedKeyInfo = 0;
  2285.     indexOp->keyInfo.release();
  2286.     indexOp->expectedAttrInfo = 0;
  2287.     indexOp->attrInfo.release();
  2288.     indexOp->expectedTransIdAI = 0;
  2289.     indexOp->transIdAI.release();
  2290.     regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);    
  2291.   }
  2292.   regApiPtr->theSeizedIndexOperations.release();
  2293. }
  2294. void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
  2295. {
  2296.   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
  2297.   copyFromToLen((UintR*)lqhKeyConf,
  2298. &trigOp->savedState[0],
  2299.                 LqhKeyConf::SignalLength);  
  2300. }
  2301. void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
  2302. {
  2303.   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
  2304.   copyFromToLen(&trigOp->savedState[0],
  2305.                 (UintR*)lqhKeyConf,
  2306. LqhKeyConf::SignalLength);
  2307.   lqhKeyConf->noFiredTriggers = 0;
  2308.   trigOp->noReceivedTriggers = 0;
  2309.   // All triggers executed successfully, continue operation
  2310.   execLQHKEYCONF(signal);
  2311. }
  2312. void Dbtc::scheduleFiredTrigger(ApiConnectRecordPtr* transPtr,
  2313.                                 TcConnectRecordPtr* opPtr)
  2314. {
  2315.   // Set initial values for trigger fireing operation
  2316.   opPtr->p->triggerExecutionCount++;
  2317.   // Insert fired trigger in execution queue
  2318.   transPtr->p->theFiredTriggers.add(opPtr->p->accumulatingTriggerData);
  2319.   opPtr->p->accumulatingTriggerData.i = RNIL;
  2320.   opPtr->p->accumulatingTriggerData.p = NULL;
  2321. }
  2322. void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
  2323. {
  2324.   ApiConnectRecord* regApiPtr = transPtr->p;
  2325.   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
  2326.   TcConnectRecordPtr opPtr;
  2327.   FiredTriggerPtr trigPtr;
  2328.   if (!regApiPtr->theFiredTriggers.isEmpty()) {
  2329.     jam();
  2330.     if ((regApiPtr->apiConnectstate == CS_STARTED) ||
  2331.         (regApiPtr->apiConnectstate == CS_START_COMMITTING)) {
  2332.       jam();
  2333.       regApiPtr->theFiredTriggers.first(trigPtr);
  2334.       while (trigPtr.i != RNIL) {
  2335.         jam();
  2336.         // Execute all ready triggers in parallel
  2337.         opPtr.i = trigPtr.p->fireingOperation;
  2338.         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
  2339. FiredTriggerPtr nextTrigPtr = trigPtr;
  2340. regApiPtr->theFiredTriggers.next(nextTrigPtr);
  2341.         if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
  2342.           jam();
  2343.           // Fireing operation is ready to have a trigger executing
  2344.           executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
  2345.           // Should allow for interleaving here by sending a CONTINUEB and 
  2346.   // return
  2347.           // Release trigger records
  2348.   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
  2349.   LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
  2350.   tmp1.release();
  2351.   LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
  2352.   tmp2.release();
  2353.   LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
  2354.   tmp3.release();
  2355.           regApiPtr->theFiredTriggers.release(trigPtr.i);
  2356.         }
  2357. trigPtr = nextTrigPtr;
  2358.       }
  2359.       return;
  2360.     // No more triggers, continue transaction after last executed trigger has
  2361.     // reurned (in execLQHKEYCONF or execLQHKEYREF)
  2362.     } else {
  2363.       // Wait until transaction is ready to execute a trigger
  2364.       jam();
  2365.       if (!regApiPtr->triggerPending) {
  2366.         jam();
  2367.         regApiPtr->triggerPending = true;
  2368.         signal->theData[0] = TcContinueB::TRIGGER_PENDING;
  2369.         signal->theData[1] = transPtr->i;
  2370.         sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
  2371.       }
  2372.       // else  
  2373.       // We are already waiting for a pending trigger (CONTINUEB)
  2374.     }
  2375.   }
  2376. }
  2377. void Dbtc::executeTrigger(Signal* signal,
  2378.                           TcFiredTriggerData* firedTriggerData,
  2379.                           ApiConnectRecordPtr* transPtr,
  2380.                           TcConnectRecordPtr* opPtr)
  2381. {
  2382.   TcDefinedTriggerData* definedTriggerData;
  2383.   if ((definedTriggerData = 
  2384.        c_theDefinedTriggers.getPtr(firedTriggerData->triggerId)) 
  2385.       != NULL) {
  2386.     switch(definedTriggerData->triggerType) {
  2387.     case(TriggerType::SECONDARY_INDEX):
  2388.       jam();
  2389.       executeIndexTrigger(signal, definedTriggerData, firedTriggerData, 
  2390.                           transPtr, opPtr);
  2391.       break;
  2392.     default:
  2393.       ndbrequire(false);
  2394.     }
  2395.   }
  2396. }
  2397. void Dbtc::executeIndexTrigger(Signal* signal,
  2398.                                TcDefinedTriggerData* definedTriggerData,
  2399.                                TcFiredTriggerData* firedTriggerData,
  2400.                                ApiConnectRecordPtr* transPtr,
  2401.                                TcConnectRecordPtr* opPtr)
  2402. {
  2403.   TcIndexData* indexData;
  2404.   indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
  2405.   ndbassert(indexData != NULL);
  2406.   switch (definedTriggerData->triggerEvent) {
  2407.   case(TriggerEvent::TE_INSERT): {
  2408.     jam();
  2409.     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
  2410.     break;
  2411.   }
  2412.   case(TriggerEvent::TE_DELETE): {
  2413.     jam();
  2414.     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
  2415.     break;
  2416.   }
  2417.   case(TriggerEvent::TE_UPDATE): {
  2418.     jam();
  2419.     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, 
  2420.  indexData, true); // Hold the triggering operation
  2421.     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
  2422.     break;
  2423.   }
  2424.   default:
  2425.     ndbrequire(false);
  2426.   }
  2427. }
  2428. void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
  2429. {
  2430.   FiredTriggerPtr trigPtr;
  2431.   triggers->first(trigPtr);
  2432.   while (trigPtr.i != RNIL) {
  2433.     jam();
  2434.     // Release trigger records
  2435.     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
  2436.     LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
  2437.     tmp1.release();
  2438.     LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
  2439.     tmp2.release();
  2440.     LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
  2441.     tmp3.release();
  2442.     
  2443.     triggers->next(trigPtr);
  2444.   }
  2445.   triggers->release();
  2446. }
  2447. void Dbtc::insertIntoIndexTable(Signal* signal, 
  2448.                                 TcFiredTriggerData* firedTriggerData, 
  2449.                                 ApiConnectRecordPtr* transPtr,
  2450.                                 TcConnectRecordPtr* opPtr,
  2451.                                 TcIndexData* indexData,
  2452.                                 bool holdOperation)
  2453. {
  2454.   ApiConnectRecord* regApiPtr = transPtr->p;
  2455.   TcConnectRecord* opRecord = opPtr->p;
  2456.   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
  2457.   Uint32 tcKeyRequestInfo = 0;
  2458.   Uint32 tcKeyLength = TcKeyReq::StaticLength;
  2459.   TableRecordPtr indexTabPtr;
  2460.   AttributeBuffer::DataBufferIterator iter;
  2461.   Uint32 attrId = 0;
  2462.   Uint32 keyLength = 0;
  2463.   Uint32 totalPrimaryKeyLength = 0;
  2464.   Uint32 hops;
  2465.   indexTabPtr.i = indexData->indexId;
  2466.   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
  2467.   tcKeyReq->apiConnectPtr = transPtr->i;
  2468.   tcKeyReq->senderData = opPtr->i;
  2469.   if (holdOperation) {
  2470.     jam();
  2471.     opRecord->triggerExecutionCount++;
  2472.   }//if
  2473.   // Calculate key length and renumber attribute id:s
  2474.   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
  2475.   LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
  2476.   bool skipNull = false;
  2477.   for(bool moreKeyAttrs = afterValues.first(iter); moreKeyAttrs; attrId++) {
  2478.     jam();
  2479.     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2480.     // Filter out NULL valued attributes
  2481.     if (attrHeader->isNULL()) {
  2482.       skipNull = true;
  2483.       break;
  2484.     }
  2485.     attrHeader->setAttributeId(attrId);      
  2486.     keyLength += attrHeader->getDataSize();
  2487.     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
  2488.     moreKeyAttrs = afterValues.next(iter, hops);
  2489.   }
  2490.   if (skipNull) {
  2491.     jam();
  2492.     opRecord->triggerExecutionCount--;
  2493.     if (opRecord->triggerExecutionCount == 0) {
  2494.       /*
  2495. We have completed current trigger execution
  2496. Continue triggering operation
  2497.       */
  2498.       jam();
  2499.       continueTriggeringOp(signal, opRecord);
  2500.     }//if
  2501.     return;
  2502.   }//if
  2503.   // Calculate total length of primary key to be stored in index table
  2504.   LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
  2505.   for(bool moreAttrData = keyValues.first(iter); moreAttrData; ) {
  2506.     jam();
  2507.     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2508.     
  2509.     totalPrimaryKeyLength += attrHeader->getDataSize();
  2510.     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
  2511.     moreAttrData = keyValues.next(iter, hops);
  2512.   }
  2513.   AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength);
  2514.   
  2515.   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
  2516.   tcKeyReq->attrLen = afterValues.getSize() + 
  2517.     pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
  2518.   tcKeyReq->tableId = indexData->indexId;
  2519.   TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
  2520.   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
  2521.   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
  2522.   tcKeyReq->transId1 = regApiPtr->transid[0];
  2523.   tcKeyReq->transId2 = regApiPtr->transid[1];
  2524.   Uint32 * dataPtr = &tcKeyReq->scanInfo;
  2525.   // Write first part of key in TCKEYREQ
  2526.   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
  2527.   Uint32 attrBufSize = 5; // Maximum for key in TCKEYREQ
  2528.   Uint32 dataPos = 0;
  2529.   // Filter out AttributeHeader:s since this should no be in key
  2530.   bool moreKeyData = afterValues.first(iter);
  2531.   Uint32 headerSize = 0, keyAttrSize = 0, dataSize = 0, headAndData = 0;
  2532.   while (moreKeyData && (dataPos < keyBufSize)) {
  2533.     /*
  2534.      * If we have not read complete key
  2535.      * and it fits in the signal
  2536.      */
  2537.     jam();
  2538.     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2539.     
  2540.     headerSize = attrHeader->getHeaderSize();
  2541.     keyAttrSize = attrHeader->getDataSize();
  2542.     headAndData = headerSize + attrHeader->getDataSize();
  2543.     // Skip header
  2544.     if (headerSize == 1) {
  2545.       jam();
  2546.       moreKeyData = afterValues.next(iter);
  2547.     } else {
  2548.       jam();
  2549.       moreKeyData = afterValues.next(iter, headerSize - 1);
  2550.     }//if
  2551.     while((keyAttrSize != 0) && (dataPos < keyBufSize)) {
  2552.       // If we have not read complete key
  2553.       jam();
  2554.       *dataPtr++ = *iter.data;
  2555.       dataPos++;
  2556.       keyAttrSize--;
  2557.       moreKeyData = afterValues.next(iter);
  2558.     }
  2559.     if (keyAttrSize != 0) {
  2560.       jam();
  2561.       break;
  2562.     }//if
  2563.   }
  2564.   tcKeyLength += dataPos;
  2565.   Uint32 attributesLength = afterValues.getSize() + 
  2566.     pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
  2567.   if (attributesLength <= attrBufSize) {
  2568.     jam();
  2569.     // ATTRINFO fits in TCKEYREQ
  2570.     // Pack ATTRINFO IN TCKEYREQ as one attribute
  2571.     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, attributesLength);
  2572.     bool moreAttrData;
  2573.     // Insert primary key attributes (insert after values of primary table)
  2574.     for(moreAttrData = afterValues.first(iter);
  2575. moreAttrData;
  2576. moreAttrData = afterValues.next(iter)) {      
  2577.       *dataPtr++ = *iter.data;
  2578.     }
  2579.     // Insert attribute values (insert key values of primary table)
  2580.     // as one attribute
  2581.     pkAttrHeader.insertHeader(dataPtr);
  2582.     dataPtr += pkAttrHeader.getHeaderSize();
  2583.     moreAttrData = keyValues.first(iter);
  2584.     while(moreAttrData) {
  2585.       jam();
  2586.       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2587.       
  2588.       headerSize = attrHeader->getHeaderSize();
  2589.       dataSize = attrHeader->getDataSize();
  2590.       // Skip header
  2591.       if (headerSize == 1) {
  2592.         jam();
  2593.         moreAttrData = keyValues.next(iter);
  2594.       } else {
  2595.         jam();
  2596.         moreAttrData = keyValues.next(iter, headerSize - 1);
  2597.       }//if
  2598.       // Copy attribute data
  2599.       while(dataSize-- != 0) {
  2600. *dataPtr++ = *iter.data;
  2601. moreAttrData = keyValues.next(iter);
  2602.       }
  2603.     }
  2604.     tcKeyLength += attributesLength;
  2605.   } else {
  2606.     jam();
  2607.     // No ATTRINFO in TCKEYREQ
  2608.     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
  2609.   }
  2610.   tcKeyReq->requestInfo = tcKeyRequestInfo;
  2611.   /**
  2612.    * Fix savepoint id -
  2613.    *   fix so that insert has same savepoint id as triggering operation
  2614.    */
  2615.   const Uint32 currSavePointId = regApiPtr->currSavePointId;
  2616.   regApiPtr->currSavePointId = opRecord->savePointId;
  2617.   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
  2618.   regApiPtr->currSavePointId = currSavePointId;
  2619.   tcConnectptr.p->currentIndexId = indexData->indexId;
  2620.   jamEntry();
  2621.   // *********** KEYINFO ***********
  2622.   if (moreKeyData) {
  2623.     jam();
  2624.     // Send KEYINFO sequence
  2625.     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
  2626.     
  2627.     keyInfo->connectPtr = transPtr->i;
  2628.     keyInfo->transId[0] = regApiPtr->transid[0];
  2629.     keyInfo->transId[1] = regApiPtr->transid[1];
  2630.     dataPtr = (Uint32 *) &keyInfo->keyData;
  2631.     dataPos = 0;
  2632.     // Pack any part of a key attribute that did no fit TCKEYREQ
  2633.     while((keyAttrSize != 0) && (dataPos < KeyInfo::DataLength)) {
  2634.       // If we have not read complete key
  2635.       *dataPtr++ = *iter.data;
  2636.       dataPos++;
  2637.       keyAttrSize--;
  2638.       if (dataPos == KeyInfo::DataLength) {
  2639.         jam();
  2640. // Flush KEYINFO
  2641. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2642. sendSignal(reference(), GSN_KEYINFO, signal, 
  2643.    KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
  2644. #else
  2645. EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2646.        KeyInfo::HeaderLength + KeyInfo::DataLength);
  2647.         jamEntry();
  2648. #endif
  2649. dataPtr = (Uint32 *) &keyInfo->keyData;
  2650. dataPos = 0;
  2651.       }
  2652.       moreKeyData = afterValues.next(iter);
  2653.     }
  2654.     
  2655.     while(moreKeyData) {
  2656.       jam();
  2657.       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2658.       
  2659.       headerSize = attrHeader->getHeaderSize();
  2660.       keyAttrSize = attrHeader->getDataSize();
  2661.       headAndData = headerSize + attrHeader->getDataSize();
  2662.       // Skip header
  2663.       if (headerSize == 1) {
  2664.         jam();
  2665.         moreKeyData = afterValues.next(iter);
  2666.       } else {
  2667.         jam();
  2668.         moreKeyData = afterValues.next(iter, headerSize - 1);
  2669.       }//if
  2670.       while (keyAttrSize-- != 0) {
  2671.         *dataPtr++ = *iter.data;
  2672.         dataPos++;
  2673.         if (dataPos == KeyInfo::DataLength) {
  2674.           jam();
  2675.           // Flush KEYINFO
  2676. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2677.   sendSignal(reference(), GSN_KEYINFO, signal, 
  2678.      KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
  2679. #else
  2680.           EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2681.  KeyInfo::HeaderLength + KeyInfo::DataLength);
  2682.           jamEntry();
  2683. #endif
  2684.   dataPtr = (Uint32 *) &keyInfo->keyData;   
  2685.           dataPos = 0;
  2686.         }       
  2687.         moreKeyData = afterValues.next(iter);
  2688.       }
  2689.     }
  2690.     if (dataPos != 0) {
  2691.       jam();
  2692.       // Flush last KEYINFO
  2693. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2694.       sendSignal(reference(), GSN_KEYINFO, signal, 
  2695.  KeyInfo::HeaderLength + dataPos, JBA);
  2696. #else
  2697.       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2698.      KeyInfo::HeaderLength + dataPos);
  2699.       jamEntry();
  2700. #endif
  2701.     }
  2702.   }
  2703.   
  2704.   // *********** ATTRINFO ***********
  2705.   if (attributesLength > attrBufSize) {
  2706.     jam();
  2707.     // No ATTRINFO in TcKeyReq
  2708.     TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
  2709.     // Send ATTRINFO sequence
  2710.     AttrInfo * const attrInfo =  (AttrInfo *)signal->getDataPtrSend();
  2711.     Uint32 attrInfoPos = 0;
  2712.     
  2713.     attrInfo->connectPtr = transPtr->i;
  2714.     attrInfo->transId[0] = regApiPtr->transid[0];
  2715.     attrInfo->transId[1] = regApiPtr->transid[1];
  2716.     dataPtr = (Uint32 *) &attrInfo->attrData;
  2717.     
  2718.     bool moreAttrData;
  2719.     // Insert primary key attributes (insert after values of primary table)
  2720.     for(moreAttrData = afterValues.first(iter);
  2721. moreAttrData;
  2722. moreAttrData = afterValues.next(iter)) {      
  2723.       *dataPtr++ = *iter.data;
  2724.       attrInfoPos++;
  2725.       if (attrInfoPos == AttrInfo::DataLength) {
  2726.         jam();
  2727. // Flush ATTRINFO
  2728. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2729. sendSignal(reference(), GSN_ATTRINFO, signal, 
  2730.    AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
  2731. #else
  2732. EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
  2733.        AttrInfo::HeaderLength + AttrInfo::DataLength);
  2734.         jamEntry();
  2735. #endif
  2736. dataPtr = (Uint32 *) &attrInfo->attrData;
  2737. attrInfoPos = 0;
  2738.       }
  2739.     }
  2740.     // Insert attribute values (insert key values of primary table)
  2741.     // as one attribute
  2742.     pkAttrHeader.insertHeader(dataPtr);
  2743.     dataPtr += pkAttrHeader.getHeaderSize();
  2744.     attrInfoPos += pkAttrHeader.getHeaderSize();
  2745.     moreAttrData = keyValues.first(iter);
  2746.     while(moreAttrData) {
  2747.       jam();
  2748.       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2749.       
  2750.       headerSize = attrHeader->getHeaderSize();
  2751.       dataSize = attrHeader->getDataSize();
  2752.       // Skip header
  2753.       if (headerSize == 1) {
  2754.         jam();
  2755.         moreAttrData = keyValues.next(iter);
  2756.       } else {
  2757.         jam();
  2758.         moreAttrData = keyValues.next(iter, headerSize - 1);
  2759.       }//if
  2760.       while(dataSize-- != 0) { // If we have not read complete key
  2761.         if (attrInfoPos == AttrInfo::DataLength) {
  2762.           jam();
  2763.           // Flush ATTRINFO
  2764. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2765.   sendSignal(reference(), GSN_ATTRINFO, signal, 
  2766.      AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
  2767. #else
  2768.   EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
  2769.  AttrInfo::HeaderLength + AttrInfo::DataLength);
  2770.           jamEntry();
  2771. #endif
  2772.   dataPtr = (Uint32 *) &attrInfo->attrData;   
  2773.           attrInfoPos = 0;
  2774.         }       
  2775.         *dataPtr++ = *iter.data;
  2776.         attrInfoPos++;
  2777.         moreAttrData = keyValues.next(iter);
  2778.       }
  2779.     }
  2780.     if (attrInfoPos != 0) {
  2781.       jam();
  2782.       // Flush last ATTRINFO
  2783. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2784.       sendSignal(reference(), GSN_ATTRINFO, signal, 
  2785.  AttrInfo::HeaderLength + attrInfoPos, JBA);
  2786. #else
  2787.       EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
  2788.      AttrInfo::HeaderLength + attrInfoPos);
  2789.       jamEntry();
  2790. #endif
  2791.     }
  2792.   }
  2793. }
  2794. void Dbtc::deleteFromIndexTable(Signal* signal, 
  2795.                                 TcFiredTriggerData* firedTriggerData, 
  2796.                                 ApiConnectRecordPtr* transPtr,
  2797.                                 TcConnectRecordPtr* opPtr,
  2798.                                 TcIndexData* indexData,
  2799.                                 bool holdOperation)
  2800. {
  2801.   ApiConnectRecord* regApiPtr = transPtr->p;
  2802.   TcConnectRecord* opRecord = opPtr->p;
  2803.   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
  2804.   Uint32 tcKeyRequestInfo = 0;
  2805.   Uint32 tcKeyLength = 12; // Static length
  2806.   TableRecordPtr indexTabPtr;
  2807.   AttributeBuffer::DataBufferIterator iter;
  2808.   Uint32 attrId = 0;
  2809.   Uint32 keyLength = 0;
  2810.   Uint32 hops;
  2811.   indexTabPtr.i = indexData->indexId;
  2812.   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
  2813.   tcKeyReq->apiConnectPtr = transPtr->i;
  2814.   tcKeyReq->senderData = opPtr->i;
  2815.   if (holdOperation) {
  2816.     jam();
  2817.     opRecord->triggerExecutionCount++;
  2818.   }//if
  2819.   // Calculate key length and renumber attribute id:s
  2820.   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
  2821.   LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
  2822.   bool skipNull = false;
  2823.   for(bool moreKeyAttrs = beforeValues.first(iter);
  2824.       (moreKeyAttrs);
  2825.       attrId++) {
  2826.     jam();
  2827.     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2828.     
  2829.     // Filter out NULL valued attributes
  2830.     if (attrHeader->isNULL()) {
  2831.       skipNull = true;
  2832.       break;
  2833.     }
  2834.     attrHeader->setAttributeId(attrId);      
  2835.     keyLength += attrHeader->getDataSize();
  2836.     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
  2837.     moreKeyAttrs = beforeValues.next(iter, hops);
  2838.   }
  2839.   if (skipNull) {
  2840.     jam();
  2841.     opRecord->triggerExecutionCount--;
  2842.     if (opRecord->triggerExecutionCount == 0) {
  2843.       /*
  2844.         We have completed current trigger execution
  2845. Continue triggering operation
  2846.       */
  2847.       jam();
  2848.       continueTriggeringOp(signal, opRecord);
  2849.     }//if
  2850.     return;
  2851.   }//if
  2852.   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
  2853.   tcKeyReq->attrLen = 0;
  2854.   tcKeyReq->tableId = indexData->indexId;
  2855.   TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
  2856.   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
  2857.   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
  2858.   tcKeyReq->transId1 = regApiPtr->transid[0];
  2859.   tcKeyReq->transId2 = regApiPtr->transid[1];
  2860.   Uint32 * dataPtr = &tcKeyReq->scanInfo;
  2861.   // Write first part of key in TCKEYREQ
  2862.   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
  2863.   Uint32 dataPos = 0;
  2864.   // Filter out AttributeHeader:s since this should no be in key
  2865.   bool moreKeyData = beforeValues.first(iter);
  2866.   Uint32 headerSize = 0, keyAttrSize = 0, headAndData = 0;
  2867.   while (moreKeyData && 
  2868.          (dataPos < keyBufSize)) {
  2869.     /*
  2870.     If we have not read complete key
  2871.     and it fits in the signal
  2872.     */
  2873.     jam();
  2874.     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2875.     
  2876.     headerSize = attrHeader->getHeaderSize();
  2877.     keyAttrSize = attrHeader->getDataSize();
  2878.     headAndData = headerSize + attrHeader->getDataSize();
  2879.     // Skip header
  2880.     if (headerSize == 1) {
  2881.       jam();
  2882.       moreKeyData = beforeValues.next(iter);
  2883.     } else {
  2884.       jam();
  2885.       moreKeyData = beforeValues.next(iter, headerSize - 1);
  2886.     }//if
  2887.     while((keyAttrSize != 0) && 
  2888.           (dataPos < keyBufSize)) {
  2889.       // If we have not read complete key
  2890.       jam();
  2891.       *dataPtr++ = *iter.data;
  2892.       dataPos++;
  2893.       keyAttrSize--;
  2894.       moreKeyData = beforeValues.next(iter);
  2895.     }
  2896.     if (keyAttrSize != 0) {
  2897.       jam();
  2898.       break;
  2899.     }//if
  2900.   }
  2901.   tcKeyLength += dataPos;
  2902.   tcKeyReq->requestInfo = tcKeyRequestInfo;
  2903.   /**
  2904.    * Fix savepoint id -
  2905.    *   fix so that delete has same savepoint id as triggering operation
  2906.    */
  2907.   const Uint32 currSavePointId = regApiPtr->currSavePointId;
  2908.   regApiPtr->currSavePointId = opRecord->savePointId;
  2909.   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
  2910.   regApiPtr->currSavePointId = currSavePointId;
  2911.   tcConnectptr.p->currentIndexId = indexData->indexId;
  2912.   jamEntry();
  2913.   // *********** KEYINFO ***********
  2914.   if (moreKeyData) {
  2915.     jam();
  2916.     // Send KEYINFO sequence
  2917.     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
  2918.     
  2919.     keyInfo->connectPtr = transPtr->i;
  2920.     keyInfo->transId[0] = regApiPtr->transid[0];
  2921.     keyInfo->transId[1] = regApiPtr->transid[1];
  2922.     dataPtr = (Uint32 *) &keyInfo->keyData;
  2923.     dataPos = 0;
  2924.     // Pack any part of a key attribute that did no fit TCKEYREQ
  2925.     while((keyAttrSize != 0) &&
  2926.   (dataPos < KeyInfo::DataLength)) {
  2927.       // If we have not read complete key
  2928.       *dataPtr++ = *iter.data;
  2929.       dataPos++;
  2930.       keyAttrSize--;
  2931.       if (dataPos == KeyInfo::DataLength) {
  2932.         jam();
  2933. // Flush KEYINFO
  2934. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2935. sendSignal(reference(), GSN_KEYINFO, signal, 
  2936.    KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
  2937. #else
  2938. EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2939.        KeyInfo::HeaderLength + KeyInfo::DataLength);
  2940.         jamEntry();
  2941. #endif
  2942. dataPtr = (Uint32 *) &keyInfo->keyData;
  2943. dataPos = 0;
  2944.       }
  2945.       moreKeyData = beforeValues.next(iter);
  2946.     }
  2947.     
  2948.     while(moreKeyData) {
  2949.       jam();
  2950.       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
  2951.       
  2952.       headerSize = attrHeader->getHeaderSize();
  2953.       keyAttrSize = attrHeader->getDataSize();
  2954.       headAndData = headerSize + attrHeader->getDataSize();
  2955.       // Skip header
  2956.       if (headerSize == 1) {
  2957.         jam();
  2958.         moreKeyData = beforeValues.next(iter);
  2959.       } else {
  2960.         jam();
  2961.         moreKeyData = beforeValues.next(iter, 
  2962.   headerSize - 1);
  2963.       }//if
  2964.       while (keyAttrSize-- != 0) {
  2965.         *dataPtr++ = *iter.data;
  2966.         dataPos++;
  2967.         if (dataPos == KeyInfo::DataLength) {
  2968.           jam();
  2969.           // Flush KEYINFO
  2970. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2971.   sendSignal(reference(), GSN_KEYINFO, signal, 
  2972.      KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
  2973. #else
  2974.           EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2975.  KeyInfo::HeaderLength + KeyInfo::DataLength);
  2976.           jamEntry();
  2977. #endif
  2978.   dataPtr = (Uint32 *) &keyInfo->keyData;   
  2979.           dataPos = 0;
  2980.         }       
  2981.         moreKeyData = beforeValues.next(iter);
  2982.       }
  2983.     }
  2984.     if (dataPos != 0) {
  2985.       jam();
  2986.       // Flush last KEYINFO
  2987. #if INTERNAL_TRIGGER_TCKEYREQ_JBA
  2988.       sendSignal(reference(), GSN_KEYINFO, signal, 
  2989.  KeyInfo::HeaderLength + dataPos, JBA);
  2990. #else
  2991.       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
  2992.      KeyInfo::HeaderLength + dataPos);
  2993.       jamEntry();
  2994. #endif
  2995.     }
  2996.   }
  2997. }
  2998. Uint32 
  2999. Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
  3000.   if(!enabled)
  3001.     return ZNO_SUCH_TABLE;
  3002.   if(dropping)
  3003.     return ZDROP_TABLE_IN_PROGRESS;
  3004.   if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
  3005.     return ZWRONG_SCHEMA_VERSION_ERROR;
  3006.   ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
  3007.       __FILE__, __LINE__);
  3008.   return 0;
  3009. }