~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to client/drizzleslap.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-10-02 14:17:48 UTC
  • mfrom: (1.1.1 upstream)
  • mto: (2.1.17 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20101002141748-m6vbfbfjhrw1153e
Tags: 2010.09.1802-1
* New upstream release.
* Removed pid-file argument hack.
* Updated GPL-2 address to be new address.
* Directly copy in drizzledump.1 since debian doesn't have sphinx 1.0 yet.
* Link to jquery from libjs-jquery. Add it as a depend.
* Add drizzled.8 symlink to the install files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
 
4
 *  Copyright (C) 2010 Vijay Samuel
4
5
 *  Copyright (C) 2008 MySQL
5
6
 *
6
7
 *  This program is free software; you can redistribute it and/or modify
60
61
  --iterations=5 --query=query.sql --create=create.sql \
61
62
  --delimiter=";"
62
63
 
63
 
  TODO:
 
64
  @todo
64
65
  Add language for better tests
65
66
  String length for files and those put on the command line are not
66
67
  setup to handle binary data.
70
71
 
71
72
*/
72
73
 
73
 
#define SLAP_VERSION "1.5"
74
 
 
75
 
#define HUGE_STRING_LENGTH 8196
76
 
#define RAND_STRING_SIZE 126
77
 
#define DEFAULT_BLOB_SIZE 1024
 
74
#include "config.h"
78
75
 
79
76
#include "client_priv.h"
80
77
#include <signal.h>
86
83
#endif
87
84
#include <fcntl.h>
88
85
#include <math.h>
89
 
#include <ctype.h>
90
86
#include <cassert>
91
87
#include <cstdlib>
92
88
#include <string>
93
 
 
 
89
#include <iostream>
 
90
#include <fstream>
94
91
#include <pthread.h>
95
 
 
 
92
#include <drizzled/configmake.h>
96
93
/* Added this for string translation. */
97
94
#include <drizzled/gettext.h>
 
95
#include <boost/program_options.hpp>
 
96
 
 
97
#define SLAP_VERSION "1.5"
 
98
 
 
99
#define HUGE_STRING_LENGTH 8196
 
100
#define RAND_STRING_SIZE 126
 
101
#define DEFAULT_BLOB_SIZE 1024
98
102
 
99
103
using namespace std;
100
104
using namespace drizzled;
 
105
namespace po= boost::program_options;
101
106
 
102
107
#ifdef HAVE_SMEM
103
108
static char *shared_memory_base_name=0;
116
121
pthread_mutex_t timer_alarm_mutex;
117
122
pthread_cond_t timer_alarm_threshold;
118
123
 
119
 
static char **defaults_argv;
120
 
 
121
 
char **primary_keys;
122
 
/* This gets passed to malloc, so lets set it to an arch-dependant size */
123
 
size_t primary_keys_number_of;
124
 
 
125
 
static char *host= NULL, *opt_password= NULL, *user= NULL,
126
 
  *user_supplied_query= NULL,
127
 
  *user_supplied_pre_statements= NULL,
128
 
  *user_supplied_post_statements= NULL,
129
 
  *default_engine= NULL,
130
 
  *pre_system= NULL,
131
 
  *post_system= NULL;
132
 
 
133
 
const char *delimiter= "\n";
134
 
 
135
 
const char *create_schema_string= "drizzleslap";
136
 
 
137
 
static bool opt_mysql= false;
 
124
std::vector < std::string > primary_keys;
 
125
 
 
126
static string host, 
 
127
  opt_password, 
 
128
  user,
 
129
  user_supplied_query,
 
130
  user_supplied_pre_statements,
 
131
  user_supplied_post_statements,
 
132
  default_engine,
 
133
  pre_system,
 
134
  post_system;
 
135
 
 
136
static vector<string> user_supplied_queries;
 
137
static string opt_verbose;
 
138
std::string opt_protocol;
 
139
string delimiter;
 
140
 
 
141
string create_schema_string;
 
142
 
 
143
static bool use_drizzle_protocol= false;
138
144
static bool opt_preserve= true;
139
 
static bool opt_only_print= false;
140
 
static bool opt_burnin= false;
 
145
static bool opt_only_print;
 
146
static bool opt_burnin;
141
147
static bool opt_ignore_sql_errors= false;
142
 
static bool tty_password= false,
143
 
  opt_silent= false,
144
 
  auto_generate_sql_autoincrement= false,
145
 
  auto_generate_sql_guid_primary= false,
146
 
  auto_generate_sql= false;
147
 
const char *opt_auto_generate_sql_type= "mixed";
 
148
static bool opt_silent,
 
149
  auto_generate_sql_autoincrement,
 
150
  auto_generate_sql_guid_primary,
 
151
  auto_generate_sql;
 
152
std::string opt_auto_generate_sql_type;
148
153
 
149
 
static int verbose, delimiter_length;
 
154
static int32_t verbose= 0;
 
155
static uint32_t delimiter_length;
150
156
static uint32_t commit_rate;
151
157
static uint32_t detach_rate;
152
158
static uint32_t opt_timer_length;
153
159
static uint32_t opt_delayed_start;
154
 
const char *num_int_cols_opt;
155
 
const char *num_char_cols_opt;
156
 
const char *num_blob_cols_opt;
157
 
const char *opt_label;
 
160
string num_blob_cols_opt,
 
161
  num_char_cols_opt,
 
162
  num_int_cols_opt;
 
163
string opt_label;
158
164
static unsigned int opt_set_random_seed;
159
165
 
160
 
const char *auto_generate_selected_columns_opt;
 
166
string auto_generate_selected_columns_opt;
161
167
 
162
168
/* Yes, we do set defaults here */
163
169
static unsigned int num_int_cols= 1;
167
173
static unsigned int num_blob_cols_size_min;
168
174
static unsigned int num_int_cols_index= 0;
169
175
static unsigned int num_char_cols_index= 0;
170
 
static unsigned int iterations;
 
176
static uint32_t iterations;
171
177
static uint64_t actual_queries= 0;
172
178
static uint64_t auto_actual_queries;
173
179
static uint64_t auto_generate_sql_unique_write_number;
174
180
static uint64_t auto_generate_sql_unique_query_number;
175
 
static unsigned int auto_generate_sql_secondary_indexes;
 
181
static uint32_t auto_generate_sql_secondary_indexes;
176
182
static uint64_t num_of_query;
177
183
static uint64_t auto_generate_sql_number;
178
 
const char *concurrency_str= NULL;
179
 
static char *create_string;
180
 
uint32_t *concurrency;
 
184
string concurrency_str;
 
185
string create_string;
 
186
std::vector <uint32_t> concurrency;
181
187
 
182
188
const char *default_dbug_option= "d:t:o,/tmp/drizzleslap.trace";
183
 
const char *opt_csv_str;
 
189
std::string opt_csv_str;
184
190
int csv_file;
185
191
 
186
 
static int get_options(int *argc,char ***argv);
 
192
static int process_options(void);
187
193
static uint32_t opt_drizzle_port= 0;
188
194
 
189
 
static const char *load_default_groups[]= { "drizzleslap","client",0 };
190
195
 
191
196
/* Types */
192
 
typedef enum {
 
197
enum slap_query_t {
193
198
  SELECT_TYPE= 0,
194
199
  UPDATE_TYPE= 1,
195
200
  INSERT_TYPE= 2,
197
202
  CREATE_TABLE_TYPE= 4,
198
203
  SELECT_TYPE_REQUIRES_PREFIX= 5,
199
204
  DELETE_TYPE_REQUIRES_PREFIX= 6
200
 
} slap_query_type;
201
 
 
202
 
typedef struct statement statement;
203
 
 
204
 
struct statement {
205
 
  char *string;
206
 
  size_t length;
207
 
  slap_query_type type;
208
 
  char *option;
209
 
  size_t option_length;
210
 
  statement *next;
211
 
};
212
 
 
213
 
typedef struct option_string option_string;
214
 
 
215
 
struct option_string {
216
 
  char *string;
217
 
  size_t length;
218
 
  char *option;
219
 
  size_t option_length;
220
 
  option_string *next;
221
 
};
222
 
 
223
 
typedef struct stats stats;
224
 
 
225
 
struct stats {
 
205
};
 
206
 
 
207
class Statement;
 
208
 
 
209
class Statement 
 
210
{
 
211
public:
 
212
  Statement(char *in_string,
 
213
            size_t in_length,
 
214
            slap_query_t in_type,
 
215
            Statement *in_next) :
 
216
    string(in_string),
 
217
    length(in_length),
 
218
    type(in_type),
 
219
    next(in_next)
 
220
  { }
 
221
 
 
222
  Statement() :
 
223
    string(NULL),
 
224
    length(0),
 
225
    type(),
 
226
    next(NULL)
 
227
  { }
 
228
 
 
229
  ~Statement()
 
230
  {
 
231
    if (string)
 
232
      free(string);
 
233
  }
 
234
   
 
235
  char *getString() const
 
236
  {
 
237
    return string;
 
238
  }
 
239
 
 
240
  size_t getLength() const
 
241
  {
 
242
    return length;
 
243
  }
 
244
 
 
245
  slap_query_t getType() const
 
246
  {
 
247
    return type;
 
248
  }
 
249
 
 
250
  Statement *getNext() const
 
251
  {
 
252
    return next;
 
253
  }
 
254
 
 
255
  void setString(char *in_string)
 
256
  {
 
257
    string= in_string;
 
258
  }
 
259
 
 
260
  void setString(size_t length_arg)
 
261
  {
 
262
    string= (char *)calloc(length_arg + 1, sizeof(char));
 
263
    length= length_arg;
 
264
  }
 
265
 
 
266
  void setString(size_t in_length, char in_char)
 
267
  {
 
268
    string[in_length]= in_char;
 
269
  }
 
270
 
 
271
  void setLength(size_t in_length)
 
272
  {
 
273
    length= in_length;
 
274
  }
 
275
 
 
276
  void setType(slap_query_t in_type)
 
277
  {
 
278
    type= in_type;
 
279
  }
 
280
 
 
281
  void setNext(Statement *in_next)
 
282
  {
 
283
    next= in_next;
 
284
  }
 
285
 
 
286
private:
 
287
  char *string;
 
288
  size_t length;
 
289
  slap_query_t type;
 
290
  Statement *next;
 
291
};
 
292
 
 
293
class OptionString;
 
294
 
 
295
class OptionString 
 
296
{
 
297
public:
 
298
  OptionString(char *in_string,
 
299
               size_t in_length,
 
300
               char *in_option,
 
301
               size_t in_option_length,
 
302
               OptionString *in_next) :
 
303
    string(in_string),
 
304
    length(in_length),
 
305
    option(in_option),
 
306
    option_length(in_option_length),
 
307
    next(in_next)
 
308
  { }  
 
309
 
 
310
  OptionString() :
 
311
    string(NULL),
 
312
    length(0),
 
313
    option(NULL),
 
314
    option_length(0),
 
315
    next(NULL)
 
316
  { }
 
317
 
 
318
  ~OptionString()
 
319
  {
 
320
    if (getString())
 
321
      free(getString());
 
322
    if (getOption())
 
323
      free(getOption());
 
324
  }
 
325
 
 
326
  char *getString() const
 
327
  {
 
328
    return string;
 
329
  }
 
330
 
 
331
  size_t getLength() const
 
332
  {
 
333
    return length;
 
334
  }
 
335
 
 
336
  char *getOption() const
 
337
  {
 
338
  return option;
 
339
  }
 
340
 
 
341
  size_t getOptionLength() const
 
342
  {
 
343
    return option_length;
 
344
  }
 
345
 
 
346
  OptionString *getNext() const
 
347
  {
 
348
    return next;
 
349
  }
 
350
 
 
351
  void setString(char *in_string)
 
352
  {
 
353
    string= in_string;
 
354
    length= strlen(in_string);
 
355
  }
 
356
 
 
357
  void setOption(char *in_option)
 
358
  {
 
359
    option= strdup(in_option);
 
360
    option_length= strlen(in_option);
 
361
  }
 
362
 
 
363
  void setNext(OptionString *in_next)
 
364
  {
 
365
    next= in_next;
 
366
  }
 
367
  
 
368
private:
 
369
  char *string;
 
370
  size_t length;
 
371
  char *option;
 
372
  size_t option_length;
 
373
  OptionString *next;
 
374
};
 
375
 
 
376
class Stats;
 
377
 
 
378
class Stats 
 
379
{
 
380
public:
 
381
  Stats(long int in_timing,
 
382
        uint32_t in_users,
 
383
        uint32_t in_real_users,
 
384
        uint32_t in_rows,
 
385
        long int in_create_timing,
 
386
        uint64_t in_create_count) :
 
387
    timing(in_timing),
 
388
    users(in_users),
 
389
    real_users(in_real_users),
 
390
    rows(in_rows),
 
391
    create_timing(in_create_timing),
 
392
    create_count(in_create_count)
 
393
  { }
 
394
 
 
395
  Stats() :
 
396
    timing(0),
 
397
    users(0),
 
398
    real_users(0),
 
399
    rows(0),
 
400
    create_timing(0),
 
401
    create_count(0)
 
402
  { }
 
403
 
 
404
  long int getTiming() const
 
405
  {
 
406
    return timing;
 
407
  }
 
408
 
 
409
  uint32_t getUsers() const
 
410
  {
 
411
    return users;
 
412
  }   
 
413
 
 
414
  uint32_t getRealUsers() const
 
415
  {
 
416
    return real_users;
 
417
  }
 
418
 
 
419
  uint64_t getRows() const
 
420
  {
 
421
    return rows;
 
422
  }
 
423
 
 
424
  long int getCreateTiming() const
 
425
  {
 
426
    return create_timing;
 
427
  }
 
428
 
 
429
  uint64_t getCreateCount() const
 
430
  {
 
431
    return create_count;
 
432
  }
 
433
 
 
434
  void setTiming(long int in_timing)
 
435
  {
 
436
  timing= in_timing;
 
437
  }
 
438
 
 
439
  void setUsers(uint32_t in_users)
 
440
  {
 
441
    users= in_users;
 
442
  }
 
443
 
 
444
  void setRealUsers(uint32_t in_real_users)
 
445
  {
 
446
    real_users= in_real_users;
 
447
  }
 
448
 
 
449
  void setRows(uint64_t in_rows)
 
450
  {
 
451
    rows= in_rows;
 
452
  }
 
453
   
 
454
  void setCreateTiming(long int in_create_timing)
 
455
  {
 
456
    create_timing= in_create_timing;
 
457
  }
 
458
 
 
459
  void setCreateCount(uint64_t in_create_count)
 
460
  {
 
461
  create_count= in_create_count;
 
462
  }
 
463
  
 
464
private:
226
465
  long int timing;
227
466
  uint32_t users;
228
467
  uint32_t real_users;
231
470
  uint64_t create_count;
232
471
};
233
472
 
234
 
typedef struct thread_context thread_context;
235
 
 
236
 
struct thread_context {
237
 
  statement *stmt;
 
473
class ThreadContext;
 
474
 
 
475
class ThreadContext 
 
476
{
 
477
public:
 
478
  ThreadContext(Statement *in_stmt,
 
479
                uint64_t in_limit) :
 
480
    stmt(in_stmt),
 
481
    limit(in_limit)
 
482
  { }
 
483
 
 
484
  ThreadContext() :
 
485
    stmt(),
 
486
    limit(0)
 
487
  { }
 
488
 
 
489
  Statement *getStmt() const
 
490
  {
 
491
    return stmt;
 
492
  }
 
493
 
 
494
  uint64_t getLimit() const
 
495
  {
 
496
    return limit;
 
497
  }
 
498
 
 
499
  void setStmt(Statement *in_stmt)
 
500
  {
 
501
    stmt= in_stmt;
 
502
  }
 
503
 
 
504
  void setLimit(uint64_t in_limit)
 
505
  {
 
506
    limit= in_limit;
 
507
  }  
 
508
 
 
509
private:
 
510
  Statement *stmt;
238
511
  uint64_t limit;
239
512
};
240
513
 
241
 
typedef struct conclusions conclusions;
242
 
 
243
 
struct conclusions {
 
514
class Conclusions;
 
515
 
 
516
class Conclusions 
 
517
{
 
518
 
 
519
public:
 
520
  Conclusions(char *in_engine,
 
521
              long int in_avg_timing,
 
522
              long int in_max_timing,
 
523
              long int in_min_timing,
 
524
              uint32_t in_users,
 
525
              uint32_t in_real_users,
 
526
              uint64_t in_avg_rows,
 
527
              long int in_sum_of_time,
 
528
              long int in_std_dev,
 
529
              long int in_create_avg_timing,
 
530
              long int in_create_max_timing,
 
531
              long int in_create_min_timing,
 
532
              uint64_t in_create_count,
 
533
              uint64_t in_max_rows,
 
534
              uint64_t in_min_rows) :
 
535
    engine(in_engine),
 
536
    avg_timing(in_avg_timing),
 
537
    max_timing(in_max_timing),
 
538
    min_timing(in_min_timing),
 
539
    users(in_users),
 
540
    real_users(in_real_users),
 
541
    avg_rows(in_avg_rows),
 
542
    sum_of_time(in_sum_of_time),
 
543
    std_dev(in_std_dev),
 
544
    create_avg_timing(in_create_avg_timing),
 
545
    create_max_timing(in_create_max_timing),
 
546
    create_min_timing(in_create_min_timing),
 
547
    create_count(in_create_count),
 
548
    max_rows(in_max_rows),
 
549
    min_rows(in_min_rows)
 
550
  { }
 
551
 
 
552
  Conclusions() :
 
553
    engine(NULL),
 
554
    avg_timing(0),
 
555
    max_timing(0),
 
556
    min_timing(0),
 
557
    users(0),
 
558
    real_users(0),
 
559
    avg_rows(0),
 
560
    sum_of_time(0),
 
561
    std_dev(0),
 
562
    create_avg_timing(0),
 
563
    create_max_timing(0),
 
564
    create_min_timing(0),
 
565
    create_count(0),
 
566
    max_rows(0),
 
567
    min_rows(0)
 
568
  { }
 
569
 
 
570
  char *getEngine() const
 
571
  {
 
572
    return engine;
 
573
  }
 
574
  
 
575
  long int getAvgTiming() const
 
576
  {
 
577
    return avg_timing;
 
578
  }
 
579
 
 
580
  long int getMaxTiming() const
 
581
  {
 
582
    return max_timing;
 
583
  }
 
584
 
 
585
  long int getMinTiming() const
 
586
  {
 
587
    return min_timing;
 
588
  }
 
589
 
 
590
  uint32_t getUsers() const
 
591
  {
 
592
    return users;
 
593
  }
 
594
 
 
595
  uint32_t getRealUsers() const
 
596
  {
 
597
    return real_users;
 
598
  }
 
599
 
 
600
  uint64_t getAvgRows() const
 
601
  {
 
602
    return avg_rows;
 
603
  }   
 
604
 
 
605
  long int getSumOfTime() const
 
606
  {
 
607
    return sum_of_time;
 
608
  }
 
609
 
 
610
  long int getStdDev() const
 
611
  {
 
612
    return std_dev;
 
613
  }
 
614
 
 
615
  long int getCreateAvgTiming() const
 
616
  {
 
617
    return create_avg_timing;
 
618
  }
 
619
 
 
620
  long int getCreateMaxTiming() const
 
621
  {
 
622
    return create_max_timing;
 
623
  }
 
624
 
 
625
  long int getCreateMinTiming() const
 
626
  {
 
627
    return create_min_timing;
 
628
  }
 
629
   
 
630
  uint64_t getCreateCount() const
 
631
  {
 
632
    return create_count;
 
633
  }
 
634
 
 
635
  uint64_t getMinRows() const
 
636
  {
 
637
    return min_rows;
 
638
  }
 
639
 
 
640
  uint64_t getMaxRows() const
 
641
  {
 
642
    return max_rows;
 
643
  }
 
644
 
 
645
  void setEngine(char *in_engine) 
 
646
  {
 
647
    engine= in_engine;
 
648
  }
 
649
  
 
650
  void setAvgTiming(long int in_avg_timing) 
 
651
  {
 
652
    avg_timing= in_avg_timing;
 
653
  }
 
654
 
 
655
  void setMaxTiming(long int in_max_timing) 
 
656
  {
 
657
    max_timing= in_max_timing;
 
658
  }
 
659
 
 
660
  void setMinTiming(long int in_min_timing) 
 
661
  {
 
662
    min_timing= in_min_timing;
 
663
  }
 
664
 
 
665
  void setUsers(uint32_t in_users) 
 
666
  {
 
667
    users= in_users;
 
668
  }
 
669
 
 
670
  void setRealUsers(uint32_t in_real_users) 
 
671
  {
 
672
    real_users= in_real_users;
 
673
  }
 
674
 
 
675
  void setAvgRows(uint64_t in_avg_rows) 
 
676
  {
 
677
    avg_rows= in_avg_rows;
 
678
  }   
 
679
 
 
680
  void setSumOfTime(long int in_sum_of_time) 
 
681
  {
 
682
    sum_of_time= in_sum_of_time;
 
683
  }
 
684
 
 
685
  void setStdDev(long int in_std_dev) 
 
686
  {
 
687
    std_dev= in_std_dev;
 
688
  }
 
689
 
 
690
  void setCreateAvgTiming(long int in_create_avg_timing) 
 
691
  {
 
692
    create_avg_timing= in_create_avg_timing;
 
693
  }
 
694
 
 
695
  void setCreateMaxTiming(long int in_create_max_timing) 
 
696
  {
 
697
    create_max_timing= in_create_max_timing;
 
698
  }
 
699
 
 
700
  void setCreateMinTiming(long int in_create_min_timing) 
 
701
  {
 
702
    create_min_timing= in_create_min_timing;
 
703
  }
 
704
   
 
705
  void setCreateCount(uint64_t in_create_count) 
 
706
  {
 
707
    create_count= in_create_count;
 
708
  }
 
709
 
 
710
  void setMinRows(uint64_t in_min_rows) 
 
711
  {
 
712
    min_rows= in_min_rows;
 
713
  }
 
714
 
 
715
  void setMaxRows(uint64_t in_max_rows) 
 
716
  {
 
717
    max_rows= in_max_rows;
 
718
  }
 
719
 
 
720
private:
244
721
  char *engine;
245
722
  long int avg_timing;
246
723
  long int max_timing;
260
737
  uint64_t min_rows;
261
738
};
262
739
 
263
 
static option_string *engine_options= NULL;
264
 
static option_string *query_options= NULL;
265
 
static statement *pre_statements= NULL;
266
 
static statement *post_statements= NULL;
267
 
static statement *create_statements= NULL;
268
 
 
269
 
static statement **query_statements= NULL;
 
740
 
 
741
static OptionString *engine_options= NULL;
 
742
static OptionString *query_options= NULL;
 
743
static Statement *pre_statements= NULL;
 
744
static Statement *post_statements= NULL;
 
745
static Statement *create_statements= NULL;
 
746
 
 
747
static std::vector <Statement *> query_statements;
270
748
static unsigned int query_statements_count;
271
749
 
272
750
 
273
751
/* Prototypes */
274
 
void print_conclusions(conclusions *con);
275
 
void print_conclusions_csv(conclusions *con);
276
 
void generate_stats(conclusions *con, option_string *eng, stats *sptr);
277
 
uint32_t parse_comma(const char *string, uint32_t **range);
278
 
uint32_t parse_delimiter(const char *script, statement **stmt, char delm);
279
 
uint32_t parse_option(const char *origin, option_string **stmt, char delm);
 
752
void print_conclusions(Conclusions *con);
 
753
void print_conclusions_csv(Conclusions *con);
 
754
void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr);
 
755
uint32_t parse_comma(const char *string, std::vector <uint32_t> &range);
 
756
uint32_t parse_delimiter(const char *script, Statement **stmt, char delm);
 
757
uint32_t parse_option(const char *origin, OptionString **stmt, char delm);
280
758
static int drop_schema(drizzle_con_st *con, const char *db);
281
759
uint32_t get_random_string(char *buf, size_t size);
282
 
static statement *build_table_string(void);
283
 
static statement *build_insert_string(void);
284
 
static statement *build_update_string(void);
285
 
static statement * build_select_string(bool key);
286
 
static int generate_primary_key_list(drizzle_con_st *con, option_string *engine_stmt);
287
 
static int drop_primary_key_list(void);
288
 
static int create_schema(drizzle_con_st *con, const char *db, statement *stmt,
289
 
                         option_string *engine_stmt, stats *sptr);
290
 
static int run_scheduler(stats *sptr, statement **stmts, uint32_t concur,
 
760
static Statement *build_table_string(void);
 
761
static Statement *build_insert_string(void);
 
762
static Statement *build_update_string(void);
 
763
static Statement * build_select_string(bool key);
 
764
static int generate_primary_key_list(drizzle_con_st *con, OptionString *engine_stmt);
 
765
static int create_schema(drizzle_con_st *con, const char *db, Statement *stmt,
 
766
                         OptionString *engine_stmt, Stats *sptr);
 
767
static int run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur,
291
768
                         uint64_t limit);
292
769
extern "C" pthread_handler_t run_task(void *p);
293
770
extern "C" pthread_handler_t timer_thread(void *p);
294
 
void statement_cleanup(statement *stmt);
295
 
void option_cleanup(option_string *stmt);
296
 
void concurrency_loop(drizzle_con_st *con, uint32_t current, option_string *eptr);
297
 
static int run_statements(drizzle_con_st *con, statement *stmt);
 
771
void statement_cleanup(Statement *stmt);
 
772
void option_cleanup(OptionString *stmt);
 
773
void concurrency_loop(drizzle_con_st *con, uint32_t current, OptionString *eptr);
 
774
static int run_statements(drizzle_con_st *con, Statement *stmt);
298
775
void slap_connect(drizzle_con_st *con, bool connect_to_schema);
299
776
void slap_close(drizzle_con_st *con);
300
777
static int run_query(drizzle_con_st *con, drizzle_result_st *result, const char *query, int len);
301
 
void standard_deviation (conclusions *con, stats *sptr);
 
778
void standard_deviation (Conclusions *con, Stats *sptr);
302
779
 
303
780
static const char ALPHANUMERICS[]=
304
781
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
317
794
  return s + us;
318
795
}
319
796
 
 
797
static void combine_queries(vector<string> queries)
 
798
{
 
799
  user_supplied_query.erase();
 
800
  for (vector<string>::iterator it= queries.begin();
 
801
       it != queries.end();
 
802
       ++it)
 
803
  {
 
804
    user_supplied_query.append(*it);
 
805
    user_supplied_query.append(delimiter);
 
806
  }
 
807
}
 
808
/**
 
809
 * commandline_options is the set of all options that can only be called via the command line.
 
810
 
 
811
 * client_options is the set of all options that can be defined via both command line and via
 
812
 * the configuration file client.cnf
 
813
 
 
814
 * slap_options is the set of all drizzleslap specific options which behave in a manner 
 
815
 * similar to that of client_options. It's configuration file is drizzleslap.cnf
 
816
 
 
817
 * long_options is the union of commandline_options, slap_options and client_options.
 
818
 
 
819
 * There are two configuration files per set of options, one which is defined by the user
 
820
 * which is found at either $XDG_CONFIG_HOME/drizzle or ~/.config/drizzle directory and the other which 
 
821
 * is the system configuration file which is found in the SYSCONFDIR/drizzle directory.
 
822
 
 
823
 * The system configuration file is over ridden by the user's configuration file which
 
824
 * in turn is over ridden by the command line.
 
825
 */
320
826
int main(int argc, char **argv)
321
827
{
322
 
  drizzle_con_st con;
323
 
  option_string *eptr;
324
 
  unsigned int x;
325
 
 
326
 
  internal::my_init();
327
 
 
328
 
  MY_INIT(argv[0]);
329
 
 
330
 
  internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
331
 
  defaults_argv=argv;
332
 
  if (get_options(&argc,&argv))
333
 
  {
334
 
    internal::free_defaults(defaults_argv);
335
 
    internal::my_end();
336
 
    exit(1);
337
 
  }
338
 
 
339
 
  /* Seed the random number generator if we will be using it. */
340
 
  if (auto_generate_sql)
341
 
  {
342
 
    if (opt_set_random_seed == 0)
343
 
      opt_set_random_seed= (unsigned int)time(NULL);
344
 
    srandom(opt_set_random_seed);
345
 
  }
346
 
 
347
 
  /* globals? Yes, so we only have to run strlen once */
348
 
  delimiter_length= strlen(delimiter);
349
 
 
350
 
  if (argc > 2)
351
 
  {
352
 
    fprintf(stderr,"%s: Too many arguments\n",internal::my_progname);
353
 
    internal::free_defaults(defaults_argv);
354
 
    internal::my_end();
355
 
    exit(1);
356
 
  }
357
 
 
358
 
  slap_connect(&con, false);
359
 
 
360
 
  pthread_mutex_init(&counter_mutex, NULL);
361
 
  pthread_cond_init(&count_threshhold, NULL);
362
 
  pthread_mutex_init(&sleeper_mutex, NULL);
363
 
  pthread_cond_init(&sleep_threshhold, NULL);
364
 
  pthread_mutex_init(&timer_alarm_mutex, NULL);
365
 
  pthread_cond_init(&timer_alarm_threshold, NULL);
366
 
 
367
 
 
368
 
  /* Main iterations loop */
 
828
  char *password= NULL;
 
829
  try
 
830
  {
 
831
    po::options_description commandline_options("Options used only in command line");
 
832
    commandline_options.add_options()
 
833
      ("help,?","Display this help and exit")
 
834
      ("info,i","Gives information and exit")
 
835
      ("burnin",po::value<bool>(&opt_burnin)->default_value(false)->zero_tokens(),
 
836
       "Run full test case in infinite loop")
 
837
      ("ignore-sql-errors", po::value<bool>(&opt_ignore_sql_errors)->default_value(false)->zero_tokens(),
 
838
       "Ignore SQL errors in query run")
 
839
      ("create-schema",po::value<string>(&create_schema_string)->default_value("drizzleslap"),
 
840
       "Schema to run tests in")
 
841
      ("create",po::value<string>(&create_string)->default_value(""),
 
842
       "File or string to use to create tables")
 
843
      ("detach",po::value<uint32_t>(&detach_rate)->default_value(0),
 
844
       "Detach (close and re open) connections after X number of requests")
 
845
      ("iterations,i",po::value<uint32_t>(&iterations)->default_value(1),
 
846
       "Number of times to run the tests")
 
847
      ("label",po::value<string>(&opt_label)->default_value(""),
 
848
       "Label to use for print and csv")
 
849
      ("number-blob-cols",po::value<string>(&num_blob_cols_opt)->default_value(""),
 
850
       "Number of BLOB columns to create table with if specifying --auto-generate-sql. Example --number-blob-cols=3:1024/2048 would give you 3 blobs with a random size between 1024 and 2048. ")
 
851
      ("number-char-cols,x",po::value<string>(&num_char_cols_opt)->default_value(""),
 
852
       "Number of VARCHAR columns to create in table if specifying --auto-generate-sql.")
 
853
      ("number-int-cols,y",po::value<string>(&num_int_cols_opt)->default_value(""),
 
854
       "Number of INT columns to create in table if specifying --auto-generate-sql.")
 
855
      ("number-of-queries",
 
856
       po::value<uint64_t>(&num_of_query)->default_value(0),
 
857
       "Limit each client to this number of queries(this is not exact)") 
 
858
      ("only-print",po::value<bool>(&opt_only_print)->default_value(false)->zero_tokens(),
 
859
       "This causes drizzleslap to not connect to the database instead print out what it would have done instead")
 
860
      ("post-query", po::value<string>(&user_supplied_post_statements)->default_value(""),
 
861
       "Query to run or file containing query to execute after tests have completed.")
 
862
      ("post-system",po::value<string>(&post_system)->default_value(""),
 
863
       "system() string to execute after tests have completed")
 
864
      ("pre-query",
 
865
       po::value<string>(&user_supplied_pre_statements)->default_value(""),
 
866
       "Query to run or file containing query to execute before running tests.")
 
867
      ("pre-system",po::value<string>(&pre_system)->default_value(""),
 
868
       "system() string to execute before running tests.")
 
869
      ("query,q",po::value<vector<string> >(&user_supplied_queries)->composing()->notifier(&combine_queries),
 
870
       "Query to run or file containing query")
 
871
      ("verbose,v", po::value<string>(&opt_verbose)->default_value("v"), "Increase verbosity level by one.")
 
872
      ("version,V","Output version information and exit") 
 
873
      ;
 
874
 
 
875
    po::options_description slap_options("Options specific to drizzleslap");
 
876
    slap_options.add_options()
 
877
      ("auto-generate-sql-select-columns",
 
878
       po::value<string>(&auto_generate_selected_columns_opt)->default_value(""),
 
879
       "Provide a string to use for the select fields used in auto tests")
 
880
      ("auto-generate-sql,a",po::value<bool>(&auto_generate_sql)->default_value(false)->zero_tokens(),
 
881
       "Generate SQL where not supplied by file or command line")  
 
882
      ("auto-generate-sql-add-autoincrement",
 
883
       po::value<bool>(&auto_generate_sql_autoincrement)->default_value(false)->zero_tokens(),
 
884
       "Add an AUTO_INCREMENT column to auto-generated tables")
 
885
      ("auto-generate-sql-execute-number",
 
886
       po::value<uint64_t>(&auto_actual_queries)->default_value(0),
 
887
       "See this number and generate a set of queries to run")
 
888
      ("auto-generate-sql-guid-primary",
 
889
       po::value<bool>(&auto_generate_sql_guid_primary)->default_value(false)->zero_tokens(),
 
890
       "Add GUID based primary keys to auto-generated tables")
 
891
      ("auto-generate-sql-load-type",
 
892
       po::value<string>(&opt_auto_generate_sql_type)->default_value("mixed"),
 
893
       "Specify test load type: mixed, update, write, key or read; default is mixed")  
 
894
      ("auto-generate-sql-secondary-indexes",
 
895
       po::value<uint32_t>(&auto_generate_sql_secondary_indexes)->default_value(0),
 
896
       "Number of secondary indexes to add to auto-generated tables")
 
897
      ("auto-generated-sql-unique-query-number",
 
898
       po::value<uint64_t>(&auto_generate_sql_unique_query_number)->default_value(10),
 
899
       "Number of unique queries to generate for automatic tests")
 
900
      ("auto-generate-sql-unique-write-number",
 
901
       po::value<uint64_t>(&auto_generate_sql_unique_write_number)->default_value(10),
 
902
       "Number of unique queries to generate for auto-generate-sql-write-number")
 
903
      ("auto-generate-sql-write-number",
 
904
       po::value<uint64_t>(&auto_generate_sql_number)->default_value(100),
 
905
       "Number of row inserts to perform for each thread (default is 100).")
 
906
      ("commit",po::value<uint32_t>(&commit_rate)->default_value(0),
 
907
       "Commit records every X number of statements")
 
908
      ("concurrency,c",po::value<string>(&concurrency_str)->default_value(""),
 
909
       "Number of clients to simulate for query to run")
 
910
      ("csv",po::value<std::string>(&opt_csv_str)->default_value(""),
 
911
       "Generate CSV output to named file or to stdout if no file is name.")
 
912
      ("delayed-start",po::value<uint32_t>(&opt_delayed_start)->default_value(0),
 
913
       "Delay the startup of threads by a random number of microsends (the maximum of the delay")
 
914
      ("delimiter,F",po::value<string>(&delimiter)->default_value("\n"),
 
915
       "Delimiter to use in SQL statements supplied in file or command line")
 
916
      ("engine,e",po::value<string>(&default_engine)->default_value(""),
 
917
       "Storage engine to use for creating the table")
 
918
      ("set-random-seed",
 
919
       po::value<uint32_t>(&opt_set_random_seed)->default_value(0), 
 
920
       "Seed for random number generator (srandom(3)) ") 
 
921
      ("silent,s",po::value<bool>(&opt_silent)->default_value(false)->zero_tokens(),
 
922
       "Run program in silent mode - no output. ") 
 
923
      ("timer-length",po::value<uint32_t>(&opt_timer_length)->default_value(0),
 
924
       "Require drizzleslap to run each specific test a certain amount of time in seconds")  
 
925
      ;
 
926
 
 
927
    po::options_description client_options("Options specific to the client");
 
928
    client_options.add_options()
 
929
      ("host,h",po::value<string>(&host)->default_value("localhost"),"Connect to the host")
 
930
      ("password,P",po::value<char *>(&password),
 
931
       "Password to use when connecting to server. If password is not given it's asked from the tty")
 
932
      ("port,p",po::value<uint32_t>(), "Port number to use for connection")
 
933
      ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
 
934
       "The protocol of connection (mysql or drizzle).")
 
935
      ("user,u",po::value<string>(&user)->default_value(""),
 
936
       "User for login if not current user")  
 
937
      ;
 
938
 
 
939
    po::options_description long_options("Allowed Options");
 
940
    long_options.add(commandline_options).add(slap_options).add(client_options);
 
941
 
 
942
    std::string system_config_dir_slap(SYSCONFDIR); 
 
943
    system_config_dir_slap.append("/drizzle/drizzleslap.cnf");
 
944
 
 
945
    std::string system_config_dir_client(SYSCONFDIR); 
 
946
    system_config_dir_client.append("/drizzle/client.cnf");
 
947
 
 
948
    std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
 
949
 
 
950
    uint64_t temp_drizzle_port= 0;
 
951
    drizzle_con_st con;
 
952
    OptionString *eptr;
 
953
 
 
954
    // Disable allow_guessing
 
955
    int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
 
956
 
 
957
    po::variables_map vm;
 
958
    po::store(po::command_line_parser(argc, argv).options(long_options).
 
959
              style(style).extra_parser(parse_password_arg).run(), vm);
 
960
 
 
961
    std::string user_config_dir_slap(user_config_dir);
 
962
    user_config_dir_slap.append("/drizzle/drizzleslap.cnf"); 
 
963
 
 
964
    std::string user_config_dir_client(user_config_dir);
 
965
    user_config_dir_client.append("/drizzle/client.cnf");
 
966
 
 
967
    ifstream user_slap_ifs(user_config_dir_slap.c_str());
 
968
    po::store(parse_config_file(user_slap_ifs, slap_options), vm);
 
969
 
 
970
    ifstream user_client_ifs(user_config_dir_client.c_str());
 
971
    po::store(parse_config_file(user_client_ifs, client_options), vm);
 
972
 
 
973
    ifstream system_slap_ifs(system_config_dir_slap.c_str());
 
974
    store(parse_config_file(system_slap_ifs, slap_options), vm);
 
975
 
 
976
    ifstream system_client_ifs(system_config_dir_client.c_str());
 
977
    store(parse_config_file(system_client_ifs, client_options), vm);
 
978
 
 
979
    po::notify(vm);
 
980
 
 
981
    if (process_options())
 
982
      exit(1);
 
983
 
 
984
    if ( vm.count("help") || vm.count("info"))
 
985
    {
 
986
      printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname, SLAP_VERSION,
 
987
          drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
 
988
      puts("Copyright (C) 2008 Sun Microsystems");
 
989
      puts("This software comes with ABSOLUTELY NO WARRANTY. "
 
990
           "This is free software,\n"
 
991
           "and you are welcome to modify and redistribute it under the GPL "
 
992
           "license\n");
 
993
      puts("Run a query multiple times against the server\n");
 
994
      cout << long_options << endl;
 
995
      exit(0);
 
996
    }   
 
997
 
 
998
    if (vm.count("protocol"))
 
999
    {
 
1000
      std::transform(opt_protocol.begin(), opt_protocol.end(),
 
1001
        opt_protocol.begin(), ::tolower);
 
1002
 
 
1003
      if (not opt_protocol.compare("mysql"))
 
1004
        use_drizzle_protocol=false;
 
1005
      else if (not opt_protocol.compare("drizzle"))
 
1006
        use_drizzle_protocol=true;
 
1007
      else
 
1008
      {
 
1009
        cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
 
1010
        exit(-1);
 
1011
      }
 
1012
    }
 
1013
    if (vm.count("port")) 
 
1014
    {
 
1015
      temp_drizzle_port= vm["port"].as<uint32_t>();
 
1016
 
 
1017
      if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
1018
      {
 
1019
        fprintf(stderr, _("Value supplied for port is not valid.\n"));
 
1020
        exit(1);
 
1021
      }
 
1022
      else
 
1023
      {
 
1024
        opt_drizzle_port= (uint32_t) temp_drizzle_port;
 
1025
      }
 
1026
    }
 
1027
 
 
1028
  if ( vm.count("password") )
 
1029
  {
 
1030
    if (!opt_password.empty())
 
1031
      opt_password.erase();
 
1032
    if (password == PASSWORD_SENTINEL)
 
1033
    {
 
1034
      opt_password= "";
 
1035
    }
 
1036
    else
 
1037
    {
 
1038
      opt_password= password;
 
1039
      tty_password= false;
 
1040
    }
 
1041
  }
 
1042
  else
 
1043
  {
 
1044
      tty_password= true;
 
1045
  }
 
1046
 
 
1047
 
 
1048
 
 
1049
    if ( vm.count("version") )
 
1050
    {
 
1051
      printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname, SLAP_VERSION,
 
1052
          drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
 
1053
      exit(0);
 
1054
    }
 
1055
 
 
1056
    /* Seed the random number generator if we will be using it. */
 
1057
    if (auto_generate_sql)
 
1058
    {
 
1059
      if (opt_set_random_seed == 0)
 
1060
        opt_set_random_seed= (unsigned int)time(NULL);
 
1061
      srandom(opt_set_random_seed);
 
1062
    }
 
1063
 
 
1064
    /* globals? Yes, so we only have to run strlen once */
 
1065
    delimiter_length= delimiter.length();
 
1066
 
 
1067
    slap_connect(&con, false);
 
1068
 
 
1069
    pthread_mutex_init(&counter_mutex, NULL);
 
1070
    pthread_cond_init(&count_threshhold, NULL);
 
1071
    pthread_mutex_init(&sleeper_mutex, NULL);
 
1072
    pthread_cond_init(&sleep_threshhold, NULL);
 
1073
    pthread_mutex_init(&timer_alarm_mutex, NULL);
 
1074
    pthread_cond_init(&timer_alarm_threshold, NULL);
 
1075
 
 
1076
 
 
1077
    /* Main iterations loop */
369
1078
burnin:
370
 
  eptr= engine_options;
371
 
  do
372
 
  {
373
 
    /* For the final stage we run whatever queries we were asked to run */
374
 
    uint32_t *current;
375
 
 
376
 
    if (verbose >= 2)
377
 
      printf("Starting Concurrency Test\n");
378
 
 
379
 
    if (*concurrency)
380
 
    {
381
 
      for (current= concurrency; current && *current; current++)
382
 
        concurrency_loop(&con, *current, eptr);
383
 
    }
384
 
    else
385
 
    {
386
 
      uint32_t infinite= 1;
387
 
      do {
388
 
        concurrency_loop(&con, infinite, eptr);
389
 
      }
390
 
      while (infinite++);
391
 
    }
392
 
 
393
 
    if (!opt_preserve)
394
 
      drop_schema(&con, create_schema_string);
395
 
 
396
 
  } while (eptr ? (eptr= eptr->next) : 0);
397
 
 
398
 
  if (opt_burnin)
399
 
    goto burnin;
400
 
 
401
 
  pthread_mutex_destroy(&counter_mutex);
402
 
  pthread_cond_destroy(&count_threshhold);
403
 
  pthread_mutex_destroy(&sleeper_mutex);
404
 
  pthread_cond_destroy(&sleep_threshhold);
405
 
  pthread_mutex_destroy(&timer_alarm_mutex);
406
 
  pthread_cond_destroy(&timer_alarm_threshold);
407
 
 
408
 
  slap_close(&con);
409
 
 
410
 
  /* now free all the strings we created */
411
 
  if (opt_password)
412
 
    free(opt_password);
413
 
 
414
 
  free(concurrency);
415
 
 
416
 
  statement_cleanup(create_statements);
417
 
  for (x= 0; x < query_statements_count; x++)
418
 
    statement_cleanup(query_statements[x]);
419
 
  free(query_statements);
420
 
  statement_cleanup(pre_statements);
421
 
  statement_cleanup(post_statements);
422
 
  option_cleanup(engine_options);
423
 
  option_cleanup(query_options);
 
1079
    eptr= engine_options;
 
1080
    do
 
1081
    {
 
1082
      /* For the final stage we run whatever queries we were asked to run */
 
1083
      uint32_t *current;
 
1084
 
 
1085
      if (verbose >= 2)
 
1086
        printf("Starting Concurrency Test\n");
 
1087
 
 
1088
      if (concurrency.size())
 
1089
      {
 
1090
        for (current= &concurrency[0]; current && *current; current++)
 
1091
          concurrency_loop(&con, *current, eptr);
 
1092
      }
 
1093
      else
 
1094
      {
 
1095
        uint32_t infinite= 1;
 
1096
        do {
 
1097
          concurrency_loop(&con, infinite, eptr);
 
1098
        }
 
1099
        while (infinite++);
 
1100
      }
 
1101
 
 
1102
      if (!opt_preserve)
 
1103
        drop_schema(&con, create_schema_string.c_str());
 
1104
 
 
1105
    } while (eptr ? (eptr= eptr->getNext()) : 0);
 
1106
 
 
1107
    if (opt_burnin)
 
1108
      goto burnin;
 
1109
 
 
1110
    pthread_mutex_destroy(&counter_mutex);
 
1111
    pthread_cond_destroy(&count_threshhold);
 
1112
    pthread_mutex_destroy(&sleeper_mutex);
 
1113
    pthread_cond_destroy(&sleep_threshhold);
 
1114
    pthread_mutex_destroy(&timer_alarm_mutex);
 
1115
    pthread_cond_destroy(&timer_alarm_threshold);
 
1116
 
 
1117
    slap_close(&con);
 
1118
 
 
1119
    /* now free all the strings we created */
 
1120
    if (!opt_password.empty())
 
1121
      opt_password.erase();
 
1122
 
 
1123
    concurrency.clear();
 
1124
 
 
1125
    statement_cleanup(create_statements);
 
1126
    for (uint32_t x= 0; x < query_statements_count; x++)
 
1127
      statement_cleanup(query_statements[x]);
 
1128
    query_statements.clear();
 
1129
    statement_cleanup(pre_statements);
 
1130
    statement_cleanup(post_statements);
 
1131
    option_cleanup(engine_options);
 
1132
    option_cleanup(query_options);
424
1133
 
425
1134
#ifdef HAVE_SMEM
426
 
  if (shared_memory_base_name)
427
 
    free(shared_memory_base_name);
 
1135
    if (shared_memory_base_name)
 
1136
      free(shared_memory_base_name);
428
1137
#endif
429
 
  internal::free_defaults(defaults_argv);
430
 
  internal::my_end();
 
1138
 
 
1139
  }
 
1140
 
 
1141
  catch(std::exception &err)
 
1142
  {
 
1143
    cerr<<"Error:"<<err.what()<<endl;
 
1144
  }
 
1145
 
 
1146
  if (csv_file != fileno(stdout))
 
1147
    close(csv_file);
431
1148
 
432
1149
  return 0;
433
1150
}
434
1151
 
435
 
void concurrency_loop(drizzle_con_st *con, uint32_t current, option_string *eptr)
 
1152
void concurrency_loop(drizzle_con_st *con, uint32_t current, OptionString *eptr)
436
1153
{
437
 
  unsigned int x;
438
 
  stats *head_sptr;
439
 
  stats *sptr;
440
 
  conclusions conclusion;
 
1154
  Stats *head_sptr;
 
1155
  Stats *sptr;
 
1156
  Conclusions conclusion;
441
1157
  uint64_t client_limit;
442
1158
 
443
 
  head_sptr= (stats *)malloc(sizeof(stats) * iterations);
 
1159
  head_sptr= new Stats[iterations];
444
1160
  if (head_sptr == NULL)
445
1161
  {
446
1162
    fprintf(stderr,"Error allocating memory in concurrency_loop\n");
447
1163
    exit(1);
448
1164
  }
449
 
  memset(head_sptr, 0, sizeof(stats) * iterations);
450
 
 
451
 
  memset(&conclusion, 0, sizeof(conclusions));
452
1165
 
453
1166
  if (auto_actual_queries)
454
1167
    client_limit= auto_actual_queries;
457
1170
  else
458
1171
    client_limit= actual_queries;
459
1172
 
 
1173
  uint32_t x;
460
1174
  for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
461
1175
  {
462
1176
    /*
465
1179
      data in the table.
466
1180
    */
467
1181
    if (opt_preserve == false)
468
 
      drop_schema(con, create_schema_string);
 
1182
      drop_schema(con, create_schema_string.c_str());
469
1183
 
470
1184
    /* First we create */
471
1185
    if (create_statements)
472
 
      create_schema(con, create_schema_string, create_statements, eptr, sptr);
 
1186
      create_schema(con, create_schema_string.c_str(), create_statements, eptr, sptr);
473
1187
 
474
1188
    /*
475
1189
      If we generated GUID we need to build a list of them from creation that
483
1197
    if (commit_rate)
484
1198
      run_query(con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
485
1199
 
486
 
    if (pre_system)
 
1200
    if (!pre_system.empty())
487
1201
    {
488
 
      int ret= system(pre_system);
 
1202
      int ret= system(pre_system.c_str());
489
1203
      assert(ret != -1);
490
1204
    }
491
1205
       
497
1211
    if (pre_statements)
498
1212
      run_statements(con, pre_statements);
499
1213
 
500
 
    run_scheduler(sptr, query_statements, current, client_limit);
 
1214
    run_scheduler(sptr, &query_statements[0], current, client_limit);
501
1215
 
502
1216
    if (post_statements)
503
1217
      run_statements(con, post_statements);
504
1218
 
505
 
    if (post_system)
 
1219
    if (!post_system.empty())
506
1220
    {
507
 
      int ret=  system(post_system);
 
1221
      int ret=  system(post_system.c_str());
508
1222
      assert(ret !=-1);
509
1223
    }
510
1224
 
511
1225
    /* We are finished with this run */
512
1226
    if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
513
 
      drop_primary_key_list();
 
1227
      primary_keys.clear();
514
1228
  }
515
1229
 
516
1230
  if (verbose >= 2)
520
1234
 
521
1235
  if (!opt_silent)
522
1236
    print_conclusions(&conclusion);
523
 
  if (opt_csv_str)
 
1237
  if (!opt_csv_str.empty())
524
1238
    print_conclusions_csv(&conclusion);
525
1239
 
526
 
  free(head_sptr);
527
 
 
528
 
}
529
 
 
530
 
 
531
 
static struct my_option my_long_options[] =
532
 
{
533
 
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
534
 
   0, 0, 0, 0, 0, 0},
535
 
  {"auto-generate-sql-select-columns", OPT_SLAP_AUTO_GENERATE_SELECT_COLUMNS,
536
 
   "Provide a string to use for the select fields used in auto tests.",
537
 
   (char**) &auto_generate_selected_columns_opt,
538
 
   (char**) &auto_generate_selected_columns_opt,
539
 
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
540
 
  {"auto-generate-sql", 'a',
541
 
   "Generate SQL where not supplied by file or command line.",
542
 
   (char**) &auto_generate_sql, (char**) &auto_generate_sql,
543
 
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
544
 
  {"auto-generate-sql-add-autoincrement", OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
545
 
   "Add an AUTO_INCREMENT column to auto-generated tables.",
546
 
   (char**) &auto_generate_sql_autoincrement,
547
 
   (char**) &auto_generate_sql_autoincrement,
548
 
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
549
 
  {"auto-generate-sql-execute-number", OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
550
 
   "Set this number to generate a set number of queries to run.",
551
 
   (char**) &auto_actual_queries, (char**) &auto_actual_queries,
552
 
   0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
553
 
  {"auto-generate-sql-guid-primary", OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
554
 
   "Add GUID based primary keys to auto-generated tables.",
555
 
   (char**) &auto_generate_sql_guid_primary,
556
 
   (char**) &auto_generate_sql_guid_primary,
557
 
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
558
 
  {"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
559
 
   "Specify test load type: mixed, update, write, key, or read; default is mixed.",
560
 
   (char**) &opt_auto_generate_sql_type, (char**) &opt_auto_generate_sql_type,
561
 
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
562
 
  {"auto-generate-sql-secondary-indexes",
563
 
   OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
564
 
   "Number of secondary indexes to add to auto-generated tables.",
565
 
   (char**) &auto_generate_sql_secondary_indexes,
566
 
   (char**) &auto_generate_sql_secondary_indexes, 0,
567
 
   GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
568
 
  {"auto-generate-sql-unique-query-number",
569
 
   OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
570
 
   "Number of unique queries to generate for automatic tests.",
571
 
   (char**) &auto_generate_sql_unique_query_number,
572
 
   (char**) &auto_generate_sql_unique_query_number,
573
 
   0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
574
 
  {"auto-generate-sql-unique-write-number",
575
 
   OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
576
 
   "Number of unique queries to generate for auto-generate-sql-write-number.",
577
 
   (char**) &auto_generate_sql_unique_write_number,
578
 
   (char**) &auto_generate_sql_unique_write_number,
579
 
   0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
580
 
  {"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
581
 
   "Number of row inserts to perform for each thread (default is 100).",
582
 
   (char**) &auto_generate_sql_number, (char**) &auto_generate_sql_number,
583
 
   0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0},
584
 
  {"burnin", OPT_SLAP_BURNIN, "Run full test case in infinite loop.",
585
 
   (char**) &opt_burnin, (char**) &opt_burnin, 0, GET_BOOL, NO_ARG, 0, 0, 0,
586
 
   0, 0, 0},
587
 
  {"ignore-sql-errors", OPT_SLAP_IGNORE_SQL_ERRORS,
588
 
   "Ignore SQL erros in query run.",
589
 
   (char**) &opt_ignore_sql_errors,
590
 
   (char**) &opt_ignore_sql_errors,
591
 
   0, GET_BOOL, NO_ARG, 0, 0, 0,
592
 
   0, 0, 0},
593
 
  {"commit", OPT_SLAP_COMMIT, "Commit records every X number of statements.",
594
 
   (char**) &commit_rate, (char**) &commit_rate, 0, GET_UINT, REQUIRED_ARG,
595
 
   0, 0, 0, 0, 0, 0},
596
 
  {"concurrency", 'c', "Number of clients to simulate for query to run.",
597
 
   (char**) &concurrency_str, (char**) &concurrency_str, 0, GET_STR,
598
 
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
599
 
  {"create", OPT_SLAP_CREATE_STRING, "File or string to use create tables.",
600
 
   (char**) &create_string, (char**) &create_string, 0, GET_STR, REQUIRED_ARG,
601
 
   0, 0, 0, 0, 0, 0},
602
 
  {"create-schema", OPT_CREATE_SLAP_SCHEMA, "Schema to run tests in.",
603
 
   (char**) &create_schema_string, (char**) &create_schema_string, 0, GET_STR,
604
 
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
605
 
  {"csv", OPT_SLAP_CSV,
606
 
   "Generate CSV output to named file or to stdout if no file is named.",
607
 
   (char**) &opt_csv_str, (char**) &opt_csv_str, 0, GET_STR,
608
 
   OPT_ARG, 0, 0, 0, 0, 0, 0},
609
 
  {"delayed-start", OPT_SLAP_DELAYED_START,
610
 
   "Delay the startup of threads by a random number of microsends (the maximum of the delay)",
611
 
   (char**) &opt_delayed_start, (char**) &opt_delayed_start, 0, GET_UINT,
612
 
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
613
 
  {"delimiter", 'F',
614
 
   "Delimiter to use in SQL statements supplied in file or command line.",
615
 
   (char**) &delimiter, (char**) &delimiter, 0, GET_STR, REQUIRED_ARG,
616
 
   0, 0, 0, 0, 0, 0},
617
 
  {"detach", OPT_SLAP_DETACH,
618
 
   "Detach (close and reopen) connections after X number of requests.",
619
 
   (char**) &detach_rate, (char**) &detach_rate, 0, GET_UINT, REQUIRED_ARG,
620
 
   0, 0, 0, 0, 0, 0},
621
 
  {"engine", 'e', "Storage engine to use for creating the table.",
622
 
   (char**) &default_engine, (char**) &default_engine, 0,
623
 
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
624
 
  {"host", 'h', "Connect to host.", (char**) &host, (char**) &host, 0, GET_STR,
625
 
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
626
 
  {"iterations", 'i', "Number of times to run the tests.", (char**) &iterations,
627
 
   (char**) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
628
 
  {"label", OPT_SLAP_LABEL, "Label to use for print and csv output.",
629
 
   (char**) &opt_label, (char**) &opt_label, 0,
630
 
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
631
 
  {"mysql", 'm', N_("Use MySQL Protocol."),
632
 
   (char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
633
 
   0, 0, 0},
634
 
  {"number-blob-cols", OPT_SLAP_BLOB_COL,
635
 
   "Number of BLOB columns to create table with if specifying --auto-generate-sql. Example --number-blob-cols=3:1024/2048 would give you 3 blobs with a random size between 1024 and 2048. ",
636
 
   (char**) &num_blob_cols_opt, (char**) &num_blob_cols_opt, 0, GET_STR, REQUIRED_ARG,
637
 
   0, 0, 0, 0, 0, 0},
638
 
  {"number-char-cols", 'x',
639
 
   "Number of VARCHAR columns to create in table if specifying --auto-generate-sql.",
640
 
   (char**) &num_char_cols_opt, (char**) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
641
 
   0, 0, 0, 0, 0, 0},
642
 
  {"number-int-cols", 'y',
643
 
   "Number of INT columns to create in table if specifying --auto-generate-sql.",
644
 
   (char**) &num_int_cols_opt, (char**) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
645
 
   0, 0, 0, 0, 0, 0},
646
 
  {"number-of-queries", OPT_DRIZZLE_NUMBER_OF_QUERY,
647
 
   "Limit each client to this number of queries (this is not exact).",
648
 
   (char**) &num_of_query, (char**) &num_of_query, 0,
649
 
   GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
650
 
  {"only-print", OPT_DRIZZLE_ONLY_PRINT,
651
 
   "This causes drizzleslap to not connect to the databases, but instead print "
652
 
   "out what it would have done instead.",
653
 
   (char**) &opt_only_print, (char**) &opt_only_print, 0, GET_BOOL,  NO_ARG,
654
 
   0, 0, 0, 0, 0, 0},
655
 
  {"password", 'P',
656
 
   "Password to use when connecting to server. If password is not given it's "
657
 
   "asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
658
 
  {"port", 'p', "Port number to use for connection.",
659
 
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
660
 
  {"post-query", OPT_SLAP_POST_QUERY,
661
 
   "Query to run or file containing query to execute after tests have completed.",
662
 
   (char**) &user_supplied_post_statements,
663
 
   (char**) &user_supplied_post_statements,
664
 
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
665
 
  {"post-system", OPT_SLAP_POST_SYSTEM,
666
 
   "system() string to execute after tests have completed.",
667
 
   (char**) &post_system,
668
 
   (char**) &post_system,
669
 
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
670
 
  {"pre-query", OPT_SLAP_PRE_QUERY,
671
 
   "Query to run or file containing query to execute before running tests.",
672
 
   (char**) &user_supplied_pre_statements,
673
 
   (char**) &user_supplied_pre_statements,
674
 
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
675
 
  {"pre-system", OPT_SLAP_PRE_SYSTEM,
676
 
   "system() string to execute before running tests.",
677
 
   (char**) &pre_system,
678
 
   (char**) &pre_system,
679
 
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
680
 
  {"protocol", OPT_DRIZZLE_PROTOCOL,
681
 
   "The protocol of connection (tcp,socket,pipe,memory).",
682
 
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
683
 
  {"query", 'q', "Query to run or file containing query to run.",
684
 
   (char**) &user_supplied_query, (char**) &user_supplied_query,
685
 
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
686
 
  {"set-random-seed", OPT_SLAP_SET_RANDOM_SEED,
687
 
   "Seed for random number generator (srandom(3))",
688
 
   (char**)&opt_set_random_seed,
689
 
   (char**)&opt_set_random_seed,0,
690
 
   GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
691
 
  {"silent", 's', "Run program in silent mode - no output.",
692
 
   (char**) &opt_silent, (char**) &opt_silent, 0, GET_BOOL,  NO_ARG,
693
 
   0, 0, 0, 0, 0, 0},
694
 
  {"timer-length", OPT_SLAP_TIMER_LENGTH,
695
 
   "Require drizzleslap to run each specific test a certain amount of time in seconds.",
696
 
   (char**) &opt_timer_length, (char**) &opt_timer_length, 0, GET_UINT,
697
 
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
698
 
  {"user", 'u', "User for login if not current user.", (char**) &user,
699
 
   (char**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
700
 
  {"verbose", 'v',
701
 
   "More verbose output; you can use this multiple times to get even more "
702
 
   "verbose output.", (char**) &verbose, (char**) &verbose, 0,
703
 
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
704
 
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
705
 
   NO_ARG, 0, 0, 0, 0, 0, 0},
706
 
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
707
 
};
708
 
 
709
 
 
710
 
static void print_version(void)
711
 
{
712
 
  printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname, SLAP_VERSION,
713
 
         drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
714
 
}
715
 
 
716
 
 
717
 
static void usage(void)
718
 
{
719
 
  print_version();
720
 
  puts("Copyright (C) 2008 Sun Microsystems");
721
 
  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\
722
 
       \nand you are welcome to modify and redistribute it under the GPL \
723
 
       license\n");
724
 
  puts("Run a query multiple times against the server\n");
725
 
  printf("Usage: %s [OPTIONS]\n",internal::my_progname);
726
 
  internal::print_defaults("drizzle",load_default_groups);
727
 
  my_print_help(my_long_options);
728
 
}
729
 
 
730
 
static bool get_one_option(int optid, const struct my_option *, char *argument)
731
 
{
732
 
  char *endchar= NULL;
733
 
  uint64_t temp_drizzle_port= 0;
734
 
 
735
 
  switch(optid) {
736
 
  case 'v':
737
 
    verbose++;
738
 
    break;
739
 
  case 'p':
740
 
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
741
 
    /* if there is an alpha character this is not a valid port */
742
 
    if (strlen(endchar) != 0)
743
 
    {
744
 
      fprintf(stderr, _("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead.\n"));
745
 
      exit(1);
746
 
    }
747
 
    /* If the port number is > 65535 it is not a valid port
748
 
       This also helps with potential data loss casting unsigned long to a
749
 
       uint32_t. */
750
 
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
751
 
    {
752
 
      fprintf(stderr, _("Value supplied for port is not valid.\n"));
753
 
      exit(1);
754
 
    }
755
 
    else
756
 
    {
757
 
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
758
 
    }
759
 
    break;
760
 
  case 'P':
761
 
    if (argument)
762
 
    {
763
 
      char *start= argument;
764
 
      if (opt_password)
765
 
        free(opt_password);
766
 
      opt_password = strdup(argument);
767
 
      if (opt_password == NULL)
768
 
      {
769
 
        fprintf(stderr, "Memory allocation error while copying password. "
770
 
                        "Aborting.\n");
771
 
        exit(ENOMEM);
772
 
      }
773
 
      while (*argument)
774
 
      {
775
 
        /* Overwriting password with 'x' */
776
 
        *argument++= 'x';
777
 
      }
778
 
      if (*start)
779
 
      {
780
 
        /* Cut length of argument */
781
 
        start[1]= 0;
782
 
      }
783
 
      tty_password= 0;
784
 
    }
785
 
    else
786
 
      tty_password= 1;
787
 
    break;
788
 
  case 'V':
789
 
    print_version();
790
 
    exit(0);
791
 
  case '?':
792
 
  case 'I':          /* Info */
793
 
    usage();
794
 
    exit(0);
795
 
  }
796
 
  return(0);
 
1240
  delete [] head_sptr;
797
1241
}
798
1242
 
799
1243
 
801
1245
get_random_string(char *buf, size_t size)
802
1246
{
803
1247
  char *buf_ptr= buf;
804
 
  size_t x;
805
1248
 
806
 
  for (x= size; x > 0; x--)
 
1249
  for (size_t x= size; x > 0; x--)
807
1250
    *buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE];
808
1251
  return(buf_ptr - buf);
809
1252
}
815
1258
  This function builds a create table query if the user opts to not supply
816
1259
  a file or string containing a create table statement
817
1260
*/
818
 
static statement *
 
1261
static Statement *
819
1262
build_table_string(void)
820
1263
{
821
1264
  char       buf[HUGE_STRING_LENGTH];
822
1265
  unsigned int        col_count;
823
 
  statement *ptr;
 
1266
  Statement *ptr;
824
1267
  string table_string;
825
1268
 
826
1269
  table_string.reserve(HUGE_STRING_LENGTH);
936
1379
    }
937
1380
 
938
1381
  table_string.append(")");
939
 
  ptr= (statement *)malloc(sizeof(statement));
940
 
  if (ptr == NULL)
941
 
  {
942
 
    fprintf(stderr, "Memory Allocation error in creating table\n");
943
 
    exit(1);
944
 
  }
945
 
  memset(ptr, 0, sizeof(statement));
946
 
  ptr->string = (char *)malloc(table_string.length()+1);
947
 
  if (ptr->string == NULL)
948
 
  {
949
 
    fprintf(stderr, "Memory Allocation error in creating table\n");
950
 
    exit(1);
951
 
  }
952
 
  memset(ptr->string, 0, table_string.length()+1);
953
 
  ptr->length= table_string.length()+1;
954
 
  ptr->type= CREATE_TABLE_TYPE;
955
 
  strcpy(ptr->string, table_string.c_str());
 
1382
  ptr= new Statement;
 
1383
  ptr->setString(table_string.length());
 
1384
  if (ptr->getString()==NULL)
 
1385
  {
 
1386
    fprintf(stderr, "Memory Allocation error in creating table\n");
 
1387
    exit(1);
 
1388
  }
 
1389
  ptr->setType(CREATE_TABLE_TYPE);
 
1390
  strcpy(ptr->getString(), table_string.c_str());
956
1391
  return(ptr);
957
1392
}
958
1393
 
962
1397
  This function builds insert statements when the user opts to not supply
963
1398
  an insert file or string containing insert data
964
1399
*/
965
 
static statement *
 
1400
static Statement *
966
1401
build_update_string(void)
967
1402
{
968
1403
  char       buf[HUGE_STRING_LENGTH];
969
1404
  unsigned int        col_count;
970
 
  statement *ptr;
 
1405
  Statement *ptr;
971
1406
  string update_string;
972
1407
 
973
1408
  update_string.reserve(HUGE_STRING_LENGTH);
1012
1447
    update_string.append(" WHERE id = ");
1013
1448
 
1014
1449
 
1015
 
  ptr= (statement *)malloc(sizeof(statement));
1016
 
  if (ptr == NULL)
1017
 
  {
1018
 
    fprintf(stderr, "Memory Allocation error in creating update\n");
1019
 
    exit(1);
1020
 
  }
1021
 
  memset(ptr, 0, sizeof(statement));
 
1450
  ptr= new Statement;
1022
1451
 
1023
 
  ptr->length= update_string.length()+1;
1024
 
  ptr->string= (char *)malloc(ptr->length);
1025
 
  if (ptr->string == NULL)
 
1452
  ptr->setString(update_string.length());
 
1453
  if (ptr->getString() == NULL)
1026
1454
  {
1027
1455
    fprintf(stderr, "Memory Allocation error in creating update\n");
1028
1456
    exit(1);
1029
1457
  }
1030
 
  memset(ptr->string, 0, ptr->length);
1031
1458
  if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
1032
 
    ptr->type= UPDATE_TYPE_REQUIRES_PREFIX ;
 
1459
    ptr->setType(UPDATE_TYPE_REQUIRES_PREFIX);
1033
1460
  else
1034
 
    ptr->type= UPDATE_TYPE;
1035
 
  strncpy(ptr->string, update_string.c_str(), ptr->length);
 
1461
    ptr->setType(UPDATE_TYPE);
 
1462
  strncpy(ptr->getString(), update_string.c_str(), ptr->getLength());
1036
1463
  return(ptr);
1037
1464
}
1038
1465
 
1043
1470
  This function builds insert statements when the user opts to not supply
1044
1471
  an insert file or string containing insert data
1045
1472
*/
1046
 
static statement *
 
1473
static Statement *
1047
1474
build_insert_string(void)
1048
1475
{
1049
1476
  char       buf[HUGE_STRING_LENGTH];
1050
1477
  unsigned int        col_count;
1051
 
  statement *ptr;
 
1478
  Statement *ptr;
1052
1479
  string insert_string;
1053
1480
 
1054
1481
  insert_string.reserve(HUGE_STRING_LENGTH);
1115
1542
 
1116
1543
  if (num_blob_cols)
1117
1544
  {
1118
 
    char *blob_ptr;
 
1545
    vector <char> blob_ptr;
1119
1546
 
1120
 
    if (num_blob_cols_size > HUGE_STRING_LENGTH)
1121
 
    {
1122
 
      blob_ptr= (char *)malloc(sizeof(char)*num_blob_cols_size);
1123
 
      if (!blob_ptr)
1124
 
      {
1125
 
        fprintf(stderr, "Memory Allocation error in creating select\n");
1126
 
        exit(1);
1127
 
      }
1128
 
      memset(blob_ptr, 0, sizeof(char)*num_blob_cols_size);
1129
 
    }
1130
 
    else
1131
 
    {
1132
 
      blob_ptr= buf;
1133
 
    }
 
1547
    blob_ptr.resize(num_blob_cols_size);
1134
1548
 
1135
1549
    for (col_count= 1; col_count <= num_blob_cols; col_count++)
1136
1550
    {
1141
1555
      size= difference ? (num_blob_cols_size_min + (random() % difference)) :
1142
1556
        num_blob_cols_size;
1143
1557
 
1144
 
      buf_len= get_random_string(blob_ptr, size);
 
1558
      buf_len= get_random_string(&blob_ptr[0], size);
1145
1559
 
1146
1560
      insert_string.append("'", 1);
1147
 
      insert_string.append(blob_ptr, buf_len);
 
1561
      insert_string.append(&blob_ptr[0], buf_len);
1148
1562
      insert_string.append("'", 1);
1149
1563
 
1150
1564
      if (col_count < num_blob_cols)
1151
1565
        insert_string.append(",", 1);
1152
1566
    }
1153
 
 
1154
 
    if (num_blob_cols_size > HUGE_STRING_LENGTH)
1155
 
      free(blob_ptr);
1156
1567
  }
1157
1568
 
1158
1569
  insert_string.append(")", 1);
1159
1570
 
1160
 
  if (!(ptr= (statement *)malloc(sizeof(statement))))
1161
 
  {
1162
 
    fprintf(stderr, "Memory Allocation error in creating select\n");
1163
 
    exit(1);
1164
 
  }
1165
 
  memset(ptr, 0, sizeof(statement));
1166
 
  ptr->length= insert_string.length()+1;
1167
 
  if (!(ptr->string= (char *)malloc(ptr->length)))
1168
 
  {
1169
 
    fprintf(stderr, "Memory Allocation error in creating select\n");
1170
 
    exit(1);
1171
 
  }
1172
 
  memset(ptr->string, 0, ptr->length);
1173
 
  ptr->type= INSERT_TYPE;
1174
 
  strcpy(ptr->string, insert_string.c_str());
 
1571
  ptr= new Statement;
 
1572
  ptr->setString(insert_string.length());
 
1573
  if (ptr->getString()==NULL)
 
1574
  {
 
1575
    fprintf(stderr, "Memory Allocation error in creating select\n");
 
1576
    exit(1);
 
1577
  }
 
1578
  ptr->setType(INSERT_TYPE);
 
1579
  strcpy(ptr->getString(), insert_string.c_str());
1175
1580
  return(ptr);
1176
1581
}
1177
1582
 
1182
1587
  This function builds a query if the user opts to not supply a query
1183
1588
  statement or file containing a query statement
1184
1589
*/
1185
 
static statement *
 
1590
static Statement *
1186
1591
build_select_string(bool key)
1187
1592
{
1188
1593
  char       buf[HUGE_STRING_LENGTH];
1189
1594
  unsigned int        col_count;
1190
 
  statement *ptr;
 
1595
  Statement *ptr;
1191
1596
  string query_string;
1192
1597
 
1193
1598
  query_string.reserve(HUGE_STRING_LENGTH);
1194
1599
 
1195
1600
  query_string.append("SELECT ", 7);
1196
 
  if (auto_generate_selected_columns_opt)
 
1601
  if (!auto_generate_selected_columns_opt.empty())
1197
1602
  {
1198
 
    query_string.append(auto_generate_selected_columns_opt);
 
1603
    query_string.append(auto_generate_selected_columns_opt.c_str());
1199
1604
  }
1200
1605
  else
1201
1606
  {
1247
1652
      (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
1248
1653
    query_string.append(" WHERE id = ");
1249
1654
 
1250
 
  ptr= (statement *)malloc(sizeof(statement));
1251
 
  if (ptr == NULL)
1252
 
  {
1253
 
    fprintf(stderr, "Memory Allocation error in creating select\n");
1254
 
    exit(1);
1255
 
  }
1256
 
  memset(ptr, 0, sizeof(statement));
1257
 
  ptr->length= query_string.length()+1;
1258
 
  ptr->string= (char *)malloc(ptr->length);
1259
 
  if (ptr->string == NULL)
1260
 
  {
1261
 
    fprintf(stderr, "Memory Allocation error in creating select\n");
1262
 
    exit(1);
1263
 
  }
1264
 
  memset(ptr->string, 0, ptr->length);
 
1655
  ptr= new Statement;
 
1656
  ptr->setString(query_string.length());
 
1657
  if (ptr->getString() == NULL)
 
1658
  {
 
1659
    fprintf(stderr, "Memory Allocation error in creating select\n");
 
1660
    exit(1);
 
1661
  }
1265
1662
  if ((key) &&
1266
1663
      (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
1267
 
    ptr->type= SELECT_TYPE_REQUIRES_PREFIX;
 
1664
    ptr->setType(SELECT_TYPE_REQUIRES_PREFIX);
1268
1665
  else
1269
 
    ptr->type= SELECT_TYPE;
1270
 
  strcpy(ptr->string, query_string.c_str());
 
1666
    ptr->setType(SELECT_TYPE);
 
1667
  strcpy(ptr->getString(), query_string.c_str());
1271
1668
  return(ptr);
1272
1669
}
1273
1670
 
1274
1671
static int
1275
 
get_options(int *argc,char ***argv)
 
1672
process_options(void)
1276
1673
{
1277
 
  int ho_error;
1278
 
  char *tmp_string;
1279
1674
  struct stat sbuf;
1280
 
  option_string *sql_type;
 
1675
  OptionString *sql_type;
1281
1676
  unsigned int sql_type_count= 0;
1282
1677
  ssize_t bytes_read= 0;
1283
 
 
1284
 
 
1285
 
  if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
1286
 
    exit(ho_error);
1287
 
 
1288
 
  if (!user)
1289
 
    user= (char *)"root";
 
1678
  
 
1679
  if (user.empty())
 
1680
    user= "root";
 
1681
 
 
1682
  verbose= opt_verbose.length();
1290
1683
 
1291
1684
  /* If something is created we clean it up, otherwise we leave schemas alone */
1292
 
  if (create_string || auto_generate_sql)
 
1685
  if ( (!create_string.empty()) || auto_generate_sql)
1293
1686
    opt_preserve= false;
1294
1687
 
1295
 
  if (auto_generate_sql && (create_string || user_supplied_query))
 
1688
  if (auto_generate_sql && (!create_string.empty() || !user_supplied_query.empty()))
1296
1689
  {
1297
1690
    fprintf(stderr,
1298
1691
            "%s: Can't use --auto-generate-sql when create and query strings are specified!\n",
1317
1710
    exit(1);
1318
1711
  }
1319
1712
 
1320
 
  parse_comma(concurrency_str ? concurrency_str : "1", &concurrency);
 
1713
  parse_comma(!concurrency_str.empty() ? concurrency_str.c_str() : "1", concurrency);
1321
1714
 
1322
 
  if (opt_csv_str)
 
1715
  if (!opt_csv_str.empty())
1323
1716
  {
1324
1717
    opt_silent= true;
1325
1718
 
1329
1722
    }
1330
1723
    else
1331
1724
    {
1332
 
      if ((csv_file= open(opt_csv_str, O_CREAT|O_WRONLY|O_APPEND, 
 
1725
      if ((csv_file= open(opt_csv_str.c_str(), O_CREAT|O_WRONLY|O_APPEND, 
1333
1726
                          S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
1334
1727
      {
1335
1728
        fprintf(stderr,"%s: Could not open csv file: %sn\n",
1336
 
                internal::my_progname, opt_csv_str);
 
1729
                internal::my_progname, opt_csv_str.c_str());
1337
1730
        exit(1);
1338
1731
      }
1339
1732
    }
1342
1735
  if (opt_only_print)
1343
1736
    opt_silent= true;
1344
1737
 
1345
 
  if (num_int_cols_opt)
 
1738
  if (!num_int_cols_opt.empty())
1346
1739
  {
1347
 
    option_string *str;
1348
 
    parse_option(num_int_cols_opt, &str, ',');
1349
 
    num_int_cols= atoi(str->string);
1350
 
    if (str->option)
1351
 
      num_int_cols_index= atoi(str->option);
 
1740
    OptionString *str;
 
1741
    parse_option(num_int_cols_opt.c_str(), &str, ',');
 
1742
    num_int_cols= atoi(str->getString());
 
1743
    if (str->getOption())
 
1744
      num_int_cols_index= atoi(str->getOption());
1352
1745
    option_cleanup(str);
1353
1746
  }
1354
1747
 
1355
 
  if (num_char_cols_opt)
 
1748
  if (!num_char_cols_opt.empty())
1356
1749
  {
1357
 
    option_string *str;
1358
 
    parse_option(num_char_cols_opt, &str, ',');
1359
 
    num_char_cols= atoi(str->string);
1360
 
    if (str->option)
1361
 
      num_char_cols_index= atoi(str->option);
 
1750
    OptionString *str;
 
1751
    parse_option(num_char_cols_opt.c_str(), &str, ',');
 
1752
    num_char_cols= atoi(str->getString());
 
1753
    if (str->getOption())
 
1754
      num_char_cols_index= atoi(str->getOption());
1362
1755
    else
1363
1756
      num_char_cols_index= 0;
1364
1757
    option_cleanup(str);
1365
1758
  }
1366
1759
 
1367
 
  if (num_blob_cols_opt)
 
1760
  if (!num_blob_cols_opt.empty())
1368
1761
  {
1369
 
    option_string *str;
1370
 
    parse_option(num_blob_cols_opt, &str, ',');
1371
 
    num_blob_cols= atoi(str->string);
1372
 
    if (str->option)
 
1762
    OptionString *str;
 
1763
    parse_option(num_blob_cols_opt.c_str(), &str, ',');
 
1764
    num_blob_cols= atoi(str->getString());
 
1765
    if (str->getOption())
1373
1766
    {
1374
1767
      char *sep_ptr;
1375
1768
 
1376
 
      if ((sep_ptr= strchr(str->option, '/')))
 
1769
      if ((sep_ptr= strchr(str->getOption(), '/')))
1377
1770
      {
1378
 
        num_blob_cols_size_min= atoi(str->option);
 
1771
        num_blob_cols_size_min= atoi(str->getOption());
1379
1772
        num_blob_cols_size= atoi(sep_ptr+1);
1380
1773
      }
1381
1774
      else
1382
1775
      {
1383
 
        num_blob_cols_size_min= num_blob_cols_size= atoi(str->option);
 
1776
        num_blob_cols_size_min= num_blob_cols_size= atoi(str->getOption());
1384
1777
      }
1385
1778
    }
1386
1779
    else
1395
1788
  if (auto_generate_sql)
1396
1789
  {
1397
1790
    uint64_t x= 0;
1398
 
    statement *ptr_statement;
 
1791
    Statement *ptr_statement;
1399
1792
 
1400
1793
    if (verbose >= 2)
1401
1794
      printf("Building Create Statements for Auto\n");
1406
1799
    */
1407
1800
    for (ptr_statement= create_statements, x= 0;
1408
1801
         x < auto_generate_sql_unique_write_number;
1409
 
         x++, ptr_statement= ptr_statement->next)
 
1802
         x++, ptr_statement= ptr_statement->getNext())
1410
1803
    {
1411
 
      ptr_statement->next= build_insert_string();
 
1804
      ptr_statement->setNext(build_insert_string());
1412
1805
    }
1413
1806
 
1414
1807
    if (verbose >= 2)
1415
1808
      printf("Building Query Statements for Auto\n");
1416
1809
 
1417
 
    if (!opt_auto_generate_sql_type)
 
1810
    if (opt_auto_generate_sql_type.empty())
1418
1811
      opt_auto_generate_sql_type= "mixed";
1419
1812
 
1420
1813
    query_statements_count=
1421
 
      parse_option(opt_auto_generate_sql_type, &query_options, ',');
 
1814
      parse_option(opt_auto_generate_sql_type.c_str(), &query_options, ',');
1422
1815
 
1423
 
    query_statements= (statement **)malloc(sizeof(statement *) * query_statements_count);
1424
 
    if (query_statements == NULL)
1425
 
    {
1426
 
      fprintf(stderr, "Memory Allocation error in Building Query Statements\n");
1427
 
      exit(1);
1428
 
    }
1429
 
    memset(query_statements, 0, sizeof(statement *) * query_statements_count);
 
1816
    query_statements.resize(query_statements_count);
1430
1817
 
1431
1818
    sql_type= query_options;
1432
1819
    do
1433
1820
    {
1434
 
      if (sql_type->string[0] == 'r')
 
1821
      if (sql_type->getString()[0] == 'r')
1435
1822
      {
1436
1823
        if (verbose >= 2)
1437
1824
          printf("Generating SELECT Statements for Auto\n");
1439
1826
        query_statements[sql_type_count]= build_select_string(false);
1440
1827
        for (ptr_statement= query_statements[sql_type_count], x= 0;
1441
1828
             x < auto_generate_sql_unique_query_number;
1442
 
             x++, ptr_statement= ptr_statement->next)
 
1829
             x++, ptr_statement= ptr_statement->getNext())
1443
1830
        {
1444
 
          ptr_statement->next= build_select_string(false);
 
1831
          ptr_statement->setNext(build_select_string(false));
1445
1832
        }
1446
1833
      }
1447
 
      else if (sql_type->string[0] == 'k')
 
1834
      else if (sql_type->getString()[0] == 'k')
1448
1835
      {
1449
1836
        if (verbose >= 2)
1450
1837
          printf("Generating SELECT for keys Statements for Auto\n");
1461
1848
        query_statements[sql_type_count]= build_select_string(true);
1462
1849
        for (ptr_statement= query_statements[sql_type_count], x= 0;
1463
1850
             x < auto_generate_sql_unique_query_number;
1464
 
             x++, ptr_statement= ptr_statement->next)
 
1851
             x++, ptr_statement= ptr_statement->getNext())
1465
1852
        {
1466
 
          ptr_statement->next= build_select_string(true);
 
1853
          ptr_statement->setNext(build_select_string(true));
1467
1854
        }
1468
1855
      }
1469
 
      else if (sql_type->string[0] == 'w')
 
1856
      else if (sql_type->getString()[0] == 'w')
1470
1857
      {
1471
1858
        /*
1472
1859
          We generate a number of strings in case the engine is
1478
1865
        query_statements[sql_type_count]= build_insert_string();
1479
1866
        for (ptr_statement= query_statements[sql_type_count], x= 0;
1480
1867
             x < auto_generate_sql_unique_query_number;
1481
 
             x++, ptr_statement= ptr_statement->next)
 
1868
             x++, ptr_statement= ptr_statement->getNext())
1482
1869
        {
1483
 
          ptr_statement->next= build_insert_string();
 
1870
          ptr_statement->setNext(build_insert_string());
1484
1871
        }
1485
1872
      }
1486
 
      else if (sql_type->string[0] == 'u')
 
1873
      else if (sql_type->getString()[0] == 'u')
1487
1874
      {
1488
1875
        if ( auto_generate_sql_autoincrement == false &&
1489
1876
             auto_generate_sql_guid_primary == false)
1497
1884
        query_statements[sql_type_count]= build_update_string();
1498
1885
        for (ptr_statement= query_statements[sql_type_count], x= 0;
1499
1886
             x < auto_generate_sql_unique_query_number;
1500
 
             x++, ptr_statement= ptr_statement->next)
 
1887
             x++, ptr_statement= ptr_statement->getNext())
1501
1888
        {
1502
 
          ptr_statement->next= build_update_string();
 
1889
          ptr_statement->setNext(build_update_string());
1503
1890
        }
1504
1891
      }
1505
1892
      else /* Mixed mode is default */
1513
1900
        */
1514
1901
        for (ptr_statement= query_statements[sql_type_count], x= 0;
1515
1902
             x < auto_generate_sql_unique_query_number;
1516
 
             x++, ptr_statement= ptr_statement->next)
 
1903
             x++, ptr_statement= ptr_statement->getNext())
1517
1904
        {
1518
1905
          if (coin)
1519
1906
          {
1520
 
            ptr_statement->next= build_insert_string();
 
1907
            ptr_statement->setNext(build_insert_string());
1521
1908
            coin= 0;
1522
1909
          }
1523
1910
          else
1524
1911
          {
1525
 
            ptr_statement->next= build_select_string(true);
 
1912
            ptr_statement->setNext(build_select_string(true));
1526
1913
            coin= 1;
1527
1914
          }
1528
1915
        }
1529
1916
      }
1530
1917
      sql_type_count++;
1531
 
    } while (sql_type ? (sql_type= sql_type->next) : 0);
 
1918
    } while (sql_type ? (sql_type= sql_type->getNext()) : 0);
1532
1919
  }
1533
1920
  else
1534
1921
  {
1535
 
    if (create_string && !stat(create_string, &sbuf))
 
1922
    if (!create_string.empty() && !stat(create_string.c_str(), &sbuf))
1536
1923
    {
1537
1924
      int data_file;
 
1925
      std::vector<char> tmp_string;
1538
1926
      if (!S_ISREG(sbuf.st_mode))
1539
1927
      {
1540
1928
        fprintf(stderr,"%s: Create file was not a regular file\n",
1541
1929
                internal::my_progname);
1542
1930
        exit(1);
1543
1931
      }
1544
 
      if ((data_file= open(create_string, O_RDWR)) == -1)
 
1932
      if ((data_file= open(create_string.c_str(), O_RDWR)) == -1)
1545
1933
      {
1546
1934
        fprintf(stderr,"%s: Could not open create file\n", internal::my_progname);
1547
1935
        exit(1);
1551
1939
        fprintf(stderr, "Request for more memory than architecture supports\n");
1552
1940
        exit(1);
1553
1941
      }
1554
 
      tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1555
 
      if (tmp_string == NULL)
1556
 
      {
1557
 
        fprintf(stderr, "Memory Allocation error in option processing\n");
1558
 
        exit(1);
1559
 
      }
1560
 
      memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
1561
 
      bytes_read= read(data_file, (unsigned char*) tmp_string,
 
1942
      tmp_string.resize(sbuf.st_size + 1);
 
1943
      bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
1562
1944
                       (size_t)sbuf.st_size);
1563
 
      tmp_string[sbuf.st_size]= '\0';
1564
1945
      close(data_file);
1565
1946
      if (bytes_read != sbuf.st_size)
1566
1947
      {
1567
1948
        fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1568
1949
      }
1569
 
      parse_delimiter(tmp_string, &create_statements, delimiter[0]);
1570
 
      free(tmp_string);
 
1950
      parse_delimiter(&tmp_string[0], &create_statements, delimiter[0]);
1571
1951
    }
1572
 
    else if (create_string)
 
1952
    else if (!create_string.empty())
1573
1953
    {
1574
 
      parse_delimiter(create_string, &create_statements, delimiter[0]);
 
1954
      parse_delimiter(create_string.c_str(), &create_statements, delimiter[0]);
1575
1955
    }
1576
1956
 
1577
1957
    /* Set this up till we fully support options on user generated queries */
1578
 
    if (user_supplied_query)
 
1958
    if (!user_supplied_query.empty())
1579
1959
    {
1580
1960
      query_statements_count=
1581
1961
        parse_option("default", &query_options, ',');
1582
1962
 
1583
 
      query_statements= (statement **)malloc(sizeof(statement *) * query_statements_count);
1584
 
      if (query_statements == NULL)
1585
 
      {
1586
 
        fprintf(stderr, "Memory Allocation error in option processing\n");
1587
 
        exit(1);
1588
 
      }
1589
 
      memset(query_statements, 0, sizeof(statement *) * query_statements_count); 
 
1963
      query_statements.resize(query_statements_count);
1590
1964
    }
1591
1965
 
1592
 
    if (user_supplied_query && !stat(user_supplied_query, &sbuf))
 
1966
    if (!user_supplied_query.empty() && !stat(user_supplied_query.c_str(), &sbuf))
1593
1967
    {
1594
1968
      int data_file;
 
1969
      std::vector<char> tmp_string;
 
1970
 
1595
1971
      if (!S_ISREG(sbuf.st_mode))
1596
1972
      {
1597
1973
        fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1598
1974
                internal::my_progname);
1599
1975
        exit(1);
1600
1976
      }
1601
 
      if ((data_file= open(user_supplied_query, O_RDWR)) == -1)
 
1977
      if ((data_file= open(user_supplied_query.c_str(), O_RDWR)) == -1)
1602
1978
      {
1603
1979
        fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1604
1980
        exit(1);
1608
1984
        fprintf(stderr, "Request for more memory than architecture supports\n");
1609
1985
        exit(1);
1610
1986
      }
1611
 
      tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1612
 
      if (tmp_string == NULL)
1613
 
      {
1614
 
        fprintf(stderr, "Memory Allocation error in option processing\n");
1615
 
        exit(1);
1616
 
      }
1617
 
      memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
1618
 
      bytes_read= read(data_file, (unsigned char*) tmp_string,
 
1987
      tmp_string.resize((size_t)(sbuf.st_size + 1));
 
1988
      bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
1619
1989
                       (size_t)sbuf.st_size);
1620
 
      tmp_string[sbuf.st_size]= '\0';
1621
1990
      close(data_file);
1622
1991
      if (bytes_read != sbuf.st_size)
1623
1992
      {
1624
1993
        fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1625
1994
      }
1626
 
      if (user_supplied_query)
1627
 
        actual_queries= parse_delimiter(tmp_string, &query_statements[0],
 
1995
      if (!user_supplied_query.empty())
 
1996
        actual_queries= parse_delimiter(&tmp_string[0], &query_statements[0],
1628
1997
                                        delimiter[0]);
1629
 
      free(tmp_string);
1630
1998
    }
1631
 
    else if (user_supplied_query)
 
1999
    else if (!user_supplied_query.empty())
1632
2000
    {
1633
 
      actual_queries= parse_delimiter(user_supplied_query, &query_statements[0],
 
2001
      actual_queries= parse_delimiter(user_supplied_query.c_str(), &query_statements[0],
1634
2002
                                      delimiter[0]);
1635
2003
    }
1636
2004
  }
1637
2005
 
1638
 
  if (user_supplied_pre_statements
1639
 
      && !stat(user_supplied_pre_statements, &sbuf))
 
2006
  if (!user_supplied_pre_statements.empty()
 
2007
      && !stat(user_supplied_pre_statements.c_str(), &sbuf))
1640
2008
  {
1641
2009
    int data_file;
 
2010
    std::vector<char> tmp_string;
 
2011
 
1642
2012
    if (!S_ISREG(sbuf.st_mode))
1643
2013
    {
1644
2014
      fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1645
2015
              internal::my_progname);
1646
2016
      exit(1);
1647
2017
    }
1648
 
    if ((data_file= open(user_supplied_pre_statements, O_RDWR)) == -1)
 
2018
    if ((data_file= open(user_supplied_pre_statements.c_str(), O_RDWR)) == -1)
1649
2019
    {
1650
2020
      fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1651
2021
      exit(1);
1655
2025
      fprintf(stderr, "Request for more memory than architecture supports\n");
1656
2026
      exit(1);
1657
2027
    }
1658
 
    tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1659
 
    if (tmp_string == NULL)
1660
 
    {
1661
 
      fprintf(stderr, "Memory Allocation error in option processing\n");
1662
 
      exit(1);
1663
 
    }
1664
 
    memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
1665
 
    bytes_read= read(data_file, (unsigned char*) tmp_string,
 
2028
    tmp_string.resize((size_t)(sbuf.st_size + 1));
 
2029
    bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
1666
2030
                     (size_t)sbuf.st_size);
1667
 
    tmp_string[sbuf.st_size]= '\0';
1668
2031
    close(data_file);
1669
2032
    if (bytes_read != sbuf.st_size)
1670
2033
    {
1671
2034
      fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1672
2035
    }
1673
 
    if (user_supplied_pre_statements)
1674
 
      (void)parse_delimiter(tmp_string, &pre_statements,
 
2036
    if (!user_supplied_pre_statements.empty())
 
2037
      (void)parse_delimiter(&tmp_string[0], &pre_statements,
1675
2038
                            delimiter[0]);
1676
 
    free(tmp_string);
1677
2039
  }
1678
 
  else if (user_supplied_pre_statements)
 
2040
  else if (!user_supplied_pre_statements.empty())
1679
2041
  {
1680
 
    (void)parse_delimiter(user_supplied_pre_statements,
 
2042
    (void)parse_delimiter(user_supplied_pre_statements.c_str(),
1681
2043
                          &pre_statements,
1682
2044
                          delimiter[0]);
1683
2045
  }
1684
2046
 
1685
 
  if (user_supplied_post_statements
1686
 
      && !stat(user_supplied_post_statements, &sbuf))
 
2047
  if (!user_supplied_post_statements.empty()
 
2048
      && !stat(user_supplied_post_statements.c_str(), &sbuf))
1687
2049
  {
1688
2050
    int data_file;
 
2051
    std::vector<char> tmp_string;
 
2052
 
1689
2053
    if (!S_ISREG(sbuf.st_mode))
1690
2054
    {
1691
2055
      fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1692
2056
              internal::my_progname);
1693
2057
      exit(1);
1694
2058
    }
1695
 
    if ((data_file= open(user_supplied_post_statements, O_RDWR)) == -1)
 
2059
    if ((data_file= open(user_supplied_post_statements.c_str(), O_RDWR)) == -1)
1696
2060
    {
1697
2061
      fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1698
2062
      exit(1);
1703
2067
      fprintf(stderr, "Request for more memory than architecture supports\n");
1704
2068
      exit(1);
1705
2069
    }
1706
 
    tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1707
 
    if (tmp_string == NULL)
1708
 
    {
1709
 
      fprintf(stderr, "Memory Allocation error in option processing\n");
1710
 
      exit(1);
1711
 
    }
1712
 
    memset(tmp_string, 0, (size_t)(sbuf.st_size+1));
 
2070
    tmp_string.resize((size_t)(sbuf.st_size + 1));
1713
2071
 
1714
 
    bytes_read= read(data_file, (unsigned char*) tmp_string,
 
2072
    bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
1715
2073
                     (size_t)(sbuf.st_size));
1716
 
    tmp_string[sbuf.st_size]= '\0';
1717
2074
    close(data_file);
1718
2075
    if (bytes_read != sbuf.st_size)
1719
2076
    {
1720
2077
      fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1721
2078
    }
1722
 
    if (user_supplied_post_statements)
1723
 
      (void)parse_delimiter(tmp_string, &post_statements,
 
2079
    if (!user_supplied_post_statements.empty())
 
2080
      (void)parse_delimiter(&tmp_string[0], &post_statements,
1724
2081
                            delimiter[0]);
1725
 
    free(tmp_string);
1726
2082
  }
1727
 
  else if (user_supplied_post_statements)
 
2083
  else if (!user_supplied_post_statements.empty())
1728
2084
  {
1729
 
    (void)parse_delimiter(user_supplied_post_statements, &post_statements,
 
2085
    (void)parse_delimiter(user_supplied_post_statements.c_str(), &post_statements,
1730
2086
                          delimiter[0]);
1731
2087
  }
1732
2088
 
1733
2089
  if (verbose >= 2)
1734
2090
    printf("Parsing engines to use.\n");
1735
2091
 
1736
 
  if (default_engine)
1737
 
    parse_option(default_engine, &engine_options, ',');
 
2092
  if (!default_engine.empty())
 
2093
    parse_option(default_engine.c_str(), &engine_options, ',');
1738
2094
 
1739
2095
  if (tty_password)
1740
2096
    opt_password= client_get_tty_password(NULL);
1773
2129
 
1774
2130
 
1775
2131
static int
1776
 
generate_primary_key_list(drizzle_con_st *con, option_string *engine_stmt)
 
2132
generate_primary_key_list(drizzle_con_st *con, OptionString *engine_stmt)
1777
2133
{
1778
2134
  drizzle_result_st result;
1779
2135
  drizzle_row_t row;
1785
2141
    of the server during load runs.
1786
2142
  */
1787
2143
  if (opt_only_print || (engine_stmt &&
1788
 
                         strstr(engine_stmt->string, "blackhole")))
 
2144
                         strstr(engine_stmt->getString(), "blackhole")))
1789
2145
  {
1790
 
    primary_keys_number_of= 1;
1791
 
    primary_keys= (char **)malloc((sizeof(char *) *
1792
 
                                  primary_keys_number_of));
1793
 
    if (primary_keys == NULL)
1794
 
    {
1795
 
      fprintf(stderr, "Memory Allocation error in option processing\n");
1796
 
      exit(1);
1797
 
    }
1798
 
    
1799
 
    memset(primary_keys, 0, (sizeof(char *) * primary_keys_number_of));
1800
2146
    /* Yes, we strdup a const string to simplify the interface */
1801
 
    primary_keys[0]= strdup("796c4422-1d94-102a-9d6d-00e0812d");
1802
 
    if (primary_keys[0] == NULL)
1803
 
    {
1804
 
      fprintf(stderr, "Memory Allocation error in option processing\n");
1805
 
      exit(1);
1806
 
    }
 
2147
    primary_keys.push_back("796c4422-1d94-102a-9d6d-00e0812d");
1807
2148
  }
1808
2149
  else
1809
2150
  {
1820
2161
      fprintf(stderr, "More primary keys than than architecture supports\n");
1821
2162
      exit(1);
1822
2163
    }
 
2164
    size_t primary_keys_number_of;
1823
2165
    primary_keys_number_of= (size_t)num_rows_ret;
1824
2166
 
1825
2167
    /* So why check this? Blackhole :) */
1828
2170
      /*
1829
2171
        We create the structure and loop and create the items.
1830
2172
      */
1831
 
      primary_keys= (char **)malloc(sizeof(char *) *
1832
 
                                    primary_keys_number_of);
1833
 
      if (primary_keys == NULL)
1834
 
      {
1835
 
        fprintf(stderr, "Memory Allocation error in option processing\n");
1836
 
        exit(1);
1837
 
      }
1838
 
      memset(primary_keys, 0, (size_t)(sizeof(char *) * primary_keys_number_of));
1839
2173
      row= drizzle_row_next(&result);
1840
2174
      for (counter= 0; counter < primary_keys_number_of;
1841
2175
           counter++, row= drizzle_row_next(&result))
1842
2176
      {
1843
 
        primary_keys[counter]= strdup(row[0]);
1844
 
        if (primary_keys[counter] == NULL)
1845
 
        {
1846
 
          fprintf(stderr, "Memory Allocation error in option processing\n");
1847
 
          exit(1);
1848
 
        }
 
2177
        primary_keys.push_back(row[0]);
1849
2178
      }
1850
2179
    }
1851
2180
 
1856
2185
}
1857
2186
 
1858
2187
static int
1859
 
drop_primary_key_list(void)
1860
 
{
1861
 
  uint64_t counter;
1862
 
 
1863
 
  if (primary_keys_number_of)
1864
 
  {
1865
 
    for (counter= 0; counter < primary_keys_number_of; counter++)
1866
 
      free(primary_keys[counter]);
1867
 
 
1868
 
    free(primary_keys);
1869
 
  }
1870
 
 
1871
 
  return 0;
1872
 
}
1873
 
 
1874
 
static int
1875
 
create_schema(drizzle_con_st *con, const char *db, statement *stmt,
1876
 
              option_string *engine_stmt, stats *sptr)
 
2188
create_schema(drizzle_con_st *con, const char *db, Statement *stmt,
 
2189
              OptionString *engine_stmt, Stats *sptr)
1877
2190
{
1878
2191
  char query[HUGE_STRING_LENGTH];
1879
 
  statement *ptr;
1880
 
  statement *after_create;
 
2192
  Statement *ptr;
 
2193
  Statement *after_create;
1881
2194
  int len;
1882
2195
  uint64_t count;
1883
2196
  struct timeval start_time, end_time;
1898
2211
  }
1899
2212
  else
1900
2213
  {
1901
 
    sptr->create_count++;
 
2214
    sptr->setCreateCount(sptr->getCreateCount()+1);
1902
2215
  }
1903
2216
 
1904
2217
  if (opt_only_print)
1922
2235
      exit(1);
1923
2236
    }
1924
2237
    drizzle_result_free(&result);
1925
 
    sptr->create_count++;
 
2238
    sptr->setCreateCount(sptr->getCreateCount()+1);
1926
2239
  }
1927
2240
 
1928
2241
  if (engine_stmt)
1929
2242
  {
1930
2243
    len= snprintf(query, HUGE_STRING_LENGTH, "set storage_engine=`%s`",
1931
 
                  engine_stmt->string);
 
2244
                  engine_stmt->getString());
1932
2245
    if (run_query(con, NULL, query, len))
1933
2246
    {
1934
2247
      fprintf(stderr,"%s: Cannot set default engine: %s\n", internal::my_progname,
1935
2248
              drizzle_con_error(con));
1936
2249
      exit(1);
1937
2250
    }
1938
 
    sptr->create_count++;
 
2251
    sptr->setCreateCount(sptr->getCreateCount()+1);
1939
2252
  }
1940
2253
 
1941
2254
  count= 0;
1942
2255
  after_create= stmt;
1943
2256
 
1944
2257
limit_not_met:
1945
 
  for (ptr= after_create; ptr && ptr->length; ptr= ptr->next, count++)
 
2258
  for (ptr= after_create; ptr && ptr->getLength(); ptr= ptr->getNext(), count++)
1946
2259
  {
1947
2260
    if (auto_generate_sql && ( auto_generate_sql_number == count))
1948
2261
      break;
1949
2262
 
1950
 
    if (engine_stmt && engine_stmt->option && ptr->type == CREATE_TABLE_TYPE)
 
2263
    if (engine_stmt && engine_stmt->getOption() && ptr->getType() == CREATE_TABLE_TYPE)
1951
2264
    {
1952
2265
      char buffer[HUGE_STRING_LENGTH];
1953
2266
 
1954
 
      snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->string,
1955
 
               engine_stmt->option);
 
2267
      snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->getString(),
 
2268
               engine_stmt->getOption());
1956
2269
      if (run_query(con, NULL, buffer, strlen(buffer)))
1957
2270
      {
1958
2271
        fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1959
 
                internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(con));
 
2272
                internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
1960
2273
        if (!opt_ignore_sql_errors)
1961
2274
          exit(1);
1962
2275
      }
1963
 
      sptr->create_count++;
 
2276
      sptr->setCreateCount(sptr->getCreateCount()+1);
1964
2277
    }
1965
2278
    else
1966
2279
    {
1967
 
      if (run_query(con, NULL, ptr->string, ptr->length))
 
2280
      if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
1968
2281
      {
1969
2282
        fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1970
 
                internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(con));
 
2283
                internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
1971
2284
        if (!opt_ignore_sql_errors)
1972
2285
          exit(1);
1973
2286
      }
1974
 
      sptr->create_count++;
 
2287
      sptr->setCreateCount(sptr->getCreateCount()+1);
1975
2288
    }
1976
2289
  }
1977
2290
 
1978
2291
  if (auto_generate_sql && (auto_generate_sql_number > count ))
1979
2292
  {
1980
2293
    /* Special case for auto create, we don't want to create tables twice */
1981
 
    after_create= stmt->next;
 
2294
    after_create= stmt->getNext();
1982
2295
    goto limit_not_met;
1983
2296
  }
1984
2297
 
1985
2298
  gettimeofday(&end_time, NULL);
1986
2299
 
1987
 
  sptr->create_timing= timedif(end_time, start_time);
 
2300
  sptr->setCreateTiming(timedif(end_time, start_time));
1988
2301
 
1989
2302
  return(0);
1990
2303
}
2010
2323
}
2011
2324
 
2012
2325
static int
2013
 
run_statements(drizzle_con_st *con, statement *stmt)
 
2326
run_statements(drizzle_con_st *con, Statement *stmt)
2014
2327
{
2015
 
  statement *ptr;
 
2328
  Statement *ptr;
2016
2329
 
2017
 
  for (ptr= stmt; ptr && ptr->length; ptr= ptr->next)
 
2330
  for (ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
2018
2331
  {
2019
 
    if (run_query(con, NULL, ptr->string, ptr->length))
 
2332
    if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
2020
2333
    {
2021
2334
      fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2022
 
              internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(con));
 
2335
              internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
2023
2336
      exit(1);
2024
2337
    }
2025
2338
  }
2028
2341
}
2029
2342
 
2030
2343
static int
2031
 
run_scheduler(stats *sptr, statement **stmts, uint32_t concur, uint64_t limit)
 
2344
run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit)
2032
2345
{
2033
 
  uint32_t x;
2034
2346
  uint32_t y;
2035
2347
  unsigned int real_concurrency;
2036
2348
  struct timeval start_time, end_time;
2037
 
  option_string *sql_type;
2038
 
  thread_context *con;
 
2349
  OptionString *sql_type;
2039
2350
  pthread_t mainthread;            /* Thread descriptor */
2040
2351
  pthread_attr_t attr;          /* Thread attributes */
2041
2352
 
2055
2366
 
2056
2367
  for (y= 0, sql_type= query_options;
2057
2368
       y < query_statements_count;
2058
 
       y++, sql_type= sql_type->next)
 
2369
       y++, sql_type= sql_type->getNext())
2059
2370
  {
2060
2371
    unsigned int options_loop= 1;
2061
2372
 
2062
 
    if (sql_type->option)
 
2373
    if (sql_type->getOption())
2063
2374
    {
2064
 
      options_loop= strtol(sql_type->option,
 
2375
      options_loop= strtol(sql_type->getOption(),
2065
2376
                           (char **)NULL, 10);
2066
2377
      options_loop= options_loop ? options_loop : 1;
2067
2378
    }
2068
2379
 
2069
2380
    while (options_loop--)
2070
 
      for (x= 0; x < concur; x++)
 
2381
    {
 
2382
      for (uint32_t x= 0; x < concur; x++)
2071
2383
      {
2072
 
        con= (thread_context *)malloc(sizeof(thread_context));
 
2384
        ThreadContext *con;
 
2385
        con= new ThreadContext;
2073
2386
        if (con == NULL)
2074
2387
        {
2075
2388
          fprintf(stderr, "Memory Allocation error in scheduler\n");
2076
2389
          exit(1);
2077
2390
        }
2078
 
        con->stmt= stmts[y];
2079
 
        con->limit= limit;
 
2391
        con->setStmt(stmts[y]);
 
2392
        con->setLimit(limit);
2080
2393
 
2081
2394
        real_concurrency++;
2082
2395
        /* now you create the thread */
2088
2401
        }
2089
2402
        thread_counter++;
2090
2403
      }
 
2404
    }
2091
2405
  }
2092
2406
 
2093
2407
  /*
2134
2448
  gettimeofday(&end_time, NULL);
2135
2449
 
2136
2450
 
2137
 
  sptr->timing= timedif(end_time, start_time);
2138
 
  sptr->users= concur;
2139
 
  sptr->real_users= real_concurrency;
2140
 
  sptr->rows= limit;
 
2451
  sptr->setTiming(timedif(end_time, start_time));
 
2452
  sptr->setUsers(concur);
 
2453
  sptr->setRealUsers(real_concurrency);
 
2454
  sptr->setRows(limit);
2141
2455
 
2142
2456
  return(0);
2143
2457
}
2181
2495
  drizzle_con_st con;
2182
2496
  drizzle_result_st result;
2183
2497
  drizzle_row_t row;
2184
 
  statement *ptr;
2185
 
  thread_context *ctx= (thread_context *)p;
 
2498
  Statement *ptr;
 
2499
  ThreadContext *ctx= (ThreadContext *)p;
2186
2500
 
2187
2501
  pthread_mutex_lock(&sleeper_mutex);
2188
2502
  while (master_wakeup)
2202
2516
    run_query(&con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
2203
2517
 
2204
2518
limit_not_met:
2205
 
  for (ptr= ctx->stmt, detach_counter= 0;
2206
 
       ptr && ptr->length;
2207
 
       ptr= ptr->next, detach_counter++)
 
2519
  for (ptr= ctx->getStmt(), detach_counter= 0;
 
2520
       ptr && ptr->getLength();
 
2521
       ptr= ptr->getNext(), detach_counter++)
2208
2522
  {
2209
2523
    if (!opt_only_print && detach_rate && !(detach_counter % detach_rate))
2210
2524
    {
2215
2529
    /*
2216
2530
      We have to execute differently based on query type. This should become a function.
2217
2531
    */
2218
 
    if ((ptr->type == UPDATE_TYPE_REQUIRES_PREFIX) ||
2219
 
        (ptr->type == SELECT_TYPE_REQUIRES_PREFIX))
 
2532
    if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
 
2533
        (ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
2220
2534
    {
2221
2535
      int length;
2222
2536
      unsigned int key_val;
2223
 
      char *key;
2224
2537
      char buffer[HUGE_STRING_LENGTH];
2225
2538
 
2226
2539
      /*
2230
2543
        Just in case someone runs this under an experimental engine we don't
2231
2544
        want a crash so the if() is placed here.
2232
2545
      */
2233
 
      assert(primary_keys_number_of);
2234
 
      if (primary_keys_number_of)
 
2546
      assert(primary_keys.size());
 
2547
      if (primary_keys.size())
2235
2548
      {
2236
 
        key_val= (unsigned int)(random() % primary_keys_number_of);
2237
 
        key= primary_keys[key_val];
 
2549
        key_val= (unsigned int)(random() % primary_keys.size());
 
2550
        const char *key;
 
2551
        key= primary_keys[key_val].c_str();
2238
2552
 
2239
2553
        assert(key);
2240
2554
 
2241
2555
        length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
2242
 
                         (int)ptr->length, ptr->string, key);
 
2556
                         (int)ptr->getLength(), ptr->getString(), key);
2243
2557
 
2244
2558
        if (run_query(&con, &result, buffer, length))
2245
2559
        {
2251
2565
    }
2252
2566
    else
2253
2567
    {
2254
 
      if (run_query(&con, &result, ptr->string, ptr->length))
 
2568
      if (run_query(&con, &result, ptr->getString(), ptr->getLength()))
2255
2569
      {
2256
2570
        fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2257
 
                internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(&con));
 
2571
                internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
2258
2572
        exit(1);
2259
2573
      }
2260
2574
    }
2278
2592
      goto end;
2279
2593
 
2280
2594
    /* If limit has been reached, and we are not in a timer_alarm just end */
2281
 
    if (ctx->limit && queries == ctx->limit && timer_alarm == false)
 
2595
    if (ctx->getLimit() && queries == ctx->getLimit() && timer_alarm == false)
2282
2596
      goto end;
2283
2597
  }
2284
2598
 
2285
2599
  if (opt_timer_length && timer_alarm == true)
2286
2600
    goto limit_not_met;
2287
2601
 
2288
 
  if (ctx->limit && queries < ctx->limit)
 
2602
  if (ctx->getLimit() && queries < ctx->getLimit())
2289
2603
    goto limit_not_met;
2290
2604
 
2291
2605
 
2300
2614
  pthread_cond_signal(&count_threshhold);
2301
2615
  pthread_mutex_unlock(&counter_mutex);
2302
2616
 
2303
 
  free(ctx);
 
2617
  delete ctx;
2304
2618
 
2305
2619
  return(0);
2306
2620
}
2310
2624
  on variables.
2311
2625
*/
2312
2626
uint
2313
 
parse_option(const char *origin, option_string **stmt, char delm)
 
2627
parse_option(const char *origin, OptionString **stmt, char delm)
2314
2628
{
2315
2629
  char *string;
2316
2630
  char *begin_ptr;
2317
2631
  char *end_ptr;
2318
 
  option_string **sptr= stmt;
2319
 
  option_string *tmp;
2320
2632
  uint32_t length= strlen(origin);
2321
2633
  uint32_t count= 0; /* We know that there is always one */
2322
2634
 
2323
2635
  end_ptr= (char *)origin + length;
2324
2636
 
2325
 
  tmp= *sptr= (option_string *)malloc(sizeof(option_string));
2326
 
  if (tmp == NULL)
2327
 
  {
2328
 
    fprintf(stderr,"Error allocating memory while parsing options\n");
2329
 
    exit(1);
2330
 
  }
2331
 
  memset(tmp, 0, sizeof(option_string));
 
2637
  OptionString *tmp;
 
2638
  *stmt= tmp= new OptionString;
2332
2639
 
2333
2640
  for (begin_ptr= (char *)origin;
2334
2641
       begin_ptr != end_ptr;
2335
 
       tmp= tmp->next)
 
2642
       tmp= tmp->getNext())
2336
2643
  {
2337
2644
    char buffer[HUGE_STRING_LENGTH];
2338
2645
    char *buffer_ptr;
2360
2667
      buffer_ptr++;
2361
2668
 
2362
2669
      /* Move past the : and the first string */
2363
 
      tmp->option_length= strlen(buffer_ptr);
2364
 
      tmp->option= (char *)malloc(tmp->option_length + 1);
2365
 
      if (tmp->option == NULL)
2366
 
      {
2367
 
        fprintf(stderr,"Error allocating memory while parsing options\n");
2368
 
        exit(1);
2369
 
      }
2370
 
      memcpy(tmp->option, buffer_ptr, tmp->option_length);
2371
 
      tmp->option[tmp->option_length]= 0; 
 
2670
      tmp->setOption(buffer_ptr);
2372
2671
    }
2373
2672
 
2374
 
    tmp->length= strlen(buffer);
2375
 
    tmp->string= strdup(buffer);
2376
 
    if (tmp->string == NULL)
 
2673
    tmp->setString(strdup(buffer));
 
2674
    if (tmp->getString() == NULL)
2377
2675
    {
2378
2676
      fprintf(stderr,"Error allocating memory while parsing options\n");
2379
2677
      exit(1);
2386
2684
 
2387
2685
    if (begin_ptr != end_ptr)
2388
2686
    {
2389
 
      tmp->next= (option_string *)malloc(sizeof(option_string));
2390
 
      if (tmp->next == NULL)
2391
 
      {
2392
 
        fprintf(stderr,"Error allocating memory while parsing options\n");
2393
 
        exit(1);
2394
 
      }
2395
 
      memset(tmp->next, 0, sizeof(option_string));
 
2687
      tmp->setNext( new OptionString);
2396
2688
    }
2397
2689
    
2398
2690
  }
2406
2698
  parse_option.
2407
2699
*/
2408
2700
uint
2409
 
parse_delimiter(const char *script, statement **stmt, char delm)
 
2701
parse_delimiter(const char *script, Statement **stmt, char delm)
2410
2702
{
2411
2703
  char *retstr;
2412
2704
  char *ptr= (char *)script;
2413
 
  statement **sptr= stmt;
2414
 
  statement *tmp;
 
2705
  Statement **sptr= stmt;
 
2706
  Statement *tmp;
2415
2707
  uint32_t length= strlen(script);
2416
2708
  uint32_t count= 0; /* We know that there is always one */
2417
2709
 
2418
 
  for (tmp= *sptr= (statement *)calloc(1, sizeof(statement));
 
2710
  for (tmp= *sptr= new Statement;
2419
2711
       (retstr= strchr(ptr, delm));
2420
 
       tmp->next=  (statement *)calloc(1, sizeof(statement)),
2421
 
       tmp= tmp->next)
 
2712
       tmp->setNext(new Statement),
 
2713
       tmp= tmp->getNext())
2422
2714
  {
2423
2715
    if (tmp == NULL)
2424
2716
    {
2427
2719
    }
2428
2720
 
2429
2721
    count++;
2430
 
    tmp->length= (size_t)(retstr - ptr);
2431
 
    tmp->string= (char *)malloc(tmp->length + 1);
 
2722
    tmp->setString((size_t)(retstr - ptr));
2432
2723
 
2433
 
    if (tmp->string == NULL)
 
2724
    if (tmp->getString() == NULL)
2434
2725
    {
2435
2726
      fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2436
2727
      exit(1);
2437
2728
    }
2438
2729
 
2439
 
    memcpy(tmp->string, ptr, tmp->length);
2440
 
    tmp->string[tmp->length]= 0;
 
2730
    memcpy(tmp->getString(), ptr, tmp->getLength());
2441
2731
    ptr+= retstr - ptr + 1;
2442
2732
    if (isspace(*ptr))
2443
2733
      ptr++;
2445
2735
 
2446
2736
  if (ptr != script+length)
2447
2737
  {
2448
 
    tmp->length= (size_t)((script + length) - ptr);
2449
 
    tmp->string= (char *)malloc(tmp->length + 1);
2450
 
    if (tmp->string == NULL)
 
2738
    tmp->setString((size_t)((script + length) - ptr));
 
2739
    if (tmp->getString() == NULL)
2451
2740
    {
2452
2741
      fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2453
2742
      exit(1);
2454
2743
    }
2455
 
    memcpy(tmp->string, ptr, tmp->length);
2456
 
    tmp->string[tmp->length]= 0;
 
2744
    memcpy(tmp->getString(), ptr, tmp->getLength());
2457
2745
    count++;
2458
2746
  }
2459
2747
 
2467
2755
  In restrospect, this is a lousy name from this function.
2468
2756
*/
2469
2757
uint
2470
 
parse_comma(const char *string, uint32_t **range)
 
2758
parse_comma(const char *string, std::vector <uint32_t> &range)
2471
2759
{
2472
2760
  unsigned int count= 1,x; /* We know that there is always one */
2473
2761
  char *retstr;
2478
2766
    if (*ptr == ',') count++;
2479
2767
 
2480
2768
  /* One extra spot for the NULL */
2481
 
  nptr= *range= (uint32_t *)malloc(sizeof(unsigned int) * (count + 1));
2482
 
  memset(nptr, 0, sizeof(unsigned int) * (count + 1));
 
2769
  range.resize(count +1);
 
2770
  nptr= &range[0];
2483
2771
 
2484
2772
  ptr= (char *)string;
2485
2773
  x= 0;
2494
2782
}
2495
2783
 
2496
2784
void
2497
 
print_conclusions(conclusions *con)
 
2785
print_conclusions(Conclusions *con)
2498
2786
{
2499
2787
  printf("Benchmark\n");
2500
 
  if (con->engine)
2501
 
    printf("\tRunning for engine %s\n", con->engine);
2502
 
  if (opt_label || opt_auto_generate_sql_type)
 
2788
  if (con->getEngine())
 
2789
    printf("\tRunning for engine %s\n", con->getEngine());
 
2790
  if (!opt_label.empty() || !opt_auto_generate_sql_type.empty())
2503
2791
  {
2504
 
    const char *ptr= opt_auto_generate_sql_type ? opt_auto_generate_sql_type : "query";
2505
 
    printf("\tLoad: %s\n", opt_label ? opt_label : ptr);
 
2792
    const char *ptr= opt_auto_generate_sql_type.c_str() ? opt_auto_generate_sql_type.c_str() : "query";
 
2793
    printf("\tLoad: %s\n", !opt_label.empty() ? opt_label.c_str() : ptr);
2506
2794
  }
2507
2795
  printf("\tAverage Time took to generate schema and initial data: %ld.%03ld seconds\n",
2508
 
         con->create_avg_timing / 1000, con->create_avg_timing % 1000);
 
2796
         con->getCreateAvgTiming() / 1000, con->getCreateAvgTiming() % 1000);
2509
2797
  printf("\tAverage number of seconds to run all queries: %ld.%03ld seconds\n",
2510
 
         con->avg_timing / 1000, con->avg_timing % 1000);
 
2798
         con->getAvgTiming() / 1000, con->getAvgTiming() % 1000);
2511
2799
  printf("\tMinimum number of seconds to run all queries: %ld.%03ld seconds\n",
2512
 
         con->min_timing / 1000, con->min_timing % 1000);
 
2800
         con->getMinTiming() / 1000, con->getMinTiming() % 1000);
2513
2801
  printf("\tMaximum number of seconds to run all queries: %ld.%03ld seconds\n",
2514
 
         con->max_timing / 1000, con->max_timing % 1000);
 
2802
         con->getMaxTiming() / 1000, con->getMaxTiming() % 1000);
2515
2803
  printf("\tTotal time for tests: %ld.%03ld seconds\n",
2516
 
         con->sum_of_time / 1000, con->sum_of_time % 1000);
2517
 
  printf("\tStandard Deviation: %ld.%03ld\n", con->std_dev / 1000, con->std_dev % 1000);
2518
 
  printf("\tNumber of queries in create queries: %"PRIu64"\n", con->create_count);
 
2804
         con->getSumOfTime() / 1000, con->getSumOfTime() % 1000);
 
2805
  printf("\tStandard Deviation: %ld.%03ld\n", con->getStdDev() / 1000, con->getStdDev() % 1000);
 
2806
  printf("\tNumber of queries in create queries: %"PRIu64"\n", con->getCreateCount());
2519
2807
  printf("\tNumber of clients running queries: %u/%u\n",
2520
 
         con->users, con->real_users);
 
2808
         con->getUsers(), con->getRealUsers());
2521
2809
  printf("\tNumber of times test was run: %u\n", iterations);
2522
 
  printf("\tAverage number of queries per client: %"PRIu64"\n", con->avg_rows);
 
2810
  printf("\tAverage number of queries per client: %"PRIu64"\n", con->getAvgRows());
2523
2811
  printf("\n");
2524
2812
}
2525
2813
 
2526
2814
void
2527
 
print_conclusions_csv(conclusions *con)
 
2815
print_conclusions_csv(Conclusions *con)
2528
2816
{
2529
2817
  unsigned int x;
2530
2818
  char buffer[HUGE_STRING_LENGTH];
2531
2819
  char label_buffer[HUGE_STRING_LENGTH];
2532
2820
  size_t string_len;
2533
 
 
2534
 
  memset(label_buffer, 0, HUGE_STRING_LENGTH);
2535
 
 
2536
 
  if (opt_label)
 
2821
  const char *temp_label= opt_label.c_str();
 
2822
 
 
2823
  memset(label_buffer, 0, sizeof(label_buffer));
 
2824
 
 
2825
  if (!opt_label.empty())
2537
2826
  {
2538
 
    string_len= strlen(opt_label);
 
2827
    string_len= opt_label.length();
2539
2828
 
2540
2829
    for (x= 0; x < string_len; x++)
2541
2830
    {
2542
 
      if (opt_label[x] == ',')
 
2831
      if (temp_label[x] == ',')
2543
2832
        label_buffer[x]= '-';
2544
2833
      else
2545
 
        label_buffer[x]= opt_label[x] ;
 
2834
        label_buffer[x]= temp_label[x] ;
2546
2835
    }
2547
2836
  }
2548
 
  else if (opt_auto_generate_sql_type)
 
2837
  else if (!opt_auto_generate_sql_type.empty())
2549
2838
  {
2550
 
    string_len= strlen(opt_auto_generate_sql_type);
 
2839
    string_len= opt_auto_generate_sql_type.length();
2551
2840
 
2552
2841
    for (x= 0; x < string_len; x++)
2553
2842
    {
2558
2847
    }
2559
2848
  }
2560
2849
  else
 
2850
  {
2561
2851
    snprintf(label_buffer, HUGE_STRING_LENGTH, "query");
 
2852
  }
2562
2853
 
2563
2854
  snprintf(buffer, HUGE_STRING_LENGTH,
2564
2855
           "%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,"
2565
2856
           "%u,%u,%u,%"PRIu64"\n",
2566
 
           con->engine ? con->engine : "", /* Storage engine we ran against */
 
2857
           con->getEngine() ? con->getEngine() : "", /* Storage engine we ran against */
2567
2858
           label_buffer, /* Load type */
2568
 
           con->avg_timing / 1000, con->avg_timing % 1000, /* Time to load */
2569
 
           con->min_timing / 1000, con->min_timing % 1000, /* Min time */
2570
 
           con->max_timing / 1000, con->max_timing % 1000, /* Max time */
2571
 
           con->sum_of_time / 1000, con->sum_of_time % 1000, /* Total time */
2572
 
           con->std_dev / 1000, con->std_dev % 1000, /* Standard Deviation */
 
2859
           con->getAvgTiming() / 1000, con->getAvgTiming() % 1000, /* Time to load */
 
2860
           con->getMinTiming() / 1000, con->getMinTiming() % 1000, /* Min time */
 
2861
           con->getMaxTiming() / 1000, con->getMaxTiming() % 1000, /* Max time */
 
2862
           con->getSumOfTime() / 1000, con->getSumOfTime() % 1000, /* Total time */
 
2863
           con->getStdDev() / 1000, con->getStdDev() % 1000, /* Standard Deviation */
2573
2864
           iterations, /* Iterations */
2574
 
           con->users, /* Children used max_timing */
2575
 
           con->real_users, /* Children used max_timing */
2576
 
           con->avg_rows  /* Queries run */
 
2865
           con->getUsers(), /* Children used max_timing */
 
2866
           con->getRealUsers(), /* Children used max_timing */
 
2867
           con->getAvgRows()  /* Queries run */
2577
2868
           );
2578
 
  internal::my_write(csv_file, (unsigned char*) buffer, (uint32_t)strlen(buffer), MYF(0));
 
2869
  size_t buff_len= strlen(buffer);
 
2870
  ssize_t write_ret= write(csv_file, (unsigned char*) buffer, buff_len);
 
2871
  if (write_ret != (ssize_t)buff_len)
 
2872
  {
 
2873
    fprintf(stderr, _("Unable to fully write %"PRIu64" bytes. "
 
2874
                      "Could only write %"PRId64"."), (uint64_t)write_ret,
 
2875
                      (int64_t)buff_len);
 
2876
    exit(-1);
 
2877
  }
2579
2878
}
2580
2879
 
2581
2880
void
2582
 
generate_stats(conclusions *con, option_string *eng, stats *sptr)
 
2881
generate_stats(Conclusions *con, OptionString *eng, Stats *sptr)
2583
2882
{
2584
 
  stats *ptr;
 
2883
  Stats *ptr;
2585
2884
  unsigned int x;
2586
2885
 
2587
 
  con->min_timing= sptr->timing;
2588
 
  con->max_timing= sptr->timing;
2589
 
  con->min_rows= sptr->rows;
2590
 
  con->max_rows= sptr->rows;
 
2886
  con->setMinTiming(sptr->getTiming());
 
2887
  con->setMaxTiming(sptr->getTiming());
 
2888
  con->setMinRows(sptr->getRows());
 
2889
  con->setMaxRows(sptr->getRows());
2591
2890
 
2592
2891
  /* At the moment we assume uniform */
2593
 
  con->users= sptr->users;
2594
 
  con->real_users= sptr->real_users;
2595
 
  con->avg_rows= sptr->rows;
 
2892
  con->setUsers(sptr->getUsers());
 
2893
  con->setRealUsers(sptr->getRealUsers());
 
2894
  con->setAvgRows(sptr->getRows());
2596
2895
 
2597
2896
  /* With no next, we know it is the last element that was malloced */
2598
2897
  for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
2599
2898
  {
2600
 
    con->avg_timing+= ptr->timing;
 
2899
    con->setAvgTiming(ptr->getTiming()+con->getAvgTiming());
2601
2900
 
2602
 
    if (ptr->timing > con->max_timing)
2603
 
      con->max_timing= ptr->timing;
2604
 
    if (ptr->timing < con->min_timing)
2605
 
      con->min_timing= ptr->timing;
 
2901
    if (ptr->getTiming() > con->getMaxTiming())
 
2902
      con->setMaxTiming(ptr->getTiming());
 
2903
    if (ptr->getTiming() < con->getMinTiming())
 
2904
      con->setMinTiming(ptr->getTiming());
2606
2905
  }
2607
 
  con->sum_of_time= con->avg_timing;
2608
 
  con->avg_timing= con->avg_timing/iterations;
 
2906
  con->setSumOfTime(con->getAvgTiming());
 
2907
  con->setAvgTiming(con->getAvgTiming()/iterations);
2609
2908
 
2610
 
  if (eng && eng->string)
2611
 
    con->engine= eng->string;
 
2909
  if (eng && eng->getString())
 
2910
    con->setEngine(eng->getString());
2612
2911
  else
2613
 
    con->engine= NULL;
 
2912
    con->setEngine(NULL);
2614
2913
 
2615
2914
  standard_deviation(con, sptr);
2616
2915
 
2617
2916
  /* Now we do the create time operations */
2618
 
  con->create_min_timing= sptr->create_timing;
2619
 
  con->create_max_timing= sptr->create_timing;
 
2917
  con->setCreateMinTiming(sptr->getCreateTiming());
 
2918
  con->setCreateMaxTiming(sptr->getCreateTiming());
2620
2919
 
2621
2920
  /* At the moment we assume uniform */
2622
 
  con->create_count= sptr->create_count;
 
2921
  con->setCreateCount(sptr->getCreateCount());
2623
2922
 
2624
2923
  /* With no next, we know it is the last element that was malloced */
2625
2924
  for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
2626
2925
  {
2627
 
    con->create_avg_timing+= ptr->create_timing;
2628
 
 
2629
 
    if (ptr->create_timing > con->create_max_timing)
2630
 
      con->create_max_timing= ptr->create_timing;
2631
 
    if (ptr->create_timing < con->create_min_timing)
2632
 
      con->create_min_timing= ptr->create_timing;
2633
 
  }
2634
 
  con->create_avg_timing= con->create_avg_timing/iterations;
2635
 
}
2636
 
 
2637
 
void
2638
 
option_cleanup(option_string *stmt)
2639
 
{
2640
 
  option_string *ptr, *nptr;
2641
 
  if (!stmt)
2642
 
    return;
2643
 
 
2644
 
  for (ptr= stmt; ptr; ptr= nptr)
2645
 
  {
2646
 
    nptr= ptr->next;
2647
 
    if (ptr->string)
2648
 
      free(ptr->string);
2649
 
    if (ptr->option)
2650
 
      free(ptr->option);
2651
 
    free(ptr);
2652
 
  }
2653
 
}
2654
 
 
2655
 
void
2656
 
statement_cleanup(statement *stmt)
2657
 
{
2658
 
  statement *ptr, *nptr;
2659
 
  if (!stmt)
2660
 
    return;
2661
 
 
2662
 
  for (ptr= stmt; ptr; ptr= nptr)
2663
 
  {
2664
 
    nptr= ptr->next;
2665
 
    if (ptr->string)
2666
 
      free(ptr->string);
2667
 
    free(ptr);
 
2926
    con->setCreateAvgTiming(ptr->getCreateTiming()+con->getCreateAvgTiming());
 
2927
 
 
2928
    if (ptr->getCreateTiming() > con->getCreateMaxTiming())
 
2929
      con->setCreateMaxTiming(ptr->getCreateTiming());
 
2930
    if (ptr->getCreateTiming() < con->getCreateMinTiming())
 
2931
      con->setCreateMinTiming(ptr->getCreateTiming());
 
2932
  }
 
2933
  con->setCreateAvgTiming(con->getCreateAvgTiming()/iterations);
 
2934
}
 
2935
 
 
2936
void
 
2937
option_cleanup(OptionString *stmt)
 
2938
{
 
2939
  OptionString *ptr, *nptr;
 
2940
  if (not stmt)
 
2941
    return;
 
2942
 
 
2943
  for (ptr= stmt; ptr; ptr= nptr)
 
2944
  {
 
2945
    nptr= ptr->getNext();
 
2946
    delete ptr;
 
2947
  }
 
2948
}
 
2949
 
 
2950
void
 
2951
statement_cleanup(Statement *stmt)
 
2952
{
 
2953
  Statement *ptr, *nptr;
 
2954
  if (!stmt)
 
2955
    return;
 
2956
 
 
2957
  for (ptr= stmt; ptr; ptr= nptr)
 
2958
  {
 
2959
    nptr= ptr->getNext();
 
2960
    delete ptr;
2668
2961
  }
2669
2962
}
2670
2963
 
2682
2975
{
2683
2976
  /* Connect to server */
2684
2977
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
2685
 
  int x, connect_error= 1;
 
2978
  int connect_error= 1;
2686
2979
  drizzle_return_t ret;
2687
2980
  drizzle_st *drizzle;
2688
2981
 
2693
2986
    usleep(random()%opt_delayed_start);
2694
2987
 
2695
2988
  if ((drizzle= drizzle_create(NULL)) == NULL ||
2696
 
      drizzle_con_add_tcp(drizzle, con, host, opt_drizzle_port, user,
2697
 
                          opt_password,
2698
 
                          connect_to_schema ? create_schema_string : NULL,
2699
 
                          opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE) == NULL)
 
2989
      drizzle_con_add_tcp(drizzle, con, host.c_str(), opt_drizzle_port,
 
2990
        user.c_str(),
 
2991
        opt_password.c_str(),
 
2992
        connect_to_schema ? create_schema_string.c_str() : NULL,
 
2993
        use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL) == NULL)
2700
2994
  {
2701
2995
    fprintf(stderr,"%s: Error creating drizzle object\n", internal::my_progname);
2702
2996
    exit(1);
2703
2997
  }
2704
2998
 
2705
 
  for (x= 0; x < 10; x++)
 
2999
  for (uint32_t x= 0; x < 10; x++)
2706
3000
  {
2707
3001
    if ((ret= drizzle_con_connect(con)) == DRIZZLE_RETURN_OK)
2708
3002
    {
2723
3017
}
2724
3018
 
2725
3019
void
2726
 
standard_deviation (conclusions *con, stats *sptr)
 
3020
standard_deviation (Conclusions *con, Stats *sptr)
2727
3021
{
2728
3022
  unsigned int x;
2729
3023
  long int sum_of_squares;
2730
3024
  double the_catch;
2731
 
  stats *ptr;
 
3025
  Stats *ptr;
2732
3026
 
2733
3027
  if (iterations == 1 || iterations == 0)
2734
3028
  {
2735
 
    con->std_dev= 0;
 
3029
    con->setStdDev(0);
2736
3030
    return;
2737
3031
  }
2738
3032
 
2740
3034
  {
2741
3035
    long int deviation;
2742
3036
 
2743
 
    deviation= ptr->timing - con->avg_timing;
 
3037
    deviation= ptr->getTiming() - con->getAvgTiming();
2744
3038
    sum_of_squares+= deviation*deviation;
2745
3039
  }
2746
3040
 
2747
3041
  the_catch= sqrt((double)(sum_of_squares/(iterations -1)));
2748
 
  con->std_dev= (long int)the_catch;
 
3042
  con->setStdDev((long int)the_catch);
2749
3043
}