|
|
|
@ -319,17 +319,6 @@ char *_double_to_buf(double data, char *buf, size_t siz, WHERE_FFL_ARGS)
|
|
|
|
|
return _data_to_buf(TYPE_DOUBLE, (void *)(&data), buf, siz, WHERE_FFL_PASS); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: do this better ... :)
|
|
|
|
|
void dsp_hash(char *hash, char *buf, size_t siz) |
|
|
|
|
{ |
|
|
|
|
char *ptr; |
|
|
|
|
|
|
|
|
|
ptr = hash + strlen(hash) - (siz - 1) - 8; |
|
|
|
|
if (ptr < hash) |
|
|
|
|
ptr = hash; |
|
|
|
|
STRNCPYSIZ(buf, ptr, siz); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// For mutiple variable function calls that need the data
|
|
|
|
|
char *_transfer_data(K_ITEM *item, WHERE_FFL_ARGS) |
|
|
|
|
{ |
|
|
|
@ -574,6 +563,149 @@ K_ITEM *_find_create_workerstatus(int64_t userid, char *workername,
|
|
|
|
|
return item; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* All data is loaded, now update workerstatus fields
|
|
|
|
|
TODO: combine set_block_share_counters() with this? */ |
|
|
|
|
void workerstatus_ready() |
|
|
|
|
{ |
|
|
|
|
K_TREE_CTX ws_ctx[1], us_ctx[1], ss_ctx[1]; |
|
|
|
|
K_ITEM *ws_item, us_look, ss_look, *us_item, *ss_item; |
|
|
|
|
USERSTATS lookuserstats, *userstats; |
|
|
|
|
SHARESUMMARY looksharesummary, *sharesummary; |
|
|
|
|
WORKERSTATUS *workerstatus; |
|
|
|
|
|
|
|
|
|
INIT_USERSTATS(&us_look); |
|
|
|
|
INIT_SHARESUMMARY(&ss_look); |
|
|
|
|
ws_item = first_in_ktree(workerstatus_root, ws_ctx); |
|
|
|
|
while (ws_item) { |
|
|
|
|
DATA_WORKERSTATUS(workerstatus, ws_item); |
|
|
|
|
lookuserstats.userid = workerstatus->userid; |
|
|
|
|
STRNCPY(lookuserstats.workername, workerstatus->workername); |
|
|
|
|
lookuserstats.statsdate.tv_sec = date_eot.tv_sec; |
|
|
|
|
lookuserstats.statsdate.tv_usec = date_eot.tv_usec; |
|
|
|
|
us_look.data = (void *)(&lookuserstats); |
|
|
|
|
us_item = find_before_in_ktree(userstats_workerstatus_root, &us_look, |
|
|
|
|
cmp_userstats_workerstatus, us_ctx); |
|
|
|
|
if (us_item) { |
|
|
|
|
DATA_USERSTATS(userstats, us_item); |
|
|
|
|
if (userstats->idle) { |
|
|
|
|
if (tv_newer(&(workerstatus->last_idle), |
|
|
|
|
&(userstats->statsdate))) { |
|
|
|
|
copy_tv(&(workerstatus->last_idle), |
|
|
|
|
&(userstats->statsdate)); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (tv_newer(&(workerstatus->last_stats), |
|
|
|
|
&(userstats->statsdate))) { |
|
|
|
|
copy_tv(&(workerstatus->last_stats), |
|
|
|
|
&(userstats->statsdate)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
looksharesummary.userid = workerstatus->userid; |
|
|
|
|
STRNCPY(looksharesummary.workername, workerstatus->workername); |
|
|
|
|
looksharesummary.workinfoid = MAXID; |
|
|
|
|
ss_look.data = (void *)(&looksharesummary); |
|
|
|
|
K_RLOCK(sharesummary_free); |
|
|
|
|
ss_item = find_before_in_ktree(sharesummary_root, &ss_look, |
|
|
|
|
cmp_sharesummary, ss_ctx); |
|
|
|
|
K_RUNLOCK(sharesummary_free); |
|
|
|
|
if (ss_item) { |
|
|
|
|
DATA_SHARESUMMARY(sharesummary, ss_item); |
|
|
|
|
if (tv_newer(&(workerstatus->last_share), |
|
|
|
|
&(sharesummary->lastshare))) { |
|
|
|
|
copy_tv(&(workerstatus->last_share), |
|
|
|
|
&(sharesummary->lastshare)); |
|
|
|
|
workerstatus->last_diff = |
|
|
|
|
sharesummary->lastdiffacc; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ws_item = next_in_ktree(ws_ctx); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void _workerstatus_update(AUTHS *auths, SHARES *shares, |
|
|
|
|
USERSTATS *userstats, WHERE_FFL_ARGS) |
|
|
|
|
{ |
|
|
|
|
WORKERSTATUS *row; |
|
|
|
|
K_ITEM *item; |
|
|
|
|
|
|
|
|
|
if (auths) { |
|
|
|
|
item = find_workerstatus(auths->userid, auths->workername, |
|
|
|
|
file, func, line); |
|
|
|
|
if (item) { |
|
|
|
|
DATA_WORKERSTATUS(row, item); |
|
|
|
|
if (tv_newer(&(row->last_auth), &(auths->createdate))) |
|
|
|
|
copy_tv(&(row->last_auth), &(auths->createdate)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (startup_complete && shares) { |
|
|
|
|
if (shares->errn == SE_NONE) { |
|
|
|
|
pool.diffacc += shares->diff; |
|
|
|
|
pool.shareacc++; |
|
|
|
|
} else { |
|
|
|
|
pool.diffinv += shares->diff; |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
switch (shares->errn) { |
|
|
|
|
case SE_NONE: |
|
|
|
|
row->diffacc += shares->diff; |
|
|
|
|
row->shareacc++; |
|
|
|
|
break; |
|
|
|
|
case SE_STALE: |
|
|
|
|
row->diffinv += shares->diff; |
|
|
|
|
row->shareinv++; |
|
|
|
|
row->diffsta += shares->diff; |
|
|
|
|
row->sharesta++; |
|
|
|
|
break; |
|
|
|
|
case SE_DUPE: |
|
|
|
|
row->diffinv += shares->diff; |
|
|
|
|
row->shareinv++; |
|
|
|
|
row->diffdup += shares->diff; |
|
|
|
|
row->sharedup++; |
|
|
|
|
break; |
|
|
|
|
case SE_HIGH_DIFF: |
|
|
|
|
row->diffinv += shares->diff; |
|
|
|
|
row->shareinv++; |
|
|
|
|
row->diffhi += shares->diff; |
|
|
|
|
row->sharehi++; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
row->diffinv += shares->diff; |
|
|
|
|
row->shareinv++; |
|
|
|
|
row->diffrej += shares->diff; |
|
|
|
|
row->sharerej++; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (startup_complete && userstats) { |
|
|
|
|
item = find_workerstatus(userstats->userid, userstats->workername, |
|
|
|
|
file, func, line); |
|
|
|
|
if (item) { |
|
|
|
|
DATA_WORKERSTATUS(row, item); |
|
|
|
|
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)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// default tree order by username asc,expirydate desc
|
|
|
|
|
cmp_t cmp_users(K_ITEM *a, K_ITEM *b) |
|
|
|
|
{ |
|
|
|
@ -1310,6 +1442,22 @@ cmp_t cmp_sharesummary_workinfoid(K_ITEM *a, K_ITEM *b)
|
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void zero_sharesummary(SHARESUMMARY *row, tv_t *cd, double diff) |
|
|
|
|
{ |
|
|
|
|
row->diffacc = row->diffsta = row->diffdup = row->diffhi = |
|
|
|
|
row->diffrej = row->shareacc = row->sharesta = row->sharedup = |
|
|
|
|
row->sharehi = row->sharerej = 0.0; |
|
|
|
|
row->sharecount = row->errorcount = row->countlastupdate = 0; |
|
|
|
|
row->reset = false; |
|
|
|
|
row->firstshare.tv_sec = cd->tv_sec; |
|
|
|
|
row->firstshare.tv_usec = cd->tv_usec; |
|
|
|
|
row->lastshare.tv_sec = row->firstshare.tv_sec; |
|
|
|
|
row->lastshare.tv_usec = row->firstshare.tv_usec; |
|
|
|
|
row->lastdiffacc = diff; |
|
|
|
|
row->complete[0] = SUMMARY_NEW; |
|
|
|
|
row->complete[1] = '\0'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
K_ITEM *find_sharesummary(int64_t userid, char *workername, int64_t workinfoid) |
|
|
|
|
{ |
|
|
|
|
SHARESUMMARY sharesummary; |
|
|
|
@ -1325,6 +1473,162 @@ K_ITEM *find_sharesummary(int64_t userid, char *workername, int64_t workinfoid)
|
|
|
|
|
return find_in_ktree(sharesummary_root, &look, cmp_sharesummary, ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void auto_age_older(PGconn *conn, int64_t workinfoid, char *poolinstance, |
|
|
|
|
char *by, char *code, char *inet, tv_t *cd) |
|
|
|
|
{ |
|
|
|
|
static int64_t last_attempted_id = -1; |
|
|
|
|
static int64_t prev_found = 0; |
|
|
|
|
static int repeat; |
|
|
|
|
|
|
|
|
|
char min_buf[DATE_BUFSIZ], max_buf[DATE_BUFSIZ]; |
|
|
|
|
int64_t ss_count_tot, s_count_tot, s_diff_tot; |
|
|
|
|
int64_t ss_count, s_count, s_diff; |
|
|
|
|
tv_t ss_first_min, ss_last_max; |
|
|
|
|
tv_t ss_first, ss_last; |
|
|
|
|
int32_t wid_count; |
|
|
|
|
SHARESUMMARY looksharesummary, *sharesummary; |
|
|
|
|
K_TREE_CTX ctx[1]; |
|
|
|
|
K_ITEM look, *ss_item; |
|
|
|
|
int64_t age_id, do_id, to_id; |
|
|
|
|
bool ok, found; |
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): workinfoid=%"PRId64" prev=%"PRId64, __func__, workinfoid, prev_found); |
|
|
|
|
|
|
|
|
|
age_id = prev_found; |
|
|
|
|
|
|
|
|
|
// Find the oldest 'unaged' sharesummary < workinfoid and >= prev_found
|
|
|
|
|
looksharesummary.workinfoid = prev_found; |
|
|
|
|
looksharesummary.userid = -1; |
|
|
|
|
looksharesummary.workername[0] = '\0'; |
|
|
|
|
INIT_SHARESUMMARY(&look); |
|
|
|
|
look.data = (void *)(&looksharesummary); |
|
|
|
|
|
|
|
|
|
K_RLOCK(sharesummary_free); |
|
|
|
|
ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &look, |
|
|
|
|
cmp_sharesummary_workinfoid, ctx); |
|
|
|
|
DATA_SHARESUMMARY_NULL(sharesummary, ss_item); |
|
|
|
|
|
|
|
|
|
ss_first_min.tv_sec = ss_first_min.tv_usec = |
|
|
|
|
ss_last_max.tv_sec = ss_last_max.tv_usec = 0; |
|
|
|
|
ss_count_tot = s_count_tot = s_diff_tot = 0; |
|
|
|
|
|
|
|
|
|
found = false; |
|
|
|
|
while (ss_item && sharesummary->workinfoid < workinfoid) { |
|
|
|
|
if (sharesummary->complete[0] == SUMMARY_NEW) { |
|
|
|
|
age_id = sharesummary->workinfoid; |
|
|
|
|
prev_found = age_id; |
|
|
|
|
found = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
ss_item = next_in_ktree(ctx); |
|
|
|
|
DATA_SHARESUMMARY_NULL(sharesummary, ss_item); |
|
|
|
|
} |
|
|
|
|
K_RUNLOCK(sharesummary_free); |
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): age_id=%"PRId64" found=%d", __func__, age_id, found); |
|
|
|
|
// Don't repeat searching old items to avoid accessing their ram
|
|
|
|
|
if (!found) |
|
|
|
|
prev_found = workinfoid; |
|
|
|
|
else { |
|
|
|
|
/* Process all the consecutive sharesummaries that's aren't aged
|
|
|
|
|
* This way we find each oldest 'batch' of sharesummaries that have |
|
|
|
|
* been missed and can report the range of data that was aged, |
|
|
|
|
* which would normally just be an approx 10min set of workinfoids |
|
|
|
|
* from the last time ckpool stopped |
|
|
|
|
* Each next group of unaged sharesummaries following this, will be |
|
|
|
|
* picked up by each next aging */ |
|
|
|
|
wid_count = 0; |
|
|
|
|
do_id = age_id; |
|
|
|
|
to_id = 0; |
|
|
|
|
do { |
|
|
|
|
ok = workinfo_age(conn, do_id, poolinstance, |
|
|
|
|
by, code, inet, cd, |
|
|
|
|
&ss_first, &ss_last, |
|
|
|
|
&ss_count, &s_count, &s_diff); |
|
|
|
|
|
|
|
|
|
ss_count_tot += ss_count; |
|
|
|
|
s_count_tot += s_count; |
|
|
|
|
s_diff_tot += s_diff; |
|
|
|
|
if (ss_first_min.tv_sec == 0 || !tv_newer(&ss_first_min, &ss_first)) |
|
|
|
|
copy_tv(&ss_first_min, &ss_first); |
|
|
|
|
if (tv_newer(&ss_last_max, &ss_last)) |
|
|
|
|
copy_tv(&ss_last_max, &ss_last); |
|
|
|
|
|
|
|
|
|
if (!ok) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
to_id = do_id; |
|
|
|
|
wid_count++; |
|
|
|
|
K_RLOCK(sharesummary_free); |
|
|
|
|
while (ss_item && sharesummary->workinfoid == to_id) { |
|
|
|
|
ss_item = next_in_ktree(ctx); |
|
|
|
|
DATA_SHARESUMMARY_NULL(sharesummary, ss_item); |
|
|
|
|
} |
|
|
|
|
K_RUNLOCK(sharesummary_free); |
|
|
|
|
|
|
|
|
|
if (ss_item) { |
|
|
|
|
do_id = sharesummary->workinfoid; |
|
|
|
|
if (do_id >= workinfoid) |
|
|
|
|
break; |
|
|
|
|
if (sharesummary->complete[0] != SUMMARY_NEW) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} while (ss_item); |
|
|
|
|
if (to_id == 0) { |
|
|
|
|
if (last_attempted_id != age_id || ++repeat >= 10) { |
|
|
|
|
// Approx once every 5min since workinfo defaults to ~30s
|
|
|
|
|
LOGWARNING("%s() Auto-age failed to age %"PRId64, |
|
|
|
|
__func__, age_id); |
|
|
|
|
last_attempted_id = age_id; |
|
|
|
|
repeat = 0; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
char idrange[64]; |
|
|
|
|
char sharerange[256]; |
|
|
|
|
if (to_id != age_id) { |
|
|
|
|
snprintf(idrange, sizeof(idrange), |
|
|
|
|
"from %"PRId64" to %"PRId64, |
|
|
|
|
age_id, to_id); |
|
|
|
|
} else { |
|
|
|
|
snprintf(idrange, sizeof(idrange), |
|
|
|
|
"%"PRId64, age_id); |
|
|
|
|
} |
|
|
|
|
tv_to_buf(&ss_first_min, min_buf, sizeof(min_buf)); |
|
|
|
|
if (tv_equal(&ss_first_min, &ss_last_max)) { |
|
|
|
|
snprintf(sharerange, sizeof(sharerange), |
|
|
|
|
"share date %s", min_buf); |
|
|
|
|
} else { |
|
|
|
|
tv_to_buf(&ss_last_max, max_buf, sizeof(max_buf)); |
|
|
|
|
snprintf(sharerange, sizeof(sharerange), |
|
|
|
|
"share dates %s to %s", |
|
|
|
|
min_buf, max_buf); |
|
|
|
|
} |
|
|
|
|
LOGWARNING("%s() Auto-aged %"PRId64"(%"PRId64") " |
|
|
|
|
"share%s %d sharesummar%s %d workinfoid%s " |
|
|
|
|
"%s %s", |
|
|
|
|
__func__, |
|
|
|
|
s_count_tot, s_diff_tot, |
|
|
|
|
(s_count_tot == 1) ? "" : "s", |
|
|
|
|
ss_count_tot, |
|
|
|
|
(ss_count_tot == 1) ? "y" : "ies", |
|
|
|
|
wid_count, |
|
|
|
|
(wid_count == 1) ? "" : "s", |
|
|
|
|
idrange, sharerange); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: do this better ... :)
|
|
|
|
|
void dsp_hash(char *hash, char *buf, size_t siz) |
|
|
|
|
{ |
|
|
|
|
char *ptr; |
|
|
|
|
|
|
|
|
|
ptr = hash + strlen(hash) - (siz - 1) - 8; |
|
|
|
|
if (ptr < hash) |
|
|
|
|
ptr = hash; |
|
|
|
|
STRNCPYSIZ(buf, ptr, siz); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void dsp_blocks(K_ITEM *item, FILE *stream) |
|
|
|
|
{ |
|
|
|
|
char createdate_buf[DATE_BUFSIZ], expirydate_buf[DATE_BUFSIZ]; |
|
|
|
@ -1425,6 +1729,109 @@ const char *blocks_confirmed(char *confirmed)
|
|
|
|
|
return blocks_unknown; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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->diffsta = workerstatus->diffdup = |
|
|
|
|
workerstatus->diffhi = workerstatus->diffrej = |
|
|
|
|
workerstatus->shareacc = workerstatus->shareinv = |
|
|
|
|
workerstatus->sharesta = workerstatus->sharedup = |
|
|
|
|
workerstatus->sharehi = workerstatus->sharerej = 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 */ |
|
|
|
|
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 */ |
|
|
|
|
K_RLOCK(sharesummary_free); |
|
|
|
|
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 */ |
|
|
|
|
K_RUNLOCK(sharesummary_free); |
|
|
|
|
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__); |
|
|
|
|
} |
|
|
|
|
K_RLOCK(sharesummary_free); |
|
|
|
|
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->diffsta += sharesummary->diffsta; |
|
|
|
|
workerstatus->diffdup += sharesummary->diffdup; |
|
|
|
|
workerstatus->diffhi += sharesummary->diffhi; |
|
|
|
|
workerstatus->diffrej += sharesummary->diffrej; |
|
|
|
|
workerstatus->shareacc += sharesummary->shareacc; |
|
|
|
|
workerstatus->shareinv += sharesummary->sharesta + sharesummary->sharedup + |
|
|
|
|
sharesummary->sharehi + sharesummary->sharerej; |
|
|
|
|
workerstatus->sharesta += sharesummary->sharesta; |
|
|
|
|
workerstatus->sharedup += sharesummary->sharedup; |
|
|
|
|
workerstatus->sharehi += sharesummary->sharehi; |
|
|
|
|
workerstatus->sharerej += sharesummary->sharerej; |
|
|
|
|
|
|
|
|
|
ss_item = prev_in_ktree(ctx); |
|
|
|
|
} |
|
|
|
|
K_RUNLOCK(sharesummary_free); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* order by height asc,userid asc,expirydate asc
|
|
|
|
|
* i.e. only one payout amount per block per user */ |
|
|
|
|
cmp_t cmp_miningpayouts(K_ITEM *a, K_ITEM *b) |
|
|
|
@ -1561,3 +1968,30 @@ cmp_t cmp_userstats_workerstatus(K_ITEM *a, K_ITEM *b)
|
|
|
|
|
} |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool userstats_starttimeband(USERSTATS *row, tv_t *statsdate) |
|
|
|
|
{ |
|
|
|
|
char buf[DATE_BUFSIZ+1]; |
|
|
|
|
|
|
|
|
|
copy_tv(statsdate, &(row->statsdate)); |
|
|
|
|
// Start of this timeband
|
|
|
|
|
switch (row->summarylevel[0]) { |
|
|
|
|
case SUMMARY_DB: |
|
|
|
|
statsdate->tv_sec -= statsdate->tv_sec % USERSTATS_DB_S; |
|
|
|
|
statsdate->tv_usec = 0; |
|
|
|
|
break; |
|
|
|
|
case SUMMARY_FULL: |
|
|
|
|
statsdate->tv_sec -= statsdate->tv_sec % USERSTATS_DB_DS; |
|
|
|
|
statsdate->tv_usec = 0; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
tv_to_buf(statsdate, buf, sizeof(buf)); |
|
|
|
|
// Bad userstats are not fatal
|
|
|
|
|
LOGERR("Unknown userstats summarylevel 0x%02x '%c' " |
|
|
|
|
"userid %"PRId64" workername %s statsdate %s", |
|
|
|
|
row->summarylevel[0], row->summarylevel[0], |
|
|
|
|
row->userid, row->workername, buf); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|