Below is the list of changes that have just been committed into a local
5.1 repository of jonas. When jonas 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@stripped, 2007-04-17 16:53:15+02:00, jonas@stripped +4 -0
Merge perch.ndb.mysql.com:/home/jonas/src/mysql-5.1-new-ndb
into perch.ndb.mysql.com:/home/jonas/src/51-telco
MERGE: 1.2494.1.103
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp@stripped, 2007-04-17 16:51:33+02:00, jonas@stripped +0 -0
Auto merged
MERGE: 1.112.1.14
storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp@stripped, 2007-04-17 16:51:33+02:00, jonas@stripped +0 -0
Auto merged
MERGE: 1.45.1.8
storage/ndb/test/ndbapi/testDict.cpp@stripped, 2007-04-17 16:53:13+02:00, jonas@stripped +8 -8
merge
MERGE: 1.35.1.1
storage/ndb/test/run-test/daily-basic-tests.txt@stripped, 2007-04-17 16:51:33+02:00, jonas@stripped +0 -0
Auto merged
MERGE: 1.61.1.18
# 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: jonas
# Host: perch.ndb.mysql.com
# Root: /home/jonas/src/51-telco/RESYNC
--- 1.90/storage/ndb/test/run-test/daily-basic-tests.txt 2007-04-17 16:53:21 +02:00
+++ 1.91/storage/ndb/test/run-test/daily-basic-tests.txt 2007-04-17 16:53:21 +02:00
@@ -599,6 +599,14 @@
cmd: testDict
args: -n Restart_NR2 T1 I3
+max-time: 500
+cmd: testDict
+args: -n Bug21755 T1
+
+max-time: 1500
+cmd: testDict
+args: -l 25 -n DictRestart T1
+
#
# TEST NDBAPI
#
--- 1.127/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2007-04-17 16:53:21 +02:00
+++ 1.128/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2007-04-17 16:53:21 +02:00
@@ -2661,25 +2661,63 @@
case DictTabInfo::IndexTrigger:
return false;
case DictTabInfo::LogfileGroup:
- return pass == 0;
+ return pass == 0 || pass == 9 || pass == 10;
case DictTabInfo::Tablespace:
- return pass == 1;
+ return pass == 1 || pass == 8 || pass == 11;
case DictTabInfo::Datafile:
case DictTabInfo::Undofile:
- return pass == 2;
+ return pass == 2 || pass == 7 || pass == 12;
case DictTabInfo::SystemTable:
case DictTabInfo::UserTable:
- return pass == 3;
+ return /* pass == 3 || pass == 6 || */ pass == 13;
case DictTabInfo::UniqueHashIndex:
case DictTabInfo::HashIndex:
case DictTabInfo::UniqueOrderedIndex:
case DictTabInfo::OrderedIndex:
- return pass == 4;
+ return /* pass == 4 || pass == 5 || */ pass == 14;
}
return false;
}
+static const Uint32 CREATE_OLD_PASS = 4;
+static const Uint32 DROP_OLD_PASS = 9;
+static const Uint32 CREATE_NEW_PASS = 14;
+static const Uint32 LAST_PASS = 14;
+
+NdbOut&
+operator<<(NdbOut& out, const SchemaFile::TableEntry entry)
+{
+ out << "[";
+ out << " state: " << entry.m_tableState;
+ out << " version: " << hex << entry.m_tableVersion << dec;
+ out << " type: " << entry.m_tableType;
+ out << " words: " << entry.m_info_words;
+ out << " gcp: " << entry.m_gcp;
+ out << " ]";
+ return out;
+}
+
+/**
+ * Pass 0 Create old LogfileGroup
+ * Pass 1 Create old Tablespace
+ * Pass 2 Create old Datafile/Undofile
+ * Pass 3 Create old Table // NOT DONE DUE TO DIH
+ * Pass 4 Create old Index // NOT DONE DUE TO DIH
+
+ * Pass 5 Drop old Index // NOT DONE DUE TO DIH
+ * Pass 6 Drop old Table // NOT DONE DUE TO DIH
+ * Pass 7 Drop old Datafile/Undofile
+ * Pass 8 Drop old Tablespace
+ * Pass 9 Drop old Logfilegroup
+
+ * Pass 10 Create new LogfileGroup
+ * Pass 11 Create new Tablespace
+ * Pass 12 Create new Datafile/Undofile
+ * Pass 13 Create new Table
+ * Pass 14 Create new Index
+ */
+
void Dbdict::checkSchemaStatus(Signal* signal)
{
XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
@@ -2694,287 +2732,132 @@
Uint32 tableId = c_restartRecord.activeTable;
SchemaFile::TableEntry *newEntry = getTableEntry(newxsf, tableId);
SchemaFile::TableEntry *oldEntry = getTableEntry(oldxsf, tableId);
- SchemaFile::TableState schemaState =
+ SchemaFile::TableState newSchemaState =
(SchemaFile::TableState)newEntry->m_tableState;
SchemaFile::TableState oldSchemaState =
(SchemaFile::TableState)oldEntry->m_tableState;
if (c_restartRecord.activeTable >= c_tableRecordPool.getSize()) {
jam();
- ndbrequire(schemaState == SchemaFile::INIT);
+ ndbrequire(newSchemaState == SchemaFile::INIT);
ndbrequire(oldSchemaState == SchemaFile::INIT);
continue;
}//if
- if(!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
- continue;
-
- if(!::checkSchemaStatus(newEntry->m_tableType, c_restartRecord.m_pass))
- continue;
+//#define PRINT_SCHEMA_RESTART
+#ifdef PRINT_SCHEMA_RESTART
+ char buf[100];
+ snprintf(buf, sizeof(buf), "checkSchemaStatus: pass: %d table: %d",
+ c_restartRecord.m_pass, tableId);
+#endif
- switch(schemaState){
- case SchemaFile::INIT:{
- jam();
- bool ok = false;
- switch(oldSchemaState) {
- case SchemaFile::INIT:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:
- jam();
- ok = true;
- jam();
- break;
+ if (c_restartRecord.m_pass <= CREATE_OLD_PASS)
+ {
+ if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
+ continue;
- case SchemaFile::ADD_STARTED:
- jam();
- case SchemaFile::TABLE_ADD_COMMITTED:
- jam();
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::ALTER_TABLE_COMMITTED:
- jam();
- ok = true;
- jam();
- newEntry->m_tableState = SchemaFile::INIT;
- restartDropTab(signal, tableId);
- return;
-
- case SchemaFile::TEMPORARY_TABLE_COMMITTED:
- // Temporary table is never written to disk, so just set to INIT.
- jam();
- ok = true;
- newEntry->m_tableState = SchemaFile::INIT;
- break;
- }//switch
- ndbrequire(ok);
- break;
- }
- case SchemaFile::ADD_STARTED:{
- jam();
- bool ok = false;
- switch(oldSchemaState) {
- case SchemaFile::INIT:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:
- jam();
- ok = true;
- break;
- case SchemaFile::ADD_STARTED:
- jam();
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::TABLE_ADD_COMMITTED:
- jam();
- case SchemaFile::ALTER_TABLE_COMMITTED:
- jam();
- ok = true;
- //------------------------------------------------------------------
- // Add Table was started but not completed. Will be dropped in all
- // nodes. Update schema information (restore table version).
- //------------------------------------------------------------------
- newEntry->m_tableState = SchemaFile::INIT;
- restartDropTab(signal, tableId);
- return;
- case SchemaFile::TEMPORARY_TABLE_COMMITTED:
- jam();
- ok = true;
- newEntry->m_tableState = SchemaFile::INIT;
- break;
+ switch(oldSchemaState){
+ case SchemaFile::INIT: jam();
+ case SchemaFile::DROP_TABLE_COMMITTED: jam();
+ case SchemaFile::ADD_STARTED: jam();
+ case SchemaFile::DROP_TABLE_STARTED: jam();
+ case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
+ continue;
+ case SchemaFile::TABLE_ADD_COMMITTED: jam();
+ case SchemaFile::ALTER_TABLE_COMMITTED: jam();
+ jam();
+#ifdef PRINT_SCHEMA_RESTART
+ ndbout_c("%s -> restartCreateTab", buf);
+ ndbout << *newEntry << " " << *oldEntry << endl;
+#endif
+ restartCreateTab(signal, tableId, oldEntry, oldEntry, true);
+ return;
}
- ndbrequire(ok);
- break;
}
- case SchemaFile::TABLE_ADD_COMMITTED:{
- jam();
- bool ok = false;
- switch(oldSchemaState) {
- case SchemaFile::INIT:
- jam();
- case SchemaFile::ADD_STARTED:
- jam();
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:
- jam();
- ok = true;
- //------------------------------------------------------------------
- // Table was added in the master node but not in our node. We can
- // retrieve the table definition from the master.
- //------------------------------------------------------------------
- restartCreateTab(signal, tableId, oldEntry, newEntry, false);
- return;
- break;
- case SchemaFile::TABLE_ADD_COMMITTED:
- jam();
- case SchemaFile::ALTER_TABLE_COMMITTED:
- jam();
- ok = true;
- //------------------------------------------------------------------
- // Table was added in both our node and the master node. We can
- // retrieve the table definition from our own disk.
- //------------------------------------------------------------------
- if(newEntry->m_tableVersion == oldEntry->m_tableVersion)
- {
- jam();
- ndbrequire(newEntry->m_gcp == oldEntry->m_gcp);
- ndbrequire(newEntry->m_tableType == oldEntry->m_tableType);
- Uint32 type= oldEntry->m_tableType;
- // On NR get index from master because index state is not on file
- const bool file = c_systemRestart || !DictTabInfo::isIndex(type);
- newEntry->m_info_words= oldEntry->m_info_words;
- restartCreateTab(signal, tableId, oldEntry, newEntry, file);
- return;
- } else {
- //------------------------------------------------------------------
- // Must be a new version of the table if anything differs. Both table
- // version and global checkpoint must be different.
- // This should not happen for the master node. This can happen after
- // drop table followed by add table or after change table.
- // Not supported in this version.
- //------------------------------------------------------------------
- ndbrequire(c_masterNodeId != getOwnNodeId());
- ndbrequire(newEntry->m_tableVersion != oldEntry->m_tableVersion);
- jam();
-
- restartCreateTab(signal, tableId, oldEntry, newEntry, false);
- return;
- }//if
- case SchemaFile::TEMPORARY_TABLE_COMMITTED:
- jam();
- ok = true;
- // For NR, we must re-create the table.
- // For SR, we do nothing as the table was never saved to disk.
- if(!c_systemRestart)
+ if (c_restartRecord.m_pass <= DROP_OLD_PASS)
+ {
+ if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
+ continue;
+
+ switch(oldSchemaState){
+ case SchemaFile::INIT: jam();
+ case SchemaFile::DROP_TABLE_COMMITTED: jam();
+ case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
+ continue;
+ case SchemaFile::ADD_STARTED: jam();
+ case SchemaFile::DROP_TABLE_STARTED: jam();
+#ifdef PRINT_SCHEMA_RESTART
+ ndbout_c("%s -> restartDropTab", buf);
+ ndbout << *newEntry << " " << *oldEntry << endl;
+#endif
+ restartDropTab(signal, tableId, oldEntry, newEntry);
+ return;
+ case SchemaFile::TABLE_ADD_COMMITTED: jam();
+ case SchemaFile::ALTER_TABLE_COMMITTED: jam();
+ if (! (* oldEntry == * newEntry))
{
- restartCreateTab(signal, tableId, oldEntry, newEntry, false);
+#ifdef PRINT_SCHEMA_RESTART
+ ndbout_c("%s -> restartDropTab", buf);
+ ndbout << *newEntry << " " << *oldEntry << endl;
+#endif
+ restartDropTab(signal, tableId, oldEntry, newEntry);
return;
}
- break;
+ continue;
}
- ndbrequire(ok);
- break;
}
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:{
- jam();
- bool ok = false;
- switch(oldSchemaState){
- case SchemaFile::INIT:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:
- jam();
- ok = true;
- break;
- case SchemaFile::ADD_STARTED:
- jam();
- case SchemaFile::TABLE_ADD_COMMITTED:
- jam();
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::ALTER_TABLE_COMMITTED:
- jam();
- newEntry->m_tableState = SchemaFile::INIT;
- restartDropTab(signal, tableId);
- return;
- case SchemaFile::TEMPORARY_TABLE_COMMITTED:
- jam();
- ok = true;
- newEntry->m_tableState = SchemaFile::INIT;
- break;
- }
- ndbrequire(ok);
- break;
- }
- case SchemaFile::ALTER_TABLE_COMMITTED: {
- jam();
- bool ok = false;
- switch(oldSchemaState) {
- case SchemaFile::INIT:
- jam();
- case SchemaFile::ADD_STARTED:
- jam();
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:
- jam();
- case SchemaFile::TEMPORARY_TABLE_COMMITTED:
- jam();
- ok = true;
- if(!c_systemRestart)
+
+ if (c_restartRecord.m_pass <= CREATE_NEW_PASS)
+ {
+ if (!::checkSchemaStatus(newEntry->m_tableType, c_restartRecord.m_pass))
+ continue;
+
+ switch(newSchemaState){
+ case SchemaFile::INIT: jam();
+ case SchemaFile::DROP_TABLE_COMMITTED: jam();
+ case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
+ * oldEntry = * newEntry;
+ continue;
+ case SchemaFile::ADD_STARTED: jam();
+ case SchemaFile::DROP_TABLE_STARTED: jam();
+ ndbrequire(false);
+ return;
+ case SchemaFile::TABLE_ADD_COMMITTED: jam();
+ case SchemaFile::ALTER_TABLE_COMMITTED: jam();
+ if (DictTabInfo::isIndex(newEntry->m_tableType) ||
+ DictTabInfo::isTable(newEntry->m_tableType))
{
- restartCreateTab(signal, tableId, oldEntry, newEntry, false);
+ bool file = * oldEntry == *newEntry &&
+ (!DictTabInfo::isIndex(newEntry->m_tableType) || c_systemRestart);
+
+#ifdef PRINT_SCHEMA_RESTART
+ ndbout_c("%s -> restartCreateTab (file: %d)", buf, file);
+ ndbout << *newEntry << " " << *oldEntry << endl;
+#endif
+ restartCreateTab(signal, tableId, newEntry, newEntry, file);
+ * oldEntry = * newEntry;
return;
}
- break;
- case SchemaFile::TABLE_ADD_COMMITTED:
- jam();
- ok = true;
- //------------------------------------------------------------------
- // Table was altered in the master node but not in our node. We can
- // retrieve the altered table definition from the master.
- //------------------------------------------------------------------
- restartCreateTab(signal, tableId, oldEntry, newEntry, false);
- return;
- break;
- case SchemaFile::ALTER_TABLE_COMMITTED:
- jam();
- ok = true;
-
- //------------------------------------------------------------------
- // Table was altered in both our node and the master node. We can
- // retrieve the table definition from our own disk.
- //------------------------------------------------------------------
-
- // On NR get index from master because index state is not on file
- Uint32 type= oldEntry->m_tableType;
- const bool file = (* newEntry == * oldEntry) &&
- (c_systemRestart || !DictTabInfo::isIndex(type));
- newEntry->m_info_words= oldEntry->m_info_words;
- restartCreateTab(signal, tableId, oldEntry, newEntry, file);
- return;
- }
- ndbrequire(ok);
- break;
- }
- case SchemaFile::TEMPORARY_TABLE_COMMITTED: {
- jam();
- bool ok = false;
- switch(oldSchemaState){
- case SchemaFile::INIT:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:
- jam();
- case SchemaFile::ADD_STARTED:
- jam();
- case SchemaFile::TABLE_ADD_COMMITTED:
- jam();
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::ALTER_TABLE_COMMITTED:
- jam();
- case SchemaFile::TEMPORARY_TABLE_COMMITTED:
- jam();
- ok = true;
- if(!c_systemRestart)
+ else if (! (* oldEntry == *newEntry))
{
- restartCreateTab(signal, tableId, oldEntry, newEntry, false);
+#ifdef PRINT_SCHEMA_RESTART
+ ndbout_c("%s -> restartCreateTab", buf);
+ ndbout << *newEntry << " " << *oldEntry << endl;
+#endif
+ restartCreateTab(signal, tableId, oldEntry, newEntry, false);
+ * oldEntry = * newEntry;
return;
- } else {
- newEntry->m_tableState = SchemaFile::INIT;
- }
- break;
+ }
+ * oldEntry = * newEntry;
+ continue;
}
- ndbrequire(ok);
- break;
- }
}
}
c_restartRecord.m_pass++;
c_restartRecord.activeTable= 0;
- if(c_restartRecord.m_pass <= 4)
+ if(c_restartRecord.m_pass <= LAST_PASS)
{
checkSchemaStatus(signal);
}
@@ -3301,7 +3184,33 @@
}
void
-Dbdict::restartDropTab(Signal* signal, Uint32 tableId){
+Dbdict::restartDropTab(Signal* signal, Uint32 tableId,
+ const SchemaFile::TableEntry * old_entry,
+ const SchemaFile::TableEntry * new_entry)
+{
+ switch(old_entry->m_tableType){
+ case DictTabInfo::UndefTableType:
+ case DictTabInfo::HashIndexTrigger:
+ case DictTabInfo::SubscriptionTrigger:
+ case DictTabInfo::ReadOnlyConstraint:
+ case DictTabInfo::IndexTrigger:
+ ndbrequire(false);
+ case DictTabInfo::SystemTable:
+ case DictTabInfo::UserTable:
+ case DictTabInfo::UniqueHashIndex:
+ case DictTabInfo::HashIndex:
+ case DictTabInfo::UniqueOrderedIndex:
+ case DictTabInfo::OrderedIndex:
+ break;
+ case DictTabInfo::Tablespace:
+ case DictTabInfo::LogfileGroup:
+ case DictTabInfo::Datafile:
+ case DictTabInfo::Undofile:
+ warningEvent("Dont drop object: %d", tableId);
+ c_restartRecord.activeTable++;
+ checkSchemaStatus(signal);
+ return;
+ }
const Uint32 key = ++c_opRecordSequence;
@@ -3335,6 +3244,7 @@
//@todo check error
+ releaseTableObject(c_restartRecord.activeTable);
c_opDropTable.release(dropTabPtr);
c_restartRecord.activeTable++;
--- 1.55/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2007-04-17 16:53:21 +02:00
+++ 1.56/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2007-04-17 16:53:21 +02:00
@@ -2562,7 +2562,9 @@
void restartCreateTab_dihComplete(Signal* signal, Uint32 callback, Uint32);
void restartCreateTab_activateComplete(Signal*, Uint32 callback, Uint32);
- void restartDropTab(Signal* signal, Uint32 tableId);
+ void restartDropTab(Signal* signal, Uint32 tableId,
+ const SchemaFile::TableEntry *,
+ const SchemaFile::TableEntry *);
void restartDropTab_complete(Signal*, Uint32 callback, Uint32);
void restart_checkSchemaStatusComplete(Signal*, Uint32 callback, Uint32);
--- 1.36/storage/ndb/test/ndbapi/testDict.cpp 2007-04-17 16:53:21 +02:00
+++ 1.37/storage/ndb/test/ndbapi/testDict.cpp 2007-04-17 16:53:21 +02:00
@@ -23,6 +23,7 @@
#include <../../include/kernel/ndb_limits.h>
#include <random.h>
#include <NdbAutoPtr.hpp>
+#include <NdbMixRestarter.hpp>
#define CHECK(b) if (!(b)) { \
g_err << "ERR: "<< step->getName() \
@@ -2321,6 +2322,448 @@
return result;
}
+int
+runBug21755(NDBT_Context* ctx, NDBT_Step* step)
+{
+ char buf[256];
+ NdbRestarter res;
+ NdbDictionary::Table pTab0 = * ctx->getTab();
+ NdbDictionary::Table pTab1 = pTab0;
+
+ if (res.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+
+ if (pDic->createTable(pTab0))
+ {
+ ndbout << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ NdbDictionary::Index idx0;
+ BaseString::snprintf(buf, sizeof(buf), "%s-idx", pTab0.getName());
+ idx0.setName(buf);
+ idx0.setType(NdbDictionary::Index::OrderedIndex);
+ idx0.setTable(pTab0.getName());
+ idx0.setStoredIndex(false);
+ for (Uint32 i = 0; i<pTab0.getNoOfColumns(); i++)
+ {
+ const NdbDictionary::Column * col = pTab0.getColumn(i);
+ if(col->getPrimaryKey()){
+ idx0.addIndexColumn(col->getName());
+ }
+ }
+
+ if (pDic->createIndex(idx0))
+ {
+ ndbout << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ BaseString::snprintf(buf, sizeof(buf), "%s-2", pTab1.getName());
+ pTab1.setName(buf);
+
+ if (pDic->createTable(pTab1))
+ {
+ ndbout << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ {
+ HugoTransactions t0 (*pDic->getTable(pTab0.getName()));
+ t0.loadTable(pNdb, 1000);
+ }
+
+ {
+ HugoTransactions t1 (*pDic->getTable(pTab1.getName()));
+ t1.loadTable(pNdb, 1000);
+ }
+
+ int node = res.getRandomNotMasterNodeId(rand());
+ res.restartOneDbNode(node, false, true, true);
+
+ if (pDic->dropTable(pTab1.getName()))
+ {
+ ndbout << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ BaseString::snprintf(buf, sizeof(buf), "%s-idx2", pTab0.getName());
+ idx0.setName(buf);
+ if (pDic->createIndex(idx0))
+ {
+ ndbout << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ res.waitNodesNoStart(&node, 1);
+ res.startNodes(&node, 1);
+
+ if (res.waitClusterStarted())
+ {
+ return NDBT_FAILED;
+ }
+
+ if (pDic->dropTable(pTab0.getName()))
+ {
+ ndbout << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+struct RandSchemaOp
+{
+ struct Obj
+ {
+ BaseString m_name;
+ Uint32 m_type;
+ struct Obj* m_parent;
+ Vector<Obj*> m_dependant;
+ };
+
+ Vector<Obj*> m_objects;
+
+ int schema_op(Ndb*);
+ int validate(Ndb*);
+ int cleanup(Ndb*);
+
+ Obj* get_obj(Uint32 mask);
+ int create_table(Ndb*);
+ int create_index(Ndb*, Obj*);
+ int drop_obj(Ndb*, Obj*);
+
+ void remove_obj(Obj*);
+};
+
+template class Vector<RandSchemaOp::Obj*>;
+
+int
+RandSchemaOp::schema_op(Ndb* ndb)
+{
+ struct Obj* obj = 0;
+ Uint32 type = 0;
+loop:
+ switch((rand() >> 16) & 3){
+ case 0:
+ return create_table(ndb);
+ case 1:
+ if ((obj = get_obj(1 << NdbDictionary::Object::UserTable)) == 0)
+ goto loop;
+ return create_index(ndb, obj);
+ case 2:
+ type = (1 << NdbDictionary::Object::UserTable);
+ goto drop_object;
+ case 3:
+ type =
+ (1 << NdbDictionary::Object::UniqueHashIndex) |
+ (1 << NdbDictionary::Object::OrderedIndex);
+ goto drop_object;
+ default:
+ goto loop;
+ }
+
+drop_object:
+ if ((obj = get_obj(type)) == 0)
+ goto loop;
+ return drop_obj(ndb, obj);
+}
+
+RandSchemaOp::Obj*
+RandSchemaOp::get_obj(Uint32 mask)
+{
+ Vector<Obj*> tmp;
+ for (Uint32 i = 0; i<m_objects.size(); i++)
+ {
+ if ((1 << m_objects[i]->m_type) & mask)
+ tmp.push_back(m_objects[i]);
+ }
+
+ if (tmp.size())
+ {
+ return tmp[rand()%tmp.size()];
+ }
+ return 0;
+}
+
+int
+RandSchemaOp::create_table(Ndb* ndb)
+{
+ int numTables = NDBT_Tables::getNumTables();
+ int num = myRandom48(numTables);
+ NdbDictionary::Table pTab = * NDBT_Tables::getTable(num);
+
+ NdbDictionary::Dictionary* pDict = ndb->getDictionary();
+
+ if (pDict->getTable(pTab.getName()))
+ {
+ char buf[100];
+ BaseString::snprintf(buf, sizeof(buf), "%s-%d",
+ pTab.getName(), rand());
+ pTab.setName(buf);
+ if (pDict->createTable(pTab))
+ return NDBT_FAILED;
+ }
+ else
+ {
+ if (NDBT_Tables::createTable(ndb, pTab.getName()))
+ {
+ return NDBT_FAILED;
+ }
+ }
+
+ ndbout_c("create table %s", pTab.getName());
+ const NdbDictionary::Table* tab2 = pDict->getTable(pTab.getName());
+ HugoTransactions trans(*tab2);
+ trans.loadTable(ndb, 1000);
+
+ Obj *obj = new Obj;
+ obj->m_name.assign(pTab.getName());
+ obj->m_type = NdbDictionary::Object::UserTable;
+ obj->m_parent = 0;
+ m_objects.push_back(obj);
+
+ return NDBT_OK;
+}
+
+int
+RandSchemaOp::create_index(Ndb* ndb, Obj* tab)
+{
+ NdbDictionary::Dictionary* pDict = ndb->getDictionary();
+ const NdbDictionary::Table * pTab = pDict->getTable(tab->m_name.c_str());
+
+ if (pTab == 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ bool ordered = (rand() >> 16) & 1;
+ bool stored = (rand() >> 16) & 1;
+
+ Uint32 type = ordered ?
+ NdbDictionary::Index::OrderedIndex :
+ NdbDictionary::Index::UniqueHashIndex;
+
+ char buf[255];
+ BaseString::snprintf(buf, sizeof(buf), "%s-%s",
+ pTab->getName(),
+ ordered ? "OI" : "UI");
+
+ if (pDict->getIndex(buf, pTab->getName()))
+ {
+ // Index exists...let it be ok
+ return NDBT_OK;
+ }
+
+ ndbout_c("create index %s", buf);
+ NdbDictionary::Index idx0;
+ idx0.setName(buf);
+ idx0.setType((NdbDictionary::Index::Type)type);
+ idx0.setTable(pTab->getName());
+ idx0.setStoredIndex(ordered ? false : stored);
+
+ for (Uint32 i = 0; i<pTab->getNoOfColumns(); i++)
+ {
+ if (pTab->getColumn(i)->getPrimaryKey())
+ idx0.addColumn(pTab->getColumn(i)->getName());
+ }
+ if (pDict->createIndex(idx0))
+ {
+ ndbout << pDict->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+ Obj *obj = new Obj;
+ obj->m_name.assign(buf);
+ obj->m_type = type;
+ obj->m_parent = tab;
+ m_objects.push_back(obj);
+
+ tab->m_dependant.push_back(obj);
+ return NDBT_OK;
+}
+
+int
+RandSchemaOp::drop_obj(Ndb* ndb, Obj* obj)
+{
+ NdbDictionary::Dictionary* pDict = ndb->getDictionary();
+
+ if (obj->m_type == NdbDictionary::Object::UserTable)
+ {
+ ndbout_c("drop table %s", obj->m_name.c_str());
+ /**
+ * Drop of table automatically drops all indexes
+ */
+ if (pDict->dropTable(obj->m_name.c_str()))
+ {
+ return NDBT_FAILED;
+ }
+ while(obj->m_dependant.size())
+ {
+ remove_obj(obj->m_dependant[0]);
+ }
+ remove_obj(obj);
+ }
+ else if (obj->m_type == NdbDictionary::Object::UniqueHashIndex ||
+ obj->m_type == NdbDictionary::Object::OrderedIndex)
+ {
+ ndbout_c("drop index %s", obj->m_name.c_str());
+ if (pDict->dropIndex(obj->m_name.c_str(),
+ obj->m_parent->m_name.c_str()))
+ {
+ return NDBT_FAILED;
+ }
+ remove_obj(obj);
+ }
+ return NDBT_OK;
+}
+
+void
+RandSchemaOp::remove_obj(Obj* obj)
+{
+ Uint32 i;
+ if (obj->m_parent)
+ {
+ bool found = false;
+ for (i = 0; i<obj->m_parent->m_dependant.size(); i++)
+ {
+ if (obj->m_parent->m_dependant[i] == obj)
+ {
+ found = true;
+ obj->m_parent->m_dependant.erase(i);
+ break;
+ }
+ }
+ assert(found);
+ }
+
+ {
+ bool found = false;
+ for (i = 0; i<m_objects.size(); i++)
+ {
+ if (m_objects[i] == obj)
+ {
+ found = true;
+ m_objects.erase(i);
+ break;
+ }
+ }
+ assert(found);
+ }
+ delete obj;
+}
+
+int
+RandSchemaOp::validate(Ndb* ndb)
+{
+ NdbDictionary::Dictionary* pDict = ndb->getDictionary();
+ for (Uint32 i = 0; i<m_objects.size(); i++)
+ {
+ if (m_objects[i]->m_type == NdbDictionary::Object::UserTable)
+ {
+ const NdbDictionary::Table* tab2 =
+ pDict->getTable(m_objects[i]->m_name.c_str());
+ HugoTransactions trans(*tab2);
+ trans.scanUpdateRecords(ndb, 1000);
+ trans.clearTable(ndb);
+ trans.loadTable(ndb, 1000);
+ }
+ }
+
+ return NDBT_OK;
+}
+
+/*
+ SystemTable = 1, ///< System table
+ UserTable = 2, ///< User table (may be temporary)
+ UniqueHashIndex = 3, ///< Unique un-ordered hash index
+ OrderedIndex = 6, ///< Non-unique ordered index
+ HashIndexTrigger = 7, ///< Index maintenance, internal
+ IndexTrigger = 8, ///< Index maintenance, internal
+ SubscriptionTrigger = 9,///< Backup or replication, internal
+ ReadOnlyConstraint = 10,///< Trigger, internal
+ Tablespace = 20, ///< Tablespace
+ LogfileGroup = 21, ///< Logfile group
+ Datafile = 22, ///< Datafile
+ Undofile = 23 ///< Undofile
+*/
+
+int
+RandSchemaOp::cleanup(Ndb* ndb)
+{
+ Int32 i;
+ for (i = m_objects.size() - 1; i >= 0; i--)
+ {
+ switch(m_objects[i]->m_type){
+ case NdbDictionary::Object::UniqueHashIndex:
+ case NdbDictionary::Object::OrderedIndex:
+ if (drop_obj(ndb, m_objects[i]))
+ return NDBT_FAILED;
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ for (i = m_objects.size() - 1; i >= 0; i--)
+ {
+ switch(m_objects[i]->m_type){
+ case NdbDictionary::Object::UserTable:
+ if (drop_obj(ndb, m_objects[i]))
+ return NDBT_FAILED;
+ break;
+ default:
+ break;
+ }
+ }
+
+ assert(m_objects.size() == 0);
+ return NDBT_OK;
+}
+
+int
+runDictRestart(NDBT_Context* ctx, NDBT_Step* step)
+{
+ Ndb* pNdb = GETNDB(step);
+ int loops = ctx->getNumLoops();
+
+ NdbMixRestarter res;
+
+ RandSchemaOp dict;
+ if (res.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ if (res.init(ctx, step))
+ return NDBT_FAILED;
+
+ for (Uint32 i = 0; i<loops; i++)
+ {
+ for (Uint32 j = 0; j<10; j++)
+ if (dict.schema_op(pNdb))
+ return NDBT_FAILED;
+
+ if (res.dostep(ctx, step))
+ return NDBT_FAILED;
+
+ if (dict.validate(pNdb))
+ return NDBT_FAILED;
+ }
+
+ if (res.finish(ctx, step))
+ return NDBT_FAILED;
+
+ if (dict.validate(pNdb))
+ return NDBT_FAILED;
+
+ if (dict.cleanup(pNdb))
+ return NDBT_FAILED;
+
+ return NDBT_OK;
+}
+
NDBT_TESTSUITE(testDict);
TESTCASE("CreateAndDrop",
"Try to create and drop the table loop number of times\n"){
@@ -2478,6 +2921,14 @@
STEP(runTableAddAttrsDuring);
STEP(runUseTableUntilStopped2);
FINALIZER(runDropTheTable);
+}
+TESTCASE("Bug21755",
+ ""){
+ INITIALIZER(runBug21755);
+}
+TESTCASE("DictRestart",
+ ""){
+ INITIALIZER(runDictRestart);
}
NDBT_TESTSUITE_END(testDict);
| Thread |
|---|
| • bk commit into 5.1 tree (jonas:1.2538) | jonas | 17 Apr |