~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleslap.cc

Merge to trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
72
72
*/
73
73
 
74
74
#include "config.h"
 
75
 
75
76
#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
77
#include <signal.h>
84
78
#include <stdarg.h>
85
79
#include <sys/types.h>
94
88
#include <string>
95
89
#include <iostream>
96
90
#include <fstream>
 
91
#include <pthread.h>
97
92
#include <drizzled/configmake.h>
98
 
#include <memory>
99
 
 
100
93
/* Added this for string translation. */
101
94
#include <drizzled/gettext.h>
102
 
 
103
 
#include <boost/thread.hpp>
104
 
#include <boost/thread/mutex.hpp>
105
 
#include <boost/thread/condition_variable.hpp>
106
95
#include <boost/program_options.hpp>
107
 
#include <boost/scoped_ptr.hpp>
108
 
#include <drizzled/atomics.h>
109
96
 
110
 
#define SLAP_NAME "drizzleslap"
111
97
#define SLAP_VERSION "1.5"
112
98
 
113
99
#define HUGE_STRING_LENGTH 8196
122
108
static char *shared_memory_base_name=0;
123
109
#endif
124
110
 
125
 
client::Wakeup master_wakeup;
 
111
/* Global Thread counter */
 
112
uint32_t thread_counter;
 
113
pthread_mutex_t counter_mutex;
 
114
pthread_cond_t count_threshhold;
 
115
uint32_t master_wakeup;
 
116
pthread_mutex_t sleeper_mutex;
 
117
pthread_cond_t sleep_threshhold;
126
118
 
127
119
/* Global Thread timer */
128
120
static bool timer_alarm= false;
129
 
boost::mutex timer_alarm_mutex;
130
 
boost::condition_variable_any timer_alarm_threshold;
 
121
pthread_mutex_t timer_alarm_mutex;
 
122
pthread_cond_t timer_alarm_threshold;
131
123
 
132
124
std::vector < std::string > primary_keys;
133
125
 
134
 
drizzled::atomic<size_t> connection_count;
135
 
drizzled::atomic<uint64_t> failed_update_for_transaction;
136
 
 
137
126
static string host, 
138
127
  opt_password, 
139
128
  user,
172
161
  num_char_cols_opt,
173
162
  num_int_cols_opt;
174
163
string opt_label;
175
 
static uint32_t opt_set_random_seed;
 
164
static unsigned int opt_set_random_seed;
176
165
 
177
166
string auto_generate_selected_columns_opt;
178
167
 
179
168
/* 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;
 
169
static unsigned int num_int_cols= 1;
 
170
static unsigned int num_char_cols= 1;
 
171
static unsigned int num_blob_cols= 0;
 
172
static unsigned int num_blob_cols_size;
 
173
static unsigned int num_blob_cols_size_min;
 
174
static unsigned int num_int_cols_index= 0;
 
175
static unsigned int num_char_cols_index= 0;
187
176
static uint32_t iterations;
188
177
static uint64_t actual_queries= 0;
189
178
static uint64_t auto_actual_queries;
196
185
string create_string;
197
186
std::vector <uint32_t> concurrency;
198
187
 
 
188
const char *default_dbug_option= "d:t:o,/tmp/drizzleslap.trace";
199
189
std::string opt_csv_str;
200
190
int csv_file;
201
191
 
202
192
static int process_options(void);
203
193
static uint32_t opt_drizzle_port= 0;
204
194
 
 
195
 
 
196
/* Types */
 
197
enum slap_query_t {
 
198
  SELECT_TYPE= 0,
 
199
  UPDATE_TYPE= 1,
 
200
  INSERT_TYPE= 2,
 
201
  UPDATE_TYPE_REQUIRES_PREFIX= 3,
 
202
  CREATE_TABLE_TYPE= 4,
 
203
  SELECT_TYPE_REQUIRES_PREFIX= 5,
 
204
  DELETE_TYPE_REQUIRES_PREFIX= 6
 
205
};
 
206
 
 
207
class Statement;
 
208
 
 
209
class Statement 
 
210
{
 
211
public:
 
212
  Statement(char *in_string,
 
213
            size_t in_length,
 
214
            slap_query_t in_type,
 
215
            Statement *in_next) :
 
216
    string(in_string),
 
217
    length(in_length),
 
218
    type(in_type),
 
219
    next(in_next)
 
220
  { }
 
221
 
 
222
  Statement() :
 
223
    string(NULL),
 
224
    length(0),
 
225
    type(),
 
226
    next(NULL)
 
227
  { }
 
228
 
 
229
  ~Statement()
 
230
  {
 
231
    if (string)
 
232
      free(string);
 
233
  }
 
234
   
 
235
  char *getString() const
 
236
  {
 
237
    return string;
 
238
  }
 
239
 
 
240
  size_t getLength() const
 
241
  {
 
242
    return length;
 
243
  }
 
244
 
 
245
  slap_query_t getType() const
 
246
  {
 
247
    return type;
 
248
  }
 
249
 
 
250
  Statement *getNext() const
 
251
  {
 
252
    return next;
 
253
  }
 
254
 
 
255
  void setString(char *in_string)
 
256
  {
 
257
    string= in_string;
 
258
  }
 
259
 
 
260
  void setString(size_t length_arg)
 
261
  {
 
262
    string= (char *)calloc(length_arg + 1, sizeof(char));
 
263
    length= length_arg;
 
264
  }
 
265
 
 
266
  void setString(size_t in_length, char in_char)
 
267
  {
 
268
    string[in_length]= in_char;
 
269
  }
 
270
 
 
271
  void setLength(size_t in_length)
 
272
  {
 
273
    length= in_length;
 
274
  }
 
275
 
 
276
  void setType(slap_query_t in_type)
 
277
  {
 
278
    type= in_type;
 
279
  }
 
280
 
 
281
  void setNext(Statement *in_next)
 
282
  {
 
283
    next= in_next;
 
284
  }
 
285
 
 
286
private:
 
287
  char *string;
 
288
  size_t length;
 
289
  slap_query_t type;
 
290
  Statement *next;
 
291
};
 
292
 
 
293
class OptionString;
 
294
 
 
295
class OptionString 
 
296
{
 
297
public:
 
298
  OptionString(char *in_string,
 
299
               size_t in_length,
 
300
               char *in_option,
 
301
               size_t in_option_length,
 
302
               OptionString *in_next) :
 
303
    string(in_string),
 
304
    length(in_length),
 
305
    option(in_option),
 
306
    option_length(in_option_length),
 
307
    next(in_next)
 
308
  { }  
 
309
 
 
310
  OptionString() :
 
311
    string(NULL),
 
312
    length(0),
 
313
    option(NULL),
 
314
    option_length(0),
 
315
    next(NULL)
 
316
  { }
 
317
 
 
318
  ~OptionString()
 
319
  {
 
320
    if (getString())
 
321
      free(getString());
 
322
    if (getOption())
 
323
      free(getOption());
 
324
  }
 
325
 
 
326
  char *getString() const
 
327
  {
 
328
    return string;
 
329
  }
 
330
 
 
331
  size_t getLength() const
 
332
  {
 
333
    return length;
 
334
  }
 
335
 
 
336
  char *getOption() const
 
337
  {
 
338
  return option;
 
339
  }
 
340
 
 
341
  size_t getOptionLength() const
 
342
  {
 
343
    return option_length;
 
344
  }
 
345
 
 
346
  OptionString *getNext() const
 
347
  {
 
348
    return next;
 
349
  }
 
350
 
 
351
  void setString(char *in_string)
 
352
  {
 
353
    string= in_string;
 
354
    length= strlen(in_string);
 
355
  }
 
356
 
 
357
  void setOption(char *in_option)
 
358
  {
 
359
    option= strdup(in_option);
 
360
    option_length= strlen(in_option);
 
361
  }
 
362
 
 
363
  void setNext(OptionString *in_next)
 
364
  {
 
365
    next= in_next;
 
366
  }
 
367
  
 
368
private:
 
369
  char *string;
 
370
  size_t length;
 
371
  char *option;
 
372
  size_t option_length;
 
373
  OptionString *next;
 
374
};
 
375
 
 
376
class Stats;
 
377
 
 
378
class Stats 
 
379
{
 
380
public:
 
381
  Stats(long int in_timing,
 
382
        uint32_t in_users,
 
383
        uint32_t in_real_users,
 
384
        uint32_t in_rows,
 
385
        long int in_create_timing,
 
386
        uint64_t in_create_count) :
 
387
    timing(in_timing),
 
388
    users(in_users),
 
389
    real_users(in_real_users),
 
390
    rows(in_rows),
 
391
    create_timing(in_create_timing),
 
392
    create_count(in_create_count)
 
393
  { }
 
394
 
 
395
  Stats() :
 
396
    timing(0),
 
397
    users(0),
 
398
    real_users(0),
 
399
    rows(0),
 
400
    create_timing(0),
 
401
    create_count(0)
 
402
  { }
 
403
 
 
404
  long int getTiming() const
 
405
  {
 
406
    return timing;
 
407
  }
 
408
 
 
409
  uint32_t getUsers() const
 
410
  {
 
411
    return users;
 
412
  }   
 
413
 
 
414
  uint32_t getRealUsers() const
 
415
  {
 
416
    return real_users;
 
417
  }
 
418
 
 
419
  uint64_t getRows() const
 
420
  {
 
421
    return rows;
 
422
  }
 
423
 
 
424
  long int getCreateTiming() const
 
425
  {
 
426
    return create_timing;
 
427
  }
 
428
 
 
429
  uint64_t getCreateCount() const
 
430
  {
 
431
    return create_count;
 
432
  }
 
433
 
 
434
  void setTiming(long int in_timing)
 
435
  {
 
436
  timing= in_timing;
 
437
  }
 
438
 
 
439
  void setUsers(uint32_t in_users)
 
440
  {
 
441
    users= in_users;
 
442
  }
 
443
 
 
444
  void setRealUsers(uint32_t in_real_users)
 
445
  {
 
446
    real_users= in_real_users;
 
447
  }
 
448
 
 
449
  void setRows(uint64_t in_rows)
 
450
  {
 
451
    rows= in_rows;
 
452
  }
 
453
   
 
454
  void setCreateTiming(long int in_create_timing)
 
455
  {
 
456
    create_timing= in_create_timing;
 
457
  }
 
458
 
 
459
  void setCreateCount(uint64_t in_create_count)
 
460
  {
 
461
  create_count= in_create_count;
 
462
  }
 
463
  
 
464
private:
 
465
  long int timing;
 
466
  uint32_t users;
 
467
  uint32_t real_users;
 
468
  uint64_t rows;
 
469
  long int create_timing;
 
470
  uint64_t create_count;
 
471
};
 
