~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqlslap.c

  • Committer: Monty Taylor
  • Date: 2008-08-01 22:33:44 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080801223344-vzhlflfmtijp1imv
First pass at gettexizing the error messages.

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