|
|
@ -47,7 +47,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
#define DB_VLOCK "1" |
|
|
|
#define DB_VLOCK "1" |
|
|
|
#define DB_VERSION "0.7" |
|
|
|
#define DB_VERSION "0.7" |
|
|
|
#define CKDB_VERSION DB_VERSION"-0.102" |
|
|
|
#define CKDB_VERSION DB_VERSION"-0.106" |
|
|
|
|
|
|
|
|
|
|
|
#define WHERE_FFL " - from %s %s() line %d" |
|
|
|
#define WHERE_FFL " - from %s %s() line %d" |
|
|
|
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ |
|
|
|
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ |
|
|
@ -774,6 +774,7 @@ enum cmd_values { |
|
|
|
CMD_USERSTAT, |
|
|
|
CMD_USERSTAT, |
|
|
|
CMD_BLOCK, |
|
|
|
CMD_BLOCK, |
|
|
|
CMD_BLOCKLIST, |
|
|
|
CMD_BLOCKLIST, |
|
|
|
|
|
|
|
CMD_BLOCKSTATUS, |
|
|
|
CMD_NEWID, |
|
|
|
CMD_NEWID, |
|
|
|
CMD_PAYMENTS, |
|
|
|
CMD_PAYMENTS, |
|
|
|
CMD_WORKERS, |
|
|
|
CMD_WORKERS, |
|
|
@ -1187,10 +1188,18 @@ typedef struct blocks { |
|
|
|
#define DATA_BLOCKS(_item) ((BLOCKS *)(_item->data)) |
|
|
|
#define DATA_BLOCKS(_item) ((BLOCKS *)(_item->data)) |
|
|
|
|
|
|
|
|
|
|
|
#define BLOCKS_NEW 'n' |
|
|
|
#define BLOCKS_NEW 'n' |
|
|
|
|
|
|
|
#define BLOCKS_NEW_STR "n" |
|
|
|
#define BLOCKS_CONFIRM '1' |
|
|
|
#define BLOCKS_CONFIRM '1' |
|
|
|
|
|
|
|
#define BLOCKS_CONFIRM_STR "1" |
|
|
|
|
|
|
|
#define BLOCKS_42 'F' |
|
|
|
|
|
|
|
#define BLOCKS_42_STR "F" |
|
|
|
|
|
|
|
#define BLOCKS_ORPHAN 'O' |
|
|
|
|
|
|
|
#define BLOCKS_ORPHAN_STR "O" |
|
|
|
|
|
|
|
|
|
|
|
static const char *blocks_new = "New"; |
|
|
|
static const char *blocks_new = "New"; |
|
|
|
static const char *blocks_confirm = "1-Confirm"; |
|
|
|
static const char *blocks_confirm = "1-Confirm"; |
|
|
|
|
|
|
|
static const char *blocks_42 = "42-Confirm"; |
|
|
|
|
|
|
|
static const char *blocks_orphan = "Orphan"; |
|
|
|
static const char *blocks_unknown = "?Unknown?"; |
|
|
|
static const char *blocks_unknown = "?Unknown?"; |
|
|
|
|
|
|
|
|
|
|
|
#define KANO -27972 |
|
|
|
#define KANO -27972 |
|
|
@ -3640,6 +3649,7 @@ static void auto_age_older(PGconn *conn, int64_t workinfoid, char *poolinstance, |
|
|
|
char *by, char *code, char *inet, tv_t *cd) |
|
|
|
char *by, char *code, char *inet, tv_t *cd) |
|
|
|
{ |
|
|
|
{ |
|
|
|
static int64_t last_attempted_id = -1; |
|
|
|
static int64_t last_attempted_id = -1; |
|
|
|
|
|
|
|
static int64_t prev_found = 0; |
|
|
|
static int repeat; |
|
|
|
static int repeat; |
|
|
|
|
|
|
|
|
|
|
|
char min_buf[DATE_BUFSIZ], max_buf[DATE_BUFSIZ]; |
|
|
|
char min_buf[DATE_BUFSIZ], max_buf[DATE_BUFSIZ]; |
|
|
@ -3648,29 +3658,44 @@ static void auto_age_older(PGconn *conn, int64_t workinfoid, char *poolinstance, |
|
|
|
tv_t ss_first_min, ss_last_max; |
|
|
|
tv_t ss_first_min, ss_last_max; |
|
|
|
tv_t ss_first, ss_last; |
|
|
|
tv_t ss_first, ss_last; |
|
|
|
int32_t wid_count; |
|
|
|
int32_t wid_count; |
|
|
|
|
|
|
|
SHARESUMMARY sharesummary; |
|
|
|
K_TREE_CTX ctx[1]; |
|
|
|
K_TREE_CTX ctx[1]; |
|
|
|
K_ITEM *ss_item; |
|
|
|
K_ITEM look, *ss_item; |
|
|
|
int64_t age_id, do_id, to_id; |
|
|
|
int64_t age_id, do_id, to_id; |
|
|
|
bool ok; |
|
|
|
bool ok, found; |
|
|
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): %"PRId64, __func__, workinfoid); |
|
|
|
LOGDEBUG("%s(): workinfoid=%"PRId64" prev=%"PRId64, __func__, workinfoid, prev_found); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
age_id = prev_found; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find the oldest 'unaged' sharesummary < workinfoid and >= prev_found
|
|
|
|
|
|
|
|
sharesummary.workinfoid = prev_found; |
|
|
|
|
|
|
|
sharesummary.userid = -1; |
|
|
|
|
|
|
|
sharesummary.workername[0] = '\0'; |
|
|
|
|
|
|
|
look.data = (void *)(&sharesummary); |
|
|
|
|
|
|
|
ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &look, |
|
|
|
|
|
|
|
cmp_sharesummary_workinfoid, ctx); |
|
|
|
|
|
|
|
|
|
|
|
ss_first_min.tv_sec = ss_first_min.tv_usec = |
|
|
|
ss_first_min.tv_sec = ss_first_min.tv_usec = |
|
|
|
ss_last_max.tv_sec = ss_last_max.tv_usec = 0; |
|
|
|
ss_last_max.tv_sec = ss_last_max.tv_usec = 0; |
|
|
|
ss_count_tot = s_count_tot = s_diff_tot = 0; |
|
|
|
ss_count_tot = s_count_tot = s_diff_tot = 0; |
|
|
|
|
|
|
|
|
|
|
|
age_id = 0; |
|
|
|
found = false; |
|
|
|
// Find the oldest 'unaged' sharesummary < workinfoid
|
|
|
|
|
|
|
|
ss_item = first_in_ktree(sharesummary_workinfoid_root, ctx); |
|
|
|
|
|
|
|
while (ss_item && DATA_SHARESUMMARY(ss_item)->workinfoid < workinfoid) { |
|
|
|
while (ss_item && DATA_SHARESUMMARY(ss_item)->workinfoid < workinfoid) { |
|
|
|
if (DATA_SHARESUMMARY(ss_item)->complete[0] == SUMMARY_NEW) { |
|
|
|
if (DATA_SHARESUMMARY(ss_item)->complete[0] == SUMMARY_NEW) { |
|
|
|
age_id = DATA_SHARESUMMARY(ss_item)->workinfoid; |
|
|
|
age_id = DATA_SHARESUMMARY(ss_item)->workinfoid; |
|
|
|
|
|
|
|
prev_found = age_id; |
|
|
|
|
|
|
|
found = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
ss_item = next_in_ktree(ctx); |
|
|
|
ss_item = next_in_ktree(ctx); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): age_id=%"PRId64, __func__, age_id); |
|
|
|
LOGDEBUG("%s(): age_id=%"PRId64" found=%d", __func__, age_id, found); |
|
|
|
|
|
|
|
// Don't repeat searching old items to avoid accessing their ram
|
|
|
|
|
|
|
|
if (!found) |
|
|
|
|
|
|
|
prev_found = workinfoid; |
|
|
|
|
|
|
|
else { |
|
|
|
/* Process all the consecutive sharesummaries that's aren't aged
|
|
|
|
/* Process all the consecutive sharesummaries that's aren't aged
|
|
|
|
* This way we find each oldest 'batch' of sharesummaries that have |
|
|
|
* This way we find each oldest 'batch' of sharesummaries that have |
|
|
|
* been missed and can report the range of data that was aged, |
|
|
|
* been missed and can report the range of data that was aged, |
|
|
@ -3678,7 +3703,6 @@ static void auto_age_older(PGconn *conn, int64_t workinfoid, char *poolinstance, |
|
|
|
* from the last time ckpool stopped |
|
|
|
* from the last time ckpool stopped |
|
|
|
* Each next group of unaged sharesummaries following this, will be |
|
|
|
* Each next group of unaged sharesummaries following this, will be |
|
|
|
* picked up by each next aging */ |
|
|
|
* picked up by each next aging */ |
|
|
|
if (age_id) { |
|
|
|
|
|
|
|
wid_count = 0; |
|
|
|
wid_count = 0; |
|
|
|
do_id = age_id; |
|
|
|
do_id = age_id; |
|
|
|
to_id = 0; |
|
|
|
to_id = 0; |
|
|
@ -4851,11 +4875,14 @@ static const char *blocks_confirmed(char *confirmed) |
|
|
|
return blocks_new; |
|
|
|
return blocks_new; |
|
|
|
case BLOCKS_CONFIRM: |
|
|
|
case BLOCKS_CONFIRM: |
|
|
|
return blocks_confirm; |
|
|
|
return blocks_confirm; |
|
|
|
|
|
|
|
case BLOCKS_42: |
|
|
|
|
|
|
|
return blocks_42; |
|
|
|
|
|
|
|
case BLOCKS_ORPHAN: |
|
|
|
|
|
|
|
return blocks_orphan; |
|
|
|
} |
|
|
|
} |
|
|
|
return blocks_unknown; |
|
|
|
return blocks_unknown; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: determine how to handle orphan blocks after 1 confirm
|
|
|
|
|
|
|
|
static bool blocks_add(PGconn *conn, char *height, char *blockhash, |
|
|
|
static bool blocks_add(PGconn *conn, char *height, char *blockhash, |
|
|
|
char *confirmed, char *workinfoid, char *username, |
|
|
|
char *confirmed, char *workinfoid, char *username, |
|
|
|
char *workername, char *clientid, char *enonce1, |
|
|
|
char *workername, char *clientid, char *enonce1, |
|
|
@ -4875,6 +4902,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, |
|
|
|
char *params[11 + HISTORYDATECOUNT]; |
|
|
|
char *params[11 + HISTORYDATECOUNT]; |
|
|
|
bool ok = false, update_old = false; |
|
|
|
bool ok = false, update_old = false; |
|
|
|
int par = 0; |
|
|
|
int par = 0; |
|
|
|
|
|
|
|
char want = '?'; |
|
|
|
int n; |
|
|
|
int n; |
|
|
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): add", __func__); |
|
|
|
LOGDEBUG("%s(): add", __func__); |
|
|
@ -4969,32 +4997,46 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, |
|
|
|
goto unparam; |
|
|
|
goto unparam; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case BLOCKS_ORPHAN: |
|
|
|
|
|
|
|
case BLOCKS_42: |
|
|
|
|
|
|
|
// These shouldn't be possible until startup completes
|
|
|
|
|
|
|
|
if (!startup_complete) { |
|
|
|
|
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
|
|
|
|
tv_to_buf(cd, cd_buf, sizeof(cd_buf)); |
|
|
|
|
|
|
|
LOGERR("%s(): Status: %s invalid during startup. " |
|
|
|
|
|
|
|
"Ignored: Block: %s/...%s/%s", |
|
|
|
|
|
|
|
__func__, |
|
|
|
|
|
|
|
blocks_confirmed(confirmed), |
|
|
|
|
|
|
|
height, blk_dsp, cd_buf); |
|
|
|
|
|
|
|
goto flail; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
want = BLOCKS_CONFIRM; |
|
|
|
case BLOCKS_CONFIRM: |
|
|
|
case BLOCKS_CONFIRM: |
|
|
|
if (!old_b_item) { |
|
|
|
if (!old_b_item) { |
|
|
|
k_add_head(blocks_free, b_item); |
|
|
|
|
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
tv_to_buf(cd, cd_buf, sizeof(cd_buf)); |
|
|
|
tv_to_buf(cd, cd_buf, sizeof(cd_buf)); |
|
|
|
LOGERR("%s(): Can't confirm a non-existent block, Status: " |
|
|
|
LOGERR("%s(): Can't %s a non-existent Block: %s/...%s/%s", |
|
|
|
"%s, Block: %s/...%s/%s", |
|
|
|
|
|
|
|
__func__, blocks_confirmed(confirmed), |
|
|
|
__func__, blocks_confirmed(confirmed), |
|
|
|
height, blk_dsp, cd_buf); |
|
|
|
height, blk_dsp, cd_buf); |
|
|
|
return false; |
|
|
|
goto flail; |
|
|
|
} |
|
|
|
} |
|
|
|
/* This will also treat an unrecognised 'confirmed' as a
|
|
|
|
if (confirmed[0] == BLOCKS_CONFIRM) |
|
|
|
* duplicate since they shouldn't exist anyway */ |
|
|
|
want = BLOCKS_NEW; |
|
|
|
if (DATA_BLOCKS(old_b_item)->confirmed[0] != BLOCKS_NEW) { |
|
|
|
if (DATA_BLOCKS(old_b_item)->confirmed[0] != want) { |
|
|
|
k_add_head(blocks_free, b_item); |
|
|
|
k_add_head(blocks_free, b_item); |
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
if (!igndup || DATA_BLOCKS(old_b_item)->confirmed[0] != BLOCKS_CONFIRM) { |
|
|
|
// No mismatch messages during startup
|
|
|
|
|
|
|
|
if (!startup_complete) { |
|
|
|
tv_to_buf(cd, cd_buf, sizeof(cd_buf)); |
|
|
|
tv_to_buf(cd, cd_buf, sizeof(cd_buf)); |
|
|
|
LOGERR("%s(): Duplicate (%s) blocks ignored, Status: " |
|
|
|
LOGERR("%s(): Request Status: %s requires Status: %s. " |
|
|
|
"%s, Block: %s/...%s/%s", |
|
|
|
"Ignored: Status: %s, Block: %s/...%s/%s", |
|
|
|
__func__, |
|
|
|
__func__, |
|
|
|
blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed), |
|
|
|
|
|
|
|
blocks_confirmed(confirmed), |
|
|
|
blocks_confirmed(confirmed), |
|
|
|
|
|
|
|
blocks_confirmed(BLOCKS_CONFIRM_STR), |
|
|
|
|
|
|
|
blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed), |
|
|
|
height, blk_dsp, cd_buf); |
|
|
|
height, blk_dsp, cd_buf); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
goto flail; |
|
|
|
} |
|
|
|
} |
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
|
|
|
|
|
|
|
@ -5102,15 +5144,19 @@ flail: |
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
K_WUNLOCK(blocks_free); |
|
|
|
|
|
|
|
|
|
|
|
if (ok) { |
|
|
|
if (ok) { |
|
|
|
char tmp[256]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (confirmed[0] != BLOCKS_NEW) |
|
|
|
|
|
|
|
tmp[0] = '\0'; |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
char pct[16] = "?"; |
|
|
|
char pct[16] = "?"; |
|
|
|
char est[16] = ""; |
|
|
|
char est[16] = ""; |
|
|
|
K_ITEM *w_item; |
|
|
|
K_ITEM *w_item; |
|
|
|
|
|
|
|
char tmp[256]; |
|
|
|
|
|
|
|
bool blk; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (confirmed[0]) { |
|
|
|
|
|
|
|
case BLOCKS_NEW: |
|
|
|
|
|
|
|
blk = true; |
|
|
|
|
|
|
|
tmp[0] = '\0'; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case BLOCKS_CONFIRM: |
|
|
|
|
|
|
|
blk = true; |
|
|
|
w_item = find_workinfo(DATA_BLOCKS(b_item)->workinfoid); |
|
|
|
w_item = find_workinfo(DATA_BLOCKS(b_item)->workinfoid); |
|
|
|
if (w_item) { |
|
|
|
if (w_item) { |
|
|
|
char wdiffbin[TXT_SML+1]; |
|
|
|
char wdiffbin[TXT_SML+1]; |
|
|
@ -5136,10 +5182,17 @@ flail: |
|
|
|
pool.diffacc = pool.differr = |
|
|
|
pool.diffacc = pool.differr = |
|
|
|
pool.best_sdiff = 0.0; |
|
|
|
pool.best_sdiff = 0.0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case BLOCKS_ORPHAN: |
|
|
|
|
|
|
|
case BLOCKS_42: |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
blk = false; |
|
|
|
|
|
|
|
tmp[0] = '\0'; |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
LOGWARNING("%s(): BLOCK! Status: %s, Block: %s/...%s%s", |
|
|
|
LOGWARNING("%s(): %sStatus: %s, Block: %s/...%s%s", |
|
|
|
__func__, |
|
|
|
__func__, blk ? "BLOCK! " : "", |
|
|
|
blocks_confirmed(confirmed), |
|
|
|
blocks_confirmed(confirmed), |
|
|
|
height, blk_dsp, tmp); |
|
|
|
height, blk_dsp, tmp); |
|
|
|
} |
|
|
|
} |
|
|
@ -7220,20 +7273,18 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, |
|
|
|
char *buf; |
|
|
|
char *buf; |
|
|
|
size_t len, off; |
|
|
|
size_t len, off; |
|
|
|
int rows; |
|
|
|
int rows; |
|
|
|
int32_t height; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): cmd '%s'", __func__, cmd); |
|
|
|
LOGDEBUG("%s(): cmd '%s'", __func__, cmd); |
|
|
|
|
|
|
|
|
|
|
|
b_item = last_in_ktree(blocks_root, ctx); |
|
|
|
|
|
|
|
APPEND_REALLOC_INIT(buf, off, len); |
|
|
|
APPEND_REALLOC_INIT(buf, off, len); |
|
|
|
APPEND_REALLOC(buf, off, len, "ok."); |
|
|
|
APPEND_REALLOC(buf, off, len, "ok."); |
|
|
|
rows = 0; |
|
|
|
rows = 0; |
|
|
|
height = -1; |
|
|
|
K_RLOCK(blocks_free); |
|
|
|
|
|
|
|
b_item = last_in_ktree(blocks_root, ctx); |
|
|
|
while (b_item && rows < 42) { |
|
|
|
while (b_item && rows < 42) { |
|
|
|
if (height != DATA_BLOCKS(b_item)->height) { |
|
|
|
if (CURRENT(&(DATA_BLOCKS(b_item)->expirydate))) { |
|
|
|
height = DATA_BLOCKS(b_item)->height; |
|
|
|
int_to_buf(DATA_BLOCKS(b_item)->height, reply, sizeof(reply)); |
|
|
|
|
|
|
|
snprintf(tmp, sizeof(tmp), "height%d=%s%c", rows, reply, FLDSEP); |
|
|
|
snprintf(tmp, sizeof(tmp), "height%d=%d%c", rows, height, FLDSEP); |
|
|
|
|
|
|
|
APPEND_REALLOC(buf, off, len, tmp); |
|
|
|
APPEND_REALLOC(buf, off, len, tmp); |
|
|
|
|
|
|
|
|
|
|
|
str_to_buf(DATA_BLOCKS(b_item)->blockhash, reply, sizeof(reply)); |
|
|
|
str_to_buf(DATA_BLOCKS(b_item)->blockhash, reply, sizeof(reply)); |
|
|
@ -7266,6 +7317,7 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, |
|
|
|
} |
|
|
|
} |
|
|
|
b_item = prev_in_ktree(ctx); |
|
|
|
b_item = prev_in_ktree(ctx); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
K_RUNLOCK(blocks_free); |
|
|
|
snprintf(tmp, sizeof(tmp), "rows=%d", rows); |
|
|
|
snprintf(tmp, sizeof(tmp), "rows=%d", rows); |
|
|
|
APPEND_REALLOC(buf, off, len, tmp); |
|
|
|
APPEND_REALLOC(buf, off, len, tmp); |
|
|
|
|
|
|
|
|
|
|
@ -7273,6 +7325,90 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, |
|
|
|
return buf; |
|
|
|
return buf; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *cmd_blockstatus(__maybe_unused PGconn *conn, char *cmd, char *id, |
|
|
|
|
|
|
|
tv_t *now, char *by, char *code, char *inet, |
|
|
|
|
|
|
|
__maybe_unused tv_t *cd, K_TREE *trf_root) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
K_ITEM *i_height, *i_blockhash, *i_action; |
|
|
|
|
|
|
|
char reply[1024] = ""; |
|
|
|
|
|
|
|
size_t siz = sizeof(reply); |
|
|
|
|
|
|
|
K_ITEM *b_item; |
|
|
|
|
|
|
|
BLOCKS *blocks; |
|
|
|
|
|
|
|
int32_t height; |
|
|
|
|
|
|
|
char *action; |
|
|
|
|
|
|
|
bool ok = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOGDEBUG("%s(): cmd '%s'", __func__, cmd); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i_height = require_name(trf_root, "height", 1, NULL, reply, siz); |
|
|
|
|
|
|
|
if (!i_height) |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TXT_TO_INT("height", DATA_TRANSFER(i_height)->data, height); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i_blockhash = require_name(trf_root, "blockhash", 1, NULL, reply, siz); |
|
|
|
|
|
|
|
if (!i_blockhash) |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i_action = require_name(trf_root, "action", 1, NULL, reply, siz); |
|
|
|
|
|
|
|
if (!i_action) |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
action = DATA_TRANSFER(i_action)->data; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
K_RLOCK(blocks_free); |
|
|
|
|
|
|
|
b_item = find_blocks(height, DATA_TRANSFER(i_blockhash)->data); |
|
|
|
|
|
|
|
K_RUNLOCK(blocks_free); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!b_item) { |
|
|
|
|
|
|
|
snprintf(reply, siz, "ERR.unknown block"); |
|
|
|
|
|
|
|
LOGERR("%s.%s", id, reply); |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
blocks = DATA_BLOCKS(b_item); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (strcasecmp(action, "orphan") == 0) { |
|
|
|
|
|
|
|
switch (blocks->confirmed[0]) { |
|
|
|
|
|
|
|
case BLOCKS_NEW: |
|
|
|
|
|
|
|
case BLOCKS_CONFIRM: |
|
|
|
|
|
|
|
ok = blocks_add(conn, DATA_TRANSFER(i_height)->data, |
|
|
|
|
|
|
|
blocks->blockhash, |
|
|
|
|
|
|
|
BLOCKS_ORPHAN_STR, |
|
|
|
|
|
|
|
EMPTY, EMPTY, EMPTY, EMPTY, |
|
|
|
|
|
|
|
EMPTY, EMPTY, EMPTY, EMPTY, |
|
|
|
|
|
|
|
by, code, inet, now, false, id, |
|
|
|
|
|
|
|
trf_root); |
|
|
|
|
|
|
|
if (!ok) { |
|
|
|
|
|
|
|
snprintf(reply, siz, |
|
|
|
|
|
|
|
"DBE.action '%s'", |
|
|
|
|
|
|
|
action); |
|
|
|
|
|
|
|
LOGERR("%s.%s", id, reply); |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// TODO: reset the share counter?
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
snprintf(reply, siz, |
|
|
|
|
|
|
|
"ERR.invalid action '%.*s%s' for block state '%s'", |
|
|
|
|
|
|
|
CMD_SIZ, action, |
|
|
|
|
|
|
|
(strlen(action) > CMD_SIZ) ? "..." : "", |
|
|
|
|
|
|
|
blocks_confirmed(blocks->confirmed)); |
|
|
|
|
|
|
|
LOGERR("%s.%s", id, reply); |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
snprintf(reply, siz, "ERR.unknown action '%s'", |
|
|
|
|
|
|
|
DATA_TRANSFER(i_action)->data); |
|
|
|
|
|
|
|
LOGERR("%s.%s", id, reply); |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
snprintf(reply, siz, "ok.%s %d", DATA_TRANSFER(i_action)->data, height); |
|
|
|
|
|
|
|
LOGDEBUG("%s.%s", id, reply); |
|
|
|
|
|
|
|
return strdup(reply); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static char *cmd_newid(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, |
|
|
|
static char *cmd_newid(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, |
|
|
|
char *code, char *inet, __maybe_unused tv_t *cd, |
|
|
|
char *code, char *inet, __maybe_unused tv_t *cd, |
|
|
|
K_TREE *trf_root) |
|
|
|
K_TREE *trf_root) |
|
|
@ -8835,6 +8971,7 @@ static struct CMDS { |
|
|
|
{ CMD_USERSTAT, "userstats", false, true, cmd_userstats, ACCESS_POOL }, |
|
|
|
{ CMD_USERSTAT, "userstats", false, true, cmd_userstats, ACCESS_POOL }, |
|
|
|
{ CMD_BLOCK, "block", false, true, cmd_blocks, ACCESS_POOL }, |
|
|
|
{ CMD_BLOCK, "block", false, true, cmd_blocks, ACCESS_POOL }, |
|
|
|
{ CMD_BLOCKLIST,"blocklist", false, false, cmd_blocklist, ACCESS_WEB }, |
|
|
|
{ CMD_BLOCKLIST,"blocklist", false, false, cmd_blocklist, ACCESS_WEB }, |
|
|
|
|
|
|
|
{ CMD_BLOCKSTATUS,"blockstatus",false, false, cmd_blockstatus,ACCESS_WEB }, |
|
|
|
{ CMD_NEWID, "newid", false, false, cmd_newid, ACCESS_SYSTEM }, |
|
|
|
{ CMD_NEWID, "newid", false, false, cmd_newid, ACCESS_SYSTEM }, |
|
|
|
{ CMD_PAYMENTS, "payments", false, false, cmd_payments, ACCESS_WEB }, |
|
|
|
{ CMD_PAYMENTS, "payments", false, false, cmd_payments, ACCESS_WEB }, |
|
|
|
{ CMD_WORKERS, "workers", false, false, cmd_workers, ACCESS_WEB }, |
|
|
|
{ CMD_WORKERS, "workers", false, false, cmd_workers, ACCESS_WEB }, |
|
|
@ -9581,6 +9718,7 @@ static void *socketer(__maybe_unused void *arg) |
|
|
|
case CMD_PAYMENTS: |
|
|
|
case CMD_PAYMENTS: |
|
|
|
case CMD_PPLNS: |
|
|
|
case CMD_PPLNS: |
|
|
|
case CMD_DSP: |
|
|
|
case CMD_DSP: |
|
|
|
|
|
|
|
case CMD_BLOCKSTATUS: |
|
|
|
if (!startup_complete) { |
|
|
|
if (!startup_complete) { |
|
|
|
snprintf(reply, sizeof(reply), |
|
|
|
snprintf(reply, sizeof(reply), |
|
|
|
"%s.%ld.loading.%s", |
|
|
|
"%s.%ld.loading.%s", |
|
|
@ -9685,8 +9823,11 @@ static void *socketer(__maybe_unused void *arg) |
|
|
|
} |
|
|
|
} |
|
|
|
K_WLOCK(transfer_free); |
|
|
|
K_WLOCK(transfer_free); |
|
|
|
k_list_transfer_to_head(trf_store, transfer_free); |
|
|
|
k_list_transfer_to_head(trf_store, transfer_free); |
|
|
|
K_WUNLOCK(transfer_free); |
|
|
|
|
|
|
|
trf_store = k_free_store(trf_store); |
|
|
|
trf_store = k_free_store(trf_store); |
|
|
|
|
|
|
|
if (transfer_free->count == transfer_free->total && |
|
|
|
|
|
|
|
transfer_free->total > ALLOC_TRANSFER * 64) |
|
|
|
|
|
|
|
k_cull_list(transfer_free); |
|
|
|
|
|
|
|
K_WUNLOCK(transfer_free); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -9750,6 +9891,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) |
|
|
|
case CMD_NEWPASS: |
|
|
|
case CMD_NEWPASS: |
|
|
|
case CMD_CHKPASS: |
|
|
|
case CMD_CHKPASS: |
|
|
|
case CMD_BLOCKLIST: |
|
|
|
case CMD_BLOCKLIST: |
|
|
|
|
|
|
|
case CMD_BLOCKSTATUS: |
|
|
|
case CMD_NEWID: |
|
|
|
case CMD_NEWID: |
|
|
|
case CMD_PAYMENTS: |
|
|
|
case CMD_PAYMENTS: |
|
|
|
case CMD_WORKERS: |
|
|
|
case CMD_WORKERS: |
|
|
@ -10035,6 +10177,7 @@ static void *listener(void *arg) |
|
|
|
startup_complete = true; |
|
|
|
startup_complete = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!everyone_die) |
|
|
|
conn = dbconnect(); |
|
|
|
conn = dbconnect(); |
|
|
|
|
|
|
|
|
|
|
|
// Process queued work
|
|
|
|
// Process queued work
|
|
|
@ -10060,6 +10203,7 @@ static void *listener(void *arg) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (conn) |
|
|
|
PQfinish(conn); |
|
|
|
PQfinish(conn); |
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
@ -10601,6 +10745,7 @@ static struct option long_options[] = { |
|
|
|
{ "name", required_argument, 0, 'n' }, |
|
|
|
{ "name", required_argument, 0, 'n' }, |
|
|
|
{ "dbpass", required_argument, 0, 'p' }, |
|
|
|
{ "dbpass", required_argument, 0, 'p' }, |
|
|
|
{ "ckpool-logdir", required_argument, 0, 'r' }, |
|
|
|
{ "ckpool-logdir", required_argument, 0, 'r' }, |
|
|
|
|
|
|
|
{ "logdir", required_argument, 0, 'R' }, |
|
|
|
{ "sockdir", required_argument, 0, 's' }, |
|
|
|
{ "sockdir", required_argument, 0, 's' }, |
|
|
|
{ "dbuser", required_argument, 0, 'u' }, |
|
|
|
{ "dbuser", required_argument, 0, 'u' }, |
|
|
|
{ "version", no_argument, 0, 'v' }, |
|
|
|
{ "version", no_argument, 0, 'v' }, |
|
|
@ -10634,7 +10779,7 @@ int main(int argc, char **argv) |
|
|
|
memset(&ckp, 0, sizeof(ckp)); |
|
|
|
memset(&ckp, 0, sizeof(ckp)); |
|
|
|
ckp.loglevel = LOG_NOTICE; |
|
|
|
ckp.loglevel = LOG_NOTICE; |
|
|
|
|
|
|
|
|
|
|
|
while ((c = getopt_long(argc, argv, "c:d:hkl:n:p:r:s:u:vyY:", long_options, &i)) != -1) { |
|
|
|
while ((c = getopt_long(argc, argv, "c:d:hkl:n:p:r:R:s:u:vyY:", long_options, &i)) != -1) { |
|
|
|
switch(c) { |
|
|
|
switch(c) { |
|
|
|
case 'c': |
|
|
|
case 'c': |
|
|
|
ckp.config = strdup(optarg); |
|
|
|
ckp.config = strdup(optarg); |
|
|
@ -10686,6 +10831,9 @@ int main(int argc, char **argv) |
|
|
|
case 'r': |
|
|
|
case 'r': |
|
|
|
restorefrom = strdup(optarg); |
|
|
|
restorefrom = strdup(optarg); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'R': |
|
|
|
|
|
|
|
ckp.logdir = strdup(optarg); |
|
|
|
|
|
|
|
break; |
|
|
|
case 's': |
|
|
|
case 's': |
|
|
|
ckp.socket_dir = strdup(optarg); |
|
|
|
ckp.socket_dir = strdup(optarg); |
|
|
|
break; |
|
|
|
break; |
|
|
|