/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define DBACC_C #include "Dbacc.hpp" #include <AttributeHeader.hpp> #include <signaldata/AccFrag.hpp> #include <signaldata/AccScan.hpp> #include <signaldata/AccLock.hpp> #include <signaldata/EventReport.hpp> #include <signaldata/FsConf.hpp> #include <signaldata/FsRef.hpp> #include <signaldata/FsRemoveReq.hpp> #include <signaldata/DropTab.hpp> #include <signaldata/DumpStateOrd.hpp> // TO_DO_RONM is a label for comments on what needs to be improved in future versions // when more time is given. #ifdef VM_TRACE #define DEBUG(x) ndbout << "DBACC: "<< x << endl; #else #define DEBUG(x) #endif Uint32 Dbacc::remainingUndoPages(){ Uint32 HeadPage = cundoposition >> ZUNDOPAGEINDEXBITS; Uint32 TailPage = clastUndoPageIdWritten; // Head must be larger or same as tail ndbrequire(HeadPage>=TailPage); Uint32 UsedPages = HeadPage - TailPage; Int32 Remaining = cundopagesize - UsedPages; // There can not be more than cundopagesize remaining if (Remaining <= 0){ // No more undolog, crash node progError(__LINE__, ERR_NO_MORE_UNDOLOG, "There are more than 1Mbyte undolog writes outstanding"); } return Remaining; } void Dbacc::updateLastUndoPageIdWritten(Signal* signal, Uint32 aNewValue){ if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) { clastUndoPageIdWritten = aNewValue; if (remainingUndoPages() >= ZMIN_UNDO_PAGES_AT_COMMIT) { jam(); EXECUTE_DIRECT(DBLQH, GSN_ACC_COM_UNBLOCK, signal, 1); jamEntry(); }//if } else { clastUndoPageIdWritten = aNewValue; }//if }//Dbacc::updateLastUndoPageIdWritten() void Dbacc::updateUndoPositionPage(Signal* signal, Uint32 aNewValue){ if (remainingUndoPages() >= ZMIN_UNDO_PAGES_AT_COMMIT) { cundoposition = aNewValue; if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) { jam(); EXECUTE_DIRECT(DBLQH, GSN_ACC_COM_BLOCK, signal, 1); jamEntry(); }//if } else { cundoposition = aNewValue; }//if }//Dbacc::updateUndoPositionPage() // Signal entries and statement blocks /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* COMMON SIGNAL RECEPTION MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* CONTINUEB CONTINUE SIGNAL */ /* ******************------------------------------+ */ /* SENDER: ACC, LEVEL B */ void Dbacc::execCONTINUEB(Signal* signal) { Uint32 tcase; jamEntry(); tcase = signal->theData[0]; tdata0 = signal->theData[1]; tresult = 0; switch (tcase) { case ZLOAD_BAL_LCP_TIMER: if (clblPageOver == 0) { jam(); clblPageCounter = clblPagesPerTick; } else { if (clblPageOver > clblPagesPerTick) { jam(); clblPageOver = clblPageOver - clblPagesPerTick; } else { jam(); clblPageOver = 0; clblPageCounter = clblPagesPerTick - clblPageOver; }//if }//if signal->theData[0] = ZLOAD_BAL_LCP_TIMER; sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1); return; break; case ZINITIALISE_RECORDS: jam(); initialiseRecordsLab(signal, signal->theData[3], signal->theData[4]); return; break; case ZSR_READ_PAGES_ALLOC: jam(); fragrecptr.i = tdata0; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); srReadPagesAllocLab(signal); return; break; case ZSTART_UNDO: jam(); startUndoLab(signal); return; break; case ZSEND_SCAN_HBREP: jam(); sendScanHbRep(signal, tdata0); break; case ZREL_ROOT_FRAG: { jam(); Uint32 tableId = signal->theData[1]; releaseRootFragResources(signal, tableId); break; } case ZREL_FRAG: { jam(); Uint32 fragIndex = signal->theData[1]; releaseFragResources(signal, fragIndex); break; } case ZREL_DIR: { jam(); Uint32 fragIndex = signal->theData[1]; Uint32 dirIndex = signal->theData[2]; Uint32 startIndex = signal->theData[3]; releaseDirResources(signal, fragIndex, dirIndex, startIndex); break; } case ZREPORT_MEMORY_USAGE:{ jam(); static int c_currentMemUsed = 0; int now = (cnoOfAllocatedPages * 100)/cpagesize; const int thresholds[] = { 99, 90, 80, 0}; Uint32 i = 0; const Uint32 sz = sizeof(thresholds)/sizeof(thresholds[0]); for(i = 0; i<sz; i++){ if(now >= thresholds[i]){ now = thresholds[i]; break; } } if(now != c_currentMemUsed){ reportMemoryUsage(signal, now > c_currentMemUsed ? 1 : -1); } c_currentMemUsed = now; signal->theData[0] = ZREPORT_MEMORY_USAGE; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 2000, 1); return; } case ZLCP_OP_WRITE_RT_BREAK: { operationRecPtr.i= signal->theData[1]; fragrecptr.i= signal->theData[2]; lcpConnectptr.i= signal->theData[3]; ptrCheckGuard(operationRecPtr, coprecsize, operationrec); ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); lcp_write_op_to_undolog(signal); return; } default: ndbrequire(false); break; }//switch return; }//Dbacc::execCONTINUEB() /* ******************--------------------------------------------------------------- */ /* FSCLOSECONF CLOSE FILE CONF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSCLOSECONF(Signal* signal) { jamEntry(); fsConnectptr.i = signal->theData[0]; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); tresult = 0; switch (fsConnectptr.p->fsState) { case WAIT_CLOSE_UNDO: jam(); releaseFsConnRec(signal); break; case LCP_CLOSE_DATA: jam(); checkSyncUndoPagesLab(signal); return; break; case SR_CLOSE_DATA: jam(); sendaccSrconfLab(signal); return; break; default: ndbrequire(false); break; }//switch return; }//Dbacc::execFSCLOSECONF() /* ******************--------------------------------------------------------------- */ /* FSCLOSEREF OPENFILE CONF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSCLOSEREF(Signal* signal) { jamEntry(); ndbrequire(false); }//Dbacc::execFSCLOSEREF() /* ******************--------------------------------------------------------------- */ /* FSOPENCONF OPENFILE CONF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSOPENCONF(Signal* signal) { jamEntry(); fsConnectptr.i = signal->theData[0]; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); tuserptr = signal->theData[1]; tresult = 0; /* RESULT CHECK VALUE */ switch (fsConnectptr.p->fsState) { case WAIT_OPEN_UNDO_LCP: jam(); lcpOpenUndofileConfLab(signal); return; break; case WAIT_OPEN_UNDO_LCP_NEXT: jam(); fsConnectptr.p->fsPtr = tuserptr; return; break; case OPEN_UNDO_FILE_SR: jam(); fsConnectptr.p->fsPtr = tuserptr; srStartUndoLab(signal); return; break; case WAIT_OPEN_DATA_FILE_FOR_WRITE: jam(); lcpFsOpenConfLab(signal); return; break; case WAIT_OPEN_DATA_FILE_FOR_READ: jam(); fsConnectptr.p->fsPtr = tuserptr; srFsOpenConfLab(signal); return; break; default: ndbrequire(false); break; }//switch return; }//Dbacc::execFSOPENCONF() /* ******************--------------------------------------------------------------- */ /* FSOPENREF OPENFILE REF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSOPENREF(Signal* signal) { jamEntry(); ndbrequire(false); }//Dbacc::execFSOPENREF() /* ******************--------------------------------------------------------------- */ /* FSREADCONF OPENFILE CONF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSREADCONF(Signal* signal) { jamEntry(); fsConnectptr.i = signal->theData[0]; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); tresult = 0; /* RESULT CHECK VALUE */ switch (fsConnectptr.p->fsState) { case WAIT_READ_PAGE_ZERO: jam(); fragrecptr.i = fsConnectptr.p->fragrecPtr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); srReadPageZeroLab(signal); return; break; case WAIT_READ_DATA: jam(); fragrecptr.i = fsConnectptr.p->fragrecPtr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); storeDataPageInDirectoryLab(signal); return; break; case READ_UNDO_PAGE: jam(); srDoUndoLab(signal); return; break; case READ_UNDO_PAGE_AND_CLOSE: jam(); fsConnectptr.p->fsState = WAIT_CLOSE_UNDO; /* ************************ */ /* FSCLOSEREQ */ /* ************************ */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = 0; sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA); /* FLAG = DO NOT DELETE FILE */ srDoUndoLab(signal); return; break; default: ndbrequire(false); break; }//switch return; }//Dbacc::execFSREADCONF() /* ******************--------------------------------------------------------------- */ /* FSREADRREF OPENFILE CONF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSREADREF(Signal* signal) { jamEntry(); progError(0, __LINE__, "Read of file refused"); return; }//Dbacc::execFSREADREF() /* ******************--------------------------------------------------------------- */ /* FSWRITECONF OPENFILE CONF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSWRITECONF(Signal* signal) { jamEntry(); fsOpptr.i = signal->theData[0]; ptrCheckGuard(fsOpptr, cfsOpsize, fsOprec); /* FS_OPERATION PTR */ tresult = 0; /* RESULT CHECK VALUE */ fsConnectptr.i = fsOpptr.p->fsConptr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); fragrecptr.i = fsOpptr.p->fsOpfragrecPtr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); switch (fsOpptr.p->fsOpstate) { case WAIT_WRITE_UNDO: jam(); updateLastUndoPageIdWritten(signal, fsOpptr.p->fsOpMemPage); releaseFsOpRec(signal); if (fragrecptr.p->nrWaitWriteUndoExit == 0) { jam(); checkSendLcpConfLab(signal); return; } else { jam(); fragrecptr.p->lastUndoIsStored = ZTRUE; }//if return; break; case WAIT_WRITE_UNDO_EXIT: jam(); updateLastUndoPageIdWritten(signal, fsOpptr.p->fsOpMemPage); releaseFsOpRec(signal); if (fragrecptr.p->nrWaitWriteUndoExit > 0) { jam(); fragrecptr.p->nrWaitWriteUndoExit--; }//if if (fsConnectptr.p->fsState == WAIT_CLOSE_UNDO) { jam(); /* ************************ */ /* FSCLOSEREQ */ /* ************************ */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = ZFALSE; sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA); }//if if (fragrecptr.p->nrWaitWriteUndoExit == 0) { if (fragrecptr.p->lastUndoIsStored == ZTRUE) { jam(); fragrecptr.p->lastUndoIsStored = ZFALSE; checkSendLcpConfLab(signal); return; }//if }//if return; break; case WAIT_WRITE_DATA: jam(); releaseFsOpRec(signal); fragrecptr.p->activeDataFilePage += ZWRITEPAGESIZE; fragrecptr.p->activeDataPage = 0; rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); switch (fragrecptr.p->fragState) { case LCP_SEND_PAGES: jam(); savepagesLab(signal); return; break; case LCP_SEND_OVER_PAGES: jam(); saveOverPagesLab(signal); return; break; case LCP_SEND_ZERO_PAGE: jam(); saveZeroPageLab(signal); return; break; case WAIT_ZERO_PAGE_STORED: jam(); lcpCloseDataFileLab(signal); return; break; default: ndbrequire(false); return; break; }//switch break; default: ndbrequire(false); break; }//switch return; }//Dbacc::execFSWRITECONF() /* ******************--------------------------------------------------------------- */ /* FSWRITEREF OPENFILE CONF */ /* ******************------------------------------+ */ /* SENDER: FS, LEVEL B */ void Dbacc::execFSWRITEREF(Signal* signal) { jamEntry(); progError(0, __LINE__, "Write to file refused"); return; }//Dbacc::execFSWRITEREF() /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* */ /* END OF COMMON SIGNAL RECEPTION MODULE */ /* */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* */ /* SYSTEM RESTART MODULE */ /* */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ void Dbacc::execNDB_STTOR(Signal* signal) { Uint32 tstartphase; Uint32 tStartType; jamEntry(); cndbcntrRef = signal->theData[0]; cmynodeid = signal->theData[1]; tstartphase = signal->theData[2]; tStartType = signal->theData[3]; switch (tstartphase) { case ZSPH1: jam(); ndbsttorryLab(signal); return; break; case ZSPH2: cnoLcpPages = 2 * (ZWRITEPAGESIZE + 1); initialiseLcpPages(signal); ndbsttorryLab(signal); return; break; case ZSPH3: if ((tStartType == NodeState::ST_NODE_RESTART) || (tStartType == NodeState::ST_INITIAL_NODE_RESTART)) { jam(); //--------------------------------------------- // csystemRestart is used to check what is needed // during log execution. When starting a node it // is not a log execution and rather a normal // execution. Thus we reset the variable here to // avoid unnecessary system crashes. //--------------------------------------------- csystemRestart = ZFALSE; }//if signal->theData[0] = ZLOAD_BAL_LCP_TIMER; sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1); break; case ZSPH6: jam(); clblPagesPerTick = clblPagesPerTickAfterSr; csystemRestart = ZFALSE; signal->theData[0] = ZREPORT_MEMORY_USAGE; sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 2000, 1); break; default: jam(); /*empty*/; break; }//switch ndbsttorryLab(signal); return; }//Dbacc::execNDB_STTOR() /* ******************--------------------------------------------------------------- */ /* STTOR START / RESTART */ /* ******************------------------------------+ */ /* SENDER: ANY, LEVEL B */ void Dbacc::execSTTOR(Signal* signal) { jamEntry(); // tstartphase = signal->theData[1]; tuserblockref = signal->theData[3]; csignalkey = signal->theData[6]; sttorrysignalLab(signal); return; }//Dbacc::execSTTOR() /* --------------------------------------------------------------------------------- */ /* ZSPH1 */ /* --------------------------------------------------------------------------------- */ void Dbacc::ndbrestart1Lab(Signal* signal) { cmynodeid = globalData.ownId; cownBlockref = numberToRef(DBACC, cmynodeid); czero = 0; cminusOne = czero - 1; ctest = 0; cundoLogActive = ZFALSE; csystemRestart = ZTRUE; clblPageOver = 0; clblPageCounter = 0; cactiveUndoFilePage = 0; cprevUndoaddress = cminusOne; cundoposition = 0; clastUndoPageIdWritten = 0; cactiveUndoFileVersion = RNIL; cactiveOpenUndoFsPtr = RNIL; for (Uint32 tmp = 0; tmp < ZMAX_UNDO_VERSION; tmp++) { csrVersList[tmp] = RNIL; }//for return; }//Dbacc::ndbrestart1Lab() void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data) { switch (tdata0) { case 0: jam(); initialiseTableRec(signal); break; case 1: jam(); initialiseFsConnectionRec(signal); break; case 2: jam(); initialiseFsOpRec(signal); break; case 3: jam(); initialiseLcpConnectionRec(signal); break; case 4: jam(); initialiseDirRec(signal); break; case 5: jam(); initialiseDirRangeRec(signal); break; case 6: jam(); initialiseFragRec(signal); break; case 7: jam(); initialiseOverflowRec(signal); break; case 8: jam(); initialiseOperationRec(signal); break; case 9: jam(); initialisePageRec(signal); break; case 10: jam(); initialiseRootfragRec(signal); break; case 11: jam(); initialiseScanRec(signal); break; case 12: jam(); initialiseSrVerRec(signal); { ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend(); conf->senderRef = reference(); conf->senderData = data; sendSignal(ref, GSN_READ_CONFIG_CONF, signal, ReadConfigConf::SignalLength, JBB); } return; break; default: ndbrequire(false); break; }//switch signal->theData[0] = ZINITIALISE_RECORDS; signal->theData[1] = tdata0 + 1; signal->theData[2] = 0; signal->theData[3] = ref; signal->theData[4] = data; sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB); return; }//Dbacc::initialiseRecordsLab() /* *********************************<< */ /* NDB_STTORRY */ /* *********************************<< */ void Dbacc::ndbsttorryLab(Signal* signal) { signal->theData[0] = cownBlockref; sendSignal(cndbcntrRef, GSN_NDB_STTORRY, signal, 1, JBB); return; }//Dbacc::ndbsttorryLab() /* *********************************<< */ /* SIZEALT_REP SIZE ALTERATION */ /* *********************************<< */ void Dbacc::execREAD_CONFIG_REQ(Signal* signal) { const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr(); Uint32 ref = req->senderRef; Uint32 senderData = req->senderData; ndbrequire(req->noOfParameters == 0); jamEntry(); const ndb_mgm_configuration_iterator * p = theConfiguration.getOwnConfigIterator(); ndbrequire(p != 0); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_RANGE, &cdirrangesize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_ARRAY, &cdirarraysize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_FRAGMENT, &cfragmentsize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OP_RECS, &coprecsize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OVERFLOW_RECS, &coverflowrecsize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_PAGE8, &cpagesize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_ROOT_FRAG, &crootfragmentsize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_TABLE, &ctablesize)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_SCAN, &cscanRecSize)); initRecords(); ndbrestart1Lab(signal); clblPagesPerTick = 50; //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTick); clblPagesPerTickAfterSr = 50; //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTickAfterSr); tdata0 = 0; initialiseRecordsLab(signal, ref, senderData); return; }//Dbacc::execSIZEALT_REP() /* *********************************<< */ /* STTORRY */ /* *********************************<< */ void Dbacc::sttorrysignalLab(Signal* signal) { signal->theData[0] = csignalkey; signal->theData[1] = 3; /* BLOCK CATEGORY */ signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */ signal->theData[3] = ZSPH1; signal->theData[4] = 255; sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB); /* END OF START PHASES */ return; }//Dbacc::sttorrysignalLab() /* --------------------------------------------------------------------------------- */ /* INITIALISE_DIR_REC */ /* INITIALATES THE DIRECTORY RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseDirRec(Signal* signal) { DirectoryarrayPtr idrDirptr; ndbrequire(cdirarraysize > 0); for (idrDirptr.i = 0; idrDirptr.i < cdirarraysize; idrDirptr.i++) { refresh_watch_dog(); ptrAss(idrDirptr, directoryarray); for (Uint32 i = 0; i <= 255; i++) { idrDirptr.p->pagep[i] = RNIL; }//for }//for cdirmemory = 0; cfirstfreedir = RNIL; }//Dbacc::initialiseDirRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_DIR_RANGE_REC */ /* INITIALATES THE DIR_RANGE RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseDirRangeRec(Signal* signal) { DirRangePtr idrDirRangePtr; ndbrequire(cdirrangesize > 0); for (idrDirRangePtr.i = 0; idrDirRangePtr.i < cdirrangesize; idrDirRangePtr.i++) { refresh_watch_dog(); ptrAss(idrDirRangePtr, dirRange); idrDirRangePtr.p->dirArray[0] = idrDirRangePtr.i + 1; for (Uint32 i = 1; i < 256; i++) { idrDirRangePtr.p->dirArray[i] = RNIL; }//for }//for idrDirRangePtr.i = cdirrangesize - 1; ptrAss(idrDirRangePtr, dirRange); idrDirRangePtr.p->dirArray[0] = RNIL; cfirstfreeDirrange = 0; }//Dbacc::initialiseDirRangeRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_FRAG_REC */ /* INITIALATES THE FRAGMENT RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseFragRec(Signal* signal) { FragmentrecPtr regFragPtr; ndbrequire(cfragmentsize > 0); for (regFragPtr.i = 0; regFragPtr.i < cfragmentsize; regFragPtr.i++) { jam(); refresh_watch_dog(); ptrAss(regFragPtr, fragmentrec); initFragGeneral(regFragPtr); regFragPtr.p->nextfreefrag = regFragPtr.i + 1; }//for regFragPtr.i = cfragmentsize - 1; ptrAss(regFragPtr, fragmentrec); regFragPtr.p->nextfreefrag = RNIL; cfirstfreefrag = 0; }//Dbacc::initialiseFragRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_FS_CONNECTION_REC */ /* INITIALATES THE FS_CONNECTION RECORDS */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseFsConnectionRec(Signal* signal) { ndbrequire(cfsConnectsize > 0); for (fsConnectptr.i = 0; fsConnectptr.i < cfsConnectsize; fsConnectptr.i++) { ptrAss(fsConnectptr, fsConnectrec); fsConnectptr.p->fsNext = fsConnectptr.i + 1; fsConnectptr.p->fsPrev = RNIL; fsConnectptr.p->fragrecPtr = RNIL; fsConnectptr.p->fsState = WAIT_NOTHING; }//for fsConnectptr.i = cfsConnectsize - 1; ptrAss(fsConnectptr, fsConnectrec); fsConnectptr.p->fsNext = RNIL; /* INITIALITES THE LAST CONNECTRECORD */ cfsFirstfreeconnect = 0; /* INITIATES THE FIRST FREE CONNECT RECORD */ }//Dbacc::initialiseFsConnectionRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_FS_OP_REC */ /* INITIALATES THE FS_OP RECORDS */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseFsOpRec(Signal* signal) { ndbrequire(cfsOpsize > 0); for (fsOpptr.i = 0; fsOpptr.i < cfsOpsize; fsOpptr.i++) { ptrAss(fsOpptr, fsOprec); fsOpptr.p->fsOpnext = fsOpptr.i + 1; fsOpptr.p->fsOpfragrecPtr = RNIL; fsOpptr.p->fsConptr = RNIL; fsOpptr.p->fsOpstate = WAIT_NOTHING; }//for fsOpptr.i = cfsOpsize - 1; ptrAss(fsOpptr, fsOprec); fsOpptr.p->fsOpnext = RNIL; cfsFirstfreeop = 0; }//Dbacc::initialiseFsOpRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_LCP_CONNECTION_REC */ /* INITIALATES THE LCP_CONNECTION RECORDS */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseLcpConnectionRec(Signal* signal) { ndbrequire(clcpConnectsize > 0); for (lcpConnectptr.i = 0; lcpConnectptr.i < clcpConnectsize; lcpConnectptr.i++) { ptrAss(lcpConnectptr, lcpConnectrec); lcpConnectptr.p->nextLcpConn = lcpConnectptr.i + 1; lcpConnectptr.p->lcpUserptr = RNIL; lcpConnectptr.p->rootrecptr = RNIL; lcpConnectptr.p->lcpstate = LCP_FREE; }//for lcpConnectptr.i = clcpConnectsize - 1; ptrAss(lcpConnectptr, lcpConnectrec); lcpConnectptr.p->nextLcpConn = RNIL; cfirstfreelcpConnect = 0; }//Dbacc::initialiseLcpConnectionRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_OPERATION_REC */ /* INITIALATES THE OPERATION RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseOperationRec(Signal* signal) { ndbrequire(coprecsize > 0); for (operationRecPtr.i = 0; operationRecPtr.i < coprecsize; operationRecPtr.i++) { refresh_watch_dog(); ptrAss(operationRecPtr, operationrec); operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->operation = ZUNDEFINED_OP; operationRecPtr.p->opState = FREE_OP; operationRecPtr.p->nextOp = operationRecPtr.i + 1; }//for operationRecPtr.i = coprecsize - 1; ptrAss(operationRecPtr, operationrec); operationRecPtr.p->nextOp = RNIL; cfreeopRec = 0; }//Dbacc::initialiseOperationRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_OVERFLOW_REC */ /* INITIALATES THE OVERFLOW RECORDS */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseOverflowRec(Signal* signal) { OverflowRecordPtr iorOverflowRecPtr; ndbrequire(coverflowrecsize > 0); for (iorOverflowRecPtr.i = 0; iorOverflowRecPtr.i < coverflowrecsize; iorOverflowRecPtr.i++) { refresh_watch_dog(); ptrAss(iorOverflowRecPtr, overflowRecord); iorOverflowRecPtr.p->nextfreeoverrec = iorOverflowRecPtr.i + 1; }//for iorOverflowRecPtr.i = coverflowrecsize - 1; ptrAss(iorOverflowRecPtr, overflowRecord); iorOverflowRecPtr.p->nextfreeoverrec = RNIL; cfirstfreeoverrec = 0; }//Dbacc::initialiseOverflowRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_PAGE_REC */ /* INITIALATES THE PAGE RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialisePageRec(Signal* signal) { ndbrequire(cpagesize > 0); cfreepage = 0; cfirstfreepage = RNIL; cnoOfAllocatedPages = 0; }//Dbacc::initialisePageRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_LCP_PAGES */ /* INITIALATES THE LCP PAGE RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseLcpPages(Signal* signal) { Uint32 tilpIndex; ndbrequire(cnoLcpPages >= (2 * (ZWRITEPAGESIZE + 1))); /* --------------------------------------------------------------------------------- */ /* AN ABSOLUTE MINIMUM IS THAT WE HAVE 16 LCP PAGES TO HANDLE TWO CONCURRENT */ /* LCP'S ON LOCAL FRAGMENTS. */ /* --------------------------------------------------------------------------------- */ ndbrequire(cpagesize >= (cnoLcpPages + 8)); /* --------------------------------------------------------------------------------- */ /* THE NUMBER OF PAGES MUST BE AT LEAST 8 PLUS THE NUMBER OF PAGES REQUIRED BY */ /* THE LOCAL CHECKPOINT PROCESS. THIS NUMBER IS 8 TIMES THE PARALLELISM OF */ /* LOCAL CHECKPOINTS. */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* WE SET UP A LINKED LIST OF PAGES FOR EXCLUSIVE USE BY LOCAL CHECKPOINTS. */ /* --------------------------------------------------------------------------------- */ cfirstfreeLcpPage = RNIL; for (tilpIndex = 0; tilpIndex < cnoLcpPages; tilpIndex++) { jam(); seizePage(signal); rlpPageptr = spPageptr; releaseLcpPage(signal); }//for }//Dbacc::initialiseLcpPages() /* --------------------------------------------------------------------------------- */ /* INITIALISE_ROOTFRAG_REC */ /* INITIALATES THE ROOTFRAG RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseRootfragRec(Signal* signal) { ndbrequire(crootfragmentsize > 0); for (rootfragrecptr.i = 0; rootfragrecptr.i < crootfragmentsize; rootfragrecptr.i++) { refresh_watch_dog(); ptrAss(rootfragrecptr, rootfragmentrec); rootfragrecptr.p->nextroot = rootfragrecptr.i + 1; rootfragrecptr.p->fragmentptr[0] = RNIL; rootfragrecptr.p->fragmentptr[1] = RNIL; }//for rootfragrecptr.i = crootfragmentsize - 1; ptrAss(rootfragrecptr, rootfragmentrec); rootfragrecptr.p->nextroot = RNIL; cfirstfreerootfrag = 0; }//Dbacc::initialiseRootfragRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_SCAN_REC */ /* INITIALATES THE QUE_SCAN RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseScanRec(Signal* signal) { ndbrequire(cscanRecSize > 0); for (scanPtr.i = 0; scanPtr.i < cscanRecSize; scanPtr.i++) { ptrAss(scanPtr, scanRec); scanPtr.p->scanNextfreerec = scanPtr.i + 1; scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT; scanPtr.p->scanTimer = 0; scanPtr.p->scanContinuebCounter = 0; }//for scanPtr.i = cscanRecSize - 1; ptrAss(scanPtr, scanRec); scanPtr.p->scanNextfreerec = RNIL; cfirstFreeScanRec = 0; }//Dbacc::initialiseScanRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_SR_VER_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseSrVerRec(Signal* signal) { ndbrequire(csrVersionRecSize > 0); for (srVersionPtr.i = 0; srVersionPtr.i < csrVersionRecSize; srVersionPtr.i++) { ptrAss(srVersionPtr, srVersionRec); srVersionPtr.p->nextFreeSr = srVersionPtr.i + 1; }//for srVersionPtr.i = csrVersionRecSize - 1; ptrAss(srVersionPtr, srVersionRec); srVersionPtr.p->nextFreeSr = RNIL; cfirstFreeSrVersionRec = 0; }//Dbacc::initialiseSrVerRec() /* --------------------------------------------------------------------------------- */ /* INITIALISE_TABLE_REC */ /* INITIALATES THE TABLE RECORDS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initialiseTableRec(Signal* signal) { ndbrequire(ctablesize > 0); for (tabptr.i = 0; tabptr.i < ctablesize; tabptr.i++) { refresh_watch_dog(); ptrAss(tabptr, tabrec); for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) { tabptr.p->fragholder[i] = RNIL; tabptr.p->fragptrholder[i] = RNIL; }//for }//for }//Dbacc::initialiseTableRec() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF SYSTEM RESTART MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* ADD/DELETE FRAGMENT MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ void Dbacc::initRootfragrec(Signal* signal) { const AccFragReq * const req = (AccFragReq*)&signal->theData[0]; rootfragrecptr.p->mytabptr = req->tableId; rootfragrecptr.p->roothashcheck = req->kValue + req->lhFragBits; rootfragrecptr.p->noOfElements = 0; rootfragrecptr.p->m_commit_count = 0; for (Uint32 i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) { rootfragrecptr.p->scan[i] = RNIL; }//for }//Dbacc::initRootfragrec() void Dbacc::execACCFRAGREQ(Signal* signal) { const AccFragReq * const req = (AccFragReq*)&signal->theData[0]; jamEntry(); tabptr.i = req->tableId; ptrCheckGuard(tabptr, ctablesize, tabrec); ndbrequire((req->reqInfo & 0xF) == ZADDFRAG); ndbrequire(!getrootfragmentrec(signal, rootfragrecptr, req->fragId)); if (cfirstfreerootfrag == RNIL) { jam(); addFragRefuse(signal, ZFULL_ROOTFRAGRECORD_ERROR); return; }//if seizeRootfragrec(signal); if (!addfragtotab(signal, rootfragrecptr.i, req->fragId)) { jam(); releaseRootFragRecord(signal, rootfragrecptr); addFragRefuse(signal, ZFULL_ROOTFRAGRECORD_ERROR); return; }//if initRootfragrec(signal); for (Uint32 i = 0; i < 2; i++) { jam(); if (cfirstfreefrag == RNIL) { jam(); addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR); return; }//if seizeFragrec(signal); initFragGeneral(fragrecptr); initFragAdd(signal, i, rootfragrecptr.i, fragrecptr); rootfragrecptr.p->fragmentptr[i] = fragrecptr.i; rootfragrecptr.p->fragmentid[i] = fragrecptr.p->myfid; if (cfirstfreeDirrange == RNIL) { jam(); addFragRefuse(signal, ZDIR_RANGE_ERROR); return; } else { jam(); seizeDirrange(signal); }//if fragrecptr.p->directory = newDirRangePtr.i; seizeDirectory(signal); if (tresult < ZLIMIT_OF_ERROR) { jam(); newDirRangePtr.p->dirArray[0] = sdDirptr.i; } else { jam(); addFragRefuse(signal, tresult); return; }//if seizePage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); addFragRefuse(signal, tresult); return; }//if sdDirptr.p->pagep[0] = spPageptr.i; tipPageId = 0; inpPageptr = spPageptr; initPage(signal); if (cfirstfreeDirrange == RNIL) { jam(); addFragRefuse(signal, ZDIR_RANGE_ERROR); return; } else { jam(); seizeDirrange(signal); }//if fragrecptr.p->overflowdir = newDirRangePtr.i; seizeDirectory(signal); if (tresult < ZLIMIT_OF_ERROR) { jam(); newDirRangePtr.p->dirArray[0] = sdDirptr.i; } else { jam(); addFragRefuse(signal, tresult); return; }//if }//for Uint32 userPtr = req->userPtr; BlockReference retRef = req->userRef; rootfragrecptr.p->rootState = ACTIVEROOT; AccFragConf * const conf = (AccFragConf*)&signal->theData[0]; conf->userPtr = userPtr; conf->rootFragPtr = rootfragrecptr.i; conf->fragId[0] = rootfragrecptr.p->fragmentid[0]; conf->fragId[1] = rootfragrecptr.p->fragmentid[1]; conf->fragPtr[0] = rootfragrecptr.p->fragmentptr[0]; conf->fragPtr[1] = rootfragrecptr.p->fragmentptr[1]; conf->rootHashCheck = rootfragrecptr.p->roothashcheck; sendSignal(retRef, GSN_ACCFRAGCONF, signal, AccFragConf::SignalLength, JBB); }//Dbacc::execACCFRAGREQ() void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode) { const AccFragReq * const req = (AccFragReq*)&signal->theData[0]; AccFragRef * const ref = (AccFragRef*)&signal->theData[0]; Uint32 userPtr = req->userPtr; BlockReference retRef = req->userRef; ref->userPtr = userPtr; ref->errorCode = errorCode; sendSignal(retRef, GSN_ACCFRAGREF, signal, AccFragRef::SignalLength, JBB); return; }//Dbacc::addFragRefuseEarly() void Dbacc::execDROP_TAB_REQ(Signal* signal){ jamEntry(); DropTabReq* req = (DropTabReq*)signal->getDataPtr(); TabrecPtr tabPtr; tabPtr.i = req->tableId; ptrCheckGuard(tabPtr, ctablesize, tabrec); tabPtr.p->tabUserRef = req->senderRef; tabPtr.p->tabUserPtr = req->senderData; signal->theData[0] = ZREL_ROOT_FRAG; signal->theData[1] = tabPtr.i; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB); } void Dbacc::releaseRootFragResources(Signal* signal, Uint32 tableId) { RootfragmentrecPtr rootPtr; TabrecPtr tabPtr; tabPtr.i = tableId; ptrCheckGuard(tabPtr, ctablesize, tabrec); for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) { jam(); if (tabPtr.p->fragholder[i] != RNIL) { jam(); Uint32 fragIndex; rootPtr.i = tabPtr.p->fragptrholder[i]; ptrCheckGuard(rootPtr, crootfragmentsize, rootfragmentrec); if (rootPtr.p->fragmentptr[0] != RNIL) { jam(); fragIndex = rootPtr.p->fragmentptr[0]; rootPtr.p->fragmentptr[0] = RNIL; } else if (rootPtr.p->fragmentptr[1] != RNIL) { jam(); fragIndex = rootPtr.p->fragmentptr[1]; rootPtr.p->fragmentptr[1] = RNIL; } else { jam(); releaseRootFragRecord(signal, rootPtr); tabPtr.p->fragholder[i] = RNIL; tabPtr.p->fragptrholder[i] = RNIL; continue; }//if releaseFragResources(signal, fragIndex); return; }//if }//for /** * Finished... */ sendFSREMOVEREQ(signal, tableId); }//Dbacc::releaseRootFragResources() void Dbacc::releaseRootFragRecord(Signal* signal, RootfragmentrecPtr rootPtr) { rootPtr.p->nextroot = cfirstfreerootfrag; cfirstfreerootfrag = rootPtr.i; }//Dbacc::releaseRootFragRecord() void Dbacc::releaseFragResources(Signal* signal, Uint32 fragIndex) { FragmentrecPtr regFragPtr; regFragPtr.i = fragIndex; ptrCheckGuard(regFragPtr, cfragmentsize, fragmentrec); verifyFragCorrect(regFragPtr); if (regFragPtr.p->directory != RNIL) { jam(); releaseDirResources(signal, regFragPtr.i, regFragPtr.p->directory, 0); regFragPtr.p->directory = RNIL; } else if (regFragPtr.p->overflowdir != RNIL) { jam(); releaseDirResources(signal, regFragPtr.i, regFragPtr.p->overflowdir, 0); regFragPtr.p->overflowdir = RNIL; } else if (regFragPtr.p->firstOverflowRec != RNIL) { jam(); releaseOverflowResources(signal, regFragPtr); } else if (regFragPtr.p->firstFreeDirindexRec != RNIL) { jam(); releaseDirIndexResources(signal, regFragPtr); } else { RootfragmentrecPtr rootPtr; jam(); rootPtr.i = regFragPtr.p->myroot; ptrCheckGuard(rootPtr, crootfragmentsize, rootfragmentrec); releaseFragRecord(signal, regFragPtr); signal->theData[0] = ZREL_ROOT_FRAG; signal->theData[1] = rootPtr.p->mytabptr; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB); }//if }//Dbacc::releaseFragResources() void Dbacc::verifyFragCorrect(FragmentrecPtr regFragPtr) { for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) { jam(); ndbrequire(regFragPtr.p->datapages[i] == RNIL); }//for ndbrequire(regFragPtr.p->lockOwnersList == RNIL); ndbrequire(regFragPtr.p->firstWaitInQueOp == RNIL); ndbrequire(regFragPtr.p->lastWaitInQueOp == RNIL); ndbrequire(regFragPtr.p->sentWaitInQueOp == RNIL); //ndbrequire(regFragPtr.p->fsConnPtr == RNIL); ndbrequire(regFragPtr.p->zeroPagePtr == RNIL); ndbrequire(regFragPtr.p->nrWaitWriteUndoExit == 0); ndbrequire(regFragPtr.p->sentWaitInQueOp == RNIL); }//Dbacc::verifyFragCorrect() void Dbacc::releaseDirResources(Signal* signal, Uint32 fragIndex, Uint32 dirIndex, Uint32 startIndex) { DirRangePtr regDirRangePtr; regDirRangePtr.i = dirIndex; ptrCheckGuard(regDirRangePtr, cdirrangesize, dirRange); for (Uint32 i = startIndex; i < 256; i++) { jam(); if (regDirRangePtr.p->dirArray[i] != RNIL) { jam(); Uint32 directoryIndex = regDirRangePtr.p->dirArray[i]; regDirRangePtr.p->dirArray[i] = RNIL; releaseDirectoryResources(signal, fragIndex, dirIndex, (i + 1), directoryIndex); return; }//if }//for rdDirRangePtr = regDirRangePtr; releaseDirrange(signal); signal->theData[0] = ZREL_FRAG; signal->theData[1] = fragIndex; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB); }//Dbacc::releaseDirResources() void Dbacc::releaseDirectoryResources(Signal* signal, Uint32 fragIndex, Uint32 dirIndex, Uint32 startIndex, Uint32 directoryIndex) { DirectoryarrayPtr regDirPtr; regDirPtr.i = directoryIndex; ptrCheckGuard(regDirPtr, cdirarraysize, directoryarray); for (Uint32 i = 0; i < 256; i++) { jam(); if (regDirPtr.p->pagep[i] != RNIL) { jam(); rpPageptr.i = regDirPtr.p->pagep[i]; ptrCheckGuard(rpPageptr, cpagesize, page8); releasePage(signal); regDirPtr.p->pagep[i] = RNIL; }//if }//for rdDirptr = regDirPtr; releaseDirectory(signal); signal->theData[0] = ZREL_DIR; signal->theData[1] = fragIndex; signal->theData[2] = dirIndex; signal->theData[3] = startIndex; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB); }//Dbacc::releaseDirectoryResources() void Dbacc::releaseOverflowResources(Signal* signal, FragmentrecPtr regFragPtr) { Uint32 loopCount = 0; OverflowRecordPtr regOverflowRecPtr; while ((regFragPtr.p->firstOverflowRec != RNIL) && (loopCount < 1)) { jam(); regOverflowRecPtr.i = regFragPtr.p->firstOverflowRec; ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord); regFragPtr.p->firstOverflowRec = regOverflowRecPtr.p->nextOverRec; rorOverflowRecPtr = regOverflowRecPtr; releaseOverflowRec(signal); loopCount++; }//while signal->theData[0] = ZREL_FRAG; signal->theData[1] = regFragPtr.i; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB); }//Dbacc::releaseOverflowResources() void Dbacc::releaseDirIndexResources(Signal* signal, FragmentrecPtr regFragPtr) { Uint32 loopCount = 0; OverflowRecordPtr regOverflowRecPtr; while ((regFragPtr.p->firstFreeDirindexRec != RNIL) && (loopCount < 1)) { jam(); regOverflowRecPtr.i = regFragPtr.p->firstFreeDirindexRec; ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord); regFragPtr.p->firstFreeDirindexRec = regOverflowRecPtr.p->nextOverList; rorOverflowRecPtr = regOverflowRecPtr; releaseOverflowRec(signal); loopCount++; }//while signal->theData[0] = ZREL_FRAG; signal->theData[1] = regFragPtr.i; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB); }//Dbacc::releaseDirIndexResources() void Dbacc::releaseFragRecord(Signal* signal, FragmentrecPtr regFragPtr) { regFragPtr.p->nextfreefrag = cfirstfreefrag; cfirstfreefrag = regFragPtr.i; initFragGeneral(regFragPtr); }//Dbacc::releaseFragRecord() void Dbacc::sendFSREMOVEREQ(Signal* signal, Uint32 tableId) { FsRemoveReq * const fsReq = (FsRemoveReq *)signal->getDataPtrSend(); fsReq->userReference = cownBlockref; fsReq->userPointer = tableId; fsReq->fileNumber[0] = tableId; fsReq->fileNumber[1] = (Uint32)-1; // Remove all fragments fsReq->fileNumber[2] = (Uint32)-1; // Remove all data files within fragment fsReq->fileNumber[3] = 255 | // No P-value used here (3 << 8) | // Data-files in D3 (0 << 16) | // Data-files (1 << 24); // Version 1 of fileNumber fsReq->directory = 1; fsReq->ownDirectory = 1; sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, FsRemoveReq::SignalLength, JBA); }//Dbacc::sendFSREMOVEREQ() void Dbacc::execFSREMOVECONF(Signal* signal) { FsConf * const fsConf = (FsConf *)signal->getDataPtrSend(); TabrecPtr tabPtr; tabPtr.i = fsConf->userPointer; ptrCheckGuard(tabPtr, ctablesize, tabrec); DropTabConf * const dropConf = (DropTabConf *)signal->getDataPtrSend(); dropConf->senderRef = reference(); dropConf->senderData = tabPtr.p->tabUserPtr; dropConf->tableId = tabPtr.i; sendSignal(tabPtr.p->tabUserRef, GSN_DROP_TAB_CONF, signal, DropTabConf::SignalLength, JBB); tabPtr.p->tabUserPtr = RNIL; tabPtr.p->tabUserRef = 0; }//Dbacc::execFSREMOVECONF() void Dbacc::execFSREMOVEREF(Signal* signal) { ndbrequire(false); }//Dbacc::execFSREMOVEREF() /* -------------------------------------------------------------------------- */ /* ADDFRAGTOTAB */ /* DESCRIPTION: PUTS A FRAGMENT ID AND A POINTER TO ITS RECORD INTO */ /* TABLE ARRRAY OF THE TABLE RECORD. */ /* -------------------------------------------------------------------------- */ bool Dbacc::addfragtotab(Signal* signal, Uint32 rootIndex, Uint32 fid) { for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) { jam(); if (tabptr.p->fragholder[i] == RNIL) { jam(); tabptr.p->fragholder[i] = fid; tabptr.p->fragptrholder[i] = rootIndex; return true; }//if }//for return false; }//Dbacc::addfragtotab() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF ADD/DELETE FRAGMENT MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* CONNECTION MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACCSEIZEREQ SEIZE REQ */ /* SENDER: LQH, LEVEL B */ /* ENTER ACCSEIZEREQ WITH */ /* TUSERPTR , CONECTION PTR OF LQH */ /* TUSERBLOCKREF BLOCK REFERENCE OF LQH */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACCSEIZEREQ SEIZE REQ */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execACCSEIZEREQ(Signal* signal) { jamEntry(); tuserptr = signal->theData[0]; /* CONECTION PTR OF LQH */ tuserblockref = signal->theData[1]; /* BLOCK REFERENCE OF LQH */ tresult = 0; if (cfreeopRec == RNIL) { jam(); refaccConnectLab(signal); return; }//if seizeOpRec(signal); ptrGuard(operationRecPtr); operationRecPtr.p->userptr = tuserptr; operationRecPtr.p->userblockref = tuserblockref; operationRecPtr.p->operation = ZUNDEFINED_OP; operationRecPtr.p->transactionstate = IDLE; /* ******************************< */ /* ACCSEIZECONF */ /* ******************************< */ signal->theData[0] = tuserptr; signal->theData[1] = operationRecPtr.i; sendSignal(tuserblockref, GSN_ACCSEIZECONF, signal, 2, JBB); return; }//Dbacc::execACCSEIZEREQ() void Dbacc::refaccConnectLab(Signal* signal) { tresult = ZCONNECT_SIZE_ERROR; /* ******************************< */ /* ACCSEIZEREF */ /* ******************************< */ signal->theData[0] = tuserptr; signal->theData[1] = tresult; sendSignal(tuserblockref, GSN_ACCSEIZEREF, signal, 2, JBB); return; }//Dbacc::refaccConnectLab() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF CONNECTION MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* EXECUTE OPERATION MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* INIT_OP_REC */ /* INFORMATION WHICH IS RECIEVED BY ACCKEYREQ WILL BE SAVED */ /* IN THE OPERATION RECORD. */ /* --------------------------------------------------------------------------------- */ void Dbacc::initOpRec(Signal* signal) { register Uint32 Treqinfo; Treqinfo = signal->theData[2]; operationRecPtr.p->hashValue = signal->theData[3]; operationRecPtr.p->tupkeylen = signal->theData[4]; operationRecPtr.p->transId1 = signal->theData[5]; operationRecPtr.p->transId2 = signal->theData[6]; operationRecPtr.p->transactionstate = ACTIVE; operationRecPtr.p->commitDeleteCheckFlag = ZFALSE; operationRecPtr.p->operation = Treqinfo & 0x7; /* --------------------------------------------------------------------------------- */ // opSimple is not used in this version. Is needed for deadlock handling later on. /* --------------------------------------------------------------------------------- */ // operationRecPtr.p->opSimple = (Treqinfo >> 3) & 0x1; operationRecPtr.p->lockMode = (Treqinfo >> 4) & 0x3; Uint32 readFlag = (((Treqinfo >> 4) & 0x3) == 0); // Only 1 if Read Uint32 dirtyFlag = (((Treqinfo >> 6) & 0x1) == 1); // Only 1 if Dirty Uint32 dirtyReadFlag = readFlag & dirtyFlag; operationRecPtr.p->dirtyRead = dirtyReadFlag; operationRecPtr.p->nodeType = (Treqinfo >> 7) & 0x3; operationRecPtr.p->fid = fragrecptr.p->myfid; operationRecPtr.p->fragptr = fragrecptr.i; operationRecPtr.p->nextParallelQue = RNIL; operationRecPtr.p->prevParallelQue = RNIL; operationRecPtr.p->prevQueOp = RNIL; operationRecPtr.p->nextQueOp = RNIL; operationRecPtr.p->nextSerialQue = RNIL; operationRecPtr.p->prevSerialQue = RNIL; operationRecPtr.p->elementPage = RNIL; operationRecPtr.p->keyinfoPage = RNIL; operationRecPtr.p->lockOwner = ZFALSE; operationRecPtr.p->insertIsDone = ZFALSE; operationRecPtr.p->elementIsDisappeared = ZFALSE; operationRecPtr.p->insertDeleteLen = fragrecptr.p->elementLength; operationRecPtr.p->longPagePtr = RNIL; operationRecPtr.p->longKeyPageIndex = RNIL; operationRecPtr.p->scanRecPtr = RNIL; // bit to mark lock operation operationRecPtr.p->isAccLockReq = (Treqinfo >> 31) & 0x1; }//Dbacc::initOpRec() /* --------------------------------------------------------------------------------- */ /* SEND_ACCKEYCONF */ /* --------------------------------------------------------------------------------- */ void Dbacc::sendAcckeyconf(Signal* signal) { signal->theData[0] = operationRecPtr.p->userptr; signal->theData[1] = operationRecPtr.p->insertIsDone; signal->theData[2] = operationRecPtr.p->fid; signal->theData[3] = operationRecPtr.p->localdata[0]; signal->theData[4] = operationRecPtr.p->localdata[1]; signal->theData[5] = fragrecptr.p->localkeylen; }//Dbacc::sendAcckeyconf() void Dbacc::ACCKEY_error(Uint32 fromWhere) { switch(fromWhere) { case 0: ndbrequire(false); case 1: ndbrequire(false); case 2: ndbrequire(false); case 3: ndbrequire(false); case 4: ndbrequire(false); case 5: ndbrequire(false); case 6: ndbrequire(false); case 7: ndbrequire(false); case 8: ndbrequire(false); case 9: ndbrequire(false); default: ndbrequire(false); }//switch }//Dbacc::ACCKEY_error() /* ******************--------------------------------------------------------------- */ /* ACCKEYREQ REQUEST FOR INSERT, DELETE, */ /* RERAD AND UPDATE, A TUPLE. */ /* SENDER: LQH, LEVEL B */ /* SIGNAL DATA: OPERATION_REC_PTR, CONNECTION PTR */ /* TABPTR, TABLE ID = TABLE RECORD POINTER */ /* TREQINFO, */ /* THASHVALUE, HASH VALUE OF THE TUP */ /* TKEYLEN, LENGTH OF THE PRIMARY KEYS */ /* TKEY1, PRIMARY KEY 1 */ /* TKEY2, PRIMARY KEY 2 */ /* TKEY3, PRIMARY KEY 3 */ /* TKEY4, PRIMARY KEY 4 */ /* ******************--------------------------------------------------------------- */ void Dbacc::execACCKEYREQ(Signal* signal) { jamEntry(); operationRecPtr.i = signal->theData[0]; /* CONNECTION PTR */ fragrecptr.i = signal->theData[1]; /* FRAGMENT RECORD POINTER */ if (!((operationRecPtr.i < coprecsize) || (fragrecptr.i < cfragmentsize))) { ACCKEY_error(0); return; }//if ptrAss(operationRecPtr, operationrec); ptrAss(fragrecptr, fragmentrec); ndbrequire(operationRecPtr.p->transactionstate == IDLE); initOpRec(signal); /*---------------------------------------------------------------*/ /* */ /* WE WILL USE THE HASH VALUE TO LOOK UP THE PROPER MEMORY */ /* PAGE AND MEMORY PAGE INDEX TO START THE SEARCH WITHIN. */ /* WE REMEMBER THESE ADDRESS IF WE LATER NEED TO INSERT */ /* THE ITEM AFTER NOT FINDING THE ITEM. */ /*---------------------------------------------------------------*/ getElement(signal); if (tgeResult == ZTRUE) { switch (operationRecPtr.p->operation) { case ZREAD: case ZUPDATE: case ZDELETE: case ZWRITE: case ZSCAN_OP: if (!tgeLocked){ sendAcckeyconf(signal); if (operationRecPtr.p->dirtyRead == ZFALSE) { /*---------------------------------------------------------------*/ // It is not a dirty read. We proceed by locking and continue with // the operation. /*---------------------------------------------------------------*/ Uint32 eh = gePageptr.p->word32[tgeElementptr]; operationRecPtr.p->scanBits = ElementHeader::getScanBits(eh); operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(eh); operationRecPtr.p->elementPage = gePageptr.i; operationRecPtr.p->elementContainer = tgeContainerptr; operationRecPtr.p->elementPointer = tgeElementptr; operationRecPtr.p->elementIsforward = tgeForward; eh = ElementHeader::setLocked(operationRecPtr.i); dbgWord32(gePageptr, tgeElementptr, eh); gePageptr.p->word32[tgeElementptr] = eh; insertLockOwnersList(signal , operationRecPtr); return; } else { jam(); /*---------------------------------------------------------------*/ // It is a dirty read. We do not lock anything. Set state to // IDLE since no COMMIT call will come. /*---------------------------------------------------------------*/ operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->operation = ZUNDEFINED_OP; return; }//if } else { jam(); accIsLockedLab(signal); return; }//if break; case ZINSERT: jam(); insertExistElemLab(signal); return; break; default: ndbrequire(false); break; }//switch } else if (tgeResult == ZFALSE) { switch (operationRecPtr.p->operation) { case ZINSERT: case ZWRITE: jam(); // If a write operation makes an insert we switch operation to ZINSERT so // that the commit-method knows an insert has been made and updates noOfElements. operationRecPtr.p->operation = ZINSERT; operationRecPtr.p->insertIsDone = ZTRUE; insertelementLab(signal); return; break; case ZREAD: case ZUPDATE: case ZDELETE: case ZSCAN_OP: jam(); acckeyref1Lab(signal, ZREAD_ERROR); return; break; default: ndbrequire(false); break; }//switch } else { jam(); acckeyref1Lab(signal, tgeResult); return; }//if return; }//Dbacc::execACCKEYREQ() void Dbacc::accIsLockedLab(Signal* signal) { ndbrequire(csystemRestart == ZFALSE); queOperPtr.i = ElementHeader::getOpPtrI(gePageptr.p->word32[tgeElementptr]); ptrCheckGuard(queOperPtr, coprecsize, operationrec); if (operationRecPtr.p->dirtyRead == ZFALSE) { Uint32 return_result; if (operationRecPtr.p->lockMode == ZREADLOCK) { jam(); priPageptr = gePageptr; tpriElementptr = tgeElementptr; return_result = placeReadInLockQueue(signal); } else { jam(); pwiPageptr = gePageptr; tpwiElementptr = tgeElementptr; return_result = placeWriteInLockQueue(signal); }//if if (return_result == ZPARALLEL_QUEUE) { jam(); sendAcckeyconf(signal); return; } else if (return_result == ZSERIAL_QUEUE) { jam(); signal->theData[0] = RNIL; return; } else if (return_result == ZWRITE_ERROR) { jam(); acckeyref1Lab(signal, return_result); return; }//if ndbrequire(false); } else { if (queOperPtr.p->elementIsDisappeared == ZFALSE) { jam(); /*---------------------------------------------------------------*/ // It is a dirty read. We do not lock anything. Set state to // IDLE since no COMMIT call will arrive. /*---------------------------------------------------------------*/ sendAcckeyconf(signal); operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->operation = ZUNDEFINED_OP; return; } else { jam(); /*---------------------------------------------------------------*/ // The tuple does not exist in the committed world currently. // Report read error. /*---------------------------------------------------------------*/ acckeyref1Lab(signal, ZREAD_ERROR); return; }//if }//if }//Dbacc::accIsLockedLab() /* --------------------------------------------------------------------------------- */ /* I N S E R T E X I S T E L E M E N T */ /* --------------------------------------------------------------------------------- */ void Dbacc::insertExistElemLab(Signal* signal) { if (!tgeLocked){ jam(); acckeyref1Lab(signal, ZWRITE_ERROR);/* THE ELEMENT ALREADY EXIST */ return; }//if accIsLockedLab(signal); }//Dbacc::insertExistElemLab() /* --------------------------------------------------------------------------------- */ /* INSERTELEMENT */ /* --------------------------------------------------------------------------------- */ void Dbacc::insertelementLab(Signal* signal) { Uint32 tinsKeyLen; if (fragrecptr.p->createLcp == ZTRUE) { if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_OPERATION) { jam(); acckeyref1Lab(signal, ZTEMPORARY_ACC_UNDO_FAILURE); return; }//if }//if if (fragrecptr.p->firstOverflowRec == RNIL) { jam(); allocOverflowPage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); acckeyref1Lab(signal, tresult); return; }//if }//if if (fragrecptr.p->keyLength != operationRecPtr.p->tupkeylen) { ndbrequire(fragrecptr.p->keyLength == 0); }//if if (fragrecptr.p->keyLength != 0) { ndbrequire(operationRecPtr.p->tupkeylen <= 8); for (Uint32 i = 0; i < operationRecPtr.p->tupkeylen; i++) { jam(); ckeys[i] = signal->theData[i + 7]; }//for tinsKeyLen = operationRecPtr.p->tupkeylen; } else { jam(); seizePage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); acckeyref1Lab(signal, tresult); return; }//if operationRecPtr.p->keyinfoPage = spPageptr.i; for (Uint32 i = 0; i < signal->theData[4]; i++) { spPageptr.p->word32[i] = signal->theData[i + 7]; }//for getLongKeyPage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); acckeyref1Lab(signal, tresult); return; }//if slkPageptr = glkPageptr; slkCopyPageptr.i = operationRecPtr.p->keyinfoPage; ptrCheckGuard(slkCopyPageptr, cpagesize, page8); tslkKeyLen = operationRecPtr.p->tupkeylen; storeLongKeys(signal); ckeys[0] = (slkPageptr.p->word32[ZPOS_PAGE_ID] << 10) + tslkPageIndex; tinsKeyLen = ZACTIVE_LONG_KEY_LEN; rpPageptr.i = operationRecPtr.p->keyinfoPage; ptrCheckGuard(rpPageptr, cpagesize, page8); releasePage(signal); operationRecPtr.p->keyinfoPage = RNIL; }//if signal->theData[0] = operationRecPtr.p->userptr; Uint32 blockNo = refToBlock(operationRecPtr.p->userblockref); EXECUTE_DIRECT(blockNo, GSN_LQH_ALLOCREQ, signal, 1); jamEntry(); if (signal->theData[0] != 0) { jam(); Uint32 result_code = signal->theData[0]; acckeyref1Lab(signal, result_code); return; }//if Uint32 localKey = (signal->theData[1] << MAX_TUPLES_BITS) + signal->theData[2]; insertLockOwnersList(signal, operationRecPtr); const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits; operationRecPtr.p->hashvaluePart = (operationRecPtr.p->hashValue >> tmp) & 0xFFFF; operationRecPtr.p->scanBits = 0; /* NOT ANY ACTIVE SCAN */ tidrElemhead = ElementHeader::setLocked(operationRecPtr.i); idrPageptr = gdiPageptr; tidrPageindex = tgdiPageindex; tidrForward = ZTRUE; tidrKeyLen = tinsKeyLen; idrOperationRecPtr = operationRecPtr; clocalkey[0] = localKey; operationRecPtr.p->localdata[0] = localKey; /* --------------------------------------------------------------------------------- */ /* WE SET THE LOCAL KEY TO MINUS ONE TO INDICATE IT IS NOT YET VALID. */ /* --------------------------------------------------------------------------------- */ insertElement(signal); sendAcckeyconf(signal); return; }//Dbacc::insertelementLab() /* --------------------------------------------------------------------------------- */ /* PLACE_READ_IN_LOCK_QUEUE */ /* INPUT: OPERATION_REC_PTR OUR OPERATION POINTER */ /* QUE_OPER_PTR LOCK QUEUE OWNER OPERATION POINTER */ /* PRI_PAGEPTR PAGE POINTER OF ELEMENT */ /* TPRI_ELEMENTPTR ELEMENT POINTER OF ELEMENT */ /* OUTPUT TRESULT = */ /* ZPARALLEL_QUEUE OPERATION PLACED IN PARALLEL QUEUE */ /* OPERATION CAN PROCEED NOW. */ /* ZSERIAL_QUEUE OPERATION PLACED IN SERIAL QUEUE */ /* ERROR CODE OPERATION NEEDS ABORTING */ /* THE ELEMENT WAS LOCKED AND WE WANT TO READ THE TUPLE. WE WILL CHECK THE LOCK */ /* QUEUES TO PERFORM THE PROPER ACTION. */ /* */ /* IN SOME PLACES IN THE CODE BELOW THAT HANDLES WHAT TO DO WHEN THE TUPLE IS LOCKED */ /* WE DO ASSUME THAT NEXT_PARALLEL_QUEUE AND NEXT_SERIAL_QUEUE ON OPERATION_REC_PTR */ /* HAVE BEEN INITIALISED TO RNIL. THUS WE DO NOT PERFORM THIS ONCE MORE EVEN IF IT */ /* COULD BE NICE FOR READABILITY. */ /* --------------------------------------------------------------------------------- */ Uint32 Dbacc::placeReadInLockQueue(Signal* signal) { tgnptMainOpPtr = queOperPtr; getNoParallelTransaction(signal); if (tgnptNrTransaction == 1) { if ((queOperPtr.p->transId1 == operationRecPtr.p->transId1) && (queOperPtr.p->transId2 == operationRecPtr.p->transId2)) { /* --------------------------------------------------------------------------------- */ /* WE ARE PERFORMING A READ OPERATION AND THIS TRANSACTION ALREADY OWNS THE LOCK */ /* ALONE. PUT THE OPERATION LAST IN THE PARALLEL QUEUE. */ /* --------------------------------------------------------------------------------- */ jam(); mlpqOperPtr = queOperPtr; moveLastParallelQueue(signal); operationRecPtr.p->localdata[0] = queOperPtr.p->localdata[0]; operationRecPtr.p->localdata[1] = queOperPtr.p->localdata[1]; operationRecPtr.p->prevParallelQue = mlpqOperPtr.i; mlpqOperPtr.p->nextParallelQue = operationRecPtr.i; switch (queOperPtr.p->lockMode) { case ZREADLOCK: jam(); /*empty*/; break; default: jam(); /* --------------------------------------------------------------------------------- */ /* IF THE TRANSACTION PREVIOUSLY SET A WRITE LOCK WE MUST ENSURE THAT ALL */ /* OPERATIONS IN THE PARALLEL QUEUE HAVE WRITE LOCK MODE TO AVOID STRANGE BUGS.*/ /* --------------------------------------------------------------------------------- */ operationRecPtr.p->lockMode = queOperPtr.p->lockMode; break; }//switch return ZPARALLEL_QUEUE; }//if }//if if (queOperPtr.p->nextSerialQue == RNIL) { /* --------------------------------------------------------------------------------- */ /* WE ARE PERFORMING A READ OPERATION AND THERE IS NO SERIAL QUEUE. IF THERE IS NO */ /* WRITE OPERATION THAT OWNS THE LOCK OR ANY WRITE OPERATION IN THE PARALLEL QUEUE */ /* IT IS ENOUGH TO CHECK THE LOCK MODE OF THE LEADER IN THE PARALLEL QUEUE. IF IT IS */ /* A READ LOCK THEN WE PLACE OURSELVES IN THE PARALLEL QUEUE OTHERWISE WE GO ON TO */ /* PLACE OURSELVES IN THE SERIAL QUEUE. */ /* --------------------------------------------------------------------------------- */ switch (queOperPtr.p->lockMode) { case ZREADLOCK: jam(); mlpqOperPtr = queOperPtr; moveLastParallelQueue(signal); operationRecPtr.p->prevParallelQue = mlpqOperPtr.i; mlpqOperPtr.p->nextParallelQue = operationRecPtr.i; operationRecPtr.p->localdata[0] = queOperPtr.p->localdata[0]; operationRecPtr.p->localdata[1] = queOperPtr.p->localdata[1]; return ZPARALLEL_QUEUE; default: jam(); queOperPtr.p->nextSerialQue = operationRecPtr.i; operationRecPtr.p->prevSerialQue = queOperPtr.i; putOpInFragWaitQue(signal); break; }//switch } else { jam(); placeSerialQueueRead(signal); }//if return ZSERIAL_QUEUE; }//Dbacc::placeReadInLockQueue() /* --------------------------------------------------------------------------------- */ /* WE WILL CHECK IF THIS TRANSACTION IS ALREADY PLACED AT SOME SPOT IN THE PARALLEL */ /* SERIAL QUEUE WITHOUT ANY NEIGHBORS FROM OTHER TRANSACTION. IF SO WE WILL INSERT */ /* IT IN THAT PARALLEL QUEUE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::placeSerialQueueRead(Signal* signal) { readWriteOpPtr.i = queOperPtr.p->nextSerialQue; ptrCheckGuard(readWriteOpPtr, coprecsize, operationrec); PSQR_LOOP: jam(); if (readWriteOpPtr.p->nextSerialQue == RNIL) { jam(); /* --------------------------------------------------------------------------------- */ /* THERE WAS NO PREVIOUS OPERATION IN THIS TRANSACTION WHICH WE COULD PUT IT */ /* IN THE PARALLEL QUEUE TOGETHER WITH. */ /* --------------------------------------------------------------------------------- */ checkOnlyReadEntry(signal); return; }//if tgnptMainOpPtr = readWriteOpPtr; getNoParallelTransaction(signal); if (tgnptNrTransaction == 1) { jam(); /* --------------------------------------------------------------------------------- */ /* THERE WAS ONLY ONE TRANSACTION INVOLVED IN THE PARALLEL QUEUE. IF THIS IS OUR */ /* TRANSACTION WE CAN STILL GET HOLD OF THE LOCK. */ /* --------------------------------------------------------------------------------- */ if ((readWriteOpPtr.p->transId1 == operationRecPtr.p->transId1) && (readWriteOpPtr.p->transId2 == operationRecPtr.p->transId2)) { jam(); /* --------------------------------------------------------------------------------- */ /* WE ARE PERFORMING A READ IN THE SAME TRANSACTION WHERE WE ALREADY */ /* PREVIOUSLY HAVE EXECUTED AN OPERATION. INSERT-DELETE, READ-UPDATE, READ-READ, */ /* UPDATE-UPDATE, UPDATE-DELETE, READ-DELETE, INSERT-READ, INSERT-UPDATE ARE ALLOWED */ /* COMBINATIONS. A NEW INSERT AFTER A DELETE IS NOT ALLOWED AND SUCH AN INSERT WILL */ /* GO TO THE SERIAL LOCK QUEUE WHICH IT WILL NOT LEAVE UNTIL A TIME-OUT AND THE */ /* TRANSACTION IS ABORTED. READS AND UPDATES AFTER DELETES IS ALSO NOT ALLOWED. */ /* --------------------------------------------------------------------------------- */ mlpqOperPtr = readWriteOpPtr; moveLastParallelQueue(signal); readWriteOpPtr = mlpqOperPtr; operationRecPtr.p->prevParallelQue = readWriteOpPtr.i; readWriteOpPtr.p->nextParallelQue = operationRecPtr.i; operationRecPtr.p->localdata[0] = readWriteOpPtr.p->localdata[0]; operationRecPtr.p->localdata[1] = readWriteOpPtr.p->localdata[1]; switch (readWriteOpPtr.p->lockMode) { case ZREADLOCK: jam(); /*empty*/; break; default: jam(); /* --------------------------------------------------------------------------------- */ /* IF THE TRANSACTION PREVIOUSLY SET A WRITE LOCK WE MUST ENSURE THAT ALL */ /* OPERATIONS IN THE PARALLEL QUEUE HAVE WRITE LOCK MODE TO AVOID STRANGE BUGS.*/ /* --------------------------------------------------------------------------------- */ operationRecPtr.p->lockMode = readWriteOpPtr.p->lockMode; break; }//switch putOpInFragWaitQue(signal); return; }//if }//if readWriteOpPtr.i = readWriteOpPtr.p->nextSerialQue; ptrCheckGuard(readWriteOpPtr, coprecsize, operationrec); goto PSQR_LOOP; }//Dbacc::placeSerialQueueRead() /* --------------------------------------------------------------------------------- */ /* WE WILL CHECK IF THE LAST ENTRY IN THE SERIAL QUEUE CONTAINS ONLY READ */ /* OPERATIONS. IF SO WE WILL INSERT IT IN THAT PARALLEL QUEUE. OTHERWISE WE */ /* WILL PLACE IT AT THE END OF THE SERIAL QUEUE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::checkOnlyReadEntry(Signal* signal) { switch (readWriteOpPtr.p->lockMode) { case ZREADLOCK: jam(); /* --------------------------------------------------------------------------------- */ /* SINCE THIS LAST QUEUE ONLY CONTAINS READ LOCKS WE CAN JOIN THE PARALLEL QUEUE AT */ /* THE END. */ /* --------------------------------------------------------------------------------- */ mlpqOperPtr = readWriteOpPtr; moveLastParallelQueue(signal); readWriteOpPtr = mlpqOperPtr; operationRecPtr.p->prevParallelQue = readWriteOpPtr.i; readWriteOpPtr.p->nextParallelQue = operationRecPtr.i; operationRecPtr.p->localdata[0] = readWriteOpPtr.p->localdata[0]; operationRecPtr.p->localdata[1] = readWriteOpPtr.p->localdata[1]; break; default: jam(); /* PUT THE OPERATION RECORD IN THE SERIAL QUEUE */ readWriteOpPtr.p->nextSerialQue = operationRecPtr.i; operationRecPtr.p->prevSerialQue = readWriteOpPtr.i; break; }//switch putOpInFragWaitQue(signal); }//Dbacc::checkOnlyReadEntry() /* --------------------------------------------------------------------------------- */ /* GET_NO_PARALLEL_TRANSACTION */ /* --------------------------------------------------------------------------------- */ void Dbacc::getNoParallelTransaction(Signal* signal) { OperationrecPtr tnptOpPtr; tgnptNrTransaction = 1; tnptOpPtr.i = tgnptMainOpPtr.p->nextParallelQue; while ((tnptOpPtr.i != RNIL) && (tgnptNrTransaction == 1)) { jam(); ptrCheckGuard(tnptOpPtr, coprecsize, operationrec); if ((tnptOpPtr.p->transId1 == tgnptMainOpPtr.p->transId1) && (tnptOpPtr.p->transId2 == tgnptMainOpPtr.p->transId2)) { tnptOpPtr.i = tnptOpPtr.p->nextParallelQue; } else { jam(); tgnptNrTransaction++; }//if }//while }//Dbacc::getNoParallelTransaction() void Dbacc::moveLastParallelQueue(Signal* signal) { while (mlpqOperPtr.p->nextParallelQue != RNIL) { jam(); mlpqOperPtr.i = mlpqOperPtr.p->nextParallelQue; ptrCheckGuard(mlpqOperPtr, coprecsize, operationrec); }//if }//Dbacc::moveLastParallelQueue() void Dbacc::moveLastParallelQueueWrite(Signal* signal) { /* --------------------------------------------------------------------------------- */ /* ENSURE THAT ALL OPERATIONS HAVE LOCK MODE SET TO WRITE SINCE WE INSERT A */ /* WRITE LOCK INTO THE PARALLEL QUEUE. */ /* --------------------------------------------------------------------------------- */ while (mlpqOperPtr.p->nextParallelQue != RNIL) { jam(); mlpqOperPtr.p->lockMode = operationRecPtr.p->lockMode; mlpqOperPtr.i = mlpqOperPtr.p->nextParallelQue; ptrCheckGuard(mlpqOperPtr, coprecsize, operationrec); }//if mlpqOperPtr.p->lockMode = operationRecPtr.p->lockMode; }//Dbacc::moveLastParallelQueueWrite() /* --------------------------------------------------------------------------------- */ /* PLACE_WRITE_IN_LOCK_QUEUE */ /* INPUT: OPERATION_REC_PTR OUR OPERATION POINTER */ /* QUE_OPER_PTR LOCK QUEUE OWNER OPERATION POINTER */ /* PWI_PAGEPTR PAGE POINTER OF ELEMENT */ /* TPWI_ELEMENTPTR ELEMENT POINTER OF ELEMENT */ /* OUTPUT TRESULT = */ /* ZPARALLEL_QUEUE OPERATION PLACED IN PARALLEL QUEUE */ /* OPERATION CAN PROCEED NOW. */ /* ZSERIAL_QUEUE OPERATION PLACED IN SERIAL QUEUE */ /* ERROR CODE OPERATION NEEDS ABORTING */ /* --------------------------------------------------------------------------------- */ Uint32 Dbacc::placeWriteInLockQueue(Signal* signal) { tgnptMainOpPtr = queOperPtr; getNoParallelTransaction(signal); if (!((tgnptNrTransaction == 1) && (queOperPtr.p->transId1 == operationRecPtr.p->transId1) && (queOperPtr.p->transId2 == operationRecPtr.p->transId2))) { jam(); placeSerialQueueWrite(signal); return ZSERIAL_QUEUE; }//if /* WE ARE PERFORMING AN READ EXCLUSIVE, INSERT, UPDATE OR DELETE IN THE SAME TRANSACTION WHERE WE PREVIOUSLY HAVE EXECUTED AN OPERATION. Read-All, Update-All, Insert-All and Delete-Insert are allowed combinations. Delete-Read, Delete-Update and Delete-Delete are not an allowed combination and will result in tuple not found error. */ mlpqOperPtr = queOperPtr; moveLastParallelQueueWrite(signal); if (operationRecPtr.p->operation == ZINSERT && mlpqOperPtr.p->operation != ZDELETE){ jam(); return ZWRITE_ERROR; }//if operationRecPtr.p->localdata[0] = queOperPtr.p->localdata[0]; operationRecPtr.p->localdata[1] = queOperPtr.p->localdata[1]; operationRecPtr.p->prevParallelQue = mlpqOperPtr.i; mlpqOperPtr.p->nextParallelQue = operationRecPtr.i; return ZPARALLEL_QUEUE; }//Dbacc::placeWriteInLockQueue() /* --------------------------------------------------------------------------------- */ /* WE HAVE TO PLACE IT SOMEWHERE IN THE SERIAL QUEUE INSTEAD. */ /* --------------------------------------------------------------------------------- */ void Dbacc::placeSerialQueueWrite(Signal* signal) { readWriteOpPtr = queOperPtr; PSQW_LOOP: if (readWriteOpPtr.p->nextSerialQue == RNIL) { jam(); /* --------------------------------------------------------------------------------- */ /* WE COULD NOT PUT IN ANY PARALLEL QUEUE. WE MUST PUT IT LAST IN THE SERIAL QUEUE. */ /* --------------------------------------------------------------------------------- */ readWriteOpPtr.p->nextSerialQue = operationRecPtr.i; operationRecPtr.p->prevSerialQue = readWriteOpPtr.i; putOpInFragWaitQue(signal); return; }//if readWriteOpPtr.i = readWriteOpPtr.p->nextSerialQue; ptrCheckGuard(readWriteOpPtr, coprecsize, operationrec); tgnptMainOpPtr = readWriteOpPtr; getNoParallelTransaction(signal); if (tgnptNrTransaction == 1) { /* --------------------------------------------------------------------------------- */ /* THERE WAS ONLY ONE TRANSACTION INVOLVED IN THE PARALLEL QUEUE. IF THIS IS OUR */ /* TRANSACTION WE CAN STILL GET HOLD OF THE LOCK. */ /* --------------------------------------------------------------------------------- */ if ((readWriteOpPtr.p->transId1 == operationRecPtr.p->transId1) && (readWriteOpPtr.p->transId2 == operationRecPtr.p->transId2)) { jam(); /* --------------------------------------------------------------------------------- */ /* WE ARE PERFORMING AN UPDATE OR DELETE IN THE SAME TRANSACTION WHERE WE ALREADY */ /* PREVIOUSLY HAVE EXECUTED AN OPERATION. INSERT-DELETE, READ-UPDATE, READ-READ, */ /* UPDATE-UPDATE, UPDATE-DELETE, READ-DELETE, INSERT-READ, INSERT-UPDATE ARE ALLOWED */ /* COMBINATIONS. A NEW INSERT AFTER A DELETE IS NOT ALLOWED AND SUCH AN INSERT WILL */ /* GO TO THE SERIAL LOCK QUEUE WHICH IT WILL NOT LEAVE UNTIL A TIME-OUT AND THE */ /* TRANSACTION IS ABORTED. READS AND UPDATES AFTER DELETES IS ALSO NOT ALLOWED. */ /* --------------------------------------------------------------------------------- */ mlpqOperPtr = readWriteOpPtr; moveLastParallelQueueWrite(signal); readWriteOpPtr = mlpqOperPtr; operationRecPtr.p->prevParallelQue = readWriteOpPtr.i; readWriteOpPtr.p->nextParallelQue = operationRecPtr.i; operationRecPtr.p->localdata[0] = readWriteOpPtr.p->localdata[0]; operationRecPtr.p->localdata[1] = readWriteOpPtr.p->localdata[1]; putOpInFragWaitQue(signal); return; }//if }//if goto PSQW_LOOP; }//Dbacc::placeSerialQueueWrite() /* ------------------------------------------------------------------------- */ /* ACC KEYREQ END */ /* ------------------------------------------------------------------------- */ void Dbacc::acckeyref1Lab(Signal* signal, Uint32 result_code) { if (operationRecPtr.p->keyinfoPage != RNIL) { jam(); rpPageptr.i = operationRecPtr.p->keyinfoPage; ptrCheckGuard(rpPageptr, cpagesize, page8); releasePage(signal); operationRecPtr.p->keyinfoPage = RNIL; }//if operationRecPtr.p->transactionstate = WAIT_COMMIT_ABORT; /* ************************<< */ /* ACCKEYREF */ /* ************************<< */ signal->theData[0] = cminusOne; signal->theData[1] = result_code; return; }//Dbacc::acckeyref1Lab() /* ******************--------------------------------------------------------------- */ /* ACCMINUPDATE UPDATE LOCAL KEY REQ */ /* DESCRIPTION: UPDATES LOCAL KEY OF AN ELEMENTS IN THE HASH TABLE */ /* THIS SIGNAL IS WAITED AFTER ANY INSERT REQ */ /* ENTER ACCMINUPDATE WITH SENDER: LQH, LEVEL B */ /* OPERATION_REC_PTR, OPERATION RECORD PTR */ /* CLOCALKEY(0), LOCAL KEY 1 */ /* CLOCALKEY(1) LOCAL KEY 2 */ /* ******************--------------------------------------------------------------- */ void Dbacc::execACCMINUPDATE(Signal* signal) { Page8Ptr ulkPageidptr; Uint32 tulkLocalPtr; Uint32 tlocalkey1, tlocalkey2; Uint32 TlogStart; jamEntry(); operationRecPtr.i = signal->theData[0]; tlocalkey1 = signal->theData[1]; tlocalkey2 = signal->theData[2]; ptrCheckGuard(operationRecPtr, coprecsize, operationrec); if (operationRecPtr.p->transactionstate == ACTIVE) { fragrecptr.i = operationRecPtr.p->fragptr; ulkPageidptr.i = operationRecPtr.p->elementPage; tulkLocalPtr = operationRecPtr.p->elementPointer + operationRecPtr.p->elementIsforward; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); ptrCheckGuard(ulkPageidptr, cpagesize, page8); if (fragrecptr.p->createLcp == ZTRUE) { //---------------------------------------------------------- // To avoid undo log the element header we take care to only // undo log the local key part. //---------------------------------------------------------- if (operationRecPtr.p->elementIsforward == 1) { jam(); TlogStart = tulkLocalPtr; } else { jam(); TlogStart = tulkLocalPtr - fragrecptr.p->localkeylen + 1; }//if datapageptr.p = ulkPageidptr.p; cundoinfolength = fragrecptr.p->localkeylen; cundoElemIndex = TlogStart; undoWritingProcess(signal); }//if dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey1); arrGuard(tulkLocalPtr, 2048); ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey1; operationRecPtr.p->localdata[0] = tlocalkey1; if (fragrecptr.p->localkeylen == 1) { return; } else if (fragrecptr.p->localkeylen == 2) { jam(); tulkLocalPtr = tulkLocalPtr + operationRecPtr.p->elementIsforward; operationRecPtr.p->localdata[1] = tlocalkey2; dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey2); arrGuard(tulkLocalPtr, 2048); ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey2; return; } else { jam(); }//if }//if ndbrequire(false); }//Dbacc::execACCMINUPDATE() /* ******************--------------------------------------------------------------- */ /* ACC_COMMITREQ COMMIT TRANSACTION */ /* SENDER: LQH, LEVEL B */ /* INPUT: OPERATION_REC_PTR , */ /* ******************--------------------------------------------------------------- */ void Dbacc::execACC_COMMITREQ(Signal* signal) { Uint8 Toperation; jamEntry(); operationRecPtr.i = signal->theData[0]; ptrCheckGuard(operationRecPtr, coprecsize, operationrec); ndbrequire(operationRecPtr.p->transactionstate == ACTIVE); fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); commitOperation(signal); Toperation = operationRecPtr.p->operation; operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->operation = ZUNDEFINED_OP; if(Toperation != ZREAD){ rootfragrecptr.p->m_commit_count++; if (Toperation != ZINSERT) { if (Toperation != ZDELETE) { return; } else { jam(); rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); rootfragrecptr.p->noOfElements--; fragrecptr.p->slack += operationRecPtr.p->insertDeleteLen; if (fragrecptr.p->slack > fragrecptr.p->slackCheck) { /* TIME FOR JOIN BUCKETS PROCESS */ if (fragrecptr.p->expandCounter > 0) { if (fragrecptr.p->expandFlag < 2) { jam(); signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; signal->theData[3] = fragrecptr.p->expandFlag; fragrecptr.p->expandFlag = 2; sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB); }//if }//if }//if }//if } else { jam(); /* EXPAND PROCESS HANDLING */ rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); rootfragrecptr.p->noOfElements++; fragrecptr.p->slack -= operationRecPtr.p->insertDeleteLen; if (fragrecptr.p->slack >= (1u << 31)) { /* IT MEANS THAT IF SLACK < ZERO */ if (fragrecptr.p->expandFlag == 0) { jam(); fragrecptr.p->expandFlag = 2; signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB); }//if }//if }//if } return; }//Dbacc::execACC_COMMITREQ() /* ******************--------------------------------------------------------------- */ /* ACC ABORT REQ ABORT ALL OPERATION OF THE TRANSACTION */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ /* ******************--------------------------------------------------------------- */ /* ACC ABORT REQ ABORT TRANSACTION */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execACC_ABORTREQ(Signal* signal) { jamEntry(); accAbortReqLab(signal, true); }//Dbacc::execACC_ABORTREQ() void Dbacc::accAbortReqLab(Signal* signal, bool sendConf) { operationRecPtr.i = signal->theData[0]; ptrCheckGuard(operationRecPtr, coprecsize, operationrec); tresult = 0; /* ZFALSE */ if ((operationRecPtr.p->transactionstate == ACTIVE) || (operationRecPtr.p->transactionstate == WAIT_COMMIT_ABORT)) { jam(); fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); operationRecPtr.p->transactionstate = ABORT; abortOperation(signal); } else { ndbrequire(operationRecPtr.p->transactionstate == IDLE); jam(); }//if operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->operation = ZUNDEFINED_OP; if (! sendConf) return; signal->theData[0] = operationRecPtr.p->userptr; sendSignal(operationRecPtr.p->userblockref, GSN_ACC_ABORTCONF, signal, 1, JBB); return; }//Dbacc::accAbortReqLab() /* * Lock or unlock tuple. */ void Dbacc::execACC_LOCKREQ(Signal* signal) { jamEntry(); AccLockReq* sig = (AccLockReq*)signal->getDataPtrSend(); AccLockReq reqCopy = *sig; AccLockReq* const req = &reqCopy; Uint32 lockOp = (req->requestInfo & 0xFF); if (lockOp == AccLockReq::LockShared || lockOp == AccLockReq::LockExclusive) { jam(); // find table tabptr.i = req->tableId; ptrCheckGuard(tabptr, ctablesize, tabrec); // find fragment (TUX will know it) if (req->fragPtrI == RNIL) { for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) { jam(); if (tabptr.p->fragptrholder[i] != RNIL) { rootfragrecptr.i = tabptr.p->fragptrholder[i]; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); if (rootfragrecptr.p->fragmentid[0] == req->fragId) { jam(); req->fragPtrI = rootfragrecptr.p->fragmentptr[0]; break; } if (rootfragrecptr.p->fragmentid[1] == req->fragId) { jam(); req->fragPtrI = rootfragrecptr.p->fragmentptr[1]; break; } } } } fragrecptr.i = req->fragPtrI; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); ndbrequire(req->fragId == fragrecptr.p->myfid); // caller must be explicit here ndbrequire(req->accOpPtr == RNIL); // seize operation to hold the lock if (cfreeopRec != RNIL) { jam(); seizeOpRec(signal); // init as in ACCSEIZEREQ operationRecPtr.p->userptr = req->userPtr; operationRecPtr.p->userblockref = req->userRef; operationRecPtr.p->operation = ZUNDEFINED_OP; operationRecPtr.p->transactionstate = IDLE; // do read with lock via ACCKEYREQ Uint32 lockMode = (lockOp == AccLockReq::LockShared) ? 0 : 1; Uint32 opCode = ZSCAN_OP; signal->theData[0] = operationRecPtr.i; signal->theData[1] = fragrecptr.i; signal->theData[2] = opCode | (lockMode << 4) | (1u << 31); signal->theData[3] = req->hashValue; signal->theData[4] = 1; // fake primKeyLen signal->theData[5] = req->transId1; signal->theData[6] = req->transId2; signal->theData[7] = req->tupAddr; EXECUTE_DIRECT(DBACC, GSN_ACCKEYREQ, signal, 8); // translate the result if (signal->theData[0] < RNIL) { jam(); req->returnCode = AccLockReq::Success; req->accOpPtr = operationRecPtr.i; } else if (signal->theData[0] == RNIL) { jam(); req->returnCode = AccLockReq::IsBlocked; req->accOpPtr = operationRecPtr.i; } else { ndbrequire(signal->theData[0] == (UintR)-1); releaseOpRec(signal); req->returnCode = AccLockReq::Refused; req->accOpPtr = RNIL; } } else { jam(); req->returnCode = AccLockReq::NoFreeOp; } *sig = *req; return; } if (lockOp == AccLockReq::Unlock) { jam(); // do unlock via ACC_COMMITREQ (immediate) signal->theData[0] = req->accOpPtr; EXECUTE_DIRECT(DBACC, GSN_ACC_COMMITREQ, signal, 1); releaseOpRec(signal); req->returnCode = AccLockReq::Success; *sig = *req; return; } if (lockOp == AccLockReq::Abort) { jam(); // do abort via ACC_ABORTREQ (immediate) signal->theData[0] = req->accOpPtr; accAbortReqLab(signal, false); releaseOpRec(signal); req->returnCode = AccLockReq::Success; *sig = *req; return; } if (lockOp == AccLockReq::AbortWithConf) { jam(); // do abort via ACC_ABORTREQ (with conf signal) signal->theData[0] = req->accOpPtr; accAbortReqLab(signal, true); releaseOpRec(signal); req->returnCode = AccLockReq::Success; *sig = *req; return; } ndbrequire(false); } /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF EXECUTE OPERATION MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* MODULE: INSERT */ /* THE FOLLOWING SUBROUTINES ARE ONLY USED BY INSERT_ELEMENT. THIS */ /* ROUTINE IS THE SOLE INTERFACE TO INSERT ELEMENTS INTO THE INDEX. */ /* CURRENT USERS ARE INSERT REQUESTS, EXPAND CONTAINER AND SHRINK */ /* CONTAINER. */ /* */ /* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */ /* INSERT_ELEMENT */ /* INSERT_CONTAINER */ /* ADDNEWCONTAINER */ /* GETFREELIST */ /* INCREASELISTCONT */ /* SEIZE_LEFTLIST */ /* SEIZE_RIGHTLIST */ /* */ /* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */ /* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */ /* TAKE_REC_OUT_OF_FREE_OVERPAGE AND RELEASE_OVERFLOW_REC ARE */ /* EXCEPTIONS TO THIS RULE. */ /* */ /* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */ /* THOSE DEFINED AS INPUT AND OUTPUT IN INSERT_ELEMENT */ /* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */ /* AND POINTER VARIABLES. */ /* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */ /* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */ /* EXECUTION. */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* INSERT_ELEMENT */ /* INPUT: */ /* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */ /* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */ /* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */ /* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */ /* CIDR_KEYS(ARRAY OF TUPLE KEYS) */ /* CLOCALKEY(ARRAY OF LOCAL KEYS). */ /* FRAGRECPTR */ /* IDR_OPERATION_REC_PTR */ /* TIDR_KEY_LEN */ /* */ /* OUTPUT: */ /* TIDR_PAGEINDEX (PAGE INDEX OF INSERTED ELEMENT) */ /* IDR_PAGEPTR (PAGE POINTER OF INSERTED ELEMENT) */ /* TIDR_FORWARD (CONTAINER DIRECTION OF INSERTED ELEMENT) */ /* NONE */ /* --------------------------------------------------------------------------------- */ void Dbacc::insertElement(Signal* signal) { DirRangePtr inrOverflowrangeptr; DirectoryarrayPtr inrOverflowDirptr; OverflowRecordPtr inrOverflowRecPtr; Page8Ptr inrNewPageptr; Uint32 tinrNextSamePage; Uint32 tinrTmp; do { insertContainer(signal); if (tidrResult != ZFALSE) { jam(); return; /* INSERTION IS DONE, OR */ /* AN ERROR IS DETECTED */ }//if if (((tidrContainerhead >> 7) & 0x3) != 0) { tinrNextSamePage = (tidrContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */ /* THE NEXT CONTAINER IS IN THE SAME PAGE */ tidrPageindex = tidrContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */ if (((tidrContainerhead >> 7) & 3) == ZLEFT) { jam(); tidrForward = ZTRUE; } else if (((tidrContainerhead >> 7) & 3) == ZRIGHT) { jam(); tidrForward = cminusOne; } else { ndbrequire(false); return; }//if if (tinrNextSamePage == ZFALSE) { jam(); /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */ tinrTmp = idrPageptr.p->word32[tidrContainerptr + 1]; inrOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(inrOverflowrangeptr, cdirrangesize, dirRange); arrGuard((tinrTmp >> 8), 256); inrOverflowDirptr.i = inrOverflowrangeptr.p->dirArray[tinrTmp >> 8]; ptrCheckGuard(inrOverflowDirptr, cdirarraysize, directoryarray); idrPageptr.i = inrOverflowDirptr.p->pagep[tinrTmp & 0xff]; ptrCheckGuard(idrPageptr, cpagesize, page8); }//if ndbrequire(tidrPageindex < ZEMPTYLIST); } else { break; }//if } while (1); gflPageptr.p = idrPageptr.p; getfreelist(signal); if (tgflPageindex == ZEMPTYLIST) { jam(); /* NO FREE BUFFER IS FOUND */ if (fragrecptr.p->firstOverflowRec == RNIL) { jam(); allocOverflowPage(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); }//if inrOverflowRecPtr.i = fragrecptr.p->firstOverflowRec; ptrCheckGuard(inrOverflowRecPtr, coverflowrecsize, overflowRecord); inrNewPageptr.i = inrOverflowRecPtr.p->overpage; ptrCheckGuard(inrNewPageptr, cpagesize, page8); gflPageptr.p = inrNewPageptr.p; getfreelist(signal); ndbrequire(tgflPageindex != ZEMPTYLIST); tancNext = 0; } else { jam(); inrNewPageptr = idrPageptr; tancNext = 1; }//if tslUpdateHeader = ZTRUE; tslPageindex = tgflPageindex; slPageptr.p = inrNewPageptr.p; if (tgflBufType == ZLEFT) { seizeLeftlist(signal); tidrForward = ZTRUE; } else { seizeRightlist(signal); tidrForward = cminusOne; }//if tancPageindex = tgflPageindex; tancPageid = inrNewPageptr.p->word32[ZPOS_PAGE_ID]; tancBufType = tgflBufType; tancContainerptr = tidrContainerptr; ancPageptr.p = idrPageptr.p; addnewcontainer(signal); idrPageptr = inrNewPageptr; tidrPageindex = tgflPageindex; insertContainer(signal); ndbrequire(tidrResult == ZTRUE); }//Dbacc::insertElement() /* --------------------------------------------------------------------------------- */ /* INSERT_CONTAINER */ /* INPUT: */ /* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */ /* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */ /* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */ /* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */ /* CKEYS(ARRAY OF TUPLE KEYS) */ /* CLOCALKEY(ARRAY 0F LOCAL KEYS). */ /* TIDR_KEY_LEN */ /* FRAGRECPTR */ /* IDR_OPERATION_REC_PTR */ /* OUTPUT: */ /* TIDR_RESULT (ZTRUE FOR SUCCESS AND ZFALSE OTHERWISE) */ /* TIDR_CONTAINERHEAD (HEADER OF CONTAINER) */ /* TIDR_CONTAINERPTR (POINTER TO CONTAINER HEADER) */ /* */ /* DESCRIPTION: */ /* THE FREE AREA OF THE CONTAINER WILL BE CALCULATED. IF IT IS */ /* LARGER THAN OR EQUAL THE ELEMENT LENGTH. THE ELEMENT WILL BE */ /* INSERT IN THE CONTAINER AND CONTAINER HEAD WILL BE UPDATED. */ /* THIS ROUTINE ALWAYS DEALS WITH ONLY ONE CONTAINER AND DO NEVER */ /* START ANYTHING OUTSIDE OF THIS CONTAINER. */ /* */ /* SHORT FORM: IDR */ /* --------------------------------------------------------------------------------- */ void Dbacc::insertContainer(Signal* signal) { Uint32 tidrContainerlen; Uint32 tidrConfreelen; Uint32 tidrNextSide; Uint32 tidrNextConLen; Uint32 tidrIndex; Uint32 tidrInputIndex; Uint32 tidrContLen; Uint32 guard26; tidrResult = ZFALSE; tidrContainerptr = (tidrPageindex << ZSHIFT_PLUS) - (tidrPageindex << ZSHIFT_MINUS); tidrContainerptr = tidrContainerptr + ZHEAD_SIZE; /* --------------------------------------------------------------------------------- */ /* CALCULATE THE POINTER TO THE ELEMENT TO BE INSERTED AND THE POINTER TO THE */ /* CONTAINER HEADER OF THE OTHER SIDE OF THE BUFFER. */ /* --------------------------------------------------------------------------------- */ if (tidrForward == ZTRUE) { jam(); tidrNextSide = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE); arrGuard(tidrNextSide + 1, 2048); tidrContainerhead = idrPageptr.p->word32[tidrContainerptr]; tidrContainerlen = tidrContainerhead >> 26; tidrIndex = tidrContainerptr + tidrContainerlen; } else { jam(); tidrNextSide = tidrContainerptr; tidrContainerptr = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE); arrGuard(tidrContainerptr + 1, 2048); tidrContainerhead = idrPageptr.p->word32[tidrContainerptr]; tidrContainerlen = tidrContainerhead >> 26; tidrIndex = (tidrContainerptr - tidrContainerlen) + (ZCON_HEAD_SIZE - 1); }//if if (tidrContainerlen > (ZBUF_SIZE - 3)) { return; }//if tidrConfreelen = ZBUF_SIZE - tidrContainerlen; /* --------------------------------------------------------------------------------- */ /* WE CALCULATE THE TOTAL LENGTH THE CONTAINER CAN EXPAND TO */ /* THIS INCLUDES THE OTHER SIDE OF THE BUFFER IF POSSIBLE TO EXPAND THERE. */ /* --------------------------------------------------------------------------------- */ if (((tidrContainerhead >> 10) & 1) == 0) { jam(); /* --------------------------------------------------------------------------------- */ /* WE HAVE NOT EXPANDED TO THE ENTIRE BUFFER YET. WE CAN THUS READ THE OTHER */ /* SIDE'S CONTAINER HEADER TO READ HIS LENGTH. */ /* --------------------------------------------------------------------------------- */ tidrNextConLen = idrPageptr.p->word32[tidrNextSide] >> 26; tidrConfreelen = tidrConfreelen - tidrNextConLen; if (tidrConfreelen > ZBUF_SIZE) { ndbrequire(false); /* --------------------------------------------------------------------------------- */ /* THE BUFFERS ARE PLACED ON TOP OF EACH OTHER. THIS SHOULD NEVER OCCUR. */ /* --------------------------------------------------------------------------------- */ return; }//if } else { jam(); tidrNextConLen = 1; /* INDICATE OTHER SIDE IS NOT PART OF FREE LIST */ }//if if (tidrConfreelen < fragrecptr.p->elementLength) { jam(); /* --------------------------------------------------------------------------------- */ /* THE CONTAINER COULD NOT BE EXPANDED TO FIT THE NEW ELEMENT. WE HAVE TO */ /* RETURN AND FIND A NEW CONTAINER TO INSERT IT INTO. */ /* --------------------------------------------------------------------------------- */ return; }//if tidrContainerlen = tidrContainerlen + fragrecptr.p->elementLength; if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = idrPageptr.p; cundoElemIndex = tidrContainerptr; cundoinfolength = 1; undoWritingProcess(signal); }//if if (tidrNextConLen == 0) { /* EACH SIDE OF THE BUFFER WHICH BELONG TO A FREE */ /* LIST, HAS ZERO AS LENGTH. */ if (tidrContainerlen > ZUP_LIMIT) { dbgWord32(idrPageptr, tidrContainerptr, idrPageptr.p->word32[tidrContainerptr] | (1 << 10)); idrPageptr.p->word32[tidrContainerptr] = idrPageptr.p->word32[tidrContainerptr] | (1 << 10); tslUpdateHeader = ZFALSE; tslPageindex = tidrPageindex; slPageptr.p = idrPageptr.p; if (tidrForward == ZTRUE) { jam(); seizeRightlist(signal); /* REMOVE THE RIGHT SIDE OF THE BUFFER FROM THE LIST */ } else { jam(); /* OF THE FREE CONTAINERS */ seizeLeftlist(signal); /* REMOVE THE LEFT SIDE OF THE BUFFER FROM THE LIST */ }//if }//if }//if /* OF THE FREE CONTAINERS */ /* --------------------------------------------------------------------------------- */ /* WE HAVE NOW FOUND A FREE SPOT IN THE CURRENT CONTAINER. WE INSERT THE */ /* ELEMENT HERE. THE ELEMENT CONTAINS A HEADER, A LOCAL KEY AND A TUPLE KEY. */ /* BEFORE INSERTING THE ELEMENT WE WILL UPDATE THE OPERATION RECORD WITH THE */ /* DATA CONCERNING WHERE WE INSERTED THE ELEMENT. THIS MAKES IT EASY TO FIND */ /* THIS INFORMATION WHEN WE RETURN TO UPDATE THE LOCAL KEY OR RETURN TO COMMIT */ /* OR ABORT THE INSERT. IF NO OPERATION RECORD EXIST IT MEANS THAT WE ARE */ /* PERFORMING THIS AS A PART OF THE EXPAND OR SHRINK PROCESS. */ /* --------------------------------------------------------------------------------- */ if (idrOperationRecPtr.i != RNIL) { jam(); idrOperationRecPtr.p->elementIsforward = tidrForward; idrOperationRecPtr.p->elementPage = idrPageptr.i; idrOperationRecPtr.p->elementContainer = tidrContainerptr; idrOperationRecPtr.p->elementPointer = tidrIndex; }//if /* --------------------------------------------------------------------------------- */ /* WE CHOOSE TO UNDO LOG INSERTS BY WRITING THE BEFORE VALUE TO THE UNDO LOG. */ /* WE COULD ALSO HAVE DONE THIS BY WRITING THIS BEFORE VALUE WHEN DELETING */ /* ELEMENTS. WE CHOOSE TO PUT IT HERE SINCE WE THEREBY ENSURE THAT WE ALWAYS */ /* UNDO LOG ALL WRITES TO PAGE MEMORY. IT SHOULD BE EASIER TO MAINTAIN SUCH A */ /* STRUCTURE. IT IS RATHER DIFFICULT TO MAINTAIN A LOGICAL STRUCTURE WHERE */ /* DELETES ARE INSERTS AND INSERTS ARE PURELY DELETES. */ /* --------------------------------------------------------------------------------- */ if (fragrecptr.p->createLcp == ZTRUE) { if (tidrForward == ZTRUE) { cundoElemIndex = tidrIndex; } else { cundoElemIndex = (tidrIndex + 1) - fragrecptr.p->elementLength; }//if cundoinfolength = fragrecptr.p->elementLength; undoWritingProcess(signal); }//if dbgWord32(idrPageptr, tidrIndex, tidrElemhead); idrPageptr.p->word32[tidrIndex] = tidrElemhead; /* INSERTS THE HEAD OF THE ELEMENT */ tidrIndex += tidrForward; guard26 = fragrecptr.p->localkeylen - 1; arrGuard(guard26, 2); for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) { dbgWord32(idrPageptr, tidrIndex, clocalkey[tidrInputIndex]); arrGuard(tidrIndex, 2048); idrPageptr.p->word32[tidrIndex] = clocalkey[tidrInputIndex]; /* INSERTS LOCALKEY */ tidrIndex += tidrForward; }//for guard26 = tidrKeyLen - 1; arrGuard(guard26, 8); for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) { dbgWord32(idrPageptr, tidrIndex, ckeys[tidrInputIndex]); arrGuard(tidrIndex, 2048); idrPageptr.p->word32[tidrIndex] = ckeys[tidrInputIndex]; /* INSERTS TUPLE KEY */ tidrIndex += tidrForward; }//for tidrContLen = idrPageptr.p->word32[tidrContainerptr] << 6; tidrContLen = tidrContLen >> 6; dbgWord32(idrPageptr, tidrContainerptr, (tidrContainerlen << 26) | tidrContLen); idrPageptr.p->word32[tidrContainerptr] = (tidrContainerlen << 26) | tidrContLen; tidrResult = ZTRUE; }//Dbacc::insertContainer() /* --------------------------------------------------------------------------------- */ /* ADDNEWCONTAINER */ /* INPUT: */ /* TANC_CONTAINERPTR */ /* ANC_PAGEPTR */ /* TANC_NEXT */ /* TANC_PAGEINDEX */ /* TANC_BUF_TYPE */ /* TANC_PAGEID */ /* OUTPUT: */ /* NONE */ /* */ /* --------------------------------------------------------------------------------- */ void Dbacc::addnewcontainer(Signal* signal) { Uint32 tancTmp1; if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = tancContainerptr; datapageptr.p = ancPageptr.p; cundoinfolength = 2; undoWritingProcess(signal); /* WHEN UNDO PROCESS HAS STARTED, */ }//if /* THE OLD DATA IS STORED ON AN UNDO PAGE */ /* --------------------------------------------------------------------------------- */ /* KEEP LENGTH INFORMATION IN BIT 26-31. */ /* SET BIT 9 INDICATING IF NEXT BUFFER IN THE SAME PAGE USING TANC_NEXT. */ /* SET TYPE OF NEXT CONTAINER IN BIT 7-8. */ /* SET PAGE INDEX OF NEXT CONTAINER IN BIT 0-6. */ /* KEEP INDICATOR OF OWNING OTHER SIDE OF BUFFER IN BIT 10. */ /* --------------------------------------------------------------------------------- */ tancTmp1 = ancPageptr.p->word32[tancContainerptr] >> 10; tancTmp1 = tancTmp1 << 1; tancTmp1 = tancTmp1 | tancNext; tancTmp1 = tancTmp1 << 2; tancTmp1 = tancTmp1 | tancBufType; /* TYPE OF THE NEXT CONTAINER */ tancTmp1 = tancTmp1 << 7; tancTmp1 = tancTmp1 | tancPageindex; dbgWord32(ancPageptr, tancContainerptr, tancTmp1); ancPageptr.p->word32[tancContainerptr] = tancTmp1; /* HEAD OF THE CONTAINER IS UPDATED */ dbgWord32(ancPageptr, tancContainerptr + 1, tancPageid); ancPageptr.p->word32[tancContainerptr + 1] = tancPageid; }//Dbacc::addnewcontainer() /* --------------------------------------------------------------------------------- */ /* GETFREELIST */ /* INPUT: */ /* GFL_PAGEPTR (POINTER TO A PAGE RECORD). */ /* OUTPUT: */ /* TGFL_PAGEINDEX(POINTER TO A FREE BUFFER IN THE FREEPAGE), AND */ /* TGFL_BUF_TYPE( TYPE OF THE FREE BUFFER). */ /* DESCRIPTION: SEARCHS IN THE FREE LIST OF THE FREE BUFFER IN THE PAGE HEAD */ /* (WORD32(1)),AND RETURN ADDRESS OF A FREE BUFFER OR NIL. */ /* THE FREE BUFFER CAN BE A RIGHT CONTAINER OR A LEFT ONE */ /* THE KIND OF THE CONTAINER IS NOTED BY TGFL_BUF_TYPE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::getfreelist(Signal* signal) { Uint32 tgflTmp; tgflTmp = gflPageptr.p->word32[ZPOS_EMPTY_LIST]; tgflPageindex = (tgflTmp >> 7) & 0x7f; /* LEFT FREE LIST */ tgflBufType = ZLEFT; if (tgflPageindex == ZEMPTYLIST) { jam(); tgflPageindex = tgflTmp & 0x7f; /* RIGHT FREE LIST */ tgflBufType = ZRIGHT; }//if ndbrequire(tgflPageindex <= ZEMPTYLIST); }//Dbacc::getfreelist() /* --------------------------------------------------------------------------------- */ /* INCREASELISTCONT */ /* INPUT: */ /* ILC_PAGEPTR PAGE POINTER TO INCREASE NUMBER OF CONTAINERS IN */ /* A CONTAINER OF AN OVERFLOW PAGE (FREEPAGEPTR) IS ALLOCATED, NR OF */ /* ALLOCATED CONTAINER HAVE TO BE INCRESE BY ONE . */ /* IF THE NUMBER OF ALLOCATED CONTAINERS IS ABOVE THE FREE LIMIT WE WILL */ /* REMOVE THE PAGE FROM THE FREE LIST. */ /* --------------------------------------------------------------------------------- */ void Dbacc::increaselistcont(Signal* signal) { OverflowRecordPtr ilcOverflowRecPtr; dbgWord32(ilcPageptr, ZPOS_ALLOC_CONTAINERS, ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1); ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1; if (ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) { if (ilcPageptr.p->word32[ZPOS_OVERFLOWREC] != RNIL) { jam(); ilcOverflowRecPtr.i = ilcPageptr.p->word32[ZPOS_OVERFLOWREC]; dbgWord32(ilcPageptr, ZPOS_OVERFLOWREC, RNIL); ilcPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL; ptrCheckGuard(ilcOverflowRecPtr, coverflowrecsize, overflowRecord); tfoOverflowRecPtr = ilcOverflowRecPtr; takeRecOutOfFreeOverpage(signal); rorOverflowRecPtr = ilcOverflowRecPtr; releaseOverflowRec(signal); }//if }//if }//Dbacc::increaselistcont() /* --------------------------------------------------------------------------------- */ /* SEIZE_LEFTLIST */ /* INPUT: */ /* TSL_PAGEINDEX PAGE INDEX OF CONTAINER TO SEIZE */ /* SL_PAGEPTR PAGE POINTER OF CONTAINER TO SEIZE */ /* TSL_UPDATE_HEADER SHOULD WE UPDATE THE CONTAINER HEADER */ /* */ /* OUTPUT: */ /* NONE */ /* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */ /* LIST OF LEFT FREE CONTAINER, IN THE HEADER OF THE PAGE */ /* (FREEPAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */ /* WILL BE UPDATED. */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeLeftlist(Signal* signal) { Uint32 tsllTmp1; Uint32 tsllNewHead; Uint32 tsllHeadIndex; Uint32 tsllTmp; tsllHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ZHEAD_SIZE; arrGuard(tsllHeadIndex + 1, 2048); tslNextfree = slPageptr.p->word32[tsllHeadIndex]; tslPrevfree = slPageptr.p->word32[tsllHeadIndex + 1]; if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = slPageptr.p; cundoElemIndex = tsllHeadIndex; cundoinfolength = 2; undoWritingProcess(signal); }//if if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = ZPOS_EMPTY_LIST; cundoinfolength = 2; undoWritingProcess(signal); }//if if (tslPrevfree == ZEMPTYLIST) { jam(); /* UPDATE FREE LIST OF LEFT CONTAINER IN PAGE HEAD */ tsllTmp1 = slPageptr.p->word32[ZPOS_EMPTY_LIST]; tsllTmp = tsllTmp1 & 0x7f; tsllTmp1 = (tsllTmp1 >> 14) << 14; tsllTmp1 = (tsllTmp1 | (tslNextfree << 7)) | tsllTmp; dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp1); slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp1; } else { ndbrequire(tslPrevfree < ZEMPTYLIST); jam(); tsllTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ZHEAD_SIZE; if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = tsllTmp; cundoinfolength = 1; undoWritingProcess(signal); }//if dbgWord32(slPageptr, tsllTmp, tslNextfree); slPageptr.p->word32[tsllTmp] = tslNextfree; }//if if (tslNextfree < ZEMPTYLIST) { jam(); tsllTmp = (((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE) + 1; if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = tsllTmp; cundoinfolength = 1; undoWritingProcess(signal); }//if dbgWord32(slPageptr, tsllTmp, tslPrevfree); slPageptr.p->word32[tsllTmp] = tslPrevfree; } else { ndbrequire(tslNextfree == ZEMPTYLIST); jam(); }//if /* --------------------------------------------------------------------------------- */ /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */ /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */ /* LISTS IN THE PAGE. */ /* */ /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */ /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */ /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */ /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */ /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */ /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */ /* WE ALSO SET BIT 25 TO INDICATE THAT IT IS A CONTAINER HEADER. */ /* --------------------------------------------------------------------------------- */ if (tslUpdateHeader == ZTRUE) { jam(); tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f; tsllNewHead = ZCON_HEAD_SIZE; tsllNewHead = ((tsllNewHead << 8) + ZEMPTYLIST) + (1 << 7); tsllNewHead = (tsllNewHead << 7) + tslNextfree; tsllNewHead = tsllNewHead << 11; dbgWord32(slPageptr, tsllHeadIndex, tsllNewHead); slPageptr.p->word32[tsllHeadIndex] = tsllNewHead; tsllTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff; tsllTmp = tsllTmp | (tslPageindex << 23); dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp); slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp; if (tslNextfree < ZEMPTYLIST) { jam(); tsllTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE; if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = tsllTmp; cundoinfolength = 1; undoWritingProcess(signal); }//if tsllTmp1 = slPageptr.p->word32[tsllTmp] & 0xfe03ffff; tsllTmp1 = tsllTmp1 | (tslPageindex << 18); dbgWord32(slPageptr, tsllTmp, tsllTmp1); slPageptr.p->word32[tsllTmp] = tsllTmp1; } else { ndbrequire(tslNextfree == ZEMPTYLIST); jam(); }//if }//if ilcPageptr.p = slPageptr.p; increaselistcont(signal); }//Dbacc::seizeLeftlist() /* --------------------------------------------------------------------------------- */ /* SEIZE_RIGHTLIST */ /* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */ /* LIST OF RIGHT FREE CONTAINER, IN THE HEADER OF THE PAGE */ /* (SL_PAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */ /* WILL BE UPDATED. */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeRightlist(Signal* signal) { Uint32 tsrlTmp1; Uint32 tsrlNewHead; Uint32 tsrlHeadIndex; Uint32 tsrlTmp; tsrlHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); arrGuard(tsrlHeadIndex + 1, 2048); tslNextfree = slPageptr.p->word32[tsrlHeadIndex]; tslPrevfree = slPageptr.p->word32[tsrlHeadIndex + 1]; if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = slPageptr.p; cundoElemIndex = tsrlHeadIndex; cundoinfolength = 2; undoWritingProcess(signal); }//if if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = ZPOS_EMPTY_LIST; cundoinfolength = 2; undoWritingProcess(signal); }//if if (tslPrevfree == ZEMPTYLIST) { jam(); tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST]; dbgWord32(slPageptr, ZPOS_EMPTY_LIST, ((tsrlTmp >> 7) << 7) | tslNextfree); slPageptr.p->word32[ZPOS_EMPTY_LIST] = ((tsrlTmp >> 7) << 7) | tslNextfree; } else { ndbrequire(tslPrevfree < ZEMPTYLIST); jam(); tsrlTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = tsrlTmp; cundoinfolength = 1; undoWritingProcess(signal); }//if dbgWord32(slPageptr, tsrlTmp, tslNextfree); slPageptr.p->word32[tsrlTmp] = tslNextfree; }//if if (tslNextfree < ZEMPTYLIST) { jam(); tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1)); if (fragrecptr.p->createLcp == ZTRUE) { cundoElemIndex = tsrlTmp; cundoinfolength = 1; undoWritingProcess(signal); }//if dbgWord32(slPageptr, tsrlTmp, tslPrevfree); slPageptr.p->word32[tsrlTmp] = tslPrevfree; } else { ndbrequire(tslNextfree == ZEMPTYLIST); jam(); }//if /* --------------------------------------------------------------------------------- */ /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */ /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */ /* LISTS IN THE PAGE. */ /* */ /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */ /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */ /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */ /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */ /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */ /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */ /* --------------------------------------------------------------------------------- */ if (tslUpdateHeader == ZTRUE) { jam(); tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f; tsrlNewHead = ZCON_HEAD_SIZE; tsrlNewHead = ((tsrlNewHead << 8) + ZEMPTYLIST) + (1 << 7); tsrlNewHead = (tsrlNewHead << 7) + tslNextfree; tsrlNewHead = tsrlNewHead << 11; dbgWord32(slPageptr, tsrlHeadIndex, tsrlNewHead); slPageptr.p->word32[tsrlHeadIndex] = tsrlNewHead; tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff; dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsrlTmp | (tslPageindex << 16)); slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsrlTmp | (tslPageindex << 16); if (tslNextfree < ZEMPTYLIST) { jam(); tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = tsrlTmp; cundoinfolength = 1; undoWritingProcess(signal); }//if tsrlTmp1 = slPageptr.p->word32[tsrlTmp] & 0xfe03ffff; dbgWord32(slPageptr, tsrlTmp, tsrlTmp1 | (tslPageindex << 18)); slPageptr.p->word32[tsrlTmp] = tsrlTmp1 | (tslPageindex << 18); } else { ndbrequire(tslNextfree == ZEMPTYLIST); jam(); }//if }//if ilcPageptr.p = slPageptr.p; increaselistcont(signal); }//Dbacc::seizeRightlist() //--------------------------------------------------------------------------------- // ALLOC_SPECIFIC_LONG_OVERFLOW_PAGE // // DESCRIPTION: ALLOCATES A LONG OVER FLOW PAGE AND PUTS IT IN A SPECIFIED // DIRINDEX. THIS IS TO SUPPORT AN UNDO_DELETE AFTER AN // UNDO_INSERT ON THE SAME LONG KEY IN A LCP. // UNDO_INSERT ONLY HAVE A REFERENCE TO THE KEY AND TO MAKE // IT POSSIBLE TO DELETE THE KEY, THE REFERENCE MUST BE // ACCURATE, WHICH MEANS THE KEY MUST BE SAVED ON THE SAME // PLACE IT WAS DELETED FROM. //--------------------------------------------------------------------------------- void Dbacc::allocSpecificLongOverflowPage(Signal* signal) { DirRangePtr aloDirRangePtr; DirectoryarrayPtr aloOverflowDirptr; if ((cfirstfreepage == RNIL) && (cfreepage >= cpagesize)) { jam(); zpagesize_error("Dbacc::allocSpecificLongOverflowPage"); tresult = ZPAGESIZE_ERROR; return; } if ((cfirstfreedir == RNIL) && (cdirarraysize <= cdirmemory)) { jam(); tresult = ZDIRSIZE_ERROR; return; } tmpP = taslpDirIndex; aloDirRangePtr.i = fragrecptr.p->overflowdir; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) { jam(); seizeDirectory(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); sendSystemerror(signal); return; } aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i; } else { jam(); sdDirptr.i = RNIL; ptrNull(sdDirptr); } aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2]; ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray); seizePage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); sendSystemerror(signal); return; }//if if (aloOverflowDirptr.p->pagep[tmpP] != RNIL) { jam(); sendSystemerror(signal); return; } aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i; iloPageptr.p = spPageptr.p; iloPageptr.i = spPageptr.i; tiloIndex = taslpDirIndex; initLongOverpage(signal); aslpPageptr.i = spPageptr.i; aslpPageptr.p = spPageptr.p; }//Dbacc::allocSpecificLongOverflowPage /* --------------------------------------------------------------------------------- */ /* ALLOC_LONG_OVERFLOW_PAGE */ /* DESCRIPTION: */ /* --------------------------------------------------------------------------------- */ void Dbacc::allocLongOverflowPage(Signal* signal) { DirRangePtr aloDirRangePtr; DirectoryarrayPtr aloOverflowDirptr; OverflowRecordPtr aloOverflowRecPtr; Uint32 taloIndex; if ((cfirstfreepage == RNIL) && (cfreepage >= cpagesize)) { jam(); zpagesize_error("Dbacc::allocLongOverflowPage"); tresult = ZPAGESIZE_ERROR; return; }//if if ((cfirstfreedir == RNIL) && (cdirarraysize <= cdirmemory)) { jam(); tresult = ZDIRSIZE_ERROR; return; }//if if (fragrecptr.p->firstFreeDirindexRec != RNIL) { jam(); aloOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec; ptrCheckGuard(aloOverflowRecPtr, coverflowrecsize, overflowRecord); troOverflowRecPtr.p = aloOverflowRecPtr.p; takeRecOutOfFreeOverdir(signal); taloIndex = aloOverflowRecPtr.p->dirindex; rorOverflowRecPtr = aloOverflowRecPtr; releaseOverflowRec(signal); } else { jam(); taloIndex = fragrecptr.p->lastOverIndex; fragrecptr.p->lastOverIndex++; }//if tmpP = taloIndex; aloDirRangePtr.i = fragrecptr.p->overflowdir; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) { jam(); seizeDirectory(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i; } else { jam(); sdDirptr.i = RNIL; ptrNull(sdDirptr); }//if aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2]; ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray); seizePage(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i; iloPageptr = spPageptr; tiloIndex = taloIndex; initLongOverpage(signal); alpPageptr = spPageptr; ipaPagePtr = spPageptr; tipaArrayPos = 3; insertPageArrayList(signal); }//Dbacc::allocLongOverflowPage() /* --------------------------------------------------------------------------------- */ /* GET_LONG_KEY_PAGE */ /* DESCRIPTION: SEARCH FOR A FREE OVERFLOW PAGE TO STORE A LONG KEY. */ /* LONG_KEY_PAGE_PTR IS RETURNED. */ /* --------------------------------------------------------------------------------- */ void Dbacc::getLongKeyPage(Signal* signal) { LongKeyPage *glkPage; jam(); Uint32 tglkLongIndex = 0; ndbrequire(operationRecPtr.p->tupkeylen <= ZWORDS_IN_PAGE - ZHEAD_SIZE); // Do not look in longKeyPageArray[tglkLongIndex] where the pages are to small. if(operationRecPtr.p->tupkeylen < 128) { jam(); tglkLongIndex = 0; } else { jam(); tglkLongIndex = (operationRecPtr.p->tupkeylen - 128) / 512; }//if // Go through the longKeyPageArray and search for a page. for (; tglkLongIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; tglkLongIndex++) { jam(); glkPageptr.i = fragrecptr.p->longKeyPageArray[tglkLongIndex]; if (glkPageptr.i != RNIL) { // A page is found. jam(); do { ptrCheckGuard(glkPageptr, cpagesize, page8); glkPage = (LongKeyPage *) &glkPageptr.p->word32[0]; // Check page if there is enough memory available. Accept only page // with free_area > tupkeylen, this leaves at least one word for eventually // an increase in the index area. if (glkPage->header.freeArea > operationRecPtr.p->tupkeylen){ // The page found is OK jam(); return; } else { // Not enough space in page, look in the next page if not RNIL, // otherwise continue with for-loop. jam(); glkPageptr.i = glkPage->header.nextPage; } }//do while (glkPageptr.i != RNIL); }//if }//for // No page with enough space was available, allocate a new page! jam(); allocLongOverflowPage(signal); glkPageptr = alpPageptr; }//Dbacc::getLongKeyPage() /* --------------------------------------------------------------------------------- */ /* INIT_LONG_OVERPAGE */ /* INPUT. ILO_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */ /* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */ /* ACCORDING TO LH3 AND PAGE STRUCTOR DISACRIPTION OF NDBACC BLOCK */ /* --------------------------------------------------------------------------------- */ void Dbacc::initLongOverpage(Signal* signal) { iloPageptr.p->word32[ZPOS_PAGE_ID] = tiloIndex; iloPageptr.p->word32[ZPOS_PAGE_TYPE] = ZLONG_PAGE_TYPE << ZPOS_PAGE_TYPE_BIT; iloPageptr.p->word32[ZPOS_NO_ELEM_IN_PAGE] = 0; iloPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL; iloPageptr.p->word32[ZPOS_FREE_AREA_IN_PAGE] = ZWORDS_IN_PAGE - ZHEAD_SIZE; iloPageptr.p->word32[ZPOS_LAST_INDEX] = 0; iloPageptr.p->word32[ZPOS_INSERT_INDEX] = ZHEAD_SIZE; iloPageptr.p->word32[ZPOS_ARRAY_POS] = ZDEFAULT_LIST; iloPageptr.p->word32[ZPOS_NEXT_FREE_INDEX] = 0; iloPageptr.p->word32[ZPOS_NEXT_PAGE] = RNIL; iloPageptr.p->word32[ZPOS_PREV_PAGE] = RNIL; iloPageptr.p->word32[12] = 0; iloPageptr.p->word32[13] = 0; iloPageptr.p->word32[14] = 0; iloPageptr.p->word32[15] = 0; // Initialize free indexes for (int i = 1; i < (ZWORDS_IN_PAGE - ZHEAD_SIZE); i++) iloPageptr.p->word32[ZWORDS_IN_PAGE - i] = i + 1; }//Dbacc::initLongOverpage() //--------------------------------------------------------------------------------- // STORE_LONG_KEYS_AT_POS // // INPUT: SLKAP_PAGEPTR // SLKAP_COPY_PAGEPTR // TSLKAP_KEY_LEN // TSLKAP_PAGE_INDEX // // DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE AT A // SPECIFIC POSITION. THIS FUNCTION IS USED BY UNDO_DELETE. //--------------------------------------------------------------------------------- void Dbacc::storeLongKeysAtPos(Signal* signal) { Uint32 tslkapHighestIndex; Uint32 tslkapLastSize; Uint32 tslkapInsertIndex; Uint32 tslkapIndexIncreaseSize; Uint32 tslkapTmp; LongKeyPage *slkapPage; jam(); slkapPage = (LongKeyPage *) &slkapPageptr.p->word32[0]; #ifdef VM_TRACE checkIndexInLongKeyPage(slkapPageptr.i, "storeLongKeysAtPos"); #endif // if (csystemRestart != ZTRUE) { if (cundoLogActive != ZTRUE) { //------------------------------------------------------------- // This function is only allowed to be called during // undolog execution. //------------------------------------------------------------- jam(); sendSystemerror(signal); return; } if (slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] >> 16 != 0 ) { //------------------------------------------------------------- // The index should be empty, we have a serious problem. //------------------------------------------------------------- jam(); sendSystemerror(signal); return; } //------------------------------------------------------------- // Calculate some variables to use later. //------------------------------------------------------------- tslkapHighestIndex = slkapPage->header.highestIndex; tslkapPageIndex > tslkapHighestIndex ? tslkapIndexIncreaseSize = tslkapPageIndex - tslkapHighestIndex : tslkapIndexIncreaseSize = 0; slkapPage->header.highestIndex += tslkapIndexIncreaseSize; if ((slkapPage->header.freeArea - tslkapIndexIncreaseSize) < tslkapKeyLen) { //------------------------------------------------------------- // Not enough area in the page, a serious problem. //------------------------------------------------------------- jam(); sendSystemerror(signal); return; } //------------------------------------------------------------- // Fix the free index list. We might put in a key in the // middle of the list, so we must fix the free list and the // free index pointers. //------------------------------------------------------------- slkapPage->header.nextFreeIndex = 0; for (Uint32 i = tslkapHighestIndex + tslkapIndexIncreaseSize; i > 0; i--) { if (i == tslkapPageIndex) { // The key index shall not be in the free list. continue; } if (slkapPage->word32[ZWORDS_IN_PAGE - i] >> 16 == 0 ) { // Go through all empty indexes. slkapPage->word32[ZWORDS_IN_PAGE - i] = slkapPage->header.nextFreeIndex; arrGuard(i, 2048); slkapPage->header.nextFreeIndex = i; } } //------------------------------------------------------------- // Decrement the free area in page according to the above // increase in index size. //------------------------------------------------------------- slkapPage->header.freeArea -= tslkapIndexIncreaseSize; tslkapLastSize = ZWORDS_IN_PAGE - slkapPage->header.highestIndex - slkapPage->header.insertPos; //------------------------------------------------------------- // Check if we have to reorganize the page. //------------------------------------------------------------- if (tslkapLastSize >= tslkapKeyLen) { jam(); } else { jam(); relpPageptr.p = slkapPageptr.p; reorgLongPage(signal); } //------------------------------------------------------------- // Insert the key and update page attributes. //------------------------------------------------------------- jam(); // Increase the number of element in the page. slkapPage->header.noOfElements++; jam(); // Put in the key reference into the index. The reference // consists of key length and insert position. arrGuard(ZWORDS_IN_PAGE - tslkapPageIndex, 2048); slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] = slkapPage->header.insertPos | (tslkapKeyLen << 16); jam(); // Increase the key insert position. tslkapInsertIndex = slkapPage->header.insertPos; slkapPage->header.insertPos += tslkapKeyLen; jam(); // Decrease the free area. slkapPage->header.freeArea -= tslkapKeyLen; jam(); // Update pageArrayPos. insertPageArrayList() called from execACC_OVER_REC // needs this value. if (slkapPage->header.freeArea < 128) { jam(); slkapPage->header.pageArrayPos = 4; } else { jam(); slkapPage->header.pageArrayPos = (slkapPage->header.freeArea - 128) / 512; }//if // Store the actual key at the insert position. Uint32 guard27 = tslkapKeyLen - 1; arrGuard(guard27 + tslkapInsertIndex, 2048); for (tslkapTmp = 0; tslkapTmp <= guard27; tslkapTmp++) { jam(); slkapPage->word32[tslkapTmp + tslkapInsertIndex] = slkapCopyPageptr.p->word32[tslkapTmp]; }//for }//Dbacc::storeLongKeysAtPos /* --------------------------------------------------------------------------------- */ /* STORE_LONG_KEYS */ /* INPUT: SLK_PAGEPTR */ /* SLK_COPY_PAGEPTR */ /* TSLK_KEY_LEN */ /* OUTPUT: TSLK_PAGE_INDEX */ /* */ /* DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::storeLongKeys(Signal* signal) { Uint32 tslkLastSize; Uint32 tslkInsertIndex; Uint32 tslkArrayPos; Uint32 tslkTmp; Uint32 guard27; LongKeyPage *slkPage; jam(); slkPage = (LongKeyPage *) &slkPageptr.p->word32[0]; #ifdef VM_TRACE checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys1"); #endif // Accept only page with free_area > tupkeylen, this leaves at least // one word for eventually an increase in the index area. ndbrequire(slkPage->header.freeArea > tslkKeyLen); dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex); dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos); tslkLastSize = ZWORDS_IN_PAGE - slkPage->header.highestIndex - slkPage->header.insertPos; if (tslkLastSize > operationRecPtr.p->tupkeylen) { // WE DO NOT NEED TO REORGANIZE THE PAGE TO INSERT THE NEW KEY. IT FITS INTO THE // SIZE REMAINING AT THE END. jam(); } else { // THE KEY FITS INTO THE PAGE BUT ONLY AFTER REORGANISING THE PAGE. jam(); relpPageptr.p = slkPageptr.p; reorgLongPage(signal); }//if if (slkPage->header.nextFreeIndex == 0) { jam(); /* --------------------------------------------------------------------------------- */ /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/ /* --------------------------------------------------------------------------------- */ tslkPageIndex = slkPage->header.highestIndex + 1; } else { jam(); tslkPageIndex = slkPage->header.nextFreeIndex; }//if if (fragrecptr.p->createLcp == ZTRUE) { jam(); /* --------------------------------------------------------------------------------- */ /* ON LONG PAGES WE USE A PHYSIOLOGICAL LOGGING SCHEME. THIS MEANS THAT WE ONLY NEED*/ /* TO SPECIFY WHICH INDEX TO DELETE IN ORDER TO UNDO THE CHANGES WE DO. THE */ /* POSSIBLE REORGANISATION DO NOT CHANGE THE LOGICAL LAYOUT OF THE PAGE. */ /* --------------------------------------------------------------------------------- */ datapageptr.p = slkPageptr.p; cundoElemIndex = tslkPageIndex; cundoinfolength = 0; undoWritingProcess(signal); }//if if (slkPage->header.nextFreeIndex == 0) { jam(); /* --------------------------------------------------------------------------------- */ /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/ /* --------------------------------------------------------------------------------- */ dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex + 1); slkPage->header.highestIndex++; ndbrequire(slkPage->header.insertPos < (ZWORDS_IN_PAGE - slkPage->header.highestIndex)); // Reset index. We have already checked that we can increase "highestIndex" value // without overwriting the data part. slkPage->word32[ZWORDS_IN_PAGE - slkPage->header.highestIndex] = 0; dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - 1); slkPage->header.freeArea--; } else { jam(); dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex]); arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048); arrGuard(slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex], 2048); slkPage->header.nextFreeIndex = slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex]; if(slkPage->header.nextFreeIndex > slkPage->header.highestIndex){ slkPage->header.nextFreeIndex = 0; dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->header.nextFreeIndex); } }//if dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, tslkKeyLen); dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, slkPage->header.insertPos); arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048); slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex] = slkPage->header.insertPos | (tslkKeyLen << 16); dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos); tslkInsertIndex = slkPage->header.insertPos; slkPage->header.insertPos += tslkKeyLen; dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - tslkKeyLen); slkPage->header.freeArea = slkPage->header.freeArea - tslkKeyLen; if (slkPage->header.freeArea < 128) { jam(); tslkArrayPos = 4; } else { jam(); tslkArrayPos = (slkPage->header.freeArea - 128) / 512; }//if if (tslkArrayPos != slkPage->header.pageArrayPos) { jam(); if (cundoLogActive != ZTRUE) { jam(); /* --------------------------------------------------------------------------------- */ /* WE ONLY HANDLE THE LISTS WHEN WE ARE NOT IN A SYSTEM RESTART. */ /* --------------------------------------------------------------------------------- */ rfpPageptr = slkPageptr; trfpArrayPos = slkPage->header.pageArrayPos; removeFromPageArrayList(signal); ipaPagePtr = slkPageptr; tipaArrayPos = tslkArrayPos; slkPage->header.pageArrayPos = tipaArrayPos; if (tslkArrayPos != 4) { jam(); /* --------------------------------------------------------------------------------- */ /* THE PAGE WILL STILL BE ON ONE OF THE FREE LISTS SINCE AT LEAST 128 * 4 */ /* BYTES OF FREE SPACE REMAINS ON THE PAGE. */ /* --------------------------------------------------------------------------------- */ insertPageArrayList(signal); }//if } else { // This should never happen. Should use storeLongKeysAtPos() instead when executing // undolog. ndbrequire(false); } }//if /* --------------------------------------------------------------------------------- */ /* INCREASE THE NUMBER OF ELEMENTS IN THE PAGE. */ /* --------------------------------------------------------------------------------- */ dbgWord32(slkPageptr, ZPOS_NO_ELEM_IN_PAGE, slkPage->header.noOfElements + 1); slkPage->header.noOfElements++; guard27 = tslkKeyLen - 1; arrGuard(guard27 + tslkInsertIndex, 2048); for (tslkTmp = 0; tslkTmp <= guard27; tslkTmp++) { dbgWord32(slkPageptr, tslkTmp + tslkInsertIndex, slkCopyPageptr.p->word32[tslkTmp]); slkPage->word32[tslkTmp + tslkInsertIndex] = slkCopyPageptr.p->word32[tslkTmp]; }//for // Used by abortoperation() in case of an abort. operationRecPtr.p->longPagePtr = slkPageptr.i; // This is for an eventual LCP start in the middle of this locked operation. operationRecPtr.p->longKeyPageIndex = tslkPageIndex; #ifdef VM_TRACE if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "storeLongKeys"); checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys2"); #endif }//Dbacc::storeLongKeys() /* --------------------------------------------------------------------------------- */ /* REORGANIZE THE PAGE BY COPYING IT TEMPORARILY TO A NEW AREA AND THEN SIMPLY */ /* PUTTING THE OBJECTS BACK ON THE PAGE IN THE SAME ORDER AS THEY ARE PLACED IN THE */ /* INDEX. */ /* --------------------------------------------------------------------------------- */ void Dbacc::reorgLongPage(Signal* signal) { Uint32 indexStartPos; Uint32 pagePos; Uint32 pagePos2; Uint32 indexNo; Uint32 insertPos; Uint32 indexValue; Uint32 keyLength; Uint32 keyPos; Uint32 keyEndPos; LongKeyPage *reOrgPage; ptrGuard(relpPageptr); reOrgPage = (LongKeyPage *) &relpPageptr.p->word32[0]; dbgWord32(relpPageptr, ZPOS_LAST_INDEX, reOrgPage->header.highestIndex); indexStartPos = ZWORDS_IN_PAGE - reOrgPage->header.highestIndex; // Copy key data part of page to a temporary page. for (pagePos = ZHEAD_SIZE; pagePos < indexStartPos; pagePos++) { jam(); arrGuard(pagePos, 2048); ckeys[pagePos] = reOrgPage->word32[pagePos]; }//for insertPos = ZHEAD_SIZE; // Walk through all the indexes. for (indexNo = 1; indexNo <= reOrgPage->header.highestIndex; indexNo++) { jam(); arrGuard(ZWORDS_IN_PAGE - indexNo, 2048); dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, reOrgPage->word32[ZWORDS_IN_PAGE - indexNo]); indexValue = reOrgPage->word32[ZWORDS_IN_PAGE - indexNo]; if ((indexValue >> 16) != 0) { // The index contains a reference to a key. jam(); keyPos = indexValue & 0xffff; keyLength = indexValue >> 16; dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, insertPos + (keyLength << 16)); arrGuard(ZWORDS_IN_PAGE - indexNo, 2048); // Refresh the index data with the new key start position in the data part. reOrgPage->word32[ZWORDS_IN_PAGE - indexNo] = insertPos + (keyLength << 16); keyEndPos = keyPos + keyLength; arrGuard(keyEndPos, 2048); // Copy the key from the temporary page // to the insert position at original page. for (pagePos2 = keyPos; pagePos2 < keyEndPos; pagePos2++, insertPos++) { jam(); dbgWord32(relpPageptr, insertPos, ckeys[pagePos2]); arrGuard(insertPos, 2048); arrGuard(pagePos2, 2048); reOrgPage->word32[insertPos] = ckeys[pagePos2]; }//for }//if }//for dbgWord32(relpPageptr, ZPOS_INSERT_INDEX, insertPos); reOrgPage->header.insertPos = insertPos; }//Dbacc::reorgLongPage() /* --------------------------------------------------------------------------------- */ /* DELETE_LONG_KEY */ /* INPUT: DLK_PAGEPTR PAGE POINTER OF DELETED KEY OBJECT */ /* TDLK_LOGICAL_PAGE_INDEX LOGICAL PAGE INDEX OF DELETED KEY OBJECT */ /* */ /* DESCRIPTION: DELETE AN ELEMENT OF A LONG_KEY_PAGE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::deleteLongKey(Signal* signal) { Uint32 tdlkLastIndex; Uint32 tdlkNextPosition; Uint32 tdlkFreeArea; Uint32 tdlkArrayPos; Uint32 tdlkOldArrayPos; LongKeyPage *dlkPage; jam(); dlkPage = (LongKeyPage *) &dlkPageptr.p->word32[0]; #ifdef VM_TRACE checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey1"); #endif dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] >> 16); dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] & 0xffff); arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048); const Uint32 tdlkIndexValue = dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex]; const Uint32 tdlkKeyLen = tdlkIndexValue >> 16; const Uint32 tdlkPhysPageIndex = tdlkIndexValue & 0xffff; if (fragrecptr.p->createLcp == ZTRUE) { jam(); /* --------------------------------------------------------------------------------- */ /* WE LOG THE DELETE LONG KEY BY LOGGING THE DELETED KEY AND ITS LOGICAL INDEX.*/ /* --------------------------------------------------------------------------------- */ datapageptr.p = dlkPageptr.p; cundoElemIndex = tdlkLogicalPageIndex; cundoinfolength = tdlkKeyLen; undoWritingProcess(signal); }//if /* --------------------------------------------------------------------------------- */ /* DECREASE THE NUMBER OF ELEMENTS IN THE PAGE. */ /* --------------------------------------------------------------------------------- */ dbgWord32(dlkPageptr, ZPOS_NO_ELEM_IN_PAGE, dlkPage->header.noOfElements - 1); dlkPage->header.noOfElements--; arrGuard(dlkPage->header.noOfElements, ZMAX_NO_OF_LONGKEYS_IN_PAGE); /* --------------------------------------------------------------------------------- */ /* INCREASE THE FREE AREA IN THE PAGE. */ /* --------------------------------------------------------------------------------- */ dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea + tdlkKeyLen); dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, dlkPage->header.highestIndex); dlkPage->header.freeArea += tdlkKeyLen; if (dlkPage->header.noOfElements == 0) { jam(); /* --------------------------------------------------------------------------------- */ /* THE PAGE IS NOW EMPTY, WE CAN RELEASE IT. */ /* --------------------------------------------------------------------------------- */ if (dlkPage->header.freeArea != (ZWORDS_IN_PAGE - ZHEAD_SIZE - dlkPage->header.highestIndex )) { jam(); /* --------------------------------------------------------------------------------- */ /* SOME AREA IN THE PAGE IS STILL LEFT BUT NO ELEMENTS, INCONSISTENT */ /* --------------------------------------------------------------------------------- */ sendSystemerror(signal); }//if /* --------------------------------------------------------------------------------- */ /* WE REMOVE THE PAGE FROM THE LIST OF FREE LONG PAGES. THERE IS NO RISK THAT IT */ /* DID NOT BELONG TO ANY SINCE IT IS NOT ALLOWED TO HAVE THAT LARGE KEYS. */ /* --------------------------------------------------------------------------------- */ if (cundoLogActive != ZTRUE) { jam(); /* --------------------------------------------------------------------------------- */ /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */ /* --------------------------------------------------------------------------------- */ // REMOVEFROMLIST is done by releaseLongPage(). EDTJAMO. // rfpPageptr = dlkPageptr; // trfpArrayPos = dlkPage->header.pageArrayPos; // removeFromPageArrayList(signal, "deleteLongKey"); rlopPageptr = dlkPageptr; releaseLongPage(signal); return; } else { // Must remove reference to the removed key, otherwise left in index. EDTJAMO. arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048); arrGuard(tdlkLogicalPageIndex, 2048); tdlkNextPosition = dlkPage->header.nextFreeIndex; dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex; dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition); dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition; } } else { /* --------------------------------------------------------------------------------- */ /* THE PAGE IS NOT EMPTY SO WE WILL REMOVE THE KEY OBJECT AND UPDATE THE */ /* HEADER INFORMATION AND PLACE THE PAGE IN THE PROPER PAGE LIST. */ /* --------------------------------------------------------------------------------- */ tdlkLastIndex = dlkPage->header.highestIndex; arrGuard(ZWORDS_IN_PAGE - tdlkLastIndex, 2048); if (tdlkLastIndex == tdlkLogicalPageIndex) { jam(); /* --------------------------------------------------------------------------------- */ /* WE DELETE THE LAST PAGE INDEX SO WE NEED TO UPDATE THE VALUE. WE MOVE */ /* BACKWARDS UNTIL WE EITHER FIND A USED INDEX OR THAT WE COME TO INDEX ZERO. */ /* --------------------------------------------------------------------------------- */ tdlkLastIndex--; while( (tdlkLastIndex > 1) && (dlkPage->word32[ZWORDS_IN_PAGE - tdlkLastIndex] >> 16) == 0 ) { jam(); tdlkLastIndex--; } //----------------------------------------------------- // Reorganize the rest of the index. Set up the free // list and the free index. //----------------------------------------------------- UintR dlkTmp = tdlkLastIndex; dlkPage->header.nextFreeIndex = 0; while( dlkTmp > 0) { if ( (dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] >> 16) == 0 ) { jam(); dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] = dlkPage->header.nextFreeIndex; arrGuard(dlkTmp, 2048); dlkPage->header.nextFreeIndex = dlkTmp; } dlkTmp--; } //----------------------------------------------------- // Update free area in page and last index. //----------------------------------------------------- dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, tdlkLastIndex); dlkPage->header.highestIndex = tdlkLastIndex; dlkPage->header.freeArea = tdlkLogicalPageIndex + dlkPage->header.freeArea - tdlkLastIndex; tdlkNextPosition = 0; } else { if (dlkPage->header.highestIndex > tdlkLogicalPageIndex) { jam(); tdlkNextPosition = dlkPage->header.nextFreeIndex; dbgWord32(dlkPageptr, ZPOS_NEXT_FREE_INDEX, tdlkLogicalPageIndex); arrGuard(tdlkLogicalPageIndex, 2048); dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex; } else { jam(); /* --------------------------------------------------------------------------------- */ /* LOGICAL PAGE INDEX LARGER THAN LARGEST INDEX, INCONSISTENT. */ /* --------------------------------------------------------------------------------- */ sendSystemerror(signal); return; // Just to keep compiler happy }//if }//if /* --------------------------------------------------------------------------------- */ /* WE INSERT ZERO INTO THE LENGTH PART TO INDICATE A FREE INDEX POSITION. */ /* WE INSERT A POINTER TO THE NEXT FREE INDEX TO AS TO PUT IT INTO A FREE */ /* LIST OF INDEX POSITIONS. WE ONLY DO SO IF IT WAS NOT THE LAST INDEX. */ /* --------------------------------------------------------------------------------- */ dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition); arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048); dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition; if (dlkPage->header.insertPos == (tdlkPhysPageIndex + tdlkKeyLen)) { jam(); /* --------------------------------------------------------------------------------- */ /* THIS ENTRY IS THE LAST ON THE PAGE SO WE WILL UPDATE THE INSERT INDEX */ /* --------------------------------------------------------------------------------- */ dbgWord32(dlkPageptr, ZPOS_INSERT_INDEX, tdlkPhysPageIndex); dlkPage->header.insertPos = tdlkPhysPageIndex; }//if }//if dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea); tdlkFreeArea = dlkPage->header.freeArea; ndbrequire(tdlkFreeArea <= (ZWORDS_IN_PAGE - ZHEAD_SIZE)); if (tdlkFreeArea < 128) { jam(); /* --------------------------------------------------------------------------------- */ /* FREE AREA IS STILL LESS THAN 128 WORDS SO IT SHOULD NOT BE PLACED IN ANY OF THE */ /* FREE LISTS. */ /* --------------------------------------------------------------------------------- */ dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos); ndbrequire(dlkPage->header.pageArrayPos == 4); } else { jam(); // Calculate an eventually new arraypos. dbgWord32(dlkPageptr, 0, (tdlkFreeArea - 128) / 512); tdlkArrayPos = (tdlkFreeArea - 128) / 512; if (cundoLogActive != ZTRUE) { jam(); /* --------------------------------------------------------------------------------- */ /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */ /* --------------------------------------------------------------------------------- */ dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos); tdlkOldArrayPos = dlkPage->header.pageArrayPos; if (tdlkArrayPos != tdlkOldArrayPos) { jam(); /* --------------------------------------------------------------------------------- */ /* THE NEW MEMORY AREA HAS ENABLED THE PAGE TO MOVE TO A NEW FREE PAGE LIST */ /* --------------------------------------------------------------------------------- */ rfpPageptr = dlkPageptr; trfpArrayPos = tdlkOldArrayPos; if (tdlkOldArrayPos != 4) { jam(); /* --------------------------------------------------------------------------------- */ /* THERE WAS A FREE PAGE LIST TO REMOVE THE PAGE FROM. IF FREE SPACE IS LESS THAN */ /* 128 BYTES THEN IT IS NOT ON ANY FREE LIST. */ /* --------------------------------------------------------------------------------- */ removeFromPageArrayList(signal); }//if dlkPage->header.pageArrayPos = tdlkArrayPos; ipaPagePtr = dlkPageptr; tipaArrayPos = tdlkArrayPos; insertPageArrayList(signal); }//if } else { // Update pageArrayPos. We are in a SR, executing undolog, insertPageArrayList() called // from execACC_OVER_REC needs this value later. dlkPage->header.pageArrayPos = tdlkArrayPos; } }//if #ifdef VM_TRACE if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "deleteLongKey"); checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey2"); #endif }//Dbacc::deleteLongKey() void Dbacc::checkIndexInLongKeyPage(Uint32 pageId, const char *calledFrom) { Page8Ptr pagePtr; LongKeyPage *page; Uint32 indexNo; Uint32 indexValue; Uint32 keyLength; Uint32 keyPos; pagePtr.i = pageId; ptrCheckGuard(pagePtr, cpagesize, page8); page = (LongKeyPage *) &pagePtr.p->word32[0]; // Check the header variables. if (page->header.nextFreeIndex > 2048 || page->header.highestIndex > 2048 || page->header.insertPos > 2048 || page->header.freeArea > 2048 || page->header.noOfElements > 225) { ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl << " pagePtr.i = " << pageId << endl; printoutInfoAndShutdown(page); } // Walk through all the indexes. for (indexNo = 1; indexNo <= page->header.highestIndex; indexNo++) { jam(); indexValue = page->word32[ZWORDS_IN_PAGE - indexNo]; if ((indexValue >> 16) == 0) { ; // key length is 0, means no key reference at this position in index. } else { // The index contains a reference to a key. jam(); keyPos = indexValue & 0xffff; keyLength = indexValue >> 16; if (keyPos >= ZWORDS_IN_PAGE || keyLength >= ZWORDS_IN_PAGE) { jam(); ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl << " keyPos = " << keyPos << endl << " keyLength = " << keyLength << endl << " page->header.noOfElements = " << page->header.noOfElements << endl << " page->header.freeArea = " << page->header.freeArea << endl << " indexNo = " << indexNo << endl << " page->header.highestIndex = " << page->header.highestIndex << endl; ndbrequire(false); } } } }//Dbacc::checkIndexInLongKeyPage /* --------------------------------------------------------------------------------- */ /* REMOVE A PAGE FROM THE PAGE ARRAY LIST. */ /* --------------------------------------------------------------------------------- */ void Dbacc::removeFromPageArrayList(Signal* signal) { Page8Ptr rfpPrevPageptr; Page8Ptr rfpNextPageptr; LongKeyPage *page; LongKeyPage *prevPage; LongKeyPage *nextPage; jam(); #ifdef VM_TRACE checkPageB4Remove(rfpPageptr.i, "removeFromPageArrayList"); #endif page = (LongKeyPage *) &rfpPageptr.p->word32[0]; if (page->header.prevPage == RNIL) { jam(); arrGuard(trfpArrayPos, 4); // This page was first in list, remove reference // to this page from the start of the list. ndbrequire(fragrecptr.p->longKeyPageArray[trfpArrayPos] == rfpPageptr.i); fragrecptr.p->longKeyPageArray[trfpArrayPos] = page->header.nextPage; } else { jam(); rfpPrevPageptr.i = page->header.prevPage; ptrCheckGuard(rfpPrevPageptr, cpagesize, page8); prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0]; // This page wasn't first in list, remove reference // to this page from the previous page. ndbrequire(prevPage->header.nextPage == rfpPageptr.i); prevPage->header.nextPage = page->header.nextPage; }//if if (page->header.nextPage != RNIL) { jam(); rfpNextPageptr.i = page->header.nextPage; ptrCheckGuard(rfpNextPageptr, cpagesize, page8); nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0]; // This page wasn't last in list, remove reference // to this page from the next page. ndbrequire(nextPage->header.prevPage == rfpPageptr.i); nextPage->header.prevPage = page->header.prevPage; // Remove reference to next page in list. page->header.nextPage = RNIL; }//if // This couldn't be set until now. // Remove reference to previous page in list. page->header.prevPage = RNIL; #ifdef VM_TRACE checkPageArrayList(signal, "removeFromPageArrayList"); #endif }//Dbacc::removeFromPageArrayList() /* --------------------------------------------------------------------------------- */ /* INSERT A PAGE INTO THE PAGE ARRAY LIST. */ /* --------------------------------------------------------------------------------- */ void Dbacc::insertPageArrayList(Signal* signal) { Page8Ptr ipaNextPagePtr; LongKeyPage *page; LongKeyPage *nextPage; jam(); #ifdef VM_TRACE checkPageArrayList(signal, "insertPageArrayList1"); checkPageB4Insert(ipaPagePtr.i, "insertPageArrayList1"); #endif page = (LongKeyPage *) &ipaPagePtr.p->word32[0]; arrGuard(tipaArrayPos, 4); if (fragrecptr.p->longKeyPageArray[tipaArrayPos] != RNIL) { jam(); ipaNextPagePtr.i = fragrecptr.p->longKeyPageArray[tipaArrayPos]; ptrCheckGuard(ipaNextPagePtr, cpagesize, page8); nextPage = (LongKeyPage *) &ipaNextPagePtr.p->word32[0]; // A page already existed in the list, add reference // to this page in the next page. nextPage->header.prevPage = ipaPagePtr.i; }//if page->header.prevPage = RNIL; page->header.nextPage = fragrecptr.p->longKeyPageArray[tipaArrayPos]; page->header.pageArrayPos = tipaArrayPos; fragrecptr.p->longKeyPageArray[tipaArrayPos] = ipaPagePtr.i; #ifdef VM_TRACE checkPageArrayList(signal, "insertPageArrayList2"); #endif }//Dbacc::insertPageArrayList() // --------------------------------------------------------------------------------- */ // Check the page array list. // --------------------------------------------------------------------------------- */ void Dbacc::checkPageArrayList(Signal* signal, const char *calledFrom) { Page8Ptr pagePtr; Uint32 pageArrayIndex; LongKeyPage *page; Uint32 prevPage; // Go through the longKeyPageArray and search for a page. for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) { jam(); pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex]; prevPage = RNIL; if (pagePtr.i != RNIL) { // A page is found. jam(); do { ptrCheckGuard(pagePtr, cpagesize, page8); page = (LongKeyPage *) &pagePtr.p->word32[0]; if ((page->header.freeArea >= 128) && (((page->header.freeArea - 128) / 512) == page->header.pageArrayPos) && (pageArrayIndex == page->header.pageArrayPos) && (page->header.prevPage == prevPage)) { // The page found is OK, test next page. prevPage = pagePtr.i; pagePtr.i = page->header.nextPage; jam(); } else { jam(); ndbout << " ERROR in checkPageArrayList, called from " << calledFrom << endl << " pagePtr.i = " << pagePtr.i << endl << " prevPage = " << prevPage << endl << " pageArrayIndex = " << pageArrayIndex << endl; printoutInfoAndShutdown(page); } }//do while (pagePtr.i != RNIL); }//if }//for }//Dbacc::checkPageArrayList() // --------------------------------------------------------------------------------- */ // Check the page to put into the pageArrayList. // --------------------------------------------------------------------------------- */ void Dbacc::checkPageB4Insert(Uint32 pageId, const char *calledFrom) { Page8Ptr pagePtr; Uint32 pageArrayIndex; LongKeyPage *page; pagePtr.i = pageId; ptrCheckGuard(pagePtr, cpagesize, page8); page = (LongKeyPage *) &pagePtr.p->word32[0]; if ((page->header.nextPage != RNIL) || (page->header.prevPage != RNIL)) { jam(); ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl << " pagePtr.i = " << pagePtr.i << endl << " page->header.nextPage = " << page->header.nextPage << endl << " page->header.prevPage = " << page->header.prevPage << endl; ndbrequire(false); } // Page should not be inserted in list if free area is less than 512 byte. if (page->header.freeArea < 128) { jam(); ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl << " Page has to little free area to be in list." << endl << " pagePtr.i = " << pagePtr.i << endl << " tipaArrayPos = " << tipaArrayPos << endl; printoutInfoAndShutdown(page); } // Check if position in list is correct if ((((page->header.freeArea - 128) / 512) != page->header.pageArrayPos) || (page->header.pageArrayPos != tipaArrayPos)) { ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl << " Incorrect position in list." << endl << " pagePtr.i = " << pagePtr.i << endl << " tipaArrayPos = " << tipaArrayPos << endl; printoutInfoAndShutdown(page); } // Check if page is already in list. for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) { jam(); pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex]; if (pagePtr.i != RNIL) { // A page is found. jam(); do { ptrCheckGuard(pagePtr, cpagesize, page8); page = (LongKeyPage *) &pagePtr.p->word32[0]; if (pagePtr.i == pageId) { jam(); ndbout << "ERROR in checkPageB4Insert, called from " << calledFrom << endl << "Page exists already in list." << endl << " pagePtr.i = " << pagePtr.i << endl; printoutInfoAndShutdown(page); } pagePtr.i = page->header.nextPage; }//do while (pagePtr.i != RNIL); }//if }//for }//Dbacc::checkPageB4Insert() // --------------------------------------------------------------------------------- */ // Check the page to remove from the pageArrayList. // --------------------------------------------------------------------------------- */ void Dbacc::checkPageB4Remove(Uint32 pageId, const char *calledFrom) { Page8Ptr pagePtr; Uint32 pageArrayIndex; Uint32 noOfOccurrence = 0; Uint32 noOfPagesInList = 0; LongKeyPage *page; LongKeyPage *prevPage; LongKeyPage *nextPage; Page8Ptr rfpPrevPageptr; Page8Ptr rfpNextPageptr; pagePtr.i = pageId; ptrCheckGuard(pagePtr, cpagesize, page8); page = (LongKeyPage *) &pagePtr.p->word32[0]; // Check that page is in list. for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) { jam(); pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex]; if (pagePtr.i != RNIL) { // A page is found. jam(); do { noOfPagesInList++; ptrCheckGuard(pagePtr, cpagesize, page8); page = (LongKeyPage *) &pagePtr.p->word32[0]; if (pagePtr.i == pageId) { // Check the consistent in list. if (page->header.prevPage != RNIL) { rfpPrevPageptr.i = page->header.prevPage; ptrCheckGuard(rfpPrevPageptr, cpagesize, page8); prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0]; if (prevPage->header.nextPage != pageId) { ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl << "prevPage->header.nextPage = " << prevPage->header.nextPage << endl << "pageId = " << pageId << endl; printoutInfoAndShutdown(page); } } // Check the consistent in list. if (page->header.nextPage != RNIL) { rfpNextPageptr.i = page->header.nextPage; ptrCheckGuard(rfpNextPageptr, cpagesize, page8); nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0]; if (nextPage->header.prevPage != pageId) { ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl << "nextPage->header.prevPage = " << nextPage->header.prevPage << endl << "pageId = " << pageId << endl; printoutInfoAndShutdown(page); } } jam(); noOfOccurrence++; } pagePtr.i = page->header.nextPage; }//do while (pagePtr.i != RNIL); }//if }//for if (noOfOccurrence != 1) { pagePtr.i = pageId; ptrCheckGuard(pagePtr, cpagesize, page8); page = (LongKeyPage *) &pagePtr.p->word32[0]; ndbout << "ERROR in checkPageB4Remove, called from " << calledFrom << endl << "Page occur " << noOfOccurrence << " times in list" << endl << "pageId = " << pageId << endl; printoutInfoAndShutdown(page); } }//Dbacc::checkPageB4Remove() // --------------------------------------------------------------------------------- */ // Printout an error message and shutdown node. // --------------------------------------------------------------------------------- */ void Dbacc::printoutInfoAndShutdown(LongKeyPage *page) { ndbout << " page->header.pageArrayPos = " << page->header.pageArrayPos << endl << " ((page->header.freeArea - 128) / 512) = " << ((page->header.freeArea - 128) / 512) << endl << " page->header.freeArea = " << page->header.freeArea << endl << " page->header.noOfElements = " << page->header.noOfElements << endl << " page->header.nextPage = " << page->header.nextPage << endl << " page->header.prevPage = " << page->header.prevPage << endl << " page->header.nextFreeIndex = " << page->header.nextFreeIndex << endl << " page->header.insertPos = " << page->header.insertPos << endl << " page->header.highestIndex = " << page->header.highestIndex << endl << " page->header.pageId = " << page->header.pageId << endl; ndbrequire(false); }//Dbacc::printoutInfoAndShutdown() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF INSERT_ELEMENT MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* MODULE: READ */ /* THE FOLLOWING SUBROUTINES ARE ONLY USED BY GET_ELEMENT AND */ /* GETDIRINDEX. THIS ROUTINE IS THE SOLE INTERFACE TO GET ELEMENTS */ /* FROM THE INDEX. CURRENT USERS ARE ALL REQUESTS AND EXECUTE UNDO LOG */ /* */ /* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */ /* GET_ELEMENT */ /* GET_DIRINDEX */ /* SEARCH_LONG_KEY */ /* */ /* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */ /* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */ /* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */ /* THOSE DEFINED AS INPUT AND OUTPUT IN GET_ELEMENT AND GETDIRINDEX */ /* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */ /* AND POINTER VARIABLES. */ /* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */ /* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */ /* EXECUTION. */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* GETDIRINDEX */ /* SUPPORT ROUTINE FOR INSERT ELEMENT, GET ELEMENT AND COMMITDELETE */ /* INPUT:FRAGRECPTR ( POINTER TO THE ACTIVE FRAGMENT REC) */ /* OPERATION_REC_PTR (POINTER TO THE OPERATION REC). */ /* */ /* OUTPUT:GDI_PAGEPTR ( POINTER TO THE PAGE OF THE ELEMENT) */ /* TGDI_PAGEINDEX ( INDEX OF THE ELEMENT IN THE PAGE). */ /* */ /* DESCRIPTION: CHECK THE HASH VALUE OF THE OPERATION REC AND CALCULATE THE */ /* THE ADDRESS OF THE ELEMENT IN THE HASH TABLE,(GDI_PAGEPTR, */ /* TGDI_PAGEINDEX) ACCORDING TO LH3. */ /* --------------------------------------------------------------------------------- */ void Dbacc::getdirindex(Signal* signal) { DirRangePtr gdiDirRangePtr; DirectoryarrayPtr gdiDirptr; Uint32 tgdiTmp; Uint32 tgdiAddress; tgdiTmp = fragrecptr.p->k + fragrecptr.p->lhfragbits; /* OBS K = 6 */ tgdiPageindex = operationRecPtr.p->hashValue & ((1 << fragrecptr.p->k) - 1); tgdiTmp = operationRecPtr.p->hashValue >> tgdiTmp; tgdiTmp = (tgdiTmp << fragrecptr.p->k) | tgdiPageindex; tgdiAddress = tgdiTmp & fragrecptr.p->maxp; gdiDirRangePtr.i = fragrecptr.p->directory; ptrCheckGuard(gdiDirRangePtr, cdirrangesize, dirRange); if (tgdiAddress < fragrecptr.p->p) { jam(); tgdiAddress = tgdiTmp & ((fragrecptr.p->maxp << 1) | 1); }//if tgdiTmp = tgdiAddress >> fragrecptr.p->k; arrGuard((tgdiTmp >> 8), 256); gdiDirptr.i = gdiDirRangePtr.p->dirArray[tgdiTmp >> 8]; ptrCheckGuard(gdiDirptr, cdirarraysize, directoryarray); gdiPageptr.i = gdiDirptr.p->pagep[tgdiTmp & 0xff]; /* DIRECTORY INDEX OF SEND BUCKET PAGE */ ptrCheckGuard(gdiPageptr, cpagesize, page8); }//Dbacc::getdirindex() /* --------------------------------------------------------------------------------- */ /* GET_ELEMENT */ /* INPUT: */ /* OPERATION_REC_PTR */ /* FRAGRECPTR */ /* OUTPUT: */ /* TGE_RESULT RESULT SUCCESS = ZTRUE OTHERWISE ZFALSE */ /* TGE_LOCKED LOCK INFORMATION IF SUCCESSFUL RESULT */ /* GE_PAGEPTR PAGE POINTER OF FOUND ELEMENT */ /* TGE_CONTAINERPTR CONTAINER INDEX OF FOUND ELEMENT */ /* TGE_ELEMENTPTR ELEMENT INDEX OF FOUND ELEMENT */ /* TGE_FORWARD DIRECTION OF CONTAINER WHERE ELEMENT FOUND */ /* */ /* DESCRIPTION: THE SUBROUTIN GOES THROUGH ALL CONTAINERS OF THE ACTIVE */ /* BUCKET, AND SERCH FOR ELEMENT.THE PRIMARY KEYS WHICH IS SAVED */ /* IN THE OPERATION REC ARE THE CHECK ITEMS IN THE SEARCHING. */ /* --------------------------------------------------------------------------------- */ void Dbacc::getElement(Signal* signal) { DirRangePtr geOverflowrangeptr; DirectoryarrayPtr geOverflowDirptr; OperationrecPtr geTmpOperationRecPtr; Uint32 tgeElementHeader; Uint32 tgeElemStep; Uint32 tgeContainerhead; Uint32 tgePageindex; Uint32 tgeActivePageDir; Uint32 tgeNextptrtype; register Uint32 tgeKeyptr; register Uint32 tgeRemLen; register Uint32 tgeCompareLen; register Uint32 TelemLen = fragrecptr.p->elementLength; register Uint32* Tkeydata = (Uint32*)&signal->theData[7]; getdirindex(signal); tgePageindex = tgdiPageindex; gePageptr = gdiPageptr; tgeResult = ZFALSE; tgeCompareLen = fragrecptr.p->keyLength; const Uint32 isAccLockReq = operationRecPtr.p->isAccLockReq; if (isAccLockReq) { jam(); tgeCompareLen = 0; } // We can handle keylength up to 8, but not more (0 means dynamic) if (tgeCompareLen >= 9) { ACCKEY_error(2); return; }//if if (TelemLen < 3) { ACCKEY_error(3); return; }//if tgeNextptrtype = ZLEFT; tgeLocked = 0; const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits; const Uint32 opHashValuePart = (operationRecPtr.p->hashValue >> tmp) &0xFFFF; do { tgeContainerptr = (tgePageindex << ZSHIFT_PLUS) - (tgePageindex << ZSHIFT_MINUS); if (tgeNextptrtype == ZLEFT) { jam(); tgeContainerptr = tgeContainerptr + ZHEAD_SIZE; tgeElementptr = tgeContainerptr + ZCON_HEAD_SIZE; tgeKeyptr = (tgeElementptr + ZELEM_HEAD_SIZE) + fragrecptr.p->localkeylen; tgeElemStep = TelemLen; tgeForward = 1; if (tgeContainerptr >= 2048) { ACCKEY_error(4); return;} tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26; if ((tgeContainerptr + tgeRemLen - 1) >= 2048) { ACCKEY_error(5); return;} } else if (tgeNextptrtype == ZRIGHT) { jam(); tgeContainerptr = tgeContainerptr + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); tgeElementptr = tgeContainerptr - 1; tgeKeyptr = (tgeElementptr - ZELEM_HEAD_SIZE) - fragrecptr.p->localkeylen; tgeElemStep = 0 - TelemLen; tgeForward = (Uint32)-1; if (tgeContainerptr >= 2048) { ACCKEY_error(4); return;} tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26; if ((tgeContainerptr - tgeRemLen) >= 2048) { ACCKEY_error(5); return;} } else { ACCKEY_error(6); return; }//if if (tgeRemLen >= TelemLen) { if (tgeRemLen > ZBUF_SIZE) { ACCKEY_error(7); return; }//if /* --------------------------------------------------------------------------------- */ // There is at least one element in this container. Check if it is the element // searched for. /* --------------------------------------------------------------------------------- */ if (tgeCompareLen != 0) { /* --------------------------------------------------------------------------------- */ /* THIS PART IS USED TO SEARCH FOR KEYS WITH FIXED SIZE. THE LOOP TAKES CARE */ /* OF SEARCHING THROUGH ALL ELEMENTS IN ONE CONTAINER. */ /* --------------------------------------------------------------------------------- */ do { register Uint32 TdataIndex = 0; register Uint32 TgeIndex = 0; jam(); tgeRemLen = tgeRemLen - TelemLen; do { if (gePageptr.p->word32[tgeKeyptr + TgeIndex] != Tkeydata[TdataIndex]) { goto compare_next; }//if TdataIndex++; TgeIndex += tgeForward; } while (TdataIndex < tgeCompareLen); /* --------------------------------------------------------------------------------- */ /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */ /* --------------------------------------------------------------------------------- */ jam(); tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]); tgeResult = ZTRUE; TdataIndex = tgeElementptr + tgeForward; TgeIndex = TdataIndex + tgeForward; operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex]; operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex]; return; /* --------------------------------------------------------------------------------- */ /* COMPARE NEXT ELEMENT */ /* --------------------------------------------------------------------------------- */ compare_next: if (tgeRemLen <= ZCON_HEAD_SIZE) { break; }//if tgeKeyptr = tgeKeyptr + tgeElemStep; tgeElementptr = tgeElementptr + tgeElemStep; } while (1); } else if (! isAccLockReq) { jam(); /* --------------------------------------------------------------------------------- */ /* THIS PART IS USED TO SEARCH FOR KEYS WITH VARIABLE LENGTH OR FIXED LENGTH */ /* GREATER THAN 32 BYTES. IN THIS CASE THE KEY PART IS STORED IN A SPECIAL */ /* LONG PAGE PART AND THE HASH INDEX CONTAINS A REFERENCE TO THERE PLUS A */ /* PART OF THE HASH VALUE. */ /* --------------------------------------------------------------------------------- */ do { tgeElementHeader = gePageptr.p->word32[tgeElementptr]; tgeRemLen = tgeRemLen - TelemLen; Uint32 hashValuePart; if (ElementHeader::getLocked(tgeElementHeader)) { jam(); /* --------------------------------------------------------------------------------- */ /* IN THIS CASE THE HASH VALUE PART OF THE ELEMENT HEADER IS STORED IN THE */ /* OPERATION THAT OWNS THE LOCK. IN THIS CASE WE MIGHT AS WELL GO AHEAD AND */ /* CHECK THE KEY IN THE LONG PAGE. */ /* --------------------------------------------------------------------------------- */ geTmpOperationRecPtr.i = ElementHeader::getOpPtrI(tgeElementHeader); ptrCheckGuard(geTmpOperationRecPtr, coprecsize, operationrec); hashValuePart = geTmpOperationRecPtr.p->hashvaluePart; } else { jam(); /* --------------------------------------------------------------------------------- */ /* IN THIS CASE THE HASH VALUE PART CAN BE CHECKED TO SEE IF THE HASH VALUE */ /* GIVES US A REASON TO CONTINUE CHECKING THE FULL KEY. */ /* --------------------------------------------------------------------------------- */ hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader); }//if if (hashValuePart == opHashValuePart) { jam(); /* --------------------------------------------------------------------------------- */ /* IF THE HASH VALUES ARE EQUAL THEN XOR-ING THEM WILL GIVE THE RESULT 0. */ /* --------------------------------------------------------------------------------- */ /* WE HAVE FOUND A KEY WITH IDENTICAL HASH VALUE. MOST LIKELY WE HAVE FOUND THE*/ /* ELEMENT BUT FIRST WE NEED TO PERFORM A KEY COMPARISON. */ /* --------------------------------------------------------------------------------- */ tslcPageIndex = gePageptr.p->word32[tgeKeyptr] & 0x3ff; tslcPagedir = gePageptr.p->word32[tgeKeyptr] >> 10; searchLongKey(signal); if (tslcResult == ZTRUE) { register Uint32 TlocData1, TlocData2; jam(); /* --------------------------------------------------------------------------------- */ /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */ /* --------------------------------------------------------------------------------- */ tgeLocked = ElementHeader::getLocked(tgeElementHeader); tgeResult = ZTRUE; TlocData1 = tgeElementptr + tgeForward; TlocData2 = TlocData1 + tgeForward; operationRecPtr.p->localdata[0] = gePageptr.p->word32[TlocData1]; operationRecPtr.p->localdata[1] = gePageptr.p->word32[TlocData2]; return; }//if } /* --------------------------------------------------------------------------------- */ /* COMPARE NEXT ELEMENT */ /* --------------------------------------------------------------------------------- */ if (tgeRemLen <= ZCON_HEAD_SIZE) { break; }//if tgeKeyptr = tgeKeyptr + tgeElemStep; tgeElementptr = tgeElementptr + tgeElemStep; } while (1); } else { jam(); /* --------------------------------------------------------------------------------- */ /* Search for local key in a lock request */ /* --------------------------------------------------------------------------------- */ do { tgeRemLen = tgeRemLen - TelemLen; // position of local key word 1 Uint32 TdataIndex = tgeElementptr + tgeForward; // XXX assume localkeylen is 1 if (gePageptr.p->word32[TdataIndex] == Tkeydata[0]) { jam(); tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]); tgeResult = ZTRUE; // position of local key word 2 Uint32 TgeIndex = TdataIndex + tgeForward; operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex]; operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex]; return; }//if if (tgeRemLen <= ZCON_HEAD_SIZE) { break; }//if tgeElementptr = tgeElementptr + tgeElemStep; } while (1); }//if }//if if (tgeRemLen != ZCON_HEAD_SIZE) { ACCKEY_error(8); return; }//if tgeContainerhead = gePageptr.p->word32[tgeContainerptr]; tgeNextptrtype = (tgeContainerhead >> 7) & 0x3; if (tgeNextptrtype == 0) { jam(); return; /* NO MORE CONTAINER */ }//if tgePageindex = tgeContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */ if (tgePageindex > ZEMPTYLIST) { ACCKEY_error(9); return; }//if if (((tgeContainerhead >> 9) & 1) == ZFALSE) { jam(); tgeActivePageDir = gePageptr.p->word32[tgeContainerptr + 1]; /* NEXT PAGE ID */ geOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(geOverflowrangeptr, cdirrangesize, dirRange); arrGuard((tgeActivePageDir >> 8), 256); geOverflowDirptr.i = geOverflowrangeptr.p->dirArray[tgeActivePageDir >> 8]; ptrCheckGuard(geOverflowDirptr, cdirarraysize, directoryarray); gePageptr.i = geOverflowDirptr.p->pagep[tgeActivePageDir & 0xff]; ptrCheckGuard(gePageptr, cpagesize, page8); }//if } while (1); return; }//Dbacc::getElement() /* --------------------------------------------------------------------------------- */ /* SEARCH_LONG_KEY */ /* INPUT: */ /* TSLC_PAGEDIR PAGE DIRECTORY OF LONG PAGE */ /* TSLC_PAGE_INDEX PAGE INDEX IN LONG PAGE */ /* GE_OPERATION_REC_PTR */ /* OUTPUT: */ /* TSLC_RESULT */ /* DESCRIPTION: SEARCH FOR AN ELEMENT IN A LONG_KEY_PAGE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::searchLongKey(Signal* signal) { DirRangePtr slcOverflowrangeptr; DirectoryarrayPtr slcOverflowDirptr; Page8Ptr slcPageptr; Uint32 tslcIndexValue; Uint32 tslcStartIndex; Uint32 tslcIndex; Uint32 guard30; Uint32* Tkeydata = (Uint32*)&signal->theData[7]; slcOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(slcOverflowrangeptr, cdirrangesize, dirRange); arrGuard((tslcPagedir >> 8), 256); slcOverflowDirptr.i = slcOverflowrangeptr.p->dirArray[tslcPagedir >> 8]; ptrCheckGuard(slcOverflowDirptr, cdirarraysize, directoryarray); // dbgWord32(slcOverflowDirptr, (int) (tslcPagedir & 0xff), slcOverflowDirptr.p->pagep[tslcPagedir & 0xff]); slcPageptr.i = slcOverflowDirptr.p->pagep[tslcPagedir & 0xff]; ptrCheckGuard(slcPageptr, cpagesize, page8); arrGuard(ZWORDS_IN_PAGE - tslcPageIndex, 2048); dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, (int)slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] & 0xffff); dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] >> 16); tslcIndexValue = slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex]; if ((tslcIndexValue >> 16) != operationRecPtr.p->tupkeylen) { jam(); tslcResult = ZFALSE; return; }//if tslcStartIndex = tslcIndexValue & 0xffff; guard30 = operationRecPtr.p->tupkeylen - 1; arrGuard(guard30, 2048); arrGuard(guard30 + tslcStartIndex, 2048); for (tslcIndex = 0; tslcIndex <= guard30; tslcIndex++) { dbgWord32(slcPageptr, tslcIndex + tslcStartIndex, slcPageptr.p->word32[tslcIndex + tslcStartIndex]); if (slcPageptr.p->word32[tslcIndex + tslcStartIndex] != Tkeydata[tslcIndex]) { jam(); tslcResult = ZFALSE; return; }//if }//for jam(); tslcResult = ZTRUE; operationRecPtr.p->longPagePtr = slcPageptr.i; operationRecPtr.p->longKeyPageIndex = tslcPageIndex; arrGuard(tslcPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE); arrGuard(slcPageptr.i, cpagesize); }//Dbacc::searchLongKey() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF GET_ELEMENT MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* MODULE: DELETE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* COMMITDELETE */ /* INPUT: OPERATION_REC_PTR, PTR TO AN OPERATION RECORD. */ /* FRAGRECPTR, PTR TO A FRAGMENT RECORD */ /* */ /* OUTPUT: */ /* NONE */ /* DESCRIPTION: DELETE OPERATIONS WILL BE COMPLETED AT THE COMMIT OF TRANSA- */ /* CTION. THIS SUBROUTINE SEARCHS FOR ELEMENT AND DELETES IT. IT DOES SO BY */ /* REPLACING IT WITH THE LAST ELEMENT IN THE BUCKET. IF THE DELETED ELEMENT */ /* IS ALSO THE LAST ELEMENT THEN IT IS ONLY NECESSARY TO REMOVE THE ELEMENT. */ /* --------------------------------------------------------------------------------- */ void Dbacc::commitdelete(Signal* signal, bool systemRestart) { if (!systemRestart) { jam(); signal->theData[0] = fragrecptr.p->myfid; signal->theData[1] = fragrecptr.p->myTableId; signal->theData[2] = operationRecPtr.p->localdata[0]; Uint32 localKey = operationRecPtr.p->localdata[0]; Uint32 pageId = localKey >> MAX_TUPLES_BITS; Uint32 pageIndex = localKey & ((1 << MAX_TUPLES_BITS) - 1); signal->theData[2] = pageId; signal->theData[3] = pageIndex; EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 4); jamEntry(); }//if if (fragrecptr.p->keyLength == 0) { jam(); tdlkLogicalPageIndex = operationRecPtr.p->longKeyPageIndex; dlkPageptr.i = operationRecPtr.p->longPagePtr; ptrCheckGuard(dlkPageptr, cpagesize, page8); deleteLongKey(signal); }//if getdirindex(signal); tlastPageindex = tgdiPageindex; lastPageptr.i = gdiPageptr.i; lastPageptr.p = gdiPageptr.p; tlastForward = ZTRUE; tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS); tlastContainerptr = tlastContainerptr + ZHEAD_SIZE; arrGuard(tlastContainerptr, 2048); tlastContainerhead = lastPageptr.p->word32[tlastContainerptr]; tlastContainerlen = tlastContainerhead >> 26; lastPrevpageptr.i = RNIL; ptrNull(lastPrevpageptr); tlastPrevconptr = 0; getLastAndRemove(signal); delPageptr.i = operationRecPtr.p->elementPage; ptrCheckGuard(delPageptr, cpagesize, page8); tdelElementptr = operationRecPtr.p->elementPointer; /* --------------------------------------------------------------------------------- */ // Here we have to take extreme care since we do not want locks to end up after the // log execution. Thus it is necessary to put back the element in unlocked shape. // We thus update the element header to ensure we log an unlocked element. We do not // need to restore it later since it is deleted immediately anyway. /* --------------------------------------------------------------------------------- */ const Uint32 hv = operationRecPtr.p->hashvaluePart; const Uint32 eh = ElementHeader::setUnlocked(hv, 0); delPageptr.p->word32[tdelElementptr] = eh; if (operationRecPtr.p->elementPage == lastPageptr.i) { if (operationRecPtr.p->elementPointer == tlastElementptr) { jam(); /* --------------------------------------------------------------------------------- */ /* THE LAST ELEMENT WAS THE ELEMENT TO BE DELETED. WE NEED NOT COPY IT. */ /* --------------------------------------------------------------------------------- */ return; }//if }//if /* --------------------------------------------------------------------------------- */ /* THE DELETED ELEMENT IS NOT THE LAST. WE READ THE LAST ELEMENT AND OVERWRITE THE */ /* DELETED ELEMENT. */ /* --------------------------------------------------------------------------------- */ tdelContainerptr = operationRecPtr.p->elementContainer; tdelForward = operationRecPtr.p->elementIsforward; deleteElement(signal); }//Dbacc::commitdelete() /* --------------------------------------------------------------------------------- */ /* DELETE_ELEMENT */ /* INPUT: FRAGRECPTR, POINTER TO A FRAGMENT RECORD */ /* LAST_PAGEPTR, POINTER TO THE PAGE OF THE LAST ELEMENT */ /* DEL_PAGEPTR, POINTER TO THE PAGE OF THE DELETED ELEMENT */ /* TLAST_ELEMENTPTR, ELEMENT POINTER OF THE LAST ELEMENT */ /* TDEL_ELEMENTPTR, ELEMENT POINTER OF THE DELETED ELEMENT */ /* TLAST_FORWARD, DIRECTION OF LAST ELEMENT */ /* TDEL_FORWARD, DIRECTION OF DELETED ELEMENT */ /* TDEL_CONTAINERPTR, CONTAINER POINTER OF DELETED ELEMENT */ /* DESCRIPTION: COPY LAST ELEMENT TO DELETED ELEMENT AND UPDATE UNDO LOG AND */ /* UPDATE ANY ACTIVE OPERATION ON THE MOVED ELEMENT. */ /* --------------------------------------------------------------------------------- */ void Dbacc::deleteElement(Signal* signal) { OperationrecPtr deOperationRecPtr; Uint32 tdeIndex; Uint32 tlastMoveElemptr; Uint32 tdelMoveElemptr; Uint32 guard31; if (tlastElementptr >= 2048) goto deleteElement_index_error1; { const Uint32 tdeElemhead = lastPageptr.p->word32[tlastElementptr]; if (fragrecptr.p->createLcp == ZTRUE) { datapageptr.p = delPageptr.p; cundoinfolength = fragrecptr.p->elementLength; if (tdelForward == ZTRUE) { jam(); cundoElemIndex = tdelElementptr; } else { jam(); cundoElemIndex = (tdelElementptr + 1) - fragrecptr.p->elementLength; }//if undoWritingProcess(signal); }//if tlastMoveElemptr = tlastElementptr; tdelMoveElemptr = tdelElementptr; guard31 = fragrecptr.p->elementLength - 1; for (tdeIndex = 0; tdeIndex <= guard31; tdeIndex++) { dbgWord32(delPageptr, tdelMoveElemptr, lastPageptr.p->word32[tlastMoveElemptr]); if ((tlastMoveElemptr >= 2048) || (tdelMoveElemptr >= 2048)) goto deleteElement_index_error2; delPageptr.p->word32[tdelMoveElemptr] = lastPageptr.p->word32[tlastMoveElemptr]; tdelMoveElemptr = tdelMoveElemptr + tdelForward; tlastMoveElemptr = tlastMoveElemptr + tlastForward; }//for if (ElementHeader::getLocked(tdeElemhead)) { /* --------------------------------------------------------------------------------- */ /* THE LAST ELEMENT IS LOCKED AND IS THUS REFERENCED BY AN OPERATION RECORD. WE NEED */ /* TO UPDATE THE OPERATION RECORD WITH THE NEW REFERENCE TO THE ELEMENT. */ /* --------------------------------------------------------------------------------- */ deOperationRecPtr.i = ElementHeader::getOpPtrI(tdeElemhead); ptrCheckGuard(deOperationRecPtr, coprecsize, operationrec); if (cundoLogActive == ZFALSE) { jam(); /* --------------------------------------------------------------------------------- */ /* WE DO NOT BOTHER WITH THIS INFORMATION DURING EXECUTION OF THE UNDO LOG. */ /* --------------------------------------------------------------------------------- */ deOperationRecPtr.p->elementPage = delPageptr.i; deOperationRecPtr.p->elementContainer = tdelContainerptr; deOperationRecPtr.p->elementPointer = tdelElementptr; deOperationRecPtr.p->elementIsforward = tdelForward; }//if /* --------------------------------------------------------------------------------- */ // We need to take extreme care to not install locked records after system restart. // An undo of the delete will reinstall the moved record. We have to ensure that the // lock is removed to ensure that no such thing happen. /* --------------------------------------------------------------------------------- */ Uint32 eh = ElementHeader::setUnlocked(deOperationRecPtr.p->hashvaluePart, 0); lastPageptr.p->word32[tlastElementptr] = eh; }//if return; } deleteElement_index_error1: arrGuard(tlastElementptr, 2048); return; deleteElement_index_error2: arrGuard(tdelMoveElemptr + guard31, 2048); arrGuard(tlastMoveElemptr, 2048); return; }//Dbacc::deleteElement() /* --------------------------------------------------------------------------------- */ /* GET_LAST_AND_REMOVE */ /* INPUT: */ /* LAST_PAGEPTR PAGE POINTER OF FIRST CONTAINER IN SEARCH OF LAST*/ /* TLAST_CONTAINERPTR CONTAINER INDEX OF THE SAME */ /* TLAST_CONTAINERHEAD CONTAINER HEADER OF THE SAME */ /* TLAST_PAGEINDEX PAGE INDEX OF THE SAME */ /* TLAST_FORWARD CONTAINER DIRECTION OF THE SAME */ /* TLAST_CONTAINERLEN CONTAINER LENGTH OF THE SAME */ /* LAST_PREVPAGEPTR PAGE POINTER OF PREVIOUS CONTAINER OF THE SAME */ /* TLAST_PREVCONPTR CONTAINER INDEX OF PREVIOUS CONTAINER OF THE SAME*/ /* */ /* OUTPUT: */ /* ALL VARIABLES FROM INPUT BUT NOW CONTAINING INFO ABOUT LAST */ /* CONTAINER. */ /* TLAST_ELEMENTPTR LAST ELEMENT POINTER IN LAST CONTAINER */ /* --------------------------------------------------------------------------------- */ void Dbacc::getLastAndRemove(Signal* signal) { DirRangePtr glrOverflowrangeptr; DirectoryarrayPtr glrOverflowDirptr; Uint32 tglrHead; Uint32 tglrTmp; GLR_LOOP_10: if (((tlastContainerhead >> 7) & 0x3) != 0) { jam(); lastPrevpageptr.i = lastPageptr.i; lastPrevpageptr.p = lastPageptr.p; tlastPrevconptr = tlastContainerptr; tlastPageindex = tlastContainerhead & 0x7f; if (((tlastContainerhead >> 9) & 0x1) == ZFALSE) { jam(); arrGuard(tlastContainerptr + 1, 2048); tglrTmp = lastPageptr.p->word32[tlastContainerptr + 1]; glrOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(glrOverflowrangeptr, cdirrangesize, dirRange); arrGuard((tglrTmp >> 8), 256); glrOverflowDirptr.i = glrOverflowrangeptr.p->dirArray[tglrTmp >> 8]; ptrCheckGuard(glrOverflowDirptr, cdirarraysize, directoryarray); lastPageptr.i = glrOverflowDirptr.p->pagep[tglrTmp & 0xff]; ptrCheckGuard(lastPageptr, cpagesize, page8); }//if tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS); if (((tlastContainerhead >> 7) & 3) == ZLEFT) { jam(); tlastForward = ZTRUE; tlastContainerptr = tlastContainerptr + ZHEAD_SIZE; } else if (((tlastContainerhead >> 7) & 3) == ZRIGHT) { jam(); tlastForward = cminusOne; tlastContainerptr = ((tlastContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE; } else { ndbrequire(false); return; }//if arrGuard(tlastContainerptr, 2048); tlastContainerhead = lastPageptr.p->word32[tlastContainerptr]; tlastContainerlen = tlastContainerhead >> 26; ndbrequire(tlastContainerlen >= ((Uint32)ZCON_HEAD_SIZE + fragrecptr.p->elementLength)); goto GLR_LOOP_10; }//if tlastContainerlen = tlastContainerlen - fragrecptr.p->elementLength; if (tlastForward == ZTRUE) { jam(); tlastElementptr = tlastContainerptr + tlastContainerlen; } else { jam(); tlastElementptr = (tlastContainerptr + (ZCON_HEAD_SIZE - 1)) - tlastContainerlen; }//if rlPageptr.i = lastPageptr.i; rlPageptr.p = lastPageptr.p; trlPageindex = tlastPageindex; if (((tlastContainerhead >> 10) & 1) == 1) { /* --------------------------------------------------------------------------------- */ /* WE HAVE OWNERSHIP OF BOTH PARTS OF THE CONTAINER ENDS. */ /* --------------------------------------------------------------------------------- */ if (tlastContainerlen < ZDOWN_LIMIT) { /* --------------------------------------------------------------------------------- */ /* WE HAVE DECREASED THE SIZE BELOW THE DOWN LIMIT, WE MUST GIVE UP THE OTHER */ /* SIDE OF THE BUFFER. */ /* --------------------------------------------------------------------------------- */ tlastContainerhead = tlastContainerhead ^ (1 << 10); trlRelCon = ZFALSE; if (tlastForward == ZTRUE) { jam(); turlIndex = tlastContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE); releaseRightlist(signal); } else { jam(); tullIndex = tlastContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE); releaseLeftlist(signal); }//if }//if }//if if (tlastContainerlen <= 2) { ndbrequire(tlastContainerlen == 2); if (lastPrevpageptr.i != RNIL) { jam(); /* --------------------------------------------------------------------------------- */ /* THE LAST CONTAINER IS EMPTY AND IS NOT THE FIRST CONTAINER WHICH IS NOT REMOVED. */ /* DELETE THE LAST CONTAINER AND UPDATE THE PREVIOUS CONTAINER. ALSO PUT THIS */ /* CONTAINER IN FREE CONTAINER LIST OF THE PAGE. */ /* --------------------------------------------------------------------------------- */ if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = lastPrevpageptr.p; cundoElemIndex = tlastPrevconptr; cundoinfolength = 1; undoWritingProcess(signal); }//if ndbrequire(tlastPrevconptr < 2048); tglrTmp = lastPrevpageptr.p->word32[tlastPrevconptr] >> 9; dbgWord32(lastPrevpageptr, tlastPrevconptr, tglrTmp << 9); lastPrevpageptr.p->word32[tlastPrevconptr] = tglrTmp << 9; trlRelCon = ZTRUE; if (tlastForward == ZTRUE) { jam(); tullIndex = tlastContainerptr; releaseLeftlist(signal); } else { jam(); turlIndex = tlastContainerptr; releaseRightlist(signal); }//if return; }//if }//if tglrHead = tlastContainerhead << 6; tglrHead = tglrHead >> 6; tglrHead = tglrHead | (tlastContainerlen << 26); if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = lastPageptr.p; cundoElemIndex = tlastContainerptr; cundoinfolength = 1; undoWritingProcess(signal); }//if dbgWord32(lastPageptr, tlastContainerptr, tglrHead); arrGuard(tlastContainerptr, 2048); lastPageptr.p->word32[tlastContainerptr] = tglrHead; }//Dbacc::getLastAndRemove() /* --------------------------------------------------------------------------------- */ /* RELEASE_LEFTLIST */ /* INPUT: */ /* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */ /* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */ /* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */ /* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */ /* A PART IS RELEASED. */ /* */ /* OUTPUT: */ /* NONE */ /* */ /* THE FREE LIST OF LEFT FREE BUFFER IN THE PAGE WILL BE UPDATE */ /* TULL_INDEX IS INDEX TO THE FIRST WORD IN THE LEFT SIDE OF THE BUFFER */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseLeftlist(Signal* signal) { Uint32 tullTmp; Uint32 tullTmp1; if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = rlPageptr.p; cundoElemIndex = tullIndex; cundoinfolength = 2; undoWritingProcess(signal); }//if if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = ZPOS_EMPTY_LIST; cundoinfolength = 2; undoWritingProcess(signal); }//if /* --------------------------------------------------------------------------------- */ /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */ /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */ /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */ /* --------------------------------------------------------------------------------- */ if (trlRelCon == ZTRUE) { arrGuard(tullIndex, 2048); trlHead = rlPageptr.p->word32[tullIndex]; trlNextused = (trlHead >> 11) & 0x7f; trlPrevused = (trlHead >> 18) & 0x7f; if (trlNextused < ZEMPTYLIST) { jam(); tullTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS); tullTmp1 = tullTmp1 + ZHEAD_SIZE; if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = tullTmp1; cundoinfolength = 1; undoWritingProcess(signal); }//if tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfe03ffff; dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlPrevused << 18)); rlPageptr.p->word32[tullTmp1] = tullTmp | (trlPrevused << 18); } else { ndbrequire(trlNextused == ZEMPTYLIST); jam(); }//if if (trlPrevused < ZEMPTYLIST) { jam(); tullTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS); tullTmp1 = tullTmp1 + ZHEAD_SIZE; if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = tullTmp1; cundoinfolength = 1; undoWritingProcess(signal); }//if tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfffc07ff; dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlNextused << 11)); rlPageptr.p->word32[tullTmp1] = tullTmp | (trlNextused << 11); } else { ndbrequire(trlPrevused == ZEMPTYLIST); jam(); /* --------------------------------------------------------------------------------- */ /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER. */ /* --------------------------------------------------------------------------------- */ tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff; dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp | (trlNextused << 23)); rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp | (trlNextused << 23); }//if }//if dbgWord32(rlPageptr, tullIndex + 1, ZEMPTYLIST); arrGuard(tullIndex + 1, 2048); rlPageptr.p->word32[tullIndex + 1] = ZEMPTYLIST; tullTmp1 = (rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> 7) & 0x7f; dbgWord32(rlPageptr, tullIndex, tullTmp1); arrGuard(tullIndex, 2048); rlPageptr.p->word32[tullIndex] = tullTmp1; if (tullTmp1 < ZEMPTYLIST) { jam(); tullTmp1 = (tullTmp1 << ZSHIFT_PLUS) - (tullTmp1 << ZSHIFT_MINUS); tullTmp1 = (tullTmp1 + ZHEAD_SIZE) + 1; if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = tullTmp1; cundoinfolength = 1; undoWritingProcess(signal); }//if dbgWord32(rlPageptr, tullTmp1, trlPageindex); rlPageptr.p->word32[tullTmp1] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */ } else { ndbrequire(tullTmp1 == ZEMPTYLIST); }//if tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST]; tullTmp = (((tullTmp >> 14) << 14) | (trlPageindex << 7)) | (tullTmp & 0x7f); dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp); rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp; dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1); rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1; ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL); if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) { jam(); colPageptr.i = rlPageptr.i; colPageptr.p = rlPageptr.p; ptrCheck(colPageptr, cpagesize, page8); checkoverfreelist(signal); }//if }//Dbacc::releaseLeftlist() /* --------------------------------------------------------------------------------- */ /* RELEASE_RIGHTLIST */ /* INPUT: */ /* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */ /* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */ /* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */ /* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */ /* A PART IS RELEASED. */ /* */ /* OUTPUT: */ /* NONE */ /* */ /* THE FREE LIST OF RIGHT FREE BUFFER IN THE PAGE WILL BE UPDATE. */ /* TURL_INDEX IS INDEX TO THE FIRST WORD IN THE RIGHT SIDE OF */ /* THE BUFFER, WHICH IS THE LAST WORD IN THE BUFFER. */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseRightlist(Signal* signal) { Uint32 turlTmp1; Uint32 turlTmp; if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = rlPageptr.p; cundoElemIndex = turlIndex; cundoinfolength = 2; undoWritingProcess(signal); }//if if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = ZPOS_EMPTY_LIST; cundoinfolength = 2; undoWritingProcess(signal); }//if /* --------------------------------------------------------------------------------- */ /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */ /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */ /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */ /* --------------------------------------------------------------------------------- */ if (trlRelCon == ZTRUE) { jam(); arrGuard(turlIndex, 2048); trlHead = rlPageptr.p->word32[turlIndex]; trlNextused = (trlHead >> 11) & 0x7f; trlPrevused = (trlHead >> 18) & 0x7f; if (trlNextused < ZEMPTYLIST) { jam(); turlTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS); turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = turlTmp1; cundoinfolength = 1; undoWritingProcess(signal); }//if turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfe03ffff; dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlPrevused << 18)); rlPageptr.p->word32[turlTmp1] = turlTmp | (trlPrevused << 18); } else { ndbrequire(trlNextused == ZEMPTYLIST); jam(); }//if if (trlPrevused < ZEMPTYLIST) { jam(); turlTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS); turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = turlTmp1; cundoinfolength = 1; undoWritingProcess(signal); }//if turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfffc07ff; dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlNextused << 11)); rlPageptr.p->word32[turlTmp1] = turlTmp | (trlNextused << 11); } else { ndbrequire(trlPrevused == ZEMPTYLIST); jam(); /* --------------------------------------------------------------------------------- */ /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER */ /* OF THE RIGHT CONTAINER LIST. */ /* --------------------------------------------------------------------------------- */ turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff; dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, turlTmp | (trlNextused << 16)); rlPageptr.p->word32[ZPOS_EMPTY_LIST] = turlTmp | (trlNextused << 16); }//if }//if dbgWord32(rlPageptr, turlIndex + 1, ZEMPTYLIST); arrGuard(turlIndex + 1, 2048); rlPageptr.p->word32[turlIndex + 1] = ZEMPTYLIST; turlTmp1 = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0x7f; dbgWord32(rlPageptr, turlIndex, turlTmp1); arrGuard(turlIndex, 2048); rlPageptr.p->word32[turlIndex] = turlTmp1; if (turlTmp1 < ZEMPTYLIST) { jam(); turlTmp = (turlTmp1 << ZSHIFT_PLUS) - (turlTmp1 << ZSHIFT_MINUS); turlTmp = turlTmp + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1)); if (fragrecptr.p->createLcp == ZTRUE) { jam(); cundoElemIndex = turlTmp; cundoinfolength = 1; undoWritingProcess(signal); }//if dbgWord32(rlPageptr, turlTmp, trlPageindex); rlPageptr.p->word32[turlTmp] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */ } else { ndbrequire(turlTmp1 == ZEMPTYLIST); }//if turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST]; dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, ((turlTmp >> 7) << 7) | trlPageindex); rlPageptr.p->word32[ZPOS_EMPTY_LIST] = ((turlTmp >> 7) << 7) | trlPageindex; dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1); rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1; ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL); if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) { jam(); colPageptr.i = rlPageptr.i; colPageptr.p = rlPageptr.p; checkoverfreelist(signal); }//if }//Dbacc::releaseRightlist() /* --------------------------------------------------------------------------------- */ /* CHECKOVERFREELIST */ /* INPUT: COL_PAGEPTR, POINTER OF AN OVERFLOW PAGE RECORD. */ /* DESCRIPTION: CHECKS IF THE PAGE HAVE TO PUT IN FREE LIST OF OVER FLOW */ /* PAGES. WHEN IT HAVE TO, AN OVERFLOW REC PTR WILL BE ALLOCATED */ /* TO KEEP NFORMATION ABOUT THE PAGE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::checkoverfreelist(Signal* signal) { Uint32 tcolTmp; if (fragrecptr.p->loadingFlag == ZFALSE) { tcolTmp = colPageptr.p->word32[ZPOS_ALLOC_CONTAINERS]; if (tcolTmp <= ZFREE_LIMIT) { if (tcolTmp == 0) { jam(); ropPageptr = colPageptr; releaseOverpage(signal); } else { jam(); if (colPageptr.p->word32[ZPOS_OVERFLOWREC] == RNIL) { ndbrequire(cfirstfreeoverrec != RNIL); jam(); seizeOverRec(signal); sorOverflowRecPtr.p->dirindex = colPageptr.p->word32[ZPOS_PAGE_ID]; sorOverflowRecPtr.p->overpage = colPageptr.i; dbgWord32(colPageptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i); colPageptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i; porOverflowRecPtr = sorOverflowRecPtr; putOverflowRecInFrag(signal); }//if }//if }//if }//if }//Dbacc::checkoverfreelist() /* --------------------------------------------------------------------------------- */ /* RELEASE_LONG_PAGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseLongPage(Signal* signal) { DirRangePtr rlpOverflowrangeptr; DirectoryarrayPtr rlpOverflowDirptr; Uint32 trlpTmp1; Uint32 trlpTmp2; Uint32 trlpTmp3; jam(); seizeOverRec(signal); sorOverflowRecPtr.p->dirindex = rlopPageptr.p->word32[ZPOS_PAGE_ID]; sorOverflowRecPtr.p->overpage = RNIL; priOverflowRecPtr = sorOverflowRecPtr; putRecInFreeOverdir(signal); trlpTmp1 = sorOverflowRecPtr.p->dirindex; rlpOverflowrangeptr.i = fragrecptr.p->overflowdir; trlpTmp2 = trlpTmp1 >> 8; trlpTmp3 = trlpTmp1 & 0xff; ptrCheckGuard(rlpOverflowrangeptr, cdirrangesize, dirRange); arrGuard(trlpTmp2, 256); rlpOverflowDirptr.i = rlpOverflowrangeptr.p->dirArray[trlpTmp2]; ptrCheckGuard(rlpOverflowDirptr, cdirarraysize, directoryarray); rlpOverflowDirptr.p->pagep[trlpTmp3] = RNIL; if (cundoLogActive != ZTRUE) { // Remove from page array. trfpArrayPos = rlopPageptr.p->word32[ZPOS_ARRAY_POS]; rfpPageptr = rlopPageptr; removeFromPageArrayList(signal); } // Reset page header iloPageptr = rlopPageptr; tiloIndex = rlopPageptr.p->word32[ZPOS_PAGE_ID]; initLongOverpage(signal); rpPageptr = rlopPageptr; releasePage(signal); }//Dbacc::releaseLongPage() /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* */ /* END OF DELETE MODULE */ /* */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* */ /* COMMIT AND ABORT MODULE */ /* */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ABORT_OPERATION */ /*DESCRIPTION: AN OPERATION RECORD CAN BE IN A LOCK QUEUE OF AN ELEMENT OR */ /*OWNS THE LOCK. BY THIS SUBROUTINE THE LOCK STATE OF THE OPERATION WILL */ /*BE CHECKED. THE OPERATION RECORD WILL BE REMOVED FROM THE QUEUE IF IT */ /*BELONGED TO ANY ONE, OTHERWISE THE ELEMENT HEAD WILL BE UPDATED. */ /* ------------------------------------------------------------------------- */ void Dbacc::abortOperation(Signal* signal) { OperationrecPtr aboOperRecPtr; OperationrecPtr TaboOperRecPtr; Page8Ptr aboPageidptr; Uint32 taboElementptr; Uint32 tmp2Olq; if (operationRecPtr.p->lockOwner == ZTRUE) { takeOutLockOwnersList(signal, operationRecPtr); if (operationRecPtr.p->insertIsDone == ZTRUE) { jam(); operationRecPtr.p->elementIsDisappeared = ZTRUE; }//if if ((operationRecPtr.p->nextParallelQue != RNIL) || (operationRecPtr.p->nextSerialQue != RNIL)) { jam(); releaselock(signal); } else { /* --------------------------------------------------------------------------------- */ /* WE ARE OWNER OF THE LOCK AND NO OTHER OPERATIONS ARE QUEUED. IF INSERT OR STANDBY */ /* WE DELETE THE ELEMENT OTHERWISE WE REMOVE THE LOCK FROM THE ELEMENT. */ /* --------------------------------------------------------------------------------- */ if (operationRecPtr.p->elementIsDisappeared == ZFALSE) { jam(); taboElementptr = operationRecPtr.p->elementPointer; aboPageidptr.i = operationRecPtr.p->elementPage; tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart, operationRecPtr.p->scanBits); ptrCheckGuard(aboPageidptr, cpagesize, page8); dbgWord32(aboPageidptr, taboElementptr, tmp2Olq); arrGuard(taboElementptr, 2048); aboPageidptr.p->word32[taboElementptr] = tmp2Olq; return; } else { jam(); commitdelete(signal, false); }//if }//if } else { /* --------------------------------------------------------------- */ // We are not the lock owner. /* --------------------------------------------------------------- */ jam(); takeOutFragWaitQue(signal); if (operationRecPtr.p->prevParallelQue != RNIL) { jam(); /* ---------------------------------------------------------------------------------- */ /* SINCE WE ARE NOT QUEUE LEADER WE NEED NOT CONSIDER IF THE ELEMENT IS TO BE DELETED.*/ /* We will simply remove it from the parallel list without any other rearrangements. */ /* ---------------------------------------------------------------------------------- */ aboOperRecPtr.i = operationRecPtr.p->prevParallelQue; ptrCheckGuard(aboOperRecPtr, coprecsize, operationrec); aboOperRecPtr.p->nextParallelQue = operationRecPtr.p->nextParallelQue; if (operationRecPtr.p->nextParallelQue != RNIL) { jam(); aboOperRecPtr.i = operationRecPtr.p->nextParallelQue; ptrCheckGuard(aboOperRecPtr, coprecsize, operationrec); aboOperRecPtr.p->prevParallelQue = operationRecPtr.p->prevParallelQue; }//if } else if (operationRecPtr.p->prevSerialQue != RNIL) { /* ------------------------------------------------------------------------- */ // We are not in the parallel queue owning the lock. Thus we are in another parallel // queue longer down in the serial queue. We are however first since prevParallelQue // == RNIL. /* ------------------------------------------------------------------------- */ if (operationRecPtr.p->nextParallelQue != RNIL) { jam(); /* ------------------------------------------------------------------------- */ // We have an operation in the queue after us. We simply rearrange this parallel queue. // The new leader of this parallel queue will be operation in the serial queue. /* ------------------------------------------------------------------------- */ aboOperRecPtr.i = operationRecPtr.p->nextParallelQue; ptrCheckGuard(aboOperRecPtr, coprecsize, operationrec); aboOperRecPtr.p->nextSerialQue = operationRecPtr.p->nextSerialQue; aboOperRecPtr.p->prevSerialQue = operationRecPtr.p->prevSerialQue; aboOperRecPtr.p->prevParallelQue = RNIL; // Queue Leader if (operationRecPtr.p->nextSerialQue != RNIL) { jam(); TaboOperRecPtr.i = operationRecPtr.p->nextSerialQue; ptrCheckGuard(TaboOperRecPtr, coprecsize, operationrec); TaboOperRecPtr.p->prevSerialQue = aboOperRecPtr.i; }//if TaboOperRecPtr.i = operationRecPtr.p->prevSerialQue; ptrCheckGuard(TaboOperRecPtr, coprecsize, operationrec); TaboOperRecPtr.p->nextSerialQue = aboOperRecPtr.i; } else { jam(); /* ------------------------------------------------------------------------- */ // We are the only operation in this parallel queue. We will thus shrink the serial // queue. /* ------------------------------------------------------------------------- */ aboOperRecPtr.i = operationRecPtr.p->prevSerialQue; ptrCheckGuard(aboOperRecPtr, coprecsize, operationrec); aboOperRecPtr.p->nextSerialQue = operationRecPtr.p->nextSerialQue; if (operationRecPtr.p->nextSerialQue != RNIL) { jam(); aboOperRecPtr.i = operationRecPtr.p->nextSerialQue; ptrCheckGuard(aboOperRecPtr, coprecsize, operationrec); aboOperRecPtr.p->prevSerialQue = operationRecPtr.p->prevSerialQue; }//if }//if }//if }//if /* ------------------------------------------------------------------------- */ // If prevParallelQue = RNIL and prevSerialQue = RNIL and we are not owner of the // lock then we cannot be in any lock queue at all. /* ------------------------------------------------------------------------- */ }//Dbacc::abortOperation() void Dbacc::commitDeleteCheck() { OperationrecPtr opPtr; OperationrecPtr lastOpPtr; OperationrecPtr deleteOpPtr; bool elementDeleted = false; bool deleteCheckOngoing = true; Uint32 hashValue = 0; lastOpPtr = operationRecPtr; opPtr.i = operationRecPtr.p->nextParallelQue; while (opPtr.i != RNIL) { jam(); ptrCheckGuard(opPtr, coprecsize, operationrec); lastOpPtr = opPtr; opPtr.i = opPtr.p->nextParallelQue; }//while deleteOpPtr = lastOpPtr; do { if (deleteOpPtr.p->operation == ZDELETE) { jam(); /* --------------------------------------------------------------------------------- */ /* IF THE CURRENT OPERATION TO BE COMMITTED IS A DELETE OPERATION DUE TO A */ /* SCAN-TAKEOVER THE ACTUAL DELETE WILL BE PERFORMED BY THE PREVIOUS OPERATION (SCAN)*/ /* IN THE PARALLEL QUEUE WHICH OWNS THE LOCK.THE PROBLEM IS THAT THE SCAN OPERATION */ /* DOES NOT HAVE A HASH VALUE ASSIGNED TO IT SO WE COPY IT FROM THIS OPERATION. */ /* */ /* WE ASSUME THAT THIS SOLUTION WILL WORK BECAUSE THE ONLY WAY A SCAN CAN PERFORM */ /* A DELETE IS BY BEING FOLLOWED BY A NORMAL DELETE-OPERATION THAT HAS A HASH VALUE. */ /* --------------------------------------------------------------------------------- */ hashValue = deleteOpPtr.p->hashValue; elementDeleted = true; deleteCheckOngoing = false; } else if ((deleteOpPtr.p->operation == ZREAD) || (deleteOpPtr.p->operation == ZSCAN_OP)) { /* --------------------------------------------------------------------------------- */ /* We are trying to find out whether the commit will in the end delete the tuple. */ /* Normally the delete will be the last operation in the list of operations on this */ /* It is however possible to issue reads and scans in the same savepoint as the */ /* delete operation was issued and these can end up after the delete in the list of */ /* operations in the parallel queue. Thus if we discover a read or a scan we have to */ /* continue scanning the list looking for a delete operation. */ /* --------------------------------------------------------------------------------- */ deleteOpPtr.i = deleteOpPtr.p->prevParallelQue; if (deleteOpPtr.i == RNIL) { jam(); deleteCheckOngoing = false; } else { jam(); ptrCheckGuard(deleteOpPtr, coprecsize, operationrec); }//if } else { jam(); /* --------------------------------------------------------------------------------- */ /* Finding an UPDATE or INSERT before finding a DELETE means we cannot be deleting */ /* as the end result of this transaction. */ /* --------------------------------------------------------------------------------- */ deleteCheckOngoing = false; }//if } while (deleteCheckOngoing); opPtr = lastOpPtr; do { jam(); opPtr.p->commitDeleteCheckFlag = ZTRUE; if (elementDeleted) { jam(); opPtr.p->elementIsDisappeared = ZTRUE; opPtr.p->hashValue = hashValue; }//if opPtr.i = opPtr.p->prevParallelQue; if (opPtr.i == RNIL) { jam(); break; }//if ptrCheckGuard(opPtr, coprecsize, operationrec); } while (true); }//Dbacc::commitDeleteCheck() /* ------------------------------------------------------------------------- */ /* COMMIT_OPERATION */ /* INPUT: OPERATION_REC_PTR, POINTER TO AN OPERATION RECORD */ /* DESCRIPTION: THE OPERATION RECORD WILL BE TAKE OUT OF ANY LOCK QUEUE. */ /* IF IT OWNS THE ELEMENT LOCK. HEAD OF THE ELEMENT WILL BE UPDATED. */ /* ------------------------------------------------------------------------- */ void Dbacc::commitOperation(Signal* signal) { OperationrecPtr tolqTmpPtr; Page8Ptr coPageidptr; Uint32 tcoElementptr; Uint32 tmp2Olq; if ((operationRecPtr.p->commitDeleteCheckFlag == ZFALSE) && (operationRecPtr.p->operation != ZSCAN_OP)) { jam(); /* This method is used to check whether the end result of the transaction will be to delete the tuple. In this case all operation will be marked with elementIsDisappeared = true to ensure that the last operation committed will remove the tuple. We only run this once per transaction (commitDeleteCheckFlag = true if performed earlier) and we don't execute this code when committing a scan operation since committing a scan operation only means that the scan is continuing and the scan lock is released. */ commitDeleteCheck(); }//if if (operationRecPtr.p->lockOwner == ZTRUE) { takeOutLockOwnersList(signal, operationRecPtr); if ((operationRecPtr.p->nextParallelQue == RNIL) && (operationRecPtr.p->nextSerialQue == RNIL) && (operationRecPtr.p->elementIsDisappeared == ZFALSE)) { /* This is the normal path through the commit for operations owning the lock without any queues and not a delete operation. */ coPageidptr.i = operationRecPtr.p->elementPage; tcoElementptr = operationRecPtr.p->elementPointer; tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart, operationRecPtr.p->scanBits); ptrCheckGuard(coPageidptr, cpagesize, page8); dbgWord32(coPageidptr, tcoElementptr, tmp2Olq); arrGuard(tcoElementptr, 2048); coPageidptr.p->word32[tcoElementptr] = tmp2Olq; return; } else if ((operationRecPtr.p->nextParallelQue != RNIL) || (operationRecPtr.p->nextSerialQue != RNIL)) { jam(); /* The case when there is a queue lined up. Release the lock and pass it to the next operation lined up. */ releaselock(signal); return; } else { jam(); /* No queue and elementIsDisappeared is true. We perform the actual delete operation. */ commitdelete(signal, false); return; }//if } else { /* THE OPERATION DOES NOT OWN THE LOCK. IT MUST BE IN A LOCK QUEUE OF THE ELEMENT. */ ndbrequire(operationRecPtr.p->prevParallelQue != RNIL); jam(); tolqTmpPtr.i = operationRecPtr.p->prevParallelQue; ptrCheckGuard(tolqTmpPtr, coprecsize, operationrec); tolqTmpPtr.p->nextParallelQue = operationRecPtr.p->nextParallelQue; if (operationRecPtr.p->nextParallelQue != RNIL) { jam(); tolqTmpPtr.i = operationRecPtr.p->nextParallelQue; ptrCheckGuard(tolqTmpPtr, coprecsize, operationrec); tolqTmpPtr.p->prevParallelQue = operationRecPtr.p->prevParallelQue; }//if }//if }//Dbacc::commitOperation() /* ------------------------------------------------------------------------- */ /* RELEASELOCK */ /* RESETS LOCK OF AN ELEMENT. */ /* INFORMATION ABOUT THE ELEMENT IS SAVED IN THE OPERATION RECORD */ /* THESE INFORMATION IS USED TO UPDATE HEADER OF THE ELEMENT */ /* ------------------------------------------------------------------------- */ void Dbacc::releaselock(Signal* signal) { OperationrecPtr rloOperPtr; OperationrecPtr trlOperPtr; OperationrecPtr trlTmpOperPtr; Uint32 TelementIsDisappeared; trlOperPtr.i = RNIL; if (operationRecPtr.p->nextParallelQue != RNIL) { jam(); /* --------------------------------------------------------------------------------- */ /* NEXT OPERATION TAKES OVER THE LOCK. We will simply move the info from the leader */ // to the new queue leader. /* --------------------------------------------------------------------------------- */ trlOperPtr.i = operationRecPtr.p->nextParallelQue; ptrCheckGuard(trlOperPtr, coprecsize, operationrec); copyInOperPtr = trlOperPtr; copyOperPtr = operationRecPtr; copyOpInfo(signal); trlOperPtr.p->prevParallelQue = RNIL; if (operationRecPtr.p->nextSerialQue != RNIL) { jam(); /* --------------------------------------------------------------------------------- */ /* THERE IS A SERIAL QUEUE. MOVE IT FROM RELEASED OP REC TO THE NEW LOCK OWNER. */ /* --------------------------------------------------------------------------------- */ trlOperPtr.p->nextSerialQue = operationRecPtr.p->nextSerialQue; trlTmpOperPtr.i = trlOperPtr.p->nextSerialQue; ptrCheckGuard(trlTmpOperPtr, coprecsize, operationrec); trlTmpOperPtr.p->prevSerialQue = trlOperPtr.i; }//if /* --------------------------------------------------------------------------------- */ /* SINCE THERE ARE STILL ITEMS IN THE PARALLEL QUEUE WE NEED NOT WORRY ABOUT */ /* STARTING QUEUED OPERATIONS. THUS WE CAN END HERE. */ /* --------------------------------------------------------------------------------- */ } else { ndbrequire(operationRecPtr.p->nextSerialQue != RNIL); jam(); /* --------------------------------------------------------------------------------- */ /* THE PARALLEL QUEUE IS EMPTY AND THE SERIAL QUEUE IS NOT EMPTY. WE NEED TO */ /* REARRANGE LISTS AND START A NUMBER OF OPERATIONS. */ /* --------------------------------------------------------------------------------- */ trlOperPtr.i = operationRecPtr.p->nextSerialQue; ptrCheckGuard(trlOperPtr, coprecsize, operationrec); copyOperPtr = operationRecPtr; copyInOperPtr = trlOperPtr; copyOpInfo(signal); trlOperPtr.p->prevSerialQue = RNIL; ndbrequire(trlOperPtr.p->prevParallelQue == RNIL); /* --------------------------------------------------------------------------------- */ /* WE HAVE MOVED TO THE NEXT PARALLEL QUEUE. WE MUST START ALL OF THOSE */ /* OPERATIONS WHICH UP TILL NOW HAVE BEEN QUEUED WAITING FOR THE LOCK. */ /* --------------------------------------------------------------------------------- */ rloOperPtr = operationRecPtr; trlTmpOperPtr = trlOperPtr; TelementIsDisappeared = trlOperPtr.p->elementIsDisappeared; Uint32 ThashValue = trlOperPtr.p->hashValue; do { /* --------------------------------------------------------------------------------- */ // Ensure that all operations in the queue are assigned with the elementIsDisappeared // to ensure that the element is removed after a previous delete. An insert does // however revert this decision since the element is put back again. Local checkpoints // complicate life here since they do not execute the next operation but simply change // the state on the operation. We need to set-up the variable elementIsDisappeared // properly even when local checkpoints and inserts/writes after deletes occur. /* --------------------------------------------------------------------------------- */ trlTmpOperPtr.p->elementIsDisappeared = TelementIsDisappeared; if (TelementIsDisappeared == ZTRUE) { /* --------------------------------------------------------------------------------- */ // If the elementIsDisappeared is set then we know that the hashValue is also set // since it always originates from a committing abort or a aborting insert. Scans // do not initialise the hashValue and must have this value initialised if they are // to successfully commit the delete. /* --------------------------------------------------------------------------------- */ jam(); trlTmpOperPtr.p->hashValue = ThashValue; }//if trlTmpOperPtr.p->localdata[0] = trlOperPtr.p->localdata[0]; trlTmpOperPtr.p->localdata[1] = trlOperPtr.p->localdata[1]; /* --------------------------------------------------------------------------------- */ // Restart the queued operation. /* --------------------------------------------------------------------------------- */ operationRecPtr = trlTmpOperPtr; TelementIsDisappeared = executeNextOperation(signal); ThashValue = operationRecPtr.p->hashValue; if (trlTmpOperPtr.p->nextParallelQue != RNIL) { jam(); /* --------------------------------------------------------------------------------- */ // We will continue with the next operation in the parallel queue and start this as // well. /* --------------------------------------------------------------------------------- */ trlTmpOperPtr.i = trlTmpOperPtr.p->nextParallelQue; ptrCheckGuard(trlTmpOperPtr, coprecsize, operationrec); } else { jam(); break; }//if } while (1); operationRecPtr = rloOperPtr; }//if // Insert the next op into the lock owner list insertLockOwnersList(signal, trlOperPtr); return; }//Dbacc::releaselock() /* --------------------------------------------------------------------------------- */ /* COPY_OP_INFO */ /* INPUT: COPY_IN_OPER_PTR AND COPY_OPER_PTR. */ /* DESCRIPTION:INFORMATION ABOUT THE ELEMENT WILL BE MOVED FROM OPERATION */ /* REC TO QUEUE OP REC. QUE OP REC TAKES OVER THE LOCK. */ /* --------------------------------------------------------------------------------- */ void Dbacc::copyOpInfo(Signal* signal) { Page8Ptr coiPageidptr; copyInOperPtr.p->elementPage = copyOperPtr.p->elementPage; copyInOperPtr.p->elementIsforward = copyOperPtr.p->elementIsforward; copyInOperPtr.p->elementContainer = copyOperPtr.p->elementContainer; copyInOperPtr.p->elementPointer = copyOperPtr.p->elementPointer; copyInOperPtr.p->scanBits = copyOperPtr.p->scanBits; copyInOperPtr.p->hashvaluePart = copyOperPtr.p->hashvaluePart; copyInOperPtr.p->elementIsDisappeared = copyOperPtr.p->elementIsDisappeared; if (copyInOperPtr.p->elementIsDisappeared == ZTRUE) { /* --------------------------------------------------------------------------------- */ // If the elementIsDisappeared is set then we know that the hashValue is also set // since it always originates from a committing abort or a aborting insert. Scans // do not initialise the hashValue and must have this value initialised if they are // to successfully commit the delete. /* --------------------------------------------------------------------------------- */ jam(); copyInOperPtr.p->hashValue = copyOperPtr.p->hashValue; }//if coiPageidptr.i = copyOperPtr.p->elementPage; ptrCheckGuard(coiPageidptr, cpagesize, page8); const Uint32 tmp = ElementHeader::setLocked(copyInOperPtr.i); dbgWord32(coiPageidptr, copyOperPtr.p->elementPointer, tmp); arrGuard(copyOperPtr.p->elementPointer, 2048); coiPageidptr.p->word32[copyOperPtr.p->elementPointer] = tmp; copyInOperPtr.p->localdata[0] = copyOperPtr.p->localdata[0]; copyInOperPtr.p->localdata[1] = copyOperPtr.p->localdata[1]; }//Dbacc::copyOpInfo() /* ******************--------------------------------------------------------------- */ /* EXECUTE NEXT OPERATION */ /* NEXT OPERATION IN A LOCK QUEUE WILL BE EXECUTED. */ /* --------------------------------------------------------------------------------- */ Uint32 Dbacc::executeNextOperation(Signal* signal) { ndbrequire(operationRecPtr.p->transactionstate == ACTIVE); if (fragrecptr.p->stopQueOp == ZTRUE) { Uint32 TelemDisappeared; jam(); TelemDisappeared = operationRecPtr.p->elementIsDisappeared; if ((operationRecPtr.p->elementIsDisappeared == ZTRUE) && (operationRecPtr.p->prevParallelQue == RNIL) && ((operationRecPtr.p->operation == ZINSERT) || (operationRecPtr.p->operation == ZWRITE))) { jam(); /* --------------------------------------------------------------------------------- */ // In this case we do not wish to change the elementIsDisappeared since that would // create an error the next time this method is called for this operation after local // checkpoint starts up operations again. We must however ensure that operations // that follow in the queue do not get the value ZTRUE when actually an INSERT/WRITE // precedes them (only if the INSERT/WRITE is the first operation). /* --------------------------------------------------------------------------------- */ TelemDisappeared = ZFALSE; }//if /* --------------------------------------------------------------------------------- */ /* A LOCAL CHECKPOINT HAS STOPPED OPERATIONS. WE MUST NOT START THE OPERATION */ /* AT THIS TIME. WE SET THE STATE TO INDICATE THAT WE ARE READY TO START AS */ /* SOON AS WE ARE ALLOWED. */ /* --------------------------------------------------------------------------------- */ operationRecPtr.p->opState = WAIT_EXE_OP; return TelemDisappeared; }//if takeOutFragWaitQue(signal); if (operationRecPtr.p->elementIsDisappeared == ZTRUE) { /* --------------------------------------------------------------------------------- */ /* PREVIOUS OPERATION WAS DELETE OPERATION AND THE ELEMENT IS ALREADY DELETED. */ /* --------------------------------------------------------------------------------- */ if (((operationRecPtr.p->operation != ZINSERT) && (operationRecPtr.p->operation != ZWRITE)) || (operationRecPtr.p->prevParallelQue != RNIL)) { if (operationRecPtr.p->operation != ZSCAN_OP || operationRecPtr.p->isAccLockReq) { jam(); /* --------------------------------------------------------------------------------- */ // Updates and reads with a previous delete simply aborts with read error indicating // that tuple did not exist. Also inserts and writes not being the first operation. /* --------------------------------------------------------------------------------- */ operationRecPtr.p->transactionstate = WAIT_COMMIT_ABORT; signal->theData[0] = operationRecPtr.p->userptr; signal->theData[1] = ZREAD_ERROR; sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYREF, signal, 2, JBB); return operationRecPtr.p->elementIsDisappeared; } else { /* --------------------------------------------------------------------------------- */ /* ABORT OF OPERATION NEEDED BUT THE OPERATION IS A SCAN => SPECIAL TREATMENT. */ /* IF THE SCAN WAITS IN QUEUE THEN WE MUST REMOVE THE OPERATION FROM THE SCAN */ /* LOCK QUEUE AND IF NO MORE OPERATIONS ARE QUEUED THEN WE SHOULD RESTART THE */ /* SCAN PROCESS. OTHERWISE WE SIMPLY RELEASE THE OPERATION AND DECREASE THE */ /* NUMBER OF LOCKS HELD. */ /* --------------------------------------------------------------------------------- */ takeOutScanLockQueue(operationRecPtr.p->scanRecPtr); putReadyScanQueue(signal, operationRecPtr.p->scanRecPtr); return operationRecPtr.p->elementIsDisappeared; }//if }//if /* --------------------------------------------------------------------------------- */ // Insert and writes can continue but need to be converted to inserts. /* --------------------------------------------------------------------------------- */ jam(); operationRecPtr.p->elementIsDisappeared = ZFALSE; operationRecPtr.p->operation = ZINSERT; operationRecPtr.p->insertIsDone = ZTRUE; } else if (operationRecPtr.p->operation == ZINSERT) { bool abortFlag = true; if (operationRecPtr.p->prevParallelQue != RNIL) { OperationrecPtr prevOpPtr; jam(); prevOpPtr.i = operationRecPtr.p->prevParallelQue; ptrCheckGuard(prevOpPtr, coprecsize, operationrec); if (prevOpPtr.p->operation == ZDELETE) { jam(); abortFlag = false; }//if }//if if (abortFlag) { jam(); /* --------------------------------------------------------------------------------- */ /* ELEMENT STILL REMAINS AND WE ARE TRYING TO INSERT IT AGAIN. THIS IS CLEARLY */ /* NOT A GOOD IDEA. */ /* --------------------------------------------------------------------------------- */ operationRecPtr.p->transactionstate = WAIT_COMMIT_ABORT; signal->theData[0] = operationRecPtr.p->userptr; signal->theData[1] = ZWRITE_ERROR; sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYREF, signal, 2, JBB); return operationRecPtr.p->elementIsDisappeared; }//if }//if if (operationRecPtr.p->operation == ZSCAN_OP && ! operationRecPtr.p->isAccLockReq) { jam(); takeOutScanLockQueue(operationRecPtr.p->scanRecPtr); putReadyScanQueue(signal, operationRecPtr.p->scanRecPtr); } else { jam(); sendAcckeyconf(signal); sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYCONF, signal, 6, JBB); }//if return operationRecPtr.p->elementIsDisappeared; }//Dbacc::executeNextOperation() /* --------------------------------------------------------------------------------- */ /* TAKE_OUT_FRAG_WAIT_QUE */ /* DESCRIPTION: AN OPERATION WHICH OWNS A LOCK OF AN ELEMENT, IS IN A LIST */ /* OF THE FRAGMENT. THIS LIST IS USED TO STOP THE QUEUE OPERATION */ /* DURING CREATE CHECK POINT PROSESS FOR STOP AND RESTART OF THE */ /* OPERATIONS. THIS SUBRUTIN TAKES A OPERATION RECORD OUT OF THE LIST */ /* -------------------------------------------------------------------------------- */ void Dbacc::takeOutFragWaitQue(Signal* signal) { OperationrecPtr tofwqOperRecPtr; if (operationRecPtr.p->opState == WAIT_IN_QUEUE) { if (fragrecptr.p->sentWaitInQueOp == operationRecPtr.i) { jam(); fragrecptr.p->sentWaitInQueOp = operationRecPtr.p->nextQueOp; }//if if (operationRecPtr.p->prevQueOp != RNIL) { jam(); tofwqOperRecPtr.i = operationRecPtr.p->prevQueOp; ptrCheckGuard(tofwqOperRecPtr, coprecsize, operationrec); tofwqOperRecPtr.p->nextQueOp = operationRecPtr.p->nextQueOp; } else { jam(); fragrecptr.p->firstWaitInQueOp = operationRecPtr.p->nextQueOp; }//if if (operationRecPtr.p->nextQueOp != RNIL) { jam(); tofwqOperRecPtr.i = operationRecPtr.p->nextQueOp; ptrCheckGuard(tofwqOperRecPtr, coprecsize, operationrec); tofwqOperRecPtr.p->prevQueOp = operationRecPtr.p->prevQueOp; } else { jam(); fragrecptr.p->lastWaitInQueOp = operationRecPtr.p->prevQueOp; }//if operationRecPtr.p->opState = FREE_OP; return; } else { ndbrequire(operationRecPtr.p->opState == FREE_OP); }//if }//Dbacc::takeOutFragWaitQue() /** * takeOutLockOwnersList * * Description: Take out an operation from the doubly linked * lock owners list on the fragment. * */ void Dbacc::takeOutLockOwnersList(Signal* signal, const OperationrecPtr& outOperPtr) { const Uint32 Tprev = outOperPtr.p->prevLockOwnerOp; const Uint32 Tnext = outOperPtr.p->nextLockOwnerOp; #ifdef VM_TRACE // Check that operation is already in the list OperationrecPtr tmpOperPtr; bool inList = false; tmpOperPtr.i = fragrecptr.p->lockOwnersList; while (tmpOperPtr.i != RNIL){ ptrCheckGuard(tmpOperPtr, coprecsize, operationrec); if (tmpOperPtr.i == outOperPtr.i) inList = true; tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp; } ndbrequire(inList == true); #endif ndbrequire(outOperPtr.p->lockOwner == ZTRUE); outOperPtr.p->lockOwner = ZFALSE; // Fast path through the code for the common case. if ((Tprev == RNIL) && (Tnext == RNIL)) { ndbrequire(fragrecptr.p->lockOwnersList == outOperPtr.i); fragrecptr.p->lockOwnersList = RNIL; return; } // Check previous operation if (Tprev != RNIL) { jam(); arrGuard(Tprev, coprecsize); operationrec[Tprev].nextLockOwnerOp = Tnext; } else { fragrecptr.p->lockOwnersList = Tnext; }//if // Check next operation if (Tnext == RNIL) { return; } else { jam(); arrGuard(Tnext, coprecsize); operationrec[Tnext].prevLockOwnerOp = Tprev; }//if return; }//Dbacc::takeOutLockOwnersList() /** * insertLockOwnersList * * Description: Insert an operation first in the dubly linked lock owners * list on the fragment. * */ void Dbacc::insertLockOwnersList(Signal* signal, const OperationrecPtr& insOperPtr) { OperationrecPtr tmpOperPtr; #ifdef VM_TRACE // Check that operation is not already in list tmpOperPtr.i = fragrecptr.p->lockOwnersList; while(tmpOperPtr.i != RNIL){ ptrCheckGuard(tmpOperPtr, coprecsize, operationrec); ndbrequire(tmpOperPtr.i != insOperPtr.i); tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp; } #endif ndbrequire(insOperPtr.p->lockOwner == ZFALSE); insOperPtr.p->lockOwner = ZTRUE; insOperPtr.p->prevLockOwnerOp = RNIL; tmpOperPtr.i = fragrecptr.p->lockOwnersList; fragrecptr.p->lockOwnersList = insOperPtr.i; insOperPtr.p->nextLockOwnerOp = tmpOperPtr.i; if (tmpOperPtr.i == RNIL) { return; } else { jam(); ptrCheckGuard(tmpOperPtr, coprecsize, operationrec); tmpOperPtr.p->prevLockOwnerOp = insOperPtr.i; }//if }//Dbacc::insertLockOwnersList() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF COMMIT AND ABORT MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* ALLOC_OVERFLOW_PAGE */ /* DESCRIPTION: */ /* --------------------------------------------------------------------------------- */ void Dbacc::allocOverflowPage(Signal* signal) { DirRangePtr aopDirRangePtr; DirectoryarrayPtr aopOverflowDirptr; OverflowRecordPtr aopOverflowRecPtr; Uint32 taopTmp1; Uint32 taopTmp2; Uint32 taopTmp3; tresult = 0; if ((cfirstfreepage == RNIL) && (cfreepage >= cpagesize)) { jam(); zpagesize_error("Dbacc::allocOverflowPage"); tresult = ZPAGESIZE_ERROR; return; }//if if (fragrecptr.p->firstFreeDirindexRec != RNIL) { jam(); /* FRAGRECPTR:FIRST_FREE_DIRINDEX_REC POINTS */ /* TO THE FIRST ELEMENT IN A FREE LIST OF THE */ /* DIRECTORY INDEX WICH HAVE NULL AS PAGE */ aopOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec; ptrCheckGuard(aopOverflowRecPtr, coverflowrecsize, overflowRecord); troOverflowRecPtr.p = aopOverflowRecPtr.p; takeRecOutOfFreeOverdir(signal); } else if (cfirstfreeoverrec == RNIL) { jam(); tresult = ZOVER_REC_ERROR; return; } else if ((cfirstfreedir == RNIL) && (cdirarraysize <= cdirmemory)) { jam(); tresult = ZDIRSIZE_ERROR; return; } else { jam(); seizeOverRec(signal); aopOverflowRecPtr = sorOverflowRecPtr; aopOverflowRecPtr.p->dirindex = fragrecptr.p->lastOverIndex; }//if aopOverflowRecPtr.p->nextOverRec = RNIL; aopOverflowRecPtr.p->prevOverRec = RNIL; fragrecptr.p->firstOverflowRec = aopOverflowRecPtr.i; fragrecptr.p->lastOverflowRec = aopOverflowRecPtr.i; taopTmp1 = aopOverflowRecPtr.p->dirindex; aopDirRangePtr.i = fragrecptr.p->overflowdir; taopTmp2 = taopTmp1 >> 8; taopTmp3 = taopTmp1 & 0xff; ptrCheckGuard(aopDirRangePtr, cdirrangesize, dirRange); arrGuard(taopTmp2, 256); if (aopDirRangePtr.p->dirArray[taopTmp2] == RNIL) { jam(); seizeDirectory(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); aopDirRangePtr.p->dirArray[taopTmp2] = sdDirptr.i; }//if aopOverflowDirptr.i = aopDirRangePtr.p->dirArray[taopTmp2]; seizePage(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); ptrCheckGuard(aopOverflowDirptr, cdirarraysize, directoryarray); aopOverflowDirptr.p->pagep[taopTmp3] = spPageptr.i; tiopPageId = aopOverflowRecPtr.p->dirindex; iopOverflowRecPtr = aopOverflowRecPtr; iopPageptr = spPageptr; initOverpage(signal); aopOverflowRecPtr.p->overpage = spPageptr.i; if (fragrecptr.p->lastOverIndex <= aopOverflowRecPtr.p->dirindex) { jam(); ndbrequire(fragrecptr.p->lastOverIndex == aopOverflowRecPtr.p->dirindex); fragrecptr.p->lastOverIndex++; }//if }//Dbacc::allocOverflowPage() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* EXPAND/SHRINK MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /*EXPANDCHECK EXPAND BUCKET ORD */ /* SENDER: ACC, LEVEL B */ /* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */ /* DESCRIPTION: A BUCKET OF A FRAGMENT PAGE WILL BE EXPAND INTO TWO BUCKETS */ /* ACCORDING TO LH3. */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* EXPANDCHECK EXPAND BUCKET ORD */ /* ******************------------------------------+ */ /* SENDER: ACC, LEVEL B */ /* A BUCKET OF THE FRAGMENT WILL */ /* BE EXPANDED ACORDING TO LH3, */ /* AND COMMIT TRANSACTION PROCESS */ /* WILL BE CONTINUED */ Uint32 Dbacc::checkScanExpand(Signal* signal) { Uint32 Ti; Uint32 TreturnCode = 0; Uint32 TPageIndex; Uint32 TDirInd; Uint32 TSplit; Uint32 TreleaseInd = 0; Uint32 TreleaseScanBucket; Uint32 TreleaseScanIndicator[4]; DirectoryarrayPtr TDirptr; DirRangePtr TDirRangePtr; Page8Ptr TPageptr; ScanRecPtr TscanPtr; RootfragmentrecPtr Trootfragrecptr; Trootfragrecptr.i = fragrecptr.p->myroot; TSplit = fragrecptr.p->p; ptrCheckGuard(Trootfragrecptr, crootfragmentsize, rootfragmentrec); for (Ti = 0; Ti < 4; Ti++) { TreleaseScanIndicator[Ti] = 0; if (Trootfragrecptr.p->scan[Ti] != RNIL) { //------------------------------------------------------------- // A scan is ongoing on this particular local fragment. We have // to check its current state. //------------------------------------------------------------- TscanPtr.i = Trootfragrecptr.p->scan[Ti]; ptrCheckGuard(TscanPtr, cscanRecSize, scanRec); if (TscanPtr.p->activeLocalFrag == fragrecptr.i) { if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) { if (TSplit == TscanPtr.p->nextBucketIndex) { jam(); //------------------------------------------------------------- // We are currently scanning this bucket. We cannot split it // simultaneously with the scan. We have to pass this offer for // splitting the bucket. //------------------------------------------------------------- TreturnCode = 1; return TreturnCode; } else if (TSplit > TscanPtr.p->nextBucketIndex) { jam(); //------------------------------------------------------------- // This bucket has not yet been scanned. We must reset the scanned // bit indicator for this scan on this bucket. //------------------------------------------------------------- TreleaseScanIndicator[Ti] = 1; TreleaseInd = 1; } else { jam(); }//if } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) { jam(); //------------------------------------------------------------- // We are performing a second lap to handle buckets that was // merged during the first lap of scanning. During this second // lap we do not allow any splits or merges. //------------------------------------------------------------- TreturnCode = 1; return TreturnCode; } else { ndbrequire(TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED); jam(); //------------------------------------------------------------- // The scan is completed and we can thus go ahead and perform // the split. //------------------------------------------------------------- }//if }//if }//if }//for if (TreleaseInd == 1) { TreleaseScanBucket = TSplit; TDirRangePtr.i = fragrecptr.p->directory; TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */ TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */ ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange); arrGuard((TDirInd >> 8), 256); TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8]; ptrCheckGuard(TDirptr, cdirarraysize, directoryarray); TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff]; ptrCheckGuard(TPageptr, cpagesize, page8); for (Ti = 0; Ti < 4; Ti++) { if (TreleaseScanIndicator[Ti] == 1) { jam(); scanPtr.i = Trootfragrecptr.p->scan[Ti]; ptrCheckGuard(scanPtr, cscanRecSize, scanRec); rsbPageidptr = TPageptr; trsbPageindex = TPageIndex; releaseScanBucket(signal); }//if }//for }//if return TreturnCode; }//Dbacc::checkScanExpand() void Dbacc::execEXPANDCHECK2(Signal* signal) { jamEntry(); if(refToBlock(signal->getSendersBlockRef()) == DBLQH){ jam(); reenable_expand_after_redo_log_exection_complete(signal); return; } DirectoryarrayPtr newDirptr; fragrecptr.i = signal->theData[0]; tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */ Uint32 tmp = 1; tmp = tmp << 31; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); fragrecptr.p->expandFlag = 0; if (fragrecptr.p->slack < tmp) { jam(); /* IT MEANS THAT IF SLACK > ZERO */ /*--------------------------------------------------------------*/ /* THE SLACK HAS IMPROVED AND IS NOW ACCEPTABLE AND WE */ /* CAN FORGET ABOUT THE EXPAND PROCESS. */ /*--------------------------------------------------------------*/ return; }//if if (fragrecptr.p->firstOverflowRec == RNIL) { jam(); allocOverflowPage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); /*--------------------------------------------------------------*/ /* WE COULD NOT ALLOCATE ANY OVERFLOW PAGE. THUS WE HAVE TO STOP*/ /* THE EXPAND SINCE WE CANNOT GUARANTEE ITS COMPLETION. */ /*--------------------------------------------------------------*/ return; }//if }//if if (cfirstfreepage == RNIL) { if (cfreepage >= cpagesize) { jam(); /*--------------------------------------------------------------*/ /* WE HAVE TO STOP THE EXPAND PROCESS SINCE THERE ARE NO FREE */ /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */ /* CANNOT COMPLETE THE EXPAND. TO AVOID THE CRASH WE EXIT HERE. */ /*--------------------------------------------------------------*/ return; }//if }//if if (checkScanExpand(signal) == 1) { jam(); /*--------------------------------------------------------------*/ // A scan state was inconsistent with performing an expand // operation. /*--------------------------------------------------------------*/ return; }//if if (fragrecptr.p->createLcp == ZTRUE) { if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_EXPAND) { jam(); /*--------------------------------------------------------------*/ // We did not have enough undo log buffers to start up an // expand operation /*--------------------------------------------------------------*/ return; }//if }//if /*--------------------------------------------------------------------------*/ /* WE START BY FINDING THE PAGE, THE PAGE INDEX AND THE PAGE DIRECTORY*/ /* OF THE NEW BUCKET WHICH SHALL RECEIVE THE ELEMENT WHICH HAVE A 1 IN*/ /* THE NEXT HASH BIT. THIS BIT IS USED IN THE SPLIT MECHANISM TO */ /* DECIDE WHICH ELEMENT GOES WHERE. */ /*--------------------------------------------------------------------------*/ expDirRangePtr.i = fragrecptr.p->directory; texpReceivedBucket = (fragrecptr.p->maxp + fragrecptr.p->p) + 1; /* RECEIVED BUCKET */ texpDirInd = texpReceivedBucket >> fragrecptr.p->k; newDirptr.i = RNIL; ptrNull(newDirptr); texpDirRangeIndex = texpDirInd >> 8; ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange); arrGuard(texpDirRangeIndex, 256); expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex]; if (expDirptr.i == RNIL) { jam(); seizeDirectory(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); return; } else { jam(); newDirptr = sdDirptr; expDirptr = sdDirptr; expDirRangePtr.p->dirArray[texpDirRangeIndex] = sdDirptr.i; }//if } else { ptrCheckGuard(expDirptr, cdirarraysize, directoryarray); }//if texpDirPageIndex = texpDirInd & 0xff; expPageptr.i = expDirptr.p->pagep[texpDirPageIndex]; if (expPageptr.i == RNIL) { jam(); seizePage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); if (newDirptr.i != RNIL) { jam(); rdDirptr.i = newDirptr.i; releaseDirectory(signal); }//if return; }//if expDirptr.p->pagep[texpDirPageIndex] = spPageptr.i; tipPageId = texpDirInd; inpPageptr = spPageptr; initPage(signal); fragrecptr.p->dirsize++; expPageptr = spPageptr; } else { ptrCheckGuard(expPageptr, cpagesize, page8); }//if fragrecptr.p->expReceivePageptr = expPageptr.i; fragrecptr.p->expReceiveIndex = texpReceivedBucket & ((1 << fragrecptr.p->k) - 1); /*--------------------------------------------------------------------------*/ /* THE NEXT ACTION IS TO FIND THE PAGE, THE PAGE INDEX AND THE PAGE */ /* DIRECTORY OF THE BUCKET TO BE SPLIT. */ /*--------------------------------------------------------------------------*/ expDirRangePtr.i = fragrecptr.p->directory; cexcPageindex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */ texpDirInd = fragrecptr.p->p >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */ ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange); arrGuard((texpDirInd >> 8), 256); expDirptr.i = expDirRangePtr.p->dirArray[texpDirInd >> 8]; ptrCheckGuard(expDirptr, cdirarraysize, directoryarray); excPageptr.i = expDirptr.p->pagep[texpDirInd & 0xff]; fragrecptr.p->expSenderIndex = cexcPageindex; fragrecptr.p->expSenderPageptr = excPageptr.i; if (excPageptr.i == RNIL) { jam(); endofexpLab(signal); /* EMPTY BUCKET */ return; }//if fragrecptr.p->expReceiveForward = ZTRUE; ptrCheckGuard(excPageptr, cpagesize, page8); expandcontainer(signal); endofexpLab(signal); return; }//Dbacc::execEXPANDCHECK2() void Dbacc::endofexpLab(Signal* signal) { fragrecptr.p->p++; fragrecptr.p->slack += fragrecptr.p->maxloadfactor; fragrecptr.p->expandCounter++; if (fragrecptr.p->p > fragrecptr.p->maxp) { jam(); fragrecptr.p->maxp = (fragrecptr.p->maxp << 1) | 1; fragrecptr.p->lhdirbits++; fragrecptr.p->hashcheckbit++; fragrecptr.p->p = 0; }//if Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p; Uint32 Thysteres = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor; fragrecptr.p->slackCheck = noOfBuckets * Thysteres; if (fragrecptr.p->slack > (1u << 31)) { jam(); /* IT MEANS THAT IF SLACK < ZERO */ /* --------------------------------------------------------------------------------- */ /* IT IS STILL NECESSARY TO EXPAND THE FRAGMENT EVEN MORE. START IT FROM HERE */ /* WITHOUT WAITING FOR NEXT COMMIT ON THE FRAGMENT. */ /* --------------------------------------------------------------------------------- */ fragrecptr.p->expandFlag = 2; signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB); }//if return; }//Dbacc::endofexpLab() void Dbacc::reenable_expand_after_redo_log_exection_complete(Signal* signal){ tabptr.i = signal->theData[0]; Uint32 fragId = signal->theData[1]; ptrCheckGuard(tabptr, ctablesize, tabrec); ndbrequire(getrootfragmentrec(signal, rootfragrecptr, fragId)); #if 0 ndbout_c("reenable expand check for table %d fragment: %d", tabptr.i, fragId); #endif for (Uint32 i = 0; i < 2; i++) { fragrecptr.i = rootfragrecptr.p->fragmentptr[i]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); switch(fragrecptr.p->expandFlag){ case 0: /** * Hmm... this means that it's alreay has been reenabled... */ ndbassert(false); continue; case 1: /** * Nothing is going on start expand check */ case 2: /** * A shrink is running, do expand check anyway * (to reset expandFlag) */ fragrecptr.p->expandFlag = 2; signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB); break; } } } void Dbacc::execDEBUG_SIG(Signal* signal) { jamEntry(); expPageptr.i = signal->theData[0]; progError(__LINE__, ERR_SR_UNDOLOG); return; }//Dbacc::execDEBUG_SIG() /* --------------------------------------------------------------------------------- */ /* EXPANDCONTAINER */ /* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */ /* CEXC_PAGEINDEX (INDEX OF THE BUCKET). */ /* */ /* DESCRIPTION: THE HASH VALUE OF ALL ELEMENTS IN THE CONTAINER WILL BE */ /* CHECKED. SOME OF THIS ELEMENTS HAVE TO MOVE TO THE NEW CONTAINER */ /* --------------------------------------------------------------------------------- */ void Dbacc::expandcontainer(Signal* signal) { Uint32 texcHashvalue; Uint32 texcTmp; Uint32 texcIndex; Uint32 texpKeyLen; Uint32 guard20; texpKeyLen = fragrecptr.p->keyLength; if (texpKeyLen == 0) { jam(); texpKeyLen = ZACTIVE_LONG_KEY_LEN; }//if cexcPrevpageptr = RNIL; cexcPrevconptr = 0; cexcForward = ZTRUE; EXP_CONTAINER_LOOP: cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS); if (cexcForward == ZTRUE) { jam(); cexcContainerptr = cexcContainerptr + ZHEAD_SIZE; cexcElementptr = cexcContainerptr + ZCON_HEAD_SIZE; } else { jam(); cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE; cexcElementptr = cexcContainerptr - 1; }//if arrGuard(cexcContainerptr, 2048); cexcContainerhead = excPageptr.p->word32[cexcContainerptr]; cexcContainerlen = cexcContainerhead >> 26; cexcMovedLen = ZCON_HEAD_SIZE; if (cexcContainerlen <= ZCON_HEAD_SIZE) { ndbrequire(cexcContainerlen >= ZCON_HEAD_SIZE); jam(); goto NEXT_ELEMENT; }//if NEXT_ELEMENT_LOOP: idrOperationRecPtr.i = RNIL; ptrNull(idrOperationRecPtr); /* --------------------------------------------------------------------------------- */ /* CEXC_PAGEINDEX PAGE INDEX OF CURRENT CONTAINER BEING EXAMINED. */ /* CEXC_CONTAINERPTR INDEX OF CURRENT CONTAINER BEING EXAMINED. */ /* CEXC_ELEMENTPTR INDEX OF CURRENT ELEMENT BEING EXAMINED. */ /* EXC_PAGEPTR PAGE WHERE CURRENT ELEMENT RESIDES. */ /* CEXC_PREVPAGEPTR PAGE OF PREVIOUS CONTAINER. */ /* CEXC_PREVCONPTR INDEX OF PREVIOUS CONTAINER */ /* CEXC_FORWARD DIRECTION OF CURRENT CONTAINER */ /* --------------------------------------------------------------------------------- */ arrGuard(cexcElementptr, 2048); tidrElemhead = excPageptr.p->word32[cexcElementptr]; if (ElementHeader::getUnlocked(tidrElemhead)){ jam(); texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead); } else { jam(); idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead); ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec); texcHashvalue = idrOperationRecPtr.p->hashvaluePart; if ((fragrecptr.p->createLcp == ZTRUE) && (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) != 0)) { jam(); /* --------------------------------------------------------------------------------- */ // During local checkpoints we must ensure that we restore the element header in // unlocked state and with the hash value part there with tuple status zeroed. // Otherwise a later insert over the same element will write an UNDO log that will // ensure that the now removed element is restored together with its locked element // header and without the hash value part. /* --------------------------------------------------------------------------------- */ const Uint32 hv = idrOperationRecPtr.p->hashvaluePart; const Uint32 eh = ElementHeader::setUnlocked(hv, 0); excPageptr.p->word32[cexcElementptr] = eh; }//if }//if if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) { jam(); /* --------------------------------------------------------------------------------- */ /* THIS ELEMENT IS NOT TO BE MOVED. WE CALCULATE THE WHEREABOUTS OF THE NEXT */ /* ELEMENT AND PROCEED WITH THAT OR END THE SEARCH IF THERE ARE NO MORE */ /* ELEMENTS IN THIS CONTAINER. */ /* --------------------------------------------------------------------------------- */ goto NEXT_ELEMENT; }//if /* --------------------------------------------------------------------------------- */ /* THE HASH BIT WAS SET AND WE SHALL MOVE THIS ELEMENT TO THE NEW BUCKET. */ /* WE START BY READING THE ELEMENT TO BE ABLE TO INSERT IT INTO THE NEW BUCKET.*/ /* THEN WE INSERT THE ELEMENT INTO THE NEW BUCKET. THE NEXT STEP IS TO DELETE */ /* THE ELEMENT FROM THIS BUCKET. THIS IS PERFORMED BY REPLACING IT WITH THE */ /* LAST ELEMENT IN THE BUCKET. IF THIS ELEMENT IS TO BE MOVED WE MOVE IT AND */ /* GET THE LAST ELEMENT AGAIN UNTIL WE EITHER FIND ONE THAT STAYS OR THIS */ /* ELEMENT IS THE LAST ELEMENT. */ /* --------------------------------------------------------------------------------- */ texcTmp = cexcElementptr + cexcForward; guard20 = fragrecptr.p->localkeylen - 1; for (texcIndex = 0; texcIndex <= guard20; texcIndex++) { arrGuard(texcIndex, 2); arrGuard(texcTmp, 2048); clocalkey[texcIndex] = excPageptr.p->word32[texcTmp]; texcTmp = texcTmp + cexcForward; }//for guard20 = texpKeyLen - 1; for (texcIndex = 0; texcIndex <= guard20; texcIndex++) { arrGuard(texcIndex, 2048); arrGuard(texcTmp, 2048); ckeys[texcIndex] = excPageptr.p->word32[texcTmp]; texcTmp = texcTmp + cexcForward; }//for tidrPageindex = fragrecptr.p->expReceiveIndex; idrPageptr.i = fragrecptr.p->expReceivePageptr; ptrCheckGuard(idrPageptr, cpagesize, page8); tidrForward = fragrecptr.p->expReceiveForward; tidrKeyLen = texpKeyLen; insertElement(signal); fragrecptr.p->expReceiveIndex = tidrPageindex; fragrecptr.p->expReceivePageptr = idrPageptr.i; fragrecptr.p->expReceiveForward = tidrForward; REMOVE_LAST_LOOP: jam(); lastPageptr.i = excPageptr.i; lastPageptr.p = excPageptr.p; tlastContainerptr = cexcContainerptr; lastPrevpageptr.i = cexcPrevpageptr; ptrCheck(lastPrevpageptr, cpagesize, page8); tlastPrevconptr = cexcPrevconptr; arrGuard(tlastContainerptr, 2048); tlastContainerhead = lastPageptr.p->word32[tlastContainerptr]; tlastContainerlen = tlastContainerhead >> 26; tlastForward = cexcForward; tlastPageindex = cexcPageindex; getLastAndRemove(signal); if (excPageptr.i == lastPageptr.i) { if (cexcElementptr == tlastElementptr) { jam(); /* --------------------------------------------------------------------------------- */ /* THE CURRENT ELEMENT WAS ALSO THE LAST ELEMENT. */ /* --------------------------------------------------------------------------------- */ return; }//if }//if /* --------------------------------------------------------------------------------- */ /* THE CURRENT ELEMENT WAS NOT THE LAST ELEMENT. IF THE LAST ELEMENT SHOULD */ /* STAY WE COPY IT TO THE POSITION OF THE CURRENT ELEMENT, OTHERWISE WE INSERT */ /* INTO THE NEW BUCKET, REMOVE IT AND TRY WITH THE NEW LAST ELEMENT. */ /* --------------------------------------------------------------------------------- */ idrOperationRecPtr.i = RNIL; ptrNull(idrOperationRecPtr); arrGuard(tlastElementptr, 2048); tidrElemhead = lastPageptr.p->word32[tlastElementptr]; if (ElementHeader::getUnlocked(tidrElemhead)) { jam(); texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead); } else { jam(); idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead); ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec); texcHashvalue = idrOperationRecPtr.p->hashvaluePart; if ((fragrecptr.p->createLcp == ZTRUE) && (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) != 0)) { jam(); /* --------------------------------------------------------------------------------- */ // During local checkpoints we must ensure that we restore the element header in // unlocked state and with the hash value part there with tuple status zeroed. // Otherwise a later insert over the same element will write an UNDO log that will // ensure that the now removed element is restored together with its locked element // header and without the hash value part. /* --------------------------------------------------------------------------------- */ const Uint32 hv = idrOperationRecPtr.p->hashvaluePart; const Uint32 eh = ElementHeader::setUnlocked(hv, 0); lastPageptr.p->word32[tlastElementptr] = eh; }//if }//if if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) { jam(); /* --------------------------------------------------------------------------------- */ /* THE LAST ELEMENT IS NOT TO BE MOVED. WE COPY IT TO THE CURRENT ELEMENT. */ /* --------------------------------------------------------------------------------- */ delPageptr = excPageptr; tdelContainerptr = cexcContainerptr; tdelForward = cexcForward; tdelElementptr = cexcElementptr; deleteElement(signal); } else { jam(); /* --------------------------------------------------------------------------------- */ /* THE LAST ELEMENT IS ALSO TO BE MOVED. */ /* --------------------------------------------------------------------------------- */ texcTmp = tlastElementptr + tlastForward; for (texcIndex = 0; texcIndex < fragrecptr.p->localkeylen; texcIndex++) { arrGuard(texcIndex, 2); arrGuard(texcTmp, 2048); clocalkey[texcIndex] = lastPageptr.p->word32[texcTmp]; texcTmp = texcTmp + tlastForward; }//for for (texcIndex = 0; texcIndex < texpKeyLen; texcIndex++) { arrGuard(texcIndex, 2048); arrGuard(texcTmp, 2048); ckeys[texcIndex] = lastPageptr.p->word32[texcTmp]; texcTmp = texcTmp + tlastForward; }//for tidrPageindex = fragrecptr.p->expReceiveIndex; idrPageptr.i = fragrecptr.p->expReceivePageptr; ptrCheckGuard(idrPageptr, cpagesize, page8); tidrForward = fragrecptr.p->expReceiveForward; tidrKeyLen = texpKeyLen; insertElement(signal); fragrecptr.p->expReceiveIndex = tidrPageindex; fragrecptr.p->expReceivePageptr = idrPageptr.i; fragrecptr.p->expReceiveForward = tidrForward; goto REMOVE_LAST_LOOP; }//if NEXT_ELEMENT: arrGuard(cexcContainerptr, 2048); cexcContainerhead = excPageptr.p->word32[cexcContainerptr]; cexcMovedLen = cexcMovedLen + fragrecptr.p->elementLength; if ((cexcContainerhead >> 26) > cexcMovedLen) { jam(); /* --------------------------------------------------------------------------------- */ /* WE HAVE NOT YET MOVED THE COMPLETE CONTAINER. WE PROCEED WITH THE NEXT */ /* ELEMENT IN THE CONTAINER. IT IS IMPORTANT TO READ THE CONTAINER LENGTH */ /* FROM THE CONTAINER HEADER SINCE IT MIGHT CHANGE BY REMOVING THE LAST */ /* ELEMENT IN THE BUCKET. */ /* --------------------------------------------------------------------------------- */ cexcElementptr = cexcElementptr + (cexcForward * fragrecptr.p->elementLength); goto NEXT_ELEMENT_LOOP; }//if if (((cexcContainerhead >> 7) & 3) != 0) { jam(); /* --------------------------------------------------------------------------------- */ /* WE PROCEED TO THE NEXT CONTAINER IN THE BUCKET. */ /* --------------------------------------------------------------------------------- */ cexcPrevpageptr = excPageptr.i; cexcPrevconptr = cexcContainerptr; nextcontainerinfoExp(signal); goto EXP_CONTAINER_LOOP; }//if }//Dbacc::expandcontainer() /* ******************--------------------------------------------------------------- */ /* SHRINKCHECK JOIN BUCKET ORD */ /* SENDER: ACC, LEVEL B */ /* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */ /* DESCRIPTION: TWO BUCKET OF A FRAGMENT PAGE WILL BE JOINED TOGETHER */ /* ACCORDING TO LH3. */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* SHRINKCHECK JOIN BUCKET ORD */ /* ******************------------------------------+ */ /* SENDER: ACC, LEVEL B */ /* TWO BUCKETS OF THE FRAGMENT */ /* WILL BE JOINED ACORDING TO LH3 */ /* AND COMMIT TRANSACTION PROCESS */ /* WILL BE CONTINUED */ Uint32 Dbacc::checkScanShrink(Signal* signal) { Uint32 Ti; Uint32 TreturnCode = 0; Uint32 TPageIndex; Uint32 TDirInd; Uint32 TmergeDest; Uint32 TmergeSource; Uint32 TreleaseScanBucket; Uint32 TreleaseInd = 0; Uint32 TreleaseScanIndicator[4]; DirectoryarrayPtr TDirptr; DirRangePtr TDirRangePtr; Page8Ptr TPageptr; ScanRecPtr TscanPtr; RootfragmentrecPtr Trootfragrecptr; Trootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(Trootfragrecptr, crootfragmentsize, rootfragmentrec); if (fragrecptr.p->p == 0) { jam(); TmergeDest = fragrecptr.p->maxp >> 1; } else { jam(); TmergeDest = fragrecptr.p->p - 1; }//if TmergeSource = fragrecptr.p->maxp + fragrecptr.p->p; for (Ti = 0; Ti < 4; Ti++) { TreleaseScanIndicator[Ti] = 0; if (Trootfragrecptr.p->scan[Ti] != RNIL) { TscanPtr.i = Trootfragrecptr.p->scan[Ti]; ptrCheckGuard(TscanPtr, cscanRecSize, scanRec); if (TscanPtr.p->activeLocalFrag == fragrecptr.i) { //------------------------------------------------------------- // A scan is ongoing on this particular local fragment. We have // to check its current state. //------------------------------------------------------------- if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) { jam(); if ((TmergeDest == TscanPtr.p->nextBucketIndex) || (TmergeSource == TscanPtr.p->nextBucketIndex)) { jam(); //------------------------------------------------------------- // We are currently scanning one of the buckets involved in the // merge. We cannot merge while simultaneously performing a scan. // We have to pass this offer for merging the buckets. //------------------------------------------------------------- TreturnCode = 1; return TreturnCode; } else if (TmergeDest < TscanPtr.p->nextBucketIndex) { jam(); TreleaseScanIndicator[Ti] = 1; TreleaseInd = 1; }//if } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) { jam(); //------------------------------------------------------------- // We are performing a second lap to handle buckets that was // merged during the first lap of scanning. During this second // lap we do not allow any splits or merges. //------------------------------------------------------------- TreturnCode = 1; return TreturnCode; } else if (TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) { jam(); //------------------------------------------------------------- // The scan is completed and we can thus go ahead and perform // the split. //------------------------------------------------------------- } else { jam(); sendSystemerror(signal); return TreturnCode; }//if }//if }//if }//for if (TreleaseInd == 1) { jam(); TreleaseScanBucket = TmergeSource; TDirRangePtr.i = fragrecptr.p->directory; TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */ TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */ ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange); arrGuard((TDirInd >> 8), 256); TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8]; ptrCheckGuard(TDirptr, cdirarraysize, directoryarray); TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff]; ptrCheckGuard(TPageptr, cpagesize, page8); for (Ti = 0; Ti < 4; Ti++) { if (TreleaseScanIndicator[Ti] == 1) { jam(); scanPtr.i = Trootfragrecptr.p->scan[Ti]; ptrCheckGuard(scanPtr, cscanRecSize, scanRec); rsbPageidptr.i = TPageptr.i; rsbPageidptr.p = TPageptr.p; trsbPageindex = TPageIndex; releaseScanBucket(signal); if (TmergeDest < scanPtr.p->minBucketIndexToRescan) { jam(); //------------------------------------------------------------- // We have to keep track of the starting bucket to Rescan in the // second lap. //------------------------------------------------------------- scanPtr.p->minBucketIndexToRescan = TmergeDest; }//if if (TmergeDest > scanPtr.p->maxBucketIndexToRescan) { jam(); //------------------------------------------------------------- // We have to keep track of the ending bucket to Rescan in the // second lap. //------------------------------------------------------------- scanPtr.p->maxBucketIndexToRescan = TmergeDest; }//if }//if }//for }//if return TreturnCode; }//Dbacc::checkScanShrink() void Dbacc::execSHRINKCHECK2(Signal* signal) { Uint32 tshrTmp1; jamEntry(); fragrecptr.i = signal->theData[0]; Uint32 oldFlag = signal->theData[3]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); fragrecptr.p->expandFlag = oldFlag; tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */ if (fragrecptr.p->slack <= fragrecptr.p->slackCheck) { jam(); /* TIME FOR JOIN BUCKETS PROCESS */ /*--------------------------------------------------------------*/ /* NO LONGER NECESSARY TO SHRINK THE FRAGMENT. */ /*--------------------------------------------------------------*/ return; }//if if (fragrecptr.p->slack > (1u << 31)) { jam(); /*--------------------------------------------------------------*/ /* THE SLACK IS NEGATIVE, IN THIS CASE WE WILL NOT NEED ANY */ /* SHRINK. */ /*--------------------------------------------------------------*/ return; }//if texpDirInd = (fragrecptr.p->maxp + fragrecptr.p->p) >> fragrecptr.p->k; if (((fragrecptr.p->maxp + fragrecptr.p->p) & ((1 << fragrecptr.p->k) - 1)) == 0) { if (fragrecptr.p->createLcp == ZTRUE) { if (fragrecptr.p->fragState == LCP_SEND_PAGES) { if (fragrecptr.p->lcpMaxDirIndex > texpDirInd) { if (fragrecptr.p->lcpDirIndex <= texpDirInd) { jam(); /*--------------------------------------------------------------*/ /* WE DO NOT ALLOW ANY SHRINKS THAT REMOVE PAGES THAT ARE */ /* NEEDED AS PART OF THE LOCAL CHECKPOINT. */ /*--------------------------------------------------------------*/ return; }//if }//if }//if }//if }//if if (fragrecptr.p->firstOverflowRec == RNIL) { jam(); allocOverflowPage(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); return; }//if }//if if (cfirstfreepage == RNIL) { if (cfreepage >= cpagesize) { jam(); /*--------------------------------------------------------------*/ /* WE HAVE TO STOP THE SHRINK PROCESS SINCE THERE ARE NO FREE */ /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */ /* CANNOT COMPLETE THE SHRINK. TO AVOID THE CRASH WE EXIT HERE. */ /*--------------------------------------------------------------*/ return; }//if }//if if (checkScanShrink(signal) == 1) { jam(); /*--------------------------------------------------------------*/ // A scan state was inconsistent with performing a shrink // operation. /*--------------------------------------------------------------*/ return; }//if if (fragrecptr.p->createLcp == ZTRUE) { if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_EXPAND) { jam(); /*--------------------------------------------------------------*/ // We did not have enough undo log buffers to start up an // shrink operation /*--------------------------------------------------------------*/ return; }//if }//if if (fragrecptr.p->p == 0) { jam(); fragrecptr.p->maxp = fragrecptr.p->maxp >> 1; fragrecptr.p->p = fragrecptr.p->maxp; fragrecptr.p->lhdirbits--; fragrecptr.p->hashcheckbit--; } else { jam(); fragrecptr.p->p--; }//if /*--------------------------------------------------------------------------*/ /* WE START BY FINDING THE NECESSARY INFORMATION OF THE BUCKET TO BE */ /* REMOVED WHICH WILL SEND ITS ELEMENTS TO THE RECEIVING BUCKET. */ /*--------------------------------------------------------------------------*/ expDirRangePtr.i = fragrecptr.p->directory; cexcPageindex = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) & ((1 << fragrecptr.p->k) - 1); texpDirInd = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) >> fragrecptr.p->k; texpDirRangeIndex = texpDirInd >> 8; texpDirPageIndex = texpDirInd & 0xff; ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange); arrGuard(texpDirRangeIndex, 256); expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex]; ptrCheckGuard(expDirptr, cdirarraysize, directoryarray); excPageptr.i = expDirptr.p->pagep[texpDirPageIndex]; fragrecptr.p->expSenderDirptr = expDirptr.i; fragrecptr.p->expSenderIndex = cexcPageindex; fragrecptr.p->expSenderPageptr = excPageptr.i; fragrecptr.p->expSenderDirIndex = texpDirInd; /*--------------------------------------------------------------------------*/ /* WE NOW PROCEED BY FINDING THE NECESSARY INFORMATION ABOUT THE */ /* RECEIVING BUCKET. */ /*--------------------------------------------------------------------------*/ expDirRangePtr.i = fragrecptr.p->directory; texpReceivedBucket = fragrecptr.p->p >> fragrecptr.p->k; ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange); arrGuard((texpReceivedBucket >> 8), 256); expDirptr.i = expDirRangePtr.p->dirArray[texpReceivedBucket >> 8]; ptrCheckGuard(expDirptr, cdirarraysize, directoryarray); fragrecptr.p->expReceivePageptr = expDirptr.p->pagep[texpReceivedBucket & 0xff]; fragrecptr.p->expReceiveIndex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1); fragrecptr.p->expReceiveForward = ZTRUE; if (excPageptr.i == RNIL) { jam(); endofshrinkbucketLab(signal); /* EMPTY BUCKET */ return; }//if /*--------------------------------------------------------------------------*/ /* INITIALISE THE VARIABLES FOR THE SHRINK PROCESS. */ /*--------------------------------------------------------------------------*/ ptrCheckGuard(excPageptr, cpagesize, page8); cexcForward = ZTRUE; cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS); cexcContainerptr = cexcContainerptr + ZHEAD_SIZE; arrGuard(cexcContainerptr, 2048); cexcContainerhead = excPageptr.p->word32[cexcContainerptr]; cexcContainerlen = cexcContainerhead >> 26; if (cexcContainerlen <= ZCON_HEAD_SIZE) { ndbrequire(cexcContainerlen == ZCON_HEAD_SIZE); } else { jam(); shrinkcontainer(signal); }//if /*--------------------------------------------------------------------------*/ /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */ /*--------------------------------------------------------------------------*/ if (((cexcContainerhead >> 10) & 1) == 1) { jam(); rlPageptr = excPageptr; trlPageindex = cexcPageindex; trlRelCon = ZFALSE; turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE); releaseRightlist(signal); }//if tshrTmp1 = ZCON_HEAD_SIZE; tshrTmp1 = tshrTmp1 << 26; if (fragrecptr.p->createLcp == ZTRUE) { jam(); datapageptr.p = excPageptr.p; cundoinfolength = 1; cundoElemIndex = cexcContainerptr; undoWritingProcess(signal); }//if dbgWord32(excPageptr, cexcContainerptr, tshrTmp1); arrGuard(cexcContainerptr, 2048); excPageptr.p->word32[cexcContainerptr] = tshrTmp1; if (((cexcContainerhead >> 7) & 0x3) == 0) { jam(); endofshrinkbucketLab(signal); return; }//if nextcontainerinfoExp(signal); do { cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS); if (cexcForward == ZTRUE) { jam(); cexcContainerptr = cexcContainerptr + ZHEAD_SIZE; } else { jam(); cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE; }//if arrGuard(cexcContainerptr, 2048); cexcContainerhead = excPageptr.p->word32[cexcContainerptr]; cexcContainerlen = cexcContainerhead >> 26; ndbrequire(cexcContainerlen > ZCON_HEAD_SIZE); /*--------------------------------------------------------------------------*/ /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */ /*--------------------------------------------------------------------------*/ shrinkcontainer(signal); cexcPrevpageptr = excPageptr.i; cexcPrevpageindex = cexcPageindex; cexcPrevforward = cexcForward; if (((cexcContainerhead >> 7) & 0x3) != 0) { jam(); /*--------------------------------------------------------------------------*/ /* WE MUST CALL THE NEXT CONTAINER INFO ROUTINE BEFORE WE RELEASE THE */ /* CONTAINER SINCE THE RELEASE WILL OVERWRITE THE NEXT POINTER. */ /*--------------------------------------------------------------------------*/ nextcontainerinfoExp(signal); }//if rlPageptr.i = cexcPrevpageptr; ptrCheckGuard(rlPageptr, cpagesize, page8); trlPageindex = cexcPrevpageindex; if (cexcPrevforward == ZTRUE) { jam(); if (((cexcContainerhead >> 10) & 1) == 1) { jam(); trlRelCon = ZFALSE; turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE); releaseRightlist(signal); }//if trlRelCon = ZTRUE; tullIndex = cexcContainerptr; releaseLeftlist(signal); } else { jam(); if (((cexcContainerhead >> 10) & 1) == 1) { jam(); trlRelCon = ZFALSE; tullIndex = cexcContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE); releaseLeftlist(signal); }//if trlRelCon = ZTRUE; turlIndex = cexcContainerptr; releaseRightlist(signal); }//if } while (((cexcContainerhead >> 7) & 0x3) != 0); endofshrinkbucketLab(signal); return; }//Dbacc::execSHRINKCHECK2() void Dbacc::endofshrinkbucketLab(Signal* signal) { fragrecptr.p->expandCounter--; fragrecptr.p->slack -= fragrecptr.p->maxloadfactor; if (fragrecptr.p->expSenderIndex == 0) { jam(); fragrecptr.p->dirsize--; if (fragrecptr.p->expSenderPageptr != RNIL) { jam(); rpPageptr.i = fragrecptr.p->expSenderPageptr; ptrCheckGuard(rpPageptr, cpagesize, page8); releasePage(signal); expDirptr.i = fragrecptr.p->expSenderDirptr; ptrCheckGuard(expDirptr, cdirarraysize, directoryarray); expDirptr.p->pagep[fragrecptr.p->expSenderDirIndex & 0xff] = RNIL; }//if if (((((fragrecptr.p->p + fragrecptr.p->maxp) + 1) >> fragrecptr.p->k) & 0xff) == 0) { jam(); rdDirptr.i = fragrecptr.p->expSenderDirptr; releaseDirectory(signal); expDirRangePtr.i = fragrecptr.p->directory; ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange); arrGuard((fragrecptr.p->expSenderDirIndex >> 8), 256); expDirRangePtr.p->dirArray[fragrecptr.p->expSenderDirIndex >> 8] = RNIL; }//if }//if if (fragrecptr.p->slack < (1u << 31)) { jam(); /*--------------------------------------------------------------*/ /* THE SLACK IS POSITIVE, IN THIS CASE WE WILL CHECK WHETHER */ /* WE WILL CONTINUE PERFORM ANOTHER SHRINK. */ /*--------------------------------------------------------------*/ Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p; Uint32 Thysteresis = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor; fragrecptr.p->slackCheck = noOfBuckets * Thysteresis; if (fragrecptr.p->slack > Thysteresis) { /*--------------------------------------------------------------*/ /* IT IS STILL NECESSARY TO SHRINK THE FRAGMENT MORE. THIS*/ /* CAN HAPPEN WHEN A NUMBER OF SHRINKS GET REJECTED */ /* DURING A LOCAL CHECKPOINT. WE START A NEW SHRINK */ /* IMMEDIATELY FROM HERE WITHOUT WAITING FOR A COMMIT TO */ /* START IT. */ /*--------------------------------------------------------------*/ if (fragrecptr.p->expandCounter > 0) { jam(); /*--------------------------------------------------------------*/ /* IT IS VERY IMPORTANT TO NOT TRY TO SHRINK MORE THAN */ /* WAS EXPANDED. IF MAXP IS SET TO A VALUE BELOW 63 THEN */ /* WE WILL LOSE RECORDS SINCE GETDIRINDEX CANNOT HANDLE */ /* SHRINKING BELOW 2^K - 1 (NOW 63). THIS WAS A BUG THAT */ /* WAS REMOVED 2000-05-12. */ /*--------------------------------------------------------------*/ signal->theData[0] = fragrecptr.i; signal->theData[1] = fragrecptr.p->p; signal->theData[2] = fragrecptr.p->maxp; signal->theData[3] = fragrecptr.p->expandFlag; ndbrequire(fragrecptr.p->expandFlag < 2); fragrecptr.p->expandFlag = 2; sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB); }//if }//if }//if ndbrequire(fragrecptr.p->maxp >= (Uint32)((1 << fragrecptr.p->k) - 1)); return; }//Dbacc::endofshrinkbucketLab() /* --------------------------------------------------------------------------------- */ /* SHRINKCONTAINER */ /* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */ /* CEXC_CONTAINERLEN (LENGTH OF THE CONTAINER). */ /* CEXC_CONTAINERPTR (ARRAY INDEX OF THE CONTAINER). */ /* CEXC_FORWARD (CONTAINER FORWARD (+1) OR BACKWARD (-1)) */ /* */ /* DESCRIPTION: ALL ELEMENTS OF THE ACTIVE CONTAINER HAVE TO MOVE TO THE NEW */ /* CONTAINER. */ /* --------------------------------------------------------------------------------- */ void Dbacc::shrinkcontainer(Signal* signal) { Uint32 tshrElementptr; Uint32 tshrRemLen; Uint32 tshrInc; Uint32 tshrKeyLen; Uint32 tshrTmp; Uint32 tshrIndex; Uint32 guard21; tshrRemLen = cexcContainerlen - ZCON_HEAD_SIZE; tshrKeyLen = fragrecptr.p->keyLength; if (tshrKeyLen == 0) { jam(); tshrKeyLen = ZACTIVE_LONG_KEY_LEN; }//if tshrInc = (ZELEM_HEAD_SIZE + tshrKeyLen) + fragrecptr.p->localkeylen; if (cexcForward == ZTRUE) { jam(); tshrElementptr = cexcContainerptr + ZCON_HEAD_SIZE; } else { jam(); tshrElementptr = cexcContainerptr - 1; }//if SHR_LOOP: idrOperationRecPtr.i = RNIL; ptrNull(idrOperationRecPtr); /* --------------------------------------------------------------------------------- */ /* THE CODE BELOW IS ALL USED TO PREPARE FOR THE CALL TO INSERT_ELEMENT AND */ /* HANDLE THE RESULT FROM INSERT_ELEMENT. INSERT_ELEMENT INSERTS THE ELEMENT */ /* INTO ANOTHER BUCKET. */ /* --------------------------------------------------------------------------------- */ arrGuard(tshrElementptr, 2048); tidrElemhead = excPageptr.p->word32[tshrElementptr]; if (ElementHeader::getLocked(tidrElemhead)) { jam(); /* --------------------------------------------------------------------------------- */ /* IF THE ELEMENT IS LOCKED WE MUST UPDATE THE ELEMENT INFO IN THE OPERATION */ /* RECORD OWNING THE LOCK. WE DO THIS BY READING THE OPERATION RECORD POINTER */ /* FROM THE ELEMENT HEADER. */ /* --------------------------------------------------------------------------------- */ idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead); ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec); if (fragrecptr.p->createLcp == ZTRUE) { jam(); /* --------------------------------------------------------------------------------- */ // During local checkpoints we must ensure that we restore the element header in // unlocked state and with the hash value part there with tuple status zeroed. // Otherwise a later insert over the same element will write an UNDO log that will // ensure that the now removed element is restored together with its locked element // header and without the hash value part. /* --------------------------------------------------------------------------------- */ const Uint32 hv = idrOperationRecPtr.p->hashvaluePart; const Uint32 eh = ElementHeader::setUnlocked(hv, 0); excPageptr.p->word32[tshrElementptr] = eh; }//if }//if tshrTmp = tshrElementptr + cexcForward; guard21 = fragrecptr.p->localkeylen - 1; for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) { arrGuard(tshrIndex, 2); arrGuard(tshrTmp, 2048); clocalkey[tshrIndex] = excPageptr.p->word32[tshrTmp]; tshrTmp = tshrTmp + cexcForward; }//for guard21 = tshrKeyLen - 1; for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) { arrGuard(tshrIndex, 2048); arrGuard(tshrTmp, 2048); ckeys[tshrIndex] = excPageptr.p->word32[tshrTmp]; tshrTmp = tshrTmp + cexcForward; }//for tidrPageindex = fragrecptr.p->expReceiveIndex; idrPageptr.i = fragrecptr.p->expReceivePageptr; ptrCheckGuard(idrPageptr, cpagesize, page8); tidrForward = fragrecptr.p->expReceiveForward; tidrKeyLen = tshrKeyLen; insertElement(signal); /* --------------------------------------------------------------------------------- */ /* TAKE CARE OF RESULT FROM INSERT_ELEMENT. */ /* --------------------------------------------------------------------------------- */ fragrecptr.p->expReceiveIndex = tidrPageindex; fragrecptr.p->expReceivePageptr = idrPageptr.i; fragrecptr.p->expReceiveForward = tidrForward; if (tshrRemLen < tshrInc) { jam(); sendSystemerror(signal); }//if tshrRemLen = tshrRemLen - tshrInc; if (tshrRemLen != 0) { jam(); tshrElementptr = tshrTmp; goto SHR_LOOP; }//if }//Dbacc::shrinkcontainer() /* --------------------------------------------------------------------------------- */ /* NEXTCONTAINERINFO_EXP */ /* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */ /* ABOUT NEXT CONTAINER IN THE BUCKET. */ /* INPUT: CEXC_CONTAINERHEAD */ /* CEXC_CONTAINERPTR */ /* EXC_PAGEPTR */ /* OUTPUT: */ /* CEXC_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED. */ /* EXC_PAGEPTR (PAGE REFERENCE OF NEXT CONTAINER) */ /* CEXC_FORWARD */ /* --------------------------------------------------------------------------------- */ void Dbacc::nextcontainerinfoExp(Signal* signal) { tnciNextSamePage = (cexcContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */ /* THE NEXT CONTAINER IS IN THE SAME PAGE */ cexcPageindex = cexcContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */ if (((cexcContainerhead >> 7) & 3) == ZLEFT) { jam(); cexcForward = ZTRUE; } else if (((cexcContainerhead >> 7) & 3) == ZRIGHT) { jam(); cexcForward = cminusOne; } else { jam(); sendSystemerror(signal); cexcForward = 0; /* DUMMY FOR COMPILER */ }//if if (tnciNextSamePage == ZFALSE) { jam(); /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */ arrGuard(cexcContainerptr + 1, 2048); tnciTmp = excPageptr.p->word32[cexcContainerptr + 1]; nciOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange); arrGuard((tnciTmp >> 8), 256); nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8]; ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray); excPageptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff]; ptrCheckGuard(excPageptr, cpagesize, page8); }//if }//Dbacc::nextcontainerinfoExp() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF EXPAND/SHRINK MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* LOCAL CHECKPOINT MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* LCP_FRAGIDREQ */ /* SENDER: LQH, LEVEL B */ /* ENTER LCP_FRAGIDREQ WITH */ /* TUSERPTR LQH CONNECTION PTR */ /* TUSERBLOCKREF, LQH BLOCK REFERENCE */ /* TCHECKPOINTID, THE CHECKPOINT NUMBER TO USE */ /* (E.G. 1,2 OR 3) */ /* TABPTR, TABLE ID = TABLE RECORD POINTER */ /* TFID ROOT FRAGMENT ID */ /* CACTIVE_UNDO_FILE_VERSION UNDO FILE VERSION 0,1,2 OR 3. */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* LCP_FRAGIDREQ REQUEST FOR LIST OF STOPED OPERATION */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execLCP_FRAGIDREQ(Signal* signal) { jamEntry(); tuserptr = signal->theData[0]; /* LQH CONNECTION PTR */ tuserblockref = signal->theData[1]; /* LQH BLOCK REFERENCE */ tcheckpointid = signal->theData[2]; /* THE CHECKPOINT NUMBER TO USE */ /* (E.G. 1,2 OR 3) */ tabptr.i = signal->theData[3]; /* TABLE ID = TABLE RECORD POINTER */ ptrCheck(tabptr, ctablesize, tabrec); tfid = signal->theData[4]; /* ROOT FRAGMENT ID */ cactiveUndoFileVersion = signal->theData[5]; /* UNDO FILE VERSION 0,1,2 OR 3. */ tresult = 0; ndbrequire(getrootfragmentrec(signal, rootfragrecptr, tfid)); ndbrequire(rootfragrecptr.p->rootState == ACTIVEROOT); seizeLcpConnectRec(signal); initLcpConnRec(signal); lcpConnectptr.p->rootrecptr = rootfragrecptr.i; rootfragrecptr.p->lcpPtr = lcpConnectptr.i; lcpConnectptr.p->localCheckPid = tcheckpointid; lcpConnectptr.p->lcpstate = LCP_ACTIVE; rootfragrecptr.p->rootState = LCP_CREATION; fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; /* D6 AT FSOPENREQ =#010003FF. */ tlfrTmp1 = 0x010003ff; /* FILE TYPE = .DATA ,VERSION OF FILENAME = 1 */ tlfrTmp2 = 0x301; /* D7 CREATE, WRITE ONLY, TRUNCATE TO ZERO */ ndbrequire(cfsFirstfreeconnect != RNIL); seizeFsConnectRec(signal); fsConnectptr.p->fragrecPtr = fragrecptr.i; fsConnectptr.p->fsState = WAIT_OPEN_DATA_FILE_FOR_WRITE; /* ----------- FILENAME (FILESYSTEM)/D3/DBACC/"T"TABID/"F"FRAGID/"S"VERSIONID.DATA ------------ */ /* ************************ */ /* FSOPENREQ */ /* ************************ */ signal->theData[0] = cownBlockref; signal->theData[1] = fsConnectptr.i; signal->theData[2] = tabptr.i; /* TABLE IDENTITY */ signal->theData[3] = rootfragrecptr.p->fragmentid[0]; /* FRAGMENT IDENTITY */ signal->theData[4] = lcpConnectptr.p->localCheckPid; /* CHECKPOINT ID */ signal->theData[5] = tlfrTmp1; signal->theData[6] = tlfrTmp2; sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA); return; }//Dbacc::execLCP_FRAGIDREQ() /* ******************--------------------------------------------------------------- */ /* FSOPENCONF OPENFILE CONF */ /* SENDER: FS, LEVEL B */ /* ENTER FSOPENCONF WITH */ /* FS_CONNECTPTR, FS_CONNECTION PTR */ /* TUSERPOINTER, FILE POINTER */ /* ******************--------------------------------------------------------------- */ void Dbacc::lcpFsOpenConfLab(Signal* signal) { fsConnectptr.p->fsPtr = tuserptr; fragrecptr.i = fsConnectptr.p->fragrecPtr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); rootfragrecptr.i = fragrecptr.p->myroot; fragrecptr.p->activeDataFilePage = 1; /* ZERO IS KEPT FOR PAGE_ZERO */ fragrecptr.p->fsConnPtr = fsConnectptr.i; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); if (rootfragrecptr.p->fragmentptr[0] == fragrecptr.i) { jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[1]; ptrCheck(fragrecptr, cfragmentsize, fragmentrec); /* ----------- FILENAME (FILESYSTEM)/D3/DBACC/"T"TABID/"F"FRAGID/"S"VERSIONID.DATA ------------ */ /* D6 AT FSOPENREQ =#010003FF. */ tlfrTmp1 = 0x010003ff; /* FILE TYPE = .DATA ,VERSION OF FILENAME = 1 */ tlfrTmp2 = 0x301; /* D7 CREATE, WRITE ONLY, TRUNCATE TO ZERO */ ndbrequire(cfsFirstfreeconnect != RNIL); seizeFsConnectRec(signal); fsConnectptr.p->fragrecPtr = fragrecptr.i; fsConnectptr.p->fsState = WAIT_OPEN_DATA_FILE_FOR_WRITE; /* ************************ */ /* FSOPENREQ */ /* ************************ */ signal->theData[0] = cownBlockref; signal->theData[1] = fsConnectptr.i; signal->theData[2] = rootfragrecptr.p->mytabptr; /* TABLE IDENTITY */ signal->theData[3] = rootfragrecptr.p->fragmentid[1]; /* FRAGMENT IDENTITY */ signal->theData[4] = lcpConnectptr.p->localCheckPid; /* CHECKPOINT ID */ signal->theData[5] = tlfrTmp1; signal->theData[6] = tlfrTmp2; sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA); return; } else { ndbrequire(rootfragrecptr.p->fragmentptr[1] == fragrecptr.i); }//if /*---- BOTH DATA FILES ARE OPEN------*/ /* ----IF THE UNDO FILE IS CLOSED , OPEN IT.----- */ if (cactiveOpenUndoFsPtr != RNIL) { jam(); sendLcpFragidconfLab(signal); return; }//if cactiveUndoFilePage = 0; cprevUndoaddress = cminusOne; cundoposition = 0; clastUndoPageIdWritten = 0; ndbrequire(cfsFirstfreeconnect != RNIL); seizeFsConnectRec(signal); fsConnectptr.p->fsState = WAIT_OPEN_UNDO_LCP; fsConnectptr.p->fsPart = 0; /* FILE INDEX, SECOND FILE IN THE DIRECTORY */ cactiveOpenUndoFsPtr = fsConnectptr.i; cactiveRootfrag = rootfragrecptr.i; tlfrTmp1 = 1; /* FILE VERSION */ tlfrTmp1 = (tlfrTmp1 << 8) + ZLOCALLOGFILE; /* .LOCLOG = 2 */ tlfrTmp1 = (tlfrTmp1 << 8) + 4; /* ROOT DIRECTORY = D4 */ tlfrTmp1 = (tlfrTmp1 << 8) + fsConnectptr.p->fsPart; /* P2 */ tlfrTmp2 = 0x302; /* D7 CREATE , READ / WRITE , TRUNCATE TO ZERO */ /* ---FILE NAME "D4"/"DBACC"/LCP_CONNECTPTR:LOCAL_CHECK_PID/FS_CONNECTPTR:FS_PART".LOCLOG-- */ /* ************************ */ /* FSOPENREQ */ /* ************************ */ signal->theData[0] = cownBlockref; signal->theData[1] = fsConnectptr.i; signal->theData[2] = cminusOne; /* #FFFFFFFF */ signal->theData[3] = cminusOne; /* #FFFFFFFF */ signal->theData[4] = cactiveUndoFileVersion; /* A GROUP OF UNDO FILES WHICH ARE UPDATED */ signal->theData[5] = tlfrTmp1; signal->theData[6] = tlfrTmp2; sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA); return; }//Dbacc::lcpFsOpenConfLab() void Dbacc::lcpOpenUndofileConfLab(Signal* signal) { ptrGuard(fsConnectptr); fsConnectptr.p->fsState = WAIT_NOTHING; rootfragrecptr.i = cactiveRootfrag; ptrCheck(rootfragrecptr, crootfragmentsize, rootfragmentrec); fsConnectptr.p->fsPtr = tuserptr; sendLcpFragidconfLab(signal); return; }//Dbacc::lcpOpenUndofileConfLab() void Dbacc::sendLcpFragidconfLab(Signal* signal) { ptrGuard(rootfragrecptr); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); /* ************************ */ /* LCP_FRAGIDCONF */ /* ************************ */ signal->theData[0] = lcpConnectptr.p->lcpUserptr; signal->theData[1] = lcpConnectptr.i; signal->theData[2] = 2; /* NO OF LOCAL FRAGMENTS */ signal->theData[3] = rootfragrecptr.p->fragmentid[0]; signal->theData[4] = rootfragrecptr.p->fragmentid[1]; signal->theData[5] = RNIL; signal->theData[6] = RNIL; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_LCP_FRAGIDCONF, signal, 7, JBB); return; }//Dbacc::sendLcpFragidconfLab() /* ******************--------------------------------------------------------------- */ /* LCP_HOLDOPERATION REQUEST FOR LIST OF STOPED OPERATION */ /* SENDER: LQH, LEVEL B */ /* ENTER LCP_HOLDOPREQ WITH */ /* LCP_CONNECTPTR CONNECTION POINTER */ /* TFID, LOCAL FRAGMENT ID */ /* THOLD_PREV_SENT_OP NR OF SENT OPERATIONS AT */ /* PREVIOUS SIGNALS */ /* TLQH_POINTER LQH USER POINTER */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* LCP_HOLDOPERATION REQUEST FOR LIST OF STOPED OPERATION */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execLCP_HOLDOPREQ(Signal* signal) { Uint32 tholdPrevSentOp; jamEntry(); lcpConnectptr.i = signal->theData[0]; /* CONNECTION POINTER */ tfid = signal->theData[1]; /* LOCAL FRAGMENT ID */ tholdPrevSentOp = signal->theData[2]; /* NR OF SENT OPERATIONS AT */ /* PREVIOUS SIGNALS */ tlqhPointer = signal->theData[3]; /* LQH USER POINTER */ tresult = 0; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE); rootfragrecptr.i = lcpConnectptr.p->rootrecptr; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); if (rootfragrecptr.p->fragmentid[0] == tfid) { jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); } else { ndbrequire(rootfragrecptr.p->fragmentid[1] == tfid); jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[1]; }//if ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); fragrecptr.p->lcpLqhPtr = tlqhPointer; if (tholdPrevSentOp != 0) { ndbrequire(fragrecptr.p->fragState == SEND_QUE_OP); } else if (tholdPrevSentOp == 0) { jam(); fragrecptr.p->fragState = SEND_QUE_OP; fragrecptr.p->stopQueOp = ZTRUE; fragrecptr.p->sentWaitInQueOp = fragrecptr.p->firstWaitInQueOp; }//if tholdSentOp = 0; /* NR OF OPERATION WHICH ARE SENT THIS TIME */ operationRecPtr.i = fragrecptr.p->sentWaitInQueOp; /* --------------------------------------------- */ /* GO THROUGH ALL OPERATION IN THE WAIT */ /* LIST AND SEND THE LQH CONNECTION PTR OF THE */ /* OPERATIONS TO THE LQH BLOCK. MAX 23 0PERATION */ /* PER SIGNAL */ /* --------------------------------------------- */ while (operationRecPtr.i != RNIL) { jam(); ptrCheckGuard(operationRecPtr, coprecsize, operationrec); ckeys[tholdSentOp] = operationRecPtr.p->userptr; operationRecPtr.i = operationRecPtr.p->nextQueOp; tholdSentOp++; if ((tholdSentOp >= 23) && (operationRecPtr.i != RNIL)) { jam(); /* ----------------------------------------------- */ /* THERE IS MORE THAN 23 WAIT OPERATION. WE */ /* HAVE TO SEND THESE 23 AND WAITE FOR NEXT SIGNAL */ /* ----------------------------------------------- */ tholdMore = ZTRUE; /* SECOUND DATA AT THE CONF SIGNAL , = MORE */ fragrecptr.p->sentWaitInQueOp = operationRecPtr.i; sendholdconfsignalLab(signal); return; }//if }//while /* ----------------------------------------------- */ /* OPERATION_REC_PTR = RNIL */ /* THERE IS NO MORE WAITING OPERATION, STATE OF */ /* THE FRAGMENT RRECORD IS CHANGED AND RETURN */ /* SIGNAL IS SENT */ /* ----------------------------------------------- */ fragrecptr.p->sentWaitInQueOp = RNIL; tholdMore = ZFALSE; /* SECOND DATA AT THE CONF SIGNAL , = NOT MORE */ fragrecptr.p->fragState = WAIT_ACC_LCPREQ; sendholdconfsignalLab(signal); return; }//Dbacc::execLCP_HOLDOPREQ() void Dbacc::sendholdconfsignalLab(Signal* signal) { tholdMore = (tholdMore << 16) + tholdSentOp; /* SECOND SIGNAL DATA, LENGTH + MORE */ /* ************************ */ /* LCP_HOLDOPCONF */ /* ************************ */ signal->theData[0] = fragrecptr.p->lcpLqhPtr; signal->theData[1] = tholdMore; signal->theData[2] = ckeys[0]; signal->theData[3] = ckeys[1]; signal->theData[4] = ckeys[2]; signal->theData[5] = ckeys[3]; signal->theData[6] = ckeys[4]; signal->theData[7] = ckeys[5]; signal->theData[8] = ckeys[6]; signal->theData[9] = ckeys[7]; signal->theData[10] = ckeys[8]; signal->theData[11] = ckeys[9]; signal->theData[12] = ckeys[10]; signal->theData[13] = ckeys[11]; signal->theData[14] = ckeys[12]; signal->theData[15] = ckeys[13]; signal->theData[16] = ckeys[14]; signal->theData[17] = ckeys[15]; signal->theData[18] = ckeys[16]; signal->theData[19] = ckeys[17]; signal->theData[20] = ckeys[18]; signal->theData[21] = ckeys[19]; signal->theData[22] = ckeys[20]; signal->theData[23] = ckeys[21]; signal->theData[24] = ckeys[22]; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_LCP_HOLDOPCONF, signal, 25, JBA); return; }//Dbacc::sendholdconfsignalLab() /** * execACC_LCPREQ * Perform local checkpoint of a fragment * * SENDER: LQH, LEVEL B * ENTER ACC_LCPREQ WITH * LCP_CONNECTPTR, OPERATION RECORD PTR * TLCP_LQH_CHECK_V, LQH'S LOCAL FRAG CHECK VALUE * TLCP_LOCAL_FRAG_ID, LOCAL FRAG ID * */ void Dbacc::execACC_LCPREQ(Signal* signal) { Uint32 tlcpLocalFragId; Uint32 tlcpLqhCheckV; jamEntry(); lcpConnectptr.i = signal->theData[0]; // CONNECTION PTR tlcpLqhCheckV = signal->theData[1]; // LQH'S LOCAL FRAG CHECK VALUE tlcpLocalFragId = signal->theData[2]; // LOCAL FRAG ID tresult = 0; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE); rootfragrecptr.i = lcpConnectptr.p->rootrecptr; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); if (rootfragrecptr.p->fragmentid[0] == tlcpLocalFragId) { jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; } else { ndbrequire(rootfragrecptr.p->fragmentid[1] == tlcpLocalFragId); jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[1]; }//if ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); ndbrequire(fragrecptr.p->fragState == WAIT_ACC_LCPREQ); fragrecptr.p->lcpLqhPtr = tlcpLqhCheckV; Page8Ptr zeroPagePtr; seizeLcpPage(zeroPagePtr); fragrecptr.p->zeroPagePtr = zeroPagePtr.i; fragrecptr.p->prevUndoposition = cminusOne; initRootFragPageZero(rootfragrecptr, zeroPagePtr); initFragPageZero(fragrecptr, zeroPagePtr); /*-----------------------------------------------------------------*/ /* SEIZE ZERO PAGE FIRST AND THEN SEIZE DATA PAGES IN */ /* BACKWARDS ORDER. THIS IS TO ENSURE THAT WE GET THE PAGES */ /* IN ORDER. ON WINDOWS NT THIS WILL BE A BENEFIT SINCE WE */ /* CAN THEN DO 1 WRITE_FILE INSTEAD OF 8. */ /* WHEN WE RELEASE THE PAGES WE RELEASE THEM IN THE OPPOSITE */ /* ORDER. */ /*-----------------------------------------------------------------*/ for (Uint32 taspTmp = ZWRITEPAGESIZE - 1; (Uint32)~taspTmp; taspTmp--) { Page8Ptr dataPagePtr; jam(); ndbrequire(fragrecptr.p->datapages[taspTmp] == RNIL); seizeLcpPage(dataPagePtr); fragrecptr.p->datapages[taspTmp] = dataPagePtr.i; }//for fragrecptr.p->lcpMaxDirIndex = fragrecptr.p->dirsize; fragrecptr.p->lcpMaxOverDirIndex = fragrecptr.p->lastOverIndex; fragrecptr.p->createLcp = ZTRUE; operationRecPtr.i = fragrecptr.p->lockOwnersList; lcp_write_op_to_undolog(signal); } void Dbacc::lcp_write_op_to_undolog(Signal* signal) { bool delay_continueb= false; Uint32 i, j; for (i= 0; i < 16; i++) { jam(); if (remainingUndoPages() <= ZMIN_UNDO_PAGES_AT_COMMIT) { jam(); delay_continueb= true; break; } for (j= 0; j < 32; j++) { if (operationRecPtr.i == RNIL) { jam(); break; } jam(); ptrCheckGuard(operationRecPtr, coprecsize, operationrec); if ((operationRecPtr.p->operation == ZINSERT) || (operationRecPtr.p->elementIsDisappeared == ZTRUE)){ /******************************************************************* * Only log inserts and elements that are marked as dissapeared. * All other operations update the element header and that is handled * when pages are written to disk ********************************************************************/ undopageptr.i = (cundoposition>>ZUNDOPAGEINDEXBITS) & (cundopagesize-1); ptrAss(undopageptr, undopage); theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; tundoindex = theadundoindex + ZUNDOHEADSIZE; writeUndoOpInfo(signal);/* THE INFORMATION ABOUT ELEMENT HEADER, STORED*/ /* IN OP REC, IS WRITTEN AT UNDO PAGES */ cundoElemIndex = 0;/* DEFAULT VALUE USED BY WRITE_UNDO_HEADER SUBROTINE */ writeUndoHeader(signal, RNIL, UndoHeader::ZOP_INFO); /* WRITE THE HEAD OF THE UNDO ELEMENT */ checkUndoPages(signal); /* SEND UNDO PAGE TO DISK WHEN A GROUP OF */ /* UNDO PAGES,CURRENTLY 8, IS FILLED */ } operationRecPtr.i = operationRecPtr.p->nextLockOwnerOp; } if (operationRecPtr.i == RNIL) { jam(); break; } } if (operationRecPtr.i != RNIL) { jam(); signal->theData[0]= ZLCP_OP_WRITE_RT_BREAK; signal->theData[1]= operationRecPtr.i; signal->theData[2]= fragrecptr.i; signal->theData[3]= lcpConnectptr.i; if (delay_continueb) { jam(); sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 10, 4); } else { jam(); sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB); } return; } signal->theData[0] = fragrecptr.p->lcpLqhPtr; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_LCPSTARTED, signal, 1, JBA); fragrecptr.p->activeDataPage = 0; fragrecptr.p->lcpDirIndex = 0; fragrecptr.p->fragState = LCP_SEND_PAGES; signal->theData[0] = lcpConnectptr.i; signal->theData[1] = fragrecptr.i; sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB); } /* ******************--------------------------------------------------------------- */ /* ACC_SAVE_PAGES A GROUP OF PAGES IS ALLOCATED. THE PAGES AND OVERFLOW */ /* PAGES OF THE FRAGMENT ARE COPIED IN THEM AND IS SEND TO */ /* THE DATA FILE OF THE CHECK POINT. */ /* SENDER: ACC, LEVEL B */ /* ENTER ACC_SAVE_PAGES WITH */ /* LCP_CONNECTPTR, CONNECTION RECORD PTR */ /* FRAGRECPTR FRAGMENT RECORD PTR */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACC_SAVE_PAGES REQUEST TO SEND THE PAGE TO DISK */ /* ******************------------------------------+ UNDO PAGES */ /* SENDER: ACC, LEVEL B */ void Dbacc::execACC_SAVE_PAGES(Signal* signal) { jamEntry(); lcpConnectptr.i = signal->theData[0]; /* CONNECTION RECORD PTR */ fragrecptr.i = signal->theData[1]; /* FRAGMENT RECORD PTR */ tresult = 0; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); if (lcpConnectptr.p->lcpstate != LCP_ACTIVE) { jam(); sendSystemerror(signal); return; }//if if (ERROR_INSERTED(3000)) { ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); if (rootfragrecptr.p->mytabptr == c_errorInsert3000_TableId){ ndbout << "Delay writing of datapages" << endl; // Delay writing of pages jam(); sendSignalWithDelay(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 1000, 2); return; } } if (clblPageCounter == 0) { jam(); signal->theData[0] = lcpConnectptr.i; signal->theData[1] = fragrecptr.i; sendSignalWithDelay(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 100, 2); return; } else { jam(); clblPageCounter = clblPageCounter - 1; }//if ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (fragrecptr.p->fragState == LCP_SEND_PAGES) { jam(); savepagesLab(signal); return; } else { if (fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) { jam(); saveOverPagesLab(signal); return; } else { ndbrequire(fragrecptr.p->fragState == LCP_SEND_ZERO_PAGE); jam(); saveZeroPageLab(signal); return; }//if }//if }//Dbacc::execACC_SAVE_PAGES() void Dbacc::savepagesLab(Signal* signal) { DirRangePtr spDirRangePtr; DirectoryarrayPtr spDirptr; Page8Ptr aspPageptr; Page8Ptr aspCopyPageptr; Uint32 taspDirindex; Uint32 taspDirIndex; Uint32 taspIndex; if ((fragrecptr.p->lcpDirIndex >= fragrecptr.p->dirsize) || (fragrecptr.p->lcpDirIndex >= fragrecptr.p->lcpMaxDirIndex)) { jam(); endsavepageLab(signal); return; }//if /* SOME EXPAND PROCESSES HAVE BEEN PERFORMED. */ /* THE ADDED PAGE ARE NOT SENT TO DISK */ arrGuard(fragrecptr.p->activeDataPage, 8); aspCopyPageptr.i = fragrecptr.p->datapages[fragrecptr.p->activeDataPage]; ptrCheckGuard(aspCopyPageptr, cpagesize, page8); taspDirindex = fragrecptr.p->lcpDirIndex; /* DIRECTORY OF ACTIVE PAGE */ spDirRangePtr.i = fragrecptr.p->directory; taspDirIndex = taspDirindex >> 8; taspIndex = taspDirindex & 0xff; ptrCheckGuard(spDirRangePtr, cdirrangesize, dirRange); arrGuard(taspDirIndex, 256); spDirptr.i = spDirRangePtr.p->dirArray[taspDirIndex]; ptrCheckGuard(spDirptr, cdirarraysize, directoryarray); aspPageptr.i = spDirptr.p->pagep[taspIndex]; ptrCheckGuard(aspPageptr, cpagesize, page8); ndbrequire(aspPageptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->lcpDirIndex); lcnPageptr = aspPageptr; lcnCopyPageptr = aspCopyPageptr; lcpCopyPage(signal); fragrecptr.p->lcpDirIndex++; fragrecptr.p->activeDataPage++; if (fragrecptr.p->activeDataPage < ZWRITEPAGESIZE) { jam(); signal->theData[0] = lcpConnectptr.i; signal->theData[1] = fragrecptr.i; sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB); return; }//if senddatapagesLab(signal); return; }//Dbacc::savepagesLab() /* FRAGRECPTR:ACTIVE_DATA_PAGE = ZWRITEPAGESIZE */ /* SEND A GROUP OF PAGES TO DISK */ void Dbacc::senddatapagesLab(Signal* signal) { fsConnectptr.i = fragrecptr.p->fsConnPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); seizeFsOpRec(signal); initFsOpRec(signal); fsOpptr.p->fsOpstate = WAIT_WRITE_DATA; ndbrequire(fragrecptr.p->activeDataPage <= 8); for (Uint32 i = 0; i < fragrecptr.p->activeDataPage; i++) { signal->theData[i + 6] = fragrecptr.p->datapages[i]; }//for signal->theData[fragrecptr.p->activeDataPage + 6] = fragrecptr.p->activeDataFilePage; signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsOpptr.i; signal->theData[3] = 0x2; signal->theData[4] = ZPAGE8_BASE_ADD; signal->theData[5] = fragrecptr.p->activeDataPage; sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 15, JBA); return; }//Dbacc::senddatapagesLab() void Dbacc::endsavepageLab(Signal* signal) { Page8Ptr espPageidptr; espPageidptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(espPageidptr, cpagesize, page8); dbgWord32(espPageidptr, ZPAGEZERO_NO_PAGES, fragrecptr.p->lcpDirIndex); espPageidptr.p->word32[ZPAGEZERO_NO_PAGES] = fragrecptr.p->lcpDirIndex; fragrecptr.p->fragState = LCP_SEND_OVER_PAGES; fragrecptr.p->noOfStoredOverPages = 0; fragrecptr.p->lcpDirIndex = 0; saveOverPagesLab(signal); return; }//Dbacc::endsavepageLab() /* ******************--------------------------------------------------------------- */ /* ACC_SAVE_OVER_PAGES CONTINUE SAVING THE LEFT OVERPAGES. */ /* ******************--------------------------------------------------------------- */ void Dbacc::saveOverPagesLab(Signal* signal) { DirRangePtr sopDirRangePtr; DirectoryarrayPtr sopOverflowDirptr; Page8Ptr sopPageptr; Page8Ptr sopCopyPageptr; Uint32 tsopDirindex; Uint32 tsopDirInd; Uint32 tsopIndex; if ((fragrecptr.p->lcpDirIndex >= fragrecptr.p->lastOverIndex) || (fragrecptr.p->lcpDirIndex >= fragrecptr.p->lcpMaxOverDirIndex)) { jam(); endsaveoverpageLab(signal); return; }//if arrGuard(fragrecptr.p->activeDataPage, 8); sopCopyPageptr.i = fragrecptr.p->datapages[fragrecptr.p->activeDataPage]; ptrCheckGuard(sopCopyPageptr, cpagesize, page8); tsopDirindex = fragrecptr.p->lcpDirIndex; sopDirRangePtr.i = fragrecptr.p->overflowdir; tsopDirInd = tsopDirindex >> 8; tsopIndex = tsopDirindex & 0xff; ptrCheckGuard(sopDirRangePtr, cdirrangesize, dirRange); arrGuard(tsopDirInd, 256); sopOverflowDirptr.i = sopDirRangePtr.p->dirArray[tsopDirInd]; ptrCheckGuard(sopOverflowDirptr, cdirarraysize, directoryarray); sopPageptr.i = sopOverflowDirptr.p->pagep[tsopIndex]; fragrecptr.p->lcpDirIndex++; if (sopPageptr.i != RNIL) { jam(); ptrCheckGuard(sopPageptr, cpagesize, page8); ndbrequire(sopPageptr.p->word32[ZPOS_PAGE_ID] == tsopDirindex); ndbrequire(((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZNORMAL_PAGE_TYPE); lcnPageptr = sopPageptr; lcnCopyPageptr = sopCopyPageptr; lcpCopyPage(signal); fragrecptr.p->noOfStoredOverPages++; fragrecptr.p->activeDataPage++; if ((sopPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0)) { //ndbrequire(((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZOVERFLOW_PAGE_TYPE); if (((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZOVERFLOW_PAGE_TYPE) { /*--------------------------------------------------------------------------------*/ /* THE PAGE IS EMPTY AND WAITING TO BE RELEASED. IT COULD NOT BE RELEASED */ /* EARLIER SINCE IT WAS PART OF A LOCAL CHECKPOINT. */ /*--------------------------------------------------------------------------------*/ jam(); ropPageptr = sopPageptr; releaseOverpage(signal); } else if (((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZLONG_PAGE_TYPE) { //---------------------------------------------------------------------- // The long key page is empty, release it. //---------------------------------------------------------------------- jam(); rlopPageptr = sopPageptr; releaseLongPage(signal); } else { jam(); sendSystemerror(signal); } }//if } if (fragrecptr.p->activeDataPage == ZWRITEPAGESIZE) { jam(); senddatapagesLab(signal); return; }//if signal->theData[0] = lcpConnectptr.i; signal->theData[1] = fragrecptr.i; sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB); return; }//Dbacc::saveOverPagesLab() void Dbacc::endsaveoverpageLab(Signal* signal) { Page8Ptr esoPageidptr; esoPageidptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(esoPageidptr, cpagesize, page8); dbgWord32(esoPageidptr, ZPAGEZERO_NO_OVER_PAGE, fragrecptr.p->noOfStoredOverPages); esoPageidptr.p->word32[ZPAGEZERO_NO_OVER_PAGE] = fragrecptr.p->noOfStoredOverPages; fragrecptr.p->fragState = LCP_SEND_ZERO_PAGE; if (fragrecptr.p->activeDataPage != 0) { jam(); senddatapagesLab(signal); /* SEND LEFT PAGES TO DISK */ return; }//if saveZeroPageLab(signal); return; }//Dbacc::endsaveoverpageLab() /* ******************--------------------------------------------------------------- */ /* ACC_SAVE_ZERO_PAGE PAGE ZERO IS SENT TO DISK.IT IS THE LAST STAGE AT THE */ /* CREATION LCP. ACC_LCPCONF IS RETURND. */ /* ******************--------------------------------------------------------------- */ void Dbacc::saveZeroPageLab(Signal* signal) { Page8Ptr szpPageidptr; Uint32 Tchs; Uint32 Ti; fragrecptr.p->createLcp = ZFALSE; fsConnectptr.i = fragrecptr.p->fsConnPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); szpPageidptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(szpPageidptr, cpagesize, page8); dbgWord32(szpPageidptr, ZPAGEZERO_PREV_UNDOP, fragrecptr.p->prevUndoposition); szpPageidptr.p->word32[ZPAGEZERO_PREV_UNDOP] = fragrecptr.p->prevUndoposition; dbgWord32(szpPageidptr, ZPAGEZERO_NEXT_UNDO_FILE, cactiveUndoFileVersion); szpPageidptr.p->word32[ZPAGEZERO_NEXT_UNDO_FILE] = cactiveUndoFileVersion; fragrecptr.p->fragState = WAIT_ZERO_PAGE_STORED; /* --------------------------------------------------------------------------------- */ // Calculate the checksum and store it for the zero page of the fragment. /* --------------------------------------------------------------------------------- */ szpPageidptr.p->word32[ZPOS_CHECKSUM] = 0; Tchs = 0; for (Ti = 0; Ti < 2048; Ti++) { Tchs = Tchs ^ szpPageidptr.p->word32[Ti]; }//for szpPageidptr.p->word32[ZPOS_CHECKSUM] = Tchs; dbgWord32(szpPageidptr, ZPOS_CHECKSUM, Tchs); seizeFsOpRec(signal); initFsOpRec(signal); fsOpptr.p->fsOpstate = WAIT_WRITE_DATA; if (clblPageCounter > 0) { jam(); clblPageCounter = clblPageCounter - 1; } else { jam(); clblPageOver = clblPageOver + 1; }//if /* ************************ */ /* FSWRITEREQ */ /* ************************ */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsOpptr.i; signal->theData[3] = 0x10; /* FLAG = LIST MEM PAGES, LIST FILE PAGES */ /* SYNC FILE AFTER WRITING */ signal->theData[4] = ZPAGE8_BASE_ADD; signal->theData[5] = 1; /* NO OF PAGES */ signal->theData[6] = fragrecptr.p->zeroPagePtr; /* ZERO PAGE */ signal->theData[7] = 0; sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA); /* ZERO PAGE AT DATA FILE */ return; }//Dbacc::saveZeroPageLab() /* ******************--------------------------------------------------------------- */ /* FSWRITECONF OPENFILE CONF */ /* ENTER FSWRITECONF WITH SENDER: FS, LEVEL B */ /* FS_OPPTR FS_CONNECTION PTR */ /* ******************--------------------------------------------------------------- */ void Dbacc::lcpCloseDataFileLab(Signal* signal) { rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); fsConnectptr.p->fsState = LCP_CLOSE_DATA; /* ************************ */ /* FSCLOSEREQ */ /* ************************ */ /* CLOSE DATA FILE */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = ZFALSE; sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA); /* FLAG = 0, DO NOT DELETE FILE */ return; }//Dbacc::lcpCloseDataFileLab() void Dbacc::checkSyncUndoPagesLab(Signal* signal) { fragrecptr.i = fsConnectptr.p->fragrecPtr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); releaseFsConnRec(signal); rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); switch (lcpConnectptr.p->syncUndopageState) { case WAIT_NOTHING: jam(); lcpConnectptr.p->syncUndopageState = WAIT_ONE_CONF; break; case WAIT_ONE_CONF: jam(); lcpConnectptr.p->syncUndopageState = WAIT_TWO_CONF; break; default: jam(); sendSystemerror(signal); return; break; }//switch /* ACTIVE UNDO PAGE ID */ Uint32 tundoPageId = cundoposition >> ZUNDOPAGEINDEXBITS; tmp1 = tundoPageId - (tundoPageId & (ZWRITE_UNDOPAGESIZE - 1)); /* START PAGE OF THE LAST UNDO PAGES GROUP */ tmp2 = (tundoPageId - tmp1) + 1; /* NO OF LEFT UNDO PAGES */ tmp1 = tmp1 & (cundopagesize - 1); /* 1 MBYTE PAGE WINDOW IN MEMORY */ fsConnectptr.i = cactiveOpenUndoFsPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); seizeFsOpRec(signal); initFsOpRec(signal); fsOpptr.p->fsOpstate = WAIT_WRITE_UNDO; fsOpptr.p->fsOpMemPage = tundoPageId; /* RECORD MEMORY PAGE WRITTEN */ if (clblPageCounter >= (4 * tmp2)) { jam(); clblPageCounter = clblPageCounter - (4 * tmp2); } else { jam(); clblPageOver = clblPageOver + ((4 * tmp2) - clblPageCounter); clblPageCounter = 0; }//if /* ************************ */ /* FSWRITEREQ */ /* ************************ */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsOpptr.i; /* FLAG = START MEM PAGES, START FILE PAGES */ /* SYNC FILE AFTER WRITING */ signal->theData[3] = 0x11; signal->theData[4] = ZUNDOPAGE_BASE_ADD; /* NO OF UNDO PAGES */ signal->theData[5] = tmp2; /* FIRST MEMORY PAGE */ signal->theData[6] = tmp1; /* ACTIVE PAGE AT UNDO FILE */ signal->theData[7] = cactiveUndoFilePage; sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA); return; }//Dbacc::checkSyncUndoPagesLab() void Dbacc::checkSendLcpConfLab(Signal* signal) { rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE); switch (lcpConnectptr.p->syncUndopageState) { case WAIT_ONE_CONF: jam(); lcpConnectptr.p->syncUndopageState = WAIT_NOTHING; break; case WAIT_TWO_CONF: jam(); lcpConnectptr.p->syncUndopageState = WAIT_ONE_CONF; break; default: ndbrequire(false); break; }//switch lcpConnectptr.p->noOfLcpConf++; ndbrequire(lcpConnectptr.p->noOfLcpConf <= 2); fragrecptr.p->fragState = ACTIVEFRAG; rlpPageptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(rlpPageptr, cpagesize, page8); releaseLcpPage(signal); fragrecptr.p->zeroPagePtr = RNIL; for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) { jam(); if (fragrecptr.p->datapages[i] != RNIL) { jam(); rlpPageptr.i = fragrecptr.p->datapages[i]; ptrCheckGuard(rlpPageptr, cpagesize, page8); releaseLcpPage(signal); fragrecptr.p->datapages[i] = RNIL; }//if }//for signal->theData[0] = fragrecptr.p->lcpLqhPtr; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_LCPCONF, signal, 1, JBB); if (lcpConnectptr.p->noOfLcpConf == 2) { jam(); releaseLcpConnectRec(signal); rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); rootfragrecptr.p->rootState = ACTIVEROOT; }//if }//Dbacc::checkSendLcpConfLab() /* ******************--------------------------------------------------------------- */ /* ACC_CONTOPREQ */ /* SENDER: LQH, LEVEL B */ /* ENTER ACC_CONTOPREQ WITH */ /* LCP_CONNECTPTR */ /* TMP1 LOCAL FRAG ID */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACC_CONTOPREQ COMMIT TRANSACTION */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execACC_CONTOPREQ(Signal* signal) { Uint32 tcorLocalFrag; jamEntry(); lcpConnectptr.i = signal->theData[0]; /* CONNECTION PTR */ tcorLocalFrag = signal->theData[1]; /* LOCAL FRAG ID */ tresult = 0; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE); rootfragrecptr.i = lcpConnectptr.p->rootrecptr; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); if (rootfragrecptr.p->fragmentid[0] == tcorLocalFrag) { jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); } else { ndbrequire(rootfragrecptr.p->fragmentid[1] == tcorLocalFrag); jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[1]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); }//if operationRecPtr.i = fragrecptr.p->firstWaitInQueOp; fragrecptr.p->sentWaitInQueOp = RNIL; fragrecptr.p->stopQueOp = ZFALSE; while (operationRecPtr.i != RNIL) { jam(); ptrCheckGuard(operationRecPtr, coprecsize, operationrec); if (operationRecPtr.p->opState == WAIT_EXE_OP) { jam(); //------------------------------------------------------------ // Indicate that we are now a normal waiter in the queue. We // will remove the operation from the queue as part of starting // operation again. //------------------------------------------------------------ operationRecPtr.p->opState = WAIT_IN_QUEUE; executeNextOperation(signal); }//if operationRecPtr.i = operationRecPtr.p->nextQueOp; }//while signal->theData[0] = fragrecptr.p->lcpLqhPtr; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_CONTOPCONF, signal, 1, JBA); return; /* ALL QUEUED OPERATION ARE RESTARTED IF NEEDED. */ }//Dbacc::execACC_CONTOPREQ() /* ******************--------------------------------------------------------------- */ /* END_LCPREQ END OF LOCAL CHECK POINT */ /* ENTER END_LCPREQ WITH SENDER: LQH, LEVEL B */ /* CLQH_PTR, LQH PTR */ /* CLQH_BLOCK_REF LQH BLOCK REF */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* END_LCPREQ PERFORM A LOCAL CHECK POINT */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execEND_LCPREQ(Signal* signal) { jamEntry(); clqhPtr = signal->theData[0]; /* LQH PTR */ clqhBlockRef = signal->theData[1]; /* LQH BLOCK REF */ tresult = 0; fsConnectptr.i = cactiveOpenUndoFsPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); fsConnectptr.p->fsState = WAIT_CLOSE_UNDO; /* CLOSE FILE AFTER WRITTING */ /* ************************ */ /* FSCLOSEREQ */ /* ************************ */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = ZFALSE; sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA); /* FLAG = 0, DO NOT DELETE FILE */ cactiveUndoFileVersion = RNIL; cactiveOpenUndoFsPtr = RNIL; /* ************************ */ /* END_LCPCONF */ /* ************************ */ signal->theData[0] = clqhPtr; sendSignal(clqhBlockRef, GSN_END_LCPCONF, signal, 1, JBB); return; }//Dbacc::execEND_LCPREQ() /*-----------------------------------------------------------------*/ /* WHEN WE COPY THE PAGE WE ALSO WRITE THE ELEMENT HEADER AS */ /* UNLOCKED IF THEY ARE CURRENTLY LOCKED. */ /*-----------------------------------------------------------------*/ void Dbacc::lcpCopyPage(Signal* signal) { Uint32 tlcnNextContainer; Uint32 tlcnTmp; Uint32 tlcnConIndex; Uint32 tlcnIndex; Uint32 Tmp1; Uint32 Tmp2; Uint32 Tmp3; Uint32 Tmp4; Uint32 Ti; Uint32 Tchs; Uint32 Tlimit; Tchs = 0; lupPageptr.p = lcnCopyPageptr.p; lcnPageptr.p->word32[ZPOS_CHECKSUM] = Tchs; for (Ti = 0; Ti < 32 ; Ti++) { Tlimit = 16 + (Ti << 6); for (tlcnTmp = (Ti << 6); tlcnTmp < Tlimit; tlcnTmp ++) { Tmp1 = lcnPageptr.p->word32[tlcnTmp]; Tmp2 = lcnPageptr.p->word32[tlcnTmp + 16]; Tmp3 = lcnPageptr.p->word32[tlcnTmp + 32]; Tmp4 = lcnPageptr.p->word32[tlcnTmp + 48]; lcnCopyPageptr.p->word32[tlcnTmp] = Tmp1; lcnCopyPageptr.p->word32[tlcnTmp + 16] = Tmp2; lcnCopyPageptr.p->word32[tlcnTmp + 32] = Tmp3; lcnCopyPageptr.p->word32[tlcnTmp + 48] = Tmp4; Tchs = Tchs ^ Tmp1; Tchs = Tchs ^ Tmp2; Tchs = Tchs ^ Tmp3; Tchs = Tchs ^ Tmp4; }//for }//for tlcnChecksum = Tchs; if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) { jam(); if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) { jam(); /*-----------------------------------------------------------------*/ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */ /* HEADER OF 2 WORDS. */ /*-----------------------------------------------------------------*/ tlcnConIndex = ZHEAD_SIZE; tlupForward = 1; for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) { tlupIndex = tlcnConIndex; tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE; lcpUpdatePage(signal); tlcnConIndex = tlcnConIndex + ZBUF_SIZE; }//for }//if /*-----------------------------------------------------------------*/ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */ /*-----------------------------------------------------------------*/ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f; while (tlcnNextContainer < ZEMPTYLIST) { tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS); tlcnConIndex = tlcnConIndex + ZHEAD_SIZE; tlupIndex = tlcnConIndex; tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE; tlupForward = 1; lcpUpdatePage(signal); tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f; }//while if (tlcnNextContainer == ZEMPTYLIST) { jam(); /*empty*/; } else { jam(); sendSystemerror(signal); return; }//if /*-----------------------------------------------------------------*/ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */ /*-----------------------------------------------------------------*/ tlupForward = cminusOne; tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f; while (tlcnNextContainer < ZEMPTYLIST) { tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS); tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); tlupIndex = tlcnConIndex; tlupElemIndex = tlcnConIndex - 1; lcpUpdatePage(signal); tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f; }//while if (tlcnNextContainer == ZEMPTYLIST) { jam(); /*empty*/; } else { jam(); sendSystemerror(signal); return; }//if }//if lcnCopyPageptr.p->word32[ZPOS_CHECKSUM] = tlcnChecksum; }//Dbacc::lcpCopyPage() /* --------------------------------------------------------------------------------- */ /* THIS SUBROUTINE GOES THROUGH ONE CONTAINER TO CHECK FOR LOCKED ELEMENTS AND */ /* UPDATING THEM TO ENSURE ALL ELEMENTS ARE UNLOCKED ON DISK. */ /* --------------------------------------------------------------------------------- */ void Dbacc::lcpUpdatePage(Signal* signal) { OperationrecPtr lupOperationRecPtr; Uint32 tlupElemHead; Uint32 tlupElemLen; Uint32 tlupElemStep; Uint32 tlupConLen; tlupConLen = lupPageptr.p->word32[tlupIndex] >> 26; tlupElemLen = fragrecptr.p->elementLength; tlupElemStep = tlupForward * tlupElemLen; while (tlupConLen > ZCON_HEAD_SIZE) { jam(); tlupElemHead = lupPageptr.p->word32[tlupElemIndex]; if (ElementHeader::getLocked(tlupElemHead)) { jam(); /* --------------------------------------------------------------------------------- */ /* WHEN CHANGING THE ELEMENT HEADER WE ALSO HAVE TO UPDATE THE CHECKSUM. IN */ /* DOING THIS WE USE THE FORMULA (A XOR B) XOR B = A WHICH MEANS THAT IF WE */ /* XOR SOMETHING TWICE WITH THE SAME OPERAND THEN WE RETURN TO THE ORIGINAL */ /* VALUE. THEN WE ALSO HAVE TO USE THE NEW ELEMENT HEADER IN THE CHECKSUM */ /* CALCULATION. */ /* --------------------------------------------------------------------------------- */ tlcnChecksum = tlcnChecksum ^ tlupElemHead; lupOperationRecPtr.i = ElementHeader::getOpPtrI(tlupElemHead); ptrCheckGuard(lupOperationRecPtr, coprecsize, operationrec); const Uint32 hv = lupOperationRecPtr.p->hashvaluePart; tlupElemHead = ElementHeader::setUnlocked(hv , 0); arrGuard(tlupElemIndex, 2048); lupPageptr.p->word32[tlupElemIndex] = tlupElemHead; tlcnChecksum = tlcnChecksum ^ tlupElemHead; }//if tlupConLen = tlupConLen - tlupElemLen; tlupElemIndex = tlupElemIndex + tlupElemStep; }//while if (tlupConLen < ZCON_HEAD_SIZE) { jam(); sendSystemerror(signal); }//if }//Dbacc::lcpUpdatePage() /*-----------------------------------------------------------------*/ // At a system restart we check that the page do not contain any // locks that hinder the system restart procedure. /*-----------------------------------------------------------------*/ void Dbacc::srCheckPage(Signal* signal) { Uint32 tlcnNextContainer; Uint32 tlcnConIndex; Uint32 tlcnIndex; lupPageptr.p = lcnCopyPageptr.p; if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) { jam(); if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) { jam(); /*-----------------------------------------------------------------*/ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */ /* HEADER OF 2 WORDS. */ /*-----------------------------------------------------------------*/ tlcnConIndex = ZHEAD_SIZE; tlupForward = 1; for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) { tlupIndex = tlcnConIndex; tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE; srCheckContainer(signal); if (tresult != 0) { jam(); return; }//if tlcnConIndex = tlcnConIndex + ZBUF_SIZE; }//for }//if /*-----------------------------------------------------------------*/ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */ /*-----------------------------------------------------------------*/ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f; while (tlcnNextContainer < ZEMPTYLIST) { tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS); tlcnConIndex = tlcnConIndex + ZHEAD_SIZE; tlupIndex = tlcnConIndex; tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE; tlupForward = 1; srCheckContainer(signal); if (tresult != 0) { jam(); return; }//if tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f; }//while if (tlcnNextContainer == ZEMPTYLIST) { jam(); /*empty*/; } else { jam(); tresult = 4; return; }//if /*-----------------------------------------------------------------*/ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */ /*-----------------------------------------------------------------*/ tlupForward = cminusOne; tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f; while (tlcnNextContainer < ZEMPTYLIST) { tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS); tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE); tlupIndex = tlcnConIndex; tlupElemIndex = tlcnConIndex - 1; srCheckContainer(signal); if (tresult != 0) { jam(); return; }//if tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f; }//while if (tlcnNextContainer == ZEMPTYLIST) { jam(); /*empty*/; } else { jam(); tresult = 4; return; }//if }//if }//Dbacc::srCheckPage() /* --------------------------------------------------------------------------------- */ /* THIS SUBROUTINE GOES THROUGH ONE CONTAINER TO CHECK FOR LOCKED ELEMENTS AND */ /* UPDATING THEM TO ENSURE ALL ELEMENTS ARE UNLOCKED ON DISK. */ /* --------------------------------------------------------------------------------- */ void Dbacc::srCheckContainer(Signal* signal) { Uint32 tlupElemLen; Uint32 tlupElemStep; Uint32 tlupConLen; tlupConLen = lupPageptr.p->word32[tlupIndex] >> 26; tlupElemLen = fragrecptr.p->elementLength; tlupElemStep = tlupForward * tlupElemLen; while (tlupConLen > ZCON_HEAD_SIZE) { jam(); const Uint32 tlupElemHead = lupPageptr.p->word32[tlupElemIndex]; if (ElementHeader::getLocked(tlupElemHead)){ jam(); //------------------------------------------------------- // This is absolutely undesirable. We have a lock remaining // after the system restart. We send a crash signal that will // enter the trace file. //------------------------------------------------------- tresult = 2; return; }//if tlupConLen = tlupConLen - tlupElemLen; tlupElemIndex = tlupElemIndex + tlupElemStep; }//while if (tlupConLen < ZCON_HEAD_SIZE) { jam(); tresult = 3; }//if return; }//Dbacc::srCheckContainer() /* ------------------------------------------------------------------------- */ /* CHECK_UNDO_PAGES */ /* DESCRIPTION: CHECKS WHEN A PAGE OR A GROUP OF UNDO PAGES IS FILLED.WHEN */ /* A PAGE IS FILLED, CUNDOPOSITION WILL BE UPDATE, THE NEW */ /* POSITION IS THE BEGNING OF THE NEXT UNDO PAGE. */ /* IN CASE THAT A GROUP IS FILLED THE PAGES ARE SENT TO DISK, */ /* AND A NEW GROUP IS CHOSEN. */ /* ------------------------------------------------------------------------- */ void Dbacc::checkUndoPages(Signal* signal) { fragrecptr.p->prevUndoposition = cundoposition; cprevUndoaddress = cundoposition; // Calculate active undo page id Uint32 tundoPageId = cundoposition >> ZUNDOPAGEINDEXBITS; /** * WE WILL WRITE UNTIL WE HAVE ABOUT 8 KBYTE REMAINING ON THE 32 KBYTE * PAGE. THIS IS TO ENSURE THAT WE DO NOT HAVE ANY UNDO LOG RECORDS THAT PASS * A PAGE BOUNDARIE. THIS SIMPLIFIES CODING TRADING SOME INEFFICIENCY. */ static const Uint32 ZMAXUNDOPAGEINDEX = 7100; if (tundoindex < ZMAXUNDOPAGEINDEX) { jam(); cundoposition = (tundoPageId << ZUNDOPAGEINDEXBITS) + tundoindex; return; }//if /** * WE CHECK IF MORE THAN 1 MBYTE OF WRITES ARE OUTSTANDING TO THE UNDO FILE. * IF SO WE HAVE TO CRASH SINCE WE HAVE NO MORE SPACE TO WRITE UNDO LOG * RECORDS IN */ Uint16 nextUndoPageId = tundoPageId + 1; updateUndoPositionPage(signal, nextUndoPageId << ZUNDOPAGEINDEXBITS); if ((tundoPageId & (ZWRITE_UNDOPAGESIZE - 1)) == (ZWRITE_UNDOPAGESIZE - 1)) { jam(); /* ---------- SEND A GROUP OF UNDO PAGES TO DISK --------- */ fsConnectptr.i = cactiveOpenUndoFsPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); Uint32 tcupTmp1 = (tundoPageId - ZWRITE_UNDOPAGESIZE) + 1; tcupTmp1 = tcupTmp1 & (cundopagesize - 1); /* 1 MBYTE PAGE WINDOW */ seizeFsOpRec(signal); initFsOpRec(signal); fsOpptr.p->fsOpstate = WAIT_WRITE_UNDO_EXIT; fsOpptr.p->fsOpMemPage = tundoPageId; fragrecptr.p->nrWaitWriteUndoExit++; if (clblPageCounter >= 8) { jam(); clblPageCounter = clblPageCounter - 8; } else { jam(); clblPageOver = clblPageOver + (8 - clblPageCounter); clblPageCounter = 0; }//if /* ************************ */ /* FSWRITEREQ */ /* ************************ */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsOpptr.i; signal->theData[3] = 0x1; /* FLAG = START MEM PAGES, START FILE PAGES */ signal->theData[4] = ZUNDOPAGE_BASE_ADD; signal->theData[5] = ZWRITE_UNDOPAGESIZE; signal->theData[6] = tcupTmp1; signal->theData[7] = cactiveUndoFilePage; sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA); cactiveUndoFilePage = cactiveUndoFilePage + ZWRITE_UNDOPAGESIZE; }//if }//Dbacc::checkUndoPages() /* --------------------------------------------------------------------------------- */ /* UNDO_WRITING_PROCESS */ /* INPUT: FRAGRECPTR, CUNDO_ELEM_INDEX, DATAPAGEPTR, CUNDOINFOLENGTH */ /* DESCRIPTION: WHEN THE PROCESS OF CREATION LOCAL CHECK POINT HAS */ /* STARTED. IF THE ACTIVE PAGE IS NOT ALREADY SENT TO DISK, THE */ /* OLD VALUE OF THE ITEM WHICH IS GOING TO BE CHECKED IS STORED ON */ /* THE ACTIVE UNDO PAGE. INFORMATION ABOUT UNDO PROCESS IN THE */ /* BLOCK AND IN THE FRAGMENT WILL BE UPDATED. */ /* --------------------------------------------------------------------------------- */ void Dbacc::undoWritingProcess(Signal* signal) { const Uint32 tactivePageDir = datapageptr.p->word32[ZPOS_PAGE_ID]; const Uint32 tpageType = (datapageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3; if (fragrecptr.p->fragState == LCP_SEND_PAGES) { if (tpageType == ZNORMAL_PAGE_TYPE) { /* --------------------------------------------------------------------------- */ /* HANDLING OF LOG OF NORMAL PAGES DURING WRITE OF NORMAL PAGES. */ /* --------------------------------------------------------------------------- */ if (tactivePageDir < fragrecptr.p->lcpDirIndex) { jam(); /* ------------------------------------------------------------------- */ /* THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT. */ /* ------------------------------------------------------------------- */ /*empty*/; } else { if (tactivePageDir >= fragrecptr.p->lcpMaxDirIndex) { jam(); /* --------------------------------------------------------------------------- */ /* OBVIOUSLY THE FRAGMENT HAS EXPANDED SINCE THE START OF THE LOCAL CHECKPOINT.*/ /* WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID NOT EXIST AT START OF LCP. */ /* --------------------------------------------------------------------------- */ /*empty*/; } else { jam(); /* --------------------------------------------------------------------------- */ /* IN ALL OTHER CASES WE HAVE TO WRITE TO THE UNDO LOG. */ /* --------------------------------------------------------------------------- */ undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1); ptrAss(undopageptr, undopage); theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; tundoindex = theadundoindex + ZUNDOHEADSIZE; writeUndoHeader(signal, tactivePageDir, UndoHeader::ZPAGE_INFO); tundoElemIndex = cundoElemIndex; writeUndoDataInfo(signal); checkUndoPages(signal); }//if }//if } else if (tpageType == ZOVERFLOW_PAGE_TYPE) { /* --------------------------------------------------------------------------------- */ /* OVERFLOW PAGE HANDLING DURING WRITE OF NORMAL PAGES. */ /* --------------------------------------------------------------------------------- */ if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) { jam(); /* --------------------------------------------------------------------------------- */ /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */ /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/ /* NOT EXIST AT START OF LCP. */ /* --------------------------------------------------------------------------------- */ /*empty*/; } else { jam(); undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1); ptrAss(undopageptr, undopage); theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; tundoindex = theadundoindex + ZUNDOHEADSIZE; writeUndoHeader(signal, tactivePageDir, UndoHeader::ZOVER_PAGE_INFO); tundoElemIndex = cundoElemIndex; writeUndoDataInfo(signal); checkUndoPages(signal); }//if } else if (tpageType != ZLONG_PAGE_TYPE) { jam(); /* --------------------------------------------------------------------------- */ /* ONLY PAGE INFO AND OVERFLOW PAGE INFO CAN BE LOGGED BY THIS ROUTINE. A */ /* SERIOUS ERROR. */ /* --------------------------------------------------------------------------- */ sendSystemerror(signal); } else { /* --------------------------------------------------------------------------------- */ /* THIS LOG RECORD IS GENERATED ON A LONG KEY PAGE. THESE PAGES USE LOGICAL */ /* LOGGING. */ /* --------------------------------------------------------------------------------- */ if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) { jam(); /* --------------------------------------------------------------------------------- */ /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */ /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/ /* NOT EXIST AT START OF LCP. */ /* --------------------------------------------------------------------------------- */ /*empty*/; } else { jam(); /* --------------------------------------------------------------------------------- */ /* LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN INSERT OR UNDO */ /* OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG THE KEY TO BE REINSERTED WHILE */ /* UNDO OF INSERT ONLY NEEDS TO LOG THE INDEX TO BE DELETED. */ /* --------------------------------------------------------------------------------- */ undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1); ptrAss(undopageptr, undopage); theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; tundoindex = theadundoindex + ZUNDOHEADSIZE; if (cundoinfolength == 0) { jam(); writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY); } else { jam(); writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY); arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048); tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff; writeUndoDataInfo(signal); }//if checkUndoPages(signal); }//if }//if } else { if (fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) { jam(); /* --------------------------------------------------------------------------------- */ /* DURING WRITE OF OVERFLOW PAGES WE NEED NOT WORRY ANYMORE ABOUT NORMAL PAGES.*/ /* --------------------------------------------------------------------------------- */ if (tpageType == ZOVERFLOW_PAGE_TYPE) { if (tactivePageDir < fragrecptr.p->lcpDirIndex) { jam(); /* --------------------------------------------------------------------------------- */ /* THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT. */ /* --------------------------------------------------------------------------------- */ /*empty*/; } else { if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) { jam(); /* --------------------------------------------------------------------------------- */ /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */ /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/ /* NOT EXIST AT START OF LCP. */ /* --------------------------------------------------------------------------------- */ /*empty*/; } else { jam(); undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1); ptrAss(undopageptr, undopage); theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; tundoindex = theadundoindex + ZUNDOHEADSIZE; writeUndoHeader(signal, tactivePageDir, UndoHeader::ZOVER_PAGE_INFO); tundoElemIndex = cundoElemIndex; writeUndoDataInfo(signal); checkUndoPages(signal); }//if }//if } else if (tpageType == ZLONG_PAGE_TYPE) { if (tactivePageDir < fragrecptr.p->lcpDirIndex) { jam(); // ------------------------------------------------------------- // THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT. // ------------------------------------------------------------- } else { if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) { jam(); // ------------------------------------------------------------- // OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW // PAGES SINCE THE START OF THE LOCAL CHECKPOINT. WE NEED NOT // LOG ANY UPDATES OF PAGES THAT DID NOT EXIST AT START OF LCP. // ------------------------------------------------------------- } else { jam(); // ------------------------------------------------------------- // LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN // INSERT OR UNDO OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG // THE KEY TO BE REINSERTED WHILE UNDO OF INSERT ONLY NEEDS TO // LOG THE INDEX TO BE DELETED. // ------------------------------------------------------------- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1); ptrAss(undopageptr, undopage); theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK; tundoindex = theadundoindex + ZUNDOHEADSIZE; if (cundoinfolength == 0) { jam(); writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY); } else { jam(); writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY); arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048); tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff; writeUndoDataInfo(signal); }//if checkUndoPages(signal); }//if }//if }//if }//if }//if }//Dbacc::undoWritingProcess() /* --------------------------------------------------------------------------------- */ /* OTHER STATES MEANS THAT WE HAVE ALREADY WRITTEN ALL PAGES BUT NOT YET RESET */ /* THE CREATE_LCP FLAG. */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* WRITE_UNDO_DATA_INFO */ /* --------------------------------------------------------------------------------- */ void Dbacc::writeUndoDataInfo(Signal* signal) { Uint32 twudiIndex; Uint32 guard22; guard22 = cundoinfolength; arrGuard((tundoindex + guard22 - 1), 8192); arrGuard((tundoElemIndex + guard22 - 1), 2048); for (twudiIndex = 1; twudiIndex <= guard22; twudiIndex++) { undopageptr.p->undoword[tundoindex] = datapageptr.p->word32[tundoElemIndex]; tundoindex++; tundoElemIndex++; }//for }//Dbacc::writeUndoDataInfo() /* --------------------------------------------------------------------------------- */ /* WRITE_UNDO_HEADER */ /* THE HEAD OF UNDO ELEMENT IS 24 BYTES AND CONTAINS THE FOLLOWING INFORMATION: */ /* TABLE IDENTITY 32 BITS */ /* ROOT FRAGMENT IDENTITY 32 BITS */ /* LOCAL FRAGMENT IDENTITY 32 BITS */ /* LENGTH OF ELEMENT INF0 (BIT 31 - 18) 14 BITS */ /* INFO TYPE (BIT 17 - 14) 4 BITS */ /* PAGE INDEX OF THE FIRST FIELD IN THE FRAGMENT (BIT 13 - 0) 14 BITS */ /* DIRECTORY INDEX OF THE PAGE IN THE FRAGMENT 32 BITS */ /* ADDRESS OF THE PREVIOUS ELEMENT OF THE FRAGMENT 64 BITS */ /* ADDRESS OF THE PREVIOUS ELEMENT IN THE UNDO PAGES 64 BITS */ /* --------------------------------------------------------------------------------- */ void Dbacc::writeUndoHeader(Signal* signal, Uint32 logicalPageId, UndoHeader::UndoHeaderType pageType) { rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); arrGuard(theadundoindex + 6, 8192); // Set the structpointer to point at the undo page at the right address. UndoHeader * const & undoHeaderPtr = (UndoHeader *) &undopageptr.p->undoword[theadundoindex]; undoHeaderPtr->tableId = rootfragrecptr.p->mytabptr; undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0]; undoHeaderPtr->localFragId = fragrecptr.p->myfid; Uint32 Ttmp = cundoinfolength; Ttmp = (Ttmp << 4) + pageType; Ttmp = Ttmp << 14; undoHeaderPtr->variousInfo = Ttmp + cundoElemIndex; undoHeaderPtr->logicalPageId = logicalPageId; undoHeaderPtr->prevUndoAddressForThisFrag = fragrecptr.p->prevUndoposition; undoHeaderPtr->prevUndoAddress = cprevUndoaddress; }//Dbacc::writeUndoHeader() /* --------------------------------------------------------------------------------- */ /* WRITE_UNDO_OP_INFO */ /* FOR A LOCKED ELEMENT, OPERATION TYPE, UNDO OF ELEMENT HEADER AND THE LENGTH OF*/ /* THE TUPLE KEY HAVE TO BE SAVED IN UNDO PAGES. IN THIS CASE AN UNDO ELEMENT */ /* INCLUDES THE FLLOWING ITEMS. */ /* OPERATION TYPE 32 BITS */ /* HASH VALUE 32 BITS */ /* LENGTH OF THE TUPLE = N 32 BITS */ /* TUPLE KEYS N * 32 BITS */ /* */ /* --------------------------------------------------------------------------------- */ void Dbacc::writeUndoOpInfo(Signal* signal) { Page8Ptr locPageptr; arrGuard((tundoindex + 3), 8192); undopageptr.p->undoword[tundoindex] = operationRecPtr.p->operation; undopageptr.p->undoword[tundoindex + 1] = operationRecPtr.p->hashValue; undopageptr.p->undoword[tundoindex + 2] = operationRecPtr.p->tupkeylen; tundoindex = tundoindex + 3; if (fragrecptr.p->keyLength != 0) { // Fixed size keys jam(); locPageptr.i = operationRecPtr.p->elementPage; ptrCheckGuard(locPageptr, cpagesize, page8); Uint32 Tforward = operationRecPtr.p->elementIsforward; Uint32 TelemPtr = operationRecPtr.p->elementPointer; TelemPtr += Tforward; TelemPtr += Tforward; //--------------------------------------------------------------------------------- // Now the pointer is at the start of the key part of the element. Now copy from there // to the UNDO log. //--------------------------------------------------------------------------------- Uint32 keyLen = operationRecPtr.p->tupkeylen; ndbrequire(keyLen <= 8); arrGuard(tundoindex+keyLen, 8192); for (Uint32 twuoiIndex = 0; twuoiIndex < keyLen; twuoiIndex++) { jam(); arrGuard(TelemPtr, 2048); undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr]; tundoindex++; TelemPtr += Tforward; }//for cundoinfolength = ZOP_HEAD_INFO_LN + operationRecPtr.p->tupkeylen; } else { // Long keys jam(); arrGuard(operationRecPtr.p->longKeyPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE); locPageptr.i = operationRecPtr.p->longPagePtr; ptrCheckGuard(locPageptr, cpagesize, page8); Uint32 indexValue = locPageptr.p->word32[ZWORDS_IN_PAGE - operationRecPtr.p->longKeyPageIndex]; Uint32 keyLen = indexValue >> 16; Uint32 physPageIndex = indexValue & 0xffff; ndbrequire(keyLen == operationRecPtr.p->tupkeylen); arrGuard(tundoindex+keyLen, 8192); arrGuard(physPageIndex+keyLen, 2048); for (Uint32 i = 0; i < keyLen; i++){ undopageptr.p->undoword[tundoindex + i] = locPageptr.p->word32[physPageIndex+i]; } tundoindex = tundoindex + keyLen; cundoinfolength = ZOP_HEAD_INFO_LN + keyLen; }//if }//Dbacc::writeUndoOpInfo() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF LOCAL CHECKPOINT MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* SYSTEM RESTART MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* SR_FRAGIDREQ REQUEST FOR RESTART OF A FRAGMENT */ /* SENDER: LQH, LEVEL B */ /* ENTER SR_FRAGIDREQ WITH */ /* TUSERPTR, LQH CONNECTION PTR */ /* TUSERBLOCKREF, LQH BLOCK REFERENCE */ /* TCHECKPOINTID, THE CHECKPOINT NUMBER TO USE */ /* (E.G. 1,2 OR 3) */ /* TABPTR, TABLE ID = TABLE RECORD POINTER */ /* TFID, ROOT FRAGMENT ID */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* SR_FRAGIDREQ REQUEST FOR LIST OF STOPED OPERATION */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execSR_FRAGIDREQ(Signal* signal) { jamEntry(); tuserptr = signal->theData[0]; /* LQH CONNECTION PTR */ tuserblockref = signal->theData[1]; /* LQH BLOCK REFERENCE */ tcheckpointid = signal->theData[2]; /* THE CHECKPOINT NUMBER TO USE */ /* (E.G. 1,2 OR 3) */ tabptr.i = signal->theData[3]; ptrCheckGuard(tabptr, ctablesize, tabrec); /* TABLE ID = TABLE RECORD POINTER */ tfid = signal->theData[4]; /* ROOT FRAGMENT ID */ tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */ seizeLcpConnectRec(signal); initLcpConnRec(signal); ndbrequire(getrootfragmentrec(signal, rootfragrecptr, tfid)); rootfragrecptr.p->lcpPtr = lcpConnectptr.i; lcpConnectptr.p->rootrecptr = rootfragrecptr.i; lcpConnectptr.p->localCheckPid = tcheckpointid; for (Uint32 i = 0; i < 2; i++) { Page8Ptr zeroPagePtr; jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[i]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); seizeLcpPage(zeroPagePtr); fragrecptr.p->zeroPagePtr = zeroPagePtr.i; }//for /* ---------------------------OPEN THE DATA FILE WHICH BELONGS TO TFID AND TCHECK POINT ---- */ fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); tfid = rootfragrecptr.p->fragmentid[0]; tmp = 0; srOpenDataFileLoopLab(signal); return; }//Dbacc::execSR_FRAGIDREQ() void Dbacc::srOpenDataFileLoopLab(Signal* signal) { /* D6 AT FSOPENREQ. FILE TYPE = .DATA */ tmp1 = 0x010003ff; /* VERSION OF FILENAME = 1 */ tmp2 = 0x0; /* D7 DON'T CREATE, READ ONLY */ ndbrequire(cfsFirstfreeconnect != RNIL); seizeFsConnectRec(signal); fragrecptr.p->fsConnPtr = fsConnectptr.i; fsConnectptr.p->fragrecPtr = fragrecptr.i; fsConnectptr.p->fsState = WAIT_OPEN_DATA_FILE_FOR_READ; fsConnectptr.p->activeFragId = tmp; /* LOCAL FRAG INDEX */ /* ************************ */ /* FSOPENREQ */ /* ************************ */ signal->theData[0] = cownBlockref; signal->theData[1] = fsConnectptr.i; signal->theData[2] = rootfragrecptr.p->mytabptr; /* TABLE IDENTITY */ signal->theData[3] = tfid; /* FRAGMENT IDENTITY */ signal->theData[4] = lcpConnectptr.p->localCheckPid; /* CHECKPOINT ID */ signal->theData[5] = tmp1; signal->theData[6] = tmp2; sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA); return; }//Dbacc::srOpenDataFileLoopLab() void Dbacc::srFsOpenConfLab(Signal* signal) { fsConnectptr.p->fsState = WAIT_READ_PAGE_ZERO; /* ------------------------ READ ZERO PAGE ---------- */ fragrecptr.i = fsConnectptr.p->fragrecPtr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = 0x0; /* FLAG = LIST MEM PAGES, LIST FILE PAGES */ signal->theData[4] = ZPAGE8_BASE_ADD; signal->theData[5] = 1; /* NO OF PAGES */ signal->theData[6] = fragrecptr.p->zeroPagePtr; /* ZERO PAGE */ signal->theData[7] = 0; /* PAGE ZERO OF THE DATA FILE */ sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA); return; }//Dbacc::srFsOpenConfLab() void Dbacc::srReadPageZeroLab(Signal* signal) { Page8Ptr srzPageptr; rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); fragrecptr.p->activeDataFilePage = 1; srzPageptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(srzPageptr, cpagesize, page8); /* --------------------------------------------------------------------------------- */ // Check that the checksum of the zero page is ok. /* --------------------------------------------------------------------------------- */ ccoPageptr.p = srzPageptr.p; checksumControl(signal, (Uint32)0); if (tresult > 0) { jam(); return; // We will crash through a DEBUG_SIG }//if ndbrequire(srzPageptr.p->word32[ZPAGEZERO_FRAGID0] == rootfragrecptr.p->fragmentid[0]); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); if (fsConnectptr.p->activeFragId == 0) { jam(); rootfragrecptr.p->fragmentid[1] = srzPageptr.p->word32[ZPAGEZERO_FRAGID1]; /* ---------------------------OPEN THE DATA FILE FOR NEXT LOCAL FRAGMENT ----------- ---- */ tfid = rootfragrecptr.p->fragmentid[1]; tmp = 1; /* LOCAL FRAG INDEX */ fragrecptr.i = rootfragrecptr.p->fragmentptr[1]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); srOpenDataFileLoopLab(signal); return; } else { jam(); lcpConnectptr.p->lcpstate = LCP_ACTIVE; signal->theData[0] = lcpConnectptr.p->lcpUserptr; signal->theData[1] = lcpConnectptr.i; signal->theData[2] = 2; /* NO OF LOCAL FRAGMENTS */ signal->theData[3] = srzPageptr.p->word32[ZPAGEZERO_FRAGID0]; /* ROOTFRAGRECPTR:FRAGMENTID(0) */ signal->theData[4] = srzPageptr.p->word32[ZPAGEZERO_FRAGID1]; /* ROOTFRAGRECPTR:FRAGMENTID(1) */ signal->theData[5] = RNIL; signal->theData[6] = RNIL; signal->theData[7] = rootfragrecptr.p->fragmentptr[0]; signal->theData[8] = rootfragrecptr.p->fragmentptr[1]; signal->theData[9] = srzPageptr.p->word32[ZPAGEZERO_HASH_CHECK]; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_SR_FRAGIDCONF, signal, 10, JBB); }//if return; }//Dbacc::srReadPageZeroLab() void Dbacc::initFragAdd(Signal* signal, Uint32 rootFragIndex, Uint32 rootIndex, FragmentrecPtr regFragPtr) { const AccFragReq * const req = (AccFragReq*)&signal->theData[0]; Uint32 lhFragBits = req->lhFragBits + 1; Uint32 minLoadFactor = (req->minLoadFactor * ZBUF_SIZE) / 100; Uint32 maxLoadFactor = (req->maxLoadFactor * ZBUF_SIZE) / 100; if (minLoadFactor >= maxLoadFactor) { jam(); minLoadFactor = maxLoadFactor - 1; }//if regFragPtr.p->fragState = ACTIVEFRAG; // NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ regFragPtr.p->myfid = (rootFragIndex << (lhFragBits - 1)) | req->fragId; regFragPtr.p->myroot = rootIndex; regFragPtr.p->myTableId = req->tableId; ndbrequire(req->kValue == 6); regFragPtr.p->k = req->kValue; /* TK_SIZE = 6 IN THIS VERSION */ regFragPtr.p->expandCounter = 0; /** * Only allow shrink during SR * - to make sure we don't run out of pages during REDO log execution * * Is later restored to 0 by LQH at end of REDO log execution */ regFragPtr.p->expandFlag = (getNodeState().getSystemRestartInProgress()?1:0); regFragPtr.p->p = 0; regFragPtr.p->maxp = (1 << req->kValue) - 1; regFragPtr.p->minloadfactor = minLoadFactor; regFragPtr.p->maxloadfactor = maxLoadFactor; regFragPtr.p->slack = (regFragPtr.p->maxp + 1) * maxLoadFactor; regFragPtr.p->lhfragbits = lhFragBits; regFragPtr.p->lhdirbits = 0; regFragPtr.p->hashcheckbit = 0; //lhFragBits; regFragPtr.p->localkeylen = req->localKeyLen; regFragPtr.p->nodetype = (req->reqInfo >> 4) & 0x3; regFragPtr.p->lastOverIndex = 0; regFragPtr.p->dirsize = 1; regFragPtr.p->loadingFlag = ZFALSE; regFragPtr.p->keyLength = req->keyLength; if (req->keyLength == 0) { jam(); regFragPtr.p->elementLength = (1 + ZELEM_HEAD_SIZE) + regFragPtr.p->localkeylen; } else { jam(); regFragPtr.p->elementLength = (ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen) + regFragPtr.p->keyLength; }//if Uint32 Tmp1 = (regFragPtr.p->maxp + 1) + regFragPtr.p->p; Uint32 Tmp2 = regFragPtr.p->maxloadfactor - regFragPtr.p->minloadfactor; Tmp2 = Tmp1 * Tmp2; regFragPtr.p->slackCheck = Tmp2; }//Dbacc::initFragAdd() void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr) { regFragPtr.p->directory = RNIL; regFragPtr.p->overflowdir = RNIL; regFragPtr.p->fsConnPtr = RNIL; regFragPtr.p->firstOverflowRec = RNIL; regFragPtr.p->lastOverflowRec = RNIL; regFragPtr.p->firstWaitInQueOp = RNIL; regFragPtr.p->lastWaitInQueOp = RNIL; regFragPtr.p->sentWaitInQueOp = RNIL; regFragPtr.p->lockOwnersList = RNIL; regFragPtr.p->firstFreeDirindexRec = RNIL; regFragPtr.p->zeroPagePtr = RNIL; regFragPtr.p->activeDataPage = 0; regFragPtr.p->createLcp = ZFALSE; regFragPtr.p->stopQueOp = ZFALSE; regFragPtr.p->nextAllocPage = 0; regFragPtr.p->nrWaitWriteUndoExit = 0; regFragPtr.p->lastUndoIsStored = ZFALSE; regFragPtr.p->loadingFlag = ZFALSE; regFragPtr.p->fragState = FREEFRAG; for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) { regFragPtr.p->datapages[i] = RNIL; }//for for (Uint32 j = 0; j < 4; j++) { regFragPtr.p->longKeyPageArray[j] = RNIL; }//for }//Dbacc::initFragGeneral() void Dbacc::initFragSr(FragmentrecPtr regFragPtr, Page8Ptr regPagePtr) { regFragPtr.p->prevUndoposition = regPagePtr.p->word32[ZPAGEZERO_PREV_UNDOP]; regFragPtr.p->noOfStoredOverPages = regPagePtr.p->word32[ZPAGEZERO_NO_OVER_PAGE]; regFragPtr.p->noStoredPages = regPagePtr.p->word32[ZPAGEZERO_NO_PAGES]; regFragPtr.p->dirsize = regPagePtr.p->word32[ZPAGEZERO_DIRSIZE]; regFragPtr.p->expandCounter = regPagePtr.p->word32[ZPAGEZERO_EXPCOUNTER]; regFragPtr.p->slack = regPagePtr.p->word32[ZPAGEZERO_SLACK]; regFragPtr.p->hashcheckbit = regPagePtr.p->word32[ZPAGEZERO_HASHCHECKBIT]; regFragPtr.p->k = regPagePtr.p->word32[ZPAGEZERO_K]; regFragPtr.p->lhfragbits = regPagePtr.p->word32[ZPAGEZERO_LHFRAGBITS]; regFragPtr.p->lhdirbits = regPagePtr.p->word32[ZPAGEZERO_LHDIRBITS]; regFragPtr.p->localkeylen = regPagePtr.p->word32[ZPAGEZERO_LOCALKEYLEN]; regFragPtr.p->maxp = regPagePtr.p->word32[ZPAGEZERO_MAXP]; regFragPtr.p->maxloadfactor = regPagePtr.p->word32[ZPAGEZERO_MAXLOADFACTOR]; regFragPtr.p->minloadfactor = regPagePtr.p->word32[ZPAGEZERO_MINLOADFACTOR]; regFragPtr.p->myfid = regPagePtr.p->word32[ZPAGEZERO_MYFID]; regFragPtr.p->lastOverIndex = regPagePtr.p->word32[ZPAGEZERO_LAST_OVER_INDEX]; regFragPtr.p->nodetype = regPagePtr.p->word32[ZPAGEZERO_NODETYPE]; regFragPtr.p->p = regPagePtr.p->word32[ZPAGEZERO_P]; regFragPtr.p->elementLength = regPagePtr.p->word32[ZPAGEZERO_ELEMENT_LENGTH]; regFragPtr.p->keyLength = regPagePtr.p->word32[ZPAGEZERO_KEY_LENGTH]; regFragPtr.p->slackCheck = regPagePtr.p->word32[ZPAGEZERO_SLACK_CHECK]; regFragPtr.p->loadingFlag = ZTRUE; }//Dbacc::initFragSr() void Dbacc::initFragPageZero(FragmentrecPtr regFragPtr, Page8Ptr regPagePtr) { //------------------------------------------------------------------ // PREV_UNDOP, NEXT_UNDO_FILE, NO_OVER_PAGE, NO_PAGES // is set at end of copy phase //------------------------------------------------------------------ regPagePtr.p->word32[ZPAGEZERO_DIRSIZE] = regFragPtr.p->dirsize; regPagePtr.p->word32[ZPAGEZERO_EXPCOUNTER] = regFragPtr.p->expandCounter; regPagePtr.p->word32[ZPAGEZERO_SLACK] = regFragPtr.p->slack; regPagePtr.p->word32[ZPAGEZERO_HASHCHECKBIT] = regFragPtr.p->hashcheckbit; regPagePtr.p->word32[ZPAGEZERO_K] = regFragPtr.p->k; regPagePtr.p->word32[ZPAGEZERO_LHFRAGBITS] = regFragPtr.p->lhfragbits; regPagePtr.p->word32[ZPAGEZERO_LHDIRBITS] = regFragPtr.p->lhdirbits; regPagePtr.p->word32[ZPAGEZERO_LOCALKEYLEN] = regFragPtr.p->localkeylen; regPagePtr.p->word32[ZPAGEZERO_MAXP] = regFragPtr.p->maxp; regPagePtr.p->word32[ZPAGEZERO_MAXLOADFACTOR] = regFragPtr.p->maxloadfactor; regPagePtr.p->word32[ZPAGEZERO_MINLOADFACTOR] = regFragPtr.p->minloadfactor; regPagePtr.p->word32[ZPAGEZERO_MYFID] = regFragPtr.p->myfid; regPagePtr.p->word32[ZPAGEZERO_LAST_OVER_INDEX] = regFragPtr.p->lastOverIndex; regPagePtr.p->word32[ZPAGEZERO_NODETYPE] = regFragPtr.p->nodetype; regPagePtr.p->word32[ZPAGEZERO_P] = regFragPtr.p->p; regPagePtr.p->word32[ZPAGEZERO_ELEMENT_LENGTH] = regFragPtr.p->elementLength; regPagePtr.p->word32[ZPAGEZERO_KEY_LENGTH] = regFragPtr.p->keyLength; regPagePtr.p->word32[ZPAGEZERO_SLACK_CHECK] = regFragPtr.p->slackCheck; }//Dbacc::initFragPageZero() void Dbacc::initRootFragPageZero(RootfragmentrecPtr rootPtr, Page8Ptr regPagePtr) { regPagePtr.p->word32[ZPAGEZERO_TABID] = rootPtr.p->mytabptr; regPagePtr.p->word32[ZPAGEZERO_FRAGID0] = rootPtr.p->fragmentid[0]; regPagePtr.p->word32[ZPAGEZERO_FRAGID1] = rootPtr.p->fragmentid[1]; regPagePtr.p->word32[ZPAGEZERO_HASH_CHECK] = rootPtr.p->roothashcheck; regPagePtr.p->word32[ZPAGEZERO_NO_OF_ELEMENTS] = rootPtr.p->noOfElements; }//Dbacc::initRootFragPageZero() void Dbacc::initRootFragSr(RootfragmentrecPtr rootPtr, Page8Ptr regPagePtr) { rootPtr.p->roothashcheck = regPagePtr.p->word32[ZPAGEZERO_HASH_CHECK]; rootPtr.p->noOfElements = regPagePtr.p->word32[ZPAGEZERO_NO_OF_ELEMENTS]; }//Dbacc::initRootFragSr() /* ******************--------------------------------------------------------------- */ /* ACC_SRREQ SYSTEM RESTART OF A LOCAL CHECK POINT */ /* SENDER: LQH, LEVEL B */ /* ENTER ACC_SRREQ WITH */ /* LCP_CONNECTPTR, OPERATION RECORD PTR */ /* TMP2, LQH'S LOCAL FRAG CHECK VALUE */ /* TFID, LOCAL FRAG ID */ /* TMP1, LOCAL CHECKPOINT ID */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACC_SRREQ PERFORM A LOCAL CHECK POINT */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execACC_SRREQ(Signal* signal) { Page8Ptr asrPageidptr; jamEntry(); lcpConnectptr.i = signal->theData[0]; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); Uint32 lqhPtr = signal->theData[1]; Uint32 fragId = signal->theData[2]; Uint32 lcpId = signal->theData[3]; tresult = 0; ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE); rootfragrecptr.i = lcpConnectptr.p->rootrecptr; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); if (rootfragrecptr.p->fragmentid[0] == fragId) { jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; } else { ndbrequire(rootfragrecptr.p->fragmentid[1] == fragId); jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[1]; }//if ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); fragrecptr.p->lcpLqhPtr = lqhPtr; fragrecptr.p->localCheckpId = lcpId; asrPageidptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(asrPageidptr, cpagesize, page8); ndbrequire(asrPageidptr.p->word32[ZPAGEZERO_TABID] == rootfragrecptr.p->mytabptr); ndbrequire(asrPageidptr.p->word32[ZPAGEZERO_FRAGID0] == rootfragrecptr.p->fragmentid[0]); ndbrequire(asrPageidptr.p->word32[ZPAGEZERO_FRAGID1] == rootfragrecptr.p->fragmentid[1]); initRootFragSr(rootfragrecptr, asrPageidptr); initFragSr(fragrecptr, asrPageidptr); for (Uint32 i = 0; i < ZMAX_UNDO_VERSION; i++) { jam(); if (csrVersList[i] != RNIL) { jam(); srVersionPtr.i = csrVersList[i]; ptrCheckGuard(srVersionPtr, csrVersionRecSize, srVersionRec); if (fragrecptr.p->localCheckpId == srVersionPtr.p->checkPointId) { jam(); ndbrequire(srVersionPtr.p->checkPointId == asrPageidptr.p->word32[ZPAGEZERO_NEXT_UNDO_FILE]); /*--------------------------------------------------------------------------------*/ /* SINCE -1 IS THE END OF LOG CODE WE MUST TREAT THIS CODE WITH CARE. WHEN */ /* COMPARING IT IS LARGER THAN EVERYTHING ELSE BUT SHOULD BE TREATED AS THE */ /* SMALLEST POSSIBLE VALUE, MEANING EMPTY. */ /*--------------------------------------------------------------------------------*/ if (fragrecptr.p->prevUndoposition != cminusOne) { if (srVersionPtr.p->prevAddress < fragrecptr.p->prevUndoposition) { jam(); srVersionPtr.p->prevAddress = fragrecptr.p->prevUndoposition; } else if (srVersionPtr.p->prevAddress == cminusOne) { jam(); srVersionPtr.p->prevAddress = fragrecptr.p->prevUndoposition; }//if }//if srAllocPage0011Lab(signal); return; }//if } else { jam(); seizeSrVerRec(signal); srVersionPtr.p->checkPointId = fragrecptr.p->localCheckpId; srVersionPtr.p->prevAddress = fragrecptr.p->prevUndoposition; csrVersList[i] = srVersionPtr.i; srAllocPage0011Lab(signal); return; }//if }//for ndbrequire(false); }//Dbacc::execACC_SRREQ() void Dbacc::releaseLogicalPage(Fragmentrec * fragP, Uint32 logicalPageId){ Ptr<struct DirRange> dirRangePtr; dirRangePtr.i = fragP->directory; ptrCheckGuard(dirRangePtr, cdirrangesize, dirRange); const Uint32 lp1 = logicalPageId >> 8; const Uint32 lp2 = logicalPageId & 0xFF; ndbrequire(lp1 < 256); Ptr<struct Directoryarray> dirArrPtr; dirArrPtr.i = dirRangePtr.p->dirArray[lp1]; ptrCheckGuard(dirArrPtr, cdirarraysize, directoryarray); const Uint32 physicalPageId = dirArrPtr.p->pagep[lp2]; rpPageptr.i = physicalPageId; ptrCheckGuard(rpPageptr, cpagesize, page8); releasePage(0); dirArrPtr.p->pagep[lp2] = RNIL; } void Dbacc::srAllocPage0011Lab(Signal* signal) { releaseLogicalPage(fragrecptr.p, 0); #if JONAS ndbrequire(cfirstfreeDirrange != RNIL); seizeDirrange(signal); fragrecptr.p->directory = newDirRangePtr.i; ndbrequire(cfirstfreeDirrange != RNIL); seizeDirrange(signal); fragrecptr.p->overflowdir = newDirRangePtr.i; seizeDirectory(signal); ndbrequire(tresult < ZLIMIT_OF_ERROR); newDirRangePtr.p->dirArray[0] = sdDirptr.i; #endif fragrecptr.p->nextAllocPage = 0; fragrecptr.p->fragState = SR_READ_PAGES; srReadPagesLab(signal); return; }//Dbacc::srAllocPage0011Lab() void Dbacc::srReadPagesLab(Signal* signal) { if (fragrecptr.p->nextAllocPage >= fragrecptr.p->noStoredPages) { /*--------------------------------------------------------------------------------*/ /* WE HAVE NOW READ ALL NORMAL PAGES FROM THE FILE. */ /*--------------------------------------------------------------------------------*/ if (fragrecptr.p->nextAllocPage == fragrecptr.p->dirsize) { jam(); /*--------------------------------------------------------------------------------*/ /* WE HAVE NOW READ ALL NORMAL PAGES AND ALLOCATED ALL THE NEEDED PAGES. */ /*--------------------------------------------------------------------------------*/ fragrecptr.p->nextAllocPage = 0; /* THE NEXT OVER FLOW PAGE WHICH WILL BE READ */ fragrecptr.p->fragState = SR_READ_OVER_PAGES; srReadOverPagesLab(signal); } else { ndbrequire(fragrecptr.p->nextAllocPage < fragrecptr.p->dirsize); jam(); /*--------------------------------------------------------------------------------*/ /* WE NEEDED TO ALLOCATE PAGES THAT WERE DEALLOCATED DURING THE LOCAL */ /* CHECKPOINT. */ /* ALLOCATE THE PAGE AND INITIALISE IT. THEN WE INSERT A REAL-TIME BREAK. */ /*--------------------------------------------------------------------------------*/ seizePage(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); tipPageId = fragrecptr.p->nextAllocPage; inpPageptr.i = spPageptr.i; ptrCheckGuard(inpPageptr, cpagesize, page8); initPage(signal); fragrecptr.p->noOfExpectedPages = 1; fragrecptr.p->datapages[0] = spPageptr.i; signal->theData[0] = ZSR_READ_PAGES_ALLOC; signal->theData[1] = fragrecptr.i; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB); }//if return; }//if Uint32 limitLoop; if ((fragrecptr.p->noStoredPages - fragrecptr.p->nextAllocPage) < ZWRITEPAGESIZE) { jam(); limitLoop = fragrecptr.p->noStoredPages - fragrecptr.p->nextAllocPage; } else { jam(); limitLoop = ZWRITEPAGESIZE; }//if ndbrequire(limitLoop <= 8); for (Uint32 i = 0; i < limitLoop; i++) { jam(); seizePage(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); fragrecptr.p->datapages[i] = spPageptr.i; signal->theData[i + 6] = spPageptr.i; }//for signal->theData[limitLoop + 6] = fragrecptr.p->activeDataFilePage; fragrecptr.p->noOfExpectedPages = limitLoop; /* -----------------SEND READ PAGES SIGNAL TO THE FILE MANAGER --------- */ fsConnectptr.i = fragrecptr.p->fsConnPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); fsConnectptr.p->fsState = WAIT_READ_DATA; signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = 2; /* FLAG = LIST MEM PAGES, RANGE OF FILE PAGES */ signal->theData[4] = ZPAGE8_BASE_ADD; signal->theData[5] = fragrecptr.p->noOfExpectedPages; sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA); return; }//Dbacc::srReadPagesLab() void Dbacc::storeDataPageInDirectoryLab(Signal* signal) { fragrecptr.p->activeDataFilePage += fragrecptr.p->noOfExpectedPages; srReadPagesAllocLab(signal); return; }//Dbacc::storeDataPageInDirectoryLab() void Dbacc::srReadPagesAllocLab(Signal* signal) { DirRangePtr srpDirRangePtr; DirectoryarrayPtr srpDirptr; DirectoryarrayPtr srpOverflowDirptr; Page8Ptr srpPageidptr; if (fragrecptr.p->fragState == SR_READ_PAGES) { jam(); for (Uint32 i = 0; i < fragrecptr.p->noOfExpectedPages; i++) { jam(); tmpP = fragrecptr.p->nextAllocPage; srpDirRangePtr.i = fragrecptr.p->directory; tmpP2 = tmpP >> 8; tmp = tmpP & 0xff; ptrCheckGuard(srpDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); if (srpDirRangePtr.p->dirArray[tmpP2] == RNIL) { seizeDirectory(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); srpDirptr.i = sdDirptr.i; srpDirRangePtr.p->dirArray[tmpP2] = srpDirptr.i; } else { jam(); srpDirptr.i = srpDirRangePtr.p->dirArray[tmpP2]; }//if ptrCheckGuard(srpDirptr, cdirarraysize, directoryarray); arrGuard(i, 8); srpDirptr.p->pagep[tmp] = fragrecptr.p->datapages[i]; srpPageidptr.i = fragrecptr.p->datapages[i]; ptrCheckGuard(srpPageidptr, cpagesize, page8); ndbrequire(srpPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage); ndbrequire(((srpPageidptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == 0); ccoPageptr.p = srpPageidptr.p; checksumControl(signal, (Uint32)1); if (tresult > 0) { jam(); return; // We will crash through a DEBUG_SIG }//if dbgWord32(srpPageidptr, ZPOS_OVERFLOWREC, RNIL); srpPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL; fragrecptr.p->datapages[i] = RNIL; fragrecptr.p->nextAllocPage++; }//for srReadPagesLab(signal); return; } else { ndbrequire(fragrecptr.p->fragState == SR_READ_OVER_PAGES); for (Uint32 i = 0; i < fragrecptr.p->noOfExpectedPages; i++) { jam(); arrGuard(i, 8); srpPageidptr.i = fragrecptr.p->datapages[i]; ptrCheckGuard(srpPageidptr, cpagesize, page8); tmpP = srpPageidptr.p->word32[ZPOS_PAGE_ID]; /* DIR INDEX OF THE OVERFLOW PAGE */ /*--------------------------------------------------------------------------------*/ /* IT IS POSSIBLE THAT WE HAVE LOGICAL PAGES WHICH ARE NOT PART OF THE LOCAL*/ /* CHECKPOINT. THUS WE USE THE LOGICAL PAGE ID FROM THE PAGE HERE. */ /*--------------------------------------------------------------------------------*/ srpDirRangePtr.i = fragrecptr.p->overflowdir; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; ptrCheckGuard(srpDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); if (srpDirRangePtr.p->dirArray[tmpP2] == RNIL) { jam(); seizeDirectory(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); srpDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i; }//if srpOverflowDirptr.i = srpDirRangePtr.p->dirArray[tmpP2]; ndbrequire(((srpPageidptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != 0); ndbrequire(((srpPageidptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != 3); ptrCheckGuard(srpOverflowDirptr, cdirarraysize, directoryarray); ndbrequire(srpOverflowDirptr.p->pagep[tmpP] == RNIL); srpOverflowDirptr.p->pagep[tmpP] = srpPageidptr.i; ccoPageptr.p = srpPageidptr.p; checksumControl(signal, (Uint32)1); ndbrequire(tresult == 0); dbgWord32(srpPageidptr, ZPOS_OVERFLOWREC, RNIL); srpPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL; fragrecptr.p->nextAllocPage++; }//for srReadOverPagesLab(signal); return; }//if }//Dbacc::srReadPagesAllocLab() void Dbacc::srReadOverPagesLab(Signal* signal) { if (fragrecptr.p->nextAllocPage >= fragrecptr.p->noOfStoredOverPages) { fragrecptr.p->nextAllocPage = 0; if (fragrecptr.p->prevUndoposition == cminusOne) { jam(); /* ************************ */ /* ACC_OVER_REC */ /* ************************ */ /*--------------------------------------------------------------------------------*/ /* UPDATE FREE LIST OF OVERFLOW PAGES AS PART OF SYSTEM RESTART AFTER */ /* READING PAGES AND EXECUTING THE UNDO LOG. */ /*--------------------------------------------------------------------------------*/ signal->theData[0] = fragrecptr.i; sendSignal(cownBlockref, GSN_ACC_OVER_REC, signal, 1, JBB); } else { jam(); srCloseDataFileLab(signal); }//if return; }//if Uint32 limitLoop; if ((fragrecptr.p->noOfStoredOverPages - fragrecptr.p->nextAllocPage) < ZWRITEPAGESIZE) { jam(); limitLoop = fragrecptr.p->noOfStoredOverPages - fragrecptr.p->nextAllocPage; } else { jam(); limitLoop = ZWRITEPAGESIZE; }//if ndbrequire(limitLoop <= 8); for (Uint32 i = 0; i < limitLoop; i++) { jam(); seizePage(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); fragrecptr.p->datapages[i] = spPageptr.i; signal->theData[i + 6] = spPageptr.i; }//for fragrecptr.p->noOfExpectedPages = limitLoop; signal->theData[limitLoop + 6] = fragrecptr.p->activeDataFilePage; /* -----------------SEND READ PAGES SIGNAL TO THE FILE MANAGER --------- */ fsConnectptr.i = fragrecptr.p->fsConnPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); fsConnectptr.p->fsState = WAIT_READ_DATA; signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = 2; signal->theData[4] = ZPAGE8_BASE_ADD; signal->theData[5] = fragrecptr.p->noOfExpectedPages; sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA); return; }//Dbacc::srReadOverPagesLab() void Dbacc::srCloseDataFileLab(Signal* signal) { fsConnectptr.i = fragrecptr.p->fsConnPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); fsConnectptr.p->fsState = SR_CLOSE_DATA; /* ************************ */ /* FSCLOSEREQ */ /* ************************ */ signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = 0; sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA); return; }//Dbacc::srCloseDataFileLab() /* ************************ */ /* ACC_SRCONF */ /* ************************ */ void Dbacc::sendaccSrconfLab(Signal* signal) { fragrecptr.i = fsConnectptr.p->fragrecPtr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); releaseFsConnRec(signal); rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); lcpConnectptr.i = rootfragrecptr.p->lcpPtr; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); fragrecptr.p->fragState = ACTIVEFRAG; fragrecptr.p->fsConnPtr = RNIL; for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) { fragrecptr.p->datapages[i] = RNIL; }//for rlpPageptr.i = fragrecptr.p->zeroPagePtr; ptrCheckGuard(rlpPageptr, cpagesize, page8); releaseLcpPage(signal); fragrecptr.p->zeroPagePtr = RNIL; signal->theData[0] = fragrecptr.p->lcpLqhPtr; sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_SRCONF, signal, 1, JBB); lcpConnectptr.p->noOfLcpConf++; if (lcpConnectptr.p->noOfLcpConf == 2) { jam(); releaseLcpConnectRec(signal); rootfragrecptr.p->lcpPtr = RNIL; rootfragrecptr.p->rootState = ACTIVEROOT; }//if return; }//Dbacc::sendaccSrconfLab() /* --------------------------------------------------------------------------------- */ /* CHECKSUM_CONTROL */ /* INPUT: CCO_PAGEPTR */ /* OUTPUT: TRESULT */ /* */ /* CHECK THAT CHECKSUM IN PAGE IS CORRECT TO ENSURE THAT NO ONE HAS CORRUPTED */ /* THE PAGE INFORMATION. WHEN CALCULATING THE CHECKSUM WE REMOVE THE CHECKSUM */ /* ITSELF FROM THE CHECKSUM BY XOR'ING THE CHECKSUM TWICE. WHEN CALCULATING */ /* THE CHECKSUM THE CHECKSUM WORD IS ZERO WHICH MEANS NO CHANGE FROM XOR'ING. */ /* --------------------------------------------------------------------------------- */ void Dbacc::checksumControl(Signal* signal, Uint32 checkPage) { Uint32 Tchs; Uint32 tccoIndex; Uint32 Ti; Uint32 Tmp1; Uint32 Tmp2; Uint32 Tmp3; Uint32 Tmp4; Uint32 Tlimit; Tchs = 0; for (Ti = 0; Ti < 32 ; Ti++) { Tlimit = 16 + (Ti << 6); for (tccoIndex = (Ti << 6); tccoIndex < Tlimit; tccoIndex ++) { Tmp1 = ccoPageptr.p->word32[tccoIndex]; Tmp2 = ccoPageptr.p->word32[tccoIndex + 16]; Tmp3 = ccoPageptr.p->word32[tccoIndex + 32]; Tmp4 = ccoPageptr.p->word32[tccoIndex + 48]; Tchs = Tchs ^ Tmp1; Tchs = Tchs ^ Tmp2; Tchs = Tchs ^ Tmp3; Tchs = Tchs ^ Tmp4; }//for }//for if (Tchs == 0) { tresult = 0; if (checkPage != 0) { jam(); lcnCopyPageptr.p = ccoPageptr.p; srCheckPage(signal); }//if } else { tresult = 1; }//if if (tresult != 0) { jam(); rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); signal->theData[0] = RNIL; signal->theData[1] = rootfragrecptr.p->mytabptr; signal->theData[2] = fragrecptr.p->myfid; signal->theData[3] = ccoPageptr.p->word32[ZPOS_PAGE_ID]; signal->theData[4] = tlupElemIndex; signal->theData[5] = ccoPageptr.p->word32[ZPOS_PAGE_TYPE]; signal->theData[6] = tresult; sendSignal(cownBlockref, GSN_DEBUG_SIG, signal, 7, JBA); }//if }//Dbacc::checksumControl() /* ******************--------------------------------------------------------------- */ /* START_RECREQ REQUEST TO START UNDO PROCESS */ /* SENDER: LQH, LEVEL B */ /* ENTER START_RECREQ WITH */ /* CLQH_PTR, LQH CONNECTION PTR */ /* CLQH_BLOCK_REF, LQH BLOCK REFERENCE */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* START_RECREQ REQUEST TO START UNDO PROCESS */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execSTART_RECREQ(Signal* signal) { jamEntry(); clqhPtr = signal->theData[0]; /* LQH CONNECTION PTR */ clqhBlockRef = signal->theData[1]; /* LQH BLOCK REFERENCE */ tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */ for (int i = 0; i < UndoHeader::ZNO_UNDORECORD_TYPES; i++) cSrUndoRecords[i] = 0; startUndoLab(signal); return; }//Dbacc::execSTART_RECREQ() void Dbacc::startUndoLab(Signal* signal) { cundoLogActive = ZTRUE; /* ----- OPEN UNDO FILES --------- */ for (tmp = 0; tmp <= ZMAX_UNDO_VERSION - 1; tmp++) { jam(); if (csrVersList[tmp] != RNIL) { jam(); /*---------------------------------------------------------------------------*/ /* SELECT THE NEXT SYSTEM RESTART RECORD WHICH CONTAINS AN UNDO LOG */ /* THAT NEEDS TO BE EXECUTED AND SET UP THE DATA TO EXECUTE IT. */ /*---------------------------------------------------------------------------*/ srVersionPtr.i = csrVersList[tmp]; csrVersList[tmp] = RNIL; ptrCheckGuard(srVersionPtr, csrVersionRecSize, srVersionRec); cactiveUndoFilePage = srVersionPtr.p->prevAddress >> 13; cprevUndoaddress = srVersionPtr.p->prevAddress; cactiveCheckpId = srVersionPtr.p->checkPointId; releaseSrRec(signal); startActiveUndo(signal); return; }//if }//for // Send report of how many undo log records where executed signal->theData[0] = EventReport::UNDORecordsExecuted; signal->theData[1] = DBACC; // From block signal->theData[2] = 0; // Total records executed for (int i = 0; i < 10; i++){ if (i < UndoHeader::ZNO_UNDORECORD_TYPES){ signal->theData[i+3] = cSrUndoRecords[i]; signal->theData[2] += cSrUndoRecords[i]; }else{ signal->theData[i+3] = 0; } } sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 12, JBB); /* ******************************< */ /* START_RECCONF */ /* ******************************< */ /*---------------------------------------------------------------------------*/ /* REPORT COMPLETION OF UNDO LOG EXECUTION. */ /*---------------------------------------------------------------------------*/ cundoLogActive = ZFALSE; signal->theData[0] = clqhPtr; sendSignal(clqhBlockRef, GSN_START_RECCONF, signal, 1, JBB); /* LQH CONNECTION PTR */ return; }//Dbacc::startUndoLab() /*---------------------------------------------------------------------------*/ /* START THE UNDO OF AN UNDO LOG FILE BY OPENING THE UNDO LOG FILE. */ /*---------------------------------------------------------------------------*/ void Dbacc::startActiveUndo(Signal* signal) { if (cprevUndoaddress == cminusOne) { jam(); /*---------------------------------------------------------------------------*/ /* THERE WAS NO UNDO LOG INFORMATION IN THIS LOG FILE. WE GET THE NEXT */ /* OR REPORT COMPLETION. */ /*---------------------------------------------------------------------------*/ signal->theData[0] = ZSTART_UNDO; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 1, JBB); } else { jam(); /*---------------------------------------------------------------------------*/ /* OPEN THE LOG FILE PERTAINING TO THIS UNDO LOG. */ /*---------------------------------------------------------------------------*/ if (cfsFirstfreeconnect == RNIL) { jam(); sendSystemerror(signal); }//if seizeFsConnectRec(signal); cactiveSrFsPtr = fsConnectptr.i; fsConnectptr.p->fsState = OPEN_UNDO_FILE_SR; fsConnectptr.p->fsPart = 0; tmp1 = 1; /* FILE VERSION ? */ tmp1 = (tmp1 << 8) + ZLOCALLOGFILE; /* .LOCLOG = 2 */ tmp1 = (tmp1 << 8) + 4; /* ROOT DIRECTORY = D4 */ tmp1 = (tmp1 << 8) + fsConnectptr.p->fsPart; /* P2 */ tmp2 = 0x0; /* D7 DON'T CREATE , READ ONLY */ /* DON'T TRUNCATE TO ZERO */ /* ---FILE NAME "D4"/"DBACC"/LCP_CONNECTPTR:LOCAL_CHECK_PID/FS_CONNECTPTR:FS_PART".LOCLOG-- */ /* ************************ */ /* FSOPENREQ */ /* ************************ */ signal->theData[0] = cownBlockref; signal->theData[1] = fsConnectptr.i; signal->theData[2] = cminusOne; /* #FFFFFFFF */ signal->theData[3] = cminusOne; /* #FFFFFFFF */ signal->theData[4] = cactiveCheckpId; /* CHECKPOINT VERSION */ signal->theData[5] = tmp1; signal->theData[6] = tmp2; sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA); }//if }//Dbacc::startActiveUndo() /* ------- READ A GROUP OF UNDO PAGES --------------- */ void Dbacc::srStartUndoLab(Signal* signal) { /*---------------------------------------------------------------------------*/ /* ALL LOG FILES HAVE BEEN OPENED. WE CAN NOW READ DATA FROM THE LAST */ /* PAGE IN THE LAST LOG FILE AND BACKWARDS UNTIL WE REACH THE VERY */ /* FIRST UNDO LOG RECORD. */ /*---------------------------------------------------------------------------*/ if (cactiveUndoFilePage >= ZWRITE_UNDOPAGESIZE) { jam(); tmp1 = ZWRITE_UNDOPAGESIZE; /* NO OF READ UNDO PAGES */ cactiveSrUndoPage = ZWRITE_UNDOPAGESIZE - 1; /* LAST PAGE */ } else { jam(); tmp1 = cactiveUndoFilePage + 1; /* NO OF READ UNDO PAGES */ cactiveSrUndoPage = cactiveUndoFilePage; }//if fsConnectptr.i = cactiveSrFsPtr; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); signal->theData[0] = fsConnectptr.p->fsPtr; signal->theData[1] = cownBlockref; signal->theData[2] = fsConnectptr.i; signal->theData[3] = 0; /* FLAG = LIST MEM PAGES, LIST FILE PAGES */ signal->theData[4] = ZUNDOPAGE_BASE_ADD; signal->theData[5] = tmp1; signal->theData[6] = 0; signal->theData[7] = (cactiveUndoFilePage - tmp1) + 1; signal->theData[8] = 1; signal->theData[9] = cactiveUndoFilePage; sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 10, JBA); if (tmp1 > cactiveUndoFilePage) { jam(); /*---------------------------------------------------------------------------*/ /* THIS IS THE LAST READ IN THIS LOG FILE. WE SET THE ACTIVE FILE */ /* POINTER. IF IT IS THE FIRST WE SHOULD NEVER ATTEMPT ANY MORE READS */ /* SINCE WE SHOULD ENCOUNTER A FIRST LOG RECORD WITH PREVIOUS PAGE ID */ /* EQUAL TO RNIL. */ /*---------------------------------------------------------------------------*/ cactiveSrFsPtr = RNIL; fsConnectptr.p->fsState = READ_UNDO_PAGE_AND_CLOSE; } else { jam(); /*---------------------------------------------------------------------------*/ /* WE STILL HAVE MORE INFORMATION IN THIS LOG FILE. WE ONLY MOVE BACK */ /* THE FILE PAGE. */ /*---------------------------------------------------------------------------*/ cactiveUndoFilePage = cactiveUndoFilePage - tmp1; fsConnectptr.p->fsState = READ_UNDO_PAGE; }//if return; }//Dbacc::srStartUndoLab() /* ------- DO UNDO ---------------------------*/ /* ******************--------------------------------------------------------------- */ /* NEXTOPERATION ORD FOR EXECUTION OF NEXT OP */ /* ******************------------------------------+ */ /* SENDER: ACC, LEVEL B */ void Dbacc::execNEXTOPERATION(Signal* signal) { jamEntry(); tresult = 0; srDoUndoLab(signal); return; }//Dbacc::execNEXTOPERATION() void Dbacc::srDoUndoLab(Signal* signal) { DirRangePtr souDirRangePtr; DirectoryarrayPtr souDirptr; Page8Ptr souPageidptr; Uint32 tundoPageindex; UndoHeader *undoHeaderPtr; Uint32 tmpindex; jam(); undopageptr.i = cactiveSrUndoPage; ptrCheckGuard(undopageptr, cundopagesize, undopage); /*---------------------------------------------------------------------------*/ /* LAYOUT OF AN UNDO LOG RECORD: */ /* ***************************** */ /* */ /* |----------------------------------------------------| */ /* | TABLE ID | */ /* |----------------------------------------------------| */ /* | ROOT FRAGMENT ID | */ /* |----------------------------------------------------| */ /* | LOCAL FRAGMENT ID | */ /* |----------------------------------------------------| */ /* | UNDO INFO LEN 14 b | TYPE 4 b | PAGE INDEX 14 b | */ /* |----------------------------------------------------| */ /* | INDEX INTO PAGE DIRECTORY (LOGICAL PAGE ID) | */ /* |----------------------------------------------------| */ /* | PREVIOUS UNDO LOG RECORD FOR THE FRAGMENT | */ /* |----------------------------------------------------| */ /* | PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS | */ /* |----------------------------------------------------| */ /* | TYPE SPECIFIC PART | */ /* |----------------------------------------------------| */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* SET THE PAGE POINTER. WE ONLY WORK WITH TWO PAGES IN THIS RESTART */ /* ACTIVITY. GET THE PAGE POINTER AND THE PAGE INDEX TO READ FROM. */ /*---------------------------------------------------------------------------*/ tundoindex = cprevUndoaddress & ZUNDOPAGEINDEX_MASK; //0x1fff, 13 bits. undoHeaderPtr = (UndoHeader *) &undopageptr.p->undoword[tundoindex]; tundoindex = tundoindex + ZUNDOHEADSIZE; /*------------------------------------------------------------------------*/ /* READ TABLE ID AND ROOT FRAGMENT ID AND USE THIS TO GET ROOT RECORD. */ /*------------------------------------------------------------------------*/ arrGuard((tundoindex + 6), 8192); // TABLE ID tabptr.i = undoHeaderPtr->tableId; ptrCheckGuard(tabptr, ctablesize, tabrec); // ROOT FRAGMENT ID tfid = undoHeaderPtr->rootFragId; if (!getrootfragmentrec(signal, rootfragrecptr, tfid)) { jam(); /*---------------------------------------------------------------------*/ /* THE ROOT RECORD WAS NOT FOUND. OBVIOUSLY WE ARE NOT RESTARTING THIS */ /* FRAGMENT. WE THUS IGNORE THIS LOG RECORD AND PROCEED WITH THE NEXT. */ /*---------------------------------------------------------------------*/ creadyUndoaddress = cprevUndoaddress; // PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS cprevUndoaddress = undoHeaderPtr->prevUndoAddress; undoNext2Lab(signal); return; }//if /*-----------------------------------------------------------------------*/ /* READ THE LOCAL FRAGMENT ID AND VERIFY THAT IT IS CORRECT. */ /*-----------------------------------------------------------------------*/ if (rootfragrecptr.p->fragmentid[0] == undoHeaderPtr->localFragId) { jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); } else { if (rootfragrecptr.p->fragmentid[1] == undoHeaderPtr->localFragId) { jam(); fragrecptr.i = rootfragrecptr.p->fragmentptr[1]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); } else { jam(); progError(__LINE__, 0, "Invalid local fragment id in undo log"); return; }//if }//if /*------------------------------------------------------------------------*/ /* READ UNDO INFO LENGTH, TYPE OF LOG RECORD AND PAGE INDEX WHERE TO */ /* APPLY THIS LOG RECORD. ALSO STEP INDEX TO PREPARE READ OF LOGICAL */ /* PAGE ID. SET TMPINDEX TO INDEX THE FIRST WORD IN THE TYPE SPECIFIC */ /* PART. */ /*------------------------------------------------------------------------*/ // UNDO INFO LENGTH 14 b | TYPE 4 b | PAGE INDEX 14 b const Uint32 tmp1 = undoHeaderPtr->variousInfo; cundoinfolength = tmp1 >> 18; const Uint32 tpageType = (tmp1 >> 14) & 0xf; tundoPageindex = tmp1 & 0x3fff; // INDEX INTO PAGE DIRECTORY (LOGICAL PAGE ID) tmpP = undoHeaderPtr->logicalPageId ; tmpindex = tundoindex; arrGuard((tmpindex + cundoinfolength - 1), 8192); if (fragrecptr.p->localCheckpId != cactiveCheckpId) { jam(); /*-----------------------------------------------------------------------*/ /* THE FRAGMENT DID EXIST BUT IS NOT AFFECTED BY THIS UNDO LOG */ /* EXECUTION. EITHER IT BELONGS TO ANOTHER OR IT IS CREATED AND ONLY IN */ /* NEED OF EXECUTION OF REDO LOG RECORDS FROM LQH. */ /*-----------------------------------------------------------------------*/ creadyUndoaddress = cprevUndoaddress; // PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS cprevUndoaddress = undoHeaderPtr->prevUndoAddress; undoNext2Lab(signal); return; }//if /*-----------------------------------------------------------------------*/ /* VERIFY CONSISTENCY OF UNDO LOG RECORDS. */ /*-----------------------------------------------------------------------*/ ndbrequire(fragrecptr.p->prevUndoposition == cprevUndoaddress); cSrUndoRecords[tpageType]++; switch(tpageType){ case UndoHeader::ZPAGE_INFO:{ jam(); /*----------------------------------------------------------------------*/ /* WE HAVE TO UNDO UPDATES IN A NORMAL PAGE. GET THE PAGE POINTER BY */ /* USING THE LOGICAL PAGE ID. THEN RESET THE OLD VALUE IN THE PAGE BY */ /* USING THE OLD DATA WHICH IS STORED IN THIS UNDO LOG RECORD. */ /*----------------------------------------------------------------------*/ souDirRangePtr.i = fragrecptr.p->directory; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); souDirptr.i = souDirRangePtr.p->dirArray[tmpP2]; ptrCheckGuard(souDirptr, cdirarraysize, directoryarray); souPageidptr.i = souDirptr.p->pagep[tmpP]; ptrCheckGuard(souPageidptr, cpagesize, page8); Uint32 loopLimit = tundoPageindex + cundoinfolength; ndbrequire(loopLimit <= 2048); for (Uint32 tmp = tundoPageindex; tmp < loopLimit; tmp++) { dbgWord32(souPageidptr, tmp, undopageptr.p->undoword[tmpindex]); souPageidptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex]; tmpindex = tmpindex + 1; }//for break; } case UndoHeader::ZOVER_PAGE_INFO:{ jam(); /*----------------------------------------------------------------------*/ /* WE HAVE TO UNDO UPDATES IN AN OVERFLOW PAGE. GET THE PAGE POINTER BY*/ /* USING THE LOGICAL PAGE ID. THEN RESET THE OLD VALUE IN THE PAGE BY */ /* USING THE OLD DATA WHICH IS STORED IN THIS UNDO LOG RECORD. */ /*----------------------------------------------------------------------*/ souDirRangePtr.i = fragrecptr.p->overflowdir; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); souDirptr.i = souDirRangePtr.p->dirArray[tmpP2]; ptrCheckGuard(souDirptr, cdirarraysize, directoryarray); souPageidptr.i = souDirptr.p->pagep[tmpP]; ptrCheckGuard(souPageidptr, cpagesize, page8); Uint32 loopLimit = tundoPageindex + cundoinfolength; ndbrequire(loopLimit <= 2048); for (Uint32 tmp = tundoPageindex; tmp < loopLimit; tmp++) { dbgWord32(souPageidptr, tmp, undopageptr.p->undoword[tmpindex]); souPageidptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex]; tmpindex = tmpindex + 1; }//for break; } case UndoHeader::ZUNDO_INSERT_LONG_KEY:{ jam(); /*---------------------------------------------------------------------*/ /* WE WILL UNDO AN INSERT OF A LONG KEY. THIS IS PERFORMED BY DELETING */ /* THE LONG KEY. */ /*---------------------------------------------------------------------*/ souDirRangePtr.i = fragrecptr.p->overflowdir; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; arrGuard(tmpP2, 256); ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange); souDirptr.i = souDirRangePtr.p->dirArray[tmpP2]; ptrCheckGuard(souDirptr, cdirarraysize, directoryarray); dlkPageptr.i = souDirptr.p->pagep[tmpP]; ptrCheckGuard(dlkPageptr, cpagesize, page8); tdlkLogicalPageIndex = tundoPageindex; deleteLongKey(signal); break; } case UndoHeader::ZUNDO_DELETE_LONG_KEY: { jam(); /*----------------------------------------------------------------------*/ /* WE WILL UNDO DELETE OF A LONG KEY. THIS IS PERFORMED BY INSERTING */ /* IT AGAIN. */ /*----------------------------------------------------------------------*/ souDirRangePtr.i = fragrecptr.p->overflowdir; taslpDirIndex = tmpP; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); souDirptr.i = souDirRangePtr.p->dirArray[tmpP2]; if(souDirptr.i == RNIL) { //---------------------------------------------------------------- // Allocate a directory. //---------------------------------------------------------------- jam(); seizeDirectory(signal); if (tresult > ZLIMIT_OF_ERROR) { jam(); sendSystemerror(signal); return; } souDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i; souDirptr.i = souDirRangePtr.p->dirArray[tmpP2]; } ptrCheckGuard(souDirptr, cdirarraysize, directoryarray); slkapPageptr.i = souDirptr.p->pagep[tmpP]; if(slkapPageptr.i == RNIL) { //---------------------------------------------------------------- // The delete operation was probably the last on the page and the // page was released and not written down to disk. We need to // allocate a page and put it in the same dirindex as it was in // before it was released. // This is because an eventual UNDO_INSERT on the same key in the // same LCP must be able to find the key and it has only the // dirindex to go on, the key itself is not saved on disk in a // UNDO_INSERT. //---------------------------------------------------------------- jam(); allocSpecificLongOverflowPage(signal); slkapPageptr.i = aslpPageptr.i; } ptrCheckGuard(slkapPageptr, cpagesize, page8); seizePage(signal); ndbrequire(tresult <= ZLIMIT_OF_ERROR); slkapCopyPageptr = spPageptr; ndbrequire(cundoinfolength <= 2048); for (Uint32 tmp = 0; tmp < cundoinfolength; tmp++) { dbgWord32(slkapCopyPageptr, tmp, undopageptr.p->undoword[tmpindex]); slkapCopyPageptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex]; tmpindex = tmpindex + 1; }//for jam(); //---------------------------------------------------------------- // We must store the key at the same place it was deleted from. // This is because an eventual UNDO_INSERT on the same key in the // same LCP must be able to find the key and it has only the index // information stored on disk to go on, the key itself is not // saved on disk in an UNDO_INSERT. //---------------------------------------------------------------- tslkapKeyLen = cundoinfolength; tslkapPageIndex = tundoPageindex; storeLongKeysAtPos(signal); rpPageptr = slkapCopyPageptr; releasePage(signal); break; } case UndoHeader::ZOP_INFO: { jam(); /*---------------------------------------------------------------------*/ /* AN OPERATION WAS ACTIVE WHEN LOCAL CHECKPOINT WAS EXECUTED. WE NEED */ /* TO RESET THE LOCKS IT HAS SET. IF THE OPERATION WAS AN INSERT OR */ /* THE ELEMENT WAS MARKED AS DISSAPEARED IT WILL ALSO BE REMOVED */ /* FROM THE PAGE */ /* */ /* BEGIN BY SEARCHING AFTER THE ELEMENT, WHEN FOUND UNDO THE */ /* CHANGES ON THE ELEMENT HEADER. IF IT WAS AN INSERT OPERATION OR */ /* MARKED AS DISSAPEARED PROCEED BY REMOVING THE ELEMENT. */ /*---------------------------------------------------------------------*/ seizeOpRec(signal); // Initialise the opRec operationRecPtr.p->transId1 = 0; operationRecPtr.p->transId2 = RNIL; operationRecPtr.p->transactionstate = ACTIVE; operationRecPtr.p->commitDeleteCheckFlag = ZFALSE; operationRecPtr.p->lockMode = 0; operationRecPtr.p->dirtyRead = 0; operationRecPtr.p->nodeType = 0; operationRecPtr.p->fid = fragrecptr.p->myfid; operationRecPtr.p->nextParallelQue = RNIL; operationRecPtr.p->prevParallelQue = RNIL; operationRecPtr.p->nextQueOp = RNIL; operationRecPtr.p->prevQueOp = RNIL; operationRecPtr.p->nextSerialQue = RNIL; operationRecPtr.p->prevSerialQue = RNIL; operationRecPtr.p->elementPage = RNIL; operationRecPtr.p->keyinfoPage = RNIL; operationRecPtr.p->insertIsDone = ZFALSE; operationRecPtr.p->lockOwner = ZFALSE; operationRecPtr.p->elementIsDisappeared = ZFALSE; operationRecPtr.p->insertDeleteLen = fragrecptr.p->elementLength; operationRecPtr.p->longPagePtr = RNIL; operationRecPtr.p->longKeyPageIndex = RNIL; operationRecPtr.p->scanRecPtr = RNIL; operationRecPtr.p->isAccLockReq = ZFALSE; // Read operation values from undo page operationRecPtr.p->operation = undopageptr.p->undoword[tmpindex]; tmpindex++; operationRecPtr.p->hashValue = undopageptr.p->undoword[tmpindex]; tmpindex++; const Uint32 tkeylen = undopageptr.p->undoword[tmpindex]; tmpindex++; operationRecPtr.p->tupkeylen = tkeylen; operationRecPtr.p->fragptr = fragrecptr.i; ndbrequire((fragrecptr.p->keyLength == 0) || ((fragrecptr.p->keyLength != 0) && (fragrecptr.p->keyLength == tkeylen))); // Read keydata from undo page for (Uint32 tmp = 0; tmp < tkeylen; tmp++) { signal->theData[7+tmp] = undopageptr.p->undoword[tmpindex]; tmpindex = tmpindex + 1; }//for arrGuard((tmpindex - 1), 8192); getElement(signal); if (tgeResult != ZTRUE) { jam(); signal->theData[0] = RNIL; signal->theData[1] = tabptr.i; signal->theData[2] = cactiveCheckpId; signal->theData[3] = cprevUndoaddress; signal->theData[4] = operationRecPtr.p->operation; signal->theData[5] = operationRecPtr.p->hashValue; signal->theData[6] = operationRecPtr.p->tupkeylen; sendSignal(cownBlockref, GSN_DEBUG_SIG, signal, 11, JBA); return; }//if operationRecPtr.p->elementPage = gePageptr.i; operationRecPtr.p->elementContainer = tgeContainerptr; operationRecPtr.p->elementPointer = tgeElementptr; operationRecPtr.p->elementIsforward = tgeForward; commitdelete(signal, true); releaseOpRec(signal); break; } default: jam(); progError(__LINE__, 0, "Invalid pagetype in undo log"); break; }//switch(tpageType) /*----------------------------------------------------------------------*/ /* READ THE PAGE ID AND THE PAGE INDEX OF THE PREVIOUS UNDO LOG RECORD */ /* FOR THIS FRAGMENT. */ /*----------------------------------------------------------------------*/ fragrecptr.p->prevUndoposition = undoHeaderPtr->prevUndoAddressForThisFrag; /*----------------------------------------------------------------------*/ /* READ THE PAGE ID AND THE PAGE INDEX OF THE PREVIOUS UNDO LOG RECORD */ /* FOR THIS UNDO LOG. */ /*----------------------------------------------------------------------*/ creadyUndoaddress = cprevUndoaddress; cprevUndoaddress = undoHeaderPtr->prevUndoAddress; if (fragrecptr.p->prevUndoposition == cminusOne) { jam(); /*---------------------------------------------------------------------*/ /* WE HAVE NOW EXECUTED ALL UNDO LOG RECORDS FOR THIS FRAGMENT. WE */ /* NOW NEED TO UPDATE THE FREE LIST OF OVERFLOW PAGES. */ /*---------------------------------------------------------------------*/ ndbrequire(fragrecptr.p->nextAllocPage == 0); signal->theData[0] = fragrecptr.i; sendSignal(cownBlockref, GSN_ACC_OVER_REC, signal, 1, JBB); return; }//if undoNext2Lab(signal); return; }//Dbacc::srDoUndoLab() void Dbacc::undoNext2Lab(Signal* signal) { /*---------------------------------------------------------------------------*/ /* EXECUTE NEXT UNDO LOG RECORD. */ /*---------------------------------------------------------------------------*/ if (cprevUndoaddress == cminusOne) { jam(); /*---------------------------------------------------------------------------*/ /* WE HAVE EXECUTED THIS UNDO LOG TO COMPLETION. IT IS NOW TIME TO TAKE*/ /* OF THE NEXT UNDO LOG OR REPORT COMPLETION OF UNDO LOG EXECUTION. */ /*---------------------------------------------------------------------------*/ signal->theData[0] = ZSTART_UNDO; sendSignal(cownBlockref, GSN_CONTINUEB, signal, 1, JBB); return; }//if if ((creadyUndoaddress >> 13) != (cprevUndoaddress >> 13)) { /*---------------------------------------------------------------------------*/ /* WE ARE CHANGING PAGE. */ /*---------------------------------------------------------------------------*/ if (cactiveSrUndoPage == 0) { jam(); /*---------------------------------------------------------------------------*/ /* WE HAVE READ AND EXECUTED ALL UNDO LOG INFORMATION IN THE CURRENTLY */ /* READ PAGES. WE STILL HAVE MORE INFORMATION TO READ FROM FILE SINCE */ /* WE HAVEN'T FOUND THE FIRST LOG RECORD IN THE LOG FILE YET. */ /*---------------------------------------------------------------------------*/ srStartUndoLab(signal); return; } else { jam(); /*---------------------------------------------------------------------------*/ /* WE HAVE ANOTHER PAGE READ THAT WE NEED TO EXECUTE. */ /*---------------------------------------------------------------------------*/ cactiveSrUndoPage = cactiveSrUndoPage - 1; }//if }//if /*---------------------------------------------------------------------------*/ /* REAL-TIME BREAK */ /*---------------------------------------------------------------------------*/ /* ******************************< */ /* NEXTOPERATION */ /* ******************************< */ sendSignal(cownBlockref, GSN_NEXTOPERATION, signal, 1, JBB); return; }//Dbacc::undoNext2Lab() /*-----------------------------------------------------------------------------------*/ /* AFTER COMPLETING THE READING OF DATA PAGES FROM DISK AND EXECUTING THE UNDO */ /* LOG WE ARE READY TO UPDATE THE FREE LIST OF OVERFLOW PAGES. THIS LIST MUST */ /* BE BUILT AGAIN SINCE IT IS NOT CHECKPOINTED. WHEN THE PAGES ARE ALLOCATED */ /* THEY ARE NOT PART OF ANY LIST. PAGES CAN EITHER BE PUT IN FREE LIST, NOT */ /* IN FREE LIST OR BE PUT INTO LIST OF LONG KEY PAGES. */ /*-----------------------------------------------------------------------------------*/ void Dbacc::execACC_OVER_REC(Signal* signal) { DirRangePtr pnoDirRangePtr; DirectoryarrayPtr pnoOverflowDirptr; Page8Ptr pnoPageidptr; Uint32 tpnoPageType; Uint32 toverPageCheck; jamEntry(); fragrecptr.i = signal->theData[0]; toverPageCheck = 0; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); ndbrequire((fragrecptr.p->nextAllocPage != 0) || (fragrecptr.p->firstOverflowRec == RNIL)); /*-----------------------------------------------------------------------------------*/ /* WHO HAS PUT SOMETHING INTO THE LIST BEFORE WE EVEN STARTED PUTTING THINGS */ /* THERE. */ /*-----------------------------------------------------------------------------------*/ ndbrequire(fragrecptr.p->loadingFlag == ZTRUE); /*---------------------------------------------------------------------------*/ /* LOADING HAS STOPPED BEFORE WE HAVE LOADED, SYSTEM ERROR. */ /*---------------------------------------------------------------------------*/ while (toverPageCheck < ZNO_OF_OP_PER_SIGNAL) { jam(); if (fragrecptr.p->nextAllocPage >= fragrecptr.p->lastOverIndex) { jam(); fragrecptr.p->loadingFlag = ZFALSE; rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); if (rootfragrecptr.p->lcpPtr != RNIL) { jam(); srCloseDataFileLab(signal); } else { jam(); undoNext2Lab(signal); }//if return; }//if tmpP = fragrecptr.p->nextAllocPage; pnoDirRangePtr.i = fragrecptr.p->overflowdir; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; arrGuard(tmpP2, 256); ptrCheckGuard(pnoDirRangePtr, cdirrangesize, dirRange); if (pnoDirRangePtr.p->dirArray[tmpP2] == RNIL) { jam(); pnoPageidptr.i = RNIL; } else { pnoOverflowDirptr.i = pnoDirRangePtr.p->dirArray[tmpP2]; if (pnoOverflowDirptr.i == RNIL) { jam(); pnoPageidptr.i = RNIL; } else { jam(); ptrCheckGuard(pnoOverflowDirptr, cdirarraysize, directoryarray); pnoPageidptr.i = pnoOverflowDirptr.p->pagep[tmpP]; }//if }//if if (pnoPageidptr.i == RNIL) { jam(); seizeOverRec(signal); sorOverflowRecPtr.p->dirindex = fragrecptr.p->nextAllocPage; sorOverflowRecPtr.p->overpage = RNIL; priOverflowRecPtr = sorOverflowRecPtr; putRecInFreeOverdir(signal); } else { ptrCheckGuard(pnoPageidptr, cpagesize, page8); tpnoPageType = pnoPageidptr.p->word32[ZPOS_PAGE_TYPE]; tpnoPageType = (tpnoPageType >> ZPOS_PAGE_TYPE_BIT) & 3; if (tpnoPageType == ZLONG_PAGE_TYPE) { jam(); // This is to clean the list parameters. pnoPageidptr.p->word32[ZPOS_PREV_PAGE] = RNIL; pnoPageidptr.p->word32[ZPOS_NEXT_PAGE] = RNIL; if (pnoPageidptr.p->word32[ZPOS_ARRAY_POS] != 4) { jam(); /*---------------------------------------------------------------------------*/ /* THE PAGE WAS A LONG PAGE AND IT BELONGED TO A FREE LIST. PUT IT INTO ONE */ /* OF THE FREE LIST THEN. */ /*---------------------------------------------------------------------------*/ // Insert page! ipaPagePtr = pnoPageidptr; tipaArrayPos = pnoPageidptr.p->word32[ZPOS_ARRAY_POS]; insertPageArrayList(signal); }//if } else { if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) { jam(); dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL); pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL; ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage); } else { jam(); seizeOverRec(signal); sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID]; ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage); dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i); pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i; sorOverflowRecPtr.p->overpage = pnoPageidptr.i; porOverflowRecPtr = sorOverflowRecPtr; putOverflowRecInFrag(signal); if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) { jam(); ropPageptr = pnoPageidptr; releaseOverpage(signal); }//if }//if }//if }//if fragrecptr.p->nextAllocPage++; toverPageCheck++; }//while signal->theData[0] = fragrecptr.i; sendSignal(cownBlockref, GSN_ACC_OVER_REC, signal, 1, JBB); }//Dbacc::execACC_OVER_REC() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF SYSTEM RESTART MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* SCAN MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACC_SCANREQ START OF A SCAN PROCESS */ /* SENDER: LQH, LEVEL B */ /* ENTER ACC_SCANREQ WITH */ /* TUSERPTR, LQH SCAN_CONNECT POINTER */ /* TUSERBLOCKREF, LQH BLOCK REFERENCE */ /* TABPTR, TABLE IDENTITY AND PTR */ /* TFID ROOT FRAGMENT IDENTITY */ /* TSCAN_FLAG , = ZCOPY, ZSCAN, ZSCAN_LOCK_ALL */ /* ZREADLOCK, ZWRITELOCK */ /* TSCAN_TRID1 , TRANSACTION ID PART 1 */ /* TSCAN_TRID2 TRANSACTION ID PART 2 */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACC_SCANREQ START OF A SCAN PROCESS */ /* ******************------------------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execACC_SCANREQ(Signal* signal) { jamEntry(); AccScanReq * req = (AccScanReq*)&signal->theData[0]; tuserptr = req->senderData; tuserblockref = req->senderRef; tabptr.i = req->tableId; tfid = req->fragmentNo; tscanFlag = req->requestInfo; tscanTrid1 = req->transId1; tscanTrid2 = req->transId2; tresult = 0; ptrCheckGuard(tabptr, ctablesize, tabrec); ndbrequire(getrootfragmentrec(signal,rootfragrecptr, tfid)); Uint32 i; for (i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) { jam(); if (rootfragrecptr.p->scan[i] == RNIL) { jam(); break; } } ndbrequire(i != MAX_PARALLEL_SCANS_PER_FRAG); ndbrequire(cfirstFreeScanRec != RNIL); seizeScanRec(signal); rootfragrecptr.p->scan[i] = scanPtr.i; scanPtr.p->scanBucketState = ScanRec::FIRST_LAP; scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag); scanPtr.p->scanKeyinfoFlag = AccScanReq::getKeyinfoFlag(tscanFlag); scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag); /* TWELVE BITS OF THE ELEMENT HEAD ARE SCAN */ /* CHECK BITS. THE MASK NOTES WHICH BIT IS */ /* ALLOCATED FOR THE ACTIVE SCAN */ scanPtr.p->scanMask = 1 << i; scanPtr.p->scanUserptr = tuserptr; scanPtr.p->scanUserblockref = tuserblockref; scanPtr.p->scanTrid1 = tscanTrid1; scanPtr.p->scanTrid2 = tscanTrid2; scanPtr.p->rootPtr = rootfragrecptr.i; scanPtr.p->scanLockHeld = 0; scanPtr.p->scanOpsAllocated = 0; scanPtr.p->scanFirstActiveOp = RNIL; scanPtr.p->scanFirstQueuedOp = RNIL; scanPtr.p->scanLastQueuedOp = RNIL; scanPtr.p->scanFirstLockedOp = RNIL; scanPtr.p->scanLastLockedOp = RNIL; scanPtr.p->scanState = ScanRec::WAIT_NEXT; fragrecptr.i = rootfragrecptr.p->fragmentptr[0]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); initScanFragmentPart(signal); /*------------------------------------------------------*/ /* We start the timeout loop for the scan process here. */ /*------------------------------------------------------*/ ndbrequire(scanPtr.p->scanTimer == 0); if (scanPtr.p->scanContinuebCounter == 0) { jam(); scanPtr.p->scanContinuebCounter = 1; signal->theData[0] = ZSEND_SCAN_HBREP; signal->theData[1] = scanPtr.i; sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 2); }//if scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter; /* ************************ */ /* ACC_SCANCONF */ /* ************************ */ signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = scanPtr.i; signal->theData[2] = 2; /* NR OF LOCAL FRAGMENT */ signal->theData[3] = rootfragrecptr.p->fragmentid[0]; signal->theData[4] = rootfragrecptr.p->fragmentid[1]; signal->theData[7] = AccScanConf::ZNOT_EMPTY_FRAGMENT; sendSignal(scanPtr.p->scanUserblockref, GSN_ACC_SCANCONF, signal, 8, JBB); /* NOT EMPTY FRAGMENT */ return; }//Dbacc::execACC_SCANREQ() /* ******************--------------------------------------------------------------- */ /* NEXT_SCANREQ REQUEST FOR NEXT ELEMENT OF */ /* ******************------------------------------+ A FRAGMENT. */ /* SENDER: LQH, LEVEL B */ void Dbacc::execNEXT_SCANREQ(Signal* signal) { Uint32 tscanNextFlag; jamEntry(); scanPtr.i = signal->theData[0]; operationRecPtr.i = signal->theData[1]; tscanNextFlag = signal->theData[2]; /* ------------------------------------------ */ /* 1 = ZCOPY_NEXT GET NEXT ELEMENT */ /* 2 = ZCOPY_NEXT_COMMIT COMMIT THE */ /* ACTIVE ELEMENT AND GET THE NEXT ONE */ /* 3 = ZCOPY_COMMIT COMMIT THE ACTIVE ELEMENT */ /* 4 = ZCOPY_REPEAT GET THE ACTIVE ELEMENT */ /* 5 = ZCOPY_ABORT RELOCK THE ACTIVE ELEMENT */ /* 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY */ /* ------------------------------------------ */ tresult = 0; ptrCheckGuard(scanPtr, cscanRecSize, scanRec); ndbrequire(scanPtr.p->scanState == ScanRec::WAIT_NEXT); scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter; switch (tscanNextFlag) { case ZCOPY_NEXT: jam(); /*empty*/; break; case ZCOPY_NEXT_COMMIT: case ZCOPY_COMMIT: jam(); /* --------------------------------------------------------------------------------- */ /* COMMIT ACTIVE OPERATION. SEND NEXT SCAN ELEMENT IF IT IS ZCOPY_NEXT_COMMIT. */ /* --------------------------------------------------------------------------------- */ ptrCheckGuard(operationRecPtr, coprecsize, operationrec); fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (!scanPtr.p->scanReadCommittedFlag) { if (fragrecptr.p->createLcp == ZTRUE) { if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) { jam(); /*--------------------------------------------------------------*/ // We did not have enough undo log buffers to safely commit an // operation. Try again in 10 milliseconds. /*--------------------------------------------------------------*/ sendSignalWithDelay(cownBlockref, GSN_NEXT_SCANREQ, signal, 10, 3); return; }//if }//if commitOperation(signal); }//if takeOutActiveScanOp(signal); releaseOpRec(signal); scanPtr.p->scanOpsAllocated--; if (tscanNextFlag == ZCOPY_COMMIT) { jam(); signal->theData[0] = scanPtr.p->scanUserptr; Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref); EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 1); return; }//if break; case ZCOPY_CLOSE: jam(); fragrecptr.i = scanPtr.p->activeLocalFrag; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (!scanPtr.p->scanReadCommittedFlag) { if (fragrecptr.p->createLcp == ZTRUE) { if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_OPERATION) { jam(); /*--------------------------------------------------------------*/ // We did not have enough undo log buffers to commit a set of // operations. Try again in 10 milliseconds. /*--------------------------------------------------------------*/ sendSignalWithDelay(cownBlockref, GSN_NEXT_SCANREQ, signal, 10, 3); return; }//if }//if }//if /* --------------------------------------------------------------------------------- */ /* THE SCAN PROCESS IS FINISHED. RELOCK ALL LOCKED EL. RELESE ALL INVOLVED REC. */ /* --------------------------------------------------------------------------------- */ releaseScanLab(signal); return; break; default: ndbrequire(false); break; }//switch signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP; execACC_CHECK_SCAN(signal); return; }//Dbacc::execNEXT_SCANREQ() void Dbacc::checkNextBucketLab(Signal* signal) { DirRangePtr cscDirRangePtr; DirectoryarrayPtr cscDirptr; DirectoryarrayPtr tnsDirptr; Page8Ptr nsPageptr; Page8Ptr cscPageidptr; Page8Ptr gnsPageidptr; Page8Ptr tnsPageidptr; Uint32 tnsElementptr; Uint32 tnsContainerptr; Uint32 tnsIsLocked; Uint32 tnsTmp1; Uint32 tnsTmp2; Uint32 tnsCopyIndex1; Uint32 tnsCopyIndex2; Uint32 tnsCopyDir; tnsCopyDir = scanPtr.p->nextBucketIndex >> fragrecptr.p->k; tnsCopyIndex1 = tnsCopyDir >> 8; tnsCopyIndex2 = tnsCopyDir & 0xff; arrGuard(tnsCopyIndex1, 256); tnsDirptr.i = gnsDirRangePtr.p->dirArray[tnsCopyIndex1]; ptrCheckGuard(tnsDirptr, cdirarraysize, directoryarray); tnsPageidptr.i = tnsDirptr.p->pagep[tnsCopyIndex2]; ptrCheckGuard(tnsPageidptr, cpagesize, page8); gnsPageidptr.i = tnsPageidptr.i; gnsPageidptr.p = tnsPageidptr.p; tnsTmp1 = (1 << fragrecptr.p->k) - 1; tgsePageindex = scanPtr.p->nextBucketIndex & tnsTmp1; gsePageidptr.i = gnsPageidptr.i; gsePageidptr.p = gnsPageidptr.p; if (!getScanElement(signal)) { scanPtr.p->nextBucketIndex++; if (scanPtr.p->scanBucketState == ScanRec::SECOND_LAP) { if (scanPtr.p->nextBucketIndex > scanPtr.p->maxBucketIndexToRescan) { /* --------------------------------------------------------------------------------- */ // We have finished the rescan phase. We are ready to proceed with the next fragment part. /* --------------------------------------------------------------------------------- */ jam(); checkNextFragmentLab(signal); return; }//if } else if (scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) { if ((fragrecptr.p->p + fragrecptr.p->maxp) < scanPtr.p->nextBucketIndex) { /* --------------------------------------------------------------------------------- */ // All buckets have been scanned a first time. /* --------------------------------------------------------------------------------- */ if (scanPtr.p->minBucketIndexToRescan == 0xFFFFFFFF) { jam(); /* --------------------------------------------------------------------------------- */ // We have not had any merges behind the scan. Thus it is not necessary to perform // any rescan any buckets and we can proceed immediately with the next fragment part. /* --------------------------------------------------------------------------------- */ checkNextFragmentLab(signal); return; } else { jam(); /* --------------------------------------------------------------------------------- */ // Some buckets are in the need of rescanning due to merges that have moved records // from in front of the scan to behind the scan. During the merges we kept track of // which buckets that need a rescan. We start with the minimum and end with maximum. /* --------------------------------------------------------------------------------- */ scanPtr.p->nextBucketIndex = scanPtr.p->minBucketIndexToRescan; scanPtr.p->scanBucketState = ScanRec::SECOND_LAP; if (scanPtr.p->maxBucketIndexToRescan > (fragrecptr.p->p + fragrecptr.p->maxp)) { jam(); /* --------------------------------------------------------------------------------- */ // If we have had so many merges that the maximum is bigger than the number of buckets // then we will simply satisfy ourselves with scanning to the end. This can only happen // after bringing down the total of buckets to less than half and the minimum should // be 0 otherwise there is some problem. /* --------------------------------------------------------------------------------- */ if (scanPtr.p->minBucketIndexToRescan != 0) { jam(); sendSystemerror(signal); return; }//if scanPtr.p->maxBucketIndexToRescan = fragrecptr.p->p + fragrecptr.p->maxp; }//if }//if }//if }//if if ((scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) && (scanPtr.p->nextBucketIndex <= scanPtr.p->startNoOfBuckets)) { /* --------------------------------------------------------------------------------- */ // We will only reset the scan indicator on the buckets that existed at the start of the // scan. The others will be handled by the split and merge code. /* --------------------------------------------------------------------------------- */ tnsTmp2 = (1 << fragrecptr.p->k) - 1; trsbPageindex = scanPtr.p->nextBucketIndex & tnsTmp2; if (trsbPageindex != 0) { jam(); rsbPageidptr.i = gnsPageidptr.i; rsbPageidptr.p = gnsPageidptr.p; } else { jam(); cscDirRangePtr.i = fragrecptr.p->directory; tmpP = scanPtr.p->nextBucketIndex >> fragrecptr.p->k; tmpP2 = tmpP >> 8; tmpP = tmpP & 0xff; ptrCheckGuard(cscDirRangePtr, cdirrangesize, dirRange); arrGuard(tmpP2, 256); cscDirptr.i = cscDirRangePtr.p->dirArray[tmpP2]; ptrCheckGuard(cscDirptr, cdirarraysize, directoryarray); cscPageidptr.i = cscDirptr.p->pagep[tmpP]; ptrCheckGuard(cscPageidptr, cpagesize, page8); tmp1 = (1 << fragrecptr.p->k) - 1; trsbPageindex = scanPtr.p->nextBucketIndex & tmp1; rsbPageidptr.i = cscPageidptr.i; rsbPageidptr.p = cscPageidptr.p; }//if releaseScanBucket(signal); }//if signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP; sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB); return; }//if /* ----------------------------------------------------------------------- */ /* AN ELEMENT WHICH HAVE NOT BEEN SCANNED WAS FOUND. WE WILL PREPARE IT */ /* TO BE SENT TO THE LQH BLOCK FOR FURTHER PROCESSING. */ /* WE ASSUME THERE ARE OPERATION RECORDS AVAILABLE SINCE LQH SHOULD HAVE*/ /* GUARANTEED THAT THROUGH EARLY BOOKING. */ /* ----------------------------------------------------------------------- */ tnsIsLocked = tgseIsLocked; tnsElementptr = tgseElementptr; tnsContainerptr = tgseContainerptr; nsPageptr.i = gsePageidptr.i; nsPageptr.p = gsePageidptr.p; seizeOpRec(signal); tisoIsforward = tgseIsforward; tisoContainerptr = tnsContainerptr; tisoElementptr = tnsElementptr; isoPageptr.i = nsPageptr.i; isoPageptr.p = nsPageptr.p; initScanOpRec(signal); if (!tnsIsLocked){ if (!scanPtr.p->scanReadCommittedFlag) { jam(); slPageidptr = nsPageptr; tslElementptr = tnsElementptr; setlock(signal); insertLockOwnersList(signal, operationRecPtr); }//if } else { arrGuard(tnsElementptr, 2048); queOperPtr.i = ElementHeader::getOpPtrI(nsPageptr.p->word32[tnsElementptr]); ptrCheckGuard(queOperPtr, coprecsize, operationrec); if (queOperPtr.p->elementIsDisappeared == ZTRUE) { jam(); /* --------------------------------------------------------------------------------- */ // If the lock owner indicates the element is disappeared then we will not report this // tuple. We will continue with the next tuple. /* --------------------------------------------------------------------------------- */ releaseOpRec(signal); scanPtr.p->scanOpsAllocated--; signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP; sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB); return; }//if if (!scanPtr.p->scanReadCommittedFlag) { Uint32 return_result; if (scanPtr.p->scanLockMode == ZREADLOCK) { jam(); priPageptr = nsPageptr; tpriElementptr = tnsElementptr; return_result = placeReadInLockQueue(signal); } else { jam(); pwiPageptr = nsPageptr; tpwiElementptr = tnsElementptr; return_result = placeWriteInLockQueue(signal); }//if if (return_result == ZSERIAL_QUEUE) { /* --------------------------------------------------------------------------------- */ /* WE PLACED THE OPERATION INTO A SERIAL QUEUE AND THUS WE HAVE TO WAIT FOR */ /* THE LOCK TO BE RELEASED. WE CONTINUE WITH THE NEXT ELEMENT. */ /* --------------------------------------------------------------------------------- */ putOpScanLockQue(); /* PUT THE OP IN A QUE IN THE SCAN REC */ signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP; sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB); return; } else if (return_result == ZWRITE_ERROR) { jam(); /* --------------------------------------------------------------------------------- */ // The tuple is either not committed yet or a delete in the same transaction (not // possible here since we are a scan). Thus we simply continue with the next tuple. /* --------------------------------------------------------------------------------- */ releaseOpRec(signal); scanPtr.p->scanOpsAllocated--; signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP; sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB); return; }//if ndbassert(return_result == ZPARALLEL_QUEUE); }//if }//if /* --------------------------------------------------------------------------------- */ // Committed read proceed without caring for locks immediately down here except when // the tuple was deleted permanently and no new operation has inserted it again. /* --------------------------------------------------------------------------------- */ putActiveScanOp(signal); sendNextScanConf(signal); return; }//Dbacc::checkNextBucketLab() void Dbacc::checkNextFragmentLab(Signal* signal) { RootfragmentrecPtr cnfRootfragrecptr; cnfRootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(cnfRootfragrecptr, crootfragmentsize, rootfragmentrec); if (scanPtr.p->activeLocalFrag == cnfRootfragrecptr.p->fragmentptr[0]) { jam(); fragrecptr.i = cnfRootfragrecptr.p->fragmentptr[1]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); initScanFragmentPart(signal); signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP; sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB); return; } else { if (scanPtr.p->activeLocalFrag == cnfRootfragrecptr.p->fragmentptr[1]) { jam(); /* --------------------------------------------------------------------------------- */ // Both fragments have completed their scan part and we can indicate that the scan is // now completed. /* --------------------------------------------------------------------------------- */ scanPtr.p->scanBucketState = ScanRec::SCAN_COMPLETED; /*empty*/; } else { jam(); /* ALL ELEMENTS ARE SENT */ sendSystemerror(signal); }//if }//if /* --------------------------------------------------------------------------------- */ // The scan is completed. ACC_CHECK_SCAN will perform all the necessary checks to see // what the next step is. /* --------------------------------------------------------------------------------- */ signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP; execACC_CHECK_SCAN(signal); return; }//Dbacc::checkNextFragmentLab() void Dbacc::initScanFragmentPart(Signal* signal) { DirRangePtr cnfDirRangePtr; DirectoryarrayPtr cnfDirptr; Page8Ptr cnfPageidptr; /* --------------------------------------------------------------------------------- */ // Set the active fragment part. // Set the current bucket scanned to the first. // Start with the first lap. // Remember the number of buckets at start of the scan. // Set the minimum and maximum to values that will always be smaller and larger than. // Reset the scan indicator on the first bucket. /* --------------------------------------------------------------------------------- */ scanPtr.p->activeLocalFrag = fragrecptr.i; scanPtr.p->nextBucketIndex = 0; /* INDEX OF SCAN BUCKET */ scanPtr.p->scanBucketState = ScanRec::FIRST_LAP; scanPtr.p->startNoOfBuckets = fragrecptr.p->p + fragrecptr.p->maxp; scanPtr.p->minBucketIndexToRescan = 0xFFFFFFFF; scanPtr.p->maxBucketIndexToRescan = 0; cnfDirRangePtr.i = fragrecptr.p->directory; ptrCheckGuard(cnfDirRangePtr, cdirrangesize, dirRange); cnfDirptr.i = cnfDirRangePtr.p->dirArray[0]; ptrCheckGuard(cnfDirptr, cdirarraysize, directoryarray); cnfPageidptr.i = cnfDirptr.p->pagep[0]; ptrCheckGuard(cnfPageidptr, cpagesize, page8); trsbPageindex = scanPtr.p->nextBucketIndex & ((1 << fragrecptr.p->k) - 1); rsbPageidptr.i = cnfPageidptr.i; rsbPageidptr.p = cnfPageidptr.p; releaseScanBucket(signal); }//Dbacc::initScanFragmentPart() /* --------------------------------------------------------------------------------- */ /* FLAG = 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY OR ABORTED. ALL OPERATION IN THE */ /* ACTIVE OR WAIT QUEUE ARE RELEASED, SCAN FLAG OF ROOT FRAG IS RESET AND THE SCAN */ /* RECORD IS RELEASED. */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseScanLab(Signal* signal) { releaseAndCommitActiveOps(signal); releaseAndCommitQueuedOps(signal); releaseAndAbortLockedOps(signal); rootfragrecptr.i = scanPtr.p->rootPtr; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); for (tmp = 0; tmp < MAX_PARALLEL_SCANS_PER_FRAG; tmp++) { jam(); if (rootfragrecptr.p->scan[tmp] == scanPtr.i) { jam(); rootfragrecptr.p->scan[tmp] = RNIL; }//if }//for // Stops the heartbeat. scanPtr.p->scanTimer = 0; signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = RNIL; signal->theData[2] = RNIL; sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB); releaseScanRec(signal); return; }//Dbacc::releaseScanLab() void Dbacc::releaseAndCommitActiveOps(Signal* signal) { OperationrecPtr trsoOperPtr; operationRecPtr.i = scanPtr.p->scanFirstActiveOp; while (operationRecPtr.i != RNIL) { jam(); ptrCheckGuard(operationRecPtr, coprecsize, operationrec); trsoOperPtr.i = operationRecPtr.p->nextOp; fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (!scanPtr.p->scanReadCommittedFlag) { jam(); commitOperation(signal); }//if takeOutActiveScanOp(signal); releaseOpRec(signal); scanPtr.p->scanOpsAllocated--; operationRecPtr.i = trsoOperPtr.i; }//if }//Dbacc::releaseAndCommitActiveOps() void Dbacc::releaseAndCommitQueuedOps(Signal* signal) { OperationrecPtr trsoOperPtr; operationRecPtr.i = scanPtr.p->scanFirstQueuedOp; while (operationRecPtr.i != RNIL) { jam(); ptrCheckGuard(operationRecPtr, coprecsize, operationrec); trsoOperPtr.i = operationRecPtr.p->nextOp; fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (!scanPtr.p->scanReadCommittedFlag) { jam(); commitOperation(signal); }//if takeOutReadyScanQueue(signal); releaseOpRec(signal); scanPtr.p->scanOpsAllocated--; operationRecPtr.i = trsoOperPtr.i; }//if }//Dbacc::releaseAndCommitQueuedOps() void Dbacc::releaseAndAbortLockedOps(Signal* signal) { OperationrecPtr trsoOperPtr; operationRecPtr.i = scanPtr.p->scanFirstLockedOp; while (operationRecPtr.i != RNIL) { jam(); ptrCheckGuard(operationRecPtr, coprecsize, operationrec); trsoOperPtr.i = operationRecPtr.p->nextOp; fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (!scanPtr.p->scanReadCommittedFlag) { jam(); abortOperation(signal); }//if takeOutScanLockQueue(scanPtr.i); releaseOpRec(signal); scanPtr.p->scanOpsAllocated--; operationRecPtr.i = trsoOperPtr.i; }//if }//Dbacc::releaseAndAbortLockedOps() /* 3.18.3 ACC_CHECK_SCAN */ /* ******************--------------------------------------------------------------- */ /* ACC_CHECK_SCAN */ /* ENTER ACC_CHECK_SCAN WITH */ /* SCAN_PTR */ /* ******************--------------------------------------------------------------- */ /* ******************--------------------------------------------------------------- */ /* ACC_CHECK_SCAN */ /* ******************------------------------------+ */ void Dbacc::execACC_CHECK_SCAN(Signal* signal) { Uint32 TcheckLcpStop; jamEntry(); scanPtr.i = signal->theData[0]; TcheckLcpStop = signal->theData[1]; ptrCheckGuard(scanPtr, cscanRecSize, scanRec); while (scanPtr.p->scanFirstQueuedOp != RNIL) { jam(); //---------------------------------------------------------------------------- // An operation has been released from the lock queue. We are in the parallel // queue of this tuple. We are ready to report the tuple now. //---------------------------------------------------------------------------- operationRecPtr.i = scanPtr.p->scanFirstQueuedOp; ptrCheckGuard(operationRecPtr, coprecsize, operationrec); takeOutReadyScanQueue(signal); if (operationRecPtr.p->elementIsDisappeared == ZTRUE) { jam(); fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (fragrecptr.p->createLcp == ZTRUE) { if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) { jam(); /*--------------------------------------------------------------*/ // We did not have enough undo log buffers to safely abort an // operation. Try again in 10 milliseconds. /*--------------------------------------------------------------*/ sendSignalWithDelay(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 10, 2); return; }//if }//if abortOperation(signal); releaseOpRec(signal); scanPtr.p->scanOpsAllocated--; continue; }//if putActiveScanOp(signal); sendNextScanConf(signal); return; }//while if ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) && (scanPtr.p->scanLockHeld == 0)) { jam(); //---------------------------------------------------------------------------- // The scan is now completed and there are no more locks outstanding. Thus we // we will report the scan as completed to LQH. //---------------------------------------------------------------------------- signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = RNIL; signal->theData[2] = RNIL; sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB); return; }//if if (TcheckLcpStop == AccCheckScan::ZCHECK_LCP_STOP) { //--------------------------------------------------------------------------- // To ensure that the block of the fragment occurring at the start of a local // checkpoint is not held for too long we insert a release and reacquiring of // that lock here. This is performed in LQH. If we are blocked or if we have // requested a sleep then we will receive RNIL in the returning signal word. //--------------------------------------------------------------------------- signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) || (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED)); EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2); jamEntry(); if (signal->theData[0] == RNIL) { jam(); return; }//if }//if /** * If we have more than max locks held OR * scan is completed AND at least one lock held * - Inform LQH about this condition */ if ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) || (cfreeopRec == RNIL) || ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) && (scanPtr.p->scanLockHeld > 0))) { jam(); signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = RNIL; // No operation is returned signal->theData[2] = 512; // MASV sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB); return; } if (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) { jam(); signal->theData[0] = scanPtr.i; signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP; execACC_CHECK_SCAN(signal); return; }//if scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter; fragrecptr.i = scanPtr.p->activeLocalFrag; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); gnsDirRangePtr.i = fragrecptr.p->directory; ptrCheckGuard(gnsDirRangePtr, cdirrangesize, dirRange); checkNextBucketLab(signal); return; }//Dbacc::execACC_CHECK_SCAN() /* ******************---------------------------------------------------- */ /* ACC_TO_REQ PERFORM A TAKE OVER */ /* ******************-------------------+ */ /* SENDER: LQH, LEVEL B */ void Dbacc::execACC_TO_REQ(Signal* signal) { OperationrecPtr tatrOpPtr; jamEntry(); tatrOpPtr.i = signal->theData[1]; /* OPER PTR OF ACC */ ptrCheckGuard(tatrOpPtr, coprecsize, operationrec); if (tatrOpPtr.p->operation == ZSCAN_OP) { tatrOpPtr.p->transId1 = signal->theData[2]; tatrOpPtr.p->transId2 = signal->theData[3]; } else { jam(); signal->theData[0] = cminusOne; signal->theData[1] = ZTO_OP_STATE_ERROR; }//if return; }//Dbacc::execACC_TO_REQ() /* --------------------------------------------------------------------------------- */ /* CONTAINERINFO */ /* INPUT: */ /* CI_PAGEIDPTR (PAGE POINTER WHERE CONTAINER RESIDES) */ /* TCI_PAGEINDEX (INDEX OF CONTAINER, USED TO CALCULATE PAGE INDEX) */ /* TCI_ISFORWARD (DIRECTION OF CONTAINER FORWARD OR BACKWARD) */ /* */ /* OUTPUT: */ /* TCI_CONTAINERPTR (A POINTER TO THE HEAD OF THE CONTAINER) */ /* TCI_CONTAINERLEN (LENGTH OF THE CONTAINER */ /* TCI_CONTAINERHEAD (THE HEADER OF THE CONTAINER) */ /* */ /* DESCRIPTION: THE ADDRESS OF THE CONTAINER WILL BE CALCULATED AND */ /* ALL INFORMATION ABOUT THE CONTAINER WILL BE READ */ /* --------------------------------------------------------------------------------- */ void Dbacc::containerinfo(Signal* signal) { tciContainerptr = (tciPageindex << ZSHIFT_PLUS) - (tciPageindex << ZSHIFT_MINUS); if (tciIsforward == ZTRUE) { jam(); tciContainerptr = tciContainerptr + ZHEAD_SIZE; } else { jam(); tciContainerptr = ((tciContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE; }//if arrGuard(tciContainerptr, 2048); tciContainerhead = ciPageidptr.p->word32[tciContainerptr]; tciContainerlen = tciContainerhead >> 26; }//Dbacc::containerinfo() /* --------------------------------------------------------------------------------- */ /* GET_SCAN_ELEMENT */ /* INPUT: GSE_PAGEIDPTR */ /* TGSE_PAGEINDEX */ /* OUTPUT: TGSE_IS_LOCKED (IF TRESULT /= ZFALSE) */ /* GSE_PAGEIDPTR */ /* TGSE_PAGEINDEX */ /* --------------------------------------------------------------------------------- */ bool Dbacc::getScanElement(Signal* signal) { tgseIsforward = ZTRUE; NEXTSEARCH_SCAN_LOOP: ciPageidptr.i = gsePageidptr.i; ciPageidptr.p = gsePageidptr.p; tciPageindex = tgsePageindex; tciIsforward = tgseIsforward; containerinfo(signal); sscPageidptr.i = gsePageidptr.i; sscPageidptr.p = gsePageidptr.p; tsscContainerlen = tciContainerlen; tsscContainerptr = tciContainerptr; tsscIsforward = tciIsforward; if (searchScanContainer(signal)) { jam(); tgseIsLocked = tsscIsLocked; tgseElementptr = tsscElementptr; tgseContainerptr = tsscContainerptr; return true; }//if if (((tciContainerhead >> 7) & 0x3) != 0) { jam(); nciPageidptr.i = gsePageidptr.i; nciPageidptr.p = gsePageidptr.p; tnciContainerhead = tciContainerhead; tnciContainerptr = tciContainerptr; nextcontainerinfo(signal); tgsePageindex = tnciPageindex; gsePageidptr.i = nciPageidptr.i; gsePageidptr.p = nciPageidptr.p; tgseIsforward = tnciIsforward; goto NEXTSEARCH_SCAN_LOOP; }//if return false; }//Dbacc::getScanElement() /* --------------------------------------------------------------------------------- */ /* INIT_SCAN_OP_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::initScanOpRec(Signal* signal) { Uint32 tisoTmp; Uint32 tisoLocalPtr; Uint32 guard24; Uint32 tisoPageIndex; Uint32 tisoPagedir; DirRangePtr tisoOverflowrangeptr; DirectoryarrayPtr tisoOverflowDirptr; Page8Ptr tisoPageptr; scanPtr.p->scanOpsAllocated++; operationRecPtr.p->scanRecPtr = scanPtr.i; operationRecPtr.p->operation = ZSCAN_OP; operationRecPtr.p->transactionstate = ACTIVE; operationRecPtr.p->commitDeleteCheckFlag = ZFALSE; operationRecPtr.p->lockMode = scanPtr.p->scanLockMode; operationRecPtr.p->fid = fragrecptr.p->myfid; operationRecPtr.p->fragptr = fragrecptr.i; operationRecPtr.p->elementIsDisappeared = ZFALSE; operationRecPtr.p->nextParallelQue = RNIL; operationRecPtr.p->prevParallelQue = RNIL; operationRecPtr.p->nextSerialQue = RNIL; operationRecPtr.p->prevSerialQue = RNIL; operationRecPtr.p->prevQueOp = RNIL; operationRecPtr.p->nextQueOp = RNIL; operationRecPtr.p->keyinfoPage = RNIL; // Safety precaution operationRecPtr.p->transId1 = scanPtr.p->scanTrid1; operationRecPtr.p->transId2 = scanPtr.p->scanTrid2; operationRecPtr.p->lockOwner = ZFALSE; operationRecPtr.p->dirtyRead = 0; operationRecPtr.p->nodeType = 0; // Not a stand-by node operationRecPtr.p->elementIsforward = tisoIsforward; operationRecPtr.p->elementContainer = tisoContainerptr; operationRecPtr.p->elementPointer = tisoElementptr; operationRecPtr.p->elementPage = isoPageptr.i; operationRecPtr.p->isAccLockReq = ZFALSE; tisoLocalPtr = tisoElementptr + tisoIsforward; guard24 = fragrecptr.p->localkeylen - 1; for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) { arrGuard(tisoTmp, 2); arrGuard(tisoLocalPtr, 2048); operationRecPtr.p->localdata[tisoTmp] = isoPageptr.p->word32[tisoLocalPtr]; tisoLocalPtr = tisoLocalPtr + tisoIsforward; }//for arrGuard(tisoLocalPtr, 2048); operationRecPtr.p->keydata[0] = isoPageptr.p->word32[tisoLocalPtr]; if (fragrecptr.p->keyLength != 0) { jam(); operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength; guard24 = fragrecptr.p->keyLength - 1; for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) { arrGuard(tisoTmp, 8); arrGuard(tisoLocalPtr, 2048); operationRecPtr.p->keydata[tisoTmp] = isoPageptr.p->word32[tisoLocalPtr]; tisoLocalPtr = tisoLocalPtr + tisoIsforward; }//for } else { // Long key handling. Put the long key reference in the operation records. tisoPageIndex = operationRecPtr.p->keydata[0] & 0x3ff; arrGuard(ZWORDS_IN_PAGE - tisoPageIndex, 2048); tisoPagedir = operationRecPtr.p->keydata[0] >> 10; arrGuard((tisoPagedir >> 8), 256); tisoOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(tisoOverflowrangeptr, cdirrangesize, dirRange); tisoOverflowDirptr.i = tisoOverflowrangeptr.p->dirArray[tisoPagedir >> 8]; ptrCheckGuard(tisoOverflowDirptr, cdirarraysize, directoryarray); tisoPageptr.i = tisoOverflowDirptr.p->pagep[tisoPagedir & 0xff]; ptrCheckGuard(tisoPageptr, cpagesize, page8); operationRecPtr.p->longPagePtr = tisoPageptr.i; operationRecPtr.p->longKeyPageIndex = tisoPageIndex; // Read length of key from page Uint32 tmp = tisoPageptr.p->word32[ZWORDS_IN_PAGE - tisoPageIndex]; operationRecPtr.p->tupkeylen = tmp >> 16; } }//Dbacc::initScanOpRec() /* --------------------------------------------------------------------------------- */ /* NEXTCONTAINERINFO */ /* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */ /* ABOUT NEXT CONTAINER IN THE BUCKET. */ /* INPUT: TNCI_CONTAINERHEAD */ /* NCI_PAGEIDPTR */ /* TNCI_CONTAINERPTR */ /* OUTPUT: */ /* TNCI_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED). */ /* TNCI_ISFORWARD (IS THE NEXT CONTAINER FORWARD (+1) OR BACKWARD (-1) */ /* NCI_PAGEIDPTR (PAGE REFERENCE OF NEXT CONTAINER) */ /* --------------------------------------------------------------------------------- */ void Dbacc::nextcontainerinfo(Signal* signal) { tnciNextSamePage = (tnciContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */ /* THE NEXT CONTAINER IS IN THE SAME PAGE */ tnciPageindex = tnciContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */ if (((tnciContainerhead >> 7) & 3) == ZLEFT) { jam(); tnciIsforward = ZTRUE; } else { jam(); tnciIsforward = cminusOne; }//if if (tnciNextSamePage == ZFALSE) { jam(); /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */ arrGuard(tnciContainerptr + 1, 2048); tnciTmp = nciPageidptr.p->word32[tnciContainerptr + 1]; nciOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange); arrGuard((tnciTmp >> 8), 256); nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8]; ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray); nciPageidptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff]; ptrCheckGuard(nciPageidptr, cpagesize, page8); }//if }//Dbacc::nextcontainerinfo() /* --------------------------------------------------------------------------------- */ /* PUT_ACTIVE_SCAN_OP */ /* --------------------------------------------------------------------------------- */ void Dbacc::putActiveScanOp(Signal* signal) { OperationrecPtr pasOperationRecPtr; pasOperationRecPtr.i = scanPtr.p->scanFirstActiveOp; if (pasOperationRecPtr.i != RNIL) { jam(); ptrCheckGuard(pasOperationRecPtr, coprecsize, operationrec); pasOperationRecPtr.p->prevOp = operationRecPtr.i; }//if operationRecPtr.p->nextOp = pasOperationRecPtr.i; operationRecPtr.p->prevOp = RNIL; scanPtr.p->scanFirstActiveOp = operationRecPtr.i; }//Dbacc::putActiveScanOp() /** * putOpScanLockQueue * * Description: Put an operation in the doubly linked * lock list on a scan record. The list is used to * keep track of which operations belonging * to the scan are put in serial lock list of another * operation * * @note Use takeOutScanLockQueue to remove an operation * from the list * */ void Dbacc::putOpScanLockQue() { #ifdef VM_TRACE // DEBUG CODE // Check that there are as many operations in the lockqueue as // scanLockHeld indicates OperationrecPtr tmpOp; int numLockedOpsBefore = 0; tmpOp.i = scanPtr.p->scanFirstLockedOp; while(tmpOp.i != RNIL){ numLockedOpsBefore++; ptrCheckGuard(tmpOp, coprecsize, operationrec); if (tmpOp.p->nextOp == RNIL) ndbrequire(tmpOp.i == scanPtr.p->scanLastLockedOp); tmpOp.i = tmpOp.p->nextOp; } ndbrequire(numLockedOpsBefore==scanPtr.p->scanLockHeld); #endif OperationrecPtr pslOperationRecPtr; ScanRec theScanRec; theScanRec = *scanPtr.p; pslOperationRecPtr.i = scanPtr.p->scanLastLockedOp; operationRecPtr.p->prevOp = pslOperationRecPtr.i; operationRecPtr.p->nextOp = RNIL; if (pslOperationRecPtr.i != RNIL) { jam(); ptrCheckGuard(pslOperationRecPtr, coprecsize, operationrec); pslOperationRecPtr.p->nextOp = operationRecPtr.i; } else { jam(); scanPtr.p->scanFirstLockedOp = operationRecPtr.i; }//if scanPtr.p->scanLastLockedOp = operationRecPtr.i; scanPtr.p->scanLockHeld++; }//Dbacc::putOpScanLockQue() /* --------------------------------------------------------------------------------- */ /* PUT_READY_SCAN_QUEUE */ /* --------------------------------------------------------------------------------- */ void Dbacc::putReadyScanQueue(Signal* signal, Uint32 scanRecIndex) { OperationrecPtr prsOperationRecPtr; ScanRecPtr TscanPtr; TscanPtr.i = scanRecIndex; ptrCheckGuard(TscanPtr, cscanRecSize, scanRec); prsOperationRecPtr.i = TscanPtr.p->scanLastQueuedOp; operationRecPtr.p->prevOp = prsOperationRecPtr.i; operationRecPtr.p->nextOp = RNIL; TscanPtr.p->scanLastQueuedOp = operationRecPtr.i; if (prsOperationRecPtr.i != RNIL) { jam(); ptrCheckGuard(prsOperationRecPtr, coprecsize, operationrec); prsOperationRecPtr.p->nextOp = operationRecPtr.i; } else { jam(); TscanPtr.p->scanFirstQueuedOp = operationRecPtr.i; }//if }//Dbacc::putReadyScanQueue() /* --------------------------------------------------------------------------------- */ /* RELEASE_SCAN_BUCKET */ // Input: // rsbPageidptr.i Index to page where buckets starts // rsbPageidptr.p Pointer to page where bucket starts // trsbPageindex Page index of starting container in bucket /* --------------------------------------------------------------------------------- */ void Dbacc::releaseScanBucket(Signal* signal) { Uint32 trsbIsforward; trsbIsforward = ZTRUE; NEXTRELEASESCANLOOP: ciPageidptr.i = rsbPageidptr.i; ciPageidptr.p = rsbPageidptr.p; tciPageindex = trsbPageindex; tciIsforward = trsbIsforward; containerinfo(signal); rscPageidptr.i = rsbPageidptr.i; rscPageidptr.p = rsbPageidptr.p; trscContainerlen = tciContainerlen; trscContainerptr = tciContainerptr; trscIsforward = trsbIsforward; releaseScanContainer(signal); if (((tciContainerhead >> 7) & 0x3) != 0) { jam(); nciPageidptr.i = rsbPageidptr.i; nciPageidptr.p = rsbPageidptr.p; tnciContainerhead = tciContainerhead; tnciContainerptr = tciContainerptr; nextcontainerinfo(signal); rsbPageidptr.i = nciPageidptr.i; rsbPageidptr.p = nciPageidptr.p; trsbPageindex = tnciPageindex; trsbIsforward = tnciIsforward; goto NEXTRELEASESCANLOOP; }//if }//Dbacc::releaseScanBucket() /* --------------------------------------------------------------------------------- */ /* RELEASE_SCAN_CONTAINER */ /* INPUT: TRSC_CONTAINERLEN */ /* RSC_PAGEIDPTR */ /* TRSC_CONTAINERPTR */ /* TRSC_ISFORWARD */ /* SCAN_PTR */ /* */ /* DESCRIPTION: SEARCHS IN A CONTAINER, AND THE SCAN BIT OF THE ELEMENTS */ /* OF THE CONTAINER IS RESET */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseScanContainer(Signal* signal) { OperationrecPtr rscOperPtr; Uint32 trscElemStep; Uint32 trscElementptr; Uint32 trscElemlens; Uint32 trscElemlen; if (trscContainerlen < 5) { if (trscContainerlen != ZCON_HEAD_SIZE) { jam(); sendSystemerror(signal); }//if return; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */ }//if trscElemlens = trscContainerlen - 2; if (fragrecptr.p->keyLength != 0) { jam(); trscElemlen = (1 + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */ } else { jam(); trscElemlen = (1 + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */ }//if if (trscIsforward == 1) { jam(); trscElementptr = trscContainerptr + ZCON_HEAD_SIZE; trscElemStep = trscElemlen; } else { jam(); trscElementptr = trscContainerptr - 1; trscElemStep = 0 - trscElemlen; }//if do { arrGuard(trscElementptr, 2048); const Uint32 eh = rscPageidptr.p->word32[trscElementptr]; const Uint32 scanMask = scanPtr.p->scanMask; if (ElementHeader::getUnlocked(eh)) { jam(); const Uint32 tmp = ElementHeader::clearScanBit(eh, scanMask); dbgWord32(rscPageidptr, trscElementptr, tmp); rscPageidptr.p->word32[trscElementptr] = tmp; } else { jam(); rscOperPtr.i = ElementHeader::getOpPtrI(eh); ptrCheckGuard(rscOperPtr, coprecsize, operationrec); rscOperPtr.p->scanBits &= ~scanMask; }//if trscElemlens = trscElemlens - trscElemlen; trscElementptr = trscElementptr + trscElemStep; } while (trscElemlens > 2); if (trscElemlens != 0) { jam(); sendSystemerror(signal); }//if }//Dbacc::releaseScanContainer() /* --------------------------------------------------------------------------------- */ /* RELEASE_SCAN_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseScanRec(Signal* signal) { // Check that all ops this scan has allocated have been // released ndbrequire(scanPtr.p->scanOpsAllocated==0); // Check that all locks this scan might have aquired // have been properly released ndbrequire(scanPtr.p->scanLockHeld == 0); ndbrequire(scanPtr.p->scanFirstLockedOp == RNIL); ndbrequire(scanPtr.p->scanLastLockedOp == RNIL); // Check that all active operations have been // properly released ndbrequire(scanPtr.p->scanFirstActiveOp == RNIL); // Check that all queued operations have been // properly released ndbrequire(scanPtr.p->scanFirstQueuedOp == RNIL); ndbrequire(scanPtr.p->scanLastQueuedOp == RNIL); // Put scan record in free list scanPtr.p->scanNextfreerec = cfirstFreeScanRec; scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT; cfirstFreeScanRec = scanPtr.i; }//Dbacc::releaseScanRec() /* --------------------------------------------------------------------------------- */ /* SEARCH_SCAN_CONTAINER */ /* INPUT: TSSC_CONTAINERLEN */ /* TSSC_CONTAINERPTR */ /* TSSC_ISFORWARD */ /* SSC_PAGEIDPTR */ /* SCAN_PTR */ /* OUTPUT: TSSC_IS_LOCKED */ /* */ /* DESCRIPTION: SEARCH IN A CONTAINER TO FIND THE NEXT SCAN ELEMENT. */ /* TO DO THIS THE SCAN BIT OF THE ELEMENT HEADER IS CHECKED. IF */ /* THIS BIT IS ZERO, IT IS SET TO ONE AND THE ELEMENT IS RETURNED.*/ /* --------------------------------------------------------------------------------- */ bool Dbacc::searchScanContainer(Signal* signal) { OperationrecPtr sscOperPtr; Uint32 tsscScanBits; Uint32 tsscElemlens; Uint32 tsscElemlen; Uint32 tsscElemStep; if (tsscContainerlen < 5) { jam(); return false; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */ }//if tsscElemlens = tsscContainerlen - ZCON_HEAD_SIZE; if (fragrecptr.p->keyLength == 0) { jam(); tsscElemlen = (ZELEM_HEAD_SIZE + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen; } else { jam(); /* LENGTH OF THE ELEMENT */ tsscElemlen = (ZELEM_HEAD_SIZE + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen; }//if /* LENGTH OF THE ELEMENT */ if (tsscIsforward == 1) { jam(); tsscElementptr = tsscContainerptr + ZCON_HEAD_SIZE; tsscElemStep = tsscElemlen; } else { jam(); tsscElementptr = tsscContainerptr - 1; tsscElemStep = 0 - tsscElemlen; }//if SCANELEMENTLOOP001: arrGuard(tsscElementptr, 2048); const Uint32 eh = sscPageidptr.p->word32[tsscElementptr]; tsscIsLocked = ElementHeader::getLocked(eh); if (!tsscIsLocked){ jam(); tsscScanBits = ElementHeader::getScanBits(eh); if ((scanPtr.p->scanMask & tsscScanBits) == 0) { jam(); const Uint32 tmp = ElementHeader::setScanBit(eh, scanPtr.p->scanMask); dbgWord32(sscPageidptr, tsscElementptr, tmp); sscPageidptr.p->word32[tsscElementptr] = tmp; return true; }//if } else { jam(); sscOperPtr.i = ElementHeader::getOpPtrI(eh); ptrCheckGuard(sscOperPtr, coprecsize, operationrec); if ((sscOperPtr.p->scanBits & scanPtr.p->scanMask) == 0) { jam(); sscOperPtr.p->scanBits |= scanPtr.p->scanMask; return true; }//if }//if /* THE ELEMENT IS ALREADY SENT. */ /* SEARCH FOR NEXT ONE */ tsscElemlens = tsscElemlens - tsscElemlen; if (tsscElemlens > 2) { jam(); tsscElementptr = tsscElementptr + tsscElemStep; goto SCANELEMENTLOOP001; }//if return false; }//Dbacc::searchScanContainer() /* --------------------------------------------------------------------------------- */ /* SEND THE RESPONSE NEXT_SCANCONF AND POSSIBLE KEYINFO SIGNALS AS WELL. */ /* --------------------------------------------------------------------------------- */ void Dbacc::sendNextScanConf(Signal* signal) { scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter; Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref); if (!scanPtr.p->scanKeyinfoFlag){ jam(); /** --------------------------------------------------------------------- * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED. * ---------------------------------------------------------------------- */ signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = operationRecPtr.i; signal->theData[2] = operationRecPtr.p->fid; signal->theData[3] = operationRecPtr.p->localdata[0]; signal->theData[4] = operationRecPtr.p->localdata[1]; signal->theData[5] = fragrecptr.p->localkeylen; EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 6); return; }//if fragrecptr.i = operationRecPtr.p->fragptr; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); if (fragrecptr.p->keyLength != 0) { jam(); signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = operationRecPtr.i; signal->theData[2] = operationRecPtr.p->fid; signal->theData[3] = operationRecPtr.p->localdata[0]; signal->theData[4] = operationRecPtr.p->localdata[1]; signal->theData[5] = fragrecptr.p->localkeylen; signal->theData[6] = fragrecptr.p->keyLength; signal->theData[7] = operationRecPtr.p->keydata[0]; signal->theData[8] = operationRecPtr.p->keydata[1]; signal->theData[9] = operationRecPtr.p->keydata[2]; signal->theData[10] = operationRecPtr.p->keydata[3]; EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11); if (fragrecptr.p->keyLength > ZKEYINKEYREQ) { jam(); /* = 4 */ signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = operationRecPtr.i; signal->theData[2] = operationRecPtr.p->fid; signal->theData[3] = fragrecptr.p->keyLength - ZKEYINKEYREQ; signal->theData[4] = operationRecPtr.p->keydata[4]; signal->theData[5] = operationRecPtr.p->keydata[5]; signal->theData[6] = operationRecPtr.p->keydata[6]; signal->theData[7] = operationRecPtr.p->keydata[7]; EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO, signal, 8); return; }//if } else { jam(); sendScaninfo(signal); return; }//if }//Dbacc::sendNextScanConf() /* --------------------------------------------------------------------------------- */ /* SEND_SCANINFO */ /* DESCRIPTION: SCAN AN ELEMENT OF A LONG_KEY_PAGE. */ /* --------------------------------------------------------------------------------- */ void Dbacc::sendScaninfo(Signal* signal) { DirRangePtr ssiOverflowrangeptr; DirectoryarrayPtr ssiOverflowDirptr; Page8Ptr ssiPageptr; Uint32 tssiPageIndex; Uint32 tssiPagedir; Uint32 tssiKeyLen; Uint32 tssiStartIndex; Uint32 tssiIndexValue; Uint32 tssiTmp; Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref); tssiPageIndex = operationRecPtr.p->keydata[0] & 0x3ff; tssiPagedir = operationRecPtr.p->keydata[0] >> 10; ssiOverflowrangeptr.i = fragrecptr.p->overflowdir; ptrCheckGuard(ssiOverflowrangeptr, cdirrangesize, dirRange); arrGuard((tssiPagedir >> 8), 256); ssiOverflowDirptr.i = ssiOverflowrangeptr.p->dirArray[tssiPagedir >> 8]; ptrCheckGuard(ssiOverflowDirptr, cdirarraysize, directoryarray); ssiPageptr.i = ssiOverflowDirptr.p->pagep[tssiPagedir & 0xff]; ptrCheckGuard(ssiPageptr, cpagesize, page8); arrGuard(ZWORDS_IN_PAGE - tssiPageIndex, 2048); tssiIndexValue = ssiPageptr.p->word32[ZWORDS_IN_PAGE - tssiPageIndex]; tssiStartIndex = tssiIndexValue & 0xffff; tssiKeyLen = tssiIndexValue >> 16; signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = operationRecPtr.i; signal->theData[2] = operationRecPtr.p->fid; signal->theData[3] = operationRecPtr.p->localdata[0]; signal->theData[4] = operationRecPtr.p->localdata[1]; signal->theData[5] = fragrecptr.p->localkeylen; signal->theData[6] = tssiKeyLen; arrGuard(tssiStartIndex + 3, 2048); signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex]; signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 1]; signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 2]; signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 3]; EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11); if (tssiKeyLen > 4) { tssiKeyLen = tssiKeyLen - 4; tssiStartIndex = tssiStartIndex + 4; SSI_LOOP_10: jamEntry(); if (tssiKeyLen > ZMAXSCANSIGNALLEN) { jam(); signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = operationRecPtr.i; signal->theData[2] = operationRecPtr.p->fid; signal->theData[3] = ZMAXSCANSIGNALLEN; arrGuard(tssiStartIndex + 19, 2048); signal->theData[4] = ssiPageptr.p->word32[tssiStartIndex]; signal->theData[5] = ssiPageptr.p->word32[tssiStartIndex + 1]; signal->theData[6] = ssiPageptr.p->word32[tssiStartIndex + 2]; signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex + 3]; signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 4]; signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 5]; signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 6]; signal->theData[11] = ssiPageptr.p->word32[tssiStartIndex + 7]; signal->theData[12] = ssiPageptr.p->word32[tssiStartIndex + 8]; signal->theData[13] = ssiPageptr.p->word32[tssiStartIndex + 9]; signal->theData[14] = ssiPageptr.p->word32[tssiStartIndex + 10]; signal->theData[15] = ssiPageptr.p->word32[tssiStartIndex + 11]; signal->theData[16] = ssiPageptr.p->word32[tssiStartIndex + 12]; signal->theData[17] = ssiPageptr.p->word32[tssiStartIndex + 13]; signal->theData[18] = ssiPageptr.p->word32[tssiStartIndex + 14]; signal->theData[19] = ssiPageptr.p->word32[tssiStartIndex + 15]; signal->theData[20] = ssiPageptr.p->word32[tssiStartIndex + 16]; signal->theData[21] = ssiPageptr.p->word32[tssiStartIndex + 17]; signal->theData[22] = ssiPageptr.p->word32[tssiStartIndex + 18]; signal->theData[23] = ssiPageptr.p->word32[tssiStartIndex + 19]; EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24); tssiStartIndex = tssiStartIndex + ZMAXSCANSIGNALLEN; tssiKeyLen = tssiKeyLen - ZMAXSCANSIGNALLEN; goto SSI_LOOP_10; } else { jam(); ndbrequire((tssiStartIndex + tssiKeyLen) <= 2048); for (tssiTmp = 0; tssiTmp < tssiKeyLen; tssiTmp++) { ckeys[tssiTmp] = ssiPageptr.p->word32[tssiStartIndex + tssiTmp]; }//for signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = operationRecPtr.i; signal->theData[2] = operationRecPtr.p->fid; /* LOCAL FRAGMENT IDENTITY */ signal->theData[3] = tssiKeyLen; signal->theData[4] = ckeys[0]; signal->theData[5] = ckeys[1]; signal->theData[6] = ckeys[2]; signal->theData[7] = ckeys[3]; signal->theData[8] = ckeys[4]; signal->theData[9] = ckeys[5]; signal->theData[10] = ckeys[6]; signal->theData[11] = ckeys[7]; signal->theData[12] = ckeys[8]; signal->theData[13] = ckeys[9]; signal->theData[14] = ckeys[10]; signal->theData[15] = ckeys[11]; signal->theData[16] = ckeys[12]; signal->theData[17] = ckeys[13]; signal->theData[18] = ckeys[14]; signal->theData[19] = ckeys[15]; signal->theData[20] = ckeys[16]; signal->theData[21] = ckeys[17]; signal->theData[22] = ckeys[18]; signal->theData[23] = ckeys[19]; EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24); }//if }//if }//Dbacc::sendScaninfo() /*--------------------------------------------------------------------------- * sendScanHbRep * Description: Using Dispatcher::execute() to send a heartbeat to DBTC * from DBLQH telling the scan is alive. We use the sendScanHbRep() * in DBLQH, this needs to be done here in DBACC since it can take * a while before LQH receives an answer the normal way from ACC. *--------------------------------------------------------------------------*/ void Dbacc::sendScanHbRep(Signal* signal, Uint32 scanPtrIndex) { scanPtr.i = scanPtrIndex; ptrCheckGuard(scanPtr, cscanRecSize, scanRec); // If the timer status is on we continue with a new heartbeat in one second, // else the loop stops and we will not send a new CONTINUEB if (scanPtr.p->scanTimer != 0){ if (scanPtr.p->scanTimer == scanPtr.p->scanContinuebCounter){ jam(); ndbrequire(scanPtr.p->scanState != ScanRec::SCAN_DISCONNECT); signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[1] = scanPtr.p->scanTrid1; signal->theData[2] = scanPtr.p->scanTrid2; EXECUTE_DIRECT(DBLQH, GSN_SCAN_HBREP, signal, 3); jamEntry(); }//if scanPtr.p->scanContinuebCounter++; signal->theData[0] = ZSEND_SCAN_HBREP; signal->theData[1] = scanPtr.i; sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 2); } else { jam(); scanPtr.p->scanContinuebCounter = 0; }//if }//Dbacc::sendScanHbRep() /* --------------------------------------------------------------------------------- */ /* SETLOCK */ /* DESCRIPTION:SETS LOCK ON AN ELEMENT. INFORMATION ABOUT THE ELEMENT IS */ /* SAVED IN THE ELEMENT HEAD.A COPY OF THIS INFORMATION WILL */ /* BE PUT IN THE OPERATION RECORD. A FIELD IN THE HEADER OF */ /* THE ELEMENT POINTS TO THE OPERATION RECORD. */ /* --------------------------------------------------------------------------------- */ void Dbacc::setlock(Signal* signal) { Uint32 tselTmp1; arrGuard(tslElementptr, 2048); tselTmp1 = slPageidptr.p->word32[tslElementptr]; operationRecPtr.p->scanBits = ElementHeader::getScanBits(tselTmp1); operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(tselTmp1); tselTmp1 = ElementHeader::setLocked(operationRecPtr.i); dbgWord32(slPageidptr, tslElementptr, tselTmp1); slPageidptr.p->word32[tslElementptr] = tselTmp1; }//Dbacc::setlock() /* --------------------------------------------------------------------------------- */ /* TAKE_OUT_ACTIVE_SCAN_OP */ /* DESCRIPTION: AN ACTIVE SCAN OPERATION IS BELOGED TO AN ACTIVE LIST OF THE */ /* SCAN RECORD. BY THIS SUBRUTIN THE LIST IS UPDATED. */ /* --------------------------------------------------------------------------------- */ void Dbacc::takeOutActiveScanOp(Signal* signal) { OperationrecPtr tasOperationRecPtr; if (operationRecPtr.p->prevOp != RNIL) { jam(); tasOperationRecPtr.i = operationRecPtr.p->prevOp; ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec); tasOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp; } else { jam(); scanPtr.p->scanFirstActiveOp = operationRecPtr.p->nextOp; }//if if (operationRecPtr.p->nextOp != RNIL) { jam(); tasOperationRecPtr.i = operationRecPtr.p->nextOp; ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec); tasOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp; }//if }//Dbacc::takeOutActiveScanOp() /** * takeOutScanLockQueue * * Description: Take out an operation from the doubly linked * lock list on a scan record. * * @note Use putOpScanLockQue to insert a operation in * the list * */ void Dbacc::takeOutScanLockQueue(Uint32 scanRecIndex) { OperationrecPtr tslOperationRecPtr; ScanRecPtr TscanPtr; TscanPtr.i = scanRecIndex; ptrCheckGuard(TscanPtr, cscanRecSize, scanRec); if (operationRecPtr.p->prevOp != RNIL) { jam(); tslOperationRecPtr.i = operationRecPtr.p->prevOp; ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec); tslOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp; } else { jam(); // Check that first are pointing at operation to take out ndbrequire(TscanPtr.p->scanFirstLockedOp==operationRecPtr.i); TscanPtr.p->scanFirstLockedOp = operationRecPtr.p->nextOp; }//if if (operationRecPtr.p->nextOp != RNIL) { jam(); tslOperationRecPtr.i = operationRecPtr.p->nextOp; ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec); tslOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp; } else { jam(); // Check that last are pointing at operation to take out ndbrequire(TscanPtr.p->scanLastLockedOp==operationRecPtr.i); TscanPtr.p->scanLastLockedOp = operationRecPtr.p->prevOp; }//if TscanPtr.p->scanLockHeld--; #ifdef VM_TRACE // DEBUG CODE // Check that there are as many operations in the lockqueue as // scanLockHeld indicates OperationrecPtr tmpOp; int numLockedOps = 0; tmpOp.i = TscanPtr.p->scanFirstLockedOp; while(tmpOp.i != RNIL){ numLockedOps++; ptrCheckGuard(tmpOp, coprecsize, operationrec); if (tmpOp.p->nextOp == RNIL) ndbrequire(tmpOp.i == TscanPtr.p->scanLastLockedOp); tmpOp.i = tmpOp.p->nextOp; } ndbrequire(numLockedOps==TscanPtr.p->scanLockHeld); #endif }//Dbacc::takeOutScanLockQueue() /* --------------------------------------------------------------------------------- */ /* TAKE_OUT_READY_SCAN_QUEUE */ /* --------------------------------------------------------------------------------- */ void Dbacc::takeOutReadyScanQueue(Signal* signal) { OperationrecPtr trsOperationRecPtr; if (operationRecPtr.p->prevOp != RNIL) { jam(); trsOperationRecPtr.i = operationRecPtr.p->prevOp; ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec); trsOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp; } else { jam(); scanPtr.p->scanFirstQueuedOp = operationRecPtr.p->nextOp; }//if if (operationRecPtr.p->nextOp != RNIL) { jam(); trsOperationRecPtr.i = operationRecPtr.p->nextOp; ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec); trsOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp; } else { jam(); scanPtr.p->scanLastQueuedOp = operationRecPtr.p->nextOp; }//if }//Dbacc::takeOutReadyScanQueue() /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* */ /* END OF SCAN MODULE */ /* */ /* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */ bool Dbacc::getrootfragmentrec(Signal* signal, RootfragmentrecPtr& rootPtr, Uint32 fid) { for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) { jam(); if (tabptr.p->fragholder[i] == fid) { jam(); rootPtr.i = tabptr.p->fragptrholder[i]; ptrCheckGuard(rootPtr, crootfragmentsize, rootfragmentrec); return true; }//if }//for return false; }//Dbacc::getrootfragmentrec() /* --------------------------------------------------------------------------------- */ /* INIT_FS_OP_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::initFsOpRec(Signal* signal) { fsOpptr.p->fsOpfragrecPtr = fragrecptr.i; fsOpptr.p->fsConptr = fsConnectptr.i; }//Dbacc::initFsOpRec() /* --------------------------------------------------------------------------------- */ /* INIT_LCP_CONN_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::initLcpConnRec(Signal* signal) { lcpConnectptr.p->lcpUserblockref = tuserblockref; lcpConnectptr.p->lcpUserptr = tuserptr; lcpConnectptr.p->noOfLcpConf = 0; /* NO OF RETUREND CONF SIGNALS */ lcpConnectptr.p->syncUndopageState = WAIT_NOTHING; }//Dbacc::initLcpConnRec() /* --------------------------------------------------------------------------------- */ /* INIT_OVERPAGE */ /* INPUT. IOP_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */ /* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */ /* ACCORDING TO LH3 AND PAGE STRUCTOR DESCRIPTION OF NDBACC BLOCK */ /* --------------------------------------------------------------------------------- */ void Dbacc::initOverpage(Signal* signal) { Uint32 tiopTmp; Uint32 tiopPrevFree; Uint32 tiopNextFree; for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) { iopPageptr.p->word32[tiopIndex] = 0; }//for iopPageptr.p->word32[ZPOS_OVERFLOWREC] = iopOverflowRecPtr.i; iopPageptr.p->word32[ZPOS_CHECKSUM] = 0; iopPageptr.p->word32[ZPOS_PAGE_ID] = tiopPageId; iopPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0; tiopTmp = ZEMPTYLIST; tiopTmp = (tiopTmp << 16) + (tiopTmp << 23); iopPageptr.p->word32[ZPOS_EMPTY_LIST] = tiopTmp + (1 << ZPOS_PAGE_TYPE_BIT); /* --------------------------------------------------------------------------------- */ /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */ /* --------------------------------------------------------------------------------- */ tiopIndex = ZHEAD_SIZE + 1; iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) { tiopIndex = tiopIndex + ZBUF_SIZE; iopPageptr.p->word32[tiopIndex] = tiopPrevFree; }//for /* --------------------------------------------------------------------------------- */ /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */ /* --------------------------------------------------------------------------------- */ tiopIndex = ZHEAD_SIZE; for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) { iopPageptr.p->word32[tiopIndex] = tiopNextFree; tiopIndex = tiopIndex + ZBUF_SIZE; }//for iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* LEFT_LIST IS UPDATED */ /* --------------------------------------------------------------------------------- */ /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */ /* --------------------------------------------------------------------------------- */ tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 1; iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) { tiopIndex = tiopIndex + ZBUF_SIZE; iopPageptr.p->word32[tiopIndex] = tiopPrevFree; }//for /* --------------------------------------------------------------------------------- */ /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */ /* --------------------------------------------------------------------------------- */ tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 2; for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) { iopPageptr.p->word32[tiopIndex] = tiopNextFree; tiopIndex = tiopIndex + ZBUF_SIZE; }//for iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* RIGHT_LIST IS UPDATED */ }//Dbacc::initOverpage() /* --------------------------------------------------------------------------------- */ /* INIT_PAGE */ /* INPUT. INP_PAGEPTR, POINTER TO A PAGE RECORD */ /* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */ /* ACCORDING TO LH3 AND PAGE STRUCTOR DISACRIPTION OF NDBACC BLOCK */ /* --------------------------------------------------------------------------------- */ void Dbacc::initPage(Signal* signal) { Uint32 tinpTmp1; Uint32 tinpIndex; Uint32 tinpTmp; Uint32 tinpPrevFree; Uint32 tinpNextFree; for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) { inpPageptr.p->word32[tiopIndex] = 0; }//for /* --------------------------------------------------------------------------------- */ /* SET PAGE ID FOR USE OF CHECKPOINTER. */ /* PREPARE CONTAINER HEADERS INDICATING EMPTY CONTAINERS WITHOUT NEXT. */ /* --------------------------------------------------------------------------------- */ inpPageptr.p->word32[ZPOS_PAGE_ID] = tipPageId; tinpTmp1 = ZCON_HEAD_SIZE; tinpTmp1 = tinpTmp1 << 26; /* --------------------------------------------------------------------------------- */ /* INITIALISE ZNO_CONTAINERS PREDEFINED HEADERS ON LEFT SIZE. */ /* --------------------------------------------------------------------------------- */ tinpIndex = ZHEAD_SIZE; for (tinpTmp = 0; tinpTmp <= ZNO_CONTAINERS - 1; tinpTmp++) { inpPageptr.p->word32[tinpIndex] = tinpTmp1; tinpIndex = tinpIndex + ZBUF_SIZE; }//for /* WORD32(ZPOS_EMPTY_LIST) DATA STRUCTURE:*/ /*--------------------------------------- */ /*| PAGE TYPE|LEFT FREE|RIGHT FREE */ /*| 1 | LIST | LIST */ /*| BIT | 7 BITS | 7 BITS */ /*--------------------------------------- */ /* --------------------------------------------------------------------------------- */ /* INITIALISE FIRST POINTER TO DOUBLY LINKED LIST OF FREE CONTAINERS. */ /* INITIALISE EMPTY LISTS OF USED CONTAINERS. */ /* INITIALISE LEFT FREE LIST TO 64 AND RIGHT FREE LIST TO ZERO. */ /* ALSO INITIALISE PAGE TYPE TO NOT OVERFLOW PAGE. */ /* --------------------------------------------------------------------------------- */ tinpTmp = ZEMPTYLIST; tinpTmp = (tinpTmp << 16) + (tinpTmp << 23); tinpTmp = tinpTmp + (ZNO_CONTAINERS << 7); inpPageptr.p->word32[ZPOS_EMPTY_LIST] = tinpTmp; /* --------------------------------------------------------------------------------- */ /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */ /* --------------------------------------------------------------------------------- */ tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 1; inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST; for (tinpPrevFree = 0; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) { tinpIndex = tinpIndex + ZBUF_SIZE; inpPageptr.p->word32[tinpIndex] = tinpPrevFree; }//for /* --------------------------------------------------------------------------------- */ /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */ /* --------------------------------------------------------------------------------- */ tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 2; for (tinpNextFree = 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) { inpPageptr.p->word32[tinpIndex] = tinpNextFree; tinpIndex = tinpIndex + ZBUF_SIZE; }//for inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST; /* --------------------------------------------------------------------------------- */ /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */ /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */ /* PREDEFINED AS OCCUPIED. */ /* --------------------------------------------------------------------------------- */ tinpIndex = (ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE; for (tinpNextFree = ZNO_CONTAINERS + 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) { inpPageptr.p->word32[tinpIndex] = tinpNextFree; tinpIndex = tinpIndex + ZBUF_SIZE; }//for inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST; /* --------------------------------------------------------------------------------- */ /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */ /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */ /* PREDEFINED AS OCCUPIED. */ /* --------------------------------------------------------------------------------- */ tinpIndex = ((ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE) + 1; inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST; for (tinpPrevFree = ZNO_CONTAINERS; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) { tinpIndex = tinpIndex + ZBUF_SIZE; inpPageptr.p->word32[tinpIndex] = tinpPrevFree; }//for /* --------------------------------------------------------------------------------- */ /* INITIALISE HEADER POSITIONS NOT CURRENTLY USED AND ENSURE USE OF OVERFLOW */ /* RECORD POINTER ON THIS PAGE LEADS TO ERROR. */ /* --------------------------------------------------------------------------------- */ inpPageptr.p->word32[ZPOS_CHECKSUM] = 0; inpPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0; inpPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL; }//Dbacc::initPage() /* --------------------------------------------------------------------------------- */ /* PUT_OP_IN_FRAG_WAIT_QUE */ /* DESCRIPTION: AN OPERATION WHICH OWNS A LOCK OF AN ELEMENT, IS PUT IN A */ /* LIST OF THE FRAGMENT. THIS LIST IS USED TO STOP THE QUEUE */ /* OPERATION DURING CREATE CHECK POINT PROSESS FOR STOP AND */ /* RESTART OF THE OPERATIONS. */ /* */ /* IF CONTINUEB SIGNALS ARE INTRODUCED AFTER STARTING TO EXECUTE ACCKEYREQ WE */ /* MUST PUT IT IN THIS LIST BEFORE EXITING TO ENSURE THAT WE ARE NOT BEING */ /* LOCKED AFTER THAT LQH HAS RECEIVED ALL LCP_HOLDOP'S. THEN THE LCP WILL NEVER*/ /* PROCEED. WE ALSO PUT IT INTO THIS LIST WHEN WAITING FOR LONG KEYS. THIS IS */ /* ONLY NEEDED IF SIGNALS CAN ENTER BETWEEN THE KEYDATA CARRYING SIGNALS. */ /* --------------------------------------------------------------------------------- */ void Dbacc::putOpInFragWaitQue(Signal* signal) { OperationrecPtr tpiwOperRecPtr; if (operationRecPtr.p->operation != ZSCAN_OP) { if (fragrecptr.p->firstWaitInQueOp == RNIL) { jam(); fragrecptr.p->firstWaitInQueOp = operationRecPtr.i; } else { jam(); tpiwOperRecPtr.i = fragrecptr.p->lastWaitInQueOp; ptrCheckGuard(tpiwOperRecPtr, coprecsize, operationrec); tpiwOperRecPtr.p->nextQueOp = operationRecPtr.i; }//if operationRecPtr.p->opState = WAIT_IN_QUEUE; operationRecPtr.p->nextQueOp = RNIL; operationRecPtr.p->prevQueOp = fragrecptr.p->lastWaitInQueOp; fragrecptr.p->lastWaitInQueOp = operationRecPtr.i; }//if }//Dbacc::putOpInFragWaitQue() /* --------------------------------------------------------------------------------- */ /* PUT_OVERFLOW_REC_IN_FRAG */ /* DESCRIPTION: AN OVERFLOW RECORD WITCH IS USED TO KEEP INFORMATION ABOUT */ /* OVERFLOW PAGE WILL BE PUT IN A LIST OF OVERFLOW RECORDS IN */ /* THE FRAGMENT RECORD. */ /* --------------------------------------------------------------------------------- */ void Dbacc::putOverflowRecInFrag(Signal* signal) { OverflowRecordPtr tpifNextOverrecPtr; OverflowRecordPtr tpifPrevOverrecPtr; tpifNextOverrecPtr.i = fragrecptr.p->firstOverflowRec; tpifPrevOverrecPtr.i = RNIL; while (tpifNextOverrecPtr.i != RNIL) { ptrCheckGuard(tpifNextOverrecPtr, coverflowrecsize, overflowRecord); if (tpifNextOverrecPtr.p->dirindex < porOverflowRecPtr.p->dirindex) { jam(); /* --------------------------------------------------------------------------------- */ /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/ /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */ /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */ /* PERFORMED. */ /* --------------------------------------------------------------------------------- */ tpifPrevOverrecPtr = tpifNextOverrecPtr; tpifNextOverrecPtr.i = tpifNextOverrecPtr.p->nextOverRec; } else { jam(); ndbrequire(tpifNextOverrecPtr.p->dirindex != porOverflowRecPtr.p->dirindex); /* --------------------------------------------------------------------------------- */ /* TRYING TO INSERT THE SAME PAGE TWICE. SYSTEM ERROR. */ /* --------------------------------------------------------------------------------- */ break; }//if }//while if (tpifNextOverrecPtr.i == RNIL) { jam(); fragrecptr.p->lastOverflowRec = porOverflowRecPtr.i; } else { jam(); tpifNextOverrecPtr.p->prevOverRec = porOverflowRecPtr.i; }//if if (tpifPrevOverrecPtr.i == RNIL) { jam(); fragrecptr.p->firstOverflowRec = porOverflowRecPtr.i; } else { jam(); tpifPrevOverrecPtr.p->nextOverRec = porOverflowRecPtr.i; }//if porOverflowRecPtr.p->prevOverRec = tpifPrevOverrecPtr.i; porOverflowRecPtr.p->nextOverRec = tpifNextOverrecPtr.i; }//Dbacc::putOverflowRecInFrag() /* --------------------------------------------------------------------------------- */ /* PUT_REC_IN_FREE_OVERDIR */ /* --------------------------------------------------------------------------------- */ void Dbacc::putRecInFreeOverdir(Signal* signal) { OverflowRecordPtr tpfoNextOverrecPtr; OverflowRecordPtr tpfoPrevOverrecPtr; tpfoNextOverrecPtr.i = fragrecptr.p->firstFreeDirindexRec; tpfoPrevOverrecPtr.i = RNIL; while (tpfoNextOverrecPtr.i != RNIL) { ptrCheckGuard(tpfoNextOverrecPtr, coverflowrecsize, overflowRecord); if (tpfoNextOverrecPtr.p->dirindex < priOverflowRecPtr.p->dirindex) { jam(); /* --------------------------------------------------------------------------------- */ /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/ /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */ /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */ /* PERFORMED. */ /* --------------------------------------------------------------------------------- */ tpfoPrevOverrecPtr = tpfoNextOverrecPtr; tpfoNextOverrecPtr.i = tpfoNextOverrecPtr.p->nextOverList; } else { jam(); ndbrequire(tpfoNextOverrecPtr.p->dirindex != priOverflowRecPtr.p->dirindex); /* --------------------------------------------------------------------------------- */ /* ENSURE WE ARE NOT TRYING TO INSERT THE SAME PAGE TWICE. */ /* --------------------------------------------------------------------------------- */ break; }//if }//while if (tpfoNextOverrecPtr.i != RNIL) { jam(); tpfoNextOverrecPtr.p->prevOverList = priOverflowRecPtr.i; }//if if (tpfoPrevOverrecPtr.i == RNIL) { jam(); fragrecptr.p->firstFreeDirindexRec = priOverflowRecPtr.i; } else { jam(); tpfoPrevOverrecPtr.p->nextOverList = priOverflowRecPtr.i; }//if priOverflowRecPtr.p->prevOverList = tpfoPrevOverrecPtr.i; priOverflowRecPtr.p->nextOverList = tpfoNextOverrecPtr.i; }//Dbacc::putRecInFreeOverdir() /* --------------------------------------------------------------------------------- */ /* RELEASE_DIRECTORY */ /* --------------------------------------- ----------------------------------------- */ void Dbacc::releaseDirectory(Signal* signal) { ptrCheckGuard(rdDirptr, cdirarraysize, directoryarray); rdDirptr.p->pagep[0] = cfirstfreedir; cfirstfreedir = rdDirptr.i; }//Dbacc::releaseDirectory() /* --------------------------------------------------------------------------------- */ /* RELEASE_DIRRANGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseDirrange(Signal* signal) { ptrCheckGuard(rdDirRangePtr, cdirrangesize, dirRange); rdDirRangePtr.p->dirArray[0] = cfirstfreeDirrange; cfirstfreeDirrange = rdDirRangePtr.i; }//Dbacc::releaseDirrange() /* --------------------------------------------------------------------------------- */ /* RELEASE_FS_CONN_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseFsConnRec(Signal* signal) { fsConnectptr.p->fsNext = cfsFirstfreeconnect; cfsFirstfreeconnect = fsConnectptr.i; fsConnectptr.p->fsState = WAIT_NOTHING; }//Dbacc::releaseFsConnRec() /* --------------------------------------------------------------------------------- */ /* RELEASE_FS_OP_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseFsOpRec(Signal* signal) { fsOpptr.p->fsOpnext = cfsFirstfreeop; cfsFirstfreeop = fsOpptr.i; fsOpptr.p->fsOpstate = WAIT_NOTHING; }//Dbacc::releaseFsOpRec() /* --------------------------------------------------------------------------------- */ /* RELEASE_LCP_CONNECT_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseLcpConnectRec(Signal* signal) { lcpConnectptr.p->lcpstate = LCP_FREE; lcpConnectptr.p->nextLcpConn = cfirstfreelcpConnect; lcpConnectptr.p->lcpstate = LCP_FREE; cfirstfreelcpConnect = lcpConnectptr.i; }//Dbacc::releaseLcpConnectRec() /* --------------------------------------------------------------------------------- */ /* RELEASE OP RECORD */ /* PUT A FREE OPERATION IN A FREE LIST OF THE OPERATIONS */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseOpRec(Signal* signal) { #if 0 // DEBUG CODE // Check that the operation to be released isn't // already in the list of free operations // Since this code loops through the entire list of free operations // it's only enabled in VM_TRACE mode OperationrecPtr opRecPtr; bool opInList = false; opRecPtr.i = cfreeopRec; while (opRecPtr.i != RNIL){ if (opRecPtr.i == operationRecPtr.i){ opInList = true; break; } ptrCheckGuard(opRecPtr, coprecsize, operationrec); opRecPtr.i = opRecPtr.p->nextOp; } ndbrequire(opInList == false); #endif ndbrequire(operationRecPtr.p->lockOwner == ZFALSE); operationRecPtr.p->nextOp = cfreeopRec; cfreeopRec = operationRecPtr.i; /* UPDATE FREE LIST OF OP RECORDS */ operationRecPtr.p->prevOp = RNIL; operationRecPtr.p->opState = FREE_OP; operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->operation = ZUNDEFINED_OP; }//Dbacc::releaseOpRec() /* --------------------------------------------------------------------------------- */ /* RELEASE_OVERFLOW_REC */ /* PUT A FREE OVERFLOW REC IN A FREE LIST OF THE OVERFLOW RECORDS */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseOverflowRec(Signal* signal) { rorOverflowRecPtr.p->nextfreeoverrec = cfirstfreeoverrec; cfirstfreeoverrec = rorOverflowRecPtr.i; }//Dbacc::releaseOverflowRec() /* --------------------------------------------------------------------------------- */ /* RELEASE_OVERPAGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseOverpage(Signal* signal) { DirRangePtr ropOverflowrangeptr; DirectoryarrayPtr ropOverflowDirptr; OverflowRecordPtr ropOverflowRecPtr; OverflowRecordPtr tuodOverflowRecPtr; Uint32 tropTmp; Uint32 tropTmp1; Uint32 tropTmp2; ropOverflowRecPtr.i = ropPageptr.p->word32[ZPOS_OVERFLOWREC]; ndbrequire(ropOverflowRecPtr.i != RNIL); /* THE OVERFLOW REC WILL BE TAKEN OUT OF THE */ /* FREELIST OF OVERFLOW PAGE WITH FREE */ /* CONTAINER AND WILL BE PUT IN THE FREE LIST */ /* OF THE FREE DIRECTORY INDEXES. */ if ((fragrecptr.p->lastOverflowRec == ropOverflowRecPtr.i) && (fragrecptr.p->firstOverflowRec == ropOverflowRecPtr.i)) { jam(); return; /* THERE IS ONLY ONE OVERFLOW PAGE */ }//if if ((fragrecptr.p->createLcp == ZTRUE) && (fragrecptr.p->lcpMaxOverDirIndex > ropPageptr.p->word32[ZPOS_PAGE_ID])) { /* --------------------------------------------------------------------------------- */ /* THE PAGE PARTICIPATES IN THE LOCAL CHECKPOINT. */ /* --------------------------------------------------------------------------------- */ if (fragrecptr.p->fragState == LCP_SEND_PAGES) { jam(); /* --------------------------------------------------------------------------------- */ /* THE PAGE PARTICIPATES IN THE LOCAL CHECKPOINT AND THE WRITE TO DISK HAS NOT */ /* YET BEEN COMPLETED. WE MUST KEEP IT A WHILE LONGER SINCE AN EMPTY PAGE IS */ /* NOT EQUIVALENT TO AN INITIALISED PAGE SINCE THE FREE LISTS CAN DIFFER. */ /* --------------------------------------------------------------------------------- */ return; } else { if ((fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) && (fragrecptr.p->lcpDirIndex <= ropPageptr.p->word32[ZPOS_PAGE_ID])) { jam(); /* --------------------------------------------------------------------------------- */ /* SEE COMMENT ABOVE */ /* --------------------------------------------------------------------------------- */ return; }//if }//if }//if #if kalle logicalPage = 0; i = fragrecptr.p->directory; p = dirRange.getPtr(i); i1 = logicalPage >> 8; i2 = logicalPage & 0xFF; ndbrequire(i1 < 256); i = p->dirArray[i1]; p = directoryarray.getPtr(i); physicPageId = p->pagep[i2]; physicPageP = page8.getPtr(physicPageId); p->pagep[i2] = RNIL; rpPageptr = { physicPageId, physicPageP }; releasePage(signal); #endif /* --------------------------------------------------------------------------------- */ /* IT WAS OK TO RELEASE THE PAGE. */ /* --------------------------------------------------------------------------------- */ ptrCheckGuard(ropOverflowRecPtr, coverflowrecsize, overflowRecord); tfoOverflowRecPtr = ropOverflowRecPtr; takeRecOutOfFreeOverpage(signal); ropOverflowRecPtr.p->overpage = RNIL; priOverflowRecPtr = ropOverflowRecPtr; putRecInFreeOverdir(signal); tropTmp = ropPageptr.p->word32[ZPOS_PAGE_ID]; ropOverflowrangeptr.i = fragrecptr.p->overflowdir; tropTmp1 = tropTmp >> 8; tropTmp2 = tropTmp & 0xff; ptrCheckGuard(ropOverflowrangeptr, cdirrangesize, dirRange); arrGuard(tropTmp1, 256); ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1]; ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray); ropOverflowDirptr.p->pagep[tropTmp2] = RNIL; rpPageptr = ropPageptr; releasePage(signal); if (ropOverflowRecPtr.p->dirindex != (fragrecptr.p->lastOverIndex - 1)) { jam(); return; }//if /* --------------------------------------------------------------------------------- */ /* THE LAST PAGE IN THE DIRECTORY WAS RELEASED IT IS NOW NECESSARY TO REMOVE */ /* ALL RELEASED OVERFLOW DIRECTORIES AT THE END OF THE LIST. */ /* --------------------------------------------------------------------------------- */ do { fragrecptr.p->lastOverIndex--; if (tropTmp2 == 0) { jam(); ndbrequire(tropTmp1 != 0); ropOverflowrangeptr.p->dirArray[tropTmp1] = RNIL; rdDirptr.i = ropOverflowDirptr.i; releaseDirectory(signal); tropTmp1--; tropTmp2 = 255; } else { jam(); tropTmp2--; }//if ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1]; ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray); } while (ropOverflowDirptr.p->pagep[tropTmp2] == RNIL); /* --------------------------------------------------------------------------------- */ /* RELEASE ANY OVERFLOW RECORDS THAT ARE PART OF THE FREE INDEX LIST WHICH */ /* DIRECTORY INDEX NOW HAS BEEN RELEASED. */ /* --------------------------------------------------------------------------------- */ tuodOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec; jam(); while (tuodOverflowRecPtr.i != RNIL) { jam(); ptrCheckGuard(tuodOverflowRecPtr, coverflowrecsize, overflowRecord); if (tuodOverflowRecPtr.p->dirindex >= fragrecptr.p->lastOverIndex) { jam(); rorOverflowRecPtr = tuodOverflowRecPtr; troOverflowRecPtr.p = tuodOverflowRecPtr.p; tuodOverflowRecPtr.i = troOverflowRecPtr.p->nextOverList; takeRecOutOfFreeOverdir(signal); releaseOverflowRec(signal); } else { jam(); tuodOverflowRecPtr.i = tuodOverflowRecPtr.p->nextOverList; }//if }//while }//Dbacc::releaseOverpage() /* --------------------------------------------------------------------------------- */ /* RELEASE_PAGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::releasePage(Signal* signal) { #ifdef VM_TRACE bool inList = false; Uint32 numInList = 0; Page8Ptr tmpPagePtr; tmpPagePtr.i = cfirstfreepage; while (tmpPagePtr.i != RNIL){ ptrCheckGuard(tmpPagePtr, cpagesize, page8); if (tmpPagePtr.i == rpPageptr.i){ jam(); inList = true; break; } numInList++; tmpPagePtr.i = tmpPagePtr.p->word32[0]; } ndbrequire(inList == false); // ndbrequire(numInList == cnoOfAllocatedPages); #endif rpPageptr.p->word32[0] = cfirstfreepage; cfirstfreepage = rpPageptr.i; cnoOfAllocatedPages--; }//Dbacc::releasePage() /* --------------------------------------------------------------------------------- */ /* RELEASE_LCP_PAGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseLcpPage(Signal* signal) { rlpPageptr.p->word32[0] = cfirstfreeLcpPage; cfirstfreeLcpPage = rlpPageptr.i; }//Dbacc::releaseLcpPage() /* --------------------------------------------------------------------------------- */ /* RELEASE_SR_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::releaseSrRec(Signal* signal) { srVersionPtr.p->nextFreeSr = cfirstFreeSrVersionRec; cfirstFreeSrVersionRec = srVersionPtr.i; }//Dbacc::releaseSrRec() /* --------------------------------------------------------------------------------- */ /* SEIZE_DIRECTORY */ /* DESCRIPTION: A DIRECTORY BLOCK (ZDIRBLOCKSIZE NUMBERS OF DIRECTORY */ /* RECORDS WILL BE ALLOCATED AND RETURNED. */ /* SIZE OF DIRECTORY ERROR_CODE, WILL BE RETURNED IF THERE IS NO ANY */ /* FREE BLOCK */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeDirectory(Signal* signal) { Uint32 tsdyIndex; if (cfirstfreedir == RNIL) { jam(); if (cdirarraysize <= cdirmemory) { jam(); tresult = ZDIRSIZE_ERROR; return; } else { jam(); sdDirptr.i = cdirmemory; ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray); cdirmemory = cdirmemory + 1; }//if } else { jam(); sdDirptr.i = cfirstfreedir; ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray); cfirstfreedir = sdDirptr.p->pagep[0]; sdDirptr.p->pagep[0] = RNIL; }//if for (tsdyIndex = 0; tsdyIndex <= 255; tsdyIndex++) { sdDirptr.p->pagep[tsdyIndex] = RNIL; }//for }//Dbacc::seizeDirectory() /* --------------------------------------------------------------------------------- */ /* SEIZE_DIRRANGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeDirrange(Signal* signal) { Uint32 tsdeIndex; newDirRangePtr.i = cfirstfreeDirrange; ptrCheckGuard(newDirRangePtr, cdirrangesize, dirRange); cfirstfreeDirrange = newDirRangePtr.p->dirArray[0]; for (tsdeIndex = 0; tsdeIndex <= 255; tsdeIndex++) { newDirRangePtr.p->dirArray[tsdeIndex] = RNIL; }//for }//Dbacc::seizeDirrange() /* --------------------------------------------------------------------------------- */ /* SEIZE FRAGREC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeFragrec(Signal* signal) { fragrecptr.i = cfirstfreefrag; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); cfirstfreefrag = fragrecptr.p->nextfreefrag; fragrecptr.p->nextfreefrag = RNIL; }//Dbacc::seizeFragrec() /* --------------------------------------------------------------------------------- */ /* SEIZE_FS_CONNECT_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeFsConnectRec(Signal* signal) { fsConnectptr.i = cfsFirstfreeconnect; ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec); cfsFirstfreeconnect = fsConnectptr.p->fsNext; fsConnectptr.p->fsNext = RNIL; fsConnectptr.p->fsState = WAIT_NOTHING; }//Dbacc::seizeFsConnectRec() /* --------------------------------------------------------------------------------- */ /* SEIZE_FS_OP_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeFsOpRec(Signal* signal) { fsOpptr.i = cfsFirstfreeop; ptrCheckGuard(fsOpptr, cfsOpsize, fsOprec); cfsFirstfreeop = fsOpptr.p->fsOpnext; fsOpptr.p->fsOpnext = RNIL; }//Dbacc::seizeFsOpRec() /* --------------------------------------------------------------------------------- */ /* SEIZE_LCP_CONNECT_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeLcpConnectRec(Signal* signal) { lcpConnectptr.i = cfirstfreelcpConnect; ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec); cfirstfreelcpConnect = lcpConnectptr.p->nextLcpConn; lcpConnectptr.p->nextLcpConn = RNIL; }//Dbacc::seizeLcpConnectRec() /* --------------------------------------------------------------------------------- */ /* SEIZE_OP_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeOpRec(Signal* signal) { operationRecPtr.i = cfreeopRec; ptrCheckGuard(operationRecPtr, coprecsize, operationrec); cfreeopRec = operationRecPtr.p->nextOp; /* UPDATE FREE LIST OF OP RECORDS */ /* PUTS OPERTION RECORD PTR IN THE LIST */ /* OF OPERATION IN CONNECTION RECORD */ operationRecPtr.p->nextOp = RNIL; }//Dbacc::seizeOpRec() /* --------------------------------------------------------------------------------- */ /* SEIZE OVERFLOW RECORD */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeOverRec(Signal* signal) { sorOverflowRecPtr.i = cfirstfreeoverrec; ptrCheckGuard(sorOverflowRecPtr, coverflowrecsize, overflowRecord); cfirstfreeoverrec = sorOverflowRecPtr.p->nextfreeoverrec; sorOverflowRecPtr.p->nextfreeoverrec = RNIL; sorOverflowRecPtr.p->prevOverRec = RNIL; sorOverflowRecPtr.p->nextOverRec = RNIL; }//Dbacc::seizeOverRec() /** * A ZPAGESIZE_ERROR has occured, out of index pages * Print some debug info if debug compiled */ void Dbacc::zpagesize_error(const char* where){ DEBUG(where << endl << " ZPAGESIZE_ERROR" << endl << " cfirstfreepage=" << cfirstfreepage << endl << " cfreepage=" <<cfreepage<<endl << " cpagesize=" <<cpagesize<<endl << " cnoOfAllocatedPages="<<cnoOfAllocatedPages); } /* --------------------------------------------------------------------------------- */ /* SEIZE_PAGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizePage(Signal* signal) { tresult = 0; if (cfirstfreepage == RNIL) { if (cfreepage < cpagesize) { jam(); spPageptr.i = cfreepage; ptrCheckGuard(spPageptr, cpagesize, page8); cfreepage++; cnoOfAllocatedPages++; } else { jam(); zpagesize_error("Dbacc::seizePage"); tresult = ZPAGESIZE_ERROR; }//if } else { jam(); spPageptr.i = cfirstfreepage; ptrCheckGuard(spPageptr, cpagesize, page8); cfirstfreepage = spPageptr.p->word32[0]; cnoOfAllocatedPages++; }//if }//Dbacc::seizePage() /* --------------------------------------------------------------------------------- */ /* SEIZE_PAGE */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeLcpPage(Page8Ptr& regPagePtr) { regPagePtr.i = cfirstfreeLcpPage; ptrCheckGuard(regPagePtr, cpagesize, page8); cfirstfreeLcpPage = regPagePtr.p->word32[0]; }//Dbacc::seizeLcpPage() /* --------------------------------------------------------------------------------- */ /* SEIZE_ROOTFRAGREC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeRootfragrec(Signal* signal) { rootfragrecptr.i = cfirstfreerootfrag; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); cfirstfreerootfrag = rootfragrecptr.p->nextroot; rootfragrecptr.p->nextroot = RNIL; }//Dbacc::seizeRootfragrec() /* --------------------------------------------------------------------------------- */ /* SEIZE_SCAN_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeScanRec(Signal* signal) { scanPtr.i = cfirstFreeScanRec; ptrCheckGuard(scanPtr, cscanRecSize, scanRec); ndbrequire(scanPtr.p->scanState == ScanRec::SCAN_DISCONNECT); cfirstFreeScanRec = scanPtr.p->scanNextfreerec; }//Dbacc::seizeScanRec() /* --------------------------------------------------------------------------------- */ /* SEIZE_SR_VERSION_REC */ /* --------------------------------------------------------------------------------- */ void Dbacc::seizeSrVerRec(Signal* signal) { srVersionPtr.i = cfirstFreeSrVersionRec; ptrCheckGuard(srVersionPtr, csrVersionRecSize, srVersionRec); cfirstFreeSrVersionRec = srVersionPtr.p->nextFreeSr; }//Dbacc::seizeSrVerRec() /* --------------------------------------------------------------------------------- */ /* SEND_SYSTEMERROR */ /* --------------------------------------------------------------------------------- */ void Dbacc::sendSystemerror(Signal* signal) { progError(0, 0); }//Dbacc::sendSystemerror() /* --------------------------------------------------------------------------------- */ /* TAKE_REC_OUT_OF_FREE_OVERDIR */ /* --------------------------------------------------------------------------------- */ void Dbacc::takeRecOutOfFreeOverdir(Signal* signal) { OverflowRecordPtr tofoOverrecPtr; if (troOverflowRecPtr.p->nextOverList != RNIL) { jam(); tofoOverrecPtr.i = troOverflowRecPtr.p->nextOverList; ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord); tofoOverrecPtr.p->prevOverList = troOverflowRecPtr.p->prevOverList; }//if if (troOverflowRecPtr.p->prevOverList != RNIL) { jam(); tofoOverrecPtr.i = troOverflowRecPtr.p->prevOverList; ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord); tofoOverrecPtr.p->nextOverList = troOverflowRecPtr.p->nextOverList; } else { jam(); fragrecptr.p->firstFreeDirindexRec = troOverflowRecPtr.p->nextOverList; }//if }//Dbacc::takeRecOutOfFreeOverdir() /* --------------------------------------------------------------------------------- */ /* TAKE_REC_OUT_OF_FREE_OVERPAGE */ /* DESCRIPTION: AN OVERFLOW PAGE WHICH IS EMPTY HAVE TO BE TAKE OUT OF THE */ /* FREE LIST OF OVERFLOW PAGE. BY THIS SUBROUTINE THIS LIST */ /* WILL BE UPDATED. */ /* --------------------------------------------------------------------------------- */ void Dbacc::takeRecOutOfFreeOverpage(Signal* signal) { OverflowRecordPtr tfoNextOverflowRecPtr; OverflowRecordPtr tfoPrevOverflowRecPtr; if (tfoOverflowRecPtr.p->nextOverRec != RNIL) { jam(); tfoNextOverflowRecPtr.i = tfoOverflowRecPtr.p->nextOverRec; ptrCheckGuard(tfoNextOverflowRecPtr, coverflowrecsize, overflowRecord); tfoNextOverflowRecPtr.p->prevOverRec = tfoOverflowRecPtr.p->prevOverRec; } else { ndbrequire(fragrecptr.p->lastOverflowRec == tfoOverflowRecPtr.i); jam(); fragrecptr.p->lastOverflowRec = tfoOverflowRecPtr.p->prevOverRec; }//if if (tfoOverflowRecPtr.p->prevOverRec != RNIL) { jam(); tfoPrevOverflowRecPtr.i = tfoOverflowRecPtr.p->prevOverRec; ptrCheckGuard(tfoPrevOverflowRecPtr, coverflowrecsize, overflowRecord); tfoPrevOverflowRecPtr.p->nextOverRec = tfoOverflowRecPtr.p->nextOverRec; } else { ndbrequire(fragrecptr.p->firstOverflowRec == tfoOverflowRecPtr.i); jam(); fragrecptr.p->firstOverflowRec = tfoOverflowRecPtr.p->nextOverRec; }//if }//Dbacc::takeRecOutOfFreeOverpage() void Dbacc::reportMemoryUsage(Signal* signal, int gth){ signal->theData[0] = EventReport::MemoryUsage; signal->theData[1] = gth; signal->theData[2] = sizeof(* rpPageptr.p); signal->theData[3] = cnoOfAllocatedPages; signal->theData[4] = cpagesize; signal->theData[5] = DBACC; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB); } void Dbacc::execDUMP_STATE_ORD(Signal* signal) { DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0]; if (dumpState->args[0] == DumpStateOrd::AccDumpOneScanRec){ Uint32 recordNo = RNIL; if (signal->length() == 2) recordNo = dumpState->args[1]; else return; if (recordNo >= cscanRecSize) return; scanPtr.i = recordNo; ptrAss(scanPtr, scanRec); infoEvent("Dbacc::ScanRec[%d]: state=%d, transid(0x%x, 0x%x)", scanPtr.i, scanPtr.p->scanState,scanPtr.p->scanTrid1, scanPtr.p->scanTrid2); infoEvent(" timer=%d, continueBCount=%d, " "activeLocalFrag=%d, root=%d, nextBucketIndex=%d", scanPtr.p->scanTimer, scanPtr.p->scanContinuebCounter, scanPtr.p->activeLocalFrag, scanPtr.p->rootPtr, scanPtr.p->nextBucketIndex); infoEvent(" scanNextfreerec=%d firstActOp=%d firstLockedOp=%d, " "scanLastLockedOp=%d firstQOp=%d lastQOp=%d", scanPtr.p->scanNextfreerec, scanPtr.p->scanFirstActiveOp, scanPtr.p->scanFirstLockedOp, scanPtr.p->scanLastLockedOp, scanPtr.p->scanFirstQueuedOp, scanPtr.p->scanLastQueuedOp); infoEvent(" scanUserP=%d, startNoBuck=%d, minBucketIndexToRescan=%d, " "maxBucketIndexToRescan=%d", scanPtr.p->scanUserptr, scanPtr.p->startNoOfBuckets, scanPtr.p->minBucketIndexToRescan, scanPtr.p->maxBucketIndexToRescan); infoEvent(" scanBucketState=%d, scanLockHeld=%d, userBlockRef=%d, " "scanMask=%d scanLockMode=%d, keyInfoFlag=%d", scanPtr.p->scanBucketState, scanPtr.p->scanLockHeld, scanPtr.p->scanUserblockref, scanPtr.p->scanMask, scanPtr.p->scanLockMode, scanPtr.p->scanKeyinfoFlag); return; } // Dump all ScanRec(ords) if (dumpState->args[0] == DumpStateOrd::AccDumpAllScanRec){ Uint32 recordNo = 0; if (signal->length() == 1) infoEvent("ACC: Dump all ScanRec - size: %d", cscanRecSize); else if (signal->length() == 2) recordNo = dumpState->args[1]; else return; dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec; dumpState->args[1] = recordNo; execDUMP_STATE_ORD(signal); if (recordNo < cscanRecSize-1){ dumpState->args[0] = DumpStateOrd::AccDumpAllScanRec; dumpState->args[1] = recordNo+1; sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB); } return; } // Dump all active ScanRec(ords) if (dumpState->args[0] == DumpStateOrd::AccDumpAllActiveScanRec){ Uint32 recordNo = 0; if (signal->length() == 1) infoEvent("ACC: Dump active ScanRec - size: %d", cscanRecSize); else if (signal->length() == 2) recordNo = dumpState->args[1]; else return; ScanRecPtr sp; sp.i = recordNo; ptrAss(sp, scanRec); if (sp.p->scanState != ScanRec::SCAN_DISCONNECT){ dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec; dumpState->args[1] = recordNo; execDUMP_STATE_ORD(signal); } if (recordNo < cscanRecSize-1){ dumpState->args[0] = DumpStateOrd::AccDumpAllActiveScanRec; dumpState->args[1] = recordNo+1; sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB); } return; } if(dumpState->args[0] == DumpStateOrd::DumpPageMemory){ reportMemoryUsage(signal, 0); return; } if(dumpState->args[0] == DumpStateOrd::EnableUndoDelayDataWrite){ ndbout << "Dbacc:: delay write of datapages for table = " << dumpState->args[1]<< endl; c_errorInsert3000_TableId = dumpState->args[1]; SET_ERROR_INSERT_VALUE(3000); return; } if(dumpState->args[0] == DumpStateOrd::AccDumpOneOperationRec){ Uint32 recordNo = RNIL; if (signal->length() == 2) recordNo = dumpState->args[1]; else return; if (recordNo >= coprecsize) return; OperationrecPtr tmpOpPtr; tmpOpPtr.i = recordNo; ptrAss(tmpOpPtr, operationrec); infoEvent("Dbacc::operationrec[%d]: opState=%d, transid(0x%x, 0x%x)", tmpOpPtr.i, tmpOpPtr.p->opState, tmpOpPtr.p->transId1, tmpOpPtr.p->transId2); infoEvent("elementIsforward=%d, elementPage=%d, elementPointer=%d ", tmpOpPtr.p->elementIsforward, tmpOpPtr.p->elementPage, tmpOpPtr.p->elementPointer); infoEvent("fid=%d, fragptr=%d, hashvaluePart=%d ", tmpOpPtr.p->fid, tmpOpPtr.p->fragptr, tmpOpPtr.p->hashvaluePart); infoEvent("hashValue=%d, insertDeleteLen=%d, keyinfoPage=%d ", tmpOpPtr.p->hashValue, tmpOpPtr.p->insertDeleteLen, tmpOpPtr.p->keyinfoPage); infoEvent("nextLockOwnerOp=%d, nextOp=%d, nextParallelQue=%d ", tmpOpPtr.p->nextLockOwnerOp, tmpOpPtr.p->nextOp, tmpOpPtr.p->nextParallelQue); infoEvent("nextQueOp=%d, nextSerialQue=%d, prevOp=%d ", tmpOpPtr.p->nextQueOp, tmpOpPtr.p->nextSerialQue, tmpOpPtr.p->prevOp); infoEvent("prevLockOwnerOp=%d, prevParallelQue=%d, prevQueOp=%d ", tmpOpPtr.p->prevLockOwnerOp, tmpOpPtr.p->nextParallelQue, tmpOpPtr.p->prevQueOp); infoEvent("prevSerialQue=%d, scanRecPtr=%d, longPagePtr=%d ", tmpOpPtr.p->prevSerialQue, tmpOpPtr.p->scanRecPtr, tmpOpPtr.p->longPagePtr); infoEvent("transactionstate=%d, elementIsDisappeared=%d, insertIsDone=%d ", tmpOpPtr.p->transactionstate, tmpOpPtr.p->elementIsDisappeared, tmpOpPtr.p->insertIsDone); infoEvent("lockMode=%d, lockOwner=%d, nodeType=%d ", tmpOpPtr.p->lockMode, tmpOpPtr.p->lockOwner, tmpOpPtr.p->nodeType); infoEvent("operation=%d, opSimple=%d, dirtyRead=%d,scanBits=%d ", tmpOpPtr.p->operation, tmpOpPtr.p->opSimple, tmpOpPtr.p->dirtyRead, tmpOpPtr.p->scanBits); return; } if(dumpState->args[0] == DumpStateOrd::AccDumpNumOpRecs){ Uint32 freeOpRecs = 0; OperationrecPtr opRecPtr; opRecPtr.i = cfreeopRec; while (opRecPtr.i != RNIL){ freeOpRecs++; ptrCheckGuard(opRecPtr, coprecsize, operationrec); opRecPtr.i = opRecPtr.p->nextOp; } infoEvent("Dbacc::OperationRecords: num=%d, free=%d", coprecsize, freeOpRecs); return; } if(dumpState->args[0] == DumpStateOrd::AccDumpFreeOpRecs){ OperationrecPtr opRecPtr; opRecPtr.i = cfreeopRec; while (opRecPtr.i != RNIL){ dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec; dumpState->args[1] = opRecPtr.i; execDUMP_STATE_ORD(signal); ptrCheckGuard(opRecPtr, coprecsize, operationrec); opRecPtr.i = opRecPtr.p->nextOp; } return; } if(dumpState->args[0] == DumpStateOrd::AccDumpNotFreeOpRecs){ Uint32 recordStart = RNIL; if (signal->length() == 2) recordStart = dumpState->args[1]; else return; if (recordStart >= coprecsize) return; for (Uint32 i = recordStart; i < coprecsize; i++){ bool inFreeList = false; OperationrecPtr opRecPtr; opRecPtr.i = cfreeopRec; while (opRecPtr.i != RNIL){ if (opRecPtr.i == i){ inFreeList = true; break; } ptrCheckGuard(opRecPtr, coprecsize, operationrec); opRecPtr.i = opRecPtr.p->nextOp; } if (inFreeList == false){ dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec; dumpState->args[1] = i; execDUMP_STATE_ORD(signal); } } return; } #if 0 if (type == 100) { RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend(); req->primaryTableId = 2; req->secondaryTableId = RNIL; req->userPtr = 2; req->userRef = DBDICT_REF; sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal, RelTabMemReq::SignalLength, JBB); return; }//if if (type == 101) { RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend(); req->primaryTableId = 4; req->secondaryTableId = 5; req->userPtr = 4; req->userRef = DBDICT_REF; sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal, RelTabMemReq::SignalLength, JBB); return; }//if if (type == 102) { RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend(); req->primaryTableId = 6; req->secondaryTableId = 8; req->userPtr = 6; req->userRef = DBDICT_REF; sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal, RelTabMemReq::SignalLength, JBB); return; }//if if (type == 103) { DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend(); req->primaryTableId = 2; req->secondaryTableId = RNIL; req->userPtr = 2; req->userRef = DBDICT_REF; sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal, DropTabFileReq::SignalLength, JBB); return; }//if if (type == 104) { DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend(); req->primaryTableId = 4; req->secondaryTableId = 5; req->userPtr = 4; req->userRef = DBDICT_REF; sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal, DropTabFileReq::SignalLength, JBB); return; }//if if (type == 105) { DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend(); req->primaryTableId = 6; req->secondaryTableId = 8; req->userPtr = 6; req->userRef = DBDICT_REF; sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal, DropTabFileReq::SignalLength, JBB); return; }//if #endif }//Dbacc::execDUMP_STATE_ORD() void Dbacc::execSET_VAR_REQ(Signal* signal) { #if 0 SetVarReq* const setVarReq = (SetVarReq*)&signal->theData[0]; ConfigParamId var = setVarReq->variable(); int val = setVarReq->value(); switch (var) { case NoOfDiskPagesToDiskAfterRestartACC: clblPagesPerTick = val; sendSignal(CMVMI_REF, GSN_SET_VAR_CONF, signal, 1, JBB); break; case NoOfDiskPagesToDiskDuringRestartACC: // Valid only during start so value not set. sendSignal(CMVMI_REF, GSN_SET_VAR_CONF, signal, 1, JBB); break; default: sendSignal(CMVMI_REF, GSN_SET_VAR_REF, signal, 1, JBB); } // switch #endif }//execSET_VAR_REQ() void Dbacc::execREAD_PSUEDO_REQ(Signal* signal){ jamEntry(); fragrecptr.i = signal->theData[0]; Uint32 attrId = signal->theData[1]; ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); rootfragrecptr.i = fragrecptr.p->myroot; ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec); Uint64 tmp; switch(attrId){ case AttributeHeader::ROW_COUNT: tmp = rootfragrecptr.p->noOfElements; break; case AttributeHeader::COMMIT_COUNT: tmp = rootfragrecptr.p->m_commit_count; break; default: tmp = 0; } memcpy(signal->theData, &tmp, 8); /* must be memcpy, gives strange results on * ithanium gcc (GCC) 3.4.1 smp linux 2.4 * otherwise */ // Uint32 * src = (Uint32*)&tmp; // signal->theData[0] = src[0]; // signal->theData[1] = src[1]; }