1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
17
/* ***************************************************
19
Perform benchmark of insert, update and delete transactions
22
-t Number of threads to start, default 1
23
-o Number of operations per loop, default 500
24
-l Number of loops to run, default 1, 0=infinite
25
-a Number of attributes, default 25
26
-c Number of tables, default 1
27
-s Size of each attribute, default 1 (Primary Key is always of size 1,
28
independent of this value)
29
-lkn Number of long primary keys, default 1
30
-lks Size of each long primary key, default 1
31
-simple Use simple read to read from database
32
-dirty Use dirty read to read from database
33
-write Use writeTuple in insert and update
34
-stdtables Use standard table names
35
-no_table_create Don't create tables in db
36
-sleep Sleep a number of seconds before running the test, this
37
can be used so that another flexBench have time to create tables
38
-temp Use tables without logging
39
-verify Verify inserts, updates and deletes
41
-statserv host:port statistics server to report to
42
-statfreq ops report every ops operations (default 100)
49
* *************************************************** */
51
#include <ndb_global.h>
58
#include <NdbTimer.hpp>
59
#include <NdbThread.h>
61
#include <NdbTest.hpp>
66
#define MAXATTRSIZE 1000
67
#define MAXNOLONGKEY 16 // Max number of long keys.
68
#define MAXLONGKEYTOTALSIZE 1023 // words = 4092 bytes
70
extern "C" { static void* flexBenchThread(void*); }
71
static int readArguments(int argc, const char** argv);
72
static int createTables(Ndb*);
73
static void sleepBeforeStartingTest(int seconds);
74
static void input_error();
91
NdbThread* threadLife;
93
StartType threadStart;
97
static int tNodeId = 0 ;
98
static char tableName[MAXTABLES][MAXSTRLEN+1];
99
static char attrName[MAXATTR][MAXSTRLEN+1];
100
static char** longKeyAttrName;
102
// Program Parameters
103
static int tNoOfLoops = 1;
104
static int tAttributeSize = 1;
105
static unsigned int tNoOfThreads = 1;
106
static unsigned int tNoOfTables = 1;
107
static unsigned int tNoOfAttributes = 25;
108
static unsigned int tNoOfOperations = 500;
109
static unsigned int tSleepTime = 0;
110
static unsigned int tNoOfLongPK = 1;
111
static unsigned int tSizeOfLongPK = 1;
114
static int theSimpleFlag = 0;
115
static int theDirtyFlag = 0;
116
static int theWriteFlag = 0;
117
static int theStdTableNameFlag = 0;
118
static int theTableCreateFlag = 0;
119
static bool theTempTable = false;
120
static bool VerifyFlag = true;
121
static bool useLongKeys = false;
124
static ErrorData theErrorData; // Part of flexBench-program
126
#define START_TIMER { NdbTimer timer; timer.doStart();
127
#define STOP_TIMER timer.doStop();
128
#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
133
#include <NdbMutex.h>
134
static bool statEnable = false;
135
static char statHost[100];
136
static int statFreq = 100;
137
static int statPort = 0;
138
static int statSock = -1;
139
static enum { statError = -1, statClosed, statOpen } statState;
140
static NdbMutex statMutex = NDB_MUTEX_INITIALIZER;
143
//-------------------------------------------------------------------
144
// Statistical Reporting routines
145
//-------------------------------------------------------------------
147
// Experimental client-side statistic for CeBIT
150
statReport(enum StartType st, int ops)
154
if (NdbMutex_Lock(&statMutex) < 0) {
155
if (statState != statError) {
156
ndbout_c("stat: lock mutex failed: %s", strerror(errno));
157
statState = statError;
163
if (statState != statOpen) {
164
char *p = getenv("NDB_NODEID"); // ndbnet sets NDB_NODEID
165
nodeid = p == 0 ? 0 : atoi(p);
166
if ((statSock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
167
if (statState != statError) {
168
ndbout_c("stat: create socket failed: %s", strerror(errno));
169
statState = statError;
171
(void)NdbMutex_Unlock(&statMutex);
174
struct sockaddr_in saddr;
175
memset(&saddr, 0, sizeof(saddr));
176
saddr.sin_family = AF_INET;
177
saddr.sin_port = htons(statPort);
178
if (Ndb_getInAddr(&saddr.sin_addr, statHost) < 0) {
179
if (statState != statError) {
180
ndbout_c("stat: host %s not found", statHost);
181
statState = statError;
183
(void)close(statSock);
184
(void)NdbMutex_Unlock(&statMutex);
187
if (connect(statSock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
188
if (statState != statError) {
189
ndbout_c("stat: connect failed: %s", strerror(errno));
190
statState = statError;
192
(void)close(statSock);
193
(void)NdbMutex_Unlock(&statMutex);
196
statState = statOpen;
197
ndbout_c("stat: connection to %s:%d opened", statHost, (int)statPort);
217
text = "verifydelete";
224
sprintf(buf, "%d %s %d\n", nodeid, text, ops);
225
int len = strlen(buf);
226
// assume SIGPIPE already ignored
227
if (write(statSock, buf, len) != len) {
228
if (statState != statError) {
229
ndbout_c("stat: write failed: %s", strerror(errno));
230
statState = statError;
232
(void)close(statSock);
233
(void)NdbMutex_Unlock(&statMutex);
236
(void)NdbMutex_Unlock(&statMutex);
241
resetThreads(ThreadData* pt){
242
for (unsigned int i = 0; i < tNoOfThreads; i++){
243
pt[i].threadReady = 0;
244
pt[i].threadResult = 0;
245
pt[i].threadStart = stIdle;
250
checkThreadResults(ThreadData* pt){
251
for (unsigned int i = 0; i < tNoOfThreads; i++){
252
if(pt[i].threadResult != 0){
253
ndbout_c("Thread%d reported fatal error %d", i, pt[i].threadResult);
262
waitForThreads(ThreadData* pt)
266
NdbSleep_MilliSleep(100);
268
for (unsigned int i = 0; i < tNoOfThreads; i++){
269
if (pt[i].threadReady == 0)
276
tellThreads(ThreadData* pt, StartType what)
278
for (unsigned int i = 0; i < tNoOfThreads; i++)
279
pt[i].threadStart = what;
282
static Ndb_cluster_connection *g_cluster_connection= 0;
284
NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
287
ThreadData* pThreadsData;
289
int returnValue = NDBT_OK;
291
if (readArguments(argc, argv) != 0){
293
return NDBT_ProgramExit(NDBT_WRONGARGS);
297
longKeyAttrName = (char **) malloc(sizeof(char*) * tNoOfLongPK);
298
for (Uint32 i = 0; i < tNoOfLongPK; i++) {
299
longKeyAttrName[i] = (char *) malloc(strlen("KEYATTR ") + 1);
300
memset(longKeyAttrName[i], 0, strlen("KEYATTR ") + 1);
301
sprintf(longKeyAttrName[i], "KEYATTR%i", i);
305
pThreadsData = new ThreadData[tNoOfThreads];
307
ndbout << endl << "FLEXBENCH - Starting normal mode" << endl;
308
ndbout << "Perform benchmark of insert, update and delete transactions"<< endl;
309
ndbout << " " << tNoOfThreads << " thread(s) " << endl;
310
ndbout << " " << tNoOfLoops << " iterations " << endl;
311
ndbout << " " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction " <<endl;
312
ndbout << " " << tNoOfAttributes << " attributes per table " << endl;
313
ndbout << " " << tNoOfOperations << " transaction(s) per thread and round " << endl;
314
ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute "<< endl;
315
ndbout << " " << "Table(s) without logging: " << (Uint32)theTempTable << endl;
318
ndbout << " " << "Using long keys with " << tNoOfLongPK << " keys a' " <<
319
tSizeOfLongPK * 4 << " bytes each." << endl;
321
ndbout << " " << "Verification is " ;
323
ndbout << "enabled" << endl ;
325
ndbout << "disabled" << endl ;
327
theErrorData.printSettings(ndbout);
329
NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
331
Ndb_cluster_connection con;
332
if(con.connect(12, 5, 1) != 0)
334
return NDBT_ProgramExit(NDBT_FAILED);
337
g_cluster_connection= &con;
340
pNdb = new Ndb(&con, "TEST_DB" );
343
tNodeId = pNdb->getNodeId();
344
ndbout << " NdbAPI node with id = " << tNodeId << endl;
347
ndbout << "Waiting for ndb to become ready..." <<endl;
348
if (pNdb->waitUntilReady(2000) != 0){
349
ndbout << "NDB is not ready" << endl;
350
ndbout << "Benchmark failed!" << endl;
351
returnValue = NDBT_FAILED;
354
if(returnValue == NDBT_OK){
355
if (createTables(pNdb) != 0){
356
returnValue = NDBT_FAILED;
360
if(returnValue == NDBT_OK){
362
sleepBeforeStartingTest(tSleepTime);
364
/****************************************************************
366
****************************************************************/
367
resetThreads(pThreadsData);
369
for (i = 0; i < tNoOfThreads; i++){
370
pThreadsData[i].threadNo = i;
371
pThreadsData[i].threadLife = NdbThread_Create(flexBenchThread,
372
(void**)&pThreadsData[i],
375
NDB_THREAD_PRIO_LOW);
378
waitForThreads(pThreadsData);
380
ndbout << endl << "All threads started" << endl << endl;
382
/****************************************************************
384
****************************************************************/
388
int loopCount = tLoops + 1;
389
ndbout << endl << "Loop # " << loopCount << endl << endl;
391
/****************************************************************
393
****************************************************************/
394
// Reset and start timer
396
// Give insert-command to all threads
397
resetThreads(pThreadsData);
398
tellThreads(pThreadsData, stInsert);
399
waitForThreads(pThreadsData);
400
if (checkThreadResults(pThreadsData) != 0){
401
ndbout << "Error: Threads failed in performing insert" << endl;
402
returnValue = NDBT_FAILED;
405
// stop timer and print results.
407
PRINT_TIMER("insert", tNoOfOperations*tNoOfThreads, tNoOfTables);
408
/****************************************************************
410
****************************************************************/
412
resetThreads(pThreadsData);
413
ndbout << "Verifying inserts...\t" ;
414
tellThreads(pThreadsData, stVerify);
415
waitForThreads(pThreadsData);
416
if (checkThreadResults(pThreadsData) != 0){
417
ndbout << "Error: Threads failed while verifying inserts" << endl;
418
returnValue = NDBT_FAILED;
421
ndbout << "\t\tOK" << endl << endl ;
425
/****************************************************************
427
****************************************************************/
428
// Reset and start timer
430
// Give read-command to all threads
431
resetThreads(pThreadsData);
432
tellThreads(pThreadsData, stRead);
433
waitForThreads(pThreadsData);
434
if (checkThreadResults(pThreadsData) != 0){
435
ndbout << "Error: Threads failed in performing read" << endl;
436
returnValue = NDBT_FAILED;
439
// stop timer and print results.
441
PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
443
/****************************************************************
445
****************************************************************/
446
// Reset and start timer
448
// Give insert-command to all threads
449
resetThreads(pThreadsData);
450
tellThreads(pThreadsData, stUpdate);
451
waitForThreads(pThreadsData);
452
if (checkThreadResults(pThreadsData) != 0){
453
ndbout << "Error: Threads failed in performing update" << endl;
454
returnValue = NDBT_FAILED;
457
// stop timer and print results.
459
PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
461
/****************************************************************
463
****************************************************************/
465
resetThreads(pThreadsData);
466
ndbout << "Verifying updates...\t" ;
467
tellThreads(pThreadsData, stVerify);
468
waitForThreads(pThreadsData);
469
if (checkThreadResults(pThreadsData) != 0){
470
ndbout << "Error: Threads failed while verifying updates" << endl;
471
returnValue = NDBT_FAILED;
474
ndbout << "\t\tOK" << endl << endl ;
478
/****************************************************************
480
****************************************************************/
481
// Reset and start timer
483
// Give insert-command to all threads
484
resetThreads(pThreadsData);
485
tellThreads(pThreadsData, stRead);
486
waitForThreads(pThreadsData);
487
if (checkThreadResults(pThreadsData) != 0){
488
ndbout << "Error: Threads failed in performing read" << endl;
489
returnValue = NDBT_FAILED;
492
// stop timer and print results.
494
PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
496
/****************************************************************
498
****************************************************************/
499
// Reset and start timer
501
// Give insert-command to all threads
502
resetThreads(pThreadsData);
503
tellThreads(pThreadsData, stDelete);
504
waitForThreads(pThreadsData);
505
if (checkThreadResults(pThreadsData) != 0){
506
ndbout << "Error: Threads failed in performing delete" << endl;
507
returnValue = NDBT_FAILED;
510
// stop timer and print results.
512
PRINT_TIMER("delete", tNoOfOperations*tNoOfThreads, tNoOfTables);
514
/****************************************************************
516
****************************************************************/
518
resetThreads(pThreadsData);
519
ndbout << "Verifying tuple deletion..." ;
520
tellThreads(pThreadsData, stVerifyDelete);
521
waitForThreads(pThreadsData);
522
if (checkThreadResults(pThreadsData) != 0){
523
ndbout << "Error: Threads failed in verifying deletes" << endl;
524
returnValue = NDBT_FAILED;
527
ndbout << "\t\tOK" << endl << endl ;
531
ndbout << "--------------------------------------------------" << endl;
535
if ( 0 != tNoOfLoops && tNoOfLoops <= tLoops )
537
theErrorData.printErrorCounters();
540
resetThreads(pThreadsData);
541
tellThreads(pThreadsData, stStop);
542
waitForThreads(pThreadsData);
545
for(i = 0; i<tNoOfThreads; i++){
546
NdbThread_WaitFor(pThreadsData[i].threadLife, &tmp);
547
NdbThread_Destroy(&pThreadsData[i].threadLife);
551
if (useLongKeys == true) {
552
// Only free these areas if they have been allocated
553
// Otherwise cores will happen
554
for (i = 0; i < tNoOfLongPK; i++)
555
free(longKeyAttrName[i]);
556
free(longKeyAttrName);
559
delete [] pThreadsData;
561
theErrorData.printErrorCounters();
562
return NDBT_ProgramExit(returnValue);
564
////////////////////////////////////////
567
unsigned long get_hash(unsigned long * hash_key, int len)
569
unsigned long hash_value = 147;
572
for (i = 0; i < len; i++)
575
hash_value = (hash_value << 5) + hash_value + (h_key & 255);
576
hash_value = (hash_value << 5) + hash_value + ((h_key >> 8) & 255);
577
hash_value = (hash_value << 5) + hash_value + ((h_key >> 16) & 255);
578
hash_value = (hash_value << 5) + hash_value + ((h_key >> 24) & 255);
583
// End of warming up phase
587
static void* flexBenchThread(void* pArg)
589
ThreadData* pThreadData = (ThreadData*)pArg;
590
unsigned int threadNo, threadBase;
592
NdbConnection *pTrans = NULL ;
593
NdbOperation** pOps = NULL ;
595
StartType tSaveType ;
596
NdbRecAttr* tTmp = NULL ;
597
int* attrValue = NULL ;
598
int* attrRefValue = NULL ;
600
int loopCountOps, loopCountTables, loopCountAttributes;
602
int tRetryAttempts = 20;
604
int tSpecialTrans = 0;
605
int nRefLocalOpOffset = 0 ;
607
tNoOfTables * tNoOfAttributes * sizeof(int) * tAttributeSize ;
609
tNoOfOperations * tNoOfAttributes * sizeof(int) * tAttributeSize ;
610
unsigned*** longKeyAttrValue;
613
threadNo = pThreadData->threadNo ;
615
attrValue = (int*)malloc(nReadBuffSize) ;
616
attrRefValue = (int*)malloc(nRefBuffSize) ;
617
pOps = (NdbOperation**)malloc(tNoOfTables*sizeof(NdbOperation*)) ;
618
pNdb = new Ndb(g_cluster_connection, "TEST_DB" );
620
if(!attrValue || !attrRefValue || !pOps || !pNdb){
621
// Check allocations to make sure we got all the memory we asked for
622
ndbout << "One or more memory allocations failed when starting thread #";
623
ndbout << threadNo << endl ;
624
ndbout << "Thread #" << threadNo << " will now exit" << endl ;
630
return 0; // thread exits
634
pNdb->waitUntilReady();
636
// To make sure that two different threads doesn't operate on the same record
637
// Calculate an "unique" number to use as primary key
638
threadBase = (threadNo * 2000000) + (tNodeId * 260000000);
641
// Allocate and populate the longkey array.
642
longKeyAttrValue = (unsigned ***) malloc(sizeof(unsigned**) * tNoOfOperations );
644
for (n = 0; n < tNoOfOperations; n++)
645
longKeyAttrValue[n] = (unsigned **) malloc(sizeof(unsigned*) * tNoOfLongPK );
646
for (n = 0; n < tNoOfOperations; n++){
647
for (Uint32 i = 0; i < tNoOfLongPK ; i++) {
648
longKeyAttrValue[n][i] = (unsigned *) malloc(sizeof(unsigned) * tSizeOfLongPK);
649
memset(longKeyAttrValue[n][i], 0, sizeof(unsigned) * tSizeOfLongPK);
650
for(Uint32 j = 0; j < tSizeOfLongPK; j++) {
651
// Repeat the unique value to fill up the long key.
652
longKeyAttrValue[n][i][j] = threadBase + n;
658
int nRefOpOffset = 0 ;
659
//Assign reference attribute values to memory
660
for(Uint32 ops = 1 ; ops < tNoOfOperations ; ops++){
661
// Calculate offset value before going into the next loop
662
nRefOpOffset = tAttributeSize*tNoOfAttributes*(ops-1) ;
663
for(Uint32 a = 0 ; a < tNoOfAttributes ; a++){
664
*(int*)&attrRefValue[nRefOpOffset + tAttributeSize*a] =
665
(int)(threadBase + ops + a) ;
670
// ops not yet reported
674
pThreadData->threadResult = tResult; // Report error to main thread,
675
// normally tResult is set to 0
676
pThreadData->threadReady = 1;
678
while (pThreadData->threadStart == stIdle){
679
NdbSleep_MilliSleep(100);
682
// Check if signal to exit is received
683
if (pThreadData->threadStart == stStop){
684
pThreadData->threadReady = 1;
685
// ndbout_c("Thread%d is stopping", threadNo);
686
// In order to stop this thread, the main thread has signaled
687
// stStop, break out of the for loop so that destructors
688
// and the proper exit functions are called
692
tType = pThreadData->threadStart;
694
pThreadData->threadStart = stIdle;
696
// Start transaction, type of transaction
697
// is received in the array ThreadStart
698
loopCountOps = tNoOfOperations;
699
loopCountTables = tNoOfTables;
700
loopCountAttributes = tNoOfAttributes;
702
for (int count = 1; count < loopCountOps && tResult == 0;){
704
pTrans = pNdb->startTransaction();
705
if (pTrans == NULL) {
706
// This is a fatal error, abort program
707
ndbout << "Could not start transaction in thread" << threadNo;
709
ndbout << pNdb->getNdbError() << endl;
710
tResult = 1; // Indicate fatal error
711
break; // Break out of for loop
714
// Calculate the current operation offset in the reference array
715
nRefLocalOpOffset = tAttributeSize*tNoOfAttributes*(count - 1) ;
717
for (int countTables = 0;
718
countTables < loopCountTables && tResult == 0;
721
pOps[countTables] = pTrans->getNdbOperation(tableName[countTables]);
722
if (pOps[countTables] == NULL) {
723
// This is a fatal error, abort program
724
ndbout << "getNdbOperation: " << pTrans->getNdbError();
725
tResult = 2; // Indicate fatal error
730
case stInsert: // Insert case
731
if (theWriteFlag == 1 && theDirtyFlag == 1)
732
pOps[countTables]->dirtyWrite();
733
else if (theWriteFlag == 1)
734
pOps[countTables]->writeTuple();
736
pOps[countTables]->insertTuple();
738
case stRead: // Read Case
739
if (theSimpleFlag == 1)
740
pOps[countTables]->simpleRead();
741
else if (theDirtyFlag == 1)
742
pOps[countTables]->dirtyRead();
744
pOps[countTables]->readTuple();
746
case stUpdate: // Update Case
747
if (theWriteFlag == 1 && theDirtyFlag == 1)
748
pOps[countTables]->dirtyWrite();
749
else if (theWriteFlag == 1)
750
pOps[countTables]->writeTuple();
751
else if (theDirtyFlag == 1)
752
pOps[countTables]->dirtyUpdate();
754
pOps[countTables]->updateTuple();
756
case stDelete: // Delete Case
757
pOps[countTables]->deleteTuple();
760
pOps[countTables]->readTuple();
763
pOps[countTables]->readTuple();
771
// Loop the equal call so the complete key is send to the kernel.
772
for(Uint32 i = 0; i < tNoOfLongPK; i++)
773
pOps[countTables]->equal(longKeyAttrName[i],
774
(char *)longKeyAttrValue[count - 1][i], tSizeOfLongPK*4);
777
pOps[countTables]->equal((Uint32)0,
778
(char*)&attrRefValue[nRefLocalOpOffset]);
780
if (tType == stInsert || tType == stUpdate){
781
for (int ca = 1; ca < loopCountAttributes; ca++){
782
pOps[countTables]->setValue((Uint32)ca,
783
(char*)&attrRefValue[nRefLocalOpOffset + tAttributeSize*ca]);
785
} else if (tType == stRead || stVerify == tType) {
786
int nTableOffset = tAttributeSize *
787
loopCountAttributes *
789
for (int ca = 1; ca < loopCountAttributes; ca++) {
790
tTmp = pOps[countTables]->getValue((Uint32)ca,
791
(char*)&attrValue[nTableOffset + tAttributeSize*ca]);
793
} else if (stVerifyDelete == tType) {
795
int nTableOffset = tAttributeSize *
796
loopCountAttributes *
798
tTmp = pOps[countTables]->getValue(longKeyAttrName[0],
799
(char*)&attrValue[nTableOffset]);
801
int nTableOffset = tAttributeSize *
802
loopCountAttributes *
804
tTmp = pOps[countTables]->getValue((Uint32)0,
805
(char*)&attrValue[nTableOffset]);
812
check = pTrans->execute(Commit);
814
// Decide what kind of error this is
815
if ((tSpecialTrans == 1) &&
817
// --------------------------------------------------------------------
818
// A special transaction have been executed, change to check = 0 in
819
// certain situations.
820
// --------------------------------------------------------------------
822
case stInsert: // Insert case
823
if (630 == pTrans->getNdbError().code ) {
825
ndbout << "Insert with 4007 was successful" << endl;
828
case stDelete: // Delete Case
829
if (626 == pTrans->getNdbError().code ) {
831
ndbout << "Delete with 4007 was successful" << endl;
840
if ((stVerifyDelete == tType) &&
841
(626 == pTrans->getNdbError().code)) {
842
// ----------------------------------------------
843
// It's good news - the deleted tuple is gone,
844
// so reset "check" flag
845
// ----------------------------------------------
849
theErrorData.handleErrorCommon(pTrans->getNdbError());
851
ndbout_c("execute: %d, %d, %s", count, tType,
852
pTrans->getNdbError().message );
853
ndbout_c("Error code = %d", pTrans->getNdbError().code );
855
} else if (retCode == 2) {
856
ndbout << "4115 should not happen in flexBench" << endl;
858
} else if (retCode == 3) {
859
// --------------------------------------------------------------------
860
// We are not certain if the transaction was successful or not.
861
// We must reexecute but might very well find that the transaction
862
// actually was updated. Updates and Reads are no problem here. Inserts
863
// will not cause a problem if error code 630 arrives. Deletes will
864
// not cause a problem if 626 arrives.
865
// --------------------------------------------------------------------
866
if ((tType == stInsert) || (tType == stDelete)) {
872
// Check if retries should be made
873
if (check == -1 && tResult == 0) {
874
if (tAttemptNo < tRetryAttempts){
877
// --------------------------------------------------------------------
878
// Too many retries have been made, report error and break out of loop
879
// --------------------------------------------------------------------
880
ndbout << "Thread" << threadNo;
881
ndbout << ": too many errors reported" << endl;
888
// Go to the next record
892
// report successful ops
894
statOps += loopCountTables;
895
if (statOps >= statFreq) {
896
statReport(tType, statOps);
903
if (stVerify == tType && 0 == check){
904
int nTableOffset = 0 ;
905
for (int a = 1 ; a < loopCountAttributes ; a++){
906
for (int tables = 0 ; tables < loopCountTables ; tables++){
907
nTableOffset = tables*loopCountAttributes*tAttributeSize ;
908
if (*(int*)&attrValue[nTableOffset + tAttributeSize*a] != *(int*)&attrRefValue[nRefLocalOpOffset + tAttributeSize*a]){
909
ndbout << "Error in verify:" << endl ;
910
ndbout << "attrValue[" << nTableOffset + tAttributeSize*a << "] = " << attrValue[a] << endl ;
911
ndbout << "attrRefValue[" << nRefLocalOpOffset + tAttributeSize*a << "]" << attrRefValue[nRefLocalOpOffset + tAttributeSize*a] << endl ;
917
}// if(stVerify ... )
918
pNdb->closeTransaction(pTrans) ;
921
// report remaining successful ops
924
statReport(tType, statOps);
935
if (useLongKeys == true) {
936
// Only free these areas if they have been allocated
937
// Otherwise cores will occur
938
for (Uint32 n = 0; n < tNoOfOperations; n++){
939
for (Uint32 i = 0; i < tNoOfLongPK; i++) {
940
free(longKeyAttrValue[n][i]);
942
free(longKeyAttrValue[n]);
944
free(longKeyAttrValue);
947
return NULL; // Thread exits
951
static int readArguments(int argc, const char** argv)
956
if (strcmp(argv[i], "-t") == 0){
957
tNoOfThreads = atoi(argv[i+1]);
958
if ((tNoOfThreads < 1))
962
}else if (strcmp(argv[i], "-o") == 0){
963
tNoOfOperations = atoi(argv[i+1]);
964
if (tNoOfOperations < 1)
968
}else if (strcmp(argv[i], "-a") == 0){
969
tNoOfAttributes = atoi(argv[i+1]);
970
if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR))
974
}else if (strcmp(argv[i], "-lkn") == 0){
975
tNoOfLongPK = atoi(argv[i+1]);
977
if ((tNoOfLongPK < 1) || (tNoOfLongPK > MAXNOLONGKEY) ||
978
(tNoOfLongPK * tSizeOfLongPK) > MAXLONGKEYTOTALSIZE){
979
ndbout << "Argument -lkn is not in the proper range." << endl;
984
}else if (strcmp(argv[i], "-lks") == 0){
985
tSizeOfLongPK = atoi(argv[i+1]);
987
if ((tSizeOfLongPK < 1) || (tNoOfLongPK * tSizeOfLongPK) > MAXLONGKEYTOTALSIZE){
988
ndbout << "Argument -lks is not in the proper range 1 to " <<
989
MAXLONGKEYTOTALSIZE << endl;
994
}else if (strcmp(argv[i], "-c") == 0){
995
tNoOfTables = atoi(argv[i+1]);
996
if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES))
1000
}else if (strcmp(argv[i], "-stdtables") == 0){
1001
theStdTableNameFlag = 1;
1002
}else if (strcmp(argv[i], "-l") == 0){
1003
tNoOfLoops = atoi(argv[i+1]);
1004
if ((tNoOfLoops < 0) || (tNoOfLoops > 100000))
1008
}else if (strcmp(argv[i], "-s") == 0){
1009
tAttributeSize = atoi(argv[i+1]);
1010
if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE))
1014
}else if (strcmp(argv[i], "-sleep") == 0){
1015
tSleepTime = atoi(argv[i+1]);
1016
if ((tSleepTime < 1) || (tSleepTime > 3600))
1020
}else if (strcmp(argv[i], "-simple") == 0){
1022
}else if (strcmp(argv[i], "-write") == 0){
1024
}else if (strcmp(argv[i], "-dirty") == 0){
1026
}else if (strcmp(argv[i], "-no_table_create") == 0){
1027
theTableCreateFlag = 1;
1028
}else if (strcmp(argv[i], "-temp") == 0){
1029
theTempTable = true;
1030
}else if (strcmp(argv[i], "-noverify") == 0){
1031
VerifyFlag = false ;
1032
}else if (theErrorData.parseCmdLineArg(argv, i) == true){
1033
; //empty, updated in errorArg(..)
1034
}else if (strcmp(argv[i], "-verify") == 0){
1037
}else if (strcmp(argv[i], "-statserv") == 0){
1040
const char *p = argv[i+1];
1041
const char *q = strrchr(p, ':');
1044
BaseString::snprintf(statHost, sizeof(statHost), "%.*s", q-p, p);
1045
statPort = atoi(q+1);
1049
}else if (strcmp(argv[i], "-statfreq") == 0){
1052
statFreq = atoi(argv[i+1]);
1067
static void sleepBeforeStartingTest(int seconds){
1069
ndbout << "Sleeping(" <<seconds << ")...";
1070
NdbSleep_SecSleep(seconds);
1071
ndbout << " done!" << endl;
1077
createTables(Ndb* pMyNdb){
1079
for (i = 0; i < tNoOfAttributes; i++){
1080
BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
1083
// Note! Uses only uppercase letters in table name's
1084
// so that we can look at the tables with SQL
1085
for (i = 0; i < tNoOfTables; i++){
1086
if (theStdTableNameFlag == 0){
1087
BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
1088
(int)(NdbTick_CurrentMillisecond() / 1000));
1090
BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
1094
for(i = 0; i < tNoOfTables; i++){
1095
ndbout << "Creating " << tableName[i] << "... ";
1097
NdbDictionary::Table tmpTable(tableName[i]);
1099
tmpTable.setStoredTable(!theTempTable);
1102
for(Uint32 i = 0; i < tNoOfLongPK; i++) {
1103
NdbDictionary::Column col(longKeyAttrName[i]);
1104
col.setType(NdbDictionary::Column::Unsigned);
1105
col.setLength(tSizeOfLongPK);
1106
col.setPrimaryKey(true);
1107
tmpTable.addColumn(col);
1110
NdbDictionary::Column col(attrName[0]);
1111
col.setType(NdbDictionary::Column::Unsigned);
1113
col.setPrimaryKey(true);
1114
tmpTable.addColumn(col);
1118
NdbDictionary::Column col;
1119
col.setType(NdbDictionary::Column::Unsigned);
1120
col.setLength(tAttributeSize);
1121
for (unsigned j = 1; j < tNoOfAttributes; j++){
1122
col.setName(attrName[j]);
1123
tmpTable.addColumn(col);
1126
if(pMyNdb->getDictionary()->createTable(tmpTable) == -1){
1129
ndbout << "done" << endl;
1136
static void input_error(){
1137
ndbout << endl << "Invalid argument!" << endl;
1138
ndbout << endl << "Arguments:" << endl;
1139
ndbout << " -t Number of threads to start, default 1" << endl;
1140
ndbout << " -o Number of operations per loop, default 500" << endl;
1141
ndbout << " -l Number of loops to run, default 1, 0=infinite" << endl;
1142
ndbout << " -a Number of attributes, default 25" << endl;
1143
ndbout << " -c Number of tables, default 1" << endl;
1144
ndbout << " -s Size of each attribute, default 1 (Primary Key is always of size 1," << endl;
1145
ndbout << " independent of this value)" << endl;
1146
ndbout << " -lkn Number of long primary keys, default 1" << endl;
1147
ndbout << " -lks Size of each long primary key, default 1" << endl;
1149
ndbout << " -simple Use simple read to read from database" << endl;
1150
ndbout << " -dirty Use dirty read to read from database" << endl;
1151
ndbout << " -write Use writeTuple in insert and update" << endl;
1152
ndbout << " -stdtables Use standard table names" << endl;
1153
ndbout << " -no_table_create Don't create tables in db" << endl;
1154
ndbout << " -sleep Sleep a number of seconds before running the test, this" << endl;
1155
ndbout << " can be used so that another flexBench have time to create tables" << endl;
1156
ndbout << " -temp Use tables without logging" << endl;
1157
ndbout << " -verify Verify inserts, updates and deletes" << endl ;
1158
theErrorData.printCmdLineArgs(ndbout);
1159
ndbout << endl <<"Returns:" << endl;
1160
ndbout << "\t 0 - Test passed" << endl;
1161
ndbout << "\t 1 - Test failed" << endl;
1162
ndbout << "\t 2 - Invalid arguments" << endl << endl;