Skip to content

Commit

Permalink
command-line: add ovs_cmdl_context
Browse files Browse the repository at this point in the history
I started working on a new command line utility that used this shared
code.  I wanted the ability to pass some data from common
initialization code to all of the commands.  You can find a similar
pattern in ovs-vsctl.

This patch updates the command handler to take a new struct,
ovs_cmdl_context, instead of argc and argv directly.  It includes argc
and argv, but also includes an opaque type (void *), where the user of
this API can attach its custom data it wants passed along to command
handlers.

This patch affected the ovstest sub-programs, as well.  The patch
includes a bit of an odd hack to OVSTEST_REGISTER() to avoid making
the main() function of the sub-programs take a ovs_cmdl_context.
The test main() functions still receive argc and argv directly, as
that seems more natural.  The test-subprograms themselves are able to
make use of a context internally, though.

Signed-off-by: Russell Bryant <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
russellb authored and blp committed Mar 17, 2015
1 parent 1774d76 commit 1636c76
Show file tree
Hide file tree
Showing 16 changed files with 504 additions and 429 deletions.
20 changes: 13 additions & 7 deletions lib/command-line.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,27 +92,33 @@ ovs_cmdl_print_options(const struct option options[])
* null pointer.
*
* Command-line options should be stripped off, so that a typical invocation
* looks like "run_command(argc - optind, argv + optind, my_commands);". */
* looks like:
* struct ovs_cmdl_context ctx = {
* .argc = argc - optind,
* .argv = argv + optind,
* };
* ovs_cmdl_run_command(&ctx, my_commands);
* */
void
ovs_cmdl_run_command(int argc, char *argv[], const struct ovs_cmdl_command commands[])
ovs_cmdl_run_command(struct ovs_cmdl_context *ctx, const struct ovs_cmdl_command commands[])
{
const struct ovs_cmdl_command *p;

if (argc < 1) {
if (ctx->argc < 1) {
ovs_fatal(0, "missing command name; use --help for help");
}

for (p = commands; p->name != NULL; p++) {
if (!strcmp(p->name, argv[0])) {
int n_arg = argc - 1;
if (!strcmp(p->name, ctx->argv[0])) {
int n_arg = ctx->argc - 1;
if (n_arg < p->min_args) {
VLOG_FATAL( "'%s' command requires at least %d arguments",
p->name, p->min_args);
} else if (n_arg > p->max_args) {
VLOG_FATAL("'%s' command takes at most %d arguments",
p->name, p->max_args);
} else {
p->handler(argc, argv);
p->handler(ctx);
if (ferror(stdout)) {
VLOG_FATAL("write to stdout failed");
}
Expand All @@ -124,7 +130,7 @@ ovs_cmdl_run_command(int argc, char *argv[], const struct ovs_cmdl_command comma
}
}

VLOG_FATAL("unknown command '%s'; use --help for help", argv[0]);
VLOG_FATAL("unknown command '%s'; use --help for help", ctx->argv[0]);
}

/* Process title. */
Expand Down
16 changes: 14 additions & 2 deletions lib/command-line.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,30 @@

struct option;

/* Command handler context */
struct ovs_cmdl_context {
/* number of command line arguments */
int argc;
/* array of command line arguments */
char **argv;
/* private context data defined by the API user */
void *pvt;
};

typedef void (*ovs_cmdl_handler)(struct ovs_cmdl_context *);

struct ovs_cmdl_command {
const char *name;
const char *usage;
int min_args;
int max_args;
void (*handler)(int argc, char *argv[]);
ovs_cmdl_handler handler;
};

char *ovs_cmdl_long_options_to_short_options(const struct option *options);
void ovs_cmdl_print_options(const struct option *options);
void ovs_cmdl_print_commands(const struct ovs_cmdl_command *commands);
void ovs_cmdl_run_command(int argc, char *argv[], const struct ovs_cmdl_command[]);
void ovs_cmdl_run_command(struct ovs_cmdl_context *, const struct ovs_cmdl_command[]);

void ovs_cmdl_proctitle_init(int argc, char **argv);
#if defined(__FreeBSD__) || defined(__NetBSD__)
Expand Down
63 changes: 33 additions & 30 deletions ovsdb/ovsdb-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,13 @@ static const char *default_schema(void);
int
main(int argc, char *argv[])
{
struct ovs_cmdl_context ctx = { .argc = 0, };
set_program_name(argv[0]);
parse_options(argc, argv);
fatal_ignore_sigpipe();
ovs_cmdl_run_command(argc - optind, argv + optind, get_all_commands());
ctx.argc = argc - optind;
ctx.argv = argv + optind;
ovs_cmdl_run_command(&ctx, get_all_commands());
return 0;
}

Expand Down Expand Up @@ -187,10 +190,10 @@ check_ovsdb_error(struct ovsdb_error *error)
}

static void
do_create(int argc, char *argv[])
do_create(struct ovs_cmdl_context *ctx)
{
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
const char *schema_file_name = argc >= 3 ? argv[2] : default_schema();
const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] : default_db();
const char *schema_file_name = ctx->argc >= 3 ? ctx->argv[2] : default_schema();
struct ovsdb_schema *schema;
struct ovsdb_log *log;
struct json *json;
Expand Down Expand Up @@ -272,20 +275,20 @@ compact_or_convert(const char *src_name_, const char *dst_name_,
}

static void
do_compact(int argc, char *argv[])
do_compact(struct ovs_cmdl_context *ctx)
{
const char *db = argc >= 2 ? argv[1] : default_db();
const char *target = argc >= 3 ? argv[2] : NULL;
const char *db = ctx->argc >= 2 ? ctx->argv[1] : default_db();
const char *target = ctx->argc >= 3 ? ctx->argv[2] : NULL;

compact_or_convert(db, target, NULL, "compacted by ovsdb-tool "VERSION);
}

static void
do_convert(int argc, char *argv[])
do_convert(struct ovs_cmdl_context *ctx)
{
const char *db = argc >= 2 ? argv[1] : default_db();
const char *schema = argc >= 3 ? argv[2] : default_schema();
const char *target = argc >= 4 ? argv[3] : NULL;
const char *db = ctx->argc >= 2 ? ctx->argv[1] : default_db();
const char *schema = ctx->argc >= 3 ? ctx->argv[2] : default_schema();
const char *target = ctx->argc >= 4 ? ctx->argv[3] : NULL;
struct ovsdb_schema *new_schema;

check_ovsdb_error(ovsdb_schema_from_file(schema, &new_schema));
Expand All @@ -295,10 +298,10 @@ do_convert(int argc, char *argv[])
}

static void
do_needs_conversion(int argc, char *argv[])
do_needs_conversion(struct ovs_cmdl_context *ctx)
{
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
const char *schema_file_name = argc >= 3 ? argv[2] : default_schema();
const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] : default_db();
const char *schema_file_name = ctx->argc >= 3 ? ctx->argv[2] : default_schema();
struct ovsdb_schema *schema1, *schema2;

check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema1));
Expand All @@ -309,9 +312,9 @@ do_needs_conversion(int argc, char *argv[])
}

