summaryrefslogtreecommitdiff
path: root/src/providers/fail_over.h
blob: 1ad081e78c866390a1a345feacc5c0899adf91a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
   SSSD

   Fail over helper functions.

   Authors:
        Martin Nagy <mnagy@redhat.com>

   Copyright (C) Red Hat, Inc 2009

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __FAIL_OVER_H__
#define __FAIL_OVER_H__

#include <stdbool.h>
#include <talloc.h>

#include "resolv/async_resolv.h"

#define FO_PROTO_TCP "tcp"
#define FO_PROTO_UDP "udp"

#define FO_DEFAULT_SVC_TIMEOUT 10

/* Some forward declarations that don't have to do anything with fail over. */
struct hostent;
struct tevent_context;
struct tevent_req;

enum port_status {
    PORT_NEUTRAL,    /* We didn't try this port yet. */
    PORT_WORKING,    /* This port was reported to work. */
    PORT_NOT_WORKING /* This port was reported to not work. */
};

enum server_status {
    SERVER_NAME_NOT_RESOLVED, /* We didn't yet resolved the host name. */
    SERVER_RESOLVING_NAME,    /* Name resolving is in progress. */
    SERVER_NAME_RESOLVED,     /* We resolved the host name but didn't try to connect. */
    SERVER_WORKING,           /* We successfully connected to the server. */
    SERVER_NOT_WORKING        /* We tried and failed to connect to the server. */
};

struct fo_ctx;
struct fo_service;
struct fo_server;

/*
 * Failover settings.
 *
 * The 'retry_timeout' member specifies the
 * duration in seconds of how long a server or port will be considered
 * non-working after being marked as such.
 *
 * The 'service_resolv_timeout' member specifies how long we wait for
 * service resolution. When this timeout is reached, the resolve request
 * is cancelled with an error
 *
 * The 'srv_retry_timeout' member specifies how long a SRV lookup
 * is considered valid until we ask the server again.
 *
 * The family_order member specifies the order of address families to
 * try when looking up the service.
 */
struct fo_options {
    time_t srv_retry_timeout;
    time_t retry_timeout;
    int service_resolv_timeout;
    enum restrict_family family_order;
};

/*
 * Create a new fail over context based on options passed in the
 * opts parameter
 */
struct fo_ctx *fo_context_init(TALLOC_CTX *mem_ctx,
                               struct fo_options *opts);

typedef int (*datacmp_fn)(void*, void*);

/*
 * Create a new service structure for 'ctx', saving it to the location pointed
 * to by '_service'. The needed memory will be allocated from 'ctx'.
 * Service name will be set to 'name'.
 *
 * Function pointed by user_data_cmp returns 0 if user_data is equal
 * or nonzero value if not. Set to NULL if no user data comparison
 * is needed in fail over duplicate servers detection.
 */
int fo_new_service(struct fo_ctx *ctx,
                   const char *name,
                   datacmp_fn user_data_cmp,
                   struct fo_service **_service);

/*
 * Look up service named 'name' from the 'ctx' service list. Target of
 * '_service' will be set to the service if it was found.
 */
int fo_get_service(struct fo_ctx *ctx,
                   const char *name,
                   struct fo_service **_service);

/*
 * Get number of servers registered for the 'service'.
 */
int fo_get_server_count(struct fo_service *service);

/*
 * Adds a server 'name' to the 'service'. Port 'port' will be used for
 * connection. If 'name' is NULL, no server resolution will be done.
 */
int fo_add_server(struct fo_service *service,
                  const char *name, int port,
                  void *user_data, bool primary);


int fo_add_srv_server(struct fo_service *service,
                      const char *srv,
                      const char *discovery_domain,
                      const char *sssd_domain,
                      const char *proto,
                      void *user_data);

/*
 * Request the first server from the service's list of servers. It is only
 * considered if it is not marked as not working (or the retry interval already
 * passed). If the server address wasn't resolved yet, it will be done.
 */
struct tevent_req *fo_resolve_service_send(TALLOC_CTX *mem_ctx,
                                           struct tevent_context *ev,
                                           struct resolv_ctx *resolv,
                                           struct fo_ctx *ctx,
                                           struct fo_service *service);

int fo_resolve_service_recv(struct tevent_req *req,
                            struct fo_server **server);

/*
 * Set feedback about 'server'. Caller should use this to indicate a problem
 * with the server itself, not only with the service on that server. This
 * should be used, for example, when the IP address of the server can't be
 * reached. This setting can affect other services as well, since they can
 * share the same server.
 */
void fo_set_server_status(struct fo_server *server,
                          enum server_status status);

/*
 * Set feedback about the port status. This function should be used when
 * the server itself is working but the service is not. When status is set
 * to PORT_WORKING, 'server' is also marked as an "active server" for its
 * service. When the next fo_resolve_service_send() function is called, this
 * server will be preferred. This will hold as long as it is not marked as
 * not-working.
 */
void fo_set_port_status(struct fo_server *server,
                        enum port_status status);

/*
 * Instruct fail-over to try next server on the next connect attempt.
 * Should be used after connection to service was unexpectedly dropped
 * but there is no authoritative information on whether active server is down.
 */
void fo_try_next_server(struct fo_service *service);

void *fo_get_server_user_data(struct fo_server *server);

int fo_get_server_port(struct fo_server *server);

const char *fo_get_server_name(struct fo_server *server);

const char *fo_get_server_str_name(struct fo_server *server);

struct resolv_hostent *fo_get_server_hostent(struct fo_server *server);

bool fo_is_server_primary(struct fo_server *server);

time_t fo_get_server_hostname_last_change(struct fo_server *server);

int fo_is_srv_lookup(struct fo_server *s);

time_t fo_get_service_retry_timeout(struct fo_service *svc);

void fo_reset_services(struct fo_ctx *fo_ctx);

bool fo_svc_has_server(struct fo_service *service, struct fo_server *server);

#endif /* !__FAIL_OVER_H__ */