[Patch] tabled: auto ports, except replication

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

 



This patch adds the automatic listening port feature to tabled in the
same way it was done in CLD and Chunk. It turns auto ports on, too.

The patch also starts making use of auto ports in CLD and Chunk.
Thus, our build requires this support in the installed versions of them.

There's still an issue of the DB4 replication using a fixed port.

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

diff --git a/include/httpstor.h b/include/httpstor.h
index 2f0b719..07a0111 100644
--- a/include/httpstor.h
+++ b/include/httpstor.h
@@ -27,6 +27,7 @@
 
 struct httpstor_client {
 	CURL		*curl;
+	char		*acc;
 	char		*host;
 	char		*user;
 	char		*key;
@@ -71,8 +72,8 @@ extern void httpstor_free_bucket(struct httpstor_bucket *buck);
 extern void httpstor_free_object(struct httpstor_object *obj);
 extern void httpstor_free_keylist(struct httpstor_keylist *keylist);
 
-extern struct httpstor_client *httpstor_new(const char *service_host,
-				 const char *user, const char *secret_key);
+extern struct httpstor_client *httpstor_new(const char *service_acc,
+	const char *service_host, const char *user, const char *secret_key);
 
 extern bool httpstor_add_bucket(struct httpstor_client *httpstor, const char *name);
 extern bool httpstor_del_bucket(struct httpstor_client *httpstor, const char *name);
diff --git a/include/httputil.h b/include/httputil.h
index ec7490d..7a1f6da 100644
--- a/include/httputil.h
+++ b/include/httputil.h
@@ -101,6 +101,9 @@ extern struct uri *uri_parse(struct uri *uri_dest, char *uri_src_text);
 extern int field_unescape(char *s, int s_len);
 extern char* field_escape (char *signed_str, unsigned char mask);
 
+/* readport.c */
+extern int tb_readport(const char *fname, char *buf, size_t len);
+
 static inline bool http11(struct http_req *req)
 {
 	if (req->major > 1)
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ca2e7a0..e22a490 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,7 +4,7 @@ INCLUDES		= -I$(top_srcdir)/include	\
 
 noinst_LIBRARIES	= libhttputil.a libtdb.a
 
-libhttputil_a_SOURCES	= httputil.c uri.c
+libhttputil_a_SOURCES	= httputil.c uri.c readport.c
 
 libtdb_a_SOURCES	= tdb.c
 
diff --git a/lib/httpstor.c b/lib/httpstor.c
index 96eac42..72e65b9 100644
--- a/lib/httpstor.c
+++ b/lib/httpstor.c
@@ -42,14 +42,21 @@ void httpstor_free(struct httpstor_client *httpstor)
 {
 	if (httpstor->curl)
 		curl_easy_cleanup(httpstor->curl);
+	free(httpstor->acc);
 	free(httpstor->host);
 	free(httpstor->user);
 	free(httpstor->key);
 	free(httpstor);
 }
 
-struct httpstor_client *httpstor_new(const char *service_host,
-				 const char *user, const char *secret_key)
+/*
+ * The service accessor is a "host:port" string that gets resolved to IP
+ * address and then create a TCP connection to the server. The service host,
+ * however, is used to form the "Host: host" HTTP header. The host of the
+ * accessor should be the same on the sane installations, but whatever.
+ */
+struct httpstor_client *httpstor_new(const char *service_acc,
+	const char *service_host, const char *user, const char *secret_key)
 {
 	struct httpstor_client *httpstor;
 
@@ -57,10 +64,11 @@ struct httpstor_client *httpstor_new(const char *service_host,
 	if (!httpstor)
 		return NULL;
 
+	httpstor->acc = strdup(service_acc);
 	httpstor->host = strdup(service_host);
 	httpstor->user = strdup(user);
 	httpstor->key = strdup(secret_key);
-	if (!httpstor->host || !httpstor->user || !httpstor->key)
+	if (!httpstor->acc || !httpstor->host || !httpstor->user || !httpstor->key)
 		goto err_out;
 
 	if (curl_global_init(CURL_GLOBAL_ALL))
@@ -170,7 +178,7 @@ next:
 struct httpstor_blist *httpstor_list_buckets(struct httpstor_client *httpstor)
 {
 	struct http_req req;
-	char datestr[80], timestr[64], hmac[64], auth[128], host[80];
+	char datestr[80], timestr[64], hmac[64], auth[128], host[80], url[80];
 	struct curl_slist *headers = NULL;
 	struct httpstor_blist *blist;
 	xmlDocPtr doc;
@@ -200,10 +208,12 @@ struct httpstor_blist *httpstor_list_buckets(struct httpstor_client *httpstor)
 	headers = curl_slist_append(headers, datestr);
 	headers = curl_slist_append(headers, auth);
 
+	snprintf(url, sizeof(url), "http://%s/";, httpstor->acc);
+
 	curl_easy_reset(httpstor->curl);
 	if (httpstor->verbose)
 		curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1);
-	curl_easy_setopt(httpstor->curl, CURLOPT_URL, "http://localhost:18080/";);
+	curl_easy_setopt(httpstor->curl, CURLOPT_URL, url);
 	curl_easy_setopt(httpstor->curl, CURLOPT_HTTPHEADER, headers);
 	curl_easy_setopt(httpstor->curl, CURLOPT_ENCODING, "");
 	curl_easy_setopt(httpstor->curl, CURLOPT_FAILONERROR, 1);
@@ -312,7 +322,7 @@ static bool __httpstor_ad_bucket(struct httpstor_client *httpstor, const char *n
 
 	sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac);
 	sprintf(host, "Host: %s", httpstor->host);
-	sprintf(url, "http://localhost:18080/%s/";, name);
+	snprintf(url, sizeof(url), "http://%s/%s/";, httpstor->acc, name);
 
 	headers = curl_slist_append(headers, host);
 	headers = curl_slist_append(headers, datestr);
@@ -371,7 +381,7 @@ bool httpstor_get(struct httpstor_client *httpstor, const char *bucket, const ch
 
 	sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac);
 	sprintf(host, "Host: %s", httpstor->host);
-	sprintf(url, "http://localhost:18080%s";, orig_path);
+	snprintf(url, sizeof(url), "http://%s%s";, httpstor->acc, orig_path);
 
 	headers = curl_slist_append(headers, host);
 	headers = curl_slist_append(headers, datestr);
@@ -450,7 +460,7 @@ bool httpstor_put(struct httpstor_client *httpstor, const char *bucket, const ch
 
 	sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac);
 	sprintf(host, "Host: %s", httpstor->host);
-	sprintf(url, "http://localhost:18080%s";, orig_path);
+	snprintf(url, sizeof(url), "http://%s%s";, httpstor->acc, orig_path);
 
 	headers = curl_slist_append(headers, host);
 	headers = curl_slist_append(headers, datestr);
@@ -541,7 +551,7 @@ bool httpstor_del(struct httpstor_client *httpstor, const char *bucket, const ch
 
 	sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac);
 	sprintf(host, "Host: %s", httpstor->host);
-	sprintf(url, "http://localhost:18080%s";, orig_path);
+	snprintf(url, sizeof(url), "http://%s%s";, httpstor->acc, orig_path);
 
 	headers = curl_slist_append(headers, host);
 	headers = curl_slist_append(headers, datestr);
@@ -748,7 +758,8 @@ struct httpstor_keylist *httpstor_keys(struct httpstor_client *httpstor, const c
 		goto err_out;
 	}
 
-	url = g_string_append(url, "http://localhost:18080";);
+	url = g_string_append(url, "http://";);
+	url = g_string_append(url, httpstor->acc);
 	url = g_string_append(url, orig_path);
 
 	if (prefix)
diff --git a/server/config.c b/server/config.c
index 45cee26..505524c 100644
--- a/server/config.c
+++ b/server/config.c
@@ -12,6 +12,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <ctype.h>
+#include <cldc.h>
 #include "tabled.h"
 
 struct config_context {
@@ -28,6 +29,7 @@ struct config_context {
 	bool		in_cld;
 	unsigned short	cld_port;
 	char		*cld_host;
+	char		*cld_port_file;
 };
 
 static void cfg_elm_start (GMarkupParseContext *context,
@@ -63,6 +65,46 @@ static void cfg_elm_start (GMarkupParseContext *context,
 	}
 }
 
+static void cfg_elm_end_listen(struct config_context *cc)
+{
+	if (cc->text) {
+		applog(LOG_WARNING, "cfgfile: Extra text '%s' in Listen",
+		       cc->text);
+		free(cc->text);
+		cc->text = NULL;
+		return;
+	}
+
+	if (cc->tmp_listen.port && cc->tmp_listen.port_file) {
+		applog(LOG_ERR, "cfgfile: Listen with both Port and PortFile");
+		goto err;
+	}
+
+	if (!cc->tmp_listen.port && !cc->tmp_listen.port_file) {
+		applog(LOG_ERR, "cfgfile: Listen with no Port or PortFile");
+		goto err;
+	}
+
+	if (tabled_srv.port) {
+		free(tabled_srv.port);
+		tabled_srv.port = NULL;
+	}
+	if (tabled_srv.port_file) {
+		free(tabled_srv.port_file);
+		tabled_srv.port_file = NULL;
+	}
+
+	tabled_srv.port = cc->tmp_listen.port;
+	tabled_srv.port_file = cc->tmp_listen.port_file;
+	memset(&cc->tmp_listen, 0, sizeof(struct listen_cfg));
+	return;
+
+ err:
+	free(cc->tmp_listen.port);
+	free(cc->tmp_listen.port_file);
+	memset(&cc->tmp_listen, 0, sizeof(struct listen_cfg));
+}
+
 static void cfg_elm_end_storage(struct config_context *cc)
 {
 	struct geo dummy_loc;
@@ -115,11 +157,30 @@ static void cfg_elm_end_cld(struct config_context *cc)
 		applog(LOG_WARNING, "No host for CLD element");
 		goto end;
 	}
-	if (!cc->cld_port) {
-		applog(LOG_WARNING, "No port for CLD element");
+	if (!cc->cld_port && !cc->cld_port_file) {
+		applog(LOG_WARNING, "No Port nor PortFile for CLD element");
 		goto end;
 	}
 
+	/*
+	 * Waiting here is disadvantageous, because it defeats testing
+	 * of bootstrap robustness for Chunk as a client of CLD.
+	 * But it's the most direct way to give us variable ports.
+	 * Also, no mysterious sleep commands in start-daemon script.
+	 */
+	if (cc->cld_port_file) {
+		int port;
+		if ((port = cld_readport(cc->cld_port_file)) <= 0) {
+			applog(LOG_INFO, "Waiting for CLD PortFile %s",
+			       cc->cld_port_file);
+			sleep(2);
+			while ((port = cld_readport(cc->cld_port_file)) <= 0)
+				sleep(3);
+			applog(LOG_INFO, "Using CLD port %u", port);
+		}
+		cc->cld_port = port;
+	}
+
 	cldu_add_host(cc->cld_host, cc->cld_port);
 
 end:
@@ -186,22 +247,8 @@ static void cfg_elm_end (GMarkupParseContext *context,
 	}
 
 	else if (!strcmp(element_name, "Listen")) {
+		cfg_elm_end_listen(cc);
 		cc->in_listen = false;
-
-		if (!cc->tmp_listen.port) {
-			applog(LOG_WARNING, "TCP port not specified in Listen");
-			free(tabled_srv.port);
-			tabled_srv.port = NULL;
-			return;
-		}
-
-		if (tabled_srv.port) {
-			free(tabled_srv.port);
-			tabled_srv.port = NULL;
-		}
-
-		tabled_srv.port = cc->tmp_listen.port;
-		cc->tmp_listen.port = NULL;
 	}
 
 	else if (!strcmp(element_name, "StorageNode")) {
@@ -279,6 +326,26 @@ static void cfg_elm_end (GMarkupParseContext *context,
 		}
 	}
 
+	else if (!strcmp(element_name, "PortFile")) {
+		if (!cc->text) {
+			applog(LOG_WARNING, "PortFile element empty");
+			return;
+		}
+
+		if (cc->in_listen) {
+			free(cc->tmp_listen.port_file);
+			cc->tmp_listen.port_file = cc->text;
+		} else if (cc->in_cld) {
+			free(cc->cld_port_file);
+			cc->cld_port_file = cc->text;
+		} else {
+			applog(LOG_WARNING,
+			       "PortFile element not in Listen or CLD");
+			free(cc->text);
+		}
+		cc->text = NULL;
+	}
+
 	else if (!strcmp(element_name, "ChunkUser") && cc->text) {
 		free(tabled_srv.chunk_user);
 		tabled_srv.chunk_user = cc->text;
diff --git a/server/server.c b/server/server.c
index dfe9287..60d28df 100644
--- a/server/server.c
+++ b/server/server.c
@@ -1427,7 +1427,131 @@ int stor_update_cb(void)
 	return num_up;
 }
 
-static int net_open(void)
+static int net_open_socket(int addr_fam, int sock_type, int sock_prot,
+			   int addr_len, void *addr_ptr)
+{
+	struct server_socket *sock;
+	int fd, on;
+	int rc;
+
+	fd = socket(addr_fam, sock_type, sock_prot);
+	if (fd < 0) {
+		rc = errno;
+		applogerr("tcp socket");
+		return -rc;
+	}
+
+	on = 1;
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
+		rc = errno;
+		applogerr("setsockopt(SO_REUSEADDR)");
+		close(fd);
+		return -rc;
+	}
+
+	if (bind(fd, addr_ptr, addr_len) < 0) {
+		rc = errno;
+		applogerr("tcp bind");
+		close(fd);
+		return -rc;
+	}
+
+	rc = fsetflags("tcp server", fd, O_NONBLOCK);
+	if (rc) {
+		close(fd);
+		return rc;
+	}
+
+	sock = calloc(1, sizeof(*sock));
+	if (!sock) {
+		close(fd);
+		return -ENOMEM;
+	}
+
+	sock->fd = fd;
+
+	event_set(&sock->ev, fd, EV_READ | EV_PERSIST, tcp_srv_event, sock);
+
+	tabled_srv.sockets = g_list_append(tabled_srv.sockets, sock);
+	return fd;
+}
+
+/*
+ * This, annoyingly, has to have a side effect: it fills out tabled_srv.port
+ * so that we can later export it into CLD.
+ */
+static int net_open_any(char *portfile)
+{
+	struct sockaddr_in addr4;
+	struct sockaddr_in6 addr6;
+	FILE *portf;
+	int fd4, fd6;
+	socklen_t addr_len;
+	unsigned short port;
+	int rc;
+
+	port = 0;
+
+	/* Thanks to Linux, IPv6 must be bound first. */
+	memset(&addr6, 0, sizeof(addr6));
+	addr6.sin6_family = AF_INET6;
+	memcpy(&addr6.sin6_addr, &in6addr_any, sizeof(struct in6_addr));
+	fd6 = net_open_socket(AF_INET6, SOCK_STREAM, 0, sizeof(addr6), &addr6);
+
+	if (fd6 >= 0) {
+		addr_len = sizeof(addr6);
+		if (getsockname(fd6, &addr6, &addr_len) != 0) {
+			rc = errno;
+			applog(LOG_ERR, "getsockname failed: %s", strerror(rc));
+			return -rc;
+		}
+		port = ntohs(addr6.sin6_port);
+	}
+
+	memset(&addr4, 0, sizeof(addr4));
+	addr4.sin_family = AF_INET;
+	addr4.sin_addr.s_addr = htonl(INADDR_ANY);
+	/* If IPv6 worked, we must use the same port number for IPv4 */
+	if (port)
+		addr4.sin_port = port;
+	fd4 = net_open_socket(AF_INET, SOCK_STREAM, 0, sizeof(addr4), &addr4);
+
+	if (!port) {
+		if (fd4 < 0)
+			return fd4;
+
+		addr_len = sizeof(addr4);
+		if (getsockname(fd4, &addr4, &addr_len) != 0) {
+			rc = errno;
+			applog(LOG_ERR, "getsockname failed: %s", strerror(rc));
+			return -rc;
+		}
+		port = ntohs(addr4.sin_port);
+	}
+
+	applog(LOG_INFO, "Listening on port %u file %s", port, portfile);
+
+	rc = asprintf(&tabled_srv.port, "%u", port);
+	if (rc < 0) {
+		applog(LOG_ERR, "OOM");
+		return -ENOMEM;
+	}
+
+	portf = fopen(portfile, "w");
+	if (portf == NULL) {
+		rc = errno;
+		applog(LOG_INFO, "Cannot create port file %s: %s",
+		       portfile, strerror(rc));
+		return -rc;
+	}
+	fprintf(portf, "%s:%u\n", tabled_srv.ourhost, port);
+	fclose(portf);
+
+	tabled_srv.state_net = ST_NET_OPEN;
+	return 0;
+}
+
+static int net_open_known(const char *portstr)
 {
 	int ipv6_found;
 	int rc;
@@ -1438,10 +1562,10 @@ static int net_open(void)
 	hints.ai_socktype = SOCK_STREAM;
 	hints.ai_flags = AI_PASSIVE;
 
-	rc = getaddrinfo(NULL, tabled_srv.port, &hints, &res0);
+	rc = getaddrinfo(NULL, portstr, &hints, &res0);
 	if (rc) {
 		applog(LOG_ERR, "getaddrinfo(*:%s) failed: %s",
-		       tabled_srv.port, gai_strerror(rc));
+		       portstr, gai_strerror(rc));
 		rc = -EINVAL;
 		goto err_addr;
 	}
@@ -1463,50 +1587,16 @@ static int net_open(void)
 	}
 
 	for (res = res0; res; res = res->ai_next) {
-		struct server_socket *sock;
-		int fd, on;
 		char listen_host[65], listen_serv[65];
 
 		if (ipv6_found && res->ai_family == PF_INET)
 			continue;
 
-		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-		if (fd < 0) {
-			applogerr("tcp socket");
-			return -errno;
-		}
-
-		on = 1;
-		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on,
-			       sizeof(on)) < 0) {
-			applogerr("setsockopt(SO_REUSEADDR)");
-			rc = -errno;
+		rc = net_open_socket(res->ai_family, res->ai_socktype,
+				     res->ai_protocol, 
+				     res->ai_addrlen, res->ai_addr);
+		if (rc < 0)
 			goto err_out;
-		}
-
-		if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
-			applogerr("tcp bind");
-			rc = -errno;
-			goto err_out;
-		}
-
-		rc = fsetflags("tcp server", fd, O_NONBLOCK);
-		if (rc)
-			goto err_out;
-
-		sock = calloc(1, sizeof(*sock));
-		if (!sock) {
-			rc = -ENOMEM;
-			goto err_out;
-		}
-
-		sock->fd = fd;
-
-		event_set(&sock->ev, fd, EV_READ | EV_PERSIST,
-			  tcp_srv_event, sock);
-
-		tabled_srv.sockets = g_list_append(tabled_srv.sockets, sock);
-
 		getnameinfo(res->ai_addr, res->ai_addrlen,
 			    listen_host, sizeof(listen_host),
 			    listen_serv, sizeof(listen_serv),
@@ -1527,6 +1617,14 @@ err_addr:
 	return rc;
 }
 
+static int net_open(void)
+{
+	if (tabled_srv.port_file)
+		return net_open_any(tabled_srv.port_file);
+	else
+		return net_open_known(tabled_srv.port);
+}
+
 static void net_listen(void)
 {
 	GList *tmp;
diff --git a/server/tabled.h b/server/tabled.h
index 2e3b52f..5f74748 100644
--- a/server/tabled.h
+++ b/server/tabled.h
@@ -199,6 +199,7 @@ struct listen_cfg {
 	/* bool			encrypt; */
 	/* char			*host; */
 	char			*port;
+	char			*port_file;
 };
 
 struct server {
@@ -210,6 +211,7 @@ struct server {
 	char			*tdb_dir;	/* TDB metadata database dir */
 	char			*pid_file;	/* PID file */
 	char			*port;		/* bind port */
+	char			*port_file;
 	char			*chunk_user;	/* username for stc_new */
 	char			*chunk_key;	/* key for stc_new */
 	unsigned short		rep_port;	/* db4 replication port */
diff --git a/test/Makefile.am b/test/Makefile.am
index 9169c8b..071c69c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -35,4 +35,6 @@ basic_bucket_LDADD	= $(TESTLDADD)
 basic_object_LDADD	= $(TESTLDADD)
 it_works_LDADD		= $(TESTLDADD)
 
+wait_for_listen_LDADD	= ../lib/libhttputil.a
+
 TESTS_ENVIRONMENT=top_srcdir=$(top_srcdir)
diff --git a/test/basic-bucket.c b/test/basic-bucket.c
index 50c2cd2..fe6e396 100644
--- a/test/basic-bucket.c
+++ b/test/basic-bucket.c
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <locale.h>
 #include <httpstor.h>
+#include <httputil.h>
 #include "test.h"
 
 int main(int argc, char *argv[])
@@ -29,10 +30,15 @@ int main(int argc, char *argv[])
 	struct httpstor_blist *blist;
 	struct httpstor_bucket *buck;
 	bool rcb;
+	char accbuf[80];
+	int rc;
 
 	setlocale(LC_ALL, "C");
 
-	httpstor = httpstor_new(TEST_HOST, TEST_USER, TEST_USER_KEY);
+	rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf));
+	OK(rc > 0);
+
+	httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY);
 	OK(httpstor);
 
 	/* make sure bucket list is empty */
diff --git a/test/basic-object.c b/test/basic-object.c
index f0f6c64..1fd37fd 100644
--- a/test/basic-object.c
+++ b/test/basic-object.c
@@ -21,11 +21,14 @@
 #include <string.h>
 #include <locale.h>
 #include <httpstor.h>
+#include <httputil.h>
 #include "test.h"
 
 int main(int argc, char *argv[])
 {
 	struct httpstor_client *httpstor;
+	char accbuf[80];
+	int rc;
 	bool rcb;
 	char val[] = "my first value";
 	char key[] = "my first key";
@@ -34,7 +37,10 @@ int main(int argc, char *argv[])
 
 	setlocale(LC_ALL, "C");
 
-	httpstor = httpstor_new(TEST_HOST, TEST_USER, TEST_USER_KEY);
+	rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf));
+	OK(rc > 0);
+
+	httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY);
 	OK(httpstor);
 
 	/* add bucket */
