diff --git a/api.c b/api.c index 8571dccd..1bf9b2b7 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 26259c6e..b2bcd5ae 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 7a7ec494..47b0b164 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 27decf2d..a965ecc9 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 {