Browse Source

Give each proxy an enonce1 union and cap the handout of enonce1 values without repeating, assuming we will recruit more proxied connections upstream to compensate

master
Con Kolivas 10 years ago
parent
commit
08e47d28cf
  1. 101
      src/stratifier.c

101
src/stratifier.c

@ -287,6 +287,14 @@ struct share {
typedef struct share share_t; typedef struct share share_t;
/* Variable length enonce1 always refers back to a u64 */
typedef union {
uint64_t u64;
uint32_t u32;
uint16_t u16;
uint8_t u8;
} enonce1_t;
struct proxy_base { struct proxy_base {
UT_hash_handle hh; UT_hash_handle hh;
int id; int id;
@ -304,6 +312,10 @@ struct proxy_base {
bool subscribed; bool subscribed;
bool notified; bool notified;
int64_t clients;
int64_t max_clients;
enonce1_t enonce1u;
}; };
typedef struct proxy_base proxy_t; typedef struct proxy_base proxy_t;
@ -321,13 +333,7 @@ struct stratifier_data {
bool ckdb_offline; bool ckdb_offline;
/* Variable length enonce1 always refers back to a u64 */ enonce1_t enonce1u;
union {
uint64_t u64;
uint32_t u32;
uint16_t u16;
uint8_t u8;
} enonce1u;
/* For protecting the hashtable data */ /* For protecting the hashtable data */
cklock_t workbase_lock; cklock_t workbase_lock;
@ -1083,13 +1089,16 @@ static void update_subscribe(ckpool_t *ckp, const char *cmd)
proxy->enonce1varlen = 4; proxy->enonce1varlen = 4;
else if (proxy->nonce2len > 5) else if (proxy->nonce2len > 5)
proxy->enonce1varlen = 2; proxy->enonce1varlen = 2;
else else if (proxy->nonce2len > 3)
proxy->enonce1varlen = 1; proxy->enonce1varlen = 1;
else
proxy->enonce1varlen = 0;
proxy->enonce2varlen = proxy->nonce2len - proxy->enonce1varlen; proxy->enonce2varlen = proxy->nonce2len - proxy->enonce1varlen;
proxy->max_clients = 1ll << (proxy->enonce1varlen * 8);
ck_wunlock(&sdata->workbase_lock); ck_wunlock(&sdata->workbase_lock);
LOGNOTICE("Upstream pool extranonce2 length %d, max proxy clients %lld", LOGNOTICE("Upstream pool extranonce2 length %d, max proxy clients %"PRId64,
proxy->nonce2len, 1ll << (proxy->enonce1varlen * 8)); proxy->nonce2len, proxy->max_clients);
json_decref(val); json_decref(val);
} }
@ -1985,34 +1994,15 @@ static void *blockupdate(void *arg)
return NULL; return NULL;
} }
/* Enter holding instance_lock */
static bool __enonce1_free(sdata_t *sdata, const uint64_t enonce1)
{
stratum_instance_t *client, *tmp;
bool ret = true;
if (unlikely(!enonce1)) {
ret = false;
goto out;
}
HASH_ITER(hh, sdata->stratum_instances, client, tmp) {
if (client->enonce1_64 == enonce1) {
ret = false;
break;
}
}
out:
return ret;
}
/* Enter holding workbase_lock and client a ref count. */ /* Enter holding workbase_lock and client a ref count. */
static void __fill_enonce1data(const workbase_t *wb, stratum_instance_t *client) static void __fill_enonce1data(const workbase_t *wb, stratum_instance_t *client)
{ {
if (wb->enonce1constlen) if (wb->enonce1constlen)
memcpy(client->enonce1bin, wb->enonce1constbin, wb->enonce1constlen); memcpy(client->enonce1bin, wb->enonce1constbin, wb->enonce1constlen);
if (wb->enonce1varlen) {
memcpy(client->enonce1bin + wb->enonce1constlen, &client->enonce1_64, wb->enonce1varlen); memcpy(client->enonce1bin + wb->enonce1constlen, &client->enonce1_64, wb->enonce1varlen);
__bin2hex(client->enonce1var, &client->enonce1_64, wb->enonce1varlen); __bin2hex(client->enonce1var, &client->enonce1_64, wb->enonce1varlen);
}
__bin2hex(client->enonce1, client->enonce1bin, wb->enonce1constlen + wb->enonce1varlen); __bin2hex(client->enonce1, client->enonce1bin, wb->enonce1constlen + wb->enonce1varlen);
} }
@ -2023,17 +2013,28 @@ static void __fill_enonce1data(const workbase_t *wb, stratum_instance_t *client)
* Needs to be entered with client holding a ref count. */ * Needs to be entered with client holding a ref count. */
static bool new_enonce1(sdata_t *sdata, stratum_instance_t *client) static bool new_enonce1(sdata_t *sdata, stratum_instance_t *client)
{ {
int enonce1varlen, i; proxy_t *proxy = NULL;
enonce1_t *enonce1u;
int enonce1varlen;
bool ret = false; bool ret = false;
if (client->ckp->proxy) { if (client->ckp->proxy) {
if (!sdata->proxy) if (!sdata->proxy)
return false; return false;
mutex_lock(&sdata->proxy_lock); mutex_lock(&sdata->proxy_lock);
client->proxyid = sdata->proxy->id; proxy = sdata->proxy;
client->subproxyid = sdata->proxy->subid; enonce1u = &proxy->enonce1u;
client->proxyid = proxy->id;
client->subproxyid = proxy->subid;
mutex_unlock(&sdata->proxy_lock); mutex_unlock(&sdata->proxy_lock);
if (proxy->clients >= proxy->max_clients) {
LOGWARNING("Proxy reached max clients %"PRId64, proxy->max_clients);
return false;
} }
} else
enonce1u = &sdata->enonce1u;
/* Extract the enonce1varlen from the current workbase which may be /* Extract the enonce1varlen from the current workbase which may be
* a different workbase to when we __fill_enonce1data but the value * a different workbase to when we __fill_enonce1data but the value
@ -2042,42 +2043,42 @@ static bool new_enonce1(sdata_t *sdata, stratum_instance_t *client)
enonce1varlen = sdata->current_workbase->enonce1varlen; enonce1varlen = sdata->current_workbase->enonce1varlen;
ck_runlock(&sdata->workbase_lock); ck_runlock(&sdata->workbase_lock);
/* instance_lock protects sdata->enonce1u */ /* instance_lock protects enonce1u. Recruiting extra proxies should
* prevent these ever locking out.*/
ck_wlock(&sdata->instance_lock); ck_wlock(&sdata->instance_lock);
switch(enonce1varlen) { switch(enonce1varlen) {
case 8: case 8:
sdata->enonce1u.u64++; enonce1u->u64++;
ret = true; ret = true;
break; break;
case 7: case 7:
case 6: case 6:
case 5: case 5:
case 4: case 4:
sdata->enonce1u.u32++; enonce1u->u32++;
ret = true; ret = true;
break; break;
case 3: case 3:
case 2: case 2:
for (i = 0; i < 65536; i++) { enonce1u->u16++;
sdata->enonce1u.u16++; ret = true;
ret = __enonce1_free(sdata, sdata->enonce1u.u64);
if (ret)
break;
}
break; break;
case 1: case 1:
for (i = 0; i < 256; i++) { enonce1u->u8++;
sdata->enonce1u.u8++; ret = true;
ret = __enonce1_free(sdata, sdata->enonce1u.u64);
if (ret)
break; break;
} case 0:
/* Only one client/enonce1 used on this proxy */
ret = true;
break; break;
default: default:
quit(0, "Invalid enonce1varlen %d", enonce1varlen); quit(0, "Invalid enonce1varlen %d", enonce1varlen);
} }
if (ret) if (ret) {
client->enonce1_64 = sdata->enonce1u.u64; if (proxy)
proxy->clients++;
client->enonce1_64 = enonce1u->u64;
}
ck_wunlock(&sdata->instance_lock); ck_wunlock(&sdata->instance_lock);
ck_rlock(&sdata->workbase_lock); ck_rlock(&sdata->workbase_lock);

Loading…
Cancel
Save