Browse Source

ckdb/php - add per worker and per block stats

master
kanoi 10 years ago
parent
commit
49a85a6856
  1. 82
      pool/page_blocks.php
  2. 24
      pool/page_workers.php
  3. 15
      sql/ckdb.sql
  4. 46
      sql/v0.8-v0.9.sql
  5. 474
      src/ckdb.c

82
pool/page_blocks.php

@ -1,5 +1,43 @@
<?php <?php
# #
function pctcolour($pct)
{
if ($pct == 100)
{
$fg = '#fff';
$bg = '#000';
}
if ($pct < 100)
{
$grn = (2.0 - log10($pct)) * 255;
if ($grn < 0)
$grn = 0;
if ($grn > 255)
$grn = 255;
if ($grn > 100)
$fg = '#00f';
else
$fg = '#fff';
$bg = sprintf("#00%02x00", $grn);
}
if ($pct > 100)
{
$red = (log10(pow($pct,4.0)) - 8.0) / 3.0 * 255;
if ($red < 0)
$red = 0;
if ($red > 255)
$red = 255;
$fg = '#fff';
$bg = sprintf("#%02x0000", $red);
}
return array($fg, $bg);
}
#
function doblocks($data, $user) function doblocks($data, $user)
{ {
$blink = '<a href=https://blockchain.info/block-height/'; $blink = '<a href=https://blockchain.info/block-height/';
@ -15,7 +53,12 @@ function doblocks($data, $user)
$pg .= "<td class=dr>Reward</td>"; $pg .= "<td class=dr>Reward</td>";
$pg .= "<td class=dc>When</td>"; $pg .= "<td class=dc>When</td>";
$pg .= "<td class=dr>Status</td>"; $pg .= "<td class=dr>Status</td>";
$pg .= "<td class=dr>Diff</td>";
$pg .= "<td class=dr>%</td>";
$pg .= "</tr>\n"; $pg .= "</tr>\n";
$blktot = 0;
$nettot = 0;
$i = 0;
if ($ans['STATUS'] == 'ok') if ($ans['STATUS'] == 'ok')
{ {
$count = $ans['rows']; $count = $ans['rows'];
@ -36,15 +79,54 @@ function doblocks($data, $user)
$hi = $ans['height:'.$i]; $hi = $ans['height:'.$i];
$hifld = "$blink$hi>$hi</a>"; $hifld = "$blink$hi>$hi</a>";
$diffacc = $ans['diffacc:'.$i];
$acc = number_format($diffacc, 0);
$netdiff = $ans['netdiff:'.$i];
if ($netdiff > 0)
{
$pct = 100.0 * $diffacc / $netdiff;
list($fg, $bg) = pctcolour($pct);
$bpct = "<font color=$fg>".number_format($pct, 2).'%</font>';
$bg = " bgcolor=$bg";
$nettot += $netdiff;
if ($stat != 'Orphan')
$blktot += $diffacc;
}
else
{
$bg = '';
$bpct = '?';
}
$pg .= "<tr class=$row>"; $pg .= "<tr class=$row>";
$pg .= "<td class=dl$ex>$hifld</td>"; $pg .= "<td class=dl$ex>$hifld</td>";
$pg .= "<td class=dl$ex>".$ans['workername:'.$i].'</td>'; $pg .= "<td class=dl$ex>".$ans['workername:'.$i].'</td>';
$pg .= "<td class=dr$ex>".btcfmt($ans['reward:'.$i]).'</td>'; $pg .= "<td class=dr$ex>".btcfmt($ans['reward:'.$i]).'</td>';
$pg .= "<td class=dl$ex>".gmdate('Y-m-d H:i:s+00', $ans['firstcreatedate:'.$i]).'</td>'; $pg .= "<td class=dl$ex>".gmdate('Y-m-d H:i:s+00', $ans['firstcreatedate:'.$i]).'</td>';
$pg .= "<td class=dr$ex>".$stat.'</td>'; $pg .= "<td class=dr$ex>".$stat.'</td>';
$pg .= "<td class=dr$ex>".$acc.'</td>';
$pg .= "<td class=dr$ex$bg>".$bpct.'</td>';
$pg .= "</tr>\n"; $pg .= "</tr>\n";
} }
} }
if ($nettot > 0)
{
if (($i % 2) == 0)
$row = 'even';
else
$row = 'odd';
$pct = 100.0 * $blktot / $nettot;
list($fg, $bg) = pctcolour($pct);
$bpct = "<font color=$fg>".number_format($pct, 2).'%</font>';
$bg = " bgcolor=$bg";
$pg .= "<tr class=$row>";
$pg .= "<td class=dl colspan=6></td>";
$pg .= "<td class=dr$bg>".$bpct.'</td>';
$pg .= "</tr>\n";
}
$pg .= "</table>\n"; $pg .= "</table>\n";
return $pg; return $pg;

24
pool/page_workers.php

@ -14,11 +14,15 @@ function doworker($data, $user)
// $pg .= "<td class=dr>Idle Notification Time</td>"; // $pg .= "<td class=dr>Idle Notification Time</td>";
$pg .= "<td class=dr>Work Diff</td>"; $pg .= "<td class=dr>Work Diff</td>";
$pg .= "<td class=dr>Last Share</td>"; $pg .= "<td class=dr>Last Share</td>";
$pg .= "<td class=dr>Shares</td>";
$pg .= "<td class=dr>Diff</td>";
$pg .= "<td class=dr>Invalid</td>";
$pg .= "<td class=dr>Hash Rate</td>"; $pg .= "<td class=dr>Hash Rate</td>";
$pg .= "</tr>\n"; $pg .= "</tr>\n";
$thr = 0;
$i = 0;
if ($ans['STATUS'] == 'ok') if ($ans['STATUS'] == 'ok')
{ {
$thr = 0;
$count = $ans['rows']; $count = $ans['rows'];
for ($i = 0; $i < $count; $i++) for ($i = 0; $i < $count; $i++)
{ {
@ -81,6 +85,20 @@ function doworker($data, $user)
} }
} }
$pg .= "<td class=dr>$lstdes</td>"; $pg .= "<td class=dr>$lstdes</td>";
$shareacc = number_format($ans['w_shareacc:'.$i], 0);
$diffacc = number_format($ans['w_diffacc:'.$i], 0);
$pg .= "<td class=dr>$shareacc</td>";
$pg .= "<td class=dr>$diffacc</td>";
$dtot = $ans['w_diffacc:'.$i] + $ans['w_diffinv:'.$i];
if ($dtot > 0)
$rej = number_format(100.0 * $ans['w_diffinv:'.$i] / $dtot, 3);
else
$rej = '0';
$pg .= "<td class=dr>$rej%</td>";
if ($ans['w_elapsed:'.$i] > 3600) if ($ans['w_elapsed:'.$i] > 3600)
$uhr = $ans['w_hashrate1hr:'.$i]; $uhr = $ans['w_hashrate1hr:'.$i];
else else
@ -102,6 +120,7 @@ function doworker($data, $user)
} }
} }
$pg .= "<td class=dr>$uhr</td>"; $pg .= "<td class=dr>$uhr</td>";
$pg .= "</tr>\n"; $pg .= "</tr>\n";
} }
} }
@ -119,7 +138,8 @@ function doworker($data, $user)
$row = 'even'; $row = 'even';
else else
$row = 'odd'; $row = 'odd';
$pg .= "<tr class=$row><td colspan=3 class=dl></td><td class=dr>$thr</td></tr>\n"; $pg .= "<tr class=$row><td colspan=6 class=dl></td>";
$pg .= "<td class=dr>$thr</td></tr>\n";
$pg .= "</table>\n"; $pg .= "</table>\n";
return $pg; return $pg;

15
sql/ckdb.sql

