[Patch 1/3] chunkd: switch to ncld

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch makes chunkd to use ncld_foo interface, so procedural
programming is now possible. Also, the code is shorter.

Signed-off-by: Pete Zaitcev <zaitcev@xxxxxxxxxx>

---
 server/chunkd.h |    1 
 server/cldu.c   |  656 ++++++++++++++++------------------------------
 server/server.c |   18 -
 3 files changed, 253 insertions(+), 422 deletions(-)

diff --git a/server/chunkd.h b/server/chunkd.h
index cd83f7b..dd86cee 100644
--- a/server/chunkd.h
+++ b/server/chunkd.h
@@ -289,6 +289,7 @@ extern void cli_out_end(struct client *cli);
 extern void cli_in_end(struct client *cli);
 
 /* cldu.c */
+extern void cld_init(void);
 extern void cldu_add_host(const char *host, unsigned int port);
 extern int cld_begin(const char *thishost, const char *thisgroup, uint32_t nid,
 		     struct geo *locp, void (*cb)(enum st_cld));
diff --git a/server/cldu.c b/server/cldu.c
index dbcf11d..4409fb4 100644
--- a/server/cldu.c
+++ b/server/cldu.c
@@ -27,16 +27,10 @@
 #include <string.h>
 #include <unistd.h>
 #include <poll.h>
-#include <netdb.h>
-#include <arpa/nameser.h>
-#include <netinet/in.h>
-#include <resolv.h>		/* must follow in.h, nameser.h */
 #include <errno.h>
-#include <cldc.h>
+#include <ncld.h>
 #include "chunkd.h"
 