472
 
 
473
class ThreadContext;
 
474
 
 
475
class ThreadContext 
 
476
{
 
477
public:
 
478
  ThreadContext(Statement *in_stmt,
 
479
                uint64_t in_limit) :
 
480
    stmt(in_stmt),
 
481
    limit(in_limit)
 
482
  { }
 
483
 
 
484
  ThreadContext() :
 
485
    stmt(),
 
486
    limit(0)
 
487
  { }
 
488
 
 
489
  Statement *getStmt() const
 
490
  {
 
491
    return stmt;
 
492
  }
 
493
 
 
494
  uint64_t getLimit() const
 
495
  {
 
496
    return limit;
 
497
  }
 
498
 
 
499
  void setStmt(Statement *in_stmt)
 
500
  {
 
501
    stmt= in_stmt;
 
502
  }
 
503
 
 
504
  void setLimit(uint64_t in_limit)
 
505
  {
 
506
    limit= in_limit;
 
507
  }  
 
508
 
 
509
private:
 
510
  Statement *stmt;
 
511
  uint64_t limit;
 
512
};
 
513
 
 
514
class Conclusions;
 
515
 
 
516
class Conclusions 
 
517
{
 
518
 
 
519
public:
 
520
  Conclusions(char *in_engine,
 
521
              long int in_avg_timing,
 
522
              long int in_max_timing,
 
523
              long int in_min_timing,
 
524
              uint32_t in_users,
 
525
              uint32_t in_real_users,
 
526
              uint64_t in_avg_rows,
 
527
              long int in_sum_of_time,
 
528
              long int in_std_dev,
 
529
              long int in_create_avg_timing,
 
530
              long int in_create_max_timing,
 
531
              long int in_create_min_timing,
 
532
              uint64_t in_create_count,
 
533
              uint64_t in_max_rows,
 
534
              uint64_t in_min_rows) :
 
535
    engine(in_engine),
 
536
    avg_timing(in_avg_timing),
 
537
    max_timing(in_max_timing),
 
538
    min_timing(in_min_timing),
 
539
    users(in_users),
 
540
    real_users(in_real_users),
 
541
    avg_rows(in_avg_rows),
 
542
    sum_of_time(in_sum_of_time),
 
543
    std_dev(in_std_dev),
 
544
    create_avg_timing(in_create_avg_timing),
 
545
    create_max_timing(in_create_max_timing),
 
546
    create_min_timing(in_create_min_timing),
 
547
    create_count(in_create_count),
 
548
    max_rows(in_max_rows),
 
549
    min_rows(in_min_rows)
 
550
  { }
 
551
 
 
552
  Conclusions() :
 
553
    engine(NULL),
 
554
    avg_timing(0),
 
555
    max_timing(0),
 
556
    min_timing(0),
 
557
    users(0),
 
558
    real_users(0),
 
559
    avg_rows(0),
 
560
    sum_of_time(0),
 
561
    std_dev(0),
 
562
    create_avg_timing(0),
 
563
    create_max_timing(0),
 
564
    create_min_timing(0),
 
565
    create_count(0),
 
566
    max_rows(0),
 
567
    min_rows(0)
 
568
  { }
 
569
 
 
570
  char *getEngine() const
 
571
  {
 
572
    return engine;
 
573
  }
 
574
  
 
575
  long int getAvgTiming() const
 
576
  {
 
577
    return avg_timing;
 
578
  }
 
579
 
 
580
  long int getMaxTiming() const
 
581
  {
 
582
    return max_timing;
 
583
  }
 
584
 
 
585
  long int getMinTiming() const
 
586
  {
 
587
    return min_timing;
 
588
  }
 
589
 
 
590
  uint32_t getUsers() const
 
591
  {
 
592
    return users;
 
593
  }
 
594
 
 
595
  uint32_t getRealUsers() const
 
596
  {
 
597
    return real_users;
 
598
  }
 
599
 
 
600
  uint64_t getAvgRows() const
 
601
  {
 
602
    return avg_rows;
 
603
  }   
 
604
 
 
605
  long int getSumOfTime() const
 
606
  {
 
607
    return sum_of_time;
 
608
  }
 
609
 
 
610
  long int getStdDev() const
 
611
  {
 
612
    return std_dev;
 
613
  }
 
614
 
 
615
  long int getCreateAvgTiming() const
 
616
  {
 
617
    return create_avg_timing;
 
618
  }
 
619
 
 
620
  long int getCreateMaxTiming() const
 
621
  {
 
622
    return create_max_timing;
 
623
  }
 
624
 
 
625
  long int getCreateMinTiming() const
 
626
  {
 
627
    return create_min_timing;
 
628
  }
 
629
   
 
630
  uint64_t getCreateCount() const
 
631
  {
 
632
    return create_count;
 
633
  }
 
634
 
 
635
  uint64_t getMinRows() const
 
636
  {
 
637
    return min_rows;
 
638
  }
 
639
 
 
640
  uint64_t getMaxRows() const
 
641
  {
 
642
    return max_rows;
 
643
  }
 
644
 
 
645
  void setEngine(char *in_engine) 
 
646
  {
 
647
    engine= in_engine;
 
648
  }
 
649
  
 
650
  void setAvgTiming(long int in_avg_timing) 
 
651
  {
 
652
    avg_timing= in_avg_timing;
 
653
  }
 
654
 
 
655
  void setMaxTiming(long int in_max_timing) 
 
656
  {
 
657
    max_timing= in_max_timing;
 
658
  }
 
659
 
 
660
  void setMinTiming(long int in_min_timing) 
 
661
  {
 
662
    min_timing= in_min_timing;
 
663
  }
 
664
 
 
665
  void setUsers(uint32_t in_users) 
 
666
  {
 
667
    users= in_users;
 
668
  }
 
669
 
 
670
  void setRealUsers(uint32_t in_real_users) 
 
671
  {
 
672
    real_users= in_real_users;
 
673
  }
 
674
 
 
675
  void setAvgRows(uint64_t in_avg_rows) 
 
676
  {
 
677
    avg_rows= in_avg_rows;
 
678
  }   
 
679
 
 
680
  void setSumOfTime(long int in_sum_of_time) 
 
681
  {
 
682
    sum_of_time= in_sum_of_time;
 
683
  }
 
684
 
 
685
  void setStdDev(long int in_std_dev) 
 
686
  {
 
687
    std_dev= in_std_dev;
 
688
  }
 
689
 
 
690
  void setCreateAvgTiming(long int in_create_avg_timing) 
 
691
  {
 
692
    create_avg_timing= in_create_avg_timing;
 
693
  }
 
694
 
 
695
  void setCreateMaxTiming(long int in_create_max_timing) 
 
696
  {
 
697
    create_max_timing= in_create_max_timing;
 
698
  }
 
699
 
 
700
  void setCreateMinTiming(long int in_create_min_timing) 
 
701
  {
 
702
    create_min_timing= in_create_min_timing;
 
703
  }
 
704
   
 
705
  void setCreateCount(uint64_t in_create_count) 
 
706
  {
 
707
    create_count= in_create_count;
 
708
  }
 
709
 
 
710
  void setMinRows(uint64_t in_min_rows) 
 
711
  {
 
712
    min_rows= in_min_rows;
 
713
  }
 
714
 
 
715
  void setMaxRows(uint64_t in_max_rows) 
 
716
  {
 
717
    max_rows= in_max_rows;
 
718
  }
 
719
 
 
720
private:
 
721
  char *engine;
 
722
  long int avg_timing;
 
723
  long int max_timing;
 
724
  long int min_timing;
 
725
  uint32_t users;
 
726
  uint32_t real_users;
 
727
  uint64_t avg_rows;
 
728
  long int sum_of_time;
 
729
  long int std_dev;
 
730
  /* These are just for create time stats */
 
731
  long int create_avg_timing;
 
732
  long int create_max_timing;
 
733
  long int create_min_timing;
 
734
  uint64_t create_count;
 
735
  /* The following are not used yet */
 
736
  uint64_t max_rows;
 
737
  uint64_t min_rows;
 
738
};
 
739
 
 
740
 
205
741
static OptionString *engine_options= NULL;
206
742
static OptionString *query_options= NULL;
207
743
static Statement *pre_statements= NULL;
209
745
static Statement *create_statements= NULL;
210
746
 
211
747
static std::vector <Statement *> query_statements;
212
 
static uint32_t query_statements_count;
 
748
static unsigned int query_statements_count;
213
749
 
214
750
 
215
751
/* Prototypes */
216
 
void print_conclusions(Conclusions &con);
217
 
void print_conclusions_csv(Conclusions &con);
 
752
void print_conclusions(Conclusions *con);
 
753
void print_conclusions_csv(Conclusions *con);
218
754
void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr);
219
755
uint32_t parse_comma(const char *string, std::vector <uint32_t> &range);
220
756
uint32_t parse_delimiter(const char *script, Statement **stmt, char delm);
221
757
uint32_t parse_option(const char *origin, OptionString **stmt, char delm);
222
 
static void drop_schema(drizzle_con_st &con, const char *db);
 
758
static int drop_schema(drizzle_con_st *con, const char *db);
223
759
uint32_t get_random_string(char *buf, size_t size);
224
760
static Statement *build_table_string(void);
225
761
static Statement *build_insert_string(void);
226
762
static Statement *build_update_string(void);
227
763
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);
 
764
static int generate_primary_key_list(drizzle_con_st *con, OptionString *engine_stmt);
 
765
static int create_schema(drizzle_con_st *con, const char *db, Statement *stmt,
 
766
                         OptionString *engine_stmt, Stats *sptr);
 
767
static int run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur,
 
768
                         uint64_t limit);
 
769
extern "C" pthread_handler_t run_task(void *p);
 
770
extern "C" pthread_handler_t timer_thread(void *p);
231
771
void statement_cleanup(Statement *stmt);
232
772
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);
 
773
void concurrency_loop(drizzle_con_st *con, uint32_t current, OptionString *eptr);
 
774
static int run_statements(drizzle_con_st *con, Statement *stmt);
 
775
void slap_connect(drizzle_con_st *con, bool connect_to_schema);
 
776
void slap_close(drizzle_con_st *con);
 
