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:
3
.gitignore
vendored
3
.gitignore
vendored
@ -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
|
||||
|
||||
@ -301,6 +301,7 @@ sys/shm.h \
|
||||
thread.h \
|
||||
unistd.h \
|
||||
limits.h \
|
||||
libgen.h \
|
||||
])
|
||||
|
||||
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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=)
|
||||
|
||||
139
sysbench/lua/internal/sysbench.cmdline.lua
Normal file
139
sysbench/lua/internal/sysbench.cmdline.lua
Normal 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
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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 *);
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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]
|
||||
|
||||
Reference in New Issue
Block a user