~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

Viewing changes to storage/ndb/test/ndbapi/flexBench.cpp

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2013-12-22 10:27:05 UTC
  • Revision ID: package-import@ubuntu.com-20131222102705-mndw7s12mz0szrcn
Tags: upstream-5.5.32
Import upstream version 5.5.32

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
 
15
 
 
16
 
 
17
/* ***************************************************
 
18
FLEXBENCH
 
19
Perform benchmark of insert, update and delete transactions
 
20
 
 
21
Arguments:
 
22
    -t Number of threads to start, default 1
 
23
    -o Number of operations per loop, default 500
 
24
    -l Number of loops to run, default 1, 0=infinite
 
25
    -a Number of attributes, default 25
 
26
    -c Number of tables, default 1
 
27
    -s Size of each attribute, default 1 (Primary Key is always of size 1,
 
28
    independent of this value)
 
29
    -lkn Number of long primary keys, default 1
 
30
    -lks Size of each long primary key, default 1
 
31
    -simple Use simple read to read from database
 
32
    -dirty Use dirty read to read from database
 
33
    -write Use writeTuple in insert and update
 
34
    -stdtables Use standard table names
 
35
    -no_table_create Don't create tables in db
 
36
    -sleep Sleep a number of seconds before running the test, this 
 
37
    can be used so that another flexBench have time to create tables
 
38
    -temp Use tables without logging
 
39
    -verify Verify inserts, updates and deletes
 
40
#ifdef CEBIT_STAT
 
41
    -statserv host:port  statistics server to report to
 
42
    -statfreq ops        report every ops operations (default 100)
 
43
#endif
 
44
    Returns:
 
45
    0 - Test passed
 
46
    1 - Test failed
 
47
    2 - Invalid arguments
 
48
 
 
49
* *************************************************** */
 
50
 
 
51
#include <ndb_global.h>
 
52
#include "NdbApi.hpp"
 
53
 
 
54
#include <NdbMain.h>
 
55
#include <NdbOut.hpp>
 
56
#include <NdbSleep.h>
 
57
#include <NdbTick.h>
 
58
#include <NdbTimer.hpp>
 
59
#include <NdbThread.h>
 
60
 
 
61
#include <NdbTest.hpp>
 
62
 
 
63
#define MAXSTRLEN 16 
 
64
#define MAXATTR 64
 
65
#define MAXTABLES 128
 
66
#define MAXATTRSIZE 1000
 
67
#define MAXNOLONGKEY 16 // Max number of long keys.
 
68
#define MAXLONGKEYTOTALSIZE 1023 // words = 4092 bytes
 
69
 
 
70
extern "C" { static void* flexBenchThread(void*); }
 
71
static int readArguments(int argc, const char** argv);
 
72
static int createTables(Ndb*);
 
73
static void sleepBeforeStartingTest(int seconds);
 
74
static void input_error();
 
75
 
 
76
enum StartType { 
 
77
  stIdle,
 
78
  stInsert,
 
79
  stVerify,
 
80
  stRead,
 
81
  stUpdate,
 
82
  stDelete,
 
83
  stTryDelete,
 
84
  stVerifyDelete,
 
85
  stStop 
 
86
};
 
87
 
 
88
struct ThreadData
 
89
{
 
90
  int threadNo;
 
91
  NdbThread* threadLife;
 
92
  int threadReady;  
 
93
  StartType threadStart;
 
94
  int threadResult;
 
95
};
 
96
 
 
97
static int                  tNodeId = 0 ;
 
98
static char                 tableName[MAXTABLES][MAXSTRLEN+1];
 
99
static char                 attrName[MAXATTR][MAXSTRLEN+1];
 
100
static char**               longKeyAttrName;
 
101
 
 
102
// Program Parameters
 
103
static int                  tNoOfLoops = 1;
 
104
static int                  tAttributeSize = 1;
 
105
static unsigned int         tNoOfThreads = 1;
 
106
static unsigned int         tNoOfTables = 1;
 
107
static unsigned int         tNoOfAttributes = 25;
 
108
static unsigned int         tNoOfOperations = 500;
 
109
static unsigned int         tSleepTime = 0;
 
110
static unsigned int         tNoOfLongPK = 1;
 
111
static unsigned int         tSizeOfLongPK = 1;
 
112
 
 
113
//Program Flags
 
114
static int                  theSimpleFlag = 0;
 
115
static int                  theDirtyFlag = 0;
 
116
static int                  theWriteFlag = 0;
 
117
static int                  theStdTableNameFlag = 0;
 
118
static int                  theTableCreateFlag = 0;
 
119
static bool                 theTempTable = false;
 
120
static bool                 VerifyFlag = true;
 
121
static bool                 useLongKeys = false;
 
122
 
 
123
 
 
124
static ErrorData theErrorData; // Part of flexBench-program
 
125
 
 
126
#define START_TIMER { NdbTimer timer; timer.doStart();
 
127
#define STOP_TIMER timer.doStop();
 
128
#define PRINT_TIMER(text, trans, opertrans) timer.printTransactionStatistics(text, trans, opertrans); };
 
129
 
 
130
#include <NdbTCP.h>
 
131
 
 
132
#ifdef CEBIT_STAT
 
133
#include <NdbMutex.h>
 
134
static bool statEnable = false;
 
135
static char statHost[100];
 
136
static int statFreq = 100;
 
137
static int statPort = 0;
 
138
static int statSock = -1;
 
139
static enum { statError = -1, statClosed, statOpen } statState;
 
140
static NdbMutex statMutex = NDB_MUTEX_INITIALIZER;
 
141
#endif
 
142
 
 
143
//-------------------------------------------------------------------
 
144
// Statistical Reporting routines
 
145
//-------------------------------------------------------------------
 
146
#ifdef CEBIT_STAT
 
147
// Experimental client-side statistic for CeBIT
 
148
 
 
149
static void
 
150
statReport(enum StartType st, int ops)
 
