00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #include <config.h>
00075 #include "client_priv.h"
00076
00077 #include "option_string.h"
00078 #include "stats.h"
00079 #include "thread_context.h"
00080 #include "conclusions.h"
00081 #include "wakeup.h"
00082
00083 #include <signal.h>
00084 #include <stdarg.h>
00085 #include <sys/types.h>
00086 #include <sys/wait.h>
00087 #ifdef HAVE_SYS_STAT_H
00088 # include <sys/stat.h>
00089 #endif
00090 #include <fcntl.h>
00091 #include <math.h>
00092 #include <cassert>
00093 #include <cstdlib>
00094 #include <string>
00095 #include <iostream>
00096 #include <fstream>
00097 #include <drizzled/configmake.h>
00098 #include <memory>
00099
00100
00101 #include <drizzled/gettext.h>
00102
00103 #include <boost/thread.hpp>
00104 #include <boost/thread/mutex.hpp>
00105 #include <boost/thread/condition_variable.hpp>
00106 #include <boost/program_options.hpp>
00107 #include <boost/scoped_ptr.hpp>
00108 #include <drizzled/atomics.h>
00109
00110 #define SLAP_NAME "drizzleslap"
00111 #define SLAP_VERSION "1.5"
00112
00113 #define HUGE_STRING_LENGTH 8196
00114 #define RAND_STRING_SIZE 126
00115 #define DEFAULT_BLOB_SIZE 1024
00116
00117 using namespace std;
00118 using namespace drizzled;
00119 namespace po= boost::program_options;
00120
00121 #ifdef HAVE_SMEM
00122 static char *shared_memory_base_name=0;
00123 #endif
00124
00125 client::Wakeup master_wakeup;
00126
00127
00128 static bool timer_alarm= false;
00129 boost::mutex timer_alarm_mutex;
00130 boost::condition_variable_any timer_alarm_threshold;
00131
00132 std::vector < std::string > primary_keys;
00133
00134 drizzled::atomic<size_t> connection_count;
00135 drizzled::atomic<uint64_t> failed_update_for_transaction;
00136
00137 static string host,
00138 opt_password,
00139 user,
00140 user_supplied_query,
00141 user_supplied_pre_statements,
00142 user_supplied_post_statements,
00143 default_engine,
00144 pre_system,
00145 post_system;
00146
00147 static vector<string> user_supplied_queries;
00148 static string opt_verbose;
00149 std::string opt_protocol;
00150 string delimiter;
00151
00152 string create_schema_string;
00153
00154 static bool use_drizzle_protocol= false;
00155 static bool opt_preserve= true;
00156 static bool opt_only_print;
00157 static bool opt_burnin;
00158 static bool opt_ignore_sql_errors= false;
00159 static bool opt_silent,
00160 auto_generate_sql_autoincrement,
00161 auto_generate_sql_guid_primary,
00162 auto_generate_sql;
00163 std::string opt_auto_generate_sql_type;
00164
00165 static int32_t verbose= 0;
00166 static uint32_t delimiter_length;
00167 static uint32_t commit_rate;
00168 static uint32_t detach_rate;
00169 static uint32_t opt_timer_length;
00170 static uint32_t opt_delayed_start;
00171 string num_blob_cols_opt,
00172 num_char_cols_opt,
00173 num_int_cols_opt;
00174 string opt_label;
00175 static uint32_t opt_set_random_seed;
00176
00177 string auto_generate_selected_columns_opt;
00178
00179
00180 static uint32_t num_int_cols= 1;
00181 static uint32_t num_char_cols= 1;
00182 static uint32_t num_blob_cols= 0;
00183 static uint32_t num_blob_cols_size;
00184 static uint32_t num_blob_cols_size_min;
00185 static uint32_t num_int_cols_index= 0;
00186 static uint32_t num_char_cols_index= 0;
00187 static uint32_t iterations;
00188 static uint64_t actual_queries= 0;
00189 static uint64_t auto_actual_queries;
00190 static uint64_t auto_generate_sql_unique_write_number;
00191 static uint64_t auto_generate_sql_unique_query_number;
00192 static uint32_t auto_generate_sql_secondary_indexes;
00193 static uint64_t num_of_query;
00194 static uint64_t auto_generate_sql_number;
00195 string concurrency_str;
00196 string create_string;
00197 std::vector <uint32_t> concurrency;
00198
00199 std::string opt_csv_str;
00200 int csv_file;
00201
00202 static int process_options(void);
00203 static uint32_t opt_drizzle_port= 0;
00204
00205 static OptionString *engine_options= NULL;
00206 static OptionString *query_options= NULL;
00207 static Statement *pre_statements= NULL;
00208 static Statement *post_statements= NULL;
00209 static Statement *create_statements= NULL;
00210
00211 static std::vector <Statement *> query_statements;
00212 static uint32_t query_statements_count;
00213
00214
00215
00216 void print_conclusions(Conclusions &con);
00217 void print_conclusions_csv(Conclusions &con);
00218 void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr);
00219 uint32_t parse_comma(const char *string, std::vector <uint32_t> &range);
00220 uint32_t parse_delimiter(const char *script, Statement **stmt, char delm);
00221 uint32_t parse_option(const char *origin, OptionString **stmt, char delm);
00222 static void drop_schema(drizzle_con_st &con, const char *db);
00223 uint32_t get_random_string(char *buf, size_t size);
00224 static Statement *build_table_string(void);
00225 static Statement *build_insert_string(void);
00226 static Statement *build_update_string(void);
00227 static Statement * build_select_string(bool key);
00228 static int generate_primary_key_list(drizzle_con_st &con, OptionString *engine_stmt);
00229 static void create_schema(drizzle_con_st &con, const char *db, Statement *stmt, OptionString *engine_stmt, Stats *sptr);
00230 static void run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit);
00231 void statement_cleanup(Statement *stmt);
00232 void option_cleanup(OptionString *stmt);
00233 void concurrency_loop(drizzle_con_st &con, uint32_t current, OptionString *eptr);
00234 static void run_statements(drizzle_con_st &con, Statement *stmt);
00235 void slap_connect(drizzle_con_st &con, bool connect_to_schema);
00236 void slap_close(drizzle_con_st &con);
00237 static int run_query(drizzle_con_st &con, drizzle_result_st *result, const char *query, int len);
00238 void standard_deviation(Conclusions &con, Stats *sptr);
00239
00240 static const char ALPHANUMERICS[]=
00241 "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
00242
00243 #define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
00244
00245
00246 static long int timedif(struct timeval a, struct timeval b)
00247 {
00248 int us, s;
00249
00250 us = a.tv_usec - b.tv_usec;
00251 us /= 1000;
00252 s = a.tv_sec - b.tv_sec;
00253 s *= 1000;
00254 return s + us;
00255 }
00256
00257 static void combine_queries(vector<string> queries)
00258 {
00259 user_supplied_query.erase();
00260 for (vector<string>::iterator it= queries.begin();
00261 it != queries.end();
00262 ++it)
00263 {
00264 user_supplied_query.append(*it);
00265 user_supplied_query.append(delimiter);
00266 }
00267 }
00268
00269
00270 static void run_task(ThreadContext *ctx)
00271 {
00272 uint64_t counter= 0, queries;
00273 uint64_t detach_counter;
00274 uint32_t commit_counter;
00275 boost::scoped_ptr<drizzle_con_st> con_ap(new drizzle_con_st);
00276 drizzle_con_st &con= *con_ap.get();
00277 drizzle_result_st result;
00278 drizzle_row_t row;
00279 Statement *ptr;
00280
00281 master_wakeup.wait();
00282
00283 slap_connect(con, true);
00284
00285 if (verbose >= 3)
00286 printf("connected!\n");
00287 queries= 0;
00288
00289 commit_counter= 0;
00290 if (commit_rate)
00291 run_query(con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
00292
00293 limit_not_met:
00294 for (ptr= ctx->getStmt(), detach_counter= 0;
00295 ptr && ptr->getLength();
00296 ptr= ptr->getNext(), detach_counter++)
00297 {
00298 if (not opt_only_print && detach_rate && !(detach_counter % detach_rate))
00299 {
00300 slap_close(con);
00301 slap_connect(con, true);
00302 }
00303
00304
00305
00306
00307 bool is_failed_update= false;
00308 if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
00309 (ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
00310 {
00311 int length;
00312 uint32_t key_val;
00313 char buffer[HUGE_STRING_LENGTH];
00314
00315
00316
00317
00318
00319
00320
00321
00322 assert(primary_keys.size());
00323 if (primary_keys.size())
00324 {
00325 key_val= (uint32_t)(random() % primary_keys.size());
00326 const char *key;
00327 key= primary_keys[key_val].c_str();
00328
00329 assert(key);
00330
00331 length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
00332 (int)ptr->getLength(), ptr->getString(), key);
00333
00334 if (run_query(con, &result, buffer, length))
00335 {
00336 if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) and commit_rate)
00337 {
00338
00339
00340
00341 is_failed_update= true;
00342 failed_update_for_transaction.fetch_and_increment();
00343 }
00344 else
00345 {
00346 fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
00347 SLAP_NAME, (uint32_t)length, buffer, drizzle_con_error(&con));
00348 abort();
00349 }
00350 }
00351 }
00352 }
00353 else
00354 {
00355 if (run_query(con, &result, ptr->getString(), ptr->getLength()))
00356 {
00357 if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) and commit_rate)
00358 {
00359
00360
00361
00362 is_failed_update= true;
00363 failed_update_for_transaction.fetch_and_increment();
00364 }
00365 else
00366 {
00367 fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
00368 SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
00369 abort();
00370 }
00371 }
00372 }
00373
00374 if (not opt_only_print and not is_failed_update)
00375 {
00376 while ((row = drizzle_row_next(&result)))
00377 counter++;
00378 drizzle_result_free(&result);
00379 }
00380 queries++;
00381
00382 if (commit_rate && (++commit_counter == commit_rate) and not is_failed_update)
00383 {
00384 commit_counter= 0;
00385 run_query(con, NULL, "COMMIT", strlen("COMMIT"));
00386 }
00387
00388
00389 if (opt_timer_length && timer_alarm == false)
00390 goto end;
00391
00392
00393 if (ctx->getLimit() && queries == ctx->getLimit() && timer_alarm == false)
00394 goto end;
00395 }
00396
00397 if (opt_timer_length && timer_alarm == true)
00398 goto limit_not_met;
00399
00400 if (ctx->getLimit() && queries < ctx->getLimit())
00401 goto limit_not_met;
00402
00403
00404 end:
00405 if (commit_rate)
00406 run_query(con, NULL, "COMMIT", strlen("COMMIT"));
00407
00408 slap_close(con);
00409
00410 delete ctx;
00411 }
00412
00431 int main(int argc, char **argv)
00432 {
00433 char *password= NULL;
00434 try
00435 {
00436 po::options_description commandline_options("Options used only in command line");
00437 commandline_options.add_options()
00438 ("help,?","Display this help and exit")
00439 ("info","Gives information and exit")
00440 ("burnin",po::value<bool>(&opt_burnin)->default_value(false)->zero_tokens(),
00441 "Run full test case in infinite loop")
00442 ("ignore-sql-errors", po::value<bool>(&opt_ignore_sql_errors)->default_value(false)->zero_tokens(),
00443 "Ignore SQL errors in query run")
00444 ("create-schema",po::value<string>(&create_schema_string)->default_value("drizzleslap"),
00445 "Schema to run tests in")
00446 ("create",po::value<string>(&create_string)->default_value(""),
00447 "File or string to use to create tables")
00448 ("detach",po::value<uint32_t>(&detach_rate)->default_value(0),
00449 "Detach (close and re open) connections after X number of requests")
00450 ("iterations,i",po::value<uint32_t>(&iterations)->default_value(1),
00451 "Number of times to run the tests")
00452 ("label",po::value<string>(&opt_label)->default_value(""),
00453 "Label to use for print and csv")
00454 ("number-blob-cols",po::value<string>(&num_blob_cols_opt)->default_value(""),
00455 "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. ")
00456 ("number-char-cols,x",po::value<string>(&num_char_cols_opt)->default_value(""),
00457 "Number of VARCHAR columns to create in table if specifying --auto-generate-sql.")
00458 ("number-int-cols,y",po::value<string>(&num_int_cols_opt)->default_value(""),
00459 "Number of INT columns to create in table if specifying --auto-generate-sql.")
00460 ("number-of-queries",
00461 po::value<uint64_t>(&num_of_query)->default_value(0),
00462 "Limit each client to this number of queries(this is not exact)")
00463 ("only-print",po::value<bool>(&opt_only_print)->default_value(false)->zero_tokens(),
00464 "This causes drizzleslap to not connect to the database instead print out what it would have done instead")
00465 ("post-query", po::value<string>(&user_supplied_post_statements)->default_value(""),
00466 "Query to run or file containing query to execute after tests have completed.")
00467 ("post-system",po::value<string>(&post_system)->default_value(""),
00468 "system() string to execute after tests have completed")
00469 ("pre-query",
00470 po::value<string>(&user_supplied_pre_statements)->default_value(""),
00471 "Query to run or file containing query to execute before running tests.")
00472 ("pre-system",po::value<string>(&pre_system)->default_value(""),
00473 "system() string to execute before running tests.")
00474 ("query,q",po::value<vector<string> >(&user_supplied_queries)->composing()->notifier(&combine_queries),
00475 "Query to run or file containing query")
00476 ("verbose,v", po::value<string>(&opt_verbose)->default_value("v"), "Increase verbosity level by one.")
00477 ("version,V","Output version information and exit")
00478 ;
00479
00480 po::options_description slap_options("Options specific to drizzleslap");
00481 slap_options.add_options()
00482 ("auto-generate-sql-select-columns",
00483 po::value<string>(&auto_generate_selected_columns_opt)->default_value(""),
00484 "Provide a string to use for the select fields used in auto tests")
00485 ("auto-generate-sql,a",po::value<bool>(&auto_generate_sql)->default_value(false)->zero_tokens(),
00486 "Generate SQL where not supplied by file or command line")
00487 ("auto-generate-sql-add-autoincrement",
00488 po::value<bool>(&auto_generate_sql_autoincrement)->default_value(false)->zero_tokens(),
00489 "Add an AUTO_INCREMENT column to auto-generated tables")
00490 ("auto-generate-sql-execute-number",
00491 po::value<uint64_t>(&auto_actual_queries)->default_value(0),
00492 "See this number and generate a set of queries to run")
00493 ("auto-generate-sql-guid-primary",
00494 po::value<bool>(&auto_generate_sql_guid_primary)->default_value(false)->zero_tokens(),
00495 "Add GUID based primary keys to auto-generated tables")
00496 ("auto-generate-sql-load-type",
00497 po::value<string>(&opt_auto_generate_sql_type)->default_value("mixed"),
00498 "Specify test load type: mixed, update, write, key or read; default is mixed")
00499 ("auto-generate-sql-secondary-indexes",
00500 po::value<uint32_t>(&auto_generate_sql_secondary_indexes)->default_value(0),
00501 "Number of secondary indexes to add to auto-generated tables")
00502 ("auto-generated-sql-unique-query-number",
00503 po::value<uint64_t>(&auto_generate_sql_unique_query_number)->default_value(10),
00504 "Number of unique queries to generate for automatic tests")
00505 ("auto-generate-sql-unique-write-number",
00506 po::value<uint64_t>(&auto_generate_sql_unique_write_number)->default_value(10),
00507 "Number of unique queries to generate for auto-generate-sql-write-number")
00508 ("auto-generate-sql-write-number",
00509 po::value<uint64_t>(&auto_generate_sql_number)->default_value(100),
00510 "Number of row inserts to perform for each thread (default is 100).")
00511 ("commit",po::value<uint32_t>(&commit_rate)->default_value(0),
00512 "Commit records every X number of statements")
00513 ("concurrency,c",po::value<string>(&concurrency_str)->default_value(""),
00514 "Number of clients to simulate for query to run")
00515 ("csv",po::value<std::string>(&opt_csv_str)->default_value(""),
00516 "Generate CSV output to named file or to stdout if no file is name.")
00517 ("delayed-start",po::value<uint32_t>(&opt_delayed_start)->default_value(0),
00518 "Delay the startup of threads by a random number of microsends (the maximum of the delay")
00519 ("delimiter,F",po::value<string>(&delimiter)->default_value("\n"),
00520 "Delimiter to use in SQL statements supplied in file or command line")
00521 ("engine,e",po::value<string>(&default_engine)->default_value(""),
00522 "Storage engine to use for creating the table")
00523 ("set-random-seed",
00524 po::value<uint32_t>(&opt_set_random_seed)->default_value(0),
00525 "Seed for random number generator (srandom(3)) ")
00526 ("silent,s",po::value<bool>(&opt_silent)->default_value(false)->zero_tokens(),
00527 "Run program in silent mode - no output. ")
00528 ("timer-length",po::value<uint32_t>(&opt_timer_length)->default_value(0),
00529 "Require drizzleslap to run each specific test a certain amount of time in seconds")
00530 ;
00531
00532 po::options_description client_options("Options specific to the client");
00533 client_options.add_options()
00534 ("host,h",po::value<string>(&host)->default_value("localhost"),"Connect to the host")
00535 ("password,P",po::value<char *>(&password),
00536 "Password to use when connecting to server. If password is not given it's asked from the tty")
00537 ("port,p",po::value<uint32_t>(), "Port number to use for connection")
00538 ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
00539 "The protocol of connection (mysql or drizzle).")
00540 ("user,u",po::value<string>(&user)->default_value(""),
00541 "User for login if not current user")
00542 ;
00543
00544 po::options_description long_options("Allowed Options");
00545 long_options.add(commandline_options).add(slap_options).add(client_options);
00546
00547 std::string system_config_dir_slap(SYSCONFDIR);
00548 system_config_dir_slap.append("/drizzle/drizzleslap.cnf");
00549
00550 std::string system_config_dir_client(SYSCONFDIR);
00551 system_config_dir_client.append("/drizzle/client.cnf");
00552
00553 std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
00554
00555 if (user_config_dir.compare(0, 2, "~/") == 0)
00556 {
00557 char *homedir;
00558 homedir= getenv("HOME");
00559 if (homedir != NULL)
00560 user_config_dir.replace(0, 1, homedir);
00561 }
00562
00563 uint64_t temp_drizzle_port= 0;
00564 boost::scoped_ptr<drizzle_con_st> con_ap(new drizzle_con_st);
00565 drizzle_con_st &con= *con_ap.get();
00566 OptionString *eptr;
00567
00568
00569 int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
00570
00571 po::variables_map vm;
00572 po::store(po::command_line_parser(argc, argv).options(long_options).
00573 style(style).extra_parser(parse_password_arg).run(), vm);
00574
00575 std::string user_config_dir_slap(user_config_dir);
00576 user_config_dir_slap.append("/drizzle/drizzleslap.cnf");
00577
00578 std::string user_config_dir_client(user_config_dir);
00579 user_config_dir_client.append("/drizzle/client.cnf");
00580
00581 ifstream user_slap_ifs(user_config_dir_slap.c_str());
00582 po::store(parse_config_file(user_slap_ifs, slap_options), vm);
00583
00584 ifstream user_client_ifs(user_config_dir_client.c_str());
00585 po::store(parse_config_file(user_client_ifs, client_options), vm);
00586
00587 ifstream system_slap_ifs(system_config_dir_slap.c_str());
00588 store(parse_config_file(system_slap_ifs, slap_options), vm);
00589
00590 ifstream system_client_ifs(system_config_dir_client.c_str());
00591 store(parse_config_file(system_client_ifs, client_options), vm);
00592
00593 po::notify(vm);
00594
00595 if (process_options())
00596 abort();
00597
00598 if ( vm.count("help") || vm.count("info"))
00599 {
00600 printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",SLAP_NAME, SLAP_VERSION,
00601 drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
00602 puts("Copyright (C) 2008 Sun Microsystems");
00603 puts("This software comes with ABSOLUTELY NO WARRANTY. "
00604 "This is free software,\n"
00605 "and you are welcome to modify and redistribute it under the GPL "
00606 "license\n");
00607 puts("Run a query multiple times against the server\n");
00608 cout << long_options << endl;
00609 abort();
00610 }
00611
00612 if (vm.count("protocol"))
00613 {
00614 std::transform(opt_protocol.begin(), opt_protocol.end(),
00615 opt_protocol.begin(), ::tolower);
00616
00617 if (not opt_protocol.compare("mysql"))
00618 use_drizzle_protocol=false;
00619 else if (not opt_protocol.compare("drizzle"))
00620 use_drizzle_protocol=true;
00621 else
00622 {
00623 cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
00624 abort();
00625 }
00626 }
00627 if (vm.count("port"))
00628 {
00629 temp_drizzle_port= vm["port"].as<uint32_t>();
00630
00631 if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
00632 {
00633 fprintf(stderr, _("Value supplied for port is not valid.\n"));
00634 abort();
00635 }
00636 else
00637 {
00638 opt_drizzle_port= (uint32_t) temp_drizzle_port;
00639 }
00640 }
00641
00642 if ( vm.count("password") )
00643 {
00644 if (not opt_password.empty())
00645 opt_password.erase();
00646 if (password == PASSWORD_SENTINEL)
00647 {
00648 opt_password= "";
00649 }
00650 else
00651 {
00652 opt_password= password;
00653 tty_password= false;
00654 }
00655 }
00656 else
00657 {
00658 tty_password= true;
00659 }
00660
00661
00662
00663 if ( vm.count("version") )
00664 {
00665 printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",SLAP_NAME, SLAP_VERSION,
00666 drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
00667 abort();
00668 }
00669
00670
00671 if (auto_generate_sql)
00672 {
00673 if (opt_set_random_seed == 0)
00674 opt_set_random_seed= (uint32_t)time(NULL);
00675 srandom(opt_set_random_seed);
00676 }
00677
00678
00679 delimiter_length= delimiter.length();
00680
00681 slap_connect(con, false);
00682
00683
00684 burnin:
00685 eptr= engine_options;
00686 do
00687 {
00688
00689 uint32_t *current;
00690
00691 if (verbose >= 2)
00692 printf("Starting Concurrency Test\n");
00693
00694 if (concurrency.size())
00695 {
00696 for (current= &concurrency[0]; current && *current; current++)
00697 concurrency_loop(con, *current, eptr);
00698 }
00699 else
00700 {
00701 uint32_t infinite= 1;
00702 do {
00703 concurrency_loop(con, infinite, eptr);
00704 }
00705 while (infinite++);
00706 }
00707
00708 if (not opt_preserve)
00709 drop_schema(con, create_schema_string.c_str());
00710
00711 } while (eptr ? (eptr= eptr->getNext()) : 0);
00712
00713 if (opt_burnin)
00714 goto burnin;
00715
00716 slap_close(con);
00717
00718
00719 if (not opt_password.empty())
00720 opt_password.erase();
00721
00722 concurrency.clear();
00723
00724 statement_cleanup(create_statements);
00725 for (uint32_t x= 0; x < query_statements_count; x++)
00726 statement_cleanup(query_statements[x]);
00727 query_statements.clear();
00728 statement_cleanup(pre_statements);
00729 statement_cleanup(post_statements);
00730 option_cleanup(engine_options);
00731 option_cleanup(query_options);
00732
00733 #ifdef HAVE_SMEM
00734 if (shared_memory_base_name)
00735 free(shared_memory_base_name);
00736 #endif
00737
00738 }
00739
00740 catch(std::exception &err)
00741 {
00742 cerr<<"Error:"<<err.what()<<endl;
00743 }
00744
00745 if (csv_file != fileno(stdout))
00746 close(csv_file);
00747
00748 return 0;
00749 }
00750
00751 void concurrency_loop(drizzle_con_st &con, uint32_t current, OptionString *eptr)
00752 {
00753 Stats *head_sptr;
00754 Stats *sptr;
00755 Conclusions conclusion;
00756 uint64_t client_limit;
00757
00758 head_sptr= new Stats[iterations];
00759 if (head_sptr == NULL)
00760 {
00761 fprintf(stderr,"Error allocating memory in concurrency_loop\n");
00762 abort();
00763 }
00764
00765 if (auto_actual_queries)
00766 client_limit= auto_actual_queries;
00767 else if (num_of_query)
00768 client_limit= num_of_query / current;
00769 else
00770 client_limit= actual_queries;
00771
00772 uint32_t x;
00773 for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
00774 {
00775
00776
00777
00778
00779
00780 if (opt_preserve == false)
00781 drop_schema(con, create_schema_string.c_str());
00782
00783
00784 if (create_statements)
00785 create_schema(con, create_schema_string.c_str(), create_statements, eptr, sptr);
00786
00787
00788
00789
00790
00791 if (verbose >= 2)
00792 printf("Generating primary key list\n");
00793 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
00794 generate_primary_key_list(con, eptr);
00795
00796 if (not pre_system.empty())
00797 {
00798 int ret= system(pre_system.c_str());
00799 assert(ret != -1);
00800 }
00801
00802
00803
00804
00805
00806 if (pre_statements)
00807 run_statements(con, pre_statements);
00808
00809 run_scheduler(sptr, &query_statements[0], current, client_limit);
00810
00811 if (post_statements)
00812 run_statements(con, post_statements);
00813
00814 if (not post_system.empty())
00815 {
00816 int ret= system(post_system.c_str());
00817 assert(ret !=-1);
00818 }
00819
00820
00821 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
00822 primary_keys.clear();
00823 }
00824
00825 if (verbose >= 2)
00826 printf("Generating stats\n");
00827
00828 generate_stats(&conclusion, eptr, head_sptr);
00829
00830 if (not opt_silent)
00831 print_conclusions(conclusion);
00832 if (not opt_csv_str.empty())
00833 print_conclusions_csv(conclusion);
00834
00835 delete [] head_sptr;
00836 }
00837
00838
00839 uint32_t get_random_string(char *buf, size_t size)
00840 {
00841 char *buf_ptr= buf;
00842
00843 for (size_t x= size; x > 0; x--)
00844 *buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE];
00845 return(buf_ptr - buf);
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855 static Statement *
00856 build_table_string(void)
00857 {
00858 char buf[HUGE_STRING_LENGTH];
00859 uint32_t col_count;
00860 Statement *ptr;
00861 string table_string;
00862
00863 table_string.reserve(HUGE_STRING_LENGTH);
00864
00865 table_string= "CREATE TABLE `t1` (";
00866
00867 if (auto_generate_sql_autoincrement)
00868 {
00869 table_string.append("id serial");
00870
00871 if (num_int_cols || num_char_cols)
00872 table_string.append(",");
00873 }
00874
00875 if (auto_generate_sql_guid_primary)
00876 {
00877 table_string.append("id varchar(128) primary key");
00878
00879 if (num_int_cols || num_char_cols || auto_generate_sql_guid_primary)
00880 table_string.append(",");
00881 }
00882
00883 if (auto_generate_sql_secondary_indexes)
00884 {
00885 for (uint32_t count= 0; count < auto_generate_sql_secondary_indexes; count++)
00886 {
00887 if (count)
00888 table_string.append(",");
00889
00890 if (snprintf(buf, HUGE_STRING_LENGTH, "id%d varchar(32) unique key", count)
00891 > HUGE_STRING_LENGTH)
00892 {
00893 fprintf(stderr, "Memory Allocation error in create table\n");
00894 abort();
00895 }
00896 table_string.append(buf);
00897 }
00898
00899 if (num_int_cols || num_char_cols)
00900 table_string.append(",");
00901 }
00902
00903 if (num_int_cols)
00904 for (col_count= 1; col_count <= num_int_cols; col_count++)
00905 {
00906 if (num_int_cols_index)
00907 {
00908 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT, INDEX(intcol%d)",
00909 col_count, col_count) > HUGE_STRING_LENGTH)
00910 {
00911 fprintf(stderr, "Memory Allocation error in create table\n");
00912 abort();
00913 }
00914 }
00915 else
00916 {
00917 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT ", col_count)
00918 > HUGE_STRING_LENGTH)
00919 {
00920 fprintf(stderr, "Memory Allocation error in create table\n");
00921 abort();
00922 }
00923 }
00924 table_string.append(buf);
00925
00926 if (col_count < num_int_cols || num_char_cols > 0)
00927 table_string.append(",");
00928 }
00929
00930 if (num_char_cols)
00931 for (col_count= 1; col_count <= num_char_cols; col_count++)
00932 {
00933 if (num_char_cols_index)
00934 {
00935 if (snprintf(buf, HUGE_STRING_LENGTH,
00936 "charcol%d VARCHAR(128), INDEX(charcol%d) ",
00937 col_count, col_count) > HUGE_STRING_LENGTH)
00938 {
00939 fprintf(stderr, "Memory Allocation error in creating table\n");
00940 abort();
00941 }
00942 }
00943 else
00944 {
00945 if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d VARCHAR(128)",
00946 col_count) > HUGE_STRING_LENGTH)
00947 {
00948 fprintf(stderr, "Memory Allocation error in creating table\n");
00949 abort();
00950 }
00951 }
00952 table_string.append(buf);
00953
00954 if (col_count < num_char_cols || num_blob_cols > 0)
00955 table_string.append(",");
00956 }
00957
00958 if (num_blob_cols)
00959 for (col_count= 1; col_count <= num_blob_cols; col_count++)
00960 {
00961 if (snprintf(buf, HUGE_STRING_LENGTH, "blobcol%d blob",
00962 col_count) > HUGE_STRING_LENGTH)
00963 {
00964 fprintf(stderr, "Memory Allocation error in creating table\n");
00965 abort();
00966 }
00967 table_string.append(buf);
00968
00969 if (col_count < num_blob_cols)
00970 table_string.append(",");
00971 }
00972
00973 table_string.append(")");
00974 ptr= new Statement;
00975 ptr->setString(table_string.length());
00976 if (ptr->getString()==NULL)
00977 {
00978 fprintf(stderr, "Memory Allocation error in creating table\n");
00979 abort();
00980 }
00981 ptr->setType(CREATE_TABLE_TYPE);
00982 strcpy(ptr->getString(), table_string.c_str());
00983 return(ptr);
00984 }
00985
00986
00987
00988
00989
00990
00991
00992 static Statement *
00993 build_update_string(void)
00994 {
00995 char buf[HUGE_STRING_LENGTH];
00996 uint32_t col_count;
00997 Statement *ptr;
00998 string update_string;
00999
01000 update_string.reserve(HUGE_STRING_LENGTH);
01001
01002 update_string= "UPDATE t1 SET ";
01003
01004 if (num_int_cols)
01005 for (col_count= 1; col_count <= num_int_cols; col_count++)
01006 {
01007 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d = %ld", col_count,
01008 random()) > HUGE_STRING_LENGTH)
01009 {
01010 fprintf(stderr, "Memory Allocation error in creating update\n");
01011 abort();
01012 }
01013 update_string.append(buf);
01014
01015 if (col_count < num_int_cols || num_char_cols > 0)
01016 update_string.append(",", 1);
01017 }
01018
01019 if (num_char_cols)
01020 for (col_count= 1; col_count <= num_char_cols; col_count++)
01021 {
01022 char rand_buffer[RAND_STRING_SIZE];
01023 int buf_len= get_random_string(rand_buffer, RAND_STRING_SIZE);
01024
01025 if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d = '%.*s'", col_count,
01026 buf_len, rand_buffer)
01027 > HUGE_STRING_LENGTH)
01028 {
01029 fprintf(stderr, "Memory Allocation error in creating update\n");
01030 abort();
01031 }
01032 update_string.append(buf);
01033
01034 if (col_count < num_char_cols)
01035 update_string.append(",", 1);
01036 }
01037
01038 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
01039 update_string.append(" WHERE id = ");
01040
01041
01042 ptr= new Statement;
01043
01044 ptr->setString(update_string.length());
01045 if (ptr->getString() == NULL)
01046 {
01047 fprintf(stderr, "Memory Allocation error in creating update\n");
01048 abort();
01049 }
01050 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
01051 ptr->setType(UPDATE_TYPE_REQUIRES_PREFIX);
01052 else
01053 ptr->setType(UPDATE_TYPE);
01054 strncpy(ptr->getString(), update_string.c_str(), ptr->getLength());
01055 return(ptr);
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065 static Statement *
01066 build_insert_string(void)
01067 {
01068 char buf[HUGE_STRING_LENGTH];
01069 uint32_t col_count;
01070 Statement *ptr;
01071 string insert_string;
01072
01073 insert_string.reserve(HUGE_STRING_LENGTH);
01074
01075 insert_string= "INSERT INTO t1 VALUES (";
01076
01077 if (auto_generate_sql_autoincrement)
01078 {
01079 insert_string.append("NULL");
01080
01081 if (num_int_cols || num_char_cols)
01082 insert_string.append(",");
01083 }
01084
01085 if (auto_generate_sql_guid_primary)
01086 {
01087 insert_string.append("uuid()");
01088
01089 if (num_int_cols || num_char_cols)
01090 insert_string.append(",");
01091 }
01092
01093 if (auto_generate_sql_secondary_indexes)
01094 {
01095 uint32_t count;
01096
01097 for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
01098 {
01099 if (count)
01100 insert_string.append(",");
01101
01102 insert_string.append("uuid()");
01103 }
01104
01105 if (num_int_cols || num_char_cols)
01106 insert_string.append(",");
01107 }
01108
01109 if (num_int_cols)
01110 for (col_count= 1; col_count <= num_int_cols; col_count++)
01111 {
01112 if (snprintf(buf, HUGE_STRING_LENGTH, "%ld", random()) > HUGE_STRING_LENGTH)
01113 {
01114 fprintf(stderr, "Memory Allocation error in creating insert\n");
01115 abort();
01116 }
01117 insert_string.append(buf);
01118
01119 if (col_count < num_int_cols || num_char_cols > 0)
01120 insert_string.append(",");
01121 }
01122
01123 if (num_char_cols)
01124 for (col_count= 1; col_count <= num_char_cols; col_count++)
01125 {
01126 int buf_len= get_random_string(buf, RAND_STRING_SIZE);
01127 insert_string.append("'", 1);
01128 insert_string.append(buf, buf_len);
01129 insert_string.append("'", 1);
01130
01131 if (col_count < num_char_cols || num_blob_cols > 0)
01132 insert_string.append(",", 1);
01133 }
01134
01135 if (num_blob_cols)
01136 {
01137 vector <char> blob_ptr;
01138
01139 blob_ptr.resize(num_blob_cols_size);
01140
01141 for (col_count= 1; col_count <= num_blob_cols; col_count++)
01142 {
01143 uint32_t buf_len;
01144 uint32_t size;
01145 uint32_t difference= num_blob_cols_size - num_blob_cols_size_min;
01146
01147 size= difference ? (num_blob_cols_size_min + (random() % difference)) :
01148 num_blob_cols_size;
01149
01150 buf_len= get_random_string(&blob_ptr[0], size);
01151
01152 insert_string.append("'", 1);
01153 insert_string.append(&blob_ptr[0], buf_len);
01154 insert_string.append("'", 1);
01155
01156 if (col_count < num_blob_cols)
01157 insert_string.append(",", 1);
01158 }
01159 }
01160
01161 insert_string.append(")", 1);
01162
01163 ptr= new Statement;
01164 ptr->setString(insert_string.length());
01165 if (ptr->getString()==NULL)
01166 {
01167 fprintf(stderr, "Memory Allocation error in creating select\n");
01168 abort();
01169 }
01170 ptr->setType(INSERT_TYPE);
01171 strcpy(ptr->getString(), insert_string.c_str());
01172 return(ptr);
01173 }
01174
01175
01176
01177
01178
01179
01180
01181
01182 static Statement *
01183 build_select_string(bool key)
01184 {
01185 char buf[HUGE_STRING_LENGTH];
01186 uint32_t col_count;
01187 Statement *ptr;
01188 string query_string;
01189
01190 query_string.reserve(HUGE_STRING_LENGTH);
01191
01192 query_string.append("SELECT ", 7);
01193 if (not auto_generate_selected_columns_opt.empty())
01194 {
01195 query_string.append(auto_generate_selected_columns_opt.c_str());
01196 }
01197 else
01198 {
01199 for (col_count= 1; col_count <= num_int_cols; col_count++)
01200 {
01201 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d", col_count)
01202 > HUGE_STRING_LENGTH)
01203 {
01204 fprintf(stderr, "Memory Allocation error in creating select\n");
01205 abort();
01206 }
01207 query_string.append(buf);
01208
01209 if (col_count < num_int_cols || num_char_cols > 0)
01210 query_string.append(",", 1);
01211
01212 }
01213 for (col_count= 1; col_count <= num_char_cols; col_count++)
01214 {
01215 if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d", col_count)
01216 > HUGE_STRING_LENGTH)
01217 {
01218 fprintf(stderr, "Memory Allocation error in creating select\n");
01219 abort();
01220 }
01221 query_string.append(buf);
01222
01223 if (col_count < num_char_cols || num_blob_cols > 0)
01224 query_string.append(",", 1);
01225
01226 }
01227 for (col_count= 1; col_count <= num_blob_cols; col_count++)
01228 {
01229 if (snprintf(buf, HUGE_STRING_LENGTH, "blobcol%d", col_count)
01230 > HUGE_STRING_LENGTH)
01231 {
01232 fprintf(stderr, "Memory Allocation error in creating select\n");
01233 abort();
01234 }
01235 query_string.append(buf);
01236
01237 if (col_count < num_blob_cols)
01238 query_string.append(",", 1);
01239 }
01240 }
01241 query_string.append(" FROM t1");
01242
01243 if ((key) &&
01244 (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
01245 query_string.append(" WHERE id = ");
01246
01247 ptr= new Statement;
01248 ptr->setString(query_string.length());
01249 if (ptr->getString() == NULL)
01250 {
01251 fprintf(stderr, "Memory Allocation error in creating select\n");
01252 abort();
01253 }
01254 if ((key) &&
01255 (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
01256 ptr->setType(SELECT_TYPE_REQUIRES_PREFIX);
01257 else
01258 ptr->setType(SELECT_TYPE);
01259 strcpy(ptr->getString(), query_string.c_str());
01260 return(ptr);
01261 }
01262
01263 static int
01264 process_options(void)
01265 {
01266 struct stat sbuf;
01267 OptionString *sql_type;
01268 uint32_t sql_type_count= 0;
01269 ssize_t bytes_read= 0;
01270
01271 if (user.empty())
01272 user= "root";
01273
01274 verbose= opt_verbose.length();
01275
01276
01277 if ( (not create_string.empty()) || auto_generate_sql)
01278 opt_preserve= false;
01279
01280 if (auto_generate_sql && (not create_string.empty() || !user_supplied_query.empty()))
01281 {
01282 fprintf(stderr,
01283 "%s: Can't use --auto-generate-sql when create and query strings are specified!\n",
01284 SLAP_NAME);
01285 abort();
01286 }
01287
01288 if (auto_generate_sql && auto_generate_sql_guid_primary &&
01289 auto_generate_sql_autoincrement)
01290 {
01291 fprintf(stderr,
01292 "%s: Either auto-generate-sql-guid-primary or auto-generate-sql-add-autoincrement can be used!\n",
01293 SLAP_NAME);
01294 abort();
01295 }
01296
01297 if (auto_generate_sql && num_of_query && auto_actual_queries)
01298 {
01299 fprintf(stderr,
01300 "%s: Either auto-generate-sql-execute-number or number-of-queries can be used!\n",
01301 SLAP_NAME);
01302 abort();
01303 }
01304
01305 parse_comma(not concurrency_str.empty() ? concurrency_str.c_str() : "1", concurrency);
01306
01307 if (not opt_csv_str.empty())
01308 {
01309 opt_silent= true;
01310
01311 if (opt_csv_str[0] == '-')
01312 {
01313 csv_file= fileno(stdout);
01314 }
01315 else
01316 {
01317 if ((csv_file= open(opt_csv_str.c_str(), O_CREAT|O_WRONLY|O_APPEND,
01318 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
01319 {
01320 fprintf(stderr,"%s: Could not open csv file: %sn\n",
01321 SLAP_NAME, opt_csv_str.c_str());
01322 abort();
01323 }
01324 }
01325 }
01326
01327 if (opt_only_print)
01328 opt_silent= true;
01329
01330 if (not num_int_cols_opt.empty())
01331 {
01332 OptionString *str;
01333 parse_option(num_int_cols_opt.c_str(), &str, ',');
01334 num_int_cols= atoi(str->getString());
01335 if (str->getOption())
01336 num_int_cols_index= atoi(str->getOption());
01337 option_cleanup(str);
01338 }
01339
01340 if (not num_char_cols_opt.empty())
01341 {
01342 OptionString *str;
01343 parse_option(num_char_cols_opt.c_str(), &str, ',');
01344 num_char_cols= atoi(str->getString());
01345 if (str->getOption())
01346 num_char_cols_index= atoi(str->getOption());
01347 else
01348 num_char_cols_index= 0;
01349 option_cleanup(str);
01350 }
01351
01352 if (not num_blob_cols_opt.empty())
01353 {
01354 OptionString *str;
01355 parse_option(num_blob_cols_opt.c_str(), &str, ',');
01356 num_blob_cols= atoi(str->getString());
01357 if (str->getOption())
01358 {
01359 char *sep_ptr;
01360
01361 if ((sep_ptr= strchr(str->getOption(), '/')))
01362 {
01363 num_blob_cols_size_min= atoi(str->getOption());
01364 num_blob_cols_size= atoi(sep_ptr+1);
01365 }
01366 else
01367 {
01368 num_blob_cols_size_min= num_blob_cols_size= atoi(str->getOption());
01369 }
01370 }
01371 else
01372 {
01373 num_blob_cols_size= DEFAULT_BLOB_SIZE;
01374 num_blob_cols_size_min= DEFAULT_BLOB_SIZE;
01375 }
01376 option_cleanup(str);
01377 }
01378
01379
01380 if (auto_generate_sql)
01381 {
01382 uint64_t x= 0;
01383 Statement *ptr_statement;
01384
01385 if (verbose >= 2)
01386 printf("Building Create Statements for Auto\n");
01387
01388 create_statements= build_table_string();
01389
01390
01391
01392 for (ptr_statement= create_statements, x= 0;
01393 x < auto_generate_sql_unique_write_number;
01394 x++, ptr_statement= ptr_statement->getNext())
01395 {
01396 ptr_statement->setNext(build_insert_string());
01397 }
01398
01399 if (verbose >= 2)
01400 printf("Building Query Statements for Auto\n");
01401
01402 if (opt_auto_generate_sql_type.empty())
01403 opt_auto_generate_sql_type= "mixed";
01404
01405 query_statements_count=
01406 parse_option(opt_auto_generate_sql_type.c_str(), &query_options, ',');
01407
01408 query_statements.resize(query_statements_count);
01409
01410 sql_type= query_options;
01411 do
01412 {
01413 if (sql_type->getString()[0] == 'r')
01414 {
01415 if (verbose >= 2)
01416 printf("Generating SELECT Statements for Auto\n");
01417
01418 query_statements[sql_type_count]= build_select_string(false);
01419 for (ptr_statement= query_statements[sql_type_count], x= 0;
01420 x < auto_generate_sql_unique_query_number;
01421 x++, ptr_statement= ptr_statement->getNext())
01422 {
01423 ptr_statement->setNext(build_select_string(false));
01424 }
01425 }
01426 else if (sql_type->getString()[0] == 'k')
01427 {
01428 if (verbose >= 2)
01429 printf("Generating SELECT for keys Statements for Auto\n");
01430
01431 if ( auto_generate_sql_autoincrement == false &&
01432 auto_generate_sql_guid_primary == false)
01433 {
01434 fprintf(stderr,
01435 "%s: Can't perform key test without a primary key!\n",
01436 SLAP_NAME);
01437 abort();
01438 }
01439
01440 query_statements[sql_type_count]= build_select_string(true);
01441 for (ptr_statement= query_statements[sql_type_count], x= 0;
01442 x < auto_generate_sql_unique_query_number;
01443 x++, ptr_statement= ptr_statement->getNext())
01444 {
01445 ptr_statement->setNext(build_select_string(true));
01446 }
01447 }
01448 else if (sql_type->getString()[0] == 'w')
01449 {
01450
01451
01452
01453
01454
01455 if (verbose >= 2)
01456 printf("Generating INSERT Statements for Auto\n");
01457 query_statements[sql_type_count]= build_insert_string();
01458 for (ptr_statement= query_statements[sql_type_count], x= 0;
01459 x < auto_generate_sql_unique_query_number;
01460 x++, ptr_statement= ptr_statement->getNext())
01461 {
01462 ptr_statement->setNext(build_insert_string());
01463 }
01464 }
01465 else if (sql_type->getString()[0] == 'u')
01466 {
01467 if ( auto_generate_sql_autoincrement == false &&
01468 auto_generate_sql_guid_primary == false)
01469 {
01470 fprintf(stderr,
01471 "%s: Can't perform update test without a primary key!\n",
01472 SLAP_NAME);
01473 abort();
01474 }
01475
01476 query_statements[sql_type_count]= build_update_string();
01477 for (ptr_statement= query_statements[sql_type_count], x= 0;
01478 x < auto_generate_sql_unique_query_number;
01479 x++, ptr_statement= ptr_statement->getNext())
01480 {
01481 ptr_statement->setNext(build_update_string());
01482 }
01483 }
01484 else
01485 {
01486 int coin= 0;
01487
01488 query_statements[sql_type_count]= build_insert_string();
01489
01490
01491
01492
01493 for (ptr_statement= query_statements[sql_type_count], x= 0;
01494 x < auto_generate_sql_unique_query_number;
01495 x++, ptr_statement= ptr_statement->getNext())
01496 {
01497 if (coin)
01498 {
01499 ptr_statement->setNext(build_insert_string());
01500 coin= 0;
01501 }
01502 else
01503 {
01504 ptr_statement->setNext(build_select_string(true));
01505 coin= 1;
01506 }
01507 }
01508 }
01509 sql_type_count++;
01510 } while (sql_type ? (sql_type= sql_type->getNext()) : 0);
01511 }
01512 else
01513 {
01514 if (not create_string.empty() && !stat(create_string.c_str(), &sbuf))
01515 {
01516 int data_file;
01517 std::vector<char> tmp_string;
01518 if (not S_ISREG(sbuf.st_mode))
01519 {
01520 fprintf(stderr,"%s: Create file was not a regular file\n",
01521 SLAP_NAME);
01522 abort();
01523 }
01524 if ((data_file= open(create_string.c_str(), O_RDWR)) == -1)
01525 {
01526 fprintf(stderr,"%s: Could not open create file\n", SLAP_NAME);
01527 abort();
01528 }
01529 if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
01530 {
01531 fprintf(stderr, "Request for more memory than architecture supports\n");
01532 abort();
01533 }
01534 tmp_string.resize(sbuf.st_size + 1);
01535 bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
01536 (size_t)sbuf.st_size);
01537 close(data_file);
01538 if (bytes_read != sbuf.st_size)
01539 {
01540 fprintf(stderr, "Problem reading file: read less bytes than requested\n");
01541 }
01542 parse_delimiter(&tmp_string[0], &create_statements, delimiter[0]);
01543 }
01544 else if (not create_string.empty())
01545 {
01546 parse_delimiter(create_string.c_str(), &create_statements, delimiter[0]);
01547 }
01548
01549
01550 if (not user_supplied_query.empty())
01551 {
01552 query_statements_count=
01553 parse_option("default", &query_options, ',');
01554
01555 query_statements.resize(query_statements_count);
01556 }
01557
01558 if (not user_supplied_query.empty() && !stat(user_supplied_query.c_str(), &sbuf))
01559 {
01560 int data_file;
01561 std::vector<char> tmp_string;
01562
01563 if (not S_ISREG(sbuf.st_mode))
01564 {
01565 fprintf(stderr,"%s: User query supplied file was not a regular file\n",
01566 SLAP_NAME);
01567 abort();
01568 }
01569 if ((data_file= open(user_supplied_query.c_str(), O_RDWR)) == -1)
01570 {
01571 fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
01572 abort();
01573 }
01574 if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
01575 {
01576 fprintf(stderr, "Request for more memory than architecture supports\n");
01577 abort();
01578 }
01579 tmp_string.resize((size_t)(sbuf.st_size + 1));
01580 bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
01581 (size_t)sbuf.st_size);
01582 close(data_file);
01583 if (bytes_read != sbuf.st_size)
01584 {
01585 fprintf(stderr, "Problem reading file: read less bytes than requested\n");
01586 }
01587 if (not user_supplied_query.empty())
01588 actual_queries= parse_delimiter(&tmp_string[0], &query_statements[0],
01589 delimiter[0]);
01590 }
01591 else if (not user_supplied_query.empty())
01592 {
01593 actual_queries= parse_delimiter(user_supplied_query.c_str(), &query_statements[0],
01594 delimiter[0]);
01595 }
01596 }
01597
01598 if (not user_supplied_pre_statements.empty()
01599 && !stat(user_supplied_pre_statements.c_str(), &sbuf))
01600 {
01601 int data_file;
01602 std::vector<char> tmp_string;
01603
01604 if (not S_ISREG(sbuf.st_mode))
01605 {
01606 fprintf(stderr,"%s: User query supplied file was not a regular file\n",
01607 SLAP_NAME);
01608 abort();
01609 }
01610 if ((data_file= open(user_supplied_pre_statements.c_str(), O_RDWR)) == -1)
01611 {
01612 fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
01613 abort();
01614 }
01615 if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
01616 {
01617 fprintf(stderr, "Request for more memory than architecture supports\n");
01618 abort();
01619 }
01620 tmp_string.resize((size_t)(sbuf.st_size + 1));
01621 bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
01622 (size_t)sbuf.st_size);
01623 close(data_file);
01624 if (bytes_read != sbuf.st_size)
01625 {
01626 fprintf(stderr, "Problem reading file: read less bytes than requested\n");
01627 }
01628 if (not user_supplied_pre_statements.empty())
01629 (void)parse_delimiter(&tmp_string[0], &pre_statements,
01630 delimiter[0]);
01631 }
01632 else if (not user_supplied_pre_statements.empty())
01633 {
01634 (void)parse_delimiter(user_supplied_pre_statements.c_str(),
01635 &pre_statements,
01636 delimiter[0]);
01637 }
01638
01639 if (not user_supplied_post_statements.empty()
01640 && !stat(user_supplied_post_statements.c_str(), &sbuf))
01641 {
01642 int data_file;
01643 std::vector<char> tmp_string;
01644
01645 if (not S_ISREG(sbuf.st_mode))
01646 {
01647 fprintf(stderr,"%s: User query supplied file was not a regular file\n",
01648 SLAP_NAME);
01649 abort();
01650 }
01651 if ((data_file= open(user_supplied_post_statements.c_str(), O_RDWR)) == -1)
01652 {
01653 fprintf(stderr,"%s: Could not open query supplied file\n", SLAP_NAME);
01654 abort();
01655 }
01656
01657 if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
01658 {
01659 fprintf(stderr, "Request for more memory than architecture supports\n");
01660 abort();
01661 }
01662 tmp_string.resize((size_t)(sbuf.st_size + 1));
01663
01664 bytes_read= read(data_file, (unsigned char*) &tmp_string[0],
01665 (size_t)(sbuf.st_size));
01666 close(data_file);
01667 if (bytes_read != sbuf.st_size)
01668 {
01669 fprintf(stderr, "Problem reading file: read less bytes than requested\n");
01670 }
01671 if (not user_supplied_post_statements.empty())
01672 (void)parse_delimiter(&tmp_string[0], &post_statements,
01673 delimiter[0]);
01674 }
01675 else if (not user_supplied_post_statements.empty())
01676 {
01677 (void)parse_delimiter(user_supplied_post_statements.c_str(), &post_statements,
01678 delimiter[0]);
01679 }
01680
01681 if (verbose >= 2)
01682 printf("Parsing engines to use.\n");
01683
01684 if (not default_engine.empty())
01685 parse_option(default_engine.c_str(), &engine_options, ',');
01686
01687 if (tty_password)
01688 opt_password= client_get_tty_password(NULL);
01689 return(0);
01690 }
01691
01692
01693 static int run_query(drizzle_con_st &con, drizzle_result_st *result,
01694 const char *query, int len)
01695 {
01696 drizzle_return_t ret;
01697 drizzle_result_st result_buffer;
01698
01699 if (opt_only_print)
01700 {
01701 printf("/* CON: %" PRIu64 " */ %.*s;\n",
01702 (uint64_t)drizzle_context(drizzle_con_drizzle(&con)),
01703 len, query);
01704 return 0;
01705 }
01706
01707 if (verbose >= 3)
01708 printf("%.*s;\n", len, query);
01709
01710 if (result == NULL)
01711 result= &result_buffer;
01712
01713 result= drizzle_query(&con, result, query, len, &ret);
01714
01715 if (ret == DRIZZLE_RETURN_OK)
01716 ret= drizzle_result_buffer(result);
01717
01718 if (result == &result_buffer)
01719 drizzle_result_free(result);
01720
01721 return ret;
01722 }
01723
01724
01725 static int
01726 generate_primary_key_list(drizzle_con_st &con, OptionString *engine_stmt)
01727 {
01728 drizzle_result_st result;
01729 drizzle_row_t row;
01730 uint64_t counter;
01731
01732
01733
01734
01735
01736
01737 if (opt_only_print || (engine_stmt &&
01738 strstr(engine_stmt->getString(), "blackhole")))
01739 {
01740
01741 primary_keys.push_back("796c4422-1d94-102a-9d6d-00e0812d");
01742 }
01743 else
01744 {
01745 if (run_query(con, &result, "SELECT id from t1", strlen("SELECT id from t1")))
01746 {
01747 fprintf(stderr,"%s: Cannot select GUID primary keys. (%s)\n", SLAP_NAME,
01748 drizzle_con_error(&con));
01749 abort();
01750 }
01751
01752 uint64_t num_rows_ret= drizzle_result_row_count(&result);
01753 if (num_rows_ret > SIZE_MAX)
01754 {
01755 fprintf(stderr, "More primary keys than than architecture supports\n");
01756 abort();
01757 }
01758 size_t primary_keys_number_of;
01759 primary_keys_number_of= (size_t)num_rows_ret;
01760
01761
01762 if (primary_keys_number_of)
01763 {
01764
01765
01766
01767 row= drizzle_row_next(&result);
01768 for (counter= 0; counter < primary_keys_number_of;
01769 counter++, row= drizzle_row_next(&result))
01770 {
01771 primary_keys.push_back(row[0]);
01772 }
01773 }
01774
01775 drizzle_result_free(&result);
01776 }
01777
01778 return(0);
01779 }
01780
01781 static void create_schema(drizzle_con_st &con, const char *db, Statement *stmt, OptionString *engine_stmt, Stats *sptr)
01782 {
01783 char query[HUGE_STRING_LENGTH];
01784 Statement *ptr;
01785 Statement *after_create;
01786 int len;
01787 struct timeval start_time, end_time;
01788
01789
01790 gettimeofday(&start_time, NULL);
01791
01792 len= snprintf(query, HUGE_STRING_LENGTH, "CREATE SCHEMA `%s`", db);
01793
01794 if (verbose >= 2)
01795 printf("Loading Pre-data\n");
01796
01797 if (run_query(con, NULL, query, len))
01798 {
01799 fprintf(stderr,"%s: Cannot create schema %s : %s\n", SLAP_NAME, db,
01800 drizzle_con_error(&con));
01801 abort();
01802 }
01803 else
01804 {
01805 sptr->setCreateCount(sptr->getCreateCount()+1);
01806 }
01807
01808 if (opt_only_print)
01809 {
01810 printf("/* CON: %" PRIu64 " */ use %s;\n",
01811 (uint64_t)drizzle_context(drizzle_con_drizzle(&con)),
01812 db);
01813 }
01814 else
01815 {
01816 drizzle_result_st result;
01817 drizzle_return_t ret;
01818
01819 if (verbose >= 3)
01820 printf("%s;\n", query);
01821
01822 if (drizzle_select_db(&con, &result, db, &ret) == NULL ||
01823 ret != DRIZZLE_RETURN_OK)
01824 {
01825 fprintf(stderr,"%s: Cannot select schema '%s': %s\n",SLAP_NAME, db,
01826 ret == DRIZZLE_RETURN_ERROR_CODE ?
01827 drizzle_result_error(&result) : drizzle_con_error(&con));
01828 abort();
01829 }
01830 drizzle_result_free(&result);
01831 sptr->setCreateCount(sptr->getCreateCount()+1);
01832 }
01833
01834 if (engine_stmt)
01835 {
01836 len= snprintf(query, HUGE_STRING_LENGTH, "set storage_engine=`%s`",
01837 engine_stmt->getString());
01838 if (run_query(con, NULL, query, len))
01839 {
01840 fprintf(stderr,"%s: Cannot set default engine: %s\n", SLAP_NAME,
01841 drizzle_con_error(&con));
01842 abort();
01843 }
01844 sptr->setCreateCount(sptr->getCreateCount()+1);
01845 }
01846
01847 uint64_t count= 0;
01848 after_create= stmt;
01849
01850 limit_not_met:
01851 for (ptr= after_create; ptr && ptr->getLength(); ptr= ptr->getNext(), count++)
01852 {
01853 if (auto_generate_sql && ( auto_generate_sql_number == count))
01854 break;
01855
01856 if (engine_stmt && engine_stmt->getOption() && ptr->getType() == CREATE_TABLE_TYPE)
01857 {
01858 char buffer[HUGE_STRING_LENGTH];
01859
01860 snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->getString(),
01861 engine_stmt->getOption());
01862 if (run_query(con, NULL, buffer, strlen(buffer)))
01863 {
01864 fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
01865 SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
01866 if (not opt_ignore_sql_errors)
01867 abort();
01868 }
01869 sptr->setCreateCount(sptr->getCreateCount()+1);
01870 }
01871 else
01872 {
01873 if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
01874 {
01875 fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
01876 SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
01877 if (not opt_ignore_sql_errors)
01878 abort();
01879 }
01880 sptr->setCreateCount(sptr->getCreateCount()+1);
01881 }
01882 }
01883
01884 if (auto_generate_sql && (auto_generate_sql_number > count ))
01885 {
01886
01887 after_create= stmt->getNext();
01888 goto limit_not_met;
01889 }
01890
01891 gettimeofday(&end_time, NULL);
01892
01893 sptr->setCreateTiming(timedif(end_time, start_time));
01894 }
01895
01896 static void drop_schema(drizzle_con_st &con, const char *db)
01897 {
01898 char query[HUGE_STRING_LENGTH];
01899 int len;
01900
01901 len= snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS `%s`", db);
01902
01903 if (run_query(con, NULL, query, len))
01904 {
01905 fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
01906 SLAP_NAME, db, drizzle_con_error(&con));
01907 abort();
01908 }
01909 }
01910
01911 static void run_statements(drizzle_con_st &con, Statement *stmt)
01912 {
01913 for (Statement *ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
01914 {
01915 if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
01916 {
01917 fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
01918 SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
01919 abort();
01920 }
01921 }
01922 }
01923
01924
01925 static void timer_thread()
01926 {
01927
01928
01929
01930
01931 master_wakeup.wait();
01932
01933 {
01934 boost::mutex::scoped_lock scopedLock(timer_alarm_mutex);
01935
01936 boost::xtime xt;
01937 xtime_get(&xt, boost::TIME_UTC);
01938 xt.sec += opt_timer_length;
01939
01940 (void)timer_alarm_threshold.timed_wait(scopedLock, xt);
01941 }
01942
01943 {
01944 boost::mutex::scoped_lock scopedLock(timer_alarm_mutex);
01945 timer_alarm= false;
01946 }
01947 }
01948
01949 typedef boost::shared_ptr<boost::thread> Thread;
01950 typedef std::vector <Thread> Threads;
01951 static void run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit)
01952 {
01953 uint32_t real_concurrency;
01954 struct timeval start_time, end_time;
01955
01956 Threads threads;
01957
01958 {
01959 OptionString *sql_type;
01960
01961 master_wakeup.reset();
01962
01963 real_concurrency= 0;
01964
01965 uint32_t y;
01966 for (y= 0, sql_type= query_options;
01967 y < query_statements_count;
01968 y++, sql_type= sql_type->getNext())
01969 {
01970 uint32_t options_loop= 1;
01971
01972 if (sql_type->getOption())
01973 {
01974 options_loop= strtol(sql_type->getOption(),
01975 (char **)NULL, 10);
01976 options_loop= options_loop ? options_loop : 1;
01977 }
01978
01979 while (options_loop--)
01980 {
01981 for (uint32_t x= 0; x < concur; x++)
01982 {
01983 ThreadContext *con;
01984 con= new ThreadContext;
01985 if (con == NULL)
01986 {
01987 fprintf(stderr, "Memory Allocation error in scheduler\n");
01988 abort();
01989 }
01990 con->setStmt(stmts[y]);
01991 con->setLimit(limit);
01992
01993 real_concurrency++;
01994
01995
01996 Thread thread;
01997 thread= Thread(new boost::thread(boost::bind(&run_task, con)));
01998 threads.push_back(thread);
01999
02000 }
02001 }
02002 }
02003
02004
02005
02006
02007
02008 if (opt_timer_length)
02009 {
02010 {
02011 boost::mutex::scoped_lock alarmLock(timer_alarm_mutex);
02012 timer_alarm= true;
02013 }
02014
02015 Thread thread;
02016 thread= Thread(new boost::thread(&timer_thread));
02017 threads.push_back(thread);
02018 }
02019 }
02020
02021 master_wakeup.start();
02022
02023 gettimeofday(&start_time, NULL);
02024
02025
02026
02027
02028 for (Threads::iterator iter= threads.begin(); iter != threads.end(); iter++)
02029 {
02030 (*iter)->join();
02031 }
02032
02033 gettimeofday(&end_time, NULL);
02034
02035 sptr->setTiming(timedif(end_time, start_time));
02036 sptr->setUsers(concur);
02037 sptr->setRealUsers(real_concurrency);
02038 sptr->setRows(limit);
02039 }
02040
02041
02042
02043
02044
02045 uint32_t parse_option(const char *origin, OptionString **stmt, char delm)
02046 {
02047 char *string;
02048 char *begin_ptr;
02049 char *end_ptr;
02050 uint32_t length= strlen(origin);
02051 uint32_t count= 0;
02052
02053 end_ptr= (char *)origin + length;
02054
02055 OptionString *tmp;
02056 *stmt= tmp= new OptionString;
02057
02058 for (begin_ptr= (char *)origin;
02059 begin_ptr != end_ptr;
02060 tmp= tmp->getNext())
02061 {
02062 char buffer[HUGE_STRING_LENGTH];
02063 char *buffer_ptr;
02064
02065 memset(buffer, 0, HUGE_STRING_LENGTH);
02066
02067 string= strchr(begin_ptr, delm);
02068
02069 if (string)
02070 {
02071 memcpy(buffer, begin_ptr, string - begin_ptr);
02072 begin_ptr= string+1;
02073 }
02074 else
02075 {
02076 size_t begin_len= strlen(begin_ptr);
02077 memcpy(buffer, begin_ptr, begin_len);
02078 begin_ptr= end_ptr;
02079 }
02080
02081 if ((buffer_ptr= strchr(buffer, ':')))
02082 {
02083
02084 buffer_ptr[0]= 0;
02085 buffer_ptr++;
02086
02087
02088 tmp->setOption(buffer_ptr);
02089 }
02090
02091 tmp->setString(strdup(buffer));
02092 if (tmp->getString() == NULL)
02093 {
02094 fprintf(stderr,"Error allocating memory while parsing options\n");
02095 abort();
02096 }
02097
02098 if (isspace(*begin_ptr))
02099 begin_ptr++;
02100
02101 count++;
02102
02103 if (begin_ptr != end_ptr)
02104 {
02105 tmp->setNext( new OptionString);
02106 }
02107
02108 }
02109
02110 return count;
02111 }
02112
02113
02114
02115
02116
02117
02118 uint32_t parse_delimiter(const char *script, Statement **stmt, char delm)
02119 {
02120 char *retstr;
02121 char *ptr= (char *)script;
02122 Statement **sptr= stmt;
02123 Statement *tmp;
02124 uint32_t length= strlen(script);
02125 uint32_t count= 0;
02126
02127 for (tmp= *sptr= new Statement;
02128 (retstr= strchr(ptr, delm));
02129 tmp->setNext(new Statement),
02130 tmp= tmp->getNext())
02131 {
02132 if (tmp == NULL)
02133 {
02134 fprintf(stderr,"Error allocating memory while parsing delimiter\n");
02135 abort();
02136 }
02137
02138 count++;
02139 tmp->setString((size_t)(retstr - ptr));
02140
02141 if (tmp->getString() == NULL)
02142 {
02143 fprintf(stderr,"Error allocating memory while parsing delimiter\n");
02144 abort();
02145 }
02146
02147 memcpy(tmp->getString(), ptr, tmp->getLength());
02148 ptr+= retstr - ptr + 1;
02149 if (isspace(*ptr))
02150 ptr++;
02151 }
02152
02153 if (ptr != script+length)
02154 {
02155 tmp->setString((size_t)((script + length) - ptr));
02156 if (tmp->getString() == NULL)
02157 {
02158 fprintf(stderr,"Error allocating memory while parsing delimiter\n");
02159 abort();
02160 }
02161 memcpy(tmp->getString(), ptr, tmp->getLength());
02162 count++;
02163 }
02164
02165 return count;
02166 }
02167
02168
02169
02170
02171
02172
02173
02174 uint32_t parse_comma(const char *string, std::vector <uint32_t> &range)
02175 {
02176 uint32_t count= 1;
02177 char *retstr;
02178 char *ptr= (char *)string;
02179 uint32_t *nptr;
02180
02181 for (;*ptr; ptr++)
02182 if (*ptr == ',') count++;
02183
02184
02185 range.resize(count +1);
02186 nptr= &range[0];
02187
02188 ptr= (char *)string;
02189 uint32_t x= 0;
02190 while ((retstr= strchr(ptr,',')))
02191 {
02192 nptr[x++]= atoi(ptr);
02193 ptr+= retstr - ptr + 1;
02194 }
02195 nptr[x++]= atoi(ptr);
02196
02197 return count;
02198 }
02199
02200 void print_conclusions(Conclusions &con)
02201 {
02202 printf("Benchmark\n");
02203 if (con.getEngine())
02204 printf("\tRunning for engine %s\n", con.getEngine());
02205
02206 if (not opt_label.empty() || !opt_auto_generate_sql_type.empty())
02207 {
02208 const char *ptr= opt_auto_generate_sql_type.c_str() ? opt_auto_generate_sql_type.c_str() : "query";
02209 printf("\tLoad: %s\n", !opt_label.empty() ? opt_label.c_str() : ptr);
02210 }
02211 printf("\tAverage Time took to generate schema and initial data: %ld.%03ld seconds\n",
02212 con.getCreateAvgTiming() / 1000, con.getCreateAvgTiming() % 1000);
02213 printf("\tAverage number of seconds to run all queries: %ld.%03ld seconds\n",
02214 con.getAvgTiming() / 1000, con.getAvgTiming() % 1000);
02215 printf("\tMinimum number of seconds to run all queries: %ld.%03ld seconds\n",
02216 con.getMinTiming() / 1000, con.getMinTiming() % 1000);
02217 printf("\tMaximum number of seconds to run all queries: %ld.%03ld seconds\n",
02218 con.getMaxTiming() / 1000, con.getMaxTiming() % 1000);
02219 printf("\tTotal time for tests: %ld.%03ld seconds\n",
02220 con.getSumOfTime() / 1000, con.getSumOfTime() % 1000);
02221 printf("\tStandard Deviation: %ld.%03ld\n", con.getStdDev() / 1000, con.getStdDev() % 1000);
02222 printf("\tNumber of queries in create queries: %"PRIu64"\n", con.getCreateCount());
02223 printf("\tNumber of clients running queries: %u/%u\n",
02224 con.getUsers(), con.getRealUsers());
02225 printf("\tNumber of times test was run: %u\n", iterations);
02226 printf("\tAverage number of queries per client: %"PRIu64"\n", con.getAvgRows());
02227
02228 uint64_t temp_val= failed_update_for_transaction;
02229 if (temp_val)
02230 printf("\tFailed number of updates %"PRIu64"\n", temp_val);
02231
02232 printf("\n");
02233 }
02234
02235 void print_conclusions_csv(Conclusions &con)
02236 {
02237 char buffer[HUGE_STRING_LENGTH];
02238 char label_buffer[HUGE_STRING_LENGTH];
02239 size_t string_len;
02240 const char *temp_label= opt_label.c_str();
02241
02242 memset(label_buffer, 0, sizeof(label_buffer));
02243
02244 if (not opt_label.empty())
02245 {
02246 string_len= opt_label.length();
02247
02248 for (uint32_t x= 0; x < string_len; x++)
02249 {
02250 if (temp_label[x] == ',')
02251 label_buffer[x]= '-';
02252 else
02253 label_buffer[x]= temp_label[x] ;
02254 }
02255 }
02256 else if (not opt_auto_generate_sql_type.empty())
02257 {
02258 string_len= opt_auto_generate_sql_type.length();
02259
02260 for (uint32_t x= 0; x < string_len; x++)
02261 {
02262 if (opt_auto_generate_sql_type[x] == ',')
02263 label_buffer[x]= '-';
02264 else
02265 label_buffer[x]= opt_auto_generate_sql_type[x] ;
02266 }
02267 }
02268 else
02269 {
02270 snprintf(label_buffer, HUGE_STRING_LENGTH, "query");
02271 }
02272
02273 snprintf(buffer, HUGE_STRING_LENGTH,
02274 "%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,"
02275 "%u,%u,%u,%"PRIu64"\n",
02276 con.getEngine() ? con.getEngine() : "",
02277 label_buffer,
02278 con.getAvgTiming() / 1000, con.getAvgTiming() % 1000,
02279 con.getMinTiming() / 1000, con.getMinTiming() % 1000,
02280 con.getMaxTiming() / 1000, con.getMaxTiming() % 1000,
02281 con.getSumOfTime() / 1000, con.getSumOfTime() % 1000,
02282 con.getStdDev() / 1000, con.getStdDev() % 1000,
02283 iterations,
02284 con.getUsers(),
02285 con.getRealUsers(),
02286 con.getAvgRows()
02287 );
02288 size_t buff_len= strlen(buffer);
02289 ssize_t write_ret= write(csv_file, (unsigned char*) buffer, buff_len);
02290 if (write_ret != (ssize_t)buff_len)
02291 {
02292 fprintf(stderr, _("Unable to fully write %"PRIu64" bytes. "
02293 "Could only write %"PRId64"."), (uint64_t)write_ret,
02294 (int64_t)buff_len);
02295 exit(-1);
02296 }
02297 }
02298
02299 void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr)
02300 {
02301 Stats *ptr;
02302 uint32_t x;
02303
02304 con->setMinTiming(sptr->getTiming());
02305 con->setMaxTiming(sptr->getTiming());
02306 con->setMinRows(sptr->getRows());
02307 con->setMaxRows(sptr->getRows());
02308
02309
02310 con->setUsers(sptr->getUsers());
02311 con->setRealUsers(sptr->getRealUsers());
02312 con->setAvgRows(sptr->getRows());
02313
02314
02315 for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
02316 {
02317 con->setAvgTiming(ptr->getTiming()+con->getAvgTiming());
02318
02319 if (ptr->getTiming() > con->getMaxTiming())
02320 con->setMaxTiming(ptr->getTiming());
02321 if (ptr->getTiming() < con->getMinTiming())
02322 con->setMinTiming(ptr->getTiming());
02323 }
02324 con->setSumOfTime(con->getAvgTiming());
02325 con->setAvgTiming(con->getAvgTiming()/iterations);
02326
02327 if (eng && eng->getString())
02328 con->setEngine(eng->getString());
02329 else
02330 con->setEngine(NULL);
02331
02332 standard_deviation(*con, sptr);
02333
02334
02335 con->setCreateMinTiming(sptr->getCreateTiming());
02336 con->setCreateMaxTiming(sptr->getCreateTiming());
02337
02338
02339 con->setCreateCount(sptr->getCreateCount());
02340
02341
02342 for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
02343 {
02344 con->setCreateAvgTiming(ptr->getCreateTiming()+con->getCreateAvgTiming());
02345
02346 if (ptr->getCreateTiming() > con->getCreateMaxTiming())
02347 con->setCreateMaxTiming(ptr->getCreateTiming());
02348 if (ptr->getCreateTiming() < con->getCreateMinTiming())
02349 con->setCreateMinTiming(ptr->getCreateTiming());
02350 }
02351 con->setCreateAvgTiming(con->getCreateAvgTiming()/iterations);
02352 }
02353
02354 void
02355 option_cleanup(OptionString *stmt)
02356 {
02357 OptionString *ptr, *nptr;
02358 if (not stmt)
02359 return;
02360
02361 for (ptr= stmt; ptr; ptr= nptr)
02362 {
02363 nptr= ptr->getNext();
02364 delete ptr;
02365 }
02366 }
02367
02368 void statement_cleanup(Statement *stmt)
02369 {
02370 Statement *ptr, *nptr;
02371 if (not stmt)
02372 return;
02373
02374 for (ptr= stmt; ptr; ptr= nptr)
02375 {
02376 nptr= ptr->getNext();
02377 delete ptr;
02378 }
02379 }
02380
02381 void slap_close(drizzle_con_st &con)
02382 {
02383 drizzle_free(drizzle_con_drizzle(&con));
02384 }
02385
02386 void slap_connect(drizzle_con_st &con, bool connect_to_schema)
02387 {
02388
02389 static uint32_t connection_retry_sleep= 100000;
02390 int connect_error= 1;
02391 drizzle_return_t ret;
02392 drizzle_st *drizzle;
02393
02394 if (opt_delayed_start)
02395 usleep(random()%opt_delayed_start);
02396
02397 if ((drizzle= drizzle_create(NULL)) == NULL ||
02398 drizzle_con_add_tcp(drizzle, &con, host.c_str(), opt_drizzle_port,
02399 user.c_str(),
02400 opt_password.c_str(),
02401 connect_to_schema ? create_schema_string.c_str() : NULL,
02402 use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL) == NULL)
02403 {
02404 fprintf(stderr,"%s: Error creating drizzle object\n", SLAP_NAME);
02405 abort();
02406 }
02407
02408 drizzle_set_context(drizzle, (void*)(connection_count.fetch_and_increment()));
02409
02410 if (opt_only_print)
02411 return;
02412
02413 for (uint32_t x= 0; x < 10; x++)
02414 {
02415 if ((ret= drizzle_con_connect(&con)) == DRIZZLE_RETURN_OK)
02416 {
02417
02418 connect_error= 0;
02419 break;
02420 }
02421 usleep(connection_retry_sleep);
02422 }
02423 if (connect_error)
02424 {
02425 fprintf(stderr,"%s: Error when connecting to server: %d %s\n", SLAP_NAME,
02426 ret, drizzle_con_error(&con));
02427 abort();
02428 }
02429 }
02430
02431 void standard_deviation(Conclusions &con, Stats *sptr)
02432 {
02433 long int sum_of_squares;
02434 double the_catch;
02435 Stats *ptr;
02436
02437 if (iterations == 1 || iterations == 0)
02438 {
02439 con.setStdDev(0);
02440 return;
02441 }
02442
02443 uint32_t x;
02444 for (ptr= sptr, x= 0, sum_of_squares= 0; x < iterations; ptr++, x++)
02445 {
02446 long int deviation;
02447
02448 deviation= ptr->getTiming() - con.getAvgTiming();
02449 sum_of_squares+= deviation*deviation;
02450 }
02451
02452 the_catch= sqrt((double)(sum_of_squares/(iterations -1)));
02453 con.setStdDev((long int)the_catch);
02454 }