ovsdb-idl: Simplify transaction retry.
[openvswitch] / utilities / ovs-vsctl.c
index d752a547d1bb9d11956e1ef63caa61fd22fd9df0..d22a518dd39f34522311c924a8a006c87154e03b 100644 (file)
@@ -138,9 +138,8 @@ static void parse_command(int argc, char *argv[], struct vsctl_command *);
 static const struct vsctl_command_syntax *find_command(const char *name);
 static void run_prerequisites(struct vsctl_command[], size_t n_commands,
                               struct ovsdb_idl *);
-static enum ovsdb_idl_txn_status do_vsctl(const char *args,
-                                          struct vsctl_command *, size_t n,
-                                          struct ovsdb_idl *);
+static void do_vsctl(const char *args, struct vsctl_command *, size_t n,
+                     struct ovsdb_idl *);
 
 static const struct vsctl_table_class *get_table(const char *table_name);
 static void set_column(const struct vsctl_table_class *,
@@ -156,9 +155,9 @@ int
 main(int argc, char *argv[])
 {
     extern struct vlog_module VLM_reconnect;
-    enum ovsdb_idl_txn_status status;
     struct ovsdb_idl *idl;
     struct vsctl_command *commands;
+    unsigned int seqno;
     size_t n_commands;
     char *args;
 
@@ -184,14 +183,23 @@ main(int argc, char *argv[])
     idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false);
     run_prerequisites(commands, n_commands, idl);
 
-    /* Now execute the commands. */
-    status = TXN_AGAIN_WAIT;
+    /* Execute the commands.
+     *
+     * 'seqno' is the database sequence number for which we last tried to
+     * execute our transaction.  There's no point in trying to commit more than
+     * once for any given sequence number, because if the transaction fails
+     * it's because the database changed and we need to obtain an up-to-date
+     * view of the database before we try the transaction again. */
+    seqno = ovsdb_idl_get_seqno(idl);
     for (;;) {
-        if (ovsdb_idl_run(idl) || status == TXN_AGAIN_NOW) {
-            status = do_vsctl(args, commands, n_commands, idl);
+        ovsdb_idl_run(idl);
+
+        if (seqno != ovsdb_idl_get_seqno(idl)) {
+            seqno = ovsdb_idl_get_seqno(idl);
+            do_vsctl(args, commands, n_commands, idl);
         }
 
-        if (status != TXN_AGAIN_NOW) {
+        if (seqno == ovsdb_idl_get_seqno(idl)) {
             ovsdb_idl_wait(idl);
             poll_block();
         }
@@ -3666,7 +3674,7 @@ run_prerequisites(struct vsctl_command *commands, size_t n_commands,
     }
 }
 
-static enum ovsdb_idl_txn_status
+static void
 do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
          struct ovsdb_idl *idl)
 {
@@ -3713,7 +3721,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
         vsctl_context_done(&ctx, c);
 
         if (ctx.try_again) {
-            status = TXN_AGAIN_WAIT;
+            status = TXN_TRY_AGAIN;
             goto try_again;
         }
     }
@@ -3770,8 +3778,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     case TXN_SUCCESS:
         break;
 
-    case TXN_AGAIN_WAIT:
-    case TXN_AGAIN_NOW:
+    case TXN_TRY_AGAIN:
         goto try_again;
 
     case TXN_ERROR:
@@ -3855,8 +3862,6 @@ try_again:
         free(c->table);
     }
     free(error);
-
-    return status;
 }
 
 static const struct vsctl_command_syntax all_commands[] = {