151
{
 
152
  if (!statEnable)
 
153
    return;
 
154
  if (NdbMutex_Lock(&statMutex) < 0) {
 
155
    if (statState != statError) {
 
156
      ndbout_c("stat: lock mutex failed: %s", strerror(errno));
 
157
      statState = statError;
 
158
    }
 
159
    return;
 
160
  }
 
161
  static int nodeid;
 
162
  // open connection
 
163
  if (statState != statOpen) {
 
164
    char *p = getenv("NDB_NODEID");             // ndbnet sets NDB_NODEID
 
165
    nodeid = p == 0 ? 0 : atoi(p);
 
166
    if ((statSock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
 
167
      if (statState != statError) {
 
168
        ndbout_c("stat: create socket failed: %s", strerror(errno));
 
169
        statState = statError;
 
170
      }
 
171
      (void)NdbMutex_Unlock(&statMutex);
 
172
      return;
 
173
    }
 
174
    struct sockaddr_in saddr;
 
175
    memset(&saddr, 0, sizeof(saddr));
 
176
    saddr.sin_family = AF_INET;
 
177
    saddr.sin_port = htons(statPort);
 
178
    if (Ndb_getInAddr(&saddr.sin_addr, statHost) < 0) {
 
179
      if (statState != statError) {
 
180
        ndbout_c("stat: host %s not found", statHost);
 
181
        statState = statError;
 
182
      }
 
183
      (void)close(statSock);
 
184
      (void)NdbMutex_Unlock(&statMutex);
 
185
      return;
 
186
    }
 
187
    if (connect(statSock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
 
188
      if (statState != statError) {
 
189
        ndbout_c("stat: connect failed: %s", strerror(errno));
 
190
        statState = statError;
 
191
      }
 
192
      (void)close(statSock);
 
193
      (void)NdbMutex_Unlock(&statMutex);
 
194
      return;
 
195
    }
 
196
    statState = statOpen;
 
197
    ndbout_c("stat: connection to %s:%d opened", statHost, (int)statPort);
 
198
  }
 
199
  const char *text;
 
200
  switch (st) {
 
201
  case stInsert:
 
202
    text = "insert";
 
203
    break;
 
204
  case stVerify:
 
205
    text = "verify";
 
206
    break;
 
207
  case stRead:
 
208
    text = "read";
 
209
    break;
 
210
  case stUpdate:
 
211
    text = "update";
 
212
    break;
 
213
  case stDelete:
 
214
    text = "delete";
 
215
    break;
 
216
  case stVerifyDelete:
 
217
    text = "verifydelete";
 
218
    break;
 
219
  default:
 
220
    text = "unknown";
 
221
    break;
 
222
  }
 
223
  char buf[100];
 
224
  sprintf(buf, "%d %s %d\n", nodeid, text, ops);
 
225
  int len = strlen(buf);
 
226
  // assume SIGPIPE already ignored
 
227
  if (write(statSock, buf, len) != len) {
 
228
    if (statState != statError) {
 
229
      ndbout_c("stat: write failed: %s", strerror(errno));
 
230
      statState = statError;
 
231
    }
 
232
    (void)close(statSock);
 
233
    (void)NdbMutex_Unlock(&statMutex);
 
234
    return;
 
235
  }
 
236
  (void)NdbMutex_Unlock(&statMutex);
 
237
}
 
238
#endif  // CEBIT_STAT
 
239
 
 
240
static void 
 
241
resetThreads(ThreadData* pt){
 
242
  for (unsigned int i = 0; i < tNoOfThreads; i++){
 
243
    pt[i].threadReady = 0;
 
244
    pt[i].threadResult = 0;
 
245
    pt[i].threadStart = stIdle;
 
246
  }
 
247
}
 
248
 
 
249
static int 
 
250
checkThreadResults(ThreadData* pt){
 
251
  for (unsigned int i = 0; i < tNoOfThreads; i++){
 
252
    if(pt[i].threadResult != 0){
 
253
      ndbout_c("Thread%d reported fatal error %d", i, pt[i].threadResult);
 
254
      return -1;
 
255
    }
 
256
  }
 
257
  return 0;
 
258
}
 
259
 
 
260
static
 
261
void 
 
262
waitForThreads(ThreadData* pt)
 
263
{
 
264
  int cont = 1;
 
265
  while (cont){
 
266
    NdbSleep_MilliSleep(100);
 
267
    cont = 0;
 
268
    for (unsigned int i = 0; i < tNoOfThreads; i++){
 
269
      if (pt[i].threadReady == 0) 
 
270
    cont = 1;
 
271
    }
 
272
  }
 
273
}
 
274
 
 
275
static void 
 
276
tellThreads(ThreadData* pt, StartType what)
 
277
{
 
278
  for (unsigned int i = 0; i < tNoOfThreads; i++) 
 
279
    pt[i].threadStart = what;
 
280
}
 
281
 
 
282
static Ndb_cluster_connection *g_cluster_connection= 0;
 
283
 
 
284
NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
 
285
{
 
286
  ndb_init();
 
287
  ThreadData*           pThreadsData;
 
288
  int                   tLoops = 0, i;
 
289
  int                   returnValue = NDBT_OK;
 
290
    
 
291
  if (readArguments(argc, argv) != 0){
 
292
    input_error();
 
293
    return NDBT_ProgramExit(NDBT_WRONGARGS);
 
294
  }
 
295
 
 
296
  if(useLongKeys){
 
297
    longKeyAttrName = (char **) malloc(sizeof(char*) * tNoOfLongPK);
 
298
    for (Uint32 i = 0; i < tNoOfLongPK; i++) {
 
299
      longKeyAttrName[i] = (char *) malloc(strlen("KEYATTR  ") + 1);
 
300
      memset(longKeyAttrName[i], 0, strlen("KEYATTR  ") + 1);
 
301
      sprintf(longKeyAttrName[i], "KEYATTR%i", i);
 
302
    }
 
303
  }
 
304
  
 
305
  pThreadsData = new ThreadData[tNoOfThreads];
 
306
 
 
307
  ndbout << endl << "FLEXBENCH - Starting normal mode" << endl;
 
308
  ndbout << "Perform benchmark of insert, update and delete transactions"<< endl;
 
309
  ndbout << "  " << tNoOfThreads << " thread(s) " << endl;
 
310
  ndbout << "  " << tNoOfLoops << " iterations " << endl;
 
311
  ndbout << "  " << tNoOfTables << " table(s) and " << 1 << " operation(s) per transaction " <<endl;
 
312
  ndbout << "  " << tNoOfAttributes << " attributes per table " << endl;
 
313
  ndbout << "  " << tNoOfOperations << " transaction(s) per thread and round " << endl;
 
314
  ndbout << "  " << tAttributeSize << " is the number of 32 bit words per attribute "<< endl;
 
315
  ndbout << "  " << "Table(s) without logging: " << (Uint32)theTempTable << endl;
 
316
  
 
317
  if(useLongKeys)
 
318
    ndbout << "  " << "Using long keys with " << tNoOfLongPK << " keys a' " << 
 
319
      tSizeOfLongPK * 4 << " bytes each." << endl;
 
320
  
 
321
  ndbout << "  " << "Verification is " ; 
 
322
  if(VerifyFlag) {
 
323
      ndbout << "enabled" << endl ;
 
324
  }else{
 
325
      ndbout << "disabled" << endl ;
 
326
  }
 
327
  theErrorData.printSettings(ndbout);
 
328
  
 
329
  NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
 
330
 
 
331
  Ndb_cluster_connection con;
 
332
  if(con.connect(12, 5, 1) != 0)
 
333
  {
 
334
    return NDBT_ProgramExit(NDBT_FAILED);
 
335
  }
 
336
 
 
337
  g_cluster_connection= &con;
 
338
 
 
339
  Ndb* pNdb;
 
340
  pNdb = new Ndb(&con, "TEST_DB" );  
 
341
  pNdb->init();
 
342
 
 
343
  tNodeId = pNdb->getNodeId();
 
344
  ndbout << "  NdbAPI node with id = " << tNodeId << endl;
 
345
  ndbout << endl;
 
346
  
 
347
  ndbout << "Waiting for ndb to become ready..." <<endl;
 
348
  if (pNdb->waitUntilReady(2000) != 0){
 
349
    ndbout << "NDB is not ready" << endl;
 
350
    ndbout << "Benchmark failed!" << endl;
 
351
    returnValue = NDBT_FAILED;
 
352
  }
 
353
 
 
354
  if(returnValue == NDBT_OK){
 
355
    if (createTables(pNdb) != 0){
 
356
      returnValue = NDBT_FAILED;
 
357
    }
 
358
  }
 
359
 
 
360
  if(returnValue == NDBT_OK){
 
361
 
 
362
    sleepBeforeStartingTest(tSleepTime);
 
363
    
 
364
    /****************************************************************
 
365
     *  Create threads.                                           *
 
366
     ****************************************************************/
 
367
    resetThreads(pThreadsData);
 
368
    
 
369
    for (i = 0; i < tNoOfThreads; i++){  
 
370
      pThreadsData[i].threadNo = i;
 
371
      pThreadsData[i].threadLife = NdbThread_Create(flexBenchThread,
 
372
                                                    (void**)&pThreadsData[i],
 
373
                                                    32768,
 
374
                                                    "flexBenchThread",
 
375
                                                    NDB_THREAD_PRIO_LOW);
 
376
    }
 
377
    
 
378
    waitForThreads(pThreadsData);
 
379
    
 
380
    ndbout << endl <<  "All threads started" << endl << endl;
 
381
    
 
382
    /****************************************************************
 
383
     * Execute program.                                             *
 
384
     ****************************************************************/
 
385
  
 
386
    for(;;){
 
387
 
 
388
      int loopCount = tLoops + 1;
 
389
      ndbout << endl << "Loop # " << loopCount  << endl << endl;
 
390
      
 
391
      /****************************************************************
 
392
       * Perform inserts.                                             *
 
393
       ****************************************************************/
 
394
      // Reset and start timer
 
395
      START_TIMER;
 
396
      // Give insert-command to all threads
 
397
      resetThreads(pThreadsData);
 
398
      tellThreads(pThreadsData, stInsert);
 
399
      waitForThreads(pThreadsData);
 
400
      if (checkThreadResults(pThreadsData) != 0){
 
401
        ndbout << "Error: Threads failed in performing insert" << endl;
 
402
        returnValue = NDBT_FAILED;
 
403
        break;
 
404
      }        
 
405
      // stop timer and print results.
 
406
      STOP_TIMER;
 
407
      PRINT_TIMER("insert", tNoOfOperations*tNoOfThreads, tNoOfTables);
 
408
      /****************************************************************
 
409
      * Verify inserts.                                             *
 
410
      ****************************************************************/
 
411
      if (VerifyFlag) {
 
412
      resetThreads(pThreadsData);
 
413
      ndbout << "Verifying inserts...\t" ;
 
414
      tellThreads(pThreadsData, stVerify);
 
415
      waitForThreads(pThreadsData);
 
416
      if (checkThreadResults(pThreadsData) != 0){
 
417
        ndbout << "Error: Threads failed while verifying inserts" << endl;
 
418
        returnValue = NDBT_FAILED;
 
419
        break;
 
420
      }else{
 
421
          ndbout << "\t\tOK" << endl << endl ;
 
422
      }
 
423
      }
 
424
      
 
425
      /****************************************************************
 
426
       * Perform read.                                                *
 
427
       ****************************************************************/
 
428
      // Reset and start timer 
 
429
      START_TIMER;
 
430
      // Give read-command to all threads
 
431
      resetThreads(pThreadsData);
 
432
      tellThreads(pThreadsData, stRead);
 
433
      waitForThreads(pThreadsData);
 
434
      if (checkThreadResults(pThreadsData) != 0){
 
435
        ndbout << "Error: Threads failed in performing read" << endl;
 
436
        returnValue = NDBT_FAILED;
 
437
        break;
 
438
      }
 
439
      // stop timer and print results.
 
440
      STOP_TIMER;
 
441
      PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
 
442
      
 
443
      /****************************************************************
 
444
       * Perform update.                                              *
 
445
       ****************************************************************/
 
446
      // Reset and start timer
 
447
      START_TIMER;
 
448
      // Give insert-command to all threads
 
449
      resetThreads(pThreadsData);
 
450
      tellThreads(pThreadsData, stUpdate);
 
451
      waitForThreads(pThreadsData);
 
452
      if (checkThreadResults(pThreadsData) != 0){
 
453
        ndbout << "Error: Threads failed in performing update" << endl;
 
454
        returnValue = NDBT_FAILED;
 
455
        break;
 
456
      }
 
457
      // stop timer and print results.
 
458
      STOP_TIMER;
 
459
      PRINT_TIMER("update", tNoOfOperations*tNoOfThreads, tNoOfTables);
 
460
      
 
461
      /****************************************************************
 
462
      * Verify updates.                                             *
 
463
      ****************************************************************/
 
464
      if (VerifyFlag) {
 
465
      resetThreads(pThreadsData);
 
466
      ndbout << "Verifying updates...\t" ;
 
467
      tellThreads(pThreadsData, stVerify);
 
468
      waitForThreads(pThreadsData);
 
469
      if (checkThreadResults(pThreadsData) != 0){
 
470
        ndbout << "Error: Threads failed while verifying updates" << endl;
 
471
        returnValue = NDBT_FAILED;
 
472
        break;
 
473
      }else{
 
474
          ndbout << "\t\tOK" << endl << endl ;
 
475
      }
 
476
      }
 
477
      
 
478
      /****************************************************************
 
479
       * Perform read.                                             *
 
480
       ****************************************************************/
 
481
      // Reset and start timer
 
482
      START_TIMER;
 
483
      // Give insert-command to all threads
 
484
      resetThreads(pThreadsData);
 
485
      tellThreads(pThreadsData, stRead);
 
486
      waitForThreads(pThreadsData);
 
487
      if (checkThreadResults(pThreadsData) != 0){
 
488
        ndbout << "Error: Threads failed in performing read" << endl;
 
489
        returnValue = NDBT_FAILED;
 
490
        break;
 
491
      }
 
492
      // stop timer and print results.
 
493
      STOP_TIMER;
 
494
      PRINT_TIMER("read", tNoOfOperations*tNoOfThreads, tNoOfTables);
 
495
 
 
496
      /****************************************************************
 
497
       * Perform delete.                                              *
 
498
       ****************************************************************/
 
499
      // Reset and start timer
 
500
      START_TIMER;
 
501
      // Give insert-command to all threads
 
502
      resetThreads(pThreadsData);
 
503
      tellThreads(pThreadsData, stDelete);
 
504
      waitForThreads(pThreadsData);
 
505
      if (checkThreadResults(pThreadsData) != 0){
 
506
        ndbout << "Error: Threads failed in performing delete" << endl;
 
507
        returnValue = NDBT_FAILED;
 
508
        break;
 
509
      }
 
510
      // stop timer and print results.
 
511
      STOP_TIMER;
 
512
      PRINT_TIMER("delete", tNoOfOperations*tNoOfThreads, tNoOfTables);
 
513
 
 
514
      /****************************************************************
 
515
      * Verify deletes.                                              *
 
516
      ****************************************************************/
 
517
      if (VerifyFlag) {
 
518
      resetThreads(pThreadsData);
 
519
      ndbout << "Verifying tuple deletion..." ;
 
520
      tellThreads(pThreadsData, stVerifyDelete);
 
521
      waitForThreads(pThreadsData);
 
522
      if (checkThreadResults(pThreadsData) != 0){
 
523
          ndbout << "Error: Threads failed in verifying deletes" << endl;
 
524
          returnValue = NDBT_FAILED;
 
525
          break;
 
526
      }else{ 
 
527
          ndbout << "\t\tOK" << endl << endl ;
 
528
      }
 
529
      }
 
530
 
 
531
      ndbout << "--------------------------------------------------" << endl;
 
532
 
 
533
      tLoops++;
 
534
 
 
535
      if ( 0 != tNoOfLoops && tNoOfLoops <= tLoops ) 
 
536
        break;
 
537
      theErrorData.printErrorCounters();
 
538
    }
 
539
    
 
540
    resetThreads(pThreadsData);
 
541
    tellThreads(pThreadsData, stStop);
 
542
    waitForThreads(pThreadsData);
 
543
 
 
544
    void * tmp;
 
545
    for(i = 0; i<tNoOfThreads; i++){
 
546
      NdbThread_WaitFor(pThreadsData[i].threadLife, &tmp);
 
547
      NdbThread_Destroy(&pThreadsData[i].threadLife);
 
548
    }
 
549
  }
 
550
 
 
551
  if (useLongKeys == true) {
 
552
    // Only free these areas if they have been allocated
 
553
    // Otherwise cores will happen
 
554
    for (i = 0; i < tNoOfLongPK; i++)
 
555
      free(longKeyAttrName[i]);
 
556
    free(longKeyAttrName);
 
557
  } // if
 
558
 
 
559
  delete [] pThreadsData;
 
560
  delete pNdb;
 
561
  theErrorData.printErrorCounters();
 
562
  return NDBT_ProgramExit(returnValue);
 
563
}
 
564
////////////////////////////////////////
 
565
 
 
566
 
 
567
unsigned long get_hash(unsigned long * hash_key, int len)
 
568
{
 
569
  unsigned long hash_value = 147;
 
570
  unsigned h_key;
 
571
  int i;
 
572
  for (i = 0; i < len; i++)
 
573
    {
 
574
      h_key = hash_key[i];
 
575
      hash_value = (hash_value << 5) + hash_value + (h_key & 255);
 
576
      hash_value = (hash_value << 5) + hash_value + ((h_key >> 8) & 255);
 
577
      hash_value = (hash_value << 5) + hash_value + ((h_key >> 16) & 255);
 
578
      hash_value = (hash_value << 5) + hash_value + ((h_key >> 24) & 255);
 
579
    }
 
580
  return hash_value;
 
581
}
 
582
 
 
583
// End of warming up phase
 
584
 
 
585
 
 
586
 
 
587
static void* flexBenchThread(void* pArg)
 
588
{
 
589
  ThreadData*       pThreadData = (ThreadData*)pArg;
 
590
  unsigned int      threadNo, threadBase;
 
591
  Ndb*              pNdb = NULL ;
 
592
  NdbConnection     *pTrans = NULL ;
 
593
  NdbOperation**    pOps = NULL ;
 
594
  StartType         tType ;
 
595
  StartType         tSaveType ;
 
596
  NdbRecAttr*       tTmp = NULL ;
 
597
  int*              attrValue = NULL ;
 
598
  int*              attrRefValue = NULL ;
 
599
  int               check = 0 ;
 
600
  int               loopCountOps, loopCountTables, loopCountAttributes;
 
601
  int               tAttemptNo = 0;
 
602
  int               tRetryAttempts = 20;
 
603
  int               tResult = 0;
 
604
  int               tSpecialTrans = 0;
 
605
  int               nRefLocalOpOffset = 0 ;
 
606
  int               nReadBuffSize = 
 
607
    tNoOfTables * tNoOfAttributes * sizeof(int) * tAttributeSize ;
 
608
  int               nRefBuffSize = 
 
609
    tNoOfOperations * tNoOfAttributes * sizeof(int) * tAttributeSize ;
 
610
  unsigned***           longKeyAttrValue;
 
611
 
 
612
 
 
613
  threadNo = pThreadData->threadNo ;
 
614
 
 
615
  attrValue = (int*)malloc(nReadBuffSize) ;
 
616
  attrRefValue = (int*)malloc(nRefBuffSize) ;
 
617
  pOps = (NdbOperation**)malloc(tNoOfTables*sizeof(NdbOperation*)) ;
 
618
  pNdb = new Ndb(g_cluster_connection, "TEST_DB" );
 
619
  
 
620
  if(!attrValue || !attrRefValue || !pOps || !pNdb){
 
621
    // Check allocations to make sure we got all the memory we asked for
 
622
    ndbout << "One or more memory allocations failed when starting thread #";
 
623
    ndbout << threadNo << endl ;
 
624
    ndbout << "Thread #" << threadNo << " will now exit" << endl ;
 
625
    tResult = 13 ;
 
626
    free(attrValue) ;
 
627
    free(attrRefValue) ;
 
628
    free(pOps) ;
 
629
    delete pNdb ;
 
630
    return 0; // thread exits
 
631
  }
 
632
  
 
633
  pNdb->init();
 
634
  pNdb->waitUntilReady();
 
635
 
 
636
  // To make sure that two different threads doesn't operate on the same record
 
637
  // Calculate an "unique" number to use as primary key
 
638
  threadBase = (threadNo * 2000000) + (tNodeId * 260000000);
 
639
  
 
640
  if(useLongKeys){
 
641
    // Allocate and populate the longkey array.
 
642
    longKeyAttrValue = (unsigned ***) malloc(sizeof(unsigned**) * tNoOfOperations );
 
643
    Uint32 n;
 
644
    for (n = 0; n < tNoOfOperations; n++)
 
645
      longKeyAttrValue[n] = (unsigned **) malloc(sizeof(unsigned*) * tNoOfLongPK );
 
646
    for (n = 0; n < tNoOfOperations; n++){
 
647
      for (Uint32 i = 0; i < tNoOfLongPK ; i++) {
 
648
        longKeyAttrValue[n][i] = (unsigned *) malloc(sizeof(unsigned) * tSizeOfLongPK);
 
649
        memset(longKeyAttrValue[n][i], 0, sizeof(unsigned) * tSizeOfLongPK);
 
650
        for(Uint32 j = 0; j < tSizeOfLongPK; j++) {
 
651
          // Repeat the unique value to fill up the long key.
 
652
          longKeyAttrValue[n][i][j] = threadBase + n; 
 
653
        }
 
654
      }
 
655
    }
 
656
  }
 
657
 
 
658
  int nRefOpOffset = 0 ;
 
659
  //Assign reference attribute values to memory
 
660
  for(Uint32 ops = 1 ; ops < tNoOfOperations ; ops++){
 
661
    // Calculate offset value before going into the next loop
 
662
    nRefOpOffset = tAttributeSize*tNoOfAttributes*(ops-1) ; 
 
663
    for(Uint32 a = 0 ; a < tNoOfAttributes ; a++){
 
664
      *(int*)&attrRefValue[nRefOpOffset + tAttributeSize*a] = 
 
665
        (int)(threadBase + ops + a) ;
 
666
    }
 
667
  }
 
668
 
 
669
#ifdef CEBIT_STAT
 
670
  // ops not yet reported
 
671
  int statOps = 0;
 
672
#endif
 
673
  for (;;) {
 
674
    pThreadData->threadResult = tResult; // Report error to main thread, 
 
675
    // normally tResult is set to 0
 
676
    pThreadData->threadReady = 1;
 
677
 
 
678
    while (pThreadData->threadStart == stIdle){
 
679
      NdbSleep_MilliSleep(100);
 
680
    }//while
 
681
 
 
682
    // Check if signal to exit is received
 
683
    if (pThreadData->threadStart == stStop){
 
684
      pThreadData->threadReady = 1;
 
685
      // ndbout_c("Thread%d is stopping", threadNo);
 
686
      // In order to stop this thread, the main thread has signaled
 
687
      // stStop, break out of the for loop so that destructors
 
688
      // and the proper exit functions are called
 
689
      break;
 
690
    }//if
 
691
 
 
692
    tType = pThreadData->threadStart;
 
693
    tSaveType = tType;
 
694
    pThreadData->threadStart = stIdle;
 
695
 
 
696
    // Start transaction, type of transaction
 
697
    // is received in the array ThreadStart
 
698
    loopCountOps = tNoOfOperations;
 
699
    loopCountTables = tNoOfTables;
 
700
    loopCountAttributes = tNoOfAttributes;
 
701
 
 
702
    for (int count = 1; count < loopCountOps && tResult == 0;){
 
703
 
 
704
      pTrans = pNdb->startTransaction();
 
705
      if (pTrans == NULL) {
 
706
        // This is a fatal error, abort program
 
707
        ndbout << "Could not start transaction in thread" << threadNo;
 
708
        ndbout << endl;
 
709
        ndbout << pNdb->getNdbError() << endl;
 
710
        tResult = 1; // Indicate fatal error
 
711
        break; // Break out of for loop
 
712
      }
 
713
 
 
714
      // Calculate the current operation offset in the reference array
 
715
      nRefLocalOpOffset = tAttributeSize*tNoOfAttributes*(count - 1) ;
 
716
 
 
717
      for (int countTables = 0;
 
718
           countTables < loopCountTables && tResult == 0;
 
719
           countTables++) {
 
720
 
 
721
        pOps[countTables] = pTrans->getNdbOperation(tableName[countTables]);  
 
722
        if (pOps[countTables] == NULL) {
 
723
          // This is a fatal error, abort program
 
724
          ndbout << "getNdbOperation: " << pTrans->getNdbError();
 
725
          tResult = 2; // Indicate fatal error
 
726
          break;
 
727
        }//if
 
728
 
 
729
        switch (tType) {
 
730
        case stInsert:          // Insert case
 
731
          if (theWriteFlag == 1 && theDirtyFlag == 1)
 
732
            pOps[countTables]->dirtyWrite();
 
733
          else if (theWriteFlag == 1)
 
734
            pOps[countTables]->writeTuple();
 
735
          else
 
736
            pOps[countTables]->insertTuple();
 
737
          break;
 
738
        case stRead:            // Read Case
 
739
          if (theSimpleFlag == 1)
 
740
            pOps[countTables]->simpleRead();
 
741
          else if (theDirtyFlag == 1)
 
742
            pOps[countTables]->dirtyRead();
 
743
          else
 
744
            pOps[countTables]->readTuple();
 
745
          break;
 
746
        case stUpdate:          // Update Case
 
747
          if (theWriteFlag == 1 && theDirtyFlag == 1)
 
748
            pOps[countTables]->dirtyWrite();
 
749
          else if (theWriteFlag == 1)
 
750
            pOps[countTables]->writeTuple();
 
751
          else if (theDirtyFlag == 1)
 
752
            pOps[countTables]->dirtyUpdate();
 
753
          else
 
754
            pOps[countTables]->updateTuple();
 
755
          break;
 
756
        case stDelete:          // Delete Case
 
757
          pOps[countTables]->deleteTuple();
 
758
          break;
 
759
        case stVerify:
 
760
          pOps[countTables]->readTuple();
 
761
          break;
 
762
        case stVerifyDelete:
 
763
          pOps[countTables]->readTuple();
 
764
          break;
 
765
        default:
 
766
          assert(false);
 
767
        }//switch
 
768
 
 
769
        
 
770
        if(useLongKeys){
 
771
          // Loop the equal call so the complete key is send to the kernel.
 
772
          for(Uint32 i = 0; i < tNoOfLongPK; i++) 
 
773
            pOps[countTables]->equal(longKeyAttrName[i], 
 
774
                                     (char *)longKeyAttrValue[count - 1][i], tSizeOfLongPK*4); 
 
775
        }
 
776
        else 
 
777
          pOps[countTables]->equal((Uint32)0, 
 
778
                                   (char*)&attrRefValue[nRefLocalOpOffset]);
 
779
        
 
780
        if (tType == stInsert || tType == stUpdate){
 
781
          for (int ca = 1; ca < loopCountAttributes; ca++){
 
782
            pOps[countTables]->setValue((Uint32)ca,
 
783
                                        (char*)&attrRefValue[nRefLocalOpOffset + tAttributeSize*ca]);
 
784
          }//for
 
785
        } else if (tType == stRead || stVerify == tType) {
 
786
          int nTableOffset = tAttributeSize * 
 
787
            loopCountAttributes *
 
788
            countTables ;
 
789
          for (int ca = 1; ca < loopCountAttributes; ca++) {
 
790
            tTmp = pOps[countTables]->getValue((Uint32)ca, 
 
791
                                               (char*)&attrValue[nTableOffset + tAttributeSize*ca]);
 
792
          }//for
 
793
        } else if (stVerifyDelete == tType) {
 
794
          if(useLongKeys){
 
795
            int nTableOffset = tAttributeSize *
 
796
              loopCountAttributes *
 
797
              countTables ;
 
798
            tTmp = pOps[countTables]->getValue(longKeyAttrName[0], 
 
799
                                               (char*)&attrValue[nTableOffset]);
 
800
          } else {
 
801
            int nTableOffset = tAttributeSize *
 
802
              loopCountAttributes *
 
803
              countTables ;
 
804
            tTmp = pOps[countTables]->getValue((Uint32)0, 
 
805
                                               (char*)&attrValue[nTableOffset]);
 
806
          }
 
807
        }//if
 
808
      }//for Tables loop
 
809
 
 
810
      if (tResult != 0)
 
811
        break;
 
812
      check = pTrans->execute(Commit);
 
813
 
 
814
      // Decide what kind of error this is
 
815
      if ((tSpecialTrans == 1) &&
 
816
          (check == -1)) {
 
817
        // --------------------------------------------------------------------
 
818
        // A special transaction have been executed, change to check = 0 in
 
819
        // certain situations.
 
820
        // --------------------------------------------------------------------
 
821
        switch (tType) {
 
822
        case stInsert:          // Insert case
 
823
          if (630 == pTrans->getNdbError().code ) {
 
824
            check = 0;
 
825
            ndbout << "Insert with 4007 was successful" << endl;
 
826
          }//if
 
827
          break;
 
828
        case stDelete:          // Delete Case
 
829
          if (626 == pTrans->getNdbError().code ) {
 
830
            check = 0;
 
831
            ndbout << "Delete with 4007 was successful" << endl;
 
832
          }//if
 
833
          break;
 
834
        default:
 
835
          assert(false);
 
836
        }//switch
 
837
      }//if
 
838
      tSpecialTrans = 0;
 
839
      if (check == -1) {
 
840
        if ((stVerifyDelete == tType) && 
 
841
            (626 == pTrans->getNdbError().code)) {
 
842
          // ----------------------------------------------
 
843
          // It's good news - the deleted tuple is gone, 
 
844
          // so reset "check" flag
 
845
          // ----------------------------------------------
 
846
          check = 0 ;
 
847
        } else {
 
848
          int retCode = 
 
849
            theErrorData.handleErrorCommon(pTrans->getNdbError());
 
850
          if (retCode == 1) {
 
851
            ndbout_c("execute: %d, %d, %s", count, tType, 
 
852
                     pTrans->getNdbError().message );
 
853
            ndbout_c("Error code = %d", pTrans->getNdbError().code );
 
854
            tResult = 20;
 
855
          } else if (retCode == 2) {
 
856
            ndbout << "4115 should not happen in flexBench" << endl;
 
857
            tResult = 20;
 
858
          } else if (retCode == 3) {
 
859
            // --------------------------------------------------------------------
 
860
            // We are not certain if the transaction was successful or not.
 
861
            // We must reexecute but might very well find that the transaction
 
862
            // actually was updated. Updates and Reads are no problem here. Inserts
 
863
            // will not cause a problem if error code 630 arrives. Deletes will
 
864
            // not cause a problem if 626 arrives.
 
865
            // --------------------------------------------------------------------
 
866
            if ((tType == stInsert) || (tType == stDelete)) {
 
867
              tSpecialTrans = 1;
 
868
            }//if
 
869
          }//if
 
870
        }//if
 
871
      }//if
 
872
      // Check if retries should be made
 
873
      if (check == -1 && tResult == 0) {
 
874
        if (tAttemptNo < tRetryAttempts){
 
875
          tAttemptNo++;
 
876
        } else {
 
877
          // --------------------------------------------------------------------
 
878
          // Too many retries have been made, report error and break out of loop
 
879
          // --------------------------------------------------------------------
 
880
          ndbout << "Thread" << threadNo;
 
881
          ndbout << ": too many errors reported" << endl;
 
882
          tResult = 10;
 
883
          break;
 
884
        }//if            
 
885
      }//if
 
886
 
 
887
      if (check == 0){
 
888
        // Go to the next record
 
889
        count++;
 
890
        tAttemptNo = 0;
 
891
#ifdef CEBIT_STAT
 
892
        // report successful ops
 
893
        if (statEnable) {
 
894
          statOps += loopCountTables;
 
895
          if (statOps >= statFreq) {
 
896
            statReport(tType, statOps);
 
897
            statOps = 0;
 
898
          }//if
 
899
        }//if
 
900
#endif
 
901
      }//if
 
902
 
 
903
      if (stVerify == tType && 0 == check){
 
904
        int nTableOffset = 0 ;
 
905
        for (int a = 1 ; a < loopCountAttributes ; a++){
 
906
          for (int tables = 0 ; tables < loopCountTables ; tables++){
 
907
            nTableOffset = tables*loopCountAttributes*tAttributeSize ;
 
908
            if (*(int*)&attrValue[nTableOffset + tAttributeSize*a] != *(int*)&attrRefValue[nRefLocalOpOffset + tAttributeSize*a]){
 
909
              ndbout << "Error in verify:" << endl ;
 
910
              ndbout << "attrValue[" << nTableOffset + tAttributeSize*a << "] = " << attrValue[a] << endl ;
 
911
              ndbout << "attrRefValue[" << nRefLocalOpOffset + tAttributeSize*a << "]" << attrRefValue[nRefLocalOpOffset + tAttributeSize*a] << endl ;
 
912
              tResult = 11 ;
 
913
              break ;
 
914
            }//if
 
915
          }//for
 
916
        }//for
 
917
      }// if(stVerify ... )
 
918
      pNdb->closeTransaction(pTrans) ;  
 
919
    }// operations loop
 
920
#ifdef CEBIT_STAT
 
921
    // report remaining successful ops
 
922
    if (statEnable) {
 
923
      if (statOps > 0) {
 
924
        statReport(tType, statOps);
 
925
        statOps = 0;
 
926
      }//if
 
927
    }//if
 
928
#endif
 
929
  }
 
930
  delete pNdb;
 
931
  free(attrValue) ;
 
932
  free(attrRefValue) ;
 
933
  free(pOps) ;
 
934
 
 
935
  if (useLongKeys == true) {
 
936
    // Only free these areas if they have been allocated
 
937
    // Otherwise cores will occur
 
938
    for (Uint32 n = 0; n < tNoOfOperations; n++){
 
939
      for (Uint32 i = 0; i < tNoOfLongPK; i++) {
 
940
        free(longKeyAttrValue[n][i]);
 
941
      }
 
942
      free(longKeyAttrValue[n]);
 
943
    }
 
944
    free(longKeyAttrValue);
 
945
  } // if
 
946
 
 
947
  return NULL; // Thread exits
 
948
}
 
949
 
 
950
 
 
951
static int readArguments(int argc, const char** argv)
 
952
{
 
953
 
 
954
  int i = 1;
 
955
  while (argc > 1){
 
956
    if (strcmp(argv[i], "-t") == 0){
 
957
      tNoOfThreads = atoi(argv[i+1]);
 
958
      if ((tNoOfThreads < 1)) 
 
959
        return -1;
 
960
      argc -= 1;
 
961
      i++;
 
962
    }else if (strcmp(argv[i], "-o") == 0){
 
963
      tNoOfOperations = atoi(argv[i+1]);
 
964
      if (tNoOfOperations < 1) 
 
965
        return -1;;
 
966
      argc -= 1;
 
967
      i++;
 
968
    }else if (strcmp(argv[i], "-a") == 0){
 
969
      tNoOfAttributes = atoi(argv[i+1]);
 
970
      if ((tNoOfAttributes < 2) || (tNoOfAttributes > MAXATTR)) 
 
971
        return -1;
 
972
      argc -= 1;
 
973
      i++;
 
974
    }else if (strcmp(argv[i], "-lkn") == 0){
 
975
     tNoOfLongPK = atoi(argv[i+1]);
 
976
     useLongKeys = true;
 
977
      if ((tNoOfLongPK < 1) || (tNoOfLongPK > MAXNOLONGKEY) || 
 
978
          (tNoOfLongPK * tSizeOfLongPK) > MAXLONGKEYTOTALSIZE){
 
979
        ndbout << "Argument -lkn is not in the proper range." << endl;  
 
980
        return -1;
 
981
      }
 
982
      argc -= 1;
 
983
      i++;
 
984
    }else if (strcmp(argv[i], "-lks") == 0){
 
985
      tSizeOfLongPK = atoi(argv[i+1]);
 
986
      useLongKeys = true;
 
987
      if ((tSizeOfLongPK < 1) || (tNoOfLongPK * tSizeOfLongPK) > MAXLONGKEYTOTALSIZE){
 
988
        ndbout << "Argument -lks is not in the proper range 1 to " << 
 
989
          MAXLONGKEYTOTALSIZE << endl;
 
990
        return -1;
 
991
      }
 
992
      argc -= 1;
 
993
      i++;
 
994
    }else if (strcmp(argv[i], "-c") == 0){
 
995
      tNoOfTables = atoi(argv[i+1]);
 
996
      if ((tNoOfTables < 1) || (tNoOfTables > MAXTABLES)) 
 
997
        return -1;
 
998
      argc -= 1;
 
999
      i++;
 
1000
    }else if (strcmp(argv[i], "-stdtables") == 0){
 
1001
      theStdTableNameFlag = 1;
 
1002
    }else if (strcmp(argv[i], "-l") == 0){
 
1003
      tNoOfLoops = atoi(argv[i+1]);
 
1004
      if ((tNoOfLoops < 0) || (tNoOfLoops > 100000)) 
 
1005
        return -1;
 
1006
      argc -= 1;
 
1007
      i++;
 
1008
    }else if (strcmp(argv[i], "-s") == 0){
 
1009
      tAttributeSize = atoi(argv[i+1]);
 
1010
      if ((tAttributeSize < 1) || (tAttributeSize > MAXATTRSIZE)) 
 
1011
        return -1;
 
1012
      argc -= 1;
 
1013
      i++;
 
1014
    }else if (strcmp(argv[i], "-sleep") == 0){
 
1015
      tSleepTime = atoi(argv[i+1]);
 
1016
      if ((tSleepTime < 1) || (tSleepTime > 3600)) 
 
1017
        return -1;
 
1018
      argc -= 1;
 
1019
      i++;
 
1020
    }else if (strcmp(argv[i], "-simple") == 0){
 
1021
      theSimpleFlag = 1;
 
1022
    }else if (strcmp(argv[i], "-write") == 0){
 
1023
      theWriteFlag = 1;
 
1024
    }else if (strcmp(argv[i], "-dirty") == 0){
 
1025
      theDirtyFlag = 1;
 
1026
    }else if (strcmp(argv[i], "-no_table_create") == 0){
 
1027
      theTableCreateFlag = 1;
 
1028
    }else if (strcmp(argv[i], "-temp") == 0){
 
1029
      theTempTable = true;
 
1030
    }else if (strcmp(argv[i], "-noverify") == 0){
 
1031
      VerifyFlag = false ;
 
1032
    }else if (theErrorData.parseCmdLineArg(argv, i) == true){
 
1033
      ; //empty, updated in errorArg(..)
 
1034
    }else if (strcmp(argv[i], "-verify") == 0){
 
1035
      VerifyFlag = true ;
 
1036
#ifdef CEBIT_STAT
 
1037
    }else if (strcmp(argv[i], "-statserv") == 0){
 
1038
      if (! (argc > 2))
 
1039
        return -1;
 
1040
      const char *p = argv[i+1];
 
1041
      const char *q = strrchr(p, ':');
 
1042
      if (q == 0)
 
1043
        return -1;
 
1044
      BaseString::snprintf(statHost, sizeof(statHost), "%.*s", q-p, p);
 
1045
      statPort = atoi(q+1);
 
1046
      statEnable = true;
 
1047
      argc -= 1;
 
1048
      i++;
 
1049
    }else if (strcmp(argv[i], "-statfreq") == 0){
 
1050
      if (! (argc > 2))
 
1051
        return -1;
 
1052
      statFreq = atoi(argv[i+1]);
 
1053
      if (statFreq < 1)
 
1054
        return -1;
 
1055
      argc -= 1;
 
1056
      i++;
 
1057
#endif
 
1058
    }else{       
 
1059
      return -1;
 
1060
    }
 
1061
    argc -= 1;
 
1062
    i++;
 
1063
  }
 
1064
  return 0;
 
1065
}
 
1066
 
 
1067
static void sleepBeforeStartingTest(int seconds){
 
1068
  if (seconds > 0){
 
1069
      ndbout << "Sleeping(" <<seconds << ")...";
 
1070
      NdbSleep_SecSleep(seconds);
 
1071
      ndbout << " done!" << endl;
 
1072
    }
 
1073
}
 
1074
 
 
1075
 
 
1076
static int
 
1077
createTables(Ndb* pMyNdb){
 
1078
  int i;
 
1079
  for (i = 0; i < tNoOfAttributes; i++){
 
1080
    BaseString::snprintf(attrName[i], MAXSTRLEN, "COL%d", i);
 
1081
  }
 
1082
 
 
1083
  // Note! Uses only uppercase letters in table name's
 
1084
  // so that we can look at the tables with SQL
 
1085
  for (i = 0; i < tNoOfTables; i++){
 
1086
    if (theStdTableNameFlag == 0){
 
1087
      BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d_%d", i, 
 
1088
               (int)(NdbTick_CurrentMillisecond() / 1000));
 
1089
    } else {
 
1090
      BaseString::snprintf(tableName[i], MAXSTRLEN, "TAB%d", i);
 
1091
    }
 
1092
  }
 
1093
  
 
1094
  for(i = 0; i < tNoOfTables; i++){
 
1095
    ndbout << "Creating " << tableName[i] << "... ";
 
1096
    
 
1097
    NdbDictionary::Table tmpTable(tableName[i]);
 
1098
    
 
1099
    tmpTable.setStoredTable(!theTempTable);
 
1100
    
 
1101
    if(useLongKeys){
 
1102
      for(Uint32 i = 0; i < tNoOfLongPK; i++) {
 
1103
        NdbDictionary::Column col(longKeyAttrName[i]);
 
1104
        col.setType(NdbDictionary::Column::Unsigned);
 
1105
        col.setLength(tSizeOfLongPK);
 
1106
        col.setPrimaryKey(true);
 
1107
        tmpTable.addColumn(col);
 
1108
      }
 
1109
    } else {
 
1110
      NdbDictionary::Column col(attrName[0]);
 
1111
      col.setType(NdbDictionary::Column::Unsigned);
 
1112
      col.setLength(1);
 
1113
      col.setPrimaryKey(true);
 
1114
      tmpTable.addColumn(col);
 
1115
    }
 
1116
    
 
1117
    
 
1118
    NdbDictionary::Column col;
 
1119
    col.setType(NdbDictionary::Column::Unsigned);
 
1120
    col.setLength(tAttributeSize);
 
1121
    for (unsigned j = 1; j < tNoOfAttributes; j++){
 
1122
      col.setName(attrName[j]);
 
1123
      tmpTable.addColumn(col);
 
1124
    }
 
1125
    
 
1126
    if(pMyNdb->getDictionary()->createTable(tmpTable) == -1){
 
1127
      return -1;
 
1128
    }
 
1129
    ndbout << "done" << endl;
 
1130
  }
 
1131
  
 
1132
  return 0;
 
1133
}
 
1134
 
 
1135
      
 
1136
static void input_error(){
 
1137
  ndbout << endl << "Invalid argument!" << endl;
 
1138
  ndbout << endl << "Arguments:" << endl;
 
1139
  ndbout << "   -t Number of threads to start, default 1" << endl;
 
1140
  ndbout << "   -o Number of operations per loop, default 500" << endl;
 
1141
  ndbout << "   -l Number of loops to run, default 1, 0=infinite" << endl;
 
1142
  ndbout << "   -a Number of attributes, default 25" << endl;
 
1143
  ndbout << "   -c Number of tables, default 1" << endl;
 
1144
  ndbout << "   -s Size of each attribute, default 1 (Primary Key is always of size 1," << endl;
 
1145
  ndbout << "      independent of this value)" << endl;
 
1146
  ndbout << "   -lkn Number of long primary keys, default 1" << endl;
 
1147
  ndbout << "   -lks Size of each long primary key, default 1" << endl;
 
1148
 
 
1149
  ndbout << "   -simple Use simple read to read from database" << endl;
 
1150
  ndbout << "   -dirty Use dirty read to read from database" << endl;
 
1151
  ndbout << "   -write Use writeTuple in insert and update" << endl;
 
1152
  ndbout << "   -stdtables Use standard table names" << endl;
 
1153
  ndbout << "   -no_table_create Don't create tables in db" << endl;
 
1154
  ndbout << "   -sleep Sleep a number of seconds before running the test, this" << endl;
 
1155
  ndbout << "    can be used so that another flexBench have time to create tables" << endl;
 
1156
  ndbout << "   -temp Use tables without logging" << endl;
 
1157
  ndbout << "   -verify Verify inserts, updates and deletes" << endl ;
 
1158
  theErrorData.printCmdLineArgs(ndbout);
 
1159
  ndbout << endl <<"Returns:" << endl;
 
1160
  ndbout << "\t 0 - Test passed" << endl;
 
1161
  ndbout << "\t 1 - Test failed" << endl;
 
1162
  ndbout << "\t 2 - Invalid arguments" << endl << endl;
 
1163
}
 
1164
 
 
1165
// vim: set sw=2: