📄 dbtupexecquery.cpp
字号:
jam(); retValue = updateAttributes(pagePtr, regOperPtr->pageOffset, &cinBuffer[0], regOperPtr->attrinbufLen); if (retValue == -1) { tupkeyErrorLab(signal); return -1; }//if } else { jam(); retValue = interpreterStartLab(signal, pagePtr, regOperPtr->pageOffset); }//if ndbrequire(regOperPtr->tupVersion != ZNIL); pagePtr->pageWord[regOperPtr->pageOffset + 1] = regOperPtr->tupVersion; if (regTabPtr->checksumIndicator) { jam(); setChecksum(pagePtr, regOperPtr->pageOffset, regTabPtr->tupheadsize); }//if return retValue;}//Dbtup::updateStartLab()voidDbtup::setNullBits(Page* const regPage, Tablerec* const regTabPtr, Uint32 pageOffset){ Uint32 noOfExtraNullWords = regTabPtr->tupNullWords; Uint32 nullOffsetStart = regTabPtr->tupNullIndex + pageOffset; ndbrequire((noOfExtraNullWords + nullOffsetStart) < ZWORDS_ON_PAGE); for (Uint32 i = 0; i < noOfExtraNullWords; i++) { regPage->pageWord[nullOffsetStart + i] = 0xFFFFFFFF; }//for}//Dbtup::setNullBits()boolDbtup::checkNullAttributes(Operationrec* const regOperPtr, Tablerec* const regTabPtr){// Implement checking of updating all not null attributes in an insert here. Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask; /* * The idea here is maybe that changeMask is not-null attributes * and must contain notNullAttributeMask. But: * * 1. changeMask has all bits set on insert * 2. not-null is checked in each UpdateFunction * 3. the code below does not work except trivially due to 1. * * XXX remove or fix */ attributeMask.clear(); attributeMask.bitOR(regOperPtr->changeMask); attributeMask.bitAND(regTabPtr->notNullAttributeMask); attributeMask.bitXOR(regTabPtr->notNullAttributeMask); if (!attributeMask.isclear()) { return false; }//if return true;}//Dbtup::checkNullAttributes()/* ---------------------------------------------------------------- *//* THIS IS THE START OF THE INTERPRETED EXECUTION OF UPDATES. WE *//* START BY LINKING ALL ATTRINFO'S IN A DOUBLY LINKED LIST (THEY ARE*//* ALREADY IN A LINKED LIST). WE ALLOCATE A REGISTER MEMORY (EQUAL *//* TO AN ATTRINFO RECORD). THE INTERPRETER GOES THROUGH FOUR PHASES*//* DURING THE FIRST PHASE IT IS ONLY ALLOWED TO READ ATTRIBUTES THAT*//* ARE SENT TO THE CLIENT APPLICATION. DURING THE SECOND PHASE IT IS*//* ALLOWED TO READ FROM ATTRIBUTES INTO REGISTERS, TO UPDATE *//* ATTRIBUTES BASED ON EITHER A CONSTANT VALUE OR A REGISTER VALUE, *//* A DIVERSE SET OF OPERATIONS ON REGISTERS ARE AVAILABLE AS WELL. *//* IT IS ALSO POSSIBLE TO PERFORM JUMPS WITHIN THE INSTRUCTIONS THAT*//* BELONGS TO THE SECOND PHASE. ALSO SUBROUTINES CAN BE CALLED IN *//* THIS PHASE. THE THIRD PHASE IS TO AGAIN READ ATTRIBUTES AND *//* FINALLY THE FOURTH PHASE READS SELECTED REGISTERS AND SEND THEM *//* TO THE CLIENT APPLICATION. *//* THERE IS A FIFTH REGION WHICH CONTAINS SUBROUTINES CALLABLE FROM *//* THE INTERPRETER EXECUTION REGION. *//* THE FIRST FIVE WORDS WILL GIVE THE LENGTH OF THE FIVEE REGIONS *//* *//* THIS MEANS THAT FROM THE APPLICATIONS POINT OF VIEW THE DATABASE *//* CAN HANDLE SUBROUTINE CALLS WHERE THE CODE IS SENT IN THE REQUEST*//* THE RETURN PARAMETERS ARE FIXED AND CAN EITHER BE GENERATED *//* BEFORE THE EXECUTION OF THE ROUTINE OR AFTER. *//* *//* IN LATER VERSIONS WE WILL ADD MORE THINGS LIKE THE POSSIBILITY *//* TO ALLOCATE MEMORY AND USE THIS AS LOCAL STORAGE. IT IS ALSO *//* IMAGINABLE TO HAVE SPECIAL ROUTINES THAT CAN PERFORM CERTAIN *//* OPERATIONS ON BLOB'S DEPENDENT ON WHAT THE BLOB REPRESENTS. *//* *//* *//* ----------------------------------------- *//* + INITIAL READ REGION + *//* ----------------------------------------- *//* + INTERPRETED EXECUTE REGION + *//* ----------------------------------------- *//* + FINAL UPDATE REGION + *//* ----------------------------------------- *//* + FINAL READ REGION + *//* ----------------------------------------- *//* + SUBROUTINE REGION + *//* ----------------------------------------- *//* ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *//* ----------------- INTERPRETED EXECUTION ----------------------- *//* ---------------------------------------------------------------- */int Dbtup::interpreterStartLab(Signal* signal, Page* const pagePtr, Uint32 TupHeadOffset) { Operationrec * const regOperPtr = operPtr.p; Uint32 RtotalLen; int TnoDataRW; Uint32 RinitReadLen = cinBuffer[0]; Uint32 RexecRegionLen = cinBuffer[1]; Uint32 RfinalUpdateLen = cinBuffer[2]; Uint32 RfinalRLen = cinBuffer[3]; Uint32 RsubLen = cinBuffer[4]; Uint32 RattrinbufLen = regOperPtr->attrinbufLen; const BlockReference sendBref = regOperPtr->recBlockref; Uint32 * dst = &signal->theData[25]; Uint32 dstLen = (MAX_READ / 4) - 25; const Uint32 node = refToNode(sendBref); if(node != 0 && node != getOwnNodeId()) { ; } else { jam(); /** * execute direct */ dst = &signal->theData[3]; dstLen = (MAX_READ / 4) - 3; } RtotalLen = RinitReadLen; RtotalLen += RexecRegionLen; RtotalLen += RfinalUpdateLen; RtotalLen += RfinalRLen; RtotalLen += RsubLen; Uint32 RattroutCounter = 0; Uint32 RinstructionCounter = 5; Uint32 RlogSize = 0; if (((RtotalLen + 5) == RattrinbufLen) && (RattrinbufLen >= 5) && (RattrinbufLen < ZATTR_BUFFER_SIZE)) { /* ---------------------------------------------------------------- */ // We start by checking consistency. We must have the first five // words of the ATTRINFO to give us the length of the regions. The // size of these regions must be the same as the total ATTRINFO // length and finally the total length must be within the limits. /* ---------------------------------------------------------------- */ if (RinitReadLen > 0) { jam(); /* ---------------------------------------------------------------- */ // The first step that can be taken in the interpreter is to read // data of the tuple before any updates have been applied. /* ---------------------------------------------------------------- */ TnoDataRW = readAttributes(pagePtr, TupHeadOffset, &cinBuffer[5], RinitReadLen, &dst[0], dstLen, false); if (TnoDataRW != -1) { RattroutCounter = TnoDataRW; RinstructionCounter += RinitReadLen; } else { jam(); tupkeyErrorLab(signal); return -1; }//if }//if if (RexecRegionLen > 0) { jam(); /* ---------------------------------------------------------------- */ // The next step is the actual interpreted execution. This executes // a register-based virtual machine which can read and write attributes // to and from registers. /* ---------------------------------------------------------------- */ Uint32 RsubPC = RinstructionCounter + RfinalUpdateLen + RfinalRLen; TnoDataRW = interpreterNextLab(signal, pagePtr, TupHeadOffset, &clogMemBuffer[0], &cinBuffer[RinstructionCounter], RexecRegionLen, &cinBuffer[RsubPC], RsubLen, &coutBuffer[0], sizeof(coutBuffer) / 4); if (TnoDataRW != -1) { RinstructionCounter += RexecRegionLen; RlogSize = TnoDataRW; } else { jam(); return -1; }//if }//if if (RfinalUpdateLen > 0) { jam(); /* ---------------------------------------------------------------- */ // We can also apply a set of updates without any conditions as part // of the interpreted execution. /* ---------------------------------------------------------------- */ if (regOperPtr->optype == ZUPDATE) { TnoDataRW = updateAttributes(pagePtr, TupHeadOffset, &cinBuffer[RinstructionCounter], RfinalUpdateLen); if (TnoDataRW != -1) { MEMCOPY_NO_WORDS(&clogMemBuffer[RlogSize], &cinBuffer[RinstructionCounter], RfinalUpdateLen); RinstructionCounter += RfinalUpdateLen; RlogSize += RfinalUpdateLen; } else { jam(); tupkeyErrorLab(signal); return -1; }//if } else { return TUPKEY_abort(signal, 19); }//if }//if if (RfinalRLen > 0) { jam(); /* ---------------------------------------------------------------- */ // The final action is that we can also read the tuple after it has // been updated. /* ---------------------------------------------------------------- */ TnoDataRW = readAttributes(pagePtr, TupHeadOffset, &cinBuffer[RinstructionCounter], RfinalRLen, &dst[RattroutCounter], (dstLen - RattroutCounter), false); if (TnoDataRW != -1) { RattroutCounter += TnoDataRW; } else { jam(); tupkeyErrorLab(signal); return -1; }//if }//if regOperPtr->logSize = RlogSize; regOperPtr->attroutbufLen = RattroutCounter; sendReadAttrinfo(signal, RattroutCounter, regOperPtr); if (RlogSize > 0) { sendLogAttrinfo(signal, RlogSize, regOperPtr); }//if return 0; } else { return TUPKEY_abort(signal, 22); }//if}//Dbtup::interpreterStartLab()/* ---------------------------------------------------------------- *//* WHEN EXECUTION IS INTERPRETED WE NEED TO SEND SOME ATTRINFO*//* BACK TO LQH FOR LOGGING AND SENDING TO BACKUP AND STANDBY *//* NODES. *//* INPUT: LOG_ATTRINFOPTR WHERE TO FETCH DATA FROM *//* TLOG_START FIRST INDEX TO LOG *//* TLOG_END LAST INDEX + 1 TO LOG *//* ---------------------------------------------------------------- */void Dbtup::sendLogAttrinfo(Signal* signal, Uint32 TlogSize, Operationrec * const regOperPtr){ Uint32 TbufferIndex = 0; signal->theData[0] = regOperPtr->userpointer; while (TlogSize > 22) { MEMCOPY_NO_WORDS(&signal->theData[3], &clogMemBuffer[TbufferIndex], 22); EXECUTE_DIRECT(refToBlock(regOperPtr->userblockref), GSN_TUP_ATTRINFO, signal, 25); TbufferIndex += 22; TlogSize -= 22; }//while MEMCOPY_NO_WORDS(&signal->theData[3], &clogMemBuffer[TbufferIndex], TlogSize); EXECUTE_DIRECT(refToBlock(regOperPtr->userblockref), GSN_TUP_ATTRINFO, signal, 3 + TlogSize);}//Dbtup::sendLogAttrinfo()inlineUint32 brancher(Uint32 TheInstruction, Uint32 TprogramCounter){ Uint32 TbranchDirection = TheInstruction >> 31; Uint32 TbranchLength = (TheInstruction >> 16) & 0x7fff; TprogramCounter--; if (TbranchDirection == 1) { jam(); /* ---------------------------------------------------------------- */ /* WE JUMP BACKWARDS. */ /* ---------------------------------------------------------------- */ return (TprogramCounter - TbranchLength); } else { jam(); /* ---------------------------------------------------------------- */ /* WE JUMP FORWARD. */ /* ---------------------------------------------------------------- */ return (TprogramCounter + TbranchLength); }//if}//brancher()int Dbtup::interpreterNextLab(Signal* signal, Page* const pagePtr, Uint32 TupHeadOffset, Uint32* logMemory, Uint32* mainProgram, Uint32 TmainProgLen, Uint32* subroutineProg, Uint32 TsubroutineLen, Uint32 * tmpArea, Uint32 tmpAreaSz){ register Uint32* TcurrentProgram = mainProgram; register Uint32 TcurrentSize = TmainProgLen; register Uint32 RnoOfInstructions = 0; register Uint32 TprogramCounter = 0; register Uint32 theInstruction; register Uint32 theRegister; Uint32 TdataWritten = 0; Uint32 RstackPtr = 0; union { Uint32 TregMemBuffer[32]; Uint64 Tdummy[16]; }; Uint32 TstackMemBuffer[32]; /* ---------------------------------------------------------------- */ // Initialise all 8 registers to contain the NULL value. // In this version we can handle 32 and 64 bit unsigned integers. // They are handled as 64 bit values. Thus the 32 most significant // bits are zeroed for 32 bit values. /* ---------------------------------------------------------------- */ TregMemBuffer[0] = 0; TregMemBuffer[4] = 0; TregMemBuffer[8] = 0; TregMemBuffer[12] = 0; TregMemBuffer[16] = 0; TregMemBuffer[20] = 0; TregMemBuffer[24] = 0; TregMemBuffer[28] = 0; Uint32 tmpHabitant = ~0; while (RnoOfInstructions < 8000) { /* ---------------------------------------------------------------- */ /* EXECUTE THE NEXT INTERPRETER INSTRUCTION. */ /* ---------------------------------------------------------------- */ RnoOfInstructions++; theInstruction = TcurrentProgram[TprogramCounter]; theRegister = Interpreter::getReg1(theInstruction) << 2; if (TprogramCounter < TcurrentSize) { TprogramCounter++; switch (Interpreter::getOpCode(theInstruction)) { case Interpreter::READ_ATTR_INTO_REG: jam(); /* ---------------------------------------------------------------- */ // Read an attribute from the tuple into a register.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -