|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Copyright 2014 Con Kolivas |
|
|
|
* Copyright 2014-2015 Con Kolivas |
|
|
|
* |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or modify it |
|
|
|
* This program is free software; you can redistribute it and/or modify it |
|
|
|
* under the terms of the GNU General Public License as published by the Free |
|
|
|
* under the terms of the GNU General Public License as published by the Free |
|
|
@ -172,6 +172,8 @@ struct user_instance { |
|
|
|
|
|
|
|
|
|
|
|
int workers; |
|
|
|
int workers; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double best_diff; /* Best share found by this user */ |
|
|
|
|
|
|
|
|
|
|
|
double dsps1; /* Diff shares per second, 1 minute rolling average */ |
|
|
|
double dsps1; /* Diff shares per second, 1 minute rolling average */ |
|
|
|
double dsps5; /* ... 5 minute ... */ |
|
|
|
double dsps5; /* ... 5 minute ... */ |
|
|
|
double dsps60;/* etc */ |
|
|
|
double dsps60;/* etc */ |
|
|
@ -195,6 +197,7 @@ struct worker_instance { |
|
|
|
tv_t last_share; |
|
|
|
tv_t last_share; |
|
|
|
time_t start_time; |
|
|
|
time_t start_time; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double best_diff; /* Best share found by this worker */ |
|
|
|
int mindiff; /* User chosen mindiff */ |
|
|
|
int mindiff; /* User chosen mindiff */ |
|
|
|
|
|
|
|
|
|
|
|
bool idle; |
|
|
|
bool idle; |
|
|
@ -252,8 +255,10 @@ struct stratum_instance { |
|
|
|
ckpool_t *ckp; |
|
|
|
ckpool_t *ckp; |
|
|
|
|
|
|
|
|
|
|
|
time_t last_txns; /* Last time this worker requested txn hashes */ |
|
|
|
time_t last_txns; /* Last time this worker requested txn hashes */ |
|
|
|
|
|
|
|
time_t disconnected_time; /* Time this instance disconnected */ |
|
|
|
|
|
|
|
|
|
|
|
int64_t suggest_diff; /* Stratum client suggested diff */ |
|
|
|
int64_t suggest_diff; /* Stratum client suggested diff */ |
|
|
|
|
|
|
|
double best_diff; /* Best share found by this instance */ |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct share { |
|
|
|
struct share { |
|
|
@ -1098,6 +1103,14 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, int64_t id, int |
|
|
|
return instance; |
|
|
|
return instance; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Add a stratum instance to the dead instances list */ |
|
|
|
|
|
|
|
static void kill_instance(sdata_t *sdata, stratum_instance_t *client) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (client->user_instance) |
|
|
|
|
|
|
|
DL_DELETE(client->user_instance->instances, client); |
|
|
|
|
|
|
|
LL_PREPEND(sdata->dead_instances, client); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Only supports a full ckpool instance sessionid with an 8 byte sessionid */ |
|
|
|
/* Only supports a full ckpool instance sessionid with an 8 byte sessionid */ |
|
|
|
static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, int64_t id) |
|
|
|
static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, int64_t id) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1112,7 +1125,7 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, |
|
|
|
/* Number is in BE but we don't swap either of them */ |
|
|
|
/* Number is in BE but we don't swap either of them */ |
|
|
|
hex2bin(&session64, sessionid, 8); |
|
|
|
hex2bin(&session64, sessionid, 8); |
|
|
|
|
|
|
|
|
|
|
|
ck_rlock(&sdata->instance_lock); |
|
|
|
ck_ilock(&sdata->instance_lock); |
|
|
|
HASH_ITER(hh, sdata->stratum_instances, instance, tmp) { |
|
|
|
HASH_ITER(hh, sdata->stratum_instances, instance, tmp) { |
|
|
|
if (instance->id == id) |
|
|
|
if (instance->id == id) |
|
|
|
continue; |
|
|
|
continue; |
|
|
@ -1123,10 +1136,18 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, |
|
|
|
} |
|
|
|
} |
|
|
|
instance = NULL; |
|
|
|
instance = NULL; |
|
|
|
HASH_FIND(hh, sdata->disconnected_instances, &session64, sizeof(uint64_t), instance); |
|
|
|
HASH_FIND(hh, sdata->disconnected_instances, &session64, sizeof(uint64_t), instance); |
|
|
|
if (instance) |
|
|
|
if (instance) { |
|
|
|
|
|
|
|
/* If we've found a matching disconnected instance, use it only
|
|
|
|
|
|
|
|
* once and discard it */ |
|
|
|
|
|
|
|
ck_ulock(&sdata->instance_lock); |
|
|
|
|
|
|
|
HASH_DEL(sdata->disconnected_instances, instance); |
|
|
|
|
|
|
|
kill_instance(sdata, instance); |
|
|
|
|
|
|
|
ck_dwilock(&sdata->instance_lock); |
|
|
|
|
|
|
|
|
|
|
|
ret = true; |
|
|
|
ret = true; |
|
|
|
|
|
|
|
} |
|
|
|
out_unlock: |
|
|
|
out_unlock: |
|
|
|
ck_runlock(&sdata->instance_lock); |
|
|
|
ck_uilock(&sdata->instance_lock); |
|
|
|
out: |
|
|
|
out: |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
@ -1209,6 +1230,7 @@ static void dec_worker(ckpool_t *ckp, user_instance_t *instance) |
|
|
|
static void drop_client(sdata_t *sdata, int64_t id) |
|
|
|
static void drop_client(sdata_t *sdata, int64_t id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
stratum_instance_t *client, *tmp; |
|
|
|
stratum_instance_t *client, *tmp; |
|
|
|
|
|
|
|
time_t now_t = time(NULL); |
|
|
|
bool dec = false; |
|
|
|
bool dec = false; |
|
|
|
|
|
|
|
|
|
|
|
LOGINFO("Stratifier dropping client %ld", id); |
|
|
|
LOGINFO("Stratifier dropping client %ld", id); |
|
|
@ -1227,13 +1249,11 @@ static void drop_client(sdata_t *sdata, int64_t id) |
|
|
|
HASH_DEL(sdata->stratum_instances, client); |
|
|
|
HASH_DEL(sdata->stratum_instances, client); |
|
|
|
HASH_FIND(hh, sdata->disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client); |
|
|
|
HASH_FIND(hh, sdata->disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client); |
|
|
|
/* Only keep around one copy of the old client in server mode */ |
|
|
|
/* Only keep around one copy of the old client in server mode */ |
|
|
|
if (!client->ckp->proxy && !old_client && client->enonce1_64) |
|
|
|
if (!client->ckp->proxy && !old_client && client->enonce1_64) { |
|
|
|
HASH_ADD(hh, sdata->disconnected_instances, enonce1_64, sizeof(uint64_t), client); |
|
|
|
HASH_ADD(hh, sdata->disconnected_instances, enonce1_64, sizeof(uint64_t), client); |
|
|
|
else { |
|
|
|
client->disconnected_time = time(NULL); |
|
|
|
if (client->user_instance) |
|
|
|
} else |
|
|
|
DL_DELETE(client->user_instance->instances, client); |
|
|
|
kill_instance(sdata, client); |
|
|
|
LL_PREPEND(sdata->dead_instances, client); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
ck_wunlock(&sdata->instance_lock); |
|
|
|
ck_wunlock(&sdata->instance_lock); |
|
|
|
|
|
|
|
|
|
|
@ -1247,6 +1267,18 @@ static void drop_client(sdata_t *sdata, int64_t id) |
|
|
|
ck_wlock(&sdata->instance_lock); |
|
|
|
ck_wlock(&sdata->instance_lock); |
|
|
|
if (client) |
|
|
|
if (client) |
|
|
|
__dec_instance_ref(client); |
|
|
|
__dec_instance_ref(client); |
|
|
|
|
|
|
|
/* Old disconnected instances will not have any valid shares so remove
|
|
|
|
|
|
|
|
* them from the disconnected instances list if they've been dead for |
|
|
|
|
|
|
|
* more than 10 minutes */ |
|
|
|
|
|
|
|
HASH_ITER(hh, sdata->disconnected_instances, client, tmp) { |
|
|
|
|
|
|
|
if (now_t - client->disconnected_time < 600) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
LOGINFO("Discarding aged disconnected instance %ld", client->id); |
|
|
|
|
|
|
|
HASH_DEL(sdata->disconnected_instances, client); |
|
|
|
|
|
|
|
kill_instance(sdata, client); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* Discard any dead instances that no longer hold any reference counts,
|
|
|
|
|
|
|
|
* freeing up their memory safely */ |
|
|
|
DL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { |
|
|
|
DL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { |
|
|
|
if (!client->ref) { |
|
|
|
if (!client->ref) { |
|
|
|
LOGINFO("Stratifier discarding instance %ld", client->id); |
|
|
|
LOGINFO("Stratifier discarding instance %ld", client->id); |
|
|
@ -2533,6 +2565,17 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, |
|
|
|
nonce2[len] = '\0'; |
|
|
|
nonce2[len] = '\0'; |
|
|
|
} |
|
|
|
} |
|
|
|
sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash); |
|
|
|
sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash); |
|
|
|
|
|
|
|
if (sdiff > client->best_diff) { |
|
|
|
|
|
|
|
worker_instance_t *worker = client->worker_instance; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client->best_diff = sdiff; |
|
|
|
|
|
|
|
LOGINFO("User %s worker %s client %ld new best diff %lf", user_instance->username, |
|
|
|
|
|
|
|
worker->workername, client->id, sdiff); |
|
|
|
|
|
|
|
if (sdiff > worker->best_diff) |
|
|
|
|
|
|
|
worker->best_diff = sdiff; |
|
|
|
|
|
|
|
if (sdiff > user_instance->best_diff) |
|
|
|
|
|
|
|
user_instance->best_diff = sdiff; |
|
|
|
|
|
|
|
} |
|
|
|
bswap_256(sharehash, hash); |
|
|
|
bswap_256(sharehash, hash); |
|
|
|
__bin2hex(hexhash, sharehash, 32); |
|
|
|
__bin2hex(hexhash, sharehash, 32); |
|
|
|
|
|
|
|
|
|
|
@ -2619,9 +2662,9 @@ out_unlock: |
|
|
|
if (ckp->logshares) { |
|
|
|
if (ckp->logshares) { |
|
|
|
fp = fopen(fname, "ae"); |
|
|
|
fp = fopen(fname, "ae"); |
|
|
|
if (likely(fp)) { |
|
|
|
if (likely(fp)) { |
|
|
|
s = json_dumps(val, 0); |
|
|
|
s = json_dumps(val, JSON_EOL); |
|
|
|
len = strlen(s); |
|
|
|
len = strlen(s); |
|
|
|
len = fprintf(fp, "%s\n", s); |
|
|
|
len = fprintf(fp, "%s", s); |
|
|
|
free(s); |
|
|
|
free(s); |
|
|
|
fclose(fp); |
|
|
|
fclose(fp); |
|
|
|
if (unlikely(len < 0)) |
|
|
|
if (unlikely(len < 0)) |
|
|
@ -3543,11 +3586,12 @@ static void *statsupdate(void *arg) |
|
|
|
ghs = worker->dsps1440 * nonces; |
|
|
|
ghs = worker->dsps1440 * nonces; |
|
|
|
suffix_string(ghs, suffix1440, 16, 0); |
|
|
|
suffix_string(ghs, suffix1440, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss}", |
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,sf}", |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate1hr", suffix60, |
|
|
|
"hashrate1hr", suffix60, |
|
|
|
"hashrate1d", suffix1440); |
|
|
|
"hashrate1d", suffix1440, |
|
|
|
|
|
|
|
"bestshare", worker->best_diff); |
|
|
|
|
|
|
|
|
|
|
|
snprintf(fname, 511, "%s/workers/%s", ckp->logdir, worker->workername); |
|
|
|
snprintf(fname, 511, "%s/workers/%s", ckp->logdir, worker->workername); |
|
|
|
fp = fopen(fname, "we"); |
|
|
|
fp = fopen(fname, "we"); |
|
|
@ -3555,8 +3599,8 @@ static void *statsupdate(void *arg) |
|
|
|
LOGERR("Failed to fopen %s", fname); |
|
|
|
LOGERR("Failed to fopen %s", fname); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); |
|
|
|
s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER | JSON_EOL); |
|
|
|
fprintf(fp, "%s\n", s); |
|
|
|
fprintf(fp, "%s", s); |
|
|
|
dealloc(s); |
|
|
|
dealloc(s); |
|
|
|
json_decref(val); |
|
|
|
json_decref(val); |
|
|
|
fclose(fp); |
|
|
|
fclose(fp); |
|
|
@ -3587,13 +3631,14 @@ static void *statsupdate(void *arg) |
|
|
|
ghs = instance->dsps10080 * nonces; |
|
|
|
ghs = instance->dsps10080 * nonces; |
|
|
|
suffix_string(ghs, suffix10080, 16, 0); |
|
|
|
suffix_string(ghs, suffix10080, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,ss,si}", |
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,sf}", |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate1hr", suffix60, |
|
|
|
"hashrate1hr", suffix60, |
|
|
|
"hashrate1d", suffix1440, |
|
|
|
"hashrate1d", suffix1440, |
|
|
|
"hashrate7d", suffix10080, |
|
|
|
"hashrate7d", suffix10080, |
|
|
|
"workers", instance->workers); |
|
|
|
"workers", instance->workers, |
|
|
|
|
|
|
|
"bestshare", instance->best_diff); |
|
|
|
|
|
|
|
|
|
|
|
snprintf(fname, 511, "%s/users/%s", ckp->logdir, instance->username); |
|
|
|
snprintf(fname, 511, "%s/users/%s", ckp->logdir, instance->username); |
|
|
|
fp = fopen(fname, "we"); |
|
|
|
fp = fopen(fname, "we"); |
|
|
|