Merge branch 'master' of https://bitbucket.org/ckolivas/ckpool
This commit is contained in:
commit
9b60f7d4af
@ -13,7 +13,7 @@
|
||||
],
|
||||
"btcaddress" : "14BMjogz69qe8hk9thyzbmR5pg34mVKB1e",
|
||||
"btcsig" : "/mined by ck/",
|
||||
"blockpoll" : 500,
|
||||
"blockpoll" : 50,
|
||||
"update_interval" : 30,
|
||||
"serverurl" : "ckpool.org:3333",
|
||||
"mindiff" : 1,
|
||||
|
||||
14
src/ckpool.c
14
src/ckpool.c
@ -1208,7 +1208,7 @@ int main(int argc, char **argv)
|
||||
if (!ckp.btcaddress)
|
||||
ckp.btcaddress = ckp.donaddress;
|
||||
if (!ckp.blockpoll)
|
||||
ckp.blockpoll = 500;
|
||||
ckp.blockpoll = 50;
|
||||
if (!ckp.update_interval)
|
||||
ckp.update_interval = 30;
|
||||
if (!ckp.mindiff)
|
||||
@ -1226,6 +1226,18 @@ int main(int argc, char **argv)
|
||||
if (ret && errno != EEXIST)
|
||||
quit(1, "Failed to make log directory %s", ckp.logdir);
|
||||
|
||||
/* Create the user logdir */
|
||||
sprintf(buf, "%s/users", ckp.logdir);
|
||||
ret = mkdir(buf, 0750);
|
||||
if (ret && errno != EEXIST)
|
||||
quit(1, "Failed to make user log directory %s", buf);
|
||||
|
||||
/* Create the pool logdir */
|
||||
sprintf(buf, "%s/pool", ckp.logdir);
|
||||
ret = mkdir(buf, 0750);
|
||||
if (ret && errno != EEXIST)
|
||||
quit(1, "Failed to make pool log directory %s", buf);
|
||||
|
||||
/* Create the logfile */
|
||||
sprintf(buf, "%s%s.log", ckp.logdir, ckp.name);
|
||||
ckp.logfp = fopen(buf, "ae");
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "jansson_private.h"
|
||||
#include "strbuffer.h"
|
||||
|
||||
@ -69,7 +70,7 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out)
|
||||
value = strtod(strbuffer->value, &end);
|
||||
assert(end == strbuffer->value + strbuffer->length);
|
||||
|
||||
if(errno == ERANGE && value != 0) {
|
||||
if((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) {
|
||||
/* Overflow */
|
||||
return -1;
|
||||
}
|
||||
|
||||
155
src/stratifier.c
155
src/stratifier.c
@ -195,6 +195,12 @@ struct user_instance {
|
||||
bool btcaddress;
|
||||
|
||||
int workers;
|
||||
|
||||
double dsps1; /* Diff shares per second, 1 minute rolling average */
|
||||
double dsps5; /* ... 5 minute ... */
|
||||
double dsps60;/* etc */
|
||||
double dsps1440;
|
||||
tv_t last_share;
|
||||
};
|
||||
|
||||
typedef struct user_instance user_instance_t;
|
||||
@ -260,6 +266,13 @@ static share_t *shares;
|
||||
|
||||
static cklock_t share_lock;
|
||||
|
||||
static int gen_priority;
|
||||
|
||||
/* Priority levels for generator messages */
|
||||
#define GEN_LAX 0
|
||||
#define GEN_NORMAL 1
|
||||
#define GEN_PRIORITY 2
|
||||
|
||||
#define ID_AUTH 0
|
||||
#define ID_WORKINFO 1
|
||||
#define ID_AGEWORKINFO 2
|
||||
@ -585,17 +598,62 @@ static void add_base(ckpool_t *ckp, workbase_t *wb, bool *new_block)
|
||||
}
|
||||
}
|
||||
|
||||
/* Mandatory send_recv to the generator which sets the message priority if this
|
||||
* message is higher priority. Races galore on gen_priority mean this might
|
||||
* read the wrong priority but occasional wrong values are harmless. */
|
||||
static char *__send_recv_generator(ckpool_t *ckp, const char *msg, int prio)
|
||||
{
|
||||
char *buf = NULL;
|
||||
bool set;
|
||||
|
||||
if (prio > gen_priority) {
|
||||
gen_priority = prio;
|
||||
set = true;
|
||||
} else
|
||||
set = false;
|
||||
buf = send_recv_proc(ckp->generator, msg);
|
||||
if (set)
|
||||
gen_priority = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Conditionally send_recv a message only if it's equal or higher priority than
|
||||
* any currently being serviced. */
|
||||
static char *send_recv_generator(ckpool_t *ckp, const char *msg, int prio)
|
||||
{
|
||||
char *buf = NULL;
|
||||
|
||||
if (prio >= gen_priority)
|
||||
buf = __send_recv_generator(ckp, msg, prio);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void send_generator(ckpool_t *ckp, const char *msg, int prio)
|
||||
{
|
||||
bool set;
|
||||
|
||||
if (prio > gen_priority) {
|
||||
gen_priority = prio;
|
||||
set = true;
|
||||
} else
|
||||
set = false;
|
||||
send_proc(ckp->generator, msg);
|
||||
if (set)
|
||||
gen_priority = 0;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* for generating work templates. */
|
||||
static void update_base(ckpool_t *ckp)
|
||||
static void update_base(ckpool_t *ckp, int prio)
|
||||
{
|
||||
bool new_block = false;
|
||||
workbase_t *wb;
|
||||
json_t *val;
|
||||
char *buf;
|
||||
|
||||
buf = send_recv_proc(ckp->generator, "getbase");
|
||||
buf = send_recv_generator(ckp, "getbase", prio);
|
||||
if (unlikely(!buf)) {
|
||||
LOGWARNING("Failed to get base from generator in update_base");
|
||||
return;
|
||||
@ -1020,7 +1078,7 @@ static void block_solve(ckpool_t *ckp)
|
||||
"createinet", ckp->serverurl);
|
||||
ck_runlock(&workbase_lock);
|
||||
|
||||
update_base(ckp);
|
||||
update_base(ckp, GEN_PRIORITY);
|
||||
|
||||
ck_rlock(&workbase_lock);
|
||||
json_set_string(val, "blockhash", current_workbase->prevhash);
|
||||
@ -1053,7 +1111,7 @@ retry:
|
||||
copy_tv(&start_tv, &end_tv);
|
||||
LOGDEBUG("%ds elapsed in strat_loop, updating gbt base",
|
||||
ckp->update_interval);
|
||||
update_base(ckp);
|
||||
update_base(ckp, GEN_NORMAL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -1092,7 +1150,7 @@ retry:
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else if (cmdmatch(buf, "update")) {
|
||||
update_base(ckp);
|
||||
update_base(ckp, GEN_PRIORITY);
|
||||
} else if (cmdmatch(buf, "subscribe")) {
|
||||
/* Proxifier has a new subscription */
|
||||
if (!update_subscribe(ckp))
|
||||
@ -1148,7 +1206,7 @@ static void *blockupdate(void *arg)
|
||||
memset(hash, 0, 68);
|
||||
while (42) {
|
||||
dealloc(buf);
|
||||
buf = send_recv_proc(ckp->generator, request);
|
||||
buf = send_recv_generator(ckp, request, GEN_LAX);
|
||||
if (buf && strcmp(buf, hash) && !cmdmatch(buf, "failed")) {
|
||||
strcpy(hash, buf);
|
||||
LOGNOTICE("Block hash changed to %s", hash);
|
||||
@ -1259,7 +1317,8 @@ static bool test_address(ckpool_t *ckp, const char *address)
|
||||
char *buf, *msg;
|
||||
|
||||
ASPRINTF(&msg, "checkaddr:%s", address);
|
||||
buf = send_recv_proc(ckp->generator, msg);
|
||||
/* Must wait for a response here */
|
||||
buf = __send_recv_generator(ckp, msg, GEN_LAX);
|
||||
dealloc(msg);
|
||||
if (!buf)
|
||||
return ret;
|
||||
@ -1505,6 +1564,7 @@ static double sane_tdiff(tv_t *end, tv_t *start)
|
||||
static void add_submit(ckpool_t *ckp, stratum_instance_t *client, int diff, bool valid)
|
||||
{
|
||||
double tdiff, bdiff, dsps, drr, network_diff, bias;
|
||||
user_instance_t *instance = client->user_instance;
|
||||
int64_t next_blockid, optimal;
|
||||
tv_t now_t;
|
||||
|
||||
@ -1518,16 +1578,24 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, int diff, bool
|
||||
network_diff = current_workbase->network_diff;
|
||||
ck_runlock(&workbase_lock);
|
||||
|
||||
tdiff = sane_tdiff(&now_t, &client->last_share);
|
||||
if (unlikely(!client->first_share.tv_sec)) {
|
||||
copy_tv(&client->first_share, &now_t);
|
||||
copy_tv(&client->ldc, &now_t);
|
||||
}
|
||||
|
||||
tdiff = sane_tdiff(&now_t, &client->last_share);
|
||||
decay_time(&client->dsps1, diff, tdiff, 60);
|
||||
decay_time(&client->dsps5, diff, tdiff, 300);
|
||||
decay_time(&client->dsps60, diff, tdiff, 3600);
|
||||
decay_time(&client->dsps1440, diff, tdiff, 86400);
|
||||
copy_tv(&client->last_share, &now_t);
|
||||
|
||||
tdiff = sane_tdiff(&now_t, &instance->last_share);
|
||||
decay_time(&instance->dsps1, diff, tdiff, 60);
|
||||
decay_time(&instance->dsps5, diff, tdiff, 300);
|
||||
decay_time(&instance->dsps60, diff, tdiff, 3600);
|
||||
decay_time(&instance->dsps1440, diff, tdiff, 86400);
|
||||
copy_tv(&instance->last_share, &now_t);
|
||||
client->idle = false;
|
||||
|
||||
client->ssdc++;
|
||||
@ -1562,10 +1630,6 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, int diff, bool
|
||||
return;
|
||||
|
||||
optimal = round(dsps * 3.33);
|
||||
/* Don't drop diff to rapidly in case the client simply switched away
|
||||
* and has just returned */
|
||||
if (optimal < client->diff / 2)
|
||||
optimal = client->diff / 2;
|
||||
/* Clamp to mindiff ~ network_diff */
|
||||
if (optimal < ckp->mindiff)
|
||||
optimal = ckp->mindiff;
|
||||
@ -1574,6 +1638,14 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, int diff, bool
|
||||
if (client->diff == optimal)
|
||||
return;
|
||||
|
||||
/* If this is the first share in a change, reset the last diff change
|
||||
* to make sure the client hasn't just fallen back after a leave of
|
||||
* absence */
|
||||
if (optimal < client->diff && client->ssdc == 1) {
|
||||
copy_tv(&client->ldc, &now_t);
|
||||
return;
|
||||
}
|
||||
|
||||
client->ssdc = 0;
|
||||
|
||||
LOGINFO("Client %d biased dsps %.2f dsps %.2f drr %.2f adjust diff from %ld to: %ld ",
|
||||
@ -1636,7 +1708,7 @@ test_blocksolve(stratum_instance_t *client, workbase_t *wb, const uchar *data, c
|
||||
if (wb->transactions)
|
||||
realloc_strcat(&gbt_block, wb->txn_data);
|
||||
ckp = wb->ckp;
|
||||
send_proc(ckp->generator, gbt_block);
|
||||
send_generator(ckp, gbt_block, GEN_PRIORITY);
|
||||
free(gbt_block);
|
||||
|
||||
flip_32(swap, hash);
|
||||
@ -1757,7 +1829,7 @@ static void submit_share(stratum_instance_t *client, int64_t jobid, const char *
|
||||
"msg_id", msg_id);
|
||||
msg = json_dumps(json_msg, 0);
|
||||
json_decref(json_msg);
|
||||
send_proc(ckp->generator, msg);
|
||||
send_generator(ckp, msg, GEN_LAX);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
@ -2417,10 +2489,11 @@ static void *statsupdate(void *arg)
|
||||
|
||||
while (42) {
|
||||
char suffix1[16], suffix5[16], suffix15[16], suffix60[16], cdfield[64];
|
||||
double ghs1, ghs5, ghs15, ghs60, ghs360, ghs1440, tdiff, bias;
|
||||
double ghs, ghs1, ghs5, ghs15, ghs60, ghs360, ghs1440, tdiff, bias;
|
||||
char suffix360[16], suffix1440[16];
|
||||
double sps1, sps5, sps15, sps60;
|
||||
user_instance_t *instance, *tmpuser;
|
||||
stratum_instance_t *client, *tmp;
|
||||
double sps1, sps5, sps15, sps60;
|
||||
char fname[512] = {};
|
||||
tv_t now, diff;
|
||||
ts_t ts_now;
|
||||
@ -2461,7 +2534,7 @@ static void *statsupdate(void *arg)
|
||||
ghs1440 = stats.dsps1440 * nonces / bias;
|
||||
suffix_string(ghs1440, suffix1440, 16, 0);
|
||||
|
||||
snprintf(fname, 511, "%s/pool.status", ckp->logdir);
|
||||
snprintf(fname, 511, "%s/pool/pool.status", ckp->logdir);
|
||||
fp = fopen(fname, "we");
|
||||
if (unlikely(!fp))
|
||||
LOGERR("Failed to fopen %s", fname);
|
||||
@ -2470,7 +2543,7 @@ static void *statsupdate(void *arg)
|
||||
"runtime", diff.tv_sec,
|
||||
"Users", stats.users,
|
||||
"Workers", stats.workers);
|
||||
s = json_dumps(val, JSON_NO_UTF8);
|
||||
s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
|
||||
json_decref(val);
|
||||
LOGNOTICE("Pool:%s", s);
|
||||
fprintf(fp, "%s\n", s);
|
||||
@ -2483,7 +2556,7 @@ static void *statsupdate(void *arg)
|
||||
"hashrate1hr", suffix60,
|
||||
"hashrate6hr", suffix360,
|
||||
"hashrate1d", suffix1440);
|
||||
s = json_dumps(val, JSON_NO_UTF8);
|
||||
s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
|
||||
json_decref(val);
|
||||
LOGNOTICE("Pool:%s", s);
|
||||
fprintf(fp, "%s\n", s);
|
||||
@ -2494,7 +2567,7 @@ static void *statsupdate(void *arg)
|
||||
"SPS5m", sps5,
|
||||
"SPS15m", sps15,
|
||||
"SPS1h", sps60);
|
||||
s = json_dumps(val, JSON_NO_UTF8);
|
||||
s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
|
||||
json_decref(val);
|
||||
LOGNOTICE("Pool:%s", s);
|
||||
fprintf(fp, "%s\n", s);
|
||||
@ -2503,14 +2576,10 @@ static void *statsupdate(void *arg)
|
||||
|
||||
ck_rlock(&instance_lock);
|
||||
HASH_ITER(hh, stratum_instances, client, tmp) {
|
||||
double ghs;
|
||||
bool idle;
|
||||
|
||||
if (!client->authorised)
|
||||
continue;
|
||||
|
||||
if (now.tv_sec - client->last_share.tv_sec > 60) {
|
||||
idle = true;
|
||||
/* No shares for over a minute, decay to 0 */
|
||||
decay_time(&client->dsps1, 0, tdiff, 60);
|
||||
decay_time(&client->dsps5, 0, tdiff, 300);
|
||||
@ -2518,35 +2587,47 @@ static void *statsupdate(void *arg)
|
||||
decay_time(&client->dsps1440, 0, tdiff, 86400);
|
||||
if (now.tv_sec - client->last_share.tv_sec > 600)
|
||||
client->idle = true;
|
||||
} else
|
||||
idle = false;
|
||||
ghs = client->dsps1 * nonces;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
HASH_ITER(hh, user_instances, instance, tmpuser) {
|
||||
bool idle = false;
|
||||
|
||||
if (now.tv_sec - instance->last_share.tv_sec > 60) {
|
||||
/* No shares for over a minute, decay to 0 */
|
||||
decay_time(&instance->dsps1, 0, tdiff, 60);
|
||||
decay_time(&instance->dsps5, 0, tdiff, 300);
|
||||
decay_time(&instance->dsps60, 0, tdiff, 3600);
|
||||
decay_time(&instance->dsps1440, 0, tdiff, 86400);
|
||||
idle = true;
|
||||
}
|
||||
ghs = instance->dsps1 * nonces;
|
||||
suffix_string(ghs, suffix1, 16, 0);
|
||||
ghs = client->dsps5 * nonces;
|
||||
ghs = instance->dsps5 * nonces;
|
||||
suffix_string(ghs, suffix5, 16, 0);
|
||||
ghs = client->dsps60 * nonces;
|
||||
ghs = instance->dsps60 * nonces;
|
||||
suffix_string(ghs, suffix60, 16, 0);
|
||||
ghs = client->dsps1440 * nonces;
|
||||
ghs = instance->dsps1440 * nonces;
|
||||
suffix_string(ghs, suffix1440, 16, 0);
|
||||
|
||||
JSON_CPACK(val, "{ss,ss,ss,ss}",
|
||||
JSON_CPACK(val, "{ss,ss,ss,ss,si}",
|
||||
"hashrate1m", suffix1,
|
||||
"hashrate5m", suffix5,
|
||||
"hashrate1hr", suffix60,
|
||||
"hashrate1d", suffix1440);
|
||||
"hashrate1d", suffix1440,
|
||||
"workers", instance->workers);
|
||||
|
||||
snprintf(fname, 511, "%s/%s", ckp->logdir, client->workername);
|
||||
snprintf(fname, 511, "%s/users/%s", ckp->logdir, instance->username);
|
||||
fp = fopen(fname, "we");
|
||||
if (unlikely(!fp)) {
|
||||
LOGERR("Failed to fopen %s", fname);
|
||||
continue;
|
||||
}
|
||||
s = json_dumps(val, JSON_NO_UTF8);
|
||||
s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
|
||||
fprintf(fp, "%s\n", s);
|
||||
/* Only display the status of connected users to the
|
||||
* console log. */
|
||||
if (!idle)
|
||||
LOGNOTICE("Worker %s:%s", client->workername, s);
|
||||
LOGNOTICE("User %s:%s", instance->username, s);
|
||||
dealloc(s);
|
||||
json_decref(val);
|
||||
fclose(fp);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user