ovs-vsctl: Allow commands to tell ovs-vsctl to try again later.
authorBen Pfaff <blp@nicira.com>
Thu, 24 Jun 2010 18:01:53 +0000 (11:01 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 29 Jun 2010 16:33:13 +0000 (09:33 -0700)
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.)

utilities/ovs-vsctl.c

index 2f78a53bcfe74be44a6fa654d7be75e8cd2ced8e..4c0a20051862445fff7375432fb485bc0978cce1 100644 (file)
@@ -122,7 +122,6 @@ main(int argc, char *argv[])
     struct vsctl_command *commands;
     size_t n_commands;
     char *args;
-    int trials;
 
     set_program_name(argv[0]);
     signal(SIGPIPE, SIG_IGN);
@@ -146,12 +145,8 @@ main(int argc, char *argv[])
 
     /* 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);
         }
 
@@ -507,6 +502,10 @@ struct vsctl_context {
     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 {
@@ -2608,6 +2607,8 @@ vsctl_context_init(struct vsctl_context *ctx, struct vsctl_command *command,
     ctx->txn = txn;
     ctx->ovs = ovs;
     ctx->symtab = symtab;
+
+    ctx->try_again = false;
 }
 
 static void
@@ -2649,13 +2650,19 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     }
 
     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);
@@ -2682,7 +2689,6 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
         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:
@@ -2697,11 +2703,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
         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);
@@ -2711,6 +2713,8 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     }
     free(error);
 
+    ovsdb_symbol_table_destroy(symtab);
+
     for (c = commands; c < &commands[n_commands]; c++) {
         struct ds *ds = &c->output;
         struct shash_node *node;
@@ -2765,6 +2769,17 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     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[] = {