Browse Source

ckdb - cmd_query to return various data in ckdb

master
kanoi 9 years ago
parent
commit
915ce9eb77
  1. 4
      src/ckdb.c
  2. 5
      src/ckdb.h
  3. 485
      src/ckdb_cmd.c
  4. 7
      src/ckdb_data.c

4
src/ckdb.c

@ -2909,7 +2909,7 @@ static void summarise_blocks()
diffacc = diffinv = shareacc = shareinv = 0; diffacc = diffinv = shareacc = shareinv = 0;
elapsed = 0; elapsed = 0;
K_RLOCK(blocks_free); K_RLOCK(blocks_free);
b_prev = find_prev_blocks(blocks->height); b_prev = find_prev_blocks(blocks->height, NULL);
K_RUNLOCK(blocks_free); K_RUNLOCK(blocks_free);
if (!b_prev) { if (!b_prev) {
wi_start = 0; wi_start = 0;
@ -4128,6 +4128,7 @@ static void *socketer(__maybe_unused void *arg)
/* Process, but reject (loading) until startup_complete /* Process, but reject (loading) until startup_complete
* and don't test for duplicates */ * and don't test for duplicates */
case CMD_MARKS: case CMD_MARKS:
case CMD_QUERY:
if (!startup_complete) { if (!startup_complete) {
snprintf(reply, sizeof(reply), snprintf(reply, sizeof(reply),
"%s.%ld.loading.%s", "%s.%ld.loading.%s",
@ -4356,6 +4357,7 @@ static void reload_line(PGconn *conn, char *filename, uint64_t count, char *buf)
case CMD_SHSTA: case CMD_SHSTA:
case CMD_USERINFO: case CMD_USERINFO:
case CMD_BTCSET: case CMD_BTCSET:
case CMD_QUERY:
LOGERR("%s() INVALID message line %"PRIu64 LOGERR("%s() INVALID message line %"PRIu64
" ignored '%.42s...", " ignored '%.42s...",
__func__, count, __func__, count,

5
src/ckdb.h

@ -55,7 +55,7 @@
#define DB_VLOCK "1" #define DB_VLOCK "1"
#define DB_VERSION "1.0.3" #define DB_VERSION "1.0.3"
#define CKDB_VERSION DB_VERSION"-1.334" #define CKDB_VERSION DB_VERSION"-1.340"
#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__
@ -410,6 +410,7 @@ enum cmd_values {
CMD_SHSTA, CMD_SHSTA,
CMD_USERINFO, CMD_USERINFO,
CMD_BTCSET, CMD_BTCSET,
CMD_QUERY,
CMD_END CMD_END
}; };
@ -2332,7 +2333,7 @@ extern double _blockhash_diff(char *hash, WHERE_FFL_ARGS);
extern void dsp_blocks(K_ITEM *item, FILE *stream); extern void dsp_blocks(K_ITEM *item, FILE *stream);
extern cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b);
extern K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx); extern K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx);
extern K_ITEM *find_prev_blocks(int32_t height); extern K_ITEM *find_prev_blocks(int32_t height, K_TREE_CTX *ctx);
extern const char *blocks_confirmed(char *confirmed); extern const char *blocks_confirmed(char *confirmed);
extern void zero_on_new_block(); extern void zero_on_new_block();
extern void set_block_share_counters(); extern void set_block_share_counters();

485
src/ckdb_cmd.c

@ -5795,7 +5795,7 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id,
TXT_TO_INT("height", transfer_data(i_height), TXT_TO_INT("height", transfer_data(i_height),
height); height);
K_RLOCK(blocks_free); K_RLOCK(blocks_free);
b_item = find_prev_blocks(height+1); b_item = find_prev_blocks(height+1, NULL);
K_RUNLOCK(blocks_free); K_RUNLOCK(blocks_free);
if (b_item) { if (b_item) {
DATA_BLOCKS(blocks, b_item); DATA_BLOCKS(blocks, b_item);
@ -6571,6 +6571,488 @@ static char *cmd_btcset(__maybe_unused PGconn *conn, char *cmd, char *id,
return strdup(buf); return strdup(buf);
} }
/* Query CKDB for certain information
* See each string compare below of 'request' for the list of queries
* For non-error conditions, rows=0 means there were no matching results
* for the request, and rows=n is placed last in the reply */
static char *cmd_query(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused tv_t *now, __maybe_unused char *by,
__maybe_unused char *code, __maybe_unused char *inet,
__maybe_unused tv_t *cd, K_TREE *trf_root)
{
K_TREE_CTX ctx[1];
char cd_buf[DATE_BUFSIZ];
char reply[1024] = "";
size_t siz = sizeof(reply);
char tmp[1024] = "";
char msg[1024] = "";
char *buf = NULL;
size_t len, off;
K_ITEM *i_request;
char *request;
bool ok = false;
int rows = 0;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
i_request = require_name(trf_root, "request", 1, NULL, reply, siz);
if (!i_request)
return strdup(reply);
request = transfer_data(i_request);
APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok.");
if (strcasecmp(request, "block") == 0) {
/* return DB information for the blocks with height=value
* if expired= is present, it will also return expired records */
K_ITEM *i_height, *i_expired, *b_item;
bool expired = false;
BLOCKS *blocks;
int32_t height;
i_height = require_name(trf_root, "height",
1, (char *)intpatt,
reply, siz);
if (!i_height)
return strdup(reply);
TXT_TO_INT("height", transfer_data(i_height), height);
i_expired = optional_name(trf_root, "expired",
0, NULL, reply, siz);
if (i_expired)
expired = true;
int_to_buf(height, reply, sizeof(reply));
snprintf(msg, sizeof(msg), "height=%s", reply);
K_RLOCK(blocks_free);
b_item = find_prev_blocks(height, ctx);
DATA_BLOCKS_NULL(blocks, b_item);
while (b_item && blocks->height <= height) {
if ((expired || CURRENT(&(blocks->expirydate))) &&
blocks->height == height) {
int_to_buf(blocks->height, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"height:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"blockhash:%d=%s%c",
rows, blocks->blockhash, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"confirmed:%d=%s%c",
rows, blocks->confirmed, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
tv_to_buf(&(blocks->expirydate), cd_buf,
sizeof(cd_buf));
snprintf(tmp, sizeof(tmp),
EDDB"_str:%d=%s%c",
rows, cd_buf, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
tv_to_buf(&(blocks->createdate), cd_buf,
sizeof(cd_buf));
snprintf(tmp, sizeof(tmp),
CDDB"_str:%d=%s%c",
rows, cd_buf, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
tv_to_buf(&(blocks->blockcreatedate), cd_buf,
sizeof(cd_buf));
snprintf(tmp, sizeof(tmp),
"block"CDDB"_str:%d=%s%c",
rows, cd_buf, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
bigint_to_buf(blocks->workinfoid, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"workinfoid:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
rows++;
}
b_item = next_in_ktree(ctx);
DATA_BLOCKS_NULL(blocks, b_item);
}
K_RUNLOCK(blocks_free);
snprintf(tmp, sizeof(tmp), "flds=%s%c",
"height,blockhash,confirmed,"EDDB"_str,"
CDDB"_str,block"CDDB"_str,workinfoid", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c",
"Blocks", FLDSEP, "", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
ok = true;
} else if (strcasecmp(request, "workinfo") == 0) {
/* return DB information for the workinfo with wid=value
* if expired= is present, it will also return expired records
* though ckdb doesn't expire workinfo records - only external
* pgsql scripts would do that to the DB, then ckdb would
* load them the next time it (re)starts */
K_ITEM *i_wid, *i_expired, *wi_item, *wm_item;
char ndiffbin[TXT_SML+1];
bool expired = false;
WORKINFO *workinfo;
WORKMARKERS *wm;
int64_t wid;
i_wid = require_name(trf_root, "wid",
1, (char *)intpatt,
reply, siz);
if (!i_wid)
return strdup(reply);
TXT_TO_BIGINT("wid", transfer_data(i_wid), wid);
i_expired = optional_name(trf_root, "expired",
0, NULL, reply, siz);
if (i_expired)
expired = true;
bigint_to_buf(wid, reply, sizeof(reply));
snprintf(msg, sizeof(msg), "wid=%s", reply);
/* We look for the 'next' (or last) workinfo then go backwards
* to ensure we find all expired records in case they
* were requested */
K_RLOCK(workinfo_free);
wi_item = next_workinfo(wid, ctx);
if (!wi_item)
wi_item = last_in_ktree(workinfo_root, ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
while (wi_item && workinfo->workinfoid >= wid) {
if ((expired || CURRENT(&(workinfo->expirydate))) &&
workinfo->workinfoid == wid) {
bigint_to_buf(workinfo->workinfoid,
reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"workinfoid:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
int_to_buf(coinbase1height(workinfo->coinbase1),
reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"height:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"prevhash:%d=%s%c",
rows, workinfo->prevhash, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
tv_to_buf(&(workinfo->expirydate), cd_buf,
sizeof(cd_buf));
snprintf(tmp, sizeof(tmp),
EDDB"_str:%d=%s%c",
rows, cd_buf, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
tv_to_buf(&(workinfo->createdate), cd_buf,
sizeof(cd_buf));
snprintf(tmp, sizeof(tmp),
CDDB"_str:%d=%s%c",
rows, cd_buf, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
hex2bin(ndiffbin, workinfo->bits, 4);
snprintf(tmp, sizeof(tmp),
"ndiff:%d=%.1f%c", rows,
diff_from_nbits(ndiffbin),
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"ppsvalue:%d=%.15f%c", rows,
workinfo_pps(wi_item,
workinfo->workinfoid,
true),
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
K_RLOCK(workmarkers_free);
wm_item = find_workmarkers(wid, false,
MARKER_PROCESSED,
NULL);
K_RUNLOCK(workmarkers_free);
if (!wm_item) {
snprintf(tmp, sizeof(tmp),
"markerid:%d=%c", rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"shift:%d=%c", rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"shiftend:%d=%c", rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"shiftstart:%d=%c", rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
} else {
DATA_WORKMARKERS(wm, wm_item);
bigint_to_buf(wm->markerid,
reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"markerid:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"shift:%d=%s%c",
rows, wm->description, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
bigint_to_buf(wm->workinfoidend,
reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"shiftend:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
bigint_to_buf(wm->workinfoidstart,
reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"shiftstart:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
}
rows++;
}
wi_item = prev_in_ktree(ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
}
K_RUNLOCK(workinfo_free);
snprintf(tmp, sizeof(tmp), "flds=%s%c",
"workinfoid,height,prevhash,"EDDB"_str,"CDDB"_str,"
"ndiff,ppsvalue,markerid,shift,shiftend,shiftstart",
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c",
"Workinfo", FLDSEP, "", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
ok = true;
} else if (strcasecmp(request, "range") == 0) {
/* Return the workinfoid range that has block height=height
* WARNING! This will traverse workinfo from the end back to
* the given height, and thus since workinfo is the 2nd
* largest tree, it may access swapped data if you request
* older data */
K_ITEM *i_height, *wi_item;
WORKINFO *workinfo;
int32_t height, this_height;
int64_t idend, idstt;
i_height = require_name(trf_root, "height",
1, (char *)intpatt,
reply, siz);
if (!i_height)
return strdup(reply);
TXT_TO_INT("height", transfer_data(i_height), height);
int_to_buf(height, reply, sizeof(reply));
snprintf(msg, sizeof(msg), "height=%s", reply);
idend = idstt = 0L;
/* Start from the last workinfo and continue until we get
* below block 'height' */
K_RLOCK(workinfo_free);
wi_item = last_in_ktree(workinfo_root, ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
while (wi_item) {
this_height = coinbase1height(workinfo->coinbase1);
if (this_height < height)
break;
if (CURRENT(&(workinfo->expirydate)) &&
this_height == height) {
if (idend == 0L)
idend = workinfo->workinfoid;
idstt = workinfo->workinfoid;
}
wi_item = prev_in_ktree(ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
}
K_RUNLOCK(workinfo_free);
int_to_buf(height, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "height:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
bigint_to_buf(idend, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "workinfoidend:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
bigint_to_buf(idstt, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "workinfoidstart:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
rows++;
snprintf(tmp, sizeof(tmp), "flds=%s%c",
"height,workinfoidend,workinfoidstart", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c",
"WorkinfoRange", FLDSEP, "", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
ok = true;
} else if (strcasecmp(request, "diff") == 0) {
/* return the details of the next diff change after
* block height=height
* WARNING! This will traverse workinfo from the end back to
* the given height, and thus since workinfo is the 2nd
* largest tree, it may access swapped data if you request
* older data */
K_ITEM *i_height, *wi_item;
WORKINFO *workinfo = NULL;
int32_t height, this_height;
char ndiffbin[TXT_SML+1];
char bits[TXT_SML+1];
bool got = false;
i_height = require_name(trf_root, "height",
1, (char *)intpatt,
reply, siz);
if (!i_height)
return strdup(reply);
TXT_TO_INT("height", transfer_data(i_height), height);
int_to_buf(height, reply, sizeof(reply));
snprintf(msg, sizeof(msg), "height=%s", reply);
snprintf(tmp, sizeof(tmp), "height0:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
/* Start from the last workinfo and continue until we get
* below block 'height' */
K_RLOCK(workinfo_free);
wi_item = last_in_ktree(workinfo_root, ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
while (wi_item) {
if (CURRENT(&(workinfo->expirydate))) {
this_height = coinbase1height(workinfo->coinbase1);
if (this_height < height)
break;
}
wi_item = prev_in_ktree(ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
}
// If we fell off the front use the first one
if (!wi_item)
wi_item = first_in_ktree(workinfo_root, ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
while (wi_item) {
if (CURRENT(&(workinfo->expirydate))) {
this_height = coinbase1height(workinfo->coinbase1);
if (this_height >= height)
break;
}
wi_item = next_in_ktree(ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
}
if (wi_item) {
DATA_WORKINFO(workinfo, wi_item);
this_height = coinbase1height(workinfo->coinbase1);
if (this_height == height) {
// We have our starting point
STRNCPY(bits, workinfo->bits);
got = true;
bigint_to_buf(workinfo->workinfoid,
reply, sizeof(reply));
snprintf(tmp, sizeof(tmp),
"workinfoid0:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
hex2bin(ndiffbin, workinfo->bits, 4);
snprintf(tmp, sizeof(tmp),
"ndiff0:%d=%.1f%c", rows,
diff_from_nbits(ndiffbin),
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
while (wi_item) {
if (CURRENT(&(workinfo->expirydate))) {
if (strcmp(bits, workinfo->bits) != 0)
break;
}
wi_item = next_in_ktree(ctx);
DATA_WORKINFO_NULL(workinfo, wi_item);
}
} else
wi_item = NULL;
}
K_RUNLOCK(workinfo_free);
if (!got) {
snprintf(tmp, sizeof(tmp), "workinfoid0:%d=%c",
rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "ndiff0:%d=%c",
rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
}
if (!wi_item) {
snprintf(tmp, sizeof(tmp), "height:%d=%c",
rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "workinfoid:%d=%c",
rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "ndiff:%d=%c",
rows, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
} else {
this_height = coinbase1height(workinfo->coinbase1);
int_to_buf(this_height, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "height:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
bigint_to_buf(workinfo->workinfoid,
reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "workinfoid:%d=%s%c",
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
hex2bin(ndiffbin, workinfo->bits, 4);
snprintf(tmp, sizeof(tmp), "ndiff:%d=%.1f%c",
rows,
diff_from_nbits(ndiffbin),
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
}
rows++;
snprintf(tmp, sizeof(tmp), "flds=%s%c",
"height0,workinfoid0,ndiff0,height,workinfo,ndiff",
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c",
"WorkinfoRange", FLDSEP, "", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
ok = true;
} else {
free(buf);
snprintf(reply, siz, "unknown request '%s'", request);
LOGERR("%s() %s.%s", __func__, id, reply);
return strdup(reply);
}
if (!ok) {
free(buf);
snprintf(reply, siz, "failed.%s%s%s",
request,
msg[0] ? " " : "",
msg[0] ? msg : "");
LOGERR("%s() %s.%s", __func__, id, reply);
return strdup(reply);
}
snprintf(tmp, sizeof(tmp), "rows=%d", rows);
APPEND_REALLOC(buf, off, len, tmp);
LOGWARNING("%s() %s.%s%s%s", __func__, id, request,
msg[0] ? " " : "",
msg[0] ? msg : "");
return buf;
}
/* The socket command format is as follows: /* The socket command format is as follows:
* Basic structure: * Basic structure:
* cmd.ID.fld1=value1 FLDSEP fld2=value2 FLDSEP fld3=... * cmd.ID.fld1=value1 FLDSEP fld2=value2 FLDSEP fld3=...
@ -6679,5 +7161,6 @@ struct CMDS ckdb_cmds[] = {
{ CMD_SHSTA, "shsta", true, false, cmd_shsta, SEQ_NONE, ACCESS_SYSTEM }, { CMD_SHSTA, "shsta", true, false, cmd_shsta, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_USERINFO, "userinfo", false, false, cmd_userinfo, SEQ_NONE, ACCESS_WEB }, { CMD_USERINFO, "userinfo", false, false, cmd_userinfo, SEQ_NONE, ACCESS_WEB },
{ CMD_BTCSET, "btcset", false, false, cmd_btcset, SEQ_NONE, ACCESS_SYSTEM }, { CMD_BTCSET, "btcset", false, false, cmd_btcset, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_QUERY, "query", false, false, cmd_query, SEQ_NONE, ACCESS_SYSTEM },
{ CMD_END, NULL, false, false, NULL, SEQ_NONE, 0 } { CMD_END, NULL, false, false, NULL, SEQ_NONE, 0 }
}; };

7
src/ckdb_data.c

@ -2702,12 +2702,15 @@ K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx)
} }
// Must be R or W locked before call // Must be R or W locked before call
K_ITEM *find_prev_blocks(int32_t height) K_ITEM *find_prev_blocks(int32_t height, K_TREE_CTX *ctx)
{ {
BLOCKS lookblocks, *blocks; BLOCKS lookblocks, *blocks;
K_TREE_CTX ctx[1]; K_TREE_CTX ctx0[1];
K_ITEM look, *b_item; K_ITEM look, *b_item;
if (ctx == NULL)
ctx = ctx0;
/* TODO: For self orphaned (if that ever happens) /* TODO: For self orphaned (if that ever happens)
* this will find based on blockhash order if it has two, * this will find based on blockhash order if it has two,
* not NEW, blocks, which might not find the right one */ * not NEW, blocks, which might not find the right one */

Loading…
Cancel
Save