Browse Source

Partial-Merge commit 'e1387dc' into cg_merges_20121231 (avoid memory fragmentation)

Conflicts:
	miner.h
	util.c
Luke Dashjr 13 years ago
parent
commit
038f5ef9ce
2 changed files with 76 additions and 42 deletions
  1. 4 9
      miner.h
  2. 72 33
      util.c

+ 4 - 9
miner.h

@@ -902,14 +902,8 @@ struct stratum_work {
 	bool opaque;
 	bool opaque;
 };
 };
 
 
-#define RECVSIZE 8192
-#define RBUFSIZE (RECVSIZE + 4)
-
-struct data_buffer {
-	void		*buf;
-	size_t		len;
-	curl_socket_t	*idlemarker;
-};
+#define RBUFSIZE 8192
+#define RECVSIZE (RBUFSIZE - 4)
 
 
 struct pool {
 struct pool {
 	int pool_no;
 	int pool_no;
@@ -984,7 +978,8 @@ struct pool {
 	char *stratum_port;
 	char *stratum_port;
 	CURL *stratum_curl;
 	CURL *stratum_curl;
 	SOCKETTYPE sock;
 	SOCKETTYPE sock;
-	struct data_buffer readbuf;
+	char *sockbuf;
+	size_t sockbuf_size;
 	char *sockaddr_url; /* stripped url used for sockaddr */
 	char *sockaddr_url; /* stripped url used for sockaddr */
 	char *nonce1;
 	char *nonce1;
 	uint32_t nonce2;
 	uint32_t nonce2;

+ 72 - 33
util.c

@@ -56,6 +56,12 @@
 bool successful_connect = false;
 bool successful_connect = false;
 struct timeval nettime;
 struct timeval nettime;
 
 
+struct data_buffer {
+	void		*buf;
+	size_t		len;
+	curl_socket_t	*idlemarker;
+};
+
 struct upload_buffer {
 struct upload_buffer {
 	const void	*buf;
 	const void	*buf;
 	size_t		len;
 	size_t		len;
@@ -1044,7 +1050,7 @@ static bool socket_full(struct pool *pool, bool wait)
 /* Check to see if Santa's been good to you */
 /* Check to see if Santa's been good to you */
 bool sock_full(struct pool *pool)
 bool sock_full(struct pool *pool)
 {
 {
-	if (pool->readbuf.buf && memchr(pool->readbuf.buf, '\n', pool->readbuf.len))
+	if (strlen(pool->sockbuf))
 		return true;
 		return true;
 
 
 	return (socket_full(pool, false));
 	return (socket_full(pool, false));
@@ -1053,60 +1059,85 @@ bool sock_full(struct pool *pool)
 static void clear_sock(struct pool *pool)
 static void clear_sock(struct pool *pool)
 {
 {
 	ssize_t n;
 	ssize_t n;
-	char buf[RECVSIZE];
 
 
 	mutex_lock(&pool->stratum_lock);
 	mutex_lock(&pool->stratum_lock);
 	do
 	do
-		n = recv(pool->sock, buf, RECVSIZE, 0);
+		n = recv(pool->sock, pool->sockbuf, RECVSIZE, 0);
 	while (n > 0);
 	while (n > 0);
 	mutex_unlock(&pool->stratum_lock);
 	mutex_unlock(&pool->stratum_lock);
-	pool->readbuf.len = 0;
+	strcpy(pool->sockbuf, "");
+}
+
+/* Make sure the pool sockbuf is large enough to cope with any coinbase size
+ * by reallocing it to a large enough size rounded up to a multiple of RBUFSIZE
+ * and zeroing the new memory */
+static void recalloc_sock(struct pool *pool, size_t len)
+{
+	size_t old, new;
+
+	old = strlen(pool->sockbuf);
+	new = old + len + 1;
+	if (new < pool->sockbuf_size)
+		return;
+	new = new + (RBUFSIZE - (new % RBUFSIZE));
+	applog(LOG_DEBUG, "Recallocing pool sockbuf to %d", new);
+	pool->sockbuf = realloc(pool->sockbuf, new);
+	if (!pool->sockbuf)
+		quit(1, "Failed to realloc pool sockbuf in recalloc_sock");
+	memset(pool->sockbuf + old, 0, new - old);
+	pool->sockbuf_size = new;
 }
 }
 
 
 /* Peeks at a socket to find the first end of line and then reads just that
 /* Peeks at a socket to find the first end of line and then reads just that
  * from the socket and returns that as a malloced char */
  * from the socket and returns that as a malloced char */
 char *recv_line(struct pool *pool)
 char *recv_line(struct pool *pool)
 {
 {
-	ssize_t len;
+	ssize_t len, buflen;
 	char *tok, *sret = NULL;
 	char *tok, *sret = NULL;
-	ssize_t n;
 
 
-	while (!(pool->readbuf.buf && memchr(pool->readbuf.buf, '\n', pool->readbuf.len))) {
-		char s[RBUFSIZE];
+	if (!strstr(pool->sockbuf, "\n")) {
+		struct timeval rstart, now;
 
 
+		gettimeofday(&rstart, NULL);
 		if (!socket_full(pool, true)) {
 		if (!socket_full(pool, true)) {
 			applog(LOG_DEBUG, "Timed out waiting for data on socket_full");
 			applog(LOG_DEBUG, "Timed out waiting for data on socket_full");
 			goto out;
 			goto out;
 		}
 		}
-		memset(s, 0, RBUFSIZE);
 
 
 		mutex_lock(&pool->stratum_lock);
 		mutex_lock(&pool->stratum_lock);
-		n = recv(pool->sock, s, RECVSIZE, 0);
+		do {
+			char s[RBUFSIZE];
+			size_t slen, n;
+
+			memset(s, 0, RBUFSIZE);
+			n = recv(pool->sock, s, RECVSIZE, 0);
+			if (n < 1 && errno != EAGAIN && errno != EWOULDBLOCK) {
+				applog(LOG_DEBUG, "Failed to recv sock in recv_line");
+				break;
+			}
+			slen = strlen(s);
+			recalloc_sock(pool, slen);
+			strcat(pool->sockbuf, s);
+			gettimeofday(&now, NULL);
+		} while (tdiff(&now, &rstart) < 60 && !strstr(pool->sockbuf, "\n"));
 		mutex_unlock(&pool->stratum_lock);
 		mutex_unlock(&pool->stratum_lock);
+	}
 
 
-		if (n < 1 && errno != EAGAIN && errno != EWOULDBLOCK) {
-			applog(LOG_DEBUG, "Failed to recv sock in recv_line: %d", errno);
-			goto out;
-		}
-
-		len = all_data_cb(s, n, 1, &pool->readbuf);
-		if (1 != len) {
-			applog(LOG_DEBUG, "Error appending readbuf in recv_line for pool %u", pool->pool_no);
-			goto out;
-		}
+	buflen = strlen(pool->sockbuf);
+	tok = strtok(pool->sockbuf, "\n");
+	if (!tok) {
+		applog(LOG_DEBUG, "Failed to parse a \\n terminated string in recv_line");
+		goto out;
 	}
 	}
+	sret = strdup(tok);
+	len = strlen(sret);
 
 
-	// Assuming the bulk of the data will be in the line, steal the buffer and return it
-	tok = memchr(pool->readbuf.buf, '\n', pool->readbuf.len);
-	*tok = '\0';
-	len = tok - (char*)pool->readbuf.buf;
-	pool->readbuf.len -= len + 1;
-	tok = memcpy(malloc(pool->readbuf.len), tok + 1, pool->readbuf.len);
-	sret = realloc(pool->readbuf.buf, len + 1);
-#ifdef DEBUG_DATABUF
-	applog(LOG_DEBUG, "recv_line realloc(%p, %lu) => %p (new readbuf.buf=%p)", pool->readbuf.buf, (unsigned long)(len + 1), sret, tok);
-#endif
-	pool->readbuf.buf = tok;
+	/* Copy what's left in the buffer after the \n, including the
+	 * terminating \0 */
+	if (buflen > len + 1)
+		memmove(pool->sockbuf, pool->sockbuf + len + 1, buflen - len + 1);
+	else
+		strcpy(pool->sockbuf, "");
 
 
 	pool->cgminer_pool_stats.times_received++;
 	pool->cgminer_pool_stats.times_received++;
 	pool->cgminer_pool_stats.bytes_received += len;
 	pool->cgminer_pool_stats.bytes_received += len;
@@ -1453,7 +1484,7 @@ bool initiate_stratum(struct pool *pool)
 	json_error_t err;
 	json_error_t err;
 	bool ret = false;
 	bool ret = false;
 
 
-	applog(LOG_DEBUG, "initiate_stratum with readbuf.buf=%p", pool->readbuf.buf);
+	applog(LOG_DEBUG, "initiate_stratum with sockbuf=%p", pool->sockbuf);
 	mutex_lock(&pool->stratum_lock);
 	mutex_lock(&pool->stratum_lock);
 	pool->swork.transparency_time = (time_t)-1;
 	pool->swork.transparency_time = (time_t)-1;
 	pool->stratum_active = false;
 	pool->stratum_active = false;
@@ -1464,10 +1495,18 @@ bool initiate_stratum(struct pool *pool)
 		if (unlikely(!pool->stratum_curl))
 		if (unlikely(!pool->stratum_curl))
 			quit(1, "Failed to curl_easy_init in initiate_stratum");
 			quit(1, "Failed to curl_easy_init in initiate_stratum");
 	}
 	}
-	pool->readbuf.len = 0;
+	if (pool->sockbuf)
+		pool->sockbuf[0] = '\0';
 	mutex_unlock(&pool->stratum_lock);
 	mutex_unlock(&pool->stratum_lock);
 	curl = pool->stratum_curl;
 	curl = pool->stratum_curl;
 
 
+	if (!pool->sockbuf) {
+		pool->sockbuf = calloc(RBUFSIZE, 1);
+		if (!pool->sockbuf)
+			quit(1, "Failed to calloc pool sockbuf in initiate_stratum");
+		pool->sockbuf_size = RBUFSIZE;
+	}
+
 	/* Create a http url for use with curl */
 	/* Create a http url for use with curl */
 	memset(s, 0, RBUFSIZE);
 	memset(s, 0, RBUFSIZE);
 	sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);
 	sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);