|
|
@ -313,10 +313,12 @@ struct stratifier_data { |
|
|
|
char lasthash[68]; |
|
|
|
char lasthash[68]; |
|
|
|
char lastswaphash[68]; |
|
|
|
char lastswaphash[68]; |
|
|
|
|
|
|
|
|
|
|
|
ckwq_t *ckwqs; // Generic workqueues
|
|
|
|
|
|
|
|
ckmsgq_t *ssends; // Stratum sends
|
|
|
|
ckmsgq_t *ssends; // Stratum sends
|
|
|
|
|
|
|
|
ckmsgq_t *srecvs; // Stratum receives
|
|
|
|
ckmsgq_t *ckdbq; // ckdb
|
|
|
|
ckmsgq_t *ckdbq; // ckdb
|
|
|
|
|
|
|
|
ckmsgq_t *sshareq; // Stratum share sends
|
|
|
|
ckmsgq_t *sauthq; // Stratum authorisations
|
|
|
|
ckmsgq_t *sauthq; // Stratum authorisations
|
|
|
|
|
|
|
|
ckmsgq_t *stxnq; // Transaction requests
|
|
|
|
|
|
|
|
|
|
|
|
int64_t user_instance_id; |
|
|
|
int64_t user_instance_id; |
|
|
|
|
|
|
|
|
|
|
@ -795,26 +797,38 @@ static void send_generator(ckpool_t *ckp, const char *msg, const int prio) |
|
|
|
set = true; |
|
|
|
set = true; |
|
|
|
} else |
|
|
|
} else |
|
|
|
set = false; |
|
|
|
set = false; |
|
|
|
async_send_proc(ckp, ckp->generator, msg); |
|
|
|
send_proc(ckp->generator, msg); |
|
|
|
if (set) |
|
|
|
if (set) |
|
|
|
sdata->gen_priority = 0; |
|
|
|
sdata->gen_priority = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct update_req { |
|
|
|
|
|
|
|
pthread_t *pth; |
|
|
|
|
|
|
|
ckpool_t *ckp; |
|
|
|
|
|
|
|
int prio; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void broadcast_ping(sdata_t *sdata); |
|
|
|
static void broadcast_ping(sdata_t *sdata); |
|
|
|
|
|
|
|
|
|
|
|
/* This function assumes it will only receive a valid json gbt base template
|
|
|
|
/* This function assumes it will only receive a valid json gbt base template
|
|
|
|
* since checking should have been done earlier, and creates the base template |
|
|
|
* since checking should have been done earlier, and creates the base template |
|
|
|
* for generating work templates. */ |
|
|
|
* for generating work templates. */ |
|
|
|
static void do_update(ckpool_t *ckp, int *prio) |
|
|
|
static void *do_update(void *arg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
struct update_req *ur = (struct update_req *)arg; |
|
|
|
|
|
|
|
ckpool_t *ckp = ur->ckp; |
|
|
|
sdata_t *sdata = ckp->data; |
|
|
|
sdata_t *sdata = ckp->data; |
|
|
|
bool new_block = false; |
|
|
|
bool new_block = false; |
|
|
|
|
|
|
|
int prio = ur->prio; |
|
|
|
bool ret = false; |
|
|
|
bool ret = false; |
|
|
|
workbase_t *wb; |
|
|
|
workbase_t *wb; |
|
|
|
json_t *val; |
|
|
|
json_t *val; |
|
|
|
char *buf; |
|
|
|
char *buf; |
|
|
|
|
|
|
|
|
|
|
|
buf = send_recv_generator(ckp, "getbase", *prio); |
|
|
|
pthread_detach(pthread_self()); |
|
|
|
|
|
|
|
rename_proc("updater"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf = send_recv_generator(ckp, "getbase", prio); |
|
|
|
if (unlikely(!buf)) { |
|
|
|
if (unlikely(!buf)) { |
|
|
|
LOGNOTICE("Get base in update_base delayed due to higher priority request"); |
|
|
|
LOGNOTICE("Get base in update_base delayed due to higher priority request"); |
|
|
|
goto out; |
|
|
|
goto out; |
|
|
@ -874,17 +888,21 @@ out: |
|
|
|
LOGINFO("Broadcast ping due to failed stratum base update"); |
|
|
|
LOGINFO("Broadcast ping due to failed stratum base update"); |
|
|
|
broadcast_ping(sdata); |
|
|
|
broadcast_ping(sdata); |
|
|
|
} |
|
|
|
} |
|
|
|
free(buf); |
|
|
|
dealloc(buf); |
|
|
|
free(prio); |
|
|
|
free(ur->pth); |
|
|
|
|
|
|
|
free(ur); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void update_base(ckpool_t *ckp, const int prio) |
|
|
|
static void update_base(ckpool_t *ckp, const int prio) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int *pprio = ckalloc(sizeof(int)); |
|
|
|
struct update_req *ur = ckalloc(sizeof(struct update_req)); |
|
|
|
sdata_t *sdata = ckp->data; |
|
|
|
pthread_t *pth = ckalloc(sizeof(pthread_t)); |
|
|
|
|
|
|
|
|
|
|
|
*pprio = prio; |
|
|
|
ur->pth = pth; |
|
|
|
ckwq_add(sdata->ckwqs, &do_update, pprio); |
|
|
|
ur->ckp = ckp; |
|
|
|
|
|
|
|
ur->prio = prio; |
|
|
|
|
|
|
|
create_pthread(pth, do_update, ur); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void __kill_instance(stratum_instance_t *client) |
|
|
|
static void __kill_instance(stratum_instance_t *client) |
|
|
@ -928,7 +946,7 @@ static void drop_allclients(ckpool_t *ckp) |
|
|
|
client->dropped = true; |
|
|
|
client->dropped = true; |
|
|
|
kills++; |
|
|
|
kills++; |
|
|
|
sprintf(buf, "dropclient=%"PRId64, client_id); |
|
|
|
sprintf(buf, "dropclient=%"PRId64, client_id); |
|
|
|
async_send_proc(ckp, ckp->connector, buf); |
|
|
|
send_proc(ckp->connector, buf); |
|
|
|
} |
|
|
|
} |
|
|
|
HASH_ITER(hh, sdata->disconnected_instances, client, tmp) { |
|
|
|
HASH_ITER(hh, sdata->disconnected_instances, client, tmp) { |
|
|
|
disconnects++; |
|
|
|
disconnects++; |
|
|
@ -1633,21 +1651,6 @@ static void ckmsgq_stats(ckmsgq_t *ckmsgq, const int size, json_t **val) |
|
|
|
JSON_CPACK(*val, "{si,si,si}", "count", objects, "memory", memsize, "generated", generated); |
|
|
|
JSON_CPACK(*val, "{si,si,si}", "count", objects, "memory", memsize, "generated", generated); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void ckwq_stats(ckwq_t *ckwq, const int size, json_t **val) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int objects, generated; |
|
|
|
|
|
|
|
int64_t memsize; |
|
|
|
|
|
|
|
ckwqmsg_t *wqmsg; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(ckwq->lock); |
|
|
|
|
|
|
|
DL_COUNT(ckwq->wqmsgs, wqmsg, objects); |
|
|
|
|
|
|
|
generated = ckwq->messages; |
|
|
|
|
|
|
|
mutex_unlock(ckwq->lock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memsize = (sizeof(ckwqmsg_t) + size) * objects; |
|
|
|
|
|
|
|
JSON_CPACK(*val, "{si,si,si}", "count", objects, "memory", memsize, "generated", generated); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *stratifier_stats(ckpool_t *ckp, sdata_t *sdata) |
|
|
|
static char *stratifier_stats(ckpool_t *ckp, sdata_t *sdata) |
|
|
|
{ |
|
|
|
{ |
|
|
|
json_t *val = json_object(), *subval; |
|
|
|
json_t *val = json_object(), *subval; |
|
|
@ -1694,14 +1697,15 @@ static char *stratifier_stats(ckpool_t *ckp, sdata_t *sdata) |
|
|
|
|
|
|
|
|
|
|
|
ckmsgq_stats(sdata->ssends, sizeof(smsg_t), &subval); |
|
|
|
ckmsgq_stats(sdata->ssends, sizeof(smsg_t), &subval); |
|
|
|
json_set_object(val, "ssends", subval); |
|
|
|
json_set_object(val, "ssends", subval); |
|
|
|
|
|
|
|
|
|
|
|
/* Don't know exactly how big the string is so just count the pointer for now */ |
|
|
|
/* Don't know exactly how big the string is so just count the pointer for now */ |
|
|
|
ckwq_stats(sdata->ckwqs, sizeof(char *) + sizeof(void *), &subval); |
|
|
|
ckmsgq_stats(sdata->srecvs, sizeof(char *), &subval); |
|
|
|
json_set_object(val, "ckwqs", subval); |
|
|
|
json_set_object(val, "srecvs", subval); |
|
|
|
if (!CKP_STANDALONE(ckp)) { |
|
|
|
if (!CKP_STANDALONE(ckp)) { |
|
|
|
ckmsgq_stats(sdata->ckdbq, sizeof(char *), &subval); |
|
|
|
ckmsgq_stats(sdata->ckdbq, sizeof(char *), &subval); |
|
|
|
json_set_object(val, "ckdbq", subval); |
|
|
|
json_set_object(val, "ckdbq", subval); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ckmsgq_stats(sdata->stxnq, sizeof(json_params_t), &subval); |
|
|
|
|
|
|
|
json_set_object(val, "stxnq", subval); |
|
|
|
|
|
|
|
|
|
|
|
buf = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); |
|
|
|
buf = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); |
|
|
|
json_decref(val); |
|
|
|
json_decref(val); |
|
|
@ -1709,8 +1713,6 @@ static char *stratifier_stats(ckpool_t *ckp, sdata_t *sdata) |
|
|
|
return buf; |
|
|
|
return buf; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void srecv_process(ckpool_t *ckp, char *buf); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int stratum_loop(ckpool_t *ckp, proc_instance_t *pi) |
|
|
|
static int stratum_loop(ckpool_t *ckp, proc_instance_t *pi) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int sockd, ret = 0, selret = 0; |
|
|
|
int sockd, ret = 0, selret = 0; |
|
|
@ -1765,7 +1767,7 @@ retry: |
|
|
|
/* The bulk of the messages will be received json from the
|
|
|
|
/* The bulk of the messages will be received json from the
|
|
|
|
* connector so look for this first. The srecv_process frees |
|
|
|
* connector so look for this first. The srecv_process frees |
|
|
|
* the buf heap ram */ |
|
|
|
* the buf heap ram */ |
|
|
|
ckwq_add(sdata->ckwqs, &srecv_process, buf); |
|
|
|
ckmsgq_add(sdata->srecvs, buf); |
|
|
|
Close(sockd); |
|
|
|
Close(sockd); |
|
|
|
buf = NULL; |
|
|
|
buf = NULL; |
|
|
|
goto retry; |
|
|
|
goto retry; |
|
|
@ -3287,14 +3289,10 @@ static void suggest_diff(stratum_instance_t *client, const char *method, const j |
|
|
|
stratum_send_diff(sdata, client); |
|
|
|
stratum_send_diff(sdata, client); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void sshare_process(ckpool_t *ckp, json_params_t *jp); |
|
|
|
|
|
|
|
static void send_transactions(ckpool_t *ckp, json_params_t *jp); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Enter with client holding ref count */ |
|
|
|
/* Enter with client holding ref count */ |
|
|
|
static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64_t client_id, |
|
|
|
static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64_t client_id, |
|
|
|
json_t *id_val, json_t *method_val, json_t *params_val, const char *address) |
|
|
|
json_t *id_val, json_t *method_val, json_t *params_val, const char *address) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ckpool_t *ckp = client->ckp; |
|
|
|
|
|
|
|
const char *method; |
|
|
|
const char *method; |
|
|
|
char buf[256]; |
|
|
|
char buf[256]; |
|
|
|
|
|
|
|
|
|
|
@ -3305,7 +3303,7 @@ static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64 |
|
|
|
if (likely(cmdmatch(method, "mining.submit") && client->authorised)) { |
|
|
|
if (likely(cmdmatch(method, "mining.submit") && client->authorised)) { |
|
|
|
json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); |
|
|
|
json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); |
|
|
|
|
|
|
|
|
|
|
|
ckwq_add(sdata->ckwqs, &sshare_process, jp); |
|
|
|
ckmsgq_add(sdata->sshareq, jp); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3340,7 +3338,7 @@ static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64 |
|
|
|
* to it since it's unauthorised. Set the flag just in case. */ |
|
|
|
* to it since it's unauthorised. Set the flag just in case. */ |
|
|
|
client->authorised = false; |
|
|
|
client->authorised = false; |
|
|
|
snprintf(buf, 255, "passthrough=%"PRId64, client_id); |
|
|
|
snprintf(buf, 255, "passthrough=%"PRId64, client_id); |
|
|
|
async_send_proc(ckp, client->ckp->connector, buf); |
|
|
|
send_proc(client->ckp->connector, buf); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3348,7 +3346,7 @@ static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64 |
|
|
|
if (!client->subscribed) { |
|
|
|
if (!client->subscribed) { |
|
|
|
LOGINFO("Dropping unsubscribed client %"PRId64, client_id); |
|
|
|
LOGINFO("Dropping unsubscribed client %"PRId64, client_id); |
|
|
|
snprintf(buf, 255, "dropclient=%"PRId64, client_id); |
|
|
|
snprintf(buf, 255, "dropclient=%"PRId64, client_id); |
|
|
|
async_send_proc(ckp, client->ckp->connector, buf); |
|
|
|
send_proc(client->ckp->connector, buf); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3371,7 +3369,7 @@ static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64 |
|
|
|
* the stratum instance data. Clients will just reconnect. */ |
|
|
|
* the stratum instance data. Clients will just reconnect. */ |
|
|
|
LOGINFO("Dropping unauthorised client %"PRId64, client_id); |
|
|
|
LOGINFO("Dropping unauthorised client %"PRId64, client_id); |
|
|
|
snprintf(buf, 255, "dropclient=%"PRId64, client_id); |
|
|
|
snprintf(buf, 255, "dropclient=%"PRId64, client_id); |
|
|
|
async_send_proc(ckp, client->ckp->connector, buf); |
|
|
|
send_proc(client->ckp->connector, buf); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3384,7 +3382,7 @@ static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64 |
|
|
|
if (cmdmatch(method, "mining.get")) { |
|
|
|
if (cmdmatch(method, "mining.get")) { |
|
|
|
json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); |
|
|
|
json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); |
|
|
|
|
|
|
|
|
|
|
|
ckwq_add(sdata->ckwqs, &send_transactions, jp); |
|
|
|
ckmsgq_add(sdata->stxnq, jp); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
/* Unhandled message here */ |
|
|
|
/* Unhandled message here */ |
|
|
@ -3403,13 +3401,12 @@ static void parse_instance_msg(sdata_t *sdata, smsg_t *msg, stratum_instance_t * |
|
|
|
{ |
|
|
|
{ |
|
|
|
json_t *val = msg->json_msg, *id_val, *method, *params; |
|
|
|
json_t *val = msg->json_msg, *id_val, *method, *params; |
|
|
|
int64_t client_id = msg->client_id; |
|
|
|
int64_t client_id = msg->client_id; |
|
|
|
ckpool_t *ckp = client->ckp; |
|
|
|
|
|
|
|
char buf[256]; |
|
|
|
char buf[256]; |
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(client->reject == 2)) { |
|
|
|
if (unlikely(client->reject == 2)) { |
|
|
|
LOGINFO("Dropping client %"PRId64" tagged for lazy invalidation", client_id); |
|
|
|
LOGINFO("Dropping client %"PRId64" tagged for lazy invalidation", client_id); |
|
|
|
snprintf(buf, 255, "dropclient=%"PRId64, client_id); |
|
|
|
snprintf(buf, 255, "dropclient=%"PRId64, client_id); |
|
|
|
async_send_proc(ckp, ckp->connector, buf); |
|
|
|
send_proc(client->ckp->connector, buf); |
|
|
|
goto out; |
|
|
|
goto out; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3543,7 +3540,7 @@ static void ssend_process(ckpool_t *ckp, smsg_t *msg) |
|
|
|
* connector process to be delivered */ |
|
|
|
* connector process to be delivered */ |
|
|
|
json_object_set_new_nocheck(msg->json_msg, "client_id", json_integer(msg->client_id)); |
|
|
|
json_object_set_new_nocheck(msg->json_msg, "client_id", json_integer(msg->client_id)); |
|
|
|
s = json_dumps(msg->json_msg, 0); |
|
|
|
s = json_dumps(msg->json_msg, 0); |
|
|
|
async_send_proc(ckp, ckp->connector, s); |
|
|
|
send_proc(ckp->connector, s); |
|
|
|
free(s); |
|
|
|
free(s); |
|
|
|
free_smsg(msg); |
|
|
|
free_smsg(msg); |
|
|
|
} |
|
|
|
} |
|
|
@ -4401,10 +4398,14 @@ int stratifier(proc_instance_t *pi) |
|
|
|
|
|
|
|
|
|
|
|
mutex_init(&sdata->ckdb_lock); |
|
|
|
mutex_init(&sdata->ckdb_lock); |
|
|
|
sdata->ssends = create_ckmsgq(ckp, "ssender", &ssend_process); |
|
|
|
sdata->ssends = create_ckmsgq(ckp, "ssender", &ssend_process); |
|
|
|
/* Create as many generic workqueue threads as there are CPUs */ |
|
|
|
/* Create half as many share processing threads as there are CPUs */ |
|
|
|
threads = sysconf(_SC_NPROCESSORS_ONLN); |
|
|
|
threads = sysconf(_SC_NPROCESSORS_ONLN) / 2 ? : 1; |
|
|
|
ckp->ckwqs = sdata->ckwqs = create_ckwqs(ckp, "strat", threads); |
|
|
|
sdata->sshareq = create_ckmsgqs(ckp, "sprocessor", &sshare_process, threads); |
|
|
|
|
|
|
|
/* Create 1/4 as many stratum processing threads as there are CPUs */ |
|
|
|
|
|
|
|
threads = threads / 2 ? : 1; |
|
|
|
|
|
|
|
sdata->srecvs = create_ckmsgqs(ckp, "sreceiver", &srecv_process, threads); |
|
|
|
sdata->sauthq = create_ckmsgq(ckp, "authoriser", &sauth_process); |
|
|
|
sdata->sauthq = create_ckmsgq(ckp, "authoriser", &sauth_process); |
|
|
|
|
|
|
|
sdata->stxnq = create_ckmsgq(ckp, "stxnq", &send_transactions); |
|
|
|
if (!CKP_STANDALONE(ckp)) { |
|
|
|
if (!CKP_STANDALONE(ckp)) { |
|
|
|
sdata->ckdbq = create_ckmsgq(ckp, "ckdbqueue", &ckdbq_process); |
|
|
|
sdata->ckdbq = create_ckmsgq(ckp, "ckdbqueue", &ckdbq_process); |
|
|
|
create_pthread(&pth_heartbeat, ckdb_heartbeat, ckp); |
|
|
|
create_pthread(&pth_heartbeat, ckdb_heartbeat, ckp); |
|
|
|