diff --git a/src/ckdb.h b/src/ckdb.h index a61cccf0..0d4b6cec 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.0" -#define CKDB_VERSION DB_VERSION"-1.045" +#define CKDB_VERSION DB_VERSION"-1.046" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -1282,6 +1282,12 @@ extern cklock_t process_pplns_lock; #define PAYOUTS_ORPHAN_STR "O" #define PAYORPHAN(_status) ((_status)[0] == PAYOUTS_ORPHAN) +// Default number of shifts (payouts) to display on web +#define SHIFTS_DEFAULT 99 +/* OptionControl can override it + * UserAtts can also at the user level */ +#define SHIFTS_SETTING_NAME "ShiftsPageSize" + /* // EVENTLOG typedef struct eventlog { @@ -1806,6 +1812,8 @@ extern cmp_t cmp_accountbalance(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_accountbalance(int64_t userid); extern cmp_t cmp_optioncontrol(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height); +extern int64_t user_sys_setting(int64_t userid, char *setting_name, + int64_t setting_default, tv_t *now); extern cmp_t cmp_workinfo(K_ITEM *a, K_ITEM *b); #define coinbase1height(_cb1) _coinbase1height(_cb1, WHERE_FFL_HERE) extern int32_t _coinbase1height(char *coinbase1, WHERE_FFL_ARGS); @@ -1856,6 +1864,7 @@ extern cmp_t cmp_payouts_id(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_payouts(int32_t height, char *blockhash); extern K_ITEM *find_last_payouts(); extern K_ITEM *find_payoutid(int64_t payoutid); +extern double payout_stats(PAYOUTS *payouts, char *statname); extern bool process_pplns(int32_t height, char *blockhash, tv_t *now); extern cmp_t cmp_auths(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_poolstats(K_ITEM *a, K_ITEM *b); diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 1da701e3..93bd8b83 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -4762,17 +4762,17 @@ static char **select_list(char *select, int *all_count) } static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, - __maybe_unused tv_t *now, __maybe_unused char *by, + tv_t *now, __maybe_unused char *by, __maybe_unused char *code, __maybe_unused char *inet, - __maybe_unused tv_t *notcd, - __maybe_unused K_TREE *trf_root) + __maybe_unused tv_t *notcd, K_TREE *trf_root) { K_ITEM *i_username, *i_select; - K_ITEM *u_item, *m_item, ms_look, *wm_item, *ms_item, *wi_item; + K_ITEM *u_item, *p_item, *m_item, ms_look, *wm_item, *ms_item, *wi_item; K_TREE_CTX wm_ctx[1], ms_ctx[1]; WORKMARKERS *wm; WORKINFO *wi; MARKERSUMMARY markersummary, *ms, ms_add; + PAYOUTS *payouts; USERS *users; MARKS *marks = NULL; char reply[1024] = ""; @@ -4785,6 +4785,8 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, size_t len, off; tv_t marker_end = { 0L, 0L }; int rows, want, i, where_all; + int64_t maxrows; + double wm_count; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -4799,6 +4801,20 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, return strdup("bad"); DATA_USERS(users, u_item); + maxrows = user_sys_setting(users->userid, SHIFTS_SETTING_NAME, + SHIFTS_DEFAULT, now); + + K_RLOCK(payouts_free); + p_item = find_last_payouts(); + K_RUNLOCK(payouts_free); + if (p_item) { + DATA_PAYOUTS(payouts, p_item); + wm_count = payout_stats(payouts, "wm_count"); + wm_count *= 1.42; + if (maxrows < wm_count) + maxrows = wm_count; + } + i_select = optional_name(trf_root, "select", 1, NULL, reply, siz); if (i_select) select = strdup(transfer_data(i_select)); @@ -4824,7 +4840,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, DATA_WORKMARKERS_NULL(wm, wm_item); /* TODO: allow to see details of a single payoutid * if it has multiple items (percent payout user) */ - while (rows < 98 && wm_item) { + while (rows < (maxrows - 1) && wm_item) { if (CURRENT(&(wm->expirydate)) && WMPROCESSED(wm->status)) { K_RUNLOCK(workmarkers_free); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 4bf9355d..a64ea4e7 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -1516,6 +1516,43 @@ K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height) return best; } +/* + * Get a setting value for the given setting name + * First check if there is a USERATTS attnum value != 0 + * If not, check if there is an OPTIONCONTROL record (can be any value) + * If not, return the default + * WARNING OPTIONCONTROL is time dependent, + * i.e. ensure now and pool.height are correct (e.g. during a reload) + */ +int64_t user_sys_setting(int64_t userid, char *setting_name, + int64_t setting_default, tv_t *now) +{ + OPTIONCONTROL *optioncontrol; + K_ITEM *ua_item, *oc_item; + USERATTS *useratts; + + if (userid != 0) { + K_RLOCK(useratts_free); + ua_item = find_useratts(userid, setting_name); + K_RUNLOCK(useratts_free); + if (ua_item) { + DATA_USERATTS(useratts, ua_item); + if (useratts->attnum != 0) + return useratts->attnum; + } + } + + K_RLOCK(optioncontrol_free); + oc_item = find_optioncontrol(setting_name, now, pool.height); + K_RUNLOCK(optioncontrol_free); + if (oc_item) { + DATA_OPTIONCONTROL(optioncontrol, oc_item); + return (int64_t)atol(optioncontrol->optionvalue); + } + + return setting_default; +} + // order by workinfoid asc,expirydate asc cmp_t cmp_workinfo(K_ITEM *a, K_ITEM *b) { @@ -2721,7 +2758,7 @@ K_ITEM *find_last_payouts() return p_item; p_item = prev_in_ktree(ctx); } - return p_item; + return NULL; } K_ITEM *find_payoutid(int64_t payoutid) @@ -2739,6 +2776,43 @@ K_ITEM *find_payoutid(int64_t payoutid) return find_in_ktree(payouts_id_root, &look, cmp_payouts_id, ctx); } +/* Values from payout stats, returns -1 if statname isn't found + * If code needs a value then it probably really should be a new payouts field + * rather than stored in the stats passed to the pplns2 web page + * but anyway ... */ +double payout_stats(PAYOUTS *payouts, char *statname) +{ + char buf[1024]; // If a number is bigger than this ... bad luck + double ret = -1.0; + size_t numlen, len = strlen(statname); + char *pos, *tab; + + pos = payouts->stats; + while (pos && *pos) { + if (strncmp(pos, statname, len) == 0 && pos[len] == '=') { + pos += len+1; + // They should only contain +ve numbers + if (*pos && isdigit(*pos)) { + tab = strchr(pos, '\t'); + if (!tab) + numlen = strlen(pos); + else + numlen = tab - pos; + if (numlen >= sizeof(buf)) + numlen = sizeof(buf) - 1; + STRNCPYSIZ(buf, pos, numlen); + // ctv will only return the seconds + ret = atof(buf); + } + break; + } + pos = strchr(pos, '\t'); + if (pos) + pos++; + } + return ret; +} + /* Find the block_workinfoid of the block requested then add all it's diffacc shares then keep stepping back shares until diffacc_total matches or exceeds