summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/Makefile.am4
-rw-r--r--client/client_priv.h3
-rw-r--r--client/mysqlslap.c225
3 files changed, 172 insertions, 60 deletions
diff --git a/client/Makefile.am b/client/Makefile.am
index fe3620bbad7..8b6da68a659 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -52,7 +52,9 @@ mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c
mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix)
mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix)
mysqlshow_SOURCES= mysqlshow.c $(yassl_dummy_link_fix)
-mysqlslap_SOURCES= mysqlslap.c $(yassl_dummy_link_fix)
+mysqlslap_SOURCES= mysqlslap.c $(top_srcdir)/mysys/my_lock.c \
+ $(top_srcdir)/mysys/my_alarm.c \
+ $(yassl_dummy_link_fix)
mysqldump_SOURCES= mysqldump.c $(yassl_dummy_link_fix)
mysqlimport_SOURCES= mysqlimport.c $(yassl_dummy_link_fix)
sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
diff --git a/client/client_priv.h b/client/client_priv.h
index 6380b37230c..3539975df6e 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -51,6 +51,9 @@ enum options_client
#endif
OPT_TRIGGERS,
OPT_MYSQL_ONLY_PRINT,
+ OPT_MYSQL_LOCK_DIRECTORY,
+ OPT_MYSQL_SLAP_SLAVE,
+ OPT_MYSQL_NUMBER_OF_QUERY, OPT_MYSQL_NUMBER_OF_ROWS,
OPT_MYSQL_REPEAT_DATA, OPT_MYSQL_REPEAT_QUERY,
OPT_MYSQL_PRESERVE_SCHEMA_ENTER, OPT_MYSQL_PRESERVE_SCHEMA_EXIT,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index bd5635d40f4..d57055219a8 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -38,9 +38,9 @@
selects for each):
mysqlslap --create="CREATE TABLE A (a int)" \
- --data="INSERT INTO A (23)" --load-concurrency=8 --number-rows=8 \
+ --data="INSERT INTO A (23)" --concurrency-load=8 --number-rows=8 \
--query="SELECT * FROM A" --concurrency=50 --iterations=200 \
- --load-concurrency=5
+ --concurrency-load=5
Let the program build create, insert and query SQL statements with a table
of two int columns, three varchar columns, with five clients loading data
@@ -58,7 +58,7 @@
mysqlslap --concurrency=5 --iterations=20 \
--number-int-cols=2 --number-char-cols=3 \
- --number-rows=12 --auto-generate-sql \
+ --number-of-rows=12 --auto-generate-sql \
--skip-data-load --skip-create-schema
Tell the program to load the create, insert and query SQL statements from
@@ -70,7 +70,7 @@
mysqlslap --drop-schema --concurrency=5 --concurrency-load=5 \
--iterations=5 --query=query.sql --create=create.sql \
- --data=insert.sql --delimiter=";" --number-rows=5
+ --data=insert.sql --delimiter=";" --number-of-rows=5
Same as the last test run, with short options
@@ -80,10 +80,12 @@
TODO:
Add language for better tests
String length for files and those put on the command line are not
- setup to handle binary data.
+ setup to handle binary data.
+ Report results of each thread into the lock file we use.
+
*/
-#define SHOW_VERSION "0.1"
+#define SHOW_VERSION "0.9"
#define HUGE_STRING_LENGTH 8096
#define RAND_STRING_SIZE 126
@@ -101,6 +103,8 @@ TODO:
#include <sys/wait.h>
#include <ctype.h>
+#define MYSLAPLOCK "/myslaplock.lck"
+#define MYSLAPLOCK_DIR "/tmp"
static char **defaults_argv;
@@ -113,10 +117,15 @@ const char *delimiter= "\n";
const char *create_schema_string= "mysqlslap";
+const char *lock_directory;
+char lock_file_str[FN_REFLEN];
+
static my_bool opt_preserve_enter= FALSE, opt_preserve_exit= FALSE;
static my_bool opt_only_print= FALSE;
+static my_bool opt_slave;
+
static my_bool opt_compress= FALSE, tty_password= FALSE,
create_string_alloced= FALSE,
insert_string_alloced= FALSE, query_string_alloced= FALSE,
@@ -126,10 +135,12 @@ static my_bool opt_compress= FALSE, tty_password= FALSE,
static int verbose, num_int_cols, num_char_cols, delimiter_length;
static int iterations;
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
-static unsigned int repeat_data, repeat_query;
-static unsigned int actual_insert_rows= 0;
-static unsigned int actual_queries= 0;
-static unsigned int children_spawned;
+static uint repeat_data, repeat_query;
+static ulonglong actual_insert_rows= 0;
+static ulonglong actual_queries= 0;
+static uint children_spawned;
+static ulonglong num_of_rows;
+static ulonglong num_of_query;
const char *concurrency_str= NULL;
uint *concurrency;
const char *concurrency_load_str= NULL;
@@ -161,16 +172,17 @@ static statement *create_statements= NULL,
uint parse_comma(const char *string, uint **range);
uint parse_delimiter(const char *script, statement **stmt, char delm);
static int drop_schema(MYSQL *mysql, const char *db);
-unsigned int get_random_string(char *buf);
+uint get_random_string(char *buf);
static int build_table_string(void);
static int build_insert_string(void);
static int build_query_string(void);
static int create_schema(MYSQL *mysql, const char *db, statement *stmt,
statement *engine_stmt);
-static int run_scheduler(statement *stmts,
- int(*task)(statement *stmt), unsigned int concur);
-int run_task(statement *stmt);
-int load_data(statement *load_stmt);
+static double run_scheduler(statement *stmts,
+ int(*task)(statement *stmt, ulonglong limit, uint repeat),
+ uint concur, ulonglong limit, uint repeat);
+int run_task(statement *stmt, ulong limit, uint repeat);
+int load_data(statement *load_stmt, ulonglong limit);
static const char ALPHANUMERICS[]=
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
@@ -206,8 +218,8 @@ int main(int argc, char **argv)
{
MYSQL mysql;
int client_flag= 0;
- double time_difference;
- struct timeval start_time, load_time, run_time;
+ double load_difference;
+ double query_difference;
int x;
DBUG_ENTER("main");
@@ -215,7 +227,7 @@ int main(int argc, char **argv)
/* Seed the random number generator if we will be using it. */
if (auto_generate_sql)
- srandom((unsigned int)time(NULL));
+ srandom((uint)time(NULL));
load_defaults("my",load_default_groups,&argc,&argv);
defaults_argv=argv;
@@ -282,36 +294,54 @@ int main(int argc, char **argv)
if (!opt_preserve_enter)
drop_schema(&mysql, create_schema_string);
+ /*
+ Three stag process:
+ create
+ insert
+ run jobs
+ */
+
+ /* First we create */
if (create_statements)
create_schema(&mysql, create_schema_string, create_statements, eptr);
+ /* For the second act we load data */
if (insert_statements)
{
- gettimeofday(&start_time, NULL);
- run_scheduler(insert_statements, load_data, concurrency_load[0]);
- gettimeofday(&load_time, NULL);
- time_difference= timedif(load_time, start_time);
-
- if (!opt_silent)
+ uint *current;
+ for (current= concurrency_load; current && *current; current++)
{
- printf("Seconds to load data: %.5f\n",time_difference);
- printf("Number of clients loading data: %d\n", children_spawned);
- printf("Number of inserts per client: %d\n", repeat_data * actual_insert_rows);
+ load_difference= run_scheduler(insert_statements, run_task,
+ *current, num_of_rows, repeat_data);
+
+ if (!opt_silent)
+ {
+ printf("Seconds to load data: %.5f\n", load_difference);
+ printf("Number of clients loading data: %d\n", children_spawned);
+ printf("Number of inserts per client: %llu\n",
+ num_of_rows ? (unsigned long long)(num_of_rows / *current) :
+ (unsigned long long)repeat_data * actual_insert_rows);
+ }
}
}
+ /* For the final stage we run whatever queries we were asked to run */
if (query_statements)
{
- gettimeofday(&start_time, NULL);
- run_scheduler(query_statements, run_task, concurrency[0]);
- gettimeofday(&run_time, 0);
- time_difference= timedif(run_time, start_time);
-
- if (!opt_silent)
+ uint *current;
+ for (current= concurrency; current && *current; current++)
{
- printf("Seconds to run all queries: %.5f\n", time_difference);
- printf("Number of clients running queries: %d\n", children_spawned);
- printf("Number of queries per client: %d\n", repeat_query * actual_queries);
+ query_difference= run_scheduler(query_statements, run_task,
+ *current, num_of_query, repeat_query);
+
+ if (!opt_silent)
+ {
+ printf("Seconds to run all queries: %.5f\n", query_difference);
+ printf("Number of clients running queries: %d\n", children_spawned);
+ printf("Number of queries per client: %llu\n",
+ num_of_query ? (unsigned long long)(num_of_query / *current) :
+ (unsigned long long)repeat_query * actual_queries);
+ }
}
}
@@ -326,6 +356,10 @@ int main(int argc, char **argv)
if (!opt_only_print)
mysql_close(&mysql); /* Close & free connection */
+
+ /* Remove lock file */
+ my_delete(lock_file_str, MYF(0));
+
/* now free all the strings we created */
if (opt_password)
my_free(opt_password, MYF(0));
@@ -345,7 +379,8 @@ int main(int argc, char **argv)
for (ptr= create_statements; ptr;)
{
nptr= ptr->next;
- my_free(ptr->string, MYF(0));
+ if (ptr->string)
+ my_free(ptr->string, MYF(0));
my_free((byte *)ptr, MYF(0));
ptr= nptr;
}
@@ -357,7 +392,8 @@ int main(int argc, char **argv)
for (ptr= engine_statements; ptr;)
{
nptr= ptr->next;
- my_free(ptr->string, MYF(0));
+ if (ptr->string)
+ my_free(ptr->string, MYF(0));
my_free((byte *)ptr, MYF(0));
ptr= nptr;
}
@@ -369,7 +405,8 @@ int main(int argc, char **argv)
for (ptr= insert_statements; ptr;)
{
nptr= ptr->next;
- my_free(ptr->string, MYF(0));
+ if (ptr->string)
+ my_free(ptr->string, MYF(0));
my_free((byte *)ptr, MYF(0));
ptr= nptr;
}
@@ -381,7 +418,8 @@ int main(int argc, char **argv)
for (ptr= query_statements; ptr;)
{
nptr= ptr->next;
- my_free(ptr->string, MYF(0));
+ if (ptr->string)
+ my_free(ptr->string, MYF(0));
my_free((byte *)ptr, MYF(0));
ptr= nptr;
}
@@ -439,6 +477,9 @@ static struct my_option my_long_options[] =
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"iterations", 'i', "Number of times too run the tests.", (gptr*) &iterations,
(gptr*) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
+ {"lock-directory", OPT_MYSQL_LOCK_DIRECTORY, "Connect to host.",
+ (gptr*) &lock_directory, (gptr*) &lock_directory, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"number-char-cols", 'x',
"Number of INT columns to create table with if specifying --sql-generate-sql.",
(gptr*) &num_char_cols, (gptr*) &num_char_cols, 0, GET_UINT, REQUIRED_ARG,
@@ -447,6 +488,14 @@ static struct my_option my_long_options[] =
"Number of VARCHAR columns to create table with if specifying \
--sql-generate-sql.", (gptr*) &num_int_cols, (gptr*) &num_int_cols, 0,
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"number-of-query", OPT_MYSQL_NUMBER_OF_QUERY,
+ "Limit each client to this number of queries (this is not exact).",
+ (gptr*) &num_of_query, (gptr*) &num_of_query, 0,
+ GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"number-of-rows", OPT_MYSQL_NUMBER_OF_ROWS,
+ "Limit each client to this number of rows (this is not exact).",
+ (gptr*) &num_of_rows, (gptr*) &num_of_rows, 0,
+ GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"only-print", OPT_MYSQL_ONLY_PRINT,
"This causes mysqlslap to not connect to the databases, but instead print \
out what it would have done instead.",
@@ -473,6 +522,9 @@ static struct my_option my_long_options[] =
{"protocol", OPT_MYSQL_PROTOCOL,
"The protocol of connection (tcp,socket,pipe,memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"query", 'q', "Query to run or file containing query to run.",
+ (gptr*) &user_supplied_query, (gptr*) &user_supplied_query,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"repeat-data", OPT_MYSQL_REPEAT_DATA, "Number of times to repeat what was specified by \
the --data option",
(gptr*) &repeat_data, (gptr*) &repeat_data, 0, GET_UINT,
@@ -490,9 +542,9 @@ static struct my_option my_long_options[] =
(gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
#endif
- {"query", 'q', "Query to run or file containing query to run.",
- (gptr*) &user_supplied_query, (gptr*) &user_supplied_query,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"slave", OPT_MYSQL_SLAP_SLAVE, "Follow master locks for other slap clients",
+ (gptr*) &opt_slave, (gptr*) &opt_slave, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -594,7 +646,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
-unsigned int
+uint
get_random_string(char *buf)
{
char *buf_ptr= buf;
@@ -790,6 +842,11 @@ get_options(int *argc,char ***argv)
concurrency[0]= 1;
}
+ if (lock_directory)
+ snprintf(lock_file_str, FN_REFLEN, "%s/%s", lock_directory, MYSLAPLOCK);
+ else
+ snprintf(lock_file_str, FN_REFLEN, "%s/%s", MYSLAPLOCK_DIR, MYSLAPLOCK);
+
if (concurrency_load_str)
parse_comma(concurrency_load_str, &concurrency_load);
else
@@ -1003,16 +1060,32 @@ drop_schema(MYSQL *mysql, const char *db)
}
-static int
+static double
run_scheduler(statement *stmts,
- int(*task)(statement *stmt), unsigned int concur)
+ int(*task)(statement *stmt, ulonglong limit, uint repeat),
+ uint concur, ulonglong limit, uint repeat)
{
uint x;
+ ulonglong client_limit= 0;
+ File lock_file;
+ struct timeval start_time, end_time;
+
+ if (limit)
+ client_limit= limit / concur;
DBUG_ENTER("run_scheduler");
/* reset to 0 */
children_spawned= 0;
+ lock_file= my_open(lock_file_str, O_CREAT|O_WRONLY|O_TRUNC, MYF(0));
+
+ if (!opt_slave)
+ if (my_lock(lock_file, F_WRLCK, 0, F_TO_EOF, MYF(0)))
+ {
+ fprintf(stderr,"%s: Could not get lockfile\n",
+ my_progname);
+ exit(0);
+ }
for (x= 0; x < concur; x++)
{
int pid;
@@ -1028,7 +1101,7 @@ run_scheduler(statement *stmts,
fprintf(stderr,
"%s: fork returned 0, calling task pid %d gid %d\n",
my_progname, pid, getgid());
- task(stmts);
+ task(stmts, client_limit, repeat);
exit(0);
break;
case -1:
@@ -1050,6 +1123,13 @@ run_scheduler(statement *stmts,
}
children_spawned++;
}
+ /* Lets release use some clients! */
+ if (!opt_slave)
+ my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
+
+ gettimeofday(&start_time, NULL);
+
+ my_close(lock_file, MYF(0));
WAIT:
while (x--)
@@ -1058,14 +1138,16 @@ WAIT:
pid= wait(&status);
DBUG_PRINT("info", ("Parent: child %d status %d", pid, status));
}
+ gettimeofday(&end_time, NULL);
- DBUG_RETURN(0);
+ DBUG_RETURN(timedif(end_time, start_time));
}
int
-run_task(statement *qstmt)
+run_task(statement *qstmt, ulonglong limit, uint repeat)
{
- uint counter= 0, x;
+ ulonglong counter= 0, x, queries;
+ File lock_file;
MYSQL mysql;
MYSQL_RES *result;
MYSQL_ROW row;
@@ -1076,6 +1158,8 @@ run_task(statement *qstmt)
mysql_init(&mysql);
DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user));
+ lock_file= my_open(lock_file_str, O_RDWR, MYF(0));
+ my_lock(lock_file, F_RDLCK, 0, F_TO_EOF, MYF(0));
if (!opt_only_print)
{
if (!(mysql_real_connect(&mysql, host, user, opt_password,
@@ -1088,7 +1172,10 @@ run_task(statement *qstmt)
}
DBUG_PRINT("info", ("connected."));
- for (x= 0; x < repeat_query; x++)
+ queries= 0;
+
+limit_not_met:
+ for (x= 0; x < repeat; x++)
{
statement *ptr;
for (ptr= qstmt; ptr && ptr->length; ptr= ptr->next)
@@ -1105,26 +1192,40 @@ run_task(statement *qstmt)
my_progname, (uint)ptr->length, ptr->string, mysql_error(&mysql));
exit(1);
}
-
- result= mysql_store_result(&mysql);
- while ((row = mysql_fetch_row(result)))
- counter++;
- mysql_free_result(result);
- result= 0;
+ if (mysql_field_count(&mysql))
+ {
+ result= mysql_store_result(&mysql);
+ while ((row = mysql_fetch_row(result)))
+ counter++;
+ mysql_free_result(result);
+ }
}
+ queries++;
+
+ if (limit && queries == limit)
+ DBUG_RETURN(0);
}
}
+ if (limit && queries < limit)
+ goto limit_not_met;
+
+ my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
+ my_close(lock_file, MYF(0));
+
if (!opt_only_print)
mysql_close(&mysql);
DBUG_RETURN(0);
}
+#ifdef TO_BE_DELETED
+
int
-load_data(statement *load_stmt)
+load_data(statement *load_stmt, ulonglong limit)
{
uint x;
+ uint inserted;
MYSQL mysql;
DBUG_ENTER("load_data");
@@ -1143,7 +1244,7 @@ load_data(statement *load_stmt)
}
}
- for (x= 0; x < repeat_data; x++)
+ for (x= 0, inserted= 0; x < repeat_data; x++)
{
statement *ptr;
for (ptr= load_stmt; ptr && ptr->length; ptr= ptr->next)
@@ -1163,6 +1264,10 @@ load_data(statement *load_stmt)
exit(1);
}
}
+ inserted++;
+
+ if (limit && inserted == limit)
+ return 0;
}
}
@@ -1171,6 +1276,8 @@ load_data(statement *load_stmt)
DBUG_RETURN(0);
}
+#endif
+
uint
parse_delimiter(const char *script, statement **stmt, char delm)