summaryrefslogtreecommitdiff
path: root/ovsdb/trigger.c
diff options
context:
space:
mode:
authorHan Zhou <hzhou@ovn.org>2020-02-28 18:07:07 -0800
committerBen Pfaff <blp@ovn.org>2020-03-06 13:47:58 -0800
commitbb66a0a6eb7971556504a294f5cf796d1d72db25 (patch)
tree874389ac602ad61d2d73cccbeec2a61cd98ca41e /ovsdb/trigger.c
parent2833885f7ab565ce07f40de2ab8d415dc0390329 (diff)
downloadopenvswitch-bb66a0a6eb7971556504a294f5cf796d1d72db25.tar.gz
raft: Avoid busy loop during leader election.
When a server doesn't see a leader yet, e.g. during leader re-election, if a transaction comes from a client, it will cause 100% CPU busy loop. With debug log enabled it is like: 2020-02-28T04:04:35.631Z|00059|poll_loop|DBG|wakeup due to 0-ms timeout at ../ovsdb/trigger.c:164 2020-02-28T04:04:35.631Z|00062|poll_loop|DBG|wakeup due to 0-ms timeout at ../ovsdb/trigger.c:164 2020-02-28T04:04:35.631Z|00065|poll_loop|DBG|wakeup due to 0-ms timeout at ../ovsdb/trigger.c:164 2020-02-28T04:04:35.631Z|00068|poll_loop|DBG|wakeup due to 0-ms timeout at ../ovsdb/trigger.c:164 2020-02-28T04:04:35.631Z|00071|poll_loop|DBG|wakeup due to 0-ms timeout at ../ovsdb/trigger.c:164 2020-02-28T04:04:35.631Z|00074|poll_loop|DBG|wakeup due to 0-ms timeout at ../ovsdb/trigger.c:164 2020-02-28T04:04:35.631Z|00077|poll_loop|DBG|wakeup due to 0-ms timeout at ../ovsdb/trigger.c:164 ... The problem is that in ovsdb_trigger_try(), all cluster errors are treated as temporary error and retry immediately. This patch fixes it by introducing 'run_triggers_now', which tells if a retry is needed immediately. When the cluster error is with detail 'not leader', we don't immediately retry, but will wait for the next poll event to trigger the retry. When 'not leader' status changes, there must be a event, i.e. raft RPC that changes the status, so the trigger is guaranteed to be triggered, without busy loop. Signed-off-by: Han Zhou <hzhou@ovn.org> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'ovsdb/trigger.c')
-rw-r--r--ovsdb/trigger.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/ovsdb/trigger.c b/ovsdb/trigger.c
index 7e62e90ae..0372302af 100644
--- a/ovsdb/trigger.c
+++ b/ovsdb/trigger.c
@@ -141,7 +141,7 @@ ovsdb_trigger_run(struct ovsdb *db, long long int now)
struct ovsdb_trigger *t, *next;
bool run_triggers = db->run_triggers;
- db->run_triggers = false;
+ db->run_triggers_now = db->run_triggers = false;
bool disconnect_all = false;
@@ -160,7 +160,7 @@ ovsdb_trigger_run(struct ovsdb *db, long long int now)
void
ovsdb_trigger_wait(struct ovsdb *db, long long int now)
{
- if (db->run_triggers) {
+ if (db->run_triggers_now) {
poll_immediate_wake();
} else {
long long int deadline = LLONG_MAX;
@@ -319,9 +319,16 @@ ovsdb_trigger_try(struct ovsdb_trigger *t, long long int now)
if (!strcmp(ovsdb_error_get_tag(error), "cluster error")) {
/* Temporary error. Transition back to "initialized" state to
* try again. */
+ char *err_s = ovsdb_error_to_string(error);
+ VLOG_DBG("cluster error %s", err_s);
+
jsonrpc_msg_destroy(t->reply);
t->reply = NULL;
t->db->run_triggers = true;
+ if (!strstr(err_s, "not leader")) {
+ t->db->run_triggers_now = true;
+ }
+ free(err_s);
ovsdb_error_destroy(error);
} else {
/* Permanent error. Transition to "completed" state to report