1
/* Copyright (C) 2005 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
original idea: Brian Aker via playing with ab for too many years
17
coded by: Patrick Galbraith
24
A simple program designed to work as if multiple clients querying the database,
25
then reporting the timing of each stage.
27
MySQL slap runs three stages:
28
1) Create schema,table, and optionally any SP or data you want to beign
29
the test with. (single client)
30
2) Load test (many clients)
31
3) Cleanup (disconnection, drop table if specified, single client)
35
Supply your own create and query SQL statements, with 50 clients
36
querying (200 selects for each):
38
mysqlslap --delimiter=";" \
39
--create="CREATE TABLE A (a int);INSERT INTO A VALUES (23)" \
40
--query="SELECT * FROM A" --concurrency=50 --iterations=200
42
Let the program build the query SQL statement with a table of two int
43
columns, three varchar columns, five clients querying (20 times each),
44
don't create the table or insert the data (using the previous test's
47
mysqlslap --concurrency=5 --iterations=20 \
48
--number-int-cols=2 --number-char-cols=3 \
51
Tell the program to load the create, insert and query SQL statements from
52
the specified files, where the create.sql file has multiple table creation
53
statements delimited by ';' and multiple insert statements delimited by ';'.
54
The --query file will have multiple queries delimited by ';', run all the
55
load statements, and then run all the queries in the query file
56
with five clients (five times each):
58
mysqlslap --concurrency=5 \
59
--iterations=5 --query=query.sql --create=create.sql \
63
Add language for better tests
64
String length for files and those put on the command line are not
65
setup to handle binary data.
67
Break up tests and run them on multiple hosts at once.
68
Allow output to be fed into a database directly.
72
#define SLAP_VERSION "1.5"
74
#define HUGE_STRING_LENGTH 8196
75
#define RAND_STRING_SIZE 126
76
#define DEFAULT_BLOB_SIZE 1024
78
#include "client_priv.h"
79
#include <mysqld_error.h>
83
#include <sys/types.h>
92
#define snprintf _snprintf
96
static char *shared_memory_base_name=0;
99
/* Global Thread counter */
101
pthread_mutex_t counter_mutex;
102
pthread_cond_t count_threshhold;
104
pthread_mutex_t sleeper_mutex;
105
pthread_cond_t sleep_threshhold;
107
/* Global Thread timer */
108
static my_bool timer_alarm= FALSE;
109
pthread_mutex_t timer_alarm_mutex;
110
pthread_cond_t timer_alarm_threshold;
112
static char **defaults_argv;
115
unsigned long long primary_keys_number_of;
117
static char *host= NULL, *opt_password= NULL, *user= NULL,
118
*user_supplied_query= NULL,
119
*user_supplied_pre_statements= NULL,
120
*user_supplied_post_statements= NULL,
121
*default_engine= NULL,
124
*opt_mysql_unix_port= NULL;
126
const char *delimiter= "\n";
128
const char *create_schema_string= "mysqlslap";
130
static my_bool opt_preserve= TRUE;
131
static my_bool debug_info_flag= 0, debug_check_flag= 0;
132
static my_bool opt_only_print= FALSE;
133
static my_bool opt_burnin= FALSE;
134
static my_bool opt_ignore_sql_errors= FALSE;
135
static my_bool opt_compress= FALSE, tty_password= FALSE,
137
auto_generate_sql_autoincrement= FALSE,
138
auto_generate_sql_guid_primary= FALSE,
139
auto_generate_sql= FALSE;
140
const char *opt_auto_generate_sql_type= "mixed";
142
static unsigned long connect_flags= CLIENT_MULTI_RESULTS |
143
CLIENT_MULTI_STATEMENTS;
145
static int verbose, delimiter_length;
146
static uint commit_rate;
147
static uint detach_rate;
148
static uint opt_timer_length;
149
static uint opt_delayed_start;
150
const char *num_int_cols_opt;
151
const char *num_char_cols_opt;
152
const char *num_blob_cols_opt;
153
const char *opt_label;
154
static unsigned int opt_set_random_seed;
156
const char *auto_generate_selected_columns_opt;
158
/* Yes, we do set defaults here */
159
static unsigned int num_int_cols= 1;
160
static unsigned int num_char_cols= 1;
161
static unsigned int num_blob_cols= 0;
162
static unsigned int num_blob_cols_size;
163
static unsigned int num_blob_cols_size_min;
164
static unsigned int num_int_cols_index= 0;
165
static unsigned int num_char_cols_index= 0;
166
static unsigned int iterations;
167
static uint my_end_arg= 0;
168
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
169
static ulonglong actual_queries= 0;
170
static ulonglong auto_actual_queries;
171
static ulonglong auto_generate_sql_unique_write_number;
172
static ulonglong auto_generate_sql_unique_query_number;
173
static unsigned int auto_generate_sql_secondary_indexes;
174
static ulonglong num_of_query;
175
static ulonglong auto_generate_sql_number;
176
const char *concurrency_str= NULL;
177
static char *create_string;
180
const char *default_dbug_option="d:t:o,/tmp/mysqlslap.trace";
181
const char *opt_csv_str;
184
static uint opt_protocol= MYSQL_PROTOCOL_TCP;
186
static int get_options(int *argc,char ***argv);
187
static uint opt_mysql_port= 0;
189
static const char *load_default_groups[]= { "mysqlslap","client",0 };
196
UPDATE_TYPE_REQUIRES_PREFIX= 3,
197
CREATE_TABLE_TYPE= 4,
198
SELECT_TYPE_REQUIRES_PREFIX= 5,
199
DELETE_TYPE_REQUIRES_PREFIX= 6
202
typedef struct statement statement;
207
slap_query_type type;
209
size_t option_length;
213
typedef struct option_string option_string;
215
struct option_string {
219
size_t option_length;
223
typedef struct stats stats;
229
unsigned long long rows;
230
long int create_timing;
231
unsigned long long create_count;
234
typedef struct thread_context thread_context;
236
struct thread_context {
241
typedef struct conclusions conclusions;
250
unsigned long long avg_rows;
251
long int sum_of_time;
253
/* These are just for create time stats */
254
long int create_avg_timing;
255
long int create_max_timing;
256
long int create_min_timing;
257
unsigned long long create_count;
258
/* The following are not used yet */
259
unsigned long long max_rows;
260
unsigned long long min_rows;
263
static option_string *engine_options= NULL;
264
static option_string *query_options= NULL;
265
static statement *pre_statements= NULL;
266
static statement *post_statements= NULL;
267
static statement *create_statements= NULL;
269
static statement **query_statements= NULL;
270
static unsigned int query_statements_count;
274
void print_conclusions(conclusions *con);
275
void print_conclusions_csv(conclusions *con);
276
void generate_stats(conclusions *con, option_string *eng, stats *sptr);
277
uint parse_comma(const char *string, uint **range);
278
uint parse_delimiter(const char *script, statement **stmt, char delm);
279
uint parse_option(const char *origin, option_string **stmt, char delm);
280
static int drop_schema(MYSQL *mysql, const char *db);
281
uint get_random_string(char *buf, size_t size);
282
static statement *build_table_string(void);
283
static statement *build_insert_string(void);
284
static statement *build_update_string(void);
285
static statement * build_select_string(my_bool key);
286
static int generate_primary_key_list(MYSQL *mysql, option_string *engine_stmt);
287
static int drop_primary_key_list(void);
288
static int create_schema(MYSQL *mysql, const char *db, statement *stmt,
289
option_string *engine_stmt, stats *sptr);
290
static int run_scheduler(stats *sptr, statement **stmts, uint concur,
292
pthread_handler_t run_task(void *p);
293
pthread_handler_t timer_thread(void *p);
294
void statement_cleanup(statement *stmt);
295
void option_cleanup(option_string *stmt);
296
void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr);
297
static int run_statements(MYSQL *mysql, statement *stmt);
298
void slap_connect(MYSQL *mysql, my_bool connect_to_schema);
299
void slap_close(MYSQL *mysql);
300
static int run_query(MYSQL *mysql, const char *query, int len);
301
void standard_deviation (conclusions *con, stats *sptr);
303
static const char ALPHANUMERICS[]=
304
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
306
#define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
309
static long int timedif(struct timeval a, struct timeval b)
313
us = a.tv_usec - b.tv_usec;
315
s = a.tv_sec - b.tv_sec;
321
static int gettimeofday(struct timeval *tp, void *tzp)
324
ticks= GetTickCount();
325
tp->tv_usec= ticks*1000;
326
tp->tv_sec= ticks/1000;
332
int main(int argc, char **argv)
342
if (!(mysql_thread_safe()))
343
fprintf(stderr, "This application was compiled incorrectly. Please recompile with thread support.\n");
345
load_defaults("my",load_default_groups,&argc,&argv);
347
if (get_options(&argc,&argv))
349
free_defaults(defaults_argv);
354
/* Seed the random number generator if we will be using it. */
355
if (auto_generate_sql)
357
if (opt_set_random_seed == 0)
358
opt_set_random_seed= (unsigned int)time(NULL);
359
srandom(opt_set_random_seed);
362
/* globals? Yes, so we only have to run strlen once */
363
delimiter_length= strlen(delimiter);
367
fprintf(stderr,"%s: Too many arguments\n",my_progname);
368
free_defaults(defaults_argv);
373
slap_connect(&mysql, FALSE);
375
VOID(pthread_mutex_init(&counter_mutex, NULL));
376
VOID(pthread_cond_init(&count_threshhold, NULL));
377
VOID(pthread_mutex_init(&sleeper_mutex, NULL));
378
VOID(pthread_cond_init(&sleep_threshhold, NULL));
379
VOID(pthread_mutex_init(&timer_alarm_mutex, NULL));
380
VOID(pthread_cond_init(&timer_alarm_threshold, NULL));
383
/* Main iterations loop */
385
eptr= engine_options;
388
/* For the final stage we run whatever queries we were asked to run */
392
printf("Starting Concurrency Test\n");
396
for (current= concurrency; current && *current; current++)
397
concurrency_loop(&mysql, *current, eptr);
403
concurrency_loop(&mysql, infinite, eptr);
409
drop_schema(&mysql, create_schema_string);
411
} while (eptr ? (eptr= eptr->next) : 0);
416
VOID(pthread_mutex_destroy(&counter_mutex));
417
VOID(pthread_cond_destroy(&count_threshhold));
418
VOID(pthread_mutex_destroy(&sleeper_mutex));
419
VOID(pthread_cond_destroy(&sleep_threshhold));
420
VOID(pthread_mutex_destroy(&timer_alarm_mutex));
421
VOID(pthread_cond_destroy(&timer_alarm_threshold));
425
/* now free all the strings we created */
427
my_free(opt_password, MYF(0));
429
my_free(concurrency, MYF(0));
431
statement_cleanup(create_statements);
432
for (x= 0; x < query_statements_count; x++)
433
statement_cleanup(query_statements[x]);
434
my_free(query_statements, MYF(0));
435
statement_cleanup(pre_statements);
436
statement_cleanup(post_statements);
437
option_cleanup(engine_options);
438
option_cleanup(query_options);
441
if (shared_memory_base_name)
442
my_free(shared_memory_base_name, MYF(MY_ALLOW_ZERO_PTR));
444
free_defaults(defaults_argv);
450
void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
455
conclusions conclusion;
456
unsigned long long client_limit;
458
head_sptr= (stats *)my_malloc(sizeof(stats) * iterations,
459
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
461
bzero(&conclusion, sizeof(conclusions));
463
if (auto_actual_queries)
464
client_limit= auto_actual_queries;
465
else if (num_of_query)
466
client_limit= num_of_query / current;
468
client_limit= actual_queries;
470
for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
473
We might not want to load any data, such as when we are calling
474
a stored_procedure that doesn't use data, or we know we already have
477
if (opt_preserve == FALSE)
478
drop_schema(mysql, create_schema_string);
480
/* First we create */
481
if (create_statements)
482
create_schema(mysql, create_schema_string, create_statements, eptr, sptr);
485
If we generated GUID we need to build a list of them from creation that
489
printf("Generating primary key list\n");
490
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
491
generate_primary_key_list(mysql, eptr);
494
run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
500
Pre statements are always run after all other logic so they can
501
correct/adjust any item that they want.
504
run_statements(mysql, pre_statements);
506
run_scheduler(sptr, query_statements, current, client_limit);
509
run_statements(mysql, post_statements);
514
/* We are finished with this run */
515
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
516
drop_primary_key_list();
520
printf("Generating stats\n");
522
generate_stats(&conclusion, eptr, head_sptr);
525
print_conclusions(&conclusion);
527
print_conclusions_csv(&conclusion);
529
my_free(head_sptr, MYF(0));
534
static struct my_option my_long_options[] =
536
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
538
{"auto-generate-sql-select-columns", OPT_SLAP_AUTO_GENERATE_SELECT_COLUMNS,
539
"Provide a string to use for the select fields used in auto tests.",
540
(uchar**) &auto_generate_selected_columns_opt,
541
(uchar**) &auto_generate_selected_columns_opt,
542
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
543
{"auto-generate-sql", 'a',
544
"Generate SQL where not supplied by file or command line.",
545
(uchar**) &auto_generate_sql, (uchar**) &auto_generate_sql,
546
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
547
{"auto-generate-sql-add-autoincrement", OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
548
"Add an AUTO_INCREMENT column to auto-generated tables.",
549
(uchar**) &auto_generate_sql_autoincrement,
550
(uchar**) &auto_generate_sql_autoincrement,
551
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
552
{"auto-generate-sql-execute-number", OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
553
"Set this number to generate a set number of queries to run.",
554
(uchar**) &auto_actual_queries, (uchar**) &auto_actual_queries,
555
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
556
{"auto-generate-sql-guid-primary", OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
557
"Add GUID based primary keys to auto-generated tables.",
558
(uchar**) &auto_generate_sql_guid_primary,
559
(uchar**) &auto_generate_sql_guid_primary,
560
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
561
{"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
562
"Specify test load type: mixed, update, write, key, or read; default is mixed.",
563
(uchar**) &opt_auto_generate_sql_type, (uchar**) &opt_auto_generate_sql_type,
564
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
565
{"auto-generate-sql-secondary-indexes",
566
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
567
"Number of secondary indexes to add to auto-generated tables.",
568
(uchar**) &auto_generate_sql_secondary_indexes,
569
(uchar**) &auto_generate_sql_secondary_indexes, 0,
570
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
571
{"auto-generate-sql-unique-query-number",
572
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
573
"Number of unique queries to generate for automatic tests.",
574
(uchar**) &auto_generate_sql_unique_query_number,
575
(uchar**) &auto_generate_sql_unique_query_number,
576
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
577
{"auto-generate-sql-unique-write-number",
578
OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
579
"Number of unique queries to generate for auto-generate-sql-write-number.",
580
(uchar**) &auto_generate_sql_unique_write_number,
581
(uchar**) &auto_generate_sql_unique_write_number,
582
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
583
{"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
584
"Number of row inserts to perform for each thread (default is 100).",
585
(uchar**) &auto_generate_sql_number, (uchar**) &auto_generate_sql_number,
586
0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0},
587
{"burnin", OPT_SLAP_BURNIN, "Run full test case in infinite loop.",
588
(uchar**) &opt_burnin, (uchar**) &opt_burnin, 0, GET_BOOL, NO_ARG, 0, 0, 0,
590
{"ignore-sql-errors", OPT_SLAP_IGNORE_SQL_ERRORS,
591
"Ignore SQL erros in query run.",
592
(uchar**) &opt_ignore_sql_errors,
593
(uchar**) &opt_ignore_sql_errors,
594
0, GET_BOOL, NO_ARG, 0, 0, 0,
596
{"commit", OPT_SLAP_COMMIT, "Commit records every X number of statements.",
597
(uchar**) &commit_rate, (uchar**) &commit_rate, 0, GET_UINT, REQUIRED_ARG,
599
{"compress", 'C', "Use compression in server/client protocol.",
600
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
602
{"concurrency", 'c', "Number of clients to simulate for query to run.",
603
(uchar**) &concurrency_str, (uchar**) &concurrency_str, 0, GET_STR,
604
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
605
{"create", OPT_SLAP_CREATE_STRING, "File or string to use create tables.",
606
(uchar**) &create_string, (uchar**) &create_string, 0, GET_STR, REQUIRED_ARG,
608
{"create-schema", OPT_CREATE_SLAP_SCHEMA, "Schema to run tests in.",
609
(uchar**) &create_schema_string, (uchar**) &create_schema_string, 0, GET_STR,
610
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
611
{"csv", OPT_SLAP_CSV,
612
"Generate CSV output to named file or to stdout if no file is named.",
613
(uchar**) &opt_csv_str, (uchar**) &opt_csv_str, 0, GET_STR,
614
OPT_ARG, 0, 0, 0, 0, 0, 0},
616
{"debug", '#', "This is a non-debug version. Catch this and exit.",
617
0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
619
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
620
(uchar**) &default_dbug_option, (uchar**) &default_dbug_option, 0, GET_STR,
621
OPT_ARG, 0, 0, 0, 0, 0, 0},
623
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
624
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
625
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
626
{"debug-info", 'T', "Print some debug info at exit.", (uchar**) &debug_info_flag,
627
(uchar**) &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
628
{"delayed-start", OPT_SLAP_DELAYED_START,
629
"Delay the startup of threads by a random number of microsends (the maximum of the delay)",
630
(uchar**) &opt_delayed_start, (uchar**) &opt_delayed_start, 0, GET_UINT,
631
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
633
"Delimiter to use in SQL statements supplied in file or command line.",
634
(uchar**) &delimiter, (uchar**) &delimiter, 0, GET_STR, REQUIRED_ARG,
636
{"detach", OPT_SLAP_DETACH,
637
"Detach (close and reopen) connections after X number of requests.",
638
(uchar**) &detach_rate, (uchar**) &detach_rate, 0, GET_UINT, REQUIRED_ARG,
640
{"engine", 'e', "Storage engine to use for creating the table.",
641
(uchar**) &default_engine, (uchar**) &default_engine, 0,
642
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
643
{"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
644
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
645
{"iterations", 'i', "Number of times to run the tests.", (uchar**) &iterations,
646
(uchar**) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
647
{"label", OPT_SLAP_LABEL, "Label to use for print and csv output.",
648
(uchar**) &opt_label, (uchar**) &opt_label, 0,
649
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
650
{"number-blob-cols", OPT_SLAP_BLOB_COL,
651
"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. ",
652
(uchar**) &num_blob_cols_opt, (uchar**) &num_blob_cols_opt, 0, GET_STR, REQUIRED_ARG,
654
{"number-char-cols", 'x',
655
"Number of VARCHAR columns to create in table if specifying --auto-generate-sql.",
656
(uchar**) &num_char_cols_opt, (uchar**) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
658
{"number-int-cols", 'y',
659
"Number of INT columns to create in table if specifying --auto-generate-sql.",
660
(uchar**) &num_int_cols_opt, (uchar**) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
662
{"number-of-queries", OPT_MYSQL_NUMBER_OF_QUERY,
663
"Limit each client to this number of queries (this is not exact).",
664
(uchar**) &num_of_query, (uchar**) &num_of_query, 0,
665
GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
666
{"only-print", OPT_MYSQL_ONLY_PRINT,
667
"This causes mysqlslap to not connect to the databases, but instead print "
668
"out what it would have done instead.",
669
(uchar**) &opt_only_print, (uchar**) &opt_only_print, 0, GET_BOOL, NO_ARG,
672
"Password to use when connecting to server. If password is not given it's "
673
"asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
675
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
676
NO_ARG, 0, 0, 0, 0, 0, 0},
678
{"port", 'P', "Port number to use for connection.", (uchar**) &opt_mysql_port,
679
(uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
681
{"post-query", OPT_SLAP_POST_QUERY,
682
"Query to run or file containing query to execute after tests have completed.",
683
(uchar**) &user_supplied_post_statements,
684
(uchar**) &user_supplied_post_statements,
685
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
686
{"post-system", OPT_SLAP_POST_SYSTEM,
687
"system() string to execute after tests have completed.",
688
(uchar**) &post_system,
689
(uchar**) &post_system,
690
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
691
{"pre-query", OPT_SLAP_PRE_QUERY,
692
"Query to run or file containing query to execute before running tests.",
693
(uchar**) &user_supplied_pre_statements,
694
(uchar**) &user_supplied_pre_statements,
695
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
696
{"pre-system", OPT_SLAP_PRE_SYSTEM,
697
"system() string to execute before running tests.",
698
(uchar**) &pre_system,
699
(uchar**) &pre_system,
700
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
701
{"protocol", OPT_MYSQL_PROTOCOL,
702
"The protocol of connection (tcp,socket,pipe,memory).",
703
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
704
{"query", 'q', "Query to run or file containing query to run.",
705
(uchar**) &user_supplied_query, (uchar**) &user_supplied_query,
706
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
707
{"set-random-seed", OPT_SLAP_SET_RANDOM_SEED,
708
"Seed for random number generator (srandom(3))",
709
(uchar**)&opt_set_random_seed,
710
(uchar**)&opt_set_random_seed,0,
711
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
713
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
714
"Base name of shared memory.", (uchar**) &shared_memory_base_name,
715
(uchar**) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG,
718
{"silent", 's', "Run program in silent mode - no output.",
719
(uchar**) &opt_silent, (uchar**) &opt_silent, 0, GET_BOOL, NO_ARG,
721
{"socket", 'S', "Socket file to use for connection.",
722
(uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR,
723
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
724
{"timer-length", OPT_SLAP_TIMER_LENGTH,
725
"Require mysqlslap to run each specific test a certain amount of time in seconds.",
726
(uchar**) &opt_timer_length, (uchar**) &opt_timer_length, 0, GET_UINT,
727
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
728
#ifndef DONT_ALLOW_USER_CHANGE
729
{"user", 'u', "User for login if not current user.", (uchar**) &user,
730
(uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
733
"More verbose output; you can use this multiple times to get even more "
734
"verbose output.", (uchar**) &verbose, (uchar**) &verbose, 0,
735
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
736
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
737
NO_ARG, 0, 0, 0, 0, 0, 0},
738
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
742
#include <help_start.h>
744
static void print_version(void)
746
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname, SLAP_VERSION,
747
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
751
static void usage(void)
754
puts("Copyright (C) 2005 MySQL AB");
755
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\
756
\nand you are welcome to modify and redistribute it under the GPL \
758
puts("Run a query multiple times against the server\n");
759
printf("Usage: %s [OPTIONS]\n",my_progname);
760
print_defaults("my",load_default_groups);
761
my_print_help(my_long_options);
764
#include <help_end.h>
767
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
770
DBUG_ENTER("get_one_option");
774
setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
783
char *start= argument;
784
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
785
opt_password= my_strdup(argument,MYF(MY_FAE));
786
while (*argument) *argument++= 'x'; /* Destroy argument */
788
start[1]= 0; /* Cut length of argument */
795
DBUG_PUSH(argument ? argument : default_dbug_option);
812
get_random_string(char *buf, size_t size)
816
DBUG_ENTER("get_random_string");
817
for (x= size; x > 0; x--)
818
*buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE];
819
DBUG_RETURN(buf_ptr - buf);
826
This function builds a create table query if the user opts to not supply
827
a file or string containing a create table statement
830
build_table_string(void)
832
char buf[HUGE_STRING_LENGTH];
833
unsigned int col_count;
835
DYNAMIC_STRING table_string;
836
DBUG_ENTER("build_table_string");
838
DBUG_PRINT("info", ("num int cols %u num char cols %u",
839
num_int_cols, num_char_cols));
841
init_dynamic_string(&table_string, "", HUGE_STRING_LENGTH, HUGE_STRING_LENGTH);
843
dynstr_append(&table_string, "CREATE TABLE `t1` (");
845
if (auto_generate_sql_autoincrement)
847
dynstr_append(&table_string, "id serial");
849
if (num_int_cols || num_char_cols)
850
dynstr_append(&table_string, ",");
853
if (auto_generate_sql_guid_primary)
855
dynstr_append(&table_string, "id varchar(128) primary key");
857
if (num_int_cols || num_char_cols || auto_generate_sql_guid_primary)
858
dynstr_append(&table_string, ",");
861
if (auto_generate_sql_secondary_indexes)
865
for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
867
if (count) /* Except for the first pass we add a comma */
868
dynstr_append(&table_string, ",");
870
if (snprintf(buf, HUGE_STRING_LENGTH, "id%d varchar(32) unique key", count)
871
> HUGE_STRING_LENGTH)
873
fprintf(stderr, "Memory Allocation error in create table\n");
876
dynstr_append(&table_string, buf);
879
if (num_int_cols || num_char_cols)
880
dynstr_append(&table_string, ",");
884
for (col_count= 1; col_count <= num_int_cols; col_count++)
886
if (num_int_cols_index)
888
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT(32), INDEX(intcol%d)",
889
col_count, col_count) > HUGE_STRING_LENGTH)
891
fprintf(stderr, "Memory Allocation error in create table\n");
897
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT(32) ", col_count)
898
> HUGE_STRING_LENGTH)
900
fprintf(stderr, "Memory Allocation error in create table\n");
904
dynstr_append(&table_string, buf);
906
if (col_count < num_int_cols || num_char_cols > 0)
907
dynstr_append(&table_string, ",");
911
for (col_count= 1; col_count <= num_char_cols; col_count++)
913
if (num_char_cols_index)
915
if (snprintf(buf, HUGE_STRING_LENGTH,
916
"charcol%d VARCHAR(128), INDEX(charcol%d) ",
917
col_count, col_count) > HUGE_STRING_LENGTH)
919
fprintf(stderr, "Memory Allocation error in creating table\n");
925
if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d VARCHAR(128)",
926
col_count) > HUGE_STRING_LENGTH)
928
fprintf(stderr, "Memory Allocation error in creating table\n");
932
dynstr_append(&table_string, buf);
934
if (col_count < num_char_cols || num_blob_cols > 0)
935
dynstr_append(&table_string, ",");
939
for (col_count= 1; col_count <= num_blob_cols; col_count++)
941
if (snprintf(buf, HUGE_STRING_LENGTH, "blobcol%d blob",
942
col_count) > HUGE_STRING_LENGTH)
944
fprintf(stderr, "Memory Allocation error in creating table\n");
947
dynstr_append(&table_string, buf);
949
if (col_count < num_blob_cols)
950
dynstr_append(&table_string, ",");
953
dynstr_append(&table_string, ")");
954
ptr= (statement *)my_malloc(sizeof(statement),
955
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
956
ptr->string = (char *)my_malloc(table_string.length+1,
957
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
958
ptr->length= table_string.length+1;
959
ptr->type= CREATE_TABLE_TYPE;
960
strmov(ptr->string, table_string.str);
961
dynstr_free(&table_string);
966
build_update_string()
968
This function builds insert statements when the user opts to not supply
969
an insert file or string containing insert data
972
build_update_string(void)
974
char buf[HUGE_STRING_LENGTH];
975
unsigned int col_count;
977
DYNAMIC_STRING update_string;
978
DBUG_ENTER("build_update_string");
980
init_dynamic_string(&update_string, "", HUGE_STRING_LENGTH, HUGE_STRING_LENGTH);
982
dynstr_append(&update_string, "UPDATE t1 SET ");
985
for (col_count= 1; col_count <= num_int_cols; col_count++)
987
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d = %ld", col_count,
988
random()) > HUGE_STRING_LENGTH)
990
fprintf(stderr, "Memory Allocation error in creating update\n");
993
dynstr_append(&update_string, buf);
995
if (col_count < num_int_cols || num_char_cols > 0)
996
dynstr_append_mem(&update_string, ",", 1);
1000
for (col_count= 1; col_count <= num_char_cols; col_count++)
1002
char rand_buffer[RAND_STRING_SIZE];
1003
int buf_len= get_random_string(rand_buffer, RAND_STRING_SIZE);
1005
if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d = '%.*s'", col_count,
1006
buf_len, rand_buffer)
1007
> HUGE_STRING_LENGTH)
1009
fprintf(stderr, "Memory Allocation error in creating update\n");
1012
dynstr_append(&update_string, buf);
1014
if (col_count < num_char_cols)
1015
dynstr_append_mem(&update_string, ",", 1);
1018
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
1019
dynstr_append(&update_string, " WHERE id = ");
1022
ptr= (statement *)my_malloc(sizeof(statement),
1023
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1025
ptr->string= (char *)my_malloc(update_string.length + 1,
1026
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1027
ptr->length= update_string.length+1;
1028
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
1029
ptr->type= UPDATE_TYPE_REQUIRES_PREFIX ;
1031
ptr->type= UPDATE_TYPE;
1032
strmov(ptr->string, update_string.str);
1033
dynstr_free(&update_string);
1039
build_insert_string()
1041
This function builds insert statements when the user opts to not supply
1042
an insert file or string containing insert data
1045
build_insert_string(void)
1047
char buf[HUGE_STRING_LENGTH];
1048
unsigned int col_count;
1050
DYNAMIC_STRING insert_string;
1051
DBUG_ENTER("build_insert_string");
1053
init_dynamic_string(&insert_string, "", HUGE_STRING_LENGTH, HUGE_STRING_LENGTH);
1055
dynstr_append(&insert_string, "INSERT INTO t1 VALUES (");
1057
if (auto_generate_sql_autoincrement)
1059
dynstr_append(&insert_string, "NULL");
1061
if (num_int_cols || num_char_cols)
1062
dynstr_append(&insert_string, ",");
1065
if (auto_generate_sql_guid_primary)
1067
dynstr_append(&insert_string, "uuid()");
1069
if (num_int_cols || num_char_cols)
1070
dynstr_append(&insert_string, ",");
1073
if (auto_generate_sql_secondary_indexes)
1077
for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
1079
if (count) /* Except for the first pass we add a comma */
1080
dynstr_append(&insert_string, ",");
1082
dynstr_append(&insert_string, "uuid()");
1085
if (num_int_cols || num_char_cols)
1086
dynstr_append(&insert_string, ",");
1090
for (col_count= 1; col_count <= num_int_cols; col_count++)
1092
if (snprintf(buf, HUGE_STRING_LENGTH, "%ld", random()) > HUGE_STRING_LENGTH)
1094
fprintf(stderr, "Memory Allocation error in creating insert\n");
1097
dynstr_append(&insert_string, buf);
1099
if (col_count < num_int_cols || num_char_cols > 0)
1100
dynstr_append_mem(&insert_string, ",", 1);
1104
for (col_count= 1; col_count <= num_char_cols; col_count++)
1106
int buf_len= get_random_string(buf, RAND_STRING_SIZE);
1107
dynstr_append_mem(&insert_string, "'", 1);
1108
dynstr_append_mem(&insert_string, buf, buf_len);
1109
dynstr_append_mem(&insert_string, "'", 1);
1111
if (col_count < num_char_cols || num_blob_cols > 0)
1112
dynstr_append_mem(&insert_string, ",", 1);
1119
if (num_blob_cols_size > HUGE_STRING_LENGTH)
1121
blob_ptr= (char *)my_malloc(sizeof(char)*num_blob_cols_size,
1122
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1125
fprintf(stderr, "Memory Allocation error in creating select\n");
1134
for (col_count= 1; col_count <= num_blob_cols; col_count++)
1136
unsigned int buf_len;
1138
unsigned int difference= num_blob_cols_size - num_blob_cols_size_min;
1140
size= difference ? (num_blob_cols_size_min + (random() % difference)) :
1143
buf_len= get_random_string(blob_ptr, size);
1145
dynstr_append_mem(&insert_string, "'", 1);
1146
dynstr_append_mem(&insert_string, blob_ptr, buf_len);
1147
dynstr_append_mem(&insert_string, "'", 1);
1149
if (col_count < num_blob_cols)
1150
dynstr_append_mem(&insert_string, ",", 1);
1153
if (num_blob_cols_size > HUGE_STRING_LENGTH)
1154
my_free(blob_ptr, MYF(0));
1157
dynstr_append_mem(&insert_string, ")", 1);
1159
if (!(ptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL|MY_FAE|MY_WME))))
1161
fprintf(stderr, "Memory Allocation error in creating select\n");
1164
if (!(ptr->string= (char *)my_malloc(insert_string.length + 1, MYF(MY_ZEROFILL|MY_FAE|MY_WME))))
1166
fprintf(stderr, "Memory Allocation error in creating select\n");
1169
ptr->length= insert_string.length+1;
1170
ptr->type= INSERT_TYPE;
1171
strmov(ptr->string, insert_string.str);
1172
dynstr_free(&insert_string);
1179
build_select_string()
1181
This function builds a query if the user opts to not supply a query
1182
statement or file containing a query statement
1185
build_select_string(my_bool key)
1187
char buf[HUGE_STRING_LENGTH];
1188
unsigned int col_count;
1190
static DYNAMIC_STRING query_string;
1191
DBUG_ENTER("build_select_string");
1193
init_dynamic_string(&query_string, "", HUGE_STRING_LENGTH, HUGE_STRING_LENGTH);
1195
dynstr_append_mem(&query_string, "SELECT ", 7);
1196
if (auto_generate_selected_columns_opt)
1198
dynstr_append(&query_string, auto_generate_selected_columns_opt);
1202
for (col_count= 1; col_count <= num_int_cols; col_count++)
1204
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d", col_count)
1205
> HUGE_STRING_LENGTH)
1207
fprintf(stderr, "Memory Allocation error in creating select\n");
1210
dynstr_append(&query_string, buf);
1212
if (col_count < num_int_cols || num_char_cols > 0)
1213
dynstr_append_mem(&query_string, ",", 1);
1216
for (col_count= 1; col_count <= num_char_cols; col_count++)
1218
if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d", col_count)
1219
> HUGE_STRING_LENGTH)
1221
fprintf(stderr, "Memory Allocation error in creating select\n");
1224
dynstr_append(&query_string, buf);
1226
if (col_count < num_char_cols || num_blob_cols > 0)
1227
dynstr_append_mem(&query_string, ",", 1);
1230
for (col_count= 1; col_count <= num_blob_cols; col_count++)
1232
if (snprintf(buf, HUGE_STRING_LENGTH, "blobcol%d", col_count)
1233
> HUGE_STRING_LENGTH)
1235
fprintf(stderr, "Memory Allocation error in creating select\n");
1238
dynstr_append(&query_string, buf);
1240
if (col_count < num_blob_cols)
1241
dynstr_append_mem(&query_string, ",", 1);
1244
dynstr_append(&query_string, " FROM t1");
1247
(auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
1248
dynstr_append(&query_string, " WHERE id = ");
1250
ptr= (statement *)my_malloc(sizeof(statement),
1251
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1252
ptr->string= (char *)my_malloc(query_string.length + 1,
1253
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1254
ptr->length= query_string.length+1;
1256
(auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
1257
ptr->type= SELECT_TYPE_REQUIRES_PREFIX;
1259
ptr->type= SELECT_TYPE;
1260
strmov(ptr->string, query_string.str);
1261
dynstr_free(&query_string);
1266
get_options(int *argc,char ***argv)
1270
MY_STAT sbuf; /* Stat information for the data file */
1271
option_string *sql_type;
1272
unsigned int sql_type_count= 0;
1274
DBUG_ENTER("get_options");
1275
if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
1277
if (debug_info_flag)
1278
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1279
if (debug_check_flag)
1280
my_end_arg= MY_CHECK_ERROR;
1283
user= (char *)"root";
1285
/* If something is created we clean it up, otherwise we leave schemas alone */
1286
if (create_string || auto_generate_sql)
1287
opt_preserve= FALSE;
1289
if (auto_generate_sql && (create_string || user_supplied_query))
1292
"%s: Can't use --auto-generate-sql when create and query strings are specified!\n",
1297
if (auto_generate_sql && auto_generate_sql_guid_primary &&
1298
auto_generate_sql_autoincrement)
1301
"%s: Either auto-generate-sql-guid-primary or auto-generate-sql-add-autoincrement can be used!\n",
1306
if (auto_generate_sql && num_of_query && auto_actual_queries)
1309
"%s: Either auto-generate-sql-execute-number or number-of-queries can be used!\n",
1314
parse_comma(concurrency_str ? concurrency_str : "1", &concurrency);
1320
if (opt_csv_str[0] == '-')
1322
csv_file= fileno(stdout);
1326
if ((csv_file= my_open(opt_csv_str, O_CREAT|O_WRONLY|O_APPEND, MYF(0)))
1329
fprintf(stderr,"%s: Could not open csv file: %sn\n",
1330
my_progname, opt_csv_str);
1339
if (num_int_cols_opt)
1342
parse_option(num_int_cols_opt, &str, ',');
1343
num_int_cols= atoi(str->string);
1345
num_int_cols_index= atoi(str->option);
1346
option_cleanup(str);
1349
if (num_char_cols_opt)
1352
parse_option(num_char_cols_opt, &str, ',');
1353
num_char_cols= atoi(str->string);
1355
num_char_cols_index= atoi(str->option);
1357
num_char_cols_index= 0;
1358
option_cleanup(str);
1361
if (num_blob_cols_opt)
1364
parse_option(num_blob_cols_opt, &str, ',');
1365
num_blob_cols= atoi(str->string);
1370
if ((sep_ptr= strchr(str->option, '/')))
1372
num_blob_cols_size_min= atoi(str->option);
1373
num_blob_cols_size= atoi(sep_ptr+1);
1377
num_blob_cols_size_min= num_blob_cols_size= atoi(str->option);
1382
num_blob_cols_size= DEFAULT_BLOB_SIZE;
1383
num_blob_cols_size_min= DEFAULT_BLOB_SIZE;
1385
option_cleanup(str);
1389
if (auto_generate_sql)
1391
unsigned long long x= 0;
1392
statement *ptr_statement;
1395
printf("Building Create Statements for Auto\n");
1397
create_statements= build_table_string();
1401
for (ptr_statement= create_statements, x= 0;
1402
x < auto_generate_sql_unique_write_number;
1403
x++, ptr_statement= ptr_statement->next)
1405
ptr_statement->next= build_insert_string();
1409
printf("Building Query Statements for Auto\n");
1411
if (!opt_auto_generate_sql_type)
1412
opt_auto_generate_sql_type= "mixed";
1414
query_statements_count=
1415
parse_option(opt_auto_generate_sql_type, &query_options, ',');
1417
query_statements= (statement **)my_malloc(sizeof(statement *) * query_statements_count,
1418
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1420
sql_type= query_options;
1423
if (sql_type->string[0] == 'r')
1426
printf("Generating SELECT Statements for Auto\n");
1428
query_statements[sql_type_count]= build_select_string(FALSE);
1429
for (ptr_statement= query_statements[sql_type_count], x= 0;
1430
x < auto_generate_sql_unique_query_number;
1431
x++, ptr_statement= ptr_statement->next)
1433
ptr_statement->next= build_select_string(FALSE);
1436
else if (sql_type->string[0] == 'k')
1439
printf("Generating SELECT for keys Statements for Auto\n");
1441
if ( auto_generate_sql_autoincrement == FALSE &&
1442
auto_generate_sql_guid_primary == FALSE)
1445
"%s: Can't perform key test without a primary key!\n",
1450
query_statements[sql_type_count]= build_select_string(TRUE);
1451
for (ptr_statement= query_statements[sql_type_count], x= 0;
1452
x < auto_generate_sql_unique_query_number;
1453
x++, ptr_statement= ptr_statement->next)
1455
ptr_statement->next= build_select_string(TRUE);
1458
else if (sql_type->string[0] == 'w')
1461
We generate a number of strings in case the engine is
1462
Archive (since strings which were identical one after another
1463
would be too easily optimized).
1466
printf("Generating INSERT Statements for Auto\n");
1467
query_statements[sql_type_count]= build_insert_string();
1468
for (ptr_statement= query_statements[sql_type_count], x= 0;
1469
x < auto_generate_sql_unique_query_number;
1470
x++, ptr_statement= ptr_statement->next)
1472
ptr_statement->next= build_insert_string();
1475
else if (sql_type->string[0] == 'u')
1477
if ( auto_generate_sql_autoincrement == FALSE &&
1478
auto_generate_sql_guid_primary == FALSE)
1481
"%s: Can't perform update test without a primary key!\n",
1486
query_statements[sql_type_count]= build_update_string();
1487
for (ptr_statement= query_statements[sql_type_count], x= 0;
1488
x < auto_generate_sql_unique_query_number;
1489
x++, ptr_statement= ptr_statement->next)
1491
ptr_statement->next= build_update_string();
1494
else /* Mixed mode is default */
1498
query_statements[sql_type_count]= build_insert_string();
1500
This logic should be extended to do a more mixed load,
1501
at the moment it results in "every other".
1503
for (ptr_statement= query_statements[sql_type_count], x= 0;
1504
x < auto_generate_sql_unique_query_number;
1505
x++, ptr_statement= ptr_statement->next)
1509
ptr_statement->next= build_insert_string();
1514
ptr_statement->next= build_select_string(TRUE);
1520
} while (sql_type ? (sql_type= sql_type->next) : 0);
1524
if (create_string && my_stat(create_string, &sbuf, MYF(0)))
1527
if (!MY_S_ISREG(sbuf.st_mode))
1529
fprintf(stderr,"%s: Create file was not a regular file\n",
1533
if ((data_file= my_open(create_string, O_RDWR, MYF(0))) == -1)
1535
fprintf(stderr,"%s: Could not open create file\n", my_progname);
1538
tmp_string= (char *)my_malloc(sbuf.st_size + 1,
1539
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1540
my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
1541
tmp_string[sbuf.st_size]= '\0';
1542
my_close(data_file,MYF(0));
1543
parse_delimiter(tmp_string, &create_statements, delimiter[0]);
1544
my_free(tmp_string, MYF(0));
1546
else if (create_string)
1548
parse_delimiter(create_string, &create_statements, delimiter[0]);
1551
/* Set this up till we fully support options on user generated queries */
1552
if (user_supplied_query)
1554
query_statements_count=
1555
parse_option("default", &query_options, ',');
1557
query_statements= (statement **)my_malloc(sizeof(statement *),
1558
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1561
if (user_supplied_query && my_stat(user_supplied_query, &sbuf, MYF(0)))
1564
if (!MY_S_ISREG(sbuf.st_mode))
1566
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1570
if ((data_file= my_open(user_supplied_query, O_RDWR, MYF(0))) == -1)
1572
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
1575
tmp_string= (char *)my_malloc(sbuf.st_size + 1,
1576
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1577
my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
1578
tmp_string[sbuf.st_size]= '\0';
1579
my_close(data_file,MYF(0));
1580
if (user_supplied_query)
1581
actual_queries= parse_delimiter(tmp_string, &query_statements[0],
1583
my_free(tmp_string, MYF(0));
1585
else if (user_supplied_query)
1587
actual_queries= parse_delimiter(user_supplied_query, &query_statements[0],
1592
if (user_supplied_pre_statements && my_stat(user_supplied_pre_statements, &sbuf, MYF(0)))
1595
if (!MY_S_ISREG(sbuf.st_mode))
1597
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1601
if ((data_file= my_open(user_supplied_pre_statements, O_RDWR, MYF(0))) == -1)
1603
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
1606
tmp_string= (char *)my_malloc(sbuf.st_size + 1,
1607
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1608
my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
1609
tmp_string[sbuf.st_size]= '\0';
1610
my_close(data_file,MYF(0));
1611
if (user_supplied_pre_statements)
1612
(void)parse_delimiter(tmp_string, &pre_statements,
1614
my_free(tmp_string, MYF(0));
1616
else if (user_supplied_pre_statements)
1618
(void)parse_delimiter(user_supplied_pre_statements,
1623
if (user_supplied_post_statements && my_stat(user_supplied_post_statements, &sbuf, MYF(0)))
1626
if (!MY_S_ISREG(sbuf.st_mode))
1628
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1632
if ((data_file= my_open(user_supplied_post_statements, O_RDWR, MYF(0))) == -1)
1634
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
1637
tmp_string= (char *)my_malloc(sbuf.st_size + 1,
1638
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1639
my_read(data_file, (uchar*) tmp_string, sbuf.st_size, MYF(0));
1640
tmp_string[sbuf.st_size]= '\0';
1641
my_close(data_file,MYF(0));
1642
if (user_supplied_post_statements)
1643
(void)parse_delimiter(tmp_string, &post_statements,
1645
my_free(tmp_string, MYF(0));
1647
else if (user_supplied_post_statements)
1649
(void)parse_delimiter(user_supplied_post_statements, &post_statements,
1654
printf("Parsing engines to use.\n");
1657
parse_option(default_engine, &engine_options, ',');
1660
opt_password= get_tty_password(NullS);
1665
static int run_query(MYSQL *mysql, const char *query, int len)
1669
printf("%.*s;\n", len, query);
1674
printf("%.*s;\n", len, query);
1675
return mysql_real_query(mysql, query, len);
1680
generate_primary_key_list(MYSQL *mysql, option_string *engine_stmt)
1684
unsigned long long counter;
1685
DBUG_ENTER("generate_primary_key_list");
1688
Blackhole is a special case, this allows us to test the upper end
1689
of the server during load runs.
1691
if (opt_only_print || (engine_stmt &&
1692
strstr(engine_stmt->string, "blackhole")))
1694
primary_keys_number_of= 1;
1695
primary_keys= (char **)my_malloc((uint)(sizeof(char *) *
1696
primary_keys_number_of),
1697
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1698
/* Yes, we strdup a const string to simplify the interface */
1699
primary_keys[0]= my_strdup("796c4422-1d94-102a-9d6d-00e0812d", MYF(0));
1703
if (run_query(mysql, "SELECT id from t1", strlen("SELECT id from t1")))
1705
fprintf(stderr,"%s: Cannot select GUID primary keys. (%s)\n", my_progname,
1706
mysql_error(mysql));
1710
result= mysql_store_result(mysql);
1711
primary_keys_number_of= mysql_num_rows(result);
1713
/* So why check this? Blackhole :) */
1714
if (primary_keys_number_of)
1717
We create the structure and loop and create the items.
1719
primary_keys= (char **)my_malloc((uint)(sizeof(char *) *
1720
primary_keys_number_of),
1721
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
1722
row= mysql_fetch_row(result);
1723
for (counter= 0; counter < primary_keys_number_of;
1724
counter++, row= mysql_fetch_row(result))
1725
primary_keys[counter]= my_strdup(row[0], MYF(0));
1728
mysql_free_result(result);
1735
drop_primary_key_list(void)
1737
unsigned long long counter;
1739
if (primary_keys_number_of)
1741
for (counter= 0; counter < primary_keys_number_of; counter++)
1742
my_free(primary_keys[counter], MYF(0));
1744
my_free(primary_keys, MYF(0));
1751
create_schema(MYSQL *mysql, const char *db, statement *stmt,
1752
option_string *engine_stmt, stats *sptr)
1754
char query[HUGE_STRING_LENGTH];
1756
statement *after_create;
1759
struct timeval start_time, end_time;
1760
DBUG_ENTER("create_schema");
1762
gettimeofday(&start_time, NULL);
1764
len= snprintf(query, HUGE_STRING_LENGTH, "CREATE SCHEMA `%s`", db);
1767
printf("Loading Pre-data\n");
1769
if (run_query(mysql, query, len))
1771
fprintf(stderr,"%s: Cannot create schema %s : %s\n", my_progname, db,
1772
mysql_error(mysql));
1777
sptr->create_count++;
1782
printf("use %s;\n", db);
1787
printf("%s;\n", query);
1789
if (mysql_select_db(mysql, db))
1791
fprintf(stderr,"%s: Cannot select schema '%s': %s\n",my_progname, db,
1792
mysql_error(mysql));
1795
sptr->create_count++;
1800
len= snprintf(query, HUGE_STRING_LENGTH, "set storage_engine=`%s`",
1801
engine_stmt->string);
1802
if (run_query(mysql, query, len))
1804
fprintf(stderr,"%s: Cannot set default engine: %s\n", my_progname,
1805
mysql_error(mysql));
1808
sptr->create_count++;
1815
for (ptr= after_create; ptr && ptr->length; ptr= ptr->next, count++)
1817
if (auto_generate_sql && ( auto_generate_sql_number == count))
1820
if (engine_stmt && engine_stmt->option && ptr->type == CREATE_TABLE_TYPE)
1822
char buffer[HUGE_STRING_LENGTH];
1824
snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->string,
1825
engine_stmt->option);
1826
if (run_query(mysql, buffer, strlen(buffer)))
1828
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1829
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
1830
if (!opt_ignore_sql_errors)
1833
sptr->create_count++;
1837
if (run_query(mysql, ptr->string, ptr->length))
1839
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1840
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
1841
if (!opt_ignore_sql_errors)
1844
sptr->create_count++;
1848
if (auto_generate_sql && (auto_generate_sql_number > count ))
1850
/* Special case for auto create, we don't want to create tables twice */
1851
after_create= stmt->next;
1855
gettimeofday(&end_time, NULL);
1857
sptr->create_timing= timedif(end_time, start_time);
1863
drop_schema(MYSQL *mysql, const char *db)
1865
char query[HUGE_STRING_LENGTH];
1867
DBUG_ENTER("drop_schema");
1868
len= snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS `%s`", db);
1870
if (run_query(mysql, query, len))
1872
fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
1873
my_progname, db, mysql_error(mysql));
1883
run_statements(MYSQL *mysql, statement *stmt)
1887
DBUG_ENTER("run_statements");
1889
for (ptr= stmt; ptr && ptr->length; ptr= ptr->next)
1891
if (run_query(mysql, ptr->string, ptr->length))
1893
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1894
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
1897
if (!opt_only_print)
1899
if (mysql_field_count(mysql))
1901
result= mysql_store_result(mysql);
1902
mysql_free_result(result);
1911
run_scheduler(stats *sptr, statement **stmts, uint concur, ulonglong limit)
1915
unsigned int real_concurrency;
1916
struct timeval start_time, end_time;
1917
option_string *sql_type;
1918
thread_context *con;
1919
pthread_t mainthread; /* Thread descriptor */
1920
pthread_attr_t attr; /* Thread attributes */
1921
DBUG_ENTER("run_scheduler");
1923
pthread_attr_init(&attr);
1924
pthread_attr_setdetachstate(&attr,
1925
PTHREAD_CREATE_DETACHED);
1927
pthread_mutex_lock(&counter_mutex);
1930
pthread_mutex_lock(&sleeper_mutex);
1932
pthread_mutex_unlock(&sleeper_mutex);
1934
real_concurrency= 0;
1936
for (y= 0, sql_type= query_options;
1937
y < query_statements_count;
1938
y++, sql_type= sql_type->next)
1940
unsigned int options_loop= 1;
1942
if (sql_type->option)
1944
options_loop= strtol(sql_type->option,
1946
options_loop= options_loop ? options_loop : 1;
1949
while (options_loop--)
1950
for (x= 0; x < concur; x++)
1952
con= (thread_context *)my_malloc(sizeof(thread_context), MYF(0));
1953
con->stmt= stmts[y];
1957
/* now you create the thread */
1958
if (pthread_create(&mainthread, &attr, run_task,
1961
fprintf(stderr,"%s: Could not create thread\n", my_progname);
1969
The timer_thread belongs to all threads so it too obeys the wakeup
1970
call that run tasks obey.
1972
if (opt_timer_length)
1974
pthread_mutex_lock(&timer_alarm_mutex);
1976
pthread_mutex_unlock(&timer_alarm_mutex);
1978
if (pthread_create(&mainthread, &attr, timer_thread,
1979
(void *)&opt_timer_length) != 0)
1981
fprintf(stderr,"%s: Could not create timer thread\n", my_progname);
1986
pthread_mutex_unlock(&counter_mutex);
1987
pthread_attr_destroy(&attr);
1989
pthread_mutex_lock(&sleeper_mutex);
1991
pthread_mutex_unlock(&sleeper_mutex);
1992
pthread_cond_broadcast(&sleep_threshhold);
1994
gettimeofday(&start_time, NULL);
1997
We loop until we know that all children have cleaned up.
1999
pthread_mutex_lock(&counter_mutex);
2000
while (thread_counter)
2002
struct timespec abstime;
2004
set_timespec(abstime, 3);
2005
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
2007
pthread_mutex_unlock(&counter_mutex);
2009
gettimeofday(&end_time, NULL);
2012
sptr->timing= timedif(end_time, start_time);
2013
sptr->users= concur;
2014
sptr->real_users= real_concurrency;
2021
pthread_handler_t timer_thread(void *p)
2023
uint *timer_length= (uint *)p;
2024
struct timespec abstime;
2026
DBUG_ENTER("timer_thread");
2028
if (mysql_thread_init())
2030
fprintf(stderr,"%s: mysql_thread_init() failed.\n",
2036
We lock around the initial call in case were we in a loop. This
2037
also keeps the value properly syncronized across call threads.
2039
pthread_mutex_lock(&sleeper_mutex);
2040
while (master_wakeup)
2042
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
2044
pthread_mutex_unlock(&sleeper_mutex);
2046
set_timespec(abstime, *timer_length);
2048
pthread_mutex_lock(&timer_alarm_mutex);
2049
pthread_cond_timedwait(&timer_alarm_threshold, &timer_alarm_mutex, &abstime);
2050
pthread_mutex_unlock(&timer_alarm_mutex);
2052
pthread_mutex_lock(&timer_alarm_mutex);
2054
pthread_mutex_unlock(&timer_alarm_mutex);
2060
pthread_handler_t run_task(void *p)
2062
ulonglong counter= 0, queries;
2063
ulonglong detach_counter;
2064
unsigned int commit_counter;
2069
thread_context *con= (thread_context *)p;
2071
DBUG_ENTER("run_task");
2073
if (mysql_thread_init())
2075
fprintf(stderr,"%s: mysql_thread_init() failed.\n",
2080
DBUG_PRINT("info", ("task script \"%s\"", con->stmt ? con->stmt->string : ""));
2082
pthread_mutex_lock(&sleeper_mutex);
2083
while (master_wakeup)
2085
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
2087
pthread_mutex_unlock(&sleeper_mutex);
2089
DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user));
2091
slap_connect(&mysql, TRUE);
2093
DBUG_PRINT("info", ("connected."));
2095
printf("connected!\n");
2100
run_query(&mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
2103
for (ptr= con->stmt, detach_counter= 0;
2105
ptr= ptr->next, detach_counter++)
2107
if (!opt_only_print && detach_rate && !(detach_counter % detach_rate))
2110
slap_connect(&mysql, TRUE);
2114
We have to execute differently based on query type. This should become a function.
2116
if ((ptr->type == UPDATE_TYPE_REQUIRES_PREFIX) ||
2117
(ptr->type == SELECT_TYPE_REQUIRES_PREFIX))
2120
unsigned int key_val;
2122
char buffer[HUGE_STRING_LENGTH];
2125
This should only happen if some sort of new engine was
2126
implemented that didn't properly handle UPDATEs.
2128
Just in case someone runs this under an experimental engine we don't
2129
want a crash so the if() is placed here.
2131
DBUG_ASSERT(primary_keys_number_of);
2132
if (primary_keys_number_of)
2134
key_val= (unsigned int)(random() % primary_keys_number_of);
2135
key= primary_keys[key_val];
2139
length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
2140
(int)ptr->length, ptr->string, key);
2142
if (run_query(&mysql, buffer, length))
2144
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2145
my_progname, (uint)length, buffer, mysql_error(&mysql));
2152
if (run_query(&mysql, ptr->string, ptr->length))
2154
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2155
my_progname, (uint)ptr->length, ptr->string, mysql_error(&mysql));
2160
if (!opt_only_print)
2164
if (mysql_field_count(&mysql))
2166
result= mysql_store_result(&mysql);
2167
while ((row = mysql_fetch_row(result)))
2169
mysql_free_result(result);
2171
} while(mysql_next_result(&mysql) == 0);
2175
if (commit_rate && (++commit_counter == commit_rate))
2178
run_query(&mysql, "COMMIT", strlen("COMMIT"));
2181
/* If the timer is set, and the alarm is not active then end */
2182
if (opt_timer_length && timer_alarm == FALSE)
2185
/* If limit has been reached, and we are not in a timer_alarm just end */
2186
if (con->limit && queries == con->limit && timer_alarm == FALSE)
2190
if (opt_timer_length && timer_alarm == TRUE)
2193
if (con->limit && queries < con->limit)
2199
run_query(&mysql, "COMMIT", strlen("COMMIT"));
2203
pthread_mutex_lock(&counter_mutex);
2205
pthread_cond_signal(&count_threshhold);
2206
pthread_mutex_unlock(&counter_mutex);
2208
my_free(con, MYF(0));
2215
Parse records from comma seperated string. : is a reserved character and is used for options
2219
parse_option(const char *origin, option_string **stmt, char delm)
2224
option_string **sptr= stmt;
2226
uint length= strlen(origin);
2227
uint count= 0; /* We know that there is always one */
2229
end_ptr= (char *)origin + length;
2231
tmp= *sptr= (option_string *)my_malloc(sizeof(option_string),
2232
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
2234
for (begin_ptr= (char *)origin;
2235
begin_ptr != end_ptr;
2238
char buffer[HUGE_STRING_LENGTH];
2241
bzero(buffer, HUGE_STRING_LENGTH);
2243
string= strchr(begin_ptr, delm);
2247
memcpy(buffer, begin_ptr, string - begin_ptr);
2248
begin_ptr= string+1;
2252
size_t length= strlen(begin_ptr);
2253
memcpy(buffer, begin_ptr, length);
2257
if ((buffer_ptr= strchr(buffer, ':')))
2259
/* Set a null so that we can get strlen() correct later on */
2263
/* Move past the : and the first string */
2264
tmp->option_length= strlen(buffer_ptr);
2265
tmp->option= my_strndup(buffer_ptr, (uint)tmp->option_length,
2269
tmp->string= my_strndup(buffer, strlen(buffer), MYF(MY_FAE));
2270
tmp->length= strlen(buffer);
2272
if (isspace(*begin_ptr))
2277
if (begin_ptr != end_ptr)
2278
tmp->next= (option_string *)my_malloc(sizeof(option_string),
2279
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
2287
Raw parsing interface. If you want the slap specific parser look at
2291
parse_delimiter(const char *script, statement **stmt, char delm)
2294
char *ptr= (char *)script;
2295
statement **sptr= stmt;
2297
uint length= strlen(script);
2298
uint count= 0; /* We know that there is always one */
2300
for (tmp= *sptr= (statement *)my_malloc(sizeof(statement),
2301
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
2302
(retstr= strchr(ptr, delm));
2303
tmp->next= (statement *)my_malloc(sizeof(statement),
2304
MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
2308
tmp->string= my_strndup(ptr, (uint)(retstr - ptr), MYF(MY_FAE));
2309
tmp->length= (size_t)(retstr - ptr);
2310
ptr+= retstr - ptr + 1;
2315
if (ptr != script+length)
2317
tmp->string= my_strndup(ptr, (uint)((script + length) - ptr),
2319
tmp->length= (size_t)((script + length) - ptr);
2328
Parse comma is different from parse_delimeter in that it parses
2329
number ranges from a comma seperated string.
2330
In restrospect, this is a lousy name from this function.
2333
parse_comma(const char *string, uint **range)
2335
uint count= 1,x; /* We know that there is always one */
2337
char *ptr= (char *)string;
2341
if (*ptr == ',') count++;
2343
/* One extra spot for the NULL */
2344
nptr= *range= (uint *)my_malloc(sizeof(uint) * (count + 1),
2345
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
2347
ptr= (char *)string;
2349
while ((retstr= strchr(ptr,',')))
2351
nptr[x++]= atoi(ptr);
2352
ptr+= retstr - ptr + 1;
2354
nptr[x++]= atoi(ptr);
2360
print_conclusions(conclusions *con)
2362
printf("Benchmark\n");
2364
printf("\tRunning for engine %s\n", con->engine);
2365
if (opt_label || opt_auto_generate_sql_type)
2367
const char *ptr= opt_auto_generate_sql_type ? opt_auto_generate_sql_type : "query";
2368
printf("\tLoad: %s\n", opt_label ? opt_label : ptr);
2370
printf("\tAverage Time took to generate schema and initial data: %ld.%03ld seconds\n",
2371
con->create_avg_timing / 1000, con->create_avg_timing % 1000);
2372
printf("\tAverage number of seconds to run all queries: %ld.%03ld seconds\n",
2373
con->avg_timing / 1000, con->avg_timing % 1000);
2374
printf("\tMinimum number of seconds to run all queries: %ld.%03ld seconds\n",
2375
con->min_timing / 1000, con->min_timing % 1000);
2376
printf("\tMaximum number of seconds to run all queries: %ld.%03ld seconds\n",
2377
con->max_timing / 1000, con->max_timing % 1000);
2378
printf("\tTotal time for tests: %ld.%03ld seconds\n",
2379
con->sum_of_time / 1000, con->sum_of_time % 1000);
2380
printf("\tStandard Deviation: %ld.%03ld\n", con->std_dev / 1000, con->std_dev % 1000);
2381
printf("\tNumber of queries in create queries: %llu\n", con->create_count);
2382
printf("\tNumber of clients running queries: %u/%u\n",
2383
con->users, con->real_users);
2384
printf("\tNumber of times test was run: %u\n", iterations);
2385
printf("\tAverage number of queries per client: %llu\n", con->avg_rows);
2390
print_conclusions_csv(conclusions *con)
2393
char buffer[HUGE_STRING_LENGTH];
2394
char label_buffer[HUGE_STRING_LENGTH];
2397
bzero(label_buffer, HUGE_STRING_LENGTH);
2401
string_len= strlen(opt_label);
2403
for (x= 0; x < string_len; x++)
2405
if (opt_label[x] == ',')
2406
label_buffer[x]= '-';
2408
label_buffer[x]= opt_label[x] ;
2411
else if (opt_auto_generate_sql_type)
2413
string_len= strlen(opt_auto_generate_sql_type);
2415
for (x= 0; x < string_len; x++)
2417
if (opt_auto_generate_sql_type[x] == ',')
2418
label_buffer[x]= '-';
2420
label_buffer[x]= opt_auto_generate_sql_type[x] ;
2424
snprintf(label_buffer, HUGE_STRING_LENGTH, "query");
2426
snprintf(buffer, HUGE_STRING_LENGTH,
2427
"%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,%u,%u,%u,%llu\n",
2428
con->engine ? con->engine : "", /* Storage engine we ran against */
2429
label_buffer, /* Load type */
2430
con->avg_timing / 1000, con->avg_timing % 1000, /* Time to load */
2431
con->min_timing / 1000, con->min_timing % 1000, /* Min time */
2432
con->max_timing / 1000, con->max_timing % 1000, /* Max time */
2433
con->sum_of_time / 1000, con->sum_of_time % 1000, /* Total time */
2434
con->std_dev / 1000, con->std_dev % 1000, /* Standard Deviation */
2435
iterations, /* Iterations */
2436
con->users, /* Children used max_timing */
2437
con->real_users, /* Children used max_timing */
2438
con->avg_rows /* Queries run */
2440
my_write(csv_file, (uchar*) buffer, (uint)strlen(buffer), MYF(0));
2444
generate_stats(conclusions *con, option_string *eng, stats *sptr)
2449
con->min_timing= sptr->timing;
2450
con->max_timing= sptr->timing;
2451
con->min_rows= sptr->rows;
2452
con->max_rows= sptr->rows;
2454
/* At the moment we assume uniform */
2455
con->users= sptr->users;
2456
con->real_users= sptr->real_users;
2457
con->avg_rows= sptr->rows;
2459
/* With no next, we know it is the last element that was malloced */
2460
for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
2462
con->avg_timing+= ptr->timing;
2464
if (ptr->timing > con->max_timing)
2465
con->max_timing= ptr->timing;
2466
if (ptr->timing < con->min_timing)
2467
con->min_timing= ptr->timing;
2469
con->sum_of_time= con->avg_timing;
2470
con->avg_timing= con->avg_timing/iterations;
2472
if (eng && eng->string)
2473
con->engine= eng->string;
2477
standard_deviation(con, sptr);
2479
/* Now we do the create time operations */
2480
con->create_min_timing= sptr->create_timing;
2481
con->create_max_timing= sptr->create_timing;
2483
/* At the moment we assume uniform */
2484
con->create_count= sptr->create_count;
2486
/* With no next, we know it is the last element that was malloced */
2487
for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
2489
con->create_avg_timing+= ptr->create_timing;
2491
if (ptr->create_timing > con->create_max_timing)
2492
con->create_max_timing= ptr->create_timing;
2493
if (ptr->create_timing < con->create_min_timing)
2494
con->create_min_timing= ptr->create_timing;
2496
con->create_avg_timing= con->create_avg_timing/iterations;
2500
option_cleanup(option_string *stmt)
2502
option_string *ptr, *nptr;
2506
for (ptr= stmt; ptr; ptr= nptr)
2510
my_free(ptr->string, MYF(0));
2512
my_free(ptr->option, MYF(0));
2513
my_free(ptr, MYF(0));
2518
statement_cleanup(statement *stmt)
2520
statement *ptr, *nptr;
2524
for (ptr= stmt; ptr; ptr= nptr)
2528
my_free(ptr->string, MYF(0));
2529
my_free(ptr, MYF(0));
2534
slap_close(MYSQL *mysql)
2543
slap_connect(MYSQL *mysql, my_bool connect_to_schema)
2545
/* Connect to server */
2546
static ulong connection_retry_sleep= 100000; /* Microseconds */
2547
int x, connect_error= 1;
2552
if (opt_delayed_start)
2553
my_sleep(random()%opt_delayed_start);
2558
mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
2559
/* We always do opt_protocol to TCP/IP */
2560
mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
2561
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
2563
for (x= 0; x < 10; x++)
2567
if (mysql_real_connect(mysql, host, user, opt_password,
2568
connect_to_schema ? create_schema_string : NULL,
2570
opt_mysql_unix_port,
2573
/* Connect suceeded */
2577
my_sleep(connection_retry_sleep);
2581
fprintf(stderr,"%s: Error when connecting to server: %d %s\n",
2582
my_progname, mysql_errno(mysql), mysql_error(mysql));
2590
standard_deviation (conclusions *con, stats *sptr)
2593
long int sum_of_squares;
2597
if (iterations == 1 || iterations == 0)
2603
for (ptr= sptr, x= 0, sum_of_squares= 0; x < iterations; ptr++, x++)
2607
deviation= ptr->timing - con->avg_timing;
2608
sum_of_squares+= deviation*deviation;
2611
catch= sqrt((double)(sum_of_squares/(iterations -1)));
2612
con->std_dev= (long int)catch;