777
static int run_query(drizzle_con_st *con, drizzle_result_st *result, const char *query, int len);
 
778
void standard_deviation (Conclusions *con, Stats *sptr);
239
779
 
240
780
static const char ALPHANUMERICS[]=
241
781
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
265
805
    user_supplied_query.append(delimiter);
266
806
  }
267
807
}
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
808
/**
414
809
 * commandline_options is the set of all options that can only be called via the command line.
415
810
 
436
831
    po::options_description commandline_options("Options used only in command line");
437
832
    commandline_options.add_options()
438
833
      ("help,?","Display this help and exit")
439
 
      ("info","Gives information and exit")
 
834
      ("info,i","Gives information and exit")
440
835
      ("burnin",po::value<bool>(&opt_burnin)->default_value(false)->zero_tokens(),
441
836
       "Run full test case in infinite loop")
442
837
      ("ignore-sql-errors", po::value<bool>(&opt_ignore_sql_errors)->default_value(false)->zero_tokens(),
552
947
 
553
948
    std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
554
949
 
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
950
    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();
 
951
    drizzle_con_st con;
566
952
    OptionString *eptr;
567
953
 
568
954
    // Disable allow_guessing
593
979
    po::notify(vm);
594
980
 
595
981
    if (process_options())
596
 
      abort();
 
982
      exit(1);
597
983
 
598
984
    if ( vm.count("help") || vm.count("info"))
599
985
    {
600
 
      printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",SLAP_NAME, SLAP_VERSION,
 
986
      printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname, SLAP_VERSION,
601
987
          drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
602
988
      puts("Copyright (C) 2008 Sun Microsystems");
603
989
      puts("This software comes with ABSOLUTELY NO WARRANTY. "
606
992
           "license\n");
607
993
      puts("Run a query multiple times against the server\n");
608
994
      cout << long_options << endl;
609
 
      abort();
 
995
      exit(0);
610
996
    }   
611
997
 
612
998
    if (vm.count("protocol"))
621
1007
      else
622
1008
      {
623
1009
        cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
624
 
        abort();
 
1010
        exit(-1);
625
1011
      }
626
1012
    }
627
1013
    if (vm.count("port")) 
631
1017
      if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
632
1018
      {
633
1019
        fprintf(stderr, _("Value supplied for port is not valid.\n"));
634
 
        abort();
 
1020
        exit(1);
635
1021
      }
636
1022
      else
637
1023
      {
641
1027
 
642
1028
  if ( vm.count("password") )
643
1029
  {
644
 
    if (not opt_password.empty())
 
1030
    if (!opt_password.empty())
645
1031
      opt_password.erase();
646
1032
    if (password == PASSWORD_SENTINEL)
647
1033
    {
662
1048
 
663
1049
    if ( vm.count("version") )
664
1050
    {
665
 
      printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",SLAP_NAME, SLAP_VERSION,
 
1051
      printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname, SLAP_VERSION,
666
1052
          drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
667
 
      abort();
 
1053
      exit(0);
668
1054
    }
669
1055
 
670
1056
    /* Seed the random number generator if we will be using it. */
671
1057
    if (auto_generate_sql)
672
1058
    {
673
1059
      if (opt_set_random_seed == 0)
674
 
        opt_set_random_seed= (uint32_t)time(NULL);
 
1060
        opt_set_random_seed= (unsigned int)time(NULL);
675
1061
      srandom(opt_set_random_seed);
676
1062
    }
677
1063
 
678
1064
    /* globals? Yes, so we only have to run strlen once */
679
1065
    delimiter_length= delimiter.length();
680
1066
 
681
 
    slap_connect(con, false);
 
1067
    slap_connect(&con, false);
 
1068
 
 
1069
    pthread_mutex_init(&counter_mutex, NULL);
 
1070
    pthread_cond_init(&count_threshhold, NULL);
 
1071
    pthread_mutex_init(&sleeper_mutex, NULL);
 
1072
    pthread_cond_init(&sleep_threshhold, NULL);
 
1073
    pthread_mutex_init(&timer_alarm_mutex, NULL);
 
1074
    pthread_cond_init(&timer_alarm_threshold, NULL);
 
1075
 
682
1076
 
683
1077
    /* Main iterations loop */
684
1078
burnin:
694
1088
      if (concurrency.size())
695
1089
      {
696
1090
        for (current= &concurrency[0]; current && *current; current++)
697
 
          concurrency_loop(con, *current, eptr);
 
1091
          concurrency_loop(&con, *current, eptr);
698
1092
      }
699
1093
      else
700
1094
      {
701
1095
        uint32_t infinite= 1;
702
1096
        do {
703
 
          concurrency_loop(con, infinite, eptr);
 
1097
          concurrency_loop(&con, infinite, eptr);
704
1098
        }
705
1099
        while (infinite++);
706
1100
      }
707
1101
 
708
 
      if (not opt_preserve)
709
 
        drop_schema(con, create_schema_string.c_str());
 
1102
      if (!opt_preserve)
 
1103
        drop_schema(&con, create_schema_string.c_str());
710
1104
 
711
1105
    } while (eptr ? (eptr= eptr->getNext()) : 0);
712
1106
 
713
1107
    if (opt_burnin)
714
1108
      goto burnin;
715
1109
 
716
 
    slap_close(con);
 
1110
    pthread_mutex_destroy(&counter_mutex);
 
1111
    pthread_cond_destroy(&count_threshhold);
 
1112
    pthread_mutex_destroy(&sleeper_mutex);
 
1113
    pthread_cond_destroy(&sleep_threshhold);
 
1114
    pthread_mutex_destroy(&timer_alarm_mutex);
 
1115
    pthread_cond_destroy(&timer_alarm_threshold);
 
1116
 
 
1117
    slap_close(&con);
717
1118
 
718
1119
    /* now free all the strings we created */
719
 
    if (not opt_password.empty())
 
1120
    if (!opt_password.empty())
720
1121
      opt_password.erase();
721
1122
 
722
1123
    concurrency.clear();
748
1149
  return 0;
749
1150
}
750
1151
 
751
 
void concurrency_loop(drizzle_con_st &con, uint32_t current, OptionString *eptr)
 
1152
void concurrency_loop(drizzle_con_st *con, uint32_t current, OptionString *eptr)
752
1153
{
753
1154
  Stats *head_sptr;
754
1155
  Stats *sptr;
759
1160
  if (head_sptr == NULL)
760
1161
  {
761
1162
    fprintf(stderr,"Error allocating memory in concurrency_loop\n");
762
 
    abort();
 
1163
    exit(1);
763
1164
  }
764
1165
 
765
1166
  if (auto_actual_queries)
793
1194
    if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
794
1195
      generate_primary_key_list(con, eptr);
795
1196
 
796
 
    if (not pre_system.empty())
 
1197
    if (commit_rate)
 
1198
      run_query(con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
 
1199
 
 
1200
    if (!pre_system.empty())
797
1201
    {
798
1202
      int ret= system(pre_system.c_str());
799
1203
      assert(ret != -1);
800
1204
    }
 
1205
       
801
1206
 
802
1207
    /*
803
1208
      Pre statements are always run after all other logic so they can
811
1216
    if (post_statements)
812
1217
      run_statements(con, post_statements);
813
1218
 
814
 
    if (not post_system.empty())
 
1219
    if (!post_system.empty())
815
1220
    {
816
1221
      int ret=  system(post_system.c_str());
817
1222
      assert(ret !=-1);
827
1232
 
828
1233
  generate_stats(&conclusion, eptr, head_sptr);
829
1234
 
830
 
  if (not opt_silent)
831
 
    print_conclusions(conclusion);
832
 
  if (not opt_csv_str.empty())
833
 
    print_conclusions_csv(conclusion);
 
1235
  if (!opt_silent)
 
1236
    print_conclusions(&conclusion);
 
1237
  if (!opt_csv_str.empty())
 
1238
    print_conclusions_csv(&conclusion);
834
1239
 
835
1240
  delete [] head_sptr;
836
1241
}
837
1242
 
838
1243
 
839
 
uint32_t get_random_string(char *buf, size_t size)
 
1244
uint
 
1245
get_random_string(char *buf, size_t size)
840
1246
{
841
1247
  char *buf_ptr= buf;
842
1248
 
856
1262
build_table_string(void)
857
1263
{
858
1264
  char       buf[HUGE_STRING_LENGTH];
859
 
  uint32_t        col_count;
 
1265
  unsigned int        col_count;
860
1266
  Statement *ptr;
861
1267
  string table_string;
862
1268
 
882
1288
 
883
1289
  if (auto_generate_sql_secondary_indexes)
884
1290
  {
885
 
    for (uint32_t count= 0; count < auto_generate_sql_secondary_indexes; count++)
 
1291
    unsigned int count;
 
1292
 
 
1293
    for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
886
1294
    {
887
1295
      if (count) /* Except for the first pass we add a comma */
888
1296
        table_string.append(",");
891
1299
          > HUGE_STRING_LENGTH)
892
1300
      {
893
1301
        fprintf(stderr, "Memory Allocation error in create table\n");
894
 
        abort();
 
1302
        exit(1);
895
1303
      }
896
1304
      table_string.append(buf);
897
1305
    }
909
1317
                     col_count, col_count) > HUGE_STRING_LENGTH)
910
1318
        {
911
1319
          fprintf(stderr, "Memory Allocation error in create table\n");
912
 
          abort();
 
1320
          exit(1);
913
1321
        }
914
1322
      }
915
1323
      else
918
1326
            > HUGE_STRING_LENGTH)
919
1327
        {
920
1328
          fprintf(stderr, "Memory Allocation error in create table\n");
921
 
          abort();
 
1329
          exit(1);
922
1330
        }
923
1331
      }
924
1332
      table_string.append(buf);
937
1345
                     col_count, col_count) > HUGE_STRING_LENGTH)
938
1346
        {
939
1347
          fprintf(stderr, "Memory Allocation error in creating table\n");
940
 
          abort();
 
1348
          exit(1);
941
1349
        }
942
1350
      }
943
1351
      else
946
1354
                     col_count) > HUGE_STRING_LENGTH)
947
1355
        {
948
1356
          fprintf(stderr, "Memory Allocation error in creating table\n");
949
 
          abort();
 
1357
          exit(1);
950
1358
        }
951
1359
      }
952
1360
      table_string.append(buf);
962
1370
                   col_count) > HUGE_STRING_LENGTH)
