DbtupIndex.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:17k
- /* 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 DBTUP_C
- #include "Dbtup.hpp"
- #include <RefConvert.hpp>
- #include <ndb_limits.h>
- #include <pc.hpp>
- #include <AttributeDescriptor.hpp>
- #include "AttributeOffset.hpp"
- #include <AttributeHeader.hpp>
- #include <signaldata/TuxMaint.hpp>
- #define ljam() { jamLine(28000 + __LINE__); }
- #define ljamEntry() { jamEntryLine(28000 + __LINE__); }
- // methods used by ordered index
- void
- Dbtup::tuxGetTupAddr(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32& tupAddr)
- {
- ljamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 fragPageId = pagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- Uint32 tupheadsize = tablePtr.p->tupheadsize;
- ndbrequire(pageOffset >= ZPAGE_HEADER_SIZE);
- Uint32 offset = pageOffset - ZPAGE_HEADER_SIZE;
- ndbrequire(offset % tupheadsize == 0);
- Uint32 pageIndex = (offset / tupheadsize) << 1;
- tupAddr = (fragPageId << MAX_TUPLES_BITS) | pageIndex;
- }
- int
- Dbtup::tuxAllocNode(Signal* signal, Uint32 fragPtrI, Uint32& pageId, Uint32& pageOffset, Uint32*& node)
- {
- ljamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- terrorCode = 0;
- if (! allocTh(fragPtr.p, tablePtr.p, NORMAL_PAGE, signal, pageOffset, pagePtr)) {
- ljam();
- ndbrequire(terrorCode != 0);
- return terrorCode;
- }
- pageId = pagePtr.i;
- Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
- node = &pagePtr.p->pageWord[pageOffset] + attrDataOffset;
- return 0;
- }
- void
- Dbtup::tuxFreeNode(Signal* signal, Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* node)
- {
- ljamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
- ndbrequire(node == &pagePtr.p->pageWord[pageOffset] + attrDataOffset);
- freeTh(fragPtr.p, tablePtr.p, signal, pagePtr.p, pageOffset);
- }
- void
- Dbtup::tuxGetNode(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32*& node)
- {
- ljamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
- node = &pagePtr.p->pageWord[pageOffset] + attrDataOffset;
- }
- int
- Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, const Uint32* attrIds, Uint32 numAttrs, Uint32* dataOut)
- {
- ljamEntry();
- // use own variables instead of globals
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- // search for tuple version if not original
- if (pagePtr.p->pageWord[pageOffset + 1] != tupVersion) {
- ljam();
- OperationrecPtr opPtr;
- opPtr.i = pagePtr.p->pageWord[pageOffset];
- Uint32 loopGuard = 0;
- while (true) {
- ptrCheckGuard(opPtr, cnoOfOprec, operationrec);
- if (opPtr.p->realPageIdC != RNIL) {
- // update page and offset
- pagePtr.i = opPtr.p->realPageIdC;
- pageOffset = opPtr.p->pageOffsetC;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- if (pagePtr.p->pageWord[pageOffset + 1] == tupVersion) {
- ljam();
- break;
- }
- }
- ljam();
- opPtr.i = opPtr.p->nextActiveOp;
- ndbrequire(++loopGuard < (1 << ZTUP_VERSION_BITS));
- }
- }
- // read key attributes from found tuple version
- // save globals
- TablerecPtr tabptr_old = tabptr;
- FragrecordPtr fragptr_old = fragptr;
- OperationrecPtr operPtr_old = operPtr;
- // new globals
- tabptr = tablePtr;
- fragptr = fragPtr;
- operPtr.i = RNIL;
- operPtr.p = NULL;
- // do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds, numAttrs, dataOut, ZNIL, true);
- // restore globals
- tabptr = tabptr_old;
- fragptr = fragptr_old;
- operPtr = operPtr_old;
- // done
- if (ret == -1) {
- ret = terrorCode ? (-(int)terrorCode) : -1;
- }
- return ret;
- }
- int
- Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut)
- {
- ljamEntry();
- // use own variables instead of globals
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- const Uint32 tabDescriptor = tablePtr.p->tabDescriptor;
- const Uint32* attrIds = &tableDescriptor[tablePtr.p->readKeyArray].tabDescr;
- const Uint32 numAttrs = tablePtr.p->noOfKeyAttr;
- // read pk attributes from original tuple
- // save globals
- TablerecPtr tabptr_old = tabptr;
- FragrecordPtr fragptr_old = fragptr;
- OperationrecPtr operPtr_old = operPtr;
- // new globals
- tabptr = tablePtr;
- fragptr = fragPtr;
- operPtr.i = RNIL;
- operPtr.p = NULL;
- // do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds,
- numAttrs, dataOut, ZNIL, true);
- // restore globals
- tabptr = tabptr_old;
- fragptr = fragptr_old;
- operPtr = operPtr_old;
- // done
- if (ret != -1) {
- // remove headers
- Uint32 n = 0;
- Uint32 i = 0;
- while (n < numAttrs) {
- const AttributeHeader ah(dataOut[i]);
- Uint32 size = ah.getDataSize();
- ndbrequire(size != 0);
- for (Uint32 j = 0; j < size; j++) {
- dataOut[i + j - n] = dataOut[i + j + 1];
- }
- n += 1;
- i += 1 + size;
- }
- ndbrequire((int)i == ret);
- ret -= numAttrs;
- } else {
- ret = terrorCode ? (-(int)terrorCode) : -1;
- }
- return ret;
- }
- bool
- Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId)
- {
- ljamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- // get page
- PagePtr pagePtr;
- Uint32 fragPageId = tupAddr >> MAX_TUPLES_BITS;
- Uint32 pageIndex = tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
- // use temp op rec
- Operationrec tempOp;
- tempOp.fragPageId = fragPageId;
- tempOp.pageIndex = pageIndex;
- tempOp.transid1 = transId1;
- tempOp.transid2 = transId2;
- tempOp.savePointId = savePointId;
- tempOp.optype = ZREAD;
- tempOp.dirtyOp = 1;
- if (getPage(pagePtr, &tempOp, fragPtr.p, tablePtr.p)) {
- /*
- * We use the normal getPage which will return the tuple to be used
- * for this transaction and savepoint id. If its tuple version
- * equals the requested then we have a visible tuple otherwise not.
- */
- ljam();
- Uint32 read_tupVersion = pagePtr.p->pageWord[tempOp.pageOffset + 1];
- if (read_tupVersion == tupVersion) {
- ljam();
- return true;
- }
- }
- return false;
- }
- // ordered index build
- //#define TIME_MEASUREMENT
- #ifdef TIME_MEASUREMENT
- static Uint32 time_events;
- NDB_TICKS tot_time_passed;
- Uint32 number_events;
- #endif
- void
- Dbtup::execBUILDINDXREQ(Signal* signal)
- {
- ljamEntry();
- #ifdef TIME_MEASUREMENT
- time_events = 0;
- tot_time_passed = 0;
- number_events = 1;
- #endif
- // get new operation
- BuildIndexPtr buildPtr;
- if (! c_buildIndexList.seize(buildPtr)) {
- ljam();
- BuildIndexRec buildRec;
- memcpy(buildRec.m_request, signal->theData, sizeof(buildRec.m_request));
- buildRec.m_errorCode = BuildIndxRef::Busy;
- buildIndexReply(signal, &buildRec);
- return;
- }
- memcpy(buildPtr.p->m_request, signal->theData, sizeof(buildPtr.p->m_request));
- // check
- buildPtr.p->m_errorCode = BuildIndxRef::NoError;
- do {
- const BuildIndxReq* buildReq = (const BuildIndxReq*)buildPtr.p->m_request;
- if (buildReq->getTableId() >= cnoOfTablerec) {
- ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::InvalidPrimaryTable;
- break;
- }
- TablerecPtr tablePtr;
- tablePtr.i = buildReq->getTableId();
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- if (tablePtr.p->tableStatus != DEFINED) {
- ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::InvalidPrimaryTable;
- break;
- }
- if (! DictTabInfo::isOrderedIndex(buildReq->getIndexType())) {
- ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::InvalidIndexType;
- break;
- }
- const ArrayList<TupTriggerData>& triggerList = tablePtr.p->tuxCustomTriggers;
- TriggerPtr triggerPtr;
- triggerList.first(triggerPtr);
- while (triggerPtr.i != RNIL) {
- if (triggerPtr.p->indexId == buildReq->getIndexId()) {
- ljam();
- break;
- }
- triggerList.next(triggerPtr);
- }
- if (triggerPtr.i == RNIL) {
- ljam();
- // trigger was not created
- buildPtr.p->m_errorCode = BuildIndxRef::InternalError;
- break;
- }
- buildPtr.p->m_triggerPtrI = triggerPtr.i;
- // set to first tuple position
- buildPtr.p->m_fragNo = 0;
- buildPtr.p->m_pageId = 0;
- buildPtr.p->m_tupleNo = 0;
- // start build
- buildIndex(signal, buildPtr.i);
- return;
- } while (0);
- // check failed
- buildIndexReply(signal, buildPtr.p);
- c_buildIndexList.release(buildPtr);
- }
- void
- Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
- {
- // get build record
- BuildIndexPtr buildPtr;
- buildPtr.i = buildPtrI;
- c_buildIndexList.getPtr(buildPtr);
- const BuildIndxReq* buildReq = (const BuildIndxReq*)buildPtr.p->m_request;
- // get table
- TablerecPtr tablePtr;
- tablePtr.i = buildReq->getTableId();
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- // get trigger
- TriggerPtr triggerPtr;
- triggerPtr.i = buildPtr.p->m_triggerPtrI;
- c_triggerPool.getPtr(triggerPtr);
- ndbrequire(triggerPtr.p->indexId == buildReq->getIndexId());
- #ifdef TIME_MEASUREMENT
- MicroSecondTimer start;
- MicroSecondTimer stop;
- NDB_TICKS time_passed;
- #endif
- do {
- // get fragment
- FragrecordPtr fragPtr;
- if (buildPtr.p->m_fragNo == 2 * MAX_FRAG_PER_NODE) {
- ljam();
- // build ready
- buildIndexReply(signal, buildPtr.p);
- c_buildIndexList.release(buildPtr);
- return;
- }
- ndbrequire(buildPtr.p->m_fragNo < 2 * MAX_FRAG_PER_NODE);
- fragPtr.i = tablePtr.p->fragrec[buildPtr.p->m_fragNo];
- if (fragPtr.i == RNIL) {
- ljam();
- buildPtr.p->m_fragNo++;
- buildPtr.p->m_pageId = 0;
- buildPtr.p->m_tupleNo = 0;
- break;
- }
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- // get page
- PagePtr pagePtr;
- if (buildPtr.p->m_pageId >= fragPtr.p->noOfPages) {
- ljam();
- buildPtr.p->m_fragNo++;
- buildPtr.p->m_pageId = 0;
- buildPtr.p->m_tupleNo = 0;
- break;
- }
- Uint32 realPageId = getRealpid(fragPtr.p, buildPtr.p->m_pageId);
- pagePtr.i = realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- const Uint32 pageState = pagePtr.p->pageWord[ZPAGE_STATE_POS];
- if (pageState != ZTH_MM_FREE &&
- pageState != ZTH_MM_FREE_COPY &&
- pageState != ZTH_MM_FULL &&
- pageState != ZTH_MM_FULL_COPY) {
- ljam();
- buildPtr.p->m_pageId++;
- buildPtr.p->m_tupleNo = 0;
- break;
- }
- // get tuple
- const Uint32 tupheadsize = tablePtr.p->tupheadsize;
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + buildPtr.p->m_tupleNo * tupheadsize;
- if (pageOffset + tupheadsize > ZWORDS_ON_PAGE) {
- ljam();
- buildPtr.p->m_pageId++;
- buildPtr.p->m_tupleNo = 0;
- break;
- }
- // skip over free tuple
- bool isFree = false;
- if (pageState == ZTH_MM_FREE ||
- pageState == ZTH_MM_FREE_COPY) {
- ljam();
- if ((pagePtr.p->pageWord[pageOffset] >> 16) == tupheadsize) {
- // verify it really is free XXX far too expensive
- Uint32 nextTuple = pagePtr.p->pageWord[ZFREELIST_HEADER_POS] >> 16;
- ndbrequire(nextTuple != 0);
- while (nextTuple != 0) {
- ljam();
- if (nextTuple == pageOffset) {
- ljam();
- isFree = true;
- break;
- }
- nextTuple = pagePtr.p->pageWord[nextTuple] & 0xffff;
- }
- }
- }
- if (isFree) {
- ljam();
- buildPtr.p->m_tupleNo++;
- break;
- }
- Uint32 tupVersion = pagePtr.p->pageWord[pageOffset + 1];
- OperationrecPtr pageOperPtr;
- pageOperPtr.i = pagePtr.p->pageWord[pageOffset];
- if (pageOperPtr.i != RNIL) {
- /*
- If there is an ongoing operation on the tuple then it is either a
- copy tuple or an original tuple with an ongoing transaction. In
- both cases realPageId and pageOffset refer to the original tuple.
- The tuple address stored in TUX will always be the original tuple
- but with the tuple version of the tuple we found.
- This is necessary to avoid having to update TUX at abort of
- update. If an update aborts then the copy tuple is copied to
- the original tuple. The build will however have found that
- tuple as a copy tuple. The original tuple is stable and is thus
- preferrable to store in TUX.
- */
- ljam();
- ptrCheckGuard(pageOperPtr, cnoOfOprec, operationrec);
- realPageId = pageOperPtr.p->realPageId;
- pageOffset = pageOperPtr.p->pageOffset;
- }//if
- #ifdef TIME_MEASUREMENT
- NdbTick_getMicroTimer(&start);
- #endif
- // add to index
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- req->errorCode = RNIL;
- req->tableId = tablePtr.i;
- req->indexId = triggerPtr.p->indexId;
- req->fragId = tablePtr.p->fragid[buildPtr.p->m_fragNo];
- req->pageId = realPageId;
- req->pageOffset = pageOffset;
- req->tupVersion = tupVersion;
- req->opInfo = TuxMaintReq::OpAdd;
- EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
- signal, TuxMaintReq::SignalLength);
- ljamEntry();
- if (req->errorCode != 0) {
- switch (req->errorCode) {
- case TuxMaintReq::NoMemError:
- ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::AllocationFailure;
- break;
- default:
- ndbrequire(false);
- break;
- }
- buildIndexReply(signal, buildPtr.p);
- c_buildIndexList.release(buildPtr);
- return;
- }
- #ifdef TIME_MEASUREMENT
- NdbTick_getMicroTimer(&stop);
- time_passed = NdbTick_getMicrosPassed(start, stop);
- if (time_passed < 1000) {
- time_events++;
- tot_time_passed += time_passed;
- if (time_events == number_events) {
- NDB_TICKS mean_time_passed = tot_time_passed / (NDB_TICKS)number_events;
- ndbout << "Number of events = " << number_events;
- ndbout << " Mean time passed = " << mean_time_passed << endl;
- number_events <<= 1;
- tot_time_passed = (NDB_TICKS)0;
- time_events = 0;
- }//if
- }
- #endif
- // next tuple
- buildPtr.p->m_tupleNo++;
- break;
- } while (0);
- signal->theData[0] = ZBUILD_INDEX;
- signal->theData[1] = buildPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- }
- void
- Dbtup::buildIndexReply(Signal* signal, const BuildIndexRec* buildPtrP)
- {
- const BuildIndxReq* const buildReq = (const BuildIndxReq*)buildPtrP->m_request;
- // conf is subset of ref
- BuildIndxRef* rep = (BuildIndxRef*)signal->getDataPtr();
- rep->setUserRef(buildReq->getUserRef());
- rep->setConnectionPtr(buildReq->getConnectionPtr());
- rep->setRequestType(buildReq->getRequestType());
- rep->setTableId(buildReq->getTableId());
- rep->setIndexType(buildReq->getIndexType());
- rep->setIndexId(buildReq->getIndexId());
- // conf
- if (buildPtrP->m_errorCode == BuildIndxRef::NoError) {
- ljam();
- sendSignal(rep->getUserRef(), GSN_BUILDINDXCONF,
- signal, BuildIndxConf::SignalLength, JBB);
- return;
- }
- // ref
- rep->setErrorCode(buildPtrP->m_errorCode);
- sendSignal(rep->getUserRef(), GSN_BUILDINDXREF,
- signal, BuildIndxRef::SignalLength, JBB);
- }