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

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. #include <NdbApi.hpp>
  14. #include <NdbOut.hpp>
  15. #include <NdbThread.h>
  16. #include <NdbSleep.h>
  17. #include <NdbMutex.h>
  18. #include "TraceNdbApi.hpp"
  19. #include "VerifyNdbApi.hpp"
  20. #define Ndb CTraceNdb
  21. #define NdbSchemaCon CTraceNdbSchemaCon
  22. #define NdbSchemaOp CTraceNdbSchemaOp
  23. #define NdbConnection CTraceNdbConnection
  24. #define NdbOperation CTraceNdbOperation
  25. #define NdbIndexOperation CTraceNdbIndexOperation
  26. #define NdbRecAttr CTraceNdbRecAttr
  27. #define Table CTraceTable
  28. #define Index CTraceIndex
  29. #define Column CTraceColumn
  30. #define NdbDictionary CTraceNdbDictionary
  31. /*
  32. #define Ndb CVerifyNdb
  33. #define NdbSchemaCon CVerifyNdbSchemaCon
  34. #define NdbSchemaOp CVerifyNdbSchemaOp
  35. #define NdbConnection CVerifyNdbConnection
  36. #define NdbOperation CVerifyNdbOperation
  37. #define NdbIndexOperation CVerifyNdbIndexOperation
  38. #define NdbRecAttr CVerifyNdbRecAttr
  39. #define Table CVerifyTable
  40. #define Index CVerifyIndex
  41. #define Column CVerifyColumn
  42. #define NdbDictionary CVerifyNdbDictionary
  43. */
  44. NdbMutex* g_pNdbMutexStop = 0;
  45. Uint32 g_nPart = 1;
  46. Uint32 g_nTable = 1;
  47. Uint32 g_nTuple = 1;
  48. Uint32 g_nAttribute = 1;
  49. char* g_szTable = 0;
  50. char* g_szIndex = 0;
  51. char* g_szAttribute = 0;
  52. bool g_bVerify = false;
  53. bool g_bUseIndex = false;
  54. #define N 624
  55. #define M 397
  56. #define MATRIX_A 0x9908b0df
  57. #define UPPER_MASK 0x80000000
  58. #define LOWER_MASK 0x7fffffff
  59. #define TEMPERING_MASK_B 0x9d2c5680
  60. #define TEMPERING_MASK_C 0xefc60000
  61. #define TEMPERING_SHIFT_U(y)  (y >> 11)
  62. #define TEMPERING_SHIFT_S(y)  (y << 7)
  63. #define TEMPERING_SHIFT_T(y)  (y << 15)
  64. #define TEMPERING_SHIFT_L(y)  (y >> 18)
  65. class MT19937
  66. {
  67. public:
  68.     MT19937(void);
  69.     void sgenrand(unsigned long seed);
  70.     unsigned long genrand(void);
  71. private:
  72.     unsigned long mt[N];
  73.     int mti;
  74.     unsigned long mag01[2];
  75. };
  76. MT19937::MT19937(void)
  77. {
  78.     mti = N+1;
  79.     mag01[0] = 0x0;
  80.     mag01[1] = MATRIX_A;
  81.     sgenrand(4357);
  82. }
  83. void MT19937::sgenrand(unsigned long seed)
  84. {
  85.     mt[0]= seed & 0xffffffff;
  86.     for (mti=1; mti<N; mti++)
  87.         mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
  88. }
  89. unsigned long MT19937::genrand(void)
  90. {
  91.     unsigned long y;
  92.     if (mti >= N) {
  93.         int kk;
  94.         if (mti == N+1)
  95.         {
  96.             sgenrand(4357);
  97.         }
  98.         for (kk=0;kk<N-M;kk++) {
  99.             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
  100.             mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
  101.         }
  102.         for (;kk<N-1;kk++) {
  103.             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
  104.             mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
  105.         }
  106.         y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
  107.         mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
  108.         mti = 0;
  109.     }
  110.     y = mt[mti++];
  111.     y ^= TEMPERING_SHIFT_U(y);
  112.     y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
  113.     y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
  114.     y ^= TEMPERING_SHIFT_L(y);
  115.     return y; 
  116. }
  117. void CreateTables(Ndb* pNdb)
  118. {
  119.     for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  120.     {
  121.         NdbDictionary::Dictionary* pDictionary = pNdb->getDictionary();
  122.         NdbDictionary::Table table;
  123.         table.setName(g_szTable+iTable*4);
  124.         NdbDictionary::Index index;
  125.         index.setName(g_szIndex+iTable*4);
  126.         index.setTable(table.getName());
  127.         index.setType(NdbDictionary::Index::UniqueHashIndex);
  128.         NdbDictionary::Column columnPK;
  129.         columnPK.setName("PK");
  130.         columnPK.setTupleKey(true);
  131.         table.addColumn(columnPK);
  132.         index.addIndexColumn(columnPK.getName());
  133.         for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  134.         {
  135.             NdbDictionary::Column columnAttr;
  136.             columnAttr.setName(g_szAttribute+iAttr*4);
  137.             columnAttr.setTupleKey(false);
  138.             table.addColumn(columnAttr);
  139.         }
  140.         pDictionary->createTable(table);
  141.         pDictionary->createIndex(index);
  142.         /*
  143.         NdbSchemaCon* pNdbSchemaCon = pNdb->startSchemaTransaction();
  144.         NdbSchemaOp* pNdbSchemaOp = pNdbSchemaCon->getNdbSchemaOp();
  145.         pNdbSchemaOp->createTable(g_szTable+iTable*4);
  146.         pNdbSchemaOp->createAttribute("PK", TupleKey);
  147.         for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  148.         {
  149.         pNdbSchemaOp->createAttribute(g_szAttribute+iAttr*4, NoKey);
  150.         }
  151.         pNdbSchemaCon->execute();
  152.         pNdb->closeSchemaTransaction(pNdbSchemaCon);
  153.         */
  154.     }
  155. }
  156. int InsertTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex)
  157. {
  158.     int iExec = -1;
  159.     int iCode = -1;
  160.     NdbConnection* pNdbConnection = pNdb->startTransaction();
  161.     if(pNdbConnection)
  162.     {
  163.         for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  164.         {
  165.             for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple)
  166.             {
  167.                 if(bIndex)
  168.                 {
  169.                     NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4);
  170.                     pNdbIndexOperation->insertTuple();
  171.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  172.                     pNdbIndexOperation->equal("PK", nPK);
  173.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  174.                     {
  175.                         Uint32 nValue = ((iPart*g_nTable+iTable)*g_nTuple+iTuple)*g_nAttribute+iAttr;
  176.                         pNdbIndexOperation->setValue(g_szAttribute+iAttr*4, nValue);
  177.                     }
  178.                 }
  179.                 else
  180.                 {
  181.                     NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4);
  182.                     pNdbOperation->insertTuple();
  183.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  184.                     pNdbOperation->equal("PK", nPK);
  185.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  186.                     {
  187.                         Uint32 nValue = ((iPart*g_nTable+iTable)*g_nTuple+iTuple)*g_nAttribute+iAttr;
  188.                         pNdbOperation->setValue(g_szAttribute+iAttr*4, nValue);
  189.                     }
  190.                 }
  191.             }
  192.         }
  193.         iExec = pNdbConnection->execute_ok(Commit);
  194.         if (iExec == -1) 
  195.         {
  196.             ndbout << pNdbConnection->getNdbError() << endl;
  197.         }
  198.         pNdb->closeTransaction(pNdbConnection);
  199.     }
  200.     return 0;
  201. }
  202. int UpdateGetAndSetTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex)
  203. {
  204.     int iExec = -1;
  205.     int iCode = -1;
  206.     NdbRecAttr** ppNdbRecAttr = new NdbRecAttr*[g_nTable*g_nTuple*g_nAttribute];
  207.     NdbConnection* pNdbConnection = pNdb->startTransaction();
  208.     if(pNdbConnection)
  209.     {
  210.         for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  211.         {
  212.             for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple)
  213.             {
  214.                 if(bIndex)
  215.                 {
  216.                     NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4);
  217.                     pNdbIndexOperation->readTupleExclusive();
  218.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  219.                     pNdbIndexOperation->equal("PK", nPK);
  220.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  221.                     {
  222.                         ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr] 
  223.                         = pNdbIndexOperation->getValue(g_szAttribute+iAttr*4);
  224.                     }
  225.                 }
  226.                 else
  227.                 {
  228.                     NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4);
  229.                     pNdbOperation->readTupleExclusive();
  230.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  231.                     pNdbOperation->equal("PK", nPK);
  232.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  233.                     {
  234.                         ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr] 
  235.                         = pNdbOperation->getValue(g_szAttribute+iAttr*4);
  236.                     }
  237.                 }
  238.             }
  239.         }
  240.         iExec = pNdbConnection->execute_ok(NoCommit);
  241.         if( iExec == -1)
  242.         {
  243.             ndbout << pNdbConnection->getNdbError() << endl;
  244.         }
  245.     }
  246.     iCode = pNdbConnection->getNdbError().code;
  247.     if(iExec==0)
  248.     {
  249.         for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  250.         {
  251.             for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple)
  252.             {
  253.                 if(bIndex)
  254.                 {
  255.                     NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4);
  256.                     pNdbIndexOperation->updateTuple();
  257.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  258.                     pNdbIndexOperation->equal("PK", nPK);
  259.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  260.                     {
  261.                         NdbRecAttr* pNdbRecAttr
  262.                             = ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr];
  263.                         Uint32 nValue = pNdbRecAttr->u_32_value() + 1;
  264.                         pNdbIndexOperation->setValue(g_szAttribute+iAttr*4, nValue);
  265.                     }
  266.                 }
  267.                 else
  268.                 {
  269.                     NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4);
  270.                     pNdbOperation->updateTuple();
  271.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  272.                     pNdbOperation->equal("PK", nPK);
  273.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  274.                     {
  275.                         NdbRecAttr* pNdbRecAttr
  276.                             = ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr];
  277.                         Uint32 nValue = pNdbRecAttr->u_32_value() + 1;
  278.                         pNdbOperation->setValue(g_szAttribute+iAttr*4, nValue);
  279.                     }
  280.                 }
  281.             }
  282.         }
  283.         iExec = pNdbConnection->execute(Commit);
  284.         if (iExec == -1) 
  285.         {
  286.             ndbout << pNdbConnection->getNdbError() << endl;
  287.         }
  288.         pNdb->closeTransaction(pNdbConnection);
  289.     }
  290.     delete[] ppNdbRecAttr;
  291.     return 0;
  292. }
  293. int UpdateInterpretedTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex)
  294. {
  295.     int iExec = -1;
  296.     int iCode = -1;
  297.     NdbConnection* pNdbConnection = pNdb->startTransaction();
  298.     if(pNdbConnection)
  299.     {
  300.         for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  301.         {
  302.             for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple)
  303.             {
  304.                 if(bIndex)
  305.                 {
  306.                     NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4);
  307.                     pNdbIndexOperation->interpretedUpdateTuple();
  308.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  309.                     pNdbIndexOperation->equal("PK", nPK);
  310.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  311.                     {
  312.                         pNdbIndexOperation->incValue(g_szAttribute+iAttr*4, (Uint32)1);
  313.                     }
  314.                 }
  315.                 else
  316.                 {
  317.                     NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4);
  318.                     pNdbOperation->interpretedUpdateTuple();
  319.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  320.                     pNdbOperation->equal("PK", nPK);
  321.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  322.                     {
  323.                         pNdbOperation->incValue(g_szAttribute+iAttr*4, (Uint32)1);
  324.                     }
  325.                 }
  326.             }
  327.         }
  328.         iExec = pNdbConnection->execute_ok(Commit);
  329.         if (iExec == -1) 
  330.         {
  331.             ndbout << pNdbConnection->getNdbError() << endl;
  332.         }
  333.         pNdb->closeTransaction(pNdbConnection);
  334.     }
  335.     return 0;
  336. }
  337. void ReportInconsistency (const Uint32 iPart,
  338.                           const Uint32 iTable,
  339.                           const Uint32 iTuple,
  340.                           const Uint32 iAttr,
  341.                           const Uint32 nValue,
  342.                           const Uint32 nExpected )
  343. {
  344.     ndbout << "INCONSISTENCY: ";
  345.     ndbout << "Part " << iPart;
  346.     ndbout << ", Table " << iTable;
  347.     ndbout << ", Tuple " << iTuple;
  348.     ndbout << ", Attr " << iAttr;
  349.     ndbout << ", Value " << nValue;
  350.     ndbout << ", Expected " << nExpected;
  351.     ndbout << endl;
  352. }
  353. int ReadTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex)
  354. {
  355.     int iExec = -1;
  356.     int iCode = -1;
  357.     NdbRecAttr** ppNdbRecAttr = new NdbRecAttr*[g_nTable*g_nTuple*g_nAttribute];
  358.     NdbConnection* pNdbConnection = pNdb->startTransaction();
  359.     if(pNdbConnection)
  360.     {
  361.         for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  362.         {
  363.             for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple)
  364.             {
  365.                 if(bIndex)
  366.                 {
  367.                     NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4);
  368.                     pNdbIndexOperation->readTuple();
  369.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  370.                     pNdbIndexOperation->equal("PK", nPK);
  371.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  372.                     {
  373.                         ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr]
  374.                         = pNdbIndexOperation->getValue(g_szAttribute+iAttr*4);
  375.                     }
  376.                 }
  377.                 else
  378.                 {
  379.                     NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4);
  380.                     pNdbOperation->readTuple();
  381.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  382.                     pNdbOperation->equal("PK", nPK);
  383.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  384.                     {
  385.                         ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr]
  386.                         = pNdbOperation->getValue(g_szAttribute+iAttr*4);
  387.                     }
  388.                 }
  389.             }
  390.         }
  391.         iExec = pNdbConnection->execute_ok(Commit);
  392.         if (iExec == -1) 
  393.         {
  394.             ndbout << pNdbConnection->getNdbError() << endl;
  395.         }
  396.         if(iExec==0)
  397.         {
  398.             Uint32 nValue0 = ppNdbRecAttr[0]->u_32_value();
  399.             for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  400.             {
  401.                 for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple)
  402.                 {
  403.                     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  404.                     {
  405.                         Uint32 nValue = ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr]->u_32_value();
  406.                         Uint32 nExpected = nValue0 + (iTable*g_nTuple+iTuple)*g_nAttribute+iAttr;
  407.                         if(nValue!=nExpected)
  408.                         {
  409.                             ReportInconsistency(iPart, iTable, iTuple, iAttr, nValue, nExpected);
  410.                         }
  411.                     }
  412.                 }
  413.             }
  414.         }
  415.         pNdb->closeTransaction(pNdbConnection);
  416.     }
  417.     return 0;
  418. }
  419. int DeleteTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex)
  420. {
  421.     int iExec = -1;
  422.     int iCode = -1;
  423.     NdbConnection* pNdbConnection = pNdb->startTransaction();
  424.     if(pNdbConnection)
  425.     {
  426.         for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  427.         {
  428.             for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple)
  429.             {
  430.                 if(bIndex)
  431.                 {
  432.                     NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4);
  433.                     pNdbIndexOperation->deleteTuple();
  434.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  435.                     pNdbIndexOperation->equal("PK", nPK);
  436.                 }
  437.                 else
  438.                 {
  439.                     NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4);
  440.                     pNdbOperation->deleteTuple();
  441.                     Uint32 nPK = iPart*g_nTuple + iTuple;
  442.                     pNdbOperation->equal("PK", nPK);
  443.                 }
  444.             }
  445.         }
  446.         iExec = pNdbConnection->execute_ok(Commit);
  447.         if (iExec == -1) 
  448.         {
  449.             ndbout << pNdbConnection->getNdbError() << endl;
  450.         }
  451.         pNdb->closeTransaction(pNdbConnection);
  452.     }
  453.     return 0;
  454. }
  455. extern "C" void* ThreadFunc(void*)
  456. {
  457.     Ndb* pNdb = new Ndb("TEST_DB");
  458.     pNdb->init();
  459.     pNdb->waitUntilReady();
  460.     MT19937 rndgen;
  461.     rndgen.sgenrand((unsigned long)pNdb);
  462.     Uint32 nInsertError = 0;
  463.     Uint32 nInsertCommit = 0;
  464.     Uint32 nInsertRollback = 0;
  465.     Uint32 nUpdateGetAndSetError = 0;
  466.     Uint32 nUpdateGetAndSetCommit = 0;
  467.     Uint32 nUpdateGetAndSetRollback = 0;
  468.     Uint32 nReadError = 0;
  469.     Uint32 nReadCommit = 0;
  470.     Uint32 nReadRollback = 0;
  471.     Uint32 nUpdateInterpretedError = 0;
  472.     Uint32 nUpdateInterpretedCommit = 0;
  473.     Uint32 nUpdateInterpretedRollback = 0;
  474.     Uint32 nDeleteError = 0;
  475.     Uint32 nDeleteCommit = 0;
  476.     Uint32 nDeleteRollback = 0;
  477.     if (g_bVerify)
  478.     {
  479.         for (Uint32 iPart = 0; iPart < g_nPart; iPart++)
  480.         {
  481.             switch(ReadTransaction(pNdb, iPart, false))
  482.             {
  483.             case -1: ++nReadError; break;
  484.             case 0: ++nReadCommit; break;
  485.             case 1: ++nReadRollback; break;
  486.             }
  487.         }
  488.     }
  489.     else
  490.         while(NdbMutex_Trylock(g_pNdbMutexStop))
  491.         {
  492.             Uint32 iPart = rndgen.genrand() % g_nPart;
  493.             Uint32 iTrans = rndgen.genrand() % 5;
  494.             bool bIndex = ((rndgen.genrand() & 1) ? true : false);
  495.             switch(iTrans)
  496.             {
  497.             case 0: 
  498.                 switch(InsertTransaction(pNdb, iPart, bIndex))
  499.                 {
  500.                 case -1: ++nInsertError; break;
  501.                 case 0: ++nInsertCommit; break;
  502.                 case 1: ++nInsertRollback; break;
  503.                 }
  504.                 break;
  505.             case 1: 
  506.                 switch(UpdateGetAndSetTransaction(pNdb, iPart, bIndex))
  507.                 {
  508.                 case -1: ++nUpdateGetAndSetError; break;
  509.                 case 0: ++nUpdateGetAndSetCommit; break;
  510.                 case 1: ++nUpdateGetAndSetRollback; break;
  511.                 }
  512.                 break;
  513.             case 2: 
  514.                 switch(ReadTransaction(pNdb, iPart, bIndex))
  515.                 {
  516.                 case -1: ++nReadError; break;
  517.                 case 0: ++nReadCommit; break;
  518.                 case 1: ++nReadRollback; break;
  519.                 }
  520.                 break;
  521.             case 3: 
  522.                 switch(UpdateInterpretedTransaction(pNdb, iPart, bIndex))
  523.                 {
  524.                 case -1: ++nUpdateInterpretedError; break;
  525.                 case 0: ++nUpdateInterpretedCommit; break;
  526.                 case 1: ++nUpdateInterpretedRollback; break;
  527.                 }
  528.                 break;
  529.             case 4: 
  530.                 switch(DeleteTransaction(pNdb, iPart, bIndex))
  531.                 {
  532.                 case -1: ++nDeleteError; break;
  533.                 case 0: ++nDeleteCommit; break;
  534.                 case 1: ++nDeleteRollback; break;
  535.                 }
  536.                 break;
  537.             }
  538.         }
  539.         ndbout << "I:" << nInsertError << ":" << nInsertCommit << ":" << nInsertRollback;
  540.         ndbout << " UG:" << nUpdateGetAndSetError << ":" << nUpdateGetAndSetCommit << ":" << nUpdateGetAndSetRollback;
  541.         ndbout << " R:" << nReadError << ":" << nReadCommit << ":" << nReadRollback;
  542.         ndbout << " UI:" << nUpdateInterpretedError << ":" << nUpdateInterpretedCommit << ":" << nUpdateInterpretedRollback;
  543.         ndbout << " D:" << nDeleteError << ":" << nDeleteCommit << ":" << nDeleteRollback << endl;
  544.         ndbout << endl;
  545.         NdbMutex_Unlock(g_pNdbMutexStop);
  546.         delete pNdb;
  547.         return 0;
  548. }
  549. int main(int argc, char* argv[])
  550. {
  551.     ndb_init();
  552.     Uint32 nSeconds = 1;
  553.     Uint32 nThread = 1;
  554.     for(int iArg=1; iArg<argc; ++iArg)
  555.     {
  556.         if(argv[iArg][0]=='-')
  557.         {
  558.             switch(argv[iArg][1])
  559.             {
  560.             case 'p': g_nPart = atol(argv[iArg]+2); break;
  561.             case 'b': g_nTable = atol(argv[iArg]+2); break;
  562.             case 'u': g_nTuple = atol(argv[iArg]+2); break;
  563.             case 'a': g_nAttribute = atol(argv[iArg]+2); break;
  564.             case 'v': g_bVerify = true; break;
  565.             case 't': nThread = atol(argv[iArg]+2); break;
  566.             case 's': nSeconds = atol(argv[iArg]+2); break;
  567.             case 'i': g_bUseIndex = true; break;
  568.             }
  569.         }
  570.     }
  571.     ndbout << argv[0];
  572.     ndbout << " -p" << g_nPart;
  573.     ndbout << " -b" << g_nTable;
  574.     ndbout << " -u" << g_nTuple;
  575.     ndbout << " -a" << g_nAttribute;
  576.     if (g_bVerify)
  577.         ndbout << " -v";
  578.     ndbout << " -t" << nThread;
  579.     ndbout << " -s" << nSeconds;
  580.     ndbout << endl;
  581.     g_szTable = new char[g_nTable*4];
  582.     for(Uint32 iTable=0; iTable<g_nTable; ++iTable)
  583.     {
  584.         sprintf(g_szTable+iTable*4, "T%02d", iTable);
  585.     }
  586.     g_szIndex = new char[g_nTable*4];
  587.     for(Uint32 iIndex=0; iIndex<g_nTable; ++iIndex)
  588.     {
  589.         sprintf(g_szIndex+iIndex*4, "I%02d", iIndex);
  590.     }
  591.     g_szAttribute = new char[g_nAttribute*4];
  592.     for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr)
  593.     {
  594.         sprintf(g_szAttribute+iAttr*4, "A%02d", iAttr);
  595.     }
  596.     Ndb* pNdb = new Ndb("TEST_DB");
  597.     pNdb->init();
  598.     pNdb->waitUntilReady();
  599.     if (!g_bVerify) CreateTables(pNdb);
  600.     g_pNdbMutexStop = NdbMutex_Create();
  601.     NdbMutex_Lock(g_pNdbMutexStop);
  602.     NdbThread_SetConcurrencyLevel(nThread+1);
  603.     NdbThread** ppNdbThread = new NdbThread*[nThread];
  604.     for(Uint32 iThread=0; iThread<nThread; ++iThread)
  605.     {
  606.         ppNdbThread[iThread] = NdbThread_Create(ThreadFunc, 0, 0, "ThreadFunc", NDB_THREAD_PRIO_MEAN);
  607.     }
  608.     NdbSleep_SecSleep(nSeconds);
  609.     NdbMutex_Unlock(g_pNdbMutexStop);
  610.     for(Uint32 iThread=0; iThread<nThread; ++iThread)
  611.     {
  612.         void* status;
  613.         NdbThread_WaitFor(ppNdbThread[iThread], &status);
  614.     }
  615.     NdbMutex_Destroy(g_pNdbMutexStop);
  616.     g_pNdbMutexStop = 0;
  617.     delete pNdb;
  618. }