@ -240,9 +240,8 @@ CREATE TABLE workmarkers ( -- range of workinfo for share accounting
createcode character varying(128) DEFAULT ''::character varying NOT NULL, createcode character varying(128) DEFAULT ''::character varying NOT NULL,
createinet character varying(128) DEFAULT ''::character varying NOT NULL, createinet character varying(128) DEFAULT ''::character varying NOT NULL,
expirydate timestamp with time zone DEFAULT '6666-06-06 06:06:06+00', expirydate timestamp with time zone DEFAULT '6666-06-06 06:06:06+00',
PRIMARY KEY (workinfoidstart) PRIMARY KEY (markerid)
); );
CREATE UNIQUE INDEX workmarkersid ON workmarkers USING btree (markerid);
CREATE TABLE markersummary ( -- sum of sharesummary for a workinfo range CREATE TABLE markersummary ( -- sum of sharesummary for a workinfo range
@ -276,8 +275,6 @@ CREATE TABLE markersummary ( -- sum of sharesummary for a workinfo range
); );
-- shares will be a flat file only
-- so this needs all info from shares
CREATE TABLE blocks ( CREATE TABLE blocks (
height integer not NULL, height integer not NULL,
blockhash character varying(256) NOT NULL, blockhash character varying(256) NOT NULL,
@ -291,10 +288,11 @@ CREATE TABLE blocks (
reward bigint NOT NULL, -- satoshis reward bigint NOT NULL, -- satoshis
confirmed char DEFAULT '' NOT NULL, confirmed char DEFAULT '' NOT NULL,
diffacc float DEFAULT 0 NOT NULL, diffacc float DEFAULT 0 NOT NULL,
differr float DEFAULT 0 NOT NULL, diffinv float DEFAULT 0 NOT NULL,
sharecount bigint DEFAULT 0 NOT NULL, shareacc float DEFAULT 0 NOT NULL,
errorcount bigint DEFAULT 0 NOT NULL, shareinv float DEFAULT 0 NOT NULL,
elapsed bigint DEFAULT 0 NOT NULL, elapsed bigint DEFAULT 0 NOT NULL,
statsconfirmed char DEFAULT 'N' NOT NULL,
createdate timestamp with time zone NOT NULL, createdate timestamp with time zone NOT NULL,
createby character varying(64) DEFAULT ''::character varying NOT NULL, createby character varying(64) DEFAULT ''::character varying NOT NULL,
createcode character varying(128) DEFAULT ''::character varying NOT NULL, createcode character varying(128) DEFAULT ''::character varying NOT NULL,
@ -306,7 +304,6 @@ CREATE TABLE blocks (
-- calculation for the given block - orphans will be here also (not deleted later) -- calculation for the given block - orphans will be here also (not deleted later)
-- rules for orphans/next block will be pool dependent -- rules for orphans/next block will be pool dependent
-- normally pay due would be related to sum of one height + for all blockhash
CREATE TABLE miningpayouts ( CREATE TABLE miningpayouts (
miningpayoutid bigint NOT NULL, -- unique per record miningpayoutid bigint NOT NULL, -- unique per record
userid bigint NOT NULL, userid bigint NOT NULL,
@ -397,4 +394,4 @@ CREATE TABLE version (
PRIMARY KEY (vlock) PRIMARY KEY (vlock)
); );
insert into version (vlock,version) values (1,'0.8'); insert into version (vlock,version) values (1,'0.9');

46
sql/v0.8-v0.9.sql

@ -0,0 +1,46 @@
SET SESSION AUTHORIZATION 'postgres';
BEGIN transaction;
DO $$
DECLARE ver TEXT;
BEGIN
UPDATE version set version='0.9' where vlock=1 and version='0.8';
IF found THEN
RETURN;
END IF;
SELECT version into ver from version
WHERE vlock=1;
RAISE EXCEPTION 'Wrong DB version - expect "0.8" - found "%"', ver;
END $$;
DROP TABLE IF EXISTS workmarkers;
CREATE TABLE workmarkers (
markerid bigint NOT NULL,
workinfoidend bigint NOT NULL,
workinfoidstart bigint NOT NULL,
description character varying(256) DEFAULT ''::character varying NOT NULL,
createdate timestamp with time zone NOT NULL,
createby character varying(64) DEFAULT ''::character varying NOT NULL,
createcode character varying(128) DEFAULT ''::character varying NOT NULL,
createinet character varying(128) DEFAULT ''::character varying NOT NULL,
expirydate timestamp with time zone DEFAULT '6666-06-06 06:06:06+00',
PRIMARY KEY (markerid)
);
ALTER TABLE ONLY blocks
DROP COLUMN differr,
DROP COLUMN sharecount,
DROP COLUMN errorcount,
ADD COLUMN diffinv float DEFAULT 0 NOT NULL,
ADD COLUMN shareacc float DEFAULT 0 NOT NULL,
ADD COLUMN shareinv float DEFAULT 0 NOT NULL,
ADD COLUMN statsconfirmed char DEFAULT 'N' NOT NULL;
END transaction;

474
src/ckdb.c

@ -46,8 +46,8 @@
*/ */
#define DB_VLOCK "1" #define DB_VLOCK "1"
#define DB_VERSION "0.8" #define DB_VERSION "0.9"
#define CKDB_VERSION DB_VERSION"-0.240" #define CKDB_VERSION DB_VERSION"-0.250"
#define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ #define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -170,11 +170,9 @@ static char *restorefrom;
* DB+RAM blocks: resolved by workinfo - any unsaved blocks (if any) * DB+RAM blocks: resolved by workinfo - any unsaved blocks (if any)
* will be after the last DB workinfo * will be after the last DB workinfo
* DB+RAM accountbalance (TODO): resolved by shares/workinfo/blocks * DB+RAM accountbalance (TODO): resolved by shares/workinfo/blocks
* RAM workerstatus: last_auth, last_share, last_stats all handled by * RAM workerstatus: all except last_idle are set at the end of the
* DB load up to whatever the CCL reload point is, and then * CCL reload
* corrected with the CCL reload * Code currently doesn't use last_idle
* last_idle will be the last idle userstats in the CCL load or 0
* Code currently doesn't use last_idle, so for now this is OK
* *
* idcontrol: only userid reuse is critical and the user is added * idcontrol: only userid reuse is critical and the user is added
* immeditately to the DB before replying to the add message * immeditately to the DB before replying to the add message
@ -234,13 +232,15 @@ static LOADSTATUS dbstatus;
typedef struct poolstatus { typedef struct poolstatus {
int64_t workinfoid; // Last block int64_t workinfoid; // Last block
double diffacc; double diffacc;
double diffinv; double diffinv; // Non-acc
double best_sdiff; // TODO double shareacc;
double shareinv; // Non-acc
double best_sdiff; // TODO (maybe)
} POOLSTATUS; } POOLSTATUS;
static POOLSTATUS pool; static POOLSTATUS pool;
/* TODO: when we know about orphans, the count reset to zero /* TODO: when we know about orphans, the count reset to zero
* will need to be undone - i.e. recalculate this data from * will need to be undone - i.e. recalculate this data from
* the memory tables */ * the memory tables - maybe ... */
// size limit on the command string // size limit on the command string
#define CMD_SIZ 31 #define CMD_SIZ 31
@ -282,7 +282,7 @@ static char *safe_text(char *txt)
char *ret, *buf; char *ret, *buf;
if (!txt) { if (!txt) {
buf = strdup("(null)"); buf = strdup("(Null)");
if (!buf) if (!buf)
quithere(1, "malloc OOM"); quithere(1, "malloc OOM");
return buf; return buf;
@ -1274,6 +1274,12 @@ typedef struct blocks {
char nonce[TXT_SML+1]; char nonce[TXT_SML+1];
int64_t reward; int64_t reward;
char confirmed[TXT_FLAG+1]; char confirmed[TXT_FLAG+1];
double diffacc;
double diffinv;
double shareacc;
double shareinv;
int64_t elapsed;
char statsconfirmed[TXT_FLAG+1];
HISTORYDATECONTROLFIELDS; HISTORYDATECONTROLFIELDS;
} BLOCKS; } BLOCKS;
@ -2310,13 +2316,29 @@ static K_ITEM *get_workerstatus(int64_t userid, char *workername)
return find; return find;
} }
static K_ITEM *_find_create_workerstatus(int64_t userid, char *workername, bool create) /* Worker loading/creation calls this with create = true
* All others with create = false since the workerstatus should exist
* Failure is a code bug and a reported error, but handled anyway
* This has 2 sets of file/func/line to allow 2 levels of traceback
*/
static K_ITEM *_find_create_workerstatus(int64_t userid, char *workername,
bool create, const char *file2,
const char *func2, const int line2,
WHERE_FFL_ARGS)
{ {
WORKERSTATUS *row; WORKERSTATUS *row;
K_ITEM *item; K_ITEM *item;
item = get_workerstatus(userid, workername); item = get_workerstatus(userid, workername);
if (!item && create) { if (!item) {
if (!create) {
LOGEMERG("%s(): Missing workerstatus %"PRId64"/%s"
WHERE_FFL WHERE_FFL,
__func__, userid, workername,
file2, func2, line2, WHERE_FFL_PASS);
return NULL;
}
K_WLOCK(workerstatus_free); K_WLOCK(workerstatus_free);
item = k_unlink_head(workerstatus_free); item = k_unlink_head(workerstatus_free);
@ -2333,15 +2355,103 @@ static K_ITEM *_find_create_workerstatus(int64_t userid, char *workername, bool
return item; return item;
} }
#define find_create_workerstatus(_u, _w) _find_create_workerstatus(_u, _w, true) #define find_create_workerstatus(_u, _w, _file, _func, _line) \
#define find_workerstatus(_u, _w) _find_create_workerstatus(_u, _w, false) _find_create_workerstatus(_u, _w, true, _file, _func, _line, WHERE_FFL_HERE)
#define find_workerstatus(_u, _w, _file, _func, _line) \
_find_create_workerstatus(_u, _w, false, _file, _func, _line, WHERE_FFL_HERE)
static cmp_t cmp_userstats_workerstatus(K_ITEM *a, K_ITEM *b); static cmp_t cmp_userstats_workerstatus(K_ITEM *a, K_ITEM *b);
static cmp_t cmp_sharesummary(K_ITEM *a, K_ITEM *b); static cmp_t cmp_sharesummary(K_ITEM *a, K_ITEM *b);
static void zero_on_new_block()
{
WORKERSTATUS *workerstatus;
K_TREE_CTX ctx[1];
K_ITEM *ws_item;
K_WLOCK(workerstatus_free);
pool.diffacc = pool.diffinv = pool.shareacc =
pool.shareinv = pool.best_sdiff = 0;
ws_item = first_in_ktree(workerstatus_root, ctx);
while (ws_item) {
DATA_WORKERSTATUS(workerstatus, ws_item);
workerstatus->diffacc = workerstatus->diffinv =
workerstatus->shareacc = workerstatus->shareinv = 0.0;
ws_item = next_in_ktree(ctx);
}
K_WUNLOCK(workerstatus_free);
}
/* Currently only used at the end of the startup
* Will need to add locking if it's used, later, after startup completes */
static void set_block_share_counters()
{
K_TREE_CTX ctx[1];
K_ITEM *ss_item, ss_look, *ws_item;
WORKERSTATUS *workerstatus;
SHARESUMMARY *sharesummary, looksharesummary;
INIT_SHARESUMMARY(&ss_look);
zero_on_new_block();
ws_item = NULL;
/* From the end backwards so we can skip the workinfoid's we don't
* want by jumping back to just before the current worker when the
* workinfoid goes below the limit */
ss_item = last_in_ktree(sharesummary_root, ctx);
while (ss_item) {
DATA_SHARESUMMARY(sharesummary, ss_item);
if (sharesummary->workinfoid < pool.workinfoid) {
// Skip back to the next worker
looksharesummary.userid = sharesummary->userid;
STRNCPY(looksharesummary.workername,
sharesummary->workername);
looksharesummary.workinfoid = -1;
ss_look.data = (void *)(&looksharesummary);
ss_item = find_before_in_ktree(sharesummary_root, &ss_look,
cmp_sharesummary, ctx);
continue;
}
/* Check for user/workername change for new workerstatus
* The tree has user/workername grouped together in order
* so this will only be once per user/workername */
if (!ws_item ||
sharesummary->userid != workerstatus->userid ||
strcmp(sharesummary->workername, workerstatus->workername)) {
/* This is to trigger a console error if it is missing
* since it should always exist
* However, it is simplest to simply create it
* and keep going */
ws_item = find_workerstatus(sharesummary->userid,
sharesummary->workername,
__FILE__, __func__, __LINE__);
if (!ws_item) {
ws_item = find_create_workerstatus(sharesummary->userid,
sharesummary->workername,
__FILE__, __func__, __LINE__);
}
DATA_WORKERSTATUS(workerstatus, ws_item);
}
pool.diffacc += sharesummary->diffacc;
pool.diffinv += sharesummary->diffsta + sharesummary->diffdup +
sharesummary->diffhi + sharesummary->diffrej;
workerstatus->diffacc += sharesummary->diffacc;
workerstatus->diffinv += sharesummary->diffsta + sharesummary->diffdup +
sharesummary->diffhi + sharesummary->diffrej;
workerstatus->shareacc += sharesummary->shareacc;
workerstatus->shareinv += sharesummary->sharesta + sharesummary->sharedup +
sharesummary->sharehi + sharesummary->sharerej;
ss_item = prev_in_ktree(ctx);
}
}
/* All data is loaded, now update workerstatus fields /* All data is loaded, now update workerstatus fields
* Since shares are all part of a sharesummary, there's no need to search shares TODO: combine set_block_share_counters() with this? */
*/
static void workerstatus_ready() static void workerstatus_ready()
{ {
K_TREE_CTX ws_ctx[1], us_ctx[1], ss_ctx[1]; K_TREE_CTX ws_ctx[1], us_ctx[1], ss_ctx[1];
@ -2400,46 +2510,63 @@ static void workerstatus_ready()
} }
} }
static void workerstatus_update(AUTHS *auths, SHARES *shares, USERSTATS *userstats, #define workerstatus_update(_auths, _shares, _userstats) \
SHARESUMMARY *sharesummary) _workerstatus_update(_auths, _shares, _userstats, WHERE_FFL_HERE)
static void _workerstatus_update(AUTHS *auths, SHARES *shares,
USERSTATS *userstats, WHERE_FFL_ARGS)
{ {
WORKERSTATUS *row; WORKERSTATUS *row;
K_ITEM *item; K_ITEM *item;
if (auths) { if (auths) {
item = find_create_workerstatus(auths->userid, auths->workername); item = find_workerstatus(auths->userid, auths->workername,
DATA_WORKERSTATUS(row, item); file, func, line);
if (tv_newer(&(row->last_auth), &(auths->createdate))) if (item) {
copy_tv(&(row->last_auth), &(auths->createdate)); DATA_WORKERSTATUS(row, item);
} if (tv_newer(&(row->last_auth), &(auths->createdate)))
copy_tv(&(row->last_auth), &(auths->createdate));
if (startup_complete && shares) {
item = find_create_workerstatus(shares->userid, shares->workername);
DATA_WORKERSTATUS(row, item);
if (tv_newer(&(row->last_share), &(shares->createdate))) {
copy_tv(&(row->last_share), &(shares->createdate));
row->last_diff = shares->diff;
} }
} }
if (startup_complete && userstats) { if (startup_complete && shares) {
item = find_create_workerstatus(userstats->userid, userstats->workername); if (shares->errn == SE_NONE) {
DATA_WORKERSTATUS(row, item); pool.diffacc += shares->diff;
if (userstats->idle) { pool.shareacc++;
if (tv_newer(&(row->last_idle), &(userstats->statsdate)))
copy_tv(&(row->last_idle), &(userstats->statsdate));
} else { } else {
if (tv_newer(&(row->last_stats), &(userstats->statsdate))) pool.diffinv += shares->diff;
copy_tv(&(row->last_stats), &(userstats->statsdate)); pool.shareinv++;
}
item = find_workerstatus(shares->userid, shares->workername,
file, func, line);
if (item) {
DATA_WORKERSTATUS(row, item);
if (tv_newer(&(row->last_share), &(shares->createdate))) {
copy_tv(&(row->last_share), &(shares->createdate));
row->last_diff = shares->diff;
}
if (shares->errn == SE_NONE) {
row->diffacc += shares->diff;
row->shareacc++;
} else {
row->diffinv += shares->diff;
row->shareinv++;
}
} }
} }
if (startup_complete && sharesummary) { if (startup_complete && userstats) {
item = find_create_workerstatus(sharesummary->userid, sharesummary->workername); item = find_workerstatus(userstats->userid, userstats->workername,
DATA_WORKERSTATUS(row, item); file, func, line);
if (tv_newer(&(row->last_share), &(sharesummary->lastshare))) { if (item) {
copy_tv(&(row->last_share), &(sharesummary->lastshare)); DATA_WORKERSTATUS(row, item);
row->last_diff = sharesummary->lastdiffacc; if (userstats->idle) {
if (tv_newer(&(row->last_idle), &(userstats->statsdate)))
copy_tv(&(row->last_idle), &(userstats->statsdate));
} else {
if (tv_newer(&(row->last_stats), &(userstats->statsdate)))
copy_tv(&(row->last_stats), &(userstats->statsdate));
}
} }
} }
} }
@ -2972,6 +3099,9 @@ unitem:
else { else {
workers_root = add_to_ktree(workers_root, item, cmp_workers); workers_root = add_to_ktree(workers_root, item, cmp_workers);
k_add_head(workers_store, item); k_add_head(workers_store, item);
// Ensure there is a matching workerstatus
find_create_workerstatus(userid, workername,
__FILE__, __func__, __LINE__);
} }
K_WUNLOCK(workers_free); K_WUNLOCK(workers_free);
@ -3250,6 +3380,13 @@ static bool workers_fill(PGconn *conn)
workers_root = add_to_ktree(workers_root, item, cmp_workers); workers_root = add_to_ktree(workers_root, item, cmp_workers);
k_add_head(workers_store, item); k_add_head(workers_store, item);
/* Make sure a workerstatus exists for each worker
* This is to ensure that code can use the workerstatus tree
* to reference other tables and not miss workers in the
* other tables */
find_create_workerstatus(row->userid, row->workername,
__FILE__, __func__, __LINE__);
} }
if (!ok) if (!ok)
k_add_head(workers_free, item); k_add_head(workers_free, item);
@ -4483,14 +4620,6 @@ static bool shares_add(PGconn *conn, char *workinfoid, char *username, char *wor
} }
if (!sharesummary->reset) { if (!sharesummary->reset) {
if (sharesummary->workinfoid >= pool.workinfoid) {
// Negate coz the shares will re-add
pool.diffacc -= sharesummary->diffacc;
pool.diffinv -= (sharesummary->diffsta +
sharesummary->diffdup +
sharesummary->diffhi +
sharesummary->diffrej);
}
zero_sharesummary(sharesummary, cd, shares->diff); zero_sharesummary(sharesummary, cd, shares->diff);
sharesummary->reset = true; sharesummary->reset = true;
} }
@ -4498,7 +4627,7 @@ static bool shares_add(PGconn *conn, char *workinfoid, char *username, char *wor
} }
if (!confirm_sharesummary) if (!confirm_sharesummary)
workerstatus_update(NULL, shares, NULL, NULL); workerstatus_update(NULL, shares, NULL);
sharesummary_update(conn, shares, NULL, NULL, by, code, inet, cd); sharesummary_update(conn, shares, NULL, NULL, by, code, inet, cd);
@ -4623,14 +4752,6 @@ static bool shareerrors_add(PGconn *conn, char *workinfoid, char *username,
} }
if (!sharesummary->reset) { if (!sharesummary->reset) {
if (sharesummary->workinfoid >= pool.workinfoid) {
// Negate coz the shares will re-add
pool.diffacc -= sharesummary->diffacc;
pool.diffinv -= (sharesummary->diffsta +
sharesummary->diffdup +
sharesummary->diffhi +
sharesummary->diffrej);
}
zero_sharesummary(sharesummary, cd, 0.0); zero_sharesummary(sharesummary, cd, 0.0);
sharesummary->reset = true; sharesummary->reset = true;
} }
@ -4803,32 +4924,22 @@ static bool _sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row
case SE_NONE: case SE_NONE:
row->diffacc += s_row->diff; row->diffacc += s_row->diff;
row->shareacc++; row->shareacc++;
if (row->workinfoid >= pool.workinfoid)
pool.diffacc += s_row->diff;
break; break;
case SE_STALE: case SE_STALE:
row->diffsta += s_row->diff; row->diffsta += s_row->diff;
row->sharesta++; row->sharesta++;
if (row->workinfoid >= pool.workinfoid)
pool.diffinv += s_row->diff;
break; break;
case SE_DUPE: case SE_DUPE:
row->diffdup += s_row->diff; row->diffdup += s_row->diff;
row->sharedup++; row->sharedup++;
if (row->workinfoid >= pool.workinfoid)
pool.diffinv += s_row->diff;
break; break;
case SE_HIGH_DIFF: case SE_HIGH_DIFF:
row->diffhi += s_row->diff; row->diffhi += s_row->diff;
row->sharehi++; row->sharehi++;
if (row->workinfoid >= pool.workinfoid)
pool.diffinv += s_row->diff;
break; break;
default: default:
row->diffrej += s_row->diff; row->diffrej += s_row->diff;
row->sharerej++; row->sharerej++;
if (row->workinfoid >= pool.workinfoid)
pool.diffinv += s_row->diff;
break; break;
} }
} }
@ -5193,8 +5304,6 @@ static bool sharesummary_fill(PGconn *conn)
sharesummary_workinfoid_root = add_to_ktree(sharesummary_workinfoid_root, item, cmp_sharesummary_workinfoid); sharesummary_workinfoid_root = add_to_ktree(sharesummary_workinfoid_root, item, cmp_sharesummary_workinfoid);
k_add_head(sharesummary_store, item); k_add_head(sharesummary_store, item);
workerstatus_update(NULL, NULL, NULL, row);
// A share summary is currently only shares in a single workinfo, at all 3 levels n,a,y // A share summary is currently only shares in a single workinfo, at all 3 levels n,a,y
if (tolower(row->complete[0]) == SUMMARY_NEW) { if (tolower(row->complete[0]) == SUMMARY_NEW) {
if (dbstatus.oldest_sharesummary_firstshare_n.tv_sec == 0 || if (dbstatus.oldest_sharesummary_firstshare_n.tv_sec == 0 ||
@ -5223,12 +5332,6 @@ static bool sharesummary_fill(PGconn *conn)
} }
} }
if (row->workinfoid >= pool.workinfoid) {
pool.diffacc += row->diffacc;
pool.diffinv += row->diffsta + row->diffdup +
row->diffhi + row->diffrej;
}
tick(); tick();
} }
if (!ok) if (!ok)
@ -5373,8 +5476,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
TXT_TO_INT("height", height, row->height); TXT_TO_INT("height", height, row->height);
STRNCPY(row->blockhash, blockhash); STRNCPY(row->blockhash, blockhash);
HISTORYDATEINIT(row, cd, by, code, inet);
dsp_hash(blockhash, hash_dsp, sizeof(hash_dsp)); dsp_hash(blockhash, hash_dsp, sizeof(hash_dsp));
K_WLOCK(blocks_free); K_WLOCK(blocks_free);
@ -5419,6 +5520,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
STRNCPY(row->nonce, nonce); STRNCPY(row->nonce, nonce);
TXT_TO_BIGINT("reward", reward, row->reward); TXT_TO_BIGINT("reward", reward, row->reward);
HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row); HISTORYDATETRANSFER(trf_root, row);
par = 0; par = 0;
@ -5436,6 +5538,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
HISTORYDATEPARAMS(params, par, row); HISTORYDATEPARAMS(params, par, row);
PARCHK(par, params); PARCHK(par, params);
// db default stats values
ins = "insert into blocks " ins = "insert into blocks "
"(height,blockhash,workinfoid,userid,workername," "(height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed" "clientid,enonce1,nonce2,nonce,reward,confirmed"
@ -5507,16 +5610,17 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
conned = true; conned = true;
} }
STRNCPY(row->confirmed, confirmed);
// New is mostly a copy of the old // New is mostly a copy of the old
row->workinfoid = oldblocks->workinfoid; memcpy(row, oldblocks, sizeof(*row));
STRNCPY(row->workername, oldblocks->workername); STRNCPY(row->confirmed, confirmed);
row->clientid = oldblocks->clientid; if (confirmed[0] == BLOCKS_CONFIRM) {
STRNCPY(row->enonce1, oldblocks->enonce1); row->diffacc = pool.diffacc;
STRNCPY(row->nonce2, oldblocks->nonce2); row->diffinv = pool.diffinv;
STRNCPY(row->nonce, oldblocks->nonce); row->shareacc = pool.shareacc;
row->reward = oldblocks->reward; row->shareinv = pool.shareinv;
}
HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row); HISTORYDATETRANSFER(trf_root, row);
res = PQexec(conn, "Begin", CKPQ_WRITE); res = PQexec(conn, "Begin", CKPQ_WRITE);
@ -5543,17 +5647,43 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
params[par++] = str_to_buf(row->blockhash, NULL, 0); params[par++] = str_to_buf(row->blockhash, NULL, 0);
params[par++] = tv_to_buf(cd, NULL, 0); params[par++] = tv_to_buf(cd, NULL, 0);
params[par++] = str_to_buf(row->confirmed, NULL, 0); params[par++] = str_to_buf(row->confirmed, NULL, 0);
HISTORYDATEPARAMS(params, par, row);
PARCHKVAL(par, 3 + HISTORYDATECOUNT, params); // 8 as per ins
ins = "insert into blocks " if (confirmed[0] == BLOCKS_CONFIRM) {
"(height,blockhash,workinfoid,userid,workername," params[par++] = double_to_buf(row->diffacc, NULL, 0);
"clientid,enonce1,nonce2,nonce,reward,confirmed" params[par++] = double_to_buf(row->diffinv, NULL, 0);
HISTORYDATECONTROL ") select " params[par++] = double_to_buf(row->shareacc, NULL, 0);
"height,blockhash,workinfoid,userid,workername," params[par++] = double_to_buf(row->shareinv, NULL, 0);
"clientid,enonce1,nonce2,nonce,reward," HISTORYDATEPARAMS(params, par, row);
"$3,$4,$5,$6,$7,$8 from blocks where " PARCHKVAL(par, 7 + HISTORYDATECOUNT, params); // 12 as per ins
"blockhash=$1 and expirydate=$2";
ins = "insert into blocks "
"(height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed,"
"diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed"
HISTORYDATECONTROL ") select "
"height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,"
"$3,$4,$5,$6,$7,elapsed,statsconfirmed,"
"$8,$9,$10,$11,$12 from blocks where "
"blockhash=$1 and expirydate=$2";
} else {
HISTORYDATEPARAMS(params, par, row);
PARCHKVAL(par, 3 + HISTORYDATECOUNT, params); // 8 as per ins
ins = "insert into blocks "
"(height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed,"
"diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed"
HISTORYDATECONTROL ") select "
"height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,"
"$3,diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed"
"$4,$5,$6,$7,$8 from blocks where "
"blockhash=$1 and expirydate=$2";
}
res = PQexecParams(conn, ins, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_WRITE); res = PQexecParams(conn, ins, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_WRITE);
rescode = PQresultStatus(res); rescode = PQresultStatus(res);
@ -5608,7 +5738,8 @@ flail:
switch (confirmed[0]) { switch (confirmed[0]) {
case BLOCKS_NEW: case BLOCKS_NEW:
blk = true; blk = true;
tmp[0] = '\0'; tv_to_buf(&(row->createdate), cd_buf, sizeof(cd_buf));
snprintf(tmp, sizeof(tmp), " UTC:%s", cd_buf);
break; break;
case BLOCKS_CONFIRM: case BLOCKS_CONFIRM:
blk = true; blk = true;
@ -5625,8 +5756,8 @@ flail:
100.0 * pool.diffacc / wdiff); 100.0 * pool.diffacc / wdiff);
} }
} }
if (pool.diffacc >= 1000000.0) { if (pool.diffacc >= 1000.0) {
suffix_string(pool.diffacc, est, sizeof(est)-1, 1); suffix_string(pool.diffacc, est, sizeof(est)-1, 0);
strcat(est, " "); strcat(est, " ");
} }
tv_to_buf(&(row->createdate), cd_buf, sizeof(cd_buf)); tv_to_buf(&(row->createdate), cd_buf, sizeof(cd_buf));
@ -5637,8 +5768,7 @@ flail:
pool.diffacc, est, pct, cd_buf); pool.diffacc, est, pct, cd_buf);
if (pool.workinfoid < row->workinfoid) { if (pool.workinfoid < row->workinfoid) {
pool.workinfoid = row->workinfoid; pool.workinfoid = row->workinfoid;
pool.diffacc = pool.diffinv = zero_on_new_block();
pool.best_sdiff = 0.0;
} }
break; break;
case BLOCKS_ORPHAN: case BLOCKS_ORPHAN:
@ -5667,14 +5797,15 @@ static bool blocks_fill(PGconn *conn)
BLOCKS *row; BLOCKS *row;
char *field; char *field;
char *sel; char *sel;
int fields = 11; int fields = 17;
bool ok; bool ok;
LOGDEBUG("%s(): select", __func__); LOGDEBUG("%s(): select", __func__);
sel = "select " sel = "select "
"height,blockhash,workinfoid,userid,workername," "height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed" "clientid,enonce1,nonce2,nonce,reward,confirmed,"
"diffacc,diffinv,shareacc,shareinv,elapsed,statsconfirmed"
HISTORYDATECONTROL HISTORYDATECONTROL
" from blocks"; " from blocks";
res = PQexec(conn, sel, CKPQ_READ); res = PQexec(conn, sel, CKPQ_READ);
@ -5756,6 +5887,36 @@ static bool blocks_fill(PGconn *conn)
break; break;
TXT_TO_STR("confirmed", field, row->confirmed); TXT_TO_STR("confirmed", field, row->confirmed);
PQ_GET_FLD(res, i, "diffacc", field, ok);
if (!ok)
break;
TXT_TO_DOUBLE("diffacc", field, row->diffacc);
PQ_GET_FLD(res, i, "diffinv", field, ok);
if (!ok)
break;
TXT_TO_DOUBLE("diffinv", field, row->diffinv);
PQ_GET_FLD(res, i, "shareacc", field, ok);
if (!ok)
break;
TXT_TO_DOUBLE("shareacc", field, row->shareacc);
PQ_GET_FLD(res, i, "shareinv", field, ok);
if (!ok)
break;
TXT_TO_DOUBLE("shareinv", field, row->shareinv);
PQ_GET_FLD(res, i, "elapsed", field, ok);
if (!ok)
break;
TXT_TO_BIGINT("elapsed", field, row->elapsed);
PQ_GET_FLD(res, i, "statsconfirmed", field, ok);
if (!ok)
break;
TXT_TO_STR("statsconfirmed", field, row->statsconfirmed);
HISTORYDATEFLDS(res, i, row, ok); HISTORYDATEFLDS(res, i, row, ok);
if (!ok) if (!ok)
break; break;
@ -6108,7 +6269,7 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username,
K_WUNLOCK(auths_free); K_WUNLOCK(auths_free);
// Update even if DB fails // Update even if DB fails
workerstatus_update(row, NULL, NULL, NULL); workerstatus_update(row, NULL, NULL);
if (conn == NULL) { if (conn == NULL) {
conn = dbconnect(); conn = dbconnect();
@ -6252,7 +6413,7 @@ static bool auths_fill(PGconn *conn)
auths_root = add_to_ktree(auths_root, item, cmp_auths); auths_root = add_to_ktree(auths_root, item, cmp_auths);
k_add_head(auths_store, item); k_add_head(auths_store, item);
workerstatus_update(row, NULL, NULL, NULL); workerstatus_update(row, NULL, NULL);
if (tv_newer(&(dbstatus.newest_createdate_auths), &(row->createdate))) if (tv_newer(&(dbstatus.newest_createdate_auths), &(row->createdate)))
copy_tv(&(dbstatus.newest_createdate_auths), &(row->createdate)); copy_tv(&(dbstatus.newest_createdate_auths), &(row->createdate));
@ -6751,7 +6912,7 @@ static bool userstats_add(char *poolinstance, char *elapsed, char *username,
} }
} }
workerstatus_update(NULL, NULL, row, NULL); workerstatus_update(NULL, NULL, row);
/* group at full key: userid,createdate,poolinstance,workername /* group at full key: userid,createdate,poolinstance,workername
i.e. ignore instance and group together down at workername */ i.e. ignore instance and group together down at workername */
@ -6959,7 +7120,7 @@ static bool userstats_fill(PGconn *conn)
cmp_userstats_workerstatus); cmp_userstats_workerstatus);
k_add_head(userstats_store, item); k_add_head(userstats_store, item);
workerstatus_update(NULL, NULL, row, NULL); workerstatus_update(NULL, NULL, row);
if (userstats_starttimeband(row, &statsdate)) { if (userstats_starttimeband(row, &statsdate)) {
if (tv_newer(&(dbstatus.newest_starttimeband_userstats), &statsdate)) if (tv_newer(&(dbstatus.newest_starttimeband_userstats), &statsdate))
copy_tv(&(dbstatus.newest_starttimeband_userstats), &statsdate); copy_tv(&(dbstatus.newest_starttimeband_userstats), &statsdate);
@ -7416,6 +7577,11 @@ static bool setup_data()
if (!reload() || everyone_die) if (!reload() || everyone_die)
return false; return false;
set_block_share_counters();
if (everyone_die)
return false;
workerstatus_ready(); workerstatus_ready();
userstats_workerstatus_root = free_ktree(userstats_workerstatus_root, NULL); userstats_workerstatus_root = free_ktree(userstats_workerstatus_root, NULL);
@ -7881,7 +8047,7 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused K_TREE *trf_root) __maybe_unused K_TREE *trf_root)
{ {
K_TREE_CTX ctx[1]; K_TREE_CTX ctx[1];
K_ITEM *b_item; K_ITEM *b_item, *w_item;
BLOCKS *blocks; BLOCKS *blocks;
char reply[1024] = ""; char reply[1024] = "";
char tmp[1024]; char tmp[1024];
@ -7940,6 +8106,44 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id,
blocks_confirmed(blocks->confirmed), FLDSEP); blocks_confirmed(blocks->confirmed), FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
double_to_buf(blocks->diffacc, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "diffacc:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf(blocks->diffinv, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "diffinv:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf(blocks->shareacc, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "shareacc:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf(blocks->shareinv, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "shareinv:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
bigint_to_buf(blocks->elapsed, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "elapsed:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
w_item = find_workinfo(blocks->workinfoid);
if (w_item) {
char wdiffbin[TXT_SML+1];
double wdiff;
WORKINFO *workinfo;
DATA_WORKINFO(workinfo, w_item);
hex2bin(wdiffbin, workinfo->bits, 4);
wdiff = diff_from_nbits(wdiffbin);
snprintf(tmp, sizeof(tmp),
"netdiff:%d=%.1f%c",
rows, wdiff, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
} else {
snprintf(tmp, sizeof(tmp),
"netdiff:%d=?%c", rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
}
rows++; rows++;
} }
b_item = prev_in_ktree(ctx); b_item = prev_in_ktree(ctx);
@ -7949,7 +8153,8 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id,
"rows=%d%cflds=%s%c", "rows=%d%cflds=%s%c",
rows, FLDSEP, rows, FLDSEP,
"height,blockhash,nonce,reward,workername,firstcreatedate," "height,blockhash,nonce,reward,workername,firstcreatedate,"
"createdate,status", FLDSEP); "createdate,status,diffacc,diffinv,shareacc,shareinv,elapsed,"
"netdiff", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Blocks", FLDSEP, ""); snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Blocks", FLDSEP, "");
@ -8267,18 +8472,25 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id,
double w_hashrate5m, w_hashrate1hr; double w_hashrate5m, w_hashrate1hr;
int64_t w_elapsed; int64_t w_elapsed;
tv_t w_lastshare; tv_t w_lastshare;
double w_lastdiff; double w_lastdiff, w_diffacc, w_diffinv;
double w_shareacc, w_shareinv;
w_hashrate5m = w_hashrate1hr = 0.0; w_hashrate5m = w_hashrate1hr = 0.0;
w_elapsed = -1; w_elapsed = -1;
w_lastshare.tv_sec = 0; w_lastshare.tv_sec = 0;
w_lastdiff = 0; w_lastdiff = w_diffacc = w_diffinv =
w_shareacc = w_shareinv = 0;
ws_item = find_workerstatus(users->userid, workers->workername); ws_item = find_workerstatus(users->userid, workers->workername,
__FILE__, __func__, __LINE__);
if (ws_item) { if (ws_item) {
DATA_WORKERSTATUS(workerstatus, ws_item); DATA_WORKERSTATUS(workerstatus, ws_item);
w_lastshare.tv_sec = workerstatus->last_share.tv_sec; w_lastshare.tv_sec = workerstatus->last_share.tv_sec;
w_lastdiff = workerstatus->last_diff; w_lastdiff = workerstatus->last_diff;
w_diffacc = workerstatus->diffacc;
w_diffinv = workerstatus->diffinv;
w_shareacc = workerstatus->shareacc;
w_shareinv = workerstatus->shareinv;
} }
// find last stored userid record // find last stored userid record
@ -8334,6 +8546,22 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), "w_lastdiff:%d=%s%c", rows, reply, FLDSEP); snprintf(tmp, sizeof(tmp), "w_lastdiff:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
double_to_buf((int)(w_diffacc), reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "w_diffacc:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf((int)(w_diffinv), reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "w_diffinv:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf((int)(w_shareacc), reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "w_shareacc:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf((int)(w_shareinv), reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "w_shareinv:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
userstats_workername_root = free_ktree(userstats_workername_root, NULL); userstats_workername_root = free_ktree(userstats_workername_root, NULL);
K_RUNLOCK(userstats_free); K_RUNLOCK(userstats_free);
} }
@ -8346,8 +8574,10 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), snprintf(tmp, sizeof(tmp),
"rows=%d%cflds=%s%s%c", "rows=%d%cflds=%s%s%c",
rows, FLDSEP, rows, FLDSEP,
"workername,difficultydefault,idlenotificationenabled,idlenotificationtime", "workername,difficultydefault,idlenotificationenabled,"
stats ? ",w_hashrate5m,w_hashrate1hr,w_elapsed,w_lastshare,w_lastdiff" : "", "idlenotificationtime",
stats ? ",w_hashrate5m,w_hashrate1hr,w_elapsed,w_lastshare,"
"w_lastdiff,w_diffacc,w_diffinv,w_shareacc,w_shareinv" : "",
FLDSEP); FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
@ -9166,6 +9396,14 @@ static char *cmd_homepage(__maybe_unused PGconn *conn, char *cmd, char *id,
pool.diffinv, FLDSEP); pool.diffinv, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "blockshareacc=%.1f%c",
pool.shareacc, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "blockshareinv=%.1f%c",
pool.shareinv, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
// TODO: assumes only one poolinstance (for now) // TODO: assumes only one poolinstance (for now)
p_item = last_in_ktree(poolstats_root, ctx); p_item = last_in_ktree(poolstats_root, ctx);
if (p_item) { if (p_item) {

Loading…
Cancel
Save