summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorunknown <msvensson@neptunus.(none)>2006-07-27 05:55:42 +0200
committerunknown <msvensson@neptunus.(none)>2006-07-27 05:55:42 +0200
commitdfaa0582bb76d4f1098e4a05dba8ee11bbcad68c (patch)
treeadc2f1ababdea23c28a72d586a5e64e3b76b0b8c /storage
parent1585d76e1fa9031abc16da2499d5d085a0cceb9c (diff)
parenta9f0f11671acfd6f31404ecc34b63177a93a1801 (diff)
downloadmariadb-git-dfaa0582bb76d4f1098e4a05dba8ee11bbcad68c.tar.gz
Merge neptunus.(none):/home/msvensson/mysql/mysql-5.1
into neptunus.(none):/home/msvensson/mysql/mysql-5.1-new-maint mysql-test/t/disabled.def: Auto merged
Diffstat (limited to 'storage')
-rw-r--r--storage/blackhole/ha_blackhole.cc2
-rw-r--r--storage/ndb/src/kernel/blocks/ERROR_codes.txt7
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp12
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp13
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp19
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp7
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp169
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp14
-rw-r--r--storage/ndb/test/ndbapi/testDict.cpp101
-rw-r--r--storage/ndb/test/run-test/daily-basic-tests.txt4
10 files changed, 307 insertions, 41 deletions
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 1a2bb264ef9..d22d9372e0d 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -206,7 +206,7 @@ static int blackhole_init()
blackhole_hton.state= SHOW_OPTION_YES;
blackhole_hton.db_type= DB_TYPE_BLACKHOLE_DB;
blackhole_hton.create= blackhole_create_handler;
- blackhole_hton.flags= HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE;
+ blackhole_hton.flags= HTON_CAN_RECREATE;
return 0;
}
diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt
index 867dc0d2efc..fc22118e113 100644
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/storage/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 4024
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:
---------------
@@ -484,3 +486,6 @@ Dbtup:
4019 - handleInsert - Alloc rowid error
4020 - handleInsert - Size change error
4021 - handleInsert - Out of disk space
+
+4022 - addTuxEntries - fail before add of first entry
+4023 - addTuxEntries - fail add of last entry (the entry for last index)
diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index 3cf62fe08ec..e19e43f6d47 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -254,6 +254,8 @@ inline const Uint32* ALIGN_WORD(const void* ptr)
#define ZSTORED_PROCEDURE_FREE 0xffff
#define ZMIN_PAGE_LIMIT_TUP_COMMITREQ 2
+#define ZSKIP_TUX_TRIGGERS 0x1 // flag for TUP_ABORTREQ
+
#endif
class Dbtup: public SimulatedBlock {
@@ -2155,6 +2157,7 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
void tupkeyErrorLab(Signal* signal);
+ void do_tup_abortreq(Signal*, Uint32 flags);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -2373,15 +2376,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
void seizeOpRec(OperationrecPtr& regOperPtr);
void seizeFragrecord(FragrecordPtr& regFragPtr);
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
index aa55985c1f2..16c51f7aa6e 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
@@ -63,11 +63,16 @@ void Dbtup::freeAttrinbufrec(Uint32 anAttrBuf)
*/
void Dbtup::execTUP_ABORTREQ(Signal* signal)
{
+ ljamEntry();
+ do_tup_abortreq(signal, 0);
+}
+
+void Dbtup::do_tup_abortreq(Signal* signal, Uint32 flags)
+{
OperationrecPtr regOperPtr;
FragrecordPtr regFragPtr;
TablerecPtr regTabPtr;
- ljamEntry();
regOperPtr.i = signal->theData[0];
c_operation_pool.getPtr(regOperPtr);
TransState trans_state= get_trans_state(regOperPtr.p);
@@ -91,7 +96,8 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
if (get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
{
ljam();
- if (!regTabPtr.p->tuxCustomTriggers.isEmpty())
+ if (!regTabPtr.p->tuxCustomTriggers.isEmpty() &&
+ (flags & ZSKIP_TUX_TRIGGERS) == 0)
executeTuxAbortTriggers(signal,
regOperPtr.p,
regFragPtr.p,
@@ -103,7 +109,8 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
ljam();
c_operation_pool.getPtr(loopOpPtr);
if (get_tuple_state(loopOpPtr.p) != TUPLE_ALREADY_ABORTED &&
- !regTabPtr.p->tuxCustomTriggers.isEmpty()) {
+ !regTabPtr.p->tuxCustomTriggers.isEmpty() &&
+ (flags & ZSKIP_TUX_TRIGGERS) == 0) {
ljam();
executeTuxAbortTriggers(signal,
loopOpPtr.p,
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 3021799fd11..6cde3e51e5a 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -747,6 +747,20 @@ void Dbtup::execTUPKEYREQ(Signal* signal)
regFragPtr,
regTabPtr) != 0) {
jam();
+ /*
+ * TUP insert succeeded but add of TUX entries failed. All
+ * TUX changes have been rolled back at this point.
+ *
+ * We will abort via tupkeyErrorLab() as usual. This routine
+ * however resets the operation to ZREAD. The TUP_ABORTREQ
+ * arriving later cannot then undo the insert.
+ *
+ * Therefore we call TUP_ABORTREQ already now. Diskdata etc
+ * should be in memory and timeslicing cannot occur. We must
+ * skip TUX abort triggers since TUX is already aborted.
+ */
+ signal->theData[0] = operPtr.i;
+ do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS);
tupkeyErrorLab(signal);
return;
}
@@ -775,6 +789,11 @@ void Dbtup::execTUPKEYREQ(Signal* signal)
regFragPtr,
regTabPtr) != 0) {
jam();
+ /*
+ * See insert case.
+ */
+ signal->theData[0] = operPtr.i;
+ do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS);
tupkeyErrorLab(signal);
return;
}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
index 88845a6ef64..8db8f423817 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
@@ -857,6 +857,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;
@@ -1109,7 +1114,6 @@ Dbtup::drop_fragment_free_var_pages(Signal* signal)
}
releaseFragPages(fragPtr.p);
-
Uint32 i;
for(i= 0; i<MAX_FRAG_PER_NODE; i++)
if(tabPtr.p->fragrec[i] == fragPtr.i)
@@ -1152,7 +1156,6 @@ Dbtup::start_restore_lcp(Uint32 tableId, Uint32 fragId)
tabPtr.p->m_attributes[DD].m_no_of_fixsize = 0;
tabPtr.p->m_attributes[DD].m_no_of_varsize = 0;
}
-
void
Dbtup::complete_restore_lcp(Uint32 tableId, Uint32 fragId)
{
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
index 3754942bb99..15a01e82d38 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
+++ b/storage/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/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
index 62cd1f06157..0e1b251d8a5 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
@@ -1111,6 +1111,12 @@ Dbtup::addTuxEntries(Signal* signal,
Operationrec* regOperPtr,
Tablerec* regTabPtr)
{
+ if (ERROR_INSERTED(4022)) {
+ ljam();
+ CLEAR_ERROR_INSERT_VALUE;
+ terrorCode = 9999;
+ return -1;
+ }
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
const DLList<TupTriggerData>& triggerList = regTabPtr->tuxCustomTriggers;
TriggerPtr triggerPtr;
@@ -1120,6 +1126,14 @@ Dbtup::addTuxEntries(Signal* signal,
ljam();
req->indexId = triggerPtr.p->indexId;
req->errorCode = RNIL;
+ if (ERROR_INSERTED(4023) &&
+ ! triggerList.hasNext(triggerPtr)) {
+ ljam();
+ CLEAR_ERROR_INSERT_VALUE;
+ terrorCode = 9999;
+ failPtrI = triggerPtr.i;
+ goto fail;
+ }
EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
signal, TuxMaintReq::SignalLength);
ljamEntry();
diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp
index f6277484b04..2972123cbbe 100644
--- a/storage/ndb/test/ndbapi/testDict.cpp
+++ b/storage/ndb/test/ndbapi/testDict.cpp
@@ -233,6 +233,101 @@ int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
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();
@@ -1945,6 +2040,12 @@ 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"
"do this loop number of times\n"){
diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt
index 68e653b1ead..f58a6f050d5 100644
--- a/storage/ndb/test/run-test/daily-basic-tests.txt
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt
@@ -497,6 +497,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