diff --git a/pool/page_pplns.php b/pool/page_pplns.php index dccd04f6..0d498110 100644 --- a/pool/page_pplns.php +++ b/pool/page_pplns.php @@ -157,6 +157,9 @@ Block: if ($ans['ERROR'] != null) return '
'.$ans['STATUS'].': '.$ans['ERROR'].'
'; + if (!isset($ans['pplns_last'])) + return '
Partial data returned
'; + $reward_sat = $ans['block_reward']; $miner_sat = round($reward_sat * 0.991); $ans['miner_sat'] = $miner_sat; @@ -191,6 +194,13 @@ Block: $pg = '
Blockchain '.$ans['block']."
\n"; + if (strlen($ans['marks_status']) > 0) + { + $pg .= '
'; + $msg = $ans['marks_status']; + $pg .= str_replace(' ', ' ', $msg)."
\n"; + } + if (strlen($ans['block_extra']) > 0) { $pg .= '
'; diff --git a/src/ckdb.c b/src/ckdb.c index 5fc66caf..1682b429 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -154,6 +154,7 @@ static bool socketer_using_data; static bool summariser_using_data; +static bool marker_using_data; static bool logger_using_data; static bool listener_using_data; @@ -275,6 +276,11 @@ int64_t dbload_workinfoid_finish = MAXID; // Only restrict sharesummary, not workinfo bool dbload_only_sharesummary = false; +/* If the above restriction - on sharesummaries - is after the last marks + * then this means the sharesummaries can't be summarised into + * markersummaries and pplns payouts may not be correct */ +bool sharesummary_marks_limit = false; + // DB users,workers,auth load is complete bool db_auths_complete = false; // DB load is complete @@ -753,6 +759,8 @@ static bool getdata3() } if (!(ok = workinfo_fill(conn)) || everyone_die) goto sukamudai; + /* marks must be loaded before sharesummary + * since sharesummary looks at the marks data */ if (!(ok = marks_fill(conn)) || everyone_die) goto sukamudai; if (!(ok = workmarkers_fill(conn)) || everyone_die) @@ -1621,7 +1629,7 @@ static void summarise_blocks() } else { DATA_BLOCKS(prev_blocks, b_prev); wi_start = prev_blocks->workinfoid; - wi_item = find_workinfo(wi_start); + wi_item = find_workinfo(wi_start, NULL); if (!wi_item) { // This will repeat until fixed ... LOGERR("%s() block %d, but prev %d wid " @@ -2024,6 +2032,86 @@ static void *summariser(__maybe_unused void *arg) return NULL; } +// Number of workinfoids per shift +#define WID_PER_SHIFT 100 + +#if 0 +static void make_shift_marks() +{ + K_TREE_CTX ctx[1]; + K_ITEM *m_item, *wi_item;; + WORKINFO *workinfo; + MARKS *marks; + int wid_count; + int64_t wid; + + K_RLOCK(marks_free); + m_item = last_in_ktree(marks_root, ctx); + if (m_item) { + DATA_MARKS(marks, m_item); + wi_item = find_workinfo(marks->workinfoid, ctx); + if (!wi_item) { + LOGEMERG("%s() last mark %"PRId64"/%s/%s/%s/%s" + " workinfoid is missing!", + __func__, marks->workinfoid, + marks_marktype(marks->marktype), + marks->status, marks->description, + marks->extra); + } + } + K_RUNLOCK(marks_free); +} +#endif + +static void *marker(__maybe_unused void *arg) +{ + int i; + + pthread_detach(pthread_self()); + + rename_proc("db_marker"); + + while (!everyone_die && !startup_complete) + cksleep_ms(42); + + marker_using_data = true; + + while (!everyone_die) { + for (i = 0; i < 5; i++) { + if (!everyone_die) + sleep(1); + } +#if 0 + if (everyone_die) + break; + else + make_shift_marks(); + + for (i = 0; i < 4; i++) { + if (!everyone_die) + sleep(1); + } + if (everyone_die) + break; + else + make_a_workmarker(); + + for (i = 0; i < 4; i++) { + if (!everyone_die) + sleep(1); + } + if (everyone_die) + break; + else + make_markersummaries(); +#endif + } + + marker_using_data = false; + + return NULL; +} + static void *logger(__maybe_unused void *arg) { K_ITEM *lq_item; @@ -2924,6 +3012,7 @@ static void *listener(void *arg) pthread_t log_pt; pthread_t sock_pt; pthread_t summ_pt; + pthread_t mark_pt; K_ITEM *wq_item; time_t now; int wqcount, wqgot; @@ -2938,6 +3027,8 @@ static void *listener(void *arg) create_pthread(&summ_pt, summariser, NULL); + create_pthread(&mark_pt, marker, NULL); + rename_proc("db_listener"); listener_using_data = true; @@ -3827,7 +3918,8 @@ int main(int argc, char **argv) trigger = start = time(NULL); while (socketer_using_data || summariser_using_data || - logger_using_data || listener_using_data) { + logger_using_data || listener_using_data || + marker_using_data) { msg = NULL; curr = time(NULL); if (curr - start > 4) { @@ -3839,12 +3931,13 @@ int main(int argc, char **argv) } if (msg) { trigger = curr; - printf("%s %ds due to%s%s%s%s\n", + printf("%s %ds due to%s%s%s%s%s\n", msg, (int)(curr - start), socketer_using_data ? " socketer" : EMPTY, summariser_using_data ? " summariser" : EMPTY, logger_using_data ? " logger" : EMPTY, - listener_using_data ? " listener" : EMPTY); + listener_using_data ? " listener" : EMPTY, + marker_using_data ? " marker" : EMPTY); fflush(stdout); } sleep(1); diff --git a/src/ckdb.h b/src/ckdb.h index 3d6bb698..e78bbad3 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.782" +#define CKDB_VERSION DB_VERSION"-0.800" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -250,6 +250,11 @@ extern int64_t dbload_workinfoid_finish; // Only restrict sharesummary, not workinfo extern bool dbload_only_sharesummary; +/* If the above restriction - on sharesummaries - is after the last marks + * then this means the sharesummaries can't be summarised into + * markersummaries and pplns payouts may not be correct */ +extern bool sharesummary_marks_limit; + // DB users,workers,auth load is complete extern bool db_auths_complete; // DB load is complete @@ -1574,7 +1579,7 @@ extern int32_t _coinbase1height(char *coinbase1, WHERE_FFL_ARGS); #define cmp_height(_cb1a, _cb1b) _cmp_height(_cb1a, _cb1b, WHERE_FFL_HERE) extern cmp_t _cmp_height(char *coinbase1a, char *coinbase1b, WHERE_FFL_ARGS); extern cmp_t cmp_workinfo_height(K_ITEM *a, K_ITEM *b); -extern K_ITEM *find_workinfo(int64_t workinfoid); +extern K_ITEM *find_workinfo(int64_t workinfoid, K_TREE_CTX *ctx); extern bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance, char *by, char *code, char *inet, tv_t *cd, tv_t *ss_first, tv_t *ss_last, int64_t *ss_count, diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index ecd43471..81546702 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -887,7 +887,7 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, snprintf(tmp, sizeof(tmp), "elapsed:%d=%s%c", rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - w_item = find_workinfo(blocks->workinfoid); + w_item = find_workinfo(blocks->workinfoid, NULL); if (w_item) { char wdiffbin[TXT_SML+1]; double wdiff; @@ -3440,7 +3440,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, __maybe_unused char *code, __maybe_unused char *inet, __maybe_unused tv_t *notcd, K_TREE *trf_root) { - char reply[1024], tmp[1024], *buf, *block_extra, *share_status = EMPTY; + char reply[1024], tmp[1024], *buf; + char *block_extra, *share_status = EMPTY, *marks_status = EMPTY; size_t siz = sizeof(reply); K_ITEM *i_height, *i_difftimes, *i_diffadd, *i_allowaged; K_ITEM b_look, ss_look, *b_item, *w_item, *ss_item; @@ -3475,6 +3476,9 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, LOGDEBUG("%s(): cmd '%s'", __func__, cmd); + if (sharesummary_marks_limit) + marks_status = "ckdb -w load value means pplns may be incorrect"; + i_height = require_name(trf_root, "height", 1, NULL, reply, siz); if (!i_height) return strdup(reply); @@ -3543,7 +3547,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, break; } block_workinfoid = blocks->workinfoid; - w_item = find_workinfo(block_workinfoid); + w_item = find_workinfo(block_workinfoid, NULL); if (!w_item) { snprintf(reply, siz, "ERR.missing workinfo %"PRId64, block_workinfoid); return strdup(reply); @@ -3705,7 +3709,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, goto shazbot; } - wb_item = find_workinfo(begin_workinfoid); + wb_item = find_workinfo(begin_workinfoid, NULL); if (!wb_item) { snprintf(reply, siz, "ERR.missing begin workinfo record! %"PRId64, block_workinfoid); goto shazbot; @@ -3737,6 +3741,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "share_status=%s%c", share_status, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "marks_status=%s%c", marks_status, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "workername=%s%c", blocks->workername, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "nonce=%s%c", blocks->nonce, FLDSEP); @@ -3870,8 +3876,10 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "wm_count=%"PRId64"%c", wm_count, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - snprintf(tmp, sizeof(tmp), "ms_count=%"PRId64, ms_count); + snprintf(tmp, sizeof(tmp), "ms_count=%"PRId64"%c", ms_count, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + // So web can always verify it received all data + APPEND_REALLOC(buf, off, len, "pplns_last=1"); mu_root = free_ktree(mu_root, NULL); K_WLOCK(mu_store); @@ -4213,7 +4221,7 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, snprintf(reply, siz, "workinfoid not found"); return strdup(reply); } - w_item = find_workinfo(workinfoid); + w_item = find_workinfo(workinfoid, NULL); if (!w_item) { snprintf(reply, siz, "invalid workinfoid %"PRId64, workinfoid); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 5730261b..977547de 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -1337,12 +1337,15 @@ cmp_t cmp_workinfo_height(K_ITEM *a, K_ITEM *b) return c; } -K_ITEM *find_workinfo(int64_t workinfoid) +K_ITEM *find_workinfo(int64_t workinfoid, K_TREE_CTX *ctx) { WORKINFO workinfo; - K_TREE_CTX ctx[1]; + K_TREE_CTX ctx0[1]; K_ITEM look, *item; + if (ctx == NULL) + ctx = ctx0; + workinfo.workinfoid = workinfoid; workinfo.expirydate.tv_sec = default_expiry.tv_sec; workinfo.expirydate.tv_usec = default_expiry.tv_usec; @@ -1377,7 +1380,7 @@ bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance, ss_last->tv_sec = ss_last->tv_usec = 0; *ss_count = *s_count = *s_diff = 0; - wi_item = find_workinfo(workinfoid); + wi_item = find_workinfo(workinfoid, NULL); if (!wi_item) { tv_to_buf(cd, cd_buf, sizeof(cd_buf)); LOGERR("%s() %"PRId64"/%s/%ld,%ld %.19s no workinfo! Age discarded!", diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 64aa9437..3db22f3e 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -2346,7 +2346,8 @@ bool workinfo_fill(PGconn *conn) char *params[3]; int n, i, par = 0; char *field; - char *sel; + char *sel = NULL; + size_t len, off; int fields = 10; bool ok; @@ -2355,14 +2356,31 @@ bool workinfo_fill(PGconn *conn) // TODO: select the data based on sharesummary since old data isn't needed // however, the ageing rules for workinfo will decide that also // keep the last block + current? Rules will depend on payout scheme also - sel = "select " -// "workinfoid,poolinstance,transactiontree,merklehash,prevhash," - "workinfoid,poolinstance,merklehash,prevhash," - "coinbase1,coinbase2,version,bits,ntime,reward" - HISTORYDATECONTROL - " from workinfo where expirydate=$1 and" - " ((workinfoid>=$2 and workinfoid<=$3) or" - " workinfoid in (select workinfoid from blocks) )"; + + APPEND_REALLOC_INIT(sel, off, len); + APPEND_REALLOC(sel, off, len, + "select " +// "workinfoid,poolinstance,transactiontree,merklehash,prevhash," + "workinfoid,poolinstance,merklehash,prevhash," + "coinbase1,coinbase2,version,bits,ntime,reward" + HISTORYDATECONTROL + " from workinfo where expirydate=$1 and" + " ((workinfoid>=$2 and workinfoid<=$3)"); + + // If we aren't loading the full range, ensure the necessary ones are loaded + if ((!dbload_only_sharesummary && dbload_workinfoid_start != -1) || + dbload_workinfoid_finish != MAXID) { + APPEND_REALLOC(sel, off, len, + // we need all blocks workinfoids + " or workinfoid in (select workinfoid from blocks)" + // we need all marks workinfoids + " or workinfoid in (select workinfoid from marks)" + // we need all workmarkers workinfoids (start and end) + " or workinfoid in (select workinfoidstart from workmarkers)" + " or workinfoid in (select workinfoidend from workmarkers)"); + } + APPEND_REALLOC(sel, off, len, ")"); + par = 0; params[par++] = tv_to_buf((tv_t *)(&default_expiry), NULL, 0); if (dbload_only_sharesummary) @@ -2550,7 +2568,7 @@ bool shares_add(PGconn *conn, char *workinfoid, char *username, char *workername HISTORYDATEINIT(shares, cd, by, code, inet); HISTORYDATETRANSFER(trf_root, shares); - wi_item = find_workinfo(shares->workinfoid); + wi_item = find_workinfo(shares->workinfoid, NULL); if (!wi_item) { tv_to_buf(cd, cd_buf, sizeof(cd_buf)); // TODO: store it for a few workinfoid changes @@ -2671,7 +2689,7 @@ bool shareerrors_add(PGconn *conn, char *workinfoid, char *username, HISTORYDATEINIT(shareerrors, cd, by, code, inet); HISTORYDATETRANSFER(trf_root, shareerrors); - wi_item = find_workinfo(shareerrors->workinfoid); + wi_item = find_workinfo(shareerrors->workinfoid, NULL); if (!wi_item) { tv_to_buf(cd, cd_buf, sizeof(cd_buf)); LOGERR("%s() %"PRId64"/%s/%ld,%ld %.19s no workinfo! Shareerror discarded!", @@ -3066,9 +3084,11 @@ bool sharesummary_fill(PGconn *conn) { ExecStatusType rescode; PGresult *res; - K_ITEM *item; + K_TREE_CTX ctx[1]; + K_ITEM *item, *m_item; int n, i, par = 0; SHARESUMMARY *row; + MARKS *marks; char *params[2]; char *field; char *sel; @@ -3077,6 +3097,32 @@ bool sharesummary_fill(PGconn *conn) LOGDEBUG("%s(): select", __func__); + /* Load needs to go back to the last marks workinfoid(+1) + * If it is later than that, we can't create markersummaries + * since some of the required data is missing - + * thus we also can't make the shift markersummaries */ + m_item = last_in_ktree(marks_root, ctx); + if (!m_item) { + if (dbload_workinfoid_start != -1) { + sharesummary_marks_limit = true; + LOGWARNING("WARNING: dbload -w start used " + "but there are no marks ..."); + } + } else { + DATA_MARKS(marks, m_item); + if (dbload_workinfoid_start > marks->workinfoid) { + sharesummary_marks_limit = true; + LOGWARNING("WARNING: dbload -w start %"PRId64 + " is after the last mark %"PRId64" ...", + dbload_workinfoid_start, + marks->workinfoid); + } + } + if (sharesummary_marks_limit) { + LOGWARNING("WARNING: ... markersummaries cannot be created " + "and pplns calculations may be wrong"); + } + // TODO: limit how far back sel = "select " "userid,workername,workinfoid,diffacc,diffsta,diffdup,diffhi," @@ -3733,7 +3779,7 @@ flail: break; case BLOCKS_CONFIRM: blk = true; - w_item = find_workinfo(row->workinfoid); + w_item = find_workinfo(row->workinfoid, NULL); if (w_item) { char wdiffbin[TXT_SML+1]; double wdiff; @@ -5302,10 +5348,10 @@ bool _workmarkers_process(PGconn *conn, bool add, int64_t markerid, WHERE_FFL_PASS); goto rollback; } - w_item = find_workinfo(workinfoidend); + w_item = find_workinfo(workinfoidend, NULL); if (!w_item) goto rollback; - w_item = find_workinfo(workinfoidstart); + w_item = find_workinfo(workinfoidstart, NULL); if (!w_item) goto rollback; K_WLOCK(workmarkers_free); @@ -5614,7 +5660,7 @@ bool _marks_process(PGconn *conn, bool add, char *poolinstance, WHERE_FFL_PASS); goto rollback; } - w_item = find_workinfo(workinfoid); + w_item = find_workinfo(workinfoid, NULL); if (!w_item) goto rollback; K_WLOCK(marks_free);