Browse Source

Merge branch 'master' of bitbucket.org:ckolivas/ckpool

master
Con Kolivas 10 years ago
parent
commit
6427c10aa1
  1. 7
      pool/base.php
  2. 6
      pool/db.php
  3. 28
      pool/page_shifts.php
  4. 20
      pool/page_workers.php
  5. 189
      src/ckdb.c
  6. 30
      src/ckdb.h
  7. 103
      src/ckdb_cmd.c
  8. 6
      src/ckdb_crypt.c
  9. 240
      src/ckdb_data.c
  10. 336
      src/ckdb_dbio.c
  11. 453
      src/ktree.c
  12. 65
      src/ktree.h

7
pool/base.php

@ -126,9 +126,12 @@ function btcfmt($amt)
return number_format($amt, 8);
}
#
function utcd($when)
function utcd($when, $brief = false)
{
return gmdate('Y-m-d H:i:s+00', round($when));
if ($brief)
return gmdate('M-d H:i:s', round($when));
else
return gmdate('Y-m-d H:i:s+00', round($when));
}
#
global $sipre;

6
pool/db.php

@ -139,13 +139,15 @@ function msgEncode($cmd, $id, $fields, $user)
{
global $send_sep, $fld_sep, $val_sep;
$t = time() % 10000;
$now = time();
$t = $now % 10000;
$msg = $cmd . $send_sep . $id.$t . $send_sep;
foreach ($fields as $name => $value)
$msg .= $name . $val_sep . $value . $fld_sep;
$msg .= 'createcode' . $val_sep . 'php' . $fld_sep;
$msg .= 'createby' . $val_sep . $user . $fld_sep;
$msg .= 'createinet' . $val_sep . zeip();
$msg .= 'createinet' . $val_sep . zeip(). $fld_sep;
$msg .= 'webtime' . $val_sep . $now;
adm($user, $msg);
return $msg;
}

28
pool/page_shifts.php

@ -4,10 +4,11 @@ function doshifts($data, $user)
{
$ans = getShifts($user);
$pg = "<table callpadding=0 cellspacing=0 border=0>\n";
$pg = "Click <a href='#payoutmark'>here</a> to jump to the start of the last payout<br><br>";
$pg .= "<table callpadding=0 cellspacing=0 border=0>\n";
$pg .= "<tr class=title>";
$pg .= "<td class=dl>Shift</td>";
$pg .= "<td class=dl>Start</td>";
$pg .= "<td class=dl>Start UTC</td>";
$pg .= "<td class=dr>Length</td>";
$pg .= "<td class=dr>Your Diff</td>";
$pg .= "<td class=dr>Inv Diff</td>";
@ -15,6 +16,8 @@ function doshifts($data, $user)
$pg .= "<td class=dr>Shares</td>";
$pg .= "<td class=dr>Avg Share</td>";
$pg .= "<td class=dr>Rewards</td>";
$pg .= "<td class=dr>Rewarded<span class=st1>*</span></td>";
$pg .= "<td class=dr>PPS%</td>";
$pg .= "</tr>\n";
if (($ans['STATUS'] != 'ok') || !isset($ans['prefix_all']))
@ -28,9 +31,13 @@ function doshifts($data, $user)
for ($i = 0; $i < $count; $i++)
{
$u = '';
$mark = '';
if (isset($ans['lastpayoutstart:'.$i])
&& $ans['lastpayoutstart:'.$i] != '')
{
$u = 'u';
$mark = '<a name=payoutmark></a>';
}
if (($i % 2) == 0)
$row = "even$u";
else
@ -52,9 +59,9 @@ function doshifts($data, $user)
$btc = ' <img src=/BTCSym.png border=0>';
else
$btc = '';
$pg .= "<td class=dl>$shif$btc</td>";
$pg .= "<td class=dl>$shif$btc$mark</td>";
$start = $ans['start:'.$i];
$pg .= '<td class=dl>'.utcd($start).'</td>';
$pg .= '<td class=dl>'.utcd($start, true).'</td>';
$nd = $ans['end:'.$i];
$elapsed = $nd - $start;
$pg .= '<td class=dr>'.howmanyhrs($elapsed).'</td>';
@ -72,10 +79,23 @@ function doshifts($data, $user)
$avgsh = 0;
$pg .= '<td class=dr>'.number_format($avgsh, 2).'</td>';
$pg .= '<td class=dr>'.$ans['rewards:'.$i].'</td>';
$ppsr = (float)$ans['ppsrewarded:'.$i];
if ($ppsr > 0)
$ppsd = sprintf('%.5f', $ppsr);
else
$ppsd = '0';
$pg .= "<td class=dr>$ppsd</td>";
$ppsv = (float)$ans['ppsvalue:'.$i];
if ($ppsv > 0)
$pgot = number_format(100.0 * $ppsr / $ppsv, 2).'%';
else
$pgot = '?';
$pg .= "<td class=dr>$pgot</td>";
$pg .= "</tr>\n";
}
}
$pg .= "</table>\n";
$pg .= "<span class=st1>*</span> The Rewarded value unit is satoshis per 1diff share<br>";
return $pg;
}

20
pool/page_workers.php

