dddd63
From a2271039d49a12390ca3118fb3a90a057577d360 Mon Sep 17 00:00:00 2001
773311
From: Numan Siddique <numans@ovn.org>
773311
Date: Fri, 5 Jun 2020 14:00:29 +0530
dddd63
Subject: [PATCH 2/4] ovsdb idl: Try committing the pending txn in
773311
 ovsdb_idl_loop_run.
773311
773311
The function ovsdb_idl_loop_run(), after calling ovsdb_idl_run(),
773311
returns a transaction object (of type 'struct ovsdb_idl_txn').
773311
The returned transaction object can be NULL if there is a pending
773311
transaction (loop->committing_txn) in the idl loop object.
773311
773311
Normally the clients of idl library, first call ovsdb_idl_loop_run(),
773311
then do their own processing and create any idl transactions during
773311
this processing and then finally call ovsdb_idl_loop_commit_and_wait().
773311
773311
If ovsdb_idl_loop_run() returns NULL transaction object, then much
773311
of the processing done by the client gets wasted as in the case
773311
of ovn-controller.
773311
773311
The client (in this case ovn-controller), can skip the processing
773311
and instead call ovsdb_idl_loop_commit_and_wait() if the transaction
773311
oject is NULL. But ovn-controller uses IDL tracking and it may
773311
loose the tracked changes in that run.
773311
773311
This patch tries to improve this scenario, by checking if the
773311
pending transaction can be committed in the ovsdb_idl_loop_run()
773311
itself and if the pending transaction is cleared (because of the
773311
response messages from ovsdb-server due to a transaction message
773311
in the previous run), ovsdb_idl_loop_run() can return a valid
773311
transaction object.
773311
773311
CC: Han Zhou <hzhou@ovn.org>
773311
Signed-off-by: Numan Siddique <numans@ovn.org>
773311
Signed-off-by: Ben Pfaff <blp@ovn.org>
773311
---
773311
 openvswitch-2.13.0/lib/ovsdb-idl.c | 143 +++++++++++++++++++----------
773311
 1 file changed, 93 insertions(+), 50 deletions(-)
773311
773311
diff --git a/openvswitch-2.13.0/lib/ovsdb-idl.c b/openvswitch-2.13.0/lib/ovsdb-idl.c
773311
index 1535ad7b5..2d351791f 100644
773311
--- a/openvswitch-2.13.0/lib/ovsdb-idl.c
773311
+++ b/openvswitch-2.13.0/lib/ovsdb-idl.c
773311
@@ -385,6 +385,8 @@ static void ovsdb_idl_send_cond_change(struct ovsdb_idl *idl);
773311
 static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *);
773311
 static void ovsdb_idl_add_to_indexes(const struct ovsdb_idl_row *);
773311
 static void ovsdb_idl_remove_from_indexes(const struct ovsdb_idl_row *);
773311
+static int ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop,
773311
+                                         bool *may_need_wakeup);
773311
 
773311
 static void