diff --git a/test/chunkd-test.conf b/test/chunkd-test.conf
index 9256b9d..3785eb5 100644
--- a/test/chunkd-test.conf
+++ b/test/chunkd-test.conf
@@ -1,16 +1,11 @@
 
-<!--
- Ports not to use:
-    82  -- too low for non-root
-  8082  -- installed chunkd may use it
- -->
 <Listen>
-  <Port>18082</Port>
+  <PortFile>/dev/null</PortFile>
 </Listen>
 <PID>chunkd.pid</PID>
 <Path>data/chunk</Path>
 <NID>1</NID>
 <CLD>
-  <Port>18081</Port>
+  <PortFile>cld.port</PortFile>
   <Host>localhost</Host>
 </CLD>
diff --git a/test/it-works.c b/test/it-works.c
index d0b92ac..98be6f8 100644
--- a/test/it-works.c
+++ b/test/it-works.c
@@ -21,16 +21,22 @@
 #include <string.h>
 #include <locale.h>
 #include <httpstor.h>
+#include <httputil.h>
 #include "test.h"
 
 int main(int argc, char *argv[])
 {
 	struct httpstor_client *httpstor;
 	struct httpstor_blist *blist;
+	char accbuf[80];
+	int rc;
 
 	setlocale(LC_ALL, "C");
 
-	httpstor = httpstor_new(TEST_HOST, TEST_USER, TEST_USER_KEY);
+	rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf));
+	OK(rc > 0);
+
+	httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY);
 	OK(httpstor);
 
 	blist = httpstor_list_buckets(httpstor);
