flexTimedAsynch.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:24k
源码类别:

MySQL数据库

开发平台:

Visual C++

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