static const struct vsctl_table_class *get_table(const char *table_name);
static void set_column(const struct vsctl_table_class *,
- const struct ovsdb_idl_row *, const char *arg);
+ const struct ovsdb_idl_row *, const char *arg,
+ struct ovsdb_symbol_table *);
int
struct ds output;
struct ovsdb_idl *idl;
struct ovsdb_idl_txn *txn;
+ struct ovsdb_symbol_table *symtab;
const struct ovsrec_open_vswitch *ovs;
};
}
for (i = 0; i < n_settings; i++) {
- set_column(get_table("Port"), &port->header_, settings[i]);
+ set_column(get_table("Port"), &port->header_, settings[i],
+ ctx->symtab);
}
bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
{{&ovsrec_table_port, &ovsrec_port_col_name, NULL},
{NULL, NULL, NULL}}},
+ {&ovsrec_table_qos,
+ {{&ovsrec_table_port, &ovsrec_port_col_name, &ovsrec_port_col_qos},
+ {NULL, NULL, NULL}}},
+
+ {&ovsrec_table_queue,
+ {{NULL, NULL, NULL},
+ {NULL, NULL, NULL}}},
+
{&ovsrec_table_ssl,
{{&ovsrec_table_open_vswitch, NULL, &ovsrec_open_vswitch_col_ssl}}},
die_if_error(ovsdb_atom_from_string(&key,
&column->type.key,
- key_string));
+ key_string, ctx->symtab));
idx = ovsdb_datum_find_key(&datum, &key,
column->type.key.type);
static void
set_column(const struct vsctl_table_class *table,
- const struct ovsdb_idl_row *row, const char *arg)
+ const struct ovsdb_idl_row *row, const char *arg,
+ struct ovsdb_symbol_table *symtab)
{
const struct ovsdb_idl_column *column;
char *key_string, *value_string;
}
die_if_error(ovsdb_atom_from_string(&key, &column->type.key,
- key_string));
+ key_string, symtab));
die_if_error(ovsdb_atom_from_string(&value, &column->type.value,
- value_string));
+ value_string, symtab));
ovsdb_datum_init_empty(&new);
ovsdb_datum_add_unsafe(&new, &key, &value, &column->type);
struct ovsdb_datum datum;
die_if_error(ovsdb_datum_from_string(&datum, &column->type,
- value_string));
+ value_string, symtab));
ovsdb_idl_txn_write(row, column, &datum);
}
table = get_table(table_name);
row = must_get_row(ctx, table, record_id);
for (i = 3; i < ctx->argc; i++) {
- set_column(table, row, ctx->argv[i]);
+ set_column(table, row, ctx->argv[i], ctx->symtab);
}
}
add_type = *type;
add_type.n_min = 1;
add_type.n_max = UINT_MAX;
- die_if_error(ovsdb_datum_from_string(&add, &add_type, ctx->argv[i]));
+ die_if_error(ovsdb_datum_from_string(&add, &add_type, ctx->argv[i],
+ ctx->symtab));
ovsdb_datum_union(&old, &add, type, false);
ovsdb_datum_destroy(&add, type);
}
rm_type = *type;
rm_type.n_min = 1;
rm_type.n_max = UINT_MAX;
- error = ovsdb_datum_from_string(&rm, &rm_type, ctx->argv[i]);
+ error = ovsdb_datum_from_string(&rm, &rm_type,
+ ctx->argv[i], ctx->symtab);
if (error && ovsdb_type_is_map(&rm_type)) {
free(error);
rm_type.value.type = OVSDB_TYPE_VOID;
- die_if_error(ovsdb_datum_from_string(&rm, &rm_type, ctx->argv[i]));
+ die_if_error(ovsdb_datum_from_string(&rm, &rm_type,
+ ctx->argv[i], ctx->symtab));
}
ovsdb_datum_subtract(&old, type, &rm, &rm_type);
ovsdb_datum_destroy(&rm, &rm_type);
static void
cmd_create(struct vsctl_context *ctx)
{
+ const char *id = shash_find_data(&ctx->options, "--id");
const char *table_name = ctx->argv[1];
const struct vsctl_table_class *table;
const struct ovsdb_idl_row *row;
+ const struct uuid *uuid;
int i;
+ if (id) {
+ struct ovsdb_symbol *symbol;
+
+ if (id[0] != '@') {
+ vsctl_fatal("row id \"%s\" does not begin with \"@\"", id);
+ }
+
+ symbol = ovsdb_symbol_table_insert(ctx->symtab, id);
+ if (symbol->used) {
+ vsctl_fatal("row id \"%s\" may only be used to insert a single "
+ "row", id);
+ }
+ symbol->used = true;
+
+ uuid = &symbol->uuid;
+ } else {
+ uuid = NULL;
+ }
+
table = get_table(table_name);
- row = ovsdb_idl_txn_insert(ctx->txn, table->class);
+ row = ovsdb_idl_txn_insert(ctx->txn, table->class, uuid);
for (i = 2; i < ctx->argc; i++) {
- set_column(table, row, ctx->argv[i]);
+ set_column(table, row, ctx->argv[i], ctx->symtab);
}
ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
}
static void
vsctl_context_init(struct vsctl_context *ctx, struct vsctl_command *command,
struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn,
- const struct ovsrec_open_vswitch *ovs)
+ const struct ovsrec_open_vswitch *ovs,
+ struct ovsdb_symbol_table *symtab)
{
ctx->argc = command->argc;
ctx->argv = command->argv;
ctx->idl = idl;
ctx->txn = txn;
ctx->ovs = ovs;
-
+ ctx->symtab = symtab;
}
static void
struct ovsdb_idl_txn *txn;
const struct ovsrec_open_vswitch *ovs;
enum ovsdb_idl_txn_status status;
+ struct ovsdb_symbol_table *symtab;
+ const char *unused;
struct vsctl_command *c;
int64_t next_cfg = 0;
char *error;
json_destroy(where);
}
+ symtab = ovsdb_symbol_table_create();
for (c = commands; c < &commands[n_commands]; c++) {
struct vsctl_context ctx;
ds_init(&c->output);
- vsctl_context_init(&ctx, c, idl, txn, ovs);
+ vsctl_context_init(&ctx, c, idl, txn, ovs, symtab);
(c->syntax->run)(&ctx);
vsctl_context_done(&ctx, c);
}
if (c->syntax->postprocess) {
struct vsctl_context ctx;
- vsctl_context_init(&ctx, c, idl, txn, ovs);
+ vsctl_context_init(&ctx, c, idl, txn, ovs, symtab);
(c->syntax->postprocess)(&ctx);
vsctl_context_done(&ctx, c);
}
ovsdb_idl_txn_destroy(txn);
the_idl_txn = NULL;
+ unused = ovsdb_symbol_table_find_unused(symtab);
+ if (unused) {
+ vsctl_fatal("row id \"%s\" is referenced but never created (e.g. "
+ "with \"-- --id=%s create ...\")", unused, unused);
+ }
+ ovsdb_symbol_table_destroy(symtab);
+
switch (status) {
case TXN_INCOMPLETE:
NOT_REACHED();
for (c = commands; c < &commands[n_commands]; c++) {
struct ds *ds = &c->output;
+ struct shash_node *node;
+
if (oneline) {
size_t j;
fputs(ds_cstr(ds), stdout);
}
ds_destroy(&c->output);
+
+ SHASH_FOR_EACH (node, &c->options) {
+ free(node->data);
+ }
shash_destroy(&c->options);
}
free(commands);
{"add", 4, INT_MAX, cmd_add, NULL, ""},
{"remove", 4, INT_MAX, cmd_remove, NULL, ""},
{"clear", 3, INT_MAX, cmd_clear, NULL, ""},
- {"create", 2, INT_MAX, cmd_create, post_create, ""},
+ {"create", 2, INT_MAX, cmd_create, post_create, "--id="},
{"destroy", 1, INT_MAX, cmd_destroy, NULL, "--if-exists"},
{NULL, 0, 0, NULL, NULL, NULL},