|
|
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 |
|