963
1371
      {
964
1372
        fprintf(stderr, "Memory Allocation error in creating table\n");
965
 
        abort();
 
1373
        exit(1);
966
1374
      }
967
1375
      table_string.append(buf);
968
1376
 
976
1384
  if (ptr->getString()==NULL)
977
1385
  {
978
1386
    fprintf(stderr, "Memory Allocation error in creating table\n");
979
 
    abort();
 
1387
    exit(1);
980
1388
  }
981
1389
  ptr->setType(CREATE_TABLE_TYPE);
982
1390
  strcpy(ptr->getString(), table_string.c_str());
993
1401
build_update_string(void)
994
1402
{
995
1403
  char       buf[HUGE_STRING_LENGTH];
996
 
  uint32_t        col_count;
 
1404
  unsigned int        col_count;
997
1405
  Statement *ptr;
998
1406
  string update_string;
999
1407
 
1008
1416
                   random()) > HUGE_STRING_LENGTH)
1009
1417
      {
1010
1418
        fprintf(stderr, "Memory Allocation error in creating update\n");
1011
 
        abort();
 
1419
        exit(1);
1012
1420
      }
1013
1421
      update_string.append(buf);
1014
1422
 
1027
1435
          > HUGE_STRING_LENGTH)
1028
1436
      {
1029
1437
        fprintf(stderr, "Memory Allocation error in creating update\n");
1030
 
        abort();
 
1438
        exit(1);
1031
1439
      }
1032
1440
      update_string.append(buf);
1033
1441
 
1045
1453
  if (ptr->getString() == NULL)
1046
1454
  {
1047
1455
    fprintf(stderr, "Memory Allocation error in creating update\n");
1048
 
    abort();
 
1456
    exit(1);
1049
1457
  }
1050
1458
  if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
1051
1459
    ptr->setType(UPDATE_TYPE_REQUIRES_PREFIX);
1066
1474
build_insert_string(void)
1067
1475
{
1068
1476
  char       buf[HUGE_STRING_LENGTH];
1069
 
  uint32_t        col_count;
 
1477
  unsigned int        col_count;
1070
1478
  Statement *ptr;
1071
1479
  string insert_string;
1072
1480
 
1092
1500
 
1093
1501
  if (auto_generate_sql_secondary_indexes)
1094
1502
  {
1095
 
    uint32_t count;
 
1503
    unsigned int count;
1096
1504
 
1097
1505
    for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
1098
1506
    {
1112
1520
      if (snprintf(buf, HUGE_STRING_LENGTH, "%ld", random()) > HUGE_STRING_LENGTH)
1113
1521
      {
1114
1522
        fprintf(stderr, "Memory Allocation error in creating insert\n");
1115
 
        abort();
 
1523
        exit(1);
1116
1524
      }
1117
1525
      insert_string.append(buf);
1118
1526
 
1140
1548
 
1141
1549
    for (col_count= 1; col_count <= num_blob_cols; col_count++)
1142
1550
    {
1143
 
      uint32_t buf_len;
1144
 
      uint32_t size;
1145
 
      uint32_t difference= num_blob_cols_size - num_blob_cols_size_min;
 
1551
      unsigned int buf_len;
 
1552
      unsigned int size;
 
1553
      unsigned int difference= num_blob_cols_size - num_blob_cols_size_min;
1146
1554
 
1147
1555
      size= difference ? (num_blob_cols_size_min + (random() % difference)) :
1148
1556
        num_blob_cols_size;
1165
1573
  if (ptr->getString()==NULL)
1166
1574
  {
1167
1575
    fprintf(stderr, "Memory Allocation error in creating select\n");
1168
 
    abort();
 
1576
    exit(1);
1169
1577
  }
1170
1578
  ptr->setType(INSERT_TYPE);
1171
1579
  strcpy(ptr->getString(), insert_string.c_str());
1183
1591
build_select_string(bool key)
1184
1592
{
1185
1593
  char       buf[HUGE_STRING_LENGTH];
1186
 
  uint32_t        col_count;
 
1594
  unsigned int        col_count;
1187
1595
  Statement *ptr;
1188
1596
  string query_string;
1189
1597
 
1190
1598
  query_string.reserve(HUGE_STRING_LENGTH);
1191
1599
 
1192
1600
  query_string.append("SELECT ", 7);
1193
 
  if (not auto_generate_selected_columns_opt.empty())
 
1601
  if (!auto_generate_selected_columns_opt.empty())
1194
1602
  {
1195
1603
    query_string.append(auto_generate_selected_columns_opt.c_str());
1196
1604
  }
1202
1610
          > HUGE_STRING_LENGTH)
1203
1611
      {
1204
1612
        fprintf(stderr, "Memory Allocation error in creating select\n");
1205
 
        abort();
 
1613
        exit(1);
1206
1614
      }
1207
1615
      query_string.append(buf);
1208
1616
 
1216
1624
          > HUGE_STRING_LENGTH)
1217
1625
      {
1218
1626
        fprintf(stderr, "Memory Allocation error in creating select\n");
1219
 
        abort();
 
1627
        exit(1);
1220
1628
      }
1221
1629
      query_string.append(buf);
1222
1630
 
1230
1638
          > HUGE_STRING_LENGTH)
1231
1639
      {
1232
1640
        fprintf(stderr, "Memory Allocation error in creating select\n");
1233
 
        abort();
 
1641
        exit(1);
1234
1642
      }
1235
1643
      query_string.append(buf);
1236
1644
 
1249
1657
  if (ptr->getString() == NULL)
1250
1658
  {
1251
1659
    fprintf(stderr, "Memory Allocation error in creating select\n");
1252
 
    abort();
 
1660
    exit(1);
1253
1661
  }
1254
1662
  if ((key) &&
1255
1663
      (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
1265
1673
{
1266
1674
  struct stat sbuf;
1267
1675
  OptionString *sql_type;
1268
 
  uint32_t sql_type_count= 0;
 
1676
  unsigned int sql_type_count= 0;
1269
1677
  ssize_t bytes_read= 0;
1270
1678
  
1271
1679
  if (user.empty())
1274
1682
  verbose= opt_verbose.length();
1275
1683
 
1276
1684
  /* If something is created we clean it up, otherwise we leave schemas alone */
1277
 
  if ( (not create_string.empty()) || auto_generate_sql)
 
1685
  if ( (!create_string.empty()) || auto_generate_sql)
1278
1686
    opt_preserve= false;
1279
1687
 
1280
 
  if (auto_generate_sql && (not create_string.empty() || !user_supplied_query.empty()))
 
1688
  if (auto_generate_sql && (!create_string.empty() || !user_supplied_query.empty()))
1281
1689
  {
1282
1690
    fprintf(stderr,
1283
1691
            "%s: Can't use --auto-generate-sql when create and query strings are specified!\n",
1284
 
            SLAP_NAME);
1285
 
    abort();
 
1692
            internal::my_progname);
 
1693
    exit(1);
1286
1694
  }
1287
1695
 
1288
1696
  if (auto_generate_sql && auto_generate_sql_guid_primary &&
1290
1698
  {
1291
1699
    fprintf(stderr,
1292
1700
            "%s: Either auto-generate-sql-guid-primary or auto-generate-sql-add-autoincrement can be used!\n",
1293
 
            SLAP_NAME);
1294
 
    abort();
 
1701
            internal::my_progname);
 
1702
    exit(1);
1295
1703
  }
1296
1704
 
1297
1705
  if (auto_generate_sql && num_of_query && auto_actual_queries)
1298
1706
  {
1299
1707
    fprintf(stderr,
1300
1708
            "%s: Either auto-generate-sql-execute-number or number-of-queries can be used!\n",
1301
 
            SLAP_NAME);
1302
 
    abort();
 
1709
            internal::my_progname);
 
1710
    exit(1);
1303
1711
  }
1304
1712
 
1305
 
  parse_comma(not concurrency_str.empty() ? concurrency_str.c_str() : "1", concurrency);
 
1713
  parse_comma(!concurrency_str.empty() ? concurrency_str.c_str() : "1", concurrency);
1306
1714
 
1307
 
  if (not opt_csv_str.empty())
 
1715
  if (!opt_csv_str.empty())
1308
1716
  {
1309
1717
    opt_silent= true;
1310
1718
 
1318
1726
                          S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
1319
1727
      {
1320
1728
        fprintf(stderr,"%s: Could not open csv file: %sn\n",
1321
 
                SLAP_NAME, opt_csv_str.c_str());
1322
 
        abort();
 
1729
                internal::my_progname, opt_csv_str.c_str());
 
1730
        exit(1);
1323
1731
      }
1324
1732
    }
1325
1733
  }
1327
1735
  if (opt_only_print)
1328
1736
    opt_silent= true;
1329
1737
 
1330
 
  if (not num_int_cols_opt.empty())
 
1738
  if (!num_int_cols_opt.empty())
1331
1739
  {
1332
1740
    OptionString *str;
1333
1741
    parse_option(num_int_cols_opt.c_str(), &str, ',');
1337
1745
    option_cleanup(str);
1338
1746
  }
1339
1747
 
1340
 
  if (not num_char_cols_opt.empty())
 
1748
  if (!num_char_cols_opt.empty())
1341
1749
  {
1342
1750
    OptionString *str;
1343
1751
    parse_option(num_char_cols_opt.c_str(), &str, ',');
1349
1757
    option_cleanup(str);
1350
1758
  }
1351
1759
 
1352
 
  if (not num_blob_cols_opt.empty())
 
1760
  if (!num_blob_cols_opt.empty())
1353
1761
  {
1354
1762
    OptionString *str;
1355
1763
    parse_option(num_blob_cols_opt.c_str(), &str, ',');
1433
1841
        {
1434
1842
          fprintf(stderr,
1435
1843
                  "%s: Can't perform key test without a primary key!\n",
1436
 
                  SLAP_NAME);
1437
 
          abort();
 
1844
                  internal::my_progname);
 
1845
          exit(1);
1438
1846
        }
1439
1847
 
1440
1848
        query_statements[sql_type_count]= build_select_string(true);
1469
1877
        {
1470
1878
          fprintf(stderr,
1471
1879
                  "%s: Can't perform update test without a primary key!\n",
1472
 
                  SLAP_NAME);
1473
 
          abort();
 
1880
                  internal::my_progname);
 
1881
          exit(1);
1474
1882
        }
1475
1883
 
1476
1884
        query_statements[sql_type_count]= build_update_string();
1511
1919
  }
1512
1920
  else
