Browse Source

ckdb/php - Hall of Fame stats (no user access yet)

master
kanoi 10 years ago
parent
commit
e1e4accda6
  1. 12
      pool/db.php
  2. 62
      pool/page_userinfo.php
  3. 14
      src/ckdb.c
  4. 43
      src/ckdb.h
  5. 84
      src/ckdb_cmd.c
  6. 192
      src/ckdb_data.c
  7. 24
      src/ckdb_dbio.c

12
pool/db.php

@ -386,6 +386,18 @@ function getBlocks($user)
return repDecode($rep);
}
#
function getUserInfo($user)
{
if ($user == false)
showIndex();
$flds = array('username' => $user);
$msg = msgEncode('userinfo', 'usr', $flds, $user);
$rep = sendsockreply('getUserInfo', $msg);
if (!$rep)
dbdown();
return repDecode($rep);
}
#
# e.g. $atts = array('ua_Reset.str' => 'FortyTwo',
# 'ua_Reset.date' => 'now+3600')
# 'ua_Tanuki.str' => 'Meme',

62
pool/page_userinfo.php

@ -0,0 +1,62 @@
<?php
#
function blocksorder($a, $b)
{
if ($b['blocks'] == $a['blocks'])
return $b['diffacc'] - $a['diffacc'];
else
return $a['blocks'] - $b['blocks'];
}
#
function douserinfo($data, $user)
{
$ans = getUserInfo($user);
$pg = '<h1>Block Hall of Fame</h1>'.$pg;
$pg .= "<table callpadding=0 cellspacing=0 border=0>\n";
$pg .= "<tr class=title>";
$pg .= "<td class=dl>User</td>";
$pg .= "<td class=dr>Blocks</td>";
$pg .= "<td class=dr>Diff</td>";
$pg .= "</tr>\n";
if ($ans['STATUS'] == 'ok')
{
$all = array();
$count = $ans['rows'];
for ($i = 0; $i < $count; $i++)
{
$all[] = array('blocks' => $ans['blocks:'.$i],
'username' => $ans['username:'.$i],
'diffacc' => $ans['diffacc:'.$i]);
}
usort($all, 'blocksorder');
for ($i = 0; $i < $count; $i++)
{
if (($i % 2) == 0)
$row = 'even';
else
$row = 'odd';
$pg .= "<tr class=$row>";
$un = htmlspecialchars($all[$i]['username']);
$pg .= "<td class=dl>$un</td>";
$bl = $all[$i]['blocks'];
$pg .= "<td class=dr>$bl</td>";
$diffacc = difffmt($all[$i]['diffacc']);
$pg .= "<td class=dr>$diffacc</td>";
$pg .= "</tr>\n";
}
}
$pg .= "</table>\n";
return $pg;
}
#
function show_userinfo($info, $page, $menu, $name, $user)
{
gopage($info, NULL, 'douserinfo', $page, $menu, $name, $user);
}
#
?>

14
src/ckdb.c

