Below is the list of changes that have just been committed into a local
4.1 repository of pekka. When pekka does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2530 06/07/07 10:57:22 pekka@stripped +6 -0
ndb - bug#20847 : DbtupTabDesMan: add merge with left buddies
ndb/test/run-test/daily-basic-tests.txt
1.33 06/07/07 10:55:58 pekka@stripped +4 -0
DbtupTabDesMan: add merge with left buddies
ndb/test/ndbapi/testDict.cpp
1.19 06/07/07 10:55:58 pekka@stripped +101 -0
DbtupTabDesMan: add merge with left buddies
ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
1.4 06/07/07 10:55:57 pekka@stripped +136 -30
DbtupTabDesMan: add merge with left buddies
ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
1.9 06/07/07 10:55:57 pekka@stripped +7 -0
DbtupTabDesMan: add merge with left buddies
ndb/src/kernel/blocks/dbtup/Dbtup.hpp
1.21 06/07/07 10:55:56 pekka@stripped +6 -3
DbtupTabDesMan: add merge with left buddies
ndb/src/kernel/blocks/ERROR_codes.txt
1.18 06/07/07 10:55:55 pekka@stripped +3 -1
DbtupTabDesMan: add merge with left buddies
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: pekka
# Host: orca.ndb.mysql.com
# Root: /space_old/pekka/ndb/version/my41-bug20847
--- 1.32/ndb/test/run-test/daily-basic-tests.txt 2006-06-01 08:24:03 +02:00
+++ 1.33/ndb/test/run-test/daily-basic-tests.txt 2006-07-07 10:55:58 +02:00
@@ -491,6 +491,10 @@ args: -n CreateAndDrop
max-time: 1500
cmd: testDict
+args: -n CreateAndDropAtRandom -l 200 T1
+
+max-time: 1500
+cmd: testDict
args: -n CreateAndDropWithData
max-time: 1500
--- 1.17/ndb/src/kernel/blocks/ERROR_codes.txt 2006-06-01 08:24:02 +02:00
+++ 1.18/ndb/src/kernel/blocks/ERROR_codes.txt 2006-07-07 10:55:55 +02:00
@@ -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 6006
Next DBDIH 7174
@@ -429,6 +429,8 @@ Drop Table/Index:
8034: Fail next index create in TC
8035: Fail next trigger drop in TC
8036: Fail next index drop in TC
+
+4013: verify TUP tab descr before and after next DROP TABLE
System Restart:
---------------
--- 1.20/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2005-09-21 17:24:38 +02:00
+++ 1.21/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2006-07-07 10:55:56 +02:00
@@ -2129,15 +2129,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
--- 1.8/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp 2005-08-31 16:14:59 +02:00
+++ 1.9/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp 2006-07-07 10:55:57 +02:00
@@ -567,6 +567,9 @@ void
Dbtup::execDROP_TAB_REQ(Signal* signal)
{
ljamEntry();
+ if (ERROR_INSERTED(4013)) {
+ verifytabdes();
+ }
DropTabReq* req = (DropTabReq*)signal->getDataPtr();
TablerecPtr tabPtr;
@@ -685,5 +688,9 @@ void Dbtup::execFSREMOVECONF(Signal* sig
releaseTabDescr(tabPtr.p);
initTab(tabPtr.p);
+ if (ERROR_INSERTED(4013)) {
+ CLEAR_ERROR_INSERT_VALUE;
+ verifytabdes();
+ }
}//Dbtup::execFSREMOVECONF()
--- 1.3/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp 2006-07-04 15:09:39 +02:00
+++ 1.4/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp 2006-07-07 10:55:57 +02:00
@@ -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)
@@ -72,8 +74,9 @@ Uint32 Dbtup::allocTabDescr(const Tabler
Uint32 retNo = (1 << i) - allocSize; /* CALCULATE THE DIFFERENCE */
if (retNo >= ZTD_FREE_SIZE) {
ljam();
- Uint32 retRef = reference + allocSize; /* SET THE RETURN POINTER */
- 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;
@@ -99,15 +102,15 @@ Uint32 Dbtup::allocTabDescr(const Tabler
}//if
}//Dbtup::allocTabDescr()
-void Dbtup::freeTabDescr(Uint32 retRef, Uint32 retNo)
+void Dbtup::freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal)
{
- retNo = itdaMergeTabDescr(retRef, retNo); /* MERGE WITH POSSIBLE RIGHT NEIGHBOURS */
+ 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
@@ -128,7 +131,7 @@ Dbtup::setTabDescrWord(Uint32 index, Uin
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);
@@ -145,19 +148,14 @@ void Dbtup::insertTdArea(Uint32 sizeOfCh
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;
@@ -171,11 +169,28 @@ Uint32 Dbtup::itdaMergeTabDescr(Uint32 r
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()
/* ---------------------------------------------------------------- */
@@ -211,3 +226,94 @@ void Dbtup::removeTdArea(Uint32 tabDesRe
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
--- 1.18/ndb/test/ndbapi/testDict.cpp 2004-12-07 10:27:00 +01:00
+++ 1.19/ndb/test/ndbapi/testDict.cpp 2006-07-07 10:55:58 +02:00
@@ -223,6 +223,101 @@ int runCreateAndDrop(NDBT_Context* ctx,
return NDBT_OK;
}
+int runCreateAndDropAtRandom(NDBT_Context* ctx, NDBT_Step* step)
+{
+ myRandom48Init(NdbTick_CurrentMillisecond());
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+ int loops = ctx->getNumLoops();
+ int numTables = NDBT_Tables::getNumTables();
+ bool* tabList = new bool [ numTables ];
+ int tabCount;
+
+ {
+ for (int num = 0; num < numTables; num++) {
+ (void)pDic->dropTable(NDBT_Tables::getTable(num)->getName());
+ tabList[num] = false;
+ }
+ tabCount = 0;
+ }
+
+ NdbRestarter restarter;
+ int result = NDBT_OK;
+ int bias = 1; // 0-less 1-more
+ int i = 0;
+
+ while (i < loops) {
+ g_info << "loop " << i << " tabs " << tabCount << "/" << numTables << endl;
+ int num = myRandom48(numTables);
+ const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num);
+ char tabName[200];
+ strcpy(tabName, pTab->getName());
+
+ if (tabList[num] == false) {
+ if (bias == 0 && myRandom48(100) < 80)
+ continue;
+ g_info << tabName << ": create" << endl;
+ if (pDic->createTable(*pTab) != 0) {
+ const NdbError err = pDic->getNdbError();
+ g_err << tabName << ": create failed: " << err << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
+ if (pTab2 == NULL) {
+ const NdbError err = pDic->getNdbError();
+ g_err << tabName << ": verify create: " << err << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ tabList[num] = true;
+ assert(tabCount < numTables);
+ tabCount++;
+ if (tabCount == numTables)
+ bias = 0;
+ }
+ else {
+ if (bias == 1 && myRandom48(100) < 80)
+ continue;
+ g_info << tabName << ": drop" << endl;
+ if (restarter.insertErrorInAllNodes(4013) != 0) {
+ g_err << "error insert failed" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ if (pDic->dropTable(tabName) != 0) {
+ const NdbError err = pDic->getNdbError();
+ g_err << tabName << ": drop failed: " << err << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
+ if (pTab2 != NULL) {
+ g_err << tabName << ": verify drop: table exists" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ if (pDic->getNdbError().code != 709 &&
+ pDic->getNdbError().code != 723) {
+ const NdbError err = pDic->getNdbError();
+ g_err << tabName << ": verify drop: " << err << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+ tabList[num] = false;
+ assert(tabCount > 0);
+ tabCount--;
+ if (tabCount == 0)
+ bias = 1;
+ }
+ i++;
+ }
+
+ delete [] tabList;
+ return result;
+}
+
+
int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
int loops = ctx->getNumLoops();
@@ -1561,6 +1656,12 @@ NDBT_TESTSUITE(testDict);
TESTCASE("CreateAndDrop",
"Try to create and drop the table loop number of times\n"){
INITIALIZER(runCreateAndDrop);
+}
+TESTCASE("CreateAndDropAtRandom",
+ "Try to create and drop table at random loop number of times\n"
+ "Uses all available tables\n"
+ "Uses error insert 4013 to make TUP verify table descriptor"){
+ INITIALIZER(runCreateAndDropAtRandom);
}
TESTCASE("CreateAndDropWithData",
"Try to create and drop the table when it's filled with data\n"
| Thread |
|---|
| • bk commit into 4.1 tree (pekka:1.2530) BUG#20847 | pekka | 7 Jul |