1513
1921
  {
1514
 
    if (not create_string.empty() && !stat(create_string.c_str(), &sbuf))
 
1922
    if (!create_string.empty() && !stat(create_string.c_str(), &sbuf))
1515
1923
    {
1516
1924
      int data_file;
1517
1925
      std::vector<char> tmp_string;
1518
 
      if (not S_ISREG(sbuf.st_mode))
 
1926
      if (!S_ISREG(sbuf.st_mode))
1519
1927
      {
1520
1928
        fprintf(stderr,"%s: Create file was not a regular file\n",
1521
 
                SLAP_NAME);
1522
 
        abort();
 
1929
                internal::my_progname);
 
1930
        exit(1);
1523
1931
      }
1524
1932
      if ((data_file= open(create_string.c_str(), O_RDWR)) == -1)
1525
1933
      {
1526
 
        fprintf(stderr,"%s: Could not open create file\n", SLAP_NAME);
1527
 
        abort();
 
1934
        fprintf(stderr,"%s: Could not open create file\n", internal::my_progname);
 
1935
        exit(1);
1528
1936
      }
1529
1937
      if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1530
1938
      {
1531
1939
        fprintf(stderr, "Request for more memory than architecture supports\n");
1532
 
        abort();
 
1940
        exit(1);
1533
1941
      }
1534
1942
      tmp_string.resize(sbuf.st_size + 1);
1535
1943
      bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
1541
1949
      }
1542
1950
      parse_delimiter(&tmp_string[0], &create_statements, delimiter[0]);
1543
1951
    }
1544
 
    else if (not create_string.empty())
 
1952
    else if (!create_string.empty())
1545
1953
    {
1546
1954
      parse_delimiter(create_string.c_str(), &create_statements, delimiter[0]);
1547
1955
    }
1548
1956
 
1549
1957
    /* Set this up till we fully support options on user generated queries */
1550
 
    if (not user_supplied_query.empty())
 
1958
    if (!user_supplied_query.empty())
1551
1959
    {
1552
1960
      query_statements_count=
1553
1961
        parse_option("default", &query_options, ',');
1555
1963
      query_statements.resize(query_statements_count);
1556
1964
    }
1557
1965
 
1558
 
    if (not user_supplied_query.empty() && !stat(user_supplied_query.c_str(), &sbuf))
 
1966
    if (!user_supplied_query.empty() && !stat(user_supplied_query.c_str(), &sbuf))
1559
1967
    {
1560
1968
      int data_file;
1561
1969
      std::vector<char> tmp_string;
1562
1970
 
1563
 
      if (not S_ISREG(sbuf.st_mode))
 
1971
      if (!S_ISREG(sbuf.st_mode))
1564
1972
      {
1565
1973
        fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1566
 
                SLAP_NAME);
1567
 
        abort();
 
1974
                internal::my_progname);
 
1975
        exit(1);
1568
1976
      }
1569
1977
      if ((data_file= open(user_supplied_query.c_str(), O_RDWR)) == -1)
1570
1978
      {
1571
 
        fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
1572
 
        abort();
 
1979
        fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
 
1980
        exit(1);
1573
1981
      }
1574
1982
      if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1575
1983
      {
1576
1984
        fprintf(stderr, "Request for more memory than architecture supports\n");
1577
 
        abort();
 
1985
        exit(1);
1578
1986
      }
1579
1987
      tmp_string.resize((size_t)(sbuf.st_size + 1));
1580
1988
      bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
1584
1992
      {
1585
1993
        fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1586
1994
      }
1587
 
      if (not user_supplied_query.empty())
 
1995
      if (!user_supplied_query.empty())
1588
1996
        actual_queries= parse_delimiter(&tmp_string[0], &query_statements[0],
1589
1997
                                        delimiter[0]);
1590
1998
    }
1591
 
    else if (not user_supplied_query.empty())
 
1999
    else if (!user_supplied_query.empty())
1592
2000
    {
1593
2001
      actual_queries= parse_delimiter(user_supplied_query.c_str(), &query_statements[0],
1594
2002
                                      delimiter[0]);
1595
2003
    }
1596
2004
  }
1597
2005
 
1598
 
  if (not user_supplied_pre_statements.empty()
 
2006
  if (!user_supplied_pre_statements.empty()
1599
2007
      && !stat(user_supplied_pre_statements.c_str(), &sbuf))
1600
2008
  {
1601
2009
    int data_file;
1602
2010
    std::vector<char> tmp_string;
1603
2011
 
1604
 
    if (not S_ISREG(sbuf.st_mode))
 
2012
    if (!S_ISREG(sbuf.st_mode))
1605
2013
    {
1606
2014
      fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1607
 
              SLAP_NAME);
1608
 
      abort();
 
2015
              internal::my_progname);
 
2016
      exit(1);
1609
2017
    }
1610
2018
    if ((data_file= open(user_supplied_pre_statements.c_str(), O_RDWR)) == -1)
1611
2019
    {
1612
 
      fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
1613
 
      abort();
 
2020
      fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
 
2021
      exit(1);
1614
2022
    }
1615
2023
    if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1616
2024
    {
1617
2025
      fprintf(stderr, "Request for more memory than architecture supports\n");
1618
 
      abort();
 
2026
      exit(1);
1619
2027
    }
1620
2028
    tmp_string.resize((size_t)(sbuf.st_size + 1));
1621
2029
    bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
1625
2033
    {
1626
2034
      fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1627
2035
    }
1628
 
    if (not user_supplied_pre_statements.empty())
 
2036
    if (!user_supplied_pre_statements.empty())
1629
2037
      (void)parse_delimiter(&tmp_string[0], &pre_statements,
1630
2038
                            delimiter[0]);
1631
2039
  }
1632
 
  else if (not user_supplied_pre_statements.empty())
 
2040
  else if (!user_supplied_pre_statements.empty())
1633
2041
  {
1634
2042
    (void)parse_delimiter(user_supplied_pre_statements.c_str(),
1635
2043
                          &pre_statements,
1636
2044
                          delimiter[0]);
1637
2045
  }
1638
2046
 
1639
 
  if (not user_supplied_post_statements.empty()
 
2047
  if (!user_supplied_post_statements.empty()
1640
2048
      && !stat(user_supplied_post_statements.c_str(), &sbuf))
1641
2049
  {
1642
2050
    int data_file;
1643
2051
    std::vector<char> tmp_string;
1644
2052
 
1645
 
    if (not S_ISREG(sbuf.st_mode))
 
2053
    if (!S_ISREG(sbuf.st_mode))
1646
2054
    {
1647
2055
      fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1648
 
              SLAP_NAME);
1649
 
      abort();
 
2056
              internal::my_progname);
 
2057
      exit(1);
1650
2058
    }
1651
2059
    if ((data_file= open(user_supplied_post_statements.c_str(), O_RDWR)) == -1)
1652
2060
    {
1653
 
      fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
1654
 
      abort();
 
2061
      fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
 
2062
      exit(1);
1655
2063
    }
1656
2064
 
1657
2065
    if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1658
2066
    {
1659
2067
      fprintf(stderr, "Request for more memory than architecture supports\n");
1660
 
      abort();
 
2068
      exit(1);
1661
2069
    }
1662
2070
    tmp_string.resize((size_t)(sbuf.st_size + 1));
1663
2071
 
1668
2076
    {
1669
2077
      fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1670
2078
    }
1671
 
    if (not user_supplied_post_statements.empty())
 
2079
    if (!user_supplied_post_statements.empty())
1672
2080
      (void)parse_delimiter(&tmp_string[0], &post_statements,
1673
2081
                            delimiter[0]);
1674
2082
  }
1675
 
  else if (not user_supplied_post_statements.empty())
 
2083
  else if (!user_supplied_post_statements.empty())
1676
2084
  {
1677
2085
    (void)parse_delimiter(user_supplied_post_statements.c_str(), &post_statements,
1678
2086
                          delimiter[0]);
1681
2089
  if (verbose >= 2)
1682
2090
    printf("Parsing engines to use.\n");
1683
2091
 
1684
 
  if (not default_engine.empty())
 
2092
  if (!default_engine.empty())
1685
2093
    parse_option(default_engine.c_str(), &engine_options, ',');
1686
2094
 
1687
2095
  if (tty_password)
1690
2098
}
1691
2099
 
1692
2100
 
1693
 
