mdbx: trinity of meta-pages.

This commit is contained in:
Leo Yuriev
2017-05-24 21:43:29 +03:00
parent 141306644d
commit 9eeb00f448
8 changed files with 537 additions and 346 deletions

View File

@@ -323,7 +323,7 @@ static int handle_freedb(const uint64_t record_number, const MDBX_val *key,
if (key->iov_len != sizeof(txnid_t))
problem_add("entry", record_number, "wrong txn-id size",
"key-size %" PRIiPTR "", key->iov_len);
else if (txnid < 1 || txnid > envinfo.me_last_txnid)
else if (txnid < 1 || txnid > envinfo.me_recent_txnid)
problem_add("entry", record_number, "wrong txn-id", "%" PRIaTXN "", txnid);
if (data->iov_len < sizeof(pgno_t) || data->iov_len % sizeof(pgno_t))
@@ -340,14 +340,14 @@ static int handle_freedb(const uint64_t record_number, const MDBX_val *key,
data->iov_len);
else {
freedb_pages += number;
if (envinfo.me_tail_txnid > txnid)
if (envinfo.me_latter_reader_txnid > txnid)
reclaimable_pages += number;
for (i = number, prev = 1; --i >= 0;) {
pg = iptr[i];
if (pg < NUM_METAS || pg > envinfo.me_last_pgno)
if (pg < NUM_METAS || pg > envinfo.me_recent_pgno)
problem_add("entry", record_number, "wrong idl entry",
"%u < %" PRIiPTR " < %" PRIiPTR "", NUM_METAS, pg,
envinfo.me_last_pgno);
envinfo.me_recent_pgno);
else if (pg <= prev) {
bad = " [bad sequence]";
problem_add("entry", record_number, "bad sequence",
@@ -431,8 +431,7 @@ static int process_db(MDBX_dbi dbi, char *name, visitor *handler, int silent) {
}
}
if (dbi >= 2 /* CORE_DBS */ && name && only_subdb &&
strcmp(only_subdb, name)) {
if (dbi >= CORE_DBS && name && only_subdb && strcmp(only_subdb, name)) {
if (verbose) {
print("Skip processing '%s'...\n", name);
fflush(NULL);
@@ -592,19 +591,132 @@ static void usage(char *prog) {
const char *meta_synctype(uint64_t sign) {
switch (sign) {
case 0:
case MDBX_DATASIGN_NONE:
return "no-sync/legacy";
case 1:
case MDBX_DATASIGN_WEAK:
return "weak";
default:
return "steady";
}
}
int meta_lt(txnid_t txn1, uint64_t sign1, txnid_t txn2, uint64_t sign2) {
return (SIGN_IS_STEADY(sign1) == SIGN_IS_STEADY(sign2))
? txn1 < txn2
: txn2 && SIGN_IS_STEADY(sign2);
static __inline bool meta_ot(txnid_t txn_a, uint64_t sign_a, txnid_t txn_b,
uint64_t sign_b, const bool roolback2steady) {
if (txn_a == txn_b)
return SIGN_IS_STEADY(sign_b);
if (roolback2steady && SIGN_IS_STEADY(sign_a) != SIGN_IS_STEADY(sign_b))
return SIGN_IS_STEADY(sign_b);
return txn_a < txn_b;
}
static __inline bool meta_eq(txnid_t txn_a, uint64_t sign_a, txnid_t txn_b,
uint64_t sign_b) {
if (txn_a != txn_b)
return false;
if (SIGN_IS_STEADY(sign_a) != SIGN_IS_STEADY(sign_b))
return false;
return true;
}
static __inline int meta_recent(const bool roolback2steady) {
if (meta_ot(envinfo.me_meta0_txnid, envinfo.me_meta0_sign,
envinfo.me_meta1_txnid, envinfo.me_meta1_sign, roolback2steady))
return meta_ot(envinfo.me_meta2_txnid, envinfo.me_meta2_sign,
envinfo.me_meta1_txnid, envinfo.me_meta1_sign,
roolback2steady)
? 1
: 2;
return meta_ot(envinfo.me_meta0_txnid, envinfo.me_meta0_sign,
envinfo.me_meta2_txnid, envinfo.me_meta2_sign, roolback2steady)
? 2
: 0;
}
static __inline int meta_ancient(const bool roolback2steady) {
if (meta_ot(envinfo.me_meta0_txnid, envinfo.me_meta0_sign,
envinfo.me_meta1_txnid, envinfo.me_meta1_sign, roolback2steady))
return meta_ot(envinfo.me_meta0_txnid, envinfo.me_meta0_sign,
envinfo.me_meta2_txnid, envinfo.me_meta2_sign,
roolback2steady)
? 0
: 2;
return meta_ot(envinfo.me_meta2_txnid, envinfo.me_meta2_sign,
envinfo.me_meta1_txnid, envinfo.me_meta1_sign, roolback2steady)
? 2
: 1;
}
static int meta_steady_head(void) { return meta_recent(true); }
static int meta_weak_head(void) { return meta_recent(false); }
static int meta_tail(void) { return meta_ancient(true); }
void verbose_meta(int num, txnid_t txnid, uint64_t sign) {
print(" - meta-%d: %s %" PRIu64, num, meta_synctype(sign), txnid);
bool stay = true;
if (num == meta_steady_head() && num == meta_weak_head()) {
print(", head");
stay = false;
} else if (num == meta_steady_head()) {
print(", head-steady");
stay = false;
} else if (num == meta_weak_head()) {
print(", head-weak");
stay = false;
}
if (num == meta_tail()) {
print(", tail");
stay = false;
}
if (stay)
print(", stay");
if (txnid > envinfo.me_recent_txnid)
print(", rolled-back %" PRIu64 " (%" PRIu64 " >>> %" PRIu64 ")",
txnid - envinfo.me_recent_txnid, txnid, envinfo.me_recent_txnid);
print("\n");
}
static int check_meta_head(bool steady) {
switch (meta_recent(steady)) {
default:
assert(false);
error(" - unexpected internal error (%s)\n",
steady ? "meta_steady_head" : "meta_weak_head");
case 0:
if (envinfo.me_meta0_txnid != envinfo.me_recent_txnid) {
print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64
")\n",
0, envinfo.me_meta0_txnid, envinfo.me_recent_txnid);
return 1;
}
break;
case 1:
if (envinfo.me_meta1_txnid != envinfo.me_recent_txnid) {
print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64
")\n",
1, envinfo.me_meta1_txnid, envinfo.me_recent_txnid);
return 1;
}
break;
case 2:
if (envinfo.me_meta2_txnid != envinfo.me_recent_txnid) {
print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64
")\n",
2, envinfo.me_meta2_txnid, envinfo.me_recent_txnid);
return 1;
}
}
return 0;
}
int main(int argc, char *argv[]) {
@@ -739,7 +851,7 @@ int main(int argc, char *argv[]) {
goto bailout;
}
lastpgno = envinfo.me_last_pgno + 1;
lastpgno = envinfo.me_recent_pgno + 1;
errno = 0;
if (verbose) {
@@ -754,71 +866,45 @@ int main(int argc, char *argv[]) {
print(" - mapaddr %p\n", envinfo.me_mapaddr);
print(" - pagesize %u, max keysize %" PRIuPTR ", max readers %u\n",
envstat.ms_psize, maxkeysize, envinfo.me_maxreaders);
print(" - transactions: last %" PRIu64 ", bottom %" PRIu64
", lag reading %" PRIi64 "\n",
envinfo.me_last_txnid, envinfo.me_tail_txnid,
envinfo.me_last_txnid - envinfo.me_tail_txnid);
print(" - transactions: recent %" PRIu64 ", latter reader %" PRIu64
", lag %" PRIi64 "\n",
envinfo.me_recent_txnid, envinfo.me_latter_reader_txnid,
envinfo.me_recent_txnid - envinfo.me_latter_reader_txnid);
print(" - meta-1: %s %" PRIu64 ", %s", meta_synctype(envinfo.me_meta1_sign),
envinfo.me_meta1_txnid,
meta_lt(envinfo.me_meta1_txnid, envinfo.me_meta1_sign,
envinfo.me_meta2_txnid, envinfo.me_meta2_sign)
? "tail"
: "head");
if (envinfo.me_meta1_txnid > envinfo.me_last_txnid)
print(", rolled-back %" PRIu64 " (%" PRIu64 " >>> %" PRIu64 ")",
envinfo.me_meta1_txnid - envinfo.me_last_txnid,
envinfo.me_meta1_txnid, envinfo.me_last_txnid);
print("\n");
verbose_meta(0, envinfo.me_meta0_txnid, envinfo.me_meta0_sign);
verbose_meta(1, envinfo.me_meta1_txnid, envinfo.me_meta1_sign);
verbose_meta(2, envinfo.me_meta2_txnid, envinfo.me_meta2_sign);
}
print(" - meta-2: %s %" PRIu64 ", %s", meta_synctype(envinfo.me_meta2_sign),
envinfo.me_meta2_txnid,
meta_lt(envinfo.me_meta2_txnid, envinfo.me_meta2_sign,
envinfo.me_meta1_txnid, envinfo.me_meta1_sign)
? "tail"
: "head");
if (envinfo.me_meta2_txnid > envinfo.me_last_txnid)
print(", rolled-back %" PRIu64 " (%" PRIu64 " >>> %" PRIu64 ")",
envinfo.me_meta2_txnid - envinfo.me_last_txnid,
envinfo.me_meta2_txnid, envinfo.me_last_txnid);
print("\n");
if (verbose)
print(" - performs check for meta-pages overlap\n");
if (meta_eq(envinfo.me_meta0_txnid, envinfo.me_meta0_sign,
envinfo.me_meta1_txnid, envinfo.me_meta1_sign)) {
print(" - meta-%d and meta-%d are clashed\n", 0, 1);
++problems_meta;
}
if (meta_eq(envinfo.me_meta1_txnid, envinfo.me_meta1_sign,
envinfo.me_meta2_txnid, envinfo.me_meta2_sign)) {
print(" - meta-%d and meta-%d are clashed\n", 1, 2);
++problems_meta;
}
if (meta_eq(envinfo.me_meta2_txnid, envinfo.me_meta2_sign,
envinfo.me_meta0_txnid, envinfo.me_meta0_sign)) {
print(" - meta-%d and meta-%d are clashed\n", 2, 0);
++problems_meta;
}
if (exclusive > 1) {
if (verbose)
print(" - perform full check last-txn-id with meta-pages\n");
if (!meta_lt(envinfo.me_meta1_txnid, envinfo.me_meta1_sign,
envinfo.me_meta2_txnid, envinfo.me_meta2_sign) &&
envinfo.me_meta1_txnid != envinfo.me_last_txnid) {
print(" - meta-1 txn-id mismatch last-txn-id (%" PRIi64 " != %" PRIi64
")\n",
envinfo.me_meta1_txnid, envinfo.me_last_txnid);
++problems_meta;
}
if (!meta_lt(envinfo.me_meta2_txnid, envinfo.me_meta2_sign,
envinfo.me_meta1_txnid, envinfo.me_meta1_sign) &&
envinfo.me_meta2_txnid != envinfo.me_last_txnid) {
print(" - meta-2 txn-id mismatch last-txn-id (%" PRIi64 " != %" PRIi64
")\n",
envinfo.me_meta2_txnid, envinfo.me_last_txnid);
++problems_meta;
}
print(" - performs full check recent-txn-id with meta-pages\n");
problems_meta += check_meta_head(true);
} else if (locktxn) {
if (verbose)
print(" - perform lite check last-txn-id with meta-pages (not a "
print(" - performs lite check recent-txn-id with meta-pages (not a "
"monopolistic mode)\n");
uint64_t last = (envinfo.me_meta2_txnid > envinfo.me_meta1_txnid)
? envinfo.me_meta2_txnid
: envinfo.me_meta1_txnid;
if (last != envinfo.me_last_txnid) {
print(" - last-meta mismatch last-txn-id (%" PRIi64 " != %" PRIi64 ")\n",
last, envinfo.me_last_txnid);
++problems_meta;
}
problems_meta += check_meta_head(false);
} else if (verbose) {
print(" - skip check last-txn-id with meta-pages (monopolistic or "
print(" - skip check recent-txn-id with meta-pages (monopolistic or "
"write-lock mode only)\n");
}

View File

@@ -125,10 +125,11 @@ int main(int argc, char *argv[]) {
printf(" Map size: %" PRIu64 "\n", mei.me_mapsize);
printf(" Page size: %u\n", mst.ms_psize);
printf(" Max pages: %" PRIu64 "\n", mei.me_mapsize / mst.ms_psize);
printf(" Number of pages used: %" PRIu64 "\n", mei.me_last_pgno + 1);
printf(" Last transaction ID: %" PRIu64 "\n", mei.me_last_txnid);
printf(" Number of pages used: %" PRIu64 "\n", mei.me_recent_pgno + 1);
printf(" Last transaction ID: %" PRIu64 "\n", mei.me_recent_txnid);
printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n",
mei.me_tail_txnid, mei.me_tail_txnid - mei.me_last_txnid);
mei.me_latter_reader_txnid,
mei.me_latter_reader_txnid - mei.me_recent_txnid);
printf(" Max readers: %u\n", mei.me_maxreaders);
printf(" Number of readers used: %u\n", mei.me_numreaders);
} else {
@@ -181,7 +182,7 @@ int main(int argc, char *argv[]) {
while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == 0) {
iptr = data.iov_base;
pages += *iptr;
if (envinfo && mei.me_tail_txnid > *(size_t *)key.iov_base)
if (envinfo && mei.me_latter_reader_txnid > *(size_t *)key.iov_base)
reclaimable += *iptr;
if (freinfo > 1) {
char *bad = "";
@@ -220,14 +221,14 @@ int main(int argc, char *argv[]) {
printf("Page Allocation Info\n");
printf(" Max pages: %9zu 100%%\n", value);
value = mei.me_last_pgno + 1;
value = mei.me_recent_pgno + 1;
printf(" Number of pages used: %" PRIuPTR " %.1f%%\n", value,
value / percent);
value = mei.me_mapsize / mst.ms_psize - (mei.me_last_pgno + 1);
value = mei.me_mapsize / mst.ms_psize - (mei.me_recent_pgno + 1);
printf(" Remained: %" PRIuPTR " %.1f%%\n", value, value / percent);
value = mei.me_last_pgno + 1 - pages;
value = mei.me_recent_pgno + 1 - pages;
printf(" Used now: %" PRIuPTR " %.1f%%\n", value, value / percent);
value = pages;
@@ -239,8 +240,8 @@ int main(int argc, char *argv[]) {
value = reclaimable;
printf(" Reclaimable: %" PRIuPTR " %.1f%%\n", value, value / percent);
value =
mei.me_mapsize / mst.ms_psize - (mei.me_last_pgno + 1) + reclaimable;
value = mei.me_mapsize / mst.ms_psize - (mei.me_recent_pgno + 1) +
reclaimable;
printf(" Available: %" PRIuPTR " %.1f%%\n", value, value / percent);
} else
printf(" Free pages: %" PRIuPTR "\n", pages);