summaryrefslogtreecommitdiff
path: root/ndb/src
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src')
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp2
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt4
-rw-r--r--ndb/src/kernel/blocks/dbdict/DictLock.txt12
-rw-r--r--ndb/src/kernel/blocks/dbdih/Dbdih.hpp3
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp40
-rw-r--r--ndb/src/kernel/blocks/dbtup/Dbtup.hpp9
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp11
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp169
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp7
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp15
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp2
11 files changed, 217 insertions, 57 deletions
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 8aedf35344f..49e3f505b11 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -399,6 +399,8 @@ const GsnName SignalNames [] = {
,{ GSN_TUP_COM_UNBLOCK, "TUP_COM_UNBLOCK" }
,{ GSN_DUMP_STATE_ORD, "DUMP_STATE_ORD" }
+ ,{ GSN_NODE_START_REP, "NODE_START_REP" }
+
,{ GSN_START_INFOREQ, "START_INFOREQ" }
,{ GSN_START_INFOREF, "START_INFOREF" }
,{ GSN_START_INFOCONF, "START_INFOCONF" }
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index ddb99cb6b56..7fee2e92f2b 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -2,7 +2,7 @@ Next QMGR 1
Next NDBCNTR 1000
Next NDBFS 2000
Next DBACC 3002
-Next DBTUP 4013
+Next DBTUP 4014
Next DBLQH 5043
Next DBDICT 6007
Next DBDIH 7177
@@ -437,6 +437,8 @@ Drop Table/Index:
8036: Fail next index drop in TC
6006: Crash participant in create index
+4013: verify TUP tab descr before and after next DROP TABLE
+
System Restart:
---------------
diff --git a/ndb/src/kernel/blocks/dbdict/DictLock.txt b/ndb/src/kernel/blocks/dbdict/DictLock.txt
index 17f24119e9d..72e23ed15a5 100644
--- a/ndb/src/kernel/blocks/dbdict/DictLock.txt
+++ b/ndb/src/kernel/blocks/dbdict/DictLock.txt
@@ -85,10 +85,14 @@ DIH/s
START_MECONF
DIH/s
-* sp7 - release DICT lock
+* (copy data, omitted)
-DIH/s
- DICT_UNLOCK_ORD
- DICT/m
+* SL_STARTED - release DICT lock
+
+CNTR/s
+ NODE_START_REP
+ DIH/s
+ DICT_UNLOCK_ORD
+ DICT/m
# vim: set et sw=4:
diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
index f4a33df9805..5c2cfac5eb1 100644
--- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
@@ -1599,6 +1599,9 @@ private:
*/
void startInfoReply(Signal *, Uint32 nodeId);
+ // DIH specifics for execNODE_START_REP (sendDictUnlockOrd)
+ void exec_node_start_rep(Signal* signal);
+
/*
* Lock master DICT. Only current use is by starting node
* during NR. A pool of slave records is convenient anyway.
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index b9ebbaf0f76..491aa0849b9 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -1356,24 +1356,6 @@ void Dbdih::execNDB_STTOR(Signal* signal)
}
ndbrequire(false);
break;
- case ZNDB_SPH7:
- jam();
- switch (typestart) {
- case NodeState::ST_INITIAL_START:
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- ndbsttorry10Lab(signal, __LINE__);
- return;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
- sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart);
- c_dictLockSlavePtrI_nodeRestart = RNIL;
- ndbsttorry10Lab(signal, __LINE__);
- return;
- }
- ndbrequire(false);
- break;
default:
jam();
ndbsttorry10Lab(signal, __LINE__);
@@ -1382,6 +1364,27 @@ void Dbdih::execNDB_STTOR(Signal* signal)
}//Dbdih::execNDB_STTOR()
void
+Dbdih::exec_node_start_rep(Signal* signal)
+{
+ /*
+ * Send DICT_UNLOCK_ORD when this node is SL_STARTED.
+ *
+ * Sending it before (sp 7) conflicts with code which assumes
+ * SL_STARTING means we are in copy phase of NR.
+ *
+ * NodeState::starting.restartType is not supposed to be used
+ * when SL_STARTED. Also it seems NODE_START_REP can arrive twice.
+ *
+ * For these reasons there are no consistency checks and
+ * we rely on c_dictLockSlavePtrI_nodeRestart alone.
+ */
+ if (c_dictLockSlavePtrI_nodeRestart != RNIL) {
+ sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart);
+ c_dictLockSlavePtrI_nodeRestart = RNIL;
+ }
+}
+
+void
Dbdih::createMutexes(Signal * signal, Uint32 count){
Callback c = { safe_cast(&Dbdih::createMutex_done), count };
@@ -1605,6 +1608,7 @@ void Dbdih::nodeRestartPh2Lab(Signal* signal)
void Dbdih::recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret)
{
ndbrequire(c_dictLockSlavePtrI_nodeRestart == RNIL);
+ ndbrequire(data != RNIL);
c_dictLockSlavePtrI_nodeRestart = data;
nodeRestartPh2Lab2(signal);
diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index 41194fba82c..0b66d9a45bb 100644
--- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -2185,15 +2185,18 @@ private:
// Public methods
Uint32 getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset);
Uint32 allocTabDescr(const Tablerec* regTabPtr, Uint32* offset);
- void freeTabDescr(Uint32 retRef, Uint32 retNo);
+ void freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal = true);
Uint32 getTabDescrWord(Uint32 index);
void setTabDescrWord(Uint32 index, Uint32 word);
// Private methods
Uint32 sizeOfReadFunction();
void removeTdArea(Uint32 tabDesRef, Uint32 list);
- void insertTdArea(Uint32 sizeOfChunk, Uint32 tabDesRef, Uint32 list);
- Uint32 itdaMergeTabDescr(Uint32 retRef, Uint32 retNo);
+ void insertTdArea(Uint32 tabDesRef, Uint32 list);
+ void itdaMergeTabDescr(Uint32& retRef, Uint32& retNo, bool normal);
+#ifdef VM_TRACE
+ void verifytabdes();
+#endif
//------------------------------------------------------------------------------------------------------
// Page Memory Manager
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
index 12cd61a17a6..7d2f7d56d48 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
@@ -601,6 +601,11 @@ void
Dbtup::execDROP_TAB_REQ(Signal* signal)
{
ljamEntry();
+ if (ERROR_INSERTED(4013)) {
+#ifdef VM_TRACE
+ verifytabdes();
+#endif
+ }
DropTabReq* req = (DropTabReq*)signal->getDataPtr();
TablerecPtr tabPtr;
@@ -719,5 +724,11 @@ void Dbtup::execFSREMOVECONF(Signal* signal)
releaseTabDescr(tabPtr.p);
initTab(tabPtr.p);
+ if (ERROR_INSERTED(4013)) {
+ CLEAR_ERROR_INSERT_VALUE;
+#ifdef VM_TRACE
+ verifytabdes();
+#endif
+ }
}//Dbtup::execFSREMOVECONF()
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
index 642ba270760..3e96bc6c14a 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
@@ -24,13 +24,15 @@
#define ljam() { jamLine(22000 + __LINE__); }
#define ljamEntry() { jamEntryLine(22000 + __LINE__); }
-/* **************************************************************** */
-/* *********** TABLE DESCRIPTOR MEMORY MANAGER ******************** */
-/* **************************************************************** */
-/* This module is used to allocate and deallocate table descriptor */
-/* memory attached to fragments (could be allocated per table */
-/* instead. Performs its task by a buddy algorithm. */
-/* **************************************************************** */
+/*
+ * TABLE DESCRIPTOR MEMORY MANAGER
+ *
+ * Each table has a descriptor which is a contiguous array of words.
+ * The descriptor is allocated from a global array using a buddy
+ * algorithm. Free lists exist for each power of 2 words. Freeing
+ * a piece first merges with free right and left neighbours and then
+ * divides itself up into free list chunks.
+ */
Uint32
Dbtup::getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset)
@@ -59,7 +61,7 @@ Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset)
Uint32 reference = RNIL;
Uint32 allocSize = getTabDescrOffsets(regTabPtr, offset);
/* ---------------------------------------------------------------- */
-/* ALWAYS ALLOCATE A MULTIPLE OF 16 BYTES */
+/* ALWAYS ALLOCATE A MULTIPLE OF 16 WORDS */
/* ---------------------------------------------------------------- */
allocSize = (((allocSize - 1) >> 4) + 1) << 4;
Uint32 list = nextHigherTwoLog(allocSize - 1); /* CALCULATE WHICH LIST IT BELONGS TO */
@@ -72,9 +74,9 @@ Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset)
Uint32 retNo = (1 << i) - allocSize; /* CALCULATE THE DIFFERENCE */
if (retNo >= ZTD_FREE_SIZE) {
ljam();
- Uint32 retRef = reference + allocSize; /* SET THE RETURN POINTER */
- retNo = itdaMergeTabDescr(retRef, retNo); /* MERGE WITH POSSIBLE RIGHT NEIGHBOURS */
- freeTabDescr(retRef, retNo); /* RETURN UNUSED TD SPACE TO THE TD AREA */
+ // return unused words, of course without attempting left merge
+ Uint32 retRef = reference + allocSize;
+ freeTabDescr(retRef, retNo, false);
} else {
ljam();
allocSize = 1 << i;
@@ -100,17 +102,19 @@ Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset)
}//if
}//Dbtup::allocTabDescr()
-void Dbtup::freeTabDescr(Uint32 retRef, Uint32 retNo)
+void Dbtup::freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal)
{
+ itdaMergeTabDescr(retRef, retNo, normal); /* MERGE WITH POSSIBLE NEIGHBOURS */
while (retNo >= ZTD_FREE_SIZE) {
ljam();
Uint32 list = nextHigherTwoLog(retNo);
list--; /* RETURN TO NEXT LOWER LIST */
Uint32 sizeOfChunk = 1 << list;
- insertTdArea(sizeOfChunk, retRef, list);
+ insertTdArea(retRef, list);
retRef += sizeOfChunk;
retNo -= sizeOfChunk;
}//while
+ ndbassert(retNo == 0);
}//Dbtup::freeTabDescr()
Uint32
@@ -127,7 +131,7 @@ Dbtup::setTabDescrWord(Uint32 index, Uint32 word)
tableDescriptor[index].tabDescr = word;
}//Dbtup::setTabDescrWord()
-void Dbtup::insertTdArea(Uint32 sizeOfChunk, Uint32 tabDesRef, Uint32 list)
+void Dbtup::insertTdArea(Uint32 tabDesRef, Uint32 list)
{
ndbrequire(list < 16);
setTabDescrWord(tabDesRef + ZTD_FL_HEADER, ZTD_TYPE_FREE);
@@ -144,19 +148,14 @@ void Dbtup::insertTdArea(Uint32 sizeOfChunk, Uint32 tabDesRef, Uint32 list)
setTabDescrWord((tabDesRef + (1 << list)) - ZTD_TR_SIZE, 1 << list);
}//Dbtup::insertTdArea()
-/* ---------------------------------------------------------------- */
-/* ----------------------- MERGE_TAB_DESCR ------------------------ */
-/* ---------------------------------------------------------------- */
-/* INPUT: TAB_DESCR_PTR POINTING AT THE CURRENT CHUNK */
-/* */
-/* SHORTNAME: MTD */
-/* -----------------------------------------------------------------*/
-Uint32 Dbtup::itdaMergeTabDescr(Uint32 retRef, Uint32 retNo)
+/*
+ * Merge to-be-removed chunk (which need not be initialized with header
+ * and trailer) with left and right buddies. The start point retRef
+ * moves to left and the size retNo increases to match the new chunk.
+ */
+void Dbtup::itdaMergeTabDescr(Uint32& retRef, Uint32& retNo, bool normal)
{
- /* THE SIZE OF THE PART TO MERGE MUST BE OF THE SAME SIZE AS THE INSERTED PART */
- /* THIS IS TRUE EITHER IF ONE PART HAS THE SAME SIZE OR THE SUM OF BOTH PARTS */
- /* TOGETHER HAS THE SAME SIZE AS THE PART TO BE INSERTED */
- /* FIND THE SIZES OF THE PARTS TO THE RIGHT OF THE PART TO BE REINSERTED */
+ // merge right
while ((retRef + retNo) < cnoOfTabDescrRec) {
ljam();
Uint32 tabDesRef = retRef + retNo;
@@ -170,11 +169,28 @@ Uint32 Dbtup::itdaMergeTabDescr(Uint32 retRef, Uint32 retNo)
removeTdArea(tabDesRef, list);
} else {
ljam();
- return retNo;
- }//if
- }//while
- ndbrequire((retRef + retNo) == cnoOfTabDescrRec);
- return retNo;
+ break;
+ }
+ }
+ // merge left
+ const bool mergeLeft = normal;
+ while (mergeLeft && retRef > 0) {
+ ljam();
+ Uint32 trailerWord = getTabDescrWord(retRef - ZTD_TR_TYPE);
+ if (trailerWord == ZTD_TYPE_FREE) {
+ ljam();
+ Uint32 sizeOfMergedPart = getTabDescrWord(retRef - ZTD_TR_SIZE);
+ ndbrequire(retRef >= sizeOfMergedPart);
+ retRef -= sizeOfMergedPart;
+ retNo += sizeOfMergedPart;
+ Uint32 list = nextHigherTwoLog(sizeOfMergedPart - 1);
+ removeTdArea(retRef, list);
+ } else {
+ ljam();
+ break;
+ }
+ }
+ ndbrequire((retRef + retNo) <= cnoOfTabDescrRec);
}//Dbtup::itdaMergeTabDescr()
/* ---------------------------------------------------------------- */
@@ -210,3 +226,94 @@ void Dbtup::removeTdArea(Uint32 tabDesRef, Uint32 list)
setTabDescrWord(tabDescrPrevPtr + ZTD_FL_NEXT, tabDescrNextPtr);
}//if
}//Dbtup::removeTdArea()
+
+#ifdef VM_TRACE
+void
+Dbtup::verifytabdes()
+{
+ struct WordType {
+ short fl; // free list 0-15
+ short ti; // table id
+ WordType() : fl(-1), ti(-1) {}
+ };
+ WordType* wt = new WordType [cnoOfTabDescrRec];
+ uint free_frags = 0;
+ // free lists
+ {
+ for (uint i = 0; i < 16; i++) {
+ Uint32 desc2 = RNIL;
+ Uint32 desc = cfreeTdList[i];
+ while (desc != RNIL) {
+ const Uint32 size = (1 << i);
+ ndbrequire(size >= ZTD_FREE_SIZE);
+ ndbrequire(desc + size <= cnoOfTabDescrRec);
+ { Uint32 index = desc + ZTD_FL_HEADER;
+ ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_FREE);
+ }
+ { Uint32 index = desc + ZTD_FL_SIZE;
+ ndbrequire(tableDescriptor[index].tabDescr == size);
+ }
+ { Uint32 index = desc + size - ZTD_TR_TYPE;
+ ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_FREE);
+ }
+ { Uint32 index = desc + size - ZTD_TR_SIZE;
+ ndbrequire(tableDescriptor[index].tabDescr == size);
+ }
+ { Uint32 index = desc + ZTD_FL_PREV;
+ ndbrequire(tableDescriptor[index].tabDescr == desc2);
+ }
+ for (uint j = 0; j < size; j++) {
+ ndbrequire(wt[desc + j].fl == -1);
+ wt[desc + j].fl = i;
+ }
+ desc2 = desc;
+ desc = tableDescriptor[desc + ZTD_FL_NEXT].tabDescr;
+ free_frags++;
+ }
+ }
+ }
+ // tables
+ {
+ for (uint i = 0; i < cnoOfTablerec; i++) {
+ TablerecPtr ptr;
+ ptr.i = i;
+ ptrAss(ptr, tablerec);
+ if (ptr.p->tableStatus == DEFINED) {
+ Uint32 offset[10];
+ const Uint32 alloc = getTabDescrOffsets(ptr.p, offset);
+ const Uint32 desc = ptr.p->readKeyArray - offset[3];
+ Uint32 size = alloc;
+ if (size % ZTD_FREE_SIZE != 0)
+ size += ZTD_FREE_SIZE - size % ZTD_FREE_SIZE;
+ ndbrequire(desc + size <= cnoOfTabDescrRec);
+ { Uint32 index = desc + ZTD_FL_HEADER;
+ ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_NORMAL);
+ }
+ { Uint32 index = desc + ZTD_FL_SIZE;
+ ndbrequire(tableDescriptor[index].tabDescr == size);
+ }
+ { Uint32 index = desc + size - ZTD_TR_TYPE;
+ ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_NORMAL);
+ }
+ { Uint32 index = desc + size - ZTD_TR_SIZE;
+ ndbrequire(tableDescriptor[index].tabDescr == size);
+ }
+ for (uint j = 0; j < size; j++) {
+ ndbrequire(wt[desc + j].ti == -1);
+ wt[desc + j].ti = i;
+ }
+ }
+ }
+ }
+ // all words
+ {
+ for (uint i = 0; i < cnoOfTabDescrRec; i++) {
+ bool is_fl = wt[i].fl != -1;
+ bool is_ti = wt[i].ti != -1;
+ ndbrequire(is_fl != is_ti);
+ }
+ }
+ delete [] wt;
+ ndbout << "verifytabdes: frags=" << free_frags << endl;
+}
+#endif
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 14efa8cd784..e6bb4d4f14f 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -591,6 +591,13 @@ Ndbcntr::execCNTR_START_REP(Signal* signal){
Uint32 nodeId = signal->theData[0];
c_startedNodes.set(nodeId);
c_start.m_starting.clear(nodeId);
+
+ /**
+ * Inform all interested blocks that node has started
+ */
+ for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){
+ sendSignal(ALL_BLOCKS[i].Ref, GSN_NODE_START_REP, signal, 1, JBB);
+ }
if(!c_start.m_starting.isclear()){
jam();
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index 3fe76e45322..b4787209d55 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -148,6 +148,7 @@ SimulatedBlock::installSimulatedBlockFunctions(){
a[GSN_FSREMOVEREF] = &SimulatedBlock::execFSREMOVEREF;
a[GSN_FSSYNCREF] = &SimulatedBlock::execFSSYNCREF;
a[GSN_FSAPPENDREF] = &SimulatedBlock::execFSAPPENDREF;
+ a[GSN_NODE_START_REP] = &SimulatedBlock::execNODE_START_REP;
}
void
@@ -913,6 +914,20 @@ SimulatedBlock::execCONTINUE_FRAGMENTED(Signal * signal){
sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
}
+void
+SimulatedBlock::execNODE_START_REP(Signal* signal)
+{
+ // common stuff for all blocks
+
+ // block specific stuff by virtual method override (default empty)
+ exec_node_start_rep(signal);
+}
+
+void
+SimulatedBlock::exec_node_start_rep(Signal* signal)
+{
+}
+
#ifdef VM_TRACE_TIME
void
SimulatedBlock::clearTimes() {
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index b7bd8c57ee8..4a3620a00ab 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -423,6 +423,8 @@ private:
void execSIGNAL_DROPPED_REP(Signal* signal);
void execCONTINUE_FRAGMENTED(Signal* signal);
+ void execNODE_START_REP(Signal* signal);
+ virtual void exec_node_start_rep(Signal* signal);
Uint32 c_fragmentIdCounter;
ArrayPool<FragmentInfo> c_fragmentInfoPool;