Commit 9087345f84825b8f43e69e0226916fc483b8c27e

Con Kolivas 2011-09-29T10:27:32

Expire shares as stale with a separate timeout from the scantime, defaulting to 120 seconds.

diff --git a/README b/README
index c8adb5e..e57500b 100644
--- a/README
+++ b/README
@@ -126,6 +126,7 @@ Options for both config file and command line:
 --disable-gpu|-G    Disable GPU mining even if suitable devices exist
 --donation <arg>    Set donation percentage to cgminer author (0.0 - 99.9) (default: 0.0)
 --enable-cpu|-C     Enable CPU mining with GPU mining (default: no CPU mining if suitable GPUs exist)
+--expiry|-E <arg>   Upper bound on how many seconds after getting work we consider a share from it stale (default: 120)
 --failover-only     Don't leak work to backup pools when primary pool is lagging
 --gpu-threads|-g <arg> Number of threads per GPU (1 - 10) (default: 2)
 --gpu-engine <arg>  GPU engine (over)clock range in Mhz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)
diff --git a/main.c b/main.c
index 3b5ff8c..cdbd804 100644
--- a/main.c
+++ b/main.c
@@ -195,6 +195,7 @@ static int opt_queue = 1;
 int opt_vectors;
 int opt_worksize;
 int opt_scantime = 60;
+int opt_expiry = 120;
 int opt_bench_algo = -1;
 static const bool opt_time = true;
 static bool opt_restart = true;
@@ -1484,6 +1485,11 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--enable-cpu|-C",
 			opt_set_bool, &opt_usecpu,
 			"Enable CPU mining with GPU mining (default: no CPU mining if suitable GPUs exist)"),
+#endif
+	OPT_WITH_ARG("--expiry|-E",
+		     set_int_0_to_9999, opt_show_intval, &opt_expiry,
+		     "Upper bound on how many seconds after getting work we consider a share from it stale"),
+#ifdef HAVE_OPENCL
 	OPT_WITHOUT_ARG("--failover-only",
 			opt_set_bool, &opt_fail_only,
 			"Don't leak work to backup pools when primary pool is lagging"),
@@ -2492,14 +2498,17 @@ static bool workio_get_work(struct workio_cmd *wc)
 	return true;
 }
 
-static bool stale_work(struct work *work)
+static bool stale_work(struct work *work, bool share)
 {
 	struct timeval now;
 	bool ret = false;
 	char *hexstr;
 
 	gettimeofday(&now, NULL);
-	if ((now.tv_sec - work->tv_staged.tv_sec) >= opt_scantime)
+	if (share) {
+		if ((now.tv_sec - work->tv_staged.tv_sec) >= opt_expiry)
+			return true;
+	} else if ((now.tv_sec - work->tv_staged.tv_sec) >= opt_scantime)
 		return true;
 
 	/* Don't compare donor work in case it's on a different chain */
@@ -2528,7 +2537,7 @@ static void *submit_work_thread(void *userdata)
 
 	pthread_detach(pthread_self());
 
-	if (!opt_submit_stale && stale_work(work)) {
+	if (!opt_submit_stale && stale_work(work, true)) {
 		applog(LOG_NOTICE, "Stale share detected, discarding");
 		total_stale++;
 		pool->stale_shares++;
@@ -2537,7 +2546,7 @@ static void *submit_work_thread(void *userdata)
 
 	/* submit solution to bitcoin via JSON-RPC */
 	while (!submit_upstream_work(work)) {
-		if (!opt_submit_stale && stale_work(work)) {
+		if (!opt_submit_stale && stale_work(work, true)) {
 			applog(LOG_NOTICE, "Stale share detected, discarding");
 			total_stale++;
 			pool->stale_shares++;
@@ -2708,7 +2717,7 @@ static int discard_stale(void)
 
 	mutex_lock(stgd_lock);
 	HASH_ITER(hh, staged_work, work, tmp) {
-		if (stale_work(work)) {
+		if (stale_work(work, false)) {
 			HASH_DEL(staged_work, work);
 			if (work->clone)
 				--staged_clones;
@@ -3156,8 +3165,8 @@ static void set_options(void)
 	clear_logwin();
 retry:
 	wlogprint("\n[L]ongpoll: %s\n", want_longpoll ? "On" : "Off");
-	wlogprint("[Q]ueue: %d\n[S]cantime: %d\n[R]etries: %d\n[P]ause: %d\n",
-		opt_queue, opt_scantime, opt_retries, opt_fail_pause);
+	wlogprint("[Q]ueue: %d\n[S]cantime: %d\n[E]xpiry: %d\n[R]etries: %d\n[P]ause: %d\n",
+		opt_queue, opt_scantime, opt_expiry, opt_retries, opt_fail_pause);
 	wlogprint("Select an option or any other key to return\n");
 	input = getch();
 
@@ -3182,6 +3191,14 @@ retry:
 		}
 		opt_scantime = selected;
 		goto retry;
+	} else if  (!strncasecmp(&input, "e", 1)) {
+		selected = curses_int("Set expiry time in seconds");
+		if (selected < 0 || selected > 9999) {
+			wlogprint("Invalid selection\n");
+			goto retry;
+		}
+		opt_expiry = selected;
+		goto retry;
 	} else if  (!strncasecmp(&input, "r", 1)) {
 		selected = curses_int("Retries before failing (-1 infinite)");
 		if (selected < -1 || selected > 9999) {
@@ -3761,7 +3778,7 @@ static inline bool should_roll(struct work *work)
 
 static inline bool can_roll(struct work *work)
 {
-	return (work->pool && !stale_work(work) && work->rolltime &&
+	return (work->pool && !stale_work(work, false) && work->rolltime &&
 		work->rolls < 11 && !work->clone && !donor(work->pool));
 }
 
@@ -3858,7 +3875,7 @@ retry:
 		goto retry;
 	}
 
-	if (stale_work(work_heap)) {
+	if (stale_work(work_heap, false)) {
 		dec_queued();
 		discard_work(work_heap);
 		goto retry;
@@ -4145,7 +4162,7 @@ static void *miner_thread(void *userdata)
 			decay_time(&hash_divfloat , (double)((MAXTHREADS / total_hashes) ? : 1));
 			hash_div = hash_divfloat;
 			needs_work = true;
-		} else if (work_restart[thr_id].restart || stale_work(work) ||
+		} else if (work_restart[thr_id].restart || stale_work(work, false) ||
 			work->blk.nonce >= MAXTHREADS - hashes_done)
 				needs_work = true;
 
@@ -4384,7 +4401,7 @@ static void *gpuminer_thread(void *userdata)
 		if (diff.tv_sec > opt_scantime ||
 		    work->blk.nonce >= MAXTHREADS - hashes ||
 		    work_restart[thr_id].restart ||
-		    stale_work(work)) {
+		    stale_work(work, false)) {
 			/* Ignore any reads since we're getting new work and queue a clean buffer */
 			status = clEnqueueWriteBuffer(clState->commandQueue, clState->outputBuffer, CL_FALSE, 0,
 					BUFFERSIZE, blank_res, 0, NULL, NULL);