@ -510,6 +510,11 @@ const char *marktype_other_finish_fmt = "fin: %s";
const char *marktype_shift_begin_skip = "Shift stt: ";
const char *marktype_shift_end_skip = "Shift fin: ";
// USERINFO from various incoming data
K_TREE *userinfo_root;
K_LIST *userinfo_free;
K_STORE *userinfo_store;
static char logname[512];
static char *dbcode;
@ -1145,6 +1150,11 @@ static void alloc_storage()
ALLOC_MARKS, LIMIT_MARKS, true);
marks_store = k_new_store(marks_free);
marks_root = new_ktree();
userinfo_free = k_new_list("UserInfo", sizeof(USERINFO),
ALLOC_USERINFO, LIMIT_USERINFO, true);
userinfo_store = k_new_store(userinfo_free);
userinfo_root = new_ktree();
}
#define SEQSETMSG(_set, _seqset, _msgtxt, _endtxt) do { \
@ -1282,6 +1292,8 @@ static void dealloc_storage()
FREE_LISTS(logqueue);
FREE_ALL(userinfo);
FREE_TREE(marks);
FREE_STORE_DATA(marks);
FREE_LIST_DATA(marks);
@ -3953,6 +3965,7 @@ static void *socketer(__maybe_unused void *arg)
case CMD_STATS:
case CMD_USERSTATUS:
case CMD_SHSTA:
case CMD_USERINFO:
ans = ckdb_cmds[msgline->which_cmds].func(NULL,
msgline->cmd,
msgline->id,
@ -4275,6 +4288,7 @@ static void reload_line(PGconn *conn, char *filename, uint64_t count, char *buf)
case CMD_MARKS:
case CMD_PSHIFT:
case CMD_SHSTA:
case CMD_USERINFO:
LOGERR("%s() INVALID message line %"PRIu64
" ignored '%.42s...",
__func__, count,

43
src/ckdb.h

@ -55,7 +55,7 @@
#define DB_VLOCK "1"
#define DB_VERSION "1.0.0"
#define CKDB_VERSION DB_VERSION"-1.092"
#define CKDB_VERSION DB_VERSION"-1.093"
#define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -403,6 +403,7 @@ enum cmd_values {
CMD_MARKS,
CMD_PSHIFT,
CMD_SHSTA,
CMD_USERINFO,
CMD_END
};
@ -1929,6 +1930,35 @@ extern const char *marktype_shift_end_skip;
#define MARK_USED_STR "u"
#define MUSED(_status) (tolower((_status)[0]) == MARK_USED)
// USERINFO from various incoming data
typedef struct userinfo {
int64_t userid;
char username[TXT_BIG+1];
int blocks;
int orphans; // How many blocks are orphans
tv_t last_block;
// For all time
double diffacc;
double diffsta;
double diffdup;
double diffhi;
double diffrej;
double shareacc;
double sharesta;
double sharedup;
double sharehi;
double sharerej;
} USERINFO;
#define ALLOC_USERINFO 1000
#define LIMIT_USERINFO 0
#define INIT_USERINFO(_item) INIT_GENERIC(_item, userinfo)
#define DATA_USERINFO(_var, _item) DATA_GENERIC(_var, _item, userinfo, true)
extern K_TREE *userinfo_root;
extern K_LIST *userinfo_free;
extern K_STORE *userinfo_store;
extern void logmsg(int loglevel, const char *fmt, ...);
extern void setnow(tv_t *now);
extern void tick();
@ -2192,6 +2222,17 @@ extern bool _marks_description(char *description, size_t siz, char *marktype,
int32_t height, char *shift, char *other,
WHERE_FFL_ARGS);
extern char *shiftcode(tv_t *createdate);
extern cmp_t cmp_userinfo(K_ITEM *a, K_ITEM *b);
#define get_userinfo(_userid) _get_userinfo(_userid, true)
extern K_ITEM *_get_userinfo(int64_t userid, bool lock);
#define find_userinfo(_userid) _find_create_userinfo(_userid, true, WHERE_FFL_HERE)
#define _find_userinfo(_userid, _lock) _find_create_userinfo(_userid, _lock, WHERE_FFL_HERE)
extern K_ITEM *_find_create_userinfo(int64_t userid, bool lock, WHERE_FFL_ARGS);
#define userinfo_update(_s, _ss, _ms) _userinfo_update(_s, _ss, _ms, true, true)
extern void _userinfo_update(SHARES *shares, SHARESUMMARY *sharesummary,
MARKERSUMMARY *markersummary, bool ss_sub, bool lock);
#define userinfo_block(_blocks, _isnew) _userinfo_block(_blocks, _isnew, true)
extern void _userinfo_block(BLOCKS *blocks, bool isnew, bool lock);
// ***
// *** PostgreSQL functions ckdb_dbio.c

84
src/ckdb_cmd.c

@ -5194,6 +5194,7 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
USEINFO(poolstats, 1, 1);
USEINFO(userstats, 2, 1);
USEINFO(workerstatus, 1, 1);
USEINFO(userinfo, 1, 1);
USEINFO(msgline, 1, 0);
USEINFO(workqueue, 1, 0);
USEINFO(transfer, 0, 0);
@ -5863,6 +5864,88 @@ static char *cmd_shsta(__maybe_unused PGconn *conn, char *cmd, char *id,
return strdup(buf);
}
static char *cmd_userinfo(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused 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)
{
K_ITEM *ui_item;
USERINFO *userinfo;
char reply[1024] = "";
char tmp[1024];
size_t len, off;
double d;
char *buf;
int rows;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok.");
rows = 0;
K_RLOCK(userinfo_free);
ui_item = userinfo_store->head;
while (ui_item) {
DATA_USERINFO(userinfo, ui_item);
str_to_buf(userinfo->username, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "username:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "blocks:%d=%d%c", rows,
userinfo->blocks - userinfo->orphans, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "orphans:%d=%d%c", rows,
userinfo->orphans, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf(userinfo->diffacc, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "diffacc:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
d = userinfo->diffsta + userinfo->diffdup + userinfo->diffhi +
userinfo->diffrej;
double_to_buf(d, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "diffinv:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
double_to_buf(userinfo->shareacc, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "shareacc:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
d = userinfo->sharesta + userinfo->sharedup + userinfo->sharehi +
userinfo->sharerej;
double_to_buf(d, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "shareinv:%d=%s%c", rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "lastblock=%ld%c",
userinfo->last_block.tv_sec, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
rows++;
ui_item = ui_item->next;
}
K_RUNLOCK(userinfo_free);
snprintf(tmp, sizeof(tmp),
"rows=%d%cflds=%s%c",
rows, FLDSEP,
"username,blocks,orphans,diffacc,diffinv,shareacc,shareinv,"
"lastblock", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=", "UserInfo", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
LOGDEBUG("%s.ok.%d_rows", id, rows);
return buf;
}
// TODO: limit access by having seperate sockets for each
#define ACCESS_POOL "p"
#define ACCESS_SYSTEM "s"
@ -5975,5 +6058,6 @@ struct CMDS ckdb_cmds[] = {
{ CMD_MARKS, "marks", false, false, cmd_marks, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_PSHIFT, "pshift", false, false, cmd_pshift, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_SHSTA, "shsta", true, false, cmd_shsta, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_USERINFO, "userinfo", false, false, cmd_userinfo, SEQ_NONE, ACCESS_WEB },
{ CMD_END, NULL, false, false, NULL, SEQ_NONE, NULL }
};

192
src/ckdb_data.c

@ -936,8 +936,10 @@ void _workerstatus_update(AUTHS *auths, SHARES *shares,
file, func, line);
if (item) {
DATA_WORKERSTATUS(row, item);
K_WLOCK(workerstatus_free);
if (tv_newer(&(row->last_auth), &(auths->createdate)))
copy_tv(&(row->last_auth), &(auths->createdate));
K_WUNLOCK(workerstatus_free);
}
}
@ -953,6 +955,7 @@ void _workerstatus_update(AUTHS *auths, SHARES *shares,
file, func, line);
if (item) {
DATA_WORKERSTATUS(row, item);
K_WLOCK(workerstatus_free);
if (tv_newer(&(row->last_share), &(shares->createdate))) {
copy_tv(&(row->last_share), &(shares->createdate));
row->last_diff = shares->diff;
@ -987,6 +990,7 @@ void _workerstatus_update(AUTHS *auths, SHARES *shares,
row->sharerej++;
break;
}
K_WLOCK(workerstatus_free);
}
}
@ -995,6 +999,7 @@ void _workerstatus_update(AUTHS *auths, SHARES *shares,
file, func, line);
if (item) {
DATA_WORKERSTATUS(row, item);
K_WLOCK(workerstatus_free);
if (userstats->idle) {
if (tv_newer(&(row->last_idle), &(userstats->statsdate)))
copy_tv(&(row->last_idle), &(userstats->statsdate));
@ -1002,6 +1007,7 @@ void _workerstatus_update(AUTHS *auths, SHARES *shares,
if (tv_newer(&(row->last_stats), &(userstats->statsdate)))
copy_tv(&(row->last_stats), &(userstats->statsdate));
}
K_WUNLOCK(workerstatus_free);
}
}
}
@ -1768,6 +1774,7 @@ bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance,
K_TREE_CTX ss_ctx[1], s_ctx[1];
char cd_buf[DATE_BUFSIZ];
int64_t ss_tot, ss_already, ss_failed, shares_tot, shares_dumped;
int64_t diff_tot;
SHARESUMMARY looksharesummary, *sharesummary;
WORKINFO *workinfo;
SHARES lookshares, *shares;
@ -1822,7 +1829,8 @@ bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance,
looksharesummary.workername = EMPTY;
ok = true;
ss_tot = ss_already = ss_failed = shares_tot = shares_dumped = 0;
ss_tot = ss_already = ss_failed = shares_tot = shares_dumped =
diff_tot = 0;
ss_look.data = (void *)(&looksharesummary);
K_RLOCK(sharesummary_free);
ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &ss_look, cmp_sharesummary_workinfoid, ss_ctx);
@ -1891,6 +1899,8 @@ bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance,
break;
shares_tot++;
if (shares->errn == SE_NONE)
diff_tot += shares->diff;
tmp_item = next_in_ktree(s_ctx);
shares_root = remove_from_ktree(shares_root, s_item, cmp_shares);
k_unlink_item(shares_store, s_item);
@ -1898,10 +1908,13 @@ bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance,
shares_dumped++;
if (reloading && skipupdate && !error[0]) {
snprintf(error, sizeof(error),
"reload found aged shares: %"PRId64"/%"PRId64"/%s",
"reload found aged share: %"PRId64
"/%"PRId64"/%s/%s%.0f",
shares->workinfoid,
shares->userid,
shares->workername);
shares->workername,
(shares->errn == SE_NONE) ? "" : "*",
shares->diff);
}
k_add_head(shares_free, s_item);
s_item = tmp_item;
@ -1923,12 +1936,13 @@ bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance,
/* If all were already aged, and no shares
* then we don't want a message */
if (!(ss_already == ss_tot && shares_tot == 0)) {
LOGERR("%s(): Summary aging of %"PRId64"/%s sstotal=%"PRId64
" already=%"PRId64" failed=%"PRId64
", sharestotal=%"PRId64" dumped=%"PRId64,
LOGERR("%s(): Summary aging of %"PRId64
"/%s sstotal=%"PRId64" already=%"PRId64
" failed=%"PRId64", sharestotal=%"PRId64
" dumped=%"PRId64", diff=%"PRId64,
__func__, workinfoid, poolinstance, ss_tot,
ss_already, ss_failed, shares_tot,
shares_dumped);
shares_dumped, diff_tot);
}
}
bye:
@ -4435,3 +4449,167 @@ char *shiftcode(tv_t *createdate)
LOGDEBUG("%s() code_buf='%s'", __func__, code_buf);
return(code_buf);
}
// order by userid asc
cmp_t cmp_userinfo(K_ITEM *a, K_ITEM *b)
{
USERINFO *ua, *ub;
DATA_USERINFO(ua, a);
DATA_USERINFO(ub, b);
return CMP_BIGINT(ua->userid, ub->userid);
}
K_ITEM *_get_userinfo(int64_t userid, bool lock)
{
USERINFO userinfo;
K_TREE_CTX ctx[1];
K_ITEM look, *find;
userinfo.userid = userid;
INIT_USERINFO(&look);
look.data = (void *)(&userinfo);
if (lock)
K_RLOCK(userinfo_free);
find = find_in_ktree(userinfo_root, &look, cmp_userinfo, ctx);
if (lock)
K_RUNLOCK(userinfo_free);
return find;
}
K_ITEM *_find_create_userinfo(int64_t userid, bool lock, WHERE_FFL_ARGS)
{
K_ITEM *ui_item, *u_item;
USERS *users = NULL;
USERINFO *row;
ui_item = _get_userinfo(userid, lock);
if (!ui_item) {
if (lock)
K_RLOCK(users_free);
u_item = find_userid(userid);
if (lock)
K_RUNLOCK(users_free);
DATA_USERS_NULL(users, u_item);
if (lock)
K_WLOCK(userinfo_free);
ui_item = k_unlink_head(userinfo_free);
DATA_USERINFO(row, ui_item);
bzero(row, sizeof(*row));
row->userid = userid;
if (u_item)
STRNCPY(row->username, users->username);
else
bigint_to_buf(userid, row->username, sizeof(row->username));
userinfo_root = add_to_ktree(userinfo_root, ui_item, cmp_userinfo);
k_add_head(userinfo_store, ui_item);
if (lock)
K_WUNLOCK(userinfo_free);
}
return ui_item;
}
void _userinfo_update(SHARES *shares, SHARESUMMARY *sharesummary,
MARKERSUMMARY *markersummary, bool ss_sub, bool lock)
{
USERINFO *row;
K_ITEM *item;
if (shares) {
item = _find_userinfo(shares->userid, lock);
DATA_USERINFO(row, item);
if (lock)
K_WLOCK(userinfo_free);
switch (shares->errn) {
case SE_NONE:
row->diffacc += shares->diff;
row->shareacc++;
break;
case SE_STALE:
row->diffsta += shares->diff;
row->sharesta++;
break;
case SE_DUPE:
row->diffdup += shares->diff;
row->sharedup++;
break;
case SE_HIGH_DIFF:
row->diffhi += shares->diff;
row->sharehi++;
break;
default:
row->diffrej += shares->diff;
row->sharerej++;
break;
}
if (lock)
K_WUNLOCK(userinfo_free);
}
// Only during db load so no locking required
if (sharesummary) {
item = _find_userinfo(sharesummary->userid, false);
DATA_USERINFO(row, item);
if (ss_sub) {
row->diffacc -= sharesummary->diffacc;
row->diffsta -= sharesummary->diffsta;
row->diffdup -= sharesummary->diffdup;
row->diffhi -= sharesummary->diffhi;
row->diffrej -= sharesummary->diffrej;
row->shareacc -= sharesummary->shareacc;
row->sharesta -= sharesummary->sharesta;
row->sharedup -= sharesummary->sharedup;
row->sharehi -= sharesummary->sharehi;
row->sharerej -= sharesummary->sharerej;
} else {
row->diffacc += sharesummary->diffacc;
row->diffsta += sharesummary->diffsta;
row->diffdup += sharesummary->diffdup;
row->diffhi += sharesummary->diffhi;
row->diffrej += sharesummary->diffrej;
row->shareacc += sharesummary->shareacc;
row->sharesta += sharesummary->sharesta;
row->sharedup += sharesummary->sharedup;
row->sharehi += sharesummary->sharehi;
row->sharerej += sharesummary->sharerej;
}
}
// Only during db load so no locking required
if (markersummary) {
item = _find_userinfo(markersummary->userid, false);
DATA_USERINFO(row, item);
row->diffacc += markersummary->diffacc;
row->diffsta += markersummary->diffsta;
row->diffdup += markersummary->diffdup;
row->diffhi += markersummary->diffhi;
row->diffrej += markersummary->diffrej;
row->shareacc += markersummary->shareacc;
row->sharesta += markersummary->sharesta;
row->sharedup += markersummary->sharedup;
row->sharehi += markersummary->sharehi;
row->sharerej += markersummary->sharerej;
}
}
// N.B. good blocks = blocks - orphans
void _userinfo_block(BLOCKS *blocks, bool isnew, bool lock)
{
USERINFO *row;
K_ITEM *item;
item = find_userinfo(blocks->userid);
DATA_USERINFO(row, item);
if (lock)
K_WLOCK(userinfo_free);
if (isnew) {
row->blocks++;
copy_tv(&(row->last_block), &(blocks->createdate));
} else
row->orphans++;
if (lock)
K_WLOCK(userinfo_free);
}

24
src/ckdb_dbio.c

@ -2836,6 +2836,9 @@ static bool shares_process(PGconn *conn, SHARES *shares, K_TREE *trf_root)
}
if (!sharesummary->reset) {
_userinfo_update(NULL, sharesummary, NULL,
true, true);
zero_sharesummary(sharesummary,
&(shares->createdate),
shares->diff);
@ -2844,8 +2847,10 @@ static bool shares_process(PGconn *conn, SHARES *shares, K_TREE *trf_root)
}
}
if (!confirm_sharesummary)
if (!confirm_sharesummary) {
workerstatus_update(NULL, shares, NULL);
userinfo_update(shares, NULL, NULL);
}
sharesummary_update(conn, shares, NULL, NULL, shares->createby,
shares->createcode, shares->createinet,
@ -3144,6 +3149,9 @@ static bool shareerrors_process(PGconn *conn, SHAREERRORS *shareerrors,
}
if (!sharesummary->reset) {
_userinfo_update(NULL, sharesummary, NULL,
true, true);
zero_sharesummary(sharesummary,
&(shareerrors->createdate),
0.0);
@ -4442,6 +4450,8 @@ bool sharesummary_fill(PGconn *conn)
sharesummary_to_pool(p_row, row);
_userinfo_update(NULL, row, NULL, false, false);
tick();
}
if (!ok) {
@ -4743,6 +4753,7 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
}
// We didn't use a Begin
ok = true;
userinfo_block(row, true);
goto unparam;
break;
case BLOCKS_ORPHAN:
@ -4877,6 +4888,8 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
}
update_old = true;
if (confirmed[0] == BLOCKS_ORPHAN)
userinfo_block(row, false);
break;
default:
LOGERR("%s(): %s.failed.invalid confirm='%s'",
@ -5131,6 +5144,12 @@ bool blocks_fill(PGconn *conn)
pool.workinfoid = row->workinfoid;
pool.height = row->height;
}
if (CURRENT(&(row->expirydate))) {
_userinfo_block(row, true, false);
if (row->confirmed[0] == BLOCKS_ORPHAN)
_userinfo_block(row, false, false);
}
}
if (!ok)
k_add_head(blocks_free, item);
@ -6461,6 +6480,8 @@ bool markersummary_fill(PGconn *conn)
markersummary_to_pool(p_row, row);
_userinfo_update(NULL, NULL, row, false, false);
tick();
}
if (!ok) {
@ -6469,6 +6490,7 @@ bool markersummary_fill(PGconn *conn)
}
p_n = markersummary_pool_store->count;
//K_WUNLOCK(markersummary_free);
PQclear(res);

Loading…
Cancel
Save