MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
flexScan.cpp
1 /*
2  Copyright (C) 2003-2008 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 /* ***************************************************
20  FLEXSCAN
21  Perform benchmark of:
22  insert
23  read
24  scan read
25  update
26  scan update
27  read
28  scan delete
29  verify delete
30 
31  Arguments:
32  -f Location of my.cnf file, default my.cnf
33  -t Number of threads to start, default 1
34  -o Number of operations per loop, default 500 -l Number of loops to run, default 1, 0=infinite
35  -a Number of attributes, default 25
36  -c Number of tables, default 1
37  -s Size of each attribute, default 1
38  -stdtables Use standard table names
39  -no_table_create Don't create tables in db
40  -sleep Sleep a number of seconds before running the test, this
41  can be used so that another flexBench hav etome to create tables
42  -p Parallellism to use 1-32, default:1
43  -abort <number> Test scan abort after a number of tuples
44  -h Print help text
45  -no_scan_update Don't do scan updates
46  -no_scan_delete Don't do scan deletes
47 
48  Returns:
49  NDBT_OK - Test passed
50  NDBT_FAILED - Test failed
51 
52  Revision history:
53  1.12 020222 epesson: Rewritten to use NDBT. Major bugs fixed
54 
55  * *************************************************** */
56 
57 #include "NdbApi.hpp"
58 
59 #include <NdbThread.h>
60 #include <NdbSleep.h>
61 #include <NdbTick.h>
62 #include <NdbOut.hpp>
63 #include <NdbTimer.hpp>
64 #include <NdbMain.h>
65 #include <NdbTest.hpp>
66 #include <NDBT_Error.hpp>
67 #include <NdbSchemaCon.hpp>
68 
69 #define PKSIZE 1
70 #define FOREVER 1
71 #define MAXSTRLEN 16
72 #define MAXATTR 64
73 #define MAXTABLES 64
74 #define NDB_MAXTHREADS 256
75 /*
76  NDB_MAXTHREADS used to be just MAXTHREADS, which collides with a
77  #define from <sys/thread.h> on AIX (IBM compiler). We explicitly
78  #undef it here lest someone use it by habit and get really funny
79  results. K&R says we may #undef non-existent symbols, so let's go.
80 */
81 #undef MAXTHREADS
82 #define MAXATTRSIZE 64
83 
84 enum StartType {
85  stIdle,
86  stInsert,
87  stRead,
88  stScanRead,
89  stUpdate,
90  stScanUpdate,
91  stDelete,
92  stVerifyDelete,
93  stScanDelete,
94  stStop,
95  stLast} ;
96 
97 
98 struct ThreadNdb
99 {
100  int ThreadNo;
101  NdbThread* threadLife;
102  StartType threadStart;
103  int threadResult;
104  int threadReady;
105 };
106 
107 extern "C" void* flexScanThread(void*);
108 static int setAttrNames(void);
109 static int setTableNames(void);
110 static int createTables(Ndb* pMyNdb);
111 static void sleepBeforeStartingTest(int seconds);
112 static int readArguments(int argc, const char** argv);
113 static void setAttrValues(int* attrValue,
114  int* readValue,
115  int Offset);
116 static int insertRows(Ndb* pNdb, int* pkValue, int* attrValue, StartType tType);
117 static int readRows(Ndb* pNdb, int* pkValue, int* readValue);
118 static int deleteRows(Ndb* pNdb, int* pkValue);
119 static int scanReadRows(Ndb* pNdb, int* readValue);
120 static int scanUpdateRows(Ndb* pNdb, int* readValue, int* attrValue);
121 static int scanDeleteRows(Ndb* pNdb, int* readValue);
122 static int verifyDeleteRows(Ndb* pNdb, int* pkValue, int* readValue);
123 static void Compare(int* attrValue, int* readValue);
124 static void UpdateArray(int *attrValue);
125 
126 static int tNoOfThreads = 1;
127 static int tNoOfAttributes = 25;
128 static int tNoOfTables = 1;
129 static int tAttributeSize = 1;
130 static int tNodeId = 0;
131 static int tNoOfOperations = 500;
132 static int tNoOfLoops = 1;
133 static int tAbortAfter = 0;
134 static int tParallellism = 1;
135 
136 static char tableName[MAXTABLES][MAXSTRLEN];
137 static char attrName[MAXATTR][MAXSTRLEN];
138 
139 static unsigned int tSleepTime = 0;
140 
141 static int theStdTableNameFlag = 0;
142 static int theTableCreateFlag = 0;
143 static int theScanAbortTestFlag = 0;
144 static int theNoScanUpdateFlag = 0;
145 static int theNoScanDeleteFlag = 0;
146 
147 //flexScanErrorData = new ErrorData;
148 ErrorData * flexScanErrorData;
149 NdbError * anerror;
150 
151 //static errorData theErrorData;
152 //static unsigned int tErrorCounter[6000];
153 
154 #define START_TIMER { NdbTimer timer; timer.doStart();
155 #define STOP_TIMER timer.doStop();
156 #define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
157 
158 static void UpdateArray(int *attrValue)
159 {
160  int tableCount = 0;
161  int attrCount = 0;
162  int opCount = 0;
163  int sizeCount = 0;
164  int* pValue = attrValue;
165 
166  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
167  for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
168  for (opCount = 0; opCount < tNoOfOperations; opCount++) {
169  for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) {
170  // Update value in array
171  (*pValue)++;
172  //ndbout << "attrValue[" << tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize +
173  //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount <<
174  //"] = " << attrValue[tableCount*tNoOfAttributes*tNoOfOperations*tAttributeSize +
175  //attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize + sizeCount] << endl;
176  // Increment pointer
177  pValue++;
178  } // sizeCount
179  } // for opCount
180  } // for attrCount
181  } // for tableCount
182 
183 } // Update
184 
185 static void Compare(int* attrValue, int* readValue)
186 {
187  int tableCount = 0;
188  int attrCount = 0;
189  int OpCount = 0;
190  int first = 0;
191 
192  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
193  for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
194  for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) {
195  if (memcmp(&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
196  attrCount*tNoOfOperations + OpCount]),
197  &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
198  attrCount*tNoOfOperations + OpCount]),
199  tAttributeSize) != 0) {
200  // Values mismatch
201  if (first == 0) {
202  //ndbout << "Read and set values differ for:" << endl;
203  first = 1;
204  ndbout << "Mismatch found.";
205  } // if
206  // Comparision of values after scan update is meaningless right now
207  //ndbout << " table " << tableName[tableCount] <<
208  //" - attr " << attrName[attrCount+1];
209  //for (sizeCount = 0; sizeCount < tAttributeSize; sizeCount++) {
210  //ndbout << ": set " <<
211  //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
212  //attrCount*tNoOfOperations*tAttributeSize +
213  //tNoOfOperations*tAttributeSize + sizeCount] << " read " <<
214  //readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
215  //attrCount*tNoOfOperations*tAttributeSize +
216  //tNoOfOperations*tAttributeSize + sizeCount] << endl;
217  //} // for
218  } // if
219  } // for OpCount
220  } // for attrCount
221  } // for tableCount
222 
223  // A final pretty-print
224  if (first == 1) {
225  ndbout << endl;
226  } // if
227 } // Compare
228 
229 static void printInfo()
230 {
231  ndbout << endl << "FLEXSCAN - Starting normal mode" << endl;
232  ndbout << "Perform benchmark of insert, update and delete transactions"<< endl;
233  ndbout << " NdbAPI node with id = " << tNodeId << endl;
234  ndbout << " " << tNoOfThreads << " thread(s) " << endl;
235  ndbout << " " << tNoOfLoops << " iterations " << endl;
236  ndbout << " " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction "
237  << endl;
238  ndbout << " " << tNoOfAttributes << " attributes per table incl. pk" << endl;
239  ndbout << " " << tNoOfOperations << " transaction(s) per thread and round " << endl;
240  if (theScanAbortTestFlag == 1) {
241  ndbout << " Scan abort test after " << tAbortAfter << " tuples" << endl;
242  } // if
243  ndbout << " " << tParallellism << " parallellism in scans" << endl;
244  ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute " <<
245  endl << endl;
246 
247 } // printInfo
248 
249 static void tellThreads(ThreadNdb *threadArrayP, StartType what)
250 {
251  int i = 0;
252 
253  for (i = 0; i < tNoOfThreads ; i++)
254  threadArrayP[i].threadStart = what;
255 } // tellThreads
256 
257 static void waitForThreads(ThreadNdb *threadArrayP)
258 {
259  int i = 0;
260  int cont = 1;
261 
262  while (cont == 1){
263 
264  NdbSleep_MilliSleep(10);
265  cont = 0;
266 
267  for (i = 0; i < tNoOfThreads ; i++) {
268  if (threadArrayP[i].threadReady == 0) {
269 // ndbout << "Main is reporting thread " << i << " not ready" << endl;
270  cont = 1;
271  } // if
272  } // for
273  } // while
274 } // waitForThreads
275 
276 
277 static void resetThreads(ThreadNdb *threadArrayP)
278 {
279  int i = 0;
280 
281  for (i = 0; i < tNoOfThreads ; i++) {
282  threadArrayP[i].threadReady = 0;
283  threadArrayP[i].threadResult = 0;
284  threadArrayP[i].threadStart = stIdle;
285  //ndbout << "threadStart[" << i << "]=" <<
286  //threadArrayP[i].threadStart << endl;
287  } // for
288 } // resetThreads
289 
290 static int checkThreadResults(ThreadNdb *threadArrayP, char *action)
291 {
292  int i = 0;
293  int retValue = 0;
294 
295  for (i = 0; i < tNoOfThreads; i++) {
296  if (threadArrayP[i].threadResult != 0) {
297  ndbout << "Thread " << i << " reported fatal error "
298  << threadArrayP[i].threadResult << " during " << action << endl;
299  retValue = -1;
300  break;
301  } // if
302  } // for
303 
304  return(retValue);
305 } // checkThreadResults
306 
307 NDB_COMMAND(flexScan, "flexScan", "flexScan", "flexScan", 65535)
308 {
309  ndb_init();
310  ThreadNdb* pThreads = NULL;
311  Ndb* pMyNdb = NULL;
312  int tLoops = 0;
313  int check = 0;
314  int returnValue = NDBT_OK;
315  int every2ndScanDelete = 0; // Switch between scan delete and normal delete
316 
317  flexScanErrorData = new ErrorData;
318 
319  flexScanErrorData->resetErrorCounters();
320 
321  if (readArguments(argc, argv) != 0) {
322  ndbout << "Wrong arguments to flexScan" << endl;
323  return NDBT_ProgramExit(NDBT_WRONGARGS);
324  } // if
325 
326  /* print Setting */
327  flexScanErrorData->printSettings(ndbout);
328 
329  check = setAttrNames();
330  if (check != 0) {
331  ndbout << "Couldn't set attribute names" << endl;
332  return NDBT_ProgramExit(NDBT_FAILED);
333  } // if
334  check = setTableNames();
335  if (check != 0) {
336  ndbout << "Couldn't set table names" << endl;
337  return NDBT_ProgramExit(NDBT_FAILED);
338  } // if
339 
340  pMyNdb = new Ndb ("TEST_DB");
341  pMyNdb->init();
342  tNodeId = pMyNdb->getNodeId();
343 
344  printInfo();
345 
346  NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
347  //NdbThread_SetConcurrencyLevel(tNoOfThreads + 8);
348 
349  pThreads = new ThreadNdb[tNoOfThreads];
350 
351  if (pMyNdb->waitUntilReady(10000) != 0) {
352  ndbout << "NDB is not ready" << endl << "Benchmark failed" << endl;
353  returnValue = NDBT_FAILED;
354  } // if
355 
356  else {
357 
358  if (createTables(pMyNdb) != 0) {
359  ndbout << "Could not create tables" << endl;
360  returnValue = NDBT_FAILED;
361  } // if
362  else {
363  sleepBeforeStartingTest(tSleepTime);
364 
365  resetThreads(pThreads);
366  // Create threads
367  for (int i = 0; i < tNoOfThreads ; i++){
368  pThreads[i].ThreadNo = i;
369  // Ignore the case that thread creation may fail
370  pThreads[i].threadLife = NdbThread_Create(flexScanThread,
371  (void**)&pThreads[i],
372  327680,
373  "flexScanThread", NDB_THREAD_PRIO_LOW);
374  if (pThreads[i].threadLife == NULL) {
375  ndbout << "Could not create thread " << i << endl;
376  returnValue = NDBT_FAILED;
377  // Use the number of threads that were actually created
378  tNoOfThreads = i;
379  break; // break for loop
380  } // if
381  } // for
382 
383  waitForThreads(pThreads);
384  if (checkThreadResults(pThreads, "init") != 0) {
385  returnValue = NDBT_FAILED;
386  } // if
387 
388  if (returnValue == NDBT_OK) {
389  ndbout << "All threads started" << endl;
390 
391  while (FOREVER) {
392 
393  resetThreads(pThreads);
394 
395  if ((tNoOfLoops != 0) && (tNoOfLoops <= tLoops)) {
396  break;
397  } // if
398 
399  // Insert
400  START_TIMER;
401 
402  tellThreads(pThreads, stInsert);
403  waitForThreads(pThreads);
404 
405  STOP_TIMER;
406  if (checkThreadResults(pThreads, "insert") != 0) {
407  returnValue = NDBT_FAILED;
408  break;
409  } // if
410  PRINT_TIMER("insert", tNoOfOperations*tNoOfThreads, tNoOfTables);
411 
412  resetThreads(pThreads);
413 
414  // Read
415  START_TIMER;
416 
417  tellThreads(pThreads, stRead);
418  waitForThreads(pThreads);
419 
420  STOP_TIMER;
421  if (checkThreadResults(pThreads, "read") != 0) {
422  returnValue = NDBT_FAILED;
423  break;
424  } // if
425  PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
426 
427  resetThreads(pThreads);
428 
429  // Update
430  START_TIMER;
431 
432  tellThreads(pThreads, stUpdate);
433  waitForThreads(pThreads);
434 
435  STOP_TIMER;
436  if (checkThreadResults(pThreads, "update") != 0) {
437  returnValue = NDBT_FAILED;
438  break;
439  } // if
440  PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
441 
442  resetThreads(pThreads);
443 
444  // Scan read
445  START_TIMER;
446 
447  tellThreads(pThreads, stScanRead);
448  waitForThreads(pThreads);
449 
450  STOP_TIMER;
451  if (checkThreadResults(pThreads, "scanread") != 0) {
452  returnValue = NDBT_FAILED;
453  break;
454  } // if
455  PRINT_TIMER("scanread", tNoOfTables*tNoOfThreads, 1);
456 
457  resetThreads(pThreads);
458 
459  // Update
460  START_TIMER;
461 
462  tellThreads(pThreads, stUpdate);
463  waitForThreads(pThreads);
464 
465  STOP_TIMER;
466  if (checkThreadResults(pThreads, "update") != 0) {
467  returnValue = NDBT_FAILED;
468  break;
469  } // if
470  PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
471 
472  resetThreads(pThreads);
473 
474  // Read
475  START_TIMER;
476 
477  tellThreads(pThreads, stRead);
478  waitForThreads(pThreads);
479 
480  STOP_TIMER;
481  if (checkThreadResults(pThreads, "read") != 0) {
482  returnValue = NDBT_FAILED;
483  break;
484  } // if
485  PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
486 
487  resetThreads(pThreads);
488 
489  // Only do scan update if told to do so
490  if (theNoScanUpdateFlag == 0) {
491  // Scan update
492  START_TIMER;
493 
494  tellThreads(pThreads, stScanUpdate);
495  waitForThreads(pThreads);
496 
497  STOP_TIMER;
498  if (checkThreadResults(pThreads, "scanupdate") != 0) {
499  returnValue = NDBT_FAILED;
500  break;
501  } // if
502  PRINT_TIMER("scanupdate", tNoOfTables*tNoOfThreads, 1);
503 
504  resetThreads(pThreads);
505 
506  // Read
507  START_TIMER;
508 
509  tellThreads(pThreads, stRead);
510  // tellThreads(pThreads, stScanRead);
511  waitForThreads(pThreads);
512 
513  STOP_TIMER;
514  if (checkThreadResults(pThreads, "read") != 0) {
515  returnValue = NDBT_FAILED;
516  break;
517  } // if
518  PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
519 
520  resetThreads(pThreads);
521  } // if theNoScanUpdateFlag
522 
523  // Shift between delete and scan delete
524  if ((every2ndScanDelete % 2 == 0) || (theNoScanDeleteFlag == 1)){
525  // Delete
526  START_TIMER;
527  tellThreads(pThreads, stDelete);
528  waitForThreads(pThreads);
529 
530  STOP_TIMER;
531  if (checkThreadResults(pThreads, "delete") != 0) {
532  returnValue = NDBT_FAILED;
533  break;
534  } // if
535  PRINT_TIMER("delete", tNoOfOperations*tNoOfThreads, tNoOfTables);
536  resetThreads(pThreads);
537  } // if
538  else {
539  resetThreads(pThreads); // Scan delete
540  START_TIMER;
541  tellThreads(pThreads, stScanDelete);
542  waitForThreads(pThreads);
543 
544  STOP_TIMER;
545  if (checkThreadResults(pThreads, "scandelete") != 0) {
546  returnValue = NDBT_FAILED;
547  break;
548  } // if
549  PRINT_TIMER("scandelete", tNoOfTables*tNoOfThreads, 1);
550 
551  resetThreads(pThreads);
552  } // else
553  every2ndScanDelete++;
554 
555  resetThreads(pThreads); // Verify delete
556  START_TIMER;
557  tellThreads(pThreads, stVerifyDelete);
558  waitForThreads(pThreads);
559 
560  STOP_TIMER;
561  if (checkThreadResults(pThreads, "verifydelete") != 0) {
562  returnValue = NDBT_FAILED;
563  break;
564  } // if
565  PRINT_TIMER("verifydelete", tNoOfOperations*tNoOfThreads*tNoOfTables, 1);
566 
567  resetThreads(pThreads);
568 
569  ndbout << "--------------------------------------------------" << endl;
570  tLoops++;
571 
572  } // while
573  } // if
574  } // else
575  } // else
576 
577  // Stop threads in a nice way
578  tellThreads(pThreads, stStop);
579  waitForThreads(pThreads);
580 
581  // Clean up
582  delete [] pThreads;
583  delete pMyNdb;
584 
585  flexScanErrorData->printErrorCounters(ndbout);
586 
587  if (returnValue == NDBT_OK) {
588  ndbout << endl << "Benchmark completed successfully" << endl;
589  } // if
590  else {
591  ndbout << endl << "Benchmark failed" << endl;
592  } // else
593 
594  // Exit via NDBT
595  return NDBT_ProgramExit(returnValue);;
596 } // main
597 
598 void*
599 flexScanThread(void* ThreadData)
600 {
601  ThreadNdb* pThreadData = (ThreadNdb*)ThreadData;
602  unsigned int thread_no = pThreadData->ThreadNo;
603  unsigned int thread_base = (thread_no * 2000000) + (tNodeId * 26000);
604  int tThreadResult = 0;
605  Ndb* MyNdb = NULL;
606  int check = 0;
607  StartType tType = stLast;
608  int* pkValue = NULL;
609  int* attrValue = NULL;
610  int* readValue = NULL;
611  int AllocSize = 0;
612 
613  AllocSize = tNoOfTables * (tNoOfAttributes-1) * tNoOfOperations *
614  tAttributeSize * sizeof(int);
615  attrValue = (int*)malloc(AllocSize);
616  readValue = (int*)malloc(AllocSize);
617  pkValue = (int*)malloc(tNoOfOperations * sizeof(int));
618  if ((attrValue == NULL) || (readValue == NULL) || (pkValue == NULL)) {
619  tThreadResult = 98;
620  pThreadData->threadStart = stIdle;
621  } // if
622 
623  setAttrValues(attrValue, readValue, thread_base);
624 
625  MyNdb = new Ndb( "TEST_DB" );
626  MyNdb->init();
627  if (MyNdb->waitUntilReady(10000) != 0) {
628  tThreadResult = 99;
629  pThreadData->threadStart = stIdle;
630  } // if
631 
632  // Set primary key value, same for all tables
633  for (int c = 0; c < tNoOfOperations; c++) {
634  pkValue[c] = (int)(c + thread_base);
635  } // for
636 
637  while (FOREVER) {
638  pThreadData->threadResult = tThreadResult;
639  pThreadData->threadReady = 1;
640 
641  while (pThreadData->threadStart == stIdle) {
642  NdbSleep_MilliSleep(10);
643  } // while
644 
645  // Check if signal to exit is received
646  if (pThreadData->threadStart >= stStop){
647  pThreadData->threadReady = 1;
648  break;
649  } // if
650  tType = pThreadData->threadStart;
651  pThreadData->threadStart = stIdle;
652 
653  switch (tType) {
654  case stInsert:
655  check = insertRows(MyNdb, pkValue, attrValue, tType);
656  break;
657  case stRead:
658  check = readRows(MyNdb, pkValue, readValue);
659  Compare(attrValue, readValue);
660  break;
661  case stUpdate:
662  UpdateArray(attrValue);
663  check = insertRows(MyNdb, pkValue, attrValue, tType);
664  break;
665  case stScanRead:
666  //check = readRows(MyNdb, pkValue, readValue);
667  check = scanReadRows(MyNdb, readValue);
668  Compare(attrValue, readValue);
669  break;
670  case stScanUpdate:
671  UpdateArray(attrValue);
672  //tType = stUpdate;
673  //check = insertRows(MyNdb, pkValue, attrValue, tType);
674  check = scanUpdateRows(MyNdb, readValue, attrValue);
675  break;
676  case stDelete:
677  check = deleteRows(MyNdb, pkValue);
678  break;
679  case stScanDelete:
680  check = scanDeleteRows(MyNdb, readValue);
681  break;
682  case stVerifyDelete:
683  check = verifyDeleteRows(MyNdb, pkValue, readValue);
684  break;
685  default:
686  ndbout << "tType is " << tType << endl;
687  assert(false);
688  break;
689  } // switch
690 
691  tThreadResult = check;
692 
693  if (tThreadResult != 0) {
694  // Check if error is fatak or not
695  } // if
696  else {
697  continue;
698  } // else
699  } // while
700 
701  // Clean up
702  delete MyNdb;
703  if (attrValue != NULL) {
704  free(attrValue);
705  } //if
706  if (readValue != NULL) {
707  free(readValue);
708  } // if
709  if (pkValue != NULL) {
710  free(pkValue);
711  } // if
712 
713  return NULL; // thread exits
714 
715 } // flexScanThread
716 
717 
718 static int setAttrNames()
719 {
720  int i = 0;
721  int retVal = 0;
722 
723  for (i = 0; i < MAXATTR ; i++) {
724  retVal = BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
725  if (retVal < 0) {
726  return(-1);
727  } // if
728  } // for
729 
730  return(0);
731 } // setAttrNames
732 
733 
734 static int setTableNames()
735 {
736  // Note! Uses only uppercase letters in table name's
737  // so that we can look at the tables with SQL
738  int i = 0;
739  int retVal = 0;
740 
741  for (i = 0; i < MAXTABLES ; i++) {
742 
743  if (theStdTableNameFlag == 0) {
744  retVal = BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i,
745  (int)(NdbTick_CurrentMillisecond() / 1000));
746  } // if
747  else {
748  retVal = BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
749  } // if else
750 
751  if (retVal < 0) {
752  return(-1);
753  } // if
754  } // for
755 
756  return(0);
757 } // setTableNames
758 
759 
760 // Create Table and Attributes.
761 static int createTables(Ndb* pMyNdb)
762 {
763 
764  NdbSchemaCon *MySchemaTransaction = NULL;
765  NdbSchemaOp *MySchemaOp = NULL;
766  int i = 0;
767  int j = 0;
768  int check = 0;
769 
770  if (theTableCreateFlag == 0) {
771 
772  i = 0;
773  do {
774  i++;
775  ndbout << endl << "Creating " << tableName[i - 1] << "..." << endl;
776 
777  MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pMyNdb);
778  if( MySchemaTransaction == NULL ) {
779  return (-1);
780  } // if
781 
782  MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
783  if( MySchemaOp == NULL ) {
784  NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
785  return (-1);
786  } // if
787 
788  check = MySchemaOp->createTable(tableName[i - 1]
789  ,8 // Table Size
790  ,TupleKey // Key Type
791  ,40); // Nr of Pages
792 
793  if (check == -1) {
794  NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
795  return -1;
796  } // if
797 
798  check = MySchemaOp->createAttribute( (char*)attrName[0], TupleKey, 32, PKSIZE,
799  UnSigned, MMBased, NotNullAttribute );
800  if (check == -1) {
801  NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
802  return -1;
803  } // if
804 
805  for (j = 1; j < tNoOfAttributes ; j++) {
806  check = MySchemaOp->createAttribute( (char*)attrName[j], NoKey, 32, tAttributeSize,
807  UnSigned, MMBased, NotNullAttribute );
808  if (check == -1) {
809  NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
810  return -1;
811  } // if
812  } // for
813 
814  if (MySchemaTransaction->execute() == -1) {
815  ndbout << MySchemaTransaction->getNdbError().message << endl;
816  ndbout << "Probably, " << tableName[i - 1] << " already exist" << endl;
817  } // if
818 
819  NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
820  } while (tNoOfTables > i);
821  }
822 
823  return 0;
824 } // createTables
825 
826 static void printUsage()
827 {
828  ndbout << "Usage of flexScan:" << endl;
829  ndbout << "-f <path> Location of my.cnf file, default: my.cnf" << endl;
830  ndbout << "-t <int> Number of threads to start, default 1" << endl;
831  ndbout << "-o <int> Number of operations per loop, default 500" << endl;
832  ndbout << "-l <int> Number of loops to run, default 1, 0=infinite" << endl;
833  ndbout << "-a <int> Number of attributes, default 25" << endl;
834  ndbout << "-c <int> Number of tables, default 1" << endl;
835  ndbout << "-s <int> Size of each attribute, default 1" << endl;
836  ndbout << "-stdtables Use standard table names" << endl;
837  ndbout << "-no_table_create Don't create tables in db" << endl;
838  ndbout << "-sleep <int> Sleep a number of seconds before running the test" << endl;
839  ndbout << "-p <int> Parallellism to use 1-32, default:1" << endl;
840  ndbout << "-abort <int> Test scan abort after a number of tuples" << endl;
841  ndbout << "-no_scan_update Don't do scan updates" << endl;
842  ndbout << "-no_scan_delete Don't do scan deletes" << endl;
843  ndbout << "-h Print this text" << endl;
844  // inputErrorArg();
845  flexScanErrorData->printCmdLineArgs(ndbout);
846 }
847 
848 static int readArguments(int argc, const char** argv)
849 {
850  int i = 1;
851  int retValue = 0;
852  int printFlag = 0;
853 
854  tNoOfThreads = 1; // Set default Value
855  tNoOfTables = 1; // Default Value
856 
857  while (argc > 1) {
858  if (strcmp(argv[i], "-t") == 0) {
859  if (argv[i + 1] != NULL) {
860  tNoOfThreads = atoi(argv[i + 1]);
861  if ((tNoOfThreads < 1) || (tNoOfThreads > NDB_MAXTHREADS)) {
862  retValue = -1;
863  } // if
864  } // if
865  else {
866  retValue = -1;
867  } // else
868  } // if
869  else if (strcmp(argv[i], "-o") == 0) {
870  if (argv[i + 1] != NULL) {
871  tNoOfOperations = atoi(argv[i + 1]);
872  if (tNoOfOperations < 1) {
873  retValue = -1;
874  } // if
875  } // if
876  else {
877  retValue = -1;
878  } // else
879  } // else if
880  else if (strcmp(argv[i], "-a") == 0) {
881  if (argv[i + 1] != NULL) {
882  tNoOfAttributes = atoi(argv[i + 1]);
883  if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR)) {
884  retValue = -1;
885  } // if
886  } // if
887  else {
888  retValue = -1;
889  } // else
890  } // else if
891  else if (strcmp(argv[i], "-c") == 0) {
892  if (argv[i + 1] != NULL) {
893  tNoOfTables = atoi(argv[i+1]);
894  if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES)) {
895  retValue = -1;
896  } // if
897  } // if
898  else {
899  retValue = -1;
900  } // else
901  } // else if
902  else if (strcmp(argv[i], "-l") == 0) {
903  if (argv[i + 1] != NULL) {
904  tNoOfLoops = atoi(argv[i+1]);
905  if ((tNoOfLoops < 0) || (tNoOfLoops > 100000)) {
906  retValue = -1;
907  } // if
908  } // if
909  else {
910  retValue = -1;
911  } // else
912  } // else if
913  else if (strcmp(argv[i], "-s") == 0) {
914  if (argv[i + 1] != NULL) {
915  tAttributeSize = atoi(argv[i+1]);
916  if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE)) {
917  retValue = -1;
918  } // if
919  } // if
920  else {
921  retValue = -1;
922  } // else
923  } // else if
924  else if (strcmp(argv[i], "-no_table_create") == 0) {
925  theTableCreateFlag = 1;
926  argc++;
927  i--;
928  } // else if
929  else if (strcmp(argv[i], "-stdtables") == 0) {
930  theStdTableNameFlag = 1;
931  argc++;
932  i--;
933  } // else if
934  else if (strcmp(argv[i], "-sleep") == 0) {
935  if (argv[i + 1] != NULL) {
936  tSleepTime = atoi(argv[i+1]);
937  if ((tSleepTime < 1) || (tSleepTime > 3600)) {
938  retValue = -1;
939  } // if
940  } // if
941  else {
942  retValue = -1;
943  } // else
944  } // else if
945  else if (strcmp(argv[i], "-abort") == 0) {
946  // Test scan abort after a number of tuples
947  theScanAbortTestFlag = 1;
948  if (argv[i + 1] != NULL) {
949  tAbortAfter = atoi(argv[i + 1]);
950  } // if
951  else {
952  retValue = -1;
953  } // else
954  } // else if
955  else if (strcmp(argv[i], "-p") == 0) {
956  if (argv[i + 1] != NULL) {
957  tParallellism = atoi(argv[i + 1]);
958  if ((tParallellism < 1) || (tParallellism > 32)) {
959  retValue = -1;
960  } // if
961  } // if
962  else {
963  retValue = -1;
964  } // else
965  } // else if
966  else if (strcmp(argv[i], "-h") == 0) {
967  printFlag = 1;
968  argc++;
969  i--;
970  } // else if
971  else if (strcmp(argv[i], "-no_scan_update") == 0) {
972  theNoScanUpdateFlag = 1;
973  argc++;
974  i--;
975  } // else if
976  else if (strcmp(argv[i], "-no_scan_delete") == 0) {
977  theNoScanDeleteFlag = 1;
978  argc++;
979  i--;
980  } // else if
981  else {
982  retValue = -1;
983  } // else
984 
985  argc -= 2;
986  i = i + 2;
987  }
988 
989  if ((retValue != 0) || (printFlag == 1)) {
990  printUsage();
991  } // if
992 
993  return(retValue);
994 
995 } // readArguments
996 
997 static void sleepBeforeStartingTest(int seconds)
998 {
999  if (seconds > 0) {
1000  ndbout << "Sleeping(" <<seconds << ")...";
1001  NdbSleep_SecSleep(seconds);
1002  ndbout << " done!" << endl;
1003  } // if
1004 } // sleepBeforeStartingTest
1005 
1006 static void setAttrValues(int* attrValue,
1007  int* readValue,
1008  int Offset)
1009 {
1010  int tableCount = 0;
1011  int attrCount = 0;
1012  int OpCount = 0;
1013  int attrSize = 0;
1014  int* pAttr = NULL;
1015  int* pRead = NULL;
1016 
1017  // Set attribute values in memory array
1018  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1019  for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
1020  for (OpCount = 0; OpCount < tNoOfOperations; OpCount++) {
1021  pAttr = &(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
1022  attrCount*tNoOfOperations + OpCount]);
1023  pRead = &(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
1024  attrCount*tNoOfOperations + OpCount]);
1025  for (attrSize = 0; attrSize < tAttributeSize; attrSize++){
1026  *pAttr = (int)(Offset + tableCount + attrCount + OpCount + attrSize);
1027  //ndbout << "attrValue[" << tableCount*(tNoOfAttributes-1)*tNoOfOperations +
1028  //attrCount*tNoOfOperations + OpCount + attrSize << "] = " <<
1029  //attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
1030  //attrCount*tNoOfOperations + OpCount + attrSize] << endl;
1031  *pRead = 0;
1032  pAttr++;
1033  pRead++;
1034  } // for attrSize
1035  } // for OpCount
1036  } // for attrCount
1037  } // for tableCount
1038 
1039 } // setAttrValues
1040 
1041 static int insertRows(Ndb* pNdb, // NDB object
1042  int* pkValue, // Primary key values
1043  int* attrValue, // Attribute values
1044  StartType tType)
1045 {
1046  int tResult = 0;
1047  int check = 0;
1048  int tableCount = 0;
1049  int attrCount = 0;
1050  NdbConnection* MyTransaction = NULL;
1051  NdbOperation* MyOperations[MAXTABLES] = {NULL};
1052  int opCount = 0;
1053 
1054  for (opCount = 0; opCount < tNoOfOperations; opCount++) {
1055  MyTransaction = pNdb->startTransaction();
1056  if (MyTransaction == NULL) {
1057  tResult = 1;
1058  } // if
1059  else {
1060  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1061 
1062  MyOperations[tableCount] =
1063  MyTransaction->getNdbOperation(tableName[tableCount]);
1064  if (MyOperations[tableCount] == NULL) {
1065  tResult = 2;
1066  // Break for tableCount loop
1067  break;
1068  } // if
1069 
1070  if (tType == stUpdate) {
1071  check = MyOperations[tableCount]->updateTuple();
1072  } // if
1073  else if (tType == stInsert) {
1074  check = MyOperations[tableCount]->insertTuple();
1075  } // else if
1076  else {
1077  assert(false);
1078  } // else
1079 
1080  if (check == -1) {
1081  tResult = 3;
1082  break;
1083  } // if
1084  check = MyOperations[tableCount]->equal((char*)attrName[0],
1085  (char*)&(pkValue[opCount]));
1086  if (check == -1) {
1087  tResult = 7;
1088  break;
1089  } // if
1090 
1091  for (attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
1092  int Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
1093  attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
1094  check = MyOperations[tableCount]->
1095  setValue((char*)attrName[attrCount + 1],
1096  (char*)&(attrValue[Index]));
1097  if (check == -1) {
1098  tResult = 8;
1099  break; // break attrCount loop
1100  } // if
1101  } // for
1102  } // for tableCount
1103 
1104  // Execute transaction with insert one tuple in every table
1105  check = MyTransaction->execute(Commit);
1106  if (check == -1) {
1107  ndbout << MyTransaction->getNdbError().message << endl;
1108 
1109  // Add complete error handling here
1110 
1111  int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
1112  if (retCode == 1) {
1113  if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
1114  ndbout_c("execute: %d, %d, %s", opCount, tType, MyTransaction->getNdbError().message);
1115  ndbout_c("Error code = %d", MyTransaction->getNdbError().code);}
1116  tResult = 20;
1117  } else if (retCode == 2) {
1118  ndbout << "4115 should not happen in flexBench" << endl;
1119  tResult = 20;
1120  } else if (retCode == 3) {
1121 // --------------------------------------------------------------------
1122 // We are not certain if the transaction was successful or not.
1123 // We must reexecute but might very well find that the transaction
1124 // actually was updated. Updates and Reads are no problem here. Inserts
1125 // will not cause a problem if error code 630 arrives. Deletes will
1126 // not cause a problem if 626 arrives.
1127 // --------------------------------------------------------------------
1128  /* What can we do here? */
1129  ndbout_c("execute: %s", MyTransaction->getNdbError().message);
1130  }//if(retCode == 3)
1131 
1132  } // if(check == -1)
1133 
1134  pNdb->closeTransaction(MyTransaction);
1135  } // else
1136  } // for opCount
1137 
1138  return(tResult);
1139 } // insertRows
1140 
1141 static int readRows(Ndb* pNdb,
1142  int* pkValue,
1143  int* readValue)
1144 {
1145  int tResult = 0;
1146  int tableCount = 0;
1147  int attrCount = 0;
1148  int check = 0;
1149  NdbConnection* MyTransaction = NULL;
1150  NdbOperation* MyOperations[MAXTABLES] = {NULL};
1151  NdbRecAttr* tmp = NULL;
1152  int Value = 0;
1153  int Index = 0;
1154  int opCount = 0;
1155 
1156  for (opCount = 0; opCount < tNoOfOperations; opCount++) {
1157  MyTransaction = pNdb->startTransaction();
1158  if (MyTransaction == NULL) {
1159  tResult = 1;
1160  } // if
1161  else {
1162  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1163 
1164  MyOperations[tableCount] =
1165  MyTransaction->getNdbOperation(tableName[tableCount]);
1166  if (MyOperations[tableCount] == NULL) {
1167  tResult = 2;
1168  // Break for tableCount loop
1169  break;
1170  } // if
1171 
1172  check = MyOperations[tableCount]->readTuple();
1173  if (check == -1) {
1174  tResult = 3;
1175  break;
1176  } // if
1177 
1178  check = MyOperations[tableCount]->
1179  equal((char*)attrName[0], (char*)&(pkValue[opCount]));
1180  if (check == -1) {
1181  tResult = 7;
1182  break;
1183  } // if
1184 
1185  for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
1186  Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
1187  attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
1188  tmp = MyOperations[tableCount]->
1189  getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index]));
1190 
1191  if (tmp == NULL) {
1192  tResult = 9;
1193  break;
1194  } // if
1195  } // for attrCount
1196  } // for tableCount
1197  // Execute transaction reading one tuple in every table
1198  check = MyTransaction->execute(Commit);
1199  if (check == -1) {
1200  ndbout << MyTransaction->getNdbError().message << endl;
1201 
1202  // Add complete error handling here
1203 
1204  int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
1205  if (retCode == 1) {
1206  if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
1207  ndbout_c("execute: %d, %s", opCount, MyTransaction ->getNdbError().message );
1208  ndbout_c("Error code = %d", MyTransaction->getNdbError().code );}
1209  tResult = 20;
1210  } else if (retCode == 2) {
1211  ndbout << "4115 should not happen in flexBench" << endl;
1212  tResult = 20;
1213  } else if (retCode == 3) {
1214 // --------------------------------------------------------------------
1215 // We are not certain if the transaction was successful or not.
1216 // We must reexecute but might very well find that the transaction
1217 // actually was updated. Updates and Reads are no problem here. Inserts
1218 // will not cause a problem if error code 630 arrives. Deletes will
1219 // not cause a problem if 626 arrives.
1220 // --------------------------------------------------------------------
1221  /* What can we do here? */
1222  ndbout_c("execute: %s", MyTransaction ->getNdbError().message );
1223  }//if(retCode == 3)
1224 
1225  } // if
1226 
1227  pNdb->closeTransaction(MyTransaction);
1228  } // else
1229  } // for opCount
1230 
1231  return(tResult);
1232 } // readRows
1233 
1234 static int scanReadRows(Ndb* pNdb, int* readValue)
1235 {
1236  int tResult = 0;
1237  int tableCount = 0;
1238  int attrCount = 0;
1239  int check = 0;
1240  int countAbort = 0; // Counts loops until scan abort if requested
1241  NdbConnection* MyTransaction = NULL;
1242  NdbOperation* MyOperation = NULL;
1243  NdbRecAttr* tmp = NULL;
1244 
1245 
1246  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1247  MyTransaction = pNdb->startTransaction();
1248  if (MyTransaction == NULL) {
1249  tResult = 1;
1250  break;
1251  } // if
1252  MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
1253  if (MyOperation == NULL) {
1254  tResult = 2;
1255  break;
1256  } // if
1257 
1258  check = MyOperation->openScanRead(tParallellism);
1259  if (check == -1) {
1260  tResult = 10;
1261  break;
1262  } // if
1263 
1264  for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
1265  // Get all attributes
1266  tmp = MyOperation->
1267  getValue((char*)attrName[attrCount+1],
1268  (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
1269  attrCount*tNoOfOperations*tAttributeSize]));
1270  if (tmp == NULL) {
1271  tResult = 9;
1272  break;
1273  } // if
1274  } // for attrCount
1275 
1276  check = MyTransaction->executeScan();
1277  if (check == -1) {
1278  tResult = 12;
1279  break;
1280  } // if
1281 
1282  check = MyTransaction->nextScanResult();
1283  while (check == 0) {
1284  // Check if scan abort is requested
1285  if (theScanAbortTestFlag == 1) {
1286  if (countAbort == tAbortAfter) {
1287  MyTransaction->stopScan();
1288  ndbout << "scanread aborted on request after " << countAbort*tParallellism <<
1289  " tuples" << endl;
1290  break; // break while loop
1291  } // if
1292  countAbort++;
1293  } // if
1294  check = MyTransaction->nextScanResult();
1295  } // while
1296 
1297  pNdb->closeTransaction(MyTransaction);
1298  } // for tableCount
1299 
1300  return(tResult);
1301 } // scanReadRows
1302 
1303 static int scanUpdateRows(Ndb* pNdb,
1304  int* readValue,
1305  int* attrValue)
1306 {
1307  int tResult = 0;
1308  int tableCount = 0;
1309  int attrCount = 0;
1310  int check = 0;
1311  int opCount = 0;
1312  NdbConnection* MyTransaction = NULL;
1313  NdbOperation* MyOperation = NULL;
1314  NdbConnection* MyTakeOverTrans = NULL;
1315  NdbOperation* MyTakeOverOp = NULL;
1316  NdbRecAttr* tTmp = NULL;
1317 
1318  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1319  MyTransaction = pNdb->startTransaction();
1320  if (MyTransaction == NULL) {
1321  tResult = 1;
1322  break; // break tableCount for loop
1323  } // if
1324  MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
1325  if (MyOperation == NULL) {
1326  tResult = 2;
1327  break;
1328  } // if
1329 
1330  check = MyOperation->openScanExclusive(tParallellism);
1331  if (check == -1) {
1332  tResult = 11;
1333  break;
1334  } // if
1335 
1336  // Fetch all attributes
1337  for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
1338  tTmp = MyOperation->
1339  getValue((char*)attrName[attrCount+1],
1340  (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
1341  attrCount*tNoOfOperations*tAttributeSize]));
1342  if (tTmp == NULL) {
1343  tResult = 9;
1344  break; // break for loop
1345  } // if
1346  } // for
1347  if (tResult != 0) {
1348  break; // break while loop also
1349  } // if
1350 
1351  check = MyTransaction->executeScan();
1352  if (check == -1) {
1353  tResult = 12;
1354  break;
1355  } // if
1356  check = MyTransaction->nextScanResult();
1357  opCount = 0;
1358  while (check == 0) {
1359  MyTakeOverTrans = pNdb->startTransaction();
1360  MyTakeOverOp = MyOperation->takeOverForUpdate(MyTakeOverTrans);
1361  for (attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
1362  check = MyTakeOverOp->setValue((char*)attrName[attrCount+1],
1363  (char*)&(attrValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations*tAttributeSize +
1364  attrCount*tNoOfOperations*tAttributeSize + opCount*tAttributeSize]));
1365  } // for
1366 
1367  check = MyTakeOverTrans->execute(Commit);
1368  if (check == 0) {
1369  check = MyTransaction->nextScanResult();
1370  opCount++;
1371  } // if
1372  else {
1373  tResult = 95;
1374 
1375  /* MyTransaction, MyTakeOverTrans, Which one? */
1376 
1377  // Any further error handling?
1378  int retCode = flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError());
1379  if (retCode == 1) {
1380  if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){
1381  ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message);
1382  ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code);}
1383  tResult = 20;
1384  } else if (retCode == 2) {
1385  ndbout << "4115 should not happen in flexBench" << endl;
1386  tResult = 20;
1387  } else if (retCode == 3) {
1388  // --------------------------------------------------------------------
1389  // We are not certain if the transaction was successful or not.
1390  // We must reexecute but might very well find that the transaction
1391  // actually was updated. Updates and Reads are no problem here. Inserts
1392  // will not cause a problem if error code 630 arrives. Deletes will
1393  // not cause a problem if 626 arrives.
1394  // --------------------------------------------------------------------
1395  /* What can we do here? */
1396  ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message);
1397  }//if(retCode == 3)
1398 
1399  } // else
1400  pNdb->closeTransaction(MyTakeOverTrans);
1401  } // while
1402 
1403  pNdb->closeTransaction(MyTransaction);
1404  } // for
1405 
1406  return(tResult);
1407 } // scanUpdateRows
1408 
1409 static int scanDeleteRows(Ndb* pNdb, int* readValue)
1410 {
1411  int tResult = 0;
1412  int tableCount = 0;
1413  int attrCount = 0;
1414  int check = 0;
1415  NdbRecAttr* tTmp = NULL;
1416  NdbConnection* MyTransaction = NULL;
1417  NdbOperation* MyOperation = NULL;
1418  NdbConnection* MyTakeOverTrans = NULL;
1419  NdbOperation* MyTakeOverOp = NULL;
1420 
1421  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1422  MyTransaction = pNdb->startTransaction();
1423  if (MyTransaction == NULL) {
1424  tResult = 1;
1425  break; // break tableCount for loop
1426  } // if
1427 
1428  MyOperation = MyTransaction->getNdbOperation(tableName[tableCount]);
1429  if (MyOperation == NULL) {
1430  tResult = 2;
1431  break;
1432  } // if
1433 
1434  check = MyOperation->openScanExclusive(tParallellism);
1435  if (check == -1) {
1436  tResult = 11;
1437  break;
1438  } // if
1439 
1440  for (int attrCount = 0; attrCount < tNoOfAttributes-1; attrCount++) {
1441  tTmp = MyOperation->
1442  getValue((char*)attrName[attrCount+1],
1443  (char*)&(readValue[tableCount*(tNoOfAttributes-1)*tNoOfOperations +
1444  attrCount*tNoOfOperations]));
1445  if (tTmp == NULL) {
1446  tResult = 9;
1447  break;
1448  } // if
1449  } // for
1450 
1451  check = MyTransaction->executeScan();
1452  if (check == -1) {
1453  tResult = 12;
1454  break;
1455  } // if
1456  check = MyTransaction->nextScanResult();
1457  while (check == 0) {
1458  MyTakeOverTrans = pNdb->startTransaction();
1459  MyTakeOverOp = MyOperation->takeOverForDelete(MyTakeOverTrans);
1460  check = MyTakeOverOp->deleteTuple();
1461 
1462  check = MyTakeOverTrans->execute(Commit);
1463 
1464  //Error handling here
1465 
1466  int retCode =flexScanErrorData->handleErrorCommon(MyTakeOverTrans->getNdbError());
1467  if (retCode == 1) {
1468  if (MyTakeOverTrans->getNdbError().code != 626 && MyTakeOverTrans->getNdbError().code != 630){
1469  ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message );
1470  ndbout_c("Error code = %d", MyTakeOverTrans->getNdbError().code );}
1471  tResult = 20;
1472  } else if (retCode == 2) {
1473  ndbout << "4115 should not happen in flexBench" << endl;
1474  tResult = 20;
1475  } else if (retCode == 3) {
1476 // --------------------------------------------------------------------
1477 // We are not certain if the transaction was successful or not.
1478 // We must reexecute but might very well find that the transaction
1479 // actually was updated. Updates and Reads are no problem here. Inserts
1480 // will not cause a problem if error code 630 arrives. Deletes will
1481 // not cause a problem if 626 arrives.
1482 // --------------------------------------------------------------------
1483  /* What can we do here? */
1484  ndbout_c("execute: %s", MyTakeOverTrans->getNdbError().message );
1485  }//if(retCode == 3) End of error handling
1486 
1487  pNdb->closeTransaction(MyTakeOverTrans);
1488  check = MyTransaction->nextScanResult();
1489  } // while
1490  pNdb->closeTransaction(MyTransaction);
1491  } // for tableCount
1492  return(tResult);
1493 } // scanDeleteRows
1494 
1495 static int deleteRows(Ndb* pNdb,
1496  int* pkValue)
1497 {
1498  int tResult = 0;
1499  NdbConnection* MyTransaction = NULL;
1500  int tableCount = 0;
1501  int opCount = 0;
1502  int check = 0;
1503  NdbOperation* MyOperations[MAXTABLES] = {NULL};
1504 
1505  for (opCount = 0; opCount < tNoOfOperations; opCount++) {
1506  MyTransaction = pNdb->startTransaction();
1507  if (MyTransaction == NULL) {
1508  tResult = 1;
1509  } // if
1510  else {
1511  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1512 
1513  MyOperations[tableCount] =
1514  MyTransaction->getNdbOperation(tableName[tableCount]);
1515  if (MyOperations[tableCount] == NULL) {
1516  tResult = 2;
1517  // Break for tableCount loop
1518  break;
1519  } // if
1520 
1521  check = MyOperations[tableCount]->deleteTuple();
1522  if (check == -1) {
1523  tResult = 3;
1524  break;
1525  } // if
1526 
1527  check = MyOperations[tableCount]->
1528  equal((char*)attrName[0], (char*)&(pkValue[opCount]));
1529  if (check == -1) {
1530  tResult = 7;
1531  break;
1532  } // if
1533 
1534  } // for tableCount
1535 
1536  // Execute transaction deleting one tuple in every table
1537  check = MyTransaction->execute(Commit);
1538  if (check == -1) {
1539  ndbout << MyTransaction->getNdbError().message << endl;
1540  // Add complete error handling here
1541 
1542  int retCode = flexScanErrorData->handleErrorCommon(MyTransaction->getNdbError());
1543  if (retCode == 1) {
1544  if (MyTransaction->getNdbError().code != 626 && MyTransaction->getNdbError().code != 630){
1545  ndbout_c("execute: %d, %s", opCount, MyTransaction->getNdbError().message );
1546  ndbout_c("Error code = %d", MyTransaction->getNdbError().code );}
1547  tResult = 20;
1548  } else if (retCode == 2) {
1549  ndbout << "4115 should not happen in flexBench" << endl;
1550  tResult = 20;
1551  } else if (retCode == 3) {
1552 // --------------------------------------------------------------------
1553 // We are not certain if the transaction was successful or not.
1554 // We must reexecute but might very well find that the transaction
1555 // actually was updated. Updates and Reads are no problem here. Inserts
1556 // will not cause a problem if error code 630 arrives. Deletes will
1557 // not cause a problem if 626 arrives.
1558 // --------------------------------------------------------------------
1559  /* What can we do here? */
1560  ndbout_c("execute: %s", MyTransaction->getNdbError().message );
1561  }//if(retCode == 3)
1562 
1563  } // if
1564 
1565  pNdb->closeTransaction(MyTransaction);
1566  } // else
1567  } // for opCount
1568 
1569  return(tResult);
1570 
1571 } // deleteRows
1572 
1574 //
1575 // Name: verifyDeleteRows
1576 //
1577 // Purpose: Verifies that all tables are empty by reading every tuple
1578 // No deletions made here
1579 //
1580 // Returns: 'Standard' error codes
1581 //
1583 static int verifyDeleteRows(Ndb* pNdb,
1584  int* pkValue,
1585  int* readValue)
1586 {
1587  int tResult = 0;
1588  int tableCount = 0;
1589  int attrCount = 0;
1590  int check = 0;
1591  NdbConnection* MyTransaction = NULL;
1592  NdbOperation* MyOperations = NULL;
1593  NdbRecAttr* tmp = NULL;
1594  int Value = 0;
1595  int Index = 0;
1596  int opCount = 0;
1597 
1598  for (opCount = 0; opCount < tNoOfOperations; opCount++) {
1599  for (tableCount = 0; tableCount < tNoOfTables; tableCount++) {
1600  MyTransaction = pNdb->startTransaction();
1601  if (MyTransaction == NULL) {
1602  tResult = 1;
1603  } // if
1604  else {
1605 
1606  MyOperations =
1607  MyTransaction->getNdbOperation(tableName[tableCount]);
1608  if (MyOperations == NULL) {
1609  tResult = 2;
1610  // Break for tableCount loop
1611  break;
1612  } // if
1613 
1614  check = MyOperations->readTuple();
1615  if (check == -1) {
1616  tResult = 3;
1617  break;
1618  } // if
1619 
1620  check = MyOperations->
1621  equal((char*)attrName[0], (char*)&(pkValue[opCount]));
1622  if (check == -1) {
1623  tResult = 7;
1624  break;
1625  } // if
1626 
1627  for (int attrCount = 0; attrCount < tNoOfAttributes - 1; attrCount++) {
1628  Index = tableCount * (tNoOfAttributes - 1) * tNoOfOperations * tAttributeSize +
1629  attrCount * tNoOfOperations * tAttributeSize + opCount * tAttributeSize;
1630  tmp = MyOperations->
1631  getValue((char*)attrName[attrCount + 1], (char*)&(readValue[Index]));
1632 
1633  if (tmp == NULL) {
1634  tResult = 9;
1635  break;
1636  } // if
1637  } // for attrCount
1638  // Execute transaction reading one tuple in every table
1639  check = MyTransaction->execute(Commit);
1640  if ((check == -1) && (MyTransaction->getNdbError().code == 626)){
1641  // This is expected because everything should be deleted
1642  } // if
1643  else if (check == 0) {
1644  // We have found a tuple that should have been deleted
1645  ndbout << "tuple " << tableName[tableCount] << ":" <<
1646  opCount << " was never deleted" << endl;
1647  tResult = 97;
1648  } // else if
1649  else {
1650  // Unexpected error
1651  ndbout << "Unexpected error during delete" << endl;
1652  assert(false);
1653  } // else
1654 
1655  pNdb->closeTransaction(MyTransaction);
1656 
1657  } // else
1658  } // for tableCount
1659  } // for opCount
1660 
1661  return(tResult);
1662 } // verifyDeleteRows