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