@ -11,9 +11,10 @@ function worktitle($data, $user)
$pg .= '<td class=dr>Shares</td>';
$pg .= "<td class=dr><span class=nb><$r id=srtdiff data-sf=r4>:Diff</span></td>";
$pg .= "<td class=dr><span class=nb><$r id=srtshrate data-sf=r5>:Share Rate</span></td>";
$pg .= "<td class=dr><span class=nb><$r id=srtinv data-sf=r6>:Invalid</span></td>";
$pg .= '<td class=dr>&laquo;Elapsed</td>';
$pg .= "<td class=dr><span class=nb><$r id=srtinv data-sf=r7>:Invalid</span></td>";
$pg .= '<td class=dr>Block %</td>';
$pg .= "<td class=dr><span class=nb><$r id=srtrate data-sf=r8>:Hash</span> Rate</td>";
$pg .= "<td class=dr><span class=nb><$r id=srtrate data-sf=r9>:Hash</span> Rate</td>";
$pg .= "</tr>\n";
return $pg;
}
@ -46,9 +47,10 @@ function workuser($data, $user, &$offset, &$totshare, &$totdiff,
}
$all = array();
$count = $ans['rows'];
$now = $ans['STAMP'];
for ($i = 0; $i < $count; $i++)
{
$lst = $ans['STAMP'] - $ans['w_lastshare:'.$i];
$lst = $now - $ans['w_lastshare:'.$i];
if ($old !== false && $lst > $old)
continue;
@ -74,7 +76,7 @@ function workuser($data, $user, &$offset, &$totshare, &$totdiff,
for ($i = 0; $i < $count; $i++)
{
$lst = $ans['STAMP'] - $all[$i]['w_lastshare'];
$lst = $now - $all[$i]['w_lastshare'];
if ($old !== false && $lst > $old)
continue;
@ -105,9 +107,12 @@ function workuser($data, $user, &$offset, &$totshare, &$totdiff,
$acthr = '0';
$acthrv = 0;
$actstt = $all[$i]['w_active_start'];
if ($actstt > 0)
if ($actstt <= 0 || ($now - $actstt) < 0)
$actsin = '&nbsp;';
else
{
$elapsed = $ans['STAMP'] - $actstt;
$actsin = howmanyhrs($now - $actstt);
$elapsed = $now - $actstt;
if ($elapsed > 0)
{
$acthrv = $all[$i]['w_active_diffacc'] *
@ -117,6 +122,7 @@ function workuser($data, $user, &$offset, &$totshare, &$totdiff,
}
}
$pg .= "<td class=dr data-srt=$acthrv>$acthr</td>";
$pg .= "<td class=dr>$actsin</td>";
$dinv = $all[$i]['w_diffinv'];
$dtot = $dacc + $dinv;
@ -178,7 +184,7 @@ function worktotal($offset, $totshare, $totdiff, $totshrate, $totinvalid,
$pg .= "<td class=dr>$shareacc</td>";
$diffacc = number_format($totdiff, 0);
$pg .= "<td class=dr>$diffacc</td>";
$pg .= "<td class=dr>$totshrate</td>";
$pg .= "<td class=dr>$totshrate</td><td>&nbsp;</td>";
$dtot = $totdiff + $totinvalid;
if ($dtot > 0)
$rej = number_format(100.0 * $totinvalid / $dtot, 3);

189
src/ckdb.c

@ -497,17 +497,18 @@ K_TREE *userinfo_root;
K_LIST *userinfo_free;
K_STORE *userinfo_store;
static char logname[512];
static char logname_db[512];
static char logname_io[512];
static char *dbcode;
// low spec version of rotating_log() - no locking
static bool rotating_log_nolock(char *msg)
static bool rotating_log_nolock(char *msg, char *prefix)
{
char *filename;
FILE *fp;
bool ok = false;
filename = rotating_filename(logname, time(NULL));
filename = rotating_filename(prefix, time(NULL));
fp = fopen(filename, "a+e");
if (unlikely(!fp)) {
LOGERR("Failed to fopen %s in rotating_log!", filename);
@ -523,7 +524,7 @@ stageleft:
return ok;
}
static void log_queue_message(char *msg)
static void log_queue_message(char *msg, bool db)
{
K_ITEM *lq_item;
LOGQUEUE *lq;
@ -534,6 +535,7 @@ static void log_queue_message(char *msg)
lq->msg = strdup(msg);
if (!(lq->msg))
quithere(1, "malloc (%d) OOM", (int)strlen(msg));
lq->db = db;
k_add_tail(logqueue_store, lq_item);
K_WUNLOCK(logqueue_free);
}
@ -999,43 +1001,43 @@ static void alloc_storage()
users_free = k_new_list("Users", sizeof(USERS),
ALLOC_USERS, LIMIT_USERS, true);
users_store = k_new_store(users_free);
users_root = new_ktree();
userid_root = new_ktree();
users_root = new_ktree(cmp_users);
userid_root = new_ktree(cmp_userid);
useratts_free = k_new_list("Useratts", sizeof(USERATTS),
ALLOC_USERATTS, LIMIT_USERATTS, true);
useratts_store = k_new_store(useratts_free);
useratts_root = new_ktree();
useratts_root = new_ktree(cmp_useratts);
optioncontrol_free = k_new_list("OptionControl", sizeof(OPTIONCONTROL),
ALLOC_OPTIONCONTROL,
LIMIT_OPTIONCONTROL, true);
optioncontrol_store = k_new_store(optioncontrol_free);
optioncontrol_root = new_ktree();
optioncontrol_root = new_ktree(cmp_optioncontrol);
workers_free = k_new_list("Workers", sizeof(WORKERS),
ALLOC_WORKERS, LIMIT_WORKERS, true);
workers_store = k_new_store(workers_free);
workers_root = new_ktree();
workers_root = new_ktree(cmp_workers);
paymentaddresses_free = k_new_list("PaymentAddresses",
sizeof(PAYMENTADDRESSES),
ALLOC_PAYMENTADDRESSES,
LIMIT_PAYMENTADDRESSES, true);
paymentaddresses_store = k_new_store(paymentaddresses_free);
paymentaddresses_root = new_ktree();
paymentaddresses_create_root = new_ktree();
paymentaddresses_root = new_ktree(cmp_paymentaddresses);
paymentaddresses_create_root = new_ktree(cmp_payaddr_create);
paymentaddresses_free->dsp_func = dsp_paymentaddresses;
payments_free = k_new_list("Payments", sizeof(PAYMENTS),
ALLOC_PAYMENTS, LIMIT_PAYMENTS, true);
payments_store = k_new_store(payments_free);
payments_root = new_ktree();
payments_root = new_ktree(cmp_payments);
accountbalance_free = k_new_list("AccountBalance", sizeof(ACCOUNTBALANCE),
ALLOC_ACCOUNTBALANCE, LIMIT_ACCOUNTBALANCE, true);
accountbalance_store = k_new_store(accountbalance_free);
accountbalance_root = new_ktree();
accountbalance_root = new_ktree(cmp_accountbalance);
idcontrol_free = k_new_list("IDControl", sizeof(IDCONTROL),
ALLOC_IDCONTROL, LIMIT_IDCONTROL, true);
@ -1044,98 +1046,98 @@ static void alloc_storage()
workinfo_free = k_new_list("WorkInfo", sizeof(WORKINFO),
ALLOC_WORKINFO, LIMIT_WORKINFO, true);
workinfo_store = k_new_store(workinfo_free);
workinfo_root = new_ktree();
workinfo_root = new_ktree(cmp_workinfo);
if (!confirm_sharesummary)
workinfo_height_root = new_ktree();
workinfo_height_root = new_ktree(cmp_workinfo_height);
shares_free = k_new_list("Shares", sizeof(SHARES),
ALLOC_SHARES, LIMIT_SHARES, true);
shares_store = k_new_store(shares_free);
shares_early_store = k_new_store(shares_free);
shares_root = new_ktree();
shares_early_root = new_ktree();
shares_root = new_ktree(cmp_shares);
shares_early_root = new_ktree(cmp_shares);
shareerrors_free = k_new_list("ShareErrors", sizeof(SHAREERRORS),
ALLOC_SHAREERRORS, LIMIT_SHAREERRORS, true);
shareerrors_store = k_new_store(shareerrors_free);
shareerrors_early_store = k_new_store(shareerrors_free);
shareerrors_root = new_ktree();
shareerrors_early_root = new_ktree();
shareerrors_root = new_ktree(cmp_shareerrors);
shareerrors_early_root = new_ktree(cmp_shareerrors);
sharesummary_free = k_new_list("ShareSummary", sizeof(SHARESUMMARY),
ALLOC_SHARESUMMARY, LIMIT_SHARESUMMARY, true);
sharesummary_store = k_new_store(sharesummary_free);
sharesummary_root = new_ktree();
sharesummary_workinfoid_root = new_ktree();
sharesummary_root = new_ktree(cmp_sharesummary);
sharesummary_workinfoid_root = new_ktree(cmp_sharesummary_workinfoid);
sharesummary_free->dsp_func = dsp_sharesummary;
sharesummary_pool_store = k_new_store(sharesummary_free);
sharesummary_pool_root = new_ktree();
sharesummary_pool_root = new_ktree(cmp_sharesummary);
blocks_free = k_new_list("Blocks", sizeof(BLOCKS),
ALLOC_BLOCKS, LIMIT_BLOCKS, true);
blocks_store = k_new_store(blocks_free);
blocks_root = new_ktree();
blocks_root = new_ktree(cmp_blocks);
blocks_free->dsp_func = dsp_blocks;
miningpayouts_free = k_new_list("MiningPayouts", sizeof(MININGPAYOUTS),
ALLOC_MININGPAYOUTS, LIMIT_MININGPAYOUTS, true);
miningpayouts_store = k_new_store(miningpayouts_free);
miningpayouts_root = new_ktree();
miningpayouts_root = new_ktree(cmp_miningpayouts);
payouts_free = k_new_list("Payouts", sizeof(PAYOUTS),
ALLOC_PAYOUTS, LIMIT_PAYOUTS, true);
payouts_store = k_new_store(payouts_free);
payouts_root = new_ktree();
payouts_id_root = new_ktree();
payouts_wid_root = new_ktree();
payouts_root = new_ktree(cmp_payouts);
payouts_id_root = new_ktree(cmp_payouts_id);
payouts_wid_root = new_ktree(cmp_payouts_wid);
auths_free = k_new_list("Auths", sizeof(AUTHS),
ALLOC_AUTHS, LIMIT_AUTHS, true);
auths_store = k_new_store(auths_free);
auths_root = new_ktree();
auths_root = new_ktree(cmp_auths);
poolstats_free = k_new_list("PoolStats", sizeof(POOLSTATS),
ALLOC_POOLSTATS, LIMIT_POOLSTATS, true);
poolstats_store = k_new_store(poolstats_free);
poolstats_root = new_ktree();
poolstats_root = new_ktree(cmp_poolstats);
userstats_free = k_new_list("UserStats", sizeof(USERSTATS),
ALLOC_USERSTATS, LIMIT_USERSTATS, true);
userstats_store = k_new_store(userstats_free);
userstats_eos_store = k_new_store(userstats_free);
userstats_root = new_ktree();
userstats_root = new_ktree(cmp_userstats);
userstats_free->dsp_func = dsp_userstats;
workerstatus_free = k_new_list("WorkerStatus", sizeof(WORKERSTATUS),
ALLOC_WORKERSTATUS, LIMIT_WORKERSTATUS, true);
workerstatus_store = k_new_store(workerstatus_free);
workerstatus_root = new_ktree();
workerstatus_root = new_ktree(cmp_workerstatus);
markersummary_free = k_new_list("MarkerSummary", sizeof(MARKERSUMMARY),
ALLOC_MARKERSUMMARY, LIMIT_MARKERSUMMARY, true);
markersummary_store = k_new_store(markersummary_free);
markersummary_root = new_ktree();
markersummary_userid_root = new_ktree();
markersummary_root = new_ktree(cmp_markersummary);
markersummary_userid_root = new_ktree(cmp_markersummary_userid);
markersummary_free->dsp_func = dsp_markersummary;
markersummary_pool_store = k_new_store(markersummary_free);
markersummary_pool_root = new_ktree();
markersummary_pool_root = new_ktree(cmp_markersummary);
workmarkers_free = k_new_list("WorkMarkers", sizeof(WORKMARKERS),
ALLOC_WORKMARKERS, LIMIT_WORKMARKERS, true);
workmarkers_store = k_new_store(workmarkers_free);
workmarkers_root = new_ktree();
workmarkers_workinfoid_root = new_ktree();
workmarkers_root = new_ktree(cmp_workmarkers);
workmarkers_workinfoid_root = new_ktree(cmp_workmarkers_workinfoid);
workmarkers_free->dsp_func = dsp_workmarkers;
marks_free = k_new_list("Marks", sizeof(MARKS),
ALLOC_MARKS, LIMIT_MARKS, true);
marks_store = k_new_store(marks_free);
marks_root = new_ktree();
marks_root = new_ktree(cmp_marks);
userinfo_free = k_new_list("UserInfo", sizeof(USERINFO),
ALLOC_USERINFO, LIMIT_USERINFO, true);
userinfo_store = k_new_store(userinfo_free);
userinfo_root = new_ktree();
userinfo_root = new_ktree(cmp_userinfo);
}
#define SEQSETMSG(_set, _seqset, _msgtxt, _endtxt) do { \
@ -1179,7 +1181,7 @@ static void alloc_storage()
#define FREE_TREE(_tree) \
if (_tree ## _root) \
_tree ## _root = free_ktree(_tree ## _root, NULL) \
free_ktree(_tree ## _root, NULL) \
#define FREE_STORE(_list) \
if (_list ## _store) \
@ -1487,13 +1489,13 @@ static bool setup_data()
INIT_WORKINFO(&look);
look.data = (void *)(&wi);
// Find the first workinfo for this height
found = find_after_in_ktree(workinfo_height_root, &look, cmp_workinfo_height, ctx);
found = find_after_in_ktree(workinfo_height_root, &look, ctx);
if (found) {
DATA_WORKINFO(wif, found);
copy_tv(&last_bc, &(wif->createdate));
}
// No longer needed
workinfo_height_root = free_ktree(workinfo_height_root, NULL);
free_ktree(workinfo_height_root, NULL);
}
return true;
@ -2518,12 +2520,18 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now,
}
if (ckdb_cmds[msgline->which_cmds].cmd_val == CMD_END) {
LOGQUE(buf, false);
LOGERR("Listener received unknown command: '%.42s...",
st2 = safe_text(buf));
FREENULL(st2);
goto nogood;
}
if (ckdb_cmds[msgline->which_cmds].access & ACCESS_POOL)
LOGQUE(buf, true);
else
LOGQUE(buf, false);
if (noid) {
if (ckdb_cmds[msgline->which_cmds].noid) {
free(cmdptr);
@ -2536,7 +2544,7 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now,
goto nogood;
}
msgline->trf_root = new_ktree();
msgline->trf_root = new_ktree(cmp_transfer);
msgline->trf_store = k_new_store(transfer_free);
next = data;
if (next && strncmp(next, JSON_TRANSFER, JSON_TRANSFER_LEN) == 0) {
@ -2688,8 +2696,7 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now,
STRNCPYSIZ(transfer->svalue, next, siz+1);
transfer->mvalue = transfer->svalue;
}
msgline->trf_root = add_to_ktree(msgline->trf_root,
t_item, cmp_transfer);
add_to_ktree(msgline->trf_root, t_item);
k_add_head(msgline->trf_store, t_item);
t_item = NULL;
@ -2732,15 +2739,12 @@ static enum cmd_values breakdown(K_ITEM **ml_item, char *buf, tv_t *now,
transfer->mvalue = transfer->svalue;
// Discard duplicates
if (find_in_ktree(msgline->trf_root, t_item,
cmp_transfer, ctx)) {
if (find_in_ktree(msgline->trf_root, t_item, ctx)) {
if (transfer->mvalue != transfer->svalue)
FREENULL(transfer->mvalue);
k_add_head(transfer_free, t_item);
} else {
msgline->trf_root = add_to_ktree(msgline->trf_root,
t_item,
cmp_transfer);
add_to_ktree(msgline->trf_root, t_item);
k_add_head(msgline->trf_store, t_item);
}
}
@ -2935,7 +2939,7 @@ static void summarise_blocks()
K_RLOCK(markersummary_free);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look,
cmp_sharesummary_workinfoid, ss_ctx);
ss_ctx);
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
while (ss_item && sharesummary->workinfoid > wi_start) {
if (sharesummary->complete[0] == SUMMARY_NEW) {
@ -2971,7 +2975,7 @@ static void summarise_blocks()
INIT_WORKMARKERS(&wm_look);
wm_look.data = (void *)(&lookworkmarkers);
wm_item = find_before_in_ktree(workmarkers_workinfoid_root, &wm_look,
cmp_workmarkers_workinfoid, ctx);
ctx);
DATA_WORKMARKERS_NULL(workmarkers, wm_item);
while (wm_item &&
CURRENT(&(workmarkers->expirydate)) &&
@ -2995,7 +2999,7 @@ static void summarise_blocks()
INIT_MARKERSUMMARY(&ms_look);
ms_look.data = (void *)(&lookmarkersummary);
ms_item = find_before_in_ktree(markersummary_root, &ms_look,
cmp_markersummary, ms_ctx);
ms_ctx);
DATA_MARKERSUMMARY_NULL(markersummary, ms_item);
while (ms_item && markersummary->markerid == workmarkers->markerid) {
has_ms = true;
@ -3350,7 +3354,7 @@ static void make_a_shift_mark()
lookworkinfo.expirydate.tv_usec = default_expiry.tv_usec;
wi_look.data = (void *)(&lookworkinfo);
K_RLOCK(workinfo_free);
wi_item = find_after_in_ktree(workinfo_root, &wi_look, cmp_workinfo, wi_ctx);
wi_item = find_after_in_ktree(workinfo_root, &wi_look, wi_ctx);
K_RUNLOCK(workinfo_free);
marks_wid = 0;
used_wid = 0;
@ -3394,8 +3398,8 @@ static void make_a_shift_mark()
looksharesummary.workername = EMPTY;
ss_look.data = (void *)(&looksharesummary);
K_RLOCK(sharesummary_free);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look,
cmp_sharesummary_workinfoid, ss_ctx);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root,
&ss_look, ss_ctx);
K_RUNLOCK(sharesummary_free);
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
if (ss_item &&
@ -3618,7 +3622,8 @@ static void *logger(__maybe_unused void *arg)
setnow(&now);
snprintf(buf, sizeof(buf), "logstart.%ld,%ld",
now.tv_sec, now.tv_usec);
LOGFILE(buf);
LOGFILE(buf, logname_db);
LOGFILE(buf, logname_io);
while (!everyone_die) {
K_WLOCK(logqueue_free);
@ -3626,7 +3631,10 @@ static void *logger(__maybe_unused void *arg)
K_WUNLOCK(logqueue_free);
while (lq_item) {
DATA_LOGQUEUE(lq, lq_item);
LOGFILE(lq->msg);
if (lq->db)
LOGFILE(lq->msg, logname_db);
else
LOGFILE(lq->msg, logname_io);
FREENULL(lq->msg);
K_WLOCK(logqueue_free);
@ -3645,14 +3653,18 @@ static void *logger(__maybe_unused void *arg)
setnow(&now);
snprintf(buf, sizeof(buf), "logstopping.%d.%ld,%ld",
count, now.tv_sec, now.tv_usec);
LOGFILE(buf);
LOGFILE(buf, logname_db);
LOGFILE(buf, logname_io);
if (count)
LOGERR("%s", buf);
lq_item = logqueue_store->head;
copy_tv(&then, &now);
while (lq_item) {
DATA_LOGQUEUE(lq, lq_item);
LOGFILE(lq->msg);
if (lq->db)
LOGFILE(lq->msg, logname_db);
else
LOGFILE(lq->msg, logname_io);
FREENULL(lq->msg);
count--;
setnow(&now);
@ -3670,7 +3682,8 @@ static void *logger(__maybe_unused void *arg)
setnow(&now);
snprintf(buf, sizeof(buf), "logstop.%ld,%ld",
now.tv_sec, now.tv_usec);
LOGFILE(buf);
LOGFILE(buf, logname_db);
LOGFILE(buf, logname_io);
LOGWARNING("%s", buf);
return NULL;
@ -3691,8 +3704,7 @@ static void *socketer(__maybe_unused void *arg)
proc_instance_t *pi = (proc_instance_t *)arg;
unixsock_t *us = &pi->us;
char *end, *ans = NULL, *rep = NULL, *buf = NULL, *dot;
char *last_auth = NULL, *reply_auth = NULL;
char *last_addrauth = NULL, *reply_addrauth = NULL;
// No dup check for pool stats, the SEQ code will handle that
char *last_chkpass = NULL, *reply_chkpass = NULL;
char *last_adduser = NULL, *reply_adduser = NULL;
char *last_newpass = NULL, *reply_newpass = NULL;
@ -3772,10 +3784,7 @@ static void *socketer(__maybe_unused void *arg)
dup = false;
show_dup = true;
// These are ordered approximately most likely first
if (last_auth && strcmp(last_auth, buf) == 0) {
reply_last = reply_auth;
dup = true;
} else if (last_chkpass && strcmp(last_chkpass, buf) == 0) {
if (last_chkpass && strcmp(last_chkpass, buf) == 0) {
reply_last = reply_chkpass;
dup = true;
} else if (last_adduser && strcmp(last_adduser, buf) == 0) {
@ -3787,9 +3796,6 @@ static void *socketer(__maybe_unused void *arg)
} else if (last_newid && strcmp(last_newid, buf) == 0) {
reply_last = reply_newid;
dup = true;
} else if (last_addrauth && strcmp(last_addrauth, buf) == 0) {
reply_last = reply_addrauth;
dup = true;
} else if (last_userset && strcmp(last_userset, buf) == 0) {
reply_last = reply_userset;
dup = true;
@ -3818,7 +3824,8 @@ static void *socketer(__maybe_unused void *arg)
*dot = '\0';
snprintf(reply, sizeof(reply), "%s%ld,%ld.%s",
LOGDUP, now.tv_sec, now.tv_usec, duptype);
LOGQUE(reply);
// dup cant be pool
LOGQUE(reply, false);
if (show_dup)
LOGWARNING("Duplicate '%s' message received", duptype);
else
@ -3827,7 +3834,6 @@ static void *socketer(__maybe_unused void *arg)
int seqentryflags = SE_SOCKET;
if (!reload_queue_complete)
seqentryflags = SE_EARLYSOCK;
LOGQUE(buf);
cmdnum = breakdown(&ml_item, buf, &now, seqentryflags);
DATA_MSGLINE(msgline, ml_item);
replied = false;
@ -3960,12 +3966,6 @@ static void *socketer(__maybe_unused void *arg)
send_unix_msg(sockd, rep);
FREENULL(ans);
switch (cmdnum) {
case CMD_AUTH:
STORELASTREPLY(auth);
break;
case CMD_ADDRAUTH:
STORELASTREPLY(addrauth);
break;
case CMD_CHKPASS:
STORELASTREPLY(chkpass);
break;
@ -4237,7 +4237,6 @@ static void reload_line(PGconn *conn, char *filename, uint64_t count, char *buf)
__func__, count);
}
LOGQUE(buf);
// ml_item is set for all but CMD_REPLY
cmdnum = breakdown(&ml_item, buf, &now, SE_RELOAD);
DATA_MSGLINE(msgline, ml_item);
@ -4448,7 +4447,8 @@ static bool reload_from(tv_t *start)
copy_tv(&begin, &now);
tvs_to_buf(&now, run, sizeof(run));
snprintf(reload_buf, MAX_READ, "reload.%s.s0", run);
LOGQUE(reload_buf);
LOGQUE(reload_buf, true);
LOGQUE(reload_buf, false);
conn = dbconnect();
@ -4541,7 +4541,8 @@ static bool reload_from(tv_t *start)
diff = 1;
snprintf(reload_buf, MAX_READ, "reload.%s.%"PRIu64, run, total);
LOGQUE(reload_buf);
LOGQUE(reload_buf, true);
LOGQUE(reload_buf, false);
LOGWARNING("%s(): read %d file%s, total %"PRIu64" line%s %.2f/s",
__func__,
processing, processing == 1 ? "" : "s",
@ -4815,7 +4816,7 @@ static void compare_summaries(K_TREE *leftsum, char *leftname,
look.data = (void *)(&looksharesummary);
total = ok = missing = diff = 0;
lss = find_after_in_ktree(leftsum, &look, cmp_sharesummary_workinfoid, ctxl);
lss = find_after_in_ktree(leftsum, &look, ctxl);
while (lss) {
DATA_SHARESUMMARY(l_ss, lss);
if (l_ss->workinfoid > confirm_last_workinfoid)
@ -4827,7 +4828,7 @@ static void compare_summaries(K_TREE *leftsum, char *leftname,
first_used = l_ss->workinfoid;
last_used = l_ss->workinfoid;
rss = find_in_ktree(rightsum, lss, cmp_sharesummary_workinfoid, ctxr);
rss = find_in_ktree(rightsum, lss, ctxr);
DATA_SHARESUMMARY_NULL(r_ss, rss);
if (!rss) {
missing++;
@ -5036,7 +5037,7 @@ static void confirm_reload()
lookblocks.height = confirm_block;
lookblocks.blockhash[0] = '\0';
b_look.data = (void *)(&lookblocks);
b_end_item = find_after_in_ktree(blocks_root, &b_look, cmp_blocks, ctx);
b_end_item = find_after_in_ktree(blocks_root, &b_look, ctx);
if (!b_end_item) {
LOGWARNING("%s(): no DB block height found matching or after %d",
__func__, confirm_block);
@ -5049,7 +5050,7 @@ static void confirm_reload()
lookblocks.height = e_blocks->height;
lookblocks.blockhash[0] = '\0';
b_look.data = (void *)(&lookblocks);
b_begin_item = find_before_in_ktree(blocks_root, &b_look, cmp_blocks, ctx);
b_begin_item = find_before_in_ktree(blocks_root, &b_look, ctx);
if (!b_begin_item)
confirm_first_workinfoid = 0;
else {
@ -5058,7 +5059,7 @@ static void confirm_reload()
lookblocks.height = b_blocks->height;
lookblocks.blockhash[0] = '\0';
b_look.data = (void *)(&lookblocks);
b_begin_item = find_after_in_ktree(blocks_root, &b_look, cmp_blocks, ctx);
b_begin_item = find_after_in_ktree(blocks_root, &b_look, ctx);
// Not possible
if (!b_begin_item)
confirm_first_workinfoid = 0;
@ -5110,7 +5111,7 @@ static void confirm_reload()
lookworkinfo.expirydate.tv_sec = date_begin.tv_sec;
lookworkinfo.expirydate.tv_usec = date_begin.tv_usec;
wi_look.data = (void *)(&lookworkinfo);
wi_item = find_before_in_ktree(workinfo_root, &wi_look, cmp_workinfo, ctx);
wi_item = find_before_in_ktree(workinfo_root, &wi_look, ctx);
if (wi_item) {
DATA_WORKINFO(workinfo, wi_item);
copy_tv(&start, &(workinfo->createdate));
@ -5138,7 +5139,7 @@ static void confirm_reload()
lookworkinfo.expirydate.tv_sec = date_eot.tv_sec;
lookworkinfo.expirydate.tv_usec = date_eot.tv_usec;
wi_look.data = (void *)(&lookworkinfo);
wi_item = find_after_in_ktree(workinfo_root, &wi_look, cmp_workinfo, ctx);
wi_item = find_after_in_ktree(workinfo_root, &wi_look, ctx);
if (wi_item) {
DATA_WORKINFO(workinfo, wi_item);
/* Now find the one after the one we found to determine the
@ -5147,7 +5148,7 @@ static void confirm_reload()
lookworkinfo.expirydate.tv_sec = date_eot.tv_sec;
lookworkinfo.expirydate.tv_usec = date_eot.tv_usec;
wi_look.data = (void *)(&lookworkinfo);
wi_item = find_after_in_ktree(workinfo_root, &wi_look, cmp_workinfo, ctx);
wi_item = find_after_in_ktree(workinfo_root, &wi_look, ctx);
if (wi_item) {
DATA_WORKINFO(workinfo, wi_item);
copy_tv(&confirm_finish, &(workinfo->createdate));
@ -5178,9 +5179,9 @@ static void confirm_reload()
sharesummary_save = sharesummary_root;
workinfo_save = workinfo_root;
sharesummary_workinfoid_root = new_ktree();
sharesummary_root = new_ktree();
workinfo_root = new_ktree();
sharesummary_workinfoid_root = new_ktree(cmp_sharesummary_workinfoid);
sharesummary_root = new_ktree(cmp_sharesummary);
workinfo_root = new_ktree(cmp_workinfo);
if (start.tv_sec < DATE_BEGIN) {
start.tv_sec = DATE_BEGIN;
@ -5586,7 +5587,11 @@ int main(int argc, char **argv)
quit(1, "Failed to open log file %s", buf);
ckp.logfd = fileno(ckp.logfp);
snprintf(logname, sizeof(logname), "%s%s-db%s-",
// -db is ckpool messages
snprintf(logname_db, sizeof(logname_db), "%s%s-db%s-",
ckp.logdir, ckp.name, dbcode);
// -io is everything else
snprintf(logname_io, sizeof(logname_io), "%s%s-io%s-",
ckp.logdir, ckp.name, dbcode);
setnow(&now);

30
src/ckdb.h

@ -55,7 +55,7 @@
#define DB_VLOCK "1"
#define DB_VERSION "1.0.2"
#define CKDB_VERSION DB_VERSION"-1.241"
#define CKDB_VERSION DB_VERSION"-1.311"
#define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -438,8 +438,8 @@ enum cmd_values {
// CCLs are every ...
#define ROLL_S 3600
#define LOGQUE(_msg) log_queue_message(_msg)
#define LOGFILE(_msg) rotating_log_nolock(_msg)
#define LOGQUE(_msg, _db) log_queue_message(_msg, _db)
#define LOGFILE(_msg, _prefix) rotating_log_nolock(_msg, _prefix)
#define LOGDUP "dup."
// ***
@ -711,6 +711,7 @@ enum cmd_values {
// LOGQUEUE
typedef struct logqueue {
char *msg;
bool db;
} LOGQUEUE;
#define ALLOC_LOGQUEUE 1024
@ -1294,6 +1295,7 @@ typedef struct optioncontrol {
// Value it must default to (to work properly)
#define OPTIONCONTROL_HEIGHT 1
#define MAX_HEIGHT 999999999
// Test it here rather than obscuring the #define elsewhere
#if ((OPTIONCONTROL_HEIGHT+1) != START_POOL_HEIGHT)
@ -1346,6 +1348,13 @@ extern tv_t last_bc;
// current network diff
extern double current_ndiff;
// Offset in binary coinbase1 of the block number
#define BLOCKNUM_OFFSET 42
// Initial block reward (satoshi)
#define REWARD_BASE 5000000000.0
// How many blocks per halving
#define REWARD_HALVE 210000.0
// SHARES shares.id.json={...}
typedef struct shares {
int64_t workinfoid;
@ -2090,6 +2099,8 @@ extern void sequence_report(bool lock);
#define REWARDOVERRIDE "MinerReward"
#define PPSOVERRIDE "PPSValue"
// Data free functions (first)
#define FREE_ITEM(item) do { } while(0)
// TODO: make a macro for all other to use above macro
@ -2200,6 +2211,7 @@ extern K_ITEM *_find_create_workerstatus(int64_t userid, char *workername,
bool create, const char *file2,
const char *func2, const int line2,
WHERE_FFL_ARGS);
extern void zero_all_active(tv_t *when);
extern void workerstatus_ready();
#define workerstatus_update(_auths, _shares, _userstats) \
_workerstatus_update(_auths, _shares, _userstats, WHERE_FFL_HERE)
@ -2264,7 +2276,7 @@ extern K_ITEM *find_first_paypayid(int64_t userid, int64_t payoutid, K_TREE_CTX
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 K_ITEM *find_optioncontrol(char *optionname, const 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);
@ -2279,6 +2291,7 @@ extern bool workinfo_age(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, int64_t *s_count,
int64_t *s_diff);
extern double workinfo_pps(K_ITEM *w_item, int64_t workinfoid, bool lock);
extern cmp_t cmp_shares(K_ITEM *a, K_ITEM *b);
extern cmp_t cmp_shareerrors(K_ITEM *a, K_ITEM *b);
extern void dsp_sharesummary(K_ITEM *item, FILE *stream);
@ -2597,6 +2610,13 @@ extern bool check_db_version(PGconn *conn);
// *** ckdb_cmd.c
// ***
// TODO: limit access by having seperate sockets for each
#define ACCESS_POOL (1 << 0)
#define ACCESS_SYSTEM (1 << 1)
#define ACCESS_WEB (1 << 2)
#define ACCESS_PROXY (1 << 3)
#define ACCESS_CKDB (1 << 4)
struct CMDS {
enum cmd_values cmd_val;
char *cmd_str;
@ -2605,7 +2625,7 @@ struct CMDS {
char *(*func)(PGconn *, char *, char *, tv_t *, char *, char *,
char *, tv_t *, K_TREE *);
enum seq_num seq;
char *access;
int access;
};
extern struct CMDS ckdb_cmds[];

103
src/ckdb_cmd.c

@ -269,6 +269,7 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id,
__func__,
st = safe_text_nonull(users->username),
users->databits);
FREENULL(st);
goto dame;
}
@ -926,7 +927,7 @@ static char *cmd_poolstats_do(PGconn *conn, char *cmd, char *id, char *by,
row.createdate.tv_usec = date_eot.tv_usec;
INIT_POOLSTATS(&look);
look.data = (void *)(&row);
ps = find_before_in_ktree(poolstats_root, &look, cmp_poolstats, ctx);
ps = find_before_in_ktree(poolstats_root, &look, ctx);
if (!ps)
store = true;
else {
@ -1730,7 +1731,7 @@ static char *cmd_percent(char *cmd, char *id, tv_t *now, USERS *users)
lookworkers.workername[0] = '\0';
DATE_ZERO(&(lookworkers.expirydate));
w_look.data = (void *)(&lookworkers);
w_item = find_after_in_ktree(workers_root, &w_look, cmp_workers, w_ctx);
w_item = find_after_in_ktree(workers_root, &w_look, w_ctx);
DATA_WORKERS_NULL(workers, w_item);
while (w_item && workers->userid == users->userid) {
if (CURRENT(&(workers->expirydate))) {
@ -1991,7 +1992,7 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id,
lookworkers.workername[0] = '\0';
DATE_ZERO(&(lookworkers.expirydate));
w_look.data = (void *)(&lookworkers);
w_item = find_after_in_ktree(workers_root, &w_look, cmp_workers, w_ctx);
w_item = find_after_in_ktree(workers_root, &w_look, w_ctx);
DATA_WORKERS_NULL(workers, w_item);
rows = 0;
while (w_item && workers->userid == users->userid) {
@ -3285,7 +3286,7 @@ static char *cmd_homepage(__maybe_unused PGconn *conn, char *cmd, char *id,
INIT_USERSTATS(&look);
look.data = (void *)(&lookuserstats);
K_RLOCK(userstats_free);
us_item = find_before_in_ktree(userstats_root, &look, cmp_userstats, ctx);
us_item = find_before_in_ktree(userstats_root, &look, ctx);
DATA_USERSTATS_NULL(userstats, us_item);
while (us_item && userstats->userid == users->userid) {
if (tvdiff(now, &(userstats->statsdate)) < USERSTATS_PER_S) {
@ -4045,7 +4046,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
INIT_BLOCKS(&b_look);
b_look.data = (void *)(&lookblocks);
K_RLOCK(blocks_free);
b_item = find_before_in_ktree(blocks_root, &b_look, cmp_blocks, ctx);
b_item = find_before_in_ktree(blocks_root, &b_look, ctx);
if (!b_item) {
K_RUNLOCK(blocks_free);
snprintf(reply, siz, "ERR.no block height %d", height);
@ -4120,7 +4121,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
ss_count = wm_count = ms_count = 0;
mu_store = k_new_store(miningpayouts_free);
mu_root = new_ktree();
mu_root = new_ktree(cmp_mu);
looksharesummary.workinfoid = block_workinfoid;
looksharesummary.userid = MAXID;
@ -4130,8 +4131,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
K_RLOCK(sharesummary_free);
K_RLOCK(workmarkers_free);
K_RLOCK(markersummary_free);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look,
cmp_sharesummary_workinfoid, ctx);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root,
&ss_look, ctx);
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
if (ss_item)
end_workinfoid = sharesummary->workinfoid;
@ -4204,8 +4205,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
lookworkmarkers.workinfoidend = block_workinfoid + 1;
INIT_WORKMARKERS(&wm_look);
wm_look.data = (void *)(&lookworkmarkers);
wm_item = find_before_in_ktree(workmarkers_workinfoid_root, &wm_look,
cmp_workmarkers_workinfoid, wm_ctx);
wm_item = find_before_in_ktree(workmarkers_workinfoid_root,
&wm_look, wm_ctx);
DATA_WORKMARKERS_NULL(workmarkers, wm_item);
LOGDEBUG("%s(): workmarkers < %"PRId64, __func__, lookworkmarkers.workinfoidend);
while (total_diff < diff_want && wm_item && CURRENT(&(workmarkers->expirydate))) {
@ -4220,8 +4221,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
lookmarkersummary.workername = EMPTY;
INIT_MARKERSUMMARY(&ms_look);
ms_look.data = (void *)(&lookmarkersummary);
ms_item = find_before_in_ktree(markersummary_root, &ms_look,
cmp_markersummary, ms_ctx);
ms_item = find_before_in_ktree(markersummary_root,
&ms_look, ms_ctx);
DATA_MARKERSUMMARY_NULL(markersummary, ms_item);
// add the whole markerid
while (ms_item && markersummary->markerid == workmarkers->markerid) {
@ -4431,7 +4432,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
// So web can always verify it received all data
APPEND_REALLOC(buf, off, len, "pplns_last=1");
mu_root = free_ktree(mu_root, NULL);
free_ktree(mu_root, NULL);
K_WLOCK(mu_store);
k_list_transfer_to_head(mu_store, miningpayouts_free);
K_WUNLOCK(mu_store);
@ -4441,7 +4442,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
return buf;
shazbot:
mu_root = free_ktree(mu_root, NULL);
free_ktree(mu_root, NULL);
K_WLOCK(mu_store);
k_list_transfer_to_head(mu_store, miningpayouts_free);
K_WUNLOCK(mu_store);
@ -4494,7 +4496,7 @@ static char *cmd_pplns2(__maybe_unused PGconn *conn, char *cmd, char *id,
INIT_BLOCKS(&b_look);
b_look.data = (void *)(&lookblocks);
K_RLOCK(blocks_free);
b_item = find_after_in_ktree(blocks_root, &b_look, cmp_blocks, b_ctx);
b_item = find_after_in_ktree(blocks_root, &b_look, b_ctx);
K_RUNLOCK(blocks_free);
if (!b_item) {
K_RUNLOCK(blocks_free);
@ -5072,6 +5074,7 @@ typedef struct worker_match {
bool match;
size_t len;
bool used;
bool everused;
} WM;
static char *worker_offset(char *workername)
@ -5157,7 +5160,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
size_t siz = sizeof(reply);
char *select = NULL;
WM workm[SELECT_LIMIT+1];
char *buf, *work;
char *buf = NULL, *work, *st = NULL;
size_t len, off;
tv_t marker_end = { 0L, 0L };
int rows, want, i, where_all;
@ -5197,12 +5200,19 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
if (i_select)
select = strdup(transfer_data(i_select));
APPEND_REALLOC_INIT(buf, off, len);
snprintf(tmp, sizeof(tmp), " select='%s'",
select ? st = safe_text_nonull(select) : "null");
FREENULL(st);
APPEND_REALLOC(buf, off, len, tmp);
bzero(workm, sizeof(workm));
where_all = select_list(&(workm[0]), select);
// Nothing selected = all
if (workm[0].worker == NULL) {
where_all = 0;
workm[0].worker = WORKERS_ALL;
APPEND_REALLOC(buf, off, len, " no workers");
} else {
for (i = 0; workm[i].worker; i++) {
// N.B. len is only used if match is true
@ -5213,12 +5223,24 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
workm[i].match = true;
workm[i].len--;
}
snprintf(tmp, sizeof(tmp), " workm[%d]=%s,%s,%d",
i, st = safe_text_nonull(workm[i].worker),
workm[i].match ? "Y" : "N",
(int)(workm[i].len));
FREENULL(st);
APPEND_REALLOC(buf, off, len, tmp);
}
}
if (where_all >= 0)
workm[where_all].used = true;
snprintf(tmp, sizeof(tmp), " where_all=%d", where_all);
APPEND_REALLOC(buf, off, len, tmp);
LOGDEBUG("%s() user=%"PRId64"/%s' %s",
__func__, users->userid, users->username, buf+1);
FREENULL(buf);
APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok.");
INIT_MARKERSUMMARY(&ms_look);
@ -5257,8 +5279,8 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
markersummary.userid = users->userid;
markersummary.workername = EMPTY;
K_RLOCK(markersummary_free);
ms_item = find_after_in_ktree(markersummary_root, &ms_look,
cmp_markersummary, ms_ctx);
ms_item = find_after_in_ktree(markersummary_root,
&ms_look, ms_ctx);
DATA_MARKERSUMMARY_NULL(ms, ms_item);
while (ms_item && ms->markerid == wm->markerid &&
ms->userid == users->userid) {
@ -5268,6 +5290,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
(workm[want].match && strncmp(work, workm[want].worker, workm[want].len) == 0) ||
(!(workm[want].match) && strcmp(workm[want].worker, work) == 0)) {
workm[want].used = true;
workm[want].everused = true;
ms_add[want].diffacc += ms->diffacc;
ms_add[want].diffsta += ms->diffsta;
ms_add[want].diffdup += ms->diffdup;
@ -5382,6 +5405,16 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
rows, wm->rewards, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
// Use %.15e -> 16 non-leading-zero decimal places
snprintf(tmp, sizeof(tmp), "ppsvalue:%d=%.15f%c",
rows, wm->pps_value, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
// Use %.15e -> 16 non-leading-zero decimal places
snprintf(tmp, sizeof(tmp), "ppsrewarded:%d=%.15e%c",
rows, wm->rewarded, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "lastpayoutstart:%d=%s%c",
rows,
(wm->workinfoidstart ==
@ -5403,7 +5436,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
K_RUNLOCK(workmarkers_free);
for (i = 0; workm[i].worker; i++) {
if (workm[i].used) {
if (workm[i].everused) {
snprintf(tmp, sizeof(tmp),
"%d_worker=%s%s%c",
i, workm[i].worker,
@ -5430,13 +5463,14 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), "rows=%d%cflds=%s%c",
rows, FLDSEP,
"markerid,shift,start,end,rewards,"
"lastpayoutstart", FLDSEP);
"ppsvalue,ppsrewarded,lastpayoutstart",
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s", "Shifts");
APPEND_REALLOC(buf, off, len, tmp);
for (i = 0; workm[i].worker; i++) {
if (workm[i].used) {
if (workm[i].everused) {
snprintf(tmp, sizeof(tmp), ",Worker_%d", i);
APPEND_REALLOC(buf, off, len, tmp);
}
@ -5445,7 +5479,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), "%carp=", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
for (i = 0; workm[i].worker; i++) {
if (workm[i].used) {
if (workm[i].everused) {
snprintf(tmp, sizeof(tmp), ",%d_", i);
APPEND_REALLOC(buf, off, len, tmp);
}
@ -6379,13 +6413,6 @@ static char *cmd_btcset(__maybe_unused PGconn *conn, char *cmd, char *id,
return strdup(buf);
}
// TODO: limit access by having seperate sockets for each
#define ACCESS_POOL "p"
#define ACCESS_SYSTEM "s"
#define ACCESS_WEB "w"
#define ACCESS_PROXY "x"
#define ACCESS_CKDB "c"
/* The socket command format is as follows:
* Basic structure:
* cmd.ID.fld1=value1 FLDSEP fld2=value2 FLDSEP fld3=...
@ -6448,8 +6475,8 @@ static char *cmd_btcset(__maybe_unused PGconn *conn, char *cmd, char *id,
// cmd_val cmd_str noid createdate func seq access
struct CMDS ckdb_cmds[] = {
{ CMD_TERMINATE, "terminate", true, false, NULL, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_PING, "ping", true, false, NULL, SEQ_NONE, ACCESS_SYSTEM ACCESS_POOL ACCESS_WEB },
{ CMD_VERSION, "version", true, false, NULL, SEQ_NONE, ACCESS_SYSTEM ACCESS_POOL ACCESS_WEB },
{ CMD_PING, "ping", true, false, NULL, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ CMD_VERSION, "version", true, false, NULL, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ CMD_LOGLEVEL, "loglevel", true, false, NULL, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_FLUSH, "flush", true, false, NULL, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_SHARELOG, STR_WORKINFO, false, true, cmd_sharelog, SEQ_WORKINFO, ACCESS_POOL },
@ -6482,15 +6509,15 @@ struct CMDS ckdb_cmds[] = {
{ CMD_GETOPTS, "getopts", false, false, cmd_getopts, SEQ_NONE, ACCESS_WEB },
{ CMD_SETOPTS, "setopts", false, false, cmd_setopts, SEQ_NONE, ACCESS_WEB },
{ CMD_DSP, "dsp", false, false, cmd_dsp, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_STATS, "stats", true, false, cmd_stats, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_PPLNS, "pplns", false, false, cmd_pplns, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_PPLNS2, "pplns2", false, false, cmd_pplns2, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_STATS, "stats", true, false, cmd_stats, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ CMD_PPLNS, "pplns", false, false, cmd_pplns, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ CMD_PPLNS2, "pplns2", false, false, cmd_pplns2, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ CMD_PAYOUTS, "payouts", false, false, cmd_payouts, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_MPAYOUTS, "mpayouts", false, false, cmd_mpayouts, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_SHIFTS, "shifts", false, false, cmd_shifts, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_USERSTATUS,"userstatus", false, false, cmd_userstatus, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_MPAYOUTS, "mpayouts", false, false, cmd_mpayouts, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ CMD_SHIFTS, "shifts", false, false, cmd_shifts, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ CMD_USERSTATUS,"userstatus", false, false, cmd_userstatus, SEQ_NONE, ACCESS_SYSTEM | ACCESS_WEB },
{ 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_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_BTCSET, "btcset", false, false, cmd_btcset, SEQ_NONE, ACCESS_SYSTEM },

6
src/ckdb_crypt.c

@ -36,7 +36,7 @@ char *_tob32(USERS *users, unsigned char *bin, size_t len, char *name,
if (osiz != olen) {
LOGEMERG("%s() of '%s' data for '%s' invalid olen=%d != osiz=%d"
WHERE_FFL,
__func__, name, safe_text_nonull(users->username),
__func__, name, st = safe_text_nonull(users->username),
(int)olen, (int)osiz, WHERE_FFL_PASS);
FREENULL(st);
olen = osiz;
@ -59,8 +59,8 @@ char *_tob32(USERS *users, unsigned char *bin, size_t len, char *name,
"ch=%d, i=%d j=%d bits=%d bin=0x%s len=%d "
"olen=%d" WHERE_FFL,
__func__, name,
safe_text_nonull(users->username), ch, i, j,
bits, binstr, (int)len, (int)olen,
st = safe_text_nonull(users->username),
ch, i, j, bits, binstr, (int)len, (int)olen,
WHERE_FFL_PASS);
FREENULL(st);
FREENULL(binstr);

240
src/ckdb_data.c

@ -20,7 +20,7 @@ void free_msgline_data(K_ITEM *item, bool t_lock, bool t_cull)
DATA_MSGLINE(msgline, item);
if (msgline->trf_root)
msgline->trf_root = free_ktree(msgline->trf_root, NULL);
free_ktree(msgline->trf_root, NULL);
if (msgline->trf_store) {
t_item = msgline->trf_store->head;
while (t_item) {
@ -691,7 +691,7 @@ K_ITEM *find_transfer(K_TREE *trf_root, char *name)
STRNCPY(transfer.name, name);
INIT_TRANSFER(&look);
look.data = (void *)(&transfer);
return find_in_ktree(trf_root, &look, cmp_transfer, ctx);
return find_in_ktree(trf_root, &look, ctx);
}
K_ITEM *_optional_name(K_TREE *trf_root, char *name, int len, char *patt,
@ -827,7 +827,7 @@ K_ITEM *get_workerstatus(int64_t userid, char *workername)
INIT_WORKERSTATUS(&look);
look.data = (void *)(&workerstatus);
K_RLOCK(workerstatus_free);
find = find_in_ktree(workerstatus_root, &look, cmp_workerstatus, ctx);
find = find_in_ktree(workerstatus_root, &look, ctx);
K_RUNLOCK(workerstatus_free);
return find;
}
@ -876,7 +876,7 @@ K_ITEM *_find_create_workerstatus(int64_t userid, char *workername,
row->userid = userid;
STRNCPY(row->workername, workername);
workerstatus_root = add_to_ktree(workerstatus_root, ws_item, cmp_workerstatus);
add_to_ktree(workerstatus_root, ws_item);
k_add_head(workerstatus_store, ws_item);
K_WUNLOCK(workerstatus_free);
@ -913,6 +913,23 @@ static void zero_on_idle(tv_t *when, WORKERSTATUS *workerstatus)
workerstatus->active_sharehi = workerstatus->active_sharerej = 0.0;
}
void zero_all_active(tv_t *when)
{
WORKERSTATUS *workerstatus;
K_TREE_CTX ws_ctx[1];
K_ITEM *ws_item;
K_WLOCK(workerstatus_free);
ws_item = first_in_ktree(workerstatus_root, ws_ctx);
while (ws_item) {
DATA_WORKERSTATUS(workerstatus, ws_item);
zero_on_idle(when, workerstatus);
ws_item = next_in_ktree(ws_ctx);
}
K_WUNLOCK(workerstatus_free);
}
/* All data is loaded, now update workerstatus fields
TODO: combine set_block_share_counters() with this? */
void workerstatus_ready()
@ -1115,7 +1132,7 @@ K_ITEM *find_users(char *username)
INIT_USERS(&look);
look.data = (void *)(&users);
return find_in_ktree(users_root, &look, cmp_users, ctx);
return find_in_ktree(users_root, &look, ctx);
}
// Must be R or W locked before call
@ -1131,7 +1148,7 @@ K_ITEM *find_userid(int64_t userid)
INIT_USERS(&look);
look.data = (void *)(&users);
return find_in_ktree(userid_root, &look, cmp_userid, ctx);
return find_in_ktree(userid_root, &look, ctx);
}
// TODO: endian? (to avoid being all zeros?)
@ -1428,7 +1445,7 @@ K_ITEM *find_useratts(int64_t userid, char *attname)
INIT_USERATTS(&look);
look.data = (void *)(&useratts);
return find_in_ktree(useratts_root, &look, cmp_useratts, ctx);
return find_in_ktree(useratts_root, &look, ctx);
}
// order by userid asc,workername asc,expirydate desc
@ -1459,7 +1476,7 @@ K_ITEM *find_workers(int64_t userid, char *workername)
INIT_WORKERS(&look);
look.data = (void *)(&workers);
return find_in_ktree(workers_root, &look, cmp_workers, ctx);
return find_in_ktree(workers_root, &look, ctx);
}
K_ITEM *first_workers(int64_t userid, K_TREE_CTX *ctx)
@ -1478,7 +1495,7 @@ K_ITEM *first_workers(int64_t userid, K_TREE_CTX *ctx)
INIT_WORKERS(&look);
look.data = (void *)(&workers);
// Caller needs to check userid/expirydate if the result != NULL
return find_after_in_ktree(workers_root, &look, cmp_workers, ctx);
return find_after_in_ktree(workers_root, &look, ctx);
}
K_ITEM *new_worker(PGconn *conn, bool update, int64_t userid, char *workername,
@ -1607,7 +1624,7 @@ K_ITEM *find_paymentaddresses(int64_t userid, K_TREE_CTX *ctx)
INIT_PAYMENTADDRESSES(&look);
look.data = (void *)(&paymentaddresses);
item = find_before_in_ktree(paymentaddresses_root, &look, cmp_paymentaddresses, ctx);
item = find_before_in_ktree(paymentaddresses_root, &look, ctx);
if (item) {
DATA_PAYMENTADDRESSES(pa, item);
if (pa->userid == userid && CURRENT(&(pa->expirydate)))
@ -1631,8 +1648,7 @@ K_ITEM *find_paymentaddresses_create(int64_t userid, K_TREE_CTX *ctx)
INIT_PAYMENTADDRESSES(&look);
look.data = (void *)(&paymentaddresses);
item = find_after_in_ktree(paymentaddresses_create_root, &look,
cmp_payaddr_create, ctx);
item = find_after_in_ktree(paymentaddresses_create_root, &look, ctx);
if (item) {
DATA_PAYMENTADDRESSES(pa, item);
if (pa->userid == userid)
@ -1655,7 +1671,7 @@ K_ITEM *find_one_payaddress(int64_t userid, char *payaddress, K_TREE_CTX *ctx)
INIT_PAYMENTADDRESSES(&look);
look.data = (void *)(&paymentaddresses);
return find_in_ktree(paymentaddresses_root, &look, cmp_paymentaddresses, ctx);
return find_in_ktree(paymentaddresses_root, &look, ctx);
}
/* This will match any user that has the payaddress
@ -1715,7 +1731,7 @@ K_ITEM *find_payments(int64_t payoutid, int64_t userid, char *subname)
INIT_PAYMENTS(&look);
look.data = (void *)(&payments);
return find_in_ktree(payments_root, &look, cmp_payments, ctx);
return find_in_ktree(payments_root, &look, ctx);
}
K_ITEM *find_first_payments(int64_t userid, K_TREE_CTX *ctx)
@ -1733,7 +1749,7 @@ K_ITEM *find_first_payments(int64_t userid, K_TREE_CTX *ctx)
INIT_PAYMENTS(&look);
look.data = (void *)(&payments);
// userid needs to be checked if item returned != NULL
item = find_after_in_ktree(payments_root, &look, cmp_payments, ctx);
item = find_after_in_ktree(payments_root, &look, ctx);
return item;
}
@ -1753,7 +1769,7 @@ K_ITEM *find_first_paypayid(int64_t userid, int64_t payoutid, K_TREE_CTX *ctx)
INIT_PAYMENTS(&look);
look.data = (void *)(&payments);
// userid+payoutid needs to be checked if item returned != NULL
item = find_after_in_ktree(payments_root, &look, cmp_payments, ctx);
item = find_after_in_ktree(payments_root, &look, ctx);
return item;
}
@ -1777,7 +1793,7 @@ K_ITEM *find_accountbalance(int64_t userid)
INIT_ACCOUNTBALANCE(&look);
look.data = (void *)(&accountbalance);
K_RLOCK(accountbalance_free);
item = find_in_ktree(accountbalance_root, &look, cmp_accountbalance, ctx);
item = find_in_ktree(accountbalance_root, &look, ctx);
K_RUNLOCK(accountbalance_free);
return item;
}
@ -1823,7 +1839,7 @@ static bool _reward_override_name(int32_t height, char *buf, size_t siz,
}
// Must be R or W locked before call
K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height)
K_ITEM *find_optioncontrol(char *optionname, const tv_t *now, int32_t height)
{
OPTIONCONTROL optioncontrol, *oc, *ocbest;
K_TREE_CTX ctx[1];
@ -1833,6 +1849,9 @@ K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height)
* 1) activationdate is <= now
* and
* 2) height <= specified height (pool.height = current)
* The logic being: if 'now' is after the record activation date
* and 'height' is after the record activation height then
* the record is active
* Remember the active record with the newest activationdate
* If two records have the same activation date, then
* remember the active record with the highest height
@ -1853,7 +1872,7 @@ K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height)
INIT_OPTIONCONTROL(&look);
look.data = (void *)(&optioncontrol);
item = find_after_in_ktree(optioncontrol_root, &look, cmp_optioncontrol, ctx);
item = find_after_in_ktree(optioncontrol_root, &look, ctx);
ocbest = NULL;
best = NULL;
while (item) {
@ -1989,7 +2008,7 @@ K_ITEM *find_workinfo(int64_t workinfoid, K_TREE_CTX *ctx)
INIT_WORKINFO(&look);
look.data = (void *)(&workinfo);
K_RLOCK(workinfo_free);
item = find_in_ktree(workinfo_root, &look, cmp_workinfo, ctx);
item = find_in_ktree(workinfo_root, &look, ctx);
K_RUNLOCK(workinfo_free);
return item;
}
@ -2010,7 +2029,7 @@ K_ITEM *next_workinfo(int64_t workinfoid, K_TREE_CTX *ctx)
INIT_WORKINFO(&look);
look.data = (void *)(&workinfo);
K_RLOCK(workinfo_free);
item = find_after_in_ktree(workinfo_root, &look, cmp_workinfo, ctx);
item = find_after_in_ktree(workinfo_root, &look, ctx);
if (item) {
DATA_WORKINFO(wi, item);
while (item && !CURRENT(&(wi->expirydate))) {
@ -2091,7 +2110,7 @@ bool workinfo_age(int64_t workinfoid, char *poolinstance, char *by, char *code,
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);
ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &ss_look, ss_ctx);
K_RUNLOCK(sharesummary_free);
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
while (ss_item && sharesummary->workinfoid == workinfoid) {
@ -2142,7 +2161,7 @@ bool workinfo_age(int64_t workinfoid, char *poolinstance, char *by, char *code,
s_look.data = (void *)(&lookshares);
K_WLOCK(shares_free);
s_item = find_after_in_ktree(shares_root, &s_look, cmp_shares, s_ctx);
s_item = find_after_in_ktree(shares_root, &s_look, s_ctx);
while (s_item) {
DATA_SHARES(shares, s_item);
if (shares->workinfoid != workinfoid ||
@ -2154,7 +2173,7 @@ bool workinfo_age(int64_t workinfoid, char *poolinstance, char *by, char *code,
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);
remove_from_ktree(shares_root, s_item);
k_unlink_item(shares_store, s_item);
if (reloading && skipupdate)
shares_dumped++;
@ -2198,6 +2217,61 @@ bye:
return ok;
}
// The PPS value of a 1diff share for the given workinfoid
double workinfo_pps(K_ITEM *w_item, int64_t workinfoid, bool lock)
{
OPTIONCONTROL *optioncontrol;
K_ITEM *oc_item;
char oc_name[TXT_SML+1];
char coinbase1bin[TXT_SML+1];
char ndiffbin[TXT_SML+1];
WORKINFO *workinfo;
double w_diff;
int w_blocknum;
size_t len;
// Allow optioncontrol override for a given workinfoid
snprintf(oc_name, sizeof(oc_name), PPSOVERRIDE"_%"PRId64, workinfoid);
if (lock)
K_RLOCK(optioncontrol_free);
// No time/height control is used, just find the latest record
oc_item = find_optioncontrol(oc_name, &date_eot, MAX_HEIGHT);
if (lock)
K_RUNLOCK(optioncontrol_free);
// Value is a floating point double of satoshi
if (oc_item) {
DATA_OPTIONCONTROL(optioncontrol, oc_item);
return atof(optioncontrol->optionvalue);
}
if (!w_item) {
LOGERR("%s(): missing workinfo %"PRId64,
__func__, workinfoid);
return 0.0;
}
DATA_WORKINFO(workinfo, w_item);
len = strlen(workinfo->coinbase1);
if (len < (BLOCKNUM_OFFSET * 2 + 4) || (len & 1)) {
LOGERR("%s(): Invalid coinbase1 len %d - "
"should be >= %d and even - for wid %"PRId64,
__func__, (int)len, (BLOCKNUM_OFFSET * 2 + 4),
workinfoid);
return 0.0;
}
hex2bin(ndiffbin, workinfo->bits, 4);
w_diff = diff_from_nbits(ndiffbin);
hex2bin(coinbase1bin, workinfo->coinbase1 + (BLOCKNUM_OFFSET * 2),
(len - (BLOCKNUM_OFFSET * 2)) >> 1);
w_blocknum = get_sernumber((uchar *)coinbase1bin);
// BASE halving to determine coinbase reward then divided by difficulty
return(REWARD_BASE * pow(0.5, floor((double)w_blocknum / REWARD_HALVE)) / w_diff);
}
// order by workinfoid asc,userid asc,workername asc,createdate asc,nonce asc,expirydate desc
cmp_t cmp_shares(K_ITEM *a, K_ITEM *b)
{
@ -2317,13 +2391,10 @@ K_ITEM *_find_sharesummary(int64_t userid, char *workername, int64_t workinfoid,
INIT_SHARESUMMARY(&look);
look.data = (void *)(&sharesummary);
if (pool) {
return find_in_ktree(sharesummary_pool_root, &look,
cmp_sharesummary, ctx);
} else {
return find_in_ktree(sharesummary_root, &look,
cmp_sharesummary, ctx);
}
if (pool)
return find_in_ktree(sharesummary_pool_root, &look, ctx);
else
return find_in_ktree(sharesummary_root, &look, ctx);
}
K_ITEM *find_last_sharesummary(int64_t userid, char *workername)
@ -2338,7 +2409,7 @@ K_ITEM *find_last_sharesummary(int64_t userid, char *workername)
INIT_SHARESUMMARY(&look);
look.data = (void *)(&look_sharesummary);
item = find_before_in_ktree(sharesummary_root, &look, cmp_sharesummary, ctx);
item = find_before_in_ktree(sharesummary_root, &look, ctx);
if (item) {
DATA_SHARESUMMARY(sharesummary, item);
if (sharesummary->userid != userid ||
@ -2381,8 +2452,7 @@ void auto_age_older(int64_t workinfoid, char *poolinstance, char *by,
look.data = (void *)(&looksharesummary);
K_RLOCK(sharesummary_free);
ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &look,
cmp_sharesummary_workinfoid, ctx);
ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &look, ctx);
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
DATE_ZERO(&ss_first_min);
@ -2613,7 +2683,7 @@ K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx)
INIT_BLOCKS(&look);
look.data = (void *)(&blocks);
return find_in_ktree(blocks_root, &look, cmp_blocks, ctx);
return find_in_ktree(blocks_root, &look, ctx);
}
// Must be R or W locked before call
@ -2632,7 +2702,7 @@ K_ITEM *find_prev_blocks(int32_t height)
INIT_BLOCKS(&look);
look.data = (void *)(&lookblocks);
b_item = find_before_in_ktree(blocks_root, &look, cmp_blocks, ctx);
b_item = find_before_in_ktree(blocks_root, &look, ctx);
while (b_item) {
DATA_BLOCKS(blocks, b_item);
if (blocks->confirmed[0] != BLOCKS_NEW &&
@ -2716,8 +2786,8 @@ void set_block_share_counters()
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);
ss_item = find_before_in_ktree(sharesummary_root,
&ss_look, ctx);
continue;
}
@ -2800,7 +2870,8 @@ void set_block_share_counters()
lookmarkersummary.userid = MAXID;
lookmarkersummary.workername = EMPTY;
ms_look.data = (void *)(&lookmarkersummary);
ms_item = find_before_in_ktree(markersummary_root, &ms_look, cmp_markersummary, ctx_ms);
ms_item = find_before_in_ktree(markersummary_root,
&ms_look, ctx_ms);
while (ms_item) {
DATA_MARKERSUMMARY(markersummary, ms_item);
if (markersummary->markerid != workmarkers->markerid)
@ -3067,7 +3138,7 @@ bool _set_prevcreatedate(int32_t oldest_height, WHERE_FFL_ARGS)
INIT_BLOCKS(&look);
look.data = (void *)(&lookblocks);
b_item = find_before_in_ktree(blocks_root, &look, cmp_blocks, b_ctx);
b_item = find_before_in_ktree(blocks_root, &look, b_ctx);
while (b_item) {
DATA_BLOCKS(blocks, b_item);
if (CURRENT(&(blocks->expirydate)) &&
@ -3194,7 +3265,7 @@ K_ITEM *find_miningpayouts(int64_t payoutid, int64_t userid)
INIT_MININGPAYOUTS(&look);
look.data = (void *)(&miningpayouts);
return find_in_ktree(miningpayouts_root, &look, cmp_miningpayouts, ctx);
return find_in_ktree(miningpayouts_root, &look, ctx);
}
K_ITEM *first_miningpayouts(int64_t payoutid, K_TREE_CTX *ctx)
@ -3212,7 +3283,7 @@ K_ITEM *first_miningpayouts(int64_t payoutid, K_TREE_CTX *ctx)
INIT_MININGPAYOUTS(&look);
look.data = (void *)(&miningpayouts);
return find_after_in_ktree(miningpayouts_root, &look, cmp_miningpayouts, ctx);
return find_after_in_ktree(miningpayouts_root, &look, ctx);
}
/* Processing payouts uses it's own tree of miningpayouts keyed only on userid
@ -3240,7 +3311,7 @@ K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid,
INIT_MININGPAYOUTS(&look);
look.data = (void *)(&lookminingpayouts);
// No locking required since it's not a shared tree or store
mu_item = find_in_ktree(mu_root, &look, cmp_mu, ctx);
mu_item = find_in_ktree(mu_root, &look, ctx);
if (mu_item) {
DATA_MININGPAYOUTS(miningpayouts, mu_item);
miningpayouts->diffacc += diffacc;
@ -3250,7 +3321,7 @@ K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid,
DATA_MININGPAYOUTS(miningpayouts, mu_item);
miningpayouts->userid = userid;
miningpayouts->diffacc = diffacc;
mu_root = add_to_ktree(mu_root, mu_item, cmp_mu);
add_to_ktree(mu_root, mu_item);
k_add_head(mu_store, mu_item);
K_WUNLOCK(mu_store);
}
@ -3314,7 +3385,7 @@ K_ITEM *find_payouts(int32_t height, char *blockhash)
INIT_PAYOUTS(&look);
look.data = (void *)(&payouts);
return find_in_ktree(payouts_root, &look, cmp_payouts, ctx);
return find_in_ktree(payouts_root, &look, ctx);
}
// Last block payout calculated
@ -3346,7 +3417,7 @@ K_ITEM *find_payoutid(int64_t payoutid)
INIT_PAYOUTS(&look);
look.data = (void *)(&payouts);
return find_in_ktree(payouts_id_root, &look, cmp_payouts_id, ctx);
return find_in_ktree(payouts_id_root, &look, ctx);
}
// First payouts workinfoidend equal or before workinfoidend
@ -3364,7 +3435,7 @@ K_ITEM *find_payouts_wid(int64_t workinfoidend, K_TREE_CTX *ctx)
INIT_PAYOUTS(&look);
look.data = (void *)(&payouts);
return find_before_in_ktree(payouts_wid_root, &look, cmp_payouts_wid, ctx);
return find_before_in_ktree(payouts_wid_root, &look, ctx);
}
/* Values from payout stats, returns -1 if statname isn't found
@ -3603,7 +3674,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
ss_count = wm_count = ms_count = 0;
mu_store = k_new_store(miningpayouts_free);
mu_root = new_ktree();
mu_root = new_ktree(cmp_mu);
looksharesummary.workinfoid = blocks->workinfoid;
looksharesummary.userid = MAXID;
@ -3614,7 +3685,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
K_RLOCK(workmarkers_free);
K_RLOCK(markersummary_free);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look,
cmp_sharesummary_workinfoid, ss_ctx);
ss_ctx);
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
if (ss_item)
end_workinfoid = sharesummary->workinfoid;
@ -3713,8 +3784,8 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
lookworkmarkers.workinfoidend = blocks->workinfoid + 1;
INIT_WORKMARKERS(&wm_look);
wm_look.data = (void *)(&lookworkmarkers);
wm_item = find_before_in_ktree(workmarkers_workinfoid_root, &wm_look,
cmp_workmarkers_workinfoid, wm_ctx);
wm_item = find_before_in_ktree(workmarkers_workinfoid_root,
&wm_look, wm_ctx);
DATA_WORKMARKERS_NULL(workmarkers, wm_item);
LOGDEBUG("%s(): workmarkers < %"PRId64, __func__, lookworkmarkers.workinfoidend);
while (total_diff < diff_want && wm_item && CURRENT(&(workmarkers->expirydate))) {
@ -3729,8 +3800,8 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
lookmarkersummary.workername = EMPTY;
INIT_MARKERSUMMARY(&ms_look);
ms_look.data = (void *)(&lookmarkersummary);
ms_item = find_before_in_ktree(markersummary_root, &ms_look,
cmp_markersummary, ms_ctx);
ms_item = find_before_in_ktree(markersummary_root,
&ms_look, ms_ctx);
DATA_MARKERSUMMARY_NULL(markersummary, ms_item);
// add the whole markerid
while (ms_item && markersummary->markerid == workmarkers->markerid) {
@ -4053,7 +4124,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
payouts_add_ram(true, p_item, old_p_item, &now);
mu_root = free_ktree(mu_root, NULL);
free_ktree(mu_root, NULL);
mu_item = k_unlink_head(mu_store);
while (mu_item) {
DATA_MININGPAYOUTS(miningpayouts, mu_item);
@ -4144,7 +4215,7 @@ oku:
;
ck_wunlock(&process_pplns_lock);
if (mu_root)
mu_root = free_ktree(mu_root, NULL);
free_ktree(mu_root, NULL);
if (mu_store) {
if (mu_store->count) {
K_WLOCK(mu_store);
@ -4245,7 +4316,7 @@ K_ITEM *find_userstats(int64_t userid, char *workername)
INIT_USERSTATS(&look);
look.data = (void *)(&userstats);
return find_in_ktree(userstats_root, &look, cmp_userstats, ctx);
return find_in_ktree(userstats_root, &look, ctx);
}
void dsp_markersummary(K_ITEM *item, FILE *stream)
@ -4312,7 +4383,7 @@ K_ITEM *find_markersummary_userid(int64_t userid, char *workername,
INIT_MARKERSUMMARY(&look);
look.data = (void *)(&markersummary);
ms_item = find_before_in_ktree(markersummary_userid_root, &look, cmp_markersummary_userid, ctx);
ms_item = find_before_in_ktree(markersummary_userid_root, &look, ctx);
if (ms_item) {
DATA_MARKERSUMMARY(ms, ms_item);
if (ms->userid != userid || strcmp(ms->workername, workername))
@ -4349,11 +4420,11 @@ K_ITEM *_find_markersummary(int64_t markerid, int64_t workinfoid,
INIT_MARKERSUMMARY(&look);
look.data = (void *)(&markersummary);
if (pool) {
ms_item = find_in_ktree(markersummary_pool_root, &look,
cmp_markersummary, ctx);
ms_item = find_in_ktree(markersummary_pool_root,
&look, ctx);
} else {
ms_item = find_in_ktree(markersummary_root, &look,
cmp_markersummary, ctx);
ms_item = find_in_ktree(markersummary_root,
&look, ctx);
}
}
@ -4476,7 +4547,7 @@ K_ITEM *find_workmarkers(int64_t workinfoid, bool anystatus, char status, K_TREE
INIT_WORKMARKERS(&look);
look.data = (void *)(&workmarkers);
wm_item = find_after_in_ktree(workmarkers_workinfoid_root, &look, cmp_workmarkers_workinfoid, ctx);
wm_item = find_after_in_ktree(workmarkers_workinfoid_root, &look, ctx);
if (wm_item) {
DATA_WORKMARKERS(wm, wm_item);
if (!CURRENT(&(wm->expirydate)) ||
@ -4500,7 +4571,7 @@ K_ITEM *find_workmarkerid(int64_t markerid, bool anystatus, char status)
INIT_WORKMARKERS(&look);
look.data = (void *)(&workmarkers);
wm_item = find_in_ktree(workmarkers_root, &look, cmp_workmarkers, ctx);
wm_item = find_in_ktree(workmarkers_root, &look, ctx);
if (wm_item) {
DATA_WORKMARKERS(wm, wm_item);
if (!CURRENT(&(wm->expirydate)) ||
@ -4530,8 +4601,7 @@ static bool gen_workmarkers(PGconn *conn, MARKS *stt, bool after, MARKS *fin,
look.data = (void *)(&workinfo);
K_RLOCK(workinfo_free);
if (after) {
wi_stt_item = find_after_in_ktree(workinfo_root, &look,
cmp_workinfo, ctx);
wi_stt_item = find_after_in_ktree(workinfo_root, &look, ctx);
while (wi_stt_item) {
DATA_WORKINFO(wi_stt, wi_stt_item);
if (CURRENT(&(wi_stt->expirydate)))
@ -4539,8 +4609,7 @@ static bool gen_workmarkers(PGconn *conn, MARKS *stt, bool after, MARKS *fin,
wi_stt_item = next_in_ktree(ctx);
}
} else {
wi_stt_item = find_in_ktree(workinfo_root, &look,
cmp_workinfo, ctx);
wi_stt_item = find_in_ktree(workinfo_root, &look, ctx);
DATA_WORKINFO_NULL(wi_stt, wi_stt_item);
}
K_RUNLOCK(workinfo_free);
@ -4556,8 +4625,7 @@ static bool gen_workmarkers(PGconn *conn, MARKS *stt, bool after, MARKS *fin,
K_RLOCK(workinfo_free);
if (before) {
DATE_ZERO(&(workinfo.expirydate));
wi_fin_item = find_before_in_ktree(workinfo_root, &look,
cmp_workinfo, ctx);
wi_fin_item = find_before_in_ktree(workinfo_root, &look, ctx);
while (wi_fin_item) {
DATA_WORKINFO(wi_fin, wi_fin_item);
if (CURRENT(&(wi_fin->expirydate)))
@ -4567,8 +4635,7 @@ static bool gen_workmarkers(PGconn *conn, MARKS *stt, bool after, MARKS *fin,
} else {
workinfo.expirydate.tv_sec = default_expiry.tv_sec;
workinfo.expirydate.tv_usec = default_expiry.tv_usec;
wi_fin_item = find_in_ktree(workinfo_root, &look,
cmp_workinfo, ctx);
wi_fin_item = find_in_ktree(workinfo_root, &look, ctx);
DATA_WORKINFO_NULL(wi_fin, wi_fin_item);
}
K_RUNLOCK(workinfo_free);
@ -4647,7 +4714,7 @@ bool workmarkers_generate(PGconn *conn, char *err, size_t siz, char *by,
INIT_MARKS(&look);
look.data = (void *)(&marks);
K_RLOCK(marks_free);
m_item = find_before_in_ktree(marks_root, &look, cmp_marks, ctx);
m_item = find_before_in_ktree(marks_root, &look, ctx);
while (m_item) {
DATA_MARKS(mused, m_item);
if (CURRENT(&(mused->expirydate)) && MUSED(mused->status))
@ -4775,6 +4842,10 @@ bool reward_shifts(PAYOUTS *payouts, bool lock, int delta)
K_ITEM *wm_item;
WORKMARKERS *wm;
bool did_one = false;
double payout_pps;
payout_pps = (double)delta * (double)(payouts->minerreward) /
payouts->diffused;
if (lock)
K_WLOCK(workmarkers_free);
@ -4789,6 +4860,7 @@ bool reward_shifts(PAYOUTS *payouts, bool lock, int delta)
* onto the PROCESSED status if it isn't already processed */
if (CURRENT(&(wm->expirydate))) {
wm->rewards += delta;
wm->rewarded += payout_pps;
did_one = true;
}
wm_item = next_in_ktree(ctx);
@ -4800,7 +4872,15 @@ bool reward_shifts(PAYOUTS *payouts, bool lock, int delta)
return did_one;
}
// (re)calculate rewards for a shift
/* (re)calculate rewards for a shift
* N.B. we don't need to zero/undo a workmarkers rewards directly
* since this is just a counter of how many times it's been rewarded
* and thus if the shift is expired the counter is ignored
* We only need to (re)calculate it when the workmarker is created
* Payouts code processing will increment/decrement all current rewards as
* needed with reward_shifts() when payouts are added/changed/removed,
* however, the last shift in a payout can be created after the payout
* is generated so we need to update all from the payouts */
bool shift_rewards(K_ITEM *wm_item)
{
PAYOUTS *payouts = NULL;
@ -4808,6 +4888,7 @@ bool shift_rewards(K_ITEM *wm_item)
WORKMARKERS *wm;
K_ITEM *p_item;
int rewards = 0;
double pps = 0.0;
DATA_WORKMARKERS(wm, wm_item);
@ -4818,14 +4899,19 @@ bool shift_rewards(K_ITEM *wm_item)
// a workmarker should not cross a payout boundary
while (p_item && payouts->workinfoidstart <= wm->workinfoidstart &&
wm->workinfoidend <= payouts->workinfoidend) {
if (CURRENT(&(payouts->expirydate)))
if (CURRENT(&(payouts->expirydate))) {
rewards++;
pps += (double)(payouts->minerreward) /
payouts->diffused;
}
p_item = prev_in_ktree(ctx);
DATA_PAYOUTS_NULL(payouts, p_item);
}
K_RUNLOCK(payouts_free);
wm->rewards = rewards;
wm->rewarded = pps;
return (rewards > 0);
}
@ -4854,7 +4940,7 @@ K_ITEM *find_marks(int64_t workinfoid)
INIT_MARKS(&look);
look.data = (void *)(&marks);
return find_in_ktree(marks_root, &look, cmp_marks, ctx);
return find_in_ktree(marks_root, &look, ctx);
}
const char *marks_marktype(char *marktype)
@ -5026,7 +5112,7 @@ K_ITEM *_get_userinfo(int64_t userid, bool lock)
look.data = (void *)(&userinfo);
if (lock)
K_RLOCK(userinfo_free);
find = find_in_ktree(userinfo_root, &look, cmp_userinfo, ctx);
find = find_in_ktree(userinfo_root, &look, ctx);
if (lock)
K_RUNLOCK(userinfo_free);
return find;
@ -5059,7 +5145,7 @@ K_ITEM *_find_create_userinfo(int64_t userid, bool lock, WHERE_FFL_ARGS)
else
bigint_to_buf(userid, row->username, sizeof(row->username));
userinfo_root = add_to_ktree(userinfo_root, ui_item, cmp_userinfo);
add_to_ktree(userinfo_root, ui_item);
k_add_head(userinfo_store, ui_item);
if (lock)
K_WUNLOCK(userinfo_free);

336
src/ckdb_dbio.c

@ -513,14 +513,14 @@ unparam:
free_users_data(item);
k_add_head(users_free, item);
} else {
users_root = remove_from_ktree(users_root, u_item, cmp_users);
userid_root = remove_from_ktree(userid_root, u_item, cmp_userid);
remove_from_ktree(users_root, u_item);
remove_from_ktree(userid_root, u_item);
copy_tv(&(users->expirydate), cd);
users_root = add_to_ktree(users_root, u_item, cmp_users);
userid_root = add_to_ktree(userid_root, u_item, cmp_userid);
add_to_ktree(users_root, u_item);
add_to_ktree(userid_root, u_item);
users_root = add_to_ktree(users_root, item, cmp_users);
userid_root = add_to_ktree(userid_root, item, cmp_userid);
add_to_ktree(users_root, item);
add_to_ktree(userid_root, item);
k_add_head(users_store, item);
}
K_WUNLOCK(users_free);
@ -648,8 +648,8 @@ unitem:
free_users_data(item);
k_add_head(users_free, item);
} else {
users_root = add_to_ktree(users_root, item, cmp_users);
userid_root = add_to_ktree(userid_root, item, cmp_userid);
add_to_ktree(users_root, item);
add_to_ktree(userid_root, item);
k_add_head(users_store, item);
}
K_WUNLOCK(users_free);
@ -760,14 +760,14 @@ unparam:
free_users_data(u_item);
k_add_head(users_free, u_item);
} else {
users_root = remove_from_ktree(users_root, old_u_item, cmp_users);
userid_root = remove_from_ktree(userid_root, old_u_item, cmp_userid);
remove_from_ktree(users_root, old_u_item);
remove_from_ktree(userid_root, old_u_item);
copy_tv(&(old_users->expirydate), cd);
users_root = add_to_ktree(users_root, old_u_item, cmp_users);
userid_root = add_to_ktree(userid_root, old_u_item, cmp_userid);
add_to_ktree(users_root, old_u_item);
add_to_ktree(userid_root, old_u_item);
users_root = add_to_ktree(users_root, u_item, cmp_users);
userid_root = add_to_ktree(userid_root, u_item, cmp_userid);
add_to_ktree(users_root, u_item);
add_to_ktree(userid_root, u_item);
k_add_head(users_store, u_item);
}
K_WUNLOCK(users_free);
@ -883,8 +883,8 @@ bool users_fill(PGconn *conn)
username_trim(row);
users_root = add_to_ktree(users_root, item, cmp_users);
userid_root = add_to_ktree(userid_root, item, cmp_userid);
add_to_ktree(users_root, item);
add_to_ktree(userid_root, item);
k_add_head(users_store, item);
}
if (!ok) {
@ -1011,11 +1011,11 @@ unparam:
if (ok) {
// Update it
if (old_item) {
useratts_root = remove_from_ktree(useratts_root, old_item, cmp_useratts);
remove_from_ktree(useratts_root, old_item);
copy_tv(&(old_useratts->expirydate), cd);
useratts_root = add_to_ktree(useratts_root, old_item, cmp_useratts);
add_to_ktree(useratts_root, old_item);
}
useratts_root = add_to_ktree(useratts_root, ua_item, cmp_useratts);
add_to_ktree(useratts_root, ua_item);
k_add_head(useratts_store, ua_item);
}
K_WUNLOCK(useratts_free);
@ -1162,9 +1162,9 @@ unparam:
K_WLOCK(useratts_free);
if (ok && item) {
useratts_root = remove_from_ktree(useratts_root, item, cmp_useratts);
remove_from_ktree(useratts_root, item);
copy_tv(&(useratts->expirydate), cd);
useratts_root = add_to_ktree(useratts_root, item, cmp_useratts);
add_to_ktree(useratts_root, item);
}
K_WUNLOCK(useratts_free);
@ -1269,7 +1269,7 @@ bool useratts_fill(PGconn *conn)
if (!ok)
break;
useratts_root = add_to_ktree(useratts_root, item, cmp_useratts);
add_to_ktree(useratts_root, item);
k_add_head(useratts_store, item);
}
if (!ok)
@ -1400,7 +1400,7 @@ unitem:
if (!ret)
k_add_head(workers_free, item);
else {
workers_root = add_to_ktree(workers_root, item, cmp_workers);
add_to_ktree(workers_root, item);
k_add_head(workers_store, item);
// Ensure there is a matching workerstatus
find_create_workerstatus(userid, workername,
@ -1639,7 +1639,7 @@ bool workers_fill(PGconn *conn)
break;
TXT_TO_BIGINT("workerid", field, row->workerid);
workers_root = add_to_ktree(workers_root, item, cmp_workers);
add_to_ktree(workers_root, item);
k_add_head(workers_store, item);
/* Make sure a workerstatus exists for each worker
@ -1869,15 +1869,11 @@ unparam:
else {
// It wasn't a match, thus it was expired
n++;
paymentaddresses_root = remove_from_ktree(paymentaddresses_root, item,
cmp_paymentaddresses);
paymentaddresses_create_root = remove_from_ktree(paymentaddresses_create_root,
item, cmp_payaddr_create);
remove_from_ktree(paymentaddresses_root, item);
remove_from_ktree(paymentaddresses_create_root, item);
copy_tv(&(row->expirydate), cd);
paymentaddresses_root = add_to_ktree(paymentaddresses_root, item,
cmp_paymentaddresses);
paymentaddresses_create_root = add_to_ktree(paymentaddresses_create_root,
item, cmp_payaddr_create);
add_to_ktree(paymentaddresses_root, item);
add_to_ktree(paymentaddresses_create_root, item);
}
item = prev;
DATA_PAYMENTADDRESSES_NULL(row, item);
@ -1889,10 +1885,8 @@ unparam:
next = match->next;
DATA_PAYMENTADDRESSES(pa, match);
if (!pa->match) {
paymentaddresses_root = add_to_ktree(paymentaddresses_root, match,
cmp_paymentaddresses);
paymentaddresses_create_root = add_to_ktree(paymentaddresses_create_root,
match, cmp_payaddr_create);
add_to_ktree(paymentaddresses_root, match);
add_to_ktree(paymentaddresses_create_root, match);
k_unlink_item(pa_store, match);
k_add_head(paymentaddresses_store, match);
count++;
@ -1981,10 +1975,8 @@ bool paymentaddresses_fill(PGconn *conn)
if (!ok)
break;
paymentaddresses_root = add_to_ktree(paymentaddresses_root, item,
cmp_paymentaddresses);
paymentaddresses_create_root = add_to_ktree(paymentaddresses_create_root,
item, cmp_payaddr_create);
add_to_ktree(paymentaddresses_root, item);
add_to_ktree(paymentaddresses_create_root, item);
k_add_head(paymentaddresses_store, item);
}
if (!ok)
@ -2015,11 +2007,11 @@ void payments_add_ram(bool ok, K_ITEM *p_item, K_ITEM *old_p_item, tv_t *cd)
} else {
if (old_p_item) {
DATA_PAYMENTS(oldp, old_p_item);
payments_root = remove_from_ktree(payments_root, old_p_item, cmp_payments);
remove_from_ktree(payments_root, old_p_item);
copy_tv(&(oldp->expirydate), cd);
payments_root = add_to_ktree(payments_root, old_p_item, cmp_payments);
add_to_ktree(payments_root, old_p_item);
}
payments_root = add_to_ktree(payments_root, p_item, cmp_payments);
add_to_ktree(payments_root, p_item);
k_add_head(payments_store, p_item);
}
K_WUNLOCK(payments_free);
@ -2252,7 +2244,7 @@ bool payments_fill(PGconn *conn)
if (!ok)
break;
payments_root = add_to_ktree(payments_root, item, cmp_payments);
add_to_ktree(payments_root, item);
k_add_head(payments_store, item);
}
if (!ok)
@ -2358,7 +2350,7 @@ K_ITEM *optioncontrol_item_add(PGconn *conn, K_ITEM *oc_item, tv_t *cd, bool beg
INIT_OPTIONCONTROL(&look);
look.data = (void *)row;
K_RLOCK(optioncontrol_free);
old_item = find_in_ktree(optioncontrol_root, &look, cmp_optioncontrol, ctx);
old_item = find_in_ktree(optioncontrol_root, &look, ctx);
K_RUNLOCK(optioncontrol_free);
if (!conn) {
@ -2446,13 +2438,12 @@ nostart:
} else {
// Discard old
if (old_item) {
optioncontrol_root = remove_from_ktree(optioncontrol_root, old_item,
cmp_optioncontrol);
remove_from_ktree(optioncontrol_root, old_item);
k_unlink_item(optioncontrol_store, old_item);
free_optioncontrol_data(old_item);
k_add_head(optioncontrol_free, old_item);
}
optioncontrol_root = add_to_ktree(optioncontrol_root, oc_item, cmp_optioncontrol);
add_to_ktree(optioncontrol_root, oc_item);
k_add_head(optioncontrol_store, oc_item);
if (strcmp(row->optionname, SWITCH_STATE_NAME) == 0) {
switch_state = atoi(row->optionvalue);
@ -2584,7 +2575,7 @@ bool optioncontrol_fill(PGconn *conn)
if (!ok)
break;
optioncontrol_root = add_to_ktree(optioncontrol_root, item, cmp_optioncontrol);
add_to_ktree(optioncontrol_root, item);
k_add_head(optioncontrol_store, item);
// There should only be one CURRENT version of switch_state
@ -2632,6 +2623,7 @@ int64_t workinfo_add(PGconn *conn, char *workinfoidstr, char *poolinstance,
char *ins;
char *params[11 + HISTORYDATECOUNT];
int n, par = 0;
bool zero_active = false;
LOGDEBUG("%s(): add", __func__);
@ -2659,7 +2651,7 @@ int64_t workinfo_add(PGconn *conn, char *workinfoidstr, char *poolinstance,
HISTORYDATETRANSFER(trf_root, row);
K_WLOCK(workinfo_free);
if (find_in_ktree(workinfo_root, item, cmp_workinfo, ctx)) {
if (find_in_ktree(workinfo_root, item, ctx)) {
workinfoid = row->workinfoid;
free_workinfo_data(item);
k_add_head(workinfo_free, item);
@ -2732,21 +2724,26 @@ unparam:
hex2bin(ndiffbin, row->bits, 4);
current_ndiff = diff_from_nbits(ndiffbin);
workinfo_root = add_to_ktree(workinfo_root, item, cmp_workinfo);
add_to_ktree(workinfo_root, item);
k_add_head(workinfo_store, item);
// Remember the bc = 'cd' when the height changes
if (workinfo_current) {
WORKINFO *wic;
DATA_WORKINFO(wic, workinfo_current);
if (cmp_height(wic->coinbase1, row->coinbase1) != 0)
if (cmp_height(wic->coinbase1, row->coinbase1) != 0) {
copy_tv(&last_bc, cd);
zero_active = true;
}
}
workinfo_current = item;
}
K_WUNLOCK(workinfo_free);
if (zero_active)
zero_all_active(cd);
return workinfoid;
}
@ -2900,9 +2897,9 @@ bool workinfo_fill(PGconn *conn)
if (!ok)
break;
workinfo_root = add_to_ktree(workinfo_root, item, cmp_workinfo);
add_to_ktree(workinfo_root, item);
if (!confirm_sharesummary)
workinfo_height_root = add_to_ktree(workinfo_height_root, item, cmp_workinfo_height);
add_to_ktree(workinfo_height_root, item);
k_add_head(workinfo_store, item);
if (tv_newer(&(dbstatus.newest_createdate_workinfo), &(row->createdate))) {
@ -3027,9 +3024,7 @@ static void shares_process_early(PGconn *conn, int64_t good_wid, tv_t *good_cd,
}
es_item = last_in_ktree(shares_early_root, ctx);
if (es_item) {
shares_early_root = remove_from_ktree(shares_early_root,
es_item,
cmp_shares);
remove_from_ktree(shares_early_root, es_item);
k_unlink_item(shares_early_store, es_item);
}
K_WUNLOCK(shares_free);
@ -3078,7 +3073,7 @@ static void shares_process_early(PGconn *conn, int64_t good_wid, tv_t *good_cd,
return;
redo:
K_WLOCK(shares_free);
shares_early_root = add_to_ktree(shares_early_root, es_item, cmp_shares);
add_to_ktree(shares_early_root, es_item);
k_add_tail(shares_early_store, es_item);
K_WUNLOCK(shares_free);
return;
@ -3093,7 +3088,7 @@ keep:
early_shares->oldcount, early_shares->redo);
FREENULL(st);
K_WLOCK(shares_free);
shares_root = add_to_ktree(shares_root, es_item, cmp_shares);
add_to_ktree(shares_root, es_item);
k_add_head(shares_store, es_item);
K_WUNLOCK(shares_free);
return;
@ -3200,8 +3195,7 @@ bool shares_add(PGconn *conn, char *workinfoid, char *username, char *workername
shares->oldcount = 0;
K_WLOCK(shares_free);
// They need to be sorted by workinfoid
shares_early_root = add_to_ktree(shares_early_root, s_item,
cmp_shares);
add_to_ktree(shares_early_root, s_item);
k_add_head(shares_early_store, s_item);
K_WUNLOCK(shares_free);
/* It was all OK except the missing workinfoid
@ -3212,7 +3206,7 @@ bool shares_add(PGconn *conn, char *workinfoid, char *username, char *workername
ok = shares_process(conn, shares, trf_root);
if (ok) {
K_WLOCK(shares_free);
shares_root = add_to_ktree(shares_root, s_item, cmp_shares);
add_to_ktree(shares_root, s_item);
k_add_head(shares_store, s_item);
K_WUNLOCK(shares_free);
@ -3327,9 +3321,7 @@ static void shareerrors_process_early(PGconn *conn, int64_t good_wid,
}
es_item = last_in_ktree(shareerrors_early_root, ctx);
if (es_item) {
shareerrors_early_root = remove_from_ktree(shareerrors_early_root,
es_item,
cmp_shareerrors);
remove_from_ktree(shareerrors_early_root, es_item);
k_unlink_item(shareerrors_early_store, es_item);
}
K_WUNLOCK(shareerrors_free);
@ -3381,8 +3373,7 @@ static void shareerrors_process_early(PGconn *conn, int64_t good_wid,
return;
redo:
K_WLOCK(shareerrors_free);
shareerrors_early_root = add_to_ktree(shareerrors_early_root, es_item,
cmp_shareerrors);
add_to_ktree(shareerrors_early_root, es_item);
k_add_tail(shareerrors_early_store, es_item);
K_WUNLOCK(shareerrors_free);
return;
@ -3397,7 +3388,7 @@ keep:
early_shareerrors->oldcount, early_shareerrors->redo);
FREENULL(st);
K_WLOCK(shareerrors_free);
shareerrors_root = add_to_ktree(shareerrors_root, es_item, cmp_shareerrors);
add_to_ktree(shareerrors_root, es_item);
k_add_head(shareerrors_store, es_item);
K_WUNLOCK(shareerrors_free);
return;
@ -3494,9 +3485,7 @@ bool shareerrors_add(PGconn *conn, char *workinfoid, char *username,
shareerrors->oldcount = 0;
K_WLOCK(shareerrors_free);
// They need to be sorted by workinfoid
shareerrors_early_root = add_to_ktree(shareerrors_early_root,
s_item,
cmp_shareerrors);
add_to_ktree(shareerrors_early_root, s_item);
k_add_head(shareerrors_early_store, s_item);
K_WUNLOCK(shareerrors_free);
/* It was all OK except the missing workinfoid
@ -3507,8 +3496,7 @@ bool shareerrors_add(PGconn *conn, char *workinfoid, char *username,
ok = shareerrors_process(conn, shareerrors, trf_root);
if (ok) {
K_WLOCK(shareerrors_free);
shareerrors_root = add_to_ktree(shareerrors_root, s_item,
cmp_shareerrors);
add_to_ktree(shareerrors_root, s_item);
k_add_head(shareerrors_store, s_item);
K_WUNLOCK(shareerrors_free);
@ -3597,7 +3585,7 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers,
K_STORE *old_sharesummary_store = k_new_store(sharesummary_free);
K_STORE *new_markersummary_store = k_new_store(markersummary_free);
K_TREE *ms_root = new_ktree();
K_TREE *ms_root = new_ktree(cmp_markersummary);
if (!CURRENT(&(workmarkers->expirydate))) {
reason = "unexpired";
@ -3617,8 +3605,7 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers,
INIT_MARKERSUMMARY(&ms_look);
ms_look.data = (void *)(&lookmarkersummary);
K_RLOCK(markersummary_free);
ms_item = find_after_in_ktree(markersummary_root, &ms_look,
cmp_markersummary, ms_ctx);
ms_item = find_after_in_ktree(markersummary_root, &ms_look, ms_ctx);
K_RUNLOCK(markersummary_free);
DATA_MARKERSUMMARY_NULL(markersummary, ms_item);
if (ms_item && markersummary->markerid == workmarkers->markerid) {
@ -3640,8 +3627,8 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers,
* Those incoming shares will not be touching the sharesummaries
* we are processing here */
K_RLOCK(sharesummary_free);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look,
cmp_sharesummary_workinfoid, ss_ctx);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root,
&ss_look, ss_ctx);
K_RUNLOCK(sharesummary_free);
while (ss_item) {
DATA_SHARESUMMARY(sharesummary, ss_item);
@ -3659,8 +3646,7 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers,
lookmarkersummary.workername = sharesummary->workername;
ms_look.data = (void *)(&lookmarkersummary);
ms_item = find_in_ktree(ms_root, &ms_look,
cmp_markersummary, ms_ctx);
ms_item = find_in_ktree(ms_root, &ms_look, ms_ctx);
if (!ms_item) {
K_WLOCK(markersummary_free);
ms_item = k_unlink_head(markersummary_free);
@ -3673,8 +3659,7 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers,
DUP_POINTER(markersummary_free,
markersummary->workername,
sharesummary->workername);
ms_root = add_to_ktree(ms_root, ms_item,
cmp_markersummary);
add_to_ktree(ms_root, ms_item);
LOGDEBUG("%s() new ms %"PRId64"/%"PRId64"/%s",
shortname, markersummary->markerid,
@ -3796,12 +3781,8 @@ flail:
ms_item = new_markersummary_store->head;
while (ms_item) {
// move the new markersummaries into the trees/stores
markersummary_root = add_to_ktree(markersummary_root,
ms_item,
cmp_markersummary);
markersummary_userid_root = add_to_ktree(markersummary_userid_root,
ms_item,
cmp_markersummary_userid);
add_to_ktree(markersummary_root, ms_item);
add_to_ktree(markersummary_userid_root, ms_item);
// create/update the pool markersummaries
DATA_MARKERSUMMARY(markersummary, ms_item);
@ -3812,9 +3793,7 @@ flail:
bzero(p_markersummary, sizeof(*p_markersummary));
p_markersummary->markerid = markersummary->markerid;
POOL_MS(p_markersummary);
markersummary_pool_root = add_to_ktree(markersummary_pool_root,
p_ms_item,
cmp_markersummary);
add_to_ktree(markersummary_pool_root, p_ms_item);
k_add_head(markersummary_pool_store, p_ms_item);
}
markersummary_to_pool(p_markersummary, markersummary);
@ -3828,20 +3807,14 @@ flail:
ss_item = old_sharesummary_store->head;
while (ss_item) {
// remove the old sharesummaries from the trees
sharesummary_root = remove_from_ktree(sharesummary_root,
ss_item,
cmp_sharesummary);
sharesummary_workinfoid_root = remove_from_ktree(sharesummary_workinfoid_root,
ss_item,
cmp_sharesummary_workinfoid);
remove_from_ktree(sharesummary_root, ss_item);
remove_from_ktree(sharesummary_workinfoid_root, ss_item);
// remove the pool sharesummaries
DATA_SHARESUMMARY(sharesummary, ss_item);
p_ss_item = find_sharesummary_p(sharesummary->workinfoid);
if (p_ss_item) {
sharesummary_pool_root = remove_from_ktree(sharesummary_pool_root,
p_ss_item,
cmp_sharesummary);
remove_from_ktree(sharesummary_pool_root, p_ss_item);
k_unlink_item(sharesummary_pool_store, p_ss_item);
free_sharesummary_data(p_ss_item);
k_add_head(sharesummary_free, p_ss_item);
@ -3864,7 +3837,7 @@ flail:
workmarkers->description,
workmarkers->status);
}
ms_root = free_ktree(ms_root, NULL);
free_ktree(ms_root, NULL);
new_markersummary_store = k_free_store(new_markersummary_store);
old_sharesummary_store = k_free_store(old_sharesummary_store);
@ -4140,16 +4113,12 @@ bool _sharesummary_update(SHARES *s_row, SHAREERRORS *e_row, K_ITEM *ss_item,
if (new || p_new) {
K_WLOCK(sharesummary_free);
if (new) {
sharesummary_root = add_to_ktree(sharesummary_root, item, cmp_sharesummary);
sharesummary_workinfoid_root = add_to_ktree(sharesummary_workinfoid_root,
item,
cmp_sharesummary_workinfoid);
add_to_ktree(sharesummary_root, item);
add_to_ktree(sharesummary_workinfoid_root, item);
k_add_head(sharesummary_store, item);
}
if (p_new) {
sharesummary_pool_root = add_to_ktree(sharesummary_pool_root,
p_item,
cmp_sharesummary);
add_to_ktree(sharesummary_pool_root, p_item);
k_add_head(sharesummary_pool_store, p_item);
}
K_WUNLOCK(sharesummary_free);
@ -4290,14 +4259,14 @@ unparam:
k_add_head(blocks_free, b_item);
else {
if (update_old) {
blocks_root = remove_from_ktree(blocks_root, old_b_item, cmp_blocks);
remove_from_ktree(blocks_root, old_b_item);
copy_tv(&(oldblocks->expirydate), cd);
blocks_root = add_to_ktree(blocks_root, old_b_item, cmp_blocks);
add_to_ktree(blocks_root, old_b_item);
// Copy it over to avoid having to recalculate it
row->netdiff = oldblocks->netdiff;
} else
row->netdiff = 0;
blocks_root = add_to_ktree(blocks_root, b_item, cmp_blocks);
add_to_ktree(blocks_root, b_item);
k_add_head(blocks_store, b_item);
blocks_stats_rebuild = true;
// 'confirmed' is unchanged so no need to recalc *createdate
@ -4670,14 +4639,14 @@ flail:
k_add_head(blocks_free, b_item);
else {
if (update_old) {
blocks_root = remove_from_ktree(blocks_root, old_b_item, cmp_blocks);
remove_from_ktree(blocks_root, old_b_item);
copy_tv(&(oldblocks->expirydate), cd);
blocks_root = add_to_ktree(blocks_root, old_b_item, cmp_blocks);
add_to_ktree(blocks_root, old_b_item);
// Copy it over to avoid having to recalculate it
row->netdiff = oldblocks->netdiff;
} else
row->netdiff = 0;
blocks_root = add_to_ktree(blocks_root, b_item, cmp_blocks);
add_to_ktree(blocks_root, b_item);
k_add_head(blocks_store, b_item);
blocks_stats_rebuild = true;
// recalc the *createdate fields for possibly affected blocks
@ -4897,7 +4866,7 @@ bool blocks_fill(PGconn *conn)
if (!ok)
break;
blocks_root = add_to_ktree(blocks_root, item, cmp_blocks);
add_to_ktree(blocks_root, item);
k_add_head(blocks_store, item);
if (tv_newer(&(dbstatus.newest_createdate_blocks), &(row->createdate)))
@ -4958,11 +4927,11 @@ void miningpayouts_add_ram(bool ok, K_ITEM *mp_item, K_ITEM *old_mp_item, tv_t *
} else {
if (old_mp_item) {
DATA_MININGPAYOUTS(oldmp, old_mp_item);
miningpayouts_root = remove_from_ktree(miningpayouts_root, old_mp_item, cmp_miningpayouts);
remove_from_ktree(miningpayouts_root, old_mp_item);
copy_tv(&(oldmp->expirydate), cd);
miningpayouts_root = add_to_ktree(miningpayouts_root, old_mp_item, cmp_miningpayouts);
add_to_ktree(miningpayouts_root, old_mp_item);
}
miningpayouts_root = add_to_ktree(miningpayouts_root, mp_item, cmp_miningpayouts);
add_to_ktree(miningpayouts_root, mp_item);
k_add_head(miningpayouts_store, mp_item);
}
K_WUNLOCK(miningpayouts_free);
@ -5142,7 +5111,7 @@ bool miningpayouts_fill(PGconn *conn)
if (!ok)
break;
miningpayouts_root = add_to_ktree(miningpayouts_root, item, cmp_miningpayouts);
add_to_ktree(miningpayouts_root, item);
k_add_head(miningpayouts_store, item);
tick();
@ -5176,17 +5145,17 @@ void payouts_add_ram(bool ok, K_ITEM *p_item, K_ITEM *old_p_item, tv_t *cd)
} else {
if (old_p_item) {
DATA_PAYOUTS(oldp, old_p_item);
payouts_root = remove_from_ktree(payouts_root, old_p_item, cmp_payouts);
payouts_id_root = remove_from_ktree(payouts_id_root, old_p_item, cmp_payouts_id);
payouts_wid_root = remove_from_ktree(payouts_wid_root, old_p_item, cmp_payouts_wid);
remove_from_ktree(payouts_root, old_p_item);
remove_from_ktree(payouts_id_root, old_p_item);
remove_from_ktree(payouts_wid_root, old_p_item);
copy_tv(&(oldp->expirydate), cd);
payouts_root = add_to_ktree(payouts_root, old_p_item, cmp_payouts);
payouts_id_root = add_to_ktree(payouts_id_root, old_p_item, cmp_payouts_id);
payouts_wid_root = add_to_ktree(payouts_wid_root, old_p_item, cmp_payouts_wid);
add_to_ktree(payouts_root, old_p_item);
add_to_ktree(payouts_id_root, old_p_item);
add_to_ktree(payouts_wid_root, old_p_item);
}
payouts_root = add_to_ktree(payouts_root, p_item, cmp_payouts);
payouts_id_root = add_to_ktree(payouts_id_root, p_item, cmp_payouts_id);
payouts_wid_root = add_to_ktree(payouts_wid_root, p_item, cmp_payouts_wid);
add_to_ktree(payouts_root, p_item);
add_to_ktree(payouts_id_root, p_item);
add_to_ktree(payouts_wid_root, p_item);
k_add_head(payouts_store, p_item);
}
K_WUNLOCK(payouts_free);
@ -5491,22 +5460,22 @@ K_ITEM *payouts_full_expire(PGconn *conn, int64_t payoutid, tv_t *now, bool lock
// No more possible errors, so update the ram tables
DATA_PAYOUTS(payouts, po_item);
payouts_root = remove_from_ktree(payouts_root, po_item, cmp_payouts);
payouts_id_root = remove_from_ktree(payouts_id_root, po_item, cmp_payouts_id);
payouts_wid_root = remove_from_ktree(payouts_wid_root, po_item, cmp_payouts_wid);
remove_from_ktree(payouts_root, po_item);
remove_from_ktree(payouts_id_root, po_item);
remove_from_ktree(payouts_wid_root, po_item);
copy_tv(&(payouts->expirydate), now);
payouts_root = add_to_ktree(payouts_root, po_item, cmp_payouts);
payouts_id_root = add_to_ktree(payouts_id_root, po_item, cmp_payouts_id);
payouts_wid_root = add_to_ktree(payouts_wid_root, po_item, cmp_payouts_wid);
add_to_ktree(payouts_root, po_item);
add_to_ktree(payouts_id_root, po_item);
add_to_ktree(payouts_wid_root, po_item);
mp_item = first_miningpayouts(payoutid, mp_ctx);
DATA_MININGPAYOUTS_NULL(mp, mp_item);
while (mp_item && mp->payoutid == payoutid) {
if (CURRENT(&(mp->expirydate))) {
next_item = next_in_ktree(mp_ctx);
miningpayouts_root = remove_from_ktree(miningpayouts_root, mp_item, cmp_miningpayouts);
remove_from_ktree(miningpayouts_root, mp_item);
copy_tv(&(mp->expirydate), now);
miningpayouts_root = add_to_ktree(miningpayouts_root, mp_item, cmp_miningpayouts);
add_to_ktree(miningpayouts_root, mp_item);
mp_item = next_item;
} else
mp_item = next_in_ktree(mp_ctx);
@ -5520,9 +5489,9 @@ K_ITEM *payouts_full_expire(PGconn *conn, int64_t payoutid, tv_t *now, bool lock
if (payments->payoutid == payoutid &&
CURRENT(&(payments->expirydate))) {
next_item = next_in_ktree(pm_ctx);
payments_root = remove_from_ktree(payments_root, pm_item, cmp_payments);
remove_from_ktree(payments_root, pm_item);
copy_tv(&(payments->expirydate), now);
payments_root = add_to_ktree(payments_root, pm_item, cmp_payments);
add_to_ktree(payments_root, pm_item);
pm_item = next_item;
} else
pm_item = next_in_ktree(pm_ctx);
@ -5698,9 +5667,9 @@ bool payouts_fill(PGconn *conn)
&(blocks->blockcreatedate));
}
payouts_root = add_to_ktree(payouts_root, item, cmp_payouts);
payouts_id_root = add_to_ktree(payouts_id_root, item, cmp_payouts_id);
payouts_wid_root = add_to_ktree(payouts_wid_root, item, cmp_payouts_wid);
add_to_ktree(payouts_root, item);
add_to_ktree(payouts_id_root, item);
add_to_ktree(payouts_wid_root, item);
k_add_head(payouts_store, item);
if (CURRENT(&(row->expirydate)) && PAYGENERATED(row->status))
@ -5792,7 +5761,7 @@ bool auths_add(PGconn *conn, char *poolinstance, char *username,
HISTORYDATETRANSFER(trf_root, row);
K_WLOCK(auths_free);
if (find_in_ktree(auths_root, a_item, cmp_auths, ctx)) {
if (find_in_ktree(auths_root, a_item, ctx)) {
k_add_head(auths_free, a_item);
K_WUNLOCK(auths_free);
@ -5825,7 +5794,7 @@ unitem:
if (!ok)
k_add_head(auths_free, a_item);
else {
auths_root = add_to_ktree(auths_root, a_item, cmp_auths);
add_to_ktree(auths_root, a_item);
k_add_head(auths_store, a_item);
}
#endif
@ -5875,7 +5844,7 @@ bool poolstats_add(PGconn *conn, bool store, char *poolinstance,
SIMPLEDATEINIT(row, cd, by, code, inet);
SIMPLEDATETRANSFER(trf_root, row);
if (igndup && find_in_ktree(poolstats_root, p_item, cmp_poolstats, ctx)) {
if (igndup && find_in_ktree(poolstats_root, p_item, ctx)) {
K_WLOCK(poolstats_free);
k_add_head(poolstats_free, p_item);
K_WUNLOCK(poolstats_free);
@ -5937,7 +5906,7 @@ unparam:
if (!ok)
k_add_head(poolstats_free, p_item);
else {
poolstats_root = add_to_ktree(poolstats_root, p_item, cmp_poolstats);
add_to_ktree(poolstats_root, p_item);
k_add_head(poolstats_store, p_item);
}
K_WUNLOCK(poolstats_free);
@ -6083,7 +6052,7 @@ bool poolstats_fill(PGconn *conn)
if (!ok)
break;
poolstats_root = add_to_ktree(poolstats_root, item, cmp_poolstats);
add_to_ktree(poolstats_root, item);
k_add_head(poolstats_store, item);
if (tv_newer(&(dbstatus.newest_createdate_poolstats), &(row->createdate)))
@ -6186,15 +6155,13 @@ bool userstats_add(char *poolinstance, char *elapsed, char *username,
K_WLOCK(userstats_free);
us_next = userstats_eos_store->head;
while (us_next) {
us_item = find_in_ktree(userstats_root, us_next,
cmp_userstats, ctx);
us_item = find_in_ktree(userstats_root, us_next, ctx);
if (!us_item) {
// New user+worker - store it in RAM
us_match = us_next;
us_next = us_match->next;
k_unlink_item(userstats_eos_store, us_match);
userstats_root = add_to_ktree(userstats_root, us_match,
cmp_userstats);
add_to_ktree(userstats_root, us_match);
k_add_head(userstats_store, us_match);
} else {
DATA_USERSTATS(next, us_next);
@ -6270,12 +6237,10 @@ bool workerstats_add(char *poolinstance, char *elapsed, char *username,
workerstatus_update(NULL, NULL, row);
K_WLOCK(userstats_free);
us_match = find_in_ktree(userstats_root, us_item,
cmp_userstats, ctx);
us_match = find_in_ktree(userstats_root, us_item, ctx);
if (!us_match) {
// New user+worker - store it in RAM
userstats_root = add_to_ktree(userstats_root, us_item,
cmp_userstats);
add_to_ktree(userstats_root, us_item);
k_add_head(userstats_store, us_item);
} else {
DATA_USERSTATS(match, us_match);
@ -6520,8 +6485,8 @@ bool markersummary_fill(PGconn *conn)
if (!ok)
break;
markersummary_root = add_to_ktree(markersummary_root, item, cmp_markersummary);
markersummary_userid_root = add_to_ktree(markersummary_userid_root, item, cmp_markersummary_userid);
add_to_ktree(markersummary_root, item);
add_to_ktree(markersummary_userid_root, item);
k_add_head(markersummary_store, item);
p_item = find_markersummary_p(row->markerid);
@ -6533,9 +6498,7 @@ bool markersummary_fill(PGconn *conn)
bzero(p_row, sizeof(*p_row));
p_row->markerid = row->markerid;
POOL_MS(p_row);
markersummary_pool_root = add_to_ktree(markersummary_pool_root,
p_item,
cmp_markersummary);
add_to_ktree(markersummary_pool_root, p_item);
k_add_head(markersummary_pool_store, p_item);
} else {
DATA_MARKERSUMMARY(p_row, p_item);
@ -6671,12 +6634,13 @@ bool _workmarkers_process(PGconn *conn, bool already, bool add,
WHERE_FFL_PASS);
goto rollback;
}
w_item = find_workinfo(workinfoidend, NULL);
w_item = find_workinfo(workinfoidstart, NULL);
if (!w_item)
goto rollback;
w_item = find_workinfo(workinfoidstart, NULL);
w_item = find_workinfo(workinfoidend, NULL);
if (!w_item)
goto rollback;
K_WLOCK(workmarkers_free);
wm_item = k_unlink_head(workmarkers_free);
K_WUNLOCK(workmarkers_free);
@ -6741,6 +6705,7 @@ bool _workmarkers_process(PGconn *conn, bool already, bool add,
PGLOGERR("Insert", rescode, conn);
goto rollback;
}
row->pps_value = workinfo_pps(w_item, workinfoidend, true);
}
ok = true;
@ -6769,29 +6734,18 @@ unparam:
}
else {
if (old_wm_item) {
workmarkers_root = remove_from_ktree(workmarkers_root,
old_wm_item,
cmp_workmarkers);
workmarkers_workinfoid_root = remove_from_ktree(workmarkers_workinfoid_root,
old_wm_item,
cmp_workmarkers_workinfoid);
remove_from_ktree(workmarkers_root, old_wm_item);
remove_from_ktree(workmarkers_workinfoid_root,
old_wm_item);
copy_tv(&(oldworkmarkers->expirydate), cd);
workmarkers_root = add_to_ktree(workmarkers_root,
old_wm_item,
cmp_workmarkers);
workmarkers_workinfoid_root = add_to_ktree(workmarkers_workinfoid_root,
old_wm_item,
cmp_workmarkers_workinfoid);
add_to_ktree(workmarkers_root, old_wm_item);
add_to_ktree(workmarkers_workinfoid_root, old_wm_item);
}
if (wm_item) {
shift_rewards(wm_item);
workmarkers_root = add_to_ktree(workmarkers_root,
wm_item,
cmp_workmarkers);
workmarkers_workinfoid_root = add_to_ktree(workmarkers_workinfoid_root,
wm_item,
cmp_workmarkers_workinfoid);
add_to_ktree(workmarkers_root, wm_item);
add_to_ktree(workmarkers_workinfoid_root, wm_item);
k_add_head(workmarkers_store, wm_item);
}
}
@ -6887,14 +6841,22 @@ bool workmarkers_fill(PGconn *conn)
if (!ok)
break;
workmarkers_root = add_to_ktree(workmarkers_root, item, cmp_workmarkers);
workmarkers_workinfoid_root = add_to_ktree(workmarkers_workinfoid_root,
item, cmp_workmarkers_workinfoid);
add_to_ktree(workmarkers_root, item);
add_to_ktree(workmarkers_workinfoid_root, item);
k_add_head(workmarkers_store, item);
wi_item = find_workinfo(row->workinfoidend, NULL);
if (!wi_item) {
LOGERR("%s(): ERROR workmarkerid %"PRId64
" wid end %"PRId64" doesn't exist! "
"PPS value will be zero",
__func__, row->markerid,
row->workinfoidend);
}
row->pps_value = workinfo_pps(wi_item, row->workinfoidend, false);
if (dbstatus.newest_workmarker_workinfoid < row->workinfoidend) {
dbstatus.newest_workmarker_workinfoid = row->workinfoidend;
wi_item = find_workinfo(row->workinfoidend, NULL);
if (!wi_item) {
LOGEMERG("%s(): FAILURE workmarkerid %"PRId64
" wid end %"PRId64" doesn't exist! "
@ -7086,12 +7048,12 @@ unparam:
}
} else {
if (old_m_item) {
marks_root = remove_from_ktree(marks_root, old_m_item, cmp_marks);
remove_from_ktree(marks_root, old_m_item);
copy_tv(&(oldmarks->expirydate), cd);
marks_root = add_to_ktree(marks_root, old_m_item, cmp_marks);
add_to_ktree(marks_root, old_m_item);
}
if (m_item) {
marks_root = add_to_ktree(marks_root, m_item, cmp_marks);
add_to_ktree(marks_root, m_item);
k_add_head(marks_store, m_item);
}
}
@ -7186,7 +7148,7 @@ bool marks_fill(PGconn *conn)
if (!ok)
break;
marks_root = add_to_ktree(marks_root, item, cmp_marks);
add_to_ktree(marks_root, item);
k_add_head(marks_store, item);
tick();

453
src/ktree.c

@ -1,5 +1,5 @@
/*
* Copyright 1995-2014 Andrew Smith
* Copyright 1995-2015 Andrew Smith
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@ -23,42 +23,56 @@ static const int dbg = 0;
#define Yo true
#define No false
static K_TREE nil[1] = { { Yo, RED_BLACK, NULL, NULL, NULL, NULL, 0 } };
static K_NODE nil[1] = { { Yo, RED_BLACK, NULL, NULL, NULL, NULL, 0 } };
K_TREE *_new_ktree(KTREE_FFL_ARGS)
static K_NODE *_new_knode(KTREE_FFL_ARGS)
{
K_TREE *ktree = (K_TREE *)malloc(sizeof(*ktree));
K_NODE *node = (K_NODE *)malloc(sizeof(*node));
if (ktree == NULL)
FAIL("%s", "OOM");
if (node == NULL)
FAIL("%s", "node OOM");
node->isNil = Yo;
node->red = RED_BLACK;
node->parent = nil;
node->left = nil;
node->right = nil;
node->data = NULL;
node->test = 0;
return node;
}
K_TREE *_new_ktree(cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), KTREE_FFL_ARGS)
{
K_TREE *tree = (K_TREE *)malloc(sizeof(*tree));
if (tree == NULL)
FAIL("%s", "tree OOM");
tree->root = _new_knode(KTREE_FFL_PASS);
ktree->isNil = Yo;
ktree->red = RED_BLACK;
ktree->parent = nil;
ktree->left = nil;
ktree->right = nil;
ktree->data = NULL;
ktree->test = 0;
tree->cmp_funct = cmp_funct;
return ktree;
return tree;
}
static K_TREE *new_data(K_ITEM *data, KTREE_FFL_ARGS)
static K_NODE *new_data(K_ITEM *data, KTREE_FFL_ARGS)
{
K_TREE *ktree = (K_TREE *)malloc(sizeof(*ktree));
K_NODE *knode = (K_NODE *)malloc(sizeof(*knode));
if (ktree == NULL)
if (knode == NULL)
FAIL("%s", "OOM");
ktree->isNil = No;
ktree->red = RED_RED;
ktree->parent = nil;
ktree->left = nil;
ktree->right = nil;
ktree->data = data;
ktree->test = 0;
knode->isNil = No;
knode->red = RED_RED;
knode->parent = nil;
knode->left = nil;
knode->right = nil;
knode->data = data;
knode->test = 0;
return ktree;
return knode;
}
static int bCount = 0;
@ -73,54 +87,54 @@ static long getTestValue()
return ++testValue;
}
static void show_ktree(K_TREE *root, char *path, int pos, char *(*dsp_funct)(K_ITEM *))
static void show_ktree(K_NODE *node, char *path, int pos, char *(*dsp_funct)(K_ITEM *))
{
char col;
if (root->isNil == Yo)
if (node->isNil == Yo)
return;
if (root->left->isNil == No)
if (node->left->isNil == No)
{
path[pos] = 'L';
path[pos+1] = '\0';
show_ktree(root->left, path, pos+1, dsp_funct);
show_ktree(node->left, path, pos+1, dsp_funct);
}
path[pos] = '\0';
if (root->red == RED_RED)
if (node->red == RED_RED)
col = 'R';
else
// if (root->red == RED_BLACK)
// if (node->red == RED_BLACK)
col = 'B';
printf(" %c %s=%s\n", col, path, dsp_funct(root->data));
printf(" %c %s=%s\n", col, path, dsp_funct(node->data));
if (root->right->isNil == No)
if (node->right->isNil == No)
{
path[pos] = 'R';
path[pos+1] = '\0';
show_ktree(root->right, path, pos+1, dsp_funct);
show_ktree(node->right, path, pos+1, dsp_funct);
}
}
void _dump_ktree(K_TREE *root, char *(*dsp_funct)(K_ITEM *), KTREE_FFL_ARGS)
void _dump_ktree(K_TREE *tree, char *(*dsp_funct)(K_ITEM *), KTREE_FFL_ARGS)
{
char buf[42424];
printf("dump:\n");
if (root->isNil == No)
if (tree->root->isNil == No)
{
buf[0] = 'T';
buf[1] = '\0';
show_ktree(root, buf, 1, dsp_funct);
show_ktree(tree->root, buf, 1, dsp_funct);
}
else
printf(" Empty ktree\n");
printf(" Empty tree\n");
}
void _dsp_ktree(K_LIST *list, K_TREE *root, char *filename, char *msg, KTREE_FFL_ARGS)
void _dsp_ktree(K_LIST *list, K_TREE *tree, char *filename, char *msg, KTREE_FFL_ARGS)
{
K_TREE_CTX ctx[1];
K_ITEM *item;
@ -154,11 +168,11 @@ void _dsp_ktree(K_LIST *list, K_TREE *root, char *filename, char *msg, KTREE_FFL
if (msg)
fprintf(stream, "%s %s\n", stamp, msg);
else
fprintf(stream, "%s Dump of ktree '%s':\n", stamp, list->name);
fprintf(stream, "%s Dump of tree '%s':\n", stamp, list->name);
if (root->isNil == No)
if (tree->root->isNil == No)
{
item = first_in_ktree(root, ctx);
item = first_in_ktree(tree, ctx);
while (item)
{
list->dsp_func(item, stream);
@ -172,7 +186,7 @@ void _dsp_ktree(K_LIST *list, K_TREE *root, char *filename, char *msg, KTREE_FFL
fclose(stream);
}
static int nilTest(K_TREE *node, char *msg, int depth, int count, K_TREE *nil2, KTREE_FFL_ARGS)
static int nilTest(K_NODE *node, char *msg, int depth, int count, K_NODE *nil2, KTREE_FFL_ARGS)
{
if (node->isNil == Yo || node == nil2)
{
@ -231,7 +245,7 @@ static int nilTest(K_TREE *node, char *msg, int depth, int count, K_TREE *nil2,
return(count);
}
static void bTest(K_TREE *root, K_TREE *cur, char *msg, int count, KTREE_FFL_ARGS)
static void bTest(K_NODE *cur, char *msg, int count, KTREE_FFL_ARGS)
{
if (cur->red != RED_RED)
count++;
@ -259,108 +273,118 @@ static void bTest(K_TREE *root, K_TREE *cur, char *msg, int count, KTREE_FFL_ARG
else
FAIL("BTESTVALUE '%s' count=%d", msg, count);
bTest(root, cur->left, msg, count, KTREE_FFL_PASS);
bTest(root, cur->right, msg, count, KTREE_FFL_PASS);
bTest(cur->left, msg, count, KTREE_FFL_PASS);
bTest(cur->right, msg, count, KTREE_FFL_PASS);
}
}
static void bTestInit(K_TREE *root, char *msg, KTREE_FFL_ARGS)
static void bTestInit(K_TREE *tree, char *msg, KTREE_FFL_ARGS)
{
bCount = 0;
bTestValue = getTestValue();
bTest(root, root, msg, 0, KTREE_FFL_PASS);
bTest(tree->root, msg, 0, KTREE_FFL_PASS);
}
static void lrpTest(K_TREE *top, char *msg, KTREE_FFL_ARGS)
static void lrpTest(K_NODE *node, char *msg, KTREE_FFL_ARGS)
{
if (top->test != lrpTestValue)
top->test = lrpTestValue;
if (node->test != lrpTestValue)
node->test = lrpTestValue;
else
FAIL("LRPTESTVALUE '%s'", msg);
if (top->left->isNil == No)
if (node->left->isNil == No)
{
if (top->left->parent != top)
if (node->left->parent != node)
FAIL("LRPTESTL '%s'", msg);
lrpTest(top->left, msg, KTREE_FFL_PASS);
lrpTest(node->left, msg, KTREE_FFL_PASS);
}
if (top->right->isNil == No)
if (node->right->isNil == No)
{
if (top->right->parent != top)
if (node->right->parent != node)
FAIL("LRPTESTR '%s'", msg);
lrpTest(top->right, msg, KTREE_FFL_PASS);
lrpTest(node->right, msg, KTREE_FFL_PASS);
}
}
static __maybe_unused void check_ktree(K_TREE *root, char *msg, K_TREE *nil2, int debugNil, int debugLRP, int debugColor, KTREE_FFL_ARGS)
static __maybe_unused void check_ktree(K_TREE *tree, char *msg, K_NODE *nil2, int debugNil, int debugLRP, int debugColor, KTREE_FFL_ARGS)
{
if (root->isNil == Yo)
if (tree->root->isNil == Yo)
return;
if (debugNil)
{
nilTestValue = getTestValue();
nilTest(root, msg, 1, 0, nil2, KTREE_FFL_PASS);
nilTest(tree->root, msg, 1, 0, nil2, KTREE_FFL_PASS);
}
if (debugLRP && root->isNil == No)
if (debugLRP && tree->root->isNil == No)
{
lrpTestValue = getTestValue();
lrpTest(root, msg, KTREE_FFL_PASS);
lrpTest(tree->root, msg, KTREE_FFL_PASS);
}
if (debugColor && root->isNil == No)
bTestInit(root, msg, KTREE_FFL_PASS);
if (debugColor && tree->root->isNil == No)
bTestInit(tree, msg, KTREE_FFL_PASS);
}
K_ITEM *_first_in_ktree(K_TREE *root, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
static K_ITEM *_first_in_knode(K_NODE *node, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
if (root->isNil == No)
if (node->isNil == No)
{
while (root->left->isNil == No)
root = root->left;
while (node->left->isNil == No)
node = node->left;
*ctx = root;
return(root->data);
*ctx = node;
return(node->data);
}
*ctx = NULL;
return(NULL);
}
K_ITEM *_last_in_ktree(K_TREE *root, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
K_ITEM *_first_in_ktree(K_TREE *tree, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
if (root->isNil == No)
return _first_in_knode(tree->root, ctx, KTREE_FFL_PASS);
}
static K_ITEM *_last_in_knode(K_NODE *node, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
if (node->isNil == No)
{
while (root->right->isNil == No)
root = root->right;
while (node->right->isNil == No)
node = node->right;
*ctx = root;
return(root->data);
*ctx = node;
return(node->data);
}
*ctx = NULL;
return(NULL);
}
K_ITEM *_last_in_ktree(K_TREE *tree, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
return _last_in_knode(tree->root, ctx, KTREE_FFL_PASS);
}
K_ITEM *_next_in_ktree(K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
K_TREE *parent;
K_TREE *ktree = (K_TREE *)(*ctx);
K_NODE *parent;
K_NODE *knode = (K_NODE *)(*ctx);
if (ktree->isNil == No)
if (knode->isNil == No)
{
if (ktree->right->isNil == No)
return(first_in_ktree(ktree->right, ctx));
if (knode->right->isNil == No)
return(_first_in_knode(knode->right, ctx, KTREE_FFL_PASS));
else
{
parent = ktree->parent;
while (parent->isNil == No && ktree == parent->right)
parent = knode->parent;
while (parent->isNil == No && knode == parent->right)
{
ktree = parent;
knode = parent;
parent = parent->parent;
}
if (parent->isNil == No)
@ -377,19 +401,19 @@ K_ITEM *_next_in_ktree(K_TREE_CTX *ctx, KTREE_FFL_ARGS)
K_ITEM *_prev_in_ktree(K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
K_TREE *parent;
K_TREE *ktree = (K_TREE *)(*ctx);
K_NODE *parent;
K_NODE *knode = (K_NODE *)(*ctx);
if (ktree->isNil == No)
if (knode->isNil == No)
{
if (ktree->left->isNil == No)
return(last_in_ktree(ktree->left, ctx));
if (knode->left->isNil == No)
return(_last_in_knode(knode->left, ctx, KTREE_FFL_PASS));
else
{
parent = ktree->parent;
while (parent->isNil == No && ktree == parent->left)
parent = knode->parent;
while (parent->isNil == No && knode == parent->left)
{
ktree = parent;
knode = parent;
parent = parent->parent;
}
if (parent->isNil == No)
@ -404,9 +428,9 @@ K_ITEM *_prev_in_ktree(K_TREE_CTX *ctx, KTREE_FFL_ARGS)
return(NULL);
}
static K_TREE *left_rotate(K_TREE *root, K_TREE *about)
static K_NODE *left_rotate(K_NODE *root, K_NODE *about)
{
K_TREE *rotate;
K_NODE *rotate;
rotate = about->right;
about->right = rotate->left;
@ -432,9 +456,9 @@ static K_TREE *left_rotate(K_TREE *root, K_TREE *about)
return(root);
}
static K_TREE *right_rotate(K_TREE *root, K_TREE *about)
static K_NODE *right_rotate(K_NODE *root, K_NODE *about)
{
K_TREE *rotate;
K_NODE *rotate;
rotate = about->left;
about->left = rotate->right;
@ -458,50 +482,50 @@ static K_TREE *right_rotate(K_TREE *root, K_TREE *about)
return(root);
}
K_TREE *_add_to_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), KTREE_FFL_ARGS)
void _add_to_ktree(K_TREE *tree, K_ITEM *data, KTREE_FFL_ARGS)
{
K_TREE *ktree;
K_TREE *x, *y;
K_TREE *pp;
K_NODE *knode;
K_NODE *x, *y;
K_NODE *pp;
cmp_t cmp;
if (root == NULL)
FAIL("%s", "ADDNULL add ktree is NULL");
if (tree == NULL)
FAIL("%s", "ADDNULL add tree is NULL");
//check_ktree(root, ">add", NULL, 1, 1, 1, KTREE_FFL_PASS);
//check_ktree(tree, ">add", NULL, 1, 1, 1, KTREE_FFL_PASS);
if (root->parent != nil && root->parent != NULL)
FAIL("%s", "ADDROOT add root isn't the root");
if (tree->root->parent != nil && tree->root->parent != NULL)
FAIL("%s", "ADDROOT add tree->root isn't the root");
ktree = new_data(data, KTREE_FFL_PASS);
knode = new_data(data, KTREE_FFL_PASS);
if (root->isNil == Yo)
if (tree->root->isNil == Yo)
{
if (root != nil)
free(root);
if (tree->root != nil)
free(tree->root);
root = ktree;
tree->root = knode;
}
else
{
x = root;
x = tree->root;
y = nil;
while (x->isNil == No)
{
y = x;
if ((cmp = (*cmp_funct)(ktree->data, x->data)) < 0)
if ((cmp = tree->cmp_funct(knode->data, x->data)) < 0)
x = x->left;
else
x = x->right;
}
ktree->parent = y;
knode->parent = y;
if (cmp < 0)
y->left = ktree;
y->left = knode;
else
y->right = ktree;
y->right = knode;
x = ktree;
while (x != root && x->parent->red == RED_RED)
x = knode;
while (x != tree->root && x->parent->red == RED_RED)
{
pp = x->parent->parent;
if (x->parent == pp->left)
@ -519,12 +543,12 @@ K_TREE *_add_to_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K
if (x == x->parent->right)
{
x = x->parent;
root = left_rotate(root, x);
tree->root = left_rotate(tree->root, x);
pp = x->parent->parent;
}
x->parent->red = RED_BLACK;
pp->red = RED_RED;
root = right_rotate(root, pp);
tree->root = right_rotate(tree->root, pp);
}
}
else
@ -542,45 +566,49 @@ K_TREE *_add_to_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K
if (x == x->parent->left)
{
x = x->parent;
root = right_rotate(root, x);
tree->root = right_rotate(tree->root, x);
pp = x->parent->parent;
}
x->parent->red = RED_BLACK;
pp->red = RED_RED;
root = left_rotate(root, pp);
tree->root = left_rotate(tree->root, pp);
}
}
}
}
root->red = RED_BLACK;
//check_ktree(root, "<add", NULL, 1, 1, 1, KTREE_FFL_PASS);
tree->root->red = RED_BLACK;
return(root);
//check_ktree(tree, "<add", NULL, 1, 1, 1, KTREE_FFL_PASS);
}
K_ITEM *_find_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS)
K_ITEM *_find_in_ktree(K_TREE *tree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
K_NODE *knode;
cmp_t cmp = -1;
if (ktree == NULL)
FAIL("%s", "FINDNULL find ktree is NULL");
if (tree == NULL)
FAIL("%s", "FINDNULL find tree is NULL");
if (tree->root == NULL)
FAIL("%s", "FINDNULL find tree->root is NULL");
while (ktree->isNil == No && cmp != 0)
knode = tree->root;
while (knode->isNil == No && cmp != 0)
{
if ((cmp = (*cmp_funct)(ktree->data, data)))
if ((cmp = tree->cmp_funct(knode->data, data)))
{
if (cmp > 0)
ktree = ktree->left;
knode = knode->left;
else
ktree = ktree->right;
knode = knode->right;
}
}
if (ktree->isNil == No)
if (knode->isNil == No)
{
*ctx = ktree;
return(ktree->data);
*ctx = knode;
return(knode->data);
}
else
{
@ -589,30 +617,35 @@ K_ITEM *_find_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *,
}
}
K_ITEM *_find_after_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS)
K_ITEM *_find_after_in_ktree(K_TREE *tree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
K_TREE *old = NULL;
K_NODE *knode, *old = NULL;
cmp_t cmp = -1, oldcmp = -1;
if (ktree == NULL)
FAIL("%s", "FINDNULL find_after ktree is NULL");
if (tree == NULL)
FAIL("%s", "FINDNULL find_after tree is NULL");
if (tree->root == NULL)
FAIL("%s", "FINDNULL find_after tree->root is NULL");
while (ktree->isNil == No && cmp != 0)
knode = tree->root;
while (knode->isNil == No && cmp != 0)
{
if ((cmp = (*cmp_funct)(ktree->data, data)))
if ((cmp = tree->cmp_funct(knode->data, data)))
{
old = ktree;
old = knode;
oldcmp = cmp;
if (cmp > 0)
ktree = ktree->left;
knode = knode->left;
else
ktree = ktree->right;
knode = knode->right;
}
}
if (ktree->isNil == No)
if (knode->isNil == No)
{
*ctx = ktree;
*ctx = knode;
return next_in_ktree(ctx);
}
else
@ -634,30 +667,35 @@ K_ITEM *_find_after_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_I
}
}
K_ITEM *_find_before_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS)
K_ITEM *_find_before_in_ktree(K_TREE *tree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
K_TREE *old = NULL;
K_NODE *knode, *old = NULL;
cmp_t cmp = 1, oldcmp = 1;
if (ktree == NULL)
FAIL("%s", "FINDNULL find_before ktree is NULL");
if (tree == NULL)
FAIL("%s", "FINDNULL find_before tree is NULL");
if (tree->root == NULL)
FAIL("%s", "FINDNULL find_before tree->root is NULL");
knode = tree->root;
while (ktree->isNil == No && cmp != 0)
while (knode->isNil == No && cmp != 0)
{
if ((cmp = (*cmp_funct)(ktree->data, data)))
if ((cmp = tree->cmp_funct(knode->data, data)))
{
old = ktree;
old = knode;
oldcmp = cmp;
if (cmp > 0)
ktree = ktree->left;
knode = knode->left;
else
ktree = ktree->right;
knode = knode->right;
}
}
if (ktree->isNil == No)
if (knode->isNil == No)
{
*ctx = ktree;
*ctx = knode;
return prev_in_ktree(ctx);
}
else
@ -679,9 +717,9 @@ K_ITEM *_find_before_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_
}
}
static K_TREE *removeFixup(K_TREE *root, K_TREE *fix)
static K_NODE *removeFixup(K_NODE *root, K_NODE *fix)
{
K_TREE *w = NULL;
K_NODE *w = NULL;
while (fix != root && fix->red != RED_RED)
{
@ -758,37 +796,40 @@ static K_TREE *removeFixup(K_TREE *root, K_TREE *fix)
return root;
}
// Does this work OK when you remove the last element in the ktree?
// Does this work OK when you remove the last element in the tree?
// It should return the root as 'nil'
K_TREE *_remove_from_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS)
void _remove_from_ktree(K_TREE *tree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS)
{
K_TREE_CTX tmpctx[1];
K_TREE *found;
K_NODE *found;
K_ITEM *fdata;
K_TREE *x, *y, *nil2;
K_NODE *x, *y, *nil2;
// cmp_t cmp;
int yred;
//check_ktree(root, ">remove", NULL, 1, 1, 1, KTREE_FFL_PASS);
//check_ktree(tree, ">remove", NULL, 1, 1, 1, KTREE_FFL_PASS);
if (root == NULL)
FAIL("%s", "REMNULL remove ktree is NULL");
if (tree == NULL)
FAIL("%s", "REMNULL remove tree is NULL");
if (root->isNil == Yo)
if (tree->root == NULL)
FAIL("%s", "REMNULL remove tree->root is NULL");
if (tree->root->isNil == Yo)
{
*ctx = NULL;
return(root);
return;
}
if (root->parent->isNil == No)
FAIL("%s", "REMROOT remove root isn't the root");
if (tree->root->parent->isNil == No)
FAIL("%s", "REMROOT remove tree->root isn't the root");
fdata = find_in_ktree(root, data, cmp_funct, ctx);
fdata = find_in_ktree(tree, data, ctx);
if (fdata == NULL)
return(root);
return;
if (cmp_funct(fdata, data) != 0)
if (tree->cmp_funct(fdata, data) != 0)
FAIL("%s", "BADFIND cmp(found, remove) != 0");
found = *ctx;
@ -819,14 +860,14 @@ K_TREE *_remove_from_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM
nil2 = NULL;
else
{
nil2 = new_ktree();
nil2 = _new_knode(KTREE_FFL_PASS);
x = nil2;
}
x->parent = y->parent;
if (x->parent->isNil == Yo)
root = x;
tree->root = x;
else
{
if (x->parent->left == y)
@ -837,8 +878,8 @@ K_TREE *_remove_from_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM
if (y != found)
{
if (root == found)
root = y;
if (tree->root == found)
tree->root = y;
if (x == found)
x = y;
@ -864,7 +905,7 @@ K_TREE *_remove_from_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM
}
if (yred != RED_RED)
root = removeFixup(root, x);
tree->root = removeFixup(tree->root, x);
if (nil2 != NULL)
{
@ -874,8 +915,8 @@ K_TREE *_remove_from_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM
if (nil2->parent->isNil == No && nil2->parent->right == nil2)
nil2->parent->right = nil;
if (root == nil2)
root = nil;
if (tree->root == nil2)
tree->root = nil;
/*
if (dbg != 0)
@ -889,24 +930,24 @@ DBG("@remove nil2->left wasn't nil!!!\n");
DBG("@remove nil2->right wasn't nil!!!\n");
}
cmp = 0;
fdata = first_in_ktree(root, tmpctx);;
fdata = first_in_ktree(tree, tmpctx);;
while (fdata != NULL)
{
cmp++;
x = *tmpctx;
if (x == nil2)
{
DBG("@remove found nil2 in ktree %f!!!\n", cmp);
DBG("@remove found nil2 in ktree %d!!!\n", (int)cmp);
}
else
if (x->left == nil2)
{
DBG("@remove found nil2 in ktree(left) %f!!!\n", cmp);
DBG("@remove found nil2 in ktree(left) %d!!!\n", (int)cmp);
}
else
if (x->right == nil2)
{
DBG("@remove found nil2 in ktree(right) %f!!!\n", cmp);
DBG("@remove found nil2 in ktree(right) %d!!!\n", (int)cmp);
}
fdata = next_in_ktree(tmpctx);;
@ -920,10 +961,10 @@ DBG("@remove found nil2 in ktree(right) %f!!!\n", cmp);
if (dbg != 0)
{
cmp = 0;
fdata = first_in_ktree(root, tmpctx);;
fdata = first_in_ktree(tree, tmpctx);;
while (fdata != NULL)
{
if (cmp_funct(fdata, root->data) < 0)
if (tree->cmp_funct(fdata, tree->root->data) < 0)
cmp--;
else
cmp++;
@ -932,52 +973,48 @@ if (dbg != 0)
}
if (cmp < -10 || cmp > 10)
{
DBG("@remove after balance=%f :(\n", cmp);
DBG("@remove after balance=%d :(\n", (int)cmp);
}
}
*/
//check_ktree(root, "<remove", NULL, 1, 1, 1, KTREE_FFL_PASS);
//check_ktree(tree, "<remove", NULL, 1, 1, 1, KTREE_FFL_PASS);
return root;
return;
}
K_TREE *_remove_from_ktree_free(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), KTREE_FFL_ARGS)
void _remove_from_ktree_free(K_TREE *root, K_ITEM *data, KTREE_FFL_ARGS)
{
K_TREE_CTX ctx[1];
root = _remove_from_ktree(root, data, cmp_funct, ctx, KTREE_FFL_PASS);
_remove_from_ktree(root, data, ctx, KTREE_FFL_PASS);
if (*ctx)
free(*ctx);
return root;
}
static void free_ktree_sub(K_TREE *ktree, void (*free_funct)(void *))
static void free_ktree_sub(K_NODE *knode, void (*free_funct)(void *))
{
if (ktree != NULL && ktree != nil)
if (knode != NULL && knode != nil)
{
if (ktree->data != NULL && free_funct)
(*free_funct)(ktree->data);
if (knode->data != NULL && free_funct)
free_funct(knode->data);
free_ktree_sub(ktree->left, free_funct);
free_ktree_sub(ktree->right, free_funct);
free_ktree_sub(knode->left, free_funct);
free_ktree_sub(knode->right, free_funct);
free(ktree);
free(knode);
}
}
K_TREE *_free_ktree(K_TREE *ktree, void (*free_funct)(void *), KTREE_FFL_ARGS)
void _free_ktree(K_TREE *tree, void (*free_funct)(void *), KTREE_FFL_ARGS)
{
if (ktree == NULL)
FAIL("%s", "FREENULL free NULL ktree");
if (ktree->parent != NULL && ktree->parent != nil)
FAIL("%s", "FREENOTROOT free ktree not root");
if (tree == NULL)
FAIL("%s", "FREENULL free NULL tree");
free_ktree_sub(ktree, free_funct);
if (tree->root->parent != NULL && tree->root->parent != nil)
FAIL("%s", "FREENOTROOT free tree->root not root");
return(nil);
free_ktree_sub(tree->root, free_funct);
}

65
src/ktree.h

@ -1,5 +1,5 @@
/*
* Copyright 1995-2014 Andrew Smith
* Copyright 1995-2015 Andrew Smith
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@ -34,45 +34,54 @@
#define CMP_BIGINT CMP_BIG
#define CMP_DOUBLE CMP_BIG
typedef struct ktree
typedef struct knode
{
bool isNil;
bool red;
struct ktree *parent;
struct ktree *left;
struct ktree *right;
struct knode *parent;
struct knode *left;
struct knode *right;
K_ITEM *data;
long test;
} K_NODE;
typedef struct ktree
{
K_NODE *root;
cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *);
} K_TREE;
typedef void *K_TREE_CTX;
extern K_TREE *_new_ktree(KTREE_FFL_ARGS);
#define new_ktree() _new_ktree(KLIST_FFL_HERE)
extern void _dump_ktree(K_TREE *root, char *(*dsp_funct)(K_ITEM *), KTREE_FFL_ARGS);
#define dump_ktree(_root, _dsp_funct) _dump_ktree(_root, _dsp_funct, KLIST_FFL_HERE)
extern void _dsp_ktree(K_LIST *list, K_TREE *root, char *filename, char *msg, KTREE_FFL_ARGS);
#define dsp_ktree(_list, _root, _filename, _msg) _dsp_ktree(_list, _root, _filename, _msg, KLIST_FFL_HERE)
extern K_ITEM *_first_in_ktree(K_TREE *root, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define first_in_ktree(_root, _ctx) _first_in_ktree(_root, _ctx, KLIST_FFL_HERE)
extern K_ITEM *_last_in_ktree(K_TREE *root, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define last_in_ktree(_root, _ctx) _last_in_ktree(_root, _ctx, KLIST_FFL_HERE)
extern K_TREE *_new_ktree(cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), KTREE_FFL_ARGS);
#define new_ktree(_cmp_funct) _new_ktree(_cmp_funct, KLIST_FFL_HERE)
extern void _dump_ktree(K_TREE *tree, char *(*dsp_funct)(K_ITEM *), KTREE_FFL_ARGS);
#define dump_ktree(_tree, _dsp_funct) _dump_ktree(_tree, _dsp_funct, KLIST_FFL_HERE)
extern void _dsp_ktree(K_LIST *list, K_TREE *tree, char *filename, char *msg, KTREE_FFL_ARGS);
#define dsp_ktree(_list, _tree, _filename, _msg) _dsp_ktree(_list, _tree, _filename, _msg, KLIST_FFL_HERE)
extern K_ITEM *_first_in_ktree(K_TREE *tree, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define first_in_ktree(_tree, _ctx) _first_in_ktree(_tree, _ctx, KLIST_FFL_HERE)
extern K_ITEM *_last_in_ktree(K_TREE *tree, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define last_in_ktree(_tree, _ctx) _last_in_ktree(_tree, _ctx, KLIST_FFL_HERE)
extern K_ITEM *_next_in_ktree(K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define next_in_ktree(_ctx) _next_in_ktree(_ctx, KLIST_FFL_HERE)
extern K_ITEM *_prev_in_ktree(K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define prev_in_ktree(_ctx) _prev_in_ktree(_ctx, KLIST_FFL_HERE)
extern K_TREE *_add_to_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_func)(K_ITEM *, K_ITEM *), KTREE_FFL_ARGS);
#define add_to_ktree(_root, _data, _cmp_func) _add_to_ktree(_root, _data, _cmp_func, KLIST_FFL_HERE)
extern K_ITEM *_find_in_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define find_in_ktree(_root, _data, _cmp_funct, _ctx) _find_in_ktree(_root, _data, _cmp_funct, _ctx, KLIST_FFL_HERE)
extern K_ITEM *_find_after_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define find_after_in_ktree(_ktree, _data, _cmp_funct, _ctx) _find_after_in_ktree(_ktree, _data, _cmp_funct, _ctx, KLIST_FFL_HERE)
extern K_ITEM *_find_before_in_ktree(K_TREE *ktree, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define find_before_in_ktree(_ktree, _data, _cmp_funct, _ctx) _find_before_in_ktree(_ktree, _data, _cmp_funct, _ctx, KLIST_FFL_HERE)
extern K_TREE *_remove_from_ktree(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx, KTREE_FFL_ARGS);
extern K_TREE *_remove_from_ktree_free(K_TREE *root, K_ITEM *data, cmp_t (*cmp_funct)(K_ITEM *, K_ITEM *), KTREE_FFL_ARGS);
#define remove_from_ktree(_root, _data, _cmp_funct) _remove_from_ktree_free(_root, _data, _cmp_funct, KLIST_FFL_HERE)
extern K_TREE *_free_ktree(K_TREE *root, void (*free_funct)(void *), KTREE_FFL_ARGS);
#define free_ktree(_root, _free_funct) _free_ktree(_root, _free_funct, KLIST_FFL_HERE)
extern void _add_to_ktree(K_TREE *tree, K_ITEM *data, KTREE_FFL_ARGS);
#define add_to_ktree(_tree, _data) _add_to_ktree(_tree, _data, KLIST_FFL_HERE)
extern K_ITEM *_find_in_ktree(K_TREE *tree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define find_in_ktree(_tree, _data, _ctx) _find_in_ktree(_tree, _data, _ctx, KLIST_FFL_HERE)
extern K_ITEM *_find_after_in_ktree(K_TREE *ktree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define find_after_in_ktree(_ktree, _data, _ctx) _find_after_in_ktree(_ktree, _data, _ctx, KLIST_FFL_HERE)
extern K_ITEM *_find_before_in_ktree(K_TREE *ktree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
#define find_before_in_ktree(_ktree, _data, _ctx) _find_before_in_ktree(_ktree, _data, _ctx, KLIST_FFL_HERE)
extern void _remove_from_ktree(K_TREE *tree, K_ITEM *data, K_TREE_CTX *ctx, KTREE_FFL_ARGS);
extern void _remove_from_ktree_free(K_TREE *tree, K_ITEM *data, KTREE_FFL_ARGS);
#define remove_from_ktree(_tree, _data) _remove_from_ktree_free(_tree, _data, KLIST_FFL_HERE)
extern void _free_ktree(K_TREE *tree, void (*free_funct)(void *), KTREE_FFL_ARGS);
#define free_ktree(_tree, _free_funct) do { \
_free_ktree(_tree, _free_funct, KLIST_FFL_HERE); \
_tree = NULL; \
} while (0)
#endif

Loading…
Cancel
Save