The "wait-until" command to be introduced in an upcoming commit needs to
be able to tell the ovs-vsctl main loop to try again later, since the
condition that it is looking for has not yet been satisfied. This commit
adds the infrastructure for this. (It's being broken out into a separate
commit because it modifies scattered code in ovs-vsctl.c and thus might
be easier to review this way.)
struct vsctl_command *commands;
size_t n_commands;
char *args;
struct vsctl_command *commands;
size_t n_commands;
char *args;
set_program_name(argv[0]);
signal(SIGPIPE, SIG_IGN);
set_program_name(argv[0]);
signal(SIGPIPE, SIG_IGN);
/* Now execute the commands. */
idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class);
/* Now execute the commands. */
idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class);
for (;;) {
if (ovsdb_idl_run(idl)) {
for (;;) {
if (ovsdb_idl_run(idl)) {
- if (++trials > 5) {
- vsctl_fatal("too many database inconsistency failures");
- }
do_vsctl(args, commands, n_commands, idl);
}
do_vsctl(args, commands, n_commands, idl);
}
struct ovsdb_idl_txn *txn;
struct ovsdb_symbol_table *symtab;
const struct ovsrec_open_vswitch *ovs;
struct ovsdb_idl_txn *txn;
struct ovsdb_symbol_table *symtab;
const struct ovsrec_open_vswitch *ovs;
+
+ /* A command may set this member to true if some prerequisite is not met
+ * and the caller should wait for something to change and then retry. */
+ bool try_again;
ctx->txn = txn;
ctx->ovs = ovs;
ctx->symtab = symtab;
ctx->txn = txn;
ctx->ovs = ovs;
ctx->symtab = symtab;
+
+ ctx->try_again = false;
}
symtab = ovsdb_symbol_table_create();
}
symtab = ovsdb_symbol_table_create();
+ for (c = commands; c < &commands[n_commands]; c++) {
+ ds_init(&c->output);
+ }
for (c = commands; c < &commands[n_commands]; c++) {
struct vsctl_context ctx;
for (c = commands; c < &commands[n_commands]; c++) {
struct vsctl_context ctx;
vsctl_context_init(&ctx, c, idl, txn, ovs, symtab);
(c->syntax->run)(&ctx);
vsctl_context_done(&ctx, c);
vsctl_context_init(&ctx, c, idl, txn, ovs, symtab);
(c->syntax->run)(&ctx);
vsctl_context_done(&ctx, c);
+
+ if (ctx.try_again) {
+ goto try_again;
+ }
}
status = ovsdb_idl_txn_commit_block(txn);
}
status = ovsdb_idl_txn_commit_block(txn);
vsctl_fatal("row id \"%s\" is referenced but never created (e.g. "
"with \"-- --id=%s create ...\")", unused, 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:
switch (status) {
case TXN_INCOMPLETE:
break;
case TXN_TRY_AGAIN:
break;
case TXN_TRY_AGAIN:
- for (c = commands; c < &commands[n_commands]; c++) {
- ds_destroy(&c->output);
- }
- free(error);
- return;
case TXN_ERROR:
vsctl_fatal("transaction error: %s", error);
case TXN_ERROR:
vsctl_fatal("transaction error: %s", error);
+ ovsdb_symbol_table_destroy(symtab);
+
for (c = commands; c < &commands[n_commands]; c++) {
struct ds *ds = &c->output;
struct shash_node *node;
for (c = commands; c < &commands[n_commands]; c++) {
struct ds *ds = &c->output;
struct shash_node *node;
ovsdb_idl_destroy(idl);
exit(EXIT_SUCCESS);
ovsdb_idl_destroy(idl);
exit(EXIT_SUCCESS);
+
+try_again:
+ /* Our transaction needs to be rerun, or a prerequisite was not met. Free
+ * resources and return so that the caller can try again. */
+ ovsdb_idl_txn_abort(txn);
+ ovsdb_idl_txn_destroy(txn);
+ ovsdb_symbol_table_destroy(symtab);
+ for (c = commands; c < &commands[n_commands]; c++) {
+ ds_destroy(&c->output);
+ }
+ free(error);
}
static const struct vsctl_command_syntax all_commands[] = {
}
static const struct vsctl_command_syntax all_commands[] = {