static void
do_db_version(int argc, char *argv[])
do_db_version(struct ovs_cmdl_context *ctx)
{
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] : default_db();
struct ovsdb_schema *schema;

check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema));
Expand All @@ -320,9 +323,9 @@ do_db_version(int argc, char *argv[])
}

static void
do_db_cksum(int argc OVS_UNUSED, char *argv[])
do_db_cksum(struct ovs_cmdl_context *ctx)
{
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] : default_db();
struct ovsdb_schema *schema;

check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema));
Expand All @@ -331,9 +334,9 @@ do_db_cksum(int argc OVS_UNUSED, char *argv[])
}

static void
do_schema_version(int argc, char *argv[])
do_schema_version(struct ovs_cmdl_context *ctx)
{
const char *schema_file_name = argc >= 2 ? argv[1] : default_schema();
const char *schema_file_name = ctx->argc >= 2 ? ctx->argv[1] : default_schema();
struct ovsdb_schema *schema;

check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
Expand All @@ -342,9 +345,9 @@ do_schema_version(int argc, char *argv[])
}

static void
do_schema_cksum(int argc, char *argv[])
do_schema_cksum(struct ovs_cmdl_context *ctx)
{
const char *schema_file_name = argc >= 2 ? argv[1] : default_schema();
const char *schema_file_name = ctx->argc >= 2 ? ctx->argv[1] : default_schema();
struct ovsdb_schema *schema;

check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
Expand All @@ -371,15 +374,15 @@ transact(bool read_only, int argc, char *argv[])
}

