97
#include <drizzled/configmake.h>
100
96
/* Added this for string translation. */
101
97
#include <drizzled/gettext.h>
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>
110
#define SLAP_NAME "drizzleslap"
111
#define SLAP_VERSION "1.5"
113
#define HUGE_STRING_LENGTH 8196
114
#define RAND_STRING_SIZE 126
115
#define DEFAULT_BLOB_SIZE 1024
117
99
using namespace std;
118
100
using namespace drizzled;
119
namespace po= boost::program_options;
122
103
static char *shared_memory_base_name=0;
125
client::Wakeup master_wakeup;
106
/* Global Thread counter */
107
uint32_t thread_counter;
108
pthread_mutex_t counter_mutex;
109
pthread_cond_t count_threshhold;
110
uint32_t master_wakeup;
111
pthread_mutex_t sleeper_mutex;
112
pthread_cond_t sleep_threshhold;
127
114
/* Global Thread timer */
128
115
static bool timer_alarm= false;
129
boost::mutex timer_alarm_mutex;
130
boost::condition_variable_any timer_alarm_threshold;
132
std::vector < std::string > primary_keys;
134
drizzled::atomic<size_t> connection_count;
135
drizzled::atomic<uint64_t> failed_update_for_transaction;
141
user_supplied_pre_statements,
142
user_supplied_post_statements,
147
static vector<string> user_supplied_queries;
148
static string opt_verbose;
149
std::string opt_protocol;
152
string create_schema_string;
154
static bool use_drizzle_protocol= false;
116
pthread_mutex_t timer_alarm_mutex;
117
pthread_cond_t timer_alarm_threshold;
119
static char **defaults_argv;
122
/* This gets passed to malloc, so lets set it to an arch-dependant size */
123
size_t primary_keys_number_of;
125
static char *host= NULL, *opt_password= NULL, *user= NULL,
126
*user_supplied_query= NULL,
127
*user_supplied_pre_statements= NULL,
128
*user_supplied_post_statements= NULL,
129
*default_engine= NULL,
133
const char *delimiter= "\n";
135
const char *create_schema_string= "drizzleslap";
137
static bool opt_mysql= false;
155
138
static bool opt_preserve= true;
156
static bool opt_only_print;
157
static bool opt_burnin;
139
static bool opt_only_print= false;
140
static bool opt_burnin= false;
158
141
static bool opt_ignore_sql_errors= false;
159
static bool opt_silent,
160
auto_generate_sql_autoincrement,
161
auto_generate_sql_guid_primary,
163
std::string opt_auto_generate_sql_type;
142
static bool tty_password= false,
144
auto_generate_sql_autoincrement= false,
145
auto_generate_sql_guid_primary= false,
146
auto_generate_sql= false;
147
const char *opt_auto_generate_sql_type= "mixed";
165
static int32_t verbose= 0;
166
static uint32_t delimiter_length;
149
static int verbose, delimiter_length;
167
150
static uint32_t commit_rate;
168
151
static uint32_t detach_rate;
169
152
static uint32_t opt_timer_length;
170
153
static uint32_t opt_delayed_start;
171
string num_blob_cols_opt,
175
static uint32_t opt_set_random_seed;
154
const char *num_int_cols_opt;
155
const char *num_char_cols_opt;
156
const char *num_blob_cols_opt;
157
const char *opt_label;
158
static unsigned int opt_set_random_seed;
177
string auto_generate_selected_columns_opt;
160
const char *auto_generate_selected_columns_opt;
179
162
/* 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;
163
static unsigned int num_int_cols= 1;
164
static unsigned int num_char_cols= 1;
165
static unsigned int num_blob_cols= 0;
166
static unsigned int num_blob_cols_size;
167
static unsigned int num_blob_cols_size_min;
168
static unsigned int num_int_cols_index= 0;
169
static unsigned int num_char_cols_index= 0;
170
static unsigned int iterations;
188
171
static uint64_t actual_queries= 0;
189
172
static uint64_t auto_actual_queries;
190
173
static uint64_t auto_generate_sql_unique_write_number;
191
174
static uint64_t auto_generate_sql_unique_query_number;
192
static uint32_t auto_generate_sql_secondary_indexes;
175
static unsigned int auto_generate_sql_secondary_indexes;
193
176
static uint64_t num_of_query;
194
177
static uint64_t auto_generate_sql_number;
195
string concurrency_str;
196
string create_string;
197
std::vector <uint32_t> concurrency;
178
const char *concurrency_str= NULL;
179
static char *create_string;
180
uint32_t *concurrency;
199
std::string opt_csv_str;
182
const char *default_dbug_option= "d:t:o,/tmp/drizzleslap.trace";
183
const char *opt_csv_str;
202
static int process_options(void);
186
static int get_options(int *argc,char ***argv);
203
187
static uint32_t opt_drizzle_port= 0;
189
static const char *load_default_groups[]= { "drizzleslap","client",0 };
196
UPDATE_TYPE_REQUIRES_PREFIX= 3,
197
CREATE_TABLE_TYPE= 4,
198
SELECT_TYPE_REQUIRES_PREFIX= 5,
199
DELETE_TYPE_REQUIRES_PREFIX= 6
207
Statement(char *in_string,
209
slap_query_type in_type,
211
size_t in_option_length,
218
option_length(in_option_length),
232
char *getString() const
237
size_t getLength() const
242
slap_query_type getType() const
247
char *getOption() const
252
size_t getOptionLength() const
254
return option_length;
257
Statement *getNext() const
262
void setString(char *in_string)
267
void setString(size_t in_length, char in_char)
269
string[in_length]= in_char;
272
void setLength(size_t in_length)
277
void setType(slap_query_type in_type)
282
void setOption(char *in_option)
287
void setOptionLength(size_t in_option_length)
289
option_length= in_option_length;
292
void setNext(Statement *in_next)
300
slap_query_type type;
302
size_t option_length;
311
OptionString(char *in_string,
314
size_t in_option_length,
315
OptionString *in_next)
320
option_length(in_option_length),
333
char *getString() const
338
size_t getLength() const
343
char *getOption() const
348
size_t getOptionLength() const
350
return option_length;
353
OptionString *getNext() const
358
void setString(char *in_string)
363
void setOptionLength(size_t in_option_length)
365
option_length= in_option_length;
368
void setLength(size_t in_length)
373
void setOption(char *in_option)
378
void setOption(size_t in_option_length, char in_char)
380
option[in_option_length]= in_char;
383
void setNext(OptionString *in_next)
392
size_t option_length;
401
Stats(long int in_timing,
403
uint32_t in_real_users,
405
long int in_create_timing,
406
uint64_t in_create_count)
410
real_users(in_real_users),
412
create_timing(in_create_timing),
413
create_count(in_create_count)
426
long int getTiming() const
431
uint32_t getUsers() const
436
uint32_t getRealUsers() const
441
uint64_t getRows() const
446
long int getCreateTiming() const
448
return create_timing;
451
uint64_t getCreateCount() const
456
void setTiming(long int in_timing)
461
void setUsers(uint32_t in_users)
466
void setRealUsers(uint32_t in_real_users)
468
real_users= in_real_users;
471
void setRows(uint64_t in_rows)
476
void setCreateTiming(long int in_create_timing)
478
create_timing= in_create_timing;
481
void setCreateCount(uint64_t in_create_count)
483
create_count= in_create_count;
491
long int create_timing;
492
uint64_t create_count;
500
ThreadContext(Statement *in_stmt,
513
Statement *getStmt() const
518
uint64_t getLimit() const
523
void setStmt(Statement *in_stmt)
528
void setLimit(uint64_t in_limit)
544
Conclusions(char *in_engine,
545
long int in_avg_timing,
546
long int in_max_timing,
547
long int in_min_timing,
549
uint32_t in_real_users,
550
uint64_t in_avg_rows,
551
long int in_sum_of_time,
553
long int in_create_avg_timing,
554
long int in_create_max_timing,
555
long int in_create_min_timing,
556
uint64_t in_create_count,
557
uint64_t in_max_rows,
558
uint64_t in_min_rows)
561
avg_timing(in_avg_timing),
562
max_timing(in_max_timing),
563
min_timing(in_min_timing),
565
real_users(in_real_users),
566
avg_rows(in_avg_rows),
567
sum_of_time(in_sum_of_time),
569
create_avg_timing(in_create_avg_timing),
570
create_max_timing(in_create_max_timing),
571
create_min_timing(in_create_min_timing),
572
create_count(in_create_count),
573
max_rows(in_max_rows),
574
min_rows(in_min_rows)
588
create_avg_timing(0),
589
create_max_timing(0),
590
create_min_timing(0),
596
char *getEngine() const
601
long int getAvgTiming() const
606
long int getMaxTiming() const
611
long int getMinTiming() const
616
uint32_t getUsers() const
621
uint32_t getRealUsers() const
626
uint64_t getAvgRows() const
631
long int getSumOfTime() const
636
long int getStdDev() const
641
long int getCreateAvgTiming() const
643
return create_avg_timing;
646
long int getCreateMaxTiming() const
648
return create_max_timing;
651
long int getCreateMinTiming() const
653
return create_min_timing;
656
uint64_t getCreateCount() const
661
uint64_t getMinRows() const
666
uint64_t getMaxRows() const
671
void setEngine(char *in_engine)
676
void setAvgTiming(long int in_avg_timing)
678
avg_timing= in_avg_timing;
681
void setMaxTiming(long int in_max_timing)
683
max_timing= in_max_timing;
686
void setMinTiming(long int in_min_timing)
688
min_timing= in_min_timing;
691
void setUsers(uint32_t in_users)
696
void setRealUsers(uint32_t in_real_users)
698
real_users= in_real_users;
701
void setAvgRows(uint64_t in_avg_rows)
703
avg_rows= in_avg_rows;
706
void setSumOfTime(long int in_sum_of_time)
708
sum_of_time= in_sum_of_time;
711
void setStdDev(long int in_std_dev)
716
void setCreateAvgTiming(long int in_create_avg_timing)
718
create_avg_timing= in_create_avg_timing;
721
void setCreateMaxTiming(long int in_create_max_timing)
723
create_max_timing= in_create_max_timing;
726
void setCreateMinTiming(long int in_create_min_timing)
728
create_min_timing= in_create_min_timing;
731
void setCreateCount(uint64_t in_create_count)
733
create_count= in_create_count;
736
void setMinRows(uint64_t in_min_rows)
738
min_rows= in_min_rows;
741
void setMaxRows(uint64_t in_max_rows)
743
max_rows= in_max_rows;
754
long int sum_of_time;
756
/* These are just for create time stats */
757
long int create_avg_timing;
758
long int create_max_timing;
759
long int create_min_timing;
760
uint64_t create_count;
761
/* The following are not used yet */
205
767
static OptionString *engine_options= NULL;
206
768
static OptionString *query_options= NULL;
207
769
static Statement *pre_statements= NULL;
208
770
static Statement *post_statements= NULL;
209
771
static Statement *create_statements= NULL;
211
static std::vector <Statement *> query_statements;
212
static uint32_t query_statements_count;
773
static Statement **query_statements= NULL;
774
static unsigned int query_statements_count;
216
void print_conclusions(Conclusions &con);
217
void print_conclusions_csv(Conclusions &con);
778
void print_conclusions(Conclusions *con);
779
void print_conclusions_csv(Conclusions *con);
218
780
void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr);
219
uint32_t parse_comma(const char *string, std::vector <uint32_t> &range);
781
uint32_t parse_comma(const char *string, uint32_t **range);
220
782
uint32_t parse_delimiter(const char *script, Statement **stmt, char delm);
221
783
uint32_t parse_option(const char *origin, OptionString **stmt, char delm);
222
static void drop_schema(drizzle_con_st &con, const char *db);
784
static int drop_schema(drizzle_con_st *con, const char *db);
223
785
uint32_t get_random_string(char *buf, size_t size);
224
786
static Statement *build_table_string(void);
225
787
static Statement *build_insert_string(void);
226
788
static Statement *build_update_string(void);
227
789
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);
790
static int generate_primary_key_list(drizzle_con_st *con, OptionString *engine_stmt);
791
static int drop_primary_key_list(void);
792
static int create_schema(drizzle_con_st *con, const char *db, Statement *stmt,
793
OptionString *engine_stmt, Stats *sptr);
794
static int run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur,
796
extern "C" pthread_handler_t run_task(void *p);
797
extern "C" pthread_handler_t timer_thread(void *p);
231
798
void statement_cleanup(Statement *stmt);
232
799
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);
800
void concurrency_loop(drizzle_con_st *con, uint32_t current, OptionString *eptr);
801
static int run_statements(drizzle_con_st *con, Statement *stmt);
802
void slap_connect(drizzle_con_st *con, bool connect_to_schema);
803
void slap_close(drizzle_con_st *con);
804
static int run_query(drizzle_con_st *con, drizzle_result_st *result, const char *query, int len);
805
void standard_deviation (Conclusions *con, Stats *sptr);
240
807
static const char ALPHANUMERICS[]=
241
808
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
257
static void combine_queries(vector<string> queries)
259
user_supplied_query.erase();
260
for (vector<string>::iterator it= queries.begin();
264
user_supplied_query.append(*it);
265
user_supplied_query.append(delimiter);
270
static void run_task(ThreadContext *ctx)
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;
281
master_wakeup.wait();
283
slap_connect(con, true);
286
printf("connected!\n");
291
run_query(con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
294
for (ptr= ctx->getStmt(), detach_counter= 0;
295
ptr && ptr->getLength();
296
ptr= ptr->getNext(), detach_counter++)
298
if (not opt_only_print && detach_rate && !(detach_counter % detach_rate))
301
slap_connect(con, true);
305
We have to execute differently based on query type. This should become a function.
307
bool is_failed_update= false;
308
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
309
(ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
313
char buffer[HUGE_STRING_LENGTH];
316
This should only happen if some sort of new engine was
317
implemented that didn't properly handle UPDATEs.
319
Just in case someone runs this under an experimental engine we don't
320
want a crash so the if() is placed here.
322
assert(primary_keys.size());
323
if (primary_keys.size())
325
key_val= (uint32_t)(random() % primary_keys.size());
327
key= primary_keys[key_val].c_str();
331
length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
332
(int)ptr->getLength(), ptr->getString(), key);
334
if (run_query(con, &result, buffer, length))
336
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) and commit_rate)
338
// Expand to check to see if Innodb, if so we should restart the
341
is_failed_update= true;
342
failed_update_for_transaction.fetch_and_increment();
346
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
347
SLAP_NAME, (uint32_t)length, buffer, drizzle_con_error(&con));
355
if (run_query(con, &result, ptr->getString(), ptr->getLength()))
357
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) and commit_rate)
359
// Expand to check to see if Innodb, if so we should restart the
362
is_failed_update= true;
363
failed_update_for_transaction.fetch_and_increment();
367
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
368
SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
374
if (not opt_only_print and not is_failed_update)
376
while ((row = drizzle_row_next(&result)))
378
drizzle_result_free(&result);
382
if (commit_rate && (++commit_counter == commit_rate) and not is_failed_update)
385
run_query(con, NULL, "COMMIT", strlen("COMMIT"));
388
/* If the timer is set, and the alarm is not active then end */
389
if (opt_timer_length && timer_alarm == false)
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)
397
if (opt_timer_length && timer_alarm == true)
400
if (ctx->getLimit() && queries < ctx->getLimit())
406
run_query(con, NULL, "COMMIT", strlen("COMMIT"));
414
* commandline_options is the set of all options that can only be called via the command line.
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
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
422
* long_options is the union of commandline_options, slap_options and client_options.
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.
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.
431
824
int main(int argc, char **argv)
433
char *password= NULL;
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")
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")
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")
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")
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")
544
po::options_description long_options("Allowed Options");
545
long_options.add(commandline_options).add(slap_options).add(client_options);
547
std::string system_config_dir_slap(SYSCONFDIR);
548
system_config_dir_slap.append("/drizzle/drizzleslap.cnf");
550
std::string system_config_dir_client(SYSCONFDIR);
551
system_config_dir_client.append("/drizzle/client.cnf");
553
std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
555
if (user_config_dir.compare(0, 2, "~/") == 0)
558
homedir= getenv("HOME");
560
user_config_dir.replace(0, 1, homedir);
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();
568
// Disable allow_guessing
569
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
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);
575
std::string user_config_dir_slap(user_config_dir);
576
user_config_dir_slap.append("/drizzle/drizzleslap.cnf");
578
std::string user_config_dir_client(user_config_dir);
579
user_config_dir_client.append("/drizzle/client.cnf");
581
ifstream user_slap_ifs(user_config_dir_slap.c_str());
582
po::store(parse_config_file(user_slap_ifs, slap_options), vm);
584
ifstream user_client_ifs(user_config_dir_client.c_str());
585
po::store(parse_config_file(user_client_ifs, client_options), vm);
587
ifstream system_slap_ifs(system_config_dir_slap.c_str());
588
store(parse_config_file(system_slap_ifs, slap_options), vm);
590
ifstream system_client_ifs(system_config_dir_client.c_str());
591
store(parse_config_file(system_client_ifs, client_options), vm);
595
if (process_options())
598
if ( vm.count("help") || vm.count("info"))
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 "
607
puts("Run a query multiple times against the server\n");
608
cout << long_options << endl;
612
if (vm.count("protocol"))
614
std::transform(opt_protocol.begin(), opt_protocol.end(),
615
opt_protocol.begin(), ::tolower);
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;
623
cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
627
if (vm.count("port"))
629
temp_drizzle_port= vm["port"].as<uint32_t>();
631
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
633
fprintf(stderr, _("Value supplied for port is not valid.\n"));
638
opt_drizzle_port= (uint32_t) temp_drizzle_port;
642
if ( vm.count("password") )
644
if (not opt_password.empty())
645
opt_password.erase();
646
if (password == PASSWORD_SENTINEL)
652
opt_password= password;
663
if ( vm.count("version") )
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);
670
/* Seed the random number generator if we will be using it. */
671
if (auto_generate_sql)
673
if (opt_set_random_seed == 0)
674
opt_set_random_seed= (uint32_t)time(NULL);
675
srandom(opt_set_random_seed);
678
/* globals? Yes, so we only have to run strlen once */
679
delimiter_length= delimiter.length();
681
slap_connect(con, false);
683
/* Main iterations loop */
834
internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
836
if (get_options(&argc,&argv))
838
internal::free_defaults(defaults_argv);
843
/* Seed the random number generator if we will be using it. */
844
if (auto_generate_sql)
846
if (opt_set_random_seed == 0)
847
opt_set_random_seed= (unsigned int)time(NULL);
848
srandom(opt_set_random_seed);
851
/* globals? Yes, so we only have to run strlen once */
852
delimiter_length= strlen(delimiter);
856
fprintf(stderr,"%s: Too many arguments\n",internal::my_progname);
857
internal::free_defaults(defaults_argv);
862
slap_connect(&con, false);
864
pthread_mutex_init(&counter_mutex, NULL);
865
pthread_cond_init(&count_threshhold, NULL);
866
pthread_mutex_init(&sleeper_mutex, NULL);
867
pthread_cond_init(&sleep_threshhold, NULL);
868
pthread_mutex_init(&timer_alarm_mutex, NULL);
869
pthread_cond_init(&timer_alarm_threshold, NULL);
872
/* Main iterations loop */
685
eptr= engine_options;
688
/* For the final stage we run whatever queries we were asked to run */
692
printf("Starting Concurrency Test\n");
694
if (concurrency.size())
696
for (current= &concurrency[0]; current && *current; current++)
697
concurrency_loop(con, *current, eptr);
701
uint32_t infinite= 1;
703
concurrency_loop(con, infinite, eptr);
708
if (not opt_preserve)
709
drop_schema(con, create_schema_string.c_str());
711
} while (eptr ? (eptr= eptr->getNext()) : 0);
718
/* now free all the strings we created */
719
if (not opt_password.empty())
720
opt_password.erase();
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);
874
eptr= engine_options;
877
/* For the final stage we run whatever queries we were asked to run */
881
printf("Starting Concurrency Test\n");
885
for (current= concurrency; current && *current; current++)
886
concurrency_loop(&con, *current, eptr);
890
uint32_t infinite= 1;
892
concurrency_loop(&con, infinite, eptr);
898
drop_schema(&con, create_schema_string);
900
} while (eptr ? (eptr= eptr->getNext()) : 0);
905
pthread_mutex_destroy(&counter_mutex);
906
pthread_cond_destroy(&count_threshhold);
907
pthread_mutex_destroy(&sleeper_mutex);
908
pthread_cond_destroy(&sleep_threshhold);
909
pthread_mutex_destroy(&timer_alarm_mutex);
910
pthread_cond_destroy(&timer_alarm_threshold);
914
/* now free all the strings we created */
920
statement_cleanup(create_statements);
921
for (x= 0; x < query_statements_count; x++)
922
statement_cleanup(query_statements[x]);
923
free(query_statements);
924
statement_cleanup(pre_statements);
925
statement_cleanup(post_statements);
926
option_cleanup(engine_options);
927
option_cleanup(query_options);
734
if (shared_memory_base_name)
735
free(shared_memory_base_name);
930
if (shared_memory_base_name)
931
free(shared_memory_base_name);
740
catch(std::exception &err)
742
cerr<<"Error:"<<err.what()<<endl;
745
if (csv_file != fileno(stdout))
933
internal::free_defaults(defaults_argv);
751
void concurrency_loop(drizzle_con_st &con, uint32_t current, OptionString *eptr)
939
void concurrency_loop(drizzle_con_st *con, uint32_t current, OptionString *eptr)
753
942
Stats *head_sptr;
755
944
Conclusions conclusion;
756
945
uint64_t client_limit;
758
head_sptr= new Stats[iterations];
947
head_sptr= (Stats *)malloc(sizeof(Stats) * iterations);
759
948
if (head_sptr == NULL)
761
950
fprintf(stderr,"Error allocating memory in concurrency_loop\n");
953
memset(head_sptr, 0, sizeof(Stats) * iterations);
955
memset(&conclusion, 0, sizeof(Conclusions));
765
957
if (auto_actual_queries)
766
958
client_limit= auto_actual_queries;
828
1023
generate_stats(&conclusion, eptr, head_sptr);
831
print_conclusions(conclusion);
832
if (not opt_csv_str.empty())
833
print_conclusions_csv(conclusion);
839
uint32_t get_random_string(char *buf, size_t size)
1026
print_conclusions(&conclusion);
1028
print_conclusions_csv(&conclusion);
1035
static struct option my_long_options[] =
1037
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
1039
{"auto-generate-sql-select-columns", OPT_SLAP_AUTO_GENERATE_SELECT_COLUMNS,
1040
"Provide a string to use for the select fields used in auto tests.",
1041
(char**) &auto_generate_selected_columns_opt,
1042
(char**) &auto_generate_selected_columns_opt,
1043
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1044
{"auto-generate-sql", 'a',
1045
"Generate SQL where not supplied by file or command line.",
1046
(char**) &auto_generate_sql, (char**) &auto_generate_sql,
1047
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1048
{"auto-generate-sql-add-autoincrement", OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
1049
"Add an AUTO_INCREMENT column to auto-generated tables.",
1050
(char**) &auto_generate_sql_autoincrement,
1051
(char**) &auto_generate_sql_autoincrement,
1052
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1053
{"auto-generate-sql-execute-number", OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
1054
"Set this number to generate a set number of queries to run.",
1055
(char**) &auto_actual_queries, (char**) &auto_actual_queries,
1056
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1057
{"auto-generate-sql-guid-primary", OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
1058
"Add GUID based primary keys to auto-generated tables.",
1059
(char**) &auto_generate_sql_guid_primary,
1060
(char**) &auto_generate_sql_guid_primary,
1061
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1062
{"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
1063
"Specify test load type: mixed, update, write, key, or read; default is mixed.",
1064
(char**) &opt_auto_generate_sql_type, (char**) &opt_auto_generate_sql_type,
1065
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1066
{"auto-generate-sql-secondary-indexes",
1067
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
1068
"Number of secondary indexes to add to auto-generated tables.",
1069
(char**) &auto_generate_sql_secondary_indexes,
1070
(char**) &auto_generate_sql_secondary_indexes, 0,
1071
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1072
{"auto-generate-sql-unique-query-number",
1073
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
1074
"Number of unique queries to generate for automatic tests.",
1075
(char**) &auto_generate_sql_unique_query_number,
1076
(char**) &auto_generate_sql_unique_query_number,
1077
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
1078
{"auto-generate-sql-unique-write-number",
1079
OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
1080
"Number of unique queries to generate for auto-generate-sql-write-number.",
1081
(char**) &auto_generate_sql_unique_write_number,
1082
(char**) &auto_generate_sql_unique_write_number,
1083
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
1084
{"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
1085
"Number of row inserts to perform for each thread (default is 100).",
1086
(char**) &auto_generate_sql_number, (char**) &auto_generate_sql_number,
1087
0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0},
1088
{"burnin", OPT_SLAP_BURNIN, "Run full test case in infinite loop.",
1089
(char**) &opt_burnin, (char**) &opt_burnin, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1091
{"ignore-sql-errors", OPT_SLAP_IGNORE_SQL_ERRORS,
1092
"Ignore SQL erros in query run.",
1093
(char**) &opt_ignore_sql_errors,
1094
(char**) &opt_ignore_sql_errors,
1095
0, GET_BOOL, NO_ARG, 0, 0, 0,
1097
{"commit", OPT_SLAP_COMMIT, "Commit records every X number of statements.",
1098
(char**) &commit_rate, (char**) &commit_rate, 0, GET_UINT, REQUIRED_ARG,
1100
{"concurrency", 'c', "Number of clients to simulate for query to run.",
1101
(char**) &concurrency_str, (char**) &concurrency_str, 0, GET_STR,
1102
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1103
{"create", OPT_SLAP_CREATE_STRING, "File or string to use create tables.",
1104
(char**) &create_string, (char**) &create_string, 0, GET_STR, REQUIRED_ARG,
1106
{"create-schema", OPT_CREATE_SLAP_SCHEMA, "Schema to run tests in.",
1107
(char**) &create_schema_string, (char**) &create_schema_string, 0, GET_STR,
1108
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1109
{"csv", OPT_SLAP_CSV,
1110
"Generate CSV output to named file or to stdout if no file is named.",
1111
(char**) &opt_csv_str, (char**) &opt_csv_str, 0, GET_STR,
1112
OPT_ARG, 0, 0, 0, 0, 0, 0},
1113
{"delayed-start", OPT_SLAP_DELAYED_START,
1114
"Delay the startup of threads by a random number of microsends (the maximum of the delay)",
1115
(char**) &opt_delayed_start, (char**) &opt_delayed_start, 0, GET_UINT,
1116
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1118
"Delimiter to use in SQL statements supplied in file or command line.",
1119
(char**) &delimiter, (char**) &delimiter, 0, GET_STR, REQUIRED_ARG,
1121
{"detach", OPT_SLAP_DETACH,
1122
"Detach (close and reopen) connections after X number of requests.",
1123
(char**) &detach_rate, (char**) &detach_rate, 0, GET_UINT, REQUIRED_ARG,
1125
{"engine", 'e', "Storage engine to use for creating the table.",
1126
(char**) &default_engine, (char**) &default_engine, 0,
1127
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1128
{"host", 'h', "Connect to host.", (char**) &host, (char**) &host, 0, GET_STR,
1129
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1130
{"iterations", 'i', "Number of times to run the tests.", (char**) &iterations,
1131
(char**) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
1132
{"label", OPT_SLAP_LABEL, "Label to use for print and csv output.",
1133
(char**) &opt_label, (char**) &opt_label, 0,
1134
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1135
{"mysql", 'm', N_("Use MySQL Protocol."),
1136
(char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
1138
{"number-blob-cols", OPT_SLAP_BLOB_COL,
1139
"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. ",
1140
(char**) &num_blob_cols_opt, (char**) &num_blob_cols_opt, 0, GET_STR, REQUIRED_ARG,
1142
{"number-char-cols", 'x',
1143
"Number of VARCHAR columns to create in table if specifying --auto-generate-sql.",
1144
(char**) &num_char_cols_opt, (char**) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
1146
{"number-int-cols", 'y',
1147
"Number of INT columns to create in table if specifying --auto-generate-sql.",
1148
(char**) &num_int_cols_opt, (char**) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
1150
{"number-of-queries", OPT_DRIZZLE_NUMBER_OF_QUERY,
1151
"Limit each client to this number of queries (this is not exact).",
1152
(char**) &num_of_query, (char**) &num_of_query, 0,
1153
GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1154
{"only-print", OPT_DRIZZLE_ONLY_PRINT,
1155
"This causes drizzleslap to not connect to the databases, but instead print "
1156
"out what it would have done instead.",
1157
(char**) &opt_only_print, (char**) &opt_only_print, 0, GET_BOOL, NO_ARG,
1160
"Password to use when connecting to server. If password is not given it's "
1161
"asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1162
{"port", 'p', "Port number to use for connection.",
1163
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1164
{"post-query", OPT_SLAP_POST_QUERY,
1165
"Query to run or file containing query to execute after tests have completed.",
1166
(char**) &user_supplied_post_statements,
1167
(char**) &user_supplied_post_statements,
1168
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1169
{"post-system", OPT_SLAP_POST_SYSTEM,
1170
"system() string to execute after tests have completed.",
1171
(char**) &post_system,
1172
(char**) &post_system,
1173
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1174
{"pre-query", OPT_SLAP_PRE_QUERY,
1175
"Query to run or file containing query to execute before running tests.",
1176
(char**) &user_supplied_pre_statements,
1177
(char**) &user_supplied_pre_statements,
1178
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1179
{"pre-system", OPT_SLAP_PRE_SYSTEM,
1180
"system() string to execute before running tests.",
1181
(char**) &pre_system,
1182
(char**) &pre_system,
1183
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1184
{"protocol", OPT_DRIZZLE_PROTOCOL,
1185
"The protocol of connection (tcp,socket,pipe,memory).",
1186
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1187
{"query", 'q', "Query to run or file containing query to run.",
1188
(char**) &user_supplied_query, (char**) &user_supplied_query,
1189
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1190
{"set-random-seed", OPT_SLAP_SET_RANDOM_SEED,
1191
"Seed for random number generator (srandom(3))",
1192
(char**)&opt_set_random_seed,
1193
(char**)&opt_set_random_seed,0,
1194
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1195
{"silent", 's', "Run program in silent mode - no output.",
1196
(char**) &opt_silent, (char**) &opt_silent, 0, GET_BOOL, NO_ARG,
1198
{"timer-length", OPT_SLAP_TIMER_LENGTH,
1199
"Require drizzleslap to run each specific test a certain amount of time in seconds.",
1200
(char**) &opt_timer_length, (char**) &opt_timer_length, 0, GET_UINT,
1201
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1202
{"user", 'u', "User for login if not current user.", (char**) &user,
1203
(char**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1205
"More verbose output; you can use this multiple times to get even more "
1206
"verbose output.", (char**) &verbose, (char**) &verbose, 0,
1207
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1208
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
1209
NO_ARG, 0, 0, 0, 0, 0, 0},
1210
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1214
static void print_version(void)
1216
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname, SLAP_VERSION,
1217
drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
1221
static void usage(void)
1224
puts("Copyright (C) 2008 Sun Microsystems");
1225
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\
1226
\nand you are welcome to modify and redistribute it under the GPL \
1228
puts("Run a query multiple times against the server\n");
1229
printf("Usage: %s [OPTIONS]\n",internal::my_progname);
1230
internal::print_defaults("drizzle",load_default_groups);
1231
my_print_help(my_long_options);
1234
static int get_one_option(int optid, const struct option *, char *argument)
1236
char *endchar= NULL;
1237
uint64_t temp_drizzle_port= 0;
1244
temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
1245
/* if there is an alpha character this is not a valid port */
1246
if (strlen(endchar) != 0)
1248
fprintf(stderr, _("Non-integer value supplied for port. If you are trying to enter a password please use --password instead.\n"));
1251
/* If the port number is > 65535 it is not a valid port
1252
This also helps with potential data loss casting unsigned long to a
1254
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
1256
fprintf(stderr, _("Value supplied for port is not valid.\n"));
1261
opt_drizzle_port= (uint32_t) temp_drizzle_port;
1267
char *start= argument;
1270
opt_password = strdup(argument);
1271
if (opt_password == NULL)
1273
fprintf(stderr, "Memory allocation error while copying password. "
1279
/* Overwriting password with 'x' */
1284
/* Cut length of argument */
1296
case 'I': /* Info */
1305
get_random_string(char *buf, size_t size)
841
1307
char *buf_ptr= buf;
843
for (size_t x= size; x > 0; x--)
1310
for (x= size; x > 0; x--)
844
1311
*buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE];
845
1312
return(buf_ptr - buf);
1514
if (not create_string.empty() && !stat(create_string.c_str(), &sbuf))
2040
if (create_string && !stat(create_string, &sbuf))
1517
std::vector<char> tmp_string;
1518
if (not S_ISREG(sbuf.st_mode))
2043
if (!S_ISREG(sbuf.st_mode))
1520
2045
fprintf(stderr,"%s: Create file was not a regular file\n",
2046
internal::my_progname);
1524
if ((data_file= open(create_string.c_str(), O_RDWR)) == -1)
2049
if ((data_file= open(create_string, O_RDWR)) == -1)
1526
fprintf(stderr,"%s: Could not open create file\n", SLAP_NAME);
2051
fprintf(stderr,"%s: Could not open create file\n", internal::my_progname);
1529
2054
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1531
2056
fprintf(stderr, "Request for more memory than architecture supports\n");
1534
tmp_string.resize(sbuf.st_size + 1);
1535
bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
2059
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
2060
if (tmp_string == NULL)
2062
fprintf(stderr, "Memory Allocation error in option processing\n");
2065
memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
2066
bytes_read= read(data_file, (unsigned char*) tmp_string,
1536
2067
(size_t)sbuf.st_size);
2068
tmp_string[sbuf.st_size]= '\0';
1537
2069
close(data_file);
1538
2070
if (bytes_read != sbuf.st_size)
1540
2072
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1542
parse_delimiter(&tmp_string[0], &create_statements, delimiter[0]);
2074
parse_delimiter(tmp_string, &create_statements, delimiter[0]);
1544
else if (not create_string.empty())
2077
else if (create_string)
1546
parse_delimiter(create_string.c_str(), &create_statements, delimiter[0]);
2079
parse_delimiter(create_string, &create_statements, delimiter[0]);
1549
2082
/* Set this up till we fully support options on user generated queries */
1550
if (not user_supplied_query.empty())
2083
if (user_supplied_query)
1552
2085
query_statements_count=
1553
2086
parse_option("default", &query_options, ',');
1555
query_statements.resize(query_statements_count);
2088
query_statements= (Statement **)malloc(sizeof(Statement *) * query_statements_count);
2089
if (query_statements == NULL)
2091
fprintf(stderr, "Memory Allocation error in option processing\n");
2094
memset(query_statements, 0, sizeof(Statement *) * query_statements_count);
1558
if (not user_supplied_query.empty() && !stat(user_supplied_query.c_str(), &sbuf))
2097
if (user_supplied_query && !stat(user_supplied_query, &sbuf))
1561
std::vector<char> tmp_string;
1563
if (not S_ISREG(sbuf.st_mode))
2100
if (!S_ISREG(sbuf.st_mode))
1565
2102
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
2103
internal::my_progname);
1569
if ((data_file= open(user_supplied_query.c_str(), O_RDWR)) == -1)
2106
if ((data_file= open(user_supplied_query, O_RDWR)) == -1)
1571
fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
2108
fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1574
2111
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1576
2113
fprintf(stderr, "Request for more memory than architecture supports\n");
1579
tmp_string.resize((size_t)(sbuf.st_size + 1));
1580
bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
2116
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
2117
if (tmp_string == NULL)
2119
fprintf(stderr, "Memory Allocation error in option processing\n");
2122
memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
2123
bytes_read= read(data_file, (unsigned char*) tmp_string,
1581
2124
(size_t)sbuf.st_size);
2125
tmp_string[sbuf.st_size]= '\0';
1582
2126
close(data_file);
1583
2127
if (bytes_read != sbuf.st_size)
1585
2129
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1587
if (not user_supplied_query.empty())
1588
actual_queries= parse_delimiter(&tmp_string[0], &query_statements[0],
2131
if (user_supplied_query)
2132
actual_queries= parse_delimiter(tmp_string, &query_statements[0],
1591
else if (not user_supplied_query.empty())
2136
else if (user_supplied_query)
1593
actual_queries= parse_delimiter(user_supplied_query.c_str(), &query_statements[0],
2138
actual_queries= parse_delimiter(user_supplied_query, &query_statements[0],
1598
if (not user_supplied_pre_statements.empty()
1599
&& !stat(user_supplied_pre_statements.c_str(), &sbuf))
2143
if (user_supplied_pre_statements
2144
&& !stat(user_supplied_pre_statements, &sbuf))
1602
std::vector<char> tmp_string;
1604
if (not S_ISREG(sbuf.st_mode))
2147
if (!S_ISREG(sbuf.st_mode))
1606
2149
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
2150
internal::my_progname);
1610
if ((data_file= open(user_supplied_pre_statements.c_str(), O_RDWR)) == -1)
2153
if ((data_file= open(user_supplied_pre_statements, O_RDWR)) == -1)
1612
fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
2155
fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1615
2158
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1617
2160
fprintf(stderr, "Request for more memory than architecture supports\n");
1620
tmp_string.resize((size_t)(sbuf.st_size + 1));
1621
bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
2163
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
2164
if (tmp_string == NULL)
2166
fprintf(stderr, "Memory Allocation error in option processing\n");
2169
memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
2170
bytes_read= read(data_file, (unsigned char*) tmp_string,
1622
2171
(size_t)sbuf.st_size);
2172
tmp_string[sbuf.st_size]= '\0';
1623
2173
close(data_file);
1624
2174
if (bytes_read != sbuf.st_size)
1626
2176
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1628
if (not user_supplied_pre_statements.empty())
1629
(void)parse_delimiter(&tmp_string[0], &pre_statements,
2178
if (user_supplied_pre_statements)
2179
(void)parse_delimiter(tmp_string, &pre_statements,
1632
else if (not user_supplied_pre_statements.empty())
2183
else if (user_supplied_pre_statements)
1634
(void)parse_delimiter(user_supplied_pre_statements.c_str(),
2185
(void)parse_delimiter(user_supplied_pre_statements,
1635
2186
&pre_statements,
1639
if (not user_supplied_post_statements.empty()
1640
&& !stat(user_supplied_post_statements.c_str(), &sbuf))
2190
if (user_supplied_post_statements
2191
&& !stat(user_supplied_post_statements, &sbuf))
1643
std::vector<char> tmp_string;
1645
if (not S_ISREG(sbuf.st_mode))
2194
if (!S_ISREG(sbuf.st_mode))
1647
2196
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
2197
internal::my_progname);
1651
if ((data_file= open(user_supplied_post_statements.c_str(), O_RDWR)) == -1)
2200
if ((data_file= open(user_supplied_post_statements, O_RDWR)) == -1)
1653
fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
2202
fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1657
2206
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1659
2208
fprintf(stderr, "Request for more memory than architecture supports\n");
1662
tmp_string.resize((size_t)(sbuf.st_size + 1));
2211
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
2212
if (tmp_string == NULL)
2214
fprintf(stderr, "Memory Allocation error in option processing\n");
2217
memset(tmp_string, 0, (size_t)(sbuf.st_size+1));
1664
bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
2219
bytes_read= read(data_file, (unsigned char*) tmp_string,
1665
2220
(size_t)(sbuf.st_size));
2221
tmp_string[sbuf.st_size]= '\0';
1666
2222
close(data_file);
1667
2223
if (bytes_read != sbuf.st_size)
1669
2225
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1671
if (not user_supplied_post_statements.empty())
1672
(void)parse_delimiter(&tmp_string[0], &post_statements,
2227
if (user_supplied_post_statements)
2228
(void)parse_delimiter(tmp_string, &post_statements,
1675
else if (not user_supplied_post_statements.empty())
2232
else if (user_supplied_post_statements)
1677
(void)parse_delimiter(user_supplied_post_statements.c_str(), &post_statements,
2234
(void)parse_delimiter(user_supplied_post_statements, &post_statements,
1681
2238
if (verbose >= 2)
1682
2239
printf("Parsing engines to use.\n");
1684
if (not default_engine.empty())
1685
parse_option(default_engine.c_str(), &engine_options, ',');
2242
parse_option(default_engine, &engine_options, ',');
1687
2244
if (tty_password)
1688
2245
opt_password= client_get_tty_password(NULL);
1903
2505
if (run_query(con, NULL, query, len))
1905
2507
fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
1906
SLAP_NAME, db, drizzle_con_error(&con));
2508
internal::my_progname, db, drizzle_con_error(con));
1911
static void run_statements(drizzle_con_st &con, Statement *stmt)
2518
run_statements(drizzle_con_st *con, Statement *stmt)
1913
for (Statement *ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
2522
for (ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
1915
2524
if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
1917
2526
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1918
SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
2527
internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
1925
static void timer_thread()
2536
run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit)
2540
unsigned int real_concurrency;
2541
struct timeval start_time, end_time;
2542
OptionString *sql_type;
2544
pthread_t mainthread; /* Thread descriptor */
2545
pthread_attr_t attr; /* Thread attributes */
2548
pthread_attr_init(&attr);
2549
pthread_attr_setdetachstate(&attr,
2550
PTHREAD_CREATE_DETACHED);
2552
pthread_mutex_lock(&counter_mutex);
2555
pthread_mutex_lock(&sleeper_mutex);
2557
pthread_mutex_unlock(&sleeper_mutex);
2559
real_concurrency= 0;
2561
for (y= 0, sql_type= query_options;
2562
y < query_statements_count;
2563
y++, sql_type= sql_type->getNext())
2565
unsigned int options_loop= 1;
2567
if (sql_type->getOption())
2569
options_loop= strtol(sql_type->getOption(),
2571
options_loop= options_loop ? options_loop : 1;
2574
while (options_loop--)
2575
for (x= 0; x < concur; x++)
2577
con= (ThreadContext *)malloc(sizeof(ThreadContext));
2580
fprintf(stderr, "Memory Allocation error in scheduler\n");
2583
con->setStmt(stmts[y]);
2584
con->setLimit(limit);
2587
/* now you create the thread */
2588
if (pthread_create(&mainthread, &attr, run_task,
2591
fprintf(stderr,"%s: Could not create thread\n", internal::my_progname);
1928
We lock around the initial call in case were we in a loop. This
1929
also keeps the value properly syncronized across call threads.
2599
The timer_thread belongs to all threads so it too obeys the wakeup
2600
call that run tasks obey.
1931
master_wakeup.wait();
1934
boost::mutex::scoped_lock scopedLock(timer_alarm_mutex);
1937
xtime_get(&xt, boost::TIME_UTC);
1938
xt.sec += opt_timer_length;
1940
(void)timer_alarm_threshold.timed_wait(scopedLock, xt);
1944
boost::mutex::scoped_lock scopedLock(timer_alarm_mutex);
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)
1953
uint32_t real_concurrency;
1954
struct timeval start_time, end_time;
1959
OptionString *sql_type;
1961
master_wakeup.reset();
1963
real_concurrency= 0;
1966
for (y= 0, sql_type= query_options;
1967
y < query_statements_count;
1968
y++, sql_type= sql_type->getNext())
1970
uint32_t options_loop= 1;
1972
if (sql_type->getOption())
1974
options_loop= strtol(sql_type->getOption(),
1976
options_loop= options_loop ? options_loop : 1;
1979
while (options_loop--)
1981
for (uint32_t x= 0; x < concur; x++)
1984
con= new ThreadContext;
1987
fprintf(stderr, "Memory Allocation error in scheduler\n");
1990
con->setStmt(stmts[y]);
1991
con->setLimit(limit);
1995
/* now you create the thread */
1997
thread= Thread(new boost::thread(boost::bind(&run_task, con)));
1998
threads.push_back(thread);
2005
The timer_thread belongs to all threads so it too obeys the wakeup
2006
call that run tasks obey.
2008
if (opt_timer_length)
2011
boost::mutex::scoped_lock alarmLock(timer_alarm_mutex);
2016
thread= Thread(new boost::thread(&timer_thread));
2017
threads.push_back(thread);
2021
master_wakeup.start();
2602
if (opt_timer_length)
2604
pthread_mutex_lock(&timer_alarm_mutex);
2606
pthread_mutex_unlock(&timer_alarm_mutex);
2608
if (pthread_create(&mainthread, &attr, timer_thread,
2609
(void *)&opt_timer_length) != 0)
2611
fprintf(stderr,"%s: Could not create timer thread\n", internal::my_progname);
2616
pthread_mutex_unlock(&counter_mutex);
2617
pthread_attr_destroy(&attr);
2619
pthread_mutex_lock(&sleeper_mutex);
2621
pthread_mutex_unlock(&sleeper_mutex);
2622
pthread_cond_broadcast(&sleep_threshhold);
2023
2624
gettimeofday(&start_time, NULL);
2026
2627
We loop until we know that all children have cleaned up.
2028
for (Threads::iterator iter= threads.begin(); iter != threads.end(); iter++)
2629
pthread_mutex_lock(&counter_mutex);
2630
while (thread_counter)
2632
struct timespec abstime;
2634
set_timespec(abstime, 3);
2635
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
2637
pthread_mutex_unlock(&counter_mutex);
2033
2639
gettimeofday(&end_time, NULL);
2035
2642
sptr->setTiming(timedif(end_time, start_time));
2036
2643
sptr->setUsers(concur);
2037
2644
sptr->setRealUsers(real_concurrency);
2038
2645
sptr->setRows(limit);
2651
pthread_handler_t timer_thread(void *p)
2653
uint32_t *timer_length= (uint32_t *)p;
2654
struct timespec abstime;
2658
We lock around the initial call in case were we in a loop. This
2659
also keeps the value properly syncronized across call threads.
2661
pthread_mutex_lock(&sleeper_mutex);
2662
while (master_wakeup)
2664
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
2666
pthread_mutex_unlock(&sleeper_mutex);
2668
set_timespec(abstime, *timer_length);
2670
pthread_mutex_lock(&timer_alarm_mutex);
2671
pthread_cond_timedwait(&timer_alarm_threshold, &timer_alarm_mutex, &abstime);
2672
pthread_mutex_unlock(&timer_alarm_mutex);
2674
pthread_mutex_lock(&timer_alarm_mutex);
2676
pthread_mutex_unlock(&timer_alarm_mutex);
2681
pthread_handler_t run_task(void *p)
2683
uint64_t counter= 0, queries;
2684
uint64_t detach_counter;
2685
unsigned int commit_counter;
2687
drizzle_result_st result;
2690
ThreadContext *ctx= (ThreadContext *)p;
2692
pthread_mutex_lock(&sleeper_mutex);
2693
while (master_wakeup)
2695
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
2697
pthread_mutex_unlock(&sleeper_mutex);
2699
slap_connect(&con, true);
2702
printf("connected!\n");
2707
run_query(&con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
2710
for (ptr= ctx->getStmt(), detach_counter= 0;
2711
ptr && ptr->getLength();
2712
ptr= ptr->getNext(), detach_counter++)
2714
if (!opt_only_print && detach_rate && !(detach_counter % detach_rate))
2717
slap_connect(&con, true);
2721
We have to execute differently based on query type. This should become a function.
2723
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
2724
(ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
2727
unsigned int key_val;
2729
char buffer[HUGE_STRING_LENGTH];
2732
This should only happen if some sort of new engine was
2733
implemented that didn't properly handle UPDATEs.
2735
Just in case someone runs this under an experimental engine we don't
2736
want a crash so the if() is placed here.
2738
assert(primary_keys_number_of);
2739
if (primary_keys_number_of)
2741
key_val= (unsigned int)(random() % primary_keys_number_of);
2742
key= primary_keys[key_val];
2746
length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
2747
(int)ptr->getLength(), ptr->getString(), key);
2749
if (run_query(&con, &result, buffer, length))
2751
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2752
internal::my_progname, (uint32_t)length, buffer, drizzle_con_error(&con));
2759
if (run_query(&con, &result, ptr->getString(), ptr->getLength()))
2761
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2762
internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
2767
if (!opt_only_print)
2769
while ((row = drizzle_row_next(&result)))
2771
drizzle_result_free(&result);
2775
if (commit_rate && (++commit_counter == commit_rate))
2778
run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
2781
/* If the timer is set, and the alarm is not active then end */
2782
if (opt_timer_length && timer_alarm == false)
2785
/* If limit has been reached, and we are not in a timer_alarm just end */
2786
if (ctx->getLimit() && queries == ctx->getLimit() && timer_alarm == false)
2790
if (opt_timer_length && timer_alarm == true)
2793
if (ctx->getLimit() && queries < ctx->getLimit())
2799
run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
2803
pthread_mutex_lock(&counter_mutex);
2805
pthread_cond_signal(&count_threshhold);
2806
pthread_mutex_unlock(&counter_mutex);
2042
2814
Parse records from comma seperated string. : is a reserved character and is used for options
2045
uint32_t parse_option(const char *origin, OptionString **stmt, char delm)
2818
parse_option(const char *origin, OptionString **stmt, char delm)
2048
2821
char *begin_ptr;
2823
OptionString **sptr= stmt;
2050
2825
uint32_t length= strlen(origin);
2051
2826
uint32_t count= 0; /* We know that there is always one */
2053
2828
end_ptr= (char *)origin + length;
2056
*stmt= tmp= new OptionString;
2830
tmp= *sptr= (OptionString *)malloc(sizeof(OptionString));
2833
fprintf(stderr,"Error allocating memory while parsing options\n");
2836
memset(tmp, 0, sizeof(OptionString));
2058
2838
for (begin_ptr= (char *)origin;
2059
2839
begin_ptr != end_ptr;