diff options
Diffstat (limited to 'src/providers/fail_over.c')
-rw-r--r-- | src/providers/fail_over.c | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c index 5ef1436de..a16ab3363 100644 --- a/src/providers/fail_over.c +++ b/src/providers/fail_over.c @@ -72,6 +72,7 @@ struct fo_server { struct fo_server *prev; struct fo_server *next; + bool primary; void *user_data; int port; int port_status; @@ -577,7 +578,7 @@ fo_add_srv_server(struct fo_service *service, const char *srv, static struct fo_server * create_fo_server(struct fo_service *service, const char *name, - int port, void *user_data) + int port, void *user_data, bool primary) { struct fo_server *server; int ret; @@ -590,6 +591,7 @@ create_fo_server(struct fo_service *service, const char *name, server->user_data = user_data; server->service = service; server->port_status = DEFAULT_PORT_STATUS; + server->primary = primary; if (name != NULL) { ret = get_server_common(server, service->ctx, name, &server->common); @@ -621,26 +623,42 @@ fo_get_server_count(struct fo_service *service) return count; } +static bool fo_server_match(struct fo_server *server, + const char *name, + int port, + void *user_data) +{ + if (server->port != port || server->user_data != user_data) { + return false; + } + + if (name == NULL && server->common == NULL) { + return true; + } + + if (name != NULL && server->common != NULL) { + if (!strcasecmp(name, server->common->name)) + return true; + } + + return false; +} + int fo_add_server(struct fo_service *service, const char *name, int port, - void *user_data) + void *user_data, bool primary) { struct fo_server *server; DEBUG(3, ("Adding new server '%s', to service '%s'\n", name ? name : "(no name)", service->name)); DLIST_FOR_EACH(server, service->server_list) { - if (server->port != port || server->user_data != user_data) - continue; - if (name == NULL && server->common == NULL) { + if (fo_server_match(server, name, port, user_data)) { return EEXIST; - } else if (name != NULL && server->common != NULL) { - if (!strcasecmp(name, server->common->name)) - return EEXIST; } } - server = create_fo_server(service, name, port, user_data); + server = create_fo_server(service, name, port, user_data, primary); if (!server) { return ENOMEM; } @@ -658,7 +676,7 @@ get_first_server_entity(struct fo_service *service, struct fo_server **_server) /* If we already have a working server, use that one. */ server = service->active_server; if (server != NULL) { - if (service_works(server)) { + if (service_works(server) && fo_is_server_primary(server)) { goto done; } service->active_server = NULL; @@ -668,17 +686,27 @@ get_first_server_entity(struct fo_service *service, struct fo_server **_server) * Otherwise iterate through the server list. */ - /* First, try servers after the last one we tried. */ - if (service->last_tried_server != NULL) { + + /* First, try primary servers after the last one we tried. + * (only if the last one was primary as well) + */ + if (service->last_tried_server != NULL && + service->last_tried_server->primary) { DLIST_FOR_EACH(server, service->last_tried_server->next) { + /* Go only through primary servers */ + if (!server->primary) continue; + if (service_works(server)) { goto done; } } } - /* If none were found, try at the start. */ + /* If none were found, try at the start, primary first */ DLIST_FOR_EACH(server, service->server_list) { + /* First iterate only over primary servers */ + if (!server->primary) continue; + if (service_works(server)) { goto done; } @@ -687,6 +715,15 @@ get_first_server_entity(struct fo_service *service, struct fo_server **_server) } } + DLIST_FOR_EACH(server, service->server_list) { + /* Now iterate only over backup servers */ + if (server->primary) continue; + + if (service_works(server)) { + goto done; + } + } + service->last_tried_server = NULL; return ENOENT; @@ -727,6 +764,8 @@ set_lookup_hook(struct fo_server *server, struct tevent_req *req) return EOK; } + + /******************************************************************* * Get server to connect to. * *******************************************************************/ @@ -740,7 +779,6 @@ struct resolve_service_state { struct fo_ctx *fo_ctx; }; - static errno_t fo_resolve_service_activate_timeout(struct tevent_req *req, struct tevent_context *ev, const unsigned long timeout_seconds); static void fo_resolve_service_cont(struct tevent_req *subreq); @@ -1171,7 +1209,8 @@ resolve_srv_done(struct tevent_req *subreq) for (reply = reply_list; reply; reply = reply->next) { server = create_fo_server(state->service, reply->host, - reply->port, state->meta->user_data); + reply->port, state->meta->user_data, + true); if (!server) { ret = ENOMEM; goto fail; @@ -1451,6 +1490,12 @@ fo_get_server_hostent(struct fo_server *server) return server->common->rhostent; } +bool +fo_is_server_primary(struct fo_server *server) +{ + return server->primary; +} + time_t fo_get_server_hostname_last_change(struct fo_server *server) { |