~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleslap.cc

  • Committer: Stewart Smith
  • Date: 2009-10-19 03:27:43 UTC
  • mto: This revision was merged to the branch mainline in revision 1188.
  • Revision ID: stewart@flamingspork.com-20091019032743-xajbflq0ktpe9vw2
remove --disable-warnings in func_in_null_scan.test

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