diff options
Diffstat (limited to 'ndb/test/ndbapi/flexScan.cpp')
-rw-r--r-- | ndb/test/ndbapi/flexScan.cpp | 1667 |
1 files changed, 1667 insertions, 0 deletions
diff --git a/ndb/test/ndbapi/flexScan.cpp b/ndb/test/ndbapi/flexScan.cpp new file mode 100644 index 00000000000..5b5b4dde730 --- /dev/null +++ b/ndb/test/ndbapi/flexScan.cpp @@ -0,0 +1,1667 @@ +/* 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 */ + +/* *************************************************** + FLEXSCAN + Perform benchmark of: + insert + read + scan read + update + scan update + read + scan delete + verify delete + + Arguments: + -f Location of Ndb.cfg file, default Ndb.cfg + -t Number of threads to start, default 1 + -o Number of operations per loop, default 500 -l Number of loops to run, default 1, 0=infinite + -a Number of attributes, default 25 + -c Number of tables, default 1 + -s Size of each attribute, default 1 + -stdtables Use standard table names + -no_table_create Don't create tables in db + -sleep Sleep a number of seconds before running the test, this + can be used so that another flexBench hav etome to create tables + -p Parallellism to use 1-32, default:1 + -abort <number> Test scan abort after a number of tuples + -h Print help text + -no_scan_update Don't do scan updates + -no_scan_delete Don't do scan deletes + + Returns: + NDBT_OK - Test passed + NDBT_FAILED - Test failed + + Revision history: + 1.12 020222 epesson: Rewritten to use NDBT. Major bugs fixed + + * *************************************************** */ + +#include "NdbApi.hpp" + +#include <NdbThread.h> +#include <NdbSleep.h> +#include <NdbTick.h> +#include <NdbOut.hpp> +#include <NdbTimer.hpp> +#include <NdbMain.h> +#include <NdbTest.hpp> +#include <NDBT_Error.hpp> +#include <NdbSchemaCon.hpp> + +#define PKSIZE 1 +#define FOREVER 1 +#define MAXSTRLEN 16 +#define MAXATTR 64 +#define MAXTABLES 64 +#define MAXTHREADS 256 +#define MAXATTRSIZE 64 + +enum StartType { + stIdle, + stInsert, + stRead, + stScanRead, + stUpdate, + stScanUpdate, + stDelete, + stVerifyDelete, + stScanDelete, + stStop, + stLast} ; + + +struct ThreadNdb +{ + int ThreadNo; + NdbThread* threadLife; + StartType threadStart; + int threadResult; + int threadReady; +}; + +extern "C" void* flexScanThread(void*); +static int setAttrNames(void); +static int setTableNames(void); +static int createTables(Ndb* pMyNdb); +static void sleepBeforeStartingTest(int seconds); +static int readArguments(int argc, const char** argv); +static void setAttrValues(int* attrValue, + int* readValue, + int Offset); +static int insertRows(Ndb* pNdb, int* pkValue, int* attrValue, StartType tType); +static int readRows(Ndb* pNdb, int* pkValue, int* readValue); +static int deleteRows(Ndb* pNdb, int* pkValue); +static int scanReadRows(Ndb* pNdb, int* readValue); +static int scanUpdateRows(Ndb* pNdb, int* readValue, int* attrValue); +static int scanDeleteRows(Ndb* pNdb, int* readValue); +static int verifyDeleteRows(Ndb* pNdb, int* pkValue, int* readValue); +static void Compare(int* attrValue, int* readValue); +static void UpdateArray(int *attrValue); + +static int tNoOfThreads = 1; +static int tNoOfAttributes = 25; +static int tNoOfTables = 1; +static int tAttributeSize = 1; +static int tNodeId = 0; +static int tNoOfOperations = 500; +static int tNoOfLoops = 1; +static int tAbortAfter = 0; +static int tParallellism = 1; + +static char tableName[MAXTABLES][MAXSTRLEN]; +static char attrName[MAXATTR][MAXSTRLEN]; + +static unsigned int tSleepTime = 0; + +static int theStdTableNameFlag = 0; +static int theTableCreateFlag = 0; +static int theScanAbortTestFlag = 0; +static int theNoScanUpdateFlag = 0; +static int theNoScanDeleteFlag = 0; + +//flexScanErrorData = new ErrorData; +ErrorData * flexScanErrorData; +NdbError * anerror; + +//static errorData theErrorData; +//static unsigned int tErrorCounter[6000]; + +#define START_TIMER { NdbTimer timer; timer.doStart(); +#define STOP_TIMER timer.doStop(); +#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); }; + +static void UpdateArray(int *attrValue) +{ + int tableCount = 0; + int attrCount = 0; + int opCount = 0; + int sizeCount = 0; + int* pValue = attrValue; + + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) { + for (opCount = 0; opCount < tNoOfOperations; opCount++) { + for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) { + // Update value in array + (*pValue)++; + //ndbout << "attrValue[" << tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize + + //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount << + //"] = " << attrValue[tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize + + //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount] << endl; + // Increment pointer + pValue++; + } // sizeCount + } // for opCount + } // for attrCount + } // for tableCount + +} // Update + +static void Compare(int* attrValue, int* readValue) +{ + int tableCount = 0; + int attrCount = 0; + int OpCount = 0; + int first = 0; + + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) { + for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) { + if (memcmp(&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations + + attrCount*tNoOfOperations + OpCount]), + &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations + + attrCount*tNoOfOperations + OpCount]), + tAttributeSize) != 0) { + // Values mismatch + if (first == 0) { + //ndbout << "Read and set values differ for:" << endl; + first = 1; + ndbout << "Mismatch found."; + } // if + // Comparision of values after scan update is meaningless right now + //ndbout << " table " << tableName[tableCount] << + //" - attr " << attrName[attrCount+1]; + //for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) { + //ndbout << ": set " << + //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize + + //attrCount*tNoOfOperations*tAttributeSize + + //tNoOfOperations*tAttributeSize + sizeCount] << " read " << + //readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize + + //attrCount*tNoOfOperations*tAttributeSize + + //tNoOfOperations*tAttributeSize + sizeCount] << endl; + //} // for + } // if + } // for OpCount + } // for attrCount + } // for tableCount + + // A final pretty-print + if (first == 1) { + ndbout << endl; + } // if +} // Compare + +static void printInfo() +{ + ndbout << endl << "FLEXSCAN - Starting normal mode" << endl; + ndbout << "Perform benchmark of insert, update and delete transactions"<< endl; + ndbout << " NdbAPI node with id = " << tNodeId << endl; + ndbout << " " << tNoOfThreads << " thread(s) " << endl; + ndbout << " " << tNoOfLoops << " iterations " << endl; + ndbout << " " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction " + << endl; + ndbout << " " << tNoOfAttributes << " attributes per table incl. pk" << endl; + ndbout << " " << tNoOfOperations << " transaction(s) per thread and round " << endl; + if (theScanAbortTestFlag == 1) { + ndbout << " Scan abort test after " << tAbortAfter << " tuples" << endl; + } // if + ndbout << " " << tParallellism << " parallellism in scans" << endl; + ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute " << + endl << endl; + +} // printInfo + +static void tellThreads(ThreadNdb *threadArrayP, StartType what) +{ + int i = 0; + + for (i = 0; i < tNoOfThreads ; i++) + threadArrayP[i].threadStart = what; +} // tellThreads + +static void waitForThreads(ThreadNdb *threadArrayP) +{ + int i = 0; + int cont = 1; + + while (cont == 1){ + + NdbSleep_MilliSleep(10); + cont = 0; + + for (i = 0; i < tNoOfThreads ; i++) { + if (threadArrayP[i].threadReady == 0) { +// ndbout << "Main is reporting thread " << i << " not ready" << endl; + cont = 1; + } // if + } // for + } // while +} // waitForThreads + + +static void resetThreads(ThreadNdb *threadArrayP) +{ + int i = 0; + + for (i = 0; i < tNoOfThreads ; i++) { + threadArrayP[i].threadReady = 0; + threadArrayP[i].threadResult = 0; + threadArrayP[i].threadStart = stIdle; + //ndbout << "threadStart[" << i << "]=" << + //threadArrayP[i].threadStart << endl; + } // for +} // resetThreads + +static int checkThreadResults(ThreadNdb *threadArrayP, char *action) +{ + int i = 0; + int retValue = 0; + + for (i = 0; i < tNoOfThreads; i++) { + if (threadArrayP[i].threadResult != 0) { + ndbout << "Thread " << i << " reported fatal error " + << threadArrayP[i].threadResult << " during " << action << endl; + retValue = -1; + break; + } // if + } // for + + return(retValue); +} // checkThreadResults + +NDB_COMMAND(flexScan, "flexScan", "flexScan", "flexScan", 65535) +{ + ThreadNdb* pThreads = NULL; + Ndb* pMyNdb = NULL; + int tLoops = 0; + int check = 0; + int returnValue = NDBT_OK; + int every2ndScanDelete = 0; // Switch between scan delete and normal delete + + flexScanErrorData = new ErrorData; + + flexScanErrorData->resetErrorCounters(); + + if (readArguments(argc, argv) != 0) { + ndbout << "Wrong arguments to flexScan" << endl; + return NDBT_ProgramExit(NDBT_WRONGARGS); + } // if + + /* print Setting */ + flexScanErrorData->printSettings(ndbout); + + check = setAttrNames(); + if (check != 0) { + ndbout << "Couldn't set attribute names" << endl; + return NDBT_ProgramExit(NDBT_FAILED); + } // if + check = setTableNames(); + if (check != 0) { + ndbout << "Couldn't set table names" << endl; + return NDBT_ProgramExit(NDBT_FAILED); + } // if + + pMyNdb = new Ndb ("TEST_DB"); + pMyNdb->init(); + tNodeId = pMyNdb->getNodeId(); + + printInfo(); + + NdbThread_SetConcurrencyLevel(tNoOfThreads + 2); + //NdbThread_SetConcurrencyLevel(tNoOfThreads + 8); + + pThreads = new ThreadNdb[tNoOfThreads]; + + if (pMyNdb->waitUntilReady(10000) != 0) { + ndbout << "NDB is not ready" << endl << "Benchmark failed" << endl; + returnValue = NDBT_FAILED; + } // if + + else { + + if (createTables(pMyNdb) != 0) { + ndbout << "Could not create tables" << endl; + returnValue = NDBT_FAILED; + } // if + else { + sleepBeforeStartingTest(tSleepTime); + + resetThreads(pThreads); + // Create threads + for (int i = 0; i < tNoOfThreads ; i++){ + pThreads[i].ThreadNo = i; + // Ignore the case that thread creation may fail + pThreads[i].threadLife = NdbThread_Create(flexScanThread, + (void**)&pThreads[i], + 327680, + "flexScanThread", NDB_THREAD_PRIO_LOW); + if (pThreads[i].threadLife == NULL) { + ndbout << "Could not create thread " << i << endl; + returnValue = NDBT_FAILED; + // Use the number of threads that were actually created + tNoOfThreads = i; + break; // break for loop + } // if + } // for + + waitForThreads(pThreads); + if (checkThreadResults(pThreads, "init") != 0) { + returnValue = NDBT_FAILED; + } // if + + if (returnValue == NDBT_OK) { + ndbout << "All threads started" << endl; + + while (FOREVER) { + + resetThreads(pThreads); + + if ((tNoOfLoops != 0) && (tNoOfLoops <= tLoops)) { + break; + } // if + + // Insert + START_TIMER; + + tellThreads(pThreads, stInsert); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "insert") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("insert", tNoOfOperations*tNoOfThreads, tNoOfTables); + + resetThreads(pThreads); + + // Read + START_TIMER; + + tellThreads(pThreads, stRead); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "read") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables); + + resetThreads(pThreads); + + // Update + START_TIMER; + + tellThreads(pThreads, stUpdate); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "update") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables); + + resetThreads(pThreads); + + // Scan read + START_TIMER; + + tellThreads(pThreads, stScanRead); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "scanread") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("scanread", tNoOfTables*tNoOfThreads, 1); + + resetThreads(pThreads); + + // Update + START_TIMER; + + tellThreads(pThreads, stUpdate); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "update") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables); + + resetThreads(pThreads); + + // Read + START_TIMER; + + tellThreads(pThreads, stRead); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "read") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables); + + resetThreads(pThreads); + + // Only do scan update if told to do so + if (theNoScanUpdateFlag == 0) { + // Scan update + START_TIMER; + + tellThreads(pThreads, stScanUpdate); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "scanupdate") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("scanupdate", tNoOfTables*tNoOfThreads, 1); + + resetThreads(pThreads); + + // Read + START_TIMER; + + tellThreads(pThreads, stRead); + // tellThreads(pThreads, stScanRead); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "read") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables); + + resetThreads(pThreads); + } // if theNoScanUpdateFlag + + // Shift between delete and scan delete + if ((every2ndScanDelete % 2 == 0) || (theNoScanDeleteFlag == 1)){ + // Delete + START_TIMER; + tellThreads(pThreads, stDelete); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "delete") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("delete", tNoOfOperations*tNoOfThreads, tNoOfTables); + resetThreads(pThreads); + } // if + else { + resetThreads(pThreads); // Scan delete + START_TIMER; + tellThreads(pThreads, stScanDelete); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "scandelete") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("scandelete", tNoOfTables*tNoOfThreads, 1); + + resetThreads(pThreads); + } // else + every2ndScanDelete++; + + resetThreads(pThreads); // Verify delete + START_TIMER; + tellThreads(pThreads, stVerifyDelete); + waitForThreads(pThreads); + + STOP_TIMER; + if (checkThreadResults(pThreads, "verifydelete") != 0) { + returnValue = NDBT_FAILED; + break; + } // if + PRINT_TIMER("verifydelete", tNoOfOperations*tNoOfThreads*tNoOfTables, 1); + + resetThreads(pThreads); + + ndbout << "--------------------------------------------------" << endl; + tLoops++; + + } // while + } // if + } // else + } // else + + // Stop threads in a nice way + tellThreads(pThreads, stStop); + waitForThreads(pThreads); + + // Clean up + delete [] pThreads; + delete pMyNdb; + + flexScanErrorData->printErrorCounters(ndbout); + + if (returnValue == NDBT_OK) { + ndbout << endl << "Benchmark completed successfully" << endl; + } // if + else { + ndbout << endl << "Benchmark failed" << endl; + } // else + + // Exit via NDBT + return NDBT_ProgramExit(returnValue);; +} // main + +void* +flexScanThread(void* ThreadData) +{ + ThreadNdb* pThreadData = (ThreadNdb*)ThreadData; + unsigned int thread_no = pThreadData->ThreadNo; + unsigned int thread_base = (thread_no * 2000000) + (tNodeId * 26000); + int tThreadResult = 0; + Ndb* MyNdb = NULL; + int check = 0; + StartType tType = stLast; + int* pkValue = NULL; + int* attrValue = NULL; + int* readValue = NULL; + int AllocSize = 0; + + AllocSize = tNoOfTables * (tNoOfAttributes-1) * tNoOfOperations * + tAttributeSize * sizeof(int); + attrValue = (int*)malloc(AllocSize); + readValue = (int*)malloc(AllocSize); + pkValue = (int*)malloc(tNoOfOperations * sizeof(int)); + if ((attrValue == NULL) || (readValue == NULL) || (pkValue == NULL)) { + tThreadResult = 98; + pThreadData->threadStart = stIdle; + } // if + + setAttrValues(attrValue, readValue, thread_base); + + MyNdb = new Ndb( "TEST_DB" ); + MyNdb->init(); + if (MyNdb->waitUntilReady(10000) != 0) { + tThreadResult = 99; + pThreadData->threadStart = stIdle; + } // if + + // Set primary key value, same for all tables + for (int c = 0; c < tNoOfOperations; c++) { + pkValue[c] = (int)(c + thread_base); + } // for + + while (FOREVER) { + pThreadData->threadResult = tThreadResult; + pThreadData->threadReady = 1; + + while (pThreadData->threadStart == stIdle) { + NdbSleep_MilliSleep(10); + } // while + + // Check if signal to exit is received + if (pThreadData->threadStart >= stStop){ + pThreadData->threadReady = 1; + break; + } // if + tType = pThreadData->threadStart; + pThreadData->threadStart = stIdle; + + switch (tType) { + case stInsert: + check = insertRows(MyNdb, pkValue, attrValue, tType); + break; + case stRead: + check = readRows(MyNdb, pkValue, readValue); + Compare(attrValue, readValue); + break; + case stUpdate: + UpdateArray(attrValue); + check = insertRows(MyNdb, pkValue, attrValue, tType); + break; + case stScanRead: + //check = readRows(MyNdb, pkValue, readValue); + check = scanReadRows(MyNdb, readValue); + Compare(attrValue, readValue); + break; + case stScanUpdate: + UpdateArray(attrValue); + //tType = stUpdate; + //check = insertRows(MyNdb, pkValue, attrValue, tType); + check = scanUpdateRows(MyNdb, readValue, attrValue); + break; + case stDelete: + check = deleteRows(MyNdb, pkValue); + break; + case stScanDelete: + check = scanDeleteRows(MyNdb, readValue); + break; + case stVerifyDelete: + check = verifyDeleteRows(MyNdb, pkValue, readValue); + break; + default: + ndbout << "tType is " << tType << endl; + assert(false); + break; + } // switch + + tThreadResult = check; + + if (tThreadResult != 0) { + // Check if error is fatak or not + } // if + else { + continue; + } // else + } // while + + // Clean up + delete MyNdb; + if (attrValue != NULL) { + free(attrValue); + } //if + if (readValue != NULL) { + free(readValue); + } // if + if (pkValue != NULL) { + free(pkValue); + } // if + + NdbThread_Exit(0); + return NULL; + +} // flexScanThread + + +static int setAttrNames() +{ + int i = 0; + int retVal = 0; + + for (i = 0; i < MAXATTR ; i++) { + retVal = snprintf(attrName[i], MAXSTRLEN, "COL%d", i); + if (retVal < 0) { + return(-1); + } // if + } // for + + return(0); +} // setAttrNames + + +static int setTableNames() +{ + // Note! Uses only uppercase letters in table name's + // so that we can look at the tables with SQL + int i = 0; + int retVal = 0; + + for (i = 0; i < MAXTABLES ; i++) { + + if (theStdTableNameFlag == 0) { + retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i, + (int)(NdbTick_CurrentMillisecond() / 1000)); + } // if + else { + retVal = snprintf(tableName[i], MAXSTRLEN, "TAB%d", i); + } // if else + + if (retVal < 0) { + return(-1); + } // if + } // for + + return(0); +} // setTableNames + + +// Create Table and Attributes. +static int createTables(Ndb* pMyNdb) +{ + + NdbSchemaCon *MySchemaTransaction = NULL; + NdbSchemaOp *MySchemaOp = NULL; + int i = 0; + int j = 0; + int check = 0; + + if (theTableCreateFlag == 0) { + + i = 0; + do { + i++; + ndbout << endl << "Creating " << tableName[i - 1] << "..." << endl; + + MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pMyNdb); + if( MySchemaTransaction == NULL ) { + return (-1); + } // if + + MySchemaOp = MySchemaTransaction->getNdbSchemaOp(); + if( MySchemaOp == NULL ) { + NdbSchemaCon::closeSchemaTrans(MySchemaTransaction); + return (-1); + } // if + +#if defined NDB_OSE || defined NDB_SOFTOSE + check = MySchemaOp->createTable(tableName[i - 1], + 8, // Table Size + TupleKey, // Key Type + 40, // Nr of Pages + All, + 6, + 78, + 80, + 1, + false); +#else + check = MySchemaOp->createTable(tableName[i - 1] + ,8 // Table Size + ,TupleKey // Key Type + ,40); // Nr of Pages +#endif + if (check == -1) { + NdbSchemaCon::closeSchemaTrans(MySchemaTransaction); + return -1; + } // if + + check = MySchemaOp->createAttribute( (char*)attrName[0], TupleKey, 32, PKSIZE, + UnSigned, MMBased, NotNullAttribute ); + if (check == -1) { + NdbSchemaCon::closeSchemaTrans(MySchemaTransaction); + return -1; + } // if + + for (j = 1; j < tNoOfAttributes ; j++) { + check = MySchemaOp->createAttribute( (char*)attrName[j], NoKey, 32, tAttributeSize, + UnSigned, MMBased, NotNullAttribute ); + if (check == -1) { + NdbSchemaCon::closeSchemaTrans(MySchemaTransaction); + return -1; + } // if + } // for + + if (MySchemaTransaction->execute() == -1) { + ndbout << MySchemaTransaction->getNdbError().message << endl; + ndbout << "Probably, " << tableName[i - 1] << " already exist" << endl; + } // if + + NdbSchemaCon::closeSchemaTrans(MySchemaTransaction); + } while (tNoOfTables > i); + } + + return 0; +} // createTables + +static void printUsage() +{ + ndbout << "Usage of flexScan:" << endl; + ndbout << "-f <path> Location of Ndb.cfg file, default: Ndb.cfg" << endl; + ndbout << "-t <int> Number of threads to start, default 1" << endl; + ndbout << "-o <int> Number of operations per loop, default 500" << endl; + ndbout << "-l <int> Number of loops to run, default 1, 0=infinite" << endl; + ndbout << "-a <int> Number of attributes, default 25" << endl; + ndbout << "-c <int> Number of tables, default 1" << endl; + ndbout << "-s <int> Size of each attribute, default 1" << endl; + ndbout << "-stdtables Use standard table names" << endl; + ndbout << "-no_table_create Don't create tables in db" << endl; + ndbout << "-sleep <int> Sleep a number of seconds before running the test" << endl; + ndbout << "-p <int> Parallellism to use 1-32, default:1" << endl; + ndbout << "-abort <int> Test scan abort after a number of tuples" << endl; + ndbout << "-no_scan_update Don't do scan updates" << endl; + ndbout << "-no_scan_delete Don't do scan deletes" << endl; + ndbout << "-h Print this text" << endl; + // inputErrorArg(); + flexScanErrorData->printCmdLineArgs(ndbout); +} + +static int readArguments(int argc, const char** argv) +{ + int i = 1; + int retValue = 0; + int printFlag = 0; + + tNoOfThreads = 1; // Set default Value + tNoOfTables = 1; // Default Value + + while (argc > 1) { + if (strcmp(argv[i], "-t") == 0) { + if (argv[i + 1] != NULL) { + tNoOfThreads = atoi(argv[i + 1]); + if ((tNoOfThreads < 1) || (tNoOfThreads > MAXTHREADS)) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // if + else if (strcmp(argv[i], "-o") == 0) { + if (argv[i + 1] != NULL) { + tNoOfOperations = atoi(argv[i + 1]); + if (tNoOfOperations < 1) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-a") == 0) { + if (argv[i + 1] != NULL) { + tNoOfAttributes = atoi(argv[i + 1]); + if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR)) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-c") == 0) { + if (argv[i + 1] != NULL) { + tNoOfTables = atoi(argv[i+1]); + if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES)) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-l") == 0) { + if (argv[i + 1] != NULL) { + tNoOfLoops = atoi(argv[i+1]); + if ((tNoOfLoops < 0) || (tNoOfLoops > 100000)) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-s") == 0) { + if (argv[i + 1] != NULL) { + tAttributeSize = atoi(argv[i+1]); + if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE)) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-no_table_create") == 0) { + theTableCreateFlag = 1; + argc++; + i--; + } // else if + else if (strcmp(argv[i], "-stdtables") == 0) { + theStdTableNameFlag = 1; + argc++; + i--; + } // else if + else if (strcmp(argv[i], "-sleep") == 0) { + if (argv[i + 1] != NULL) { + tSleepTime = atoi(argv[i+1]); + if ((tSleepTime < 1) || (tSleepTime > 3600)) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-abort") == 0) { + // Test scan abort after a number of tuples + theScanAbortTestFlag = 1; + if (argv[i + 1] != NULL) { + tAbortAfter = atoi(argv[i + 1]); + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-p") == 0) { + if (argv[i + 1] != NULL) { + tParallellism = atoi(argv[i + 1]); + if ((tParallellism < 1) || (tParallellism > 32)) { + retValue = -1; + } // if + } // if + else { + retValue = -1; + } // else + } // else if + else if (strcmp(argv[i], "-h") == 0) { + printFlag = 1; + argc++; + i--; + } // else if + else if (strcmp(argv[i], "-no_scan_update") == 0) { + theNoScanUpdateFlag = 1; + argc++; + i--; + } // else if + else if (strcmp(argv[i], "-no_scan_delete") == 0) { + theNoScanDeleteFlag = 1; + argc++; + i--; + } // else if + else { + retValue = -1; + } // else + + argc -= 2; + i = i + 2; + } + + if ((retValue != 0) || (printFlag == 1)) { + printUsage(); + } // if + + return(retValue); + +} // readArguments + +static void sleepBeforeStartingTest(int seconds) +{ + if (seconds > 0) { + ndbout << "Sleeping(" <<seconds << ")..."; + NdbSleep_SecSleep(seconds); + ndbout << " done!" << endl; + } // if +} // sleepBeforeStartingTest + +static void setAttrValues(int* attrValue, + int* readValue, + int Offset) +{ + int tableCount = 0; + int attrCount = 0; + int OpCount = 0; + int attrSize = 0; + int* pAttr = NULL; + int* pRead = NULL; + + // Set attribute values in memory array + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) { + for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) { + pAttr = &(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations + + attrCount*tNoOfOperations + OpCount]); + pRead = &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations + + attrCount*tNoOfOperations + OpCount]); + for (attrSize = 0; attrSize < tAttributeSize; attrSize++){ + *pAttr = (int)(Offset + tableCount + attrCount + OpCount + attrSize); + //ndbout << "attrValue[" << tableCount*(tNoOfAttributes-1)*tNoOfOperations + + //attrCount*tNoOfOperations + OpCount + attrSize << "] = " << + //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations + + //attrCount*tNoOfOperations + OpCount + attrSize] << endl; + *pRead = 0; + pAttr++; + pRead++; + } // for attrSize + } // for OpCount + } // for attrCount + } // for tableCount + +} // setAttrValues + +static int insertRows(Ndb* pNdb, // NDB object + int* pkValue, // Primary key values + int* attrValue, // Attribute values + StartType tType) +{ + int tResult = 0; + int check = 0; + int tableCount = 0; + int attrCount = 0; + NdbConnection* MyTransaction = NULL; + NdbOperation* MyOperations[MAXTABLES] = {NULL}; + int opCount = 0; + + for (opCount = 0; opCount < tNoOfOperations; opCount++) { + MyTransaction = pNdb->startTransaction(); + if (MyTransaction == NULL) { + tResult = 1; + } // if + else { + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + + MyOperations[tableCount] = + MyTransaction->getNdbOperation(tableName[tableCount]); + if (MyOperations[tableCount] == NULL) { + tResult = 2; + // Break for tableCount loop + break; + } // if + + if (tType == stUpdate) { + check = MyOperations[tableCount]->updateTuple(); + } // if + else if (tType == stInsert) { + check = MyOperations[tableCount]->insertTuple(); + } // else if + else { + assert(false); + } // else + + if (check == -1) { + tResult = 3; + break; + } // if + check = MyOperations[tableCount]->equal((char*)attrName[0], + (char*)&(pkValue[opCount])); + if (check == -1) { + tResult = 7; + break; + } // if + + for (attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) { + int Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize + + attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize; + check = MyOperations[tableCount]-> + setValue((char*)attrName[attrCount + 1], + (char*)&(attrValue[Index])); + if (check == -1) { + tResult = 8; + break; // break attrCount loop + } // if + } // for + } // for tableCount + + // Execute transaction with insert one tuple in every table + check = MyTransaction->execute(Commit); + if (check == -1) { + ndbout << MyTransaction->getNdbError().message << endl; + + // Add complete error handling here + + int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError()); + if (retCode == 1) { + if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){ + ndbout_c("execute: %d, %d, %s", opCount, tType, MyTransaction->getNdbError().message); + ndbout_c("Error code = %d", MyTransaction->getNdbError().code);} + tResult = 20; + } else if (retCode == 2) { + ndbout << "4115 should not happen in flexBench" << endl; + tResult = 20; + } else if (retCode == 3) { +// -------------------------------------------------------------------- +// We are not certain if the transaction was successful or not. +// We must reexecute but might very well find that the transaction +// actually was updated. Updates and Reads are no problem here. Inserts +// will not cause a problem if error code 630 arrives. Deletes will +// not cause a problem if 626 arrives. +// -------------------------------------------------------------------- + /* What can we do here? */ + ndbout_c("execute: %s", MyTransaction->getNdbError().message); + }//if(retCode == 3) + + } // if(check == -1) + + pNdb->closeTransaction(MyTransaction); + } // else + } // for opCount + + return(tResult); +} // insertRows + +static int readRows(Ndb* pNdb, + int* pkValue, + int* readValue) +{ + int tResult = 0; + int tableCount = 0; + int attrCount = 0; + int check = 0; + NdbConnection* MyTransaction = NULL; + NdbOperation* MyOperations[MAXTABLES] = {NULL}; + NdbRecAttr* tmp = NULL; + int Value = 0; + int Index = 0; + int opCount = 0; + + for (opCount = 0; opCount < tNoOfOperations; opCount++) { + MyTransaction = pNdb->startTransaction(); + if (MyTransaction == NULL) { + tResult = 1; + } // if + else { + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + + MyOperations[tableCount] = + MyTransaction->getNdbOperation(tableName[tableCount]); + if (MyOperations[tableCount] == NULL) { + tResult = 2; + // Break for tableCount loop + break; + } // if + + check = MyOperations[tableCount]->readTuple(); + if (check == -1) { + tResult = 3; + break; + } // if + + check = MyOperations[tableCount]-> + equal((char*)attrName[0], (char*)&(pkValue[opCount])); + if (check == -1) { + tResult = 7; + break; + } // if + + for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) { + Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize + + attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize; + tmp = MyOperations[tableCount]-> + getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index])); + + if (tmp == NULL) { + tResult = 9; + break; + } // if + } // for attrCount + } // for tableCount + // Execute transaction reading one tuple in every table + check = MyTransaction->execute(Commit); + if (check == -1) { + ndbout << MyTransaction->getNdbError().message << endl; + + // Add complete error handling here + + int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError()); + if (retCode == 1) { + if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){ + ndbout_c("execute: %d, %s", opCount, MyTransaction ->getNdbError().message ); + ndbout_c("Error code = %d", MyTransaction->getNdbError().code );} + tResult = 20; + } else if (retCode == 2) { + ndbout << "4115 should not happen in flexBench" << endl; + tResult = 20; + } else if (retCode == 3) { +// -------------------------------------------------------------------- +// We are not certain if the transaction was successful or not. +// We must reexecute but might very well find that the transaction +// actually was updated. Updates and Reads are no problem here. Inserts +// will not cause a problem if error code 630 arrives. Deletes will +// not cause a problem if 626 arrives. +// -------------------------------------------------------------------- + /* What can we do here? */ + ndbout_c("execute: %s", MyTransaction ->getNdbError().message ); + }//if(retCode == 3) + + } // if + + pNdb->closeTransaction(MyTransaction); + } // else + } // for opCount + + return(tResult); +} // readRows + +static int scanReadRows(Ndb* pNdb, int* readValue) +{ + int tResult = 0; + int tableCount = 0; + int attrCount = 0; + int check = 0; + int countAbort = 0; // Counts loops until scan abort if requested + NdbConnection* MyTransaction = NULL; + NdbOperation* MyOperation = NULL; + NdbRecAttr* tmp = NULL; + + + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + MyTransaction = pNdb->startTransaction(); + if (MyTransaction == NULL) { + tResult = 1; + break; + } // if + MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]); + if (MyOperation == NULL) { + tResult = 2; + break; + } // if + + check = MyOperation->openScanRead(tParallellism); + if (check == -1) { + tResult = 10; + break; + } // if + + for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) { + // Get all attributes + tmp = MyOperation-> + getValue((char*)attrName[attrCount+1], + (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize + + attrCount*tNoOfOperations*tAttributeSize])); + if (tmp == NULL) { + tResult = 9; + break; + } // if + } // for attrCount + + check = MyTransaction->executeScan(); + if (check == -1) { + tResult = 12; + break; + } // if + + check = MyTransaction->nextScanResult(); + while (check == 0) { + // Check if scan abort is requested + if (theScanAbortTestFlag == 1) { + if (countAbort == tAbortAfter) { + MyTransaction->stopScan(); + ndbout << "scanread aborted on request after " << countAbort*tParallellism << + " tuples" << endl; + break; // break while loop + } // if + countAbort++; + } // if + check = MyTransaction->nextScanResult(); + } // while + + pNdb->closeTransaction(MyTransaction); + } // for tableCount + + return(tResult); +} // scanReadRows + +static int scanUpdateRows(Ndb* pNdb, + int* readValue, + int* attrValue) +{ + int tResult = 0; + int tableCount = 0; + int attrCount = 0; + int check = 0; + int opCount = 0; + NdbConnection* MyTransaction = NULL; + NdbOperation* MyOperation = NULL; + NdbConnection* MyTakeOverTrans = NULL; + NdbOperation* MyTakeOverOp = NULL; + NdbRecAttr* tTmp = NULL; + + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + MyTransaction = pNdb->startTransaction(); + if (MyTransaction == NULL) { + tResult = 1; + break; // break tableCount for loop + } // if + MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]); + if (MyOperation == NULL) { + tResult = 2; + break; + } // if + + check = MyOperation->openScanExclusive(tParallellism); + if (check == -1) { + tResult = 11; + break; + } // if + + MyOperation->interpret_exit_ok(); + // Fetch all attributes + for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) { + tTmp = MyOperation-> + getValue((char*)attrName[attrCount+1], + (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize + + attrCount*tNoOfOperations*tAttributeSize])); + if (tTmp == NULL) { + tResult = 9; + break; // break for loop + } // if + } // for + if (tResult != 0) { + break; // break while loop also + } // if + + check = MyTransaction->executeScan(); + if (check == -1) { + tResult = 12; + break; + } // if + check = MyTransaction->nextScanResult(); + opCount = 0; + while (check == 0) { + MyTakeOverTrans = pNdb->startTransaction(); + MyTakeOverOp = MyOperation->takeOverForUpdate(MyTakeOverTrans); + for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) { + check = MyTakeOverOp->setValue((char*)attrName[attrCount+1], + (char*)&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize + + attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize])); + } // for + + check = MyTakeOverTrans->execute(Commit); + if (check == 0) { + check = MyTransaction->nextScanResult(); + opCount++; + } // if + else { + tResult = 95; + + /* MyTransaction, MyTakeOverTrans, Which one? */ + + // Any further error handling? + int retCode = flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError()); + if (retCode == 1) { + if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){ + ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message); + ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code);} + tResult = 20; + } else if (retCode == 2) { + ndbout << "4115 should not happen in flexBench" << endl; + tResult = 20; + } else if (retCode == 3) { + // -------------------------------------------------------------------- + // We are not certain if the transaction was successful or not. + // We must reexecute but might very well find that the transaction + // actually was updated. Updates and Reads are no problem here. Inserts + // will not cause a problem if error code 630 arrives. Deletes will + // not cause a problem if 626 arrives. + // -------------------------------------------------------------------- + /* What can we do here? */ + ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message); + }//if(retCode == 3) + + } // else + pNdb->closeTransaction(MyTakeOverTrans); + } // while + + pNdb->closeTransaction(MyTransaction); + } // for + + return(tResult); +} // scanUpdateRows + +static int scanDeleteRows(Ndb* pNdb, int* readValue) +{ + int tResult = 0; + int tableCount = 0; + int attrCount = 0; + int check = 0; + NdbRecAttr* tTmp = NULL; + NdbConnection* MyTransaction = NULL; + NdbOperation* MyOperation = NULL; + NdbConnection* MyTakeOverTrans = NULL; + NdbOperation* MyTakeOverOp = NULL; + + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + MyTransaction = pNdb->startTransaction(); + if (MyTransaction == NULL) { + tResult = 1; + break; // break tableCount for loop + } // if + + MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]); + if (MyOperation == NULL) { + tResult = 2; + break; + } // if + + check = MyOperation->openScanExclusive(tParallellism); + if (check == -1) { + tResult = 11; + break; + } // if + + MyOperation->interpret_exit_ok(); + for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) { + tTmp = MyOperation-> + getValue((char*)attrName[attrCount+1], + (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations + + attrCount*tNoOfOperations])); + if (tTmp == NULL) { + tResult = 9; + break; + } // if + } // for + + check = MyTransaction->executeScan(); + if (check == -1) { + tResult = 12; + break; + } // if + check = MyTransaction->nextScanResult(); + while (check == 0) { + MyTakeOverTrans = pNdb->startTransaction(); + MyTakeOverOp = MyOperation->takeOverForDelete(MyTakeOverTrans); + check = MyTakeOverOp->deleteTuple(); + + check = MyTakeOverTrans->execute(Commit); + + //Error handling here + + int retCode =flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError()); + if (retCode == 1) { + if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){ + ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message ); + ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code );} + tResult = 20; + } else if (retCode == 2) { + ndbout << "4115 should not happen in flexBench" << endl; + tResult = 20; + } else if (retCode == 3) { +// -------------------------------------------------------------------- +// We are not certain if the transaction was successful or not. +// We must reexecute but might very well find that the transaction +// actually was updated. Updates and Reads are no problem here. Inserts +// will not cause a problem if error code 630 arrives. Deletes will +// not cause a problem if 626 arrives. +// -------------------------------------------------------------------- + /* What can we do here? */ + ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message ); + }//if(retCode == 3) End of error handling + + pNdb->closeTransaction(MyTakeOverTrans); + check = MyTransaction->nextScanResult(); + } // while + pNdb->closeTransaction(MyTransaction); + } // for tableCount + return(tResult); +} // scanDeleteRows + +static int deleteRows(Ndb* pNdb, + int* pkValue) +{ + int tResult = 0; + NdbConnection* MyTransaction = NULL; + int tableCount = 0; + int opCount = 0; + int check = 0; + NdbOperation* MyOperations[MAXTABLES] = {NULL}; + + for (opCount = 0; opCount < tNoOfOperations; opCount++) { + MyTransaction = pNdb->startTransaction(); + if (MyTransaction == NULL) { + tResult = 1; + } // if + else { + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + + MyOperations[tableCount] = + MyTransaction->getNdbOperation(tableName[tableCount]); + if (MyOperations[tableCount] == NULL) { + tResult = 2; + // Break for tableCount loop + break; + } // if + + check = MyOperations[tableCount]->deleteTuple(); + if (check == -1) { + tResult = 3; + break; + } // if + + check = MyOperations[tableCount]-> + equal((char*)attrName[0], (char*)&(pkValue[opCount])); + if (check == -1) { + tResult = 7; + break; + } // if + + } // for tableCount + + // Execute transaction deleting one tuple in every table + check = MyTransaction->execute(Commit); + if (check == -1) { + ndbout << MyTransaction->getNdbError().message << endl; + // Add complete error handling here + + int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError()); + if (retCode == 1) { + if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){ + ndbout_c("execute: %d, %s", opCount, MyTransaction->getNdbError().message ); + ndbout_c("Error code = %d", MyTransaction->getNdbError().code );} + tResult = 20; + } else if (retCode == 2) { + ndbout << "4115 should not happen in flexBench" << endl; + tResult = 20; + } else if (retCode == 3) { +// -------------------------------------------------------------------- +// We are not certain if the transaction was successful or not. +// We must reexecute but might very well find that the transaction +// actually was updated. Updates and Reads are no problem here. Inserts +// will not cause a problem if error code 630 arrives. Deletes will +// not cause a problem if 626 arrives. +// -------------------------------------------------------------------- + /* What can we do here? */ + ndbout_c("execute: %s", MyTransaction->getNdbError().message ); + }//if(retCode == 3) + + } // if + + pNdb->closeTransaction(MyTransaction); + } // else + } // for opCount + + return(tResult); + +} // deleteRows + +//////////////////////////////////////// +// +// Name: verifyDeleteRows +// +// Purpose: Verifies that all tables are empty by reading every tuple +// No deletions made here +// +// Returns: 'Standard' error codes +// +///////////////////////////////////// +static int verifyDeleteRows(Ndb* pNdb, + int* pkValue, + int* readValue) +{ + int tResult = 0; + int tableCount = 0; + int attrCount = 0; + int check = 0; + NdbConnection* MyTransaction = NULL; + NdbOperation* MyOperations = NULL; + NdbRecAttr* tmp = NULL; + int Value = 0; + int Index = 0; + int opCount = 0; + + for (opCount = 0; opCount < tNoOfOperations; opCount++) { + for (tableCount = 0; tableCount < tNoOfTables; tableCount++) { + MyTransaction = pNdb->startTransaction(); + if (MyTransaction == NULL) { + tResult = 1; + } // if + else { + + MyOperations = + MyTransaction->getNdbOperation(tableName[tableCount]); + if (MyOperations == NULL) { + tResult = 2; + // Break for tableCount loop + break; + } // if + + check = MyOperations->readTuple(); + if (check == -1) { + tResult = 3; + break; + } // if + + check = MyOperations-> + equal((char*)attrName[0], (char*)&(pkValue[opCount])); + if (check == -1) { + tResult = 7; + break; + } // if + + for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) { + Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize + + attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize; + tmp = MyOperations-> + getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index])); + + if (tmp == NULL) { + tResult = 9; + break; + } // if + } // for attrCount + // Execute transaction reading one tuple in every table + check = MyTransaction->execute(Commit); + if ((check == -1) && (MyTransaction->getNdbError().code == 626)){ + // This is expected because everything should be deleted + } // if + else if (check == 0) { + // We have found a tuple that should have been deleted + ndbout << "tuple " << tableName[tableCount] << ":" << + opCount << " was never deleted" << endl; + tResult = 97; + } // else if + else { + // Unexpected error + ndbout << "Unexpected error during delete" << endl; + assert(false); + } // else + + pNdb->closeTransaction(MyTransaction); + + } // else + } // for tableCount + } // for opCount + + return(tResult); +} // verifyDeleteRows |