Commit eb60ca55f1966ace2a1655cdb6883cc3151fe9c5

nelisky 2012-05-04T04:11:08

Merge remote-tracking branch 'upstream/master' into ztex-120417

diff --git a/api.c b/api.c
index 8571dcc..1bf9b2b 100644
--- a/api.c
+++ b/api.c
@@ -158,7 +158,7 @@ static const char SEPARATOR = '|';
 #define SEPSTR "|"
 static const char GPUSEP = ',';
 
-static const char *APIVERSION = "1.9";
+static const char *APIVERSION = "1.10";
 static const char *DEAD = "Dead";
 static const char *SICK = "Sick";
 static const char *NOSTART = "NoStart";
@@ -1221,8 +1221,8 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, 
 		rpc_user = escape_string(pool->rpc_user, isjson);
 
 		sprintf(buf, isjson
-			? "%s{\"POOL\":%d,\"URL\":\"%s\",\"Status\":\"%s\",\"Priority\":%d,\"Long Poll\":\"%s\",\"Getworks\":%d,\"Accepted\":%d,\"Rejected\":%d,\"Discarded\":%d,\"Stale\":%d,\"Get Failures\":%d,\"Remote Failures\":%d,\"User\":\"%s\"}"
-			: "%sPOOL=%d,URL=%s,Status=%s,Priority=%d,Long Poll=%s,Getworks=%d,Accepted=%d,Rejected=%d,Discarded=%d,Stale=%d,Get Failures=%d,Remote Failures=%d,User=%s" SEPSTR,
+			? "%s{\"POOL\":%d,\"URL\":\"%s\",\"Status\":\"%s\",\"Priority\":%d,\"Long Poll\":\"%s\",\"Getworks\":%d,\"Accepted\":%d,\"Rejected\":%d,\"Discarded\":%d,\"Stale\":%d,\"Get Failures\":%d,\"Remote Failures\":%d,\"User\":\"%s\",\"Last Share Time\":%lu}"
+			: "%sPOOL=%d,URL=%s,Status=%s,Priority=%d,Long Poll=%s,Getworks=%d,Accepted=%d,Rejected=%d,Discarded=%d,Stale=%d,Get Failures=%d,Remote Failures=%d,User=%s,Last Share Time=%lu" SEPSTR,
 			(isjson && (i > 0)) ? COMMA : BLANK,
 			i, rpc_url, status, pool->prio, lp,
 			pool->getwork_requested,
@@ -1231,7 +1231,7 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, 
 			pool->stale_shares,
 			pool->getfail_occasions,
 			pool->remotefail_occasions,
-			rpc_user);
+			rpc_user, pool->last_share_time);
 
 		strcat(io_buffer, buf);
 
diff --git a/cgminer.c b/cgminer.c
index 26259c6..b2bcd5a 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -1660,6 +1660,7 @@ static bool submit_upstream_work(const struct work *work, CURL *curl)
 		pool->seq_rejects = 0;
 		cgpu->last_share_pool = pool->pool_no;
 		cgpu->last_share_pool_time = time(NULL);
+		pool->last_share_time = cgpu->last_share_pool_time;
 		applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)");
 		if (!QUIET) {
 			if (total_pools > 1)
@@ -1675,6 +1676,16 @@ static bool submit_upstream_work(const struct work *work, CURL *curl)
 			kill_work();
 			goto out;
 		}
+
+		/* Detect if a pool that has been temporarily disabled for
+		 * continually rejecting shares has started accepting shares.
+		 * This will only happen with the work returned from a
+		 * longpoll */
+		if (unlikely(pool->enabled == POOL_REJECTING)) {
+			applog(LOG_WARNING, "Rejecting pool %d now accepting shares, re-enabling!", pool->pool_no);
+			pool->enabled = POOL_ENABLED;
+			switch_pools(NULL);
+		}
 	} else {
 		cgpu->rejected++;
 		total_rejected++;
@@ -1721,9 +1732,10 @@ static bool submit_upstream_work(const struct work *work, CURL *curl)
 			if (pool->seq_rejects > utility) {
 				applog(LOG_WARNING, "Pool %d rejected %d sequential shares, disabling!",
 				       pool->pool_no, pool->seq_rejects);
-				pool->enabled = false;
+				pool->enabled = POOL_REJECTING;
 				if (pool == current_pool())
 					switch_pools(NULL);
+				pool->seq_rejects = 0;
 			}
 		}
 	}
@@ -1768,7 +1780,7 @@ static inline struct pool *select_pool(bool lagging)
 		if (++rotating_pool >= total_pools)
 			rotating_pool = 0;
 		pool = pools[rotating_pool];
-		if ((!pool->idle && pool->enabled) || pool == cp)
+		if ((!pool->idle && pool->enabled == POOL_ENABLED) || pool == cp)
 			break;
 		pool = NULL;
 	}
@@ -2042,25 +2054,30 @@ static void *get_work_thread(void *userdata)
 	else
 		ret_work->thr = NULL;
 
