1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 MySQL
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
A simple program designed to work as if multiple clients querying the database,
26
then reporting the timing of each stage.
28
Drizzle slap runs three stages:
29
1) Create schema,table, and optionally any SP or data you want to beign
30
the test with. (single client)
31
2) Load test (many clients)
32
3) Cleanup (disconnection, drop table if specified, single client)
36
Supply your own create and query SQL statements, with 50 clients
37
querying (200 selects for each):
39
drizzleslap --delimiter=";" \
40
--create="CREATE TABLE A (a int);INSERT INTO A VALUES (23)" \
41
--query="SELECT * FROM A" --concurrency=50 --iterations=200
43
Let the program build the query SQL statement with a table of two int
44
columns, three varchar columns, five clients querying (20 times each),
45
don't create the table or insert the data (using the previous test's
48
drizzleslap --concurrency=5 --iterations=20 \
49
--number-int-cols=2 --number-char-cols=3 \
52
Tell the program to load the create, insert and query SQL statements from
53
the specified files, where the create.sql file has multiple table creation
54
statements delimited by ';' and multiple insert statements delimited by ';'.
55
The --query file will have multiple queries delimited by ';', run all the
56
load statements, and then run all the queries in the query file
57
with five clients (five times each):
59
drizzleslap --concurrency=5 \
60
--iterations=5 --query=query.sql --create=create.sql \
64
Add language for better tests
65
String length for files and those put on the command line are not
66
setup to handle binary data.
68
Break up tests and run them on multiple hosts at once.
69
Allow output to be fed into a database directly.
73
#define SLAP_VERSION "1.5"
75
#define HUGE_STRING_LENGTH 8196
76
#define RAND_STRING_SIZE 126
77
#define DEFAULT_BLOB_SIZE 1024
79
#include "client_priv.h"
82
#include <sys/types.h>
84
#ifdef HAVE_SYS_STAT_H
85
# include <sys/stat.h>
96
/* Added this for string translation. */
97
#include <drizzled/gettext.h>
100
using namespace drizzled;
103
static char *shared_memory_base_name=0;
106
/* Global Thread counter */
107
uint32_t thread_counter;
108
pthread_mutex_t counter_mutex;
109
pthread_cond_t count_threshhold;
110
uint32_t master_wakeup;
111
pthread_mutex_t sleeper_mutex;
112
pthread_cond_t sleep_threshhold;
114
/* Global Thread timer */
115
static bool timer_alarm= false;
116
pthread_mutex_t timer_alarm_mutex;
117
pthread_cond_t timer_alarm_threshold;
119
static char **defaults_argv;
122
/* This gets passed to malloc, so lets set it to an arch-dependant size */
123
size_t primary_keys_number_of;
125
static char *host= NULL, *opt_password= NULL, *user= NULL,
126
*user_supplied_query= NULL,
127
*user_supplied_pre_statements= NULL,
128
*user_supplied_post_statements= NULL,
129
*default_engine= NULL,
133
const char *delimiter= "\n";
135
const char *create_schema_string= "drizzleslap";
137
static bool opt_mysql= false;
138
static bool opt_preserve= true;
139
static bool opt_only_print= false;
140
static bool opt_burnin= false;
141
static bool opt_ignore_sql_errors= false;
142
static bool tty_password= false,
144
auto_generate_sql_autoincrement= false,
145
auto_generate_sql_guid_primary= false,
146
auto_generate_sql= false;
147
const char *opt_auto_generate_sql_type= "mixed";
149
static int verbose, delimiter_length;
150
static uint32_t commit_rate;
151
static uint32_t detach_rate;
152
static uint32_t opt_timer_length;
153
static uint32_t opt_delayed_start;
154
const char *num_int_cols_opt;
155
const char *num_char_cols_opt;
156
const char *num_blob_cols_opt;
157
const char *opt_label;
158
static unsigned int opt_set_random_seed;
160
const char *auto_generate_selected_columns_opt;
162
/* Yes, we do set defaults here */
163
static unsigned int num_int_cols= 1;
164
static unsigned int num_char_cols= 1;
165
static unsigned int num_blob_cols= 0;
166
static unsigned int num_blob_cols_size;
167
static unsigned int num_blob_cols_size_min;
168
static unsigned int num_int_cols_index= 0;
169
static unsigned int num_char_cols_index= 0;
170
static unsigned int iterations;
171
static uint64_t actual_queries= 0;
172
static uint64_t auto_actual_queries;
173
static uint64_t auto_generate_sql_unique_write_number;
174
static uint64_t auto_generate_sql_unique_query_number;
175
static unsigned int auto_generate_sql_secondary_indexes;
176
static uint64_t num_of_query;
177
static uint64_t auto_generate_sql_number;
178
const char *concurrency_str= NULL;
179
static char *create_string;
180
uint32_t *concurrency;
182
const char *default_dbug_option= "d:t:o,/tmp/drizzleslap.trace";
183
const char *opt_csv_str;
186
static int get_options(int *argc,char ***argv);
187
static uint32_t opt_drizzle_port= 0;
189
static const char *load_default_groups[]= { "drizzleslap","client",0 };
196
UPDATE_TYPE_REQUIRES_PREFIX= 3,
197
CREATE_TABLE_TYPE= 4,
198
SELECT_TYPE_REQUIRES_PREFIX= 5,
199
DELETE_TYPE_REQUIRES_PREFIX= 6
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;
230
long int create_timing;
231
uint64_t create_count;
234
typedef struct thread_context thread_context;
236
struct thread_context {
241
typedef struct conclusions conclusions;
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
uint64_t create_count;
258
/* The following are not used yet */
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
uint32_t parse_comma(const char *string, uint32_t **range);
278
uint32_t parse_delimiter(const char *script, statement **stmt, char delm);
279
uint32_t parse_option(const char *origin, option_string **stmt, char delm);
280
static int drop_schema(drizzle_con_st *con, const char *db);
281
uint32_t 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(bool key);
286
static int generate_primary_key_list(drizzle_con_st *con, option_string *engine_stmt);
287
static int drop_primary_key_list(void);
288
static int create_schema(drizzle_con_st *con, const char *db, statement *stmt,
289
option_string *engine_stmt, stats *sptr);
290
static int run_scheduler(stats *sptr, statement **stmts, uint32_t concur,
292
extern "C" pthread_handler_t run_task(void *p);
293
extern "C" pthread_handler_t timer_thread(void *p);
294
void statement_cleanup(statement *stmt);
295
void option_cleanup(option_string *stmt);
296
void concurrency_loop(drizzle_con_st *con, uint32_t current, option_string *eptr);
297
static int run_statements(drizzle_con_st *con, statement *stmt);
298
void slap_connect(drizzle_con_st *con, bool connect_to_schema);
299
void slap_close(drizzle_con_st *con);
300
static int run_query(drizzle_con_st *con, drizzle_result_st *result, 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;
320
int main(int argc, char **argv)
330
internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
332
if (get_options(&argc,&argv))
334
internal::free_defaults(defaults_argv);
339
/* Seed the random number generator if we will be using it. */
340
if (auto_generate_sql)
342
if (opt_set_random_seed == 0)
343
opt_set_random_seed= (unsigned int)time(NULL);
344
srandom(opt_set_random_seed);
347
/* globals? Yes, so we only have to run strlen once */
348
delimiter_length= strlen(delimiter);
352
fprintf(stderr,"%s: Too many arguments\n",internal::my_progname);
353
internal::free_defaults(defaults_argv);
358
slap_connect(&con, false);
360
pthread_mutex_init(&counter_mutex, NULL);
361
pthread_cond_init(&count_threshhold, NULL);
362
pthread_mutex_init(&sleeper_mutex, NULL);
363
pthread_cond_init(&sleep_threshhold, NULL);
364
pthread_mutex_init(&timer_alarm_mutex, NULL);
365
pthread_cond_init(&timer_alarm_threshold, NULL);
368
/* Main iterations loop */
370
eptr= engine_options;
373
/* For the final stage we run whatever queries we were asked to run */
377
printf("Starting Concurrency Test\n");
381
for (current= concurrency; current && *current; current++)
382
concurrency_loop(&con, *current, eptr);
386
uint32_t infinite= 1;
388
concurrency_loop(&con, infinite, eptr);
394
drop_schema(&con, create_schema_string);
396
} while (eptr ? (eptr= eptr->next) : 0);
401
pthread_mutex_destroy(&counter_mutex);
402
pthread_cond_destroy(&count_threshhold);
403
pthread_mutex_destroy(&sleeper_mutex);
404
pthread_cond_destroy(&sleep_threshhold);
405
pthread_mutex_destroy(&timer_alarm_mutex);
406
pthread_cond_destroy(&timer_alarm_threshold);
410
/* now free all the strings we created */
416
statement_cleanup(create_statements);
417
for (x= 0; x < query_statements_count; x++)
418
statement_cleanup(query_statements[x]);
419
free(query_statements);
420
statement_cleanup(pre_statements);
421
statement_cleanup(post_statements);
422
option_cleanup(engine_options);
423
option_cleanup(query_options);
426
if (shared_memory_base_name)
427
free(shared_memory_base_name);
429
internal::free_defaults(defaults_argv);
435
void concurrency_loop(drizzle_con_st *con, uint32_t current, option_string *eptr)
440
conclusions conclusion;
441
uint64_t client_limit;
443
head_sptr= (stats *)malloc(sizeof(stats) * iterations);
444
if (head_sptr == NULL)
446
fprintf(stderr,"Error allocating memory in concurrency_loop\n");
449
memset(head_sptr, 0, sizeof(stats) * iterations);
451
memset(&conclusion, 0, sizeof(conclusions));
453
if (auto_actual_queries)
454
client_limit= auto_actual_queries;
455
else if (num_of_query)
456
client_limit= num_of_query / current;
458
client_limit= actual_queries;
460
for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
463
We might not want to load any data, such as when we are calling
464
a stored_procedure that doesn't use data, or we know we already have
467
if (opt_preserve == false)
468
drop_schema(con, create_schema_string);
470
/* First we create */
471
if (create_statements)
472
create_schema(con, create_schema_string, create_statements, eptr, sptr);
475
If we generated GUID we need to build a list of them from creation that
479
printf("Generating primary key list\n");
480
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
481
generate_primary_key_list(con, eptr);
484
run_query(con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
488
int ret= system(pre_system);
494
Pre statements are always run after all other logic so they can
495
correct/adjust any item that they want.
498
run_statements(con, pre_statements);
500
run_scheduler(sptr, query_statements, current, client_limit);
503
run_statements(con, post_statements);
507
int ret= system(post_system);
511
/* We are finished with this run */
512
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
513
drop_primary_key_list();
517
printf("Generating stats\n");
519
generate_stats(&conclusion, eptr, head_sptr);
522
print_conclusions(&conclusion);
524
print_conclusions_csv(&conclusion);
531
static struct my_option my_long_options[] =
533
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
535
{"auto-generate-sql-select-columns", OPT_SLAP_AUTO_GENERATE_SELECT_COLUMNS,
536
"Provide a string to use for the select fields used in auto tests.",
537
(char**) &auto_generate_selected_columns_opt,
538
(char**) &auto_generate_selected_columns_opt,
539
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
540
{"auto-generate-sql", 'a',
541
"Generate SQL where not supplied by file or command line.",
542
(char**) &auto_generate_sql, (char**) &auto_generate_sql,
543
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
544
{"auto-generate-sql-add-autoincrement", OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
545
"Add an AUTO_INCREMENT column to auto-generated tables.",
546
(char**) &auto_generate_sql_autoincrement,
547
(char**) &auto_generate_sql_autoincrement,
548
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
549
{"auto-generate-sql-execute-number", OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
550
"Set this number to generate a set number of queries to run.",
551
(char**) &auto_actual_queries, (char**) &auto_actual_queries,
552
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
553
{"auto-generate-sql-guid-primary", OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
554
"Add GUID based primary keys to auto-generated tables.",
555
(char**) &auto_generate_sql_guid_primary,
556
(char**) &auto_generate_sql_guid_primary,
557
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
558
{"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
559
"Specify test load type: mixed, update, write, key, or read; default is mixed.",
560
(char**) &opt_auto_generate_sql_type, (char**) &opt_auto_generate_sql_type,
561
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
562
{"auto-generate-sql-secondary-indexes",
563
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
564
"Number of secondary indexes to add to auto-generated tables.",
565
(char**) &auto_generate_sql_secondary_indexes,
566
(char**) &auto_generate_sql_secondary_indexes, 0,
567
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
568
{"auto-generate-sql-unique-query-number",
569
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
570
"Number of unique queries to generate for automatic tests.",
571
(char**) &auto_generate_sql_unique_query_number,
572
(char**) &auto_generate_sql_unique_query_number,
573
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
574
{"auto-generate-sql-unique-write-number",
575
OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
576
"Number of unique queries to generate for auto-generate-sql-write-number.",
577
(char**) &auto_generate_sql_unique_write_number,
578
(char**) &auto_generate_sql_unique_write_number,
579
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
580
{"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
581
"Number of row inserts to perform for each thread (default is 100).",
582
(char**) &auto_generate_sql_number, (char**) &auto_generate_sql_number,
583
0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0},
584
{"burnin", OPT_SLAP_BURNIN, "Run full test case in infinite loop.",
585
(char**) &opt_burnin, (char**) &opt_burnin, 0, GET_BOOL, NO_ARG, 0, 0, 0,
587
{"ignore-sql-errors", OPT_SLAP_IGNORE_SQL_ERRORS,
588
"Ignore SQL erros in query run.",
589
(char**) &opt_ignore_sql_errors,
590
(char**) &opt_ignore_sql_errors,
591
0, GET_BOOL, NO_ARG, 0, 0, 0,
593
{"commit", OPT_SLAP_COMMIT, "Commit records every X number of statements.",
594
(char**) &commit_rate, (char**) &commit_rate, 0, GET_UINT, REQUIRED_ARG,
596
{"concurrency", 'c', "Number of clients to simulate for query to run.",
597
(char**) &concurrency_str, (char**) &concurrency_str, 0, GET_STR,
598
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
599
{"create", OPT_SLAP_CREATE_STRING, "File or string to use create tables.",
600
(char**) &create_string, (char**) &create_string, 0, GET_STR, REQUIRED_ARG,
602
{"create-schema", OPT_CREATE_SLAP_SCHEMA, "Schema to run tests in.",
603
(char**) &create_schema_string, (char**) &create_schema_string, 0, GET_STR,
604
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
605
{"csv", OPT_SLAP_CSV,
606
"Generate CSV output to named file or to stdout if no file is named.",
607
(char**) &opt_csv_str, (char**) &opt_csv_str, 0, GET_STR,
608
OPT_ARG, 0, 0, 0, 0, 0, 0},
609
{"delayed-start", OPT_SLAP_DELAYED_START,
610
"Delay the startup of threads by a random number of microsends (the maximum of the delay)",
611
(char**) &opt_delayed_start, (char**) &opt_delayed_start, 0, GET_UINT,
612
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
614
"Delimiter to use in SQL statements supplied in file or command line.",
615
(char**) &delimiter, (char**) &delimiter, 0, GET_STR, REQUIRED_ARG,
617
{"detach", OPT_SLAP_DETACH,
618
"Detach (close and reopen) connections after X number of requests.",
619
(char**) &detach_rate, (char**) &detach_rate, 0, GET_UINT, REQUIRED_ARG,
621
{"engine", 'e', "Storage engine to use for creating the table.",
622
(char**) &default_engine, (char**) &default_engine, 0,
623
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
624
{"host", 'h', "Connect to host.", (char**) &host, (char**) &host, 0, GET_STR,
625
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
626
{"iterations", 'i', "Number of times to run the tests.", (char**) &iterations,
627
(char**) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
628
{"label", OPT_SLAP_LABEL, "Label to use for print and csv output.",
629
(char**) &opt_label, (char**) &opt_label, 0,
630
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
631
{"mysql", 'm', N_("Use MySQL Protocol."),
632
(char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
634
{"number-blob-cols", OPT_SLAP_BLOB_COL,
635
"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. ",
636
(char**) &num_blob_cols_opt, (char**) &num_blob_cols_opt, 0, GET_STR, REQUIRED_ARG,
638
{"number-char-cols", 'x',
639
"Number of VARCHAR columns to create in table if specifying --auto-generate-sql.",
640
(char**) &num_char_cols_opt, (char**) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
642
{"number-int-cols", 'y',
643
"Number of INT columns to create in table if specifying --auto-generate-sql.",
644
(char**) &num_int_cols_opt, (char**) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
646
{"number-of-queries", OPT_DRIZZLE_NUMBER_OF_QUERY,
647
"Limit each client to this number of queries (this is not exact).",
648
(char**) &num_of_query, (char**) &num_of_query, 0,
649
GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
650
{"only-print", OPT_DRIZZLE_ONLY_PRINT,
651
"This causes drizzleslap to not connect to the databases, but instead print "
652
"out what it would have done instead.",
653
(char**) &opt_only_print, (char**) &opt_only_print, 0, GET_BOOL, NO_ARG,
656
"Password to use when connecting to server. If password is not given it's "
657
"asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
658
{"port", 'p', "Port number to use for connection.",
659
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
660
{"post-query", OPT_SLAP_POST_QUERY,
661
"Query to run or file containing query to execute after tests have completed.",
662
(char**) &user_supplied_post_statements,
663
(char**) &user_supplied_post_statements,
664
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
665
{"post-system", OPT_SLAP_POST_SYSTEM,
666
"system() string to execute after tests have completed.",
667
(char**) &post_system,
668
(char**) &post_system,
669
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
670
{"pre-query", OPT_SLAP_PRE_QUERY,
671
"Query to run or file containing query to execute before running tests.",
672
(char**) &user_supplied_pre_statements,
673
(char**) &user_supplied_pre_statements,
674
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
675
{"pre-system", OPT_SLAP_PRE_SYSTEM,
676
"system() string to execute before running tests.",
677
(char**) &pre_system,
678
(char**) &pre_system,
679
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
680
{"protocol", OPT_DRIZZLE_PROTOCOL,
681
"The protocol of connection (tcp,socket,pipe,memory).",
682
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
683
{"query", 'q', "Query to run or file containing query to run.",
684
(char**) &user_supplied_query, (char**) &user_supplied_query,
685
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
686
{"set-random-seed", OPT_SLAP_SET_RANDOM_SEED,
687
"Seed for random number generator (srandom(3))",
688
(char**)&opt_set_random_seed,
689
(char**)&opt_set_random_seed,0,
690
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
691
{"silent", 's', "Run program in silent mode - no output.",
692
(char**) &opt_silent, (char**) &opt_silent, 0, GET_BOOL, NO_ARG,
694
{"timer-length", OPT_SLAP_TIMER_LENGTH,
695
"Require drizzleslap to run each specific test a certain amount of time in seconds.",
696
(char**) &opt_timer_length, (char**) &opt_timer_length, 0, GET_UINT,
697
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
698
{"user", 'u', "User for login if not current user.", (char**) &user,
699
(char**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
701
"More verbose output; you can use this multiple times to get even more "
702
"verbose output.", (char**) &verbose, (char**) &verbose, 0,
703
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
704
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
705
NO_ARG, 0, 0, 0, 0, 0, 0},
706
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
710
static void print_version(void)
712
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname, SLAP_VERSION,
713
drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
717
static void usage(void)
720
puts("Copyright (C) 2008 Sun Microsystems");
721
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\
722
\nand you are welcome to modify and redistribute it under the GPL \
724
puts("Run a query multiple times against the server\n");
725
printf("Usage: %s [OPTIONS]\n",internal::my_progname);
726
internal::print_defaults("drizzle",load_default_groups);
727
my_print_help(my_long_options);
730
static bool get_one_option(int optid, const struct my_option *, char *argument)
733
uint64_t temp_drizzle_port= 0;
740
temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
741
/* if there is an alpha character this is not a valid port */
742
if (strlen(endchar) != 0)
744
fprintf(stderr, _("Non-integer value supplied for port. If you are trying to enter a password please use --password instead.\n"));
747
/* If the port number is > 65535 it is not a valid port
748
This also helps with potential data loss casting unsigned long to a
750
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
752
fprintf(stderr, _("Value supplied for port is not valid.\n"));
757
opt_drizzle_port= (uint32_t) temp_drizzle_port;
763
char *start= argument;
766
opt_password = strdup(argument);
767
if (opt_password == NULL)
769
fprintf(stderr, "Memory allocation error while copying password. "
775
/* Overwriting password with 'x' */
780
/* Cut length of argument */
801
get_random_string(char *buf, size_t size)
806
for (x= size; x > 0; x--)
807
*buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE];
808
return(buf_ptr - buf);
815
This function builds a create table query if the user opts to not supply
816
a file or string containing a create table statement
819
build_table_string(void)
821
char buf[HUGE_STRING_LENGTH];
822
unsigned int col_count;
826
table_string.reserve(HUGE_STRING_LENGTH);
828
table_string= "CREATE TABLE `t1` (";
830
if (auto_generate_sql_autoincrement)
832
table_string.append("id serial");
834
if (num_int_cols || num_char_cols)
835
table_string.append(",");
838
if (auto_generate_sql_guid_primary)
840
table_string.append("id varchar(128) primary key");
842
if (num_int_cols || num_char_cols || auto_generate_sql_guid_primary)
843
table_string.append(",");
846
if (auto_generate_sql_secondary_indexes)
850
for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
852
if (count) /* Except for the first pass we add a comma */
853
table_string.append(",");
855
if (snprintf(buf, HUGE_STRING_LENGTH, "id%d varchar(32) unique key", count)
856
> HUGE_STRING_LENGTH)
858
fprintf(stderr, "Memory Allocation error in create table\n");
861
table_string.append(buf);
864
if (num_int_cols || num_char_cols)
865
table_string.append(",");
869
for (col_count= 1; col_count <= num_int_cols; col_count++)
871
if (num_int_cols_index)
873
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT, INDEX(intcol%d)",
874
col_count, col_count) > HUGE_STRING_LENGTH)
876
fprintf(stderr, "Memory Allocation error in create table\n");
882
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT ", col_count)
883
> HUGE_STRING_LENGTH)
885
fprintf(stderr, "Memory Allocation error in create table\n");
889
table_string.append(buf);
891
if (col_count < num_int_cols || num_char_cols > 0)
892
table_string.append(",");
896
for (col_count= 1; col_count <= num_char_cols; col_count++)
898
if (num_char_cols_index)
900
if (snprintf(buf, HUGE_STRING_LENGTH,
901
"charcol%d VARCHAR(128), INDEX(charcol%d) ",
902
col_count, col_count) > HUGE_STRING_LENGTH)
904
fprintf(stderr, "Memory Allocation error in creating table\n");
910
if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d VARCHAR(128)",
911
col_count) > HUGE_STRING_LENGTH)
913
fprintf(stderr, "Memory Allocation error in creating table\n");
917
table_string.append(buf);
919
if (col_count < num_char_cols || num_blob_cols > 0)
920
table_string.append(",");
924
for (col_count= 1; col_count <= num_blob_cols; col_count++)
926
if (snprintf(buf, HUGE_STRING_LENGTH, "blobcol%d blob",
927
col_count) > HUGE_STRING_LENGTH)
929
fprintf(stderr, "Memory Allocation error in creating table\n");
932
table_string.append(buf);
934
if (col_count < num_blob_cols)
935
table_string.append(",");
938
table_string.append(")");
939
ptr= (statement *)malloc(sizeof(statement));
942
fprintf(stderr, "Memory Allocation error in creating table\n");
945
memset(ptr, 0, sizeof(statement));
946
ptr->string = (char *)malloc(table_string.length()+1);
947
if (ptr->string == NULL)
949
fprintf(stderr, "Memory Allocation error in creating table\n");
952
memset(ptr->string, 0, table_string.length()+1);
953
ptr->length= table_string.length()+1;
954
ptr->type= CREATE_TABLE_TYPE;
955
strcpy(ptr->string, table_string.c_str());
960
build_update_string()
962
This function builds insert statements when the user opts to not supply
963
an insert file or string containing insert data
966
build_update_string(void)
968
char buf[HUGE_STRING_LENGTH];
969
unsigned int col_count;
971
string update_string;
973
update_string.reserve(HUGE_STRING_LENGTH);
975
update_string= "UPDATE t1 SET ";
978
for (col_count= 1; col_count <= num_int_cols; col_count++)
980
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d = %ld", col_count,
981
random()) > HUGE_STRING_LENGTH)
983
fprintf(stderr, "Memory Allocation error in creating update\n");
986
update_string.append(buf);
988
if (col_count < num_int_cols || num_char_cols > 0)
989
update_string.append(",", 1);
993
for (col_count= 1; col_count <= num_char_cols; col_count++)
995
char rand_buffer[RAND_STRING_SIZE];
996
int buf_len= get_random_string(rand_buffer, RAND_STRING_SIZE);
998
if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d = '%.*s'", col_count,
999
buf_len, rand_buffer)
1000
> HUGE_STRING_LENGTH)
1002
fprintf(stderr, "Memory Allocation error in creating update\n");
1005
update_string.append(buf);
1007
if (col_count < num_char_cols)
1008
update_string.append(",", 1);
1011
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
1012
update_string.append(" WHERE id = ");
1015
ptr= (statement *)malloc(sizeof(statement));
1018
fprintf(stderr, "Memory Allocation error in creating update\n");
1021
memset(ptr, 0, sizeof(statement));
1023
ptr->length= update_string.length()+1;
1024
ptr->string= (char *)malloc(ptr->length);
1025
if (ptr->string == NULL)
1027
fprintf(stderr, "Memory Allocation error in creating update\n");
1030
memset(ptr->string, 0, ptr->length);
1031
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
1032
ptr->type= UPDATE_TYPE_REQUIRES_PREFIX ;
1034
ptr->type= UPDATE_TYPE;
1035
strncpy(ptr->string, update_string.c_str(), ptr->length);
1041
build_insert_string()
1043
This function builds insert statements when the user opts to not supply
1044
an insert file or string containing insert data
1047
build_insert_string(void)
1049
char buf[HUGE_STRING_LENGTH];
1050
unsigned int col_count;
1052
string insert_string;
1054
insert_string.reserve(HUGE_STRING_LENGTH);
1056
insert_string= "INSERT INTO t1 VALUES (";
1058
if (auto_generate_sql_autoincrement)
1060
insert_string.append("NULL");
1062
if (num_int_cols || num_char_cols)
1063
insert_string.append(",");
1066
if (auto_generate_sql_guid_primary)
1068
insert_string.append("uuid()");
1070
if (num_int_cols || num_char_cols)
1071
insert_string.append(",");
1074
if (auto_generate_sql_secondary_indexes)
1078
for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
1080
if (count) /* Except for the first pass we add a comma */
1081
insert_string.append(",");
1083
insert_string.append("uuid()");
1086
if (num_int_cols || num_char_cols)
1087
insert_string.append(",");
1091
for (col_count= 1; col_count <= num_int_cols; col_count++)
1093
if (snprintf(buf, HUGE_STRING_LENGTH, "%ld", random()) > HUGE_STRING_LENGTH)
1095
fprintf(stderr, "Memory Allocation error in creating insert\n");
1098
insert_string.append(buf);
1100
if (col_count < num_int_cols || num_char_cols > 0)
1101
insert_string.append(",");
1105
for (col_count= 1; col_count <= num_char_cols; col_count++)
1107
int buf_len= get_random_string(buf, RAND_STRING_SIZE);
1108
insert_string.append("'", 1);
1109
insert_string.append(buf, buf_len);
1110
insert_string.append("'", 1);
1112
if (col_count < num_char_cols || num_blob_cols > 0)
1113
insert_string.append(",", 1);
1120
if (num_blob_cols_size > HUGE_STRING_LENGTH)
1122
blob_ptr= (char *)malloc(sizeof(char)*num_blob_cols_size);
1125
fprintf(stderr, "Memory Allocation error in creating select\n");
1128
memset(blob_ptr, 0, sizeof(char)*num_blob_cols_size);
1135
for (col_count= 1; col_count <= num_blob_cols; col_count++)
1137
unsigned int buf_len;
1139
unsigned int difference= num_blob_cols_size - num_blob_cols_size_min;
1141
size= difference ? (num_blob_cols_size_min + (random() % difference)) :
1144
buf_len= get_random_string(blob_ptr, size);
1146
insert_string.append("'", 1);
1147
insert_string.append(blob_ptr, buf_len);
1148
insert_string.append("'", 1);
1150
if (col_count < num_blob_cols)
1151
insert_string.append(",", 1);
1154
if (num_blob_cols_size > HUGE_STRING_LENGTH)
1158
insert_string.append(")", 1);
1160
if (!(ptr= (statement *)malloc(sizeof(statement))))
1162
fprintf(stderr, "Memory Allocation error in creating select\n");
1165
memset(ptr, 0, sizeof(statement));
1166
ptr->length= insert_string.length()+1;
1167
if (!(ptr->string= (char *)malloc(ptr->length)))
1169
fprintf(stderr, "Memory Allocation error in creating select\n");
1172
memset(ptr->string, 0, ptr->length);
1173
ptr->type= INSERT_TYPE;
1174
strcpy(ptr->string, insert_string.c_str());
1180
build_select_string()
1182
This function builds a query if the user opts to not supply a query
1183
statement or file containing a query statement
1186
build_select_string(bool key)
1188
char buf[HUGE_STRING_LENGTH];
1189
unsigned int col_count;
1191
string query_string;
1193
query_string.reserve(HUGE_STRING_LENGTH);
1195
query_string.append("SELECT ", 7);
1196
if (auto_generate_selected_columns_opt)
1198
query_string.append(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
query_string.append(buf);
1212
if (col_count < num_int_cols || num_char_cols > 0)
1213
query_string.append(",", 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
query_string.append(buf);
1226
if (col_count < num_char_cols || num_blob_cols > 0)
1227
query_string.append(",", 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
query_string.append(buf);
1240
if (col_count < num_blob_cols)
1241
query_string.append(",", 1);
1244
query_string.append(" FROM t1");
1247
(auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
1248
query_string.append(" WHERE id = ");
1250
ptr= (statement *)malloc(sizeof(statement));
1253
fprintf(stderr, "Memory Allocation error in creating select\n");
1256
memset(ptr, 0, sizeof(statement));
1257
ptr->length= query_string.length()+1;
1258
ptr->string= (char *)malloc(ptr->length);
1259
if (ptr->string == NULL)
1261
fprintf(stderr, "Memory Allocation error in creating select\n");
1264
memset(ptr->string, 0, ptr->length);
1266
(auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
1267
ptr->type= SELECT_TYPE_REQUIRES_PREFIX;
1269
ptr->type= SELECT_TYPE;
1270
strcpy(ptr->string, query_string.c_str());
1275
get_options(int *argc,char ***argv)
1280
option_string *sql_type;
1281
unsigned int sql_type_count= 0;
1282
ssize_t bytes_read= 0;
1285
if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
1289
user= (char *)"root";
1291
/* If something is created we clean it up, otherwise we leave schemas alone */
1292
if (create_string || auto_generate_sql)
1293
opt_preserve= false;
1295
if (auto_generate_sql && (create_string || user_supplied_query))
1298
"%s: Can't use --auto-generate-sql when create and query strings are specified!\n",
1299
internal::my_progname);
1303
if (auto_generate_sql && auto_generate_sql_guid_primary &&
1304
auto_generate_sql_autoincrement)
1307
"%s: Either auto-generate-sql-guid-primary or auto-generate-sql-add-autoincrement can be used!\n",
1308
internal::my_progname);
1312
if (auto_generate_sql && num_of_query && auto_actual_queries)
1315
"%s: Either auto-generate-sql-execute-number or number-of-queries can be used!\n",
1316
internal::my_progname);
1320
parse_comma(concurrency_str ? concurrency_str : "1", &concurrency);
1326
if (opt_csv_str[0] == '-')
1328
csv_file= fileno(stdout);
1332
if ((csv_file= open(opt_csv_str, O_CREAT|O_WRONLY|O_APPEND,
1333
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
1335
fprintf(stderr,"%s: Could not open csv file: %sn\n",
1336
internal::my_progname, opt_csv_str);
1345
if (num_int_cols_opt)
1348
parse_option(num_int_cols_opt, &str, ',');
1349
num_int_cols= atoi(str->string);
1351
num_int_cols_index= atoi(str->option);
1352
option_cleanup(str);
1355
if (num_char_cols_opt)
1358
parse_option(num_char_cols_opt, &str, ',');
1359
num_char_cols= atoi(str->string);
1361
num_char_cols_index= atoi(str->option);
1363
num_char_cols_index= 0;
1364
option_cleanup(str);
1367
if (num_blob_cols_opt)
1370
parse_option(num_blob_cols_opt, &str, ',');
1371
num_blob_cols= atoi(str->string);
1376
if ((sep_ptr= strchr(str->option, '/')))
1378
num_blob_cols_size_min= atoi(str->option);
1379
num_blob_cols_size= atoi(sep_ptr+1);
1383
num_blob_cols_size_min= num_blob_cols_size= atoi(str->option);
1388
num_blob_cols_size= DEFAULT_BLOB_SIZE;
1389
num_blob_cols_size_min= DEFAULT_BLOB_SIZE;
1391
option_cleanup(str);
1395
if (auto_generate_sql)
1398
statement *ptr_statement;
1401
printf("Building Create Statements for Auto\n");
1403
create_statements= build_table_string();
1407
for (ptr_statement= create_statements, x= 0;
1408
x < auto_generate_sql_unique_write_number;
1409
x++, ptr_statement= ptr_statement->next)
1411
ptr_statement->next= build_insert_string();
1415
printf("Building Query Statements for Auto\n");
1417
if (!opt_auto_generate_sql_type)
1418
opt_auto_generate_sql_type= "mixed";
1420
query_statements_count=
1421
parse_option(opt_auto_generate_sql_type, &query_options, ',');
1423
query_statements= (statement **)malloc(sizeof(statement *) * query_statements_count);
1424
if (query_statements == NULL)
1426
fprintf(stderr, "Memory Allocation error in Building Query Statements\n");
1429
memset(query_statements, 0, sizeof(statement *) * query_statements_count);
1431
sql_type= query_options;
1434
if (sql_type->string[0] == 'r')
1437
printf("Generating SELECT Statements for Auto\n");
1439
query_statements[sql_type_count]= build_select_string(false);
1440
for (ptr_statement= query_statements[sql_type_count], x= 0;
1441
x < auto_generate_sql_unique_query_number;
1442
x++, ptr_statement= ptr_statement->next)
1444
ptr_statement->next= build_select_string(false);
1447
else if (sql_type->string[0] == 'k')
1450
printf("Generating SELECT for keys Statements for Auto\n");
1452
if ( auto_generate_sql_autoincrement == false &&
1453
auto_generate_sql_guid_primary == false)
1456
"%s: Can't perform key test without a primary key!\n",
1457
internal::my_progname);
1461
query_statements[sql_type_count]= build_select_string(true);
1462
for (ptr_statement= query_statements[sql_type_count], x= 0;
1463
x < auto_generate_sql_unique_query_number;
1464
x++, ptr_statement= ptr_statement->next)
1466
ptr_statement->next= build_select_string(true);
1469
else if (sql_type->string[0] == 'w')
1472
We generate a number of strings in case the engine is
1473
Archive (since strings which were identical one after another
1474
would be too easily optimized).
1477
printf("Generating INSERT Statements for Auto\n");
1478
query_statements[sql_type_count]= build_insert_string();
1479
for (ptr_statement= query_statements[sql_type_count], x= 0;
1480
x < auto_generate_sql_unique_query_number;
1481
x++, ptr_statement= ptr_statement->next)
1483
ptr_statement->next= build_insert_string();
1486
else if (sql_type->string[0] == 'u')
1488
if ( auto_generate_sql_autoincrement == false &&
1489
auto_generate_sql_guid_primary == false)
1492
"%s: Can't perform update test without a primary key!\n",
1493
internal::my_progname);
1497
query_statements[sql_type_count]= build_update_string();
1498
for (ptr_statement= query_statements[sql_type_count], x= 0;
1499
x < auto_generate_sql_unique_query_number;
1500
x++, ptr_statement= ptr_statement->next)
1502
ptr_statement->next= build_update_string();
1505
else /* Mixed mode is default */
1509
query_statements[sql_type_count]= build_insert_string();
1511
This logic should be extended to do a more mixed load,
1512
at the moment it results in "every other".
1514
for (ptr_statement= query_statements[sql_type_count], x= 0;
1515
x < auto_generate_sql_unique_query_number;
1516
x++, ptr_statement= ptr_statement->next)
1520
ptr_statement->next= build_insert_string();
1525
ptr_statement->next= build_select_string(true);
1531
} while (sql_type ? (sql_type= sql_type->next) : 0);
1535
if (create_string && !stat(create_string, &sbuf))
1538
if (!S_ISREG(sbuf.st_mode))
1540
fprintf(stderr,"%s: Create file was not a regular file\n",
1541
internal::my_progname);
1544
if ((data_file= open(create_string, O_RDWR)) == -1)
1546
fprintf(stderr,"%s: Could not open create file\n", internal::my_progname);
1549
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1551
fprintf(stderr, "Request for more memory than architecture supports\n");
1554
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1555
if (tmp_string == NULL)
1557
fprintf(stderr, "Memory Allocation error in option processing\n");
1560
memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
1561
bytes_read= read(data_file, (unsigned char*) tmp_string,
1562
(size_t)sbuf.st_size);
1563
tmp_string[sbuf.st_size]= '\0';
1565
if (bytes_read != sbuf.st_size)
1567
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1569
parse_delimiter(tmp_string, &create_statements, delimiter[0]);
1572
else if (create_string)
1574
parse_delimiter(create_string, &create_statements, delimiter[0]);
1577
/* Set this up till we fully support options on user generated queries */
1578
if (user_supplied_query)
1580
query_statements_count=
1581
parse_option("default", &query_options, ',');
1583
query_statements= (statement **)malloc(sizeof(statement *) * query_statements_count);
1584
if (query_statements == NULL)
1586
fprintf(stderr, "Memory Allocation error in option processing\n");
1589
memset(query_statements, 0, sizeof(statement *) * query_statements_count);
1592
if (user_supplied_query && !stat(user_supplied_query, &sbuf))
1595
if (!S_ISREG(sbuf.st_mode))
1597
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1598
internal::my_progname);
1601
if ((data_file= open(user_supplied_query, O_RDWR)) == -1)
1603
fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1606
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1608
fprintf(stderr, "Request for more memory than architecture supports\n");
1611
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1612
if (tmp_string == NULL)
1614
fprintf(stderr, "Memory Allocation error in option processing\n");
1617
memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
1618
bytes_read= read(data_file, (unsigned char*) tmp_string,
1619
(size_t)sbuf.st_size);
1620
tmp_string[sbuf.st_size]= '\0';
1622
if (bytes_read != sbuf.st_size)
1624
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1626
if (user_supplied_query)
1627
actual_queries= parse_delimiter(tmp_string, &query_statements[0],
1631
else if (user_supplied_query)
1633
actual_queries= parse_delimiter(user_supplied_query, &query_statements[0],
1638
if (user_supplied_pre_statements
1639
&& !stat(user_supplied_pre_statements, &sbuf))
1642
if (!S_ISREG(sbuf.st_mode))
1644
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1645
internal::my_progname);
1648
if ((data_file= open(user_supplied_pre_statements, O_RDWR)) == -1)
1650
fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1653
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1655
fprintf(stderr, "Request for more memory than architecture supports\n");
1658
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1659
if (tmp_string == NULL)
1661
fprintf(stderr, "Memory Allocation error in option processing\n");
1664
memset(tmp_string, 0, (size_t)(sbuf.st_size + 1));
1665
bytes_read= read(data_file, (unsigned char*) tmp_string,
1666
(size_t)sbuf.st_size);
1667
tmp_string[sbuf.st_size]= '\0';
1669
if (bytes_read != sbuf.st_size)
1671
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1673
if (user_supplied_pre_statements)
1674
(void)parse_delimiter(tmp_string, &pre_statements,
1678
else if (user_supplied_pre_statements)
1680
(void)parse_delimiter(user_supplied_pre_statements,
1685
if (user_supplied_post_statements
1686
&& !stat(user_supplied_post_statements, &sbuf))
1689
if (!S_ISREG(sbuf.st_mode))
1691
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
1692
internal::my_progname);
1695
if ((data_file= open(user_supplied_post_statements, O_RDWR)) == -1)
1697
fprintf(stderr,"%s: Could not open query supplied file\n", internal::my_progname);
1701
if ((uint64_t)(sbuf.st_size + 1) > SIZE_MAX)
1703
fprintf(stderr, "Request for more memory than architecture supports\n");
1706
tmp_string= (char *)malloc((size_t)(sbuf.st_size + 1));
1707
if (tmp_string == NULL)
1709
fprintf(stderr, "Memory Allocation error in option processing\n");
1712
memset(tmp_string, 0, (size_t)(sbuf.st_size+1));
1714
bytes_read= read(data_file, (unsigned char*) tmp_string,
1715
(size_t)(sbuf.st_size));
1716
tmp_string[sbuf.st_size]= '\0';
1718
if (bytes_read != sbuf.st_size)
1720
fprintf(stderr, "Problem reading file: read less bytes than requested\n");
1722
if (user_supplied_post_statements)
1723
(void)parse_delimiter(tmp_string, &post_statements,
1727
else if (user_supplied_post_statements)
1729
(void)parse_delimiter(user_supplied_post_statements, &post_statements,
1734
printf("Parsing engines to use.\n");
1737
parse_option(default_engine, &engine_options, ',');
1740
opt_password= client_get_tty_password(NULL);
1745
static int run_query(drizzle_con_st *con, drizzle_result_st *result,
1746
const char *query, int len)
1748
drizzle_return_t ret;
1749
drizzle_result_st result_buffer;
1753
printf("%.*s;\n", len, query);
1758
printf("%.*s;\n", len, query);
1761
result= &result_buffer;
1763
result= drizzle_query(con, result, query, len, &ret);
1765
if (ret == DRIZZLE_RETURN_OK)
1766
ret= drizzle_result_buffer(result);
1768
if (result == &result_buffer)
1769
drizzle_result_free(result);
1776
generate_primary_key_list(drizzle_con_st *con, option_string *engine_stmt)
1778
drizzle_result_st result;
1784
Blackhole is a special case, this allows us to test the upper end
1785
of the server during load runs.
1787
if (opt_only_print || (engine_stmt &&
1788
strstr(engine_stmt->string, "blackhole")))
1790
primary_keys_number_of= 1;
1791
primary_keys= (char **)malloc((sizeof(char *) *
1792
primary_keys_number_of));
1793
if (primary_keys == NULL)
1795
fprintf(stderr, "Memory Allocation error in option processing\n");
1799
memset(primary_keys, 0, (sizeof(char *) * primary_keys_number_of));
1800
/* Yes, we strdup a const string to simplify the interface */
1801
primary_keys[0]= strdup("796c4422-1d94-102a-9d6d-00e0812d");
1802
if (primary_keys[0] == NULL)
1804
fprintf(stderr, "Memory Allocation error in option processing\n");
1810
if (run_query(con, &result, "SELECT id from t1", strlen("SELECT id from t1")))
1812
fprintf(stderr,"%s: Cannot select GUID primary keys. (%s)\n", internal::my_progname,
1813
drizzle_con_error(con));
1817
uint64_t num_rows_ret= drizzle_result_row_count(&result);
1818
if (num_rows_ret > SIZE_MAX)
1820
fprintf(stderr, "More primary keys than than architecture supports\n");
1823
primary_keys_number_of= (size_t)num_rows_ret;
1825
/* So why check this? Blackhole :) */
1826
if (primary_keys_number_of)
1829
We create the structure and loop and create the items.
1831
primary_keys= (char **)malloc(sizeof(char *) *
1832
primary_keys_number_of);
1833
if (primary_keys == NULL)
1835
fprintf(stderr, "Memory Allocation error in option processing\n");
1838
memset(primary_keys, 0, (size_t)(sizeof(char *) * primary_keys_number_of));
1839
row= drizzle_row_next(&result);
1840
for (counter= 0; counter < primary_keys_number_of;
1841
counter++, row= drizzle_row_next(&result))
1843
primary_keys[counter]= strdup(row[0]);
1844
if (primary_keys[counter] == NULL)
1846
fprintf(stderr, "Memory Allocation error in option processing\n");
1852
drizzle_result_free(&result);
1859
drop_primary_key_list(void)
1863
if (primary_keys_number_of)
1865
for (counter= 0; counter < primary_keys_number_of; counter++)
1866
free(primary_keys[counter]);
1875
create_schema(drizzle_con_st *con, const char *db, statement *stmt,
1876
option_string *engine_stmt, stats *sptr)
1878
char query[HUGE_STRING_LENGTH];
1880
statement *after_create;
1883
struct timeval start_time, end_time;
1886
gettimeofday(&start_time, NULL);
1888
len= snprintf(query, HUGE_STRING_LENGTH, "CREATE SCHEMA `%s`", db);
1891
printf("Loading Pre-data\n");
1893
if (run_query(con, NULL, query, len))
1895
fprintf(stderr,"%s: Cannot create schema %s : %s\n", internal::my_progname, db,
1896
drizzle_con_error(con));
1901
sptr->create_count++;
1906
printf("use %s;\n", db);
1910
drizzle_result_st result;
1911
drizzle_return_t ret;
1914
printf("%s;\n", query);
1916
if (drizzle_select_db(con, &result, db, &ret) == NULL ||
1917
ret != DRIZZLE_RETURN_OK)
1919
fprintf(stderr,"%s: Cannot select schema '%s': %s\n",internal::my_progname, db,
1920
ret == DRIZZLE_RETURN_ERROR_CODE ?
1921
drizzle_result_error(&result) : drizzle_con_error(con));
1924
drizzle_result_free(&result);
1925
sptr->create_count++;
1930
len= snprintf(query, HUGE_STRING_LENGTH, "set storage_engine=`%s`",
1931
engine_stmt->string);
1932
if (run_query(con, NULL, query, len))
1934
fprintf(stderr,"%s: Cannot set default engine: %s\n", internal::my_progname,
1935
drizzle_con_error(con));
1938
sptr->create_count++;
1945
for (ptr= after_create; ptr && ptr->length; ptr= ptr->next, count++)
1947
if (auto_generate_sql && ( auto_generate_sql_number == count))
1950
if (engine_stmt && engine_stmt->option && ptr->type == CREATE_TABLE_TYPE)
1952
char buffer[HUGE_STRING_LENGTH];
1954
snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->string,
1955
engine_stmt->option);
1956
if (run_query(con, NULL, buffer, strlen(buffer)))
1958
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1959
internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(con));
1960
if (!opt_ignore_sql_errors)
1963
sptr->create_count++;
1967
if (run_query(con, NULL, ptr->string, ptr->length))
1969
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1970
internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(con));
1971
if (!opt_ignore_sql_errors)
1974
sptr->create_count++;
1978
if (auto_generate_sql && (auto_generate_sql_number > count ))
1980
/* Special case for auto create, we don't want to create tables twice */
1981
after_create= stmt->next;
1985
gettimeofday(&end_time, NULL);
1987
sptr->create_timing= timedif(end_time, start_time);
1993
drop_schema(drizzle_con_st *con, const char *db)
1995
char query[HUGE_STRING_LENGTH];
1998
len= snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS `%s`", db);
2000
if (run_query(con, NULL, query, len))
2002
fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
2003
internal::my_progname, db, drizzle_con_error(con));
2013
run_statements(drizzle_con_st *con, statement *stmt)
2017
for (ptr= stmt; ptr && ptr->length; ptr= ptr->next)
2019
if (run_query(con, NULL, ptr->string, ptr->length))
2021
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2022
internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(con));
2031
run_scheduler(stats *sptr, statement **stmts, uint32_t concur, uint64_t limit)
2035
unsigned int real_concurrency;
2036
struct timeval start_time, end_time;
2037
option_string *sql_type;
2038
thread_context *con;
2039
pthread_t mainthread; /* Thread descriptor */
2040
pthread_attr_t attr; /* Thread attributes */
2043
pthread_attr_init(&attr);
2044
pthread_attr_setdetachstate(&attr,
2045
PTHREAD_CREATE_DETACHED);
2047
pthread_mutex_lock(&counter_mutex);
2050
pthread_mutex_lock(&sleeper_mutex);
2052
pthread_mutex_unlock(&sleeper_mutex);
2054
real_concurrency= 0;
2056
for (y= 0, sql_type= query_options;
2057
y < query_statements_count;
2058
y++, sql_type= sql_type->next)
2060
unsigned int options_loop= 1;
2062
if (sql_type->option)
2064
options_loop= strtol(sql_type->option,
2066
options_loop= options_loop ? options_loop : 1;
2069
while (options_loop--)
2070
for (x= 0; x < concur; x++)
2072
con= (thread_context *)malloc(sizeof(thread_context));
2075
fprintf(stderr, "Memory Allocation error in scheduler\n");
2078
con->stmt= stmts[y];
2082
/* now you create the thread */
2083
if (pthread_create(&mainthread, &attr, run_task,
2086
fprintf(stderr,"%s: Could not create thread\n", internal::my_progname);
2094
The timer_thread belongs to all threads so it too obeys the wakeup
2095
call that run tasks obey.
2097
if (opt_timer_length)
2099
pthread_mutex_lock(&timer_alarm_mutex);
2101
pthread_mutex_unlock(&timer_alarm_mutex);
2103
if (pthread_create(&mainthread, &attr, timer_thread,
2104
(void *)&opt_timer_length) != 0)
2106
fprintf(stderr,"%s: Could not create timer thread\n", internal::my_progname);
2111
pthread_mutex_unlock(&counter_mutex);
2112
pthread_attr_destroy(&attr);
2114
pthread_mutex_lock(&sleeper_mutex);
2116
pthread_mutex_unlock(&sleeper_mutex);
2117
pthread_cond_broadcast(&sleep_threshhold);
2119
gettimeofday(&start_time, NULL);
2122
We loop until we know that all children have cleaned up.
2124
pthread_mutex_lock(&counter_mutex);
2125
while (thread_counter)
2127
struct timespec abstime;
2129
set_timespec(abstime, 3);
2130
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
2132
pthread_mutex_unlock(&counter_mutex);
2134
gettimeofday(&end_time, NULL);
2137
sptr->timing= timedif(end_time, start_time);
2138
sptr->users= concur;
2139
sptr->real_users= real_concurrency;
2146
pthread_handler_t timer_thread(void *p)
2148
uint32_t *timer_length= (uint32_t *)p;
2149
struct timespec abstime;
2153
We lock around the initial call in case were we in a loop. This
2154
also keeps the value properly syncronized across call threads.
2156
pthread_mutex_lock(&sleeper_mutex);
2157
while (master_wakeup)
2159
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
2161
pthread_mutex_unlock(&sleeper_mutex);
2163
set_timespec(abstime, *timer_length);
2165
pthread_mutex_lock(&timer_alarm_mutex);
2166
pthread_cond_timedwait(&timer_alarm_threshold, &timer_alarm_mutex, &abstime);
2167
pthread_mutex_unlock(&timer_alarm_mutex);
2169
pthread_mutex_lock(&timer_alarm_mutex);
2171
pthread_mutex_unlock(&timer_alarm_mutex);
2176
pthread_handler_t run_task(void *p)
2178
uint64_t counter= 0, queries;
2179
uint64_t detach_counter;
2180
unsigned int commit_counter;
2182
drizzle_result_st result;
2185
thread_context *ctx= (thread_context *)p;
2187
pthread_mutex_lock(&sleeper_mutex);
2188
while (master_wakeup)
2190
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
2192
pthread_mutex_unlock(&sleeper_mutex);
2194
slap_connect(&con, true);
2197
printf("connected!\n");
2202
run_query(&con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
2205
for (ptr= ctx->stmt, detach_counter= 0;
2207
ptr= ptr->next, detach_counter++)
2209
if (!opt_only_print && detach_rate && !(detach_counter % detach_rate))
2212
slap_connect(&con, true);
2216
We have to execute differently based on query type. This should become a function.
2218
if ((ptr->type == UPDATE_TYPE_REQUIRES_PREFIX) ||
2219
(ptr->type == SELECT_TYPE_REQUIRES_PREFIX))
2222
unsigned int key_val;
2224
char buffer[HUGE_STRING_LENGTH];
2227
This should only happen if some sort of new engine was
2228
implemented that didn't properly handle UPDATEs.
2230
Just in case someone runs this under an experimental engine we don't
2231
want a crash so the if() is placed here.
2233
assert(primary_keys_number_of);
2234
if (primary_keys_number_of)
2236
key_val= (unsigned int)(random() % primary_keys_number_of);
2237
key= primary_keys[key_val];
2241
length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
2242
(int)ptr->length, ptr->string, key);
2244
if (run_query(&con, &result, buffer, length))
2246
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2247
internal::my_progname, (uint32_t)length, buffer, drizzle_con_error(&con));
2254
if (run_query(&con, &result, ptr->string, ptr->length))
2256
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2257
internal::my_progname, (uint32_t)ptr->length, ptr->string, drizzle_con_error(&con));
2262
if (!opt_only_print)
2264
while ((row = drizzle_row_next(&result)))
2266
drizzle_result_free(&result);
2270
if (commit_rate && (++commit_counter == commit_rate))
2273
run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
2276
/* If the timer is set, and the alarm is not active then end */
2277
if (opt_timer_length && timer_alarm == false)
2280
/* If limit has been reached, and we are not in a timer_alarm just end */
2281
if (ctx->limit && queries == ctx->limit && timer_alarm == false)
2285
if (opt_timer_length && timer_alarm == true)
2288
if (ctx->limit && queries < ctx->limit)
2294
run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
2298
pthread_mutex_lock(&counter_mutex);
2300
pthread_cond_signal(&count_threshhold);
2301
pthread_mutex_unlock(&counter_mutex);
2309
Parse records from comma seperated string. : is a reserved character and is used for options
2313
parse_option(const char *origin, option_string **stmt, char delm)
2318
option_string **sptr= stmt;
2320
uint32_t length= strlen(origin);
2321
uint32_t count= 0; /* We know that there is always one */
2323
end_ptr= (char *)origin + length;
2325
tmp= *sptr= (option_string *)malloc(sizeof(option_string));
2328
fprintf(stderr,"Error allocating memory while parsing options\n");
2331
memset(tmp, 0, sizeof(option_string));
2333
for (begin_ptr= (char *)origin;
2334
begin_ptr != end_ptr;
2337
char buffer[HUGE_STRING_LENGTH];
2340
memset(buffer, 0, HUGE_STRING_LENGTH);
2342
string= strchr(begin_ptr, delm);
2346
memcpy(buffer, begin_ptr, string - begin_ptr);
2347
begin_ptr= string+1;
2351
size_t begin_len= strlen(begin_ptr);
2352
memcpy(buffer, begin_ptr, begin_len);
2356
if ((buffer_ptr= strchr(buffer, ':')))
2358
/* Set a null so that we can get strlen() correct later on */
2362
/* Move past the : and the first string */
2363
tmp->option_length= strlen(buffer_ptr);
2364
tmp->option= (char *)malloc(tmp->option_length + 1);
2365
if (tmp->option == NULL)
2367
fprintf(stderr,"Error allocating memory while parsing options\n");
2370
memcpy(tmp->option, buffer_ptr, tmp->option_length);
2371
tmp->option[tmp->option_length]= 0;
2374
tmp->length= strlen(buffer);
2375
tmp->string= strdup(buffer);
2376
if (tmp->string == NULL)
2378
fprintf(stderr,"Error allocating memory while parsing options\n");
2382
if (isspace(*begin_ptr))
2387
if (begin_ptr != end_ptr)
2389
tmp->next= (option_string *)malloc(sizeof(option_string));
2390
if (tmp->next == NULL)
2392
fprintf(stderr,"Error allocating memory while parsing options\n");
2395
memset(tmp->next, 0, sizeof(option_string));
2405
Raw parsing interface. If you want the slap specific parser look at
2409
parse_delimiter(const char *script, statement **stmt, char delm)
2412
char *ptr= (char *)script;
2413
statement **sptr= stmt;
2415
uint32_t length= strlen(script);
2416
uint32_t count= 0; /* We know that there is always one */
2418
for (tmp= *sptr= (statement *)calloc(1, sizeof(statement));
2419
(retstr= strchr(ptr, delm));
2420
tmp->next= (statement *)calloc(1, sizeof(statement)),
2425
fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2430
tmp->length= (size_t)(retstr - ptr);
2431
tmp->string= (char *)malloc(tmp->length + 1);
2433
if (tmp->string == NULL)
2435
fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2439
memcpy(tmp->string, ptr, tmp->length);
2440
tmp->string[tmp->length]= 0;
2441
ptr+= retstr - ptr + 1;
2446
if (ptr != script+length)
2448
tmp->length= (size_t)((script + length) - ptr);
2449
tmp->string= (char *)malloc(tmp->length + 1);
2450
if (tmp->string == NULL)
2452
fprintf(stderr,"Error allocating memory while parsing delimiter\n");
2455
memcpy(tmp->string, ptr, tmp->length);
2456
tmp->string[tmp->length]= 0;
2465
Parse comma is different from parse_delimeter in that it parses
2466
number ranges from a comma seperated string.
2467
In restrospect, this is a lousy name from this function.
2470
parse_comma(const char *string, uint32_t **range)
2472
unsigned int count= 1,x; /* We know that there is always one */
2474
char *ptr= (char *)string;
2478
if (*ptr == ',') count++;
2480
/* One extra spot for the NULL */
2481
nptr= *range= (uint32_t *)malloc(sizeof(unsigned int) * (count + 1));
2482
memset(nptr, 0, sizeof(unsigned int) * (count + 1));
2484
ptr= (char *)string;
2486
while ((retstr= strchr(ptr,',')))
2488
nptr[x++]= atoi(ptr);
2489
ptr+= retstr - ptr + 1;
2491
nptr[x++]= atoi(ptr);
2497
print_conclusions(conclusions *con)
2499
printf("Benchmark\n");
2501
printf("\tRunning for engine %s\n", con->engine);
2502
if (opt_label || opt_auto_generate_sql_type)
2504
const char *ptr= opt_auto_generate_sql_type ? opt_auto_generate_sql_type : "query";
2505
printf("\tLoad: %s\n", opt_label ? opt_label : ptr);
2507
printf("\tAverage Time took to generate schema and initial data: %ld.%03ld seconds\n",
2508
con->create_avg_timing / 1000, con->create_avg_timing % 1000);
2509
printf("\tAverage number of seconds to run all queries: %ld.%03ld seconds\n",
2510
con->avg_timing / 1000, con->avg_timing % 1000);
2511
printf("\tMinimum number of seconds to run all queries: %ld.%03ld seconds\n",
2512
con->min_timing / 1000, con->min_timing % 1000);
2513
printf("\tMaximum number of seconds to run all queries: %ld.%03ld seconds\n",
2514
con->max_timing / 1000, con->max_timing % 1000);
2515
printf("\tTotal time for tests: %ld.%03ld seconds\n",
2516
con->sum_of_time / 1000, con->sum_of_time % 1000);
2517
printf("\tStandard Deviation: %ld.%03ld\n", con->std_dev / 1000, con->std_dev % 1000);
2518
printf("\tNumber of queries in create queries: %"PRIu64"\n", con->create_count);
2519
printf("\tNumber of clients running queries: %u/%u\n",
2520
con->users, con->real_users);
2521
printf("\tNumber of times test was run: %u\n", iterations);
2522
printf("\tAverage number of queries per client: %"PRIu64"\n", con->avg_rows);
2527
print_conclusions_csv(conclusions *con)
2530
char buffer[HUGE_STRING_LENGTH];
2531
char label_buffer[HUGE_STRING_LENGTH];
2534
memset(label_buffer, 0, HUGE_STRING_LENGTH);
2538
string_len= strlen(opt_label);
2540
for (x= 0; x < string_len; x++)
2542
if (opt_label[x] == ',')
2543
label_buffer[x]= '-';
2545
label_buffer[x]= opt_label[x] ;
2548
else if (opt_auto_generate_sql_type)
2550
string_len= strlen(opt_auto_generate_sql_type);
2552
for (x= 0; x < string_len; x++)
2554
if (opt_auto_generate_sql_type[x] == ',')
2555
label_buffer[x]= '-';
2557
label_buffer[x]= opt_auto_generate_sql_type[x] ;
2561
snprintf(label_buffer, HUGE_STRING_LENGTH, "query");
2563
snprintf(buffer, HUGE_STRING_LENGTH,
2564
"%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,"
2565
"%u,%u,%u,%"PRIu64"\n",
2566
con->engine ? con->engine : "", /* Storage engine we ran against */
2567
label_buffer, /* Load type */
2568
con->avg_timing / 1000, con->avg_timing % 1000, /* Time to load */
2569
con->min_timing / 1000, con->min_timing % 1000, /* Min time */
2570
con->max_timing / 1000, con->max_timing % 1000, /* Max time */
2571
con->sum_of_time / 1000, con->sum_of_time % 1000, /* Total time */
2572
con->std_dev / 1000, con->std_dev % 1000, /* Standard Deviation */
2573
iterations, /* Iterations */
2574
con->users, /* Children used max_timing */
2575
con->real_users, /* Children used max_timing */
2576
con->avg_rows /* Queries run */
2578
internal::my_write(csv_file, (unsigned char*) buffer, (uint32_t)strlen(buffer), MYF(0));
2582
generate_stats(conclusions *con, option_string *eng, stats *sptr)
2587
con->min_timing= sptr->timing;
2588
con->max_timing= sptr->timing;
2589
con->min_rows= sptr->rows;
2590
con->max_rows= sptr->rows;
2592
/* At the moment we assume uniform */
2593
con->users= sptr->users;
2594
con->real_users= sptr->real_users;
2595
con->avg_rows= sptr->rows;
2597
/* With no next, we know it is the last element that was malloced */
2598
for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
2600
con->avg_timing+= ptr->timing;
2602
if (ptr->timing > con->max_timing)
2603
con->max_timing= ptr->timing;
2604
if (ptr->timing < con->min_timing)
2605
con->min_timing= ptr->timing;
2607
con->sum_of_time= con->avg_timing;
2608
con->avg_timing= con->avg_timing/iterations;
2610
if (eng && eng->string)
2611
con->engine= eng->string;
2615
standard_deviation(con, sptr);
2617
/* Now we do the create time operations */
2618
con->create_min_timing= sptr->create_timing;
2619
con->create_max_timing= sptr->create_timing;
2621
/* At the moment we assume uniform */
2622
con->create_count= sptr->create_count;
2624
/* With no next, we know it is the last element that was malloced */
2625
for (ptr= sptr, x= 0; x < iterations; ptr++, x++)
2627
con->create_avg_timing+= ptr->create_timing;
2629
if (ptr->create_timing > con->create_max_timing)
2630
con->create_max_timing= ptr->create_timing;
2631
if (ptr->create_timing < con->create_min_timing)
2632
con->create_min_timing= ptr->create_timing;
2634
con->create_avg_timing= con->create_avg_timing/iterations;
2638
option_cleanup(option_string *stmt)
2640
option_string *ptr, *nptr;
2644
for (ptr= stmt; ptr; ptr= nptr)
2656
statement_cleanup(statement *stmt)
2658
statement *ptr, *nptr;
2662
for (ptr= stmt; ptr; ptr= nptr)
2672
slap_close(drizzle_con_st *con)
2677
drizzle_free(drizzle_con_drizzle(con));
2681
slap_connect(drizzle_con_st *con, bool connect_to_schema)
2683
/* Connect to server */
2684
static uint32_t connection_retry_sleep= 100000; /* Microseconds */
2685
int x, connect_error= 1;
2686
drizzle_return_t ret;
2687
drizzle_st *drizzle;
2692
if (opt_delayed_start)
2693
usleep(random()%opt_delayed_start);
2695
if ((drizzle= drizzle_create(NULL)) == NULL ||
2696
drizzle_con_add_tcp(drizzle, con, host, opt_drizzle_port, user,
2698
connect_to_schema ? create_schema_string : NULL,
2699
opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE) == NULL)
2701
fprintf(stderr,"%s: Error creating drizzle object\n", internal::my_progname);
2705
for (x= 0; x < 10; x++)
2707
if ((ret= drizzle_con_connect(con)) == DRIZZLE_RETURN_OK)
2709
/* Connect suceeded */
2713
usleep(connection_retry_sleep);
2717
fprintf(stderr,"%s: Error when connecting to server: %d %s\n", internal::my_progname,
2718
ret, drizzle_con_error(con));
2726
standard_deviation (conclusions *con, stats *sptr)
2729
long int sum_of_squares;
2733
if (iterations == 1 || iterations == 0)
2739
for (ptr= sptr, x= 0, sum_of_squares= 0; x < iterations; ptr++, x++)
2743
deviation= ptr->timing - con->avg_timing;
2744
sum_of_squares+= deviation*deviation;
2747
the_catch= sqrt((double)(sum_of_squares/(iterations -1)));
2748
con->std_dev= (long int)the_catch;