mariadb/storage/ndb/test/ndbapi/testDict.cpp
jonas@perch.ndb.mysql.com f7115f126b Merge perch.ndb.mysql.com:/home/jonas/src/51-telco-gca
into  perch.ndb.mysql.com:/home/jonas/src/mysql-5.1-new-ndb
2007-04-17 16:50:08 +02:00

2718 lines
73 KiB
C++

/* 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; version 2 of the License.
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>
#include <NdbMixRestarter.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 (NDBT_Tables::createTable(pNdb, pTab->getName()) != 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 (NDBT_Tables::createTable(pNdb, pTab->getName()) == 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 (NDBT_Tables::createTable(pNdb, pTab->getName()) != 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 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++;
}
for (Uint32 i = 0; i<numTables; i++)
if (tabList[i])
pDic->dropTable(NDBT_Tables::getTable(i)->getName());
delete [] tabList;
return result;
}
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 (NDBT_Tables::createTable(pNdb, pTab->getName()) != 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 (NDBT_Tables::createTable(pNdb, pTab->getName()) != 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)
{
char tabName[256];
int numTables = ctx->getProperty("tables", 1000);
Ndb* pNdb = GETNDB(step);
NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
int i = 0;
for (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;
}
const NdbDictionary::Table* pTab = ctx->getTab();
//ndbout << "|- " << tabName << endl;
// Set new name for T1
NdbDictionary::Table newTab(* pTab);
newTab.setName(tabName);
// Drop any old (or try to)
(void)pDic->dropTable(newTab.getName());
// Try to create table in db
if (newTab.createTableInDb(pNdb) != 0) {
ndbout << tabName << " could not be created: "
<< pDic->getNdbError() << endl;
if (pDic->getNdbError().code == 707 ||
pDic->getNdbError().code == 708 ||
pDic->getNdbError().code == 826 ||
pDic->getNdbError().code == 827)
break;
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: "
<< pDic->getNdbError() << endl;
return NDBT_FAILED;
}
if (! newTab.equal(*pTab3)) {
ndbout << "It was not equal" << endl; abort();
return NDBT_FAILED;
}
int records = ctx->getNumRecords();
HugoTransactions hugoTrans(*pTab3);
if (hugoTrans.loadTable(pNdb, records) != 0) {
ndbout << "It can NOT be loaded" << endl;
return NDBT_FAILED;
}
UtilTransactions utilTrans(*pTab3);
if (utilTrans.clearTable(pNdb, records, 64) != 0) {
ndbout << "It can NOT be cleared" << endl;
return NDBT_FAILED;
}
}
if (pNdb->waitUntilReady(30) != 0) {
// Db is not ready, return with failure
return NDBT_FAILED;
}
ctx->setProperty("maxtables", i);
// HURRAAA!
return NDBT_OK;
}
int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step)
{
char tabName[256];
int numTables = ctx->getProperty("maxtables", (Uint32)0);
Ndb* pNdb = GETNDB(step);
NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
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: "
<< pDic->getNdbError() << endl;
return NDBT_FAILED;
}
// Try to drop table in db
if (pDic->dropTable(pTab3->getName()) != 0) {
ndbout << tabName << " could not be dropped: "
<< pDic->getNdbError() << endl;
return NDBT_FAILED;
}
}
return NDBT_OK;
}
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 << *(NDBT_Table*)pTab; // gcc-4.1.2
g_info << *(NDBT_Table*)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 << *(NDBT_Table*)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;
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");
}
}
}
}
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;
if (myNdb->getAutoIncrementValue(tabname, value, 1) == -1) {
g_err << "getAutoIncrementValue failed on " << tabname << endl;
APIERROR(myNdb->getNdbError());
return NDBT_FAILED;
}
else 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
runCreateLogfileGroup(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
NdbDictionary::LogfileGroup lg;
lg.setName("DEFAULT-LG");
lg.setUndoBufferSize(8*1024*1024);
int res;
res = pNdb->getDictionary()->createLogfileGroup(lg);
if(res != 0){
g_err << "Failed to create logfilegroup:"
<< endl << pNdb->getDictionary()->getNdbError() << endl;
return NDBT_FAILED;
}
NdbDictionary::Undofile uf;
uf.setPath("undofile01.dat");
uf.setSize(5*1024*1024);
uf.setLogfileGroup("DEFAULT-LG");
res = pNdb->getDictionary()->createUndofile(uf);
if(res != 0){
g_err << "Failed to create undofile:"
<< endl << pNdb->getDictionary()->getNdbError() << endl;
return NDBT_FAILED;
}
uf.setPath("undofile02.dat");
uf.setSize(5*1024*1024);
uf.setLogfileGroup("DEFAULT-LG");
res = pNdb->getDictionary()->createUndofile(uf);
if(res != 0){
g_err << "Failed to create undofile:"
<< endl << pNdb->getDictionary()->getNdbError() << endl;
return NDBT_FAILED;
}
return NDBT_OK;
}
int
runCreateTablespace(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
NdbDictionary::Tablespace lg;
lg.setName("DEFAULT-TS");
lg.setExtentSize(1024*1024);
lg.setDefaultLogfileGroup("DEFAULT-LG");
int res;
res = pNdb->getDictionary()->createTablespace(lg);
if(res != 0){
g_err << "Failed to create tablespace:"
<< endl << pNdb->getDictionary()->getNdbError() << endl;
return NDBT_FAILED;
}
NdbDictionary::Datafile uf;
uf.setPath("datafile01.dat");
uf.setSize(10*1024*1024);
uf.setTablespace("DEFAULT-TS");
res = pNdb->getDictionary()->createDatafile(uf);
if(res != 0){
g_err << "Failed to create datafile:"
<< endl << pNdb->getDictionary()->getNdbError() << endl;
return NDBT_FAILED;
}
return NDBT_OK;
}
int
runCreateDiskTable(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
NdbDictionary::Table tab = *ctx->getTab();
tab.setTablespaceName("DEFAULT-TS");
for(Uint32 i = 0; i<tab.getNoOfColumns(); i++)
if(!tab.getColumn(i)->getPrimaryKey())
tab.getColumn(i)->setStorageType(NdbDictionary::Column::StorageTypeDisk);
int res;
res = pNdb->getDictionary()->createTable(tab);
if(res != 0){
g_err << "Failed to create table:"
<< endl << pNdb->getDictionary()->getNdbError() << endl;
return NDBT_FAILED;
}
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;
}
// NFNR
// Restarter controls dict ops : 1-run 2-pause 3-stop
// synced by polling...
static bool
send_dict_ops_cmd(NDBT_Context* ctx, Uint32 cmd)
{
ctx->setProperty("DictOps_CMD", cmd);
while (1) {
if (ctx->isTestStopped())
return false;
if (ctx->getProperty("DictOps_ACK") == cmd)
break;
NdbSleep_MilliSleep(100);
}
return true;
}
static bool
recv_dict_ops_run(NDBT_Context* ctx)
{
while (1) {
if (ctx->isTestStopped())
return false;
Uint32 cmd = ctx->getProperty("DictOps_CMD");
ctx->setProperty("DictOps_ACK", cmd);
if (cmd == 1)
break;
if (cmd == 3)
return false;
NdbSleep_MilliSleep(100);
}
return true;
}
int
runRestarts(NDBT_Context* ctx, NDBT_Step* step)
{
static int errlst_master[] = { // non-crashing
7175, // send one fake START_PERMREF
0
};
static int errlst_node[] = {
7174, // crash before sending DICT_LOCK_REQ
7176, // pretend master does not support DICT lock
7121, // crash at receive START_PERMCONF
0
};
const uint errcnt_master = sizeof(errlst_master)/sizeof(errlst_master[0]);
const uint errcnt_node = sizeof(errlst_node)/sizeof(errlst_node[0]);
myRandom48Init(NdbTick_CurrentMillisecond());
NdbRestarter restarter;
int result = NDBT_OK;
const int loops = ctx->getNumLoops();
for (int l = 0; l < loops && result == NDBT_OK; l++) {
g_info << "1: === loop " << l << " ===" << endl;
// assuming 2-way replicated
int numnodes = restarter.getNumDbNodes();
CHECK(numnodes >= 1);
if (numnodes == 1)
break;
int masterNodeId = restarter.getMasterNodeId();
CHECK(masterNodeId != -1);
// for more complex cases need more restarter support methods
int nodeIdList[2] = { 0, 0 };
int nodeIdCnt = 0;
if (numnodes >= 2) {
int rand = myRandom48(numnodes);
int nodeId = restarter.getRandomNotMasterNodeId(rand);
CHECK(nodeId != -1);
nodeIdList[nodeIdCnt++] = nodeId;
}
if (numnodes >= 4 && myRandom48(2) == 0) {
int rand = myRandom48(numnodes);
int nodeId = restarter.getRandomNodeOtherNodeGroup(nodeIdList[0], rand);
CHECK(nodeId != -1);
if (nodeId != masterNodeId)
nodeIdList[nodeIdCnt++] = nodeId;
}
g_info << "1: master=" << masterNodeId << " nodes=" << nodeIdList[0] << "," << nodeIdList[1] << endl;
const uint timeout = 60; //secs for node wait
const unsigned maxsleep = 2000; //ms
bool NF_ops = ctx->getProperty("Restart_NF_ops");
uint NF_type = ctx->getProperty("Restart_NF_type");
bool NR_ops = ctx->getProperty("Restart_NR_ops");
bool NR_error = ctx->getProperty("Restart_NR_error");
g_info << "1: " << (NF_ops ? "run" : "pause") << " dict ops" << endl;
if (! send_dict_ops_cmd(ctx, NF_ops ? 1 : 2))
break;
NdbSleep_MilliSleep(myRandom48(maxsleep));
{
for (int i = 0; i < nodeIdCnt; i++) {
int nodeId = nodeIdList[i];
bool nostart = true;
bool abort = NF_type == 0 ? myRandom48(2) : (NF_type == 2);
bool initial = myRandom48(2);
char flags[40];
strcpy(flags, "flags: nostart");
if (abort)
strcat(flags, ",abort");
if (initial)
strcat(flags, ",initial");
g_info << "1: restart " << nodeId << " " << flags << endl;
CHECK(restarter.restartOneDbNode(nodeId, initial, nostart, abort) == 0);
}
}
g_info << "1: wait for nostart" << endl;
CHECK(restarter.waitNodesNoStart(nodeIdList, nodeIdCnt, timeout) == 0);
NdbSleep_MilliSleep(myRandom48(maxsleep));
int err_master = 0;
int err_node[2] = { 0, 0 };
if (NR_error) {
err_master = errlst_master[l % errcnt_master];
// limitation: cannot have 2 node restarts and crash_insert
// one node may die for real (NF during startup)
for (int i = 0; i < nodeIdCnt && nodeIdCnt == 1; i++) {
err_node[i] = errlst_node[l % errcnt_node];
// 7176 - no DICT lock protection
if (err_node[i] == 7176) {
g_info << "1: no dict ops due to error insert "
<< err_node[i] << endl;
NR_ops = false;
}
}
}
g_info << "1: " << (NR_ops ? "run" : "pause") << " dict ops" << endl;
if (! send_dict_ops_cmd(ctx, NR_ops ? 1 : 2))
break;
NdbSleep_MilliSleep(myRandom48(maxsleep));
g_info << "1: start nodes" << endl;
CHECK(restarter.startNodes(nodeIdList, nodeIdCnt) == 0);
if (NR_error) {
{
int err = err_master;
if (err != 0) {
g_info << "1: insert master error " << err << endl;
CHECK(restarter.insertErrorInNode(masterNodeId, err) == 0);
}
}
for (int i = 0; i < nodeIdCnt; i++) {
int nodeId = nodeIdList[i];
int err = err_node[i];
if (err != 0) {
g_info << "1: insert node " << nodeId << " error " << err << endl;
CHECK(restarter.insertErrorInNode(nodeId, err) == 0);
}
}
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
g_info << "1: wait cluster started" << endl;
CHECK(restarter.waitClusterStarted(timeout) == 0);
NdbSleep_MilliSleep(myRandom48(maxsleep));
g_info << "1: restart done" << endl;
}
g_info << "1: stop dict ops" << endl;
send_dict_ops_cmd(ctx, 3);
return result;
}
int
runDictOps(NDBT_Context* ctx, NDBT_Step* step)
{
myRandom48Init(NdbTick_CurrentMillisecond());
int result = NDBT_OK;
for (int l = 0; result == NDBT_OK; l++) {
if (! recv_dict_ops_run(ctx))
break;
g_info << "2: === loop " << l << " ===" << endl;
Ndb* pNdb = GETNDB(step);
NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
const NdbDictionary::Table* pTab = ctx->getTab();
//const char* tabName = pTab->getName(); //XXX what goes on?
char tabName[40];
strcpy(tabName, pTab->getName());
const unsigned long maxsleep = 100; //ms
g_info << "2: create table" << endl;
{
uint count = 0;
try_create:
count++;
if (pDic->createTable(*pTab) != 0) {
const NdbError err = pDic->getNdbError();
if (count == 1)
g_err << "2: " << tabName << ": create failed: " << err << endl;
if (err.code != 711) {
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
goto try_create;
}
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
g_info << "2: verify create" << endl;
const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
if (pTab2 == NULL) {
const NdbError err = pDic->getNdbError();
g_err << "2: " << tabName << ": verify create: " << err << endl;
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
// replace by the Retrieved table
pTab = pTab2;
// create indexes
const char** indlist = NDBT_Tables::getIndexes(tabName);
uint indnum = 0;
while (indlist != 0 && *indlist != 0) {
uint count = 0;
try_create_index:
count++;
if (count == 1)
g_info << "2: create index " << indnum << " " << *indlist << endl;
NdbDictionary::Index ind;
char indName[200];
sprintf(indName, "%s_X%u", tabName, indnum);
ind.setName(indName);
ind.setTable(tabName);
if (strcmp(*indlist, "UNIQUE") == 0) {
ind.setType(NdbDictionary::Index::UniqueHashIndex);
ind.setLogging(pTab->getLogging());
} else if (strcmp(*indlist, "ORDERED") == 0) {
ind.setType(NdbDictionary::Index::OrderedIndex);
ind.setLogging(false);
} else {
assert(false);
}
const char** indtemp = indlist;
while (*++indtemp != 0) {
ind.addColumn(*indtemp);
}
if (pDic->createIndex(ind) != 0) {
const NdbError err = pDic->getNdbError();
if (count == 1)
g_err << "2: " << indName << ": create failed: " << err << endl;
if (err.code != 711) {
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
goto try_create_index;
}
indlist = ++indtemp;
indnum++;
}
if (result == NDBT_FAILED)
break;
uint indcount = indnum;
int records = myRandom48(ctx->getNumRecords());
g_info << "2: load " << records << " records" << endl;
HugoTransactions hugoTrans(*pTab);
if (hugoTrans.loadTable(pNdb, records) != 0) {
// XXX get error code from hugo
g_err << "2: " << tabName << ": load failed" << endl;
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
// drop indexes
indnum = 0;
while (indnum < indcount) {
uint count = 0;
try_drop_index:
count++;
if (count == 1)
g_info << "2: drop index " << indnum << endl;
char indName[200];
sprintf(indName, "%s_X%u", tabName, indnum);
if (pDic->dropIndex(indName, tabName) != 0) {
const NdbError err = pDic->getNdbError();
if (count == 1)
g_err << "2: " << indName << ": drop failed: " << err << endl;
if (err.code != 711) {
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
goto try_drop_index;
}
indnum++;
}
if (result == NDBT_FAILED)
break;
g_info << "2: drop" << endl;
{
uint count = 0;
try_drop:
count++;
if (pDic->dropTable(tabName) != 0) {
const NdbError err = pDic->getNdbError();
if (count == 1)
g_err << "2: " << tabName << ": drop failed: " << err << endl;
if (err.code != 711) {
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
goto try_drop;
}
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
g_info << "2: verify drop" << endl;
const NdbDictionary::Table* pTab3 = pDic->getTable(tabName);
if (pTab3 != NULL) {
g_err << "2: " << 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 << "2: " << tabName << ": verify drop: " << err << endl;
result = NDBT_FAILED;
break;
}
NdbSleep_MilliSleep(myRandom48(maxsleep));
}
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"){
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"){
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);
INITIALIZER(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("CreateLogfileGroup", ""){
INITIALIZER(runCreateLogfileGroup);
}
TESTCASE("CreateTablespace", ""){
INITIALIZER(runCreateTablespace);
}
TESTCASE("CreateDiskTable", ""){
INITIALIZER(runCreateDiskTable);
}
TESTCASE("FailAddFragment",
"Fail add fragment or attribute in ACC or TUP or TUX\n"){
INITIALIZER(runFailAddFragment);
}
TESTCASE("Restart_NF1",
"DICT ops during node graceful shutdown (not master)"){
TC_PROPERTY("Restart_NF_ops", 1);
TC_PROPERTY("Restart_NF_type", 1);
STEP(runRestarts);
STEP(runDictOps);
}
TESTCASE("Restart_NF2",
"DICT ops during node shutdown abort (not master)"){
TC_PROPERTY("Restart_NF_ops", 1);
TC_PROPERTY("Restart_NF_type", 2);
STEP(runRestarts);
STEP(runDictOps);
}
TESTCASE("Restart_NR1",
"DICT ops during node startup (not master)"){
TC_PROPERTY("Restart_NR_ops", 1);
STEP(runRestarts);
STEP(runDictOps);
}
TESTCASE("Restart_NR2",
"DICT ops during node startup with crash inserts (not master)"){
TC_PROPERTY("Restart_NR_ops", 1);
TC_PROPERTY("Restart_NR_error", 1);
STEP(runRestarts);
STEP(runDictOps);
}
TESTCASE("Bug21755",
""){
INITIALIZER(runBug21755);
}
TESTCASE("DictRestart",
""){
INITIALIZER(runDictRestart);
}
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);
}