Browse Source

Merge branch 'cg_merges_20121231' into bfgminer

Luke Dashjr 13 years ago
parent
commit
91096df0b7
5 changed files with 130 additions and 63 deletions
  1. 13 0
      NEWS
  2. 15 7
      miner.c
  3. 5 9
      miner.h
  4. 96 46
      util.c
  5. 1 1
      util.h

+ 13 - 0
NEWS

@@ -1,3 +1,16 @@
+BFGMiner Version 2.10.3 - Future
+
+- Change the pool stratum socket buffer to be dynamically allocated to
+accomodate any size coinbase and keep receiving data in recv line for up to 60s
+if no end of line has been received.
+- Differentiate socket full from sock full.
+- Allow stratum to startup without notify but check it is valid before creating
+stratum work.
+- Do not try to generate stratum work unless the notify command has succeeded.
+- Reset total diff1 shares when zeroing stats as well to show correct work
+utility.
+
+
 BFGMiner Version 2.10.2 - December 27, 2012
 
 - Update documentation to include block difficulty

+ 15 - 7
miner.c

@@ -4758,6 +4758,7 @@ void zero_stats(void)
 	total_secs = 1.0;
 	best_diff = 0;
 	total_diff1 = 0;
+	memset(best_share, 0, 8);
 	suffix_string(best_diff, best_share, 0);
 
 	for (i = 0; i < total_pools; i++) {
@@ -5650,6 +5651,16 @@ static void wait_lpcurrent(struct pool *pool);
 static void pool_resus(struct pool *pool);
 static void gen_stratum_work(struct pool *pool, struct work *work);
 
+static void stratum_resumed(struct pool *pool)
+{
+	if (!pool->stratum_notify)
+		return;
+	if (!pool_tclear(pool, &pool->idle))
+		return;
+	applog(LOG_INFO, "Stratum connection to pool %d resumed", pool->pool_no);
+	pool_resus(pool);
+}
+
 /* One stratum thread per pool that has stratum waits on the socket checking
  * for new messages and for the integrity of the socket connection. We reset
  * the connection based on the integrity of the receive side only as the send
@@ -5675,7 +5686,7 @@ static void *stratum_thread(void *userdata)
 		/* Check to see whether we need to maintain this connection
 		 * indefinitely or just bring it up when we switch to this
 		 * pool */
-		if (!sock_full(pool, false) && !cnx_needed(pool)) {
+		if (!sock_full(pool) && !cnx_needed(pool)) {
 			suspend_stratum(pool);
 			clear_stratum_shares(pool);
 			clear_pool_work(pool);
@@ -5699,7 +5710,7 @@ static void *stratum_thread(void *userdata)
 		/* If we fail to receive any notify messages for 2 minutes we
 		 * assume the connection has been dropped and treat this pool
 		 * as dead */
-		if (!sock_full(pool, false) && select(pool->sock + 1, &rd, NULL, NULL, &timeout) < 1)
+		if (!sock_full(pool) && select(pool->sock + 1, &rd, NULL, NULL, &timeout) < 1)
 			s = NULL;
 		else
 			s = recv_line(pool);
@@ -5734,10 +5745,7 @@ static void *stratum_thread(void *userdata)
 
 		/* Check this pool hasn't died while being a backup pool and
 		 * has not had its idle flag cleared */
-		if (pool_tclear(pool, &pool->idle)) {
-			applog(LOG_INFO, "Stratum connection to pool %d resumed", pool->pool_no);
-			pool_resus(pool);
-		}
+		stratum_resumed(pool);
 
 		if (!parse_method(pool, s) && !parse_stratum_response(pool, s))
 			applog(LOG_INFO, "Unknown stratum msg: %s", s);
@@ -8171,7 +8179,7 @@ begin_bench:
 		pool = select_pool(lagging);
 retry:
 		if (pool->has_stratum) {
-			while (!pool->stratum_active) {
+			while (!pool->stratum_active || !pool->stratum_notify) {
 				struct pool *altpool = select_pool(true);
 
 				if (altpool == pool && pool->has_stratum)

+ 5 - 9
miner.h

@@ -902,14 +902,8 @@ struct stratum_work {
 	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 {
 	int pool_no;
@@ -984,7 +978,8 @@ struct pool {
 	char *stratum_port;
 	CURL *stratum_curl;
 	SOCKETTYPE sock;
-	struct data_buffer readbuf;
+	char *sockbuf;
+	size_t sockbuf_size;
 	char *sockaddr_url; /* stripped url used for sockaddr */
 	char *nonce1;
 	uint32_t nonce2;
@@ -993,6 +988,7 @@ struct pool {
 	bool stratum_active;
 	time_t last_work_time;  /* only set for Stratum right now */
 	bool stratum_auth;
+	bool stratum_notify;
 	struct stratum_work swork;
 	pthread_t stratum_thread;
 	pthread_mutex_t stratum_lock;

+ 96 - 46
util.c

@@ -56,6 +56,12 @@
 bool successful_connect = false;
 struct timeval nettime;
 
+struct data_buffer {
+	void		*buf;
+	size_t		len;
+	curl_socket_t	*idlemarker;
+};
+
 struct upload_buffer {
 	const void	*buf;
 	size_t		len;
@@ -1023,16 +1029,12 @@ bool stratum_send(struct pool *pool, char *s, ssize_t len)
 	return ret;
 }
 
-/* Check to see if Santa's been good to you */
-bool sock_full(struct pool *pool, bool wait)
+static bool socket_full(struct pool *pool, bool wait)
 {
 	SOCKETTYPE sock = pool->sock;
 	struct timeval timeout;
 	fd_set rd;
 
-	if (pool->readbuf.buf && memchr(pool->readbuf.buf, '\n', pool->readbuf.len))
-		return true;
-
 	FD_ZERO(&rd);
 	FD_SET(sock, &rd);
 	timeout.tv_usec = 0;
@@ -1045,63 +1047,97 @@ bool sock_full(struct pool *pool, bool wait)
 	return false;
 }
 
+/* Check to see if Santa's been good to you */
+bool sock_full(struct pool *pool)
+{
+	if (strlen(pool->sockbuf))
+		return true;
+
+	return (socket_full(pool, false));
+}
+
 static void clear_sock(struct pool *pool)
 {
 	ssize_t n;
-	char buf[RECVSIZE];
 
 	mutex_lock(&pool->stratum_lock);
 	do
-		n = recv(pool->sock, buf, RECVSIZE, 0);
+		n = recv(pool->sock, pool->sockbuf, RECVSIZE, 0);
 	while (n > 0);
 	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
  * from the socket and returns that as a malloced char */
 char *recv_line(struct pool *pool)
 {
-	ssize_t len;
+	ssize_t len, buflen;
 	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;
 
-		if (!sock_full(pool, true)) {
-			applog(LOG_DEBUG, "Timed out waiting for data on sock_full");
+		gettimeofday(&rstart, NULL);
+		if (!socket_full(pool, true)) {
+			applog(LOG_DEBUG, "Timed out waiting for data on socket_full");
 			goto out;
 		}
-		memset(s, 0, RBUFSIZE);
 
 		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);
+	}
 
-		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.bytes_received += len;
@@ -1148,13 +1184,13 @@ static char *json_array_string(json_t *val, unsigned int entry)
 static bool parse_notify(struct pool *pool, json_t *val)
 {
 	char *job_id, *prev_hash, *coinbase1, *coinbase2, *bbversion, *nbit, *ntime;
+	bool clean, ret = false;
 	int merkles, i;
 	json_t *arr;
-	bool clean;
 
 	arr = json_array_get(val, 4);
 	if (!arr || !json_is_array(arr))
-		return false;
+		goto out;
 
 	merkles = json_array_size(arr);
 
@@ -1183,7 +1219,7 @@ static bool parse_notify(struct pool *pool, json_t *val)
 			free(nbit);
 		if (ntime)
 			free(ntime);
-		return false;
+		goto out;
 	}
 
 	mutex_lock(&pool->pool_lock);
@@ -1248,7 +1284,9 @@ static bool parse_notify(struct pool *pool, json_t *val)
 		pool->swork.transparency_probed = true;
 	}
 
-	return true;
+	ret = true;
+out:
+	return ret;
 }
 
 static bool parse_diff(struct pool *pool, json_t *val)
@@ -1352,8 +1390,11 @@ bool parse_method(struct pool *pool, char *s)
 	if (!buf)
 		goto out;
 
-	if (!strncasecmp(buf, "mining.notify", 13) && parse_notify(pool, params)) {
-		ret = true;
+	if (!strncasecmp(buf, "mining.notify", 13)) {
+		if (parse_notify(pool, params))
+			pool->stratum_notify = ret = true;
+		else
+			pool->stratum_notify = ret = false;
 		goto out;
 	}
 
@@ -1421,6 +1462,7 @@ bool auth_stratum(struct pool *pool)
 
 		goto out;
 	}
+
 	ret = true;
 	applog(LOG_INFO, "Stratum authorisation success for pool %d", pool->pool_no);
 	pool->probed = true;
@@ -1442,7 +1484,7 @@ bool initiate_stratum(struct pool *pool)
 	json_error_t err;
 	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);
 	pool->swork.transparency_time = (time_t)-1;
 	pool->stratum_active = false;
@@ -1453,10 +1495,18 @@ bool initiate_stratum(struct pool *pool)
 		if (unlikely(!pool->stratum_curl))
 			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);
 	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 */
 	memset(s, 0, RBUFSIZE);
 	sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);
@@ -1500,7 +1550,7 @@ bool initiate_stratum(struct pool *pool)
 		goto out;
 	}
 
-	if (!sock_full(pool, true)) {
+	if (!socket_full(pool, true)) {
 		applog(LOG_DEBUG, "Timed out waiting for response in initiate_stratum");
 		goto out;
 	}

+ 1 - 1
util.h

@@ -59,7 +59,7 @@ extern bool hash_target_check(const unsigned char *hash, const unsigned char *ta
 extern bool hash_target_check_v(const unsigned char *hash, const unsigned char *target);
 
 bool stratum_send(struct pool *pool, char *s, ssize_t len);
-bool sock_full(struct pool *pool, bool wait);
+bool sock_full(struct pool *pool);
 char *recv_line(struct pool *pool);
 bool parse_method(struct pool *pool, char *s);
 bool extract_sockaddr(struct pool *pool, char *url);