diff options
Diffstat (limited to 'xlators/cluster/nsr-server/src/leader.c')
-rw-r--r-- | xlators/cluster/nsr-server/src/leader.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/xlators/cluster/nsr-server/src/leader.c b/xlators/cluster/nsr-server/src/leader.c new file mode 100644 index 000000000..02a2609c8 --- /dev/null +++ b/xlators/cluster/nsr-server/src/leader.c @@ -0,0 +1,138 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include <regex.h> +//#include <stdlib.h> +#include <string.h> + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "call-stub.h" +#include "defaults.h" +#include "xlator.h" +#include "api/src/glfs.h" +#include "api/src/glfs-internal.h" + +#ifndef NSR_SIM_ETCD +#include "etcd-api.h" +#endif +#include "nsr-internal.h" +#include "../../nsr-recon/src/recon_driver.h" +#include "../../nsr-recon/src/recon_xlator.h" + +#define NSR_TTL 5 + +static void +nsr_set_leader (xlator_t *this, etcd_session etcd) +{ + long term = 0; + etcd_result res; + nsr_private_t *priv = this->private; + char n_t[sizeof(long)+1]; + char *text = NULL; + + gf_log (this->name, GF_LOG_INFO, "Just became leader"); + + text = etcd_get(etcd, priv->term_key); + if(text == NULL) { + term = 0; + } else { + term = strtol(text, NULL, 10); + } + sprintf(n_t,"%ld",term+1); + res = etcd_set(etcd, priv->term_key,n_t,text,0); + if(res != ETCD_OK) { + gf_log (this->name, GF_LOG_ERROR, "failed to set term"); + return; + } + priv->leader = _gf_true; + + priv->current_term = term + 1; + + if (priv->nsr_recon_start == _gf_false) { + atomic_fetch_and(&(priv->fence_io), 0); + return; + } + + // Move this inside recon notify??? + atomic_fetch_or(&(priv->fence_io), 1); + + nsr_recon_notify_event_set_leader(priv); + + return; +} + +void * +nsr_leader_thread (void *arg) +{ + xlator_t *this = (xlator_t *) arg; + nsr_private_t *priv = this->private; + etcd_result res; + char *index_in = NULL; + char *index_out = NULL; + + gf_log (this->name, GF_LOG_INFO, + "calling etcd_open_str on servers %s", priv->etcd_servers); + + priv->etcd = etcd_open_str(priv->etcd_servers); + if (!(priv->etcd)) { + gf_log (this->name, GF_LOG_ERROR, + "failed to open etcd session\n"); + return NULL; + } + + priv->leader_inited = 1; + + for (;;) { + /* Not leader yet. Try to become leader. */ + for (;;) { + res = etcd_lock (priv->etcd, priv->leader_key, NSR_TTL, + index_in, &index_out); + if (res == ETCD_OK) { + break; + } + gf_log (this->name, GF_LOG_WARNING, + "etcd_lock failed (%d)", res); + sleep(1); + } + /* We're there. Notify other parts of the code. */ + nsr_set_leader(this,priv->etcd); + /* Try to retain leadership. */ + index_in = index_out; + index_out = NULL; + for (;;) { + res = etcd_lock (priv->etcd, priv->leader_key, NSR_TTL, + index_in, &index_out); + if (index_out && (index_in != index_out)) { + if (index_in) { + free(index_in); + } + index_in = index_out; + index_out = NULL; + } + if (res != ETCD_OK) { + gf_log (this->name, GF_LOG_WARNING, + "lost leadership (%d)", res); + if (index_out) { + free(index_out); + } + break; + } + sleep(1); + } + } + + etcd_close_str(priv->etcd); + return NULL; +} + |