kanoi 10 years ago
parent
commit
9b60f7d4af
  1. 2
      ckpool.conf
  2. 14
      src/ckpool.c
  3. 3
      src/jansson-2.6/src/strconv.c
  4. 155
      src/stratifier.c

2
ckpool.conf

@ -13,7 +13,7 @@
], ],
"btcaddress" : "14BMjogz69qe8hk9thyzbmR5pg34mVKB1e", "btcaddress" : "14BMjogz69qe8hk9thyzbmR5pg34mVKB1e",
"btcsig" : "/mined by ck/", "btcsig" : "/mined by ck/",
"blockpoll" : 500, "blockpoll" : 50,
"update_interval" : 30, "update_interval" : 30,
"serverurl" : "ckpool.org:3333", "serverurl" : "ckpool.org:3333",
"mindiff" : 1, "mindiff" : 1,

14
src/ckpool.c

@ -1208,7 +1208,7 @@ int main(int argc, char **argv)
if (!ckp.btcaddress) if (!ckp.btcaddress)
ckp.btcaddress = ckp.donaddress; ckp.btcaddress = ckp.donaddress;
if (!ckp.blockpoll) if (!ckp.blockpoll)
ckp.blockpoll = 500; ckp.blockpoll = 50;
if (!ckp.update_interval) if (!ckp.update_interval)
ckp.update_interval = 30; ckp.update_interval = 30;
if (!ckp.mindiff) if (!ckp.mindiff)
@ -1226,6 +1226,18 @@ int main(int argc, char **argv)
if (ret && errno != EEXIST) if (ret && errno != EEXIST)
quit(1, "Failed to make log directory %s", ckp.logdir); 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 */ /* Create the logfile */
sprintf(buf, "%s%s.log", ckp.logdir, ckp.name); sprintf(buf, "%s%s.log", ckp.logdir, ckp.name);
ckp.logfp = fopen(buf, "ae"); ckp.logfp = fopen(buf, "ae");

3
src/jansson-2.6/src/strconv.c

