Commit 019446f0 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/data0/bk/mysql-5.1

into  bk-internal.mysql.com:/data0/bk/mysql-5.1-marvel


client/client_priv.h:
  Auto merged
client/mysqlslap.c:
  Auto merged
sql/mysqld.cc:
  Auto merged
parents 940eb733 f4422bd4
...@@ -131,10 +131,10 @@ ADD_SUBDIRECTORY(dbug) ...@@ -131,10 +131,10 @@ ADD_SUBDIRECTORY(dbug)
ADD_SUBDIRECTORY(strings) ADD_SUBDIRECTORY(strings)
ADD_SUBDIRECTORY(regex) ADD_SUBDIRECTORY(regex)
ADD_SUBDIRECTORY(mysys) ADD_SUBDIRECTORY(mysys)
ADD_SUBDIRECTORY(zlib)
ADD_SUBDIRECTORY(extra/yassl) ADD_SUBDIRECTORY(extra/yassl)
ADD_SUBDIRECTORY(extra/yassl/taocrypt) ADD_SUBDIRECTORY(extra/yassl/taocrypt)
ADD_SUBDIRECTORY(extra) ADD_SUBDIRECTORY(extra)
ADD_SUBDIRECTORY(zlib)
ADD_SUBDIRECTORY(storage/heap) ADD_SUBDIRECTORY(storage/heap)
ADD_SUBDIRECTORY(storage/myisam) ADD_SUBDIRECTORY(storage/myisam)
ADD_SUBDIRECTORY(storage/myisammrg) ADD_SUBDIRECTORY(storage/myisammrg)
......
...@@ -147,6 +147,28 @@ test-force-full: ...@@ -147,6 +147,28 @@ test-force-full:
test-force-mem: test-force-mem:
$(MAKE) force=--force mem=--mem test $(MAKE) force=--force mem=--mem test
test-bt:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=normal --force --timer \
--skip-ndbcluster --report-features
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=ps --force --timer \
--skip-ndbcluster --ps-protocol
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=normal+rowrepl --force --timer \
--skip-ndbcluster --mysqld=--binlog-format=row
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=ps+rowrepl+NDB --force --timer \
--ps-protocol --mysqld=--binlog-format=row
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=NDB --force --timer \
--with-ndbcluster-only
test-bt-debug:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=debug --force --timer \
--skip-ndbcluster --skip-rpl --report-features
# Keep these for a while # Keep these for a while
test-pl: test test-pl: test
test-full-pl: test-full test-full-pl: test-full
......
...@@ -95,6 +95,7 @@ ADD_EXECUTABLE(mysqladmin mysqladmin.cc) ...@@ -95,6 +95,7 @@ ADD_EXECUTABLE(mysqladmin mysqladmin.cc)
TARGET_LINK_LIBRARIES(mysqladmin mysqlclient mysys dbug yassl taocrypt zlib wsock32) TARGET_LINK_LIBRARIES(mysqladmin mysqlclient mysys dbug yassl taocrypt zlib wsock32)
ADD_EXECUTABLE(mysqlslap mysqlslap.c) ADD_EXECUTABLE(mysqlslap mysqlslap.c)
SET_SOURCE_FILES_PROPERTIES(mysqlslap.c PROPERTIES COMPILE_FLAGS "-DTHREADS")
TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys yassl taocrypt zlib wsock32 dbug) TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys yassl taocrypt zlib wsock32 dbug)
ADD_EXECUTABLE(echo echo.c) ADD_EXECUTABLE(echo echo.c)
......
...@@ -34,7 +34,7 @@ LDADD= @CLIENT_EXTRA_LDFLAGS@ $(CLIENT_THREAD_LIBS) \ ...@@ -34,7 +34,7 @@ LDADD= @CLIENT_EXTRA_LDFLAGS@ $(CLIENT_THREAD_LIBS) \
noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \ noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
client_priv.h client_priv.h
EXTRA_DIST = get_password.c CMakeLists.txt EXTRA_DIST = get_password.c CMakeLists.txt echo.c
bin_PROGRAMS = mysql \ bin_PROGRAMS = mysql \
mysqladmin \ mysqladmin \
...@@ -76,6 +76,7 @@ mysqlimport_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \ ...@@ -76,6 +76,7 @@ mysqlimport_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
mysqlshow_SOURCES= mysqlshow.c mysqlshow_SOURCES= mysqlshow.c
mysqlslap_SOURCES= mysqlslap.c mysqlslap_SOURCES= mysqlslap.c
mysqlslap_CFLAGS= -DTHREAD -UUNDEF_THREADS_HACK
mysqlslap_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \ mysqlslap_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
@CLIENT_EXTRA_LDFLAGS@ \ @CLIENT_EXTRA_LDFLAGS@ \
$(LIBMYSQLCLIENT_LA) \ $(LIBMYSQLCLIENT_LA) \
...@@ -96,7 +97,6 @@ DEFS = -DUNDEF_THREADS_HACK \ ...@@ -96,7 +97,6 @@ DEFS = -DUNDEF_THREADS_HACK \
sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
strings_src=decimal.c strings_src=decimal.c
EXTRA_DIST = get_password.c CMakeLists.txt echo.c
link_sources: link_sources:
for f in $(sql_src) ; do \ for f in $(sql_src) ; do \
......
...@@ -49,7 +49,6 @@ enum options_client ...@@ -49,7 +49,6 @@ enum options_client
OPT_TRIGGERS, OPT_TRIGGERS,
OPT_MYSQL_ONLY_PRINT, OPT_MYSQL_ONLY_PRINT,
OPT_MYSQL_LOCK_DIRECTORY, OPT_MYSQL_LOCK_DIRECTORY,
OPT_MYSQL_SLAP_SLAVE,
OPT_USE_THREADS, OPT_USE_THREADS,
OPT_IMPORT_USE_THREADS, OPT_IMPORT_USE_THREADS,
OPT_MYSQL_NUMBER_OF_QUERY, OPT_MYSQL_NUMBER_OF_QUERY,
...@@ -58,6 +57,14 @@ enum options_client ...@@ -58,6 +57,14 @@ enum options_client
OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA, OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA,
OPT_SLAP_CSV, OPT_SLAP_CREATE_STRING, OPT_SLAP_CSV, OPT_SLAP_CREATE_STRING,
OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, OPT_SLAP_AUTO_GENERATE_WRITE_NUM, OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
OPT_SLAP_PRE_QUERY,
OPT_SLAP_POST_QUERY,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT, OPT_SERVER_ID, OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT, OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
OPT_DEBUG_INFO, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE OPT_DEBUG_INFO, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE
......
...@@ -62,7 +62,6 @@ TODO: ...@@ -62,7 +62,6 @@ TODO:
Add language for better tests Add language for better tests
String length for files and those put on the command line are not 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.
More stats More stats
Break up tests and run them on multiple hosts at once. Break up tests and run them on multiple hosts at once.
Allow output to be fed into a database directly. Allow output to be fed into a database directly.
...@@ -71,16 +70,18 @@ TODO: ...@@ -71,16 +70,18 @@ TODO:
#define SHOW_VERSION "0.9" #define SHOW_VERSION "0.9"
#define HUGE_STRING_LENGTH 8096 #define HUGE_STRING_LENGTH 8196
#define RAND_STRING_SIZE 126 #define RAND_STRING_SIZE 126
/* Types */
#define SELECT_TYPE 0
#define UPDATE_TYPE 1
#define INSERT_TYPE 2
#define UPDATE_TYPE_REQUIRES_PREFIX 3
#define CREATE_TABLE_TYPE 4
#define SELECT_TYPE_REQUIRES_PREFIX 5
#include "client_priv.h" #include "client_priv.h"
#ifdef HAVE_LIBPTHREAD
#include <my_pthread.h>
#endif
#include <my_sys.h>
#include <m_string.h>
#include <mysql.h>
#include <mysqld_error.h> #include <mysqld_error.h>
#include <my_dir.h> #include <my_dir.h>
#include <signal.h> #include <signal.h>
...@@ -92,9 +93,6 @@ TODO: ...@@ -92,9 +93,6 @@ TODO:
#endif #endif
#include <ctype.h> #include <ctype.h>
#define MYSLAPLOCK "/myslaplock.lck"
#define MYSLAPLOCK_DIR "/tmp"
#ifdef __WIN__ #ifdef __WIN__
#define srandom srand #define srandom srand
#define random rand #define random rand
...@@ -105,10 +103,23 @@ TODO: ...@@ -105,10 +103,23 @@ TODO:
static char *shared_memory_base_name=0; static char *shared_memory_base_name=0;
#endif #endif
/* Global Thread counter */
uint thread_counter;
pthread_mutex_t counter_mutex;
pthread_cond_t count_threshhold;
uint master_wakeup;
pthread_mutex_t sleeper_mutex;
pthread_cond_t sleep_threshhold;
static char **defaults_argv; static char **defaults_argv;
char **primary_keys;
unsigned long long primary_keys_number_of;
static char *host= NULL, *opt_password= NULL, *user= NULL, static char *host= NULL, *opt_password= NULL, *user= NULL,
*user_supplied_query= NULL, *user_supplied_query= NULL,
*user_supplied_pre_statements= NULL,
*user_supplied_post_statements= NULL,
*default_engine= NULL, *default_engine= NULL,
*opt_mysql_unix_port= NULL; *opt_mysql_unix_port= NULL;
...@@ -116,26 +127,35 @@ const char *delimiter= "\n"; ...@@ -116,26 +127,35 @@ const char *delimiter= "\n";
const char *create_schema_string= "mysqlslap"; const char *create_schema_string= "mysqlslap";
const char *lock_directory;
char lock_file_str[FN_REFLEN];
static my_bool opt_preserve; static my_bool opt_preserve;
static my_bool opt_only_print= FALSE; static my_bool opt_only_print= FALSE;
static my_bool opt_slave;
static my_bool opt_compress= FALSE, tty_password= FALSE, static my_bool opt_compress= FALSE, tty_password= FALSE,
opt_silent= FALSE, opt_silent= FALSE,
auto_generate_sql_autoincrement= FALSE,
auto_generate_sql_guid_primary= FALSE,
auto_generate_sql= FALSE; auto_generate_sql= FALSE;
const char *auto_generate_sql_type= "mixed"; const char *auto_generate_sql_type= "mixed";
static unsigned long connect_flags= CLIENT_MULTI_RESULTS; static unsigned long connect_flags= CLIENT_MULTI_RESULTS;
static int verbose, num_int_cols, num_char_cols, delimiter_length; static int verbose, delimiter_length;
static int iterations; const char *num_int_cols_opt;
const char *num_char_cols_opt;
/* Yes, we do set defaults here */
static unsigned int num_int_cols= 1;
static unsigned int num_char_cols= 1;
static unsigned int num_int_cols_index= 0;
static unsigned int num_char_cols_index= 0;
static unsigned int iterations;
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
static ulonglong actual_queries= 0; static ulonglong actual_queries= 0;
static ulonglong auto_actual_queries;
static ulonglong auto_generate_sql_unique_write_number;
static ulonglong auto_generate_sql_unique_query_number;
static unsigned int auto_generate_sql_secondary_indexes;
static ulonglong num_of_query; static ulonglong num_of_query;
static ulonglong auto_generate_sql_number; static ulonglong auto_generate_sql_number;
const char *concurrency_str= NULL; const char *concurrency_str= NULL;
...@@ -150,7 +170,6 @@ static uint opt_protocol= 0; ...@@ -150,7 +170,6 @@ static uint opt_protocol= 0;
static int get_options(int *argc,char ***argv); static int get_options(int *argc,char ***argv);
static uint opt_mysql_port= 0; static uint opt_mysql_port= 0;
static uint opt_use_threads;
static const char *load_default_groups[]= { "mysqlslap","client",0 }; static const char *load_default_groups[]= { "mysqlslap","client",0 };
...@@ -159,9 +178,22 @@ typedef struct statement statement; ...@@ -159,9 +178,22 @@ typedef struct statement statement;
struct statement { struct statement {
char *string; char *string;
size_t length; size_t length;
unsigned char type;
char *option;
size_t option_length;
statement *next; statement *next;
}; };
typedef struct option_string option_string;
struct option_string {
char *string;
size_t length;
char *option;
size_t option_length;
option_string *next;
};
typedef struct stats stats; typedef struct stats stats;
struct stats { struct stats {
...@@ -175,7 +207,6 @@ typedef struct thread_context thread_context; ...@@ -175,7 +207,6 @@ typedef struct thread_context thread_context;
struct thread_context { struct thread_context {
statement *stmt; statement *stmt;
ulonglong limit; ulonglong limit;
bool thread;
}; };
typedef struct conclusions conclusions; typedef struct conclusions conclusions;
...@@ -192,27 +223,36 @@ struct conclusions { ...@@ -192,27 +223,36 @@ struct conclusions {
unsigned long long min_rows; unsigned long long min_rows;
}; };
static option_string *engine_options= NULL;
static statement *pre_statements= NULL;
static statement *post_statements= NULL;
static statement *create_statements= NULL, static statement *create_statements= NULL,
*engine_statements= NULL,
*query_statements= NULL; *query_statements= NULL;
/* Prototypes */ /* Prototypes */
void print_conclusions(conclusions *con); void print_conclusions(conclusions *con);
void print_conclusions_csv(conclusions *con); void print_conclusions_csv(conclusions *con);
void generate_stats(conclusions *con, statement *eng, stats *sptr); void generate_stats(conclusions *con, option_string *eng, stats *sptr);
uint parse_comma(const char *string, uint **range); uint parse_comma(const char *string, uint **range);
uint parse_delimiter(const char *script, statement **stmt, char delm); uint parse_delimiter(const char *script, statement **stmt, char delm);
uint parse_option(const char *origin, option_string **stmt, char delm);
static int drop_schema(MYSQL *mysql, const char *db); static int drop_schema(MYSQL *mysql, const char *db);
uint get_random_string(char *buf); uint get_random_string(char *buf);
static statement *build_table_string(void); static statement *build_table_string(void);
static statement *build_insert_string(void); static statement *build_insert_string(void);
static statement *build_query_string(void); static statement *build_update_string(void);
static statement * build_select_string(my_bool key);
static int generate_primary_key_list(MYSQL *mysql, option_string *engine_stmt);
static int drop_primary_key_list(void);
static int create_schema(MYSQL *mysql, const char *db, statement *stmt, static int create_schema(MYSQL *mysql, const char *db, statement *stmt,
statement *engine_stmt); option_string *engine_stmt);
static int run_scheduler(stats *sptr, statement *stmts, uint concur, static int run_scheduler(stats *sptr, statement *stmts, uint concur,
ulonglong limit); ulonglong limit);
int run_task(thread_context *con); pthread_handler_t run_task(void *p);
void statement_cleanup(statement *stmt); 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);
static const char ALPHANUMERICS[]= static const char ALPHANUMERICS[]=
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz"; "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
...@@ -246,13 +286,7 @@ static int gettimeofday(struct timeval *tp, void *tzp) ...@@ -246,13 +286,7 @@ static int gettimeofday(struct timeval *tp, void *tzp)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
MYSQL mysql; MYSQL mysql;
int x; option_string *eptr;
unsigned long long client_limit;
statement *eptr;
#ifdef __WIN__
opt_use_threads= 1;
#endif
MY_INIT(argv[0]); MY_INIT(argv[0]);
...@@ -309,78 +343,63 @@ int main(int argc, char **argv) ...@@ -309,78 +343,63 @@ int main(int argc, char **argv)
} }
} }
VOID(pthread_mutex_init(&counter_mutex, NULL));
VOID(pthread_cond_init(&count_threshhold, NULL));
VOID(pthread_mutex_init(&sleeper_mutex, NULL));
VOID(pthread_cond_init(&sleep_threshhold, NULL));
/* Main iterations loop */ /* Main iterations loop */
eptr= engine_statements; eptr= engine_options;
do do
{ {
/* For the final stage we run whatever queries we were asked to run */ /* For the final stage we run whatever queries we were asked to run */
uint *current; uint *current;
conclusions conclusion;
for (current= concurrency; current && *current; current++)
{
stats *head_sptr;
stats *sptr;
head_sptr= (stats *)my_malloc(sizeof(stats) * iterations, MYF(MY_ZEROFILL));
bzero(&conclusion, sizeof(conclusions));
if (num_of_query) if (verbose >= 2)
client_limit= num_of_query / *current; printf("Starting Concurrency Test\n");
else
client_limit= actual_queries;
for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
{
/*
We might not want to load any data, such as when we are calling
a stored_procedure that doesn't use data, or we know we already have
data in the table.
*/
if (!opt_preserve)
drop_schema(&mysql, create_schema_string);
/* First we create */
if (create_statements)
create_schema(&mysql, create_schema_string, create_statements, eptr);
run_scheduler(sptr, query_statements, *current, client_limit); if (*concurrency)
{
for (current= concurrency; current && *current; current++)
concurrency_loop(&mysql, *current, eptr);
}
else
{
uint infinite= 1;
do {
concurrency_loop(&mysql, infinite, eptr);
} }
while (infinite++);
generate_stats(&conclusion, eptr, head_sptr);
if (!opt_silent)
print_conclusions(&conclusion);
if (opt_csv_str)
print_conclusions_csv(&conclusion);
my_free((byte *)head_sptr, MYF(0));
} }
if (!opt_preserve) if (!opt_preserve)
drop_schema(&mysql, create_schema_string); drop_schema(&mysql, create_schema_string);
} while (eptr ? (eptr= eptr->next) : 0); } while (eptr ? (eptr= eptr->next) : 0);
VOID(pthread_mutex_destroy(&counter_mutex));
VOID(pthread_cond_destroy(&count_threshhold));
VOID(pthread_mutex_destroy(&sleeper_mutex));
VOID(pthread_cond_destroy(&sleep_threshhold));
if (!opt_only_print) if (!opt_only_print)
mysql_close(&mysql); /* Close & free connection */ mysql_close(&mysql); /* Close & free connection */
/* Remove lock file */
my_delete(lock_file_str, MYF(0));
/* now free all the strings we created */ /* now free all the strings we created */
if (opt_password) if (opt_password)
my_free(opt_password, MYF(0)); my_free((gptr)opt_password, MYF(0));
my_free((byte *)concurrency, MYF(0)); my_free((gptr)concurrency, MYF(0));
statement_cleanup(create_statements); statement_cleanup(create_statements);
statement_cleanup(engine_statements);
statement_cleanup(query_statements); statement_cleanup(query_statements);
statement_cleanup(pre_statements);
statement_cleanup(post_statements);
option_cleanup(engine_options);
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
if (shared_memory_base_name) if (shared_memory_base_name)
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); my_free((gptr)shared_memory_base_name, MYF(MY_ALLOW_ZERO_PTR));
#endif #endif
free_defaults(defaults_argv); free_defaults(defaults_argv);
my_end(0); my_end(0);
...@@ -388,6 +407,76 @@ int main(int argc, char **argv) ...@@ -388,6 +407,76 @@ int main(int argc, char **argv)
return 0; return 0;
} }
void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
{
unsigned int x;
stats *head_sptr;
stats *sptr;
conclusions conclusion;
unsigned long long client_limit;
head_sptr= (stats *)my_malloc(sizeof(stats) * iterations,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
bzero(&conclusion, sizeof(conclusions));
if (auto_actual_queries)
client_limit= auto_actual_queries;
else if (num_of_query)
client_limit= num_of_query / current;
else
client_limit= actual_queries;
for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
{
/*
We might not want to load any data, such as when we are calling
a stored_procedure that doesn't use data, or we know we already have
data in the table.
*/
if (!opt_preserve)
drop_schema(mysql, create_schema_string);
/* First we create */
if (create_statements)
create_schema(mysql, create_schema_string, create_statements, eptr);
/*
If we generated GUID we need to build a list of them from creation that
we can later use.
*/
if (verbose >= 2)
printf("Generating primary key list\n");
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
generate_primary_key_list(mysql, eptr);
if (pre_statements)
run_statements(mysql, pre_statements);
run_scheduler(sptr, query_statements, current, client_limit);
if (post_statements)
run_statements(mysql, post_statements);
/* We are finished with this run */
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
drop_primary_key_list();
}
if (verbose >= 2)
printf("Generating stats\n");
generate_stats(&conclusion, eptr, head_sptr);
if (!opt_silent)
print_conclusions(&conclusion);
if (opt_csv_str)
print_conclusions_csv(&conclusion);
my_free((gptr)head_sptr, MYF(0));
}
static struct my_option my_long_options[] = static struct my_option my_long_options[] =
{ {
...@@ -397,10 +486,42 @@ static struct my_option my_long_options[] = ...@@ -397,10 +486,42 @@ static struct my_option my_long_options[] =
"Generate SQL where not supplied by file or command line.", "Generate SQL where not supplied by file or command line.",
(gptr*) &auto_generate_sql, (gptr*) &auto_generate_sql, (gptr*) &auto_generate_sql, (gptr*) &auto_generate_sql,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-add-autoincrement", OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
"Add autoincrement to auto-generated tables.",
(gptr*) &auto_generate_sql_autoincrement,
(gptr*) &auto_generate_sql_autoincrement,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-execute-number", OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
"Set this number to generate a set number of queries to run.\n",
(gptr*) &auto_actual_queries, (gptr*) &auto_actual_queries,
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-guid-primary", OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
"Add GUID based primary keys to auto-generated tables.",
(gptr*) &auto_generate_sql_guid_primary,
(gptr*) &auto_generate_sql_guid_primary,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, {"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
"Load types are mixed, write, or read. Default is mixed\n", "Load types are mixed, update, write, key, or read. Default is mixed\n",
(gptr*) &auto_generate_sql_type, (gptr*) &auto_generate_sql_type, (gptr*) &auto_generate_sql_type, (gptr*) &auto_generate_sql_type,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-secondary-indexes",
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
"Number of secondary indexes to add auto-generated tables.",
(gptr*) &auto_generate_sql_secondary_indexes,
(gptr*) &auto_generate_sql_secondary_indexes, 0,
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-unique-query-number",
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
"Number of unique queries auto tests",
(gptr*) &auto_generate_sql_unique_query_number,
(gptr*) &auto_generate_sql_unique_query_number,
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
{"auto-generate-sql-unique-write-number",
OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
"Number of unique queries for auto-generate-sql-write-number",
(gptr*) &auto_generate_sql_unique_write_number,
(gptr*) &auto_generate_sql_unique_write_number,
0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
{"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM, {"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
"Number of rows to insert to used in read and write loads (default is 100).\n", "Number of rows to insert to used in read and write loads (default is 100).\n",
(gptr*) &auto_generate_sql_number, (gptr*) &auto_generate_sql_number, (gptr*) &auto_generate_sql_number, (gptr*) &auto_generate_sql_number,
...@@ -435,17 +556,14 @@ static struct my_option my_long_options[] = ...@@ -435,17 +556,14 @@ static struct my_option my_long_options[] =
REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"iterations", 'i', "Number of times too run the tests.", (gptr*) &iterations, {"iterations", 'i', "Number of times too run the tests.", (gptr*) &iterations,
(gptr*) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, (gptr*) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{"lock-directory", OPT_MYSQL_LOCK_DIRECTORY, "Directory to use to keep locks.",
(gptr*) &lock_directory, (gptr*) &lock_directory, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"number-char-cols", 'x', {"number-char-cols", 'x',
"Number of VARCHAR columns to create table with if specifying --auto-generate-sql ", "Number of VARCHAR columns to create table with if specifying --auto-generate-sql ",
(gptr*) &num_char_cols, (gptr*) &num_char_cols, 0, GET_UINT, REQUIRED_ARG, (gptr*) &num_char_cols_opt, (gptr*) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
1, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"number-int-cols", 'y', {"number-int-cols", 'y',
"Number of INT columns to create table with if specifying --auto-generate-sql.", "Number of INT columns to create table with if specifying --auto-generate-sql.",
(gptr*) &num_int_cols, (gptr*) &num_int_cols, 0, GET_UINT, REQUIRED_ARG, (gptr*) &num_int_cols_opt, (gptr*) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
1, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"number-of-queries", OPT_MYSQL_NUMBER_OF_QUERY, {"number-of-queries", OPT_MYSQL_NUMBER_OF_QUERY,
"Limit each client to this number of queries (this is not exact).", "Limit each client to this number of queries (this is not exact).",
(gptr*) &num_of_query, (gptr*) &num_of_query, 0, (gptr*) &num_of_query, (gptr*) &num_of_query, 0,
...@@ -465,6 +583,16 @@ static struct my_option my_long_options[] = ...@@ -465,6 +583,16 @@ static struct my_option my_long_options[] =
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
(gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0}, 0},
{"post-query", OPT_SLAP_POST_QUERY,
"Query to run or file containing query to run after executing.",
(gptr*) &user_supplied_post_statements,
(gptr*) &user_supplied_post_statements,
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.",
(gptr*) &user_supplied_pre_statements,
(gptr*) &user_supplied_pre_statements,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"preserve-schema", OPT_MYSQL_PRESERVE_SCHEMA, {"preserve-schema", OPT_MYSQL_PRESERVE_SCHEMA,
"Preserve the schema from the mysqlslap run, this happens unless " "Preserve the schema from the mysqlslap run, this happens unless "
"--auto-generate-sql or --create are used.", "--auto-generate-sql or --create are used.",
...@@ -485,17 +613,10 @@ static struct my_option my_long_options[] = ...@@ -485,17 +613,10 @@ static struct my_option my_long_options[] =
{"silent", 's', "Run program in silent mode - no output.", {"silent", 's', "Run program in silent mode - no output.",
(gptr*) &opt_silent, (gptr*) &opt_silent, 0, GET_BOOL, NO_ARG, (gptr*) &opt_silent, (gptr*) &opt_silent, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0}, 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.", {"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h> #include <sslopt-longopts.h>
{"use-threads", OPT_USE_THREADS,
"Use pthread calls instead of fork() calls (default on Windows)",
(gptr*) &opt_use_threads, (gptr*) &opt_use_threads, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE #ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.", (gptr*) &user, {"user", 'u', "User for login if not current user.", (gptr*) &user,
(gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
...@@ -552,7 +673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -552,7 +673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (argument) if (argument)
{ {
char *start= argument; char *start= argument;
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); my_free((gptr)opt_password, MYF(MY_ALLOW_ZERO_PTR));
opt_password= my_strdup(argument,MYF(MY_FAE)); opt_password= my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */ while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start) if (*start)
...@@ -609,43 +730,196 @@ get_random_string(char *buf) ...@@ -609,43 +730,196 @@ get_random_string(char *buf)
static statement * static statement *
build_table_string(void) build_table_string(void)
{ {
char buf[512]; char buf[HUGE_STRING_LENGTH];
int col_count; unsigned int col_count;
statement *ptr; statement *ptr;
DYNAMIC_STRING table_string; DYNAMIC_STRING table_string;
DBUG_ENTER("build_table_string"); DBUG_ENTER("build_table_string");
DBUG_PRINT("info", ("num int cols %d num char cols %d", DBUG_PRINT("info", ("num int cols %u num char cols %u",
num_int_cols, num_char_cols)); num_int_cols, num_char_cols));
init_dynamic_string(&table_string, "", 1024, 1024); init_dynamic_string(&table_string, "", 1024, 1024);
dynstr_append(&table_string, "CREATE TABLE `t1` ("); dynstr_append(&table_string, "CREATE TABLE `t1` (");
for (col_count= 1; col_count <= num_int_cols; col_count++)
if (auto_generate_sql_autoincrement)
{ {
sprintf(buf, "intcol%d INT(32)", col_count); dynstr_append(&table_string, "id serial");
dynstr_append(&table_string, buf);
if (col_count < num_int_cols || num_char_cols > 0) if (num_int_cols || num_char_cols)
dynstr_append(&table_string, ","); dynstr_append(&table_string, ",");
} }
for (col_count= 1; col_count <= num_char_cols; col_count++)
if (auto_generate_sql_guid_primary)
{ {
sprintf(buf, "charcol%d VARCHAR(128)", col_count); dynstr_append(&table_string, "id varchar(32) primary key");
dynstr_append(&table_string, buf);
if (col_count < num_char_cols) if (num_int_cols || num_char_cols || auto_generate_sql_guid_primary)
dynstr_append(&table_string, ","); dynstr_append(&table_string, ",");
} }
if (auto_generate_sql_secondary_indexes)
{
unsigned int count;
for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
{
if (count) /* Except for the first pass we add a comma */
dynstr_append(&table_string, ",");
if (snprintf(buf, HUGE_STRING_LENGTH, "id%d varchar(32) unique key", count)
> HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in create table\n");
exit(1);
}
dynstr_append(&table_string, buf);
}
if (num_int_cols || num_char_cols)
dynstr_append(&table_string, ",");
}
if (num_int_cols)
for (col_count= 1; col_count <= num_int_cols; col_count++)
{
if (num_int_cols_index)
{
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT(32), INDEX(intcol%d)",
col_count, col_count) > HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in create table\n");
exit(1);
}
}
else
{
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT(32) ", col_count)
> HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in create table\n");
exit(1);
}
}
dynstr_append(&table_string, buf);
if (col_count < num_int_cols || num_char_cols > 0)
dynstr_append(&table_string, ",");
}
if (num_char_cols)
for (col_count= 1; col_count <= num_char_cols; col_count++)
{
if (num_char_cols_index)
{
if (snprintf(buf, HUGE_STRING_LENGTH,
"charcol%d VARCHAR(128), INDEX(charcol%d) ",
col_count, col_count) > HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in creating table\n");
exit(1);
}
}
else
{
if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d VARCHAR(128)",
col_count) > HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in creating table\n");
exit(1);
}
}
dynstr_append(&table_string, buf);
if (col_count < num_char_cols)
dynstr_append(&table_string, ",");
}
dynstr_append(&table_string, ")"); dynstr_append(&table_string, ")");
ptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL)); ptr= (statement *)my_malloc(sizeof(statement),
ptr->string = (char *)my_malloc(table_string.length+1, MYF(MY_WME)); MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->string = (char *)my_malloc(table_string.length+1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->length= table_string.length+1; ptr->length= table_string.length+1;
ptr->type= CREATE_TABLE_TYPE;
strmov(ptr->string, table_string.str); strmov(ptr->string, table_string.str);
dynstr_free(&table_string); dynstr_free(&table_string);
DBUG_RETURN(ptr); DBUG_RETURN(ptr);
} }
/*
build_update_string()
This function builds insert statements when the user opts to not supply
an insert file or string containing insert data
*/
static statement *
build_update_string(void)
{
char buf[HUGE_STRING_LENGTH];
unsigned int col_count;
statement *ptr;
DYNAMIC_STRING update_string;
DBUG_ENTER("build_update_string");
init_dynamic_string(&update_string, "", 1024, 1024);
dynstr_append(&update_string, "UPDATE t1 SET ");
if (num_int_cols)
for (col_count= 1; col_count <= num_int_cols; col_count++)
{
if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d = %ld", col_count,
random()) > HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in creating update\n");
exit(1);
}
dynstr_append(&update_string, buf);
if (col_count < num_int_cols || num_char_cols > 0)
dynstr_append_mem(&update_string, ",", 1);
}
if (num_char_cols)
for (col_count= 1; col_count <= num_char_cols; col_count++)
{
char rand_buffer[RAND_STRING_SIZE];
int buf_len= get_random_string(rand_buffer);
if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d = '%.*s'", col_count,
buf_len, rand_buffer)
> HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in creating update\n");
exit(1);
}
dynstr_append(&update_string, buf);
if (col_count < num_char_cols)
dynstr_append_mem(&update_string, ",", 1);
}
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
dynstr_append(&update_string, " WHERE id = ");
ptr= (statement *)my_malloc(sizeof(statement),
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->string= (char *)my_malloc(update_string.length + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->length= update_string.length+1;
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
ptr->type= UPDATE_TYPE_REQUIRES_PREFIX ;
else
ptr->type= UPDATE_TYPE;
strmov(ptr->string, update_string.str);
dynstr_free(&update_string);
DBUG_RETURN(ptr);
}
/* /*
build_insert_string() build_insert_string()
...@@ -656,38 +930,82 @@ build_table_string(void) ...@@ -656,38 +930,82 @@ build_table_string(void)
static statement * static statement *
build_insert_string(void) build_insert_string(void)
{ {
char buf[RAND_STRING_SIZE]; char buf[HUGE_STRING_LENGTH];
int col_count; unsigned int col_count;
statement *ptr; statement *ptr;
DYNAMIC_STRING insert_string; DYNAMIC_STRING insert_string;
DBUG_ENTER("build_insert_string"); DBUG_ENTER("build_insert_string");
init_dynamic_string(&insert_string, "", 1024, 1024); init_dynamic_string(&insert_string, "", 1024, 1024);
dynstr_append_mem(&insert_string, "INSERT INTO t1 VALUES (", 23); dynstr_append(&insert_string, "INSERT INTO t1 VALUES (");
for (col_count= 1; col_count <= num_int_cols; col_count++)
if (auto_generate_sql_autoincrement)
{ {
sprintf(buf, "%ld", random()); dynstr_append(&insert_string, "NULL");
dynstr_append(&insert_string, buf);
if (col_count < num_int_cols || num_char_cols > 0) if (num_int_cols || num_char_cols)
dynstr_append_mem(&insert_string, ",", 1); dynstr_append(&insert_string, ",");
} }
for (col_count= 1; col_count <= num_char_cols; col_count++)
if (auto_generate_sql_guid_primary)
{ {
int buf_len= get_random_string(buf); dynstr_append(&insert_string, "uuid()");
dynstr_append_mem(&insert_string, "'", 1);
dynstr_append_mem(&insert_string, buf, buf_len);
dynstr_append_mem(&insert_string, "'", 1);
if (col_count < num_char_cols) if (num_int_cols || num_char_cols)
dynstr_append_mem(&insert_string, ",", 1); dynstr_append(&insert_string, ",");
}
if (auto_generate_sql_secondary_indexes)
{
unsigned int count;
for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
{
if (count) /* Except for the first pass we add a comma */
dynstr_append(&insert_string, ",");
dynstr_append(&insert_string, "uuid()");
}
if (num_int_cols || num_char_cols)
dynstr_append(&insert_string, ",");
} }
if (num_int_cols)
for (col_count= 1; col_count <= num_int_cols; col_count++)
{
if (snprintf(buf, HUGE_STRING_LENGTH, "%ld", random()) > HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in creating insert\n");
exit(1);
}
dynstr_append(&insert_string, buf);
if (col_count < num_int_cols || num_char_cols > 0)
dynstr_append_mem(&insert_string, ",", 1);
}
if (num_char_cols)
for (col_count= 1; col_count <= num_char_cols; col_count++)
{
int buf_len= get_random_string(buf);
dynstr_append_mem(&insert_string, "'", 1);
dynstr_append_mem(&insert_string, buf, buf_len);
dynstr_append_mem(&insert_string, "'", 1);
if (col_count < num_char_cols)
dynstr_append_mem(&insert_string, ",", 1);
}
dynstr_append_mem(&insert_string, ")", 1); dynstr_append_mem(&insert_string, ")", 1);
ptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL)); ptr= (statement *)my_malloc(sizeof(statement),
ptr->string= (char *)my_malloc(insert_string.length+1, MYF(MY_WME)); MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->string= (char *)my_malloc(insert_string.length + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->length= insert_string.length+1; ptr->length= insert_string.length+1;
ptr->type= INSERT_TYPE;
strmov(ptr->string, insert_string.str); strmov(ptr->string, insert_string.str);
dynstr_free(&insert_string); dynstr_free(&insert_string);
DBUG_RETURN(ptr); DBUG_RETURN(ptr);
...@@ -695,26 +1013,31 @@ build_insert_string(void) ...@@ -695,26 +1013,31 @@ build_insert_string(void)
/* /*
build_query_string() build_select_string()
This function builds a query if the user opts to not supply a query This function builds a query if the user opts to not supply a query
statement or file containing a query statement statement or file containing a query statement
*/ */
static statement * static statement *
build_query_string(void) build_select_string(my_bool key)
{ {
char buf[512]; char buf[HUGE_STRING_LENGTH];
int col_count; unsigned int col_count;
statement *ptr; statement *ptr;
static DYNAMIC_STRING query_string; static DYNAMIC_STRING query_string;
DBUG_ENTER("build_query_string"); DBUG_ENTER("build_select_string");
init_dynamic_string(&query_string, "", 1024, 1024); init_dynamic_string(&query_string, "", 1024, 1024);
dynstr_append_mem(&query_string, "SELECT ", 7); dynstr_append_mem(&query_string, "SELECT ", 7);
for (col_count= 1; col_count <= num_int_cols; col_count++) for (col_count= 1; col_count <= num_int_cols; col_count++)
{ {
sprintf(buf, "intcol%d", col_count); if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d", col_count)
> HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in creating select\n");
exit(1);
}
dynstr_append(&query_string, buf); dynstr_append(&query_string, buf);
if (col_count < num_int_cols || num_char_cols > 0) if (col_count < num_int_cols || num_char_cols > 0)
...@@ -723,17 +1046,34 @@ build_query_string(void) ...@@ -723,17 +1046,34 @@ build_query_string(void)
} }
for (col_count= 1; col_count <= num_char_cols; col_count++) for (col_count= 1; col_count <= num_char_cols; col_count++)
{ {
sprintf(buf, "charcol%d", col_count); if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d", col_count)
> HUGE_STRING_LENGTH)
{
fprintf(stderr, "Memory Allocation error in creating select\n");
exit(1);
}
dynstr_append(&query_string, buf); dynstr_append(&query_string, buf);
if (col_count < num_char_cols) if (col_count < num_char_cols)
dynstr_append_mem(&query_string, ",", 1); dynstr_append_mem(&query_string, ",", 1);
} }
dynstr_append_mem(&query_string, " FROM t1", 8); dynstr_append(&query_string, " FROM t1");
ptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL));
ptr->string= (char *)my_malloc(query_string.length+1, MYF(MY_WME)); if ((key) &&
(auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
dynstr_append(&query_string, " WHERE id = ");
ptr= (statement *)my_malloc(sizeof(statement),
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->string= (char *)my_malloc(query_string.length + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->length= query_string.length+1; ptr->length= query_string.length+1;
if ((key) &&
(auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
ptr->type= SELECT_TYPE_REQUIRES_PREFIX;
else
ptr->type= SELECT_TYPE;
strmov(ptr->string, query_string.str); strmov(ptr->string, query_string.str);
dynstr_free(&query_string); dynstr_free(&query_string);
DBUG_RETURN(ptr); DBUG_RETURN(ptr);
...@@ -768,12 +1108,40 @@ get_options(int *argc,char ***argv) ...@@ -768,12 +1108,40 @@ get_options(int *argc,char ***argv)
exit(1); exit(1);
} }
parse_comma(concurrency_str ? concurrency_str : "1", &concurrency); if (auto_generate_sql && auto_generate_sql_guid_primary &&
auto_generate_sql_autoincrement)
{
fprintf(stderr,
"%s: Either auto-generate-sql-guid-primary or auto-generate-sql-add-autoincrement can be used!\n",
my_progname);
exit(1);
}
/*
We are testing to make sure that if someone specified a key search
that we actually added a key!
*/
if (auto_generate_sql && auto_generate_sql_type[0] == 'k')
if ( auto_generate_sql_autoincrement == FALSE &&
auto_generate_sql_guid_primary == FALSE)
{
fprintf(stderr,
"%s: Can't perform key test without a primary key!\n",
my_progname);
exit(1);
}
if (lock_directory)
snprintf(lock_file_str, FN_REFLEN, "%s/%s", lock_directory, MYSLAPLOCK); if (auto_generate_sql && num_of_query && auto_actual_queries)
else {
snprintf(lock_file_str, FN_REFLEN, "%s/%s", MYSLAPLOCK_DIR, MYSLAPLOCK); fprintf(stderr,
"%s: Either auto-generate-sql-execute-number or number-of-queries can be used!\n",
my_progname);
exit(1);
}
parse_comma(concurrency_str ? concurrency_str : "1", &concurrency);
if (opt_csv_str) if (opt_csv_str)
{ {
...@@ -798,23 +1166,76 @@ get_options(int *argc,char ***argv) ...@@ -798,23 +1166,76 @@ get_options(int *argc,char ***argv)
if (opt_only_print) if (opt_only_print)
opt_silent= TRUE; opt_silent= TRUE;
if (num_int_cols_opt)
{
option_string *str;
parse_option(num_int_cols_opt, &str, ',');
num_int_cols= atoi(str->string);
if (str->option)
num_int_cols_index= atoi(str->option);
option_cleanup(str);
}
if (num_char_cols_opt)
{
option_string *str;
parse_option(num_char_cols_opt, &str, ',');
num_char_cols= atoi(str->string);
if (str->option)
num_char_cols_index= atoi(str->option);
else
num_char_cols_index= 0;
option_cleanup(str);
}
if (auto_generate_sql) if (auto_generate_sql)
{ {
unsigned long long x= 0; unsigned long long x= 0;
statement *ptr_statement; statement *ptr_statement;
if (verbose >= 2)
printf("Building Create Statements for Auto\n");
create_statements= build_table_string(); create_statements= build_table_string();
/*
Pre-populate table
*/
for (ptr_statement= create_statements, x= 0;
x < auto_generate_sql_unique_write_number;
x++, ptr_statement= ptr_statement->next)
{
ptr_statement->next= build_insert_string();
}
if (verbose >= 2)
printf("Building Query Statements for Auto\n");
if (auto_generate_sql_type[0] == 'r') if (auto_generate_sql_type[0] == 'r')
{ {
for (ptr_statement= create_statements, x= 0; if (verbose >= 2)
x < auto_generate_sql_number; printf("Generating SELECT Statements for Auto\n");
query_statements= build_select_string(FALSE);
for (ptr_statement= query_statements, x= 0;
x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next) x++, ptr_statement= ptr_statement->next)
{ {
ptr_statement->next= build_insert_string(); ptr_statement->next= build_select_string(FALSE);
} }
}
else if (auto_generate_sql_type[0] == 'k')
{
if (verbose >= 2)
printf("Generating SELECT for keys Statements for Auto\n");
query_statements= build_query_string(); query_statements= build_select_string(TRUE);
for (ptr_statement= query_statements, x= 0;
x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next)
{
ptr_statement->next= build_select_string(TRUE);
}
} }
else if (auto_generate_sql_type[0] == 'w') else if (auto_generate_sql_type[0] == 'w')
{ {
...@@ -823,14 +1244,26 @@ get_options(int *argc,char ***argv) ...@@ -823,14 +1244,26 @@ get_options(int *argc,char ***argv)
Archive (since strings which were identical one after another Archive (since strings which were identical one after another
would be too easily optimized). would be too easily optimized).
*/ */
if (verbose >= 2)
printf("Generating INSERT Statements for Auto\n");
query_statements= build_insert_string(); query_statements= build_insert_string();
for (ptr_statement= query_statements, x= 0; for (ptr_statement= query_statements, x= 0;
x < auto_generate_sql_number; x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next) x++, ptr_statement= ptr_statement->next)
{ {
ptr_statement->next= build_insert_string(); ptr_statement->next= build_insert_string();
} }
} }
else if (auto_generate_sql_type[0] == 'u')
{
query_statements= build_update_string();
for (ptr_statement= query_statements, x= 0;
x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next)
{
ptr_statement->next= build_update_string();
}
}
else /* Mixed mode is default */ else /* Mixed mode is default */
{ {
int coin= 0; int coin= 0;
...@@ -841,7 +1274,7 @@ get_options(int *argc,char ***argv) ...@@ -841,7 +1274,7 @@ get_options(int *argc,char ***argv)
at the moment it results in "every other". at the moment it results in "every other".
*/ */
for (ptr_statement= query_statements, x= 0; for (ptr_statement= query_statements, x= 0;
x < 4; x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next) x++, ptr_statement= ptr_statement->next)
{ {
if (coin) if (coin)
...@@ -851,7 +1284,7 @@ get_options(int *argc,char ***argv) ...@@ -851,7 +1284,7 @@ get_options(int *argc,char ***argv)
} }
else else
{ {
ptr_statement->next= build_query_string(); ptr_statement->next= build_select_string(TRUE);
coin= 1; coin= 1;
} }
} }
...@@ -873,12 +1306,13 @@ get_options(int *argc,char ***argv) ...@@ -873,12 +1306,13 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open create file\n", my_progname); fprintf(stderr,"%s: Could not open create file\n", my_progname);
exit(1); exit(1);
} }
tmp_string= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME)); tmp_string= (char *)my_malloc(sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
my_read(data_file, tmp_string, sbuf.st_size, MYF(0)); my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0'; tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0)); my_close(data_file,MYF(0));
parse_delimiter(tmp_string, &create_statements, delimiter[0]); parse_delimiter(tmp_string, &create_statements, delimiter[0]);
my_free(tmp_string, MYF(0)); my_free((gptr)tmp_string, MYF(0));
} }
else if (create_string) else if (create_string)
{ {
...@@ -899,14 +1333,15 @@ get_options(int *argc,char ***argv) ...@@ -899,14 +1333,15 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname); fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
exit(1); exit(1);
} }
tmp_string= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME)); tmp_string= (char *)my_malloc(sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
my_read(data_file, tmp_string, sbuf.st_size, MYF(0)); my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0'; tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0)); my_close(data_file,MYF(0));
if (user_supplied_query) if (user_supplied_query)
actual_queries= parse_delimiter(tmp_string, &query_statements, actual_queries= parse_delimiter(tmp_string, &query_statements,
delimiter[0]); delimiter[0]);
my_free(tmp_string, MYF(0)); my_free((gptr)tmp_string, MYF(0));
} }
else if (user_supplied_query) else if (user_supplied_query)
{ {
...@@ -915,8 +1350,71 @@ get_options(int *argc,char ***argv) ...@@ -915,8 +1350,71 @@ get_options(int *argc,char ***argv)
} }
} }
if (user_supplied_pre_statements && my_stat(user_supplied_pre_statements, &sbuf, MYF(0)))
{
File data_file;
if (!MY_S_ISREG(sbuf.st_mode))
{
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
my_progname);
exit(1);
}
if ((data_file= my_open(user_supplied_pre_statements, O_RDWR, MYF(0))) == -1)
{
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
exit(1);
}
tmp_string= (char *)my_malloc(sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
if (user_supplied_pre_statements)
actual_queries= parse_delimiter(tmp_string, &pre_statements,
delimiter[0]);
my_free((gptr)tmp_string, MYF(0));
}
else if (user_supplied_pre_statements)
{
actual_queries= parse_delimiter(user_supplied_pre_statements, &pre_statements,
delimiter[0]);
}
if (user_supplied_post_statements && my_stat(user_supplied_post_statements, &sbuf, MYF(0)))
{
File data_file;
if (!MY_S_ISREG(sbuf.st_mode))
{
fprintf(stderr,"%s: User query supplied file was not a regular file\n",
my_progname);
exit(1);
}
if ((data_file= my_open(user_supplied_post_statements, O_RDWR, MYF(0))) == -1)
{
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
exit(1);
}
tmp_string= (char *)my_malloc(sbuf.st_size + 1,
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
if (user_supplied_post_statements)
parse_delimiter(tmp_string, &post_statements,
delimiter[0]);
my_free((gptr)tmp_string, MYF(0));
}
else if (user_supplied_post_statements)
{
parse_delimiter(user_supplied_post_statements, &post_statements,
delimiter[0]);
}
if (verbose >= 2)
printf("Parsing engines to use.\n");
if (default_engine) if (default_engine)
parse_delimiter(default_engine, &engine_statements, ','); parse_option(default_engine, &engine_options, ',');
if (tty_password) if (tty_password)
opt_password= get_tty_password(NullS); opt_password= get_tty_password(NullS);
...@@ -932,24 +1430,99 @@ static int run_query(MYSQL *mysql, const char *query, int len) ...@@ -932,24 +1430,99 @@ static int run_query(MYSQL *mysql, const char *query, int len)
return 0; return 0;
} }
if (verbose >= 2) if (verbose >= 3)
printf("%.*s;\n", len, query); printf("%.*s;\n", len, query);
return mysql_real_query(mysql, query, len); return mysql_real_query(mysql, query, len);
} }
static int
generate_primary_key_list(MYSQL *mysql, option_string *engine_stmt)
{
MYSQL_RES *result;
MYSQL_ROW row;
unsigned long long counter;
DBUG_ENTER("generate_primary_key_list");
/*
Blackhole is a special case, this allows us to test the upper end
of the server during load runs.
*/
if (opt_only_print || (engine_stmt &&
strstr(engine_stmt->string, "blackhole")))
{
primary_keys_number_of= 1;
primary_keys= (char **)my_malloc((uint)(sizeof(char *) *
primary_keys_number_of),
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
/* Yes, we strdup a const string to simplify the interface */
primary_keys[0]= my_strdup("796c4422-1d94-102a-9d6d-00e0812d", MYF(0));
}
else
{
if (run_query(mysql, "SELECT id from t1", strlen("SELECT id from t1")))
{
fprintf(stderr,"%s: Cannot select GUID primary keys. (%s)\n", my_progname,
mysql_error(mysql));
exit(1);
}
result= mysql_store_result(mysql);
primary_keys_number_of= mysql_num_rows(result);
/* So why check this? Blackhole :) */
if (primary_keys_number_of)
{
/*
We create the structure and loop and create the items.
*/
primary_keys= (char **)my_malloc((uint)(sizeof(char *) *
primary_keys_number_of),
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
row= mysql_fetch_row(result);
for (counter= 0; counter < primary_keys_number_of;
counter++, row= mysql_fetch_row(result))
primary_keys[counter]= my_strdup(row[0], MYF(0));
}
mysql_free_result(result);
}
DBUG_RETURN(0);
}
static int
drop_primary_key_list(void)
{
unsigned long long counter;
if (primary_keys_number_of)
{
for (counter= 0; counter < primary_keys_number_of; counter++)
my_free((gptr)primary_keys[counter], MYF(0));
my_free((gptr)primary_keys, MYF(0));
}
return 0;
}
static int static int
create_schema(MYSQL *mysql, const char *db, statement *stmt, create_schema(MYSQL *mysql, const char *db, statement *stmt,
statement *engine_stmt) option_string *engine_stmt)
{ {
char query[HUGE_STRING_LENGTH]; char query[HUGE_STRING_LENGTH];
statement *ptr; statement *ptr;
statement *after_create;
int len; int len;
ulonglong count;
DBUG_ENTER("create_schema"); DBUG_ENTER("create_schema");
len= snprintf(query, HUGE_STRING_LENGTH, "CREATE SCHEMA `%s`", db); len= snprintf(query, HUGE_STRING_LENGTH, "CREATE SCHEMA `%s`", db);
if (verbose >= 2)
printf("Loading Pre-data\n");
if (run_query(mysql, query, len)) if (run_query(mysql, query, len))
{ {
fprintf(stderr,"%s: Cannot create schema %s : %s\n", my_progname, db, fprintf(stderr,"%s: Cannot create schema %s : %s\n", my_progname, db,
...@@ -963,8 +1536,9 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt, ...@@ -963,8 +1536,9 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt,
} }
else else
{ {
if (verbose >= 2) if (verbose >= 3)
printf("%s;\n", query); printf("%s;\n", query);
if (mysql_select_db(mysql, db)) if (mysql_select_db(mysql, db))
{ {
fprintf(stderr,"%s: Cannot select schema '%s': %s\n",my_progname, db, fprintf(stderr,"%s: Cannot select schema '%s': %s\n",my_progname, db,
...@@ -985,16 +1559,46 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt, ...@@ -985,16 +1559,46 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt,
} }
} }
for (ptr= stmt; ptr && ptr->length; ptr= ptr->next) count= 0;
after_create= stmt;
limit_not_met:
for (ptr= after_create; ptr && ptr->length; ptr= ptr->next, count++)
{ {
if (run_query(mysql, ptr->string, ptr->length)) if (auto_generate_sql && ( auto_generate_sql_number == count))
break;
if (engine_stmt && engine_stmt->option && ptr->type == CREATE_TABLE_TYPE)
{ {
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n", char buffer[HUGE_STRING_LENGTH];
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
exit(1); snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->string,
engine_stmt->option);
if (run_query(mysql, buffer, strlen(buffer)))
{
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
exit(1);
}
}
else
{
if (run_query(mysql, ptr->string, ptr->length))
{
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
exit(1);
}
} }
} }
if (auto_generate_sql && (auto_generate_sql_number > count ))
{
/* Special case for auto create, we don't want to create tables twice */
after_create= stmt->next;
goto limit_not_met;
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1018,137 +1622,85 @@ drop_schema(MYSQL *mysql, const char *db) ...@@ -1018,137 +1622,85 @@ drop_schema(MYSQL *mysql, const char *db)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
static int
run_statements(MYSQL *mysql, statement *stmt)
{
statement *ptr;
DBUG_ENTER("run_statements");
for (ptr= stmt; ptr && ptr->length; ptr= ptr->next)
{
if (run_query(mysql, ptr->string, ptr->length))
{
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
exit(1);
}
}
DBUG_RETURN(0);
}
static int static int
run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit) run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
{ {
#ifndef __WIN__
uint x; uint x;
#endif
File lock_file;
struct timeval start_time, end_time; struct timeval start_time, end_time;
thread_context con; thread_context con;
pthread_t mainthread; /* Thread descriptor */
pthread_attr_t attr; /* Thread attributes */
DBUG_ENTER("run_scheduler"); DBUG_ENTER("run_scheduler");
con.stmt= stmts; con.stmt= stmts;
con.limit= limit; con.limit= limit;
con.thread= opt_use_threads ? 1 :0;
lock_file= my_open(lock_file_str, O_CREAT|O_WRONLY|O_TRUNC, MYF(0));
if (!opt_slave) pthread_attr_init(&attr);
if (my_lock(lock_file, F_WRLCK, 0, F_TO_EOF, MYF(0))) pthread_attr_setdetachstate(&attr,
{ PTHREAD_CREATE_DETACHED);
fprintf(stderr,"%s: Could not get lockfile\n",
my_progname);
exit(0);
}
#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&counter_mutex);
if (opt_use_threads) thread_counter= 0;
{
pthread_t mainthread; /* Thread descriptor */
pthread_attr_t attr; /* Thread attributes */
for (x= 0; x < concur; x++)
{
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_DETACHED);
/* now create the thread */ pthread_mutex_lock(&sleeper_mutex);
if (pthread_create(&mainthread, &attr, (void *)run_task, master_wakeup= 1;
(void *)&con) != 0) pthread_mutex_unlock(&sleeper_mutex);
{ for (x= 0; x < concur; x++)
fprintf(stderr,"%s: Could not create thread\n",
my_progname);
exit(0);
}
}
}
#endif
#if !(defined(__WIN__) || defined(__NETWARE__))
#ifdef HAVE_LIBPTHREAD
else
#endif
{ {
fflush(NULL); /* now you create the thread */
for (x= 0; x < concur; x++) if (pthread_create(&mainthread, &attr, run_task,
(void *)&con) != 0)
{ {
int pid; fprintf(stderr,"%s: Could not create thread\n",
DBUG_PRINT("info", ("x: %d concurrency: %u", x, *concurrency)); my_progname);
pid= fork(); exit(0);
switch(pid)
{
case 0:
/* child */
DBUG_PRINT("info", ("fork returned 0, calling task(\"%s\"), pid %d gid %d",
stmts ? stmts->string : "", pid, getgid()));
if (verbose >= 2)
fprintf(stderr,
"%s: fork returned 0, calling task pid %d gid %d\n",
my_progname, pid, getgid());
run_task(&con);
exit(0);
break;
case -1:
/* error */
DBUG_PRINT("info",
("fork returned -1, failing pid %d gid %d", pid, getgid()));
fprintf(stderr,
"%s: Failed on fork: -1, max procs per parent exceeded.\n",
my_progname);
/*exit(1);*/
goto WAIT;
default:
/* parent, forked */
DBUG_PRINT("info", ("default, break: pid %d gid %d", pid, getgid()));
if (verbose >= 2)
fprintf(stderr,"%s: fork returned %d, gid %d\n",
my_progname, pid, getgid());
break;
}
} }
thread_counter++;
} }
#endif pthread_mutex_unlock(&counter_mutex);
pthread_attr_destroy(&attr);
/* Lets release use some clients! */ pthread_mutex_lock(&sleeper_mutex);
if (!opt_slave) master_wakeup= 0;
my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0)); pthread_mutex_unlock(&sleeper_mutex);
pthread_cond_broadcast(&sleep_threshhold);
gettimeofday(&start_time, NULL); gettimeofday(&start_time, NULL);
/* /*
We look to grab a write lock at this point. Once we get it we know that We loop until we know that all children have cleaned up.
all clients have completed their work.
*/ */
if (opt_use_threads) pthread_mutex_lock(&counter_mutex);
while (thread_counter)
{ {
if (my_lock(lock_file, F_WRLCK, 0, F_TO_EOF, MYF(0))) struct timespec abstime;
{
fprintf(stderr,"%s: Could not get lockfile\n", set_timespec(abstime, 3);
my_progname); pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
exit(0);
}
my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
}
#ifndef __WIN__
else
{
WAIT:
while (x--)
{
int status, pid;
pid= wait(&status);
DBUG_PRINT("info", ("Parent: child %d status %d", pid, status));
if (status != 0)
printf("%s: Child %d died with the status %d\n",
my_progname, pid, status);
}
} }
#endif pthread_mutex_unlock(&counter_mutex);
gettimeofday(&end_time, NULL); gettimeofday(&end_time, NULL);
my_close(lock_file, MYF(0));
sptr->timing= timedif(end_time, start_time); sptr->timing= timedif(end_time, start_time);
sptr->users= concur; sptr->users= concur;
...@@ -1158,28 +1710,41 @@ WAIT: ...@@ -1158,28 +1710,41 @@ WAIT:
} }
int pthread_handler_t run_task(void *p)
run_task(thread_context *con)
{ {
ulonglong counter= 0, queries; ulonglong counter= 0, queries;
File lock_file= -1;
MYSQL *mysql; MYSQL *mysql;
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_ROW row; MYSQL_ROW row;
statement *ptr; statement *ptr;
thread_context *con= (thread_context *)p;
DBUG_ENTER("run_task"); DBUG_ENTER("run_task");
DBUG_PRINT("info", ("task script \"%s\"", con->stmt ? con->stmt->string : "")); DBUG_PRINT("info", ("task script \"%s\"", con->stmt ? con->stmt->string : ""));
pthread_mutex_lock(&sleeper_mutex);
while (master_wakeup)
{
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
}
pthread_mutex_unlock(&sleeper_mutex);
if (!(mysql= mysql_init(NULL))) if (!(mysql= mysql_init(NULL)))
goto end; {
fprintf(stderr,"%s: mysql_init() failed ERROR : %s\n",
my_progname, mysql_error(mysql));
exit(0);
}
if (con->thread && mysql_thread_init()) if (mysql_thread_init())
goto end; {
fprintf(stderr,"%s: mysql_thread_init() failed ERROR : %s\n",
my_progname, mysql_error(mysql));
exit(0);
}
DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user)); 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 (!opt_only_print)
{ {
/* Connect to server */ /* Connect to server */
...@@ -1208,18 +1773,59 @@ run_task(thread_context *con) ...@@ -1208,18 +1773,59 @@ run_task(thread_context *con)
} }
DBUG_PRINT("info", ("connected.")); DBUG_PRINT("info", ("connected."));
if (verbose >= 3) if (verbose >= 3)
fprintf(stderr, "connected!\n"); printf("connected!\n");
queries= 0; queries= 0;
limit_not_met: limit_not_met:
for (ptr= con->stmt; ptr && ptr->length; ptr= ptr->next) for (ptr= con->stmt; ptr && ptr->length; ptr= ptr->next)
{ {
if (run_query(mysql, ptr->string, ptr->length)) /*
We have to execute differently based on query type. This should become a function.
*/
if ((ptr->type == UPDATE_TYPE_REQUIRES_PREFIX) ||
(ptr->type == SELECT_TYPE_REQUIRES_PREFIX))
{ {
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n", int length;
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql)); unsigned int key_val;
goto end; char *key;
char buffer[HUGE_STRING_LENGTH];
/*
This should only happen if some sort of new engine was
implemented that didn't properly handle UPDATEs.
Just in case someone runs this under an experimental engine we don't
want a crash so the if() is placed here.
*/
DBUG_ASSERT(primary_keys_number_of);
if (primary_keys_number_of)
{
key_val= (unsigned int)(random() % primary_keys_number_of);
key= primary_keys[key_val];
DBUG_ASSERT(key);
length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
(int)ptr->length, ptr->string, key);
if (run_query(mysql, buffer, length))
{
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
my_progname, (uint)length, buffer, mysql_error(mysql));
exit(0);
}
}
} }
else
{
if (run_query(mysql, ptr->string, ptr->length))
{
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
exit(0);
}
}
if (mysql_field_count(mysql)) if (mysql_field_count(mysql))
{ {
result= mysql_store_result(mysql); result= mysql_store_result(mysql);
...@@ -1238,20 +1844,97 @@ limit_not_met: ...@@ -1238,20 +1844,97 @@ limit_not_met:
end: end:
if (lock_file != -1)
{
my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
my_close(lock_file, MYF(0));
}
if (!opt_only_print) if (!opt_only_print)
mysql_close(mysql); mysql_close(mysql);
if (con->thread) my_thread_end();
my_thread_end();
pthread_mutex_lock(&counter_mutex);
thread_counter--;
pthread_cond_signal(&count_threshhold);
pthread_mutex_unlock(&counter_mutex);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
uint
parse_option(const char *origin, option_string **stmt, char delm)
{
char *retstr;
char *ptr= (char *)origin;
option_string **sptr= stmt;
option_string *tmp;
uint length= strlen(origin);
uint count= 0; /* We know that there is always one */
for (tmp= *sptr= (option_string *)my_malloc(sizeof(option_string),
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
(retstr= strchr(ptr, delm));
tmp->next= (option_string *)my_malloc(sizeof(option_string),
MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
tmp= tmp->next)
{
char buffer[HUGE_STRING_LENGTH];
char *buffer_ptr;
count++;
strncpy(buffer, ptr, (size_t)(retstr - ptr));
if ((buffer_ptr= strchr(buffer, ':')))
{
char *option_ptr;
tmp->length= (size_t)(buffer_ptr - buffer);
tmp->string= my_strndup(ptr, (uint)tmp->length, MYF(MY_FAE));
option_ptr= ptr + 1 + tmp->length;
/* Move past the : and the first string */
tmp->option_length= (size_t)(retstr - option_ptr);
tmp->option= my_strndup(option_ptr, (uint)tmp->option_length,
MYF(MY_FAE));
}
else
{
tmp->string= my_strndup(ptr, (size_t)(retstr - ptr), MYF(MY_FAE));
tmp->length= (size_t)(retstr - ptr);
}
ptr+= retstr - ptr + 1;
if (isspace(*ptr))
ptr++;
count++;
}
if (ptr != origin+length)
{
char *origin_ptr;
if ((origin_ptr= strchr(ptr, ':')))
{
char *option_ptr;
tmp->length= (size_t)(origin_ptr - ptr);
tmp->string= my_strndup(origin, tmp->length, MYF(MY_FAE));
option_ptr= (char *)ptr + 1 + tmp->length;
/* Move past the : and the first string */
tmp->option_length= (size_t)((ptr + length) - option_ptr);
tmp->option= my_strndup(option_ptr, tmp->option_length,
MYF(MY_FAE));
}
else
{
tmp->length= (size_t)((ptr + length) - ptr);
tmp->string= my_strndup(ptr, tmp->length, MYF(MY_FAE));
}
count++;
}
return count;
}
uint uint
parse_delimiter(const char *script, statement **stmt, char delm) parse_delimiter(const char *script, statement **stmt, char delm)
...@@ -1263,13 +1946,15 @@ parse_delimiter(const char *script, statement **stmt, char delm) ...@@ -1263,13 +1946,15 @@ parse_delimiter(const char *script, statement **stmt, char delm)
uint length= strlen(script); uint length= strlen(script);
uint count= 0; /* We know that there is always one */ uint count= 0; /* We know that there is always one */
for (tmp= *sptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL)); for (tmp= *sptr= (statement *)my_malloc(sizeof(statement),
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
(retstr= strchr(ptr, delm)); (retstr= strchr(ptr, delm));
tmp->next= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL)), tmp->next= (statement *)my_malloc(sizeof(statement),
MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
tmp= tmp->next) tmp= tmp->next)
{ {
count++; count++;
tmp->string= my_strndup(ptr, (size_t)(retstr - ptr), MYF(MY_FAE)); tmp->string= my_strndup(ptr, (uint)(retstr - ptr), MYF(MY_FAE));
tmp->length= (size_t)(retstr - ptr); tmp->length= (size_t)(retstr - ptr);
ptr+= retstr - ptr + 1; ptr+= retstr - ptr + 1;
if (isspace(*ptr)) if (isspace(*ptr))
...@@ -1279,7 +1964,7 @@ parse_delimiter(const char *script, statement **stmt, char delm) ...@@ -1279,7 +1964,7 @@ parse_delimiter(const char *script, statement **stmt, char delm)
if (ptr != script+length) if (ptr != script+length)
{ {
tmp->string= my_strndup(ptr, (size_t)((script + length) - ptr), tmp->string= my_strndup(ptr, (uint)((script + length) - ptr),
MYF(MY_FAE)); MYF(MY_FAE));
tmp->length= (size_t)((script + length) - ptr); tmp->length= (size_t)((script + length) - ptr);
count++; count++;
...@@ -1301,7 +1986,8 @@ parse_comma(const char *string, uint **range) ...@@ -1301,7 +1986,8 @@ parse_comma(const char *string, uint **range)
if (*ptr == ',') count++; if (*ptr == ',') count++;
/* One extra spot for the NULL */ /* One extra spot for the NULL */
nptr= *range= (uint *)my_malloc(sizeof(uint) * (count + 1), MYF(MY_ZEROFILL)); nptr= *range= (uint *)my_malloc(sizeof(uint) * (count + 1),
MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr= (char *)string; ptr= (char *)string;
x= 0; x= 0;
...@@ -1336,23 +2022,25 @@ void ...@@ -1336,23 +2022,25 @@ void
print_conclusions_csv(conclusions *con) print_conclusions_csv(conclusions *con)
{ {
char buffer[HUGE_STRING_LENGTH]; char buffer[HUGE_STRING_LENGTH];
const char *ptr= auto_generate_sql_type ? auto_generate_sql_type : "query";
snprintf(buffer, HUGE_STRING_LENGTH, snprintf(buffer, HUGE_STRING_LENGTH,
"%s,query,%ld.%03ld,%ld.%03ld,%ld.%03ld,%d,%llu\n", "%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%d,%llu\n",
con->engine ? con->engine : "", /* Storage engine we ran against */ con->engine ? con->engine : "", /* Storage engine we ran against */
ptr, /* Load type */
con->avg_timing / 1000, con->avg_timing % 1000, /* Time to load */ con->avg_timing / 1000, con->avg_timing % 1000, /* Time to load */
con->min_timing / 1000, con->min_timing % 1000, /* Min time */ con->min_timing / 1000, con->min_timing % 1000, /* Min time */
con->max_timing / 1000, con->max_timing % 1000, /* Max time */ con->max_timing / 1000, con->max_timing % 1000, /* Max time */
con->users, /* Children used */ con->users, /* Children used */
con->avg_rows /* Queries run */ con->avg_rows /* Queries run */
); );
my_write(csv_file, buffer, strlen(buffer), MYF(0)); my_write(csv_file, buffer, (uint)strlen(buffer), MYF(0));
} }
void void
generate_stats(conclusions *con, statement *eng, stats *sptr) generate_stats(conclusions *con, option_string *eng, stats *sptr)
{ {
stats *ptr; stats *ptr;
int x; unsigned int x;
con->min_timing= sptr->timing; con->min_timing= sptr->timing;
con->max_timing= sptr->timing; con->max_timing= sptr->timing;
...@@ -1381,6 +2069,24 @@ generate_stats(conclusions *con, statement *eng, stats *sptr) ...@@ -1381,6 +2069,24 @@ generate_stats(conclusions *con, statement *eng, stats *sptr)
con->engine= NULL; con->engine= NULL;
} }
void
option_cleanup(option_string *stmt)
{
option_string *ptr, *nptr;
if (!stmt)
return;
for (ptr= stmt; ptr; ptr= nptr)
{
nptr= ptr->next;
if (ptr->string)
my_free((gptr)ptr->string, MYF(0));
if (ptr->option)
my_free((gptr)ptr->option, MYF(0));
my_free((gptr)(byte *)ptr, MYF(0));
}
}
void void
statement_cleanup(statement *stmt) statement_cleanup(statement *stmt)
{ {
...@@ -1392,7 +2098,7 @@ statement_cleanup(statement *stmt) ...@@ -1392,7 +2098,7 @@ statement_cleanup(statement *stmt)
{ {
nptr= ptr->next; nptr= ptr->next;
if (ptr->string) if (ptr->string)
my_free(ptr->string, MYF(0)); my_free((gptr)ptr->string, MYF(0));
my_free((byte *)ptr, MYF(0)); my_free((gptr)(byte *)ptr, MYF(0));
} }
} }
...@@ -2296,12 +2296,18 @@ AC_ARG_WITH(man, ...@@ -2296,12 +2296,18 @@ AC_ARG_WITH(man,
[with_man=yes] [with_man=yes]
) )
if test "$with_man" = "yes" if test X"$with_man" = Xyes
then then
man_dirs="man" man_dirs="man"
man1_files=`ls -1 $srcdir/man/*.1 | sed -e 's;^.*man/;;'` if test X"$have_ndbcluster" = Xyes
then
man1_files=`ls $srcdir/man/*.1 | sed -e 's;^.*man/;;'`
man8_files=`ls $srcdir/man/*.8 | sed -e 's;^.*man/;;'`
else
man1_files=`ls $srcdir/man/*.1 | grep -v '/ndb' | sed -e 's;^.*man/;;'`
man8_files=`ls $srcdir/man/*.8 | grep -v '/ndb' | sed -e 's;^.*man/;;'`
fi
man1_files=`echo $man1_files` man1_files=`echo $man1_files`
man8_files=`ls -1 $srcdir/man/*.8 | sed -e 's;^.*man/;;'`
man8_files=`echo $man8_files` man8_files=`echo $man8_files`
else else
man_dirs="" man_dirs=""
......
...@@ -425,14 +425,8 @@ inline double ulonglong2double(ulonglong value) ...@@ -425,14 +425,8 @@ inline double ulonglong2double(ulonglong value)
#define shared_memory_buffer_length 16000 #define shared_memory_buffer_length 16000
#define default_shared_memory_base_name "MYSQL" #define default_shared_memory_base_name "MYSQL"
#ifdef CYBOZU
#define MYSQL_DEFAULT_CHARSET_NAME "utf8"
#define MYSQL_DEFAULT_COLLATION_NAME "utf8_general_cs"
#define HAVE_UTF8_GENERAL_CS 1
#else
#define MYSQL_DEFAULT_CHARSET_NAME "latin1" #define MYSQL_DEFAULT_CHARSET_NAME "latin1"
#define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci" #define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci"
#endif
#define HAVE_SPATIAL 1 #define HAVE_SPATIAL 1
#define HAVE_RTREE_KEYS 1 #define HAVE_RTREE_KEYS 1
...@@ -443,10 +437,8 @@ inline double ulonglong2double(ulonglong value) ...@@ -443,10 +437,8 @@ inline double ulonglong2double(ulonglong value)
/* Define charsets you want */ /* Define charsets you want */
/* #undef HAVE_CHARSET_armscii8 */ /* #undef HAVE_CHARSET_armscii8 */
/* #undef HAVE_CHARSET_ascii */ /* #undef HAVE_CHARSET_ascii */
#ifndef CYBOZU
#define HAVE_CHARSET_big5 1 #define HAVE_CHARSET_big5 1
#define HAVE_CHARSET_cp1250 1 #define HAVE_CHARSET_cp1250 1
#endif
/* #undef HAVE_CHARSET_cp1251 */ /* #undef HAVE_CHARSET_cp1251 */
/* #undef HAVE_CHARSET_cp1256 */ /* #undef HAVE_CHARSET_cp1256 */
/* #undef HAVE_CHARSET_cp1257 */ /* #undef HAVE_CHARSET_cp1257 */
...@@ -455,33 +447,27 @@ inline double ulonglong2double(ulonglong value) ...@@ -455,33 +447,27 @@ inline double ulonglong2double(ulonglong value)
/* #undef HAVE_CHARSET_cp866 */ /* #undef HAVE_CHARSET_cp866 */
#define HAVE_CHARSET_cp932 1 #define HAVE_CHARSET_cp932 1
/* #undef HAVE_CHARSET_dec8 */ /* #undef HAVE_CHARSET_dec8 */
#ifndef CYBOZU
#define HAVE_CHARSET_eucjpms 1 #define HAVE_CHARSET_eucjpms 1
#define HAVE_CHARSET_euckr 1 #define HAVE_CHARSET_euckr 1
#define HAVE_CHARSET_gb2312 1 #define HAVE_CHARSET_gb2312 1
#define HAVE_CHARSET_gbk 1 #define HAVE_CHARSET_gbk 1
#endif
/* #undef HAVE_CHARSET_greek */ /* #undef HAVE_CHARSET_greek */
/* #undef HAVE_CHARSET_hebrew */ /* #undef HAVE_CHARSET_hebrew */
/* #undef HAVE_CHARSET_hp8 */ /* #undef HAVE_CHARSET_hp8 */
/* #undef HAVE_CHARSET_keybcs2 */ /* #undef HAVE_CHARSET_keybcs2 */
/* #undef HAVE_CHARSET_koi8r */ /* #undef HAVE_CHARSET_koi8r */
/* #undef HAVE_CHARSET_koi8u */ /* #undef HAVE_CHARSET_koi8u */
#ifndef CYBOZU
#define HAVE_CHARSET_latin1 1 #define HAVE_CHARSET_latin1 1
#define HAVE_CHARSET_latin2 1 #define HAVE_CHARSET_latin2 1
#endif
/* #undef HAVE_CHARSET_latin5 */ /* #undef HAVE_CHARSET_latin5 */
/* #undef HAVE_CHARSET_latin7 */ /* #undef HAVE_CHARSET_latin7 */
/* #undef HAVE_CHARSET_macce */ /* #undef HAVE_CHARSET_macce */
/* #undef HAVE_CHARSET_macroman */ /* #undef HAVE_CHARSET_macroman */
#define HAVE_CHARSET_sjis 1 #define HAVE_CHARSET_sjis 1
/* #undef HAVE_CHARSET_swe7 */ /* #undef HAVE_CHARSET_swe7 */
#ifndef CYBOZU
#define HAVE_CHARSET_tis620 1 #define HAVE_CHARSET_tis620 1
#define HAVE_CHARSET_ucs2 1 #define HAVE_CHARSET_ucs2 1
#define HAVE_CHARSET_ujis 1 #define HAVE_CHARSET_ujis 1
#endif
#define HAVE_CHARSET_utf8 1 #define HAVE_CHARSET_utf8 1
#define HAVE_UCA_COLLATIONS 1 #define HAVE_UCA_COLLATIONS 1
...@@ -701,6 +701,15 @@ extern uint my_thread_end_wait_time; ...@@ -701,6 +701,15 @@ extern uint my_thread_end_wait_time;
Keep track of shutdown,signal, and main threads so that my_end() will not Keep track of shutdown,signal, and main threads so that my_end() will not
report errors with them report errors with them
*/ */
/* Which kind of thread library is in use */
#define THD_LIB_OTHER 1
#define THD_LIB_NPTL 2
#define THD_LIB_LT 4
extern uint thd_lib_detected;
/* statistics_xxx functions are for not essential statistic */ /* statistics_xxx functions are for not essential statistic */
#ifndef thread_safe_increment #ifndef thread_safe_increment
......
...@@ -24,11 +24,6 @@ extern "C" { ...@@ -24,11 +24,6 @@ extern "C" {
#ifndef USE_ALARM_THREAD #ifndef USE_ALARM_THREAD
#define USE_ONE_SIGNAL_HAND /* One must call process_alarm */ #define USE_ONE_SIGNAL_HAND /* One must call process_alarm */
#endif #endif
#ifdef HAVE_LINUXTHREADS
#define THR_CLIENT_ALARM SIGALRM
#else
#define THR_CLIENT_ALARM SIGUSR1
#endif
#ifdef HAVE_rts_threads #ifdef HAVE_rts_threads
#undef USE_ONE_SIGNAL_HAND #undef USE_ONE_SIGNAL_HAND
#define USE_ALARM_THREAD #define USE_ALARM_THREAD
...@@ -90,6 +85,9 @@ typedef struct st_alarm { ...@@ -90,6 +85,9 @@ typedef struct st_alarm {
my_bool malloced; my_bool malloced;
} ALARM; } ALARM;
extern uint thr_client_alarm;
extern pthread_t alarm_thread;
#define thr_alarm_init(A) (*(A))=0 #define thr_alarm_init(A) (*(A))=0
#define thr_alarm_in_use(A) (*(A)!= 0) #define thr_alarm_in_use(A) (*(A)!= 0)
void init_thr_alarm(uint max_alarm); void init_thr_alarm(uint max_alarm);
......
...@@ -1885,8 +1885,7 @@ sub environment_setup () { ...@@ -1885,8 +1885,7 @@ sub environment_setup () {
mtr_native_path($exe_mysqlslap) . mtr_native_path($exe_mysqlslap) .
" -uroot " . " -uroot " .
"--port=$master->[0]->{'port'} " . "--port=$master->[0]->{'port'} " .
"--socket=$master->[0]->{'path_sock'} --password= " . "--socket=$master->[0]->{'path_sock'} --password= ";
"--lock-directory=$opt_tmpdir";
if ( $opt_debug ) if ( $opt_debug )
{ {
......
...@@ -143,3 +143,27 @@ select * from t1; ...@@ -143,3 +143,27 @@ select * from t1;
select * from t2; select * from t2;
select * from t1; select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; 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');
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=`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');
SHOW TABLES;
select * from t1;
SHOW TABLES;
DROP SCHEMA IF EXISTS `mysqlslap`;
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --use-threads --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql
--exec $MYSQL_SLAP --only-print --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";" --exec $MYSQL_SLAP --only-print --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";"
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";" --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";"
...@@ -14,3 +14,25 @@ ...@@ -14,3 +14,25 @@
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --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')" --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --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')"
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --create-schema=test_env --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --create-schema=test_env
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --create-schema=test_env --auto-generate-sql-add-autoincrement
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-add-autoincrement
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=update
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=read
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=write
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=mixed
--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=update
--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=update --auto-generate-sql-execute-number=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
--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";
...@@ -61,7 +61,7 @@ fi ...@@ -61,7 +61,7 @@ fi
########################################################################### ###########################################################################
client_args="--silent --socket=$socket_path --connect_timeout=1 " client_args="--no-defaults --silent --socket=$socket_path --connect_timeout=1 "
[ -n "$username" ] && client_args="$client_args --user=$username " [ -n "$username" ] && client_args="$client_args --user=$username "
[ -n "$password" ] && client_args="$client_args --password=$password " [ -n "$password" ] && client_args="$client_args --password=$password "
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
uint thd_lib_detected= 0; uint thd_lib_detected= 0;
uint thd_lib_detected;
#ifndef my_pthread_setprio #ifndef my_pthread_setprio
void my_pthread_setprio(pthread_t thread_id,int prior) void my_pthread_setprio(pthread_t thread_id,int prior)
{ {
...@@ -51,8 +53,6 @@ int my_pthread_getprio(pthread_t thread_id) ...@@ -51,8 +53,6 @@ int my_pthread_getprio(pthread_t thread_id)
int policy; int policy;
if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param)) if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param))
{ {
DBUG_PRINT("thread",("policy: %d priority: %d",
policy,tmp_sched_param.sched_priority));
return tmp_sched_param.sched_priority; return tmp_sched_param.sched_priority;
} }
#endif #endif
...@@ -314,8 +314,6 @@ void sigwait_handle_sig(int sig) ...@@ -314,8 +314,6 @@ void sigwait_handle_sig(int sig)
pthread_mutex_unlock(&LOCK_sigwait); pthread_mutex_unlock(&LOCK_sigwait);
} }
extern pthread_t alarm_thread;
void *sigwait_thread(void *set_arg) void *sigwait_thread(void *set_arg)
{ {
sigset_t *set=(sigset_t*) set_arg; sigset_t *set=(sigset_t*) set_arg;
...@@ -334,7 +332,9 @@ void *sigwait_thread(void *set_arg) ...@@ -334,7 +332,9 @@ void *sigwait_thread(void *set_arg)
sigaction(i, &sact, (struct sigaction*) 0); sigaction(i, &sact, (struct sigaction*) 0);
} }
} }
sigaddset(set,THR_CLIENT_ALARM); /* Ensure that init_thr_alarm() is called */
DBUG_ASSERT(thr_client_alarm);
sigaddset(set, thr_client_alarm);
pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0);
alarm_thread=pthread_self(); /* For thr_alarm */ alarm_thread=pthread_self(); /* For thr_alarm */
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "mysys_priv.h" #include "mysys_priv.h"
#include <m_string.h> #include <m_string.h>
#include <signal.h>
#ifdef THREAD #ifdef THREAD
#ifdef USE_TLS #ifdef USE_TLS
...@@ -63,6 +64,8 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused))) ...@@ -63,6 +64,8 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
#endif #endif
static uint get_thread_lib(void);
/* /*
initialize thread environment initialize thread environment
...@@ -76,6 +79,8 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused))) ...@@ -76,6 +79,8 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
my_bool my_thread_global_init(void) my_bool my_thread_global_init(void)
{ {
thd_lib_detected= get_thread_lib();
if (pthread_key_create(&THR_KEY_mysys,0)) if (pthread_key_create(&THR_KEY_mysys,0))
{ {
fprintf(stderr,"Can't initialize threads: error %d\n",errno); fprintf(stderr,"Can't initialize threads: error %d\n",errno);
...@@ -395,4 +400,20 @@ const char *my_thread_name(void) ...@@ -395,4 +400,20 @@ const char *my_thread_name(void)
} }
#endif /* DBUG_OFF */ #endif /* DBUG_OFF */
static uint get_thread_lib(void)
{
#ifdef _CS_GNU_LIBPTHREAD_VERSION
char buff[64];
confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
if (!strncasecmp(buff, "NPTL", 4))
return THD_LIB_NPTL;
if (!strncasecmp(buff, "linuxthreads", 12))
return THD_LIB_LT;
#endif
return THD_LIB_OTHER;
}
#endif /* THREAD */ #endif /* THREAD */
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define ETIME ETIMEDOUT #define ETIME ETIMEDOUT
#endif #endif
uint thr_client_alarm;
static int alarm_aborted=1; /* No alarm thread */ static int alarm_aborted=1; /* No alarm thread */
my_bool thr_alarm_inited= 0; my_bool thr_alarm_inited= 0;
volatile my_bool alarm_thread_running= 0; volatile my_bool alarm_thread_running= 0;
...@@ -56,9 +57,7 @@ static void *alarm_handler(void *arg); ...@@ -56,9 +57,7 @@ static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) #define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM)
#endif #endif
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
static sig_handler thread_alarm(int sig __attribute__((unused))); static sig_handler thread_alarm(int sig __attribute__((unused)));
#endif
static int compare_ulong(void *not_used __attribute__((unused)), static int compare_ulong(void *not_used __attribute__((unused)),
byte *a_ptr,byte* b_ptr) byte *a_ptr,byte* b_ptr)
...@@ -77,9 +76,13 @@ void init_thr_alarm(uint max_alarms) ...@@ -77,9 +76,13 @@ void init_thr_alarm(uint max_alarms)
sigfillset(&full_signal_set); /* Neaded to block signals */ sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_alarm,NULL); pthread_cond_init(&COND_alarm,NULL);
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) thr_client_alarm= thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1;
my_sigset(THR_CLIENT_ALARM,thread_alarm); #ifndef USE_ALARM_THREAD
if (thd_lib_detected != THD_LIB_LT)
#endif #endif
{
my_sigset(thr_client_alarm, thread_alarm);
}
sigemptyset(&s); sigemptyset(&s);
sigaddset(&s, THR_SERVER_ALARM); sigaddset(&s, THR_SERVER_ALARM);
alarm_thread=pthread_self(); alarm_thread=pthread_self();
...@@ -97,10 +100,11 @@ void init_thr_alarm(uint max_alarms) ...@@ -97,10 +100,11 @@ void init_thr_alarm(uint max_alarms)
} }
#elif defined(USE_ONE_SIGNAL_HAND) #elif defined(USE_ONE_SIGNAL_HAND)
pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */
#if THR_SERVER_ALARM == THR_CLIENT_ALARM if (thd_lib_detected == THD_LIB_LT)
my_sigset(THR_CLIENT_ALARM,process_alarm); /* Linuxthreads */ {
pthread_sigmask(SIG_UNBLOCK, &s, NULL); my_sigset(thr_client_alarm, process_alarm); /* Linuxthreads */
#endif pthread_sigmask(SIG_UNBLOCK, &s, NULL);
}
#else #else
my_sigset(THR_SERVER_ALARM, process_alarm); my_sigset(THR_SERVER_ALARM, process_alarm);
pthread_sigmask(SIG_UNBLOCK, &s, NULL); pthread_sigmask(SIG_UNBLOCK, &s, NULL);
...@@ -152,7 +156,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) ...@@ -152,7 +156,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
now=(ulong) time((time_t*) 0); now=(ulong) time((time_t*) 0);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
if (alarm_aborted > 0) if (alarm_aborted > 0)
{ /* No signal thread */ { /* No signal thread */
DBUG_PRINT("info", ("alarm aborted")); DBUG_PRINT("info", ("alarm aborted"));
...@@ -273,18 +277,17 @@ sig_handler process_alarm(int sig __attribute__((unused))) ...@@ -273,18 +277,17 @@ sig_handler process_alarm(int sig __attribute__((unused)))
This must be first as we can't call DBUG inside an alarm for a normal thread This must be first as we can't call DBUG inside an alarm for a normal thread
*/ */
#if THR_SERVER_ALARM == THR_CLIENT_ALARM if (thd_lib_detected == THD_LIB_LT &&
if (!pthread_equal(pthread_self(),alarm_thread)) !pthread_equal(pthread_self(),alarm_thread))
{ {
#if defined(MAIN) && !defined(__bsdi__) #if defined(MAIN) && !defined(__bsdi__)
printf("thread_alarm in process_alarm\n"); fflush(stdout); printf("thread_alarm in process_alarm\n"); fflush(stdout);
#endif #endif
#ifdef DONT_REMEMBER_SIGNAL #ifdef DONT_REMEMBER_SIGNAL
my_sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */ my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */
#endif #endif
return; return;
} }
#endif
/* /*
We have to do do the handling of the alarm in a sub function, We have to do do the handling of the alarm in a sub function,
...@@ -328,7 +331,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) ...@@ -328,7 +331,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
alarm_data=(ALARM*) queue_element(&alarm_queue,i); alarm_data=(ALARM*) queue_element(&alarm_queue,i);
alarm_data->alarmed=1; /* Info to thread */ alarm_data->alarmed=1; /* Info to thread */
if (pthread_equal(alarm_data->thread,alarm_thread) || if (pthread_equal(alarm_data->thread,alarm_thread) ||
pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) pthread_kill(alarm_data->thread, thr_client_alarm))
{ {
#ifdef MAIN #ifdef MAIN
printf("Warning: pthread_kill couldn't find thread!!!\n"); printf("Warning: pthread_kill couldn't find thread!!!\n");
...@@ -352,7 +355,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) ...@@ -352,7 +355,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
alarm_data->alarmed=1; /* Info to thread */ alarm_data->alarmed=1; /* Info to thread */
DBUG_PRINT("info",("sending signal to waiting thread")); DBUG_PRINT("info",("sending signal to waiting thread"));
if (pthread_equal(alarm_data->thread,alarm_thread) || if (pthread_equal(alarm_data->thread,alarm_thread) ||
pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) pthread_kill(alarm_data->thread, thr_client_alarm))
{ {
#ifdef MAIN #ifdef MAIN
printf("Warning: pthread_kill couldn't find thread!!!\n"); printf("Warning: pthread_kill couldn't find thread!!!\n");
...@@ -488,7 +491,7 @@ void thr_alarm_info(ALARM_INFO *info) ...@@ -488,7 +491,7 @@ void thr_alarm_info(ALARM_INFO *info)
ARGSUSED ARGSUSED
*/ */
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
static sig_handler thread_alarm(int sig) static sig_handler thread_alarm(int sig)
{ {
#ifdef MAIN #ifdef MAIN
...@@ -498,7 +501,6 @@ static sig_handler thread_alarm(int sig) ...@@ -498,7 +501,6 @@ static sig_handler thread_alarm(int sig)
my_sigset(sig,thread_alarm); /* int. thread system calls */ my_sigset(sig,thread_alarm); /* int. thread system calls */
#endif #endif
} }
#endif
#ifdef HAVE_TIMESPEC_TS_SEC #ifdef HAVE_TIMESPEC_TS_SEC
...@@ -784,9 +786,7 @@ static void *signal_hand(void *arg __attribute__((unused))) ...@@ -784,9 +786,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
sigaddset(&set,SIGINT); sigaddset(&set,SIGINT);
sigaddset(&set,SIGQUIT); sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGTERM); sigaddset(&set,SIGTERM);
#if THR_CLIENT_ALARM != SIGHUP
sigaddset(&set,SIGHUP); sigaddset(&set,SIGHUP);
#endif
#ifdef SIGTSTP #ifdef SIGTSTP
sigaddset(&set,SIGTSTP); sigaddset(&set,SIGTSTP);
#endif #endif
...@@ -797,7 +797,7 @@ static void *signal_hand(void *arg __attribute__((unused))) ...@@ -797,7 +797,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
puts("Starting signal handling thread"); puts("Starting signal handling thread");
#endif #endif
printf("server alarm: %d thread alarm: %d\n", printf("server alarm: %d thread alarm: %d\n",
THR_SERVER_ALARM,THR_CLIENT_ALARM); THR_SERVER_ALARM, thr_client_alarm);
DBUG_PRINT("info",("Starting signal and alarm handling thread")); DBUG_PRINT("info",("Starting signal and alarm handling thread"));
for(;;) for(;;)
{ {
...@@ -865,11 +865,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) ...@@ -865,11 +865,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
sigaddset(&set,SIGTSTP); sigaddset(&set,SIGTSTP);
#endif #endif
sigaddset(&set,THR_SERVER_ALARM); sigaddset(&set,THR_SERVER_ALARM);
sigdelset(&set,THR_CLIENT_ALARM); sigdelset(&set, thr_client_alarm);
(void) pthread_sigmask(SIG_SETMASK,&set,NULL); (void) pthread_sigmask(SIG_SETMASK,&set,NULL);
#ifdef NOT_USED #ifdef NOT_USED
sigemptyset(&set); sigemptyset(&set);
sigaddset(&set,THR_CLIENT_ALARM); sigaddset(&set, thr_client_alarm);
VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0));
#endif #endif
......
...@@ -66,6 +66,7 @@ struct show_table_authors_st show_table_authors[]= { ...@@ -66,6 +66,7 @@ struct show_table_authors_st show_table_authors[]= {
"Parser, port to OS/2, storage engines and some random stuff" }, "Parser, port to OS/2, storage engines and some random stuff" },
{ "Yuri Dario", "", "OS/2 port" }, { "Yuri Dario", "", "OS/2 port" },
{ "Andrei Elkin", "Espoo, Finland", "Replication" }, { "Andrei Elkin", "Espoo, Finland", "Replication" },
{ "Patrick Galbraith", "Sharon, NH", "Federated Engine, mysqlslap" },
{ "Sergei Golubchik", "Kerpen, Germany", { "Sergei Golubchik", "Kerpen, Germany",
"Full-text search, precision math" }, "Full-text search, precision math" },
{ "Lenz Grimmer", "Hamburg, Germany", { "Lenz Grimmer", "Hamburg, Germany",
......
...@@ -195,12 +195,6 @@ inline void reset_floating_point_exceptions() ...@@ -195,12 +195,6 @@ inline void reset_floating_point_exceptions()
} /* cplusplus */ } /* cplusplus */
#if defined(HAVE_LINUXTHREADS)
#define THR_KILL_SIGNAL SIGINT
#else
#define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads
#endif
#define MYSQL_KILL_SIGNAL SIGTERM #define MYSQL_KILL_SIGNAL SIGTERM
#ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R #ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
...@@ -638,6 +632,7 @@ struct rand_struct sql_rand; // used by sql_class.cc:THD::THD() ...@@ -638,6 +632,7 @@ struct rand_struct sql_rand; // used by sql_class.cc:THD::THD()
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
struct passwd *user_info; struct passwd *user_info;
static pthread_t select_thread; static pthread_t select_thread;
static uint thr_kill_signal;
#endif #endif
/* OS specific variables */ /* OS specific variables */
...@@ -790,7 +785,7 @@ static void close_connections(void) ...@@ -790,7 +785,7 @@ static void close_connections(void)
DBUG_PRINT("info",("Waiting for select thread")); DBUG_PRINT("info",("Waiting for select thread"));
#ifndef DONT_USE_THR_ALARM #ifndef DONT_USE_THR_ALARM
if (pthread_kill(select_thread,THR_CLIENT_ALARM)) if (pthread_kill(select_thread, thr_client_alarm))
break; // allready dead break; // allready dead
#endif #endif
set_timespec(abstime, 2); set_timespec(abstime, 2);
...@@ -2296,7 +2291,9 @@ static void init_signals(void) ...@@ -2296,7 +2291,9 @@ static void init_signals(void)
DBUG_ENTER("init_signals"); DBUG_ENTER("init_signals");
if (test_flags & TEST_SIGINT) if (test_flags & TEST_SIGINT)
my_sigset(THR_KILL_SIGNAL,end_thread_signal); {
my_sigset(thr_kill_signal, end_thread_signal);
}
my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
...@@ -2351,10 +2348,13 @@ static void init_signals(void) ...@@ -2351,10 +2348,13 @@ static void init_signals(void)
#ifdef SIGTSTP #ifdef SIGTSTP
sigaddset(&set,SIGTSTP); sigaddset(&set,SIGTSTP);
#endif #endif
sigaddset(&set,THR_SERVER_ALARM); if (thd_lib_detected != THD_LIB_LT)
sigaddset(&set,THR_SERVER_ALARM);
if (test_flags & TEST_SIGINT) if (test_flags & TEST_SIGINT)
sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT {
sigdelset(&set,THR_CLIENT_ALARM); // For alarms // May be SIGINT
sigdelset(&set, thr_kill_signal);
}
sigprocmask(SIG_SETMASK,&set,NULL); sigprocmask(SIG_SETMASK,&set,NULL);
pthread_sigmask(SIG_SETMASK,&set,NULL); pthread_sigmask(SIG_SETMASK,&set,NULL);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -2417,23 +2417,19 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) ...@@ -2417,23 +2417,19 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
*/ */
init_thr_alarm(thread_scheduler.max_threads + init_thr_alarm(thread_scheduler.max_threads +
global_system_variables.max_insert_delayed_threads + 10); global_system_variables.max_insert_delayed_threads + 10);
#if SIGINT != THR_KILL_SIGNAL if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
if (test_flags & TEST_SIGINT)
{ {
(void) sigemptyset(&set); // Setup up SIGINT for debug (void) sigemptyset(&set); // Setup up SIGINT for debug
(void) sigaddset(&set,SIGINT); // For debugging (void) sigaddset(&set,SIGINT); // For debugging
(void) pthread_sigmask(SIG_UNBLOCK,&set,NULL); (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
} }
#endif
(void) sigemptyset(&set); // Setup up SIGINT for debug (void) sigemptyset(&set); // Setup up SIGINT for debug
#ifdef USE_ONE_SIGNAL_HAND #ifdef USE_ONE_SIGNAL_HAND
(void) sigaddset(&set,THR_SERVER_ALARM); // For alarms (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms
#endif #endif
#ifndef IGNORE_SIGHUP_SIGQUIT #ifndef IGNORE_SIGHUP_SIGQUIT
(void) sigaddset(&set,SIGQUIT); (void) sigaddset(&set,SIGQUIT);
#if THR_CLIENT_ALARM != SIGHUP
(void) sigaddset(&set,SIGHUP); (void) sigaddset(&set,SIGHUP);
#endif
#endif #endif
(void) sigaddset(&set,SIGTERM); (void) sigaddset(&set,SIGTERM);
(void) sigaddset(&set,SIGTSTP); (void) sigaddset(&set,SIGTSTP);
...@@ -3628,6 +3624,13 @@ int main(int argc, char **argv) ...@@ -3628,6 +3624,13 @@ int main(int argc, char **argv)
MY_INIT(argv[0]); // init my_sys library & pthreads MY_INIT(argv[0]); // init my_sys library & pthreads
/* nothing should come before this line ^^^ */ /* nothing should come before this line ^^^ */
/* Set signal used to kill MySQL */
#if defined(SIGUSR2)
thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
#else
thr_kill_signal= SIGINT;
#endif
/* /*
Perform basic logger initialization logger. Should be called after Perform basic logger initialization logger. Should be called after
MY_INIT, as it initializes mutexes. Log tables are inited later. MY_INIT, as it initializes mutexes. Log tables are inited later.
......
...@@ -53,21 +53,6 @@ void safe_print_str(const char* name, const char* val, int max_len) ...@@ -53,21 +53,6 @@ void safe_print_str(const char* name, const char* val, int max_len)
#define SIGRETURN_FRAME_OFFSET 23 #define SIGRETURN_FRAME_OFFSET 23
#endif #endif
static my_bool is_nptl;
/* Check if we are using NPTL or LinuxThreads on Linux */
void check_thread_lib(void)
{
char buf[5];
#ifdef _CS_GNU_LIBPTHREAD_VERSION
confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf));
is_nptl = !strncasecmp(buf, "NPTL", sizeof(buf));
#else
is_nptl = 0;
#endif
}
#if defined(__alpha__) && defined(__GNUC__) #if defined(__alpha__) && defined(__GNUC__)
/* /*
The only way to backtrace without a symbol table on alpha The only way to backtrace without a symbol table on alpha
...@@ -173,8 +158,8 @@ terribly wrong...\n"); ...@@ -173,8 +158,8 @@ terribly wrong...\n");
#endif /* __alpha__ */ #endif /* __alpha__ */
/* We are 1 frame above signal frame with NPTL and 2 frames above with LT */ /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
sigreturn_frame_count = is_nptl ? 1 : 2; sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
while (fp < (uchar**) stack_bottom) while (fp < (uchar**) stack_bottom)
{ {
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
......
...@@ -27,11 +27,9 @@ extern char* heap_start; ...@@ -27,11 +27,9 @@ extern char* heap_start;
#define init_stacktrace() do { \ #define init_stacktrace() do { \
heap_start = (char*) &__bss_start; \ heap_start = (char*) &__bss_start; \
check_thread_lib(); \
} while(0); } while(0);
void print_stacktrace(gptr stack_bottom, ulong thread_stack); void print_stacktrace(gptr stack_bottom, ulong thread_stack);
void safe_print_str(const char* name, const char* val, int max_len); void safe_print_str(const char* name, const char* val, int max_len);
void check_thread_lib(void);
#endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */
#endif /* TARGET_OS_LINUX */ #endif /* TARGET_OS_LINUX */
......
...@@ -217,14 +217,13 @@ int main(int argc, char *argv[]) ...@@ -217,14 +217,13 @@ int main(int argc, char *argv[])
azclose(&writer_handle); azclose(&writer_handle);
azclose(&reader_handle); azclose(&reader_handle);
exit(0);
unlink(TEST_FILENAME); unlink(TEST_FILENAME);
/* Start size tests */ /* Start size tests */
printf("About to run 2/4/8 gig tests now, you may want to hit CTRL-C\n"); printf("About to run 2/4/8 gig tests now, you may want to hit CTRL-C\n");
size_test(TWOGIG, 2097152L); size_test(TWOGIG, 2088992L);
size_test(FOURGIG, 4194304L); size_test(FOURGIG, 4177984L);
size_test(EIGHTGIG, 8388608L); size_test(EIGHTGIG, 8355968L);
return 0; return 0;
} }
...@@ -234,6 +233,7 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for) ...@@ -234,6 +233,7 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for)
azio_stream writer_handle, reader_handle; azio_stream writer_handle, reader_handle;
unsigned long long write_length; unsigned long long write_length;
unsigned long long read_length= 0; unsigned long long read_length= 0;
unsigned long long count;
unsigned int ret; unsigned int ret;
char buffer[BUFFER_LEN]; char buffer[BUFFER_LEN];
int error; int error;
...@@ -244,8 +244,10 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for) ...@@ -244,8 +244,10 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for)
return 0; return 0;
} }
for (write_length= 0; write_length < length ; write_length+= ret) for (count= 0, write_length= 0; write_length < length ;
write_length+= ret)
{ {
count++;
ret= azwrite(&writer_handle, test_string, BUFFER_LEN); ret= azwrite(&writer_handle, test_string, BUFFER_LEN);
if (ret != BUFFER_LEN) if (ret != BUFFER_LEN)
{ {
...@@ -257,7 +259,7 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for) ...@@ -257,7 +259,7 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for)
azflush(&writer_handle, Z_SYNC_FLUSH); azflush(&writer_handle, Z_SYNC_FLUSH);
} }
} }
assert(write_length == length); assert(write_length != count * BUFFER_LEN); /* Number of rows time BUFFER_LEN */
azflush(&writer_handle, Z_SYNC_FLUSH); azflush(&writer_handle, Z_SYNC_FLUSH);
printf("Reading back data\n"); printf("Reading back data\n");
...@@ -279,7 +281,7 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for) ...@@ -279,7 +281,7 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for)
} }
} }
assert(read_length == length); assert(read_length == write_length);
assert(writer_handle.rows == rows_to_test_for); assert(writer_handle.rows == rows_to_test_for);
azclose(&writer_handle); azclose(&writer_handle);
azclose(&reader_handle); azclose(&reader_handle);
......
...@@ -55,8 +55,8 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd) ...@@ -55,8 +55,8 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd)
s->stream.zalloc = (alloc_func)0; s->stream.zalloc = (alloc_func)0;
s->stream.zfree = (free_func)0; s->stream.zfree = (free_func)0;
s->stream.opaque = (voidpf)0; s->stream.opaque = (voidpf)0;
memset(s->inbuf, 0, AZ_BUFSIZE); memset(s->inbuf, 0, AZ_BUFSIZE_READ);
memset(s->outbuf, 0, AZ_BUFSIZE); memset(s->outbuf, 0, AZ_BUFSIZE_WRITE);
s->stream.next_in = s->inbuf; s->stream.next_in = s->inbuf;
s->stream.next_out = s->outbuf; s->stream.next_out = s->outbuf;
s->stream.avail_in = s->stream.avail_out = 0; s->stream.avail_in = s->stream.avail_out = 0;
...@@ -109,7 +109,7 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd) ...@@ -109,7 +109,7 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd)
return Z_NULL; return Z_NULL;
} }
} }
s->stream.avail_out = AZ_BUFSIZE; s->stream.avail_out = AZ_BUFSIZE_WRITE;
errno = 0; errno = 0;
s->file = fd < 0 ? my_open(path, Flags, MYF(0)) : fd; s->file = fd < 0 ? my_open(path, Flags, MYF(0)) : fd;
...@@ -159,7 +159,7 @@ void write_header(azio_stream *s) ...@@ -159,7 +159,7 @@ void write_header(azio_stream *s)
char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE]; char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
char *ptr= buffer; char *ptr= buffer;
s->block_size= AZ_BUFSIZE; s->block_size= AZ_BUFSIZE_WRITE;
s->version = (unsigned char)az_magic[1]; s->version = (unsigned char)az_magic[1];
s->minor_version = (unsigned char)az_magic[2]; s->minor_version = (unsigned char)az_magic[2];
...@@ -224,7 +224,7 @@ int get_byte(s) ...@@ -224,7 +224,7 @@ int get_byte(s)
if (s->stream.avail_in == 0) if (s->stream.avail_in == 0)
{ {
errno = 0; errno = 0;
s->stream.avail_in = my_read(s->file, (byte *)s->inbuf, AZ_BUFSIZE, MYF(0)); s->stream.avail_in = my_read(s->file, (byte *)s->inbuf, AZ_BUFSIZE_READ, MYF(0));
if (s->stream.avail_in == 0) if (s->stream.avail_in == 0)
{ {
s->z_eof = 1; s->z_eof = 1;
...@@ -260,7 +260,7 @@ void check_header(azio_stream *s) ...@@ -260,7 +260,7 @@ void check_header(azio_stream *s)
if (len < 2) { if (len < 2) {
if (len) s->inbuf[0] = s->stream.next_in[0]; if (len) s->inbuf[0] = s->stream.next_in[0];
errno = 0; errno = 0;
len = (uInt)my_read(s->file, (byte *)s->inbuf + len, AZ_BUFSIZE >> len, MYF(0)); len = (uInt)my_read(s->file, (byte *)s->inbuf + len, AZ_BUFSIZE_READ >> len, MYF(0));
if (len == 0) s->z_err = Z_ERRNO; if (len == 0) s->z_err = Z_ERRNO;
s->stream.avail_in += len; s->stream.avail_in += len;
s->stream.next_in = s->inbuf; s->stream.next_in = s->inbuf;
...@@ -455,7 +455,7 @@ unsigned int ZEXPORT azread ( azio_stream *s, voidp buf, unsigned int len, int * ...@@ -455,7 +455,7 @@ unsigned int ZEXPORT azread ( azio_stream *s, voidp buf, unsigned int len, int *
if (s->stream.avail_in == 0 && !s->z_eof) { if (s->stream.avail_in == 0 && !s->z_eof) {
errno = 0; errno = 0;
s->stream.avail_in = (uInt)my_read(s->file, (byte *)s->inbuf, AZ_BUFSIZE, MYF(0)); s->stream.avail_in = (uInt)my_read(s->file, (byte *)s->inbuf, AZ_BUFSIZE_READ, MYF(0));
if (s->stream.avail_in == 0) if (s->stream.avail_in == 0)
{ {
s->z_eof = 1; s->z_eof = 1;
...@@ -522,12 +522,13 @@ unsigned int azwrite (azio_stream *s, voidpc buf, unsigned int len) ...@@ -522,12 +522,13 @@ unsigned int azwrite (azio_stream *s, voidpc buf, unsigned int len)
{ {
s->stream.next_out = s->outbuf; s->stream.next_out = s->outbuf;
if (my_write(s->file, (byte *)s->outbuf, AZ_BUFSIZE, MYF(0)) != AZ_BUFSIZE) if (my_write(s->file, (byte *)s->outbuf, AZ_BUFSIZE_WRITE,
MYF(0)) != AZ_BUFSIZE_WRITE)
{ {
s->z_err = Z_ERRNO; s->z_err = Z_ERRNO;
break; break;
} }
s->stream.avail_out = AZ_BUFSIZE; s->stream.avail_out = AZ_BUFSIZE_WRITE;
} }
s->in += s->stream.avail_in; s->in += s->stream.avail_in;
s->out += s->stream.avail_out; s->out += s->stream.avail_out;
...@@ -563,7 +564,7 @@ int do_flush (azio_stream *s, int flush) ...@@ -563,7 +564,7 @@ int do_flush (azio_stream *s, int flush)
for (;;) for (;;)
{ {
len = AZ_BUFSIZE - s->stream.avail_out; len = AZ_BUFSIZE_WRITE - s->stream.avail_out;
if (len != 0) if (len != 0)
{ {
...@@ -574,7 +575,7 @@ int do_flush (azio_stream *s, int flush) ...@@ -574,7 +575,7 @@ int do_flush (azio_stream *s, int flush)
return Z_ERRNO; return Z_ERRNO;
} }
s->stream.next_out = s->outbuf; s->stream.next_out = s->outbuf;
s->stream.avail_out = AZ_BUFSIZE; s->stream.avail_out = AZ_BUFSIZE_WRITE;
} }
if (done) break; if (done) break;
s->out += s->stream.avail_out; s->out += s->stream.avail_out;
...@@ -675,8 +676,8 @@ my_off_t azseek (s, offset, whence) ...@@ -675,8 +676,8 @@ my_off_t azseek (s, offset, whence)
/* There was a zmemzero here if inbuf was null -Brian */ /* There was a zmemzero here if inbuf was null -Brian */
while (offset > 0) while (offset > 0)
{ {
uInt size = AZ_BUFSIZE; uInt size = AZ_BUFSIZE_WRITE;
if (offset < AZ_BUFSIZE) size = (uInt)offset; if (offset < AZ_BUFSIZE_WRITE) size = (uInt)offset;
size = azwrite(s, s->inbuf, size); size = azwrite(s, s->inbuf, size);
if (size == 0) return -1L; if (size == 0) return -1L;
...@@ -719,8 +720,8 @@ my_off_t azseek (s, offset, whence) ...@@ -719,8 +720,8 @@ my_off_t azseek (s, offset, whence)
} }
while (offset > 0) { while (offset > 0) {
int error; int error;
unsigned int size = AZ_BUFSIZE; unsigned int size = AZ_BUFSIZE_READ;
if (offset < AZ_BUFSIZE) size = (int)offset; if (offset < AZ_BUFSIZE_READ) size = (int)offset;
size = azread(s, s->outbuf, size, &error); size = azread(s, s->outbuf, size, &error);
if (error <= 0) return -1L; if (error <= 0) return -1L;
......
...@@ -196,7 +196,8 @@ extern "C" { ...@@ -196,7 +196,8 @@ extern "C" {
/* The deflate compression method (the only one supported in this version) */ /* The deflate compression method (the only one supported in this version) */
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
#define AZ_BUFSIZE 16384 #define AZ_BUFSIZE_READ 32768
#define AZ_BUFSIZE_WRITE 16384
typedef struct azio_stream { typedef struct azio_stream {
...@@ -204,8 +205,8 @@ typedef struct azio_stream { ...@@ -204,8 +205,8 @@ typedef struct azio_stream {
int z_err; /* error code for last stream operation */ int z_err; /* error code for last stream operation */
int z_eof; /* set if end of input file */ int z_eof; /* set if end of input file */
File file; /* .gz file */ File file; /* .gz file */
Byte inbuf[AZ_BUFSIZE]; /* input buffer */ Byte inbuf[AZ_BUFSIZE_READ]; /* input buffer */
Byte outbuf[AZ_BUFSIZE]; /* output buffer */ Byte outbuf[AZ_BUFSIZE_WRITE]; /* output buffer */
uLong crc; /* crc32 of uncompressed data */ uLong crc; /* crc32 of uncompressed data */
char *msg; /* error message */ char *msg; /* error message */
int transparent; /* 1 if input file is not a .gz file */ int transparent; /* 1 if input file is not a .gz file */
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
TODO: TODO:
Allow users to set compression level. Allow users to set compression level.
Allow adjustable block size.
Implement versioning, should be easy. Implement versioning, should be easy.
Allow for errors, find a way to mark bad rows. Allow for errors, find a way to mark bad rows.
Add optional feature so that rows can be flushed at interval (which will cause less Add optional feature so that rows can be flushed at interval (which will cause less
...@@ -210,7 +211,8 @@ ha_archive::ha_archive(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -210,7 +211,8 @@ ha_archive::ha_archive(handlerton *hton, TABLE_SHARE *table_arg)
buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info); buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
/* The size of the offset value we will use for position() */ /* The size of the offset value we will use for position() */
ref_length = sizeof(my_off_t); ref_length= sizeof(my_off_t);
archive_reader_open= FALSE;
} }
int archive_discover(handlerton *hton, THD* thd, const char *db, int archive_discover(handlerton *hton, THD* thd, const char *db,
...@@ -434,6 +436,29 @@ int ha_archive::init_archive_writer() ...@@ -434,6 +436,29 @@ int ha_archive::init_archive_writer()
} }
int ha_archive::init_archive_reader()
{
DBUG_ENTER("ha_archive::init_archive_reader");
/*
It is expensive to open and close the data files and since you can't have
a gzip file that can be both read and written we keep a writer open
that is shared amoung all open tables.
*/
if (!archive_reader_open)
{
if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)))
{
DBUG_PRINT("ha_archive", ("Could not open archive read file"));
share->crashed= TRUE;
DBUG_RETURN(1);
}
archive_reader_open= TRUE;
}
DBUG_RETURN(0);
}
/* /*
We just implement one additional file extension. We just implement one additional file extension.
*/ */
...@@ -477,7 +502,6 @@ int ha_archive::open(const char *name, int mode, uint open_options) ...@@ -477,7 +502,6 @@ int ha_archive::open(const char *name, int mode, uint open_options)
DBUG_ASSERT(share); DBUG_ASSERT(share);
record_buffer= create_record_buffer(table->s->reclength + record_buffer= create_record_buffer(table->s->reclength +
ARCHIVE_ROW_HEADER_SIZE); ARCHIVE_ROW_HEADER_SIZE);
...@@ -489,14 +513,6 @@ int ha_archive::open(const char *name, int mode, uint open_options) ...@@ -489,14 +513,6 @@ int ha_archive::open(const char *name, int mode, uint open_options)
thr_lock_data_init(&share->lock, &lock, NULL); thr_lock_data_init(&share->lock, &lock, NULL);
DBUG_PRINT("ha_archive", ("archive data_file_name %s", share->data_file_name));
if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)))
{
if (errno == EROFS || errno == EACCES)
DBUG_RETURN(my_errno= errno);
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
}
DBUG_PRINT("ha_archive", ("archive table was crashed %s", DBUG_PRINT("ha_archive", ("archive table was crashed %s",
rc == HA_ERR_CRASHED_ON_USAGE ? "yes" : "no")); rc == HA_ERR_CRASHED_ON_USAGE ? "yes" : "no"));
if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR) if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR)
...@@ -533,8 +549,11 @@ int ha_archive::close(void) ...@@ -533,8 +549,11 @@ int ha_archive::close(void)
destroy_record_buffer(record_buffer); destroy_record_buffer(record_buffer);
/* First close stream */ /* First close stream */
if (azclose(&archive)) if (archive_reader_open)
rc= 1; {
if (azclose(&archive))
rc= 1;
}
/* then also close share */ /* then also close share */
rc|= free_share(); rc|= free_share();
...@@ -904,7 +923,7 @@ int ha_archive::index_read(byte *buf, const byte *key, ...@@ -904,7 +923,7 @@ int ha_archive::index_read(byte *buf, const byte *key,
int ha_archive::index_read_idx(byte *buf, uint index, const byte *key, int ha_archive::index_read_idx(byte *buf, uint index, const byte *key,
uint key_len, enum ha_rkey_function find_flag) uint key_len, enum ha_rkey_function find_flag)
{ {
int rc= 0; int rc;
bool found= 0; bool found= 0;
KEY *mkey= &table->s->key_info[index]; KEY *mkey= &table->s->key_info[index];
current_k_offset= mkey->key_part->offset; current_k_offset= mkey->key_part->offset;
...@@ -914,22 +933,10 @@ int ha_archive::index_read_idx(byte *buf, uint index, const byte *key, ...@@ -914,22 +933,10 @@ int ha_archive::index_read_idx(byte *buf, uint index, const byte *key,
DBUG_ENTER("ha_archive::index_read_idx"); DBUG_ENTER("ha_archive::index_read_idx");
/* rc= rnd_init(TRUE);
All of the buffer must be written out or we won't see all of the
data
*/
pthread_mutex_lock(&share->mutex);
azflush(&(share->archive_write), Z_SYNC_FLUSH);
pthread_mutex_unlock(&share->mutex);
/* if (rc)
Set the position of the local read thread to the beginning postion.
*/
if (read_data_header(&archive))
{
rc= HA_ERR_CRASHED_ON_USAGE;
goto error; goto error;
}
while (!(get_row(&archive, buf))) while (!(get_row(&archive, buf)))
{ {
...@@ -979,10 +986,11 @@ int ha_archive::rnd_init(bool scan) ...@@ -979,10 +986,11 @@ int ha_archive::rnd_init(bool scan)
if (share->crashed) if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
init_archive_reader();
/* We rewind the file so that we can read from the beginning if scan */ /* We rewind the file so that we can read from the beginning if scan */
if (scan) if (scan)
{ {
scan_rows= share->rows_recorded;
DBUG_PRINT("info", ("archive will retrieve %llu rows", DBUG_PRINT("info", ("archive will retrieve %llu rows",
(unsigned long long) scan_rows)); (unsigned long long) scan_rows));
stats.records= 0; stats.records= 0;
...@@ -991,17 +999,18 @@ int ha_archive::rnd_init(bool scan) ...@@ -991,17 +999,18 @@ int ha_archive::rnd_init(bool scan)
If dirty, we lock, and then reset/flush the data. If dirty, we lock, and then reset/flush the data.
I found that just calling azflush() doesn't always work. 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)
{ {
pthread_mutex_lock(&share->mutex);
if (share->dirty == TRUE) if (share->dirty == TRUE)
{ {
DBUG_PRINT("ha_archive", ("archive flushing out rows for scan")); DBUG_PRINT("ha_archive", ("archive flushing out rows for scan"));
azflush(&(share->archive_write), Z_SYNC_FLUSH); azflush(&(share->archive_write), Z_SYNC_FLUSH);
share->dirty= FALSE; share->dirty= FALSE;
} }
pthread_mutex_unlock(&share->mutex);
} }
pthread_mutex_unlock(&share->mutex);
if (read_data_header(&archive)) if (read_data_header(&archive))
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
...@@ -1283,6 +1292,8 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1283,6 +1292,8 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
azio_stream writer; azio_stream writer;
char writer_filename[FN_REFLEN]; char writer_filename[FN_REFLEN];
init_archive_reader();
// now we close both our writer and our reader for the rename // now we close both our writer and our reader for the rename
if (share->archive_write_open) if (share->archive_write_open)
{ {
...@@ -1475,6 +1486,7 @@ int ha_archive::info(uint flag) ...@@ -1475,6 +1486,7 @@ int ha_archive::info(uint flag)
if (flag & HA_STATUS_AUTO) if (flag & HA_STATUS_AUTO)
{ {
init_archive_reader();
azflush(&archive, Z_SYNC_FLUSH); azflush(&archive, Z_SYNC_FLUSH);
stats.auto_increment_value= archive.auto_increment; stats.auto_increment_value= archive.auto_increment;
} }
...@@ -1557,6 +1569,8 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1557,6 +1569,8 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
Now we will rewind the archive file so that we are positioned at the Now we will rewind the archive file so that we are positioned at the
start of the file. start of the file.
*/ */
init_archive_reader();
if (!rc) if (!rc)
read_data_header(&archive); read_data_header(&archive);
......
...@@ -71,6 +71,7 @@ class ha_archive: public handler ...@@ -71,6 +71,7 @@ class ha_archive: public handler
uint current_key_len; uint current_key_len;
uint current_k_offset; uint current_k_offset;
archive_record_buffer *record_buffer; archive_record_buffer *record_buffer;
bool archive_reader_open;
archive_record_buffer *create_record_buffer(unsigned int length); archive_record_buffer *create_record_buffer(unsigned int length);
void destroy_record_buffer(archive_record_buffer *r); void destroy_record_buffer(archive_record_buffer *r);
...@@ -119,6 +120,7 @@ public: ...@@ -119,6 +120,7 @@ public:
ARCHIVE_SHARE *get_share(const char *table_name, int *rc); ARCHIVE_SHARE *get_share(const char *table_name, int *rc);
int free_share(); int free_share();
int init_archive_writer(); int init_archive_writer();
int init_archive_reader();
bool auto_repair() const { return 1; } // For the moment we just do this bool auto_repair() const { return 1; } // For the moment we just do this
int read_data_header(azio_stream *file_to_read); int read_data_header(azio_stream *file_to_read);
void position(const byte *record); void position(const byte *record);
......
...@@ -337,11 +337,7 @@ then ...@@ -337,11 +337,7 @@ then
cp -fp mysql-debug-%{mysql_version}/config.log "$MYSQL_DEBUGCONFLOG_DEST" cp -fp mysql-debug-%{mysql_version}/config.log "$MYSQL_DEBUGCONFLOG_DEST"
fi fi
MTR_BUILD_THREAD=auto (cd mysql-debug-%{mysql_version} ; make test-bt-debug)
export MTR_BUILD_THREAD
(cd mysql-debug-%{mysql_version}/mysql-test ; \
./mysql-test-run.pl --comment=debug --skip-rpl --skip-ndbcluster --force --report-features ; \
true)
############################################################################## ##############################################################################
# #
...@@ -370,15 +366,7 @@ then ...@@ -370,15 +366,7 @@ then
cp -fp mysql-release-%{mysql_version}/config.log "$MYSQL_CONFLOG_DEST" cp -fp mysql-release-%{mysql_version}/config.log "$MYSQL_CONFLOG_DEST"
fi fi
MTR_BUILD_THREAD=auto (cd mysql-release-%{mysql_version} ; make test-bt)
export MTR_BUILD_THREAD
cd mysql-release-%{mysql_version}/mysql-test
./mysql-test-run.pl --comment=normal --force --skip-ndbcluster --timer --report-features || true
./mysql-test-run.pl --comment=ps --ps-protocol --force --skip-ndbcluster --timer || true
./mysql-test-run.pl --comment=normal+rowrepl --mysqld=--binlog-format=row --force --skip-ndbcluster --timer || true
./mysql-test-run.pl --comment=ps+rowrepl+NDB --ps-protocol --mysqld=--binlog-format=row --force --timer || true
./mysql-test-run.pl --comment=NDB --with-ndbcluster-only --force --timer || true
cd ../..
############################################################################## ##############################################################################
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment