mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
889cb7db35
into mysql.com:/home/jonas/src/mysql-4.1-ndb-jonas
1578 lines
42 KiB
C++
1578 lines
42 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; 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++){
|
|
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 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++){
|
|
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++){
|
|
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;
|
|
|
|
// enum FragmentType {
|
|
// Unknown = 0,
|
|
// Single = 1, ///< Only one fragment
|
|
// All = 2, ///< Default value. One fragment per node group
|
|
// AllLarge = 3 ///< Sixten fragments per node group.
|
|
// };
|
|
|
|
if (pNdb->waitUntilReady(30) != 0){
|
|
// Db is not ready, return with failure
|
|
return NDBT_FAILED;
|
|
}
|
|
|
|
const NdbDictionary::Table* pTab = ctx->getTab();
|
|
|
|
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;
|
|
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;
|
|
}
|
|
|
|
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++){
|
|
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;
|
|
}
|
|
|
|
int
|
|
NF_codes[] = {
|
|
6003
|
|
,6004
|
|
//,6005
|
|
};
|
|
|
|
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);
|
|
int error = NF_codes[i];
|
|
|
|
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");
|
|
|
|
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.setPrimaryKey(true);
|
|
myColumn.setType(NdbDictionary::Column::Unsigned);
|
|
myColumn.setLength(1);
|
|
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 = dict->getTableForAlteration(pTabName.c_str());
|
|
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 = dict->getTableForAlteration(pTabName.c_str());
|
|
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];
|
|
|
|
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 = dict->getTableForAlteration(pTabName.c_str());
|
|
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;
|
|
|
|
Ndb* pNdb = GETNDB(step);
|
|
|
|
const Uint32 count = NDBT_Tables::getNumTables();
|
|
for (int 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(int 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;
|
|
}
|
|
|
|
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(runClearTable);
|
|
}
|
|
TESTCASE("FragmentTypeSingle",
|
|
"Create the table with fragment type Single\n"){
|
|
TC_PROPERTY("FragmentType", 1);
|
|
INITIALIZER(runTestFragmentTypes);
|
|
}
|
|
TESTCASE("FragmentTypeAll",
|
|
"Create the table with fragment type All\n"){
|
|
TC_PROPERTY("FragmentType", 2);
|
|
INITIALIZER(runTestFragmentTypes);
|
|
}
|
|
TESTCASE("FragmentTypeAllLarge",
|
|
"Create the table with fragment type AllLarge\n"){
|
|
TC_PROPERTY("FragmentType", 3);
|
|
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);
|
|
}
|
|
NDBT_TESTSUITE_END(testDict);
|
|
|
|
int main(int argc, const char** argv){
|
|
// Tables should not be auto created
|
|
testDict.setCreateTable(false);
|
|
myRandom48Init(NdbTick_CurrentMillisecond());
|
|
return testDict.execute(argc, argv);
|
|
}
|
|
|
|
|