|
|
@ -2081,19 +2081,25 @@ static int64_t prio_sort(proxy_t *a, proxy_t *b) |
|
|
|
return (a->priority - b->priority); |
|
|
|
return (a->priority - b->priority); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Masked increment */ |
|
|
|
|
|
|
|
static int64_t masked_inc(int64_t value, int64_t mask) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
value &= ~mask; |
|
|
|
|
|
|
|
value++; |
|
|
|
|
|
|
|
value |= mask; |
|
|
|
|
|
|
|
return value; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Priority values can be sparse, they do not need to be sequential */ |
|
|
|
/* Priority values can be sparse, they do not need to be sequential */ |
|
|
|
static void __set_proxy_prio(sdata_t *sdata, proxy_t *proxy, int64_t priority) |
|
|
|
static void __set_proxy_prio(sdata_t *sdata, proxy_t *proxy, int64_t priority) |
|
|
|
{ |
|
|
|
{ |
|
|
|
proxy_t *tmpa, *tmpb, *exists = NULL; |
|
|
|
proxy_t *tmpa, *tmpb, *exists = NULL; |
|
|
|
int64_t next_prio = 0; |
|
|
|
int64_t mask, next_prio = 0; |
|
|
|
|
|
|
|
|
|
|
|
/* Encode the userid as the high bits in priority */ |
|
|
|
/* Encode the userid as the high bits in priority */ |
|
|
|
if (!proxy->global) { |
|
|
|
mask = proxy->userid; |
|
|
|
int64_t high_bits = proxy->userid; |
|
|
|
mask <<= 32; |
|
|
|
|
|
|
|
priority |= mask; |
|
|
|
high_bits <<= 32; |
|
|
|
|
|
|
|
priority |= high_bits; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* See if the priority is already in use */ |
|
|
|
/* See if the priority is already in use */ |
|
|
|
HASH_ITER(hh, sdata->proxies, tmpa, tmpb) { |
|
|
|
HASH_ITER(hh, sdata->proxies, tmpa, tmpb) { |
|
|
@ -2101,7 +2107,7 @@ static void __set_proxy_prio(sdata_t *sdata, proxy_t *proxy, int64_t priority) |
|
|
|
break; |
|
|
|
break; |
|
|
|
if (tmpa->priority == priority) { |
|
|
|
if (tmpa->priority == priority) { |
|
|
|
exists = tmpa; |
|
|
|
exists = tmpa; |
|
|
|
next_prio = exists->priority + 1; |
|
|
|
next_prio = masked_inc(priority, mask); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -2109,7 +2115,7 @@ static void __set_proxy_prio(sdata_t *sdata, proxy_t *proxy, int64_t priority) |
|
|
|
HASH_ITER(hh, exists, tmpa, tmpb) { |
|
|
|
HASH_ITER(hh, exists, tmpa, tmpb) { |
|
|
|
if (tmpa->priority > next_prio) |
|
|
|
if (tmpa->priority > next_prio) |
|
|
|
break; |
|
|
|
break; |
|
|
|
tmpa->priority++; |
|
|
|
tmpa->priority = masked_inc(tmpa->priority, mask); |
|
|
|
next_prio++; |
|
|
|
next_prio++; |
|
|
|
} |
|
|
|
} |
|
|
|
proxy->priority = priority; |
|
|
|
proxy->priority = priority; |
|
|
@ -2225,11 +2231,16 @@ static proxy_t *existing_subproxy(sdata_t *sdata, const int id, const int subid) |
|
|
|
return subproxy; |
|
|
|
return subproxy; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void check_userproxies(sdata_t *sdata, proxy_t *proxy, const int userid); |
|
|
|
|
|
|
|
|
|
|
|
static void set_proxy_prio(sdata_t *sdata, proxy_t *proxy, const int priority) |
|
|
|
static void set_proxy_prio(sdata_t *sdata, proxy_t *proxy, const int priority) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mutex_lock(&sdata->proxy_lock); |
|
|
|
mutex_lock(&sdata->proxy_lock); |
|
|
|
__set_proxy_prio(sdata, proxy, priority); |
|
|
|
__set_proxy_prio(sdata, proxy, priority); |
|
|
|
mutex_unlock(&sdata->proxy_lock); |
|
|
|
mutex_unlock(&sdata->proxy_lock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!proxy->global) |
|
|
|
|
|
|
|
check_userproxies(sdata, proxy, proxy->userid); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Set proxy to the current proxy and calculate how much headroom it has */ |
|
|
|
/* Set proxy to the current proxy and calculate how much headroom it has */ |
|
|
@ -2290,7 +2301,7 @@ static void generator_recruit(const ckpool_t *ckp, const int proxyid, const int |
|
|
|
/* Find how much headroom we have and connect up to that many clients that are
|
|
|
|
/* Find how much headroom we have and connect up to that many clients that are
|
|
|
|
* not currently on this pool, recruiting more slots to switch more clients |
|
|
|
* not currently on this pool, recruiting more slots to switch more clients |
|
|
|
* later on lazily. Only reconnect clients bound to global proxies. */ |
|
|
|
* later on lazily. Only reconnect clients bound to global proxies. */ |
|
|
|
static void reconnect_clients(sdata_t *sdata) |
|
|
|
static void reconnect_global_clients(sdata_t *sdata) |
|
|
|
{ |
|
|
|
{ |
|
|
|
stratum_instance_t *client, *tmpclient; |
|
|
|
stratum_instance_t *client, *tmpclient; |
|
|
|
int reconnects = 0; |
|
|
|
int reconnects = 0; |
|
|
@ -2372,6 +2383,32 @@ static void check_bestproxy(sdata_t *sdata) |
|
|
|
LOGNOTICE("Stratifier setting active proxy to %d", changed_id); |
|
|
|
LOGNOTICE("Stratifier setting active proxy to %d", changed_id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static proxy_t *best_proxy(sdata_t *sdata) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
proxy_t *proxy; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&sdata->proxy_lock); |
|
|
|
|
|
|
|
proxy = sdata->proxy; |
|
|
|
|
|
|
|
mutex_unlock(&sdata->proxy_lock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return proxy; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void check_globalproxies(sdata_t *sdata, proxy_t *proxy) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
check_bestproxy(sdata); |
|
|
|
|
|
|
|
if (proxy->parent == best_proxy(sdata)->parent) |
|
|
|
|
|
|
|
reconnect_global_clients(sdata); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void check_proxy(sdata_t *sdata, proxy_t *proxy) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (proxy->global) |
|
|
|
|
|
|
|
check_globalproxies(sdata, proxy); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
check_userproxies(sdata, proxy, proxy->userid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void dead_proxyid(sdata_t *sdata, const int id, const int subid, const bool replaced, const bool deleted) |
|
|
|
static void dead_proxyid(sdata_t *sdata, const int id, const int subid, const bool replaced, const bool deleted) |
|
|
|
{ |
|
|
|
{ |
|
|
|
stratum_instance_t *client, *tmp; |
|
|
|
stratum_instance_t *client, *tmp; |
|
|
@ -2383,6 +2420,7 @@ static void dead_proxyid(sdata_t *sdata, const int id, const int subid, const bo |
|
|
|
if (proxy) { |
|
|
|
if (proxy) { |
|
|
|
proxy->dead = true; |
|
|
|
proxy->dead = true; |
|
|
|
proxy->deleted = deleted; |
|
|
|
proxy->deleted = deleted; |
|
|
|
|
|
|
|
set_proxy_prio(sdata, proxy, 0xFFFF); |
|
|
|
if (!replaced && proxy->global) |
|
|
|
if (!replaced && proxy->global) |
|
|
|
check_bestproxy(sdata); |
|
|
|
check_bestproxy(sdata); |
|
|
|
} |
|
|
|
} |
|
|
@ -2516,6 +2554,8 @@ static void update_subscribe(ckpool_t *ckp, const char *cmd) |
|
|
|
LOGWARNING("Only able to set nonce2len %d of requested %d on proxy %d:%d", |
|
|
|
LOGWARNING("Only able to set nonce2len %d of requested %d on proxy %d:%d", |
|
|
|
proxy->enonce2varlen, ckp->nonce2length, id, subid); |
|
|
|
proxy->enonce2varlen, ckp->nonce2length, id, subid); |
|
|
|
json_decref(val); |
|
|
|
json_decref(val); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
check_proxy(sdata, proxy); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Find the highest priority alive proxy belonging to userid and recruit extra
|
|
|
|
/* Find the highest priority alive proxy belonging to userid and recruit extra
|
|
|
@ -2544,7 +2584,7 @@ static void recruit_best_userproxy(sdata_t *sdata, const int userid, const int r |
|
|
|
|
|
|
|
|
|
|
|
/* Check how much headroom the userid proxies have and reconnect any clients
|
|
|
|
/* Check how much headroom the userid proxies have and reconnect any clients
|
|
|
|
* that are not bound to it that should be */ |
|
|
|
* that are not bound to it that should be */ |
|
|
|
static void check_userproxies(sdata_t *sdata, const int userid) |
|
|
|
static void check_userproxies(sdata_t *sdata, proxy_t *proxy, const int userid) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int64_t headroom = proxy_headroom(sdata, userid); |
|
|
|
int64_t headroom = proxy_headroom(sdata, userid); |
|
|
|
stratum_instance_t *client, *tmpclient; |
|
|
|
stratum_instance_t *client, *tmpclient; |
|
|
@ -2558,8 +2598,10 @@ static void check_userproxies(sdata_t *sdata, const int userid) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
if (client->user_id != userid) |
|
|
|
if (client->user_id != userid) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
/* Is this client bound to a dead proxy? */ |
|
|
|
/* Is the client already bound to a proxy of its own userid of
|
|
|
|
if (!client->reconnect && client->proxy->userid == userid) |
|
|
|
* a higher priority than this one. */ |
|
|
|
|
|
|
|
if (client->proxy->userid == userid && |
|
|
|
|
|
|
|
client->proxy->parent->priority <= proxy->parent->priority) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
if (headroom-- < 1) |
|
|
|
if (headroom-- < 1) |
|
|
|
continue; |
|
|
|
continue; |
|
|
@ -2576,17 +2618,6 @@ static void check_userproxies(sdata_t *sdata, const int userid) |
|
|
|
recruit_best_userproxy(sdata, userid, -headroom); |
|
|
|
recruit_best_userproxy(sdata, userid, -headroom); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static proxy_t *best_proxy(sdata_t *sdata) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
proxy_t *proxy; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&sdata->proxy_lock); |
|
|
|
|
|
|
|
proxy = sdata->proxy; |
|
|
|
|
|
|
|
mutex_unlock(&sdata->proxy_lock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return proxy; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void update_notify(ckpool_t *ckp, const char *cmd) |
|
|
|
static void update_notify(ckpool_t *ckp, const char *cmd) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sdata_t *sdata = ckp->sdata, *dsdata; |
|
|
|
sdata_t *sdata = ckp->sdata, *dsdata; |
|
|
@ -2676,12 +2707,7 @@ static void update_notify(ckpool_t *ckp, const char *cmd) |
|
|
|
LOGNOTICE("Block hash on proxy %d changed to %s", id, dsdata->lastswaphash); |
|
|
|
LOGNOTICE("Block hash on proxy %d changed to %s", id, dsdata->lastswaphash); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (proxy->global) { |
|
|
|
check_proxy(sdata, proxy); |
|
|
|
check_bestproxy(sdata); |
|
|
|
|
|
|
|
if (proxy->parent != best_proxy(sdata)->parent) |
|
|
|
|
|
|
|
reconnect_clients(sdata); |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
check_userproxies(sdata, proxy->userid); |
|
|
|
|
|
|
|
clean |= new_block; |
|
|
|
clean |= new_block; |
|
|
|
LOGINFO("Proxy %d:%d broadcast updated stratum notify with%s clean", id, |
|
|
|
LOGINFO("Proxy %d:%d broadcast updated stratum notify with%s clean", id, |
|
|
|
subid, clean ? "" : "out"); |
|
|
|
subid, clean ? "" : "out"); |
|
|
@ -4355,19 +4381,16 @@ static proxy_t *__best_subproxy(proxy_t *proxy) |
|
|
|
* running out of room. */ |
|
|
|
* running out of room. */ |
|
|
|
static sdata_t *select_sdata(const ckpool_t *ckp, sdata_t *ckp_sdata, const int userid) |
|
|
|
static sdata_t *select_sdata(const ckpool_t *ckp, sdata_t *ckp_sdata, const int userid) |
|
|
|
{ |
|
|
|
{ |
|
|
|
proxy_t *current, *proxy, *tmp, *best = NULL; |
|
|
|
proxy_t *global, *proxy, *tmp, *best = NULL; |
|
|
|
|
|
|
|
|
|
|
|
if (!ckp->proxy || ckp->passthrough) |
|
|
|
if (!ckp->proxy || ckp->passthrough) |
|
|
|
return ckp_sdata; |
|
|
|
return ckp_sdata; |
|
|
|
current = ckp_sdata->proxy; |
|
|
|
|
|
|
|
if (!current) { |
|
|
|
|
|
|
|
LOGWARNING("No proxy available yet to generate subscribes"); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Proxies are ordered by priority so first available will be the best
|
|
|
|
/* Proxies are ordered by priority so first available will be the best
|
|
|
|
* priority */ |
|
|
|
* priority */ |
|
|
|
mutex_lock(&ckp_sdata->proxy_lock); |
|
|
|
mutex_lock(&ckp_sdata->proxy_lock); |
|
|
|
|
|
|
|
best = global = ckp_sdata->proxy; |
|
|
|
|
|
|
|
|
|
|
|
HASH_ITER(hh, ckp_sdata->proxies, proxy, tmp) { |
|
|
|
HASH_ITER(hh, ckp_sdata->proxies, proxy, tmp) { |
|
|
|
if (proxy->userid < userid) |
|
|
|
if (proxy->userid < userid) |
|
|
|
continue; |
|
|
|
continue; |
|
|
@ -4381,12 +4404,14 @@ static sdata_t *select_sdata(const ckpool_t *ckp, sdata_t *ckp_sdata, const int |
|
|
|
|
|
|
|
|
|
|
|
if (!best) { |
|
|
|
if (!best) { |
|
|
|
if (!userid) |
|
|
|
if (!userid) |
|
|
|
LOGWARNING("Temporarily insufficient subproxies to accept more clients"); |
|
|
|
LOGWARNING("Temporarily insufficient proxies to accept more clients"); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
LOGNOTICE("Temporarily insufficient proxies for userid %d to accept more clients", userid); |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!userid) { |
|
|
|
if (!userid) { |
|
|
|
if (best->id != current->id || current_headroom(ckp_sdata, &proxy) < 2) |
|
|
|
if (best->id != global->id || current_headroom(ckp_sdata, &proxy) < 2) |
|
|
|
generator_recruit(ckp, current->id, 1); |
|
|
|
generator_recruit(ckp, global->id, 1); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if (proxy_headroom(ckp_sdata, userid) < 2) |
|
|
|
if (proxy_headroom(ckp_sdata, userid) < 2) |
|
|
|
generator_recruit(ckp, best->id, 1); |
|
|
|
generator_recruit(ckp, best->id, 1); |
|
|
|