kanoi 9 years ago
parent
commit
b9a1d074d3
  1. 17
      src/ckpool.c
  2. 33
      src/connector.c
  3. 9
      src/libckpool.c
  4. 313
      src/stratifier.c

17
src/ckpool.c

@ -84,6 +84,7 @@ void logmsg(int loglevel, const char *fmt, ...) {
tm.tm_min, tm.tm_min,
tm.tm_sec, ms); tm.tm_sec, ms);
if (loglevel <= LOG_WARNING) { if (loglevel <= LOG_WARNING) {
fprintf(stderr, "\33[2K\r");
if (loglevel <= LOG_ERR && errno != 0) if (loglevel <= LOG_ERR && errno != 0)
fprintf(stderr, "%s %s with errno %d: %s\n", stamp, buf, errno, strerror(errno)); fprintf(stderr, "%s %s with errno %d: %s\n", stamp, buf, errno, strerror(errno));
else else
@ -1467,7 +1468,8 @@ static bool send_recv_path(const char *path, const char *msg)
ret = true; ret = true;
LOGWARNING("Received: %s in response to %s request", response, msg); LOGWARNING("Received: %s in response to %s request", response, msg);
dealloc(response); dealloc(response);
} } else
LOGWARNING("Received not response to %s request", msg);
Close(sockd); Close(sockd);
return ret; return ret;
} }
@ -1707,6 +1709,7 @@ int main(int argc, char **argv)
if (send_recv_path(path, "ping")) { if (send_recv_path(path, "ping")) {
for (i = 0; i < ckp.serverurls; i++) { for (i = 0; i < ckp.serverurls; i++) {
char oldurl[INET6_ADDRSTRLEN], oldport[8];
char getfd[16]; char getfd[16];
int sockd; int sockd;
@ -1718,10 +1721,16 @@ int main(int argc, char **argv)
break; break;
ckp.oldconnfd[i] = get_fd(sockd); ckp.oldconnfd[i] = get_fd(sockd);
Close(sockd); Close(sockd);
if (!ckp.oldconnfd[i]) sockd = ckp.oldconnfd[i];
if (!sockd)
break; break;
LOGWARNING("Inherited old server socket %d with new file descriptor %d!", if (url_from_socket(sockd, oldurl, oldport)) {
i, ckp.oldconnfd[i]); LOGWARNING("Inherited old server socket %d url %s:%s !",
i, oldurl, oldport);
} else {
LOGWARNING("Inherited old server socket %d with new file descriptor %d!",
i, ckp.oldconnfd[i]);
}
} }
send_recv_path(path, "reject"); send_recv_path(path, "reject");
send_recv_path(path, "reconnect"); send_recv_path(path, "reconnect");

33
src/connector.c

@ -45,7 +45,8 @@ struct client_instance {
client_instance_t *next; client_instance_t *next;
client_instance_t *prev; client_instance_t *prev;
struct sockaddr address; struct sockaddr_storage address_storage;
struct sockaddr *address;
char address_name[INET6_ADDRSTRLEN]; char address_name[INET6_ADDRSTRLEN];
/* Which serverurl is this instance connected to */ /* Which serverurl is this instance connected to */
@ -57,6 +58,9 @@ struct client_instance {
/* Are we currently sending a blocked message from this client */ /* Are we currently sending a blocked message from this client */
sender_send_t *sending; sender_send_t *sending;
bool passthrough; bool passthrough;
/* Time this client started blocking, 0 when not blocked */
time_t blocked_time;
}; };
struct sender_send { struct sender_send {
@ -192,8 +196,9 @@ static int accept_client(cdata_t *cdata, const int epfd, const uint64_t server)
sockd = cdata->serverfd[server]; sockd = cdata->serverfd[server];
client = recruit_client(cdata); client = recruit_client(cdata);
client->server = server; client->server = server;
address_len = sizeof(client->address); client->address = (struct sockaddr *)&client->address_storage;
fd = accept(sockd, &client->address, &address_len); address_len = sizeof(client->address_storage);
fd = accept(sockd, client->address, &address_len);
if (unlikely(fd < 0)) { if (unlikely(fd < 0)) {
/* Handle these errors gracefully should we ever share this /* Handle these errors gracefully should we ever share this
* socket */ * socket */
@ -206,17 +211,17 @@ static int accept_client(cdata_t *cdata, const int epfd, const uint64_t server)
return -1; return -1;
} }
switch (client->address.sa_family) { switch (client->address->sa_family) {
const struct sockaddr_in *inet4_in; const struct sockaddr_in *inet4_in;
const struct sockaddr_in6 *inet6_in; const struct sockaddr_in6 *inet6_in;
case AF_INET: case AF_INET:
inet4_in = (struct sockaddr_in *)&client->address; inet4_in = (struct sockaddr_in *)client->address;
inet_ntop(AF_INET, &inet4_in->sin_addr, client->address_name, INET6_ADDRSTRLEN); inet_ntop(AF_INET, &inet4_in->sin_addr, client->address_name, INET6_ADDRSTRLEN);
port = htons(inet4_in->sin_port); port = htons(inet4_in->sin_port);
break; break;
case AF_INET6: case AF_INET6:
inet6_in = (struct sockaddr_in6 *)&client->address; inet6_in = (struct sockaddr_in6 *)client->address;
inet_ntop(AF_INET6, &inet6_in->sin6_addr, client->address_name, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &inet6_in->sin6_addr, client->address_name, INET6_ADDRSTRLEN);
port = htons(inet6_in->sin6_port); port = htons(inet6_in->sin6_port);
break; break;
@ -556,6 +561,7 @@ out:
static bool send_sender_send(ckpool_t *ckp, cdata_t *cdata, sender_send_t *sender_send) static bool send_sender_send(ckpool_t *ckp, cdata_t *cdata, sender_send_t *sender_send)
{ {
client_instance_t *client = sender_send->client; client_instance_t *client = sender_send->client;
time_t now_t;
if (unlikely(client->invalid)) if (unlikely(client->invalid))
goto out_true; goto out_true;
@ -563,14 +569,26 @@ static bool send_sender_send(ckpool_t *ckp, cdata_t *cdata, sender_send_t *sende
/* Make sure we only send one message at a time to each client */ /* Make sure we only send one message at a time to each client */
if (unlikely(client->sending && client->sending != sender_send)) if (unlikely(client->sending && client->sending != sender_send))
return false; return false;
client->sending = sender_send; client->sending = sender_send;
now_t = time(NULL);
while (sender_send->len) { while (sender_send->len) {
int ret = write(client->fd, sender_send->buf + sender_send->ofs, sender_send->len); int ret = write(client->fd, sender_send->buf + sender_send->ofs, sender_send->len);
if (unlikely(ret < 1)) { if (unlikely(ret < 1)) {
if (errno == EAGAIN || errno == EWOULDBLOCK || !ret) /* Invalidate clients that block for more than 60 seconds */
if (unlikely(client->blocked_time && now_t - client->blocked_time >= 60)) {
LOGNOTICE("Client id %"PRId64" fd %d blocked for >60 seconds, disconnecting",
client->id, client->fd);
invalidate_client(ckp, cdata, client);
goto out_true;
}
if (errno == EAGAIN || errno == EWOULDBLOCK || !ret) {
if (!client->blocked_time)
client->blocked_time = now_t;
return false; return false;
}
LOGINFO("Client id %"PRId64" fd %d disconnected with write errno %d:%s", LOGINFO("Client id %"PRId64" fd %d disconnected with write errno %d:%s",
client->id, client->fd, errno, strerror(errno)); client->id, client->fd, errno, strerror(errno));
invalidate_client(ckp, cdata, client); invalidate_client(ckp, cdata, client);
@ -578,6 +596,7 @@ static bool send_sender_send(ckpool_t *ckp, cdata_t *cdata, sender_send_t *sende
} }
sender_send->ofs += ret; sender_send->ofs += ret;
sender_send->len -= ret; sender_send->len -= ret;
client->blocked_time = 0;
} }
out_true: out_true:
client->sending = NULL; client->sending = NULL;

9
src/libckpool.c

@ -570,14 +570,15 @@ out:
* INET6_ADDRSTRLEN size, port at least a string of 6 bytes */ * INET6_ADDRSTRLEN size, port at least a string of 6 bytes */
bool url_from_socket(const int sockd, char *url, char *port) bool url_from_socket(const int sockd, char *url, char *port)
{ {
socklen_t addrlen = sizeof(struct sockaddr); struct sockaddr_storage storage;
struct sockaddr addr; socklen_t addrlen = sizeof(struct sockaddr_storage);
struct sockaddr *addr = (struct sockaddr *)&storage;
if (sockd < 1) if (sockd < 1)
return false; return false;
if (getsockname(sockd, &addr, &addrlen)) if (getsockname(sockd, addr, &addrlen))
return false; return false;
if (!url_from_sockaddr(&addr, url, port)) if (!url_from_sockaddr(addr, url, port))
return false; return false;
return true; return true;
} }

313
src/stratifier.c

@ -28,10 +28,19 @@
#include "uthash.h" #include "uthash.h"
#include "utlist.h" #include "utlist.h"
#define MIN1 60
#define MIN5 300
#define MIN15 900
#define HOUR 3600
#define HOUR6 21600
#define DAY 86400
#define WEEK 604800
/* Consistent across all pool instances */ /* Consistent across all pool instances */
static const char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"; static const char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000";
static const char *scriptsig_header = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff"; static const char *scriptsig_header = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff";
static uchar scriptsig_header_bin[41]; static uchar scriptsig_header_bin[41];
static const double nonces = 4294967296;
/* Add unaccounted shares when they arrive, remove them with each update of /* Add unaccounted shares when they arrive, remove them with each update of
* rolling stats. */ * rolling stats. */
@ -173,12 +182,14 @@ struct user_instance {
double best_diff; /* Best share found by this user */ double best_diff; /* Best share found by this user */
int64_t shares;
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 */
double dsps1440; double dsps1440;
double dsps10080; double dsps10080;
tv_t last_share; tv_t last_share;
tv_t last_decay;
tv_t last_update; tv_t last_update;
bool authorised; /* Has this username ever been authorised? */ bool authorised; /* Has this username ever been authorised? */
@ -196,11 +207,14 @@ struct worker_instance {
worker_instance_t *next; worker_instance_t *next;
worker_instance_t *prev; worker_instance_t *prev;
int64_t shares;
double dsps1; double dsps1;
double dsps5; double dsps5;
double dsps60; double dsps60;
double dsps1440; double dsps1440;
double dsps10080;
tv_t last_share; tv_t last_share;
tv_t last_decay;
tv_t last_update; tv_t last_update;
time_t start_time; time_t start_time;
@ -241,6 +255,7 @@ struct stratum_instance {
int ssdc; /* Shares since diff change */ int ssdc; /* Shares since diff change */
tv_t first_share; tv_t first_share;
tv_t last_share; tv_t last_share;
tv_t last_decay;
time_t first_invalid; /* Time of first invalid in run of non stale rejects */ time_t first_invalid; /* Time of first invalid in run of non stale rejects */
time_t start_time; time_t start_time;
@ -679,10 +694,15 @@ static void _ckdbq_add(ckpool_t *ckp, const int idtype, json_t *val, const char
now_t = time(NULL); now_t = time(NULL);
if (now_t != time_counter) { if (now_t != time_counter) {
pool_stats_t *stats = &sdata->stats;
char hashrate[16];
/* Rate limit to 1 update per second */ /* Rate limit to 1 update per second */
time_counter = now_t; time_counter = now_t;
suffix_string(stats->dsps1 * nonces, hashrate, 16, 3);
ch = status_chars[(counter++) & 0x3]; ch = status_chars[(counter++) & 0x3];
fprintf(stdout, "%c\r", ch); fprintf(stdout, "\33[2K\r%c %sH/s %.1f SPS %d users %d workers",
ch, hashrate, stats->sps1, stats->users, stats->workers);
fflush(stdout); fflush(stdout);
} }
@ -1560,15 +1580,92 @@ static void reset_bestshares(sdata_t *sdata)
ck_runlock(&sdata->instance_lock); ck_runlock(&sdata->instance_lock);
} }
static user_instance_t *get_user(sdata_t *sdata, const char *username);
static user_instance_t *user_by_workername(sdata_t *sdata, const char *workername)
{
char *username = strdupa(workername), *ignore;
user_instance_t *user;
ignore = username;
strsep(&ignore, "._");
/* Find the user first */
user = get_user(sdata, username);
return user;
}
static worker_instance_t *get_worker(sdata_t *sdata, user_instance_t *user, const char *workername);
static json_t *worker_stats(const worker_instance_t *worker)
{
char suffix1[16], suffix5[16], suffix60[16], suffix1440[16], suffix10080[16];
json_t *val;
double ghs;
ghs = worker->dsps1 * nonces;
suffix_string(ghs, suffix1, 16, 0);
ghs = worker->dsps5 * nonces;
suffix_string(ghs, suffix5, 16, 0);
ghs = worker->dsps60 * nonces;
suffix_string(ghs, suffix60, 16, 0);
ghs = worker->dsps1440 * nonces;
suffix_string(ghs, suffix1440, 16, 0);
ghs = worker->dsps10080 * nonces;
suffix_string(ghs, suffix10080, 16, 0);
JSON_CPACK(val, "{ss,ss,ss,ss,ss}",
"hashrate1m", suffix1,
"hashrate5m", suffix5,
"hashrate1hr", suffix60,
"hashrate1d", suffix1440,
"hashrate7d", suffix10080);
return val;
}
static json_t *user_stats(const user_instance_t *user)
{
char suffix1[16], suffix5[16], suffix60[16], suffix1440[16], suffix10080[16];
json_t *val;
double ghs;
ghs = user->dsps1 * nonces;
suffix_string(ghs, suffix1, 16, 0);
ghs = user->dsps5 * nonces;
suffix_string(ghs, suffix5, 16, 0);
ghs = user->dsps60 * nonces;
suffix_string(ghs, suffix60, 16, 0);
ghs = user->dsps1440 * nonces;
suffix_string(ghs, suffix1440, 16, 0);
ghs = user->dsps10080 * nonces;
suffix_string(ghs, suffix10080, 16, 0);
JSON_CPACK(val, "{ss,ss,ss,ss,ss}",
"hashrate1m", suffix1,
"hashrate5m", suffix5,
"hashrate1hr", suffix60,
"hashrate1d", suffix1440,
"hashrate7d", suffix10080);
return val;
}
static void block_solve(ckpool_t *ckp, const char *blockhash) static void block_solve(ckpool_t *ckp, const char *blockhash)
{ {
ckmsg_t *block, *tmp, *found = NULL; ckmsg_t *block, *tmp, *found = NULL;
char *msg, *workername = NULL;
sdata_t *sdata = ckp->data; sdata_t *sdata = ckp->data;
char cdfield[64]; char cdfield[64];
int height = 0; int height = 0;
ts_t ts_now; ts_t ts_now;
json_t *val; json_t *val;
char *msg;
update_base(ckp, GEN_PRIORITY); update_base(ckp, GEN_PRIORITY);
@ -1587,6 +1684,7 @@ static void block_solve(ckpool_t *ckp, const char *blockhash)
} }
if (!strcmp(solvehash, blockhash)) { if (!strcmp(solvehash, blockhash)) {
dealloc(solvehash); dealloc(solvehash);
json_get_string(&workername, val, "workername");
found = block; found = block;
DL_DELETE(sdata->block_solves, block); DL_DELETE(sdata->block_solves, block);
break; break;
@ -1608,11 +1706,40 @@ static void block_solve(ckpool_t *ckp, const char *blockhash)
ckdbq_add(ckp, ID_BLOCK, val); ckdbq_add(ckp, ID_BLOCK, val);
free(found); free(found);
ASPRINTF(&msg, "Block %d solved by %s!", height, ckp->name); if (unlikely(!workername)) {
/* This should be impossible! */
ASPRINTF(&msg, "Block %d solved by %s!", height, ckp->name);
LOGWARNING("Solved and confirmed block %d", height);
} else {
json_t *user_val, *worker_val;
worker_instance_t *worker;
user_instance_t *user;
char *s;
ASPRINTF(&msg, "Block %d solved by %s @ %s!", height, workername, ckp->name);
LOGWARNING("Solved and confirmed block %d by %s", height, workername);
user = user_by_workername(sdata, workername);
worker = get_worker(sdata, user, workername);
ck_rlock(&sdata->instance_lock);
user_val = user_stats(user);
worker_val = worker_stats(worker);
ck_runlock(&sdata->instance_lock);
s = json_dumps(user_val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
json_decref(user_val);
LOGWARNING("User %s:%s", user->username, s);
dealloc(s);
s = json_dumps(worker_val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER);
json_decref(worker_val);
LOGWARNING("Worker %s:%s", workername, s);
dealloc(s);
}
stratum_broadcast_message(sdata, msg); stratum_broadcast_message(sdata, msg);
free(msg); free(msg);
LOGWARNING("Solved and confirmed block %d", height); free(workername);
reset_bestshares(sdata); reset_bestshares(sdata);
} }
@ -2076,8 +2203,6 @@ static bool test_address(ckpool_t *ckp, const char *address)
return ret; return ret;
} }
static const double nonces = 4294967296;
static double dsps_from_key(json_t *val, const char *key) static double dsps_from_key(json_t *val, const char *key)
{ {
char *string, *endptr; char *string, *endptr;
@ -2109,6 +2234,52 @@ static double dsps_from_key(json_t *val, const char *key)
return ret; return ret;
} }
/* Sanity check to prevent clock adjustments backwards from screwing up stats */
static double sane_tdiff(tv_t *end, tv_t *start)
{
double tdiff = tvdiff(end, start);
if (unlikely(tdiff < 0.001))
tdiff = 0.001;
return tdiff;
}
static void decay_client(stratum_instance_t *client, double diff, tv_t *now_t)
{
double tdiff = sane_tdiff(now_t, &client->last_decay);
decay_time(&client->dsps1, diff, tdiff, MIN1);
decay_time(&client->dsps5, diff, tdiff, MIN5);
decay_time(&client->dsps60, diff, tdiff, HOUR);
decay_time(&client->dsps1440, diff, tdiff, DAY);
decay_time(&client->dsps10080, diff, tdiff, WEEK);
copy_tv(&client->last_decay, now_t);
}
static void decay_worker(worker_instance_t *worker, double diff, tv_t *now_t)
{
double tdiff = sane_tdiff(now_t, &worker->last_decay);
decay_time(&worker->dsps1, diff, tdiff, MIN1);
decay_time(&worker->dsps5, diff, tdiff, MIN5);
decay_time(&worker->dsps60, diff, tdiff, HOUR);
decay_time(&worker->dsps1440, diff, tdiff, DAY);
decay_time(&worker->dsps10080, diff, tdiff, WEEK);
copy_tv(&worker->last_decay, now_t);
}
static void decay_user(user_instance_t *user, double diff, tv_t *now_t)
{
double tdiff = sane_tdiff(now_t, &user->last_decay);
decay_time(&user->dsps1, diff, tdiff, MIN1);
decay_time(&user->dsps5, diff, tdiff, MIN5);
decay_time(&user->dsps60, diff, tdiff, HOUR);
decay_time(&user->dsps1440, diff, tdiff, DAY);
decay_time(&user->dsps10080, diff, tdiff, WEEK);
copy_tv(&user->last_decay, now_t);
}
/* Enter holding a reference count */ /* Enter holding a reference count */
static void read_userstats(ckpool_t *ckp, user_instance_t *user) static void read_userstats(ckpool_t *ckp, user_instance_t *user)
{ {
@ -2139,12 +2310,14 @@ static void read_userstats(ckpool_t *ckp, user_instance_t *user)
tv_time(&now); tv_time(&now);
copy_tv(&user->last_share, &now); copy_tv(&user->last_share, &now);
copy_tv(&user->last_decay, &now);
user->dsps1 = dsps_from_key(val, "hashrate1m"); user->dsps1 = dsps_from_key(val, "hashrate1m");
user->dsps5 = dsps_from_key(val, "hashrate5m"); user->dsps5 = dsps_from_key(val, "hashrate5m");
user->dsps60 = dsps_from_key(val, "hashrate1hr"); user->dsps60 = dsps_from_key(val, "hashrate1hr");
user->dsps1440 = dsps_from_key(val, "hashrate1d"); user->dsps1440 = dsps_from_key(val, "hashrate1d");
user->dsps10080 = dsps_from_key(val, "hashrate7d"); user->dsps10080 = dsps_from_key(val, "hashrate7d");
json_get_int64(&user->last_update.tv_sec, val, "lastupdate"); json_get_int64(&user->last_update.tv_sec, val, "lastupdate");
json_get_int64(&user->shares, val, "shares");
json_get_double(&user->best_diff, val, "bestshare"); json_get_double(&user->best_diff, val, "bestshare");
LOGINFO("Successfully read user %s stats %f %f %f %f %f %f", user->username, LOGINFO("Successfully read user %s stats %f %f %f %f %f %f", user->username,
user->dsps1, user->dsps5, user->dsps60, user->dsps1440, user->dsps1, user->dsps5, user->dsps60, user->dsps1440,
@ -2155,11 +2328,7 @@ static void read_userstats(ckpool_t *ckp, user_instance_t *user)
if (tvsec_diff > 60) { if (tvsec_diff > 60) {
LOGINFO("Old user stats indicate not logged for %d seconds, decaying stats", LOGINFO("Old user stats indicate not logged for %d seconds, decaying stats",
tvsec_diff); tvsec_diff);
decay_time(&user->dsps1, 0, tvsec_diff, 60); decay_user(user, 0, &now);
decay_time(&user->dsps5, 0, tvsec_diff, 300);
decay_time(&user->dsps60, 0, tvsec_diff, 3600);
decay_time(&user->dsps1440, 0, tvsec_diff, 86400);
decay_time(&user->dsps10080, 0, tvsec_diff, 604800);
} }
} }
@ -2193,12 +2362,15 @@ static void read_workerstats(ckpool_t *ckp, worker_instance_t *worker)
tv_time(&now); tv_time(&now);
copy_tv(&worker->last_share, &now); copy_tv(&worker->last_share, &now);
copy_tv(&worker->last_decay, &now);
worker->dsps1 = dsps_from_key(val, "hashrate1m"); worker->dsps1 = dsps_from_key(val, "hashrate1m");
worker->dsps5 = dsps_from_key(val, "hashrate5m"); worker->dsps5 = dsps_from_key(val, "hashrate5m");
worker->dsps60 = dsps_from_key(val, "hashrate1d"); worker->dsps60 = dsps_from_key(val, "hashrate1d");
worker->dsps1440 = dsps_from_key(val, "hashrate1d"); worker->dsps1440 = dsps_from_key(val, "hashrate1d");
worker->dsps10080 = dsps_from_key(val, "hashrate7d");
json_get_double(&worker->best_diff, val, "bestshare"); json_get_double(&worker->best_diff, val, "bestshare");
json_get_int64(&worker->last_update.tv_sec, val, "lastupdate"); json_get_int64(&worker->last_update.tv_sec, val, "lastupdate");
json_get_int64(&worker->shares, val, "shares");
LOGINFO("Successfully read worker %s stats %f %f %f %f %f", worker->workername, LOGINFO("Successfully read worker %s stats %f %f %f %f %f", worker->workername,
worker->dsps1, worker->dsps5, worker->dsps60, worker->dsps1440, worker->best_diff); worker->dsps1, worker->dsps5, worker->dsps60, worker->dsps1440, worker->best_diff);
json_decref(val); json_decref(val);
@ -2207,10 +2379,7 @@ static void read_workerstats(ckpool_t *ckp, worker_instance_t *worker)
if (tvsec_diff > 60) { if (tvsec_diff > 60) {
LOGINFO("Old worker stats indicate not logged for %d seconds, decaying stats", LOGINFO("Old worker stats indicate not logged for %d seconds, decaying stats",
tvsec_diff); tvsec_diff);
decay_time(&worker->dsps1, 0, tvsec_diff, 60); decay_worker(worker, 0, &now);
decay_time(&worker->dsps5, 0, tvsec_diff, 300);
decay_time(&worker->dsps60, 0, tvsec_diff, 3600);
decay_time(&worker->dsps1440, 0, tvsec_diff, 86400);
} }
} }
@ -2636,16 +2805,6 @@ static double time_bias(const double tdiff, const double period)
return 1.0 - 1.0 / exp(dexp); return 1.0 - 1.0 / exp(dexp);
} }
/* Sanity check to prevent clock adjustments backwards from screwing up stats */
static double sane_tdiff(tv_t *end, tv_t *start)
{
double tdiff = tvdiff(end, start);
if (unlikely(tdiff < 0.001))
tdiff = 0.001;
return tdiff;
}
/* Needs to be entered with client holding a ref count. */ /* Needs to be entered with client holding a ref count. */
static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff, const bool valid, static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff, const bool valid,
const bool submit) const bool submit)
@ -2666,7 +2825,10 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff
mutex_unlock(&sdata->stats_lock); mutex_unlock(&sdata->stats_lock);
/* Count only accepted and stale rejects in diff calculation. */ /* Count only accepted and stale rejects in diff calculation. */
if (!valid && !submit) if (valid) {
worker->shares += diff;
user->shares += diff;
} else if (!submit)
return; return;
tv_time(&now_t); tv_time(&now_t);
@ -2684,28 +2846,14 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff
copy_tv(&client->ldc, &now_t); copy_tv(&client->ldc, &now_t);
} }
tdiff = sane_tdiff(&now_t, &client->last_share); decay_client(client, diff, &now_t);
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);
decay_time(&client->dsps10080, diff, tdiff, 604800);
copy_tv(&client->last_share, &now_t); copy_tv(&client->last_share, &now_t);
tdiff = sane_tdiff(&now_t, &worker->last_share); decay_worker(worker, diff, &now_t);
decay_time(&worker->dsps1, diff, tdiff, 60);
decay_time(&worker->dsps5, diff, tdiff, 300);
decay_time(&worker->dsps60, diff, tdiff, 3600);
decay_time(&worker->dsps1440, diff, tdiff, 86400);
copy_tv(&worker->last_share, &now_t); copy_tv(&worker->last_share, &now_t);
worker->idle = false; worker->idle = false;
tdiff = sane_tdiff(&now_t, &user->last_share); decay_user(user, diff, &now_t);
decay_time(&user->dsps1, diff, tdiff, 60);
decay_time(&user->dsps5, diff, tdiff, 300);
decay_time(&user->dsps60, diff, tdiff, 3600);
decay_time(&user->dsps1440, diff, tdiff, 86400);
decay_time(&user->dsps10080, diff, tdiff, 604800);
copy_tv(&user->last_share, &now_t); copy_tv(&user->last_share, &now_t);
client->idle = false; client->idle = false;
@ -3302,17 +3450,13 @@ static json_params_t
static void set_worker_mindiff(ckpool_t *ckp, const char *workername, int mindiff) static void set_worker_mindiff(ckpool_t *ckp, const char *workername, int mindiff)
{ {
char *username = strdupa(workername), *ignore;
stratum_instance_t *client; stratum_instance_t *client;
sdata_t *sdata = ckp->data; sdata_t *sdata = ckp->data;
worker_instance_t *worker; worker_instance_t *worker;
user_instance_t *user; user_instance_t *user;
ignore = username;
strsep(&ignore, "._");
/* Find the user first */ /* Find the user first */
user = get_user(sdata, username); user = user_by_workername(sdata, workername);
/* Then find the matching worker user */ /* Then find the matching worker user */
worker = get_worker(sdata, user, workername); worker = get_worker(sdata, user, workername);
@ -4110,11 +4254,7 @@ static void *statsupdate(void *arg)
/* Decay times per connected instance */ /* Decay times per connected instance */
if (per_tdiff > 60) { if (per_tdiff > 60) {
/* No shares for over a minute, decay to 0 */ /* No shares for over a minute, decay to 0 */
decay_time(&client->dsps1, 0, per_tdiff, 60); decay_client(client, 0, &now);
decay_time(&client->dsps5, 0, per_tdiff, 300);
decay_time(&client->dsps60, 0, per_tdiff, 3600);
decay_time(&client->dsps1440, 0, per_tdiff, 86400);
decay_time(&client->dsps10080, 0, per_tdiff, 604800);
idle_workers++; idle_workers++;
if (per_tdiff > 600) if (per_tdiff > 600)
client->idle = true; client->idle = true;
@ -4133,10 +4273,7 @@ static void *statsupdate(void *arg)
DL_FOREACH(user->worker_instances, worker) { DL_FOREACH(user->worker_instances, worker) {
per_tdiff = tvdiff(&now, &worker->last_share); per_tdiff = tvdiff(&now, &worker->last_share);
if (per_tdiff > 60) { if (per_tdiff > 60) {
decay_time(&worker->dsps1, 0, per_tdiff, 60); decay_worker(worker, 0, &now);
decay_time(&worker->dsps5, 0, per_tdiff, 300);
decay_time(&worker->dsps60, 0, per_tdiff, 3600);
decay_time(&worker->dsps1440, 0, per_tdiff, 86400);
worker->idle = true; worker->idle = true;
} }
ghs = worker->dsps1 * nonces; ghs = worker->dsps1 * nonces;
@ -4151,14 +4288,19 @@ 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);
ghs = worker->dsps10080 * nonces;
suffix_string(ghs, suffix10080, 16, 0);
copy_tv(&worker->last_update, &now); copy_tv(&worker->last_update, &now);
JSON_CPACK(val, "{ss,ss,ss,ss,si,sf}", JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,sI,sf}",
"hashrate1m", suffix1, "hashrate1m", suffix1,
"hashrate5m", suffix5, "hashrate5m", suffix5,
"hashrate1hr", suffix60, "hashrate1hr", suffix60,
"hashrate1d", suffix1440, "hashrate1d", suffix1440,
"hashrate7d", suffix10080,
"lastupdate", now.tv_sec, "lastupdate", now.tv_sec,
"shares", worker->shares,
"bestshare", worker->best_diff); "bestshare", worker->best_diff);
ASPRINTF(&fname, "%s/workers/%s", ckp->logdir, worker->workername); ASPRINTF(&fname, "%s/workers/%s", ckp->logdir, worker->workername);
@ -4170,11 +4312,7 @@ static void *statsupdate(void *arg)
/* Decay times per user */ /* Decay times per user */
per_tdiff = tvdiff(&now, &user->last_share); per_tdiff = tvdiff(&now, &user->last_share);
if (per_tdiff > 60) { if (per_tdiff > 60) {
decay_time(&user->dsps1, 0, per_tdiff, 60); decay_user(user, 0, &now);
decay_time(&user->dsps5, 0, per_tdiff, 300);
decay_time(&user->dsps60, 0, per_tdiff, 3600);
decay_time(&user->dsps1440, 0, per_tdiff, 86400);
decay_time(&user->dsps10080, 0, per_tdiff, 604800);
idle = true; idle = true;
} }
ghs = user->dsps1 * nonces; ghs = user->dsps1 * nonces;
@ -4194,7 +4332,7 @@ static void *statsupdate(void *arg)
copy_tv(&user->last_update, &now); copy_tv(&user->last_update, &now);
JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,si,sf}", JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,si,sI,sf}",
"hashrate1m", suffix1, "hashrate1m", suffix1,
"hashrate5m", suffix5, "hashrate5m", suffix5,
"hashrate1hr", suffix60, "hashrate1hr", suffix60,
@ -4202,6 +4340,7 @@ static void *statsupdate(void *arg)
"hashrate7d", suffix10080, "hashrate7d", suffix10080,
"lastupdate", now.tv_sec, "lastupdate", now.tv_sec,
"workers", user->workers, "workers", user->workers,
"shares", user->shares,
"bestshare", user->best_diff); "bestshare", user->best_diff);
ASPRINTF(&fname, "%s/users/%s", ckp->logdir, user->username); ASPRINTF(&fname, "%s/users/%s", ckp->logdir, user->username);
@ -4323,18 +4462,18 @@ static void *statsupdate(void *arg)
stats->accounted_diff_shares += stats->unaccounted_diff_shares; stats->accounted_diff_shares += stats->unaccounted_diff_shares;
stats->accounted_rejects += stats->unaccounted_rejects; stats->accounted_rejects += stats->unaccounted_rejects;
decay_time(&stats->sps1, stats->unaccounted_shares, 1.875, 60); decay_time(&stats->sps1, stats->unaccounted_shares, 1.875, MIN1);
decay_time(&stats->sps5, stats->unaccounted_shares, 1.875, 300); decay_time(&stats->sps5, stats->unaccounted_shares, 1.875, MIN5);
decay_time(&stats->sps15, stats->unaccounted_shares, 1.875, 900); decay_time(&stats->sps15, stats->unaccounted_shares, 1.875, MIN15);
decay_time(&stats->sps60, stats->unaccounted_shares, 1.875, 3600); decay_time(&stats->sps60, stats->unaccounted_shares, 1.875, HOUR);
decay_time(&stats->dsps1, stats->unaccounted_diff_shares, 1.875, 60); decay_time(&stats->dsps1, stats->unaccounted_diff_shares, 1.875, MIN1);
decay_time(&stats->dsps5, stats->unaccounted_diff_shares, 1.875, 300); decay_time(&stats->dsps5, stats->unaccounted_diff_shares, 1.875, MIN5);
decay_time(&stats->dsps15, stats->unaccounted_diff_shares, 1.875, 900); decay_time(&stats->dsps15, stats->unaccounted_diff_shares, 1.875, MIN15);
decay_time(&stats->dsps60, stats->unaccounted_diff_shares, 1.875, 3600); decay_time(&stats->dsps60, stats->unaccounted_diff_shares, 1.875, HOUR);
decay_time(&stats->dsps360, stats->unaccounted_diff_shares, 1.875, 21600); decay_time(&stats->dsps360, stats->unaccounted_diff_shares, 1.875, HOUR6);
decay_time(&stats->dsps1440, stats->unaccounted_diff_shares, 1.875, 86400); decay_time(&stats->dsps1440, stats->unaccounted_diff_shares, 1.875, DAY);
decay_time(&stats->dsps10080, stats->unaccounted_diff_shares, 1.875, 604800); decay_time(&stats->dsps10080, stats->unaccounted_diff_shares, 1.875, WEEK);
stats->unaccounted_shares = stats->unaccounted_shares =
stats->unaccounted_diff_shares = stats->unaccounted_diff_shares =
@ -4453,18 +4592,18 @@ static void read_poolstats(ckpool_t *ckp)
if (tvsec_diff > 60) { if (tvsec_diff > 60) {
LOGNOTICE("Old pool stats indicate pool down for %d seconds, decaying stats", LOGNOTICE("Old pool stats indicate pool down for %d seconds, decaying stats",
tvsec_diff); tvsec_diff);
decay_time(&stats->sps1, 0, tvsec_diff, 60); decay_time(&stats->sps1, 0, tvsec_diff, MIN1);
decay_time(&stats->sps5, 0, tvsec_diff, 300); decay_time(&stats->sps5, 0, tvsec_diff, MIN5);
decay_time(&stats->sps15, 0, tvsec_diff, 900); decay_time(&stats->sps15, 0, tvsec_diff, MIN15);
decay_time(&stats->sps60, 0, tvsec_diff, 3600); decay_time(&stats->sps60, 0, tvsec_diff, HOUR);
decay_time(&stats->dsps1, 0, tvsec_diff, 60); decay_time(&stats->dsps1, 0, tvsec_diff, MIN1);
decay_time(&stats->dsps5, 0, tvsec_diff, 300); decay_time(&stats->dsps5, 0, tvsec_diff, MIN5);
decay_time(&stats->dsps15, 0, tvsec_diff, 900); decay_time(&stats->dsps15, 0, tvsec_diff, MIN15);
decay_time(&stats->dsps60, 0, tvsec_diff, 3600); decay_time(&stats->dsps60, 0, tvsec_diff, HOUR);
decay_time(&stats->dsps360, 0, tvsec_diff, 21600); decay_time(&stats->dsps360, 0, tvsec_diff, HOUR6);
decay_time(&stats->dsps1440, 0, tvsec_diff, 86400); decay_time(&stats->dsps1440, 0, tvsec_diff, DAY);
decay_time(&stats->dsps10080, 0, tvsec_diff, 604800); decay_time(&stats->dsps10080, 0, tvsec_diff, WEEK);
} }
} }

Loading…
Cancel
Save