diff options
author | Han Zhou <hzhou@ovn.org> | 2020-02-28 18:07:07 -0800 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2020-03-06 13:47:58 -0800 |
commit | bb66a0a6eb7971556504a294f5cf796d1d72db25 (patch) | |
tree | 874389ac602ad61d2d73cccbeec2a61cd98ca41e /ovsdb/trigger.c | |
parent | 2833885f7ab565ce07f40de2ab8d415dc0390329 (diff) | |
download | openvswitch-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.c | 11 |
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 |