diff --git a/test/start-daemon b/test/start-daemon
index efe0548..589bfe5 100755
--- a/test/start-daemon
+++ b/test/start-daemon
@@ -17,7 +17,7 @@ then
 fi
 
 # May be different on Solaris... like /usr/libexec or such.
-cld -d data/cld -P cld.pid -p 18081 -E
+cld -d data/cld -P cld.pid --port-file=cld.port -E
 chunkd -C $top_srcdir/test/chunkd-test.conf -E
 ../server/tabled -C $top_srcdir/test/tabled-test.conf -E -D
 
diff --git a/test/stop-daemon b/test/stop-daemon
index 10864b8..de5db0c 100755
--- a/test/stop-daemon
+++ b/test/stop-daemon
@@ -19,6 +19,8 @@ killpid () {
 	return 1
 }
 
+rm -f cld.port tabled.acc
+
 ret=0
 
 if [ ! -f tabled.pid ]
diff --git a/test/tabled-test.conf b/test/tabled-test.conf
index 7958505..2de599c 100644
--- a/test/tabled-test.conf
+++ b/test/tabled-test.conf
@@ -1,12 +1,12 @@
 
 <PID>tabled.pid</PID>
 <ForceHost>localhost.localdomain</ForceHost>
-<Listen><Port>18080</Port></Listen>
+<Listen><PortFile>tabled.acc</PortFile></Listen>
 <TDB>data/tdb</TDB>
 <TDBRepPort>18083</TDBRepPort>
 
 <CLD>
