summaryrefslogtreecommitdiff
path: root/ndb/test/ndbapi/flexScan.cpp
diff options
context:
space:
mode:
authorunknown <tomas@poseidon.(none)>2004-05-26 16:02:21 +0000
committerunknown <tomas@poseidon.(none)>2004-05-26 16:02:21 +0000
commit5790e2b34f2252fdeb618bd76ce2bdb54336d24e (patch)
treeac848783937176c7a424196d8749f87e3a91b418 /ndb/test/ndbapi/flexScan.cpp
parent4cfa10deafcad9c85eb05d0c00d1b422c4c66fdb (diff)
parentabee640f44e4475a6b5448f30dcec9bca5455bda (diff)
downloadmariadb-git-5790e2b34f2252fdeb618bd76ce2bdb54336d24e.tar.gz
Merge poseidon.(none):/home/tomas/mysql-4.1-ndb
into poseidon.(none):/home/tomas/mysql-4.1-ndb-make configure.in: Auto merged ndb/src/Makefile_old: Auto merged ndb/test/ndbapi/acid.cpp: Auto merged ndb/test/ndbapi/flexAsynch.cpp: Auto merged ndb/test/ndbapi/flexHammer.cpp: Auto merged ndb/test/ndbapi/flexTT.cpp: Auto merged ndb/test/ndbapi/initronja.cpp: Auto merged ndb/test/ndbapi/interpreterInTup.cpp: Auto merged ndb/test/ndbapi/msa.cpp: Auto merged ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userInterface.cpp: Auto merged ndb/test/ndbapi/testDataBuffers.cpp: Auto merged ndb/test/ndbapi/testNdbApi.cpp: Auto merged ndb/test/ndbapi/testRestartGci.cpp: Auto merged ndb/test/ndbapi/testScan.cpp: Auto merged ndb/tools/desc.cpp: Auto merged ndb/test/ndbapi/flexScan.cpp: Auto merged
Diffstat (limited to 'ndb/test/ndbapi/flexScan.cpp')
-rw-r--r--ndb/test/ndbapi/flexScan.cpp1667
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