From efeff4b2d52525f35ba3c719a3432c3b390e3df2 Mon Sep 17 00:00:00 2001 From: Martin Nagy Date: Thu, 10 Dec 2009 22:34:07 +0100 Subject: fail over: Change the first server pick logic The logic of selecting the server to fail over to was changed so that we start from the server next to the one that didn't work the last time. This is because the status of a server that failed last time might get reset before we try another one. This can cause that we try to use the nonworking server repeatedly, not giving a chance to other servers. Fixes: #321 --- server/providers/fail_over.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'server') diff --git a/server/providers/fail_over.c b/server/providers/fail_over.c index 5c91bfc6d..9795ccecd 100644 --- a/server/providers/fail_over.c +++ b/server/providers/fail_over.c @@ -56,6 +56,7 @@ struct fo_service { struct fo_ctx *ctx; char *name; struct fo_server *active_server; + struct fo_server *last_tried_server; struct fo_server *server_list; }; @@ -391,21 +392,41 @@ get_first_server_entity(struct fo_service *service, struct fo_server **_server) server = service->active_server; if (server != NULL) { if (service_works(server)) { - *_server = server; - return EOK; + goto done; } service->active_server = NULL; } - /* Otherwise iterate through the server list. */ + /* + * Otherwise iterate through the server list. + */ + + /* First, try servers after the last one we tried. */ + if (service->last_tried_server != NULL) { + DLIST_FOR_EACH(server, service->last_tried_server->next) { + if (service_works(server)) { + goto done; + } + } + } + + /* If none were found, try at the start. */ DLIST_FOR_EACH(server, service->server_list) { if (service_works(server)) { - *_server = server; - return EOK; + goto done; + } + if (server == service->last_tried_server) { + break; } } + service->last_tried_server = NULL; return ENOENT; + +done: + service->last_tried_server = server; + *_server = server; + return EOK; } static int -- cgit