95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang Fail over helper functions.
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang Martin Nagy <mnagy@redhat.com>
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang Jakub Hrozek <jhrozek@redhat.com>
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang Copyright (C) Red Hat, Inc 2010
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang This program is free software; you can redistribute it and/or modify
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang it under the terms of the GNU General Public License as published by
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang the Free Software Foundation; either version 3 of the License, or
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang (at your option) any later version.
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang This program is distributed in the hope that it will be useful,
67d5e49547d78aa56a8f9ba5e64a950b730eba66Till Mossakowski but WITHOUT ANY WARRANTY; without even the implied warranty of
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang GNU General Public License for more details.
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang You should have received a copy of the GNU General Public License
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang along with this program. If not, see <http://www.gnu.org/licenses/>.
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang#define STATUS_DIFF(p, now) ((now).tv_sec - (p)->last_status_change.tv_sec)
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang#define SERVER_NAME(s) ((s)->common ? (s)->common->name : "(no name)")
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang#define DEFAULT_SERVER_STATUS SERVER_NAME_NOT_RESOLVED
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang SRV_NEUTRAL, /* We didn't try this SRV lookup yet */
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang SRV_RESOLVE_ERROR, /* Could not resolve this SRV lookup */
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang /* Function pointed by user_data_cmp returns 0 if user_data is equal
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang * or nonzero value if not. Set to NULL if no user data comparison
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang * is needed in fail over duplicate servers detection.
6c8dc7ab7cb52a12cba748fe0f6b8d8d17a95eb9Heng Jiangfo_context_init(TALLOC_CTX *mem_ctx, struct fo_options *opts)
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang ctx->opts->srv_retry_neg_timeout = opts->srv_retry_neg_timeout;
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang ctx->opts->service_resolv_timeout = opts->service_resolv_timeout;
806bce66335c88260a63e7524b1efc68d8dfacc1Heng Jiang "Created new fail over context, retry timeout is %ld\n",
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiangstatic const char *
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "neutral";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "working";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "not working";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "unknown port status";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiangstatic const char *
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiangstr_srv_data_status(enum srv_lookup_status status)
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "neutral";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "resolved";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "not resolved";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "expired";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "unknown SRV lookup status";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiangstatic const char *
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "name not resolved";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "resolving name";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "name resolved";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "working";
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang return "not working";
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang return "unknown server status";
b91c4dbd00294ce29ab1ae84ad4e8c93ca5ad943Heng Jiang return s && s->srv_data;
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiangstatic void fo_server_free(struct fo_server *server)
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiangstatic struct fo_server *
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DEBUG(SSSDBG_CONF_SETTINGS, "Need to refresh SRV lookup for domain %s\n",
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang while (server->prev && server->prev->srv_data == meta->srv_data) {
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang while (server->next && server->next->srv_data == meta->srv_data) {
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang if (server == server->service->last_tried_server) {
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang /* add back the meta server to denote SRV lookup */
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DLIST_ADD_AFTER(server->service->server_list, meta, server);
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DLIST_REMOVE(server->service->server_list, server);
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang /* Determine timeout value based on state of previous lookup. */
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang if (data->srv_lookup_status == SRV_RESOLVE_ERROR) {
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang timeout = data->meta->service->ctx->opts->srv_retry_neg_timeout;
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang "Changing state of SRV lookup from 'SRV_RESOLVE_ERROR' to "
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang "'SRV_NEUTRAL'.\n");
67d5e49547d78aa56a8f9ba5e64a950b730eba66Till Mossakowski DEBUG(SSSDBG_CRIT_FAILURE, "Unknown state for SRV server!\n");
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiangset_srv_data_status(struct srv_data *data, enum srv_lookup_status status)
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DEBUG(SSSDBG_CONF_SETTINGS, "Marking SRV lookup of service '%s' as '%s'\n",
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang data->meta->service->name, str_srv_data_status(status));
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang * This function will return the status of the server. If the status was
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang * last updated a long time ago, we will first reset the status.
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang "Status of server '%s' is '%s'\n", SERVER_NAME(server),
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang str_server_status(server->common->server_status));
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang timeout = server->service->ctx->opts->retry_timeout;
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang if (timeout != 0 && server->common->server_status == SERVER_NOT_WORKING) {
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DEBUG(SSSDBG_CONF_SETTINGS, "Reseting the server status of '%s'\n",
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang server->common->server_status = SERVER_NAME_NOT_RESOLVED;
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang server->common->last_status_change.tv_sec = tv.tv_sec;
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang if (server->common->rhostent && STATUS_DIFF(server->common, tv) >
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang "Hostname resolution expired, resetting the server "
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED);
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang * This function will return the status of the service. If the status was
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang * last updated a long time ago, we will first reset the status.
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang "Port status of port %d for server '%s' is '%s'\n", server->port,
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang SERVER_NAME(server), str_port_status(server->port_status));
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang timeout = server->service->ctx->opts->retry_timeout;
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang if (timeout != 0 && server->port_status == PORT_NOT_WORKING) {
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang "Reseting the status of port %d for server '%s'\n",
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang if (get_server_status(server) == SERVER_NOT_WORKING)
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DLIST_REMOVE(service->ctx->service_list, service);
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiangfo_new_service(struct fo_ctx *ctx, const char *name,
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DEBUG(SSSDBG_TRACE_FUNC, "Creating new service '%s'\n", name);
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiang DEBUG(SSSDBG_FUNC_DATA, "Service '%s' already exists\n", name);
c10df434f8e16b46ccf703bf2e38b799f7bcb38bHeng Jiang talloc_set_destructor(service, service_destructor);
44ea7e3effe9200ccc6abd3231ae56cf5cfb0fb8Heng Jiangfo_get_service(struct fo_ctx *ctx, const char *name,
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiangget_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name,
b91c4dbd00294ce29ab1ae84ad4e8c93ca5ad943Heng Jiang DLIST_FOR_EACH(common, ctx->server_common_list) {
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang *_common = rc_reference(mem_ctx, struct server_common, common);
b3c65285705f6d184b5f8b00b1a328d96b6b19c5Heng Jiang common = talloc_get_type(memptr, struct server_common);
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang "BUG: pending requests still associated with this server\n");
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang DLIST_REMOVE(common->ctx->server_common_list, common);
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiangstatic struct server_common *
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiangcreate_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name)
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang common = rc_alloc(mem_ctx, struct server_common);
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang talloc_set_destructor((TALLOC_CTX *) common, server_common_destructor);
95242ab07e9aa13b37c16cac36a75d190e1766e4Heng Jiang DLIST_ADD_END(ctx->server_common_list, common, struct server_common *);
static struct fo_server *
return NULL;
return NULL;
return server;
return EEXIST;
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (discovery_domain) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
return EOK;
static struct fo_server *
return NULL;
return NULL;
return NULL;
return server;
count++;
return count;
const char *name,
int port,
void *user_data)
const char *name,
int port,
void *user_data)
const char *service_name)
if (exists) {
return EEXIST;
return EOK;
void *user_data,
bool primary,
size_t i;
for (i = 0; i < num_servers; i++) {
return ENOMEM;
return EOK;
if (!server) {
return ENOMEM;
return ret;
if (server) {
goto done;
goto done;
goto done;
goto done;
goto done;
return ENOENT;
done:
return EOK;
return ENOMEM;
return ENOMEM;
return EOK;
static struct tevent_req *
struct tevent_req *
return NULL;
goto done;
goto done;
goto done;
req);
return req;
done:
return req;
static errno_t
const unsigned long timeout_seconds)
struct resolve_service_state);
return ENOMEM;
return EOK;
struct tevent_req);
struct resolve_service_state);
struct resolve_service_state);
case SERVER_RESOLVING_NAME:
struct server_common);
if (ret) {
return EOK;
static struct tevent_req *
return NULL;
switch(status) {
goto done;
goto done;
goto done;
return req;
goto done;
done:
return req;
struct tevent_req);
struct resolve_srv_state);
switch (ret) {
case EOK:
goto done;
true, &last_server);
goto done;
false, &last_server);
goto done;
goto done;
goto done;
goto done;
case ERR_SRV_NOT_FOUND:
case ERR_SRV_LOOKUP_ERROR:
done:
struct resolve_srv_state);
if (server) {
return EOK;
if (!service) {
if (!server) {
return NULL;
struct resolv_hostent *
return NULL;
count = 0;
count++;
return NULL;
count = 0;
return NULL;
count++;
return list;
void *pvt)