MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
flexTimedAsynch.cpp
1 /*
2  Copyright (C) 2003-2007 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  FLEXTIMEDASYNCH
21  Perform benchmark of insert, update and delete transactions.
22 
23  Arguments:
24  -t Number of threads to start, i.e., number of parallel loops, default 1
25  -p Number of transactions in a batch, default 32
26  -o Number of batches per loop, default 200
27  -i Time between batch starts, default 0
28  -l Number of loops to run, default 1, 0=infinite
29  -a Number of attributes, default 25
30  -c Number of operations per transaction
31  -s Size of each attribute in 32 bit word, default 1 (Primary Key is always of size 1,
32  independent of this value)
33  -simple Use simple read to read from database
34  -dirty Use dirty read to read from database
35  -write Use writeTuple in insert and update
36  -n Use standard table names
37  -no_table_create Don't create tables in db
38  -temp Use temporary tables, no writing to disk.
39 
40  Returns:
41  0 - Test passed
42  -1 - Test failed
43  1 - Invalid arguments
44 
45  * *************************************************** */
46 
47 #include "NdbApi.hpp"
48 
49 #include <NdbThread.h>
50 #include <NdbSleep.h>
51 #include <NdbTick.h>
52 #include <NdbOut.hpp>
53 #include <NdbTimer.hpp>
54 #include <string.h>
55 #include <NdbMain.h>
56 #include <NdbTest.hpp>
57 
58 #include <NDBT_Error.hpp>
59 
60 #define MAXSTRLEN 16
61 #define MAXATTR 64
62 #define MAXTABLES 64
63 #define NDB_MAXTHREADS 256
64 /*
65  NDB_MAXTHREADS used to be just MAXTHREADS, which collides with a
66  #define from <sys/thread.h> on AIX (IBM compiler). We explicitly
67  #undef it here lest someone use it by habit and get really funny
68  results. K&R says we may #undef non-existent symbols, so let's go.
69 */
70 #undef MAXTHREADS
71 #define MAXATTRSIZE 1000
72 #define PKSIZE 1
73 
74 enum StartType { stIdle,
75  stInsert,
76  stRead,
77  stUpdate,
78  stDelete,
79  stStop } ;
80 
81 ErrorData * flexTimedAsynchErrorData;
82 
83 struct ThreadNdb
84 {
85  int NoOfOps;
86  int ThreadNo;
87  unsigned int threadBase;
88  unsigned int transactionCompleted;
89 };
90 
91 extern "C" void* threadLoop(void*);
92 void setAttrNames(void);
93 void setTableNames(void);
94 void readArguments(int argc, const char** argv);
95 void createAttributeSpace();
96 void createTables(Ndb*);
97 void defineOperation(NdbConnection* aTransObject, StartType aType, unsigned int key, int *);
98 void execute(StartType aType);
99 void executeThread(StartType aType, Ndb* aNdbObject, ThreadNdb* threadInfo);
100 void executeCallback(int result, NdbConnection* NdbObject, void* aObject);
101 
102 /* epaulsa > *************************************************************/
103 bool error_handler(const NdbError &) ; //replaces 'goto' things
104 static int failed = 0 ; // lame global variable that keeps track of failed transactions
105  // incremented in executeCallback() and reset in main()
106 /************************************************************* < epaulsa */
107 
108 static NdbThread* threadLife[NDB_MAXTHREADS];
109 static int tNodeId;
110 static int ThreadReady[NDB_MAXTHREADS];
111 static StartType ThreadStart[NDB_MAXTHREADS];
112 static char tableName[MAXTABLES][MAXSTRLEN+1];
113 static char attrName[MAXATTR][MAXSTRLEN+1];
114 static int *getAttrValueTable;
115 
116 // Program Parameters
117 static int tNoOfLoops = 1;
118 static int tAttributeSize = 1;
119 static unsigned int tNoOfThreads = 1;
120 static unsigned int tNoOfTransInBatch = 32;
121 static unsigned int tNoOfAttributes = 25;
122 static unsigned int tNoOfBatchesInLoop = 200;
123 static unsigned int tNoOfOpsPerTrans = 1;
124 static unsigned int tTimeBetweenBatches = 0;
125 
126 //Program Flags
127 static int theTestFlag = 0;
128 static int theTempFlag = 1;
129 static int theSimpleFlag = 0;
130 static int theDirtyFlag = 0;
131 static int theWriteFlag = 0;
132 static int theStdTableNameFlag = 0;
133 static int theTableCreateFlag = 0;
134 
135 #define START_REAL_TIME NdbTimer timer; timer.doStart();
136 #define STOP_REAL_TIME timer.doStop();
137 
138 #define START_TIMER { NdbTimer timer; timer.doStart();
139 #define STOP_TIMER timer.doStop();
140 #define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
141 
142 void
143 resetThreads(){
144 
145  for (int i = 0; i < tNoOfThreads ; i++) {
146  ThreadReady[i] = 0;
147  ThreadStart[i] = stIdle;
148  }
149 }
150 
151 void
152 waitForThreads(void)
153 {
154  int cont;
155  do {
156  cont = 0;
157  NdbSleep_MilliSleep(20);
158  for (int i = 0; i < tNoOfThreads ; i++) {
159  if (ThreadReady[i] == 0) {
160  cont = 1;
161  }
162  }
163  } while (cont == 1);
164 }
165 
166 void
167 tellThreads(StartType what)
168 {
169  for (int i = 0; i < tNoOfThreads ; i++)
170  ThreadStart[i] = what;
171 }
172 
173 void createAttributeSpace(){
174  getAttrValueTable = new int[tAttributeSize*
175  tNoOfThreads *
176  tNoOfAttributes ];
177 
178 }
179 
180 void deleteAttributeSpace(){
181  delete [] getAttrValueTable;
182 }
183 
184 NDB_COMMAND(flexTimedAsynch, "flexTimedAsynch", "flexTimedAsynch [-tpoilcas]", "flexTimedAsynch", 65535)
185 {
186  ndb_init();
187  ThreadNdb tabThread[NDB_MAXTHREADS];
188  int tLoops=0;
189  int returnValue;
190  //NdbOut flexTimedAsynchNdbOut;
191 
192  flexTimedAsynchErrorData = new ErrorData;
193  flexTimedAsynchErrorData->resetErrorCounters();
194 
195  Ndb* pNdb;
196  pNdb = new Ndb( "TEST_DB" );
197  pNdb->init();
198 
199  readArguments(argc, argv);
200 
201  createAttributeSpace();
202 
203  ndbout << endl << "FLEXTIMEDASYNCH - Starting normal mode" << endl;
204  ndbout << "Perform benchmark of insert, update and delete transactions" << endl << endl;
205 
206  if(theTempFlag == 0)
207  ndbout << " " << "Using temporary tables. " << endl;
208 
209  // -t, tNoOfThreads
210  ndbout << " " << tNoOfThreads << " number of concurrent threads " << endl;
211  // -c, tNoOfOpsPerTrans
212  ndbout << " " << tNoOfOpsPerTrans << " operations per transaction " << endl;
213  // -p, tNoOfTransInBatch
214  ndbout << " " << tNoOfTransInBatch << " number of transactions in a batch per thread " << endl;
215  // -o, tNoOfBatchesInLoop
216  ndbout << " " << tNoOfBatchesInLoop << " number of batches per loop " << endl;
217  // -i, tTimeBetweenBatches
218  ndbout << " " << tTimeBetweenBatches << " milli seconds at least between batch starts " << endl;
219  // -l, tNoOfLoops
220  ndbout << " " << tNoOfLoops << " loops " << endl;
221  // -a, tNoOfAttributes
222  ndbout << " " << tNoOfAttributes << " attributes per table " << endl;
223  // -s, tAttributeSize
224  ndbout << " " << tAttributeSize << " is the number of 32 bit words per attribute " << endl << endl;
225 
226  NdbThread_SetConcurrencyLevel(2 + tNoOfThreads);
227 
228  /* print Setting */
229  flexTimedAsynchErrorData->printSettings(ndbout);
230 
231  setAttrNames();
232  setTableNames();
233 
234  ndbout << "Waiting for ndb to become ready..." <<endl;
235  if (pNdb->waitUntilReady() == 0) {
236  tNodeId = pNdb->getNodeId();
237  ndbout << " NdbAPI node with id = " << tNodeId << endl;
238  createTables(pNdb);
239 
240  /****************************************************************
241  * Create NDB objects. *
242  ****************************************************************/
243  resetThreads();
244  for (int i = 0; i < tNoOfThreads ; i++) {
245  tabThread[i].ThreadNo = i;
246 
247  threadLife[i] = NdbThread_Create(threadLoop,
248  (void**)&tabThread[i],
249  32768,
250  "flexTimedAsynchThread",
251  NDB_THREAD_PRIO_LOW);
252  }
253  ndbout << endl << "All NDB objects and table created" << endl << endl;
254  int noOfTransacts = tNoOfTransInBatch*tNoOfBatchesInLoop*tNoOfThreads;
255 
256  /****************************************************************
257  * Execute program. *
258  ****************************************************************/
259 
260 
261  for(;;) {
262 
263  int loopCount = tLoops + 1 ;
264  ndbout << endl << "Loop # " << loopCount << endl << endl ;
265 
266  /****************************************************************
267  * Perform inserts. *
268  ****************************************************************/
269 
270  failed = 0 ;
271 
272  START_TIMER;
273  execute(stInsert);
274  STOP_TIMER;
275  PRINT_TIMER("insert", noOfTransacts, tNoOfOpsPerTrans);
276 
277  if (0 < failed) {
278  ndbout << failed << " of the transactions returned errors!, moving on now..."<<endl ;
279  }
280 
281  /****************************************************************
282  * Perform read. *
283  ****************************************************************/
284 
285  failed = 0 ;
286 
287  START_TIMER;
288  execute(stRead);
289  STOP_TIMER;
290  PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
291 
292  if (0 < failed) {
293  ndbout << failed << " of the transactions returned errors!, moving on now..."<<endl ;
294  }
295 
296 
297 
298  /****************************************************************
299  * Perform update. *
300  ***************************************************************/
301 
302  failed = 0 ;
303 
304  START_TIMER;
305  execute(stUpdate);
306  STOP_TIMER;
307  PRINT_TIMER("update", noOfTransacts, tNoOfOpsPerTrans) ;
308 
309  if (0 < failed) {
310  ndbout << failed << " of the transactions returned errors!, moving on now..."<<endl ;
311  }
312 
313  /****************************************************************
314  * Perform read after update.
315  ****************************************************************/
316 
317  failed = 0 ;
318 
319  START_TIMER;
320  execute(stRead);
321  STOP_TIMER;
322  PRINT_TIMER("read", noOfTransacts, tNoOfOpsPerTrans);
323 
324  if (0 < failed) {
325  ndbout << failed << " of the transactions returned errors!, moving on now..."<<endl ;
326  }
327 
328 
329  /****************************************************************
330  * Perform delete. *
331  ****************************************************************/
332 
333  failed = 0;
334 
335  START_TIMER;
336  execute(stDelete);
337  STOP_TIMER;
338  PRINT_TIMER("delete", noOfTransacts, tNoOfOpsPerTrans);
339 
340  if (0 < failed) {
341  ndbout << failed << " of the transactions returned errors!, moving on now..."<<endl ;
342  }
343 
344  tLoops++;
345  ndbout << "--------------------------------------------------" << endl;
346 
347  if(tNoOfLoops != 0){
348  if(tNoOfLoops <= tLoops)
349  break ;
350  }
351  }
352 
353  ndbout << endl << "Benchmark completed!" << endl;
354  returnValue = NDBT_OK;
355 
356  execute(stStop);
357  void * tmp;
358  for(int i = 0; i<tNoOfThreads; i++){
359  NdbThread_WaitFor(threadLife[i], &tmp);
360  NdbThread_Destroy(&threadLife[i]);
361  }
362  } else {
363  ndbout << "NDB is not ready" << endl;
364  ndbout << "Benchmark failed!" << endl;
365  returnValue = NDBT_FAILED;
366  }
367 
368  deleteAttributeSpace();
369  delete pNdb;
370 
371  //printing errorCounters
372  flexTimedAsynchErrorData->printErrorCounters(ndbout);
373 
374  return NDBT_ProgramExit(returnValue);
375 }//main()
376 
378 
379 void execute(StartType aType)
380 {
381  resetThreads();
382  tellThreads(aType);
383  waitForThreads();
384 }
385 
386 void*
387 threadLoop(void* ThreadData)
388 {
389  // Do work until signaled to stop.
390 
391  Ndb* localNdb;
392  StartType tType;
393  ThreadNdb* threadInfo = (ThreadNdb*)ThreadData;
394  int threadNo = threadInfo->ThreadNo;
395  localNdb = new Ndb("TEST_DB");
396  localNdb->init(512);
397  localNdb->waitUntilReady();
398  threadInfo->threadBase = (threadNo * 2000000) + (tNodeId * 260000000);
399 
400  for (;;) {
401  while (ThreadStart[threadNo] == stIdle) {
402  NdbSleep_MilliSleep(10);
403  }
404 
405  // Check if signal to exit is received
406  if (ThreadStart[threadNo] == stStop) {
407  break;
408  }
409 
410  tType = ThreadStart[threadNo];
411  ThreadStart[threadNo] = stIdle;
412  executeThread(tType, localNdb, threadInfo);
413  ThreadReady[threadNo] = 1;
414  }
415 
416  delete localNdb;
417  ThreadReady[threadNo] = 1;
418 
419  return NULL; // thread exits
420 }
421 
422 void executeThread(StartType aType, Ndb* aNdbObject, ThreadNdb* threadInfo)
423 {
424  // Do all batch job in loop with start specified delay
425  int i, j, k;
426  NdbConnection* tConArray[1024];
427  unsigned int tBase;
428  unsigned int tBase2;
429  int threadId = threadInfo->ThreadNo;
430  int *getValueRowAddress = NULL;
431 
432  NdbTimer timer;
433  timer.doStart();
434 
435  for (i = 0; i < tNoOfBatchesInLoop; i++) {
436  //tBase = threadBase + (i * tNoOfTransInBatch * tNoOfOpsPerTrans);
437  tBase = threadInfo->threadBase + (i * tNoOfTransInBatch * tNoOfOpsPerTrans);
438  //tCompleted = 0;
439  threadInfo->transactionCompleted = 0;
440 
441  for (j = 0; j < tNoOfTransInBatch; j++) {
442  tBase2 = tBase + (j * tNoOfOpsPerTrans);
443  tConArray[j] = aNdbObject->startTransaction();
444  if ( tConArray[j] == NULL && !error_handler(aNdbObject->getNdbError())) {
445  ndbout << endl << "Unable to recover! Quiting now" << endl ;
446  exit (-1) ;
447  return ;
448  }
449 
450  for (k = 0; k < tNoOfOpsPerTrans; k++) {
451  //-------------------------------------------------------
452  // Define the operation, but do not execute it yet.
453  //-------------------------------------------------------
454  if(aType == stRead){
455  getValueRowAddress = getAttrValueTable +
456  threadId * tNoOfAttributes * tAttributeSize;
457  }
458  defineOperation(tConArray[j], aType, (tBase2 + k), getValueRowAddress);
459  }
460 
461  tConArray[j]->executeAsynchPrepare(Commit, &executeCallback, threadInfo);
462  }
463 
464  //-------------------------------------------------------
465  // Now we have defined a set of transactions (= batch), it is now time
466  // to execute all of them.
467  //-------------------------------------------------------
468  aNdbObject->sendPollNdb(3000, 0, 0);
469 
470  //while (tCompleted < tNoOfTransInBatch) {
471  while (threadInfo->transactionCompleted < tNoOfTransInBatch) {
472  aNdbObject->pollNdb(3000, 0);
473  ndbout << "threadInfo->transactionCompleted = " <<
474  threadInfo->transactionCompleted << endl;
475  }
476 
477  for (j = 0 ; j < tNoOfTransInBatch ; j++) {
478  aNdbObject->closeTransaction(tConArray[j]);
479  }
480 
481  // Control the elapsed time since the last batch start.
482  // Wait at least tTimeBetweenBatches milli seconds.
483  timer.doStop();
484  while(timer.elapsedTime() < tTimeBetweenBatches){
485  NdbSleep_MilliSleep(1);
486  timer.doStop();
487  }
488  // Ready to start new batch
489  timer.doStart();
490  }
491  return;
492 }
493 
494 void
495 executeCallback(int result, NdbConnection* NdbObject, void* aObject)
496 {
497  //tCompleted++;
498  ThreadNdb *threadInfo = (ThreadNdb *)aObject;
499  threadInfo->transactionCompleted++;
500 
501  if (result == -1) {
502 
503  // Add complete error handling here
504 
505  int retCode = flexTimedAsynchErrorData->handleErrorCommon(NdbObject->getNdbError());
506  if (retCode == 1) {
507  if (NdbObject->getNdbError().code != 626 && NdbObject->getNdbError().code != 630){
508  ndbout_c("execute: %s", NdbObject->getNdbError().message);
509  ndbout_c("Error code = %d", NdbObject->getNdbError().code);}
510  } else if (retCode == 2) {
511  ndbout << "4115 should not happen in flexAsynch" << endl;
512  } else if (retCode == 3) {
513  /* What can we do here? */
514  ndbout_c("execute: %s", NdbObject->getNdbError().message);
515  }//if(retCode == 3)
516 
517  // ndbout << "Error occured in poll:" << NdbObject->getNdbError() <<
518  // " ErrorCode = " << NdbObject->getNdbError() << endl;
519  ndbout << "executeCallback threadInfo->transactionCompleted = " <<
520  threadInfo->transactionCompleted << endl;
521  failed++ ;
522  return;
523  }
524  return;
525 }
526 
527 void
528 defineOperation(NdbConnection* localNdbConnection,
529  StartType aType,
530  unsigned int threadBase,
531  int *pRow )
532 {
533  NdbOperation* localNdbOperation;
534  unsigned int loopCountAttributes = tNoOfAttributes;
535  unsigned int countAttributes;
536  int attrValue[MAXATTRSIZE];
537 
538  //-------------------------------------------------------
539  // Set-up the attribute values for this operation.
540  //-------------------------------------------------------
541  for (int k = 0; k < loopCountAttributes; k++) {
542  *(int *)&attrValue[k] = (int)threadBase;
543  }
544  localNdbOperation = localNdbConnection->getNdbOperation(tableName[0]);
545  if (localNdbOperation == NULL) {
546  error_handler(localNdbOperation->getNdbError()) ;
547  }
548 
549  switch (aType) {
550  case stInsert: { // Insert case
551  if (theWriteFlag == 1 && theDirtyFlag == 1) {
552  localNdbOperation->dirtyWrite();
553  } else if (theWriteFlag == 1) {
554  localNdbOperation->writeTuple();
555  } else {
556  localNdbOperation->insertTuple();
557  }
558  break;
559  }
560  case stRead: { // Read Case
561  if (theSimpleFlag == 1) {
562  localNdbOperation->simpleRead();
563  } else if (theDirtyFlag == 1) {
564  localNdbOperation->dirtyRead();
565  } else {
566  localNdbOperation->readTuple();
567  }
568  break;
569  }
570  case stUpdate: { // Update Case
571  if (theWriteFlag == 1 && theDirtyFlag == 1) {
572  localNdbOperation->dirtyWrite();
573  } else if (theWriteFlag == 1) {
574  localNdbOperation->writeTuple();
575  } else if (theDirtyFlag == 1) {
576  localNdbOperation->dirtyUpdate();
577  } else {
578  localNdbOperation->updateTuple();
579  }
580  break;
581  }
582  case stDelete: { // Delete Case
583  localNdbOperation->deleteTuple();
584  break;
585  }
586  default: {
587  error_handler(localNdbOperation->getNdbError());
588  }
589  }
590 
591  localNdbOperation->equal((char*)attrName[0],(char*)&attrValue[0]);
592 
593  switch (aType) {
594  case stInsert: // Insert case
595  case stUpdate: // Update Case
596  {
597  for (countAttributes = 1; countAttributes < loopCountAttributes; countAttributes++) {
598  localNdbOperation->setValue( (char*)attrName[countAttributes],(char*)&attrValue[0]);
599  }
600  break;
601  }
602  case stRead: { // Read Case
603  for (countAttributes = 1; countAttributes < loopCountAttributes; countAttributes++) {
604  //localNdbOperation->getValue((char*)attrName[countAttributes],(char*)&attrValue[0]);
605  localNdbOperation->getValue((char*)attrName[countAttributes],
606  (char *) (pRow + countAttributes*tAttributeSize));
607  }
608  break;
609  }
610  case stDelete: { // Delete Case
611  break;
612  }
613  default: {
614  error_handler(localNdbOperation->getNdbError());
615  }
616  }
617  return;
618 }
619 
620 void readArguments(int argc, const char** argv)
621 {
622  int i = 1;
623  while (argc > 1)
624  {
625  if (strcmp(argv[i], "-t") == 0)
626  {
627  tNoOfThreads = atoi(argv[i+1]);
628  // if ((tNoOfThreads < 1) || (tNoOfThreads > NDB_MAXTHREADS))
629  if ((tNoOfThreads < 1) || (tNoOfThreads > NDB_MAXTHREADS))
630  exit(-1);
631  }
632  else if (strcmp(argv[i], "-i") == 0)
633  {
634  tTimeBetweenBatches = atoi(argv[i+1]);
635  if (tTimeBetweenBatches < 0)
636  exit(-1);
637  }
638  else if (strcmp(argv[i], "-p") == 0)
639  {
640  tNoOfTransInBatch = atoi(argv[i+1]);
641  //if ((tNoOfTransInBatch < 1) || (tNoOfTransInBatch > NDB_MAXTHREADS))
642  if ((tNoOfTransInBatch < 1) || (tNoOfTransInBatch > 10000))
643  exit(-1);
644  }
645  else if (strcmp(argv[i], "-c") == 0)
646  {
647  tNoOfOpsPerTrans = atoi(argv[i+1]);
648  if (tNoOfOpsPerTrans < 1)
649  exit(-1);
650  }
651  else if (strcmp(argv[i], "-o") == 0)
652  {
653  tNoOfBatchesInLoop = atoi(argv[i+1]);
654  if (tNoOfBatchesInLoop < 1)
655  exit(-1);
656  }
657  else if (strcmp(argv[i], "-a") == 0)
658  {
659  tNoOfAttributes = atoi(argv[i+1]);
660  if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR))
661  exit(-1);
662  }
663  else if (strcmp(argv[i], "-n") == 0)
664  {
665  theStdTableNameFlag = 1;
666  argc++;
667  i--;
668  }
669  else if (strcmp(argv[i], "-l") == 0)
670  {
671  tNoOfLoops = atoi(argv[i+1]);
672  if ((tNoOfLoops < 0) || (tNoOfLoops > 100000))
673  exit(-1);
674  }
675  else if (strcmp(argv[i], "-s") == 0)
676  {
677  tAttributeSize = atoi(argv[i+1]);
678  if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE))
679  exit(-1);
680  }
681  else if (strcmp(argv[i], "-simple") == 0)
682  {
683  theSimpleFlag = 1;
684  argc++;
685  i--;
686  }
687  else if (strcmp(argv[i], "-write") == 0)
688  {
689  theWriteFlag = 1;
690  argc++;
691  i--;
692  }
693  else if (strcmp(argv[i], "-dirty") == 0)
694  {
695  theDirtyFlag = 1;
696  argc++;
697  i--;
698  }
699  else if (strcmp(argv[i], "-test") == 0)
700  {
701  theTestFlag = 1;
702  argc++;
703  i--;
704  }
705  else if (strcmp(argv[i], "-temp") == 0)
706  {
707  theTempFlag = 0; // 0 if temporary tables.
708  argc++;
709  i--;
710  }
711  else if (strcmp(argv[i], "-no_table_create") == 0)
712  {
713  theTableCreateFlag = 1;
714  argc++;
715  i--;
716  }
717  else
718  {
719  ndbout << "Arguments: " << endl;
720  ndbout << "-t Number of threads to start, i.e., number of parallel loops, default 1 " << endl;
721  ndbout << "-p Number of transactions in a batch, default 32 " << endl;
722  ndbout << "-o Number of batches per loop, default 200 " << endl;
723  ndbout << "-i Minimum time between batch starts in milli seconds, default 0 " << endl;
724  ndbout << "-l Number of loops to run, default 1, 0=infinite " << endl;
725  ndbout << "-a Number of attributes, default 25 " << endl;
726  ndbout << "-c Number of operations per transaction, default 1 " << endl;
727  ndbout << "-s Size of each attribute in 32 bit word, default 1"
728  "(Primary Key is always of size 1, independent of this value) " << endl;
729  ndbout << "-simple Use simple read to read from database " << endl;
730  ndbout << "-dirty Use dirty read to read from database " << endl;
731  ndbout << "-write Use writeTuple in insert and update " << endl;
732  ndbout << "-n Use standard table names " << endl;
733  ndbout << "-no_table_create Don't create tables in db " << endl;
734  ndbout << "-temp Use temporary tables, no writing to disk. " << endl;
735  exit(-1);
736  }
737 
738  argc -= 2;
739  i = i + 2;
740  }
741 }
742 
743 void setAttrNames()
744 {
745  int i;
746 
747  for (i = 0; i < MAXATTR ; i++)
748  {
749  sprintf(attrName[i], "COL%d", i);
750  }
751 }
752 
753 
754 void setTableNames()
755 {
756  // Note! Uses only uppercase letters in table name's
757  // so that we can look at the tables with SQL
758  int i;
759  for (i = 0; i < MAXTABLES ; i++)
760  {
761  if (theStdTableNameFlag==1)
762  {
763  sprintf(tableName[i], "TAB%d_%d", tNoOfAttributes,
764  NdbTick_CurrentMillisecond()/1000);
765  } else {
766  sprintf(tableName[i], "TAB%d_%d", tNoOfAttributes, tAttributeSize*4);
767  }
768  }
769 }
770 
771 void createTables(Ndb* pMyNdb)
772 {
773 
774  NdbSchemaCon *MySchemaTransaction;
775  NdbSchemaOp *MySchemaOp;
776  int check;
777 
778  if (theTableCreateFlag == 0)
779  {
780  for(int i=0; i < 1 ;i++)
781  {
782  ndbout << "Creating " << tableName[i] << "..." << endl;
783  MySchemaTransaction = pMyNdb->startSchemaTransaction();
784 
785  if( MySchemaTransaction ==
786  NULL && (!error_handler(MySchemaTransaction->getNdbError())))
787  exit(-1) ;/*goto error_handler; <epaulsa*/
788 
789  MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
790  if( MySchemaOp == NULL
791  && (!error_handler(MySchemaTransaction->getNdbError())))
792  exit(-1) ;
793 
794  check = MySchemaOp->createTable( tableName[i],
795  8, // Table Size
796  TupleKey, // Key Type
797  40, // Nr of Pages
798  All, // FragmentType
799  6,
800  78,
801  80,
802  1, // MemoryType
803  theTempFlag // 0 if temporary tables else 1
804  );
805 
806  if ( check == -1 && (!error_handler(MySchemaTransaction->getNdbError())))
807  exit(-1) ; /* epaulsa > goto error_handler; < epaulsa */
808 
809 
810  check = MySchemaOp->createAttribute( (char*)attrName[0],
811  TupleKey,
812  32,
813  PKSIZE,
814  UnSigned,
815  MMBased,
816  NotNullAttribute );
817 
818  if ( check == -1 &&(!error_handler(MySchemaTransaction->getNdbError())))
819  exit(-1) ; /* epaulsa > goto error_handler; < epaulsa */
820 
821  for (int j = 1; j < tNoOfAttributes ; j++)
822  {
823  check = MySchemaOp->createAttribute( (char*)attrName[j],
824  NoKey,
825  32,
826  tAttributeSize,
827  UnSigned,
828  MMBased,
829  NotNullAttribute );
830  if ( check == -1
831  && (!error_handler(MySchemaTransaction->getNdbError())))
832  exit(-1) ; /* epaulsa > goto error_handler; < epaulsa */
833  }
834 
835  if ( MySchemaTransaction->execute() == -1
836  &&(!error_handler(MySchemaTransaction->getNdbError())))
837  exit(-1) ; /* epaulsa > goto error_handler; < epaulsa */
838 
839  pMyNdb->closeSchemaTransaction(MySchemaTransaction);
840  }
841  }
842 
843  return;
844 }
845 
846 bool error_handler(const NdbError & err) {
847  ndbout << err << endl ;
848  if ( 4008==err.code || 721==err.code || 266==err.code ){
849  ndbout << endl << "Attempting to recover and continue now..." << endl ;
850  return true ; // return true to retry
851  }
852  return false ; // return false to abort
853 }
854 
855 
856 //*******************************************************************************************
857 
858 
859 
860 
861