~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzleslap.cc

  • Committer: Monty Taylor
  • Date: 2008-10-14 21:20:42 UTC
  • mto: (511.1.4 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081014212042-tef3njx3368b6lwt
Override copy ctr and op= because we have pointer members.

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