struct vsctl_command *commands;
size_t n_commands;
char *args;
- int trials;
set_program_name(argv[0]);
signal(SIGPIPE, SIG_IGN);
/* Now execute the commands. */
idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class);
- trials = 0;
for (;;) {
if (ovsdb_idl_run(idl)) {
- if (++trials > 5) {
- vsctl_fatal("too many database inconsistency failures");
- }
do_vsctl(args, commands, n_commands, idl);
}
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;
};
struct vsctl_bridge {
ctx->txn = txn;
ctx->ovs = ovs;
ctx->symtab = symtab;
+
+ ctx->try_again = false;
}
static void
}
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;
- ds_init(&c->output);
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);
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:
break;
case TXN_TRY_AGAIN:
- for (c = commands; c < &commands[n_commands]; c++) {
- ds_destroy(&c->output);
- }
- free(error);
- return;
+ goto try_again;
case TXN_ERROR:
vsctl_fatal("transaction error: %s", error);
}
free(error);
+ ovsdb_symbol_table_destroy(symtab);
+
for (c = commands; c < &commands[n_commands]; c++) {
struct ds *ds = &c->output;
struct shash_node *node;
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[] = {