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/client_priv.h"
00076
00077 #include "client/option_string.h"
00078 #include "client/stats.h"
00079 #include "client/thread_context.h"
00080 #include "client/conclusions.h"
00081 #include "client/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/algorithm/string.hpp>
00104 #include <boost/thread.hpp>
00105 #include <boost/thread/mutex.hpp>
00106 #include <boost/thread/condition_variable.hpp>
00107 #include <boost/program_options.hpp>
00108 #include <boost/scoped_ptr.hpp>
00109 #include <drizzled/atomics.h>
00110
00111 #define SLAP_NAME "drizzleslap"
00112 #define SLAP_VERSION "1.5"
00113
00114 #define HUGE_STRING_LENGTH 8196
00115 #define RAND_STRING_SIZE 126
00116 #define DEFAULT_BLOB_SIZE 1024
00117
00118 using namespace std;
00119 using namespace drizzled;
00120 namespace po= boost::program_options;
00121
00122 #ifdef HAVE_SMEM
00123 static char *shared_memory_base_name=0;
00124 #endif
00125
00126 client::Wakeup master_wakeup;
00127
00128
00129 static bool timer_alarm= false;
00130 boost::mutex timer_alarm_mutex;
00131 boost::condition_variable_any timer_alarm_threshold;
00132
00133 std::vector < std::string > primary_keys;
00134
00135 drizzled::atomic<size_t> connection_count;
00136 drizzled::atomic<uint64_t> failed_update_for_transaction;
00137
00138 static string host,
00139 opt_password,
00140 user,
00141 user_supplied_query,
00142 user_supplied_pre_statements,
00143 user_supplied_post_statements,
00144 default_engine,
00145 pre_system,
00146 post_system;
00147
00148 static vector<string> user_supplied_queries;
00149 static string opt_verbose;
00150 std::string opt_protocol;
00151 string delimiter;
00152
00153 string create_schema_string;
00154
00155 static bool use_drizzle_protocol= false;
00156 static bool opt_preserve= true;
00157 static bool opt_only_print;
00158 static bool opt_burnin;
00159 static bool opt_ignore_sql_errors= false;
00160 static bool opt_silent,
00161 auto_generate_sql_autoincrement,
00162 auto_generate_sql_guid_primary,
00163 auto_generate_sql;
00164 std::string opt_auto_generate_sql_type;
00165
00166 static int32_t verbose= 0;
00167 static uint32_t delimiter_length;
00168 static uint32_t commit_rate;
00169 static uint32_t detach_rate;
00170 static uint32_t opt_timer_length;
00171 static uint32_t opt_delayed_start;
00172 string num_blob_cols_opt,
00173 num_char_cols_opt,
00174 num_int_cols_opt;
00175 string opt_label;
00176 static uint32_t opt_set_random_seed;
00177
00178 string auto_generate_selected_columns_opt;
00179
00180
00181 static uint32_t num_int_cols= 1;
00182 static uint32_t num_char_cols= 1;
00183 static uint32_t num_blob_cols= 0;
00184 static uint32_t num_blob_cols_size;
00185 static uint32_t num_blob_cols_size_min;
00186 static uint32_t num_int_cols_index= 0;
00187 static uint32_t num_char_cols_index= 0;
00188 static uint32_t iterations;
00189 static uint64_t actual_queries= 0;
00190 static uint64_t auto_actual_queries;
00191 static uint64_t auto_generate_sql_unique_write_number;
00192 static uint64_t auto_generate_sql_unique_query_number;
00193 static uint32_t auto_generate_sql_secondary_indexes;
00194 static uint64_t num_of_query;
00195 static uint64_t auto_generate_sql_number;
00196 string concurrency_str;
00197 string create_string;
00198 std::vector <uint32_t> concurrency;
00199
00200 std::string opt_csv_str;
00201 int csv_file;
00202
00203 static int process_options(void);
00204 static uint32_t opt_drizzle_port= 0;
00205
00206 static OptionString *engine_options= NULL;
00207 static OptionString *query_options= NULL;
00208 static Statement *pre_statements= NULL;
00209 static Statement *post_statements= NULL;
00210 static Statement *create_statements= NULL;
00211
00212 static std::vector <Statement *> query_statements;
00213 static uint32_t query_statements_count;
00214
00215
00216
00217 void print_conclusions(Conclusions &con);
00218 void print_conclusions_csv(Conclusions &con);
00219 void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr);
00220 uint32_t parse_comma(const char *string, std::vector <uint32_t> &range);
00221 uint32_t parse_delimiter(const char *script, Statement **stmt, char delm);
00222 uint32_t parse_option(const char *origin, OptionString **stmt, char delm);
00223 static void drop_schema(drizzle_con_st &con, const char *db);
00224 uint32_t get_random_string(char *buf, size_t size);
00225 static Statement *build_table_string(void);
00226 static Statement *build_insert_string(void);
00227 static Statement *build_update_string(void);
00228 static Statement * build_select_string(bool key);
00229 static int generate_primary_key_list(drizzle_con_st &con, OptionString *engine_stmt);
00230 static void create_schema(drizzle_con_st &con, const char *db, Statement *stmt, OptionString *engine_stmt, Stats *sptr);
00231 static void run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit);
00232 void statement_cleanup(Statement *stmt);
00233 void option_cleanup(OptionString *stmt);
00234 void concurrency_loop(drizzle_con_st &con, uint32_t current, OptionString *eptr);
00235 static void run_statements(drizzle_con_st &con, Statement *stmt);
00236 drizzle_con_st *slap_connect(bool connect_to_schema);
00237 void slap_close(drizzle_con_st *con);
00238 static int run_query(drizzle_con_st &con, drizzle_result_st *result, const char *query, int len);
00239 void standard_deviation(Conclusions &con, Stats *sptr);
00240
00241 static const char ALPHANUMERICS[]=
00242 "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
00243
00244 #define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
00245
00246
00247 static long int timedif(struct timeval a, struct timeval b)
00248 {
00249 int us, s;
00250
00251 us = a.tv_usec - b.tv_usec;
00252 us /= 1000;
00253 s = a.tv_sec - b.tv_sec;
00254 s *= 1000;
00255 return s + us;
00256 }
00257
00258 static void combine_queries(vector<string> queries)
00259 {
00260 user_supplied_query.erase();
00261 for (vector<string>::iterator it= queries.begin();
00262 it != queries.end();
00263 ++it)
00264 {
00265 user_supplied_query.append(*it);
00266 user_supplied_query.append(delimiter);
00267 }
00268 }
00269
00270
00271 static void run_task(ThreadContext *ctx)
00272 {
00273 uint64_t counter= 0, queries;
00274 uint64_t detach_counter;
00275 uint32_t commit_counter;
00276 drizzle_result_st result;
00277 drizzle_row_t row;
00278 Statement *ptr;
00279
00280 master_wakeup.wait();
00281
00282 drizzle_con_st *con= slap_connect(true);
00283
00284 if (verbose >= 3)
00285 {
00286 printf("connected!\n");
00287 }
00288 queries= 0;
00289
00290 commit_counter= 0;
00291 if (commit_rate)
00292 {
00293 run_query(*con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
00294 }
00295
00296 limit_not_met:
00297 for (ptr= ctx->getStmt(), detach_counter= 0;
00298 ptr && ptr->getLength();
00299 ptr= ptr->getNext(), detach_counter++)
00300 {
00301 if (not opt_only_print && detach_rate && !(detach_counter % detach_rate))
00302 {
00303 slap_close(con);
00304 con= slap_connect(true);
00305 }
00306
00307
00308
00309
00310 bool is_failed_update= false;
00311 if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
00312 (ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
00313 {
00314 uint32_t key_val;
00315 char buffer[HUGE_STRING_LENGTH];
00316
00317
00318
00319
00320
00321
00322
00323
00324 assert(primary_keys.size());
00325 if (primary_keys.size())
00326 {
00327 key_val= (uint32_t)(random() % primary_keys.size());
00328 const char *key= primary_keys[key_val].c_str();
00329
00330 assert(key);
00331
00332 int length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'", (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 {
00407 run_query(*con, NULL, "COMMIT", strlen("COMMIT"));
00408 }
00409
00410 slap_close(con);
00411 con= NULL;
00412
00413 delete ctx;
00414 }
00415
00434 int main(int argc, char **argv)
00435 {
00436 char *password= NULL;
00437 try
00438 {
00439 po::options_description commandline_options("Options used only in command line");
00440 commandline_options.add_options()
00441 ("help,?","Display this help and exit")
00442 ("info","Gives information and exit")
00443 ("burnin",po::value<bool>(&opt_burnin)->default_value(false)->zero_tokens(),
00444 "Run full test case in infinite loop")
00445 ("ignore-sql-errors", po::value<bool>(&opt_ignore_sql_errors)->default_value(false)->zero_tokens(),
00446 "Ignore SQL errors in query run")
00447 ("create-schema",po::value<string>(&create_schema_string)->default_value("drizzleslap"),
00448 "Schema to run tests in")
00449 ("create",po::value<string>(&create_string)->default_value(""),
00450 "File or string to use to create tables")
00451 ("detach",po::value<uint32_t>(&detach_rate)->default_value(0),
00452 "Detach (close and re open) connections after X number of requests")
00453 ("iterations,i",po::value<uint32_t>(&iterations)->default_value(1),
00454 "Number of times to run the tests")
00455 ("label",po::value<string>(&opt_label)->default_value(""),
00456 "Label to use for print and csv")
00457 ("number-blob-cols",po::value<string>(&num_blob_cols_opt)->default_value(""),
00458 "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. ")
00459 ("number-char-cols,x",po::value<string>(&num_char_cols_opt)->default_value(""),
00460 "Number of VARCHAR columns to create in table if specifying --auto-generate-sql.")
00461 ("number-int-cols,y",po::value<string>(&num_int_cols_opt)->default_value(""),
00462 "Number of INT columns to create in table if specifying --auto-generate-sql.")
00463 ("number-of-queries",
00464 po::value<uint64_t>(&num_of_query)->default_value(0),
00465 "Limit each client to this number of queries(this is not exact)")
00466 ("only-print",po::value<bool>(&opt_only_print)->default_value(false)->zero_tokens(),
00467 "This causes drizzleslap to not connect to the database instead print out what it would have done instead")
00468 ("post-query", po::value<string>(&user_supplied_post_statements)->default_value(""),
00469 "Query to run or file containing query to execute after tests have completed.")
00470 ("post-system",po::value<string>(&post_system)->default_value(""),
00471 "system() string to execute after tests have completed")
00472 ("pre-query",
00473 po::value<string>(&user_supplied_pre_statements)->default_value(""),
00474 "Query to run or file containing query to execute before running tests.")
00475 ("pre-system",po::value<string>(&pre_system)->default_value(""),
00476 "system() string to execute before running tests.")
00477 ("query,q",po::value<vector<string> >(&user_supplied_queries)->composing()->notifier(&combine_queries),
00478 "Query to run or file containing query")
00479 ("verbose,v", po::value<string>(&opt_verbose)->default_value("v"), "Increase verbosity level by one.")
00480 ("version,V","Output version information and exit")
00481 ;
00482
00483 po::options_description slap_options("Options specific to drizzleslap");
00484 slap_options.add_options()
00485 ("auto-generate-sql-select-columns",
00486 po::value<string>(&auto_generate_selected_columns_opt)->default_value(""),
00487 "Provide a string to use for the select fields used in auto tests")
00488 ("auto-generate-sql,a",po::value<bool>(&auto_generate_sql)->default_value(false)->zero_tokens(),
00489 "Generate SQL where not supplied by file or command line")
00490 ("auto-generate-sql-add-autoincrement",
00491 po::value<bool>(&auto_generate_sql_autoincrement)->default_value(false)->zero_tokens(),
00492 "Add an AUTO_INCREMENT column to auto-generated tables")
00493 ("auto-generate-sql-execute-number",
00494 po::value<uint64_t>(&auto_actual_queries)->default_value(0),
00495 "See this number and generate a set of queries to run")
00496 ("auto-generate-sql-guid-primary",
00497 po::value<bool>(&auto_generate_sql_guid_primary)->default_value(false)->zero_tokens(),
00498 "Add GUID based primary keys to auto-generated tables")
00499 ("auto-generate-sql-load-type",
00500 po::value<string>(&opt_auto_generate_sql_type)->default_value("mixed"),
00501 "Specify test load type: mixed, update, write, key or read; default is mixed")
00502 ("auto-generate-sql-secondary-indexes",
00503 po::value<uint32_t>(&auto_generate_sql_secondary_indexes)->default_value(0),
00504 "Number of secondary indexes to add to auto-generated tables")
00505 ("auto-generated-sql-unique-query-number",
00506 po::value<uint64_t>(&auto_generate_sql_unique_query_number)->default_value(10),
00507 "Number of unique queries to generate for automatic tests")
00508 ("auto-generate-sql-unique-write-number",
00509 po::value<uint64_t>(&auto_generate_sql_unique_write_number)->default_value(10),
00510 "Number of unique queries to generate for auto-generate-sql-write-number")
00511 ("auto-generate-sql-write-number",
00512 po::value<uint64_t>(&auto_generate_sql_number)->default_value(100),
00513 "Number of row inserts to perform for each thread (default is 100).")
00514 ("commit",po::value<uint32_t>(&commit_rate)->default_value(0),
00515 "Commit records every X number of statements")
00516 ("concurrency,c",po::value<string>(&concurrency_str)->default_value(""),
00517 "Number of clients to simulate for query to run")
00518 ("csv",po::value<std::string>(&opt_csv_str)->default_value(""),
00519 "Generate CSV output to named file or to stdout if no file is name.")
00520 ("delayed-start",po::value<uint32_t>(&opt_delayed_start)->default_value(0),
00521 "Delay the startup of threads by a random number of microsends (the maximum of the delay")
00522 ("delimiter,F",po::value<string>(&delimiter)->default_value("\n"),
00523 "Delimiter to use in SQL statements supplied in file or command line")
00524 ("engine,e",po::value<string>(&default_engine)->default_value(""),
00525 "Storage engine to use for creating the table")
00526 ("set-random-seed",
00527 po::value<uint32_t>(&opt_set_random_seed)->default_value(0),
00528 "Seed for random number generator (srandom(3)) ")
00529 ("silent,s",po::value<bool>(&opt_silent)->default_value(false)->zero_tokens(),
00530 "Run program in silent mode - no output. ")
00531 ("timer-length",po::value<uint32_t>(&opt_timer_length)->default_value(0),
00532 "Require drizzleslap to run each specific test a certain amount of time in seconds")
00533 ;
00534
00535 po::options_description client_options("Options specific to the client");
00536 client_options.add_options()
00537 ("host,h",po::value<string>(&host)->default_value("localhost"),"Connect to the host")
00538 ("password,P",po::value<char *>(&password),
00539 "Password to use when connecting to server. If password is not given it's asked from the tty")
00540 ("port,p",po::value<uint32_t>(), "Port number to use for connection")
00541 ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
00542 "The protocol of connection (mysql or drizzle).")
00543 ("user,u",po::value<string>(&user)->default_value(""),
00544 "User for login if not current user")
00545 ;
00546
00547 po::options_description long_options("Allowed Options");
00548 long_options.add(commandline_options).add(slap_options).add(client_options);
00549
00550 std::string system_config_dir_slap(SYSCONFDIR);
00551 system_config_dir_slap.append("/drizzle/drizzleslap.cnf");
00552
00553 std::string system_config_dir_client(SYSCONFDIR);
00554 system_config_dir_client.append("/drizzle/client.cnf");
00555
00556 std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
00557
00558 if (user_config_dir.compare(0, 2, "~/") == 0)
00559 {
00560 char *homedir;
00561 homedir= getenv("HOME");
00562 if (homedir != NULL)
00563 user_config_dir.replace(0, 1, homedir);
00564 }
00565
00566 uint64_t temp_drizzle_port= 0;
00567 boost::scoped_ptr<drizzle_con_st> con_ap(new drizzle_con_st);
00568 OptionString *eptr;
00569
00570
00571 int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
00572
00573 po::variables_map vm;
00574 po::store(po::command_line_parser(argc, argv).options(long_options).
00575 style(style).extra_parser(parse_password_arg).run(), vm);
00576
00577 std::string user_config_dir_slap(user_config_dir);
00578 user_config_dir_slap.append("/drizzle/drizzleslap.cnf");
00579
00580 std::string user_config_dir_client(user_config_dir);
00581 user_config_dir_client.append("/drizzle/client.cnf");
00582
00583 ifstream user_slap_ifs(user_config_dir_slap.c_str());
00584 po::store(parse_config_file(user_slap_ifs, slap_options), vm);
00585
00586 ifstream user_client_ifs(user_config_dir_client.c_str());
00587 po::store(parse_config_file(user_client_ifs, client_options), vm);
00588
00589 ifstream system_slap_ifs(system_config_dir_slap.c_str());
00590 store(parse_config_file(system_slap_ifs, slap_options), vm);
00591
00592 ifstream system_client_ifs(system_config_dir_client.c_str());
00593 store(parse_config_file(system_client_ifs, client_options), vm);
00594
00595 po::notify(vm);
00596
00597 if (process_options())
00598 abort();
00599
00600 if ( vm.count("help") || vm.count("info"))
00601 {
00602 printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",SLAP_NAME, SLAP_VERSION,
00603 drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
00604 puts("Copyright (C) 2008 Sun Microsystems");
00605 puts("This software comes with ABSOLUTELY NO WARRANTY. "
00606 "This is free software,\n"
00607 "and you are welcome to modify and redistribute it under the GPL "
00608 "license\n");
00609 puts("Run a query multiple times against the server\n");
00610 cout << long_options << endl;
00611 abort();
00612 }
00613
00614 if (vm.count("protocol"))
00615 {
00616 boost::to_lower(opt_protocol);
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 drizzle_con_st *con= slap_connect(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 {
00715 goto burnin;
00716 }
00717
00718 slap_close(con);
00719
00720
00721 if (not opt_password.empty())
00722 opt_password.erase();
00723
00724 concurrency.clear();
00725
00726 statement_cleanup(create_statements);
00727 for (uint32_t x= 0; x < query_statements_count; x++)
00728 statement_cleanup(query_statements[x]);
00729 query_statements.clear();
00730 statement_cleanup(pre_statements);
00731 statement_cleanup(post_statements);
00732 option_cleanup(engine_options);
00733 option_cleanup(query_options);
00734
00735 #ifdef HAVE_SMEM
00736 free(shared_memory_base_name);
00737 #endif
00738
00739 }
00740
00741 catch(std::exception &err)
00742 {
00743 cerr<<"Error:"<<err.what()<<endl;
00744 }
00745
00746 if (csv_file != fileno(stdout))
00747 close(csv_file);
00748
00749 return 0;
00750 }
00751
00752 void concurrency_loop(drizzle_con_st &con, uint32_t current, OptionString *eptr)
00753 {
00754 Stats *head_sptr;
00755 Stats *sptr;
00756 Conclusions conclusion;
00757 uint64_t client_limit;
00758
00759 head_sptr= new Stats[iterations];
00760 if (head_sptr == NULL)
00761 {
00762 fprintf(stderr,"Error allocating memory in concurrency_loop\n");
00763 abort();
00764 }
00765
00766 if (auto_actual_queries)
00767 client_limit= auto_actual_queries;
00768 else if (num_of_query)
00769 client_limit= num_of_query / current;
00770 else
00771 client_limit= actual_queries;
00772
00773 uint32_t x;
00774 for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
00775 {
00776
00777
00778
00779
00780
00781 if (opt_preserve == false)
00782 drop_schema(con, create_schema_string.c_str());
00783
00784
00785 if (create_statements)
00786 create_schema(con, create_schema_string.c_str(), create_statements, eptr, sptr);
00787
00788
00789
00790
00791
00792 if (verbose >= 2)
00793 printf("Generating primary key list\n");
00794 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
00795 generate_primary_key_list(con, eptr);
00796
00797 if (not pre_system.empty())
00798 {
00799 int ret= system(pre_system.c_str());
00800 assert(ret != -1);
00801 }
00802
00803
00804
00805
00806
00807 if (pre_statements)
00808 run_statements(con, pre_statements);
00809
00810 run_scheduler(sptr, &query_statements[0], current, client_limit);
00811
00812 if (post_statements)
00813 run_statements(con, post_statements);
00814
00815 if (not post_system.empty())
00816 {
00817 int ret= system(post_system.c_str());
00818 assert(ret !=-1);
00819 }
00820
00821
00822 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
00823 primary_keys.clear();
00824 }
00825
00826 if (verbose >= 2)
00827 printf("Generating stats\n");
00828
00829 generate_stats(&conclusion, eptr, head_sptr);
00830
00831 if (not opt_silent)
00832 print_conclusions(conclusion);
00833 if (not opt_csv_str.empty())
00834 print_conclusions_csv(conclusion);
00835
00836 delete[] head_sptr;
00837 }
00838
00839
00840 uint32_t get_random_string(char *buf, size_t size)
00841 {
00842 char *buf_ptr= buf;
00843
00844 for (size_t x= size; x > 0; x--)
00845 *buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE];
00846 return(buf_ptr - buf);
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856 static Statement *
00857 build_table_string(void)
00858 {
00859 char buf[HUGE_STRING_LENGTH];
00860 uint32_t col_count;
00861 Statement *ptr;
00862 string table_string;
00863
00864 table_string.reserve(HUGE_STRING_LENGTH);
00865
00866 table_string= "CREATE TABLE `t1` (";
00867
00868 if (auto_generate_sql_autoincrement)
00869 {
00870 table_string.append("id serial");
00871
00872 if (num_int_cols || num_char_cols)
00873 table_string.append(",");
00874 }
00875
00876 if (auto_generate_sql_guid_primary)
00877 {
00878 table_string.append("id varchar(128) primary key");
00879
00880 if (num_int_cols || num_char_cols || auto_generate_sql_guid_primary)
00881 table_string.append(",");
00882 }
00883
00884 if (auto_generate_sql_secondary_indexes)
00885 {
00886 for (uint32_t count= 0; count < auto_generate_sql_secondary_indexes; count++)
00887 {
00888 if (count)
00889 table_string.append(",");
00890
00891 if (snprintf(buf, HUGE_STRING_LENGTH, "id%d varchar(32) unique key", count)
00892 > HUGE_STRING_LENGTH)
00893 {
00894 fprintf(stderr, "Memory Allocation error in create table\n");
00895 abort();
00896 }
00897 table_string.append(buf);
00898 }
00899
00900 if (num_int_cols || num_char_cols)
00901 table_string.append(",");
00902 }
00903
00904 if (num_int_cols)
00905 for (col_count= 1; col_count <= num_int_cols; col_count++)
00906 {
00907 if (num_int_cols_index)
00908 {
00909 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT, INDEX(intcol%d)",
00910 col_count, col_count) > HUGE_STRING_LENGTH)
00911 {
00912 fprintf(stderr, "Memory Allocation error in create table\n");
00913 abort();
00914 }
00915 }
00916 else
00917 {
00918 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT ", col_count)
00919 > HUGE_STRING_LENGTH)
00920 {
00921 fprintf(stderr, "Memory Allocation error in create table\n");
00922 abort();
00923 }
00924 }
00925 table_string.append(buf);
00926
00927 if (col_count < num_int_cols || num_char_cols > 0)
00928 table_string.append(",");
00929 }
00930
00931 if (num_char_cols)
00932 for (col_count= 1; col_count <= num_char_cols; col_count++)
00933 {
00934 if (num_char_cols_index)
00935 {
00936 if (snprintf(buf, HUGE_STRING_LENGTH,
00937 "charcol%d VARCHAR(128), INDEX(charcol%d) ",
00938 col_count, col_count) > HUGE_STRING_LENGTH)
00939 {
00940 fprintf(stderr, "Memory Allocation error in creating table\n");
00941 abort();
00942 }
00943 }
00944 else
00945 {
00946 if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d VARCHAR(128)",
00947 col_count) > HUGE_STRING_LENGTH)
00948 {
00949 fprintf(stderr, "Memory Allocation error in creating table\n");
00950 abort();
00951 }
00952 }
00953 table_string.append(buf);
00954
00955 if (col_count < num_char_cols || num_blob_cols > 0)
00956 table_string.append(",");
00957 }
00958
00959 if (num_blob_cols)
00960 for (col_count= 1; col_count <= num_blob_cols; col_count++)
00961 {
00962 if (snprintf(buf, HUGE_STRING_LENGTH, "blobcol%d blob",
00963 col_count) > HUGE_STRING_LENGTH)
00964 {
00965 fprintf(stderr, "Memory Allocation error in creating table\n");
00966 abort();
00967 }
00968 table_string.append(buf);
00969
00970 if (col_count < num_blob_cols)
00971 table_string.append(",");
00972 }
00973
00974 table_string.append(")");
00975 ptr= new Statement;
00976 ptr->setString(table_string.length());
00977 if (ptr->getString()==NULL)
00978 {
00979 fprintf(stderr, "Memory Allocation error in creating table\n");
00980 abort();
00981 }
00982 ptr->setType(CREATE_TABLE_TYPE);
00983 strcpy(ptr->getString(), table_string.c_str());
00984 return(ptr);
00985 }
00986
00987
00988
00989
00990
00991
00992
00993 static Statement *
00994 build_update_string(void)
00995 {
00996 char buf[HUGE_STRING_LENGTH];
00997 uint32_t col_count;
00998 Statement *ptr;
00999 string update_string;
01000
01001 update_string.reserve(HUGE_STRING_LENGTH);
01002
01003 update_string= "UPDATE t1 SET ";
01004
01005 if (num_int_cols)
01006 for (col_count= 1; col_count <= num_int_cols; col_count++)
01007 {
01008 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d = %ld", col_count,
01009 random()) > HUGE_STRING_LENGTH)
01010 {
01011 fprintf(stderr, "Memory Allocation error in creating update\n");
01012 abort();
01013 }
01014 update_string.append(buf);
01015
01016 if (col_count < num_int_cols || num_char_cols > 0)
01017 update_string.append(",", 1);
01018 }
01019
01020 if (num_char_cols)
01021 for (col_count= 1; col_count <= num_char_cols; col_count++)
01022 {
01023 char rand_buffer[RAND_STRING_SIZE];
01024 int buf_len= get_random_string(rand_buffer, RAND_STRING_SIZE);
01025
01026 if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d = '%.*s'", col_count,
01027 buf_len, rand_buffer)
01028 > HUGE_STRING_LENGTH)
01029 {
01030 fprintf(stderr, "Memory Allocation error in creating update\n");
01031 abort();
01032 }
01033 update_string.append(buf);
01034
01035 if (col_count < num_char_cols)
01036 update_string.append(",", 1);
01037 }
01038
01039 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
01040 update_string.append(" WHERE id = ");
01041
01042
01043 ptr= new Statement;
01044
01045 ptr->setString(update_string.length());
01046 if (ptr->getString() == NULL)
01047 {
01048 fprintf(stderr, "Memory Allocation error in creating update\n");
01049 abort();
01050 }
01051 if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
01052 ptr->setType(UPDATE_TYPE_REQUIRES_PREFIX);
01053 else
01054 ptr->setType(UPDATE_TYPE);
01055 strncpy(ptr->getString(), update_string.c_str(), ptr->getLength());
01056 return(ptr);
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066 static Statement *
01067 build_insert_string(void)
01068 {
01069 char buf[HUGE_STRING_LENGTH];
01070 uint32_t col_count;
01071 Statement *ptr;
01072 string insert_string;
01073
01074 insert_string.reserve(HUGE_STRING_LENGTH);
01075
01076 insert_string= "INSERT INTO t1 VALUES (";
01077
01078 if (auto_generate_sql_autoincrement)
01079 {
01080 insert_string.append("NULL");
01081
01082 if (num_int_cols || num_char_cols)
01083 insert_string.append(",");
01084 }
01085
01086 if (auto_generate_sql_guid_primary)
01087 {
01088 insert_string.append("uuid()");
01089
01090 if (num_int_cols || num_char_cols)
01091 insert_string.append(",");
01092 }
01093
01094 if (auto_generate_sql_secondary_indexes)
01095 {
01096 uint32_t count;
01097
01098 for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
01099 {
01100 if (count)
01101 insert_string.append(",");
01102
01103 insert_string.append("uuid()");
01104 }
01105
01106 if (num_int_cols || num_char_cols)
01107 insert_string.append(",");
01108 }
01109
01110 if (num_int_cols)
01111 for (col_count= 1; col_count <= num_int_cols; col_count++)
01112 {
01113 if (snprintf(buf, HUGE_STRING_LENGTH, "%ld", random()) > HUGE_STRING_LENGTH)
01114 {
01115 fprintf(stderr, "Memory Allocation error in creating insert\n");
01116 abort();
01117 }
01118 insert_string.append(buf);
01119
01120 if (col_count < num_int_cols || num_char_cols > 0)
01121 insert_string.append(",");
01122 }
01123
01124 if (num_char_cols)
01125 for (col_count= 1; col_count <= num_char_cols; col_count++)
01126 {
01127 int buf_len= get_random_string(buf, RAND_STRING_SIZE);
01128 insert_string.append("'", 1);
01129 insert_string.append(buf, buf_len);
01130 insert_string.append("'", 1);
01131
01132 if (col_count < num_char_cols || num_blob_cols > 0)
01133 insert_string.append(",", 1);
01134 }
01135
01136 if (num_blob_cols)
01137 {
01138 vector <char> blob_ptr;
01139
01140 blob_ptr.resize(num_blob_cols_size);
01141
01142 for (col_count= 1; col_count <= num_blob_cols; col_count++)
01143 {
01144 uint32_t buf_len;
01145 uint32_t size;
01146 uint32_t difference= num_blob_cols_size - num_blob_cols_size_min;
01147
01148 size= difference ? (num_blob_cols_size_min + (random() % difference)) :
01149 num_blob_cols_size;
01150
01151 buf_len= get_random_string(&blob_ptr[0], size);
01152
01153 insert_string.append("'", 1);
01154 insert_string.append(&blob_ptr[0], buf_len);
01155 insert_string.append("'", 1);
01156
01157 if (col_count < num_blob_cols)
01158 insert_string.append(",", 1);
01159 }
01160 }
01161
01162 insert_string.append(")", 1);
01163
01164 ptr= new Statement;
01165 ptr->setString(insert_string.length());
01166 if (ptr->getString()==NULL)
01167 {
01168 fprintf(stderr, "Memory Allocation error in creating select\n");
01169 abort();
01170 }
01171 ptr->setType(INSERT_TYPE);
01172 strcpy(ptr->getString(), insert_string.c_str());
01173 return(ptr);
01174 }
01175
01176
01177
01178
01179
01180
01181
01182
01183 static Statement *
01184 build_select_string(bool key)
01185 {
01186 char buf[HUGE_STRING_LENGTH];
01187 uint32_t col_count;
01188 Statement *ptr;
01189 string query_string;
01190
01191 query_string.reserve(HUGE_STRING_LENGTH);
01192
01193 query_string.append("SELECT ", 7);
01194 if (not auto_generate_selected_columns_opt.empty())
01195 {
01196 query_string.append(auto_generate_selected_columns_opt.c_str());
01197 }
01198 else
01199 {
01200 for (col_count= 1; col_count <= num_int_cols; col_count++)
01201 {
01202 if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d", col_count)
01203 > HUGE_STRING_LENGTH)
01204 {
01205 fprintf(stderr, "Memory Allocation error in creating select\n");
01206 abort();
01207 }
01208 query_string.append(buf);
01209
01210 if (col_count < num_int_cols || num_char_cols > 0)
01211 query_string.append(",", 1);
01212
01213 }
01214 for (col_count= 1; col_count <= num_char_cols; col_count++)
01215 {
01216 if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d", col_count)
01217 > HUGE_STRING_LENGTH)
01218 {
01219 fprintf(stderr, "Memory Allocation error in creating select\n");
01220 abort();
01221 }
01222 query_string.append(buf);
01223
01224 if (col_count < num_char_cols || num_blob_cols > 0)
01225 query_string.append(",", 1);
01226
01227 }
01228 for (col_count= 1; col_count <= num_blob_cols; col_count++)
01229 {
01230 if (snprintf(buf, HUGE_STRING_LENGTH, "blobcol%d", col_count)
01231 > HUGE_STRING_LENGTH)
01232 {
01233 fprintf(stderr, "Memory Allocation error in creating select\n");
01234 abort();
01235 }
01236 query_string.append(buf);
01237
01238 if (col_count < num_blob_cols)
01239 query_string.append(",", 1);
01240 }
01241 }
01242 query_string.append(" FROM t1");
01243
01244 if ((key) &&
01245 (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
01246 query_string.append(" WHERE id = ");
01247
01248 ptr= new Statement;
01249 ptr->setString(query_string.length());
01250 if (ptr->getString() == NULL)
01251 {
01252 fprintf(stderr, "Memory Allocation error in creating select\n");
01253 abort();
01254 }
01255 if ((key) &&
01256 (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
01257 ptr->setType(SELECT_TYPE_REQUIRES_PREFIX);
01258 else
01259 ptr->setType(SELECT_TYPE);
01260 strcpy(ptr->getString(), query_string.c_str());
01261 return(ptr);
01262 }
01263
01264 static int
01265 process_options(void)
01266 {
01267 struct stat sbuf;
01268 ssize_t bytes_read= 0;
01269
01270 if (user.empty())
01271 user= "root";
01272
01273 verbose= opt_verbose.length();
01274
01275
01276 if ( (not create_string.empty()) || auto_generate_sql)
01277 opt_preserve= false;
01278
01279 if (auto_generate_sql && (not create_string.empty() || !user_supplied_query.empty()))
01280 {
01281 fprintf(stderr,
01282 "%s: Can't use --auto-generate-sql when create and query strings are specified!\n",
01283 SLAP_NAME);
01284 abort();
01285 }
01286
01287 if (auto_generate_sql && auto_generate_sql_guid_primary &&
01288 auto_generate_sql_autoincrement)
01289 {
01290 fprintf(stderr,
01291 "%s: Either auto-generate-sql-guid-primary or auto-generate-sql-add-autoincrement can be used!\n",
01292 SLAP_NAME);
01293 abort();
01294 }
01295
01296 if (auto_generate_sql && num_of_query && auto_actual_queries)
01297 {
01298 fprintf(stderr,
01299 "%s: Either auto-generate-sql-execute-number or number-of-queries can be used!\n",
01300 SLAP_NAME);
01301 abort();
01302 }
01303
01304 parse_comma(not concurrency_str.empty() ? concurrency_str.c_str() : "1", concurrency);
01305
01306 if (not opt_csv_str.empty())
01307 {
01308 opt_silent= true;
01309
01310 if (opt_csv_str[0] == '-')
01311 {
01312 csv_file= fileno(stdout);
01313 }
01314 else
01315 {
01316 if ((csv_file= open(opt_csv_str.c_str(), O_CREAT|O_WRONLY|O_APPEND,
01317 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
01318 {
01319 fprintf(stderr,"%s: Could not open csv file: %sn\n",
01320 SLAP_NAME, opt_csv_str.c_str());
01321 abort();
01322 }
01323 }
01324 }
01325
01326 if (opt_only_print)
01327 opt_silent= true;
01328
01329 if (not num_int_cols_opt.empty())
01330 {
01331 OptionString *str;
01332 parse_option(num_int_cols_opt.c_str(), &str, ',');
01333 num_int_cols= atoi(str->getString());
01334 if (str->getOption())
01335 num_int_cols_index= atoi(str->getOption());
01336 option_cleanup(str);
01337 }
01338
01339 if (not num_char_cols_opt.empty())
01340 {
01341 OptionString *str;
01342 parse_option(num_char_cols_opt.c_str(), &str, ',');
01343 num_char_cols= atoi(str->getString());
01344 if (str->getOption())
01345 num_char_cols_index= atoi(str->getOption());
01346 else
01347 num_char_cols_index= 0;
01348 option_cleanup(str);
01349 }
01350
01351 uint32_t sql_type_count= 0;
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 OptionString* 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 drizzle_con_st* slap_connect(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 drizzle_con_st* con;
02398 if ((drizzle= drizzle_create()) == NULL or
02399 (con= drizzle_con_add_tcp(drizzle,
02400 host.c_str(), opt_drizzle_port,
02401 user.c_str(), opt_password.c_str(),
02402 connect_to_schema ? create_schema_string.c_str() : NULL,
02403 use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL)) == NULL)
02404 {
02405 fprintf(stderr,"%s: Error creating drizzle object\n", SLAP_NAME);
02406 abort();
02407 }
02408
02409 drizzle_set_context(drizzle, (void*)(connection_count.fetch_and_increment()));
02410
02411 if (opt_only_print)
02412 {
02413 return con;
02414 }
02415
02416 for (uint32_t x= 0; x < 10; x++)
02417 {
02418 if ((ret= drizzle_con_connect(con)) == DRIZZLE_RETURN_OK)
02419 {
02420
02421 connect_error= 0;
02422 break;
02423 }
02424 usleep(connection_retry_sleep);
02425 }
02426 if (connect_error)
02427 {
02428 fprintf(stderr,"%s: Error when connecting to server: %d %s\n", SLAP_NAME,
02429 ret, drizzle_con_error(con));
02430 abort();
02431 }
02432
02433 return con;
02434 }
02435
02436 void standard_deviation(Conclusions &con, Stats *sptr)
02437 {
02438 long int sum_of_squares;
02439 double the_catch;
02440 Stats *ptr;
02441
02442 if (iterations == 1 || iterations == 0)
02443 {
02444 con.setStdDev(0);
02445 return;
02446 }
02447
02448 uint32_t x;
02449 for (ptr= sptr, x= 0, sum_of_squares= 0; x < iterations; ptr++, x++)
02450 {
02451 long int deviation;
02452
02453 deviation= ptr->getTiming() - con.getAvgTiming();
02454 sum_of_squares+= deviation*deviation;
02455 }
02456
02457 the_catch= sqrt((double)(sum_of_squares/(iterations -1)));
02458 con.setStdDev((long int)the_catch);
02459 }