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

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #define DBTUP_C
  14. #include "Dbtup.hpp"
  15. #include <RefConvert.hpp>
  16. #include <ndb_limits.h>
  17. #include <pc.hpp>
  18. #include <signaldata/TupCommit.hpp>
  19. #define ljam() { jamLine(5000 + __LINE__); }
  20. #define ljamEntry() { jamEntryLine(5000 + __LINE__); }
  21. void Dbtup::execTUP_WRITELOG_REQ(Signal* signal)
  22. {
  23.   jamEntry();
  24.   OperationrecPtr loopOpPtr;
  25.   loopOpPtr.i = signal->theData[0];
  26.   Uint32 gci = signal->theData[1];
  27.   ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
  28.   while (loopOpPtr.p->nextActiveOp != RNIL) {
  29.     ljam();
  30.     loopOpPtr.i = loopOpPtr.p->nextActiveOp;
  31.     ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
  32.   }//while
  33.   do {
  34.     Uint32 blockNo = refToBlock(loopOpPtr.p->userblockref);
  35.     ndbrequire(loopOpPtr.p->transstate == STARTED);
  36.     signal->theData[0] = loopOpPtr.p->userpointer;
  37.     signal->theData[1] = gci;
  38.     if (loopOpPtr.p->prevActiveOp == RNIL) {
  39.       ljam();
  40.       EXECUTE_DIRECT(blockNo, GSN_LQH_WRITELOG_REQ, signal, 2);
  41.       return;
  42.     }//if
  43.     ljam();
  44.     EXECUTE_DIRECT(blockNo, GSN_LQH_WRITELOG_REQ, signal, 2);
  45.     jamEntry();
  46.     loopOpPtr.i = loopOpPtr.p->prevActiveOp;
  47.     ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
  48.   } while (true);
  49. }//Dbtup::execTUP_WRITELOG_REQ()
  50. void Dbtup::execTUP_DEALLOCREQ(Signal* signal)
  51. {
  52.   TablerecPtr regTabPtr;
  53.   FragrecordPtr regFragPtr;
  54.   jamEntry();
  55.   Uint32 fragId = signal->theData[0];
  56.   regTabPtr.i = signal->theData[1];
  57.   Uint32 fragPageId = signal->theData[2];
  58.   Uint32 pageIndex = signal->theData[3];
  59.   ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
  60.   getFragmentrec(regFragPtr, fragId, regTabPtr.p);
  61.   ndbrequire(regFragPtr.p != NULL);
  62.   PagePtr pagePtr;
  63.   pagePtr.i = getRealpid(regFragPtr.p, fragPageId);
  64.   ptrCheckGuard(pagePtr, cnoOfPage, page);
  65.   Uint32 pageIndexScaled = pageIndex >> 1;
  66.   ndbrequire((pageIndex & 1) == 0);
  67.   Uint32 pageOffset = ZPAGE_HEADER_SIZE + 
  68.                      (regTabPtr.p->tupheadsize * pageIndexScaled);
  69. //---------------------------------------------------
  70. /* --- Deallocate a tuple as requested by ACC  --- */
  71. //---------------------------------------------------
  72.   if (isUndoLoggingNeeded(regFragPtr.p, fragPageId)) {
  73.     ljam();
  74.     cprAddUndoLogRecord(signal,
  75.                         ZLCPR_TYPE_INSERT_TH,
  76.                         fragPageId,
  77.                         pageIndex,
  78.                         regTabPtr.i,
  79.                         fragId,
  80.                         regFragPtr.p->checkpointVersion);
  81.     cprAddData(signal,
  82.                regFragPtr.p,
  83.                pagePtr.i,
  84.                regTabPtr.p->tupheadsize,
  85.                pageOffset);
  86.   }//if
  87.   {
  88.     freeTh(regFragPtr.p,
  89.            regTabPtr.p,
  90.            signal,
  91.            pagePtr.p,
  92.            pageOffset);
  93.   }
  94. }
  95. /* ---------------------------------------------------------------- */
  96. /* ------------ PERFORM A COMMIT ON AN UPDATE OPERATION  ---------- */
  97. /* ---------------------------------------------------------------- */
  98. void Dbtup::commitUpdate(Signal* signal,
  99.                          Operationrec*  const regOperPtr,
  100.                          Fragrecord* const regFragPtr,
  101.                          Tablerec* const regTabPtr)
  102. {
  103.   if (regOperPtr->realPageIdC != RNIL) {
  104.     if (isUndoLoggingNeeded(regFragPtr, regOperPtr->fragPageIdC)) {
  105. /* ------------------------------------------------------------------------ */
  106. /* IF THE COPY WAS CREATED WITHIN THIS CHECKPOINT WE ONLY HAVE              */
  107. /* TO LOG THE CREATION OF THE COPY. IF HOWEVER IT WAS CREATED BEFORE  SAVE  */
  108. /* THIS CHECKPOINT, WE HAVE TO THE DATA AS WELL.                            */
  109. /* ------------------------------------------------------------------------ */
  110.       if (regOperPtr->undoLogged) {
  111.         ljam();
  112.         cprAddUndoLogRecord(signal,
  113.                             ZLCPR_TYPE_INSERT_TH_NO_DATA,
  114.                             regOperPtr->fragPageIdC,
  115.                             regOperPtr->pageIndexC,
  116.                             regOperPtr->tableRef,
  117.                             regOperPtr->fragId,
  118.                             regFragPtr->checkpointVersion);
  119.       } else {
  120.         ljam();
  121.         cprAddUndoLogRecord(signal,
  122.                             ZLCPR_TYPE_INSERT_TH,
  123.                             regOperPtr->fragPageIdC,
  124.                             regOperPtr->pageIndexC,
  125.                             regOperPtr->tableRef,
  126.                             regOperPtr->fragId,
  127.                             regFragPtr->checkpointVersion);
  128.         cprAddData(signal,
  129.                    regFragPtr,
  130.                    regOperPtr->realPageIdC,
  131.                    regTabPtr->tupheadsize,
  132.                    regOperPtr->pageOffsetC);
  133.       }//if
  134.     }//if
  135.     PagePtr copyPagePtr;
  136.     copyPagePtr.i = regOperPtr->realPageIdC;
  137.     ptrCheckGuard(copyPagePtr, cnoOfPage, page);
  138.     freeTh(regFragPtr,
  139.            regTabPtr,
  140.            signal,
  141.            copyPagePtr.p,
  142.            (Uint32)regOperPtr->pageOffsetC);
  143.     regOperPtr->realPageIdC = RNIL;
  144.     regOperPtr->fragPageIdC = RNIL;
  145.     regOperPtr->pageOffsetC = ZNIL;
  146.     regOperPtr->pageIndexC = ZNIL;
  147.   }//if
  148. }//Dbtup::commitUpdate()
  149. void
  150. Dbtup::commitSimple(Signal* signal,
  151.                     Operationrec* const regOperPtr,
  152.                     Fragrecord* const regFragPtr,
  153.                     Tablerec* const regTabPtr)
  154. {
  155.   operPtr.p = regOperPtr;
  156.   fragptr.p = regFragPtr;
  157.   tabptr.p = regTabPtr;
  158.   // Checking detached triggers
  159.   checkDetachedTriggers(signal,
  160.                         regOperPtr,
  161.                         regTabPtr);
  162.   removeActiveOpList(regOperPtr);
  163.   if (regOperPtr->optype == ZUPDATE) {
  164.     ljam();
  165.     commitUpdate(signal, regOperPtr, regFragPtr, regTabPtr);
  166.     if (regTabPtr->GCPIndicator) {
  167.       updateGcpId(signal, regOperPtr, regFragPtr, regTabPtr);
  168.     }//if
  169.   } else if (regOperPtr->optype == ZINSERT) {
  170.     ljam();
  171.     if (regTabPtr->GCPIndicator) {
  172.       updateGcpId(signal, regOperPtr, regFragPtr, regTabPtr);
  173.     }//if
  174.   } else {
  175.     ndbrequire(regOperPtr->optype == ZDELETE);
  176.   }//if
  177. }//Dbtup::commitSimple()
  178. void Dbtup::removeActiveOpList(Operationrec*  const regOperPtr)
  179. {
  180.   if (regOperPtr->inActiveOpList == ZTRUE) {
  181.     OperationrecPtr raoOperPtr;
  182.     regOperPtr->inActiveOpList = ZFALSE;
  183.     if (regOperPtr->prevActiveOp != RNIL) {
  184.       ljam();
  185.       raoOperPtr.i = regOperPtr->prevActiveOp;
  186.       ptrCheckGuard(raoOperPtr, cnoOfOprec, operationrec);
  187.       raoOperPtr.p->nextActiveOp = regOperPtr->nextActiveOp;
  188.     } else {
  189.       ljam();
  190.       PagePtr pagePtr;
  191.       pagePtr.i = regOperPtr->realPageId;
  192.       ptrCheckGuard(pagePtr, cnoOfPage, page);
  193.       ndbrequire(regOperPtr->pageOffset < ZWORDS_ON_PAGE);
  194.       pagePtr.p->pageWord[regOperPtr->pageOffset] = regOperPtr->nextActiveOp;
  195.     }//if
  196.     if (regOperPtr->nextActiveOp != RNIL) {
  197.       ljam();
  198.       raoOperPtr.i = regOperPtr->nextActiveOp;
  199.       ptrCheckGuard(raoOperPtr, cnoOfOprec, operationrec);
  200.       raoOperPtr.p->prevActiveOp = regOperPtr->prevActiveOp;
  201.     }//if
  202.     regOperPtr->prevActiveOp = RNIL;
  203.     regOperPtr->nextActiveOp = RNIL;
  204.   }//if
  205. }//Dbtup::removeActiveOpList()
  206. /* ---------------------------------------------------------------- */
  207. /* INITIALIZATION OF ONE CONNECTION RECORD TO PREPARE FOR NEXT OP.  */
  208. /* ---------------------------------------------------------------- */
  209. void Dbtup::initOpConnection(Operationrec* regOperPtr,
  210.      Fragrecord * fragPtrP)
  211. {
  212.   Uint32 RinFragList = regOperPtr->inFragList;
  213.   regOperPtr->transstate = IDLE;
  214.   regOperPtr->currentAttrinbufLen = 0;
  215.   regOperPtr->optype = ZREAD;
  216.   if (RinFragList == ZTRUE) {
  217.     OperationrecPtr tropNextLinkPtr;
  218.     OperationrecPtr tropPrevLinkPtr;
  219. /*----------------------------------------------------------------- */
  220. /*       TO ENSURE THAT WE HAVE SUCCESSFUL ABORTS OF FOLLOWING      */
  221. /*       OPERATIONS WHICH NEVER STARTED WE SET THE OPTYPE TO READ.  */
  222. /*----------------------------------------------------------------- */
  223. /*       REMOVE IT FROM THE DOUBLY LINKED LIST ON THE FRAGMENT      */
  224. /*----------------------------------------------------------------- */
  225.     tropPrevLinkPtr.i = regOperPtr->prevOprecInList;
  226.     tropNextLinkPtr.i = regOperPtr->nextOprecInList;
  227.     regOperPtr->inFragList = ZFALSE;
  228.     if (tropPrevLinkPtr.i == RNIL) {
  229.       ljam();
  230.       fragPtrP->firstusedOprec = tropNextLinkPtr.i;
  231.     } else {
  232.       ljam();
  233.       ptrCheckGuard(tropPrevLinkPtr, cnoOfOprec, operationrec);
  234.       tropPrevLinkPtr.p->nextOprecInList = tropNextLinkPtr.i;
  235.     }//if
  236.     if (tropNextLinkPtr.i == RNIL) {
  237.       fragPtrP->lastusedOprec = tropPrevLinkPtr.i;
  238.     } else {
  239.       ptrCheckGuard(tropNextLinkPtr, cnoOfOprec, operationrec);
  240.       tropNextLinkPtr.p->prevOprecInList = tropPrevLinkPtr.i;
  241.     }
  242.     regOperPtr->prevOprecInList = RNIL;
  243.     regOperPtr->nextOprecInList = RNIL;
  244.   }//if
  245. }//Dbtup::initOpConnection()
  246. /* ----------------------------------------------------------------- */
  247. /* --------------- COMMIT THIS PART OF A TRANSACTION --------------- */
  248. /* ----------------------------------------------------------------- */
  249. void Dbtup::execTUP_COMMITREQ(Signal* signal) 
  250. {
  251.   FragrecordPtr regFragPtr;
  252.   OperationrecPtr regOperPtr;
  253.   TablerecPtr regTabPtr;
  254.   TupCommitReq * const tupCommitReq = (TupCommitReq *)signal->getDataPtr();
  255.   ljamEntry();
  256.   regOperPtr.i = tupCommitReq->opPtr;
  257.   ptrCheckGuard(regOperPtr, cnoOfOprec, operationrec);
  258.   ndbrequire(regOperPtr.p->transstate == STARTED);
  259.   regOperPtr.p->gci = tupCommitReq->gci;
  260.   regOperPtr.p->hashValue = tupCommitReq->hashValue;
  261.   regFragPtr.i = regOperPtr.p->fragmentPtr;
  262.   ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
  263.   regTabPtr.i = regOperPtr.p->tableRef;
  264.   ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
  265.   if (!regTabPtr.p->tuxCustomTriggers.isEmpty()) {
  266.     ljam();
  267.     executeTuxCommitTriggers(signal,
  268.                              regOperPtr.p,
  269.                              regTabPtr.p);
  270.   }
  271.   if (regOperPtr.p->tupleState == NO_OTHER_OP) {
  272.     if ((regOperPtr.p->prevActiveOp == RNIL) &&
  273.         (regOperPtr.p->nextActiveOp == RNIL)) {
  274.       ljam();
  275. /* ---------------------------------------------------------- */
  276. // We handle the simple case separately as an optimisation
  277. /* ---------------------------------------------------------- */
  278.       commitSimple(signal,
  279.                    regOperPtr.p,
  280.                    regFragPtr.p,
  281.                    regTabPtr.p);
  282.     } else {
  283. /* ---------------------------------------------------------- */
  284. // This is the first commit message of this record in this
  285. // transaction. We will commit this record completely for this
  286. // transaction. If there are other operations they will be
  287. // responsible to release their own resources. Also commit of
  288. // a delete is postponed until the last operation is committed
  289. // on the tuple.
  290. //
  291. // As part of this commitRecord we will also handle detached
  292. // triggers and release of resources for this operation.
  293. /* ---------------------------------------------------------- */
  294.       ljam();
  295.       commitRecord(signal,
  296.                    regOperPtr.p,
  297.                    regFragPtr.p,
  298.                    regTabPtr.p);
  299.       removeActiveOpList(regOperPtr.p);
  300.     }//if
  301.   } else {
  302.     ljam();
  303. /* ---------------------------------------------------------- */
  304. // Release any copy tuples
  305. /* ---------------------------------------------------------- */
  306.     ndbrequire(regOperPtr.p->tupleState == TO_BE_COMMITTED);
  307.     commitUpdate(signal, regOperPtr.p, regFragPtr.p, regTabPtr.p);
  308.     removeActiveOpList(regOperPtr.p);
  309.   }//if
  310.   initOpConnection(regOperPtr.p, regFragPtr.p);
  311. }//execTUP_COMMITREQ()
  312. void
  313. Dbtup::updateGcpId(Signal* signal,
  314.                    Operationrec* const regOperPtr,
  315.                    Fragrecord* const regFragPtr,
  316.                    Tablerec* const regTabPtr)
  317. {
  318.   PagePtr pagePtr;
  319.   ljam();
  320. //--------------------------------------------------------------------
  321. // Is this code safe for UNDO logging. Not sure currently. RONM
  322. //--------------------------------------------------------------------
  323.   pagePtr.i = regOperPtr->realPageId;
  324.   ptrCheckGuard(pagePtr, cnoOfPage, page);
  325.   Uint32 temp = regOperPtr->pageOffset + regTabPtr->tupGCPIndex;
  326.   ndbrequire((temp < ZWORDS_ON_PAGE) &&
  327.              (regTabPtr->tupGCPIndex < regTabPtr->tupheadsize));
  328.   if (isUndoLoggingNeeded(regFragPtr, regOperPtr->fragPageId)) {
  329.     Uint32 prevGCI = pagePtr.p->pageWord[temp];
  330.     ljam();
  331.     cprAddUndoLogRecord(signal,
  332.                         ZLCPR_TYPE_UPDATE_GCI,
  333.                         regOperPtr->fragPageId,
  334.                         regOperPtr->pageIndex,
  335.                         regOperPtr->tableRef,
  336.                         regOperPtr->fragId,
  337.                         regFragPtr->checkpointVersion);
  338.     cprAddGCIUpdate(signal,
  339.                     prevGCI,
  340.                     regFragPtr);
  341.   }//if
  342.   pagePtr.p->pageWord[temp] = regOperPtr->gci;
  343.   if (regTabPtr->checksumIndicator) {
  344.     ljam();
  345.     setChecksum(pagePtr.p, regOperPtr->pageOffset, regTabPtr->tupheadsize);
  346.   }//if
  347. }//Dbtup::updateGcpId()
  348. void
  349. Dbtup::commitRecord(Signal* signal,
  350.                     Operationrec* const regOperPtr,
  351.                     Fragrecord* const regFragPtr,
  352.                     Tablerec* const regTabPtr)
  353. {
  354.   Uint32 opType;
  355.   OperationrecPtr firstOpPtr;
  356.   PagePtr pagePtr;
  357.   pagePtr.i = regOperPtr->realPageId;
  358.   ptrCheckGuard(pagePtr, cnoOfPage, page);
  359.   setTupleStatesSetOpType(regOperPtr, pagePtr.p, opType, firstOpPtr);
  360.   fragptr.p = regFragPtr;
  361.   tabptr.p = regTabPtr;
  362.   if (opType == ZINSERT_DELETE) {
  363.     ljam();
  364. //--------------------------------------------------------------------
  365. // We started by inserting the tuple and ended by deleting. Seen from
  366. // transactions point of view no changes were made.
  367. //--------------------------------------------------------------------
  368.     commitUpdate(signal, regOperPtr, regFragPtr, regTabPtr);
  369.     return;
  370.   } else if (opType == ZINSERT) {
  371.     ljam();
  372. //--------------------------------------------------------------------
  373. // We started by inserting whereafter we made several changes to the
  374. // tuple that could include updates, deletes and new inserts. The final
  375. // state of the tuple is the original tuple. This is reached from this
  376. // operation. We change the optype on this operation to ZINSERT to
  377. // ensure proper operation of the detached trigger.
  378. // We restore the optype after executing triggers although not really
  379. // needed.
  380. //--------------------------------------------------------------------
  381.     Uint32 saveOpType = regOperPtr->optype;
  382.     regOperPtr->optype = ZINSERT;
  383.     operPtr.p = regOperPtr;
  384.     checkDetachedTriggers(signal,
  385.                           regOperPtr,
  386.                           regTabPtr);
  387.     regOperPtr->optype = saveOpType;
  388.   } else if (opType == ZUPDATE) {
  389.     ljam();
  390. //--------------------------------------------------------------------
  391. // We want to use the first operation which contains a copy tuple
  392. // reference. This operation contains the before value of this record
  393. // for this transaction. Then this operation is used for executing
  394. // triggers with optype set to update.
  395. //--------------------------------------------------------------------
  396.     OperationrecPtr befOpPtr;
  397.     findBeforeValueOperation(befOpPtr, firstOpPtr);
  398.     Uint32 saveOpType = befOpPtr.p->optype;
  399.     Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
  400.     Bitmask<MAXNROFATTRIBUTESINWORDS> saveAttributeMask;
  401.     calculateChangeMask(pagePtr.p,
  402.                         regTabPtr,
  403.                         befOpPtr.p->pageOffset,
  404.                         attributeMask);
  405.     saveAttributeMask.clear();
  406.     saveAttributeMask.bitOR(befOpPtr.p->changeMask);
  407.     befOpPtr.p->changeMask.clear();
  408.     befOpPtr.p->changeMask.bitOR(attributeMask);
  409.     befOpPtr.p->gci = regOperPtr->gci;
  410.     
  411.     operPtr.p = befOpPtr.p;
  412.     checkDetachedTriggers(signal,
  413.                           befOpPtr.p,
  414.                           regTabPtr);
  415.     befOpPtr.p->changeMask.clear();
  416.     befOpPtr.p->changeMask.bitOR(saveAttributeMask);
  417.     befOpPtr.p->optype = saveOpType;
  418.   } else if (opType == ZDELETE) {
  419.     ljam();
  420. //--------------------------------------------------------------------
  421. // We want to use the first operation which contains a copy tuple.
  422. // We benefit from the fact that we know that it cannot be a simple
  423. // delete and it cannot be an insert followed by a delete. Thus there
  424. // must either be an update or a insert following a delete. In both
  425. // cases we will find a before value in a copy tuple.
  426. //
  427. // An added complexity is that the trigger handling assumes that the
  428. // before value is located in the original tuple so we have to move the
  429. // copy tuple reference to the original tuple reference and afterwards
  430. // restore it again.
  431. //--------------------------------------------------------------------
  432.     OperationrecPtr befOpPtr;
  433.     findBeforeValueOperation(befOpPtr, firstOpPtr);
  434.     Uint32 saveOpType = befOpPtr.p->optype;
  435.     Uint32 realPageId = befOpPtr.p->realPageId;
  436.     Uint32 pageOffset = befOpPtr.p->pageOffset;
  437.     Uint32 fragPageId = befOpPtr.p->fragPageId;
  438.     Uint32 pageIndex  = befOpPtr.p->pageIndex;
  439.     befOpPtr.p->realPageId = befOpPtr.p->realPageIdC;
  440.     befOpPtr.p->pageOffset = befOpPtr.p->pageOffsetC;
  441.     befOpPtr.p->fragPageId = befOpPtr.p->fragPageIdC;
  442.     befOpPtr.p->pageIndex  = befOpPtr.p->pageIndexC;
  443.     befOpPtr.p->gci = regOperPtr->gci;
  444.     operPtr.p = befOpPtr.p;
  445.     checkDetachedTriggers(signal,
  446.                           befOpPtr.p,
  447.                           regTabPtr);
  448.     befOpPtr.p->realPageId = realPageId;
  449.     befOpPtr.p->pageOffset = pageOffset;
  450.     befOpPtr.p->fragPageId = fragPageId;
  451.     befOpPtr.p->pageIndex  = pageIndex;
  452.     befOpPtr.p->optype     = saveOpType;
  453.   } else {
  454.     ndbrequire(false);
  455.   }//if
  456.   commitUpdate(signal, regOperPtr, regFragPtr, regTabPtr);
  457.   if (regTabPtr->GCPIndicator) {
  458.     updateGcpId(signal, regOperPtr, regFragPtr, regTabPtr);
  459.   }//if
  460. }//Dbtup::commitRecord()
  461. void
  462. Dbtup::setTupleStatesSetOpType(Operationrec* const regOperPtr,
  463.                                Page* const pagePtr,
  464.                                Uint32& opType,
  465.                                OperationrecPtr& firstOpPtr)
  466. {
  467.   OperationrecPtr loopOpPtr;
  468.   OperationrecPtr lastOpPtr;
  469.   ndbrequire(regOperPtr->pageOffset < ZWORDS_ON_PAGE);
  470.   loopOpPtr.i = pagePtr->pageWord[regOperPtr->pageOffset];
  471.   ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
  472.   lastOpPtr = loopOpPtr;
  473.   if (loopOpPtr.p->optype == ZDELETE) {
  474.     ljam();
  475.     opType = ZDELETE;
  476.   } else {
  477.     ljam();
  478.     opType = ZUPDATE;
  479.   }//if
  480.   do {
  481.     ljam();
  482.     ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
  483.     firstOpPtr = loopOpPtr;
  484.     loopOpPtr.p->tupleState = TO_BE_COMMITTED;
  485.     loopOpPtr.i = loopOpPtr.p->nextActiveOp;
  486.   } while (loopOpPtr.i != RNIL);
  487.   if (opType == ZDELETE) {
  488.     ljam();
  489.     if (firstOpPtr.p->optype == ZINSERT) {
  490.       ljam();
  491.       opType = ZINSERT_DELETE;
  492.     }//if
  493.   } else {
  494.     ljam();
  495.     if (firstOpPtr.p->optype == ZINSERT) {
  496.       ljam();
  497.       opType = ZINSERT;
  498.     }//if
  499.   }///if
  500. }//Dbtup::setTupleStatesSetOpType()
  501. void Dbtup::findBeforeValueOperation(OperationrecPtr& befOpPtr,
  502.                                      OperationrecPtr firstOpPtr)
  503. {
  504.   befOpPtr = firstOpPtr;
  505.   if (befOpPtr.p->realPageIdC != RNIL) {
  506.     ljam();
  507.     return;
  508.   } else {
  509.     ljam();
  510.     befOpPtr.i = befOpPtr.p->prevActiveOp;
  511.     ptrCheckGuard(befOpPtr, cnoOfOprec, operationrec);
  512.     ndbrequire(befOpPtr.p->realPageIdC != RNIL);
  513.   }//if
  514. }//Dbtup::findBeforeValueOperation()
  515. void
  516. Dbtup::calculateChangeMask(Page* const pagePtr,
  517.                            Tablerec* const regTabPtr,
  518.                            Uint32 pageOffset,
  519.                            Bitmask<MAXNROFATTRIBUTESINWORDS>& attributeMask)
  520. {
  521.   OperationrecPtr loopOpPtr;
  522.   attributeMask.clear();
  523.   ndbrequire(pageOffset < ZWORDS_ON_PAGE);
  524.   loopOpPtr.i = pagePtr->pageWord[pageOffset];
  525.   do {
  526.     ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
  527.     if (loopOpPtr.p->optype == ZUPDATE) {
  528.       ljam();
  529.       attributeMask.bitOR(loopOpPtr.p->changeMask);
  530.     } else if (loopOpPtr.p->optype == ZINSERT) {
  531.       ljam();
  532.       attributeMask.set();
  533.       return;
  534.     } else {
  535.       ndbrequire(loopOpPtr.p->optype == ZDELETE);
  536.     }//if
  537.     loopOpPtr.i = loopOpPtr.p->nextActiveOp;
  538.   } while (loopOpPtr.i != RNIL);
  539. }//Dbtup::calculateChangeMask()