~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqlslap.c

  • Committer: Monty Taylor
  • Date: 2008-07-15 21:40:58 UTC
  • mfrom: (77.1.113 codestyle32)
  • mto: This revision was merged to the branch mainline in revision 176.
  • Revision ID: mordred@camelot-20080715214058-rm3phulldos9xehv
Merged from codestyle.

Show diffs side-by-side

added added

removed removed

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