diff --git a/src/ckpool.c b/src/ckpool.c index 6fbffb98..a57adb34 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -84,6 +84,7 @@ void logmsg(int loglevel, const char *fmt, ...) { tm.tm_min, tm.tm_sec, ms); if (loglevel <= LOG_WARNING) { + fprintf(stderr, "\33[2K\r"); if (loglevel <= LOG_ERR && errno != 0) fprintf(stderr, "%s %s with errno %d: %s\n", stamp, buf, errno, strerror(errno)); else @@ -1467,7 +1468,8 @@ static bool send_recv_path(const char *path, const char *msg) ret = true; LOGWARNING("Received: %s in response to %s request", response, msg); dealloc(response); - } + } else + LOGWARNING("Received not response to %s request", msg); Close(sockd); return ret; } @@ -1707,6 +1709,7 @@ int main(int argc, char **argv) if (send_recv_path(path, "ping")) { for (i = 0; i < ckp.serverurls; i++) { + char oldurl[INET6_ADDRSTRLEN], oldport[8]; char getfd[16]; int sockd; @@ -1718,10 +1721,16 @@ int main(int argc, char **argv) break; ckp.oldconnfd[i] = get_fd(sockd); Close(sockd); - if (!ckp.oldconnfd[i]) + sockd = ckp.oldconnfd[i]; + if (!sockd) break; - LOGWARNING("Inherited old server socket %d with new file descriptor %d!", - i, ckp.oldconnfd[i]); + if (url_from_socket(sockd, oldurl, oldport)) { + 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, "reconnect"); diff --git a/src/connector.c b/src/connector.c index a7b776ab..6ddd3f53 100644 --- a/src/connector.c +++ b/src/connector.c @@ -45,7 +45,8 @@ struct client_instance { client_instance_t *next; client_instance_t *prev; - struct sockaddr address; + struct sockaddr_storage address_storage; + struct sockaddr *address; char address_name[INET6_ADDRSTRLEN]; /* Which serverurl is this instance connected to */ @@ -57,6 +58,9 @@ struct client_instance { /* Are we currently sending a blocked message from this client */ sender_send_t *sending; bool passthrough; + + /* Time this client started blocking, 0 when not blocked */ + time_t blocked_time; }; 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]; client = recruit_client(cdata); client->server = server; - address_len = sizeof(client->address); - fd = accept(sockd, &client->address, &address_len); + client->address = (struct sockaddr *)&client->address_storage; + address_len = sizeof(client->address_storage); + fd = accept(sockd, client->address, &address_len); if (unlikely(fd < 0)) { /* Handle these errors gracefully should we ever share this * socket */ @@ -206,17 +211,17 @@ static int accept_client(cdata_t *cdata, const int epfd, const uint64_t server) return -1; } - switch (client->address.sa_family) { + switch (client->address->sa_family) { const struct sockaddr_in *inet4_in; const struct sockaddr_in6 *inet6_in; 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); port = htons(inet4_in->sin_port); break; 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); port = htons(inet6_in->sin6_port); break; @@ -556,6 +561,7 @@ out: static bool send_sender_send(ckpool_t *ckp, cdata_t *cdata, sender_send_t *sender_send) { client_instance_t *client = sender_send->client; + time_t now_t; if (unlikely(client->invalid)) 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 */ if (unlikely(client->sending && client->sending != sender_send)) return false; + client->sending = sender_send; + now_t = time(NULL); while (sender_send->len) { int ret = write(client->fd, sender_send->buf + sender_send->ofs, sender_send->len); 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; + } LOGINFO("Client id %"PRId64" fd %d disconnected with write errno %d:%s", client->id, client->fd, errno, strerror(errno)); 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->len -= ret; + client->blocked_time = 0; } out_true: client->sending = NULL; diff --git a/src/libckpool.c b/src/libckpool.c index 91799eff..0c1b891e 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -570,14 +570,15 @@ out: * INET6_ADDRSTRLEN size, port at least a string of 6 bytes */ bool url_from_socket(const int sockd, char *url, char *port) { - socklen_t addrlen = sizeof(struct sockaddr); - struct sockaddr addr; + struct sockaddr_storage storage; + socklen_t addrlen = sizeof(struct sockaddr_storage); + struct sockaddr *addr = (struct sockaddr *)&storage; if (sockd < 1) return false; - if (getsockname(sockd, &addr, &addrlen)) + if (getsockname(sockd, addr, &addrlen)) return false; - if (!url_from_sockaddr(&addr, url, port)) + if (!url_from_sockaddr(addr, url, port)) return false; return true; } diff --git a/src/stratifier.c b/src/stratifier.c index 7073f97a..f93d0f99 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -28,10 +28,19 @@ #include "uthash.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 */ static const char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"; static const char *scriptsig_header = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff"; static uchar scriptsig_header_bin[41]; +static const double nonces = 4294967296; /* Add unaccounted shares when they arrive, remove them with each update of * rolling stats. */ @@ -173,12 +182,14 @@ struct user_instance { double best_diff; /* Best share found by this user */ + int64_t shares; double dsps1; /* Diff shares per second, 1 minute rolling average */ double dsps5; /* ... 5 minute ... */ double dsps60;/* etc */ double dsps1440; double dsps10080; tv_t last_share; + tv_t last_decay; tv_t last_update; bool authorised; /* Has this username ever been authorised? */ @@ -196,11 +207,14 @@ struct worker_instance { worker_instance_t *next; worker_instance_t *prev; + int64_t shares; double dsps1; double dsps5; double dsps60; double dsps1440; + double dsps10080; tv_t last_share; + tv_t last_decay; tv_t last_update; time_t start_time; @@ -241,6 +255,7 @@ struct stratum_instance { int ssdc; /* Shares since diff change */ tv_t first_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 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); if (now_t != time_counter) { + pool_stats_t *stats = &sdata->stats; + char hashrate[16]; + /* Rate limit to 1 update per second */ time_counter = now_t; + suffix_string(stats->dsps1 * nonces, hashrate, 16, 3); 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); } @@ -1560,15 +1580,92 @@ static void reset_bestshares(sdata_t *sdata) 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) { ckmsg_t *block, *tmp, *found = NULL; + char *msg, *workername = NULL; sdata_t *sdata = ckp->data; char cdfield[64]; int height = 0; ts_t ts_now; json_t *val; - char *msg; update_base(ckp, GEN_PRIORITY); @@ -1587,6 +1684,7 @@ static void block_solve(ckpool_t *ckp, const char *blockhash) } if (!strcmp(solvehash, blockhash)) { dealloc(solvehash); + json_get_string(&workername, val, "workername"); found = block; DL_DELETE(sdata->block_solves, block); break; @@ -1608,11 +1706,40 @@ static void block_solve(ckpool_t *ckp, const char *blockhash) ckdbq_add(ckp, ID_BLOCK, val); 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); free(msg); - LOGWARNING("Solved and confirmed block %d", height); + free(workername); + reset_bestshares(sdata); } @@ -2076,8 +2203,6 @@ static bool test_address(ckpool_t *ckp, const char *address) return ret; } -static const double nonces = 4294967296; - static double dsps_from_key(json_t *val, const char *key) { char *string, *endptr; @@ -2109,6 +2234,52 @@ static double dsps_from_key(json_t *val, const char *key) 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 */ 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); copy_tv(&user->last_share, &now); + copy_tv(&user->last_decay, &now); user->dsps1 = dsps_from_key(val, "hashrate1m"); user->dsps5 = dsps_from_key(val, "hashrate5m"); user->dsps60 = dsps_from_key(val, "hashrate1hr"); user->dsps1440 = dsps_from_key(val, "hashrate1d"); user->dsps10080 = dsps_from_key(val, "hashrate7d"); 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"); LOGINFO("Successfully read user %s stats %f %f %f %f %f %f", user->username, 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) { LOGINFO("Old user stats indicate not logged for %d seconds, decaying stats", tvsec_diff); - decay_time(&user->dsps1, 0, tvsec_diff, 60); - 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); + decay_user(user, 0, &now); } } @@ -2193,12 +2362,15 @@ static void read_workerstats(ckpool_t *ckp, worker_instance_t *worker) tv_time(&now); copy_tv(&worker->last_share, &now); + copy_tv(&worker->last_decay, &now); worker->dsps1 = dsps_from_key(val, "hashrate1m"); worker->dsps5 = dsps_from_key(val, "hashrate5m"); worker->dsps60 = 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_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, worker->dsps1, worker->dsps5, worker->dsps60, worker->dsps1440, worker->best_diff); json_decref(val); @@ -2207,10 +2379,7 @@ static void read_workerstats(ckpool_t *ckp, worker_instance_t *worker) if (tvsec_diff > 60) { LOGINFO("Old worker stats indicate not logged for %d seconds, decaying stats", tvsec_diff); - decay_time(&worker->dsps1, 0, tvsec_diff, 60); - decay_time(&worker->dsps5, 0, tvsec_diff, 300); - decay_time(&worker->dsps60, 0, tvsec_diff, 3600); - decay_time(&worker->dsps1440, 0, tvsec_diff, 86400); + decay_worker(worker, 0, &now); } } @@ -2636,16 +2805,6 @@ static double time_bias(const double tdiff, const double period) 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. */ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff, const bool valid, 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); /* Count only accepted and stale rejects in diff calculation. */ - if (!valid && !submit) + if (valid) { + worker->shares += diff; + user->shares += diff; + } else if (!submit) return; 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); } - 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); - decay_time(&client->dsps10080, diff, tdiff, 604800); + decay_client(client, diff, &now_t); copy_tv(&client->last_share, &now_t); - tdiff = sane_tdiff(&now_t, &worker->last_share); - 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); + decay_worker(worker, diff, &now_t); copy_tv(&worker->last_share, &now_t); worker->idle = false; - tdiff = sane_tdiff(&now_t, &user->last_share); - 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); + decay_user(user, diff, &now_t); copy_tv(&user->last_share, &now_t); client->idle = false; @@ -3302,17 +3450,13 @@ static json_params_t static void set_worker_mindiff(ckpool_t *ckp, const char *workername, int mindiff) { - char *username = strdupa(workername), *ignore; stratum_instance_t *client; sdata_t *sdata = ckp->data; worker_instance_t *worker; user_instance_t *user; - ignore = username; - strsep(&ignore, "._"); - /* Find the user first */ - user = get_user(sdata, username); + user = user_by_workername(sdata, workername); /* Then find the matching worker user */ worker = get_worker(sdata, user, workername); @@ -4110,11 +4254,7 @@ static void *statsupdate(void *arg) /* Decay times per connected instance */ if (per_tdiff > 60) { /* No shares for over a minute, decay to 0 */ - decay_time(&client->dsps1, 0, per_tdiff, 60); - 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); + decay_client(client, 0, &now); idle_workers++; if (per_tdiff > 600) client->idle = true; @@ -4133,10 +4273,7 @@ static void *statsupdate(void *arg) DL_FOREACH(user->worker_instances, worker) { per_tdiff = tvdiff(&now, &worker->last_share); if (per_tdiff > 60) { - decay_time(&worker->dsps1, 0, per_tdiff, 60); - decay_time(&worker->dsps5, 0, per_tdiff, 300); - decay_time(&worker->dsps60, 0, per_tdiff, 3600); - decay_time(&worker->dsps1440, 0, per_tdiff, 86400); + decay_worker(worker, 0, &now); worker->idle = true; } ghs = worker->dsps1 * nonces; @@ -4151,14 +4288,19 @@ static void *statsupdate(void *arg) ghs = worker->dsps1440 * nonces; suffix_string(ghs, suffix1440, 16, 0); + ghs = worker->dsps10080 * nonces; + suffix_string(ghs, suffix10080, 16, 0); + 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, "hashrate5m", suffix5, "hashrate1hr", suffix60, "hashrate1d", suffix1440, + "hashrate7d", suffix10080, "lastupdate", now.tv_sec, + "shares", worker->shares, "bestshare", worker->best_diff); ASPRINTF(&fname, "%s/workers/%s", ckp->logdir, worker->workername); @@ -4170,11 +4312,7 @@ static void *statsupdate(void *arg) /* Decay times per user */ per_tdiff = tvdiff(&now, &user->last_share); if (per_tdiff > 60) { - decay_time(&user->dsps1, 0, per_tdiff, 60); - 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); + decay_user(user, 0, &now); idle = true; } ghs = user->dsps1 * nonces; @@ -4194,7 +4332,7 @@ static void *statsupdate(void *arg) 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, "hashrate5m", suffix5, "hashrate1hr", suffix60, @@ -4202,6 +4340,7 @@ static void *statsupdate(void *arg) "hashrate7d", suffix10080, "lastupdate", now.tv_sec, "workers", user->workers, + "shares", user->shares, "bestshare", user->best_diff); 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_rejects += stats->unaccounted_rejects; - decay_time(&stats->sps1, stats->unaccounted_shares, 1.875, 60); - decay_time(&stats->sps5, stats->unaccounted_shares, 1.875, 300); - decay_time(&stats->sps15, stats->unaccounted_shares, 1.875, 900); - decay_time(&stats->sps60, stats->unaccounted_shares, 1.875, 3600); + decay_time(&stats->sps1, stats->unaccounted_shares, 1.875, MIN1); + decay_time(&stats->sps5, stats->unaccounted_shares, 1.875, MIN5); + decay_time(&stats->sps15, stats->unaccounted_shares, 1.875, MIN15); + decay_time(&stats->sps60, stats->unaccounted_shares, 1.875, HOUR); - decay_time(&stats->dsps1, stats->unaccounted_diff_shares, 1.875, 60); - decay_time(&stats->dsps5, stats->unaccounted_diff_shares, 1.875, 300); - decay_time(&stats->dsps15, stats->unaccounted_diff_shares, 1.875, 900); - decay_time(&stats->dsps60, stats->unaccounted_diff_shares, 1.875, 3600); - decay_time(&stats->dsps360, stats->unaccounted_diff_shares, 1.875, 21600); - decay_time(&stats->dsps1440, stats->unaccounted_diff_shares, 1.875, 86400); - decay_time(&stats->dsps10080, stats->unaccounted_diff_shares, 1.875, 604800); + decay_time(&stats->dsps1, stats->unaccounted_diff_shares, 1.875, MIN1); + decay_time(&stats->dsps5, stats->unaccounted_diff_shares, 1.875, MIN5); + decay_time(&stats->dsps15, stats->unaccounted_diff_shares, 1.875, MIN15); + decay_time(&stats->dsps60, stats->unaccounted_diff_shares, 1.875, HOUR); + decay_time(&stats->dsps360, stats->unaccounted_diff_shares, 1.875, HOUR6); + decay_time(&stats->dsps1440, stats->unaccounted_diff_shares, 1.875, DAY); + decay_time(&stats->dsps10080, stats->unaccounted_diff_shares, 1.875, WEEK); stats->unaccounted_shares = stats->unaccounted_diff_shares = @@ -4453,18 +4592,18 @@ static void read_poolstats(ckpool_t *ckp) if (tvsec_diff > 60) { LOGNOTICE("Old pool stats indicate pool down for %d seconds, decaying stats", tvsec_diff); - decay_time(&stats->sps1, 0, tvsec_diff, 60); - decay_time(&stats->sps5, 0, tvsec_diff, 300); - decay_time(&stats->sps15, 0, tvsec_diff, 900); - decay_time(&stats->sps60, 0, tvsec_diff, 3600); - - decay_time(&stats->dsps1, 0, tvsec_diff, 60); - decay_time(&stats->dsps5, 0, tvsec_diff, 300); - decay_time(&stats->dsps15, 0, tvsec_diff, 900); - decay_time(&stats->dsps60, 0, tvsec_diff, 3600); - decay_time(&stats->dsps360, 0, tvsec_diff, 21600); - decay_time(&stats->dsps1440, 0, tvsec_diff, 86400); - decay_time(&stats->dsps10080, 0, tvsec_diff, 604800); + decay_time(&stats->sps1, 0, tvsec_diff, MIN1); + decay_time(&stats->sps5, 0, tvsec_diff, MIN5); + decay_time(&stats->sps15, 0, tvsec_diff, MIN15); + decay_time(&stats->sps60, 0, tvsec_diff, HOUR); + + decay_time(&stats->dsps1, 0, tvsec_diff, MIN1); + decay_time(&stats->dsps5, 0, tvsec_diff, MIN5); + decay_time(&stats->dsps15, 0, tvsec_diff, MIN15); + decay_time(&stats->dsps60, 0, tvsec_diff, HOUR); + decay_time(&stats->dsps360, 0, tvsec_diff, HOUR6); + decay_time(&stats->dsps1440, 0, tvsec_diff, DAY); + decay_time(&stats->dsps10080, 0, tvsec_diff, WEEK); } }