diff --git a/src/db_driver.c b/src/db_driver.c index 0e39ad7..ccd19c3 100644 --- a/src/db_driver.c +++ b/src/db_driver.c @@ -364,7 +364,7 @@ db_conn_t *db_connection_create(db_driver_t *drv) con->driver = drv; con->state = DB_CONN_READY; - db_set_thread(con, sb_tls_thread_id); + con->thread_id = sb_tls_thread_id; if (drv->ops.connect(con)) { @@ -376,14 +376,6 @@ db_conn_t *db_connection_create(db_driver_t *drv) } -/* Associate connection with a thread (required only for statistics */ - -void db_set_thread(db_conn_t *con, int thread_id) -{ - con->thread_id = thread_id; -} - - /* Disconnect from database */ diff --git a/src/db_driver.h b/src/db_driver.h index d46b510..60b9790 100644 --- a/src/db_driver.h +++ b/src/db_driver.h @@ -334,9 +334,6 @@ int db_bulk_insert_done(db_conn_t *); /* Print database-specific test stats */ void db_print_stats(sb_stat_t type); -/* Associate connection with a thread (required only for statistics */ -void db_set_thread(db_conn_t *, int); - /* Initialize per-thread stats */ int db_thread_stat_init(void); diff --git a/src/lua/internal/sysbench.cmdline.lua b/src/lua/internal/sysbench.cmdline.lua index 906fbb6..c9babe8 100644 --- a/src/lua/internal/sysbench.cmdline.lua +++ b/src/lua/internal/sysbench.cmdline.lua @@ -64,6 +64,9 @@ sysbench.cmdline.ARG_LIST = ffi.C.SB_ARG_TYPE_LIST sysbench.cmdline.ARG_FILE = ffi.C.SB_ARG_TYPE_FILE sysbench.cmdline.ARG_MAX = ffi.C.SB_ARG_TYPE_MAX +-- Attribute indicating that a custom command can be executed in parallel +sysbench.cmdline.PARALLEL_COMMAND = true + local arg_types = { boolean = sysbench.cmdline.ARG_BOOL, string = sysbench.cmdline.ARG_STRING, @@ -71,7 +74,7 @@ local arg_types = { table = sysbench.cmdline.ARG_LIST } --- Parse command line options definitions, if present in the script as a a +-- Parse command line options definitions, if present in the script as a -- 'sysbench.option_defs' table. If no such table exists, or if there a parsing -- error, return false. Return true on success. function sysbench.cmdline.read_option_defs() @@ -137,3 +140,30 @@ function sysbench.cmdline.read_option_defs() return ffi.C.sb_lua_set_test_args(args, i) == 0 end + +function sysbench.cmdline.command_defined(name) + return type(sysbench.cmdline.commands) == "table" and + sysbench.cmdline.commands[name] ~= nil and + sysbench.cmdline.commands[name][1] ~= nil +end + +function sysbench.cmdline.command_parallel(name) + return sysbench.cmdline.command_defined(name) and + sysbench.cmdline.commands[name][2] == sysbench.cmdline.PARALLEL_COMMAND +end + +function sysbench.cmdline.call_command(name) + if not sysbench.cmdline.command_defined(name) then + return false + end + + local rc = sysbench.cmdline.commands[name][1]() + + if rc == nil then + -- handle the case when the command does not return and value as success + return true + else + -- otherwise return success for any returned value other than false + return rc and true or false + end +end diff --git a/src/lua/select_random_points.lua b/src/lua/select_random_points.lua index 801a326..9370e09 100755 --- a/src/lua/select_random_points.lua +++ b/src/lua/select_random_points.lua @@ -49,9 +49,11 @@ function thread_init() stmt:bind_param(unpack(params)) rlen = sysbench.opt.table_size / sysbench.opt.num_threads + + thread_id = sysbench.tid % sysbench.opt.num_threads end -function event(thread_id) +function event() -- To prevent overlapping of our range queries we need to partition the whole -- table into num_threads segments and then make each thread work with its -- own segment. diff --git a/src/lua/select_random_ranges.lua b/src/lua/select_random_ranges.lua index 7d0cb20..f5ad690 100755 --- a/src/lua/select_random_ranges.lua +++ b/src/lua/select_random_ranges.lua @@ -52,9 +52,11 @@ function thread_init() stmt:bind_param(unpack(params)) rlen = sysbench.opt.table_size / sysbench.opt.num_threads + + thread_id = sysbench.tid % sysbench.opt.num_threads end -function event(thread_id) +function event() -- To prevent overlapping of our range queries we need to partition the whole -- table into num_threads segments and then make each thread work with its -- own segment. diff --git a/src/sb_lua.c b/src/sb_lua.c index dce89e3..5a09b86 100644 --- a/src/sb_lua.c +++ b/src/sb_lua.c @@ -58,7 +58,6 @@ /* Interpreter context */ typedef struct { - int thread_id; /* sysbench thread id */ db_conn_t *con; /* Database connection */ } sb_lua_ctxt_t; @@ -98,7 +97,7 @@ typedef enum { } sb_lua_error_t; bool sb_lua_more_events(int); -int sb_lua_set_test_args(sb_arg_t *args, size_t len); +int sb_lua_set_test_args(sb_arg_t *, size_t); /* Lua interpreter states */ @@ -124,6 +123,9 @@ static internal_script_t internal_scripts[] = { /* Main (global) interpreter state */ static lua_State *gstate; +/* Custom command name */ +static const char * sb_lua_custom_command; + /* Lua test operations */ static int sb_lua_op_init(void); @@ -135,6 +137,8 @@ static void sb_lua_op_print_stats(sb_stat_t type); static sb_operations_t lua_ops = { .init = sb_lua_op_init, + .thread_init = sb_lua_op_thread_init, + .thread_done = sb_lua_op_thread_done, .done = sb_lua_op_done }; @@ -144,7 +148,7 @@ static int sb_lua_cmd_cleanup(void); static int sb_lua_cmd_help(void); /* Initialize interpreter state */ -static lua_State *sb_lua_new_state(int); +static lua_State *sb_lua_new_state(void); /* Close interpretet state */ static int sb_lua_close_state(lua_State *); @@ -312,7 +316,7 @@ sb_test_t *sb_load_lua(const char *testname) } /* Initialize global interpreter state */ - gstate = sb_lua_new_state(-1); + gstate = sb_lua_new_state(); if (gstate == NULL) goto error; @@ -321,21 +325,17 @@ sb_test_t *sb_load_lua(const char *testname) /* Test commands */ if (func_available(gstate, PREPARE_FUNC)) - sbtest.cmds.prepare = &sb_lua_cmd_prepare; + sbtest.builtin_cmds.prepare = &sb_lua_cmd_prepare; if (func_available(gstate, CLEANUP_FUNC)) - sbtest.cmds.cleanup = &sb_lua_cmd_cleanup; + sbtest.builtin_cmds.cleanup = &sb_lua_cmd_cleanup; if (func_available(gstate, HELP_FUNC)) - sbtest.cmds.help = &sb_lua_cmd_help; + sbtest.builtin_cmds.help = &sb_lua_cmd_help; /* Test operations */ sbtest.ops = lua_ops; - sbtest.ops.thread_init = &sb_lua_op_thread_init; - - sbtest.ops.thread_done = &sb_lua_op_thread_done; - if (func_available(gstate, THREAD_RUN_FUNC)) sbtest.ops.thread_run = &sb_lua_op_thread_run; @@ -387,7 +387,7 @@ int sb_lua_op_thread_init(int thread_id) { lua_State * L; - L = sb_lua_new_state(thread_id); + L = sb_lua_new_state(); if (L == NULL) return 1; @@ -596,7 +596,7 @@ static void sb_lua_set_paths(lua_State *L) lua_pop(L, 1); /* package */ } -/* Create a deep copy of the 'args' array and set it to sbtest.args */ +/* Create a deep copy of the 'args' array and store it in sbtest.args */ int sb_lua_set_test_args(sb_arg_t *args, size_t len) { @@ -633,7 +633,7 @@ static int read_option_defs(lua_State *L) { log_text(LOG_WARNING, "Cannot find the sysbench.cmdline.read_option_defs() function"); - lua_pop(L, 2); + lua_pop(L, 3); return 1; } @@ -641,20 +641,20 @@ static int read_option_defs(lua_State *L) if (lua_pcall(L, 0, 1, 0) != 0) { call_error(L, "sysbench.cmdline.read_option_defs"); - lua_pop(L, 3); + lua_pop(L, 2); return 1; } int rc = lua_toboolean(L, -1) == 0; - lua_pop(L, 4); + lua_pop(L, 3); return rc; } /* Allocate and initialize new interpreter state */ -static lua_State *sb_lua_new_state(int thread_id) +static lua_State *sb_lua_new_state() { lua_State *L; @@ -669,8 +669,7 @@ static lua_State *sb_lua_new_state(int thread_id) lua_newtable(L); /* sysbench.tid */ - if (thread_id >= 0) - sb_lua_var_number(L, "tid", thread_id); + sb_lua_var_number(L, "tid", sb_tls_thread_id); /* Export functions into per-state 'sysbench.db' table */ @@ -743,8 +742,6 @@ static lua_State *sb_lua_new_state(int thread_id) if (tls_lua_ctxt == NULL) return NULL; - tls_lua_ctxt->thread_id = thread_id; - return L; } @@ -816,7 +813,6 @@ int sb_lua_db_connect(lua_State *L) tls_lua_ctxt->con = db_connection_create(db_driver); if (tls_lua_ctxt->con == NULL) luaL_error(L, "Failed to connect to the database"); - db_set_thread(tls_lua_ctxt->con, tls_lua_ctxt->thread_id); return 0; } @@ -1263,6 +1259,9 @@ unsigned int sb_lua_table_size(lua_State *L, int index) bool sb_lua_hook_defined(lua_State *L, const char *name) { + if (L == NULL) + return false; + lua_getglobal(L, "sysbench"); lua_getfield(L, -1, "hooks"); lua_getfield(L, -1, name); @@ -1273,3 +1272,148 @@ bool sb_lua_hook_defined(lua_State *L, const char *name) return rc; } + +/* Check if a specified custom command exists */ + +bool sb_lua_custom_command_defined(const char *name) +{ + lua_State * const L = gstate; + + if (L == NULL) + return false; + + lua_getglobal(L, "sysbench"); + lua_getfield(L, -1, "cmdline"); + lua_getfield(L, -1, "command_defined"); + + if (!lua_isfunction(L, -1)) + { + log_text(LOG_WARNING, + "Cannot find the sysbench.cmdline.command_defined function"); + lua_pop(L, 3); + + return 1; + } + + lua_pushstring(L, name); + + if (lua_pcall(L, 1, 1, 0) != 0) + { + call_error(L, "sysbench.cmdline.command_defined"); + lua_pop(L, 2); + return 1; + } + + bool rc = lua_toboolean(L, -1); + + lua_pop(L, 3); + + return rc; +} + +/* Check if a specified custom command supports parallel execution */ + +static bool sb_lua_custom_command_parallel(const char *name) +{ + lua_State * const L = gstate; + + lua_getglobal(L, "sysbench"); + lua_getfield(L, -1, "cmdline"); + lua_getfield(L, -1, "command_parallel"); + + if (!lua_isfunction(L, -1)) + { + log_text(LOG_WARNING, + "Cannot find the sysbench.cmdline.command_parallel function"); + lua_pop(L, 3); + + return 1; + } + + lua_pushstring(L, name); + + if (lua_pcall(L, 1, 1, 0) != 0) + { + call_error(L, "sysbench.cmdline.command_parallel"); + lua_pop(L, 2); + return 1; + } + + bool rc = lua_toboolean(L, -1); + + lua_pop(L, 3); + + return rc; +} + +static int call_custom_command(lua_State *L) +{ + lua_getglobal(L, "sysbench"); + lua_getfield(L, -1, "cmdline"); + lua_getfield(L, -1, "call_command"); + + if (!lua_isfunction(L, -1)) + { + log_text(LOG_WARNING, + "Cannot find the sysbench.cmdline.call_command function"); + lua_pop(L, 3); + + return 1; + } + + lua_pushstring(L, sb_lua_custom_command); + + if (lua_pcall(L, 1, 1, 0) != 0) + { + call_error(L, "sysbench.cmdline.command_defined"); + lua_pop(L, 2); + return 1; + } + + bool rc = lua_toboolean(L, -1); + + lua_pop(L, 3); + + return rc ? EXIT_SUCCESS : EXIT_FAILURE; +} + + +static void *cmd_worker_thread(void *arg) +{ + sb_thread_ctxt_t *ctxt= (sb_thread_ctxt_t *)arg; + + sb_tls_thread_id = ctxt->id; + + lua_State * const L = sb_lua_new_state(); + + if (L == NULL) + { + log_text(LOG_FATAL, "failed to create a thread to execute command"); + return NULL; + } + + call_custom_command(L); + + sb_lua_close_state(L); + + return NULL; +} + +/* Call a specified custom command */ + +int sb_lua_call_custom_command(const char *name) +{ + sb_lua_custom_command = name; + + if (sb_lua_custom_command_parallel(name)) + { + int err; + + if ((err = sb_thread_create_workers(cmd_worker_thread))) + return err; + + return sb_thread_join_workers(); + } + + return call_custom_command(gstate); +} diff --git a/src/sb_lua.h b/src/sb_lua.h index 412dc76..f3e2205 100644 --- a/src/sb_lua.h +++ b/src/sb_lua.h @@ -30,3 +30,7 @@ sb_test_t *sb_load_lua(const char *testname); bool sb_lua_hook_defined(lua_State *L, const char *name); int sb_lua_hook_call(const char *name); + +bool sb_lua_custom_command_defined(const char *name); + +int sb_lua_call_custom_command(const char *name); diff --git a/src/sb_thread.c b/src/sb_thread.c index f33ecf5..016018f 100644 --- a/src/sb_thread.c +++ b/src/sb_thread.c @@ -35,6 +35,54 @@ #include "sb_thread.h" #include "sb_rand.h" +#include "sb_logger.h" +#include "sysbench.h" +#include "ck_pr.h" + +pthread_attr_t sb_thread_attr; + +/* Thread descriptors */ +static sb_thread_ctxt_t *threads; + +/* Stack size for each thread */ +static int thread_stack_size; + +int sb_thread_init(void) +{ + thread_stack_size = sb_get_value_size("thread-stack-size"); + if (thread_stack_size <= 0) + { + log_text(LOG_FATAL, "Invalid value for thread-stack-size: %d.\n", thread_stack_size); + return 1; + } + + /* initialize attr */ + pthread_attr_init(&sb_thread_attr); +#ifdef PTHREAD_SCOPE_SYSTEM + pthread_attr_setscope(&sb_thread_attr,PTHREAD_SCOPE_SYSTEM); +#endif + pthread_attr_setstacksize(&sb_thread_attr, thread_stack_size); + +#ifdef HAVE_THR_SETCONCURRENCY + /* Set thread concurrency (required on Solaris) */ + thr_setconcurrency(sb_globals.num_threads); +#endif + + threads = malloc(sb_globals.num_threads * sizeof(sb_thread_ctxt_t)); + if (threads == NULL) + { + log_text(LOG_FATAL, "Memory allocation failure.\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +void sb_thread_done(void) +{ + if (threads != NULL) + free(threads); +} int sb_thread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) @@ -51,3 +99,46 @@ int sb_thread_cancel(pthread_t thread) { return pthread_cancel(thread); } + +int sb_thread_create_workers(void *(*worker_routine)(void*)) +{ + unsigned int i; + + log_text(LOG_NOTICE, "Initializing worker threads...\n"); + + for(i = 0; i < sb_globals.num_threads; i++) + { + threads[i].id = i; + } + + + for(i = 0; i < sb_globals.num_threads; i++) + { + int err; + + if ((err = sb_thread_create(&(threads[i].thread), &sb_thread_attr, + worker_routine, (void*)(threads + i))) != 0) + { + log_errno(LOG_FATAL, "sb_thread_create() for thread #%d failed.", i); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} + + +int sb_thread_join_workers(void) +{ + for(unsigned i = 0; i < sb_globals.num_threads; i++) + { + int err; + + if((err = sb_thread_join(threads[i].thread, NULL)) != 0) + log_errno(LOG_FATAL, "sb_thread_join() for thread #%d failed.", i); + + ck_pr_dec_uint(&sb_globals.num_running); + } + + return EXIT_SUCCESS; +} diff --git a/src/sb_thread.h b/src/sb_thread.h index e8e247d..f0fafb1 100644 --- a/src/sb_thread.h +++ b/src/sb_thread.h @@ -36,6 +36,16 @@ # include #endif +/* Thread context definition */ + +typedef struct +{ + pthread_t thread; + unsigned int id; +} sb_thread_ctxt_t; + +extern pthread_attr_t sb_thread_attr; + int sb_thread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); @@ -43,4 +53,12 @@ int sb_thread_join(pthread_t thread, void **retval); int sb_thread_cancel(pthread_t thread); +int sb_thread_create_workers(void *(*worker_routine)(void*)); + +int sb_thread_join_workers(void); + +int sb_thread_init(void); + +void sb_thread_done(void); + #endif /* SB_THREAD_H */ diff --git a/src/sysbench.c b/src/sysbench.c index 720c84e..0e33f19 100644 --- a/src/sysbench.c +++ b/src/sysbench.c @@ -93,9 +93,6 @@ typedef struct { /* Mutex to protect report_interval */ static pthread_mutex_t report_interval_mutex; -/* Stack size for each thread */ -static int thread_stack_size; - /* General options */ sb_arg_t general_args[] = { @@ -124,9 +121,6 @@ sb_arg_t general_args[] = SB_OPT_END }; -/* Thread descriptors */ -sb_thread_ctxt_t *threads; - /* List of available tests */ sb_list_t tests; @@ -137,10 +131,6 @@ sb_test_t *current_test; /* Barrier to ensure we start the benchmark run when all workers are ready */ static sb_barrier_t thread_start_barrier; -/* Mutexes */ - -static pthread_attr_t thread_attr; - /* structures to handle queue of events, needed for tx_rate mode */ pthread_mutex_t event_queue_mutex; static sb_list_t event_queue; @@ -600,12 +590,11 @@ static int thread_run(sb_test_t *test, int thread_id) static void *worker_thread(void *arg) { sb_thread_ctxt_t *ctxt; - sb_test_t *test; unsigned int thread_id; int rc; ctxt = (sb_thread_ctxt_t *)arg; - test = ctxt->test; + sb_test_t * const test = current_test; sb_tls_thread_id = thread_id = ctxt->id; @@ -841,14 +830,13 @@ static int threads_started_callback(void *arg) return 0; } + /* - Main test function. Start threads. - Wait for them to complete and measure time + Main test function: start threads, wait for them to finish and measure time. */ static int run_test(sb_test_t *test) { - unsigned int i; int err; pthread_t report_thread; pthread_t checkpoints_thread; @@ -867,11 +855,6 @@ static int run_test(sb_test_t *test) sb_timer_init(&sb_intermediate_timer); sb_timer_init(&sb_checkpoint_timer1); sb_timer_init(&sb_checkpoint_timer2); - for(i = 0; i < sb_globals.num_threads; i++) - { - threads[i].id = i; - threads[i].test = test; - } /* prepare test */ if (test->ops.prepare != NULL && test->ops.prepare() != 0) @@ -887,18 +870,6 @@ static int run_test(sb_test_t *test) sb_globals.num_running = 0; - /* initialize attr */ - pthread_attr_init(&thread_attr); -#ifdef PTHREAD_SCOPE_SYSTEM - pthread_attr_setscope(&thread_attr,PTHREAD_SCOPE_SYSTEM); -#endif - pthread_attr_setstacksize(&thread_attr, thread_stack_size); - -#ifdef HAVE_THR_SETCONCURRENCY - /* Set thread concurrency (required on Solaris) */ - thr_setconcurrency(sb_globals.num_threads); -#endif - pthread_mutex_init(&report_interval_mutex, NULL); /* Calculate the required number of threads for the start barrier */ @@ -917,8 +888,8 @@ static int run_test(sb_test_t *test) if (sb_globals.report_interval > 0) { /* Create a thread for intermediate statistic reports */ - if ((err = sb_thread_create(&report_thread, &thread_attr, &report_thread_proc, - NULL)) != 0) + if ((err = sb_thread_create(&report_thread, &sb_thread_attr, + &report_thread_proc, NULL)) != 0) { log_errno(LOG_FATAL, "sb_thread_create() for the reporting thread failed."); @@ -928,8 +899,8 @@ static int run_test(sb_test_t *test) if (sb_globals.tx_rate > 0) { - if ((err = sb_thread_create(&eventgen_thread, &thread_attr, &eventgen_thread_proc, - NULL)) != 0) + if ((err = sb_thread_create(&eventgen_thread, &sb_thread_attr, + &eventgen_thread_proc, NULL)) != 0) { log_errno(LOG_FATAL, "sb_thread_create() for the reporting thread failed."); @@ -940,7 +911,7 @@ static int run_test(sb_test_t *test) if (sb_globals.n_checkpoints > 0) { /* Create a thread for checkpoint statistic reports */ - if ((err = sb_thread_create(&checkpoints_thread, &thread_attr, + if ((err = sb_thread_create(&checkpoints_thread, &sb_thread_attr, &checkpoints_thread_proc, NULL)) != 0) { log_errno(LOG_FATAL, @@ -949,18 +920,8 @@ static int run_test(sb_test_t *test) } } - log_text(LOG_NOTICE, "Initializing worker threads...\n"); - - /* Starting the worker threads */ - for(i = 0; i < sb_globals.num_threads; i++) - { - if ((err = sb_thread_create(&(threads[i].thread), &thread_attr, - &worker_thread, (void*)(threads + i))) != 0) - { - log_errno(LOG_FATAL, "sb_thread_create() for thread #%d failed.", i); - return 1; - } - } + if ((err = sb_thread_create_workers(&worker_thread))) + return err; #ifdef HAVE_ALARM /* Exit with an error if thread initialization timeout expires */ @@ -987,13 +948,8 @@ static int run_test(sb_test_t *test) } #endif - for(i = 0; i < sb_globals.num_threads; i++) - { - if((err = sb_thread_join(threads[i].thread, NULL)) != 0) - log_errno(LOG_FATAL, "sb_thread_join() for thread #%d failed.", i); - - ck_pr_dec_uint(&sb_globals.num_running); - } + if ((err = sb_thread_join_workers())) + return err; sb_timer_stop(&sb_exec_timer); sb_timer_stop(&sb_intermediate_timer); @@ -1126,20 +1082,9 @@ static int init(void) sb_globals.force_shutdown = 0; } - threads = (sb_thread_ctxt_t *)malloc(sb_globals.num_threads * - sizeof(sb_thread_ctxt_t)); - if (threads == NULL) - { - log_text(LOG_FATAL, "Memory allocation failure.\n"); - return 1; - } - - thread_stack_size = sb_get_value_size("thread-stack-size"); - if (thread_stack_size <= 0) - { - log_text(LOG_FATAL, "Invalid value for thread-stack-size: %d.\n", thread_stack_size); - return 1; - } + int err; + if ((err = sb_thread_init())) + return err; sb_globals.debug = sb_get_value_flag("debug"); /* Automatically set logger verbosity to 'debug' */ @@ -1196,7 +1141,7 @@ static int init(void) int main(int argc, char *argv[]) { sb_test_t *test = NULL; - + /* Initialize options library */ sb_options_init(); @@ -1283,7 +1228,11 @@ int main(int argc, char *argv[]) if (parse_test_arguments(test, argc, argv)) return EXIT_FAILURE; - if (!strcmp(sb_globals.cmdname, "help")) + if (sb_lua_custom_command_defined(sb_globals.cmdname)) + { + return sb_lua_call_custom_command(sb_globals.cmdname); + } + else if (!strcmp(sb_globals.cmdname, "help")) { if (test == NULL) print_help(); @@ -1294,32 +1243,32 @@ int main(int argc, char *argv[]) printf("%s options:\n", test->sname); sb_print_options(test->args); } - if (test->cmds.help != NULL) - test->cmds.help(); + if (test->builtin_cmds.help != NULL) + test->builtin_cmds.help(); } return EXIT_SUCCESS; } else if (!strcmp(sb_globals.cmdname, "prepare")) { - if (test->cmds.prepare == NULL) + if (test->builtin_cmds.prepare == NULL) { - fprintf(stderr, "'%s' test does not have the 'prepare' command.\n", + fprintf(stderr, "'%s' test does not implement the 'prepare' command.\n", test->sname); exit(1); } - return test->cmds.prepare(); + return test->builtin_cmds.prepare(); } else if (!strcmp(sb_globals.cmdname, "cleanup")) { - if (test->cmds.cleanup == NULL) + if (test->builtin_cmds.cleanup == NULL) { - fprintf(stderr, "'%s' test does not have the 'cleanup' command.\n", + fprintf(stderr, "'%s' test does not implement the 'cleanup' command.\n", test->sname); return EXIT_FAILURE; } - return test->cmds.cleanup(); + return test->builtin_cmds.cleanup(); } else if (!strcmp(sb_globals.cmdname, "run")) { @@ -1341,6 +1290,7 @@ int main(int argc, char *argv[]) sb_rand_done(); + sb_thread_done(); + exit(0); } - diff --git a/src/sysbench.h b/src/sysbench.h index cd61c3d..6eb538e 100644 --- a/src/sysbench.h +++ b/src/sysbench.h @@ -90,13 +90,10 @@ typedef enum SB_STAT_CUMULATIVE } sb_stat_t; -/* Test commands definition */ - -typedef int sb_cmd_help(void); -typedef int sb_cmd_prepare(void); -typedef int sb_cmd_run(void); -typedef int sb_cmd_cleanup(void); +/* Commands */ +typedef int sb_builtin_cmd_func_t(void); +typedef int sb_custom_cmd_func_t(int); /* Test operations definition */ @@ -116,11 +113,11 @@ typedef int sb_op_done(void); typedef struct { - sb_cmd_help *help; /* print help */ - sb_cmd_prepare *prepare; /* prepare for the test */ - sb_cmd_run *run; /* run the test */ - sb_cmd_cleanup *cleanup; /* cleanup the test database, files, etc. */ -} sb_commands_t; + sb_builtin_cmd_func_t *help; /* print help */ + sb_builtin_cmd_func_t *prepare; /* prepare for the test */ + sb_builtin_cmd_func_t *run; /* run the test */ + sb_builtin_cmd_func_t *cleanup; /* cleanup the test database, files, etc. */ +} sb_builtin_cmds_t; /* Test operations structure definition */ @@ -146,25 +143,15 @@ typedef struct typedef struct sb_test { - const char *sname; - const char *lname; - sb_operations_t ops; - sb_commands_t cmds; - sb_arg_t *args; + const char *sname; + const char *lname; + sb_operations_t ops; + sb_builtin_cmds_t builtin_cmds; + sb_arg_t *args; - sb_list_item_t listitem; + sb_list_item_t listitem; } sb_test_t; -/* Thread context definition */ - -typedef struct -{ - sb_test_t *test; - pthread_t thread; - unsigned int id; -} sb_thread_ctxt_t; - - /* sysbench global variables */ typedef struct diff --git a/src/tests/fileio/sb_fileio.c b/src/tests/fileio/sb_fileio.c index 0e06798..d78ac05 100644 --- a/src/tests/fileio/sb_fileio.c +++ b/src/tests/fileio/sb_fileio.c @@ -272,7 +272,7 @@ static sb_test_t fileio_test = #endif .done = file_done }, - .cmds = { + .builtin_cmds = { .prepare = file_cmd_prepare, .cleanup = file_cmd_cleanup }, diff --git a/tests/t/api_basic.t b/tests/t/api_basic.t index aeec0cc..dd35072 100644 --- a/tests/t/api_basic.t +++ b/tests/t/api_basic.t @@ -58,7 +58,7 @@ Basic Lua API tests tid:(nil) cleanup() $ sysbench $SB_ARGS help - tid:(nil) help() + tid:0 help() $ cat >$CRAMTMP/api_basic.lua < function event() diff --git a/tests/t/api_legacy_basic.t b/tests/t/api_legacy_basic.t index 293f430..2e3ae84 100644 --- a/tests/t/api_legacy_basic.t +++ b/tests/t/api_legacy_basic.t @@ -53,7 +53,7 @@ Legacy basic Lua API tests tid:(nil) cleanup() $ sysbench $SB_ARGS help - tid:(nil) help() + tid:0 help() $ cat >$CRAMTMP/api_legacy_basic.lua < function prepare() diff --git a/tests/t/cmdline.t b/tests/t/cmdline.t index 4d62637..f45dfc7 100644 --- a/tests/t/cmdline.t +++ b/tests/t/cmdline.t @@ -166,7 +166,7 @@ Command line options tests $ sysbench cmdline.lua prepare sysbench * (glob) - 'cmdline.lua' test does not have the 'prepare' command. + 'cmdline.lua' test does not implement the 'prepare' command. [1] $ sysbench --non-existing-option=3 cmdline.lua prepare @@ -184,7 +184,7 @@ Command line options tests $ sysbench cmdline.lua cleanup sysbench * (glob) - 'cmdline.lua' test does not have the 'cleanup' command. + 'cmdline.lua' test does not implement the 'cleanup' command. [1] $ cat >cmdline.lua < sysbench.cmdline.commands = { + > cmd1 = "wrong structure" + > } + > EOF + sysbench * (glob) + + $ sysbench < sysbench.cmdline.commands = { + > cmd1 = { non_existing_func } + > } + > EOF + sysbench * (glob) + + $ cat >cmdline.lua < ffi.cdef "unsigned int sleep(unsigned int);" + > function cmd1_func() + > print("cmd1, sysbench.tid = " .. sysbench.tid) + > end + > function cmd2_func() + > ffi.C.sleep(sysbench.tid % 2) + > print("cmd2, sysbench.tid = " .. sysbench.tid) + > end + > function prepare_func() + > ffi.C.sleep(sysbench.tid % 2) + > print("prepare_func, sysbench.tid = " .. sysbench.tid) + > end + > sysbench.cmdline.commands = { + > cmd1 = { cmd1_func }, + > cmd2 = { cmd2_func, sysbench.cmdline.PARALLEL_COMMAND }, + > prepare = { prepare_func, sysbench.cmdline.PARALLEL_COMMAND } + > } + > EOF + + $ sysbench --num-threads=2 cmdline.lua cmd1 + sysbench * (glob) + + cmd1, sysbench.tid = 0 + $ sysbench --num-threads=2 cmdline.lua cmd2 + sysbench * (glob) + + Initializing worker threads... + + cmd2, sysbench.tid = [01] (re) + cmd2, sysbench.tid = [01] (re) + + $ sysbench --num-threads=2 cmdline.lua prepare + sysbench * (glob) + + Initializing worker threads... + + prepare_func, sysbench.tid = [01] (re) + prepare_func, sysbench.tid = [01] (re) + + $ sysbench --num-threads=2 cmdline.lua cmd3 + sysbench * (glob) + + Unknown command: cmd3 (no-eol) + [1] diff --git a/tests/t/test_cpu.t b/tests/t/test_cpu.t index d450ff4..97d7e43 100644 --- a/tests/t/test_cpu.t +++ b/tests/t/test_cpu.t @@ -11,7 +11,7 @@ cpu benchmark tests $ sysbench $args prepare sysbench *.* * (glob) - 'cpu' test does not have the 'prepare' command. + 'cpu' test does not implement the 'prepare' command. [1] $ sysbench $args run sysbench *.* * (glob) @@ -46,5 +46,5 @@ cpu benchmark tests $ sysbench $args cleanup sysbench *.* * (glob) - 'cpu' test does not have the 'cleanup' command. + 'cpu' test does not implement the 'cleanup' command. [1] diff --git a/tests/t/test_memory.t b/tests/t/test_memory.t index 2916c36..2e40850 100644 --- a/tests/t/test_memory.t +++ b/tests/t/test_memory.t @@ -28,7 +28,7 @@ help' only on Linux. $ sysbench $args prepare sysbench *.* * (glob) - 'memory' test does not have the 'prepare' command. + 'memory' test does not implement the 'prepare' command. [1] $ sysbench $args run sysbench *.* * (glob) @@ -65,5 +65,5 @@ help' only on Linux. $ sysbench $args cleanup sysbench *.* * (glob) - 'memory' test does not have the 'cleanup' command. + 'memory' test does not implement the 'cleanup' command. [1] diff --git a/tests/t/test_mutex.t b/tests/t/test_mutex.t index 4a47593..f49e319 100644 --- a/tests/t/test_mutex.t +++ b/tests/t/test_mutex.t @@ -13,7 +13,7 @@ mutex benchmark tests $ sysbench $args prepare sysbench *.* * (glob) - 'mutex' test does not have the 'prepare' command. + 'mutex' test does not implement the 'prepare' command. [1] $ sysbench $args run sysbench *.* * (glob) @@ -46,5 +46,5 @@ mutex benchmark tests $ sysbench $args cleanup sysbench *.* * (glob) - 'mutex' test does not have the 'cleanup' command. + 'mutex' test does not implement the 'cleanup' command. [1] diff --git a/tests/t/test_threads.t b/tests/t/test_threads.t index 933602d..8b9ba26 100644 --- a/tests/t/test_threads.t +++ b/tests/t/test_threads.t @@ -13,7 +13,7 @@ threads benchmark tests $ sysbench $args prepare sysbench *.* * (glob) - 'threads' test does not have the 'prepare' command. + 'threads' test does not implement the 'prepare' command. [1] $ sysbench $args run sysbench *.* * (glob) @@ -46,5 +46,5 @@ threads benchmark tests $ sysbench $args cleanup sysbench *.* * (glob) - 'threads' test does not have the 'cleanup' command. + 'threads' test does not implement the 'cleanup' command. [1]