static int run_query(drizzle_con_st &con, drizzle_result_st *result,
 
2101
static int run_query(drizzle_con_st *con, drizzle_result_st *result,
1694
2102
                     const char *query, int len)
1695
2103
{
1696
2104
  drizzle_return_t ret;
1698
2106
 
1699
2107
  if (opt_only_print)
1700
2108
  {
1701
 
    printf("/* CON: %" PRIu64 " */ %.*s;\n",
1702
 
           (uint64_t)drizzle_context(drizzle_con_drizzle(&con)),
1703
 
           len, query);
 
2109
    printf("%.*s;\n", len, query);
1704
2110
    return 0;
1705
2111
  }
1706
2112
 
1710
2116
  if (result == NULL)
1711
2117
    result= &result_buffer;
1712
2118
 
1713
 
  result= drizzle_query(&con, result, query, len, &ret);
 
2119
  result= drizzle_query(con, result, query, len, &ret);
1714
2120
 
1715
2121
  if (ret == DRIZZLE_RETURN_OK)
1716
2122
    ret= drizzle_result_buffer(result);
1723
2129
 
1724
2130
 
1725
2131
static int
1726
 
generate_primary_key_list(drizzle_con_st &con, OptionString *engine_stmt)
 
2132
generate_primary_key_list(drizzle_con_st *con, OptionString *engine_stmt)
1727
2133
{
1728
2134
  drizzle_result_st result;
1729
2135
  drizzle_row_t row;
1744
2150
  {
1745
2151
    if (run_query(con, &result, "SELECT id from t1", strlen("SELECT id from t1")))
1746
2152
    {
1747
 
      fprintf(stderr,"%s: Cannot select GUID primary keys. (%s)\n", SLAP_NAME,
1748
 
              drizzle_con_error(&con));
1749
 
      abort();
 
2153
      fprintf(stderr,"%s: Cannot select GUID primary keys. (%s)\n", internal::my_progname,
 
2154
              drizzle_con_error(con));
 
2155
      exit(1);
1750
2156
    }
1751
2157
 
1752
2158
    uint64_t num_rows_ret= drizzle_result_row_count(&result);
1753
2159
    if (num_rows_ret > SIZE_MAX)
1754
2160
    {
1755
2161
      fprintf(stderr, "More primary keys than than architecture supports\n");
1756
 
      abort();
 
2162
      exit(1);
1757
2163
    }
1758
2164
    size_t primary_keys_number_of;
1759
2165
    primary_keys_number_of= (size_t)num_rows_ret;
1778
2184
  return(0);
1779
2185
}
1780
2186
 
1781
 
static void create_schema(drizzle_con_st &con, const char *db, Statement *stmt, OptionString *engine_stmt, Stats *sptr)
 
2187
static int
 
2188
create_schema(drizzle_con_st *con, const char *db, Statement *stmt,
 
2189
              OptionString *engine_stmt, Stats *sptr)
1782
2190
{
1783
2191
  char query[HUGE_STRING_LENGTH];
1784
2192
  Statement *ptr;
1785
2193
  Statement *after_create;
1786
2194
  int len;
 
2195
  uint64_t count;
1787
2196
  struct timeval start_time, end_time;
1788
2197
 
1789
2198
 
1796
2205
 
1797
2206
  if (run_query(con, NULL, query, len))
1798
2207
  {
1799
 
    fprintf(stderr,"%s: Cannot create schema %s : %s\n", SLAP_NAME, db,
1800
 
            drizzle_con_error(&con));
1801
 
    abort();
 
2208
    fprintf(stderr,"%s: Cannot create schema %s : %s\n", internal::my_progname, db,
 
2209
            drizzle_con_error(con));
 
2210
    exit(1);
1802
2211
  }
1803
2212
  else
1804
2213
  {
1807
2216
 
1808
2217
  if (opt_only_print)
1809
2218
  {
1810
 
    printf("/* CON: %" PRIu64 " */ use %s;\n",
1811
 
           (uint64_t)drizzle_context(drizzle_con_drizzle(&con)),
1812
 
           db);
 
2219
    printf("use %s;\n", db);
1813
2220
  }
1814
2221
  else
1815
2222
  {
1819
2226
    if (verbose >= 3)
1820
2227
      printf("%s;\n", query);
1821
2228
 
1822
 
    if (drizzle_select_db(&con,  &result, db, &ret) == NULL ||
 
2229
    if (drizzle_select_db(con,  &result, db, &ret) == NULL ||
1823
2230
        ret != DRIZZLE_RETURN_OK)
1824
2231
    {
1825
 
      fprintf(stderr,"%s: Cannot select schema '%s': %s\n",SLAP_NAME, db,
 
2232
      fprintf(stderr,"%s: Cannot select schema '%s': %s\n",internal::my_progname, db,
1826
2233
              ret == DRIZZLE_RETURN_ERROR_CODE ?
1827
 
              drizzle_result_error(&result) : drizzle_con_error(&con));
1828
 
      abort();
 
2234
              drizzle_result_error(&result) : drizzle_con_error(con));
 
2235
      exit(1);
1829
2236
    }
1830
2237
    drizzle_result_free(&result);
1831
2238
    sptr->setCreateCount(sptr->getCreateCount()+1);
1837
2244
                  engine_stmt->getString());
1838
2245
    if (run_query(con, NULL, query, len))
1839
2246
    {
1840
 
      fprintf(stderr,"%s: Cannot set default engine: %s\n", SLAP_NAME,
1841
 
              drizzle_con_error(&con));
1842
 
      abort();
 
2247
      fprintf(stderr,"%s: Cannot set default engine: %s\n", internal::my_progname,
 
2248
              drizzle_con_error(con));
 
2249
      exit(1);
1843
2250
    }
1844
2251
    sptr->setCreateCount(sptr->getCreateCount()+1);
1845
2252
  }
1846
2253
 
1847
 
  uint64_t count= 0;
 
2254
  count= 0;
1848
2255
  after_create= stmt;
1849
2256
 
1850
2257
limit_not_met:
1862
2269
      if (run_query(con, NULL, buffer, strlen(buffer)))
1863
2270
      {
1864
2271
        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();
 
2272
                internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
 
2273
        if (!opt_ignore_sql_errors)
 
2274
          exit(1);
1868
2275
      }
1869
2276
      sptr->setCreateCount(sptr->getCreateCount()+1);
1870
2277
    }
1873
2280
      if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
1874
2281
      {
1875
2282
        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();
 
2283
                internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
 
2284
        if (!opt_ignore_sql_errors)
 
2285
          exit(1);
1879
2286
      }
1880
2287
      sptr->setCreateCount(sptr->getCreateCount()+1);
1881
2288
    }
1891
2298
  gettimeofday(&end_time, NULL);
1892
2299
 
1893
2300
  sptr->setCreateTiming(timedif(end_time, start_time));
 
2301
 
 
2302
  return(0);
1894
2303
}
1895
2304
 
1896
 
static void drop_schema(drizzle_con_st &con, const char *db)
 
2305
static int
 
2306
drop_schema(drizzle_con_st *con, const char *db)
1897
2307
{
1898
2308
  char query[HUGE_STRING_LENGTH];
1899
2309
  int len;
1903
2313
  if (run_query(con, NULL, query, len))
1904
2314
  {
1905
2315
    fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
1906
 
            SLAP_NAME, db, drizzle_con_error(&con));
1907
 
    abort();
 
2316
            internal::my_progname, db, drizzle_con_error(con));
 
2317
    exit(1);
1908
2318
  }
 
2319
 
 
2320
 
 
2321
 
 
2322
  return(0);
1909
2323
}
1910
2324
 
1911
 
static void run_statements(drizzle_con_st &con, Statement *stmt)
 
2325
static int
 
