bbaaef
From ab959077c3dce4bd856f3d6bf633779a41dccdff Mon Sep 17 00:00:00 2001
bbaaef
From: Dumitru Ceara <dceara@redhat.com>
bbaaef
Date: Mon, 9 Dec 2019 09:12:18 +0100
bbaaef
Subject: [PATCH ovn] ovn-controller: Run I-P engine even when no SB txn is
bbaaef
 available.
bbaaef
bbaaef
If the last ovn-controller main loop run started a transaction to the
bbaaef
Southbound DB and the transaction is still in progress, ovn-controller
bbaaef
will not call engine_run(). In case there were changes to the DB,
bbaaef
engine_need_run() would return true which would trigger an immediate
bbaaef
forced recompute in the next processing loop iteration.
bbaaef
bbaaef
However, there are scenarios when updates can be processed incrementally
bbaaef
even if no Southbound DB transaction is available. One example, often
bbaaef
seen in the field, is when the MAC_Binding table is updated. Currently
bbaaef
such an update received while a transaction is still committing would
bbaaef
trigger a forced recompute.
bbaaef
bbaaef
This patch performs only incremental processing when the SB DB txn
bbaaef
is NULL, which means executing change_handler() methods
bbaaef
only, without calling the run() methods of the I-P engine nodes.
bbaaef
Assuming that some change handlers need to update the DB and that
bbaaef
some don't, if the SB DB txn is NULL:
bbaaef
- if the incoming change doesn't trigger a SB DB update (currently true
bbaaef
  for all existing change handlers) then the change handler might
bbaaef
  complete without aborting if it doesn't trigger a run() of the node.
bbaaef
- if the incoming change tries to perform a SB DB update, the change
bbaaef
  handler should return false (SB DB txn is NULL) triggering the engine
bbaaef
  to call run() and abort computation.
bbaaef
bbaaef
CC: Han Zhou <hzhou@ovn.org>
bbaaef
CC: Numan Siddique <numans@ovn.org>
bbaaef
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
bbaaef
Signed-off-by: Han Zhou <hzhou@ovn.org>
bbaaef
bbaaef
(cherry picked from upstream commit e2ab60e3a7c60f3adb8da40e4d1cfeb890d6f80e)
bbaaef
bbaaef
Change-Id: Ifdc87b925fc3e9c8b3c22d9b853ac27f2480f388
bbaaef
---
bbaaef
 ovn/controller/ovn-controller.c |  8 ++++++++
bbaaef
 ovn/lib/inc-proc-eng.h          | 15 ++++++++++++++-
bbaaef
 2 files changed, 22 insertions(+), 1 deletion(-)
bbaaef
bbaaef
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
bbaaef
index cb23bc8..c8470ce 100644
bbaaef
--- a/ovn/controller/ovn-controller.c
bbaaef
+++ b/ovn/controller/ovn-controller.c
bbaaef
@@ -2059,6 +2059,14 @@ main(int argc, char *argv[])
bbaaef
                         } else {
bbaaef
                             engine_run(true);
bbaaef
                         }
bbaaef
+                    } else {
bbaaef
+                        /* Even if there's no SB DB transaction available,
bbaaef
+                         * try to run the engine so that we can handle any
bbaaef
+                         * incremental changes that don't require a recompute.
bbaaef
+                         * If a recompute is required, the engine will abort,
bbaaef
+                         * triggerring a full run in the next iteration.
bbaaef
+                         */
bbaaef
+                        engine_run(false);
bbaaef
                     }
bbaaef
                     stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME,
bbaaef
                                    time_msec());
bbaaef
diff --git a/ovn/lib/inc-proc-eng.h b/ovn/lib/inc-proc-eng.h
bbaaef
index 9cc99a3..c62f3bc 100644
bbaaef
--- a/ovn/lib/inc-proc-eng.h
bbaaef
+++ b/ovn/lib/inc-proc-eng.h
bbaaef
@@ -84,6 +84,10 @@ struct engine_node_input {
bbaaef
      * evaluated against all the other inputs. Returns:
bbaaef
      *  - true: if change can be handled
bbaaef
      *  - false: if change cannot be handled (indicating full recompute needed)
bbaaef
+     * A change handler can also call engine_get_context() but it must make
bbaaef
+     * sure the txn pointers returned by it are non-NULL. In case the change
bbaaef
+     * handler needs to use the txn pointers returned by engine_get_context(),
bbaaef
+     * and the pointers are NULL, the change handler MUST return false.
bbaaef
      */
bbaaef
     bool (*change_handler)(struct engine_node *node, void *data);
bbaaef
 };
bbaaef
@@ -133,6 +137,9 @@ struct engine_node {
bbaaef
 
bbaaef
     /* Fully processes all inputs of this node and regenerates the data
bbaaef
      * of this node. The pointer to the node's data is passed as argument.
bbaaef
+     * 'run' handlers can also call engine_get_context() and the
bbaaef
+     * implementation guarantees that the txn pointers returned
bbaaef
+     * engine_get_context() are not NULL and valid.
bbaaef
      */
bbaaef
     void (*run)(struct engine_node *node, void *data);
bbaaef
 
bbaaef
@@ -189,7 +196,13 @@ void engine_add_input(struct engine_node *node, struct engine_node *input,
bbaaef
  * iteration, and the change can't be tracked across iterations */
bbaaef
 void engine_set_force_recompute(bool val);
bbaaef
 
bbaaef
-const struct engine_context * engine_get_context(void);
bbaaef
+/* Return the current engine_context. The values in the context can be NULL
bbaaef
+ * if the engine is run with allow_recompute == false in the current
bbaaef
+ * iteration.
bbaaef
+ * Therefore, it is the responsibility of the caller to check the context
bbaaef
+ * values when called from change handlers.
bbaaef
+ */
bbaaef
+const struct engine_context *engine_get_context(void);
bbaaef
 
bbaaef
 void engine_set_context(const struct engine_context *);
bbaaef
 
bbaaef
-- 
bbaaef
1.8.3.1
bbaaef