diff --git a/README b/README index 4fadbcfd..54eb7960 100644 --- a/README +++ b/README @@ -517,9 +517,9 @@ If all pools are set to zero quota or all pools with quota are dead, it will fall back to a failover mode. See quota below for more information. The failover-only flag has special meaning in combination with load-balance -mode and it will distribute quota back to pool 0 from any pools that are -unable to provide work for any reason so as to maintain quota ratios between -the rest of the pools. +mode and it will distribute quota back to priority pool 0 from any pools that +are unable to provide work for any reason so as to maintain quota ratios +between the rest of the pools. BALANCE: This strategy monitors the amount of difficulty 1 shares solved for each pool diff --git a/api.c b/api.c index cc769ab0..e962bb00 100644 --- a/api.c +++ b/api.c @@ -2661,6 +2661,7 @@ static void poolquota(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } pool->quota = quota; + adjust_quota_gcd(); message(io_data, MSG_SETQUOTA, quota, pool->rpc_url, isjson); } diff --git a/cgminer.c b/cgminer.c index 5c5d1f94..de5c6f48 100644 --- a/cgminer.c +++ b/cgminer.c @@ -100,6 +100,7 @@ int opt_scantime = -1; int opt_expiry = 120; static const bool opt_time = true; unsigned long long global_hashrate; +unsigned long global_quota_gcd = 1; #if defined(HAVE_OPENCL) || defined(USE_USBUTILS) int nDevs; @@ -488,6 +489,47 @@ static char *getwork_req = "{\"method\": \"getwork\", \"params\": [], \"id\":0}\ static char *gbt_req = "{\"id\": 0, \"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": [\"coinbasetxn\", \"workid\", \"coinbase/append\"]}]}\n"; +/* Adjust all the pools' quota to the greatest common denominator after a pool + * has been added or the quotas changed. */ +void adjust_quota_gcd(void) +{ + unsigned long gcd, lowest_quota = ~0UL, quota; + struct pool *pool; + int i; + + for (i = 0; i < total_pools; i++) { + pool = pools[i]; + quota = pool->quota; + if (!quota) + continue; + if (quota < lowest_quota) + lowest_quota = quota; + } + + if (likely(lowest_quota < ~0UL)) { + gcd = lowest_quota; + for (i = 0; i < total_pools; i++) { + pool = pools[i]; + quota = pool->quota; + if (!quota) + continue; + while (quota % gcd) + gcd--; + } + } else + gcd = 1; + + for (i = 0; i < total_pools; i++) { + pool = pools[i]; + pool->quota_used *= global_quota_gcd; + pool->quota_used /= gcd; + pool->quota_gcd = pool->quota / gcd; + } + + global_quota_gcd = gcd; + applog(LOG_DEBUG, "Global quota greatest common denominator set to %lu", gcd); +} + /* Return value is ignored if not called from add_pool_details */ struct pool *add_pool(void) { @@ -513,6 +555,7 @@ struct pool *add_pool(void) pool->rpc_req = getwork_req; pool->rpc_proxy = NULL; pool->quota = 1; + adjust_quota_gcd(); return pool; } @@ -759,6 +802,7 @@ static char *set_quota(char *arg) setup_url(pool, url); pool->quota = quota; applog(LOG_INFO, "Setting pool %d to quota %d", pool->pool_no, pool->quota); + adjust_quota_gcd(); return NULL; } @@ -2840,16 +2884,16 @@ static inline struct pool *select_pool(bool lagging) tested = 0; while (!pool && tested++ < total_pools) { pool = pools[rotating_pool]; - if (pool->quota_used++ >= pool->quota) { + if (pool->quota_used++ >= pool->quota_gcd) { pool->quota_used = 0; pool = NULL; } else { if (!pool_unworkable(pool)) break; /* Failover-only flag for load-balance means distribute - * unused quota to pool 0. */ + * unused quota to priority pool 0. */ if (opt_fail_only) - pools[0]->quota++; + priority_pool(0)->quota_used--; } pool = NULL; if (++rotating_pool >= total_pools) @@ -4547,6 +4591,7 @@ retry: goto retry; } pool->quota = selected; + adjust_quota_gcd(); goto updated; } else if (!strncasecmp(&input, "f", 1)) { opt_fail_only ^= true; diff --git a/miner.h b/miner.h index 4fc863b3..2f5fc660 100644 --- a/miner.h +++ b/miner.h @@ -973,6 +973,7 @@ extern int enabled_pools; extern void get_intrange(char *arg, int *val1, int *val2); extern bool detect_stratum(struct pool *pool, char *url); extern void print_summary(void); +extern void adjust_quota_gcd(void); extern struct pool *add_pool(void); extern bool add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass); @@ -1121,6 +1122,7 @@ struct pool { int diff1; char diff[8]; int quota; + int quota_gcd; int quota_used; double diff_accepted;