-	pool = ret_work->pool = select_pool(wc->lagging);
-	ce = pop_curl_entry(pool);
+	if (opt_benchmark)
+		get_benchmark_work(ret_work);
+	else {
+		pool = ret_work->pool = select_pool(wc->lagging);
+		
+		ce = pop_curl_entry(pool);
+
+		/* obtain new work from bitcoin via JSON-RPC */
+		while (!get_upstream_work(ret_work, ce->curl)) {
+			if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) {
+				applog(LOG_ERR, "json_rpc_call failed, terminating workio thread");
+				free_work(ret_work);
+				kill_work();
+				goto out;
+			}
 
-	/* obtain new work from bitcoin via JSON-RPC */
-	while (!get_upstream_work(ret_work, ce->curl)) {
-		if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) {
-			applog(LOG_ERR, "json_rpc_call failed, terminating workio thread");
-			free_work(ret_work);
-			kill_work();
-			goto out;
+			/* pause, then restart work-request loop */
+			applog(LOG_DEBUG, "json_rpc_call failed on get work, retry after %d seconds",
+				fail_pause);
+			sleep(fail_pause);
+			fail_pause += opt_fail_pause;
 		}
-
-		/* pause, then restart work-request loop */
-		applog(LOG_DEBUG, "json_rpc_call failed on get work, retry after %d seconds",
-			fail_pause);
-		sleep(fail_pause);
-		fail_pause += opt_fail_pause;
+		fail_pause = opt_fail_pause;
 	}
-	fail_pause = opt_fail_pause;
 
 	applog(LOG_DEBUG, "Pushing work to requesting thread");
 
@@ -2073,7 +2090,8 @@ static void *get_work_thread(void *userdata)
 
 out:
 	workio_cmd_free(wc);
-	push_curl_entry(ce, pool);
+	if (!opt_benchmark)
+		push_curl_entry(ce, pool);
 	return NULL;
 }
 
@@ -2094,6 +2112,7 @@ static bool workio_get_work(struct workio_cmd *wc)
 static bool stale_work(struct work *work, bool share)
 {
 	struct timeval now;
+	struct pool *pool;
 
 	if (opt_benchmark)
 		return false;
@@ -2108,7 +2127,8 @@ static bool stale_work(struct work *work, bool share)
 	if (work->work_block != work_block)
 		return true;
 
-	if (opt_fail_only && !share && work->pool != current_pool())
+	pool = work->pool;
+	if (opt_fail_only && !share && pool != current_pool() && pool->enabled != POOL_REJECTING)
 		return true;
 
 	return false;
@@ -2233,7 +2253,7 @@ void switch_pools(struct pool *selected)
 		case POOL_LOADBALANCE:
 			for (i = 0; i < total_pools; i++) {
 				pool = priority_pool(i);
-				if (!pool->idle && pool->enabled) {
+				if (!pool->idle && pool->enabled == POOL_ENABLED) {
 					pool_no = pool->pool_no;
 					break;
 				}
@@ -2542,7 +2562,7 @@ int active_pools(void)
 	int i;
 
 	for (i = 0; i < total_pools; i++) {
-		if ((pools[i])->enabled)
+		if ((pools[i])->enabled == POOL_ENABLED)
 			ret++;
 	}
 	return ret;
@@ -2764,11 +2784,21 @@ updated:
 
 		if (pool == current_pool())
 			wattron(logwin, A_BOLD);
-		if (!pool->enabled)
+		if (pool->enabled != POOL_ENABLED)
 			wattron(logwin, A_DIM);
-		wlogprint("%d: %s %s Priority %d: %s  User:%s\n",
-			pool->pool_no,
-			pool->enabled? "Enabled" : "Disabled",
+		wlogprint("%d: ");
+		switch (pool->enabled) {
+			case POOL_ENABLED:
+				wlogprint("Enabled ");
+				break;
+			case POOL_DISABLED:
+				wlogprint("Disabled ");
+				break;
+			case POOL_REJECTING:
+				wlogprint("Rejecting ");
+				break;
+		}
+		wlogprint("%s Priority %d: %s  User:%s\n",
 			pool->idle? "Dead" : "Alive",
 			pool->prio,
 			pool->rpc_url, pool->rpc_user);
@@ -2804,7 +2834,7 @@ retry:
 			wlogprint("Unable to remove pool due to activity\n");
 			goto retry;
 		}
-		pool->enabled = false;
+		pool->enabled = POOL_DISABLED;
 		remove_pool(pool);
 		goto updated;
 	} else if (!strncasecmp(&input, "s", 1)) {
@@ -2814,7 +2844,7 @@ retry:
 			goto retry;
 		}
 		pool = pools[selected];
-		pool->enabled = true;
+		pool->enabled = POOL_ENABLED;
 		switch_pools(pool);
 		goto updated;
 	} else if (!strncasecmp(&input, "d", 1)) {
@@ -2828,7 +2858,7 @@ retry:
 			goto retry;
 		}
 		pool = pools[selected];
-		pool->enabled = false;
+		pool->enabled = POOL_DISABLED;
 		if (pool == current_pool())
 			switch_pools(NULL);
 		goto updated;
@@ -2839,7 +2869,7 @@ retry:
 			goto retry;
 		}
 		pool = pools[selected];
