summaryrefslogtreecommitdiff
path: root/storage/ndb/test/ndbapi/testDict.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/test/ndbapi/testDict.cpp')
-rw-r--r--storage/ndb/test/ndbapi/testDict.cpp1680
1 files changed, 1680 insertions, 0 deletions
diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp
new file mode 100644
index 00000000000..5240735dcc6
--- /dev/null
+++ b/storage/ndb/test/ndbapi/testDict.cpp
@@ -0,0 +1,1680 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbRestarter.hpp>
+#include <Vector.hpp>
+#include <signaldata/DumpStateOrd.hpp>
+#include <../../include/kernel/ndb_limits.h>
+#include <random.h>
+#include <NdbAutoPtr.hpp>
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ break; }
+
+#define CHECK2(b, c) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << ": " << c << endl; \
+ result = NDBT_FAILED; \
+ goto end; }
+
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+
+int runCreateInvalidTables(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+
+ char failTabName[256];
+
+ for (int i = 0; i < 10; i++){
+ BaseString::snprintf(failTabName, 256, "F%d", i);
+
+ const NdbDictionary::Table* pFailTab = NDBT_Tables::getTable(failTabName);
+ if (pFailTab != NULL){
+ ndbout << "|- " << failTabName << endl;
+
+ // Try to create table in db
+ if (pFailTab->createTableInDb(pNdb) == 0){
+ ndbout << failTabName << " created, this was not expected"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, failTabName) ;
+ if (pTab2 != NULL){
+ ndbout << failTabName << " was found in DB, this was not expected"<< endl;
+ result = NDBT_FAILED;
+ if (pFailTab->equal(*pTab2) == true){
+ ndbout << "It was equal" << endl;
+ } else {
+ ndbout << "It was not equal" << endl;
+ }
+ int records = 1000;
+ HugoTransactions hugoTrans(*pTab2);
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ ndbout << "It can NOT be loaded" << endl;
+ } else{
+ ndbout << "It can be loaded" << endl;
+
+ UtilTransactions utilTrans(*pTab2);
+ if (utilTrans.clearTable(pNdb, records, 64) != 0){
+ ndbout << "It can NOT be cleared" << endl;
+ } else{
+ ndbout << "It can be cleared" << endl;
+ }
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) == -1){
+ ndbout << "It can NOT be dropped" << endl;
+ } else {
+ ndbout << "It can be dropped" << endl;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ return NDBT_OK;
+}
+
+int runDropTheTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ pNdb->getDictionary()->dropTable(pTab->getName());
+
+ return NDBT_OK;
+}
+
+int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ const char* tabName = "TRANSACTION"; //Use a util table
+
+ const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
+ if (pTab != NULL){
+ ndbout << "|- " << tabName << endl;
+
+ // Verify that table is not in db
+ if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
+ ndbout << tabName << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) == 0){
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
+ ndbout << tabName << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ return result;
+}
+
+int runDropTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ const char* tabName = "TRANSACTION"; //Use a util table
+
+ const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(pNdb, tabName);
+ if (pTab != NULL){
+ ndbout << "|- TRANSACTION" << endl;
+
+ // Try to drop table in db
+ if (pNdb->getDictionary()->dropTable(pTab->getName()) == -1){
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
+ ndbout << tabName << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ return result;
+
+}
+
+
+int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int loops = ctx->getNumLoops();
+ int i = 0;
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ while (i < loops){
+
+ ndbout << i << ": ";
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName())){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ ndbout << pTab3->getName() << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+
+ return NDBT_OK;
+}
+
+int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int i = 0;
+
+ NdbRestarter restarter;
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ int result;
+ do { CHECK(0); } while (0);
+ g_err << "Unable to change timebetween LCP" << endl;
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ while (i < loops){
+ ndbout << i << ": ";
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ HugoTransactions hugoTrans(*pTab2);
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ int count = 0;
+ UtilTransactions utilTrans(*pTab2);
+ if (utilTrans.selectCount(pNdb, 64, &count) != 0){
+ return NDBT_FAILED;
+ }
+ if (count != records){
+ ndbout << count <<" != "<<records << endl;
+ return NDBT_FAILED;
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ ndbout << pTab3->getName() << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+
+ i++;
+ }
+
+ return NDBT_OK;
+}
+
+int runFillTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.fillTable(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ int records = ctx->getNumRecords();
+
+ UtilTransactions utilTrans(*ctx->getTab());
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int i = 0;
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ while (i < loops && result == NDBT_OK){
+ ndbout << i << ": " << endl;
+ // Try to create table in db
+
+ Ndb* pNdb = GETNDB(step);
+ g_debug << "Creating table" << endl;
+
+ if (pTab->createTableInDb(pNdb) != 0){
+ g_err << "createTableInDb failed" << endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ g_debug << "Verifying creation of table" << endl;
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ g_err << pTab->getName() << " was not found in DB"<< endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ NdbSleep_MilliSleep(3000);
+
+ g_debug << "Dropping table" << endl;
+
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ g_err << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ g_debug << "Verifying dropping of table" << endl;
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ g_err << pTab3->getName() << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+ i++;
+ }
+ ctx->stopTest();
+
+ return result;
+}
+
+
+int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ while (ctx->isTestStopped() == false) {
+ // g_info << i++ << ": ";
+
+
+ // Delete and recreate Ndb object
+ // Otherwise you always get Invalid Schema Version
+ // It would be a nice feature to remove this two lines
+ //step->tearDown();
+ //step->setUp();
+
+ Ndb* pNdb = GETNDB(step);
+
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL)
+ continue;
+
+ int res;
+ HugoTransactions hugoTrans(*pTab2);
+ if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
+ NdbError err = pNdb->getNdbError(res);
+ if(err.classification == NdbError::SchemaError){
+ pNdb->getDictionary()->invalidateTable(pTab->getName());
+ }
+ continue;
+ }
+
+ UtilTransactions utilTrans(*pTab2);
+ if ((res = utilTrans.clearTable(pNdb, records)) != 0){
+ NdbError err = pNdb->getNdbError(res);
+ if(err.classification == NdbError::SchemaError){
+ pNdb->getDictionary()->invalidateTable(pTab->getName());
+ }
+ continue;
+ }
+ }
+ g_info << endl;
+ return NDBT_OK;
+}
+
+
+int runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step){
+ int failures = 0;
+ char tabName[256];
+ int numTables = ctx->getProperty("tables", 1000);
+ Ndb* pNdb = GETNDB(step);
+
+ for (int i = 0; i < numTables && failures < 5; i++){
+ BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << tabName << endl;
+
+ // Set new name for T1
+ NdbDictionary::Table newTab(* pTab);
+ newTab.setName(tabName);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ ndbout << tabName << " coult not be created"<< endl;
+ failures++;
+ continue;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
+ if (pTab3 == NULL){
+ ndbout << tabName << " was not found in DB"<< endl;
+ failures++;
+ continue;
+ }
+
+ if (pTab->equal(*pTab3) == false){
+ ndbout << "It was not equal" << endl;
+ failures++;
+ }
+
+ int records = 1000;
+ HugoTransactions hugoTrans(*pTab3);
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ ndbout << "It can NOT be loaded" << endl;
+ } else{
+ ndbout << "It can be loaded" << endl;
+
+ UtilTransactions utilTrans(*pTab3);
+ if (utilTrans.clearTable(pNdb, records, 64) != 0){
+ ndbout << "It can NOT be cleared" << endl;
+ } else{
+ ndbout << "It can be cleared" << endl;
+ }
+ }
+
+ }
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+ // HURRAAA!
+ return NDBT_OK;
+}
+
+int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ char tabName[256];
+ int numTables = ctx->getProperty("tables", 1000);
+ Ndb* pNdb = GETNDB(step);
+
+ for (int i = 0; i < numTables; i++){
+ BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
+ if (pTab3 == NULL){
+ ndbout << tabName << " was not found in DB"<< endl;
+ continue;
+ }
+
+
+ // Try to drop table in db
+ if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
+ ndbout << tabName << " coult not be dropped"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ }
+ return result;
+}
+
+int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ int fragTtype = ctx->getProperty("FragmentType");
+ Ndb* pNdb = GETNDB(step);
+ int result = NDBT_OK;
+ NdbRestarter restarter;
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ pNdb->getDictionary()->dropTable(pTab->getName());
+
+ NdbDictionary::Table newTab(* pTab);
+ // Set fragment type for table
+ newTab.setFragmentType((NdbDictionary::Object::FragmentType)fragTtype);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ ndbout << newTab.getName() << " could not be created"
+ << ", fragmentType = "<<fragTtype <<endl;
+ ndbout << pNdb->getDictionary()->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName()) ;
+ if (pTab3 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+
+ }
+
+ if (pTab3->getFragmentType() != fragTtype){
+ ndbout << pTab->getName() << " fragmentType error "<< endl;
+ result = NDBT_FAILED;
+ goto drop_the_tab;
+ }
+/**
+ This test does not work since fragmentation is
+ decided by the kernel, hence the fragementation
+ attribute on the column will differ
+
+ if (newTab.equal(*pTab3) == false){
+ ndbout << "It was not equal" << endl;
+ result = NDBT_FAILED;
+ goto drop_the_tab;
+ }
+*/
+ do {
+
+ HugoTransactions hugoTrans(*pTab3);
+ UtilTransactions utilTrans(*pTab3);
+ int count;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ // restart all
+ ndbout << "Restarting cluster" << endl;
+ CHECK(restarter.restartAll() == 0);
+ int timeout = 120;
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ // Verify content
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.clearTable(pNdb, records, 64) == 0);
+
+ } while(false);
+
+ drop_the_tab:
+
+ // Try to drop table in db
+ if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
+ ndbout << pTab3->getName() << " could not be dropped"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ return result;
+}
+
+
+int runTestTemporaryTables(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ Ndb* pNdb = GETNDB(step);
+ int i = 0;
+ NdbRestarter restarter;
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+
+ NdbDictionary::Table newTab(* pTab);
+ // Set table as temporary
+ newTab.setStoredTable(false);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ if (pTab2->getStoredTable() != false){
+ ndbout << pTab->getName() << " was not temporary in DB"<< endl;
+ result = NDBT_FAILED;
+ goto drop_the_tab;
+ }
+
+
+ while (i < loops && result == NDBT_OK){
+ ndbout << i << ": ";
+
+ HugoTransactions hugoTrans(*pTab2);
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+
+ int count = 0;
+ UtilTransactions utilTrans(*pTab2);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+
+ // restart all
+ ndbout << "Restarting cluster" << endl;
+ CHECK(restarter.restartAll() == 0);
+ int timeout = 120;
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+ CHECK(pNdb->waitUntilReady(timeout) == 0);
+
+ ndbout << "Verifying records..." << endl;
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+
+ i++;
+ }
+
+ drop_the_tab:
+
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ result = NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 != NULL){
+ ndbout << pTab3->getName() << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ }
+
+ return result;
+}
+
+int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ char tabName[256];
+ int minPkSize = 1;
+ ndbout << "minPkSize=" <<minPkSize<<endl;
+ int maxPkSize = MAX_KEY_SIZE_IN_WORDS * 4;
+ ndbout << "maxPkSize=" <<maxPkSize<<endl;
+ Ndb* pNdb = GETNDB(step);
+ int numRecords = ctx->getNumRecords();
+
+ for (int i = minPkSize; i < maxPkSize; i++){
+ BaseString::snprintf(tabName, 256, "TPK_%d", i);
+
+ int records = numRecords;
+ int max = ~0;
+ // Limit num records for small PKs
+ if (i == 1)
+ max = 99;
+ if (i == 2)
+ max = 999;
+ if (i == 3)
+ max = 9999;
+ if (records > max)
+ records = max;
+ ndbout << "records =" << records << endl;
+
+ if (pNdb->waitUntilReady(30) != 0){
+ // Db is not ready, return with failure
+ return NDBT_FAILED;
+ }
+
+ ndbout << "|- " << tabName << endl;
+
+ if (NDBT_Tables::createTable(pNdb, tabName) != 0){
+ ndbout << tabName << " could not be created"<< endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table exists in db
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
+ if (pTab3 == NULL){
+ g_err << tabName << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ // ndbout << *pTab3 << endl;
+
+ if (pTab3->equal(*NDBT_Tables::getTable(tabName)) == false){
+ g_err << "It was not equal" << endl;
+ return NDBT_FAILED;
+ }
+
+ do {
+ // Do it all
+ HugoTransactions hugoTrans(*pTab3);
+ UtilTransactions utilTrans(*pTab3);
+ int count;
+ CHECK(hugoTrans.loadTable(pNdb, records) == 0);
+ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == records);
+ CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
+ CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == (records/2));
+ CHECK(utilTrans.clearTable(pNdb, records) == 0);
+
+#if 0
+ // Fill table
+ CHECK(hugoTrans.fillTable(pNdb) == 0);
+ CHECK(utilTrans.clearTable2(pNdb, records) == 0);
+ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
+ CHECK(count == 0);
+#endif
+ } while(false);
+
+ // Drop table
+ if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
+ ndbout << "Failed to drop "<<pTab3->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+ }
+ return result;
+}
+
+int runStoreFrm(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+
+ Uint32 dataLen = (Uint32)myRandom48(MAX_FRM_DATA_SIZE);
+ // size_t dataLen = 10;
+ unsigned char data[MAX_FRM_DATA_SIZE];
+
+ char start = l + 248;
+ for(Uint32 i = 0; i < dataLen; i++){
+ data[i] = start;
+ start++;
+ }
+#if 0
+ ndbout << "dataLen="<<dataLen<<endl;
+ for (Uint32 i = 0; i < dataLen; i++){
+ unsigned char c = data[i];
+ ndbout << hex << c << ", ";
+ }
+ ndbout << endl;
+#endif
+
+ NdbDictionary::Table newTab(* pTab);
+ void* pData = &data;
+ newTab.setFrm(pData, dataLen);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) != 0){
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ g_err << pTab->getName() << " was not found in DB"<< endl;
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ const void* pData2 = pTab2->getFrmData();
+ Uint32 resultLen = pTab2->getFrmLength();
+ if (dataLen != resultLen){
+ g_err << "Length of data failure" << endl
+ << " expected = " << dataLen << endl
+ << " got = " << resultLen << endl;
+ result = NDBT_FAILED;
+ }
+
+ // Verfiy the frm data
+ if (memcmp(pData, pData2, resultLen) != 0){
+ g_err << "Wrong data recieved" << endl;
+ for (size_t i = 0; i < dataLen; i++){
+ unsigned char c = ((unsigned char*)pData2)[i];
+ g_err << hex << c << ", ";
+ }
+ g_err << endl;
+ result = NDBT_FAILED;
+ }
+
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ g_err << "It can NOT be dropped" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+
+ return result;
+}
+
+int runStoreFrmError(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+
+ const Uint32 dataLen = MAX_FRM_DATA_SIZE + 10;
+ unsigned char data[dataLen];
+
+ char start = l + 248;
+ for(Uint32 i = 0; i < dataLen; i++){
+ data[i] = start;
+ start++;
+ }
+#if 0
+ ndbout << "dataLen="<<dataLen<<endl;
+ for (Uint32 i = 0; i < dataLen; i++){
+ unsigned char c = data[i];
+ ndbout << hex << c << ", ";
+ }
+ ndbout << endl;
+#endif
+
+ NdbDictionary::Table newTab(* pTab);
+
+ void* pData = &data;
+ newTab.setFrm(pData, dataLen);
+
+ // Try to create table in db
+ if (newTab.createTableInDb(pNdb) == 0){
+ result = NDBT_FAILED;
+ continue;
+ }
+
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 != NULL){
+ g_err << pTab->getName() << " was found in DB"<< endl;
+ result = NDBT_FAILED;
+ if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
+ g_err << "It can NOT be dropped" << endl;
+ result = NDBT_FAILED;
+ }
+
+ continue;
+ }
+
+ }
+
+ return result;
+}
+
+int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary::Table* pTab2){
+ // Verify that getPrimaryKey only returned true for primary keys
+ for (int i = 0; i < pTab2->getNoOfColumns(); i++){
+ const NdbDictionary::Column* col = pTab->getColumn(i);
+ const NdbDictionary::Column* col2 = pTab2->getColumn(i);
+ if (col->getPrimaryKey() != col2->getPrimaryKey()){
+ g_err << "col->getPrimaryKey() != col2->getPrimaryKey()" << endl;
+ return NDBT_FAILED;
+ }
+ }
+
+ if (!pTab->equal(*pTab2)){
+ g_err << "equal failed" << endl;
+ g_info << *pTab;
+ g_info << *pTab2;
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ ndbout << "|- " << pTab->getName() << endl;
+ g_info << *pTab;
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ int result = NDBT_OK;
+ if (verifyTablesAreEqual(pTab, pTab2) != NDBT_OK)
+ result = NDBT_FAILED;
+
+
+#if 0
+ // Create an index on the table and see what
+ // the function returns now
+ char name[200];
+ sprintf(name, "%s_X007", pTab->getName());
+ NDBT_Index* pInd = new NDBT_Index(name);
+ pInd->setTable(pTab->getName());
+ pInd->setType(NdbDictionary::Index::UniqueHashIndex);
+ // pInd->setLogging(false);
+ for (int i = 0; i < 2; i++){
+ const NDBT_Attribute* pAttr = pTab->getAttribute(i);
+ pInd->addAttribute(*pAttr);
+ }
+ g_info << "Create index:" << endl << *pInd;
+ if (pInd->createIndexInDb(pNdb, false) != 0){
+ result = NDBT_FAILED;
+ }
+ delete pInd;
+
+ const NdbDictionary::Table* pTab3 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab3 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+
+ if (verifyTablesAreEqual(pTab, pTab3) != NDBT_OK)
+ result = NDBT_FAILED;
+ if (verifyTablesAreEqual(pTab2, pTab3) != NDBT_OK)
+ result = NDBT_FAILED;
+#endif
+
+#if 0
+ if (pTab2->getDictionary()->dropTable(pNdb) != 0){
+ ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is not in db
+ const NdbDictionary::Table* pTab4 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab4 != NULL){
+ ndbout << pTab4->getName() << " was found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+#endif
+
+ return result;
+}
+
+struct ErrorCodes { int error_id; bool crash;};
+ErrorCodes
+NF_codes[] = {
+ {6003, true},
+ {6004, true},
+ //,6005, true,
+ {7173, false}
+};
+
+int
+runNF1(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+ if(restarter.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ myRandom48Init(NdbTick_CurrentMillisecond());
+
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ dict->dropTable(pTab->getName());
+
+ int result = NDBT_OK;
+
+ /**
+ * Need to run LCP at high rate otherwise
+ * packed replicas become "to many"
+ */
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ do { CHECK(0); } while(0);
+ g_err << "Failed to set LCP to min value" << endl;
+ return NDBT_FAILED;
+ }
+
+ const int loops = ctx->getNumLoops();
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ const int sz = sizeof(NF_codes)/sizeof(NF_codes[0]);
+ for(int i = 0; i<sz; i++){
+ int rand = myRandom48(restarter.getNumDbNodes());
+ int nodeId = restarter.getRandomNotMasterNodeId(rand);
+ struct ErrorCodes err_struct = NF_codes[i];
+ int error = err_struct.error_id;
+ bool crash = err_struct.crash;
+
+ g_info << "NF1: node = " << nodeId << " error code = " << error << endl;
+
+ int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 3};
+
+ CHECK2(restarter.dumpStateOneNode(nodeId, val2, 2) == 0,
+ "failed to set RestartOnErrorInsert");
+
+ CHECK2(restarter.insertErrorInNode(nodeId, error) == 0,
+ "failed to set error insert");
+
+ CHECK2(dict->createTable(* pTab) == 0,
+ "failed to create table");
+
+ if (crash) {
+ CHECK2(restarter.waitNodesNoStart(&nodeId, 1) == 0,
+ "waitNodesNoStart failed");
+
+ if(myRandom48(100) > 50){
+ CHECK2(restarter.startNodes(&nodeId, 1) == 0,
+ "failed to start node");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+
+ CHECK2(dict->dropTable(pTab->getName()) == 0,
+ "drop table failed");
+ } else {
+ CHECK2(dict->dropTable(pTab->getName()) == 0,
+ "drop table failed");
+
+ CHECK2(restarter.startNodes(&nodeId, 1) == 0,
+ "failed to start node");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+ }
+
+ CHECK2(restarter.dumpStateOneNode(nodeId, &val, 1) == 0,
+ "Failed to set LCP to min value");
+ }
+ }
+ }
+ end:
+ dict->dropTable(pTab->getName());
+
+ return result;
+}
+
+#define APIERROR(error) \
+ { g_err << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
+ << error.code << ", msg: " << error.message << "." << endl; \
+ }
+
+int
+runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){
+
+ Uint32 startvalues[5] = {256-2, 0, 256*256-2, ~0, 256*256*256-2};
+
+ int ret = NDBT_OK;
+
+ for (int jj = 0; jj < 5 && ret == NDBT_OK; jj++) {
+ char tabname[] = "AUTOINCTAB";
+ Uint32 startvalue = startvalues[jj];
+
+ NdbDictionary::Table myTable;
+ NdbDictionary::Column myColumn;
+
+ Ndb* myNdb = GETNDB(step);
+ NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
+
+
+ if (myDict->getTable(tabname) != NULL) {
+ g_err << "NDB already has example table: " << tabname << endl;
+ APIERROR(myNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ myTable.setName(tabname);
+
+ myColumn.setName("ATTR1");
+ myColumn.setType(NdbDictionary::Column::Unsigned);
+ myColumn.setLength(1);
+ myColumn.setPrimaryKey(true);
+ myColumn.setNullable(false);
+ myColumn.setAutoIncrement(true);
+ if (startvalue != ~0) // check that default value starts with 1
+ myColumn.setAutoIncrementInitialValue(startvalue);
+ myTable.addColumn(myColumn);
+
+ if (myDict->createTable(myTable) == -1) {
+ g_err << "Failed to create table " << tabname << endl;
+ APIERROR(myNdb->getNdbError());
+ return NDBT_FAILED;
+ }
+
+
+ if (startvalue == ~0) // check that default value starts with 1
+ startvalue = 1;
+
+ for (int i = 0; i < 16; i++) {
+
+ Uint64 value = myNdb->getAutoIncrementValue(tabname, 1);
+
+ if (value != (startvalue+i)) {
+ g_err << "value = " << value << " expected " << startvalue+i << endl;;
+ APIERROR(myNdb->getNdbError());
+ // ret = NDBT_FAILED;
+ // break;
+ }
+ }
+
+ if (myDict->dropTable(tabname) == -1) {
+ g_err << "Failed to drop table " << tabname << endl;
+ APIERROR(myNdb->getNdbError());
+ ret = NDBT_FAILED;
+ }
+ }
+
+ return ret;
+}
+
+int
+runTableRename(NDBT_Context* ctx, NDBT_Step* step){
+
+ int result = NDBT_OK;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ int records = ctx->getNumRecords();
+ const int loops = ctx->getNumLoops();
+
+ ndbout << "|- " << ctx->getTab()->getName() << endl;
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ // Load table
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Rename table
+ BaseString pTabName(pTab->getName());
+ BaseString pTabNewName(pTabName);
+ pTabNewName.append("xx");
+
+ const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
+ if (oldTable) {
+ NdbDictionary::Table newTable = *oldTable;
+ newTable.setName(pTabNewName.c_str());
+ CHECK2(dict->alterTable(newTable) == 0,
+ "TableRename failed");
+ }
+ else {
+ result = NDBT_FAILED;
+ }
+
+ // Verify table contents
+ NdbDictionary::Table pNewTab(pTabNewName.c_str());
+
+ UtilTransactions utilTrans(pNewTab);
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ continue;
+ }
+
+ // Drop table
+ dict->dropTable(pNewTab.getName());
+ }
+ end:
+
+ return result;
+}
+
+int
+runTableRenameNF(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+ if(restarter.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ int result = NDBT_OK;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ int records = ctx->getNumRecords();
+ const int loops = ctx->getNumLoops();
+
+ ndbout << "|- " << ctx->getTab()->getName() << endl;
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ // Load table
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ BaseString pTabName(pTab->getName());
+ BaseString pTabNewName(pTabName);
+ pTabNewName.append("xx");
+
+ const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
+ if (oldTable) {
+ NdbDictionary::Table newTable = *oldTable;
+ newTable.setName(pTabNewName.c_str());
+ CHECK2(dict->alterTable(newTable) == 0,
+ "TableRename failed");
+ }
+ else {
+ result = NDBT_FAILED;
+ }
+
+ // Restart one node at a time
+
+ /**
+ * Need to run LCP at high rate otherwise
+ * packed replicas become "to many"
+ */
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ do { CHECK(0); } while(0);
+ g_err << "Failed to set LCP to min value" << endl;
+ return NDBT_FAILED;
+ }
+
+ const int numNodes = restarter.getNumDbNodes();
+ for(int i = 0; i<numNodes; i++){
+ int nodeId = restarter.getDbNodeId(i);
+ int error = NF_codes[i].error_id;
+
+ g_info << "NF1: node = " << nodeId << " error code = " << error << endl;
+
+ CHECK2(restarter.restartOneDbNode(nodeId) == 0,
+ "failed to set restartOneDbNode");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+
+ }
+
+ // Verify table contents
+ NdbDictionary::Table pNewTab(pTabNewName.c_str());
+
+ UtilTransactions utilTrans(pNewTab);
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ continue;
+ }
+
+ // Drop table
+ dict->dropTable(pTabNewName.c_str());
+ }
+ end:
+ return result;
+}
+
+int
+runTableRenameSR(NDBT_Context* ctx, NDBT_Step* step){
+ NdbRestarter restarter;
+ if(restarter.getNumDbNodes() < 2)
+ return NDBT_OK;
+
+ int result = NDBT_OK;
+
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+ int records = ctx->getNumRecords();
+ const int loops = ctx->getNumLoops();
+
+ ndbout << "|- " << ctx->getTab()->getName() << endl;
+
+ for (int l = 0; l < loops && result == NDBT_OK ; l++){
+ // Rename table
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ if (pTab->createTableInDb(pNdb) != 0){
+ return NDBT_FAILED;
+ }
+
+ // Verify that table is in db
+ const NdbDictionary::Table* pTab2 =
+ NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
+ if (pTab2 == NULL){
+ ndbout << pTab->getName() << " was not found in DB"<< endl;
+ return NDBT_FAILED;
+ }
+ ctx->setTab(pTab2);
+
+ // Load table
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(pNdb, records) != 0){
+ return NDBT_FAILED;
+ }
+
+ BaseString pTabName(pTab->getName());
+ BaseString pTabNewName(pTabName);
+ pTabNewName.append("xx");
+
+ const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
+ if (oldTable) {
+ NdbDictionary::Table newTable = *oldTable;
+ newTable.setName(pTabNewName.c_str());
+ CHECK2(dict->alterTable(newTable) == 0,
+ "TableRename failed");
+ }
+ else {
+ result = NDBT_FAILED;
+ }
+
+ // Restart cluster
+
+ /**
+ * Need to run LCP at high rate otherwise
+ * packed replicas become "to many"
+ */
+ int val = DumpStateOrd::DihMinTimeBetweenLCP;
+ if(restarter.dumpStateAllNodes(&val, 1) != 0){
+ do { CHECK(0); } while(0);
+ g_err << "Failed to set LCP to min value" << endl;
+ return NDBT_FAILED;
+ }
+
+ CHECK2(restarter.restartAll() == 0,
+ "failed to set restartOneDbNode");
+
+ CHECK2(restarter.waitClusterStarted() == 0,
+ "waitClusterStarted failed");
+
+ // Verify table contents
+ NdbDictionary::Table pNewTab(pTabNewName.c_str());
+
+ UtilTransactions utilTrans(pNewTab);
+ if (utilTrans.clearTable(pNdb, records) != 0){
+ continue;
+ }
+
+ // Drop table
+ dict->dropTable(pTabNewName.c_str());
+ }
+ end:
+ return result;
+}
+
+static void
+f(const NdbDictionary::Column * col){
+ if(col == 0){
+ abort();
+ }
+}
+
+int
+runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
+ Vector<char*> cols;
+ Vector<const NdbDictionary::Table*> tabs;
+ int i;
+
+ Ndb* pNdb = GETNDB(step);
+
+ const Uint32 count = NDBT_Tables::getNumTables();
+ for (i=0; i < count; i++){
+ const NdbDictionary::Table * tab = NDBT_Tables::getTable(i);
+ pNdb->getDictionary()->createTable(* tab);
+
+ const NdbDictionary::Table * tab2 = pNdb->getDictionary()->getTable(tab->getName());
+
+ for(size_t j = 0; j<tab->getNoOfColumns(); j++){
+ cols.push_back((char*)tab2);
+ cols.push_back(strdup(tab->getColumn(j)->getName()));
+ }
+ }
+
+ const Uint32 times = 10000000;
+
+ ndbout_c("%d tables and %d columns",
+ NDBT_Tables::getNumTables(), cols.size()/2);
+
+ char ** tcols = cols.getBase();
+
+ srand(time(0));
+ Uint32 size = cols.size() / 2;
+ char ** columns = &cols[0];
+ Uint64 start = NdbTick_CurrentMillisecond();
+ for(i = 0; i<times; i++){
+ int j = 2 * (rand() % size);
+ const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j];
+ const char * col = tcols[j+1];
+ const NdbDictionary::Column* column = tab->getColumn(col);
+ f(column);
+ }
+ Uint64 stop = NdbTick_CurrentMillisecond();
+ stop -= start;
+
+ Uint64 per = stop;
+ per *= 1000;
+ per /= times;
+
+ ndbout_c("%d random getColumn(name) in %Ld ms -> %d us/get",
+ times, stop, per);
+
+ return NDBT_OK;
+}
+
+int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
+ static int acclst[] = { 3001 };
+ static int tuplst[] = { 4007, 4008, 4009, 4010, 4011, 4012 };
+ static int tuxlst[] = { 12001, 12002, 12003, 12004, 12005, 12006 };
+ static unsigned acccnt = sizeof(acclst)/sizeof(acclst[0]);
+ static unsigned tupcnt = sizeof(tuplst)/sizeof(tuplst[0]);
+ static unsigned tuxcnt = sizeof(tuxlst)/sizeof(tuxlst[0]);
+
+ NdbRestarter restarter;
+ int nodeId = restarter.getMasterNodeId();
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+ NdbDictionary::Table tab(*ctx->getTab());
+ tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
+
+ // ordered index on first few columns
+ NdbDictionary::Index idx("X");
+ idx.setTable(tab.getName());
+ idx.setType(NdbDictionary::Index::OrderedIndex);
+ idx.setLogging(false);
+ for (int i_hate_broken_compilers = 0;
+ i_hate_broken_compilers < 3 &&
+ i_hate_broken_compilers < tab.getNoOfColumns();
+ i_hate_broken_compilers++) {
+ idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
+ }
+
+ const int loops = ctx->getNumLoops();
+ int result = NDBT_OK;
+ (void)pDic->dropTable(tab.getName());
+
+ for (int l = 0; l < loops; l++) {
+ for (unsigned i0 = 0; i0 < acccnt; i0++) {
+ unsigned j = (l == 0 ? i0 : myRandom48(acccnt));
+ int errval = acclst[j];
+ g_info << "insert error node=" << nodeId << " value=" << errval << endl;
+ CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
+ "failed to set error insert");
+ CHECK2(pDic->createTable(tab) != 0,
+ "failed to fail after error insert " << errval);
+ CHECK2(pDic->createTable(tab) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->dropTable(tab.getName()) == 0,
+ pDic->getNdbError());
+ }
+ for (unsigned i1 = 0; i1 < tupcnt; i1++) {
+ unsigned j = (l == 0 ? i1 : myRandom48(tupcnt));
+ int errval = tuplst[j];
+ g_info << "insert error node=" << nodeId << " value=" << errval << endl;
+ CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
+ "failed to set error insert");
+ CHECK2(pDic->createTable(tab) != 0,
+ "failed to fail after error insert " << errval);
+ CHECK2(pDic->createTable(tab) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->dropTable(tab.getName()) == 0,
+ pDic->getNdbError());
+ }
+ for (unsigned i2 = 0; i2 < tuxcnt; i2++) {
+ unsigned j = (l == 0 ? i2 : myRandom48(tuxcnt));
+ int errval = tuxlst[j];
+ g_info << "insert error node=" << nodeId << " value=" << errval << endl;
+ CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
+ "failed to set error insert");
+ CHECK2(pDic->createTable(tab) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->createIndex(idx) != 0,
+ "failed to fail after error insert " << errval);
+ CHECK2(pDic->createIndex(idx) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->dropTable(tab.getName()) == 0,
+ pDic->getNdbError());
+ }
+ }
+end:
+ return result;
+}
+
+NDBT_TESTSUITE(testDict);
+TESTCASE("CreateAndDrop",
+ "Try to create and drop the table loop number of times\n"){
+ INITIALIZER(runCreateAndDrop);
+}
+TESTCASE("CreateAndDropWithData",
+ "Try to create and drop the table when it's filled with data\n"
+ "do this loop number of times\n"){
+ INITIALIZER(runCreateAndDropWithData);
+}
+TESTCASE("CreateAndDropDuring",
+ "Try to create and drop the table when other thread is using it\n"
+ "do this loop number of times\n"){
+ STEP(runCreateAndDropDuring);
+ STEP(runUseTableUntilStopped);
+}
+TESTCASE("CreateInvalidTables",
+ "Try to create the invalid tables we have defined\n"){
+ INITIALIZER(runCreateInvalidTables);
+}
+TESTCASE("CreateTableWhenDbIsFull",
+ "Try to create a new table when db already is full\n"){
+ INITIALIZER(runCreateTheTable);
+ INITIALIZER(runFillTable);
+ INITIALIZER(runCreateTableWhenDbIsFull);
+ INITIALIZER(runDropTableWhenDbIsFull);
+ FINALIZER(runDropTheTable);
+}
+TESTCASE("FragmentTypeSingle",
+ "Create the table with fragment type Single\n"){
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragSingle);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("FragmentTypeAllSmall",
+ "Create the table with fragment type AllSmall\n"){
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllSmall);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("FragmentTypeAllMedium",
+ "Create the table with fragment type AllMedium\n"){
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllMedium);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("FragmentTypeAllLarge",
+ "Create the table with fragment type AllLarge\n"){
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllLarge);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("TemporaryTables",
+ "Create the table as temporary and make sure it doesn't\n"
+ "contain any data when system is restarted\n"){
+ INITIALIZER(runTestTemporaryTables);
+}
+TESTCASE("CreateMaxTables",
+ "Create tables until db says that it can't create any more\n"){
+ TC_PROPERTY("tables", 1000);
+ INITIALIZER(runCreateMaxTables);
+ FINALIZER(runDropMaxTables);
+}
+TESTCASE("PkSizes",
+ "Create tables with all different primary key sizes.\n"\
+ "Test all data operations insert, update, delete etc.\n"\
+ "Drop table."){
+ INITIALIZER(runPkSizes);
+}
+TESTCASE("StoreFrm",
+ "Test that a frm file can be properly stored as part of the\n"
+ "data in Dict."){
+ INITIALIZER(runStoreFrm);
+}
+TESTCASE("GetPrimaryKey",
+ "Test the function NdbDictionary::Column::getPrimaryKey\n"
+ "It should return true only if the column is part of \n"
+ "the primary key in the table"){
+ INITIALIZER(runGetPrimaryKey);
+}
+TESTCASE("StoreFrmError",
+ "Test that a frm file with too long length can't be stored."){
+ INITIALIZER(runStoreFrmError);
+}
+TESTCASE("NF1",
+ "Test that create table can handle NF (not master)"){
+ INITIALIZER(runNF1);
+}
+TESTCASE("TableRename",
+ "Test basic table rename"){
+ INITIALIZER(runTableRename);
+}
+TESTCASE("TableRenameNF",
+ "Test that table rename can handle node failure"){
+ INITIALIZER(runTableRenameNF);
+}
+TESTCASE("TableRenameSR",
+ "Test that table rename can handle system restart"){
+ INITIALIZER(runTableRenameSR);
+}
+TESTCASE("DictionaryPerf",
+ ""){
+ INITIALIZER(runTestDictionaryPerf);
+}
+TESTCASE("FailAddFragment",
+ "Fail add fragment or attribute in ACC or TUP or TUX\n"){
+ INITIALIZER(runFailAddFragment);
+}
+NDBT_TESTSUITE_END(testDict);
+
+int main(int argc, const char** argv){
+ ndb_init();
+ // Tables should not be auto created
+ testDict.setCreateTable(false);
+ myRandom48Init(NdbTick_CurrentMillisecond());
+ return testDict.execute(argc, argv);
+}