Commit ab1e9404a7fea31a03954ba7e9435ed8cb6e0f8f

Con Kolivas 2013-11-03T00:47:43

Make each pool store its on reference for what the most current block is and fine tune management of block change in shared pool failover strategies using the information.

diff --git a/cgminer.c b/cgminer.c
index 08168b6..67ac1a0 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -279,6 +279,7 @@ bool curses_active;
 /* Protected by ch_lock */
 char current_hash[68];
 static char prev_block[12];
+static char current_block[32];
 
 static char datestamp[40];
 static char blocktime[32];
@@ -2272,6 +2273,11 @@ static void get_statline(char *buf, size_t bufsiz, struct cgpu_info *cgpu)
 	wprintw(win, "%s", tmp42); \
 } while (0)
 
+static bool shared_strategy(void)
+{
+	return (pool_strategy == POOL_LOADBALANCE || pool_strategy == POOL_BALANCE);
+}
+
 /* Must be called with curses mutex lock held and curses_active */
 static void curses_print_status(void)
 {
@@ -2287,7 +2293,7 @@ static void curses_print_status(void)
 		total_staged(), total_stale, new_blocks,
 		local_work, total_go, total_ro);
 	wclrtoeol(statuswin);
-	if ((pool_strategy == POOL_LOADBALANCE  || pool_strategy == POOL_BALANCE) && total_pools > 1) {
+	if (shared_strategy() && total_pools > 1) {
 		cg_mvwprintw(statuswin, 4, 0, " Connected to multiple pools with%s block change notify",
 			have_longpoll ? "": "out");
 	} else if (pool->has_stratum) {
@@ -4015,13 +4021,14 @@ static void signal_work_update(void)
 	rd_unlock(&mining_thr_lock);
 }
 
-static void set_curblock(char *hexstr)
+static void set_curblock(char *hexstr, unsigned char *bedata)
 {
 	int ofs;
 
 	cg_wlock(&ch_lock);
 	cgtime(&block_timeval);
 	strcpy(current_hash, hexstr);
+	memcpy(current_block, bedata, 32);
 	get_timestamp(blocktime, sizeof(blocktime), &block_timeval);
 	cg_wunlock(&ch_lock);
 
@@ -4083,6 +4090,7 @@ static void set_blockdiff(const struct work *work)
 
 static bool test_work_current(struct work *work)
 {
+	struct pool *pool = work->pool;
 	unsigned char bedata[32];
 	char hexstr[68];
 	bool ret = true;
@@ -4098,7 +4106,6 @@ static bool test_work_current(struct work *work)
 	if (!block_exists(hexstr)) {
 		struct block *s = calloc(sizeof(struct block), 1);
 		int deleted_block = 0;
-		ret = false;
 
 		if (unlikely(!s))
 			quit (1, "test_work_current OOM");
@@ -4124,31 +4131,71 @@ static bool test_work_current(struct work *work)
 
 		if (deleted_block)
 			applog(LOG_DEBUG, "Deleted block %d from database", deleted_block);
-		set_curblock(hexstr);
-		if (unlikely(new_blocks == 1))
-			return ret;
+		set_curblock(hexstr, bedata);
+		/* Copy the information to this pool's prev_block since it
+		 * knows the new block exists. */
+		memcpy(pool->prev_block, bedata, 32);
+		if (unlikely(new_blocks == 1)) {
+			ret = false;
+			goto out;
+		}
 
 		work->work_block = ++work_block;
 
-		if (!work->stratum) {
-			if (work->longpoll) {
+		if (work->longpoll) {
+			if (work->stratum) {
+				applog(LOG_NOTICE, "Stratum from pool %d detected new block",
+				       pool->pool_no);
+			} else {
 				applog(LOG_NOTICE, "%sLONGPOLL from pool %d detected new block",
 				       work->gbt ? "GBT " : "", work->pool->pool_no);
-			} else if (have_longpoll)
-				applog(LOG_NOTICE, "New block detected on network before longpoll");
-			else
-				applog(LOG_NOTICE, "New block detected on network");
-		}
+			}
+		} else if (have_longpoll)
+			applog(LOG_NOTICE, "New block detected on network before longpoll");
+		else
+			applog(LOG_NOTICE, "New block detected on network");
 		restart_threads();
-	} else if (work->longpoll) {
-		work->work_block = ++work_block;
-		if (work->pool == current_pool()) {
-			applog(LOG_NOTICE, "%sLONGPOLL from pool %d requested work restart",
-			       work->gbt ? "GBT " : "", work->pool->pool_no);
-			restart_threads();
+	} else {
+		if (memcmp(pool->prev_block, bedata, 32)) {
+			/* Work doesn't match what this pool has stored as
+			 * prev_block. Let's see if the work is from an old
+			 * block or the pool is just learning about a new
+			 * block. */
+			if (memcmp(bedata, current_block, 32)) {
+				/* Doesn't match current block. It's stale */
+				applog(LOG_DEBUG, "Stale data from pool %d", pool->pool_no);
+				ret = false;
+			} else {
+				/* Work is from new block and pool is up now
+				 * current. */
+				applog(LOG_INFO, "Pool %d now up to date", pool->pool_no);
+				memcpy(pool->prev_block, bedata, 32);
+			}
+		}
+#if 0
+		/* This isn't ideal, this pool is still on an old block but
+		 * accepting shares from it. To maintain fair work distribution
+		 * we work on it anyway. */
+		if (memcmp(bedata, current_block, 32))
+			applog(LOG_DEBUG, "Pool %d still on old block", pool->pool_no);
+#endif
+		if (work->longpoll) {
+			work->work_block = ++work_block;
+			if (shared_strategy() || work->pool == current_pool()) {
+				if (work->stratum) {
+					applog(LOG_NOTICE, "Stratum from pool %d requested work restart",
+					       pool->pool_no);
+				} else {
+					applog(LOG_NOTICE, "%sLONGPOLL from pool %d requested work restart",
+					       work->gbt ? "GBT " : "", work->pool->pool_no);
+				}
+				restart_threads();
+			}
 		}
 	}
+out:
 	work->longpoll = false;
+
 	return ret;
 }
 
@@ -5501,15 +5548,10 @@ static void *stratum_rthread(void *userdata)
 			 * block database */
 			pool->swork.clean = false;
 			gen_stratum_work(pool, work);
-			if (test_work_current(work)) {
-				/* Only accept a work restart if this stratum
-				 * connection is from the current pool */
-				if (pool == current_pool()) {
-					restart_threads();
-					applog(LOG_NOTICE, "Stratum from pool %d requested work restart", pool->pool_no);
-				}
-			} else
-				applog(LOG_NOTICE, "Stratum from pool %d detected new block", pool->pool_no);
+			work->longpoll = true;
+			/* Return value doesn't matter. We're just informing
+			 * that we may need to restart. */
+			test_work_current(work);
 			free_work(work);
 		}
 	}
diff --git a/miner.h b/miner.h
index 19156e7..d0be71e 100644
--- a/miner.h
+++ b/miner.h
@@ -1326,6 +1326,9 @@ struct pool {
 	struct cgminer_stats cgminer_stats;
 	struct cgminer_pool_stats cgminer_pool_stats;
 
+	/* The last block this particular pool knows about */
+	char prev_block[32];
+
 	/* Stratum variables */
 	char *stratum_url;
 	char *stratum_port;