@ -2,6 +2,7 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <math.h>
#include "jansson_private.h" #include "jansson_private.h"
#include "strbuffer.h" #include "strbuffer.h"
@ -69,7 +70,7 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out)
value = strtod(strbuffer->value, &end); value = strtod(strbuffer->value, &end);
assert(end == strbuffer->value + strbuffer->length); assert(end == strbuffer->value + strbuffer->length);
if(errno == ERANGE && value != 0) { if((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) {
/* Overflow */ /* Overflow */
return -1; return -1;
} }

155
src/stratifier.c

@ -195,6 +195,12 @@ struct user_instance {
bool btcaddress; bool btcaddress;
int workers; 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; typedef struct user_instance user_instance_t;
@ -260,6 +266,13 @@ static share_t *shares;
static cklock_t share_lock; 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_AUTH 0
#define ID_WORKINFO 1 #define ID_WORKINFO 1
#define ID_AGEWORKINFO 2 #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 /* 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 update_base(ckpool_t *ckp) static void update_base(ckpool_t *ckp, int prio)
{ {
bool new_block = false; bool new_block = false;
workbase_t *wb; workbase_t *wb;
json_t *val; json_t *val;
char *buf; char *buf;
buf = send_recv_proc(ckp->generator, "getbase"); buf = send_recv_generator(ckp, "getbase", prio);
if (unlikely(!buf)) { if (unlikely(!buf)) {
LOGWARNING("Failed to get base from generator in update_base"); LOGWARNING("Failed to get base from generator in update_base");
return; return;
@ -1020,7 +1078,7 @@ static void block_solve(ckpool_t *ckp)
"createinet", ckp->serverurl); "createinet", ckp->serverurl);
ck_runlock(&workbase_lock); ck_runlock(&workbase_lock);
update_base(ckp); update_base(ckp, GEN_PRIORITY);
ck_rlock(&workbase_lock); ck_rlock(&workbase_lock);
json_set_string(val, "blockhash", current_workbase->prevhash); json_set_string(val, "blockhash", current_workbase->prevhash);
@ -1053,7 +1111,7 @@ retry:
copy_tv(&start_tv, &end_tv); copy_tv(&start_tv, &end_tv);
LOGDEBUG("%ds elapsed in strat_loop, updating gbt base", LOGDEBUG("%ds elapsed in strat_loop, updating gbt base",
ckp->update_interval); ckp->update_interval);
update_base(ckp); update_base(ckp, GEN_NORMAL);
continue; continue;
} }
} }
@ -1092,7 +1150,7 @@ retry:
ret = 0; ret = 0;
goto out; goto out;
} else if (cmdmatch(buf, "update")) { } else if (cmdmatch(buf, "update")) {
update_base(ckp); update_base(ckp, GEN_PRIORITY);
} else if (cmdmatch(buf, "subscribe")) { } else if (cmdmatch(buf, "subscribe")) {
/* Proxifier has a new subscription */ /* Proxifier has a new subscription */
if (!update_subscribe(ckp)) if (!update_subscribe(ckp))
@ -1148,7 +1206,7 @@ static void *blockupdate(void *arg)
memset(hash, 0, 68); memset(hash, 0, 68);
while (42) { while (42) {
dealloc(buf); 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")) { if (buf && strcmp(buf, hash) && !cmdmatch(buf, "failed")) {
strcpy(hash, buf); strcpy(hash, buf);
LOGNOTICE("Block hash changed to %s", hash); LOGNOTICE("Block hash changed to %s", hash);
@ -1259,7 +1317,8 @@ static bool test_address(ckpool_t *ckp, const char *address)
char *buf, *msg; char *buf, *msg;
ASPRINTF(&msg, "checkaddr:%s", address); 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); dealloc(msg);
if (!buf) if (!buf)
return ret; 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) static void add_submit(ckpool_t *ckp, stratum_instance_t *client, int diff, bool valid)
{ {
double tdiff, bdiff, dsps, drr, network_diff, bias; double tdiff, bdiff, dsps, drr, network_diff, bias;
user_instance_t *instance = client->user_instance;
int64_t next_blockid, optimal; int64_t next_blockid, optimal;
tv_t now_t; 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; network_diff = current_workbase->network_diff;
ck_runlock(&workbase_lock); ck_runlock(&workbase_lock);
tdiff = sane_tdiff(&now_t, &client->last_share);
if (unlikely(!client->first_share.tv_sec)) { if (unlikely(!client->first_share.tv_sec)) {
copy_tv(&client->first_share, &now_t); copy_tv(&client->first_share, &now_t);
copy_tv(&client->ldc, &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->dsps1, diff, tdiff, 60);
decay_time(&client->dsps5, diff, tdiff, 300); decay_time(&client->dsps5, diff, tdiff, 300);
decay_time(&client->dsps60, diff, tdiff, 3600); decay_time(&client->dsps60, diff, tdiff, 3600);
decay_time(&client->dsps1440, diff, tdiff, 86400); decay_time(&client->dsps1440, diff, tdiff, 86400);
copy_tv(&client->last_share, &now_t); 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->idle = false;
client->ssdc++; client->ssdc++;
@ -1562,10 +1630,6 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, int diff, bool
return; return;
optimal = round(dsps * 3.33); 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 */ /* Clamp to mindiff ~ network_diff */
if (optimal < ckp->mindiff) if (optimal < ckp->mindiff)
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) if (client->diff == optimal)
return; 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; client->ssdc = 0;
LOGINFO("Client %d biased dsps %.2f dsps %.2f drr %.2f adjust diff from %ld to: %ld ", 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) if (wb->transactions)
realloc_strcat(&gbt_block, wb->txn_data); realloc_strcat(&gbt_block, wb->txn_data);
ckp = wb->ckp; ckp = wb->ckp;
send_proc(ckp->generator, gbt_block); send_generator(ckp, gbt_block, GEN_PRIORITY);
free(gbt_block); free(gbt_block);
flip_32(swap, hash); 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_id", msg_id);
msg = json_dumps(json_msg, 0); msg = json_dumps(json_msg, 0);
json_decref(json_msg); json_decref(json_msg);
send_proc(ckp->generator, msg); send_generator(ckp, msg, GEN_LAX);
free(msg); free(msg);
} }
@ -2417,10 +2489,11 @@ static void *statsupdate(void *arg)
while (42) { while (42) {
char suffix1[16], suffix5[16], suffix15[16], suffix60[16], cdfield[64]; 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]; char suffix360[16], suffix1440[16];
double sps1, sps5, sps15, sps60; user_instance_t *instance, *tmpuser;
stratum_instance_t *client, *tmp; stratum_instance_t *client, *tmp;
double sps1, sps5, sps15, sps60;
char fname[512] = {}; char fname[512] = {};
tv_t now, diff; tv_t now, diff;
ts_t ts_now; ts_t ts_now;
@ -2461,7 +2534,7 @@ static void *statsupdate(void *arg)
ghs1440 = stats.dsps1440 * nonces / bias; ghs1440 = stats.dsps1440 * nonces / bias;
suffix_string(ghs1440, suffix1440, 16, 0); 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"); fp = fopen(fname, "we");
if (unlikely(!fp)) if (unlikely(!fp))
LOGERR("Failed to fopen %s", fname); LOGERR("Failed to fopen %s", fname);
@ -2470,7 +2543,7 @@ static void *statsupdate(void *arg)
"runtime", diff.tv_sec, "runtime", diff.tv_sec,
"Users", stats.users, "Users", stats.users,
"Workers", stats.workers); "Workers", stats.workers);
s = json_dumps(val, JSON_NO_UTF8); s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
json_decref(val); json_decref(val);
LOGNOTICE("Pool:%s", s); LOGNOTICE("Pool:%s", s);
fprintf(fp, "%s\n", s); fprintf(fp, "%s\n", s);
@ -2483,7 +2556,7 @@ static void *statsupdate(void *arg)
"hashrate1hr", suffix60, "hashrate1hr", suffix60,
"hashrate6hr", suffix360, "hashrate6hr", suffix360,
"hashrate1d", suffix1440); "hashrate1d", suffix1440);
s = json_dumps(val, JSON_NO_UTF8); s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
json_decref(val); json_decref(val);
LOGNOTICE("Pool:%s", s); LOGNOTICE("Pool:%s", s);
fprintf(fp, "%s\n", s); fprintf(fp, "%s\n", s);
@ -2494,7 +2567,7 @@ static void *statsupdate(void *arg)
"SPS5m", sps5, "SPS5m", sps5,
"SPS15m", sps15, "SPS15m", sps15,
"SPS1h", sps60); "SPS1h", sps60);
s = json_dumps(val, JSON_NO_UTF8); s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
json_decref(val); json_decref(val);
LOGNOTICE("Pool:%s", s); LOGNOTICE("Pool:%s", s);
fprintf(fp, "%s\n", s); fprintf(fp, "%s\n", s);
@ -2503,14 +2576,10 @@ static void *statsupdate(void *arg)
ck_rlock(&instance_lock); ck_rlock(&instance_lock);
HASH_ITER(hh, stratum_instances, client, tmp) { HASH_ITER(hh, stratum_instances, client, tmp) {
double ghs;
bool idle;
if (!client->authorised) if (!client->authorised)
continue; continue;
if (now.tv_sec - client->last_share.tv_sec > 60) { if (now.tv_sec - client->last_share.tv_sec > 60) {
idle = true;
/* No shares for over a minute, decay to 0 */ /* No shares for over a minute, decay to 0 */
decay_time(&client->dsps1, 0, tdiff, 60); decay_time(&client->dsps1, 0, tdiff, 60);
decay_time(&client->dsps5, 0, tdiff, 300); decay_time(&client->dsps5, 0, tdiff, 300);
@ -2518,35 +2587,47 @@ static void *statsupdate(void *arg)
decay_time(&client->dsps1440, 0, tdiff, 86400); decay_time(&client->dsps1440, 0, tdiff, 86400);
if (now.tv_sec - client->last_share.tv_sec > 600) if (now.tv_sec - client->last_share.tv_sec > 600)
client->idle = true; client->idle = true;
} else continue;
idle = false; }
ghs = client->dsps1 * nonces; }
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); suffix_string(ghs, suffix1, 16, 0);
ghs = client->dsps5 * nonces; ghs = instance->dsps5 * nonces;
suffix_string(ghs, suffix5, 16, 0); suffix_string(ghs, suffix5, 16, 0);
ghs = client->dsps60 * nonces; ghs = instance->dsps60 * nonces;
suffix_string(ghs, suffix60, 16, 0); suffix_string(ghs, suffix60, 16, 0);
ghs = client->dsps1440 * nonces; ghs = instance->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,si}",
"hashrate1m", suffix1, "hashrate1m", suffix1,
"hashrate5m", suffix5, "hashrate5m", suffix5,
"hashrate1hr", suffix60, "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"); fp = fopen(fname, "we");
if (unlikely(!fp)) { if (unlikely(!fp)) {
LOGERR("Failed to fopen %s", fname); LOGERR("Failed to fopen %s", fname);
continue; continue;
} }
s = json_dumps(val, JSON_NO_UTF8); s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
fprintf(fp, "%s\n", s); fprintf(fp, "%s\n", s);
/* Only display the status of connected users to the
* console log. */
if (!idle) if (!idle)
LOGNOTICE("Worker %s:%s", client->workername, s); LOGNOTICE("User %s:%s", instance->username, s);
dealloc(s); dealloc(s);
json_decref(val); json_decref(val);
fclose(fp); fclose(fp);

Loading…
Cancel
Save