773311
 ovsdb_idl_db_init(struct ovsdb_idl_db *db, const struct ovsdb_idl_class *class,
773311
@@ -5329,6 +5331,12 @@ struct ovsdb_idl_txn *
773311
 ovsdb_idl_loop_run(struct ovsdb_idl_loop *loop)
773311
 {
773311
     ovsdb_idl_run(loop->idl);
773311
+
773311
+    /* See if we can commit the loop->committing_txn. */
773311
+    if (loop->committing_txn) {
773311
+        ovsdb_idl_try_commit_loop_txn(loop, NULL);
773311
+    }
773311
+
773311
     loop->open_txn = (loop->committing_txn
773311
                       || ovsdb_idl_get_seqno(loop->idl) == loop->skip_seqno
773311
                       ? NULL
773311
@@ -5336,6 +5344,87 @@ ovsdb_idl_loop_run(struct ovsdb_idl_loop *loop)
773311
     return loop->open_txn;
773311
 }
773311
 
773311
+/* Attempts to commit the current transaction, if one is open.
773311
+ *
773311
+ * If a transaction was open, in this or a previous iteration of the main loop,
773311
+ * and had not before finished committing (successfully or unsuccessfully), the
773311
+ * return value is one of:
773311
+ *
773311
+ *  1: The transaction committed successfully (or it did not change anything in
773311
+ *     the database).
773311
+ *  0: The transaction failed.
773311
+ * -1: The commit is still in progress.
773311
+ *
773311
+ * Thus, the return value is -1 if the transaction is in progress and otherwise
773311
+ * true for success, false for failure.
773311
+ *
773311
+ * (In the corner case where the IDL sends a transaction to the database and
773311
+ * the database commits it, and the connection between the IDL and the database
773311
+ * drops before the IDL receives the message confirming the commit, this
773311
+ * function can return 0 even though the transaction succeeded.)
773311
+ */
773311
+static int
773311
+ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop,
773311
+                              bool *may_need_wakeup)
773311
+{
773311
+    if (!loop->committing_txn) {
773311
+        /* Not a meaningful return value: no transaction was in progress. */
773311
+        return 1;
773311
+    }
773311
+
773311
+    int retval;
773311
+    struct ovsdb_idl_txn *txn = loop->committing_txn;
773311
+
773311
+    enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn);
773311
+    if (status != TXN_INCOMPLETE) {
773311
+        switch (status) {
773311
+        case TXN_TRY_AGAIN:
773311
+            /* We want to re-evaluate the database when it's changed from
773311
+             * the contents that it had when we started the commit.  (That
773311
+             * might have already happened.) */
773311
+            loop->skip_seqno = loop->precommit_seqno;
773311
+            if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno
773311
+                && may_need_wakeup) {
773311
+                *may_need_wakeup = true;
773311
+            }
773311
+            retval = 0;
773311
+            break;
773311
+
773311
+        case TXN_SUCCESS:
773311
+            /* Possibly some work on the database was deferred because no
773311
+             * further transaction could proceed.  Wake up again. */
773311
+            retval = 1;
773311
+            loop->cur_cfg = loop->next_cfg;
773311
+            if (may_need_wakeup) {
773311
+                *may_need_wakeup =  true;
773311
+            }
773311
+            break;
773311
+
773311
+        case TXN_UNCHANGED:
773311
+            retval = 1;
773311
+            loop->cur_cfg = loop->next_cfg;
773311
+            break;
773311
+
773311
+        case TXN_ABORTED:
773311
+        case TXN_NOT_LOCKED:
773311
+        case TXN_ERROR:
773311
+            retval = 0;
773311
+            break;
773311
+
773311
+        case TXN_UNCOMMITTED:
773311
+        case TXN_INCOMPLETE:
773311
+        default:
773311
+            OVS_NOT_REACHED();
773311
+        }
773311
+        ovsdb_idl_txn_destroy(txn);
773311
+        loop->committing_txn = NULL;
773311
+    } else {
773311
+        retval = -1;
773311
+    }
773311
+
773311
+    return retval;
773311
+}
773311
+
773311
 /* Attempts to commit the current transaction, if one is open, and sets up the
773311
  * poll loop to wake up when some more work might be needed.
773311
  *
773311
@@ -5366,57 +5455,11 @@ ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *loop)
773311
         loop->precommit_seqno = ovsdb_idl_get_seqno(loop->idl);
773311
     }
773311
 
773311
-    struct ovsdb_idl_txn *txn = loop->committing_txn;
773311
-    int retval;
773311
-    if (txn) {
773311
-        enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn);
773311
-        if (status != TXN_INCOMPLETE) {
773311
-            switch (status) {
773311
-            case TXN_TRY_AGAIN:
773311
-                /* We want to re-evaluate the database when it's changed from
773311
-                 * the contents that it had when we started the commit.  (That
773311
-                 * might have already happened.) */
773311
-                loop->skip_seqno = loop->precommit_seqno;
773311
-                if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno) {
773311
-                    poll_immediate_wake();
773311
-                }
773311
-                retval = 0;
773311
-                break;
773311
-
773311
-            case TXN_SUCCESS:
773311
-                /* Possibly some work on the database was deferred because no
773311
-                 * further transaction could proceed.  Wake up again. */
773311
-                retval = 1;
773311
-                loop->cur_cfg = loop->next_cfg;
773311
-                poll_immediate_wake();
773311
-                break;
773311
-
773311
-            case TXN_UNCHANGED:
773311
-                retval = 1;
773311
-                loop->cur_cfg = loop->next_cfg;
773311
-                break;
773311
-
773311
-            case TXN_ABORTED:
773311
-            case TXN_NOT_LOCKED:
773311
-            case TXN_ERROR:
773311
-                retval = 0;
773311
-                break;
773311
-
773311
-            case TXN_UNCOMMITTED:
773311
-            case TXN_INCOMPLETE:
773311
-            default:
773311
-                OVS_NOT_REACHED();
773311
-            }
773311
-            ovsdb_idl_txn_destroy(txn);
773311
-            loop->committing_txn = NULL;
773311
-        } else {
773311
-            retval = -1;
773311
-        }
773311
-    } else {
773311
-        /* Not a meaningful return value: no transaction was in progress. */
773311
-        retval = 1;
773311
+    bool may_need_wakeup = false;
773311
+    int retval = ovsdb_idl_try_commit_loop_txn(loop, &may_need_wakeup);
773311
+    if (may_need_wakeup) {
773311
+        poll_immediate_wake();
773311
     }
773311
-
773311
     ovsdb_idl_wait(loop->idl);
773311
 
773311
     return retval;
773311
-- 
773311
2.26.2
773311