-  <Port>18081</Port>
+  <PortFile>cld.port</PortFile>
   <Host>localhost</Host>
 </CLD>
 
diff --git a/test/test.h b/test/test.h
index 8b59130..e627a0c 100644
--- a/test/test.h
+++ b/test/test.h
@@ -27,6 +27,8 @@
 #define TEST_USER "testuser"
 #define TEST_USER_KEY "testpw"
 
+#define TEST_FILE_TB  "tabled.acc"
+
 #define OK(expr)				\
 	do {					\
 		if (!(expr)) {			\
diff --git a/test/wait-for-listen.c b/test/wait-for-listen.c
index cb30183..3adf94c 100644
--- a/test/wait-for-listen.c
+++ b/test/wait-for-listen.c
@@ -11,6 +11,8 @@
 #include <time.h>
 #include <unistd.h>
 #include <netdb.h>
+#include <httputil.h>
+#include "test.h"
 
 #define ADDRSIZE	24	/* Enough for IPv6, including port. */
 
@@ -62,17 +64,43 @@ int main()
 {
 	struct server_node snode, *sn = &snode;
 	time_t start_time;
+	const static char accname[] = TEST_FILE_TB;
+	char accbuf[80];
+	char *s;
+	int cnt;
 	int sfd;
 	int rc;
 
-	/*
-	 * We hardcode host and port because we don't know an easy way
-	 * to pass parameters to tests.
-	 */
+	cnt = 0;
+	for (;;) {
+		rc = tb_readport(accname, accbuf, sizeof(accbuf));
+		if (rc > 0)
+			break;
+		if (++cnt >= 5) {	/* should not take long */
+			if (rc == 0) {
+				fprintf(stderr, "Nothing to read in %s\n",
+					accname);
+				exit(1);
+			}
+			if (rc < 0) {
+				fprintf(stderr, "Failed to read %s: %s\n",
+					accname, strerror(-rc));
+				exit(1);
+			}
+		}
+		sleep(1);
+	}
+
+	s = strchr(accbuf, ':');
+	if (!s)
+		s = "80";
+	else
+		*s++ = 0;
+
 	memset(sn, 0, sizeof(struct server_node));
-	if (node_resolve(sn, "localhost", "18080") != 0) {
+	if (node_resolve(sn, accbuf, s) != 0) {
 		fprintf(stderr,
-			"Unable to resolve host localhost port 18080\n");
+			"Unable to resolve host %s port %s\n", accbuf, s);
 		exit(1);
 	}
 
--
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