X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=tests%2Ftest-ovsdb.c;h=670a141faa6ef445d5fe070538904ed059e7be58;hb=HEAD;hp=672759be8be49fe3e1336b518cc24a3028d081b1;hpb=ca247927bd5445e77391ffb98f713b2cd258c017;p=cascardo%2Fovs.git diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 672759be8..670a141fa 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ #include "ovsdb/ovsdb.h" #include "ovsdb/query.h" #include "ovsdb/row.h" +#include "ovsdb/server.h" #include "ovsdb/table.h" #include "ovsdb/transaction.h" #include "ovsdb/trigger.h" @@ -48,34 +49,41 @@ #include "tests/idltest.h" #include "timeval.h" #include "util.h" -#include "vlog.h" +#include "openvswitch/vlog.h" -static struct command all_commands[]; +struct test_ovsdb_pvt_context { + bool track; +}; -static void usage(void) NO_RETURN; -static void parse_options(int argc, char *argv[]); +OVS_NO_RETURN static void usage(void); +static void parse_options(int argc, char *argv[], + struct test_ovsdb_pvt_context *pvt); +static struct ovs_cmdl_command *get_all_commands(void); int main(int argc, char *argv[]) { + struct test_ovsdb_pvt_context pvt = {.track = false}; + struct ovs_cmdl_context ctx = { .argc = 0, .pvt = &pvt}; set_program_name(argv[0]); - time_init(); - vlog_init(); - parse_options(argc, argv); - run_command(argc - optind, argv + optind, all_commands); + parse_options(argc, argv, &pvt); + ctx.argc = argc - optind; + ctx.argv = argv + optind; + ovs_cmdl_run_command(&ctx, get_all_commands()); return 0; } static void -parse_options(int argc, char *argv[]) +parse_options(int argc, char *argv[], struct test_ovsdb_pvt_context *pvt) { - static struct option long_options[] = { - {"timeout", required_argument, 0, 't'}, - {"verbose", optional_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0}, + static const struct option long_options[] = { + {"timeout", required_argument, NULL, 't'}, + {"verbose", optional_argument, NULL, 'v'}, + {"change-track", optional_argument, NULL, 'c'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}, }; - char *short_options = long_options_to_short_options(long_options); + char *short_options = ovs_cmdl_long_options_to_short_options(long_options); for (;;) { unsigned long int timeout; @@ -104,6 +112,10 @@ parse_options(int argc, char *argv[]) vlog_set_verbosity(optarg); break; + case 'c': + pvt->track = true; + break; + case '?': exit(EXIT_FAILURE); @@ -121,6 +133,10 @@ usage(void) "usage: %s [OPTIONS] COMMAND [ARG...]\n\n" " log-io FILE FLAGS COMMAND...\n" " open FILE with FLAGS, run COMMANDs\n" + " default-atoms\n" + " test ovsdb_atom_default()\n" + " default-data\n" + " test ovsdb_datum_default()\n" " parse-atomic-type TYPE\n" " parse TYPE as OVSDB atomic type, and re-serialize\n" " parse-base-type TYPE\n" @@ -139,7 +155,7 @@ usage(void) " parse string DATUMs as data of given TYPE, and re-serialize\n" " parse-column NAME OBJECT\n" " parse column NAME with info OBJECT, and re-serialize\n" - " parse-table NAME OBJECT\n" + " parse-table NAME OBJECT [DEFAULT-IS-ROOT]\n" " parse table NAME with info OBJECT\n" " parse-row TABLE ROW..., and re-serialize\n" " parse each ROW of defined TABLE\n" @@ -186,7 +202,9 @@ usage(void) vlog_usage(); printf("\nOther options:\n" " -t, --timeout=SECS give up after SECS seconds\n" - " -h, --help display this help message\n"); + " -h, --help display this help message\n" + " -c, --change-track used with the 'idl' command to\n" + " enable tracking of IDL changes\n"); exit(EXIT_SUCCESS); } @@ -254,10 +272,10 @@ die_if_error(char *error) /* Command implementations. */ static void -do_log_io(int argc, char *argv[]) +do_log_io(struct ovs_cmdl_context *ctx) { - const char *name = argv[1]; - char *mode_string = argv[2]; + const char *name = ctx->argv[1]; + char *mode_string = ctx->argv[2]; struct ovsdb_error *error; enum ovsdb_log_open_mode mode; @@ -277,8 +295,8 @@ do_log_io(int argc, char *argv[]) check_ovsdb_error(ovsdb_log_open(name, mode, -1, &log)); printf("%s: open successful\n", name); - for (i = 3; i < argc; i++) { - const char *command = argv[i]; + for (i = 3; i < ctx->argc; i++) { + const char *command = ctx->argv[i]; if (!strcmp(command, "read")) { struct json *json; @@ -315,24 +333,149 @@ do_log_io(int argc, char *argv[]) } static void -do_parse_atomic_type(int argc OVS_UNUSED, char *argv[]) +do_default_atoms(struct ovs_cmdl_context *ctx OVS_UNUSED) +{ + int type; + + for (type = 0; type < OVSDB_N_TYPES; type++) { + union ovsdb_atom atom; + + if (type == OVSDB_TYPE_VOID) { + continue; + } + + printf("%s: ", ovsdb_atomic_type_to_string(type)); + + ovsdb_atom_init_default(&atom, type); + if (!ovsdb_atom_equals(&atom, ovsdb_atom_default(type), type)) { + printf("wrong\n"); + exit(1); + } + ovsdb_atom_destroy(&atom, type); + + printf("OK\n"); + } +} + +static void +do_default_data(struct ovs_cmdl_context *ctx OVS_UNUSED) +{ + unsigned int n_min; + int key, value; + + for (n_min = 0; n_min <= 1; n_min++) { + for (key = 0; key < OVSDB_N_TYPES; key++) { + if (key == OVSDB_TYPE_VOID) { + continue; + } + for (value = 0; value < OVSDB_N_TYPES; value++) { + struct ovsdb_datum datum; + struct ovsdb_type type; + + ovsdb_base_type_init(&type.key, key); + ovsdb_base_type_init(&type.value, value); + type.n_min = n_min; + type.n_max = 1; + assert(ovsdb_type_is_valid(&type)); + + printf("key %s, value %s, n_min %u: ", + ovsdb_atomic_type_to_string(key), + ovsdb_atomic_type_to_string(value), n_min); + + ovsdb_datum_init_default(&datum, &type); + if (!ovsdb_datum_equals(&datum, ovsdb_datum_default(&type), + &type)) { + printf("wrong\n"); + exit(1); + } + ovsdb_datum_destroy(&datum, &type); + ovsdb_type_destroy(&type); + + printf("OK\n"); + } + } + } +} + +static void +do_diff_data(struct ovs_cmdl_context *ctx) +{ + struct ovsdb_type type; + struct json *json; + struct ovsdb_datum new, old, diff, reincarnation; + + json = unbox_json(parse_json(ctx->argv[1])); + check_ovsdb_error(ovsdb_type_from_json(&type, json)); + json_destroy(json); + + /* Arguments in pairs of 'old' and 'new'. */ + for (int i = 2; i < ctx->argc - 1; i+=2) { + struct ovsdb_error *error; + + json = unbox_json(parse_json(ctx->argv[i])); + check_ovsdb_error(ovsdb_datum_from_json(&old, &type, json, NULL)); + json_destroy(json); + + json = unbox_json(parse_json(ctx->argv[i+1])); + check_ovsdb_error(ovsdb_transient_datum_from_json(&new, &type, json)); + json_destroy(json); + + /* Generate the diff. */ + ovsdb_datum_diff(&diff, &old, &new, &type); + + /* Apply diff to 'old' to create'reincarnation'. */ + error = ovsdb_datum_apply_diff(&reincarnation, &old, &diff, &type); + if (error) { + char *string = ovsdb_error_to_string(error); + ovsdb_error_destroy(error); + ovs_fatal(0, "%s", string); + } + + /* Test to make sure 'new' equals 'reincarnation'. */ + if (!ovsdb_datum_equals(&new, &reincarnation, &type)) { + ovs_fatal(0, "failed to apply diff"); + } + + /* Print diff */ + json = ovsdb_datum_to_json(&diff, &type); + printf ("diff: "); + print_and_free_json(json); + + /* Print reincarnation */ + json = ovsdb_datum_to_json(&reincarnation, &type); + printf ("apply diff: "); + print_and_free_json(json); + + ovsdb_datum_destroy(&new, &type); + ovsdb_datum_destroy(&old, &type); + ovsdb_datum_destroy(&diff, &type); + ovsdb_datum_destroy(&reincarnation, &type); + + printf("OK\n"); + } + + ovsdb_type_destroy(&type); +} + +static void +do_parse_atomic_type(struct ovs_cmdl_context *ctx) { enum ovsdb_atomic_type type; struct json *json; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_atomic_type_from_json(&type, json)); json_destroy(json); print_and_free_json(ovsdb_atomic_type_to_json(type)); } static void -do_parse_base_type(int argc OVS_UNUSED, char *argv[]) +do_parse_base_type(struct ovs_cmdl_context *ctx) { struct ovsdb_base_type base; struct json *json; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_base_type_from_json(&base, json)); json_destroy(json); print_and_free_json(ovsdb_base_type_to_json(&base)); @@ -340,12 +483,12 @@ do_parse_base_type(int argc OVS_UNUSED, char *argv[]) } static void -do_parse_type(int argc OVS_UNUSED, char *argv[]) +do_parse_type(struct ovs_cmdl_context *ctx) { struct ovsdb_type type; struct json *json; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_type_from_json(&type, json)); json_destroy(json); print_and_free_json(ovsdb_type_to_json(&type)); @@ -353,21 +496,21 @@ do_parse_type(int argc OVS_UNUSED, char *argv[]) } static void -do_parse_atoms(int argc, char *argv[]) +do_parse_atoms(struct ovs_cmdl_context *ctx) { struct ovsdb_base_type base; struct json *json; int i; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_base_type_from_json(&base, json)); json_destroy(json); - for (i = 2; i < argc; i++) { + for (i = 2; i < ctx->argc; i++) { struct ovsdb_error *error; union ovsdb_atom atom; - json = unbox_json(parse_json(argv[i])); + json = unbox_json(parse_json(ctx->argv[i])); error = ovsdb_atom_from_json(&atom, &base, json, NULL); json_destroy(json); @@ -382,21 +525,21 @@ do_parse_atoms(int argc, char *argv[]) } static void -do_parse_atom_strings(int argc, char *argv[]) +do_parse_atom_strings(struct ovs_cmdl_context *ctx) { struct ovsdb_base_type base; struct json *json; int i; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_base_type_from_json(&base, json)); json_destroy(json); - for (i = 2; i < argc; i++) { + for (i = 2; i < ctx->argc; i++) { union ovsdb_atom atom; struct ds out; - die_if_error(ovsdb_atom_from_string(&atom, &base, argv[i])); + die_if_error(ovsdb_atom_from_string(&atom, &base, ctx->argv[i], NULL)); ds_init(&out); ovsdb_atom_to_string(&atom, base.type, &out); @@ -409,7 +552,12 @@ do_parse_atom_strings(int argc, char *argv[]) } static void -do_parse_data(int argc, char *argv[]) +do_parse_data__(int argc, char *argv[], + struct ovsdb_error * + (*parse)(struct ovsdb_datum *datum, + const struct ovsdb_type *type, + const struct json *json, + struct ovsdb_symbol_table *symtab)) { struct ovsdb_type type; struct json *json; @@ -423,7 +571,7 @@ do_parse_data(int argc, char *argv[]) struct ovsdb_datum datum; json = unbox_json(parse_json(argv[i])); - check_ovsdb_error(ovsdb_datum_from_json(&datum, &type, json, NULL)); + check_ovsdb_error(parse(&datum, &type, json, NULL)); json_destroy(json); print_and_free_json(ovsdb_datum_to_json(&datum, &type)); @@ -434,21 +582,27 @@ do_parse_data(int argc, char *argv[]) } static void -do_parse_data_strings(int argc, char *argv[]) +do_parse_data(struct ovs_cmdl_context *ctx) +{ + do_parse_data__(ctx->argc, ctx->argv, ovsdb_datum_from_json); +} + +static void +do_parse_data_strings(struct ovs_cmdl_context *ctx) { struct ovsdb_type type; struct json *json; int i; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_type_from_json(&type, json)); json_destroy(json); - for (i = 2; i < argc; i++) { + for (i = 2; i < ctx->argc; i++) { struct ovsdb_datum datum; struct ds out; - die_if_error(ovsdb_datum_from_string(&datum, &type, argv[i])); + die_if_error(ovsdb_datum_from_string(&datum, &type, ctx->argv[i], NULL)); ds_init(&out); ovsdb_datum_to_string(&datum, &type, &out); @@ -472,7 +626,7 @@ compare_atoms(const void *a_, const void *b_) } static void -do_sort_atoms(int argc OVS_UNUSED, char *argv[]) +do_sort_atoms(struct ovs_cmdl_context *ctx) { struct ovsdb_base_type base; union ovsdb_atom *atoms; @@ -480,11 +634,11 @@ do_sort_atoms(int argc OVS_UNUSED, char *argv[]) size_t n_atoms; int i; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_base_type_from_json(&base, json)); json_destroy(json); - json = unbox_json(parse_json(argv[2])); + json = unbox_json(parse_json(ctx->argv[2])); if (json->type != JSON_ARRAY) { ovs_fatal(0, "second argument must be array"); } @@ -514,33 +668,36 @@ do_sort_atoms(int argc OVS_UNUSED, char *argv[]) } static void -do_parse_column(int argc OVS_UNUSED, char *argv[]) +do_parse_column(struct ovs_cmdl_context *ctx) { struct ovsdb_column *column; struct json *json; - json = parse_json(argv[2]); - check_ovsdb_error(ovsdb_column_from_json(json, argv[1], &column)); + json = parse_json(ctx->argv[2]); + check_ovsdb_error(ovsdb_column_from_json(json, ctx->argv[1], &column)); json_destroy(json); print_and_free_json(ovsdb_column_to_json(column)); ovsdb_column_destroy(column); } static void -do_parse_table(int argc OVS_UNUSED, char *argv[]) +do_parse_table(struct ovs_cmdl_context *ctx) { struct ovsdb_table_schema *ts; + bool default_is_root; struct json *json; - json = parse_json(argv[2]); - check_ovsdb_error(ovsdb_table_schema_from_json(json, argv[1], &ts)); + default_is_root = ctx->argc > 3 && !strcmp(ctx->argv[3], "true"); + + json = parse_json(ctx->argv[2]); + check_ovsdb_error(ovsdb_table_schema_from_json(json, ctx->argv[1], &ts)); json_destroy(json); - print_and_free_json(ovsdb_table_schema_to_json(ts)); + print_and_free_json(ovsdb_table_schema_to_json(ts, default_is_root)); ovsdb_table_schema_destroy(ts); } static void -do_parse_rows(int argc, char *argv[]) +do_parse_rows(struct ovs_cmdl_context *ctx) { struct ovsdb_column_set all_columns; struct ovsdb_table_schema *ts; @@ -548,7 +705,7 @@ do_parse_rows(int argc, char *argv[]) struct json *json; int i; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); @@ -556,14 +713,14 @@ do_parse_rows(int argc, char *argv[]) ovsdb_column_set_init(&all_columns); ovsdb_column_set_add_all(&all_columns, table); - for (i = 2; i < argc; i++) { + for (i = 2; i < ctx->argc; i++) { struct ovsdb_column_set columns; struct ovsdb_row *row; ovsdb_column_set_init(&columns); row = ovsdb_row_create(table); - json = unbox_json(parse_json(argv[i])); + json = unbox_json(parse_json(ctx->argv[i])); check_ovsdb_error(ovsdb_row_from_json(row, json, NULL, &columns)); json_destroy(json); @@ -596,7 +753,7 @@ do_parse_rows(int argc, char *argv[]) } static void -do_compare_rows(int argc, char *argv[]) +do_compare_rows(struct ovs_cmdl_context *ctx) { struct ovsdb_column_set all_columns; struct ovsdb_table_schema *ts; @@ -607,7 +764,7 @@ do_compare_rows(int argc, char *argv[]) int n_rows; int i, j; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); @@ -615,17 +772,17 @@ do_compare_rows(int argc, char *argv[]) ovsdb_column_set_init(&all_columns); ovsdb_column_set_add_all(&all_columns, table); - n_rows = argc - 2; + n_rows = ctx->argc - 2; rows = xmalloc(sizeof *rows * n_rows); names = xmalloc(sizeof *names * n_rows); for (i = 0; i < n_rows; i++) { rows[i] = ovsdb_row_create(table); - json = parse_json(argv[i + 2]); + json = parse_json(ctx->argv[i + 2]); if (json->type != JSON_ARRAY || json->u.array.n != 2 || json->u.array.elems[0]->type != JSON_STRING) { ovs_fatal(0, "\"%s\" does not have expected form " - "[\"name\", {data}]", argv[i]); + "[\"name\", {data}]", ctx->argv[i]); } names[i] = xstrdup(json->u.array.elems[0]->u.string); check_ovsdb_error(ovsdb_row_from_json(rows[i], json->u.array.elems[1], @@ -659,22 +816,22 @@ do_compare_rows(int argc, char *argv[]) } static void -do_parse_conditions(int argc, char *argv[]) +do_parse_conditions(struct ovs_cmdl_context *ctx) { struct ovsdb_table_schema *ts; struct json *json; int exit_code = 0; int i; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); - for (i = 2; i < argc; i++) { + for (i = 2; i < ctx->argc; i++) { struct ovsdb_condition cnd; struct ovsdb_error *error; - json = parse_json(argv[i]); + json = parse_json(ctx->argv[i]); error = ovsdb_condition_from_json(ts, json, NULL, &cnd); if (!error) { print_and_free_json(ovsdb_condition_to_json(&cnd)); @@ -695,7 +852,7 @@ do_parse_conditions(int argc, char *argv[]) } static void -do_evaluate_conditions(int argc OVS_UNUSED, char *argv[]) +do_evaluate_conditions(struct ovs_cmdl_context *ctx) { struct ovsdb_table_schema *ts; struct ovsdb_table *table; @@ -707,14 +864,14 @@ do_evaluate_conditions(int argc OVS_UNUSED, char *argv[]) size_t i, j; /* Parse table schema, create table. */ - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); table = ovsdb_table_create(ts); /* Parse conditions. */ - json = parse_json(argv[2]); + json = parse_json(ctx->argv[2]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "CONDITION argument is not JSON array"); } @@ -727,7 +884,7 @@ do_evaluate_conditions(int argc OVS_UNUSED, char *argv[]) json_destroy(json); /* Parse rows. */ - json = parse_json(argv[3]); + json = parse_json(ctx->argv[3]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "ROW argument is not JSON array"); } @@ -741,7 +898,7 @@ do_evaluate_conditions(int argc OVS_UNUSED, char *argv[]) json_destroy(json); for (i = 0; i < n_conditions; i++) { - printf("condition %2zu:", i); + printf("condition %2"PRIuSIZE":", i); for (j = 0; j < n_rows; j++) { bool result = ovsdb_condition_evaluate(rows[j], &conditions[i]); if (j % 5 == 0) { @@ -764,22 +921,22 @@ do_evaluate_conditions(int argc OVS_UNUSED, char *argv[]) } static void -do_parse_mutations(int argc, char *argv[]) +do_parse_mutations(struct ovs_cmdl_context *ctx) { struct ovsdb_table_schema *ts; struct json *json; int exit_code = 0; int i; - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); - for (i = 2; i < argc; i++) { + for (i = 2; i < ctx->argc; i++) { struct ovsdb_mutation_set set; struct ovsdb_error *error; - json = parse_json(argv[i]); + json = parse_json(ctx->argv[i]); error = ovsdb_mutation_set_from_json(ts, json, NULL, &set); if (!error) { print_and_free_json(ovsdb_mutation_set_to_json(&set)); @@ -800,7 +957,7 @@ do_parse_mutations(int argc, char *argv[]) } static void -do_execute_mutations(int argc OVS_UNUSED, char *argv[]) +do_execute_mutations(struct ovs_cmdl_context *ctx) { struct ovsdb_table_schema *ts; struct ovsdb_table *table; @@ -812,14 +969,14 @@ do_execute_mutations(int argc OVS_UNUSED, char *argv[]) size_t i, j; /* Parse table schema, create table. */ - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); table = ovsdb_table_create(ts); /* Parse mutations. */ - json = parse_json(argv[2]); + json = parse_json(ctx->argv[2]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "MUTATION argument is not JSON array"); } @@ -833,7 +990,7 @@ do_execute_mutations(int argc OVS_UNUSED, char *argv[]) json_destroy(json); /* Parse rows. */ - json = parse_json(argv[3]); + json = parse_json(ctx->argv[3]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "ROW argument is not JSON array"); } @@ -847,7 +1004,7 @@ do_execute_mutations(int argc OVS_UNUSED, char *argv[]) json_destroy(json); for (i = 0; i < n_sets; i++) { - printf("mutation %2zu:\n", i); + printf("mutation %2"PRIuSIZE":\n", i); for (j = 0; j < n_rows; j++) { struct ovsdb_error *error; struct ovsdb_row *row; @@ -855,7 +1012,7 @@ do_execute_mutations(int argc OVS_UNUSED, char *argv[]) row = ovsdb_row_clone(rows[j]); error = ovsdb_mutation_set_execute(row, &sets[i]); - printf("row %zu: ", j); + printf("row %"PRIuSIZE": ", j); if (error) { print_and_free_ovsdb_error(error); } else { @@ -894,6 +1051,16 @@ do_execute_mutations(int argc OVS_UNUSED, char *argv[]) ovsdb_table_destroy(table); /* Also destroys 'ts'. */ } +/* Inserts a row, without bothering to update metadata such as refcounts. */ +static void +put_row(struct ovsdb_table *table, struct ovsdb_row *row) +{ + const struct uuid *uuid = ovsdb_row_get_uuid(row); + if (!ovsdb_table_get_row(table, uuid)) { + hmap_insert(&table->rows, &row->hmap_node, uuid_hash(uuid)); + } +} + struct do_query_cbdata { struct uuid *row_uuids; int *counts; @@ -916,7 +1083,7 @@ do_query_cb(const struct ovsdb_row *row, void *cbdata_) } static void -do_query(int argc OVS_UNUSED, char *argv[]) +do_query(struct ovs_cmdl_context *ctx) { struct do_query_cbdata cbdata; struct ovsdb_table_schema *ts; @@ -926,14 +1093,14 @@ do_query(int argc OVS_UNUSED, char *argv[]) size_t i; /* Parse table schema, create table. */ - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); table = ovsdb_table_create(ts); /* Parse rows, add to table. */ - json = parse_json(argv[2]); + json = parse_json(ctx->argv[2]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "ROW argument is not JSON array"); } @@ -950,12 +1117,12 @@ do_query(int argc OVS_UNUSED, char *argv[]) UUID_ARGS(ovsdb_row_get_uuid(row))); } cbdata.row_uuids[i] = *ovsdb_row_get_uuid(row); - ovsdb_table_put_row(table, row); + put_row(table, row); } json_destroy(json); /* Parse conditions and execute queries. */ - json = parse_json(argv[3]); + json = parse_json(ctx->argv[3]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "CONDITION argument is not JSON array"); } @@ -969,7 +1136,7 @@ do_query(int argc OVS_UNUSED, char *argv[]) memset(cbdata.counts, 0, cbdata.n_rows * sizeof *cbdata.counts); ovsdb_query(table, &cnd, do_query_cb, &cbdata); - printf("query %2zu:", i); + printf("query %2"PRIuSIZE":", i); for (j = 0; j < cbdata.n_rows; j++) { if (j % 5 == 0) { putchar(' '); @@ -1006,7 +1173,7 @@ struct do_query_distinct_row { }; static void -do_query_distinct(int argc OVS_UNUSED, char *argv[]) +do_query_distinct(struct ovs_cmdl_context *ctx) { struct ovsdb_column_set columns; struct ovsdb_table_schema *ts; @@ -1017,22 +1184,23 @@ do_query_distinct(int argc OVS_UNUSED, char *argv[]) size_t n_classes; struct json *json; int exit_code = 0; - size_t i, j, k; + size_t i; /* Parse table schema, create table. */ - json = unbox_json(parse_json(argv[1])); + json = unbox_json(parse_json(ctx->argv[1])); check_ovsdb_error(ovsdb_table_schema_from_json(json, "mytable", &ts)); json_destroy(json); table = ovsdb_table_create(ts); /* Parse column set. */ - json = parse_json(argv[4]); - check_ovsdb_error(ovsdb_column_set_from_json(json, table, &columns)); + json = parse_json(ctx->argv[4]); + check_ovsdb_error(ovsdb_column_set_from_json(json, table->schema, + &columns)); json_destroy(json); /* Parse rows, add to table. */ - json = parse_json(argv[2]); + json = parse_json(ctx->argv[2]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "ROW argument is not JSON array"); } @@ -1070,19 +1238,20 @@ do_query_distinct(int argc OVS_UNUSED, char *argv[]) ovs_fatal(0, "duplicate UUID "UUID_FMT" in table", UUID_ARGS(ovsdb_row_get_uuid(row))); } - ovsdb_table_put_row(table, row); + put_row(table, row); } json_destroy(json); /* Parse conditions and execute queries. */ - json = parse_json(argv[3]); + json = parse_json(ctx->argv[3]); if (json->type != JSON_ARRAY) { ovs_fatal(0, "CONDITION argument is not JSON array"); } for (i = 0; i < json->u.array.n; i++) { struct ovsdb_row_set results; struct ovsdb_condition cnd; + size_t j; check_ovsdb_error(ovsdb_condition_from_json(ts, json->u.array.elems[i], NULL, &cnd)); @@ -1093,6 +1262,8 @@ do_query_distinct(int argc OVS_UNUSED, char *argv[]) ovsdb_row_set_init(&results); ovsdb_query_distinct(table, &cnd, &columns, &results); for (j = 0; j < results.n_rows; j++) { + size_t k; + for (k = 0; k < n_rows; k++) { if (uuid_equals(ovsdb_row_get_uuid(results.rows[j]), &rows[k].uuid)) { @@ -1102,7 +1273,7 @@ do_query_distinct(int argc OVS_UNUSED, char *argv[]) } ovsdb_row_set_destroy(&results); - printf("query %2zu:", i); + printf("query %2"PRIuSIZE":", i); for (j = 0; j < n_rows; j++) { int count = rows[j].class->count; @@ -1125,18 +1296,24 @@ do_query_distinct(int argc OVS_UNUSED, char *argv[]) } json_destroy(json); + for (i = 0; i < n_classes; i++) { + ovsdb_row_destroy(classes[i].example); + } + ovsdb_table_destroy(table); /* Also destroys 'ts'. */ + free(rows); + free(classes); exit(exit_code); } static void -do_parse_schema(int argc OVS_UNUSED, char *argv[]) +do_parse_schema(struct ovs_cmdl_context *ctx) { struct ovsdb_schema *schema; struct json *json; - json = parse_json(argv[1]); + json = parse_json(ctx->argv[1]); check_ovsdb_error(ovsdb_schema_from_json(json, &schema)); json_destroy(json); print_and_free_json(ovsdb_schema_to_json(schema)); @@ -1144,7 +1321,7 @@ do_parse_schema(int argc OVS_UNUSED, char *argv[]) } static void -do_execute(int argc OVS_UNUSED, char *argv[]) +do_execute(struct ovs_cmdl_context *ctx) { struct ovsdb_schema *schema; struct json *json; @@ -1152,17 +1329,17 @@ do_execute(int argc OVS_UNUSED, char *argv[]) int i; /* Create database. */ - json = parse_json(argv[1]); + json = parse_json(ctx->argv[1]); check_ovsdb_error(ovsdb_schema_from_json(json, &schema)); json_destroy(json); db = ovsdb_create(schema); - for (i = 2; i < argc; i++) { + for (i = 2; i < ctx->argc; i++) { struct json *params, *result; char *s; - params = parse_json(argv[i]); - result = ovsdb_execute(db, params, 0, NULL); + params = parse_json(ctx->argv[i]); + result = ovsdb_execute(db, NULL, params, 0, NULL); s = json_to_string(result, JSSF_SORT); printf("%s\n", s); free(s); @@ -1194,10 +1371,11 @@ do_trigger_dump(struct test_trigger *t, long long int now, const char *title) } static void -do_trigger(int argc OVS_UNUSED, char *argv[]) +do_trigger(struct ovs_cmdl_context *ctx) { struct ovsdb_schema *schema; - struct list completions; + struct ovsdb_session session; + struct ovsdb_server server; struct json *json; struct ovsdb *db; long long int now; @@ -1205,16 +1383,19 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) int i; /* Create database. */ - json = parse_json(argv[1]); + json = parse_json(ctx->argv[1]); check_ovsdb_error(ovsdb_schema_from_json(json, &schema)); json_destroy(json); db = ovsdb_create(schema); - list_init(&completions); + ovsdb_server_init(&server); + ovsdb_server_add_db(&server, db); + ovsdb_session_init(&session, &server); + now = 0; number = 0; - for (i = 2; i < argc; i++) { - struct json *params = parse_json(argv[i]); + for (i = 2; i < ctx->argc; i++) { + struct json *params = parse_json(ctx->argv[i]); if (params->type == JSON_ARRAY && json_array(params)->n == 2 && json_array(params)->elems[0]->type == JSON_STRING @@ -1224,7 +1405,7 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) json_destroy(params); } else { struct test_trigger *t = xmalloc(sizeof *t); - ovsdb_trigger_init(db, &t->trigger, params, &completions, now); + ovsdb_trigger_init(&session, db, &t->trigger, params, now); t->number = number++; if (ovsdb_trigger_is_complete(&t->trigger)) { do_trigger_dump(t, now, "immediate"); @@ -1234,8 +1415,8 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) } ovsdb_trigger_run(db, now); - while (!list_is_empty(&completions)) { - do_trigger_dump(CONTAINER_OF(list_pop_front(&completions), + while (!list_is_empty(&session.completions)) { + do_trigger_dump(CONTAINER_OF(list_pop_front(&session.completions), struct test_trigger, trigger.node), now, "delayed"); } @@ -1245,11 +1426,12 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) poll_block(); } + ovsdb_server_destroy(&server); ovsdb_destroy(db); } static void -do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +do_help(struct ovs_cmdl_context *ctx OVS_UNUSED) { usage(); } @@ -1261,14 +1443,14 @@ static struct ovsdb_txn *do_transact_txn; static struct ovsdb_table *do_transact_table; static void -do_transact_commit(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +do_transact_commit(struct ovs_cmdl_context *ctx OVS_UNUSED) { - ovsdb_txn_commit(do_transact_txn, false); + ovsdb_error_destroy(ovsdb_txn_commit(do_transact_txn, false)); do_transact_txn = NULL; } static void -do_transact_abort(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +do_transact_abort(struct ovs_cmdl_context *ctx OVS_UNUSED) { ovsdb_txn_abort(do_transact_txn); do_transact_txn = NULL; @@ -1328,7 +1510,7 @@ do_transact_set_i_j(struct ovsdb_row *row, } static void -do_transact_insert(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +do_transact_insert(struct ovs_cmdl_context *ctx) { struct ovsdb_row *row; struct uuid *uuid; @@ -1337,34 +1519,34 @@ do_transact_insert(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) /* Set UUID. */ uuid = ovsdb_row_get_uuid_rw(row); - uuid_from_integer(atoi(argv[1]), uuid); + uuid_from_integer(atoi(ctx->argv[1]), uuid); if (ovsdb_table_get_row(do_transact_table, uuid)) { ovs_fatal(0, "table already contains row with UUID "UUID_FMT, UUID_ARGS(uuid)); } - do_transact_set_i_j(row, argv[2], argv[3]); + do_transact_set_i_j(row, ctx->argv[2], ctx->argv[3]); /* Insert row. */ ovsdb_txn_row_insert(do_transact_txn, row); } static void -do_transact_delete(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +do_transact_delete(struct ovs_cmdl_context *ctx) { - const struct ovsdb_row *row = do_transact_find_row(argv[1]); + const struct ovsdb_row *row = do_transact_find_row(ctx->argv[1]); ovsdb_txn_row_delete(do_transact_txn, row); } static void -do_transact_modify(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +do_transact_modify(struct ovs_cmdl_context *ctx) { const struct ovsdb_row *row_ro; struct ovsdb_row *row_rw; - row_ro = do_transact_find_row(argv[1]); + row_ro = do_transact_find_row(ctx->argv[1]); row_rw = ovsdb_txn_row_modify(do_transact_txn, row_ro); - do_transact_set_i_j(row_rw, argv[2], argv[3]); + do_transact_set_i_j(row_rw, ctx->argv[2], ctx->argv[3]); } static int @@ -1377,7 +1559,7 @@ compare_rows_by_uuid(const void *a_, const void *b_) } static void -do_transact_print(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +do_transact_print(struct ovs_cmdl_context *ctx OVS_UNUSED) { const struct ovsdb_row **rows; const struct ovsdb_row *row; @@ -1387,8 +1569,7 @@ do_transact_print(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) n_rows = hmap_count(&do_transact_table->rows); rows = xmalloc(n_rows * sizeof *rows); i = 0; - HMAP_FOR_EACH (row, struct ovsdb_row, hmap_node, - &do_transact_table->rows) { + HMAP_FOR_EACH (row, hmap_node, &do_transact_table->rows) { rows[i++] = row; } assert(i == n_rows); @@ -1406,16 +1587,16 @@ do_transact_print(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) } static void -do_transact(int argc, char *argv[]) -{ - static const struct command do_transact_commands[] = { - { "commit", 0, 0, do_transact_commit }, - { "abort", 0, 0, do_transact_abort }, - { "insert", 2, 3, do_transact_insert }, - { "delete", 1, 1, do_transact_delete }, - { "modify", 2, 3, do_transact_modify }, - { "print", 0, 0, do_transact_print }, - { NULL, 0, 0, NULL }, +do_transact(struct ovs_cmdl_context *ctx) +{ + static const struct ovs_cmdl_command do_transact_commands[] = { + { "commit", NULL, 0, 0, do_transact_commit }, + { "abort", NULL, 0, 0, do_transact_abort }, + { "insert", NULL, 2, 3, do_transact_insert }, + { "delete", NULL, 1, 1, do_transact_delete }, + { "modify", NULL, 2, 3, do_transact_modify }, + { "print", NULL, 0, 0, do_transact_print }, + { NULL, NULL, 0, 0, NULL }, }; struct ovsdb_schema *schema; @@ -1435,13 +1616,14 @@ do_transact(int argc, char *argv[]) do_transact_table = ovsdb_get_table(do_transact_db, "mytable"); assert(do_transact_table != NULL); - for (i = 1; i < argc; i++) { + for (i = 1; i < ctx->argc; i++) { struct json *command; size_t n_args; char **args; int j; + struct ovs_cmdl_context transact_ctx = { .argc = 0, }; - command = parse_json(argv[i]); + command = parse_json(ctx->argv[i]); if (command->type != JSON_ARRAY) { ovs_fatal(0, "transaction %d must be JSON array " "with at least 1 element", i); @@ -1470,7 +1652,9 @@ do_transact(int argc, char *argv[]) fputs(args[j], stdout); } fputs(":", stdout); - run_command(n_args, args, do_transact_commands); + transact_ctx.argc = n_args; + transact_ctx.argv = args; + ovs_cmdl_run_command(&transact_ctx, do_transact_commands); putchar('\n'); for (j = 0; j < n_args; j++) { @@ -1494,6 +1678,133 @@ compare_link1(const void *a_, const void *b_) return a->i < b->i ? -1 : a->i > b->i; } +static void +print_idl_row_updated_simple(const struct idltest_simple *s, int step) +{ + size_t i; + bool updated = false; + + for (i = 0; i < IDLTEST_SIMPLE_N_COLUMNS; i++) { + if (idltest_simple_is_updated(s, i)) { + if (!updated) { + printf("%03d: updated columns:", step); + updated = true; + } + printf(" %s", idltest_simple_columns[i].name); + } + } + if (updated) { + printf("\n"); + } +} + +static void +print_idl_row_updated_link1(const struct idltest_link1 *l1, int step) +{ + size_t i; + bool updated = false; + + for (i = 0; i < IDLTEST_LINK1_N_COLUMNS; i++) { + if (idltest_link1_is_updated(l1, i)) { + if (!updated) { + printf("%03d: updated columns:", step); + updated = true; + } + printf(" %s", idltest_link1_columns[i].name); + } + } + if (updated) { + printf("\n"); + } +} + +static void +print_idl_row_updated_link2(const struct idltest_link2 *l2, int step) +{ + size_t i; + bool updated = false; + + for (i = 0; i < IDLTEST_LINK2_N_COLUMNS; i++) { + if (idltest_link2_is_updated(l2, i)) { + if (!updated) { + printf("%03d: updated columns:", step); + updated = true; + } + printf(" %s", idltest_link2_columns[i].name); + } + } + if (updated) { + printf("\n"); + } +} + +static void +print_idl_row_simple(const struct idltest_simple *s, int step) +{ + size_t i; + + printf("%03d: i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[", + step, s->i, s->r, s->b ? "true" : "false", + s->s, UUID_ARGS(&s->u)); + for (i = 0; i < s->n_ia; i++) { + printf("%s%"PRId64, i ? " " : "", s->ia[i]); + } + printf("] ra=["); + for (i = 0; i < s->n_ra; i++) { + printf("%s%g", i ? " " : "", s->ra[i]); + } + printf("] ba=["); + for (i = 0; i < s->n_ba; i++) { + printf("%s%s", i ? " " : "", s->ba[i] ? "true" : "false"); + } + printf("] sa=["); + for (i = 0; i < s->n_sa; i++) { + printf("%s%s", i ? " " : "", s->sa[i]); + } + printf("] ua=["); + for (i = 0; i < s->n_ua; i++) { + printf("%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s->ua[i])); + } + printf("] uuid="UUID_FMT"\n", UUID_ARGS(&s->header_.uuid)); + print_idl_row_updated_simple(s, step); +} + +static void +print_idl_row_link1(const struct idltest_link1 *l1, int step) +{ + struct idltest_link1 **links; + size_t i; + + printf("%03d: i=%"PRId64" k=", step, l1->i); + if (l1->k) { + printf("%"PRId64, l1->k->i); + } + printf(" ka=["); + links = xmemdup(l1->ka, l1->n_ka * sizeof *l1->ka); + qsort(links, l1->n_ka, sizeof *links, compare_link1); + for (i = 0; i < l1->n_ka; i++) { + printf("%s%"PRId64, i ? " " : "", links[i]->i); + } + free(links); + printf("] l2="); + if (l1->l2) { + printf("%"PRId64, l1->l2->i); + } + printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l1->header_.uuid)); + print_idl_row_updated_link1(l1, step); +} + +static void +print_idl_row_link2(const struct idltest_link2 *l2, int step) +{ + printf("%03d: i=%"PRId64" l1=", step, l2->i); + if (l2->l1) { + printf("%"PRId64, l2->l1->i); + } + printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l2->header_.uuid)); + print_idl_row_updated_link2(l2, step); +} + static void print_idl(struct ovsdb_idl *idl, int step) { @@ -1503,61 +1814,15 @@ print_idl(struct ovsdb_idl *idl, int step) int n = 0; IDLTEST_SIMPLE_FOR_EACH (s, idl) { - size_t i; - - printf("%03d: i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[", - step, s->i, s->r, s->b ? "true" : "false", - s->s, UUID_ARGS(&s->u)); - for (i = 0; i < s->n_ia; i++) { - printf("%s%"PRId64, i ? " " : "", s->ia[i]); - } - printf("] ra=["); - for (i = 0; i < s->n_ra; i++) { - printf("%s%g", i ? " " : "", s->ra[i]); - } - printf("] ba=["); - for (i = 0; i < s->n_ba; i++) { - printf("%s%s", i ? " " : "", s->ba[i] ? "true" : "false"); - } - printf("] sa=["); - for (i = 0; i < s->n_sa; i++) { - printf("%s%s", i ? " " : "", s->sa[i]); - } - printf("] ua=["); - for (i = 0; i < s->n_ua; i++) { - printf("%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s->ua[i])); - } - printf("] uuid="UUID_FMT"\n", UUID_ARGS(&s->header_.uuid)); + print_idl_row_simple(s, step); n++; } IDLTEST_LINK1_FOR_EACH (l1, idl) { - struct idltest_link1 **links; - size_t i; - - printf("%03d: i=%"PRId64" k=", step, l1->i); - if (l1->k) { - printf("%"PRId64, l1->k->i); - } - printf(" ka=["); - links = xmemdup(l1->ka, l1->n_ka * sizeof *l1->ka); - qsort(links, l1->n_ka, sizeof *links, compare_link1); - for (i = 0; i < l1->n_ka; i++) { - printf("%s%"PRId64, i ? " " : "", links[i]->i); - } - free(links); - printf("] l2="); - if (l1->l2) { - printf("%"PRId64, l1->l2->i); - } - printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l1->header_.uuid)); + print_idl_row_link1(l1, step); n++; } IDLTEST_LINK2_FOR_EACH (l2, idl) { - printf("%03d: i=%"PRId64" l1=", step, l2->i); - if (l2->l1) { - printf("%"PRId64, l2->l1->i); - } - printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l2->header_.uuid)); + print_idl_row_link2(l2, step); n++; } if (!n) { @@ -1565,28 +1830,40 @@ print_idl(struct ovsdb_idl *idl, int step) } } -static unsigned int -print_updated_idl(struct ovsdb_idl *idl, struct jsonrpc *rpc, - int step, unsigned int seqno) +static void +print_idl_track(struct ovsdb_idl *idl, int step, unsigned int seqno) { - for (;;) { - unsigned int new_seqno; + const struct idltest_simple *s; + const struct idltest_link1 *l1; + const struct idltest_link2 *l2; + int n = 0; - if (rpc) { - jsonrpc_run(rpc); + IDLTEST_SIMPLE_FOR_EACH_TRACKED (s, idl) { + if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) { + printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid)); + } else { + print_idl_row_simple(s, step); } - ovsdb_idl_run(idl); - new_seqno = ovsdb_idl_get_seqno(idl); - if (new_seqno != seqno) { - print_idl(idl, step); - return new_seqno; + n++; + } + IDLTEST_LINK1_FOR_EACH_TRACKED (l1, idl) { + if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) { + printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid)); + } else { + print_idl_row_link1(l1, step); } - - if (rpc) { - jsonrpc_wait(rpc); + n++; + } + IDLTEST_LINK2_FOR_EACH_TRACKED (l2, idl) { + if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) { + printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid)); + } else { + print_idl_row_link2(l2, step); } - ovsdb_idl_wait(idl); - poll_block(); + n++; + } + if (!n) { + printf("%03d: empty\n", step); } } @@ -1597,7 +1874,7 @@ parse_uuids(const struct json *json, struct ovsdb_symbol_table *symtab, struct uuid uuid; if (json->type == JSON_STRING && uuid_from_string(&uuid, json->u.string)) { - char *name = xasprintf("#%zu#", *n); + char *name = xasprintf("#%"PRIuSIZE"#", *n); fprintf(stderr, "%s = "UUID_FMT"\n", name, UUID_ARGS(&uuid)); ovsdb_symbol_table_put(symtab, name, &uuid, false); free(name); @@ -1694,7 +1971,9 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step) idltest_simple_set_s(s, arg3); } else if (!strcmp(arg2, "u")) { struct uuid uuid; - uuid_from_string(&uuid, arg3); + if (!uuid_from_string(&uuid, arg3)) { + ovs_fatal(0, "\"%s\" is not a valid UUID", arg3); + } idltest_simple_set_u(s, uuid); } else if (!strcmp(arg2, "r")) { idltest_simple_set_r(s, atof(arg3)); @@ -1706,7 +1985,7 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step) struct idltest_simple *s; if (!arg1 || arg2) { - ovs_fatal(0, "\"set\" command requires 1 argument"); + ovs_fatal(0, "\"insert\" command requires 1 argument"); } s = idltest_simple_insert(txn); @@ -1715,21 +1994,64 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step) const struct idltest_simple *s; if (!arg1 || arg2) { - ovs_fatal(0, "\"set\" command requires 1 argument"); + ovs_fatal(0, "\"delete\" command requires 1 argument"); } s = idltest_find_simple(idl, atoi(arg1)); if (!s) { - ovs_fatal(0, "\"set\" command asks for nonexistent " + ovs_fatal(0, "\"delete\" command asks for nonexistent " "i=%d", atoi(arg1)); } idltest_simple_delete(s); - } else if (!strcmp(name, "increment")) { + } else if (!strcmp(name, "verify")) { + const struct idltest_simple *s; + if (!arg2 || arg3) { - ovs_fatal(0, "\"set\" command requires 2 arguments"); + ovs_fatal(0, "\"verify\" command requires 2 arguments"); + } + + s = idltest_find_simple(idl, atoi(arg1)); + if (!s) { + ovs_fatal(0, "\"verify\" command asks for nonexistent " + "i=%d", atoi(arg1)); + } + + if (!strcmp(arg2, "i")) { + idltest_simple_verify_i(s); + } else if (!strcmp(arg2, "b")) { + idltest_simple_verify_b(s); + } else if (!strcmp(arg2, "s")) { + idltest_simple_verify_s(s); + } else if (!strcmp(arg2, "u")) { + idltest_simple_verify_s(s); + } else if (!strcmp(arg2, "r")) { + idltest_simple_verify_r(s); + } else { + ovs_fatal(0, "\"verify\" command asks for unknown column %s", + arg2); + } + } else if (!strcmp(name, "increment")) { + const struct idltest_simple *s; + + if (!arg1 || arg2) { + ovs_fatal(0, "\"increment\" command requires 1 argument"); + } + + s = idltest_find_simple(idl, atoi(arg1)); + if (!s) { + ovs_fatal(0, "\"set\" command asks for nonexistent " + "i=%d", atoi(arg1)); } - ovsdb_idl_txn_increment(txn, arg1, arg2, NULL); + + ovsdb_idl_txn_increment(txn, &s->header_, &idltest_simple_col_i); increment = true; + } else if (!strcmp(name, "abort")) { + ovsdb_idl_txn_abort(txn); + break; + } else if (!strcmp(name, "destroy")) { + printf("%03d: destroy\n", step); + ovsdb_idl_txn_destroy(txn); + return; } else { ovs_fatal(0, "unknown command %s", name); } @@ -1747,7 +2069,7 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step) } static void -do_idl(int argc, char *argv[]) +do_idl(struct ovs_cmdl_context *ctx) { struct jsonrpc *rpc; struct ovsdb_idl *idl; @@ -1757,37 +2079,63 @@ do_idl(int argc, char *argv[]) int step = 0; int error; int i; + bool track; idltest_init(); - idl = ovsdb_idl_create(argv[1], &idltest_idl_class); - if (argc > 2) { + track = ((struct test_ovsdb_pvt_context *)(ctx->pvt))->track; + + idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, true, true); + if (ctx->argc > 2) { struct stream *stream; - error = stream_open_block(jsonrpc_stream_open(argv[1], &stream), - &stream); + error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, + DSCP_DEFAULT), &stream); if (error) { - ovs_fatal(error, "failed to connect to \"%s\"", argv[1]); + ovs_fatal(error, "failed to connect to \"%s\"", ctx->argv[1]); } rpc = jsonrpc_open(stream); } else { rpc = NULL; } - setvbuf(stdout, NULL, _IOLBF, 0); + if (track) { + ovsdb_idl_track_add_all(idl); + } + + setvbuf(stdout, NULL, _IONBF, 0); symtab = ovsdb_symbol_table_create(); - for (i = 2; i < argc; i++) { - char *arg = argv[i]; + for (i = 2; i < ctx->argc; i++) { + char *arg = ctx->argv[i]; struct jsonrpc_msg *request, *reply; - int error; if (*arg == '+') { /* The previous transaction didn't change anything. */ arg++; } else { - seqno = print_updated_idl(idl, rpc, step++, seqno); + /* Wait for update. */ + for (;;) { + ovsdb_idl_run(idl); + if (ovsdb_idl_get_seqno(idl) != seqno) { + break; + } + jsonrpc_run(rpc); + + ovsdb_idl_wait(idl); + jsonrpc_wait(rpc); + poll_block(); + } + + /* Print update. */ + if (track) { + print_idl_track(idl, step++, ovsdb_idl_get_seqno(idl)); + ovsdb_idl_track_clear(idl); + } else { + print_idl(idl, step++); + } } + seqno = ovsdb_idl_get_seqno(idl); if (!strcmp(arg, "reconnect")) { printf("%03d: reconnect\n", step++); @@ -1799,7 +2147,7 @@ do_idl(int argc, char *argv[]) substitute_uuids(json, symtab); request = jsonrpc_create_request("transact", json, NULL); error = jsonrpc_transact_block(rpc, request, &reply); - if (error) { + if (error || reply->error) { ovs_fatal(error, "jsonrpc transaction failed"); } printf("%03d: ", step++); @@ -1816,36 +2164,54 @@ do_idl(int argc, char *argv[]) if (rpc) { jsonrpc_close(rpc); } - print_updated_idl(idl, NULL, step++, seqno); + for (;;) { + ovsdb_idl_run(idl); + if (ovsdb_idl_get_seqno(idl) != seqno) { + break; + } + ovsdb_idl_wait(idl); + poll_block(); + } + print_idl(idl, step++); + ovsdb_idl_track_clear(idl); ovsdb_idl_destroy(idl); printf("%03d: done\n", step); } -static struct command all_commands[] = { - { "log-io", 2, INT_MAX, do_log_io }, - { "parse-atomic-type", 1, 1, do_parse_atomic_type }, - { "parse-base-type", 1, 1, do_parse_base_type }, - { "parse-type", 1, 1, do_parse_type }, - { "parse-atoms", 2, INT_MAX, do_parse_atoms }, - { "parse-atom-strings", 2, INT_MAX, do_parse_atom_strings }, - { "parse-data", 2, INT_MAX, do_parse_data }, - { "parse-data-strings", 2, INT_MAX, do_parse_data_strings }, - { "sort-atoms", 2, 2, do_sort_atoms }, - { "parse-column", 2, 2, do_parse_column }, - { "parse-table", 2, 2, do_parse_table }, - { "parse-rows", 2, INT_MAX, do_parse_rows }, - { "compare-rows", 2, INT_MAX, do_compare_rows }, - { "parse-conditions", 2, INT_MAX, do_parse_conditions }, - { "evaluate-conditions", 3, 3, do_evaluate_conditions }, - { "parse-mutations", 2, INT_MAX, do_parse_mutations }, - { "execute-mutations", 3, 3, do_execute_mutations }, - { "query", 3, 3, do_query }, - { "query-distinct", 4, 4, do_query_distinct }, - { "transact", 1, INT_MAX, do_transact }, - { "parse-schema", 1, 1, do_parse_schema }, - { "execute", 2, INT_MAX, do_execute }, - { "trigger", 2, INT_MAX, do_trigger }, - { "idl", 1, INT_MAX, do_idl }, - { "help", 0, INT_MAX, do_help }, - { NULL, 0, 0, NULL }, +static struct ovs_cmdl_command all_commands[] = { + { "log-io", NULL, 2, INT_MAX, do_log_io }, + { "default-atoms", NULL, 0, 0, do_default_atoms }, + { "default-data", NULL, 0, 0, do_default_data }, + { "diff-data", NULL, 3, INT_MAX, do_diff_data}, + { "parse-atomic-type", NULL, 1, 1, do_parse_atomic_type }, + { "parse-base-type", NULL, 1, 1, do_parse_base_type }, + { "parse-type", NULL, 1, 1, do_parse_type }, + { "parse-atoms", NULL, 2, INT_MAX, do_parse_atoms }, + { "parse-atom-strings", NULL, 2, INT_MAX, do_parse_atom_strings }, + { "parse-data", NULL, 2, INT_MAX, do_parse_data }, + { "parse-data-strings", NULL, 2, INT_MAX, do_parse_data_strings }, + { "sort-atoms", NULL, 2, 2, do_sort_atoms }, + { "parse-column", NULL, 2, 2, do_parse_column }, + { "parse-table", NULL, 2, 3, do_parse_table }, + { "parse-rows", NULL, 2, INT_MAX, do_parse_rows }, + { "compare-rows", NULL, 2, INT_MAX, do_compare_rows }, + { "parse-conditions", NULL, 2, INT_MAX, do_parse_conditions }, + { "evaluate-conditions", NULL, 3, 3, do_evaluate_conditions }, + { "parse-mutations", NULL, 2, INT_MAX, do_parse_mutations }, + { "execute-mutations", NULL, 3, 3, do_execute_mutations }, + { "query", NULL, 3, 3, do_query }, + { "query-distinct", NULL, 4, 4, do_query_distinct }, + { "transact", NULL, 1, INT_MAX, do_transact }, + { "parse-schema", NULL, 1, 1, do_parse_schema }, + { "execute", NULL, 2, INT_MAX, do_execute }, + { "trigger", NULL, 2, INT_MAX, do_trigger }, + { "idl", NULL, 1, INT_MAX, do_idl }, + { "help", NULL, 0, INT_MAX, do_help }, + { NULL, NULL, 0, 0, NULL }, }; + +static struct ovs_cmdl_command * +get_all_commands(void) +{ + return all_commands; +}