~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleslap.cc

  • Committer: Stewart Smith
  • Date: 2010-02-05 01:20:18 UTC
  • mto: (1286.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1287.
  • Revision ID: stewart@flamingspork.com-20100205012018-blvmeky20wze8eyg
initial TableProtoTester engine. We can't just use table_write as some protobuf library versions don't let us write invalid protobuf messages :(

Show diffs side-by-side

added added

removed removed

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