2326
run_statements(drizzle_con_st *con, Statement *stmt)
1912
2327
{
1913
 
  for (Statement *ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
 
2328
  Statement *ptr;
 
2329
 
 
2330
  for (ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
1914
2331
  {
1915
2332
    if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
1916
2333
    {
1917
2334
      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();
 
2335
              internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
 
2336
      exit(1);
1920
2337
    }
1921
2338
  }
 
2339
 
 
2340
  return(0);
1922
2341
}
1923
2342
 
1924
 
 
1925
 
static void timer_thread()
 
2343
static int
 
2344
run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit)
1926
2345
{
 
2346
  uint32_t y;
 
2347
  unsigned int real_concurrency;
 
2348
  struct timeval start_time, end_time;
 
2349
  OptionString *sql_type;
 
2350
  pthread_t mainthread;            /* Thread descriptor */
 
2351
  pthread_attr_t attr;          /* Thread attributes */
 
2352
 
 
2353
 
 
2354
  pthread_attr_init(&attr);
 
2355
  pthread_attr_setdetachstate(&attr,
 
2356
                              PTHREAD_CREATE_DETACHED);
 
2357
 
 
2358
  pthread_mutex_lock(&counter_mutex);
 
2359
  thread_counter= 0;
 
2360
 
 
2361
  pthread_mutex_lock(&sleeper_mutex);
 
2362
  master_wakeup= 1;
 
2363
  pthread_mutex_unlock(&sleeper_mutex);
 
2364
 
 
2365
  real_concurrency= 0;
 
2366
 
 
2367
  for (y= 0, sql_type= query_options;
 
2368
       y < query_statements_count;
 
2369
       y++, sql_type= sql_type->getNext())
 
2370
  {
 
2371
    unsigned int options_loop= 1;
 
2372
 
 
2373
    if (sql_type->getOption())
 
2374
    {
 
2375
      options_loop= strtol(sql_type->getOption(),
 
2376
                           (char **)NULL, 10);
 
2377
      options_loop= options_loop ? options_loop : 1;
 
2378
    }
 
2379
 
 
2380
    while (options_loop--)
 
2381
    {
 
2382
      for (uint32_t x= 0; x < concur; x++)
 
2383
      {
 
2384
        ThreadContext *con;
 
2385
        con= new ThreadContext;
 
2386
        if (con == NULL)
 
2387
        {
 
2388
          fprintf(stderr, "Memory Allocation error in scheduler\n");
 
2389
          exit(1);
 
2390
        }
 
2391
        con->setStmt(stmts[y]);
 
2392
        con->setLimit(limit);
 
2393
 
 
2394
        real_concurrency++;
 
2395
        /* now you create the thread */
 
2396
        if (pthread_create(&mainthread, &attr, run_task,
 
2397
                           (void *)con) != 0)
 
2398
        {
 
2399
          fprintf(stderr,"%s: Could not create thread\n", internal::my_progname);
 
2400
          exit(1);
 
2401
        }
 
2402
        thread_counter++;
 
2403
      }
 
2404
    }
 
2405
  }
 
2406
 
1927
2407
  /*
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.
 
2408
    The timer_thread belongs to all threads so it too obeys the wakeup
 
2409
    call that run tasks obey.
1930
2410
  */
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();
 
2411
  if (opt_timer_length)
 
2412
  {
 
2413
    pthread_mutex_lock(&timer_alarm_mutex);
 
2414
    timer_alarm= true;
 
2415
    pthread_mutex_unlock(&timer_alarm_mutex);
 
2416
 
 
2417
    if (pthread_create(&mainthread, &attr, timer_thread,
 
2418
                       (void *)&opt_timer_length) != 0)
 
2419
    {
 
2420
      fprintf(stderr,"%s: Could not create timer thread\n", internal::my_progname);
 
2421
      exit(1);
 
2422
    }
 
2423
  }
 
2424
 
 
2425
  pthread_mutex_unlock(&counter_mutex);
 
2426
  pthread_attr_destroy(&attr);
 
2427
 
 
2428
  pthread_mutex_lock(&sleeper_mutex);
 
2429
  master_wakeup= 0;
 
2430
  pthread_mutex_unlock(&sleeper_mutex);
 
2431
  pthread_cond_broadcast(&sleep_threshhold);
2022
2432
 
2023
2433
  gettimeofday(&start_time, NULL);
2024
2434
 
2025
2435
  /*
2026
2436
    We loop until we know that all children have cleaned up.
2027
2437
  */
2028
 
  for (Threads::iterator iter= threads.begin(); iter != threads.end(); iter++)
 
2438
  pthread_mutex_lock(&counter_mutex);
 
2439
  while (thread_counter)
2029
2440
  {
2030
 
    (*iter)->join();
 
2441
    struct timespec abstime;
 
2442
 
 
2443
    set_timespec(abstime, 3);
 
2444
    pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
2031
2445
  }
 
2446
  pthread_mutex_unlock(&counter_mutex);
2032
2447
 
2033
2448
  gettimeofday(&end_time, NULL);
2034
2449
 
 
2450
 
2035
2451
  sptr->setTiming(timedif(end_time, start_time));
2036
2452
  sptr->setUsers(concur);
2037
2453
  sptr->setRealUsers(real_concurrency);
2038
2454
  sptr->setRows(limit);
 
2455
 
 
2456
  return(0);
 
2457
}
 
2458
 
 
2459
 
 
2460
pthread_handler_t timer_thread(void *p)
 
2461
{
 
2462
  uint32_t *timer_length= (uint32_t *)p;
 
2463
  struct timespec abstime;
 
2464
 
 
2465
 
 
2466
  /*
 
2467
    We lock around the initial call in case were we in a loop. This
 
2468
    also keeps the value properly syncronized across call threads.
 
2469
  */
 
2470
  pthread_mutex_lock(&sleeper_mutex);
 
2471
  while (master_wakeup)
 
2472
  {
 
2473
    pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
 
2474
  }
 
2475
  pthread_mutex_unlock(&sleeper_mutex);
 
2476
 
 
2477
  set_timespec(abstime, *timer_length);
 
2478
 
 
2479
  pthread_mutex_lock(&timer_alarm_mutex);
 
2480
  pthread_cond_timedwait(&timer_alarm_threshold, &timer_alarm_mutex, &abstime);
 
2481
  pthread_mutex_unlock(&timer_alarm_mutex);
 
2482
 
 
2483
  pthread_mutex_lock(&timer_alarm_mutex);
 
2484
  timer_alarm= false;
 
2485
  pthread_mutex_unlock(&timer_alarm_mutex);
 
2486
 
 
2487
  return(0);
 
2488
}
 
2489
 
 
2490
pthread_handler_t run_task(void *p)
 
2491
{
 
2492
  uint64_t counter= 0, queries;
 
2493
  uint64_t detach_counter;
 
2494
  unsigned int commit_counter;
 
2495
  drizzle_con_st con;
 
2496
  drizzle_result_st result;
 
2497
  drizzle_row_t row;
 
2498
  Statement *ptr;
 
2499
  ThreadContext *ctx= (ThreadContext *)p;
 
2500
 
 
2501
  pthread_mutex_lock(&sleeper_mutex);
 
2502
  while (master_wakeup)
 
2503
  {
 
2504
    pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
 
2505
  }
 
2506
  pthread_mutex_unlock(&sleeper_mutex);
 
2507
 
 
2508
  slap_connect(&con, true);
 
2509
 
 
2510
  if (verbose >= 3)
 
2511
    printf("connected!\n");
 
2512
  queries= 0;
 
2513
 
 
2514
  commit_counter= 0;
 
2515
  if (commit_rate)
 
2516
    run_query(&con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
 
2517
 
 
2518
limit_not_met:
 
2519
  for (ptr= ctx->getStmt(), detach_counter= 0;
 
2520
       ptr && ptr->getLength();
 
2521
       ptr= ptr->getNext(), detach_counter++)
 
2522
  {
 
2523
    if (!opt_only_print && detach_rate && !(detach_counter % detach_rate))
 
2524
    {
 
2525
      slap_close(&con);
 
2526
      slap_connect(&con, true);
 
2527
    }
 
2528
 
 
2529
    /*
 
2530
      We have to execute differently based on query type. This should become a function.
 
2531
    */
 
2532
    if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
 
2533
        (ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
 
2534
    {
 
2535
      int length;
 
2536
      unsigned int key_val;
 
2537
      char buffer[HUGE_STRING_LENGTH];
 
2538
 
 
2539
      /*
 
2540
        This should only happen if some sort of new engine was
 
2541
        implemented that didn't properly handle UPDATEs.
 
2542
 
 
2543
        Just in case someone runs this under an experimental engine we don't
 
2544
        want a crash so the if() is placed here.
 
2545
      */
 
2546
      assert(primary_keys.size());
 
2547
      if (primary_keys.size())
 
2548
      {
 
2549
        key_val= (unsigned int)(random() % primary_keys.size());
 
2550
        const char *key;
 
2551
        key= primary_keys[key_val].c_str();
 
2552
 
 
2553
        assert(key);
 
2554
 
 
2555
        length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
 
2556
                         (int)ptr->getLength(), ptr->getString(), key);
 
2557
 
 
2558
        if (run_query(&con, &result, buffer, length))
 
2559
        {
 
2560
          fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
 
2561
                  internal::my_progname, (uint32_t)length, buffer, drizzle_con_error(&con));
 
2562
          exit(1);
 
2563
        }
 
2564
      }
 
2565
    }
 
2566
    else
 
2567
    {
 
2568
      if (run_query(&con, &result, ptr->getString(), ptr->getLength()))
 
2569
      {
 
2570
        fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
 
2571
                internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
 
2572
        exit(1);
 
2573
      }
 
2574
    }
 
2575
 
 
2576
    if (!opt_only_print)
 
2577
    {
 
2578
      while ((row = drizzle_row_next(&result)))
 
2579
        counter++;
 
2580
      drizzle_result_free(&result);
 
2581
    }
 
2582
    queries++;
 
2583
 
 
2584
    if (commit_rate && (++commit_counter == commit_rate))
 
2585
    {
 
2586
      commit_counter= 0;
 
2587
      run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
 
2588
    }
 
2589
 
 
2590
    /* If the timer is set, and the alarm is not active then end */
 
2591
    if (opt_timer_length && timer_alarm == false)
 
2592
      goto end;
 
2593
 
 
2594
    /* If limit has been reached, and we are not in a timer_alarm just end */
 
2595
    if (ctx->getLimit() && queries == ctx->getLimit() && timer_alarm == false)
 
2596
      goto end;
 
2597
  }
 
2598
 
 
2599
  if (opt_timer_length && timer_alarm == true)
 
2600
    goto limit_not_met;
 
2601
 
 
2602
  if (ctx->getLimit() && queries < ctx->getLimit())
 
2603
    goto limit_not_met;
 
2604
 
 
2605
 
 
2606
end:
 
2607
  if (commit_rate)
 
2608
    run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
 
2609
 
 
2610
  slap_close(&con);
 
2611
 
 
2612
  pthread_mutex_lock(&counter_mutex);
 
2613
  thread_counter--;
 
2614
  pthread_cond_signal(&count_threshhold);
 
2615
  pthread_mutex_unlock(&counter_mutex);
 
2616
 
 
2617
  delete ctx;
 
2618
 
 
2619
  return(0);
2039
2620
}
2040
2621
 
2041
2622
/*
2042
2623
  Parse records from comma seperated string. : is a reserved character and is used for options
2043
2624
  on variables.
2044
2625
*/
2045
 
uint32_t parse_option(const char *origin, OptionString **stmt, char delm)
 
2626
uint
 
2627
parse_option(const char *origin, OptionString **stmt, char delm)
2046
2628
{
2047
2629
  char *string;
2048
2630
  char *begin_ptr;
2092
2674
    if (tmp->getString() == NULL)
2093
2675
    {
2094
2676
      fprintf(stderr,"Error allocating memory while parsing options\n");
2095
 
      abort();
 
2677
      exit(1);
2096
2678
    }
2097
2679
 
2098
2680
    if (isspace(*begin_ptr))
2115
2697
  Raw parsing interface. If you want the slap specific parser look at
2116
2698
  parse_option.
2117
2699
*/
2118
 
uint32_t parse_delimiter(const char *script, Statement **stmt, char delm)
 
2700
uint
 
2701
parse_delimiter(const char *script, Statement **stmt, char delm)
2119
2702
{
2120
2703
  char *retstr;
2121
2704
  char *ptr= (char *)script;
2132
2715
    if (tmp == NULL)
2133
2716
    {
2134
2717
      fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2135
 
      abort();
 
2718
      exit(1);
2136
2719
    }
2137
2720
 
2138
2721
    count++;
2141
2724
    if (tmp->getString() == NULL)
2142
2725
    {
2143
2726
      fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2144
 
      abort();
 
2727
      exit(1);
2145
2728
    }
2146
2729
 
2147
2730
    memcpy(tmp->getString(), ptr, tmp->getLength());
2156
2739
    if (tmp->getString() == NULL)
2157
2740
    {
2158
2741
      fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2159
 
      abort();
 
2742
      exit(1);
2160
2743
    }
2161
2744
    memcpy(tmp->getString(), ptr, tmp->getLength());
2162
2745
    count++;
2171
2754
  number ranges from a comma seperated string.
2172
2755
  In restrospect, this is a lousy name from this function.
2173
2756
*/
2174
 
uint32_t parse_comma(const char *string, std::vector <uint32_t> &range)
 
2757
uint
 
2758
parse_comma(const char *string, std::vector <uint32_t> &range)
2175
2759
{
2176
 
  uint32_t count= 1; /* We know that there is always one */
 
2760
  unsigned int count= 1,x; /* We know that there is always one */
2177
2761
  char *retstr;
2178
2762
  char *ptr= (char *)string;
2179
 
  uint32_t *nptr;
 
2763
  unsigned int *nptr;
2180
2764
 
2181
2765
  for (;*ptr; ptr++)
2182
2766
    if (*ptr == ',') count++;
2186
2770
  nptr= &range[0];
2187
2771
 
2188
2772
  ptr= (char *)string;
2189
 
  uint32_t x= 0;
 
2773
  x= 0;
2190
2774
  while ((retstr= strchr(ptr,',')))
2191
2775
  {
2192
2776
    nptr[x++]= atoi(ptr);
2197
2781
  return count;
2198
2782
}
2199
2783
 
2200
 
void print_conclusions(Conclusions &con)
 
2784
void
 
2785
print_conclusions(Conclusions *con)
2201
2786
{
2202
2787
  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())
 
2788
  if (con->getEngine())
 
2789
    printf("\tRunning for engine %s\n", con->getEngine());
 
2790
  if (!opt_label.empty() || !opt_auto_generate_sql_type.empty())
2207
2791
  {
2208
2792
    const char *ptr= opt_auto_generate_sql_type.c_str() ? opt_auto_generate_sql_type.c_str() : "query";
2209
2793
    printf("\tLoad: %s\n", !opt_label.empty() ? opt_label.c_str() : ptr);
2210
2794
  }
2211
2795
  printf("\tAverage Time took to generate schema and initial data: %ld.%03ld seconds\n",
2212
 
         con.getCreateAvgTiming() / 1000, con.getCreateAvgTiming() % 1000);
 
2796
         con->getCreateAvgTiming() / 1000, con->getCreateAvgTiming() % 1000);
2213
2797
  printf("\tAverage number of seconds to run all queries: %ld.%03ld seconds\n",
2214
 
         con.getAvgTiming() / 1000, con.getAvgTiming() % 1000);
 
2798
         con->getAvgTiming() / 1000, con->getAvgTiming() % 1000);
2215
2799
  printf("\tMinimum number of seconds to run all queries: %ld.%03ld seconds\n",
2216
 
         con.getMinTiming() / 1000, con.getMinTiming() % 1000);
 
2800
         con->getMinTiming() / 1000, con->getMinTiming() % 1000);
2217
2801
  printf("\tMaximum number of seconds to run all queries: %ld.%03ld seconds\n",
2218
 
         con.getMaxTiming() / 1000, con.getMaxTiming() % 1000);
 
2802
         con->getMaxTiming() / 1000, con->getMaxTiming() % 1000);
