~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleslap.cc

  • Committer: Brian Aker
  • Date: 2010-05-21 18:25:00 UTC
  • mfrom: (1530.2.10)
  • Revision ID: brian@gaz-20100521182500-c30dbqd2ko56cf56
Merge Monty

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