~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleslap.cc

  • Committer: Brian Aker
  • Date: 2010-11-19 19:42:44 UTC
  • mto: (1945.2.1 quick)
  • mto: This revision was merged to the branch mainline in revision 1944.
  • Revision ID: brian@tangent.org-20101119194244-7vx6u5vwzvu9uvex
Remove dead getShare() call which should have been a call on the cache
directly.

Show diffs side-by-side

added added

removed removed

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