Expire shares as stale with a separate timeout from the scantime, defaulting to 120 seconds.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
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);