-		pool->enabled = true;
+		pool->enabled = POOL_ENABLED;
 		if (pool->prio < current_pool()->prio)
 			switch_pools(pool);
 		goto updated;
@@ -3880,8 +3910,11 @@ static void convert_to_work(json_t *val, bool rolltime, struct pool *pool)
 	 * allows testwork to know whether LP discovered the block or not. */
 	test_work_current(work);
 
-	/* Don't use backup LPs as work if we have failover-only enabled */
-	if (pool != current_pool() && opt_fail_only) {
+	/* Don't use backup LPs as work if we have failover-only enabled. Use
+	 * the longpoll work from a pool that has been rejecting shares as a
+	 * way to detect when the pool has recovered.
+	 */
+	if (pool != current_pool() && opt_fail_only && pool->enabled != POOL_REJECTING) {
 		free_work(work);
 		return;
 	}
@@ -4058,8 +4091,9 @@ static void *watchpool_thread(void __maybe_unused *userdata)
 		for (i = 0; i < total_pools; i++) {
 			struct pool *pool = pools[i];
 
-			reap_curl(pool);
-			if (!pool->enabled)
+			if (!opt_benchmark)
+				reap_curl(pool);
+			if (pool->enabled != POOL_ENABLED)
 				continue;
 
 			/* Test pool is idle once every minute */
@@ -4408,7 +4442,7 @@ int add_pool_details(bool live, char *url, char *user, char *pass)
 
 	/* Test the pool is not idle if we're live running, otherwise
 	 * it will be tested separately */
-	pool->enabled = true;
+	pool->enabled = POOL_ENABLED;
 	if (live && !pool_active(pool, false))
 		pool->idle = true;
 
@@ -4728,7 +4762,7 @@ int main(int argc, char *argv[])
 		strcpy(pool->rpc_url, "Benchmark");
 		pool->rpc_user = pool->rpc_url;
 		pool->rpc_pass = pool->rpc_url;
-		pool->enabled = true;
+		pool->enabled = POOL_ENABLED;
 		pool->idle = false;
 		successful_connect = true;
 	}
@@ -4957,7 +4991,7 @@ int main(int argc, char *argv[])
 	for (i = 0; i < total_pools; i++) {
 		struct pool *pool  = pools[i];
 
-		pool->enabled = true;
+		pool->enabled = POOL_ENABLED;
 		pool->idle = true;
 	}
 
diff --git a/driver-icarus.c b/driver-icarus.c
index 7a7ec49..47b0b16 100644
--- a/driver-icarus.c
+++ b/driver-icarus.c
@@ -72,12 +72,8 @@
 // 2 x 11.1 / (5.26 x 10^-9)
 //#define ESTIMATE_HASHES	0xFB90365E
 
-// This is the 8s value but causes hash rate loss
-//#define ESTIMATE_HASHES	0xB54E9147
-
-// TODO: determine why returning any other value when no nonce is found
-//	causes hash rate loss
-#define ESTIMATE_HASHES	0xffffffff
+// This is the 8s value
+#define ESTIMATE_HASHES	0xB54E9147
 
 struct device_api icarus_api;
 
@@ -353,6 +349,7 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 	if (opt_debug)
 		gettimeofday(&tv_finish, NULL);
 
+	work->blk.nonce = 0xffffffff;
 	memcpy((char *)&nonce, nonce_bin, sizeof(nonce_bin));
 
 	// aborted before becoming idle, get new work
@@ -369,7 +366,6 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 	nonce = swab32(nonce);
 #endif
 
-	work->blk.nonce = 0xffffffff;
 	submit_nonce(thr, work, nonce);
 
 	if (opt_debug) {
diff --git a/miner.h b/miner.h
index 27decf2..a965ecc 100644
--- a/miner.h
+++ b/miner.h
@@ -604,6 +604,12 @@ struct curl_ent {
 	struct timeval tv;
 };
 
+enum pool_enable {
+	POOL_ENABLED,
+	POOL_DISABLED,
+	POOL_REJECTING,
+};
+
 struct pool {
 	int pool_no;
 	int prio;
@@ -614,7 +620,7 @@ struct pool {
 	bool idle;
 	bool lagging;
 	bool probed;
-	bool enabled;
+	enum pool_enable enabled;
 	bool submit_old;
 	bool removed;
 	bool lp_started;
@@ -645,6 +651,8 @@ struct pool {
 	int curls;
 	pthread_cond_t cr_cond;
 	struct list_head curlring;
+
+	time_t last_share_time;
 };
 
 struct work {