From 104312d15e6d1cb0642afcb4ab371270d69fc76d Mon Sep 17 00:00:00 2001 From: Leo Yuriev Date: Mon, 11 May 2015 21:50:18 +0300 Subject: [PATCH] lmdb: update mdb_chk for checkpoints, minor cosmetics. This is 9/9 for https://github.com/ReOpen/ReOpenLDAP/issues/1 and https://github.com/ReOpen/ReOpenLDAP/issues/2 Change-Id: I05f59313b4346c08bcd63d62e6c48a5f53c47852 --- lmdb.h | 4 +++- mdb.c | 23 +++++++++++++----- mdb_chk.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 82 insertions(+), 15 deletions(-) diff --git a/lmdb.h b/lmdb.h index 9009d837..b87d98ec 100644 --- a/lmdb.h +++ b/lmdb.h @@ -446,6 +446,8 @@ typedef struct MDB_envinfo { size_t me_tail_txnid; /**< ID of the last reader transaction */ unsigned me_maxreaders; /**< max reader slots in the environment */ unsigned me_numreaders; /**< max reader slots used in the environment */ + size_t me_meta1_txnid, me_meta1_sign; + size_t me_meta2_txnid, me_meta2_sign; } MDB_envinfo; /** @brief Return the LMDB library version information. @@ -695,7 +697,7 @@ int mdb_env_stat(MDB_env *env, MDB_stat *stat); * @param[out] stat The address of an #MDB_envinfo structure * where the information will be copied */ -int mdb_env_info(MDB_env *env, MDB_envinfo *stat); +int mdb_env_info(MDB_env *env, MDB_envinfo *info); /** @brief Flush the data buffers to disk. * diff --git a/mdb.c b/mdb.c index 041e14db..37e5a39c 100644 --- a/mdb.c +++ b/mdb.c @@ -9039,21 +9039,32 @@ mdb_env_stat(MDB_env *env, MDB_stat *arg) int ESECT mdb_env_info(MDB_env *env, MDB_envinfo *arg) { - MDB_meta *meta; + MDB_meta *meta, *m1, *m2; if (env == NULL || arg == NULL) return EINVAL; - meta = mdb_meta_head_r(env); - arg->me_mapaddr = meta->mm_address; + m1 = METAPAGE_1(env); + m2 = METAPAGE_2(env); + arg->me_mapsize = env->me_mapsize; arg->me_maxreaders = env->me_maxreaders; arg->me_numreaders = env->me_txns->mti_numreaders; - arg->me_last_pgno = meta->mm_last_pg; - arg->me_last_txnid = meta->mm_txnid; - arg->me_tail_txnid = 0; + do { + meta = mdb_meta_head_r(env); + arg->me_meta1_txnid = m1->mm_txnid; + arg->me_meta1_sign = m1->mm_datasync_sign; + arg->me_meta2_txnid = m2->mm_txnid; + arg->me_meta2_sign = m2->mm_datasync_sign; + arg->me_last_pgno = meta->mm_last_pg; + arg->me_last_txnid = meta->mm_txnid; + } while (unlikely( meta->mm_txnid != env->me_txns->mti_txnid + || arg->me_meta1_sign != m1->mm_datasync_sign + || arg->me_meta2_sign != m2->mm_datasync_sign )); + arg->me_mapaddr = meta->mm_address; + arg->me_tail_txnid = 0; MDB_reader *r = env->me_txns->mti_readers; int i; arg->me_tail_txnid = arg->me_last_txnid; diff --git a/mdb_chk.c b/mdb_chk.c index e450e774..1315e0cb 100644 --- a/mdb_chk.c +++ b/mdb_chk.c @@ -244,10 +244,10 @@ static long handle_freedb(size_t record_number, MDB_val *key, MDB_val* data) { pg += span; for (; i >= span && iptr[i - span] == pg; span++, pg++) ; } - if (verbose > 1) + if (verbose > 2) print(" - transaction %zu, %zd pages, maxspan %zd%s\n", *(size_t *)key->mv_data, number, span, bad); - if (verbose > 2) { + if (verbose > 3) { int j = number - 1; while (j >= 0) { pg = iptr[j]; @@ -430,6 +430,21 @@ static void usage(char *prog) exit(EXIT_FAILURE); } +const char* meta_synctype(size_t sign) { + switch(sign) { + case 0: + return "legacy/unknown"; + case 1: + return "weak"; + default: + return "steady"; + } +} + +int meta_lt(size_t txn1, size_t sign1, size_t txn2, size_t sign2) { + return ((sign1 > 1) == (sign2 > 1)) ? txn1 < txn2 : sign2 > 1; +} + int main(int argc, char *argv[]) { int i, rc; @@ -437,6 +452,7 @@ int main(int argc, char *argv[]) char *envname; int envflags = 0; long problems_maindb = 0, problems_freedb = 0, problems_deep = 0; + int problems_meta = 0; size_t n; if (argc < 2) { @@ -480,6 +496,8 @@ int main(int argc, char *argv[]) signal(SIGTERM, signal_hanlder); envname = argv[optind]; + print("Running mdb_chk for '%s'...\n", envname); + rc = mdb_env_create(&env); if (rc) { error("mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); @@ -523,15 +541,50 @@ int main(int argc, char *argv[]) } if (verbose) { - print(" - map size %zu (%.1fMb, %.1fGb)\n", info.me_mapsize, - (double) info.me_mapsize / (1024 * 1024), - (double) info.me_mapsize / (1024 * 1024 * 1024)); + double k = 1024.0; + const char sf[] = "KMGTPEZY"; /* LY: Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta! */ + for(i = 0; sf[i+1] && info.me_mapsize / k > 1000.0; ++i) + k *= 1024; + print(" - map size %zu (%.1f%cb)\n", info.me_mapsize, + info.me_mapsize / k, sf[i]); if (info.me_mapaddr) print(" - mapaddr %p\n", info.me_mapaddr); print(" - pagesize %u, max keysize %zu, max readers %u\n", stat.ms_psize, maxkeysize, info.me_maxreaders); - print(" - last txn %zu, tail %zu (%zi)\n", info.me_last_txnid, - info.me_tail_txnid, info.me_tail_txnid - info.me_last_txnid); + print(" - transactions: last %zu, bottom %zu, lag reading %zi\n", info.me_last_txnid, + info.me_tail_txnid, info.me_last_txnid - info.me_tail_txnid); + + print(" - meta-1: %s %zu, %s", + meta_synctype(info.me_meta1_sign), info.me_meta1_txnid, + meta_lt(info.me_meta1_txnid, info.me_meta1_sign, + info.me_meta2_txnid, info.me_meta2_sign) ? "tail" : "head"); + print(info.me_meta1_txnid > info.me_last_txnid + ? ", rolled-back %zu (%zu >>> %zu)\n" : "\n", + info.me_meta1_txnid - info.me_last_txnid, + info.me_meta1_txnid, info.me_last_txnid); + + print(" - meta-2: %s %zu, %s", + meta_synctype(info.me_meta2_sign), info.me_meta2_txnid, + meta_lt(info.me_meta2_txnid, info.me_meta2_sign, + info.me_meta1_txnid, info.me_meta1_sign) ? "tail" : "head"); + print(info.me_meta2_txnid > info.me_last_txnid + ? ", rolled-back %zu (%zu >>> %zu)\n" : "\n", + info.me_meta2_txnid - info.me_last_txnid, + info.me_meta2_txnid, info.me_last_txnid); + } + + if (! meta_lt(info.me_meta1_txnid, info.me_meta1_sign, + info.me_meta2_txnid, info.me_meta2_sign) + && info.me_meta1_txnid != info.me_last_txnid) { + print(" - meta1 txn-id mismatch\n"); + ++problems_meta; + } + + if (! meta_lt(info.me_meta2_txnid, info.me_meta2_sign, + info.me_meta1_txnid, info.me_meta1_sign) + && info.me_meta2_txnid != info.me_last_txnid) { + print(" - meta2 txn-id mismatch\n"); + ++problems_meta; } rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); @@ -610,9 +663,10 @@ bailout: free(pagemap); if (rc) return EXIT_FAILURE + 2; - if (problems_maindb || problems_freedb) + if (problems_meta || problems_maindb || problems_freedb) return EXIT_FAILURE + 1; if (problems_deep) return EXIT_FAILURE; + print("No error is detected.\n"); return EXIT_SUCCESS; }