Browse Source

ckdb - fix block tree corruptions

master
kanoi 10 years ago
parent
commit
13f50e3329
  1. 55
      src/ckdb.c

55
src/ckdb.c

@ -47,7 +47,7 @@
#define DB_VLOCK "1" #define DB_VLOCK "1"
#define DB_VERSION "0.9" #define DB_VERSION "0.9"
#define CKDB_VERSION DB_VERSION"-0.260" #define CKDB_VERSION DB_VERSION"-0.270"
#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__
@ -674,7 +674,8 @@ static const tv_t date_begin = { DATE_BEGIN, 0L };
#define PQPARAM14 PQPARAM8 ",$9,$10,$11,$12,$13,$14" #define PQPARAM14 PQPARAM8 ",$9,$10,$11,$12,$13,$14"
#define PQPARAM15 PQPARAM8 ",$9,$10,$11,$12,$13,$14,$15" #define PQPARAM15 PQPARAM8 ",$9,$10,$11,$12,$13,$14,$15"
#define PQPARAM16 PQPARAM8 ",$9,$10,$11,$12,$13,$14,$15,$16" #define PQPARAM16 PQPARAM8 ",$9,$10,$11,$12,$13,$14,$15,$16"
#define PQPARAM27 PQPARAM16 ",$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27" #define PQPARAM22 PQPARAM16 ",$17,$18,$19,$20,$21,$22"
#define PQPARAM27 PQPARAM22 ",$23,$24,$25,$26,$27"
#define PARCHK(_par, _params) do { \ #define PARCHK(_par, _params) do { \
if (_par != (int)(sizeof(_params)/sizeof(_params[0]))) { \ if (_par != (int)(sizeof(_params)/sizeof(_params[0]))) { \
@ -1302,7 +1303,9 @@ typedef struct blocks {
#define BLOCKS_ORPHAN_STR "O" #define BLOCKS_ORPHAN_STR "O"
#define BLOCKS_STATSPENDING FALSE_CHR #define BLOCKS_STATSPENDING FALSE_CHR
#define BLOCKS_STATSPENDING_STR FALSE_STR
#define BLOCKS_STATSCONFIRMED TRUE_CHR #define BLOCKS_STATSCONFIRMED TRUE_CHR
#define BLOCKS_STATSCONFIRMED_STR TRUE_STR
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";
@ -5413,9 +5416,10 @@ static void dsp_blocks(K_ITEM *item, FILE *stream)
dsp_hash(b->blockhash, hash_dsp, sizeof(hash_dsp)); dsp_hash(b->blockhash, hash_dsp, sizeof(hash_dsp));
tv_to_buf(&(b->createdate), createdate_buf, sizeof(createdate_buf)); tv_to_buf(&(b->createdate), createdate_buf, sizeof(createdate_buf));
tv_to_buf(&(b->expirydate), expirydate_buf, sizeof(expirydate_buf)); tv_to_buf(&(b->expirydate), expirydate_buf, sizeof(expirydate_buf));
fprintf(stream, " hi=%d hash='%.16s' uid=%"PRId64" w='%s' " fprintf(stream, " hi=%d hash='%.16s' conf=%s uid=%"PRId64
"cd=%s ed=%s\n", " w='%s' sconf=%s cd=%s ed=%s\n",
b->height, hash_dsp, b->userid, b->workername, b->height, hash_dsp, b->confirmed, b->userid,
b->workername, b->statsconfirmed,
createdate_buf, expirydate_buf); createdate_buf, expirydate_buf);
} }
} }
@ -5525,12 +5529,12 @@ static bool blocks_stats(PGconn *conn, int32_t height, char *blockhash,
K_RUNLOCK(blocks_free); K_RUNLOCK(blocks_free);
if (!old_b_item) { if (!old_b_item) {
LOGERR("%s(): Non-existent Block: %s/...%s", LOGERR("%s(): Non-existent Block: %d/...%s",
__func__, height, hash_dsp); __func__, height, hash_dsp);
return false; return false;
} }
DATA_BLOCKS_NULL(oldblocks, old_b_item); DATA_BLOCKS(oldblocks, old_b_item);
K_WLOCK(blocks_free); K_WLOCK(blocks_free);
b_item = k_unlink_head(blocks_free); b_item = k_unlink_head(blocks_free);
@ -5659,7 +5663,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
BLOCKS *row, *oldblocks; BLOCKS *row, *oldblocks;
USERS *users; USERS *users;
char *upd, *ins; char *upd, *ins;
char *params[11 + HISTORYDATECOUNT]; char *params[17 + HISTORYDATECOUNT];
bool ok = false, update_old = false; bool ok = false, update_old = false;
int par = 0; int par = 0;
char want = '?'; char want = '?';
@ -5678,14 +5682,16 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
dsp_hash(blockhash, hash_dsp, sizeof(hash_dsp)); dsp_hash(blockhash, hash_dsp, sizeof(hash_dsp));
K_WLOCK(blocks_free); K_RLOCK(blocks_free);
old_b_item = find_blocks(row->height, blockhash); old_b_item = find_blocks(row->height, blockhash);
K_RUNLOCK(blocks_free);
DATA_BLOCKS_NULL(oldblocks, old_b_item); DATA_BLOCKS_NULL(oldblocks, old_b_item);
switch (confirmed[0]) { switch (confirmed[0]) {
case BLOCKS_NEW: case BLOCKS_NEW:
// None should exist - so must be a duplicate // None should exist - so must be a duplicate
if (old_b_item) { if (old_b_item) {
K_WLOCK(blocks_free);
k_add_head(blocks_free, b_item); k_add_head(blocks_free, b_item);
K_WUNLOCK(blocks_free); K_WUNLOCK(blocks_free);
if (!igndup) { if (!igndup) {
@ -5699,7 +5705,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
} }
return true; return true;
} }
K_WUNLOCK(blocks_free);
K_RLOCK(users_free); K_RLOCK(users_free);
u_item = find_users(username); u_item = find_users(username);
@ -5719,6 +5724,13 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
STRNCPY(row->nonce2, nonce2); STRNCPY(row->nonce2, nonce2);
STRNCPY(row->nonce, nonce); STRNCPY(row->nonce, nonce);
TXT_TO_BIGINT("reward", reward, row->reward); TXT_TO_BIGINT("reward", reward, row->reward);
// Specify them
row->diffacc = 0;
row->diffinv = 0;
row->shareacc = 0;
row->shareinv = 0;
row->elapsed = 0;
STRNCPY(row->statsconfirmed, BLOCKS_STATSPENDING_STR);
HISTORYDATEINIT(row, cd, by, code, inet); HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row); HISTORYDATETRANSFER(trf_root, row);
@ -5735,14 +5747,21 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
params[par++] = str_to_buf(row->nonce, NULL, 0); params[par++] = str_to_buf(row->nonce, NULL, 0);
params[par++] = bigint_to_buf(row->reward, NULL, 0); params[par++] = bigint_to_buf(row->reward, NULL, 0);
params[par++] = str_to_buf(row->confirmed, NULL, 0); params[par++] = str_to_buf(row->confirmed, NULL, 0);
params[par++] = double_to_buf(row->diffacc, NULL, 0);
params[par++] = double_to_buf(row->diffinv, NULL, 0);
params[par++] = double_to_buf(row->shareacc, NULL, 0);
params[par++] = double_to_buf(row->shareinv, NULL, 0);
params[par++] = bigint_to_buf(row->elapsed, NULL, 0);
params[par++] = str_to_buf(row->statsconfirmed, NULL, 0);
HISTORYDATEPARAMS(params, par, row); HISTORYDATEPARAMS(params, par, row);
PARCHK(par, params); PARCHK(par, params);
// db default stats values
ins = "insert into blocks " ins = "insert into blocks "
"(height,blockhash,workinfoid,userid,workername," "(height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed" "clientid,enonce1,nonce2,nonce,reward,confirmed,"
HISTORYDATECONTROL ") values (" PQPARAM16 ")"; "diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed"
HISTORYDATECONTROL ") values (" PQPARAM22 ")";
if (conn == NULL) { if (conn == NULL) {
conn = dbconnect(); conn = dbconnect();
@ -5760,7 +5779,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
case BLOCKS_42: case BLOCKS_42:
// These shouldn't be possible until startup completes // These shouldn't be possible until startup completes
if (!startup_complete) { if (!startup_complete) {
K_WUNLOCK(blocks_free);
tv_to_buf(cd, cd_buf, sizeof(cd_buf)); tv_to_buf(cd, cd_buf, sizeof(cd_buf));
LOGERR("%s(): Status: %s invalid during startup. " LOGERR("%s(): Status: %s invalid during startup. "
"Ignored: Block: %s/...%s/%s", "Ignored: Block: %s/...%s/%s",
@ -5772,7 +5790,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
want = BLOCKS_CONFIRM; want = BLOCKS_CONFIRM;
case BLOCKS_CONFIRM: case BLOCKS_CONFIRM:
if (!old_b_item) { if (!old_b_item) {
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 %s a non-existent Block: %s/...%s/%s", LOGERR("%s(): Can't %s a non-existent Block: %s/...%s/%s",
__func__, blocks_confirmed(confirmed), __func__, blocks_confirmed(confirmed),
@ -5782,8 +5799,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
if (confirmed[0] == BLOCKS_CONFIRM) if (confirmed[0] == BLOCKS_CONFIRM)
want = BLOCKS_NEW; want = BLOCKS_NEW;
if (oldblocks->confirmed[0] != want) { if (oldblocks->confirmed[0] != want) {
k_add_head(blocks_free, b_item);
K_WUNLOCK(blocks_free);
// No mismatch messages during startup // No mismatch messages during startup
if (startup_complete) { if (startup_complete) {
tv_to_buf(cd, cd_buf, sizeof(cd_buf)); tv_to_buf(cd, cd_buf, sizeof(cd_buf));
@ -5796,7 +5811,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
} }
goto flail; goto flail;
} }
K_WUNLOCK(blocks_free);
upd = "update blocks set expirydate=$1 where blockhash=$2 and expirydate=$3"; upd = "update blocks set expirydate=$1 where blockhash=$2 and expirydate=$3";
par = 0; par = 0;
@ -5899,7 +5913,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
res = PQexec(conn, "Commit", CKPQ_WRITE); res = PQexec(conn, "Commit", CKPQ_WRITE);
break; break;
default: default:
K_WUNLOCK(blocks_free);
LOGERR("%s(): %s.failed.invalid confirm='%s'", LOGERR("%s(): %s.failed.invalid confirm='%s'",
__func__, id, confirmed); __func__, id, confirmed);
goto flail; goto flail;
@ -6027,7 +6040,6 @@ static bool blocks_fill(PGconn *conn)
n = PQntuples(res); n = PQntuples(res);
LOGDEBUG("%s(): tree build count %d", __func__, n); LOGDEBUG("%s(): tree build count %d", __func__, n);
ok = true; ok = true;
K_WLOCK(blocks_free);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
item = k_unlink_head(blocks_free); item = k_unlink_head(blocks_free);
DATA_BLOCKS(row, item); DATA_BLOCKS(row, item);
@ -6133,7 +6145,6 @@ static bool blocks_fill(PGconn *conn)
if (!ok) if (!ok)
k_add_head(blocks_free, item); k_add_head(blocks_free, item);
K_WUNLOCK(blocks_free);
PQclear(res); PQclear(res);
if (ok) { if (ok) {
@ -6148,10 +6159,8 @@ void blocks_reload()
{ {
PGconn *conn = dbconnect(); PGconn *conn = dbconnect();
K_WLOCK(blocks_free);
blocks_root = free_ktree(blocks_root, NULL); blocks_root = free_ktree(blocks_root, NULL);
k_list_transfer_to_head(blocks_store, blocks_free); k_list_transfer_to_head(blocks_store, blocks_free);
K_WUNLOCK(blocks_free);
blocks_fill(conn); blocks_fill(conn);

Loading…
Cancel
Save