summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/client_priv.h4
-rw-r--r--client/mysqlslap.c109
-rw-r--r--mysql-test/r/mysqlslap.result44
-rw-r--r--mysql-test/t/mysqlslap.test2
-rw-r--r--storage/archive/ha_archive.cc59
-rw-r--r--storage/archive/ha_archive.h3
6 files changed, 173 insertions, 48 deletions
diff --git a/client/client_priv.h b/client/client_priv.h
index 25241cc8c59..8bc8ef692de 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -73,6 +73,10 @@ enum options_client
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
OPT_SLAP_PRE_QUERY,
OPT_SLAP_POST_QUERY,
+ OPT_SLAP_PRE_SYSTEM,
+ OPT_SLAP_POST_SYSTEM,
+ OPT_SLAP_COMMIT,
+ OPT_SLAP_DETACH,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
OPT_DEBUG_INFO, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE, OPT_WRITE_BINLOG,
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index 546b9dee3f5..aa15141bfdc 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -81,6 +81,7 @@ TODO:
#define UPDATE_TYPE_REQUIRES_PREFIX 3
#define CREATE_TABLE_TYPE 4
#define SELECT_TYPE_REQUIRES_PREFIX 5
+#define DELETE_TYPE_REQUIRES_PREFIX 6
#include "client_priv.h"
#include <mysqld_error.h>
@@ -122,6 +123,8 @@ static char *host= NULL, *opt_password= NULL, *user= NULL,
*user_supplied_pre_statements= NULL,
*user_supplied_post_statements= NULL,
*default_engine= NULL,
+ *pre_system= NULL,
+ *post_system= NULL,
*opt_mysql_unix_port= NULL;
const char *delimiter= "\n";
@@ -142,6 +145,8 @@ const char *auto_generate_sql_type= "mixed";
static unsigned long connect_flags= CLIENT_MULTI_RESULTS;
static int verbose, delimiter_length;
+static uint commit_rate;
+static uint detach_rate;
const char *num_int_cols_opt;
const char *num_char_cols_opt;
/* Yes, we do set defaults here */
@@ -254,6 +259,8 @@ void statement_cleanup(statement *stmt);
void option_cleanup(option_string *stmt);
void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr);
static int run_statements(MYSQL *mysql, statement *stmt);
+int slap_connect(MYSQL *mysql);
+static int run_query(MYSQL *mysql, const char *query, int len);
static const char ALPHANUMERICS[]=
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
@@ -451,6 +458,16 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
generate_primary_key_list(mysql, eptr);
+ if (commit_rate)
+ run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
+
+ if (pre_system)
+ system(pre_system);
+
+ /*
+ Pre statements are always run after all other logic so they can
+ correct/adjust any item that they want.
+ */
if (pre_statements)
run_statements(mysql, pre_statements);
@@ -459,6 +476,9 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (post_statements)
run_statements(mysql, post_statements);
+ if (post_system)
+ system(post_system);
+
/* We are finished with this run */
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
drop_primary_key_list();
@@ -527,6 +547,9 @@ static struct my_option my_long_options[] =
"Number of rows to insert to used in read and write loads (default is 100).\n",
(uchar**) &auto_generate_sql_number, (uchar**) &auto_generate_sql_number,
0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0},
+ {"commit", OPT_SLAP_COMMIT, "Commit records after X number of statements.",
+ (uchar**) &commit_rate, (uchar**) &commit_rate, 0, GET_UINT, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use compression in server/client protocol.",
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -550,6 +573,9 @@ static struct my_option my_long_options[] =
"Delimiter to use in SQL statements supplied in file or command line.",
(uchar**) &delimiter, (uchar**) &delimiter, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
+ {"detach", OPT_SLAP_DETACH, "Detach connections after X number of requests.",
+ (uchar**) &detach_rate, (uchar**) &detach_rate, 0, GET_UINT, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"engine", 'e', "Storage engine to use for creating the table.",
(uchar**) &default_engine, (uchar**) &default_engine, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -589,11 +615,21 @@ static struct my_option my_long_options[] =
(uchar**) &user_supplied_post_statements,
(uchar**) &user_supplied_post_statements,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"post-system", OPT_SLAP_POST_SYSTEM,
+ "System() string to run after the load has completed.",
+ (uchar**) &post_system,
+ (uchar**) &post_system,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"pre-query", OPT_SLAP_PRE_QUERY,
"Query to run or file containing query to run before executing.",
(uchar**) &user_supplied_pre_statements,
(uchar**) &user_supplied_pre_statements,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"pre-system", OPT_SLAP_PRE_SYSTEM,
+ "System() string to before load has completed.",
+ (uchar**) &pre_system,
+ (uchar**) &pre_system,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"preserve-schema", OPT_MYSQL_PRESERVE_SCHEMA,
"Preserve the schema from the mysqlslap run, this happens unless "
"--auto-generate-sql or --create are used.",
@@ -1715,6 +1751,7 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
pthread_handler_t run_task(void *p)
{
ulonglong counter= 0, queries;
+ ulonglong trans_counter;
MYSQL *mysql;
MYSQL_RES *result;
MYSQL_ROW row;
@@ -1749,38 +1786,28 @@ pthread_handler_t run_task(void *p)
if (!opt_only_print)
{
- /* Connect to server */
- static ulong connection_retry_sleep= 100000; /* Microseconds */
- int i, connect_error= 1;
- for (i= 0; i < 10; i++)
- {
- if (mysql_real_connect(mysql, host, user, opt_password,
- create_schema_string,
- opt_mysql_port,
- opt_mysql_unix_port,
- connect_flags))
- {
- /* Connect suceeded */
- connect_error= 0;
- break;
- }
- my_sleep(connection_retry_sleep);
- }
- if (connect_error)
- {
- fprintf(stderr,"%s: Error when connecting to server: %d %s\n",
- my_progname, mysql_errno(mysql), mysql_error(mysql));
+ if (slap_connect(mysql))
goto end;
- }
}
+
DBUG_PRINT("info", ("connected."));
if (verbose >= 3)
printf("connected!\n");
queries= 0;
limit_not_met:
- for (ptr= con->stmt; ptr && ptr->length; ptr= ptr->next)
+ for (ptr= con->stmt, trans_counter= 0;
+ ptr && ptr->length;
+ ptr= ptr->next, trans_counter++)
{
+ if (!opt_only_print && detach_rate && !(trans_counter % detach_rate))
+ {
+ mysql_close(mysql);
+
+ if (slap_connect(mysql))
+ goto end;
+ }
+
/*
We have to execute differently based on query type. This should become a function.
*/
@@ -1837,6 +1864,9 @@ limit_not_met:
}
queries++;
+ if (commit_rate && commit_rate <= trans_counter)
+ run_query(mysql, "COMMIT", strlen("COMMIT"));
+
if (con->limit && queries == con->limit)
goto end;
}
@@ -1845,6 +1875,8 @@ limit_not_met:
goto limit_not_met;
end:
+ if (commit_rate)
+ run_query(mysql, "COMMIT", strlen("COMMIT"));
if (!opt_only_print)
mysql_close(mysql);
@@ -2104,3 +2136,34 @@ statement_cleanup(statement *stmt)
my_free(ptr, MYF(0));
}
}
+
+
+int
+slap_connect(MYSQL *mysql)
+{
+ /* Connect to server */
+ static ulong connection_retry_sleep= 100000; /* Microseconds */
+ int x, connect_error= 1;
+ for (x= 0; x < 10; x++)
+ {
+ if (mysql_real_connect(mysql, host, user, opt_password,
+ create_schema_string,
+ opt_mysql_port,
+ opt_mysql_unix_port,
+ connect_flags))
+ {
+ /* Connect suceeded */
+ connect_error= 0;
+ break;
+ }
+ my_sleep(connection_retry_sleep);
+ }
+ if (connect_error)
+ {
+ fprintf(stderr,"%s: Error when connecting to server: %d %s\n",
+ my_progname, mysql_errno(mysql), mysql_error(mysql));
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/mysql-test/r/mysqlslap.result b/mysql-test/r/mysqlslap.result
index bca7919d78c..cc8bc3dac31 100644
--- a/mysql-test/r/mysqlslap.result
+++ b/mysql-test/r/mysqlslap.result
@@ -167,3 +167,47 @@ SHOW TABLES;
select * from t1;
SHOW TABLES;
DROP SCHEMA IF EXISTS `mysqlslap`;
+DROP SCHEMA IF EXISTS `mysqlslap`;
+CREATE SCHEMA `mysqlslap`;
+use mysqlslap;
+set storage_engine=`heap`;
+CREATE TABLE t1 (id int, name varchar(64));
+create table t2(foo1 varchar(32), foo2 varchar(32));
+INSERT INTO t1 VALUES (1, 'This is a test');
+insert into t2 values ('test', 'test2');
+SET AUTOCOMMIT=0;
+SHOW TABLES;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+COMMIT;
+SHOW TABLES;
+DROP SCHEMA IF EXISTS `mysqlslap`;
+DROP SCHEMA IF EXISTS `mysqlslap`;
+CREATE SCHEMA `mysqlslap`;
+use mysqlslap;
+set storage_engine=`myisam`;
+CREATE TABLE t1 (id int, name varchar(64));
+create table t2(foo1 varchar(32), foo2 varchar(32));
+INSERT INTO t1 VALUES (1, 'This is a test');
+insert into t2 values ('test', 'test2');
+SET AUTOCOMMIT=0;
+SHOW TABLES;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+COMMIT;
+SHOW TABLES;
+DROP SCHEMA IF EXISTS `mysqlslap`;
diff --git a/mysql-test/t/mysqlslap.test b/mysql-test/t/mysqlslap.test
index 2a7bbfed932..192aefb0e03 100644
--- a/mysql-test/t/mysqlslap.test
+++ b/mysql-test/t/mysqlslap.test
@@ -36,3 +36,5 @@
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-guid-primary --auto-generate-sql-load-type=key --auto-generate-sql-execute-number=5 --auto-generate-sql-secondary-indexes=3
--exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --post-query="SHOW TABLES" --pre-query="SHOW TABLES";
+
+ --exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --post-query="SHOW TABLES" --pre-query="SHOW TABLES" --number-of-queries=6 --commit=1;
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index bdc59cbe795..6696eac2fbb 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -436,6 +436,9 @@ int ha_archive::init_archive_writer()
}
+/*
+ No locks are required because it is associated with just one handler instance
+*/
int ha_archive::init_archive_reader()
{
DBUG_ENTER("ha_archive::init_archive_reader");
@@ -794,15 +797,16 @@ int ha_archive::write_row(uchar *buf)
if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- if (!share->archive_write_open)
- if (init_archive_writer())
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
-
ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
pthread_mutex_lock(&share->mutex);
+ if (!share->archive_write_open)
+ if (init_archive_writer())
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+
if (table->next_number_field && record == table->record[0])
{
KEY *mkey= &table->s->key_info[0]; // We only support one key right now
@@ -992,24 +996,6 @@ int ha_archive::rnd_init(bool scan)
{
DBUG_PRINT("info", ("archive will retrieve %llu rows",
(unsigned long long) scan_rows));
- stats.records= 0;
-
- /*
- If dirty, we lock, and then reset/flush the data.
- I found that just calling azflush() doesn't always work.
- */
- pthread_mutex_lock(&share->mutex);
- scan_rows= share->rows_recorded;
- if (share->dirty == TRUE)
- {
- if (share->dirty == TRUE)
- {
- DBUG_PRINT("ha_archive", ("archive flushing out rows for scan"));
- azflush(&(share->archive_write), Z_SYNC_FLUSH);
- share->dirty= FALSE;
- }
- }
- pthread_mutex_unlock(&share->mutex);
if (read_data_header(&archive))
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
@@ -1223,9 +1209,7 @@ int ha_archive::rnd_next(uchar *buf)
current_position= aztell(&archive);
rc= get_row(&archive, buf);
-
- if (rc != HA_ERR_END_OF_FILE)
- stats.records++;
+ table->status=rc ? STATUS_NOT_FOUND: 0;
DBUG_RETURN(rc);
}
@@ -1461,12 +1445,33 @@ void ha_archive::update_create_info(HA_CREATE_INFO *create_info)
int ha_archive::info(uint flag)
{
DBUG_ENTER("ha_archive::info");
+
+ /*
+ If dirty, we lock, and then reset/flush the data.
+ I found that just calling azflush() doesn't always work.
+ */
+ pthread_mutex_lock(&share->mutex);
+ if (share->dirty == TRUE)
+ {
+ if (share->dirty == TRUE)
+ {
+ DBUG_PRINT("ha_archive", ("archive flushing out rows for scan"));
+ azflush(&(share->archive_write), Z_SYNC_FLUSH);
+ share->dirty= FALSE;
+ }
+ }
+
/*
This should be an accurate number now, though bulk and delayed inserts can
cause the number to be inaccurate.
*/
stats.records= share->rows_recorded;
+ pthread_mutex_unlock(&share->mutex);
+
+ scan_rows= stats.records;
stats.deleted= 0;
+
+ DBUG_PRINT("ha_archive", ("Stats rows is %d\n", (int)stats.records));
/* Costs quite a bit more to get all information */
if (flag & HA_STATUS_TIME)
{
@@ -1486,7 +1491,9 @@ int ha_archive::info(uint flag)
if (flag & HA_STATUS_AUTO)
{
init_archive_reader();
+ pthread_mutex_lock(&share->mutex);
azflush(&archive, Z_SYNC_FLUSH);
+ pthread_mutex_unlock(&share->mutex);
stats.auto_increment_value= archive.auto_increment;
}
@@ -1554,7 +1561,9 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
old_proc_info= thd_proc_info(thd, "Checking table");
/* Flush any waiting data */
+ pthread_mutex_lock(&share->mutex);
azflush(&(share->archive_write), Z_SYNC_FLUSH);
+ pthread_mutex_unlock(&share->mutex);
/*
Now we will rewind the archive file so that we are positioned at the
diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h
index 22fb57b0cc7..ab630ed22fd 100644
--- a/storage/archive/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -88,6 +88,8 @@ public:
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+ HA_STATS_RECORDS_IS_EXACT |
+ HA_HAS_RECORDS |
HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
@@ -101,6 +103,7 @@ public:
uint max_supported_keys() const { return 1; }
uint max_supported_key_length() const { return sizeof(ulonglong); }
uint max_supported_key_part_length() const { return sizeof(ulonglong); }
+ ha_rows records() { return share->rows_recorded; }
int index_init(uint keynr, bool sorted);
virtual int index_read(uchar * buf, const uchar * key,
uint key_len, enum ha_rkey_function find_flag);