2219
2803
  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());
 
2804
         con->getSumOfTime() / 1000, con->getSumOfTime() % 1000);
 
2805
  printf("\tStandard Deviation: %ld.%03ld\n", con->getStdDev() / 1000, con->getStdDev() % 1000);
 
2806
  printf("\tNumber of queries in create queries: %"PRIu64"\n", con->getCreateCount());
2223
2807
  printf("\tNumber of clients running queries: %u/%u\n",
2224
 
         con.getUsers(), con.getRealUsers());
 
2808
         con->getUsers(), con->getRealUsers());
2225
2809
  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
 
 
 
2810
  printf("\tAverage number of queries per client: %"PRIu64"\n", con->getAvgRows());
2232
2811
  printf("\n");
2233
2812
}
2234
2813
 
2235
 
void print_conclusions_csv(Conclusions &con)
 
2814
void
 
2815
print_conclusions_csv(Conclusions *con)
2236
2816
{
 
2817
  unsigned int x;
2237
2818
  char buffer[HUGE_STRING_LENGTH];
2238
2819
  char label_buffer[HUGE_STRING_LENGTH];
2239
2820
  size_t string_len;
2241
2822
 
2242
2823
  memset(label_buffer, 0, sizeof(label_buffer));
2243
2824
 
2244
 
  if (not opt_label.empty())
 
2825
  if (!opt_label.empty())
2245
2826
  {
2246
2827
    string_len= opt_label.length();
2247
2828
 
2248
 
    for (uint32_t x= 0; x < string_len; x++)
 
2829
    for (x= 0; x < string_len; x++)
2249
2830
    {
2250
2831
      if (temp_label[x] == ',')
2251
2832
        label_buffer[x]= '-';
2253
2834
        label_buffer[x]= temp_label[x] ;
2254
2835
    }
2255
2836
  }
2256
 
  else if (not opt_auto_generate_sql_type.empty())
 
2837
  else if (!opt_auto_generate_sql_type.empty())
2257
2838
  {
2258
2839
    string_len= opt_auto_generate_sql_type.length();
2259
2840
 
2260
 
    for (uint32_t x= 0; x < string_len; x++)
 
2841
    for (x= 0; x < string_len; x++)
2261
2842
    {
2262
2843
      if (opt_auto_generate_sql_type[x] == ',')
2263
2844
        label_buffer[x]= '-';
2273
2854
  snprintf(buffer, HUGE_STRING_LENGTH,
2274
2855
           "%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,"
2275
2856
           "%u,%u,%u,%"PRIu64"\n",
2276
 
           con.getEngine() ? con.getEngine() : "", /* Storage engine we ran against */
 
2857
           con->getEngine() ? con->getEngine() : "", /* Storage engine we ran against */
2277
2858
           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 */
 
2859
           con->getAvgTiming() / 1000, con->getAvgTiming() % 1000, /* Time to load */
 
2860
           con->getMinTiming() / 1000, con->getMinTiming() % 1000, /* Min time */
 
2861
           con->getMaxTiming() / 1000, con->getMaxTiming() % 1000, /* Max time */
 
2862
           con->getSumOfTime() / 1000, con->getSumOfTime() % 1000, /* Total time */
 
2863
           con->getStdDev() / 1000, con->getStdDev() % 1000, /* Standard Deviation */
2283
2864
           iterations, /* Iterations */
2284
 
           con.getUsers(), /* Children used max_timing */
2285
 
           con.getRealUsers(), /* Children used max_timing */
2286
 
           con.getAvgRows()  /* Queries run */
 
2865
           con->getUsers(), /* Children used max_timing */
 
2866
           con->getRealUsers(), /* Children used max_timing */
 
2867
           con->getAvgRows()  /* Queries run */
2287
2868
           );
2288
2869
  size_t buff_len= strlen(buffer);
2289
2870
  ssize_t write_ret= write(csv_file, (unsigned char*) buffer, buff_len);
2296
2877
  }
2297
2878
}
2298
2879
 
2299
 
void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr)
 
2880
void
 
2881
generate_stats(Conclusions *con, OptionString *eng, Stats *sptr)
2300
2882
{
2301
2883
  Stats *ptr;
2302
 
  uint32_t x;
 
2884
  unsigned int x;
2303
2885
 
2304
2886
  con->setMinTiming(sptr->getTiming());
2305
2887
  con->setMaxTiming(sptr->getTiming());
2329
2911
  else
2330
2912
    con->setEngine(NULL);
2331
2913
 
2332
 
  standard_deviation(*con, sptr);
 
2914
  standard_deviation(con, sptr);
2333
2915
 
2334
2916
  /* Now we do the create time operations */
2335
2917
  con->setCreateMinTiming(sptr->getCreateTiming());
2365
2947
  }
2366
2948
}
2367
2949
 
2368
 
void statement_cleanup(Statement *stmt)
 
2950
void
 
2951
statement_cleanup(Statement *stmt)
2369
2952
{
2370
2953
  Statement *ptr, *nptr;
2371
 
  if (not stmt)
 
2954
  if (!stmt)
2372
2955
    return;
2373
2956
 
2374
2957
  for (ptr= stmt; ptr; ptr= nptr)
2378
2961
  }
2379
2962
}
2380
2963
 
2381
 
void slap_close(drizzle_con_st &con)
 
2964
void
 
2965
slap_close(drizzle_con_st *con)
2382
2966
{
2383
 
  drizzle_free(drizzle_con_drizzle(&con));
 
2967
  if (opt_only_print)
 
2968
    return;
 
2969
 
 
2970
  drizzle_free(drizzle_con_drizzle(con));
2384
2971
}
2385
2972
 
2386
 
void slap_connect(drizzle_con_st &con, bool connect_to_schema)
 
2973
void
 
2974
slap_connect(drizzle_con_st *con, bool connect_to_schema)
2387
2975
{
2388
2976
  /* Connect to server */
2389
2977
  static uint32_t connection_retry_sleep= 100000; /* Microseconds */
2391
2979
  drizzle_return_t ret;
2392
2980
  drizzle_st *drizzle;
2393
2981
 
 
2982
  if (opt_only_print)
 
2983
    return;
 
2984
 
2394
2985
  if (opt_delayed_start)
2395
2986
    usleep(random()%opt_delayed_start);
2396
2987
 
2397
2988
  if ((drizzle= drizzle_create(NULL)) == NULL ||
2398
 
      drizzle_con_add_tcp(drizzle, &con, host.c_str(), opt_drizzle_port,
 
2989
      drizzle_con_add_tcp(drizzle, con, host.c_str(), opt_drizzle_port,
2399
2990
        user.c_str(),
2400
2991
        opt_password.c_str(),
2401
2992
        connect_to_schema ? create_schema_string.c_str() : NULL,
2402
2993
        use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL) == NULL)
2403
2994
  {
2404
 
    fprintf(stderr,"%s: Error creating drizzle object\n", SLAP_NAME);
2405
 
    abort();
 
2995
    fprintf(stderr,"%s: Error creating drizzle object\n", internal::my_progname);
 
2996
    exit(1);
2406
2997
  }
2407
2998
 
2408
 
  drizzle_set_context(drizzle, (void*)(connection_count.fetch_and_increment()));
2409
 
 
2410
 
  if (opt_only_print)
2411
 
    return;
2412
 
 
2413
2999
  for (uint32_t x= 0; x < 10; x++)
2414
3000
  {
2415
 
    if ((ret= drizzle_con_connect(&con)) == DRIZZLE_RETURN_OK)
 
3001
    if ((ret= drizzle_con_connect(con)) == DRIZZLE_RETURN_OK)
2416
3002
    {
2417
3003
      /* Connect suceeded */
2418
3004
      connect_error= 0;
2422
3008
  }
2423
3009
  if (connect_error)
2424
3010
  {
2425
 
    fprintf(stderr,"%s: Error when connecting to server: %d %s\n", SLAP_NAME,
2426
 
            ret, drizzle_con_error(&con));
2427
 
    abort();
 
3011
    fprintf(stderr,"%s: Error when connecting to server: %d %s\n", internal::my_progname,
 
3012
            ret, drizzle_con_error(con));
 
3013
    exit(1);
2428
3014
  }
 
3015
 
 
3016
  return;
2429
3017
}
2430
3018
 
2431
 
void standard_deviation(Conclusions &con, Stats *sptr)
 
3019
void
 
3020
standard_deviation (Conclusions *con, Stats *sptr)
2432
3021
{
 
3022
  unsigned int x;
2433
3023
  long int sum_of_squares;
2434
3024
  double the_catch;
2435
3025
  Stats *ptr;
2436
3026
 
2437
3027
  if (iterations == 1 || iterations == 0)
2438
3028
  {
2439
 
    con.setStdDev(0);
 
3029
    con->setStdDev(0);
2440
3030
    return;
2441
3031
  }
2442
3032
 
2443
 
  uint32_t x;
2444
3033
  for (ptr= sptr, x= 0, sum_of_squares= 0; x < iterations; ptr++, x++)
2445
3034
  {
2446
3035
    long int deviation;
2447
3036
 
2448
 
    deviation= ptr->getTiming() - con.getAvgTiming();
 
3037
    deviation= ptr->getTiming() - con->getAvgTiming();
2449
3038
    sum_of_squares+= deviation*deviation;
2450
3039
  }
2451
3040
 
2452
3041
  the_catch= sqrt((double)(sum_of_squares/(iterations -1)));
2453
 
  con.setStdDev((long int)the_catch);
 
3042
  con->setStdDev((long int)the_catch);
2454
3043
}