static void
do_query(int argc, char *argv[])
do_query(struct ovs_cmdl_context *ctx)
{
transact(true, argc, argv);
transact(true, ctx->argc, ctx->argv);
}

static void
do_transact(int argc, char *argv[])
do_transact(struct ovs_cmdl_context *ctx)
{
transact(false, argc, argv);
transact(false, ctx->argc, ctx->argv);
}

static void
Expand Down Expand Up @@ -495,9 +498,9 @@ print_db_changes(struct shash *tables, struct shash *names,
}

static void
do_show_log(int argc, char *argv[])
do_show_log(struct ovs_cmdl_context *ctx)
{
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] : default_db();
struct shash names;
struct ovsdb_log *log;
struct ovsdb_schema *schema;
Expand Down Expand Up @@ -558,13 +561,13 @@ do_show_log(int argc, char *argv[])
}

static void
do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
do_help(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
usage();
}

static void
do_list_commands(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
do_list_commands(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
ovs_cmdl_print_commands(get_all_commands());
}
Expand Down
10 changes: 7 additions & 3 deletions tests/ovstest.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ flush_help_string(struct ds *ds)
}

static void
help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
help(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
const struct ovs_cmdl_command *p;
struct ds test_names = DS_EMPTY_INITIALIZER;
Expand Down Expand Up @@ -92,7 +92,7 @@ add_top_level_commands(void)
}

void
ovstest_register(const char *test_name, ovstest_func f)
ovstest_register(const char *test_name, ovs_cmdl_handler f)
{
struct ovs_cmdl_command test_cmd;

Expand Down Expand Up @@ -125,7 +125,11 @@ main(int argc, char *argv[])

add_top_level_commands();
if (argc > 1) {
ovs_cmdl_run_command(argc - 1, argv + 1, commands);
struct ovs_cmdl_context ctx = {
.argc = argc - 1,
.argv = argv + 1,
};
ovs_cmdl_run_command(&ctx, commands);
}
cleanup();

Expand Down
12 changes: 10 additions & 2 deletions tests/ovstest.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include "compiler.h"

#include "command-line.h"

/* Overview
* ========
*
Expand All @@ -41,7 +43,8 @@
*/

typedef void (*ovstest_func)(int argc, char *argv[]);
void ovstest_register(const char *test_name, ovstest_func f);

void ovstest_register(const char *test_name, ovs_cmdl_handler f);

/* Usage
* =====
Expand Down Expand Up @@ -72,8 +75,13 @@ void ovstest_register(const char *test_name, ovstest_func f);
* OVSTEST_REGISTER("my-test", my_test_main);
*/
#define OVSTEST_REGISTER(name, function) \
static void \
ovstest_wrapper_##function##__(struct ovs_cmdl_context *ctx) \
{ \
function(ctx->argc, ctx->argv); \
} \
OVS_CONSTRUCTOR(register_##function) { \
ovstest_register(name, function); \
ovstest_register(name, ovstest_wrapper_##function##__); \
}

#endif
13 changes: 9 additions & 4 deletions tests/test-bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,17 @@ run_test(void (*function)(void))
}

static void
run_tests(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
run_tests(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
run_test(test_bitmap_equal);
run_test(test_bitmap_scan);
printf("\n");
}

static void
run_benchmarks(int argc OVS_UNUSED, char *argv[])
run_benchmarks(struct ovs_cmdl_context *ctx)
{
int n_iter = strtol(argv[1], NULL, 10);
int n_iter = strtol(ctx->argv[1], NULL, 10);
struct timeval start;

xgettimeofday(&start);
Expand All @@ -157,8 +157,13 @@ static const struct ovs_cmdl_command commands[] = {
static void
test_bitmap_main(int argc, char *argv[])
{
struct ovs_cmdl_context ctx = {
.argc = argc - 1,
.argv = argv + 1,
};

set_program_name(argv[0]);
ovs_cmdl_run_command(argc - 1, argv + 1, commands);
ovs_cmdl_run_command(&ctx, commands);
}

OVSTEST_REGISTER("test-bitmap", test_bitmap_main);
Loading

0 comments on commit 1636c76

Please sign in to comment.