summaryrefslogtreecommitdiffstats
path: root/src/providers/fail_over.c
diff options
context:
space:
mode:
authorJan Zeleny <jzeleny@redhat.com>2012-06-04 12:06:53 -0400
committerJakub Hrozek <jhrozek@redhat.com>2012-08-01 16:19:41 +0200
commitbbd33e46aa6194c1086939f7cf8538c067186455 (patch)
treead91dc6f2042491e3728d096d7571f7e3b13e73a /src/providers/fail_over.c
parent75ee7925a9e289bc24f0ce8a7988cca926b71513 (diff)
downloadsssd_unused-bbd33e46aa6194c1086939f7cf8538c067186455.tar.gz
sssd_unused-bbd33e46aa6194c1086939f7cf8538c067186455.tar.xz
sssd_unused-bbd33e46aa6194c1086939f7cf8538c067186455.zip
Primary server support: basic support in failover code
Now there are two list of servers for each service. If currently selected server is only backup, then an event will be scheduled which tries to get connection to one of primary servers and if it succeeds, it starts using this server instead of the one which is currently connected to.
Diffstat (limited to 'src/providers/fail_over.c')
-rw-r--r--src/providers/fail_over.c75
1 files changed, 60 insertions, 15 deletions
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index 5ef1436d..a16ab336 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)
{