-#define ALIGN8(n)	((8 - ((n) & 7)) & 7)
-
 #define N_CLD		10	/* 5 * (v4+v6) */
 
 struct cld_host {
@@ -46,8 +40,8 @@ struct cld_host {
 
 struct cld_session {
 	bool forced_hosts;		/* Administrator overrode default CLD */
-	bool sess_open;
-	struct cldc_udp *lib;		/* library state */
+	bool is_dead;
+	struct ncld_sess *nsess;	/* library state */
 
 	int actx;		/* Active host cldv[actx] */
 	struct cld_host cldv[N_CLD];
@@ -55,9 +49,8 @@ struct cld_session {
 	struct timer timer;
 
 	char *cfname;		/* /chunk-GROUP directory */
-	struct cldc_fh *cfh;	/* /chunk-GROUP directory fh */
 	char *ffname;		/* /chunk-GROUP/NID */
-	struct cldc_fh *ffh;	/* /chunk-GROUP/NID, keep open for lock */
+	struct ncld_fh *ffh;	/* /chunk-GROUP/NID, keep open for lock */
 	uint32_t nid;
 	const char *ourhost;	/* N.B. points to some global data. */
 	struct geo *ploc;	/* N.B. points to some global data. */
@@ -65,14 +58,7 @@ struct cld_session {
 	void (*state_cb)(enum st_cld);
 };
 
-static int cldu_set_cldc(struct cld_session *sp, int newactive);
-static int cldu_new_sess(struct cldc_call_opts *carg, enum cle_err_codes errc);
-static int cldu_open_c_cb(struct cldc_call_opts *carg, enum cle_err_codes errc);
-static int cldu_close_c_cb(struct cldc_call_opts *carg, enum cle_err_codes errc);
-static int cldu_open_f_cb(struct cldc_call_opts *carg, enum cle_err_codes errc);
-static int cldu_lock_cb(struct cldc_call_opts *carg, enum cle_err_codes errc);
-static int cldu_put_cb(struct cldc_call_opts *carg, enum cle_err_codes errc);
-static int cldu_make_ffile(char **ret, struct cld_session *sp);
+static int cldu_set_cldc(struct cld_session *cs, int newactive);
 
 #define SVC "chunk"
 static char svc[] = SVC;
@@ -86,26 +72,26 @@ struct hail_log cldu_hail_log = {
  *
  * In theory we should at least look at priorities, if not weights. Maybe later.
  */
-static int cldu_nextactive(struct cld_session *sp)
+static int cldu_nextactive(struct cld_session *cs)
 {
 	int i;
 	int n;
 
-	if ((n = sp->actx + 1) >= N_CLD)
+	if ((n = cs->actx + 1) >= N_CLD)
 		n = 0;
 	for (i = 0; i < N_CLD; i++) {
-		if (sp->cldv[n].known)
+		if (cs->cldv[n].known)
 			return n;
 		if (++n >= N_CLD)
 			n = 0;
 	}
 	/* Full circle, end on the old actx */
-	return sp->actx;
+	return cs->actx;
 }
 
 static int cldu_setgroup(struct cld_session *sp, const char *thisgroup,
 			 uint32_t thisnid, const char *thishost,
-			 struct geo *locp)
+			 struct geo *loc)
 {
 	size_t cnlen;
 	size_t mlen;
@@ -138,378 +124,70 @@ static int cldu_setgroup(struct cld_session *sp, const char *thisgroup,
 
 	sp->nid = thisnid;
 	sp->ourhost = thishost;
-	sp->ploc = locp;
+	sp->ploc = loc;
 
 	return 0;
 }
 
-static bool cldu_event(int fd, short events, void *userdata)
-{
-	struct cld_session *sp = userdata;
-	int rc;
-
-	if (!sp->lib) {
-		applog(LOG_WARNING, "Stray UDP event");
-		return true; /* continue main loop; do NOT terminate server */
-	}
-
-	rc = cldc_udp_receive_pkt(sp->lib);
-	if (rc) {
-		applog(LOG_INFO, "cldc_udp_receive_pkt failed: %d", rc);
-		/*
-		 * Reacting to ICMP messages is a bad idea, because
-		 *  - it makes us loop hard in case CLD is down, unless we
-		 *    insert additional tricky timeouts
-		 *  - it deals poorly with transient problems like CLD reboots
-		 */
-#if 0
-		if (rc == -ECONNREFUSED) {	/* ICMP tells us */
-			int newactive;
-			/* P3 */ applog(LOG_INFO, "Restarting session");
-			// timer_del(&sp->tm);
-			cldc_kill_sess(sp->lib->sess);
-			sp->lib->sess = NULL;
-			newactive = cldu_nextactive(sp);
-			if (cldu_set_cldc(sp, newactive))
-				return true; /* continue main loop */
-			// timer_add(&sp->tm, &cldc_to_delay);
-		}
-		return true; /* continue main loop; do NOT terminate server */
-#endif
-	}
-
-	srv_poll_ready(fd);
-
-	return true;	/* continue main loop; do NOT terminate server */
-}
-
 static void cldu_timer_event(struct timer *timer)
 {
-	struct cld_session *sp = timer->userdata;
-	struct cldc_udp *udp = sp->lib;
-
-	if (udp->cb)
-		udp->cb(udp->sess, udp->cb_private);
-}
-
-static bool cldu_p_timer_ctl(void *priv, bool add,
-			     int (*cb)(struct cldc_session *, void *),
-			     void *cb_priv, time_t secs)
-{
-	struct cld_session *sp = priv;
+	struct cld_session *cs = timer->userdata;
+	int newactive;
 
-	if (add) {
-		sp->lib->cb = cb;
-		sp->lib->cb_private = cb_priv;
-		timer_add(&sp->timer, time(NULL) + secs);
-	} else
-		timer_del(&sp->timer);
+	if (cs->is_dead) {
+		/* This would be the perfect time to call cs->state_cb. XXX */
 
-	return true;
-}
+		if (debugging)
+			applog(LOG_DEBUG, "Reopening Chunk in %s", cs->ffname);
 
-static int cldu_p_pkt_send(void *priv, const void *addr, size_t addrlen,
-			       const void *buf, size_t buflen)
-{
-	struct cld_session *sp = priv;
-	return cldc_udp_pkt_send(sp->lib, addr, addrlen, buf, buflen);
+		ncld_sess_close(cs->nsess);
+		cs->nsess = NULL;
+		cs->ffh = NULL;			/* closed automatically */
+		cs->is_dead = false;
+		newactive = cldu_nextactive(cs);
+		if (cldu_set_cldc(cs, newactive)) {
+			/* Oops, should not happen. Just loop, then... */
+			timer_add(&cs->timer, time(NULL) + 30);
+			return;
+		}
+	}
 }
 
-static void cldu_p_event(void *priv, struct cldc_session *csp,
-			 struct cldc_fh *fh, uint32_t what)
+static void cldu_sess_event(void *priv, uint32_t what)
 {
-	struct cld_session *sp = priv;
-	int newactive;
+	struct cld_session *cs = priv;
 
 	if (what == CE_SESS_FAILED) {
-		sp->sess_open = false;
-		if (sp->lib->sess != csp)
-			applog(LOG_ERR, "Stray session failed, sid " SIDFMT,
-			       SIDARG(csp->sid));
-		else
+		/*
+		 * In ncld, we are not allowed to free the session structures
+		 * from an event (it's wages of all-conquering 100% reliable
+		 * ncld_close_sess), so we bounce that off to a thread. Which
+		 * we do not have, so we steal a timer for an erzatz thread.
+		 */
+		if (cs->nsess) {
 			applog(LOG_ERR, "Session failed, sid " SIDFMT,
-			       SIDARG(csp->sid));
-		// timer_del(&sp->tm);
-		sp->lib->sess = NULL;
-		newactive = cldu_nextactive(sp);
-		if (cldu_set_cldc(sp, newactive))
-			return;
-		// timer_add(&sp->tm, &cldc_to_delay);
+			       SIDARG(cs->nsess->udp->sess->sid));
+		} else {
+			applog(LOG_ERR, "Session open failed");
+		}
+		cs->is_dead = true;
+		timer_add(&cs->timer, time(NULL) + 1);
 	} else {
-		if (csp)
+		if (cs)
 			applog(LOG_INFO, "cldc event 0x%x sid " SIDFMT,
-			       what, SIDARG(csp->sid));
+			       what, SIDARG(cs->nsess->udp->sess->sid));
 		else
 			applog(LOG_INFO, "cldc event 0x%x no sid", what);
 	}
 }
 
-static struct cldc_ops cld_ops = {
-	.timer_ctl =	cldu_p_timer_ctl,
-	.pkt_send =	cldu_p_pkt_send,
-	.event =	cldu_p_event,
-};
-
-/*
- * Open the library, start its session, and reguster its socket with libevent.
- * Our session remains consistent in case of an error in this function,
- * so that we can continue and retry meaningfuly.
- */
-static int cldu_set_cldc(struct cld_session *sp, int newactive)
-{
-	struct cldc_host *hp;
-	struct cldc_udp *lib;
-	struct cldc_call_opts copts;
-	int rc;
-	struct server_poll *spoll;
-
-	if (sp->lib) {
-		if (sp->lib->fd >= 0)
-			srv_poll_del(sp->lib->fd);
-		cldc_udp_free(sp->lib);
-		sp->lib = NULL;
-	}
-
-	sp->actx = newactive;
-	if (!sp->cldv[sp->actx].known) {
-		applog(LOG_ERR, "No CLD hosts");
-		goto err_addr;
-	}
-	hp = &sp->cldv[sp->actx].h;
-
-	rc = cldc_udp_new(hp->host, hp->port, &sp->lib);
-	if (rc) {
-		applog(LOG_ERR, "cldc_udp_new(%s,%u) error: %d",
-		       hp->host, hp->port, rc);
-		goto err_lib_new;
-	}
-	lib = sp->lib;
-
-	if (debugging)
-		applog(LOG_INFO, "Selected CLD host %s port %u",
-		       hp->host, hp->port);
-
-	spoll = calloc(1, sizeof(*spoll));
-	if (!spoll)
-		goto err_sess;
-
-	spoll->fd = sp->lib->fd;
-	spoll->events = POLLIN;
-	spoll->cb = cldu_event;
-	spoll->userdata = sp;
-
-	g_hash_table_insert(chunkd_srv.fd_info, GINT_TO_POINTER(sp->lib->fd),
-			    spoll);
-
-	memset(&copts, 0, sizeof(struct cldc_call_opts));
-	copts.cb = cldu_new_sess;
-	copts.private = sp;
-	rc = cldc_new_sess(&cld_ops, &copts, lib->addr, lib->addr_len,
-			   "tabled", "tabled", sp, &lib->sess);
-	if (rc) {
-		applog(LOG_INFO,
-		       "Failed to start CLD session on host %s port %u",
-		       hp->host, hp->port);
-		goto err_sess;
-	}
-
-	// if (debugging)
-	//	lib->sess->verbose = true;
-
-	return 0;
-
-err_sess:
-	cldc_udp_free(sp->lib);
-	sp->lib = NULL;
-err_lib_new:
-err_addr:
-	return -1;
-}
-
-static int cldu_new_sess(struct cldc_call_opts *carg, enum cle_err_codes errc)
-{
-	struct cld_session *sp = carg->private;
-	struct cldc_call_opts copts;
-	int rc;
-
-	if (errc != CLE_OK) {
-		applog(LOG_INFO, "New CLD session creation failed: %d", errc);
-		return 0;
-	}
-
-	sp->sess_open = true;
-	applog(LOG_INFO, "New CLD session created, sid " SIDFMT,
-	       SIDARG(sp->lib->sess->sid));
-
-	/*
-	 * First, make sure the base directory exists.
-	 */
-	memset(&copts, 0, sizeof(copts));
-	copts.cb = cldu_open_c_cb;
-	copts.private = sp;
-	rc = cldc_open(sp->lib->sess, &copts, sp->cfname,
-		       COM_READ | COM_WRITE | COM_CREATE | COM_DIRECTORY,
-		       CE_MASTER_FAILOVER | CE_SESS_FAILED, &sp->cfh);
-	if (rc) {
-		applog(LOG_ERR, "cldc_open(%s) call error: %d\n",
-		       sp->cfname, rc);
-	}
-	return 0;
-}
-
-static int cldu_open_c_cb(struct cldc_call_opts *carg, enum cle_err_codes errc)
-{
-	struct cld_session *sp = carg->private;
-	struct cldc_call_opts copts;
-	int rc;
-
-	if (errc != CLE_OK) {
-		applog(LOG_ERR, "CLD open(%s) failed: %d", sp->cfname, errc);
-		return 0;
-	}
-	if (sp->cfh == NULL) {
-		applog(LOG_ERR, "CLD open(%s) failed: NULL fh", sp->cfname);
-		return 0;
-	}
-	if (!sp->cfh->valid) {
-		applog(LOG_ERR, "CLD open(%s) failed: invalid fh", sp->cfname);
-		return 0;
-	}
-
-	/*
-	 * We don't use directory handle to open files in it, so close it.
-	 */
-	memset(&copts, 0, sizeof(copts));
-	copts.cb = cldu_close_c_cb;
-	copts.private = sp;
-	rc = cldc_close(sp->cfh, &copts);
-	if (rc) {
-		applog(LOG_ERR, "cldc_close call error %d", rc);
-	}
-
-	return 0;
-}
-
-static int cldu_close_c_cb(struct cldc_call_opts *carg, enum cle_err_codes errc)
-{
-	struct cld_session *sp = carg->private;
-	struct cldc_call_opts copts;
-	int rc;
-
-	if (errc != CLE_OK) {
-		applog(LOG_ERR, "CLD close(%s) failed: %d", sp->cfname, errc);
-		return 0;
-	}
-
-	/*
-	 * Then, create the membership file for us.
-	 *
-	 * It is a bit racy to create a file like this, applications can see
-	 * an empty file, or a file with stale contents. But what to do?
-	 */
-	memset(&copts, 0, sizeof(copts));
-	copts.cb = cldu_open_f_cb;
-	copts.private = sp;
-	rc = cldc_open(sp->lib->sess, &copts, sp->ffname,
-		       COM_WRITE | COM_LOCK | COM_CREATE,
-		       CE_MASTER_FAILOVER | CE_SESS_FAILED, &sp->ffh);
-	if (rc) {
-		applog(LOG_ERR, "cldc_open(%s) call error: %d\n",
-		       sp->ffname, rc);
-	}
-	return 0;
-}
-
-static int cldu_open_f_cb(struct cldc_call_opts *carg, enum cle_err_codes errc)
-{
-	struct cld_session *sp = carg->private;
-	struct cldc_call_opts copts;
-	int rc;
-
-	if (errc != CLE_OK) {
-		applog(LOG_ERR, "CLD open(%s) failed: %d", sp->ffname, errc);
-		return 0;
-	}
-	if (sp->ffh == NULL) {
-		applog(LOG_ERR, "CLD open(%s) failed: NULL fh", sp->ffname);
-		return 0;
-	}
-	if (!sp->ffh->valid) {
-		applog(LOG_ERR, "CLD open(%s) failed: invalid fh", sp->ffname);
-		return 0;
-	}
-
-	if (debugging)
-		applog(LOG_DEBUG, "CLD file \"%s\" created", sp->ffname);
-
-	/*
-	 * Lock the file, in case two hosts got the same NID.
-	 */
-	memset(&copts, 0, sizeof(copts));
-	copts.cb = cldu_lock_cb;
-	copts.private = sp;
-	rc = cldc_lock(sp->ffh, &copts, 0, false);
-	if (rc) {
-		applog(LOG_ERR, "cldc_lock call error %d", rc);
-	}
-
-	return 0;
-}
-
-static int cldu_lock_cb(struct cldc_call_opts *carg, enum cle_err_codes errc)
-{
-	struct cld_session *sp = carg->private;
-	char *buf = NULL; /* stupid gcc 4.4.1 throws a warning */
-	int len;
-	struct cldc_call_opts copts;
-	int rc;
-
-	if (errc != CLE_OK) {
-		applog(LOG_ERR, "CLD lock(%s) failed: %d", sp->ffname, errc);
-		return 0;
-	}
-
-	if (cldu_make_ffile(&buf, sp))
-		return 0;
-	len = strlen(buf);
-
-	memset(&copts, 0, sizeof(copts));
-	copts.cb = cldu_put_cb;
-	copts.private = sp;
-	rc = cldc_put(sp->ffh, &copts, buf, len);
-	if (rc) {
-		applog(LOG_ERR, "cldc_put(%s) call error: %d\n",
-		       sp->ffname, rc);
-	}
-
-	free(buf);
-
-	return 0;
-}
-
-static int cldu_put_cb(struct cldc_call_opts *carg, enum cle_err_codes errc)
-{
-	struct cld_session *sp = carg->private;
-	// struct cldc_call_opts copts;
-	// int rc;
-
-	if (errc != CLE_OK) {
-		applog(LOG_ERR, "CLD put(%s) failed: %d", sp->ffname, errc);
-		return 0;
-	}
-
-	if (debugging)
-		applog(LOG_DEBUG, "CLD file \"%s\" written", sp->ffname);
-
-	return 0;
-}
-
 /*
  * Create the file with our parameters in memory, return as ret.
  */
-static int cldu_make_ffile(char **ret, struct cld_session *sp)
+static int cldu_make_ffile(char **ret, struct cld_session *cs)
 {
 	GList *str_list = NULL;
+	struct geo *loc = cs->ploc;
 	char *buf;
 	char *str;
 	size_t len;
@@ -517,9 +195,9 @@ static int cldu_make_ffile(char **ret, struct cld_session *sp)
 	int rc;
 
 	rc = asprintf(&str,
-		"<Chunk>\r\n"
-		" <NID>%u</NID>\r\n",
-		sp->nid);
+		      "<Chunk>\r\n"
+		      " <NID>%u</NID>\r\n",
+		      cs->nid);
 	if (rc == -1) {
 		applog(LOG_ERR, "OOM in asprintf\n");
 		goto error;
@@ -536,7 +214,7 @@ static int cldu_make_ffile(char **ret, struct cld_session *sp)
 
 		host = cfg->node;
 		if (host == NULL || host[0] == 0)
-			host = sp->ourhost;
+			host = cs->ourhost;
 
 		rc = asprintf(&str,
 			" <Socket>\r\n"
@@ -559,9 +237,9 @@ static int cldu_make_ffile(char **ret, struct cld_session *sp)
 		"  <Rack>%s</Rack>\r\n"
 		" </Geo>\r\n"
 		"</Chunk>\r\n",
-		sp->ploc->area ? sp->ploc->area : "-",
-		sp->ploc->zone ? sp->ploc->zone : "-",
-		sp->ploc->rack ? sp->ploc->rack : "-");
+		loc->area ? loc->area : "-",
+		loc->zone ? loc->zone : "-",
+		loc->rack ? loc->rack : "-");
 	if (rc == -1) {
 		applog(LOG_ERR, "OOM in asprintf\n");
 		goto error;
@@ -597,10 +275,156 @@ error:
 }
 
 /*
+ * Open the library, start its session, and reguster its socket with libevent.
+ * Our session remains consistent in case of an error in this function,
+ * so that we can continue and retry meaningfuly.
+ */
+static int cldu_set_cldc(struct cld_session *cs, int newactive)
+{
+	struct cldc_host *hp;
+	struct ncld_fh *cfh;	/* /chunk-GROUP directory fh */
+	struct timespec tm;
+	char *buf = NULL; /* stupid gcc 4.4.1 throws a warning */
+	int len;
+	int error;
+	int rc;
+
+	if (cs->nsess) {
+		ncld_sess_close(cs->nsess);
+		cs->nsess = NULL;
+	}
+
+	cs->actx = newactive;
+	if (!cs->cldv[cs->actx].known) {
+		applog(LOG_ERR, "No CLD hosts");
+		goto err_addr;
+	}
+	hp = &cs->cldv[cs->actx].h;
+
+	if (debugging)
+		applog(LOG_INFO, "Selected CLD host %s port %u",
+		       hp->host, hp->port);
+
+	cs->nsess = ncld_sess_open(hp->host, hp->port, &error,
+				   cldu_sess_event, cs, "tabled", "tabled");
+	if (cs->nsess == NULL) {
+		if (error < 1000) {
+			applog(LOG_ERR, "ncld_sess_open(%s,%u) error: %s",
+			       hp->host, hp->port, strerror(error));
+		} else {
+			applog(LOG_ERR, "ncld_sess_open(%s,%u) error: %d",
+			       hp->host, hp->port, error);
+		}
+		goto err_nsess;
+	}
+
+	applog(LOG_INFO, "New CLD session created, sid " SIDFMT,
+	       SIDARG(cs->nsess->udp->sess->sid));
+
+	/*
+	 * First, make sure the base directory exists.
+	 */
+	cfh = ncld_open(cs->nsess, cs->cfname,
+			COM_READ | COM_WRITE | COM_CREATE | COM_DIRECTORY,
+			&error, 0 /* CE_MASTER_FAILOVER | CE_SESS_FAILED */,
+			NULL, NULL);
+	if (!cfh) {
+		applog(LOG_ERR, "CLD open(%s) failed: %d", cs->cfname, error);
+		goto err_copen;
+	}
+
+	/*
+	 * We don't use directory handle to open files in it, so close it.
+	 */
+	ncld_close(cfh);
+
+	/*
+	 * Then, create the membership file for us.
+	 *
+	 * It is a bit racy to create a file like this, applications can see
+	 * an empty file, or a file with stale contents. But what to do?
+	 */
+	cs->ffh = ncld_open(cs->nsess, cs->ffname,
+			    COM_WRITE | COM_LOCK | COM_CREATE,
+			    &error, 0 /* CE_MASTER_FAILOVER | CE_SESS_FAILED */,
+			    NULL, NULL);
+	if (cs->ffh == NULL) {
+		applog(LOG_ERR, "CLD open(%s) failed: NULL fh", cs->ffname);
+		goto err_fopen;
+	}
+
+	if (debugging)
+		applog(LOG_DEBUG, "CLD file \"%s\" created", cs->ffname);
+
+	/*
+	 * Lock the file, in case two hosts got the same NID.
+	 */
+	for (;;) {
+		rc = ncld_trylock(cs->ffh);
+		if (!rc)
+			break;
+
+		applog(LOG_ERR, "CLD lock(%s) failed: %d", cs->ffname, rc);
+		if (rc != CLE_LOCK_CONFLICT + 1100)
+			goto err_lock;
+
+		/*
+		 * The usual reason why we get a lock conflict is
+		 * restarting too quickly and hitting the previous lock
+		 * that is going to disappear soon.
+		 */
+		tm.tv_sec = 10;
+		tm.tv_nsec = 0;
+		nanosleep(&tm, NULL);
+	}
+
+	if (cldu_make_ffile(&buf, cs))
+		goto err_buf;
+	len = strlen(buf);
+
+	rc = ncld_write(cs->ffh, buf, len);
+	if (rc) {
+		applog(LOG_ERR, "CLD put(%s) failed: %d", cs->ffname, rc);
+		goto err_write;
+	}
+
+	free(buf);
+
+	if (debugging)
+		applog(LOG_DEBUG, "CLD file \"%s\" written", cs->ffname);
+
+	/*
+	 * At this point we just hang here with cs->ffh open and locked
+	 * until session fails or we shut down completely.
+	 */
+	return 0;
+
+err_write:
+err_buf:
+err_lock:
+	ncld_close(cs->ffh);	/* session-close closes these, maybe drop */
+err_fopen:
+err_copen:
+	ncld_sess_close(cs->nsess);
+	cs->nsess = NULL;
+err_nsess:
+err_addr:
+	return -1;
+}
+
+/*
  */
 static struct cld_session ses;
 
 /*
+ * Global and 1-instance initialization.
+ */
+void cld_init()
+{
+	ncld_init();
+}
+
+/*
  * This initiates our sole session with a CLD instance.
  *
  * Mostly due to our laziness and lack of need, thishost and locp are saved
@@ -610,10 +434,10 @@ static struct cld_session ses;
 int cld_begin(const char *thishost, const char *thisgroup, uint32_t nid,
 	      struct geo *locp, void (*cb)(enum st_cld))
 {
+	static struct cld_session *cs = &ses;
 
 	if (!nid)
 		return 0;
-	cldc_init();
 
 	/*
 	 * As long as we permit pre-seeding lists of CLD hosts,
@@ -621,16 +445,16 @@ int cld_begin(const char *thishost, const char *thisgroup, uint32_t nid,
 	 * as cld_end terminates it right, we can call cld_begin again.
 	 */
 	// memset(&ses, 0, sizeof(struct cld_session));
-	ses.state_cb = cb;
+	cs->state_cb = cb;
 
-	timer_init(&ses.timer, "chunkd_cldu_timer", cldu_timer_event, &ses);
+	timer_init(&cs->timer, "chunkd_cldu_timer", cldu_timer_event, cs);
 
-	if (cldu_setgroup(&ses, thisgroup, nid, thishost, locp)) {
+	if (cldu_setgroup(cs, thisgroup, nid, thishost, locp)) {
 		/* Already logged error */
 		goto err_group;
 	}
 
-	if (!ses.forced_hosts) {
+	if (!cs->forced_hosts) {
 		GList *tmp, *host_list = NULL;
 		int i;
 
@@ -646,9 +470,9 @@ int cld_begin(const char *thishost, const char *thisgroup, uint32_t nid,
 		for (tmp = host_list; tmp; tmp = tmp->next) {
 			struct cldc_host *hp = tmp->data;
 			if (i < N_CLD) {
-				memcpy(&ses.cldv[i].h, hp,
+				memcpy(&cs->cldv[i].h, hp,
 				       sizeof(struct cldc_host));
-				ses.cldv[i].known = 1;
+				cs->cldv[i].known = 1;
 				i++;
 			} else {
 				free(hp->host);
@@ -665,7 +489,7 @@ int cld_begin(const char *thishost, const char *thisgroup, uint32_t nid,
 	 * -- Actually, it only works when recovering from CLD failure.
 	 *    Thereafter, any slave CLD redirects us to the master.
 	 */
-	if (cldu_set_cldc(&ses, 0)) {
+	if (cldu_set_cldc(cs, 0)) {
 		/* Already logged error */
 		goto err_net;
 	}
@@ -678,41 +502,14 @@ err_group:
 	return -1;
 }
 
-void cld_end(void)
-{
-	int i;
-
-	if (!ses.nid)
-		return;
-
-	if (ses.lib) {
-		// if (ses.sess_open)	/* kill it always, include half-open */
-		cldc_kill_sess(ses.lib->sess);
-		if (ses.lib->fd >= 0)
-			srv_poll_del(ses.lib->fd);
-		cldc_udp_free(ses.lib);
-		ses.lib = NULL;
-	}
-
-	if (!ses.forced_hosts) {
-		for (i = 0; i < N_CLD; i++) {
-			if (ses.cldv[i].known)
-				free(ses.cldv[i].h.host);
-		}
-	}
-
-	free(ses.cfname);
-	free(ses.ffname);
-}
-
 void cldu_add_host(const char *hostname, unsigned int port)
 {
-	static struct cld_session *sp = &ses;
+	static struct cld_session *cs = &ses;
 	struct cld_host *hp;
 	int i;
 
 	for (i = 0; i < N_CLD; i++) {
-		hp = &sp->cldv[i];
+		hp = &cs->cldv[i];
 		if (!hp->known)
 			break;
 	}
@@ -724,5 +521,36 @@ void cldu_add_host(const char *hostname, unsigned int port)
 		return;
 	hp->known = 1;
 
-	sp->forced_hosts = true;
+	cs->forced_hosts = true;
 }
+
+void cld_end(void)
+{
+	static struct cld_session *cs = &ses;
+	int i;
+
+	if (!cs->nid)
+		return;
+
+	timer_del(&cs->timer);
+
+	if (cs->nsess) {
+		ncld_sess_close(cs->nsess);
+		cs->nsess = NULL;
+	}
+
+	if (!cs->forced_hosts) {
+		for (i = 0; i < N_CLD; i++) {
+			if (cs->cldv[i].known) {
+				free(cs->cldv[i].h.host);
+				cs->cldv[i].known = false;
+			}
+		}
+	}
+
+	free(cs->cfname);
+	cs->cfname = NULL;
+	free(cs->ffname);
+	cs->ffname = NULL;
+}
+
diff --git a/server/server.c b/server/server.c
index 5b34725..b2a30bc 100644
--- a/server/server.c
+++ b/server/server.c
@@ -1756,6 +1756,8 @@ int main (int argc, char *argv[])
 	SSL_CTX_set_mode(ssl_ctx, SSL_CTX_get_mode(ssl_ctx) |
 			 SSL_MODE_ENABLE_PARTIAL_WRITE);
 
+	cld_init();
+
 	/*
 	 * Next, read master configuration. This should be done as
 	 * early as possible, so that tunables are available.
@@ -1817,12 +1819,6 @@ int main (int argc, char *argv[])
 		goto err_out_fs;
 	}
 
-	if (cld_begin(chunkd_srv.ourhost, chunkd_srv.group, chunkd_srv.nid,
-		      &chunkd_srv.loc, NULL)) {
-		rc = 1;
-		goto err_out_cld;
-	}
-
 	/* set up server networking */
 	for (tmpl = chunkd_srv.listeners; tmpl; tmpl = tmpl->next) {
 		rc = net_open(tmpl->data);
@@ -1830,16 +1826,22 @@ int main (int argc, char *argv[])
 			goto err_out_listen;
 	}
 
+	if (cld_begin(chunkd_srv.ourhost, chunkd_srv.group, chunkd_srv.nid,
+		      &chunkd_srv.loc, NULL)) {
+		rc = 1;
+		goto err_out_cld;
+	}
+
 	applog(LOG_INFO, "initialized");
 
 	rc = main_loop();
 
 	applog(LOG_INFO, "shutting down");
 
+	/* cld_end(); */
+err_out_cld:
 	/* net_close(); */
 err_out_listen:
-	cld_end();
-err_out_cld:
 	fs_close();
 err_out_fs:
 	cmd = CHK_CMD_EXIT;
--
To unsubscribe from this list: send the line "unsubscribe hail-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Fedora Clound]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux