Allow Lua scripts to declare supported options.

Lua scripts can now declare their supported options, in which case
sysbench validates command line arguments and display usage
information.

This is a prerequisite for fixing #15 and #79.
This commit is contained in:
Alexey Kopytov
2017-01-26 04:23:55 +03:00
parent 2cda228c7e
commit 9d73ed0865
13 changed files with 470 additions and 56 deletions

3
.gitignore vendored
View File

@ -76,3 +76,6 @@ third_party/luajit/tmp/
sysbench/lua/internal/sysbench.lua.h
sysbench/lua/internal/sysbench.sql.lua.h
/sysbench/lua/internal/sysbench.rand.lua.h
/sysbench/lua/internal/sysbench.opt.lua.h
tests/t/*.err
/sysbench/lua/internal/sysbench.cmdline.lua.h

View File

@ -301,6 +301,7 @@ sys/shm.h \
thread.h \
unistd.h \
limits.h \
libgen.h \
])

View File

@ -49,7 +49,7 @@ sb_options.c sb_options.h sb_logger.c sb_logger.h sb_list.h db_driver.h \
db_driver.c sb_histogram.c sb_histogram.h sb_rand.c sb_rand.h \
sb_thread.c sb_thread.h sb_barrier.c sb_barrier.h sb_lua.c \
sb_lua.h lua/internal/sysbench.lua.h lua/internal/sysbench.sql.lua.h \
lua/internal/sysbench.rand.lua.h sb_util.h \
lua/internal/sysbench.rand.lua.h lua/internal/sysbench.cmdline.lua.h sb_util.h \
xoroshiro128plus.h sb_util.c
sysbench_LDADD = tests/fileio/libsbfileio.a tests/threads/libsbthreads.a \

View File

@ -14,7 +14,9 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
BUILT_SOURCES = sysbench.lua.h sysbench.rand.lua.h sysbench.sql.lua.h
BUILT_SOURCES = sysbench.lua.h sysbench.rand.lua.h sysbench.sql.lua.h \
sysbench.cmdline.lua.h
CLEARFILES = $(BUILT_SOURCES)
EXTRA_DIST = $(BUILT_SOURCES:.h=)

View File

@ -0,0 +1,139 @@
-- Copyright (C) 2017 Alexey Kopytov <akopytov@gmail.com>
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Command line option handling
-- ----------------------------------------------------------------------
ffi = require("ffi")
sysbench.cmdline = {}
ffi.cdef[[
/* The following has been copied from sb_option.h */
typedef enum
{
SB_ARG_TYPE_NULL,
SB_ARG_TYPE_BOOL,
SB_ARG_TYPE_INT,
SB_ARG_TYPE_SIZE,
SB_ARG_TYPE_DOUBLE,
SB_ARG_TYPE_STRING,
SB_ARG_TYPE_LIST,
SB_ARG_TYPE_FILE,
SB_ARG_TYPE_MAX
} sb_arg_type_t;
/* Option validation function */
typedef bool sb_arg_validate_t(const char *, const char *);
/* Test option definition */
typedef struct
{
const char *name;
const char *desc;
const char *value;
sb_arg_type_t type;
sb_arg_validate_t *validate;
} sb_arg_t;
int sb_lua_set_test_args(sb_arg_t *args, size_t len);
]]
sysbench.cmdline.ARG_NULL = ffi.C.SB_ARG_TYPE_NULL
sysbench.cmdline.ARG_BOOL = ffi.C.SB_ARG_TYPE_BOOL
sysbench.cmdline.ARG_INT = ffi.C.SB_ARG_TYPE_INT
sysbench.cmdline.ARG_SIZE = ffi.C.SB_ARG_TYPE_SIZE
sysbench.cmdline.ARG_DOUBLE = ffi.C.SB_ARG_TYPE_DOUBLE
sysbench.cmdline.ARG_STRING = ffi.C.SB_ARG_TYPE_STRING
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
local arg_types = {
boolean = sysbench.cmdline.ARG_BOOL,
string = sysbench.cmdline.ARG_STRING,
number = sysbench.cmdline.ARG_DOUBLE,
table = sysbench.cmdline.ARG_LIST
}
-- Parse command line options definitions, if present in the script as a 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()
if sysbench.option_defs == nil then
return true
end
local t = type(sysbench.option_defs)
assert(t == "table", "wrong type for sysbench.option_defs: " .. t)
local i = 0
for name, def in pairs(sysbench.option_defs) do
i = i+1
end
local args = ffi.new('sb_arg_t[?]', i)
i = 0
for name, def in pairs(sysbench.option_defs) do
-- name
assert(type(name) == "string", "wrong table structure in " ..
"sysbench.option_defs")
args[i].name = name
-- description
assert(def[1] ~= nil, "nil description for option " .. name)
args[i].desc = def[1]
if type(def[2]) == "table" then
assert(type(def[3]) == "nil" or
type(def[3]) == sysbench.cmdline.ARG_LIST,
"wrong type for list option " .. name)
args[i].value = table.concat(def[2], ',')
else
if type(def[2]) == "boolean" then
args[i].value = def[2] and 'on' or 'off'
elseif type(def[2]) == "number" then
args[i].value = tostring(def[2])
else
args[i].value = def[2]
end
end
-- type
local t = def[3]
if t == nil then
if def[2] ~= nil then
-- Try to determine the type by the default value
t = arg_types[type(def[2])]
else
t = sysbench.cmdline.ARG_STRING
end
end
assert(t ~= nil, "cannot determine type for option " .. name)
args[i].type = t
-- validation function
args[i].validate = def[4]
i = i + 1
end
return ffi.C.sb_lua_set_test_args(args, i) == 0
end

View File

@ -20,6 +20,10 @@
# include "config.h"
#endif
#ifdef HAVE_LIBGEN_H
# include <libgen.h>
#endif
#include "sb_lua.h"
#include "lua.h"
#include "lualib.h"
@ -33,9 +37,10 @@
/*
Auto-generated headers for internal scripts. If you add a new header here,
make sure it is also added to the internal_sources array below.
make sure it is also added to the internal_scripts array below.
*/
#include "lua/internal/sysbench.lua.h"
#include "lua/internal/sysbench.cmdline.lua.h"
#include "lua/internal/sysbench.rand.lua.h"
#include "lua/internal/sysbench.sql.lua.h"
@ -92,6 +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);
/* Lua interpreter states */
@ -99,8 +105,6 @@ static lua_State **states CK_CC_CACHELINE;
static sb_test_t sbtest CK_CC_CACHELINE;
static const char *sb_lua_script_path CK_CC_CACHELINE;
static TLS sb_lua_ctxt_t *tls_lua_ctxt CK_CC_CACHELINE;
/* Database driver */
@ -110,6 +114,7 @@ static TLS db_driver_t *db_driver;
static internal_script_t internal_scripts[] = {
{"sysbench.rand.lua", sysbench_rand_lua, &sysbench_rand_lua_len},
{"sysbench.lua", sysbench_lua, &sysbench_lua_len},
{"sysbench.cmdline.lua", sysbench_cmdline_lua, &sysbench_cmdline_lua_len},
{"sysbench.sql.lua", sysbench_sql_lua, &sysbench_sql_lua_len},
{NULL, NULL, 0}
};
@ -159,6 +164,8 @@ static int sb_lua_db_free_results(lua_State *);
static unsigned int sb_lua_table_size(lua_State *, int);
static int read_option_defs(lua_State *L);
static void call_error(lua_State *L, const char *name)
{
const char * const err = lua_tostring(L, -1);
@ -182,17 +189,36 @@ static bool func_available(lua_State *L, const char *func)
return rc;
}
static void xfree(const void *ptr)
{
if (ptr != NULL)
free((void *) ptr);
}
/* Load a specified Lua script */
sb_test_t *sb_load_lua(const char *testname)
{
sb_lua_script_path = testname;
if (testname != NULL)
{
char *tmp = strdup(testname);
sbtest.sname = strdup(basename(tmp));
sbtest.lname = tmp;
}
else
{
sbtest.sname = strdup("<stdin>");
sbtest.lname = NULL;
}
/* Initialize global interpreter state */
gstate = sb_lua_new_state(-1);
if (gstate == NULL)
goto error;
if (read_option_defs(gstate))
goto error;
/* Test commands */
if (func_available(gstate, PREPARE_FUNC))
sbtest.cmds.prepare = &sb_lua_cmd_prepare;
@ -225,8 +251,10 @@ sb_test_t *sb_load_lua(const char *testname)
error:
sb_lua_close_state(gstate);
if (states != NULL)
free(states);
xfree(states);
xfree(sbtest.sname);
xfree(sbtest.lname);
return NULL;
}
@ -248,7 +276,7 @@ int sb_lua_op_init(void)
if (!func_available(gstate, EVENT_FUNC))
{
log_text(LOG_FATAL, "cannot find the event() function in %s",
sb_lua_script_path);
sbtest.sname);
return 1;
}
@ -325,8 +353,7 @@ void sb_lua_op_print_stats(sb_stat_t type)
int sb_lua_op_done(void)
{
if (states != NULL)
free(states);
xfree(states);
lua_getglobal(gstate, DONE_FUNC);
if (!lua_isnil(gstate, -1))
@ -338,6 +365,23 @@ int sb_lua_op_done(void)
}
}
sb_lua_close_state(gstate);
if (sbtest.args != NULL)
{
for (size_t i = 0; sbtest.args[i].name != NULL; i++)
{
xfree(sbtest.args[i].name);
xfree(sbtest.args[i].desc);
xfree(sbtest.args[i].value);
}
free(sbtest.args);
}
xfree(sbtest.sname);
xfree(sbtest.lname);
return 0;
}
@ -450,12 +494,24 @@ static void sb_lua_set_paths(lua_State *L)
}
/* Export command line options */
static int export_options(lua_State *L)
{
sb_list_item_t *pos;
option_t *opt;
char *tmp;
/*
Export options to the 'sysbench.opt' table, if the script declares supported
options with sysbench.option_defs, or to the global namespace otherwise
*/
if (sbtest.args != NULL)
{
lua_getglobal(L, "sysbench");
lua_pushliteral(L, "opt");
lua_newtable(L);
}
pos = sb_options_enum_start();
while ((pos = sb_options_enum_next(pos, &opt)) != NULL)
{
@ -465,13 +521,20 @@ static int export_options(lua_State *L)
which case name collisions with user-defined functions and variables might
occur. For example, the --help option might redefine the help() function.
*/
lua_getglobal(L, opt->name);
if (!lua_isnil(L, -1))
if (sbtest.args == NULL)
{
lua_getglobal(L, opt->name);
if (!lua_isnil(L, -1))
{
lua_pop(L, 1);
continue;
}
lua_pop(L, 1);
continue;
}
lua_pop(L, 1);
else
{
lua_pushstring(L, opt->name);
}
switch (opt->type)
{
@ -481,8 +544,8 @@ static int export_options(lua_State *L)
case SB_ARG_TYPE_INT:
lua_pushnumber(L, sb_opt_to_int(opt));
break;
case SB_ARG_TYPE_FLOAT:
lua_pushnumber(L, sb_opt_to_float(opt));
case SB_ARG_TYPE_DOUBLE:
lua_pushnumber(L, sb_opt_to_double(opt));
break;
case SB_ARG_TYPE_SIZE:
lua_pushnumber(L, sb_opt_to_size(opt));
@ -492,11 +555,20 @@ static int export_options(lua_State *L)
lua_pushstring(L, tmp ? tmp : "");
break;
case SB_ARG_TYPE_LIST:
/*FIXME: should be exported as tables */
lua_pushnil(L);
lua_newtable(L);
sb_list_item_t *val;
int count = 1;
SB_LIST_FOR_EACH(val, sb_opt_to_list(opt))
{
lua_pushstring(L, SB_LIST_ENTRY(val, value_t, listitem)->data);
lua_rawseti(L, -2, count++);
}
break;
case SB_ARG_TYPE_FILE:
/* FIXME: no need to export anything */
/* no need to export anything */
lua_pushnil(L);
break;
default:
@ -506,15 +578,78 @@ static int export_options(lua_State *L)
break;
}
lua_setglobal(L, opt->name);
/* set var = value */
if (sbtest.args != NULL)
lua_settable(L, -3);
else
lua_setglobal(L, opt->name);
}
if (sbtest.args != NULL)
lua_settable(L, -3); /* set sysbench.opt */
return 0;
}
/* Create a deep copy of the 'args' array and set it to sbtest.args */
int sb_lua_set_test_args(sb_arg_t *args, size_t len)
{
sbtest.args = malloc((len + 1) * sizeof(sb_arg_t));
for (size_t i = 0; i < len; i++)
{
sbtest.args[i].name = strdup(args[i].name);
sbtest.args[i].desc = strdup(args[i].desc);
sbtest.args[i].type = args[i].type;
sbtest.args[i].value = args[i].value != NULL ? strdup(args[i].value) : NULL;
sbtest.args[i].validate = args[i].validate;
}
sbtest.args[len] = (sb_arg_t) {.name = NULL};
return 0;
}
/*
Parse command line options definitions, if present in the script as a
'sysbench.option_defs' table. If there was a parsing error, return 1. Return 0
on success.
*/
static int read_option_defs(lua_State *L)
{
lua_getglobal(L, "sysbench");
lua_getfield(L, -1, "cmdline");
lua_getfield(L, -1, "read_option_defs");
if (!lua_isfunction(L, -1))
{
log_text(LOG_WARNING,
"Cannot find the sysbench.cmdline.read_option_defs() function");
lua_pop(L, 2);
return 1;
}
if (lua_pcall(L, 0, 1, 0) != 0)
{
call_error(L, "sysbench.cmdline.read_option_defs");
lua_pop(L, 3);
return 1;
}
int rc = lua_toboolean(L, -1) == 0;
lua_pop(L, 4);
return rc;
}
/* Allocate and initialize new interpreter state */
lua_State *sb_lua_new_state(int thread_id)
static lua_State *sb_lua_new_state(int thread_id)
{
lua_State *L;
@ -577,7 +712,7 @@ lua_State *sb_lua_new_state(int thread_id)
lua_pushliteral(L, "test");
lua_newtable(L);
sb_lua_var_string(L, "path", sb_lua_script_path);
sb_lua_var_string(L, "path", sbtest.lname);
lua_settable(L, -3); /* sysbench.test */
@ -591,7 +726,7 @@ lua_State *sb_lua_new_state(int thread_id)
int rc;
if ((rc = luaL_loadfile(L, sb_lua_script_path)))
if ((rc = luaL_loadfile(L, sbtest.lname)))
{
lua_error(L);
return NULL;
@ -642,6 +777,8 @@ static int execute_command(const char *cmd)
return 1;
}
lua_pop(gstate, 1);
return 0;
}
@ -707,7 +844,7 @@ static void throw_restart_event(lua_State *L)
{
log_text(LOG_DEBUG, "Ignored error encountered, restarting transaction");
lua_newtable(L);
lua_createtable(L, 0, 1);
lua_pushliteral(L, "errcode");
lua_pushnumber(L, SB_LUA_ERROR_RESTART_EVENT);
lua_settable(L, -3);

View File

@ -66,7 +66,7 @@ static char *opt_formats[] = {
"[=on|off]", /* SB_ARG_TYPE_FLAG */
"=N", /* SB_ARG_TYPE_INT */
"=SIZE", /* SB_ARG_TYPE_SIZE */
"=N", /* SB_ARG_TYPE_FLOAT */
"=N", /* SB_ARG_TYPE_DOUBLE */
"=STRING", /* SB_ARG_TYPE_STRING */
"=[LIST,...]", /* SB_ARG_TYPE_LIST */
"=FILENAME" /* SB_ARG_TYPE_FILE */
@ -144,7 +144,7 @@ int set_option(const char *name, const char *value, sb_arg_type_t type)
break;
case SB_ARG_TYPE_INT:
case SB_ARG_TYPE_SIZE:
case SB_ARG_TYPE_FLOAT:
case SB_ARG_TYPE_DOUBLE:
case SB_ARG_TYPE_STRING:
add_value(&opt->values, value);
break;
@ -326,24 +326,23 @@ unsigned long long sb_get_value_size(const char *name)
}
float sb_opt_to_float(option_t *opt)
double sb_opt_to_double(option_t *opt)
{
value_t *val;
sb_list_item_t *pos;
float res;
double res;
SB_LIST_FOR_EACH(pos, &opt->values)
{
val = SB_LIST_ENTRY(pos, value_t, listitem);
if (sscanf(val->data, "%f", &res) < 1)
res = 0;
res = strtod(val->data, NULL);
}
return res;
}
float sb_get_value_float(const char *name)
double sb_get_value_double(const char *name)
{
option_t *opt;
@ -351,7 +350,7 @@ float sb_get_value_float(const char *name)
if (opt == NULL)
return 0;
return sb_opt_to_float(opt);
return sb_opt_to_double(opt);
}

View File

@ -41,7 +41,7 @@ typedef enum
SB_ARG_TYPE_BOOL,
SB_ARG_TYPE_INT,
SB_ARG_TYPE_SIZE,
SB_ARG_TYPE_FLOAT,
SB_ARG_TYPE_DOUBLE,
SB_ARG_TYPE_STRING,
SB_ARG_TYPE_LIST,
SB_ARG_TYPE_FILE,
@ -56,8 +56,8 @@ typedef struct
{
const char *name;
const char *desc;
sb_arg_type_t type;
const char *value;
sb_arg_type_t type;
sb_arg_validate_t *validate;
} sb_arg_t;
@ -103,7 +103,7 @@ int sb_get_value_int(const char *name);
unsigned long long sb_get_value_size(const char *name);
float sb_get_value_float(const char *name);
double sb_get_value_double(const char *name);
char *sb_get_value_string(const char *name);
@ -117,7 +117,7 @@ int sb_opt_to_int(option_t *);
unsigned long long sb_opt_to_size(option_t *);
float sb_opt_to_float(option_t *);
double sb_opt_to_double(option_t *);
char *sb_opt_to_string(option_t *);

View File

@ -46,18 +46,23 @@ int sb_rand_seed; /* optional seed set on the command line */
static sb_arg_t rand_args[] =
{
{"rand-type", "random numbers distribution {uniform,gaussian,special,pareto}",
SB_ARG_TYPE_STRING, "special"},
{"rand-spec-iter", "number of iterations used for numbers generation", SB_ARG_TYPE_INT, "12"},
{"rand-spec-pct", "percentage of values to be treated as 'special' (for special distribution)",
SB_ARG_TYPE_INT, "1"},
{"rand-spec-res", "percentage of 'special' values to use (for special distribution)",
SB_ARG_TYPE_INT, "75"},
{"rand-seed", "seed for random number generator. When 0, the current time is "
"used as a RNG seed.", SB_ARG_TYPE_INT, "0"},
{"rand-pareto-h", "parameter h for pareto distibution", SB_ARG_TYPE_FLOAT,
"0.2"},
{NULL, NULL, SB_ARG_TYPE_NULL, NULL}
SB_OPT("rand-type",
"random numbers distribution {uniform,gaussian,special,pareto}",
"special", STRING),
SB_OPT("rand-spec-iter",
"number of iterations used for numbers generation", "12", INT),
SB_OPT("rand-spec-pct",
"percentage of values to be treated as 'special' "
"(for special distribution)", "1", INT),
SB_OPT("rand-spec-res",
"percentage of 'special' values to use "
"(for special distribution)", "75", INT),
SB_OPT("rand-seed",
"seed for random number generator. When 0, the current time is "
"used as a RNG seed.", "0", INT),
SB_OPT("rand-pareto-h", "parameter h for pareto distibution", "0.2", DOUBLE),
SB_OPT_END
};
static rand_dist_t rand_type;
@ -143,7 +148,7 @@ int sb_rand_init(void)
rand_res = sb_get_value_int("rand-spec-res");
rand_res_mult = 100.0 / (100.0 - rand_res);
pareto_h = sb_get_value_float("rand-pareto-h");
pareto_h = sb_get_value_double("rand-pareto-h");
pareto_power = log(pareto_h) / log(1.0-pareto_h);
/* Seed PRNG for the main thread. Worker thread do their own seeding */

View File

@ -373,7 +373,10 @@ static int parse_test_arguments(sb_test_t *test, int argc, char *argv[])
latter case we just export all unrecognized options as strings.
*/
if (parse_option(argv[i]+2, test->args == NULL))
return 1;
{
fprintf(stderr, "invalid option: %s\n", argv[i]);
return 1;
}
argv[i] = NULL;
}
@ -1250,7 +1253,12 @@ int main(int argc, char *argv[])
strerror(errno));
return EXIT_FAILURE;
}
test = sb_load_lua(sb_globals.testname);
if ((test = sb_load_lua(sb_globals.testname)) == NULL)
{
fprintf(stderr, "Script execution failed");
return EXIT_FAILURE;
}
if (sb_globals.cmdname == NULL)
{

View File

@ -233,7 +233,7 @@ static sb_arg_t fileio_args[] = {
"fsync", STRING),
SB_OPT("file-merged-requests", "merge at most this number of IO requests "
"if possible (0 - don't merge)", "0", INT),
SB_OPT("file-rw-ratio", "reads/writes ratio for combined test", "1.5", FLOAT),
SB_OPT("file-rw-ratio", "reads/writes ratio for combined test", "1.5", DOUBLE),
SB_OPT_END
};
@ -1907,7 +1907,7 @@ int parse_arguments(void)
return 1;
}
file_rw_ratio = sb_get_value_float("file-rw-ratio");
file_rw_ratio = sb_get_value_double("file-rw-ratio");
if (file_rw_ratio < 0)
{
log_text(LOG_FATAL, "Invalid value for --file-rw-ratio: %f.", file_rw_ratio);

View File

@ -101,5 +101,5 @@ Error handling
> end
> EOF
$ sysbench $SB_ARGS run
FATAL: cannot find the event() function in */api_basic.lua (glob)
FATAL: cannot find the event() function in *api_basic.lua (glob)
[1]

View File

@ -86,4 +86,124 @@
Threads fairness:
events (avg/stddev): 1.0000/0.00
execution time (avg/stddev): 0.0000/0.00
########################################################################
Command line options tests
########################################################################
$ cat >cmdline.lua <<EOF
> sysbench.option_defs = {
> str_opt1 = {"str_opt1 description"},
> str_opt2 = {"str_opt2 description", "opt2"},
> str_opt3 = {"str_opt3 description", "opt3", sysbench.cmdline.ARG_STRING},
> bool_opt1 = {"bool_opt1 description", false},
> bool_opt2 = {"bool_opt2 description", true},
> bool_opt3 = {"bool_opt3 description", nil, sysbench.cmdline.ARG_BOOL},
> int_opt1 = {"int_opt1 description", 10},
> int_opt2 = {"int_opt2 description", nil, sysbench.cmdline.ARG_INT},
> int_opt3 = {"int_opt3 description", 20, sysbench.cmdline.ARG_INT},
> float_opt1 = {"float_opt1 description", 3.14, sysbench.cmdline.ARG_DOUBLE},
> float_opt2 = {"float_opt2 description", 0.2},
> list_opt1 = {"list_opt1 description", {"foo", "bar"}},
> list_opt2 = {"list_opt2 description", nil, sysbench.cmdline.ARG_LIST},
> ["dash-opt"] = {"dash-opt desc", "dash-opt val"}
> }
>
> function help()
> local o = sysbench.opt
> print(o.str_opt1)
> print(o.str_opt2)
> print(o.str_opt3)
> print(o.bool_opt1)
> print(o.bool_opt2)
> print(o.bool_opt3)
> print(o.int_opt1)
> print(o.int_opt2)
> print(o.float_opt1)
> print(o.float_opt2)
> print(o.list_opt1)
> print(o.list_opt2)
> print(o.dash_opt)
> end
> EOF
$ sysbench cmdline.lua
sysbench * (glob)
$ sysbench cmdline.lua help
sysbench * (glob)
cmdline.lua options:
--dash-opt=STRING dash-opt desc [dash-opt val]
--str_opt1=STRING str_opt1 description
--bool_opt3[=on|off] bool_opt3 description
--int_opt2=N int_opt2 description
--list_opt2=[LIST,...] list_opt2 description
--float_opt2=N float_opt2 description [0.2]
--str_opt2=STRING str_opt2 description [opt2]
--list_opt1=[LIST,...] list_opt1 description [foo,bar]
--str_opt3=STRING str_opt3 description [opt3]
--int_opt3=N int_opt3 description [20]
--bool_opt1[=on|off] bool_opt1 description [off]
--float_opt1=N float_opt1 description [3.14]
--bool_opt2[=on|off] bool_opt2 description [on]
--int_opt1=N int_opt1 description [10]
opt2
opt3
false
true
true
10
0
3.14
0.2
table: 0x* (glob)
table: 0x* (glob)
dash-opt val
$ sysbench cmdline.lua prepare
sysbench * (glob)
'cmdline.lua' test does not have the 'prepare' command.
[1]
$ sysbench --non-existing-option=3 cmdline.lua prepare
sysbench * (glob)
invalid option: --non-existing-option=3
[1]
$ sysbench cmdline.lua run
sysbench * (glob)
FATAL: cannot find the event() function in cmdline.lua
[1]
$ sysbench cmdline.lua cleanup
sysbench * (glob)
'cmdline.lua' test does not have the 'cleanup' command.
[1]
$ cat >cmdline.lua <<EOF
> sysbench.option_defs = {
> {},
> }
>
> function help()
> end
> EOF
$ sysbench cmdline.lua help
sysbench * (glob)
FATAL: `sysbench.cmdline.read_option_defs' function failed: [string "sysbench.cmdline.lua"]:95: wrong table structure in sysbench.option_defs
Script execution failed (no-eol)
[1]
$ sysbench fileio --invalid-option prepare
sysbench * (glob)
invalid option: --invalid-option
[1]