From 43dc33a54caefc130570d403d8f95e89efa88c04 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 13 Jan 2015 16:07:59 +1100 Subject: [PATCH 01/39] Age and discard old disconnected instance data after it's been used or no longer relevant --- src/stratifier.c | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 0b974d5f..20c4f4a5 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -255,6 +255,7 @@ struct stratum_instance { ckpool_t *ckp; 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 */ double best_diff; /* Best share found by this instance */ @@ -1102,6 +1103,14 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, int64_t id, int 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 */ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, int64_t id) { @@ -1116,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 */ hex2bin(&session64, sessionid, 8); - ck_rlock(&sdata->instance_lock); + ck_ilock(&sdata->instance_lock); HASH_ITER(hh, sdata->stratum_instances, instance, tmp) { if (instance->id == id) continue; @@ -1127,10 +1136,18 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, } instance = NULL; 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; + } out_unlock: - ck_runlock(&sdata->instance_lock); + ck_uilock(&sdata->instance_lock); out: return ret; } @@ -1213,6 +1230,7 @@ static void dec_worker(ckpool_t *ckp, user_instance_t *instance) static void drop_client(sdata_t *sdata, int64_t id) { stratum_instance_t *client, *tmp; + time_t now_t = time(NULL); bool dec = false; LOGINFO("Stratifier dropping client %ld", id); @@ -1231,13 +1249,11 @@ static void drop_client(sdata_t *sdata, int64_t id) HASH_DEL(sdata->stratum_instances, 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 */ - 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); - else { - if (client->user_instance) - DL_DELETE(client->user_instance->instances, client); - LL_PREPEND(sdata->dead_instances, client); - } + client->disconnected_time = time(NULL); + } else + kill_instance(sdata, client); } ck_wunlock(&sdata->instance_lock); @@ -1251,6 +1267,18 @@ static void drop_client(sdata_t *sdata, int64_t id) ck_wlock(&sdata->instance_lock); if (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) { if (!client->ref) { LOGINFO("Stratifier discarding instance %ld", client->id); From 4103a3bae8862d505c6eba817c071480f579aab7 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 13 Jan 2015 16:30:52 +1100 Subject: [PATCH 02/39] Tell the stratifier to drop a client if the connector is told to drop it and cannot find it any more --- src/connector.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/connector.c b/src/connector.c index c23173e1..235ca6de 100644 --- a/src/connector.c +++ b/src/connector.c @@ -674,19 +674,6 @@ retry: * so look for them first. */ if (likely(buf[0] == '{')) { process_client_msg(cdata, buf); - } else if (cmdmatch(buf, "ping")) { - LOGDEBUG("Connector received ping request"); - send_unix_msg(sockd, "pong"); - } else if (cmdmatch(buf, "accept")) { - LOGDEBUG("Connector received accept signal"); - cdata->accept = true; - } else if (cmdmatch(buf, "reject")) { - LOGDEBUG("Connector received reject signal"); - cdata->accept = false; - } else if (cmdmatch(buf, "loglevel")) { - sscanf(buf, "loglevel=%d", &ckp->loglevel); - } else if (cmdmatch(buf, "shutdown")) { - goto out; } else if (cmdmatch(buf, "dropclient")) { client_instance_t *client; @@ -699,12 +686,26 @@ retry: client = ref_client_by_id(cdata, client_id); if (unlikely(!client)) { LOGINFO("Connector failed to find client id %ld to drop", client_id); + stratifier_drop_client(ckp, client_id); goto retry; } ret = drop_client(cdata, client); dec_instance_ref(cdata, client); if (ret >= 0) LOGINFO("Connector dropped client id: %ld", client_id); + } else if (cmdmatch(buf, "ping")) { + LOGDEBUG("Connector received ping request"); + send_unix_msg(sockd, "pong"); + } else if (cmdmatch(buf, "accept")) { + LOGDEBUG("Connector received accept signal"); + cdata->accept = true; + } else if (cmdmatch(buf, "reject")) { + LOGDEBUG("Connector received reject signal"); + cdata->accept = false; + } else if (cmdmatch(buf, "loglevel")) { + sscanf(buf, "loglevel=%d", &ckp->loglevel); + } else if (cmdmatch(buf, "shutdown")) { + goto out; } else if (cmdmatch(buf, "passthrough")) { client_instance_t *client; From 2545b081288209441a005d1b0344fcec9dfbe0cf Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 13 Jan 2015 16:49:16 +1100 Subject: [PATCH 03/39] Use invalidate in the connector when dropping a client to ensure the stratifier drops it as well --- src/connector.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/connector.c b/src/connector.c index 235ca6de..0bfae189 100644 --- a/src/connector.c +++ b/src/connector.c @@ -236,13 +236,14 @@ static void stratifier_drop_client(ckpool_t *ckp, int64_t id) * regularly but keep the instances in a linked list until their ref count * drops to zero when we can remove them lazily. Client must hold a reference * count. */ -static void invalidate_client(ckpool_t *ckp, cdata_t *cdata, client_instance_t *client) +static int invalidate_client(ckpool_t *ckp, cdata_t *cdata, client_instance_t *client) { client_instance_t *tmp; + int ret; - drop_client(cdata, client); + ret = drop_client(cdata, client); if (ckp->passthrough) - return; + goto out; stratifier_drop_client(ckp, client->id); /* Cull old unused clients lazily when there are no more reference @@ -256,6 +257,9 @@ static void invalidate_client(ckpool_t *ckp, cdata_t *cdata, client_instance_t * } } ck_wunlock(&cdata->lock); + +out: + return ret; } static void send_client(cdata_t *cdata, int64_t id, char *buf); @@ -689,7 +693,7 @@ retry: stratifier_drop_client(ckp, client_id); goto retry; } - ret = drop_client(cdata, client); + ret = invalidate_client(ckp, cdata, client); dec_instance_ref(cdata, client); if (ret >= 0) LOGINFO("Connector dropped client id: %ld", client_id); From 546768bfb78e03e5aead95e57c23d161c07e4aca Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Wed, 14 Jan 2015 20:10:51 +1100 Subject: [PATCH 04/39] Push version number to 0.8.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 65d311c0..3983bd0d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(ckpool, 0.8, kernel@kolivas.org) +AC_INIT(ckpool, 0.8.1, kernel@kolivas.org) AC_CANONICAL_SYSTEM AC_CONFIG_MACRO_DIR([m4]) From 297ae72e064d0e81e53c17535c540ca442736da4 Mon Sep 17 00:00:00 2001 From: kanoi Date: Thu, 15 Jan 2015 19:08:31 +1100 Subject: [PATCH 05/39] ckdb - enable, optionally automatic but off by default, workmarkers processing --- src/ckdb.c | 101 ++---------- src/ckdb.h | 65 ++++++-- src/ckdb_cmd.c | 14 +- src/ckdb_data.c | 131 ++++++++++++++- src/ckdb_dbio.c | 425 ++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 621 insertions(+), 115 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 8fa5580d..91bb3fdc 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -169,6 +169,9 @@ static char *status_chars = "|/-\\"; static char *restorefrom; +// Only accessed in here +static bool markersummary_auto; + // disallow: '/' '.' '_' and FLDSEP const char *userpatt = "^[^/\\._"FLDSEPSTR"]*$"; const char *mailpatt = "^[A-Za-z0-9_-][A-Za-z0-9_\\.-]*@[A-Za-z0-9][A-Za-z0-9\\.-]*[A-Za-z0-9]$"; @@ -1076,82 +1079,6 @@ static void alloc_storage() marks_root = new_ktree(); } -static void free_workinfo_data(K_ITEM *item) -{ - WORKINFO *workinfo; - - DATA_WORKINFO(workinfo, item); - if (workinfo->transactiontree) - FREENULL(workinfo->transactiontree); - if (workinfo->merklehash) - FREENULL(workinfo->merklehash); -} - -static void free_sharesummary_data(K_ITEM *item) -{ - SHARESUMMARY *sharesummary; - - DATA_SHARESUMMARY(sharesummary, item); - if (sharesummary->workername) { - LIST_MEM_SUB(sharesummary_free, sharesummary->workername); - FREENULL(sharesummary->workername); - } - SET_CREATEBY(sharesummary_free, sharesummary->createby, EMPTY); - SET_CREATECODE(sharesummary_free, sharesummary->createcode, EMPTY); - SET_CREATEINET(sharesummary_free, sharesummary->createinet, EMPTY); - SET_MODIFYBY(sharesummary_free, sharesummary->modifyby, EMPTY); - SET_MODIFYCODE(sharesummary_free, sharesummary->modifycode, EMPTY); - SET_MODIFYINET(sharesummary_free, sharesummary->modifyinet, EMPTY); -} - -static void free_optioncontrol_data(K_ITEM *item) -{ - OPTIONCONTROL *optioncontrol; - - DATA_OPTIONCONTROL(optioncontrol, item); - if (optioncontrol->optionvalue) - FREENULL(optioncontrol->optionvalue); -} - -static void free_markersummary_data(K_ITEM *item) -{ - MARKERSUMMARY *markersummary; - - DATA_MARKERSUMMARY(markersummary, item); - if (markersummary->workername) - FREENULL(markersummary->workername); - SET_CREATEBY(markersummary_free, markersummary->createby, EMPTY); - SET_CREATECODE(markersummary_free, markersummary->createcode, EMPTY); - SET_CREATEINET(markersummary_free, markersummary->createinet, EMPTY); - SET_MODIFYBY(markersummary_free, markersummary->modifyby, EMPTY); - SET_MODIFYCODE(markersummary_free, markersummary->modifycode, EMPTY); - SET_MODIFYINET(markersummary_free, markersummary->modifyinet, EMPTY); -} - -static void free_workmarkers_data(K_ITEM *item) -{ - WORKMARKERS *workmarkers; - - DATA_WORKMARKERS(workmarkers, item); - if (workmarkers->poolinstance) - FREENULL(workmarkers->poolinstance); - if (workmarkers->description) - FREENULL(workmarkers->description); -} - -static void free_marks_data(K_ITEM *item) -{ - MARKS *marks; - - DATA_MARKS(marks, item); - if (marks->poolinstance && marks->poolinstance != EMPTY) - FREENULL(marks->poolinstance); - if (marks->description && marks->description != EMPTY) - FREENULL(marks->description); - if (marks->extra && marks->extra != EMPTY) - FREENULL(marks->extra); -} - #define FREE_TREE(_tree) \ if (_tree ## _root) \ _tree ## _root = free_ktree(_tree ## _root, NULL) \ @@ -2081,8 +2008,8 @@ static void make_a_shift_mark() K_ITEM wi_look, ss_look; SHARESUMMARY *sharesummary, looksharesummary; WORKINFO *workinfo, lookworkinfo; - BLOCKS *blocks; - MARKS *marks, *sh_marks; + BLOCKS *blocks = NULL; + MARKS *marks = NULL, *sh_marks = NULL; int64_t ss_age_wid, last_marks_wid, marks_wid, prev_wid; bool was_block = false, ok; char cd_buf[DATE_BUFSIZ], cd_buf2[DATE_BUFSIZ]; @@ -2197,7 +2124,8 @@ static void make_a_shift_mark() if (m_item) { /* First block after the last mark - * Shift must stop at or before this */ + * Shift must stop at or before this + * N.B. any block, even 'New' */ K_RLOCK(blocks_free); b_item = first_in_ktree(blocks_root, b_ctx); while (b_item) { @@ -2474,16 +2402,16 @@ static void *marker(__maybe_unused void *arg) else make_a_workmarker(); -#if 0 for (i = 0; i < 4; i++) { if (!everyone_die) sleep(1); } if (everyone_die) break; - else - make_markersummaries(); -#endif + else { + if (markersummary_auto) + make_markersummaries(false, NULL, NULL, NULL, NULL, NULL); + } } marker_using_data = false; @@ -4044,6 +3972,8 @@ static struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "killold", no_argument, 0, 'k' }, { "loglevel", required_argument, 0, 'l' }, + // markersummary = enable markersummary auto generation + { "markersummary", no_argument, 0, 'm' }, { "name", required_argument, 0, 'n' }, { "dbpass", required_argument, 0, 'p' }, { "btc-pass", required_argument, 0, 'P' }, @@ -4088,7 +4018,7 @@ int main(int argc, char **argv) memset(&ckp, 0, sizeof(ckp)); ckp.loglevel = LOG_NOTICE; - while ((c = getopt_long(argc, argv, "c:d:hkl:n:p:P:r:R:s:S:t:u:U:vw:yY:", long_options, &i)) != -1) { + while ((c = getopt_long(argc, argv, "c:d:hkl:mn:p:P:r:R:s:S:t:u:U:vw:yY:", long_options, &i)) != -1) { switch(c) { case 'c': ckp.config = strdup(optarg); @@ -4126,6 +4056,9 @@ int main(int argc, char **argv) LOG_EMERG, LOG_DEBUG, ckp.loglevel); } break; + case 'm': + markersummary_auto = true; + break; case 'n': ckp.name = strdup(optarg); break; diff --git a/src/ckdb.h b/src/ckdb.h index 6206887d..341ced0c 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.822" +#define CKDB_VERSION DB_VERSION"-0.830" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -523,6 +523,34 @@ enum cmd_values { _row->pointers = _row->pointers; \ } while (0) +/* Override _row defaults if transfer fields are present + * We don't care about the reply so it can be small + * This is the pointer version - only one required so far */ +#define MODIFYDATETRANSFER(_list, _root, _row) do { \ + if (_root) { \ + char __reply[16]; \ + size_t __siz = sizeof(__reply); \ + K_ITEM *__item; \ + TRANSFER *__transfer; \ + __item = optional_name(_root, "createby", 1, NULL, __reply, __siz); \ + if (__item) { \ + DATA_TRANSFER(__transfer, __item); \ + SET_CREATEBY(_list, _row->createby, __transfer->mvalue); \ + } \ + __item = optional_name(_root, "createcode", 1, NULL, __reply, __siz); \ + if (__item) { \ + DATA_TRANSFER(__transfer, __item); \ + SET_CREATECODE(_list, _row->createcode, __transfer->mvalue); \ + } \ + __item = optional_name(_root, "createinet", 1, NULL, __reply, __siz); \ + if (__item) { \ + DATA_TRANSFER(__transfer, __item); \ + SET_CREATEINET(_list, _row->createinet, __transfer->mvalue); \ + } \ + _row->pointers = _row->pointers; \ + } \ + } while (0) + #define SIMPLEDATECONTROL ",createdate,createby,createcode,createinet" #define SIMPLEDATECOUNT 4 #define SIMPLEDATECONTROLFIELDS \ @@ -1480,6 +1508,14 @@ extern PGconn *dbconnect(); // *** ckdb_data.c *** // *** +// Data free functions (first) +extern void free_workinfo_data(K_ITEM *item); +extern void free_sharesummary_data(K_ITEM *item); +extern void free_optioncontrol_data(K_ITEM *item); +extern void free_markersummary_data(K_ITEM *item); +extern void free_workmarkers_data(K_ITEM *item); +extern void free_marks_data(K_ITEM *item); + extern char *safe_text(char *txt); extern void username_trim(USERS *users); extern bool like_address(char *username); @@ -1629,10 +1665,12 @@ extern bool userstats_starttimeband(USERSTATS *row, tv_t *statsdate); extern void dsp_markersummary(K_ITEM *item, FILE *stream); extern cmp_t cmp_markersummary(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_markersummary_userid(K_ITEM *a, K_ITEM *b); -extern K_ITEM *find_markersummary(int64_t workinfoid, int64_t userid, - char *workername); extern K_ITEM *find_markersummary_userid(int64_t userid, char *workername, K_TREE_CTX *ctx); +extern K_ITEM *find_markersummary(int64_t workinfoid, int64_t userid, + char *workername); +extern bool make_markersummaries(bool msg, char *by, char *code, char *inet, + tv_t *cd, K_TREE *trf_root); extern void dsp_workmarkers(K_ITEM *item, FILE *stream); extern cmp_t cmp_workmarkers(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_workmarkers_workinfoid(K_ITEM *a, K_ITEM *b); @@ -1750,6 +1788,9 @@ extern bool shareerrors_add(PGconn *conn, char *workinfoid, char *username, char *workername, char *clientid, char *errn, char *error, char *secondaryuserid, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root); +extern bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers, + char *by, char *code, char *inet, + tv_t *cd, K_TREE *trf_root); #define sharesummary_update(_conn, _s_row, _e_row, _ss_item, _by, _code, _inet, _cd) \ _sharesummary_update(_conn, _s_row, _e_row, _ss_item, _by, _code, _inet, _cd, \ WHERE_FFL_HERE) @@ -1796,20 +1837,22 @@ extern bool workerstats_add(char *poolinstance, char *elapsed, char *username, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root); extern bool userstats_fill(PGconn *conn); +extern bool markersummary_add(PGconn *conn, K_ITEM *ms_item, char *by, char *code, + char *inet, tv_t *cd, K_TREE *trf_root); extern bool markersummary_fill(PGconn *conn); -#define workmarkers_process(_conn, _add, _markerid, _poolinstance, \ +#define workmarkers_process(_conn, _already, _add, _markerid, _poolinstance, \ _workinfoidend, _workinfoidstart, _description, \ _status, _by, _code, _inet, _cd, _trf_root) \ - _workmarkers_process(_conn, _add, _markerid, _poolinstance, \ + _workmarkers_process(_conn, _already, _add, _markerid, _poolinstance, \ _workinfoidend, _workinfoidstart, _description, \ _status, _by, _code, _inet, _cd, _trf_root, \ WHERE_FFL_HERE) -extern bool _workmarkers_process(PGconn *conn, bool add, int64_t markerid, - char *poolinstance, int64_t workinfoidend, - int64_t workinfoidstart, char *description, - char *status, char *by, char *code, - char *inet, tv_t *cd, K_TREE *trf_root, - WHERE_FFL_ARGS); +extern bool _workmarkers_process(PGconn *conn, bool already, bool add, + int64_t markerid, char *poolinstance, + int64_t workinfoidend, int64_t workinfoidstart, + char *description, char *status, char *by, + char *code, char *inet, tv_t *cd, + K_TREE *trf_root, WHERE_FFL_ARGS); extern bool workmarkers_fill(PGconn *conn); #define marks_process(_conn, _add, _poolinstance, _workinfoid, _description, \ _extra, _marktype, _status, _by, _code, _inet, _cd, \ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 2ec947a6..233b36bf 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -4092,7 +4092,7 @@ static char *cmd_userstatus(PGconn *conn, char *cmd, char *id, tv_t *now, char * } /* Socket interface to the functions that will be used later to automatically - * create marks, workmarkers and process the workmarkers + * create marks, workmarkers and process the workmarkers and sharesummaries * to generate markersummaries */ static char *cmd_marks(PGconn *conn, char *cmd, char *id, __maybe_unused tv_t *now, char *by, @@ -4372,7 +4372,7 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, DATA_WORKMARKERS(workmarkers, wm_item); if (CURRENT(&(workmarkers->expirydate)) && !WMPROCESSED(workmarkers->status)) { - ok = workmarkers_process(conn, false, + ok = workmarkers_process(conn, false, false, workmarkers->markerid, NULL, 0, 0, NULL, NULL, by, code, inet, cd, trf_root); @@ -4391,6 +4391,16 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, "%d workmarkers expunged", count); } } + } else if (strcasecmp(action, "sum") == 0) { + /* For the last available workmarker, + * summarise it's sharesummaries into markersummaries + * No parameters */ + ok = make_markersummaries(true, by, code, inet, cd, trf_root); + if (!ok) { + snprintf(reply, siz, "%s failed", action); + LOGERR("%s.%s", id, reply); + return strdup(reply); + } } else { snprintf(reply, siz, "unknown action '%s'", action); LOGERR("%s.%s", id, reply); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index be92fbd0..abb1b40f 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -9,6 +9,83 @@ #include "ckdb.h" +// Data free functions (added here as needed) +void free_workinfo_data(K_ITEM *item) +{ + WORKINFO *workinfo; + + DATA_WORKINFO(workinfo, item); + if (workinfo->transactiontree) + FREENULL(workinfo->transactiontree); + if (workinfo->merklehash) + FREENULL(workinfo->merklehash); +} + +void free_sharesummary_data(K_ITEM *item) +{ + SHARESUMMARY *sharesummary; + + DATA_SHARESUMMARY(sharesummary, item); + if (sharesummary->workername) { + LIST_MEM_SUB(sharesummary_free, sharesummary->workername); + FREENULL(sharesummary->workername); + } + SET_CREATEBY(sharesummary_free, sharesummary->createby, EMPTY); + SET_CREATECODE(sharesummary_free, sharesummary->createcode, EMPTY); + SET_CREATEINET(sharesummary_free, sharesummary->createinet, EMPTY); + SET_MODIFYBY(sharesummary_free, sharesummary->modifyby, EMPTY); + SET_MODIFYCODE(sharesummary_free, sharesummary->modifycode, EMPTY); + SET_MODIFYINET(sharesummary_free, sharesummary->modifyinet, EMPTY); +} + +void free_optioncontrol_data(K_ITEM *item) +{ + OPTIONCONTROL *optioncontrol; + + DATA_OPTIONCONTROL(optioncontrol, item); + if (optioncontrol->optionvalue) + FREENULL(optioncontrol->optionvalue); +} + +void free_markersummary_data(K_ITEM *item) +{ + MARKERSUMMARY *markersummary; + + DATA_MARKERSUMMARY(markersummary, item); + if (markersummary->workername) + FREENULL(markersummary->workername); + SET_CREATEBY(markersummary_free, markersummary->createby, EMPTY); + SET_CREATECODE(markersummary_free, markersummary->createcode, EMPTY); + SET_CREATEINET(markersummary_free, markersummary->createinet, EMPTY); + SET_MODIFYBY(markersummary_free, markersummary->modifyby, EMPTY); + SET_MODIFYCODE(markersummary_free, markersummary->modifycode, EMPTY); + SET_MODIFYINET(markersummary_free, markersummary->modifyinet, EMPTY); +} + +void free_workmarkers_data(K_ITEM *item) +{ + WORKMARKERS *workmarkers; + + DATA_WORKMARKERS(workmarkers, item); + if (workmarkers->poolinstance) + FREENULL(workmarkers->poolinstance); + if (workmarkers->description) + FREENULL(workmarkers->description); +} + +void free_marks_data(K_ITEM *item) +{ + MARKS *marks; + + DATA_MARKS(marks, item); + if (marks->poolinstance && marks->poolinstance != EMPTY) + FREENULL(marks->poolinstance); + if (marks->description && marks->description != EMPTY) + FREENULL(marks->description); + if (marks->extra && marks->extra != EMPTY) + FREENULL(marks->extra); +} + // Clear text printable version of txt up to first '\0' char *safe_text(char *txt) { @@ -2390,6 +2467,58 @@ K_ITEM *find_markersummary(int64_t workinfoid, int64_t userid, char *workername) return ms_item; } +bool make_markersummaries(bool msg, char *by, char *code, char *inet, + tv_t *cd, K_TREE *trf_root) +{ + K_TREE_CTX ctx[1]; + WORKMARKERS *workmarkers; + K_ITEM *wm_item, *wm_last = NULL; + tv_t now; + + K_RLOCK(workmarkers_free); + wm_item = last_in_ktree(workmarkers_workinfoid_root, ctx); + while (wm_item) { + DATA_WORKMARKERS(workmarkers, wm_item); + if (!CURRENT(&(workmarkers->expirydate))) + break; + // find the oldest READY workinfoid + if (WMREADY(workmarkers->status)) + wm_last = wm_item; + wm_item = prev_in_ktree(ctx); + } + K_RUNLOCK(workmarkers_free); + + if (!wm_last) { + if (!msg) + LOGDEBUG("%s() no READY workmarkers", __func__); + else + LOGWARNING("%s() no READY workmarkers", __func__); + return false; + } + + DATA_WORKMARKERS(workmarkers, wm_last); + + LOGDEBUG("%s() processing workmarkers %"PRId64"/%s/End %"PRId64"/" + "Stt %"PRId64"/%s/%s", + __func__, workmarkers->markerid, workmarkers->poolinstance, + workmarkers->workinfoidend, workmarkers->workinfoidstart, + workmarkers->description, workmarkers->status); + + if (by == NULL) + by = (char *)by_default; + if (code == NULL) + code = (char *)__func__; + if (inet == NULL) + inet = (char *)inet_default; + if (cd) + copy_tv(&now, cd); + else + setnow(&now); + + return sharesummaries_to_markersummaries(NULL, workmarkers, by, code, + inet, &now, trf_root); +} + void dsp_workmarkers(K_ITEM *item, FILE *stream) { WORKMARKERS *wm; @@ -2573,7 +2702,7 @@ static bool gen_workmarkers(PGconn *conn, MARKS *stt, bool after, MARKS *fin, stt->description, after ? "++" : "", fin->description, before ? "--" : ""); - ok = workmarkers_process(conn, true, 0, EMPTY, + ok = workmarkers_process(conn, false, true, 0, EMPTY, wi_fin->workinfoid, wi_stt->workinfoid, description, MARKER_READY_STR, by, code, inet, cd, trf_root); diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 9245f968..c4385982 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2014 Andrew Smith + * Copyright 1995-2015 Andrew Smith * * 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 @@ -168,7 +168,8 @@ char *pqerrmsg(PGconn *conn) #define PQPARAM15 PQPARAM8 ",$9,$10,$11,$12,$13,$14,$15" #define PQPARAM16 PQPARAM8 ",$9,$10,$11,$12,$13,$14,$15,$16" #define PQPARAM22 PQPARAM16 ",$17,$18,$19,$20,$21,$22" -#define PQPARAM27 PQPARAM22 ",$23,$24,$25,$26,$27" +#define PQPARAM26 PQPARAM22 ",$23,$24,$25,$26" +#define PQPARAM27 PQPARAM26 ",$27" #define PARCHK(_par, _params) do { \ if (_par != (int)(sizeof(_params)/sizeof(_params[0]))) { \ @@ -2751,6 +2752,318 @@ bool shareerrors_fill() return true; } +/* TODO: what to do about a failure? + * since it will repeat every ~13s + * Of course manual intervention is possible via cmd_marks, + * so that is probably the best solution since + * we should be watching the pool all the time :) + * The cause would most likely be either a code bug or a DB problem + * so there many be no obvious automated fix + * and flagging the workmarkers to be skipped may or may not be the solution, + * thus manual intervention will be the rule for now */ +bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers, + char *by, char *code, char *inet, tv_t *cd, + K_TREE *trf_root) +{ + // shorter name for log messages + const char *shortname = "SS_to_MS"; + ExecStatusType rescode; + PGresult *res; + K_TREE_CTX ss_ctx[1], ms_ctx[1]; + SHARESUMMARY *sharesummary, looksharesummary; + MARKERSUMMARY *markersummary, lookmarkersummary; + K_ITEM *ss_item, *ss_prev, ss_look, *ms_item, ms_look; + bool ok = false, conned = false; + int64_t diffacc, shareacc; + char *reason = NULL, *tuples = NULL; + char *params[2]; + int n, par = 0, deleted = -7; + int ss_count, ms_count; + char *del; + + LOGWARNING("%s() Processing: workmarkers %"PRId64"/%s/" + "End %"PRId64"/Stt %"PRId64"/%s/%s", + shortname, workmarkers->markerid, workmarkers->poolinstance, + workmarkers->workinfoidend, workmarkers->workinfoidstart, + workmarkers->description, workmarkers->status); + + K_STORE *old_sharesummary_store = k_new_store(sharesummary_free); + K_STORE *new_markersummary_store = k_new_store(markersummary_free); + K_TREE *ms_root = new_ktree(); + + if (!CURRENT(&(workmarkers->expirydate))) { + reason = "unexpired"; + goto flail; + } + + if (!WMREADY(workmarkers->status)) { + reason = "not ready"; + goto flail; + } + + // Check there aren't already any matching markersummaries + lookmarkersummary.markerid = workmarkers->markerid; + lookmarkersummary.userid = 0; + lookmarkersummary.workername = EMPTY; + + INIT_MARKERSUMMARY(&ms_look); + ms_look.data = (void *)(&lookmarkersummary); + K_RLOCK(markersummary_free); + ms_item = find_after_in_ktree(markersummary_root, &ms_look, + cmp_markersummary, ms_ctx); + K_RUNLOCK(markersummary_free); + DATA_MARKERSUMMARY_NULL(markersummary, ms_item); + if (ms_item && markersummary->markerid == workmarkers->markerid) { + reason = "markersummaries already exist"; + goto flail; + } + + diffacc = shareacc = 0; + ms_item = NULL; + + looksharesummary.workinfoid = workmarkers->workinfoidend; + looksharesummary.userid = MAXID; + looksharesummary.workername = EMPTY; + + INIT_SHARESUMMARY(&ss_look); + ss_look.data = (void *)(&looksharesummary); + /* Since shares come in from ckpool at a high rate, + * we don't want to lock sharesummary for long + * Those incoming shares will not be touching the sharesummaries + * we are processing here */ + K_RLOCK(sharesummary_free); + ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look, + cmp_sharesummary_workinfoid, ss_ctx); + K_RUNLOCK(sharesummary_free); + while (ss_item) { + DATA_SHARESUMMARY(sharesummary, ss_item); + if (sharesummary->workinfoid < workmarkers->workinfoidstart) + break; + K_RLOCK(sharesummary_free); + ss_prev = prev_in_ktree(ss_ctx); + K_RUNLOCK(sharesummary_free); + + // Find/create the markersummary only once per worker change + if (!ms_item || markersummary->userid != sharesummary->userid || + strcmp(markersummary->workername, sharesummary->workername) != 0) { + lookmarkersummary.markerid = workmarkers->markerid; + lookmarkersummary.userid = sharesummary->userid; + lookmarkersummary.workername = sharesummary->workername; + + ms_look.data = (void *)(&lookmarkersummary); + ms_item = find_in_ktree(ms_root, &ms_look, + cmp_markersummary, ms_ctx); + if (!ms_item) { + K_WLOCK(markersummary_free); + ms_item = k_unlink_head(markersummary_free); + K_WUNLOCK(markersummary_free); + k_add_head(new_markersummary_store, ms_item); + DATA_MARKERSUMMARY(markersummary, ms_item); + bzero(markersummary, sizeof(*markersummary)); + markersummary->markerid = workmarkers->markerid; + markersummary->userid = sharesummary->userid; + markersummary->workername = strdup(sharesummary->workername); + LIST_MEM_ADD(markersummary_free, markersummary->workername); + ms_root = add_to_ktree(ms_root, ms_item, cmp_markersummary); + + LOGDEBUG("%s() new ms %"PRId64"/%"PRId64"/%s", + shortname, markersummary->markerid, + markersummary->userid, + markersummary->workername); + } else { + DATA_MARKERSUMMARY(markersummary, ms_item); + } + } + markersummary->diffacc += sharesummary->diffacc; + markersummary->diffsta += sharesummary->diffsta; + markersummary->diffdup += sharesummary->diffdup; + markersummary->diffhi += sharesummary->diffhi; + markersummary->diffrej += sharesummary->diffrej; + markersummary->shareacc += sharesummary->shareacc; + markersummary->sharesta += sharesummary->sharesta; + markersummary->sharedup += sharesummary->sharedup; + markersummary->sharehi += sharesummary->sharehi; + markersummary->sharerej += sharesummary->sharerej; + markersummary->sharecount += sharesummary->sharecount; + markersummary->errorcount += sharesummary->errorcount; + if (!markersummary->firstshare.tv_sec || + !tv_newer(&(markersummary->firstshare), &(sharesummary->firstshare))) { + copy_tv(&(markersummary->firstshare), &(sharesummary->firstshare)); + } + if (tv_newer(&(markersummary->lastshare), &(sharesummary->lastshare))) { + copy_tv(&(markersummary->lastshare), &(sharesummary->lastshare)); + markersummary->lastdiffacc = sharesummary->lastdiffacc; + } + + diffacc += sharesummary->diffacc; + shareacc += sharesummary->shareacc; + + k_unlink_item(sharesummary_store, ss_item); + k_add_head(old_sharesummary_store, ss_item); + + ss_item = ss_prev; + } + + if (old_sharesummary_store->count == 0) + reason = "no sharesummaries"; + else { + if (conn == NULL) { + conn = dbconnect(); + conned = true; + } + + res = PQexec(conn, "Begin", CKPQ_WRITE); + rescode = PQresultStatus(res); + PQclear(res); + if (!PGOK(rescode)) { + PGLOGERR("Begin", rescode, conn); + goto flail; + } + + ms_item = new_markersummary_store->head; + while (ms_item) { + if (!(markersummary_add(conn, ms_item, by, code, inet, + cd, trf_root))) { + reason = "db error"; + goto rollback; + } + ms_item = ms_item->next; + } + + par = 0; + params[par++] = bigint_to_buf(workmarkers->workinfoidstart, NULL, 0); + params[par++] = bigint_to_buf(workmarkers->workinfoidend, NULL, 0); + PARCHK(par, params); + + del = "delete from sharesummary " + "where workinfoid >= $1 and workinfoid <= $2"; + + res = PQexecParams(conn, del, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_WRITE); + rescode = PQresultStatus(res); + if (PGOK(rescode)) { + tuples = PQcmdTuples(res); + if (tuples && *tuples) + deleted = atoi(tuples); + } + PQclear(res); + if (!PGOK(rescode)) { + PGLOGERR("Delete", rescode, conn); + reason = "delete failure"; + goto rollback; + } + + if (deleted != old_sharesummary_store->count) { + LOGERR("%s() processed sharesummaries=%d but deleted=%d", + shortname, old_sharesummary_store->count, deleted); + reason = "delete mismatch"; + goto rollback; + } + + ok = workmarkers_process(conn, true, true, + workmarkers->markerid, + workmarkers->poolinstance, + workmarkers->workinfoidend, + workmarkers->workinfoidstart, + workmarkers->description, + MARKER_PROCESSED_STR, + by, code, inet, cd, trf_root); +rollback: + if (ok) + res = PQexec(conn, "Commit", CKPQ_WRITE); + else + res = PQexec(conn, "Rollback", CKPQ_WRITE); + + PQclear(res); + } +flail: + for (n = 0; n < par; n++) + free(params[n]); + + if (conned) + PQfinish(conn); + + if (reason) { + // already displayed the full workmarkers detail at the top + LOGERR("%s() %s: workmarkers %"PRId64"/%s/%s", + shortname, reason, workmarkers->markerid, + workmarkers->description, workmarkers->status); + + ok = false; + } + + if (!ok) { + if (new_markersummary_store->count > 0) { + // Throw them away (they don't exist anywhere else) + ms_item = new_markersummary_store->head; + while (ms_item) { + free_markersummary_data(ms_item); + ms_item = ms_item->next; + } + K_WLOCK(markersummary_free); + k_list_transfer_to_head(new_markersummary_store, markersummary_free); + K_WUNLOCK(markersummary_free); + } + if (old_sharesummary_store->count > 0) { + // Put them back in the store where they came from + K_WLOCK(sharesummary_free); + k_list_transfer_to_head(old_sharesummary_store, sharesummary_store); + K_WUNLOCK(sharesummary_free); + } + } else { + ms_count = new_markersummary_store->count; + ss_count = old_sharesummary_store->count; + // Deadlock alert for other newer code ... + K_WLOCK(sharesummary_free); + K_WLOCK(markersummary_free); + ms_item = new_markersummary_store->head; + while (ms_item) { + // Move the new markersummaries into the trees/stores + markersummary_root = add_to_ktree(markersummary_root, + ms_item, + cmp_markersummary); + markersummary_userid_root = add_to_ktree(markersummary_userid_root, + ms_item, + cmp_markersummary_userid); + ms_item = ms_item->next; + } + k_list_transfer_to_head(new_markersummary_store, markersummary_store); + + /* For normal shift processing this wont be very quick + * so it will be a 'long' LOCK */ + ss_item = old_sharesummary_store->head; + while (ss_item) { + // remove the old sharesummaries from the trees + sharesummary_root = remove_from_ktree(sharesummary_root, + ss_item, + cmp_sharesummary); + sharesummary_workinfoid_root = remove_from_ktree(sharesummary_workinfoid_root, + ss_item, + cmp_sharesummary_workinfoid); + free_sharesummary_data(ss_item); + + ss_item = ss_item->next; + } + k_list_transfer_to_head(old_sharesummary_store, sharesummary_free); + K_WUNLOCK(markersummary_free); + K_WUNLOCK(sharesummary_free); + + LOGWARNING("%s() Processed: %d ms %d ss %"PRId64" shares " + "%"PRId64" diff for workmarkers %"PRId64"/%s/" + "End %"PRId64"/Stt %"PRId64"/%s/%s", + shortname, ms_count, ss_count, shareacc, diffacc, + workmarkers->markerid, workmarkers->poolinstance, + workmarkers->workinfoidend, + workmarkers->workinfoidstart, + workmarkers->description, + workmarkers->status); + } + ms_root = free_ktree(ms_root, NULL); + new_markersummary_store = k_free_store(new_markersummary_store); + old_sharesummary_store = k_free_store(old_sharesummary_store); + + return ok; +} + bool _sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row, K_ITEM *ss_item, char *by, char *code, char *inet, tv_t *cd, WHERE_FFL_ARGS) { @@ -5204,6 +5517,82 @@ clean: return ok; } +bool markersummary_add(PGconn *conn, K_ITEM *ms_item, char *by, char *code, + char *inet, tv_t *cd, K_TREE *trf_root) +{ + ExecStatusType rescode; + bool conned = false; + PGresult *res; + MARKERSUMMARY *row; + char *params[18 + MODIFYDATECOUNT]; + int n, par = 0; + char *ins; + bool ok = false; + + LOGDEBUG("%s(): add", __func__); + + DATA_MARKERSUMMARY(row, ms_item); + + MODIFYDATEPOINTERS(markersummary_free, row, cd, by, code, inet); + MODIFYDATETRANSFER(markersummary_free, trf_root, row); + + par = 0; + params[par++] = bigint_to_buf(row->markerid, NULL, 0); + params[par++] = bigint_to_buf(row->userid, NULL, 0); + params[par++] = str_to_buf(row->workername, NULL, 0); + params[par++] = double_to_buf(row->diffacc, NULL, 0); + params[par++] = double_to_buf(row->diffsta, NULL, 0); + params[par++] = double_to_buf(row->diffdup, NULL, 0); + params[par++] = double_to_buf(row->diffhi, NULL, 0); + params[par++] = double_to_buf(row->diffrej, NULL, 0); + params[par++] = double_to_buf(row->shareacc, NULL, 0); + params[par++] = double_to_buf(row->sharesta, NULL, 0); + params[par++] = double_to_buf(row->sharedup, NULL, 0); + params[par++] = double_to_buf(row->sharehi, NULL, 0); + params[par++] = double_to_buf(row->sharerej, NULL, 0); + params[par++] = bigint_to_buf(row->sharecount, NULL, 0); + params[par++] = bigint_to_buf(row->errorcount, NULL, 0); + params[par++] = tv_to_buf(&(row->firstshare), NULL, 0); + params[par++] = tv_to_buf(&(row->lastshare), NULL, 0); + params[par++] = double_to_buf(row->lastdiffacc, NULL, 0); + MODIFYDATEPARAMS(params, par, row); + PARCHK(par, params); + + ins = "insert into markersummary " + "(markerid,userid,workername,diffacc,diffsta,diffdup,diffhi," + "diffrej,shareacc,sharesta,sharedup,sharehi,sharerej," + "sharecount,errorcount,firstshare,lastshare,lastdiffacc" + MODIFYDATECONTROL ") values (" PQPARAM26 ")"; + + LOGDEBUG("%s() adding ms %"PRId64"/%"PRId64"/%s/%.0f", + __func__, row->markerid, row->userid, row->workername, + row->diffacc); + + if (!conn) { + conn = dbconnect(); + conned = true; + } + + res = PQexecParams(conn, ins, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_WRITE); + rescode = PQresultStatus(res); + if (!PGOK(rescode)) { + PGLOGERR("Insert", rescode, conn); + goto unparam; + } + + ok = true; +unparam: + PQclear(res); + if (conned) + PQfinish(conn); + for (n = 0; n < par; n++) + free(params[n]); + + // caller must do tree/list/store changes + + return ok; +} + bool markersummary_fill(PGconn *conn) { ExecStatusType rescode; @@ -5380,10 +5769,10 @@ bool markersummary_fill(PGconn *conn) * since we only check for a CURRENT workmarkers * N.B. also, this returns success if !add and there is no matching * old workmarkers */ -bool _workmarkers_process(PGconn *conn, bool add, int64_t markerid, - char *poolinstance, int64_t workinfoidend, - int64_t workinfoidstart, char *description, - char *status, char *by, char *code, +bool _workmarkers_process(PGconn *conn, bool already, bool add, + int64_t markerid, char *poolinstance, + int64_t workinfoidend, int64_t workinfoidstart, + char *description, char *status, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root, WHERE_FFL_ARGS) { @@ -5391,7 +5780,7 @@ bool _workmarkers_process(PGconn *conn, bool add, int64_t markerid, bool conned = false; PGresult *res = NULL; K_ITEM *wm_item = NULL, *old_wm_item = NULL, *w_item; - WORKMARKERS *row, *oldworkmarkers; + WORKMARKERS *row, *oldworkmarkers = NULL; char *upd, *ins; char *params[6 + HISTORYDATECOUNT]; bool ok = false, begun = false; @@ -5414,15 +5803,17 @@ bool _workmarkers_process(PGconn *conn, bool add, int64_t markerid, conn = dbconnect(); conned = true; } - res = PQexec(conn, "Begin", CKPQ_WRITE); - rescode = PQresultStatus(res); - PQclear(res); - if (!PGOK(rescode)) { - PGLOGERR("Begin", rescode, conn); - goto unparam; - } + if (!already) { + res = PQexec(conn, "Begin", CKPQ_WRITE); + rescode = PQresultStatus(res); + PQclear(res); + if (!PGOK(rescode)) { + PGLOGERR("Begin", rescode, conn); + goto unparam; + } - begun = true; + begun = true; + } upd = "update workmarkers set expirydate=$1 where markerid=$2" " and expirydate=$3"; @@ -5473,7 +5864,7 @@ bool _workmarkers_process(PGconn *conn, bool add, int64_t markerid, conned = true; } - if (!begun) { + if (!already && !begun) { res = PQexec(conn, "Begin", CKPQ_WRITE); rescode = PQresultStatus(res); PQclear(res); @@ -5707,7 +6098,7 @@ bool _marks_process(PGconn *conn, bool add, char *poolinstance, bool conned = false; PGresult *res = NULL; K_ITEM *m_item = NULL, *old_m_item = NULL, *w_item; - MARKS *row, *oldmarks; + MARKS *row, *oldmarks = NULL; char *upd, *ins; char *params[6 + HISTORYDATECOUNT]; bool ok = false, begun = false; From 3ae5e9d2b742970f58440d09b129af123c59e56c Mon Sep 17 00:00:00 2001 From: kanoi Date: Thu, 15 Jan 2015 21:16:36 +1100 Subject: [PATCH 06/39] ckdb - allow setting workmarkers as processed via marks command --- src/ckdb.h | 2 +- src/ckdb_cmd.c | 37 +++++++++++++++++++++++++++++++++++-- src/ckdb_dbio.c | 4 +++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 341ced0c..03184147 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.830" +#define CKDB_VERSION DB_VERSION"-0.831" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 233b36bf..5ece47c8 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -4105,13 +4105,13 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, char msg[1024] = ""; K_ITEM *i_action, *i_workinfoid, *i_marktype, *i_description; K_ITEM *i_height, *i_status, *i_extra, *m_item, *b_item, *w_item; - K_ITEM *wm_item, *wm_item_prev; + K_ITEM *wm_item, *wm_item_prev, *i_markerid; WORKMARKERS *workmarkers; K_TREE_CTX ctx[1]; BLOCKS *blocks; MARKS *marks; char *action; - int64_t workinfoid = -1; + int64_t workinfoid = -1, markerid = -1; char *marktype; int32_t height = 0; char description[TXT_BIG+1] = { '\0' }; @@ -4401,6 +4401,39 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, LOGERR("%s.%s", id, reply); return strdup(reply); } + } else if (strcasecmp(action, "processed") == 0) { + /* Mark a workmarker as processed + * Requires markerid */ + i_markerid = require_name(trf_root, "markerid", 1, (char *)intpatt, reply, siz); + if (!i_markerid) + return strdup(reply); + TXT_TO_BIGINT("markerid", transfer_data(i_markerid), markerid); + K_RLOCK(workmarkers_free); + wm_item = find_workmarkerid(markerid, true, '\0'); + K_RUNLOCK(workmarkers_free); + if (!wm_item) { + snprintf(reply, siz, + "unknown workmarkers with markerid %"PRId64, markerid); + return strdup(reply); + } + DATA_WORKMARKERS(workmarkers, wm_item); + if (WMPROCESSED(workmarkers->status)) { + snprintf(reply, siz, + "already processed markerid %"PRId64, markerid); + return strdup(reply); + } + ok = workmarkers_process(NULL, false, true, markerid, + workmarkers->poolinstance, + workmarkers->workinfoidend, + workmarkers->workinfoidstart, + workmarkers->description, + MARKER_PROCESSED_STR, + by, code, inet, cd, trf_root); + if (!ok) { + snprintf(reply, siz, "%s failed", action); + LOGERR("%s.%s", id, reply); + return strdup(reply); + } } else { snprintf(reply, siz, "unknown action '%s'", action); LOGERR("%s.%s", id, reply); diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index c4385982..74877f58 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -5756,7 +5756,9 @@ bool markersummary_fill(PGconn *conn) return ok; } -/* Add means create a new one and expire the old one if it exists, +/* Already means there is a transaction already in progress + * so don't begin or commit/rollback + * Add means create a new one and expire the old one if it exists, * otherwise we only expire the old one if it exists * Add requires all db fields except markerid, however if markerid * is non-zero, it will be used instead of getting a new one From 91aa3d0e367ed8bb998cbfdd188e526edbb2c3a3 Mon Sep 17 00:00:00 2001 From: kanoi Date: Thu, 15 Jan 2015 21:25:17 +1100 Subject: [PATCH 07/39] ckdb - workmarkers processing: no sharesummaries is not an error --- src/ckdb.h | 2 +- src/ckdb_dbio.c | 70 ++++++++++++++++++++++++------------------------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 03184147..b0733d55 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.831" +#define CKDB_VERSION DB_VERSION"-0.832" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 74877f58..6c453461 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -2904,32 +2904,30 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers, ss_item = ss_prev; } - if (old_sharesummary_store->count == 0) - reason = "no sharesummaries"; - else { - if (conn == NULL) { - conn = dbconnect(); - conned = true; - } + if (conn == NULL) { + conn = dbconnect(); + conned = true; + } - res = PQexec(conn, "Begin", CKPQ_WRITE); - rescode = PQresultStatus(res); - PQclear(res); - if (!PGOK(rescode)) { - PGLOGERR("Begin", rescode, conn); - goto flail; - } + res = PQexec(conn, "Begin", CKPQ_WRITE); + rescode = PQresultStatus(res); + PQclear(res); + if (!PGOK(rescode)) { + PGLOGERR("Begin", rescode, conn); + goto flail; + } - ms_item = new_markersummary_store->head; - while (ms_item) { - if (!(markersummary_add(conn, ms_item, by, code, inet, - cd, trf_root))) { - reason = "db error"; - goto rollback; - } - ms_item = ms_item->next; + ms_item = new_markersummary_store->head; + while (ms_item) { + if (!(markersummary_add(conn, ms_item, by, code, inet, + cd, trf_root))) { + reason = "db error"; + goto rollback; } + ms_item = ms_item->next; + } + if (old_sharesummary_store->count > 0) { par = 0; params[par++] = bigint_to_buf(workmarkers->workinfoidstart, NULL, 0); params[par++] = bigint_to_buf(workmarkers->workinfoidend, NULL, 0); @@ -2958,23 +2956,23 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers, reason = "delete mismatch"; goto rollback; } + } - ok = workmarkers_process(conn, true, true, - workmarkers->markerid, - workmarkers->poolinstance, - workmarkers->workinfoidend, - workmarkers->workinfoidstart, - workmarkers->description, - MARKER_PROCESSED_STR, - by, code, inet, cd, trf_root); + ok = workmarkers_process(conn, true, true, + workmarkers->markerid, + workmarkers->poolinstance, + workmarkers->workinfoidend, + workmarkers->workinfoidstart, + workmarkers->description, + MARKER_PROCESSED_STR, + by, code, inet, cd, trf_root); rollback: - if (ok) - res = PQexec(conn, "Commit", CKPQ_WRITE); - else - res = PQexec(conn, "Rollback", CKPQ_WRITE); + if (ok) + res = PQexec(conn, "Commit", CKPQ_WRITE); + else + res = PQexec(conn, "Rollback", CKPQ_WRITE); - PQclear(res); - } + PQclear(res); flail: for (n = 0; n < par; n++) free(params[n]); From a90b1fd0241750c41f1bd3c6274d3b26d170dca8 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 16 Jan 2015 09:41:50 +1100 Subject: [PATCH 08/39] Preauth workers for the first 10 minutes after a user first authorises --- src/stratifier.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index 20c4f4a5..8800b73e 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -180,6 +180,7 @@ struct user_instance { double dsps1440; double dsps10080; tv_t last_share; + time_t auth_time; }; /* Combined data from workers with the same workername */ @@ -1981,6 +1982,8 @@ static int send_recv_auth(stratum_instance_t *client) json_get_string(&secondaryuserid, val, "secondaryuserid"); json_get_int(&worker->mindiff, val, "difficultydefault"); client->suggest_diff = worker->mindiff; + if (!user_instance->auth_time) + user_instance->auth_time = time(NULL); } if (secondaryuserid && (!safecmp(response, "ok.authorise") || !safecmp(response, "ok.addrauth"))) { @@ -2082,7 +2085,13 @@ static json_t *parse_authorise(stratum_instance_t *client, json_t *params_val, j if (CKP_STANDALONE(ckp)) ret = true; else { - *errnum = send_recv_auth(client); + /* Preauth workers for the first 10 minutes after the user is + * first authorised by ckdb to avoid floods of worker auths. + * *errnum is implied zero already so ret will be set true */ + if (user_instance->auth_time && time(NULL) - user_instance->auth_time < 600) + queue_delayed_auth(client); + else + *errnum = send_recv_auth(client); if (!*errnum) ret = true; else if (*errnum < 0 && user_instance->secondaryuserid) { From 8f103477757347be969baa449e62f775804f5141 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 16 Jan 2015 11:52:34 +1100 Subject: [PATCH 09/39] Dead instances are a singly linked list only --- src/stratifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index 8800b73e..6ea66790 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1280,7 +1280,7 @@ static void drop_client(sdata_t *sdata, int64_t id) } /* Discard any dead instances that no longer hold any reference counts, * freeing up their memory safely */ - DL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { + LL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { if (!client->ref) { LOGINFO("Stratifier discarding instance %ld", client->id); LL_DELETE(sdata->dead_instances, client); From 9df5a9cf2ec934617dc3e06bd3038ac4002bd162 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 16 Jan 2015 12:06:15 +1100 Subject: [PATCH 10/39] Get rid of cute locking in disconnected session check for simplicity --- src/stratifier.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 6ea66790..42b73038 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1126,7 +1126,7 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, /* Number is in BE but we don't swap either of them */ hex2bin(&session64, sessionid, 8); - ck_ilock(&sdata->instance_lock); + ck_wlock(&sdata->instance_lock); HASH_ITER(hh, sdata->stratum_instances, instance, tmp) { if (instance->id == id) continue; @@ -1140,15 +1140,12 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, 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; } out_unlock: - ck_uilock(&sdata->instance_lock); + ck_wunlock(&sdata->instance_lock); out: return ret; } From 0f56ed8c3837c4f8269895f33836e63c6514ef2e Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 16 Jan 2015 13:28:03 +1100 Subject: [PATCH 11/39] Add idle, disconnected and dead counts to pool stats --- src/stratifier.c | 166 ++++++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 75 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 42b73038..30e57b93 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -41,6 +41,8 @@ struct pool_stats { int workers; int users; + int disconnected; + int dead; /* Absolute shares stats */ int64_t unaccounted_shares; @@ -855,6 +857,12 @@ static void update_base(ckpool_t *ckp, int prio) create_pthread(pth, do_update, ur); } +static void __del_disconnected(sdata_t *sdata, stratum_instance_t *client) +{ + HASH_DEL(sdata->disconnected_instances, client); + sdata->stats.disconnected--; +} + static void drop_allclients(ckpool_t *ckp) { stratum_instance_t *client, *tmp; @@ -868,7 +876,7 @@ static void drop_allclients(ckpool_t *ckp) send_proc(ckp->connector, buf); } HASH_ITER(hh, sdata->disconnected_instances, client, tmp) - HASH_DEL(sdata->disconnected_instances, client); + __del_disconnected(sdata, client); sdata->stats.users = sdata->stats.workers = 0; ck_wunlock(&sdata->instance_lock); } @@ -1110,6 +1118,7 @@ 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); + sdata->stats.dead++; } /* Only supports a full ckpool instance sessionid with an 8 byte sessionid */ @@ -1140,7 +1149,7 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, if (instance) { /* If we've found a matching disconnected instance, use it only * once and discard it */ - HASH_DEL(sdata->disconnected_instances, instance); + __del_disconnected(sdata, instance); kill_instance(sdata, instance); ret = true; } @@ -1249,6 +1258,7 @@ static void drop_client(sdata_t *sdata, int64_t id) /* Only keep around one copy of the old client in server mode */ if (!client->ckp->proxy && !old_client && client->enonce1_64) { HASH_ADD(hh, sdata->disconnected_instances, enonce1_64, sizeof(uint64_t), client); + sdata->stats.disconnected++; client->disconnected_time = time(NULL); } else kill_instance(sdata, client); @@ -1272,7 +1282,7 @@ static void drop_client(sdata_t *sdata, int64_t id) if (now_t - client->disconnected_time < 600) continue; LOGINFO("Discarding aged disconnected instance %ld", client->id); - HASH_DEL(sdata->disconnected_instances, client); + __del_disconnected(sdata, client); kill_instance(sdata, client); } /* Discard any dead instances that no longer hold any reference counts, @@ -1281,6 +1291,7 @@ static void drop_client(sdata_t *sdata, int64_t id) if (!client->ref) { LOGINFO("Stratifier discarding instance %ld", client->id); LL_DELETE(sdata->dead_instances, client); + sdata->stats.dead--; free(client->workername); free(client->useragent); free(client); @@ -3462,6 +3473,7 @@ static void *statsupdate(void *arg) user_instance_t *instance, *tmpuser; stratum_instance_t *client, *tmp; double sps1, sps5, sps15, sps60; + int idle_workers = 0; char fname[512] = {}; tv_t now, diff; ts_t ts_now; @@ -3474,78 +3486,6 @@ static void *statsupdate(void *arg) timersub(&now, &stats->start_time, &diff); tdiff = diff.tv_sec + (double)diff.tv_usec / 1000000; - ghs1 = stats->dsps1 * nonces; - suffix_string(ghs1, suffix1, 16, 0); - sps1 = stats->sps1; - - bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 300); - ghs5 = stats->dsps5 * nonces / bias; - sps5 = stats->sps5 / bias; - suffix_string(ghs5, suffix5, 16, 0); - - bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 900); - ghs15 = stats->dsps15 * nonces / bias; - suffix_string(ghs15, suffix15, 16, 0); - sps15 = stats->sps15 / bias; - - bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 3600); - ghs60 = stats->dsps60 * nonces / bias; - sps60 = stats->sps60 / bias; - suffix_string(ghs60, suffix60, 16, 0); - - bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 21600); - ghs360 = stats->dsps360 * nonces / bias; - suffix_string(ghs360, suffix360, 16, 0); - - bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 86400); - ghs1440 = stats->dsps1440 * nonces / bias; - suffix_string(ghs1440, suffix1440, 16, 0); - - bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 604800); - ghs10080 = stats->dsps10080 * nonces / bias; - suffix_string(ghs10080, suffix10080, 16, 0); - - snprintf(fname, 511, "%s/pool/pool.status", ckp->logdir); - fp = fopen(fname, "we"); - if (unlikely(!fp)) - LOGERR("Failed to fopen %s", fname); - - JSON_CPACK(val, "{si,si,si}", - "runtime", diff.tv_sec, - "Users", stats->users, - "Workers", stats->workers); - s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); - json_decref(val); - LOGNOTICE("Pool:%s", s); - fprintf(fp, "%s\n", s); - dealloc(s); - - JSON_CPACK(val, "{ss,ss,ss,ss,ss,ss,ss}", - "hashrate1m", suffix1, - "hashrate5m", suffix5, - "hashrate15m", suffix15, - "hashrate1hr", suffix60, - "hashrate6hr", suffix360, - "hashrate1d", suffix1440, - "hashrate7d", suffix10080); - s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); - json_decref(val); - LOGNOTICE("Pool:%s", s); - fprintf(fp, "%s\n", s); - dealloc(s); - - JSON_CPACK(val, "{sf,sf,sf,sf}", - "SPS1m", sps1, - "SPS5m", sps5, - "SPS15m", sps15, - "SPS1h", sps60); - s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); - json_decref(val); - LOGNOTICE("Pool:%s", s); - fprintf(fp, "%s\n", s); - dealloc(s); - fclose(fp); - ck_rlock(&sdata->instance_lock); HASH_ITER(hh, sdata->stratum_instances, client, tmp) { if (!client->authorised) @@ -3578,6 +3518,7 @@ static void *statsupdate(void *arg) decay_time(&worker->dsps5, 0, per_tdiff, 300); decay_time(&worker->dsps60, 0, per_tdiff, 3600); decay_time(&worker->dsps1440, 0, per_tdiff, 86400); + idle_workers++; worker->idle = true; } ghs = worker->dsps1 * nonces; @@ -3662,6 +3603,81 @@ static void *statsupdate(void *arg) } ck_runlock(&sdata->instance_lock); + ghs1 = stats->dsps1 * nonces; + suffix_string(ghs1, suffix1, 16, 0); + sps1 = stats->sps1; + + bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 300); + ghs5 = stats->dsps5 * nonces / bias; + sps5 = stats->sps5 / bias; + suffix_string(ghs5, suffix5, 16, 0); + + bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 900); + ghs15 = stats->dsps15 * nonces / bias; + suffix_string(ghs15, suffix15, 16, 0); + sps15 = stats->sps15 / bias; + + bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 3600); + ghs60 = stats->dsps60 * nonces / bias; + sps60 = stats->sps60 / bias; + suffix_string(ghs60, suffix60, 16, 0); + + bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 21600); + ghs360 = stats->dsps360 * nonces / bias; + suffix_string(ghs360, suffix360, 16, 0); + + bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 86400); + ghs1440 = stats->dsps1440 * nonces / bias; + suffix_string(ghs1440, suffix1440, 16, 0); + + bias = !CKP_STANDALONE(ckp) ? 1.0 : time_bias(tdiff, 604800); + ghs10080 = stats->dsps10080 * nonces / bias; + suffix_string(ghs10080, suffix10080, 16, 0); + + snprintf(fname, 511, "%s/pool/pool.status", ckp->logdir); + fp = fopen(fname, "we"); + if (unlikely(!fp)) + LOGERR("Failed to fopen %s", fname); + + JSON_CPACK(val, "{si,si,si,si,si,si}", + "runtime", diff.tv_sec, + "Users", stats->users, + "Workers", stats->workers, + "Idle", idle_workers, + "Disconnected", stats->disconnected, + "Dead", stats->dead); + s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); + json_decref(val); + LOGNOTICE("Pool:%s", s); + fprintf(fp, "%s\n", s); + dealloc(s); + + JSON_CPACK(val, "{ss,ss,ss,ss,ss,ss,ss}", + "hashrate1m", suffix1, + "hashrate5m", suffix5, + "hashrate15m", suffix15, + "hashrate1hr", suffix60, + "hashrate6hr", suffix360, + "hashrate1d", suffix1440, + "hashrate7d", suffix10080); + s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); + json_decref(val); + LOGNOTICE("Pool:%s", s); + fprintf(fp, "%s\n", s); + dealloc(s); + + JSON_CPACK(val, "{sf,sf,sf,sf}", + "SPS1m", sps1, + "SPS5m", sps5, + "SPS15m", sps15, + "SPS1h", sps60); + s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); + json_decref(val); + LOGNOTICE("Pool:%s", s); + fprintf(fp, "%s\n", s); + dealloc(s); + fclose(fp); + ts_realtime(&ts_now); sprintf(cdfield, "%lu,%lu", ts_now.tv_sec, ts_now.tv_nsec); JSON_CPACK(val, "{ss,si,si,si,sf,sf,sf,sf,ss,ss,ss,ss}", From 4662873d7004cff6c1bc16d131309da5e337c8a6 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 16 Jan 2015 13:31:54 +1100 Subject: [PATCH 12/39] Only add authorised clients to disconnected list --- src/stratifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index 30e57b93..a7badc22 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1256,7 +1256,7 @@ static void drop_client(sdata_t *sdata, int64_t id) HASH_DEL(sdata->stratum_instances, 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 */ - if (!client->ckp->proxy && !old_client && client->enonce1_64) { + if (!client->ckp->proxy && !old_client && client->enonce1_64 && dec) { HASH_ADD(hh, sdata->disconnected_instances, enonce1_64, sizeof(uint64_t), client); sdata->stats.disconnected++; client->disconnected_time = time(NULL); From 33c2465eef2ee2c86cf8f99bad64621b40a5061b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 16 Jan 2015 13:48:49 +1100 Subject: [PATCH 13/39] Remove worker instances and their data on killing their client instances --- src/stratifier.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index a7badc22..53f16551 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1115,8 +1115,17 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, int64_t id, int /* 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); + user_instance_t *instance = client->user_instance; + + if (instance) { + worker_instance_t *worker = client->worker_instance; + + DL_DELETE(instance->instances, client); + if (worker) { + DL_DELETE(instance->worker_instances, worker); + free(worker); + } + } LL_PREPEND(sdata->dead_instances, client); sdata->stats.dead++; } From 7abd2923573554831e7c8fb925324d0583b5573f Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 16 Jan 2015 14:32:27 +1100 Subject: [PATCH 14/39] ckdb - log steps in the storage dealloc during shutdown --- src/ckdb.c | 16 ++++++++++++++++ src/ckdb.h | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ckdb.c b/src/ckdb.c index 91bb3fdc..3b9858a2 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -1117,6 +1117,8 @@ static void alloc_storage() static void dealloc_storage() { + LOGWARNING("%s() logqueue ...", __func__); + FREE_LISTS(logqueue); FREE_TREE(marks); @@ -1128,6 +1130,8 @@ static void dealloc_storage() FREE_STORE_DATA(workmarkers); FREE_LIST_DATA(workmarkers); + LOGWARNING("%s() markersummary ...", __func__); + FREE_TREE(markersummary_userid); FREE_TREE(markersummary); FREE_STORE_DATA(markersummary); @@ -1135,6 +1139,8 @@ static void dealloc_storage() FREE_ALL(workerstatus); + LOGWARNING("%s() userstats ...", __func__); + FREE_TREE(userstats_workerstatus); FREE_TREE(userstats_statsdate); if (userstats_summ) @@ -1142,11 +1148,15 @@ static void dealloc_storage() FREE_STORE(userstats_eos); FREE_ALL(userstats); + LOGWARNING("%s() poolstats ...", __func__); + FREE_ALL(poolstats); FREE_ALL(auths); FREE_ALL(miningpayouts); FREE_ALL(blocks); + LOGWARNING("%s() sharesummary ...", __func__); + FREE_TREE(sharesummary_workinfoid); FREE_TREE(sharesummary); FREE_STORE_DATA(sharesummary); @@ -1155,6 +1165,8 @@ static void dealloc_storage() FREE_ALL(shareerrors); FREE_ALL(shares); + LOGWARNING("%s() workinfo ...", __func__); + FREE_TREE(workinfo_height); FREE_TREE(workinfo); FREE_STORE_DATA(workinfo); @@ -1174,9 +1186,13 @@ static void dealloc_storage() FREE_TREE(userid); FREE_ALL(users); + LOGWARNING("%s() transfer/heartbeatqueue/workqueue ...", __func__); + FREE_LIST(transfer); FREE_LISTS(heartbeatqueue); FREE_LISTS(workqueue); + + LOGWARNING("%s() finished", __func__); } static bool setup_data() diff --git a/src/ckdb.h b/src/ckdb.h index b0733d55..443c32c6 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.832" +#define CKDB_VERSION DB_VERSION"-0.833" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ From 8eee70a4a51d3127f48fdb105b4145d0690e2e78 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 16 Jan 2015 14:38:06 +1100 Subject: [PATCH 15/39] Do not delete the worker instance linked list on removing the worker from the list --- src/stratifier.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 53f16551..c04aa3f3 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1113,7 +1113,7 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, int64_t id, int } /* Add a stratum instance to the dead instances list */ -static void kill_instance(sdata_t *sdata, stratum_instance_t *client) +static void __kill_instance(sdata_t *sdata, stratum_instance_t *client) { user_instance_t *instance = client->user_instance; @@ -1121,10 +1121,8 @@ static void kill_instance(sdata_t *sdata, stratum_instance_t *client) worker_instance_t *worker = client->worker_instance; DL_DELETE(instance->instances, client); - if (worker) { + if (worker) DL_DELETE(instance->worker_instances, worker); - free(worker); - } } LL_PREPEND(sdata->dead_instances, client); sdata->stats.dead++; @@ -1159,7 +1157,7 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, /* If we've found a matching disconnected instance, use it only * once and discard it */ __del_disconnected(sdata, instance); - kill_instance(sdata, instance); + __kill_instance(sdata, instance); ret = true; } out_unlock: @@ -1270,7 +1268,7 @@ static void drop_client(sdata_t *sdata, int64_t id) sdata->stats.disconnected++; client->disconnected_time = time(NULL); } else - kill_instance(sdata, client); + __kill_instance(sdata, client); } ck_wunlock(&sdata->instance_lock); @@ -1292,7 +1290,7 @@ static void drop_client(sdata_t *sdata, int64_t id) continue; LOGINFO("Discarding aged disconnected instance %ld", client->id); __del_disconnected(sdata, client); - kill_instance(sdata, client); + __kill_instance(sdata, client); } /* Discard any dead instances that no longer hold any reference counts, * freeing up their memory safely */ From 84cb20ccaa8c8a9241d3163ef83aaef5eef3d26f Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 16 Jan 2015 14:46:34 +1100 Subject: [PATCH 16/39] ckdb - since they are as yet unused, don't store new auths in ram --- src/ckdb.h | 2 +- src/ckdb_dbio.c | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 443c32c6..4de78164 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.833" +#define CKDB_VERSION DB_VERSION"-0.834" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 6c453461..0a903aad 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -4627,12 +4627,18 @@ unitem: if (conned) PQfinish(conn); K_WLOCK(auths_free); +#if 1 + /* To save ram for now, don't store them, + * we don't actually use them anywhere yet */ + k_add_head(auths_free, a_item); +#else if (!ok) k_add_head(auths_free, a_item); else { auths_root = add_to_ktree(auths_root, a_item, cmp_auths); k_add_head(auths_store, a_item); } +#endif K_WUNLOCK(auths_free); return ok; @@ -4644,25 +4650,30 @@ bool auths_fill(PGconn *conn) PGresult *res; K_ITEM *item; AUTHS *row; -// char *params[1]; + char *params[2]; int n, i; -// int par = 0; + int par = 0; char *field; char *sel; - int fields = 7 + 1; // +1 = 'best' + int fields = 7; bool ok; + tv_t now; LOGDEBUG("%s(): select", __func__); // TODO: add/update a (single) fake auth every ~10min or 10min after the last one? -#if 0 + sel = "select " "authid,userid,workername,clientid,enonce1,useragent,preauth" HISTORYDATECONTROL - " from auths where expirydate=$1"; + " from auths where expirydate=$1 and createdate>=$2"; + + setnow(&now); + now.tv_sec -= (24 * 60 * 60); // last day worth par = 0; params[par++] = tv_to_buf((tv_t *)(&default_expiry), NULL, 0); + params[par++] = tv_to_buf((tv_t *)(&now), NULL, 0); PARCHK(par, params); res = PQexecParams(conn, sel, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_READ); rescode = PQresultStatus(res); @@ -4671,8 +4682,8 @@ bool auths_fill(PGconn *conn) PQclear(res); return false; } -#endif +#if 0 // Only load the last record for each workername sel = "with last as (" "select authid,userid,workername,clientid,enonce1,useragent,preauth" @@ -4689,6 +4700,7 @@ bool auths_fill(PGconn *conn) PQclear(res); return false; } +#endif n = PQnfields(res); if (n != (fields + HISTORYDATECOUNT)) { From 468e9ee8d70c44eecfe71058cd3ec194523be10e Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 16 Jan 2015 18:31:55 +1100 Subject: [PATCH 17/39] ckdb - add a flush socket command to flush stdin, stdout and the logmsg log file --- src/ckdb.c | 12 ++++++++++++ src/ckdb.h | 3 ++- src/ckdb_cmd.c | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ckdb.c b/src/ckdb.c index 3b9858a2..71b22bea 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -2720,6 +2720,17 @@ static void *socketer(__maybe_unused void *arg) } send_unix_msg(sockd, reply); break; + case CMD_FLUSH: + LOGDEBUG("Listener received flush request"); + snprintf(reply, sizeof(reply), + "%s.%ld.ok.splash", + id, now.tv_sec); + send_unix_msg(sockd, reply); + fflush(stdout); + fflush(stderr); + if (global_ckp && global_ckp->logfd) + fflush(global_ckp->logfp); + break; // Always process immediately: case CMD_AUTH: case CMD_ADDRAUTH: @@ -2996,6 +3007,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) case CMD_PING: case CMD_VERSION: case CMD_LOGLEVEL: + case CMD_FLUSH: // Non pool commands, shouldn't be there case CMD_ADDUSER: case CMD_NEWPASS: diff --git a/src/ckdb.h b/src/ckdb.h index 4de78164..40da3ffa 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.834" +#define CKDB_VERSION DB_VERSION"-0.835" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -290,6 +290,7 @@ enum cmd_values { CMD_PING, CMD_VERSION, CMD_LOGLEVEL, + CMD_FLUSH, CMD_SHARELOG, CMD_AUTH, CMD_ADDRAUTH, diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 5ece47c8..37fbd179 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -4525,6 +4525,7 @@ struct CMDS ckdb_cmds[] = { { CMD_PING, "ping", true, false, NULL, ACCESS_SYSTEM ACCESS_POOL ACCESS_WEB }, { CMD_VERSION, "version", true, false, NULL, ACCESS_SYSTEM ACCESS_POOL ACCESS_WEB }, { CMD_LOGLEVEL, "loglevel", true, false, NULL, ACCESS_SYSTEM }, + { CMD_FLUSH, "flush", true, false, NULL, ACCESS_SYSTEM }, { CMD_SHARELOG, STR_WORKINFO, false, true, cmd_sharelog, ACCESS_POOL }, { CMD_SHARELOG, STR_SHARES, false, true, cmd_sharelog, ACCESS_POOL }, { CMD_SHARELOG, STR_SHAREERRORS, false, true, cmd_sharelog, ACCESS_POOL }, From 112c5d01f485d63337513787154c42947fafb929 Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 16 Jan 2015 20:22:09 +1100 Subject: [PATCH 18/39] php - convert a failed blocks access to pblocks --- pool/prime.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pool/prime.php b/pool/prime.php index 529e0438..2ac16d2e 100644 --- a/pool/prime.php +++ b/pool/prime.php @@ -22,6 +22,7 @@ function process($p, $user, $menu) $menu['Admin']['PPLNS'] = 'pplns'; $menu['Admin']['AllWork'] = 'allwork'; } +bp: $page = ''; $n = ''; foreach ($menu as $item => $options) @@ -33,6 +34,11 @@ function process($p, $user, $menu) $n = " - $name"; } + if ($page === '' and $p == 'blocks') + { + $p = 'pblocks'; + goto bp; + } if ($page === '') showPage($info, 'index', $menu, '', $user); else From 450f2040b2022633e56783cc1c9f1a5d0966b65a Mon Sep 17 00:00:00 2001 From: ckolivas Date: Fri, 16 Jan 2015 20:33:52 +1100 Subject: [PATCH 19/39] Only iterate over workers in workerstats if some are left in the worker_instances list --- src/stratifier.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/stratifier.c b/src/stratifier.c index c04aa3f3..b669e235 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -3517,6 +3517,9 @@ static void *statsupdate(void *arg) worker_instance_t *worker; bool idle = false; + if (instance->workers < 1) + continue; + /* Decay times per worker */ DL_FOREACH(instance->worker_instances, worker) { per_tdiff = tvdiff(&now, &worker->last_share); From 003408e441b2b1a79e91c6a5dd202043f64c5cda Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 16 Jan 2015 23:11:31 +1100 Subject: [PATCH 20/39] ckdb - add debug to pplns --- src/ckdb.h | 2 +- src/ckdb_cmd.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 40da3ffa..d243a037 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.835" +#define CKDB_VERSION DB_VERSION"-0.836" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 37fbd179..c64775ec 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -3502,6 +3502,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, allow_aged = true; } + LOGDEBUG("%s(): height %"PRId32, __func__, height); + block_tv.tv_sec = block_tv.tv_usec = 0L; cd.tv_sec = cd.tv_usec = 0L; lookblocks.height = height + 1; @@ -3538,6 +3540,9 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, blocks_confirmed(BLOCKS_NEW_STR)); return strdup(reply); } + LOGDEBUG("%s(): block %"PRId32"/%"PRId64"/%s/%s/%"PRId64, + __func__, blocks->height, blocks->workinfoid, + blocks->workername, blocks->confirmed, blocks->reward); switch (blocks->confirmed[0]) { case BLOCKS_NEW: block_extra = "Can't be paid out yet"; @@ -3571,7 +3576,9 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, countbacklimit = true; else countbacklimit = false; - + LOGDEBUG("%s(): ndiff %.0f limit=%s", + __func__, ndiff, + countbacklimit ? "true" : "false"); begin_workinfoid = end_workinfoid = 0; total_share_count = acc_share_count = 0; total_diff = 0; @@ -3649,7 +3656,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, ss_item = prev_in_ktree(ctx); DATA_SHARESUMMARY_NULL(sharesummary, ss_item); } - + LOGDEBUG("%s(): ss %"PRId64" total %.0f want %.0f", + __func__, ss_count, total_diff, diff_want); /* If we haven't met or exceeded the required N, * move on to the markersummaries */ if (total_diff < diff_want) { @@ -3664,6 +3672,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, wm_item = find_before_in_ktree(workmarkers_workinfoid_root, &wm_look, cmp_workmarkers_workinfoid, wm_ctx); DATA_WORKMARKERS_NULL(workmarkers, wm_item); + LOGDEBUG("%s(): workmarkers < %"PRId64, __func__, lookworkmarkers.workinfoidend); while (total_diff < diff_want && wm_item && CURRENT(&(workmarkers->expirydate))) { if (WMPROCESSED(workmarkers->status)) { // Stop before FIVExWID if necessary @@ -3700,11 +3709,14 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, wm_item = prev_in_ktree(wm_ctx); DATA_WORKMARKERS_NULL(workmarkers, wm_item); } + LOGDEBUG("%s(): wm %"PRId64" ms %"PRId64" total %.0f want %.0f", + __func__, wm_count, ms_count, total_diff, diff_want); } K_RUNLOCK(markersummary_free); K_RUNLOCK(workmarkers_free); K_RUNLOCK(sharesummary_free); + LOGDEBUG("%s(): total %.0f want %.0f", __func__, total_diff, diff_want); if (total_diff == 0.0) { snprintf(reply, siz, "ERR.total share diff 0 before workinfo %"PRId64, From deb63501b91679500091e0384f2f74721aae9317 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 17 Jan 2015 13:20:41 +1100 Subject: [PATCH 21/39] ckdb - workmarkers has 2 trees, fix so both are always updated --- src/ckdb.h | 2 +- src/ckdb_dbio.c | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ckdb.h b/src/ckdb.h index d243a037..731607a5 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.836" +#define CKDB_VERSION DB_VERSION"-0.837" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 0a903aad..f2b194cb 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -5978,15 +5978,24 @@ unparam: workmarkers_root = remove_from_ktree(workmarkers_root, old_wm_item, cmp_workmarkers); + workmarkers_workinfoid_root = remove_from_ktree(workmarkers_workinfoid_root, + old_wm_item, + cmp_workmarkers_workinfoid); copy_tv(&(oldworkmarkers->expirydate), cd); workmarkers_root = add_to_ktree(workmarkers_root, old_wm_item, cmp_workmarkers); + workmarkers_workinfoid_root = add_to_ktree(workmarkers_workinfoid_root, + old_wm_item, + cmp_workmarkers_workinfoid); } if (wm_item) { workmarkers_root = add_to_ktree(workmarkers_root, wm_item, cmp_workmarkers); + workmarkers_workinfoid_root = add_to_ktree(workmarkers_workinfoid_root, + wm_item, + cmp_workmarkers_workinfoid); k_add_head(workmarkers_store, wm_item); } } From 11fc2fb67df9e452698b84eae0e029805ce1a018 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sat, 17 Jan 2015 17:05:24 +1100 Subject: [PATCH 22/39] Revert "Only iterate over workers in workerstats if some are left in the worker_instances list" This reverts commit 450f2040b2022633e56783cc1c9f1a5d0966b65a. Of no advantage. --- src/stratifier.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index b669e235..c04aa3f3 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -3517,9 +3517,6 @@ static void *statsupdate(void *arg) worker_instance_t *worker; bool idle = false; - if (instance->workers < 1) - continue; - /* Decay times per worker */ DL_FOREACH(instance->worker_instances, worker) { per_tdiff = tvdiff(&now, &worker->last_share); From b172162f276e5993ce974b1032e6567c48bee7fa Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sat, 17 Jan 2015 17:07:34 +1100 Subject: [PATCH 23/39] kill_instance always follows del_disconnected --- src/stratifier.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index c04aa3f3..d45fedce 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -857,10 +857,27 @@ static void update_base(ckpool_t *ckp, int prio) create_pthread(pth, do_update, ur); } +/* Add a stratum instance to the dead instances list */ +static void __kill_instance(sdata_t *sdata, stratum_instance_t *client) +{ + user_instance_t *instance = client->user_instance; + + if (instance) { + worker_instance_t *worker = client->worker_instance; + + DL_DELETE(instance->instances, client); + if (worker) + DL_DELETE(instance->worker_instances, worker); + } + LL_PREPEND(sdata->dead_instances, client); + sdata->stats.dead++; +} + static void __del_disconnected(sdata_t *sdata, stratum_instance_t *client) { HASH_DEL(sdata->disconnected_instances, client); sdata->stats.disconnected--; + __kill_instance(sdata, client); } static void drop_allclients(ckpool_t *ckp) @@ -1112,22 +1129,6 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, int64_t id, int return instance; } -/* Add a stratum instance to the dead instances list */ -static void __kill_instance(sdata_t *sdata, stratum_instance_t *client) -{ - user_instance_t *instance = client->user_instance; - - if (instance) { - worker_instance_t *worker = client->worker_instance; - - DL_DELETE(instance->instances, client); - if (worker) - DL_DELETE(instance->worker_instances, worker); - } - LL_PREPEND(sdata->dead_instances, client); - sdata->stats.dead++; -} - /* 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) { @@ -1157,7 +1158,6 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, /* If we've found a matching disconnected instance, use it only * once and discard it */ __del_disconnected(sdata, instance); - __kill_instance(sdata, instance); ret = true; } out_unlock: @@ -1290,7 +1290,6 @@ static void drop_client(sdata_t *sdata, int64_t id) continue; LOGINFO("Discarding aged disconnected instance %ld", client->id); __del_disconnected(sdata, client); - __kill_instance(sdata, client); } /* Discard any dead instances that no longer hold any reference counts, * freeing up their memory safely */ From 1465002ecc1e2c1e474575d8ce2165ffcec9c598 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sat, 17 Jan 2015 17:17:09 +1100 Subject: [PATCH 24/39] Only lock and release the write instance lock once in drop_client --- src/stratifier.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index d45fedce..b0351cba 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1244,17 +1244,18 @@ static void dec_worker(ckpool_t *ckp, user_instance_t *instance) static void drop_client(sdata_t *sdata, int64_t id) { stratum_instance_t *client, *tmp; + user_instance_t *instance = NULL; time_t now_t = time(NULL); + ckpool_t *ckp = NULL; bool dec = false; - LOGINFO("Stratifier dropping client %ld", id); + LOGINFO("Stratifier requested to drop client %ld", id); ck_wlock(&sdata->instance_lock); client = __instance_by_id(sdata, id); if (client) { stratum_instance_t *old_client = NULL; - __inc_instance_ref(client); if (client->authorised) { dec = true; client->authorised = false; @@ -1269,19 +1270,11 @@ static void drop_client(sdata_t *sdata, int64_t id) client->disconnected_time = time(NULL); } else __kill_instance(sdata, client); + ckp = client->ckp; + instance = client->user_instance; + LOGINFO("Stratifer dropped %sauthorised client %ld", dec ? "" : "un", id); } - ck_wunlock(&sdata->instance_lock); - - /* Decrease worker count outside of instance_lock to avoid recursive - * locking */ - if (dec) - dec_worker(client->ckp, client->user_instance); - /* Cull old unused clients lazily when there are no more reference - * counts for them. */ - ck_wlock(&sdata->instance_lock); - if (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 */ @@ -1291,8 +1284,9 @@ static void drop_client(sdata_t *sdata, int64_t id) LOGINFO("Discarding aged disconnected instance %ld", client->id); __del_disconnected(sdata, client); } - /* Discard any dead instances that no longer hold any reference counts, - * freeing up their memory safely */ + + /* Cull old unused clients lazily when there are no more reference + * counts for them. */ LL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { if (!client->ref) { LOGINFO("Stratifier discarding instance %ld", client->id); @@ -1304,6 +1298,11 @@ static void drop_client(sdata_t *sdata, int64_t id) } } ck_wunlock(&sdata->instance_lock); + + /* Decrease worker count outside of instance_lock to avoid recursive + * locking. ckp and instance are guaranteed to be set if dec is true */ + if (dec) + dec_worker(ckp, instance); } static void stratum_broadcast_message(sdata_t *sdata, const char *msg) From e91ea6c235b9972fe0bb132608278bc45ca65c00 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sat, 17 Jan 2015 17:25:48 +1100 Subject: [PATCH 25/39] Add sanity breakout of worker instance looping in statsupdate --- src/stratifier.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/stratifier.c b/src/stratifier.c index b0351cba..c3f795c6 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -3513,10 +3513,18 @@ static void *statsupdate(void *arg) HASH_ITER(hh, sdata->user_instances, instance, tmpuser) { worker_instance_t *worker; + int iterations = 0; bool idle = false; /* Decay times per worker */ DL_FOREACH(instance->worker_instances, worker) { + /* FIXME: This shouldn't happen and is purely a sanity + * breakout till the real issue is found fixed. */ + if (unlikely(iterations++ > instance->workers)) { + LOGWARNING("Statsupdate trying to iterate more than %d existing workers for worker %s", + instance->workers, worker->workername); + break; + } per_tdiff = tvdiff(&now, &worker->last_share); if (per_tdiff > 60) { decay_time(&worker->dsps1, 0, per_tdiff, 60); From e397757ec8bc39820096da81d5198c2c5c1c3239 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 17 Jan 2015 21:09:58 +1100 Subject: [PATCH 26/39] php - update the payout details to match the new shift code --- pool/page_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pool/page_payout.php b/pool/page_payout.php index 5949edf3..2363c1a3 100644 --- a/pool/page_payout.php +++ b/pool/page_payout.php @@ -10,7 +10,7 @@ function dopayout($data, $user) $pg .= ' when a block is found,
'; $pg .= 'but includes the full shift at the start and end of the range,
'; $pg .= 'so it usually will be a bit more than 5N.

'; - $pg .= 'Shifts are ~30s long, however, when any network block is found
'; + $pg .= 'Shifts are ~50min long, however, when we find any pool blocks
'; $pg .= 'the current shift ends at the point the block was found.
'; $pg .= 'A ckpool restart will also start a new shift.

'; $pg .= 'Transaction fees are included in the miner payout.
'; From 9c262b7fe86b65fd1565128c081c7be5e11bac23 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sat, 17 Jan 2015 22:48:13 +1100 Subject: [PATCH 27/39] Keep worker instances in the linked list since we don't know if we're removing the last one or not --- src/stratifier.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index c3f795c6..59eaaf52 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -862,13 +862,8 @@ static void __kill_instance(sdata_t *sdata, stratum_instance_t *client) { user_instance_t *instance = client->user_instance; - if (instance) { - worker_instance_t *worker = client->worker_instance; - + if (likely(instance)) DL_DELETE(instance->instances, client); - if (worker) - DL_DELETE(instance->worker_instances, worker); - } LL_PREPEND(sdata->dead_instances, client); sdata->stats.dead++; } From 137203c01aacad5bf93a586dc8c0a8a8f2b4e4c0 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sat, 17 Jan 2015 22:50:40 +1100 Subject: [PATCH 28/39] Count each idle client as an idle worker instead of per workername --- src/stratifier.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 59eaaf52..99dac9e9 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -3502,7 +3502,7 @@ static void *statsupdate(void *arg) decay_time(&client->dsps10080, 0, per_tdiff, 604800); if (per_tdiff > 600) client->idle = true; - continue; + idle_workers++; } } @@ -3514,7 +3514,7 @@ static void *statsupdate(void *arg) /* Decay times per worker */ DL_FOREACH(instance->worker_instances, worker) { /* FIXME: This shouldn't happen and is purely a sanity - * breakout till the real issue is found fixed. */ + * breakout till the real issue is found and fixed. */ if (unlikely(iterations++ > instance->workers)) { LOGWARNING("Statsupdate trying to iterate more than %d existing workers for worker %s", instance->workers, worker->workername); @@ -3526,7 +3526,6 @@ static void *statsupdate(void *arg) decay_time(&worker->dsps5, 0, per_tdiff, 300); decay_time(&worker->dsps60, 0, per_tdiff, 3600); decay_time(&worker->dsps1440, 0, per_tdiff, 86400); - idle_workers++; worker->idle = true; } ghs = worker->dsps1 * nonces; From 24cb6e0c3e7b0011c7b3ea5be149c88c9ba1d0c2 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sat, 17 Jan 2015 23:20:02 +1100 Subject: [PATCH 29/39] Count the number of workernames and use that as the upper limit for the sanity check in statsupdate --- src/stratifier.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 99dac9e9..0f8fbd0d 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -171,6 +171,7 @@ struct user_instance { /* A linked list of all connected workers of this user */ worker_instance_t *worker_instances; + int workernames; /* How many different workernames exist */ int workers; @@ -1905,6 +1906,7 @@ static user_instance_t *generate_user(ckpool_t *ckp, stratum_instance_t *client, read_workerstats(ckp, worker); worker->start_time = time(NULL); client->worker_instance = worker; + instance->workernames++; } DL_APPEND(instance->instances, client); ck_wunlock(&sdata->instance_lock); @@ -3513,11 +3515,10 @@ static void *statsupdate(void *arg) /* Decay times per worker */ DL_FOREACH(instance->worker_instances, worker) { - /* FIXME: This shouldn't happen and is purely a sanity - * breakout till the real issue is found and fixed. */ - if (unlikely(iterations++ > instance->workers)) { + /* Sanity check, should never happen */ + if (unlikely(iterations++ > instance->workernames)) { LOGWARNING("Statsupdate trying to iterate more than %d existing workers for worker %s", - instance->workers, worker->workername); + instance->workernames, worker->workername); break; } per_tdiff = tvdiff(&now, &worker->last_share); From e1514cdc014e662e966d678c634d40ad8c816f2d Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sun, 18 Jan 2015 09:04:33 +1100 Subject: [PATCH 30/39] Drop two potentally unhandled reference counts --- src/stratifier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 0f8fbd0d..14243316 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -2935,7 +2935,7 @@ static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val /* Shouldn't happen, sanity check */ if (unlikely(!result_val)) { LOGWARNING("parse_subscribe returned NULL result_val"); - return; + goto out; } val = json_object(); json_object_set_new_nocheck(val, "result", result_val); @@ -2990,7 +2990,7 @@ static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val if (cmdmatch(method, "mining.suggest")) { suggest_diff(client, method, params_val); - return; + goto out; } /* Covers both get_transactions and get_txnhashes */ From 85230c270eb4503d0d0521e7e192b8f3a34c7025 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sun, 18 Jan 2015 09:24:30 +1100 Subject: [PATCH 31/39] Reset all best share counters after a block solve --- src/stratifier.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/stratifier.c b/src/stratifier.c index 14243316..c26eed6d 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1332,6 +1332,26 @@ static void reconnect_clients(sdata_t *sdata, const char *cmd) stratum_broadcast(sdata, json_msg); } +static void reset_bestshares(sdata_t *sdata) +{ + user_instance_t *instance, *tmpuser; + stratum_instance_t *client, *tmp; + + ck_rlock(&sdata->instance_lock); + HASH_ITER(hh, sdata->stratum_instances, client, tmp) { + client->best_diff = 0; + } + HASH_ITER(hh, sdata->user_instances, instance, tmpuser) { + worker_instance_t *worker; + + instance->best_diff = 0; + DL_FOREACH(instance->worker_instances, worker) { + worker->best_diff = 0; + } + } + ck_runlock(&sdata->instance_lock); +} + static void block_solve(ckpool_t *ckp, const char *blockhash) { ckmsg_t *block, *tmp, *found = NULL; @@ -1385,6 +1405,7 @@ static void block_solve(ckpool_t *ckp, const char *blockhash) free(msg); LOGWARNING("Solved and confirmed block %d", height); + reset_bestshares(sdata); } static void block_reject(sdata_t *sdata, const char *blockhash) From 93822b28a262d4204873cee1fba2d310425a36ad Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sun, 18 Jan 2015 09:36:47 +1100 Subject: [PATCH 32/39] Add a json_get_double helper --- src/ckpool.c | 20 ++++++++++++++++++++ src/ckpool.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/ckpool.c b/src/ckpool.c index bef14365..60374273 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -997,6 +997,26 @@ out: return ret; } +bool json_get_double(double *store, json_t *val, const char *res) +{ + json_t *entry = json_object_get(val, res); + bool ret = false; + + if (!entry) { + LOGDEBUG("Json did not find entry %s", res); + goto out; + } + if (!json_is_real(entry)) { + LOGWARNING("Json entry %s is not a double", res); + goto out; + } + *store = json_real_value(entry); + LOGDEBUG("Json found entry %s: %f", res, *store); + ret = true; +out: + return ret; +} + static bool json_get_bool(bool *store, json_t *val, const char *res) { json_t *entry = json_object_get(val, res); diff --git a/src/ckpool.h b/src/ckpool.h index b8293474..0b28aa40 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -214,5 +214,6 @@ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req); int process_exit(ckpool_t *ckp, proc_instance_t *pi, int ret); bool json_get_string(char **store, json_t *val, const char *res); bool json_get_int(int *store, json_t *val, const char *res); +bool json_get_double(double *store, json_t *val, const char *res); #endif /* CKPOOL_H */ From 0c51e7e86315fd36b1c55ed2a93bc4fbcd2ac6b0 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Sun, 18 Jan 2015 09:40:32 +1100 Subject: [PATCH 33/39] Read off best share stats if they exist per user and worker --- src/stratifier.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index c26eed6d..a8d138ff 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1833,9 +1833,10 @@ static void read_userstats(ckpool_t *ckp, user_instance_t *instance) instance->dsps60 = dsps_from_key(val, "hashrate1hr"); instance->dsps1440 = dsps_from_key(val, "hashrate1d"); instance->dsps10080 = dsps_from_key(val, "hashrate7d"); - LOGINFO("Successfully read user %s stats %f %f %f %f %f", instance->username, + json_get_double(&instance->best_diff, val, "bestshare"); + LOGINFO("Successfully read user %s stats %f %f %f %f %f %f", instance->username, instance->dsps1, instance->dsps5, instance->dsps60, instance->dsps1440, - instance->dsps10080); + instance->dsps10080, instance->best_diff); json_decref(val); } @@ -1870,8 +1871,9 @@ static void read_workerstats(ckpool_t *ckp, worker_instance_t *worker) worker->dsps5 = dsps_from_key(val, "hashrate5m"); worker->dsps60 = dsps_from_key(val, "hashrate1d"); worker->dsps1440 = dsps_from_key(val, "hashrate1d"); - LOGINFO("Successfully read worker %s stats %f %f %f %f", worker->workername, - worker->dsps1, worker->dsps5, worker->dsps60, worker->dsps1440); + json_get_double(&worker->best_diff, val, "bestshare"); + 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); } From 84dc0146e524f64a41c2754121911d9d252fba5b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 18 Jan 2015 19:22:13 +1100 Subject: [PATCH 34/39] Check for corrupt ckdb responses in send_recv_auth --- src/stratifier.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index a8d138ff..1abede5e 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1982,7 +1982,7 @@ static int send_recv_auth(stratum_instance_t *client) json_msg = ckdb_msg(ckp, val, ID_AUTH); if (unlikely(!json_msg)) { LOGWARNING("Failed to dump json in send_recv_auth"); - return ret; + goto out; } /* We want responses from ckdb serialised and not interleaved with @@ -2002,7 +2002,10 @@ static int send_recv_auth(stratum_instance_t *client) json_t *val = NULL; LOGINFO("Got ckdb response: %s", buf); - sscanf(buf, "id.%*d.%s", response); + if (unlikely(sscanf(buf, "id.%*d.%s", response) < 1 || strlen(response) < 1 || !strchr(response, '='))) { + LOGWARNING("Got unparseable ckdb auth response: %s", buf); + goto out_fail; + } cmd = response; strsep(&cmd, "="); LOGINFO("User %s Worker %s got auth response: %s cmd: %s", @@ -2010,7 +2013,7 @@ static int send_recv_auth(stratum_instance_t *client) response, cmd); val = json_loads(cmd, 0, &err_val); if (unlikely(!val)) - LOGINFO("AUTH JSON decode failed(%d): %s", err_val.line, err_val.text); + LOGWARNING("AUTH JSON decode failed(%d): %s", err_val.line, err_val.text); else { json_get_string(&secondaryuserid, val, "secondaryuserid"); json_get_int(&worker->mindiff, val, "difficultydefault"); @@ -2028,11 +2031,12 @@ static int send_recv_auth(stratum_instance_t *client) } if (likely(val)) json_decref(val); - } else { - ret = -1; - LOGWARNING("Got no auth response from ckdb :("); + goto out; } - + LOGWARNING("Got no auth response from ckdb :("); +out_fail: + ret = -1; +out: return ret; } From 9edf91d17e21443ad8cf208ef77de040d6552412 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 18 Jan 2015 20:46:33 +1100 Subject: [PATCH 35/39] Differentiate generated authed users from unauthorised and don't do any stats on unauthed users --- src/stratifier.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 1abede5e..84f9a9a7 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -183,6 +183,8 @@ struct user_instance { double dsps1440; double dsps10080; tv_t last_share; + + bool authorised; /* Has this username ever been authorised? */ time_t auth_time; }; @@ -2116,8 +2118,6 @@ static json_t *parse_authorise(stratum_instance_t *client, json_t *params_val, j client->start_time = now.tv_sec; strcpy(client->address, address); - LOGNOTICE("Authorised client %ld worker %s as user %s", client->id, buf, - user_instance->username); client->workername = strdup(buf); if (CKP_STANDALONE(ckp)) ret = true; @@ -2139,9 +2139,16 @@ static json_t *parse_authorise(stratum_instance_t *client, json_t *params_val, j ret = true; } } - client->authorised = ret; - if (client->authorised) + if (ret) { + client->authorised = ret; + user_instance->authorised = ret; inc_worker(ckp, user_instance); + LOGNOTICE("Authorised client %ld worker %s as user %s", client->id, buf, + user_instance->username); + } else { + LOGNOTICE("Client %ld worker %s failed to authorise as user %s", client->id, buf, + user_instance->username); + } out: return json_boolean(ret); } @@ -3439,6 +3446,9 @@ static void update_workerstats(ckpool_t *ckp, sdata_t *sdata) worker_instance_t *worker; uint8_t cycle_mask; + if (!user->authorised) + continue; + /* Select users using a mask to return each user's stats once * every ~10 minutes */ cycle_mask = user->id & 0x1f; @@ -3540,6 +3550,9 @@ static void *statsupdate(void *arg) int iterations = 0; bool idle = false; + if (!instance->authorised) + continue; + /* Decay times per worker */ DL_FOREACH(instance->worker_instances, worker) { /* Sanity check, should never happen */ From 2980ff40329c99cc1309f86b165d93097b0dd58c Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 18 Jan 2015 21:01:34 +1100 Subject: [PATCH 36/39] Only give unparseable auth message when failed message is not recognised --- src/stratifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index 84f9a9a7..43512fdc 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -2005,7 +2005,8 @@ static int send_recv_auth(stratum_instance_t *client) LOGINFO("Got ckdb response: %s", buf); if (unlikely(sscanf(buf, "id.%*d.%s", response) < 1 || strlen(response) < 1 || !strchr(response, '='))) { - LOGWARNING("Got unparseable ckdb auth response: %s", buf); + if (!cmdmatch(response, "failed")) + LOGWARNING("Got unparseable ckdb auth response: %s", buf); goto out_fail; } cmd = response; From b1f7cd833d0090a4d916493fe083b456eedb49cf Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 18 Jan 2015 21:04:13 +1100 Subject: [PATCH 37/39] Give an outright fail response if failed msg is received from ckdb on auth --- src/stratifier.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 43512fdc..241cc981 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -2005,8 +2005,9 @@ static int send_recv_auth(stratum_instance_t *client) LOGINFO("Got ckdb response: %s", buf); if (unlikely(sscanf(buf, "id.%*d.%s", response) < 1 || strlen(response) < 1 || !strchr(response, '='))) { - if (!cmdmatch(response, "failed")) - LOGWARNING("Got unparseable ckdb auth response: %s", buf); + if (cmdmatch(response, "failed")) + goto out; + LOGWARNING("Got unparseable ckdb auth response: %s", buf); goto out_fail; } cmd = response; From 9b56c0c54620e42a356e6d104cccd12e27189c8d Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 18 Jan 2015 21:24:42 +1100 Subject: [PATCH 38/39] Fill enonce1 data properly for stratum reconnect support --- src/stratifier.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 241cc981..a3715dfb 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1621,6 +1621,16 @@ out: return ret; } +/* Enter holding workbase_lock */ +static void __fill_enonce1data(workbase_t *wb, stratum_instance_t *client) +{ + if (wb->enonce1constlen) + memcpy(client->enonce1bin, wb->enonce1constbin, wb->enonce1constlen); + memcpy(client->enonce1bin + wb->enonce1constlen, &client->enonce1_64, wb->enonce1varlen); + __bin2hex(client->enonce1var, &client->enonce1_64, wb->enonce1varlen); + __bin2hex(client->enonce1, client->enonce1bin, wb->enonce1constlen + wb->enonce1varlen); +} + /* Create a new enonce1 from the 64 bit enonce1_64 value, using only the number * of bytes we have to work with when we are proxying with a split nonce2. * When the proxy space is less than 32 bits to work with, we look for an @@ -1669,11 +1679,7 @@ static bool new_enonce1(stratum_instance_t *client) } if (ret) client->enonce1_64 = sdata->enonce1u.u64; - if (wb->enonce1constlen) - memcpy(client->enonce1bin, wb->enonce1constbin, wb->enonce1constlen); - memcpy(client->enonce1bin + wb->enonce1constlen, &client->enonce1_64, wb->enonce1varlen); - __bin2hex(client->enonce1var, &client->enonce1_64, wb->enonce1varlen); - __bin2hex(client->enonce1, client->enonce1bin, wb->enonce1constlen + wb->enonce1varlen); + __fill_enonce1data(wb, client); ck_wunlock(&sdata->workbase_lock); if (unlikely(!ret)) @@ -1722,6 +1728,10 @@ static json_t *parse_subscribe(stratum_instance_t *client, int64_t client_id, js if (disconnected_sessionid_exists(sdata, buf, client_id)) { sprintf(client->enonce1, "%016lx", client->enonce1_64); old_match = true; + + ck_rlock(&sdata->workbase_lock); + __fill_enonce1data(sdata->current_workbase, client); + ck_runlock(&sdata->workbase_lock); } } } else From 8964743cd1306be027646df1fb00206c9f6922a7 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 18 Jan 2015 22:04:18 +1100 Subject: [PATCH 39/39] Disable resume support till dereference issue in disconnected_instances resolved --- src/stratifier.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index a3715dfb..3a5f26b3 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1243,7 +1243,6 @@ static void drop_client(sdata_t *sdata, int64_t id) { stratum_instance_t *client, *tmp; user_instance_t *instance = NULL; - time_t now_t = time(NULL); ckpool_t *ckp = NULL; bool dec = false; @@ -1252,14 +1251,16 @@ static void drop_client(sdata_t *sdata, int64_t id) ck_wlock(&sdata->instance_lock); client = __instance_by_id(sdata, id); if (client) { - stratum_instance_t *old_client = NULL; - if (client->authorised) { dec = true; client->authorised = false; } HASH_DEL(sdata->stratum_instances, client); +#if 0 + /* Disable resume support till debugged properly */ + stratum_instance_t *old_client = NULL; + 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 */ if (!client->ckp->proxy && !old_client && client->enonce1_64 && dec) { @@ -1267,12 +1268,16 @@ static void drop_client(sdata_t *sdata, int64_t id) sdata->stats.disconnected++; client->disconnected_time = time(NULL); } else +#endif __kill_instance(sdata, client); ckp = client->ckp; instance = client->user_instance; LOGINFO("Stratifer dropped %sauthorised client %ld", dec ? "" : "un", id); } +#if 0 + time_t now_t = time(NULL); + /* 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 */ @@ -1282,6 +1287,7 @@ static void drop_client(sdata_t *sdata, int64_t id) LOGINFO("Discarding aged disconnected instance %ld", client->id); __del_disconnected(sdata, client); } +#endif /* Cull old unused clients lazily when there are no more reference * counts for them. */