/* Copyright (c) 2003-2006 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; version 2 of the License. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #define DBTUX_MAINT_CPP #include "Dbtux.hpp" /* * Maintain index. */ void Dbtux::execTUX_MAINT_REQ(Signal* signal) { jamEntry(); TuxMaintReq* const sig = (TuxMaintReq*)signal->getDataPtrSend(); // ignore requests from redo log if (c_internalStartPhase < 6 && c_typeOfStart != NodeState::ST_NODE_RESTART && c_typeOfStart != NodeState::ST_INITIAL_NODE_RESTART) { jam(); #ifdef VM_TRACE if (debugFlags & DebugMaint) { TupLoc tupLoc(sig->pageId, sig->pageIndex); debugOut << "opInfo=" << hex << sig->opInfo; debugOut << " tableId=" << dec << sig->tableId; debugOut << " indexId=" << dec << sig->indexId; debugOut << " fragId=" << dec << sig->fragId; debugOut << " tupLoc=" << tupLoc; debugOut << " tupVersion=" << dec << sig->tupVersion; debugOut << " -- ignored at ISP=" << dec << c_internalStartPhase; debugOut << " TOS=" << dec << c_typeOfStart; debugOut << endl; } #endif sig->errorCode = 0; return; } TuxMaintReq reqCopy = *sig; TuxMaintReq* const req = &reqCopy; const Uint32 opCode = req->opInfo & 0xFF; const Uint32 opFlag = req->opInfo >> 8; // get the index IndexPtr indexPtr; c_indexPool.getPtr(indexPtr, req->indexId); ndbrequire(indexPtr.p->m_tableId == req->tableId); // get base fragment id and extra bits const Uint32 fragId = req->fragId; // get the fragment FragPtr fragPtr; fragPtr.i = RNIL; for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) { jam(); if (indexPtr.p->m_fragId[i] == fragId) { jam(); c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]); break; } } ndbrequire(fragPtr.i != RNIL); Frag& frag = *fragPtr.p; // set up index keys for this operation setKeyAttrs(frag); // set up search entry TreeEnt ent; ent.m_tupLoc = TupLoc(req->pageId, req->pageIndex); ent.m_tupVersion = req->tupVersion; // read search key readKeyAttrs(frag, ent, 0, c_searchKey); if (! frag.m_storeNullKey) { // check if all keys are null const unsigned numAttrs = frag.m_numAttrs; bool allNull = true; for (unsigned i = 0; i < numAttrs; i++) { if (c_searchKey[i] != 0) { jam(); allNull = false; break; } } if (allNull) { jam(); req->errorCode = 0; *sig = *req; return; } } #ifdef VM_TRACE if (debugFlags & DebugMaint) { debugOut << "opCode=" << dec << opCode; debugOut << " opFlag=" << dec << opFlag; debugOut << " tableId=" << dec << req->tableId; debugOut << " indexId=" << dec << req->indexId; debugOut << " fragId=" << dec << req->fragId; debugOut << " entry=" << ent; debugOut << endl; } #endif // do the operation req->errorCode = 0; TreePos treePos; bool ok; switch (opCode) { case TuxMaintReq::OpAdd: jam(); ok = searchToAdd(frag, c_searchKey, ent, treePos); #ifdef VM_TRACE if (debugFlags & DebugMaint) { debugOut << treePos << (! ok ? " - error" : "") << endl; } #endif if (! ok) { jam(); // there is no "Building" state so this will have to do if (indexPtr.p->m_state == Index::Online) { jam(); req->errorCode = TuxMaintReq::SearchError; } break; } /* * At most one new node is inserted in the operation. Pre-allocate * it so that the operation cannot fail. */ if (frag.m_freeLoc == NullTupLoc) { jam(); NodeHandle node(frag); req->errorCode = allocNode(signal, node); if (req->errorCode != 0) { jam(); break; } // link to freelist node.setLink(0, frag.m_freeLoc); frag.m_freeLoc = node.m_loc; ndbrequire(frag.m_freeLoc != NullTupLoc); } treeAdd(frag, treePos, ent); break; case TuxMaintReq::OpRemove: jam(); ok = searchToRemove(frag, c_searchKey, ent, treePos); #ifdef VM_TRACE if (debugFlags & DebugMaint) { debugOut << treePos << (! ok ? " - error" : "") << endl; } #endif if (! ok) { jam(); // there is no "Building" state so this will have to do if (indexPtr.p->m_state == Index::Online) { jam(); req->errorCode = TuxMaintReq::SearchError; } break; } treeRemove(frag, treePos); break; default: ndbrequire(false); break; } #ifdef VM_TRACE if (debugFlags & DebugTree) { printTree(signal, frag, debugOut); } #endif // copy back *sig = *req; }