summaryrefslogtreecommitdiff
path: root/plugins/Dbx_mdbx/src/libmdbx/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Dbx_mdbx/src/libmdbx/src/tools')
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c1139
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.vcxproj166
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.157
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.c107
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.vcxproj166
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.177
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.c336
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.vcxproj166
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.179
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.c513
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.vcxproj166
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.166
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.c385
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.vcxproj166
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.c95
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.h26
16 files changed, 3710 insertions, 0 deletions
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c
new file mode 100644
index 0000000000..ef2184ffe9
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.c
@@ -0,0 +1,1139 @@
+/* mdbx_chk.c - memory-mapped database check tool */
+
+/*
+ * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>. */
+
+#ifdef _MSC_VER
+#if _MSC_VER > 1800
+#pragma warning(disable : 4464) /* relative include path contains '..' */
+#endif
+#pragma warning(disable : 4996) /* The POSIX name is deprecated... */
+#endif /* _MSC_VER (warnings) */
+
+#include "../bits.h"
+
+typedef struct flagbit {
+ int bit;
+ char *name;
+} flagbit;
+
+flagbit dbflags[] = {{MDBX_DUPSORT, "dupsort"},
+ {MDBX_INTEGERKEY, "integerkey"},
+ {MDBX_REVERSEKEY, "reversekey"},
+ {MDBX_DUPFIXED, "dupfixed"},
+ {MDBX_REVERSEDUP, "reversedup"},
+ {MDBX_INTEGERDUP, "integerdup"},
+ {0, NULL}};
+
+#if defined(_WIN32) || defined(_WIN64)
+#include "wingetopt.h"
+
+static volatile BOOL user_break;
+static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
+ (void)dwCtrlType;
+ user_break = true;
+ return true;
+}
+
+#else /* WINDOWS */
+
+static volatile sig_atomic_t user_break;
+static void signal_handler(int sig) {
+ (void)sig;
+ user_break = 1;
+}
+
+#endif /* !WINDOWS */
+
+#define EXIT_INTERRUPTED (EXIT_FAILURE + 4)
+#define EXIT_FAILURE_SYS (EXIT_FAILURE + 3)
+#define EXIT_FAILURE_MDB (EXIT_FAILURE + 2)
+#define EXIT_FAILURE_CHECK_MAJOR (EXIT_FAILURE + 1)
+#define EXIT_FAILURE_CHECK_MINOR EXIT_FAILURE
+
+struct {
+ const char *dbi_names[MAX_DBI];
+ uint64_t dbi_pages[MAX_DBI];
+ uint64_t dbi_empty_pages[MAX_DBI];
+ uint64_t dbi_payload_bytes[MAX_DBI];
+ uint64_t dbi_lost_bytes[MAX_DBI];
+ short *pagemap;
+ uint64_t total_payload_bytes;
+ uint64_t pgcount;
+} walk;
+
+uint64_t total_unused_bytes;
+int exclusive = 2;
+int envflags = MDBX_RDONLY;
+
+MDBX_env *env;
+MDBX_txn *txn, *locktxn;
+MDBX_envinfo envinfo;
+MDBX_stat envstat;
+size_t maxkeysize, userdb_count, skipped_subdb;
+uint64_t reclaimable_pages, freedb_pages, lastpgno;
+unsigned verbose, quiet;
+const char *only_subdb;
+
+struct problem {
+ struct problem *pr_next;
+ uint64_t count;
+ const char *caption;
+};
+
+struct problem *problems_list;
+uint64_t total_problems;
+
+static void
+#ifdef __GNU__
+ __attribute__((format(printf, 1, 2)))
+#endif
+ print(const char *msg, ...) {
+ if (!quiet) {
+ va_list args;
+
+ fflush(stderr);
+ va_start(args, msg);
+ vfprintf(stdout, msg, args);
+ va_end(args);
+ }
+}
+
+static void
+#ifdef __GNU__
+ __attribute__((format(printf, 1, 2)))
+#endif
+ error(const char *msg, ...) {
+ total_problems++;
+
+ if (!quiet) {
+ va_list args;
+
+ fflush(stdout);
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fflush(NULL);
+ }
+}
+
+static void pagemap_cleanup(void) {
+ int i;
+
+ for (i = 1; i < MAX_DBI; ++i) {
+ if (walk.dbi_names[i]) {
+ free((void *)walk.dbi_names[i]);
+ walk.dbi_names[i] = NULL;
+ }
+ }
+
+ free(walk.pagemap);
+ walk.pagemap = NULL;
+}
+
+static int pagemap_lookup_dbi(const char *dbi) {
+ static int last;
+ int i;
+
+ if (last > 0 && strcmp(walk.dbi_names[last], dbi) == 0)
+ return last;
+
+ for (i = 1; walk.dbi_names[i] && last < MAX_DBI; ++i)
+ if (strcmp(walk.dbi_names[i], dbi) == 0)
+ return last = i;
+
+ if (i == MAX_DBI)
+ return -1;
+
+ walk.dbi_names[i] = strdup(dbi);
+
+ if (verbose > 1) {
+ print(" - found '%s' area\n", dbi);
+ fflush(NULL);
+ }
+
+ return last = i;
+}
+
+static void problem_add(const char *object, uint64_t entry_number,
+ const char *msg, const char *extra, ...) {
+ total_problems++;
+
+ if (!quiet) {
+ int need_fflush = 0;
+ struct problem *p;
+
+ for (p = problems_list; p; p = p->pr_next)
+ if (p->caption == msg)
+ break;
+
+ if (!p) {
+ p = calloc(1, sizeof(*p));
+ p->caption = msg;
+ p->pr_next = problems_list;
+ problems_list = p;
+ need_fflush = 1;
+ }
+
+ p->count++;
+ if (verbose > 1) {
+ print(" %s #%" PRIu64 ": %s", object, entry_number, msg);
+ if (extra) {
+ va_list args;
+ printf(" (");
+ va_start(args, extra);
+ vfprintf(stdout, extra, args);
+ va_end(args);
+ printf(")");
+ }
+ printf("\n");
+ if (need_fflush)
+ fflush(NULL);
+ }
+ }
+}
+
+static struct problem *problems_push(void) {
+ struct problem *p = problems_list;
+ problems_list = NULL;
+ return p;
+}
+
+static uint64_t problems_pop(struct problem *list) {
+ uint64_t count = 0;
+
+ if (problems_list) {
+ int i;
+
+ print(" - problems: ");
+ for (i = 0; problems_list; ++i) {
+ struct problem *p = problems_list->pr_next;
+ count += problems_list->count;
+ print("%s%s (%" PRIu64 ")", i ? ", " : "", problems_list->caption,
+ problems_list->count);
+ free(problems_list);
+ problems_list = p;
+ }
+ print("\n");
+ fflush(NULL);
+ }
+
+ problems_list = list;
+ return count;
+}
+
+static int pgvisitor(uint64_t pgno, unsigned pgnumber, void *ctx,
+ const char *dbi, const char *type, size_t nentries,
+ size_t payload_bytes, size_t header_bytes,
+ size_t unused_bytes) {
+ (void)ctx;
+
+ if (type) {
+ uint64_t page_bytes = payload_bytes + header_bytes + unused_bytes;
+ size_t page_size = (size_t)pgnumber * envstat.ms_psize;
+ int index = pagemap_lookup_dbi(dbi);
+ if (index < 0)
+ return MDBX_ENOMEM;
+
+ if (verbose > 2 && (!only_subdb || strcmp(only_subdb, dbi) == 0)) {
+ if (pgnumber == 1)
+ print(" %s-page %" PRIu64, type, pgno);
+ else
+ print(" %s-span %" PRIu64 "[%u]", type, pgno, pgnumber);
+ print(" of %s: header %" PRIiPTR ", payload %" PRIiPTR
+ ", unused %" PRIiPTR "\n",
+ dbi, header_bytes, payload_bytes, unused_bytes);
+ }
+
+ walk.pgcount += pgnumber;
+
+ if (unused_bytes > page_size)
+ problem_add("page", pgno, "illegal unused-bytes", "%u < %i < %u", 0,
+ unused_bytes, envstat.ms_psize);
+
+ if (header_bytes < (int)sizeof(long) ||
+ (size_t)header_bytes >= envstat.ms_psize - sizeof(long))
+ problem_add("page", pgno, "illegal header-length",
+ "%" PRIuPTR " < %i < %" PRIuPTR "", sizeof(long),
+ header_bytes, envstat.ms_psize - sizeof(long));
+ if (payload_bytes < 1) {
+ if (nentries > 1) {
+ problem_add("page", pgno, "zero size-of-entry",
+ "payload %i bytes, %i entries", payload_bytes, nentries);
+ if ((size_t)header_bytes + unused_bytes < page_size) {
+ /* LY: hush a misuse error */
+ page_bytes = page_size;
+ }
+ } else {
+ problem_add("page", pgno, "empty", "payload %i bytes, %i entries",
+ payload_bytes, nentries);
+ walk.dbi_empty_pages[index] += 1;
+ }
+ }
+
+ if (page_bytes != page_size) {
+ problem_add("page", pgno, "misused",
+ "%" PRIu64 " != %" PRIu64 " (%ih + %ip + %iu)", page_size,
+ page_bytes, header_bytes, payload_bytes, unused_bytes);
+ if (page_size > page_bytes)
+ walk.dbi_lost_bytes[index] += page_size - page_bytes;
+ } else {
+ walk.dbi_payload_bytes[index] += payload_bytes + header_bytes;
+ walk.total_payload_bytes += payload_bytes + header_bytes;
+ }
+
+ if (pgnumber) {
+ do {
+ if (pgno >= lastpgno)
+ problem_add("page", pgno, "wrong page-no",
+ "%" PRIu64 " > %" PRIu64 "", pgno, lastpgno);
+ else if (walk.pagemap[pgno])
+ problem_add("page", pgno, "already used", "in %s",
+ walk.dbi_names[walk.pagemap[pgno]]);
+ else {
+ walk.pagemap[pgno] = (short)index;
+ walk.dbi_pages[index] += 1;
+ }
+ ++pgno;
+ } while (--pgnumber);
+ }
+ }
+
+ return user_break ? MDBX_EINTR : MDBX_SUCCESS;
+}
+
+typedef int(visitor)(const uint64_t record_number, const MDBX_val *key,
+ const MDBX_val *data);
+static int process_db(MDBX_dbi dbi, char *name, visitor *handler, bool silent);
+
+static int handle_userdb(const uint64_t record_number, const MDBX_val *key,
+ const MDBX_val *data) {
+ (void)record_number;
+ (void)key;
+ (void)data;
+ return MDBX_SUCCESS;
+}
+
+static int handle_freedb(const uint64_t record_number, const MDBX_val *key,
+ const MDBX_val *data) {
+ char *bad = "";
+ pgno_t *iptr = data->iov_base;
+ txnid_t txnid = *(txnid_t *)key->iov_base;
+
+ 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.mi_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))
+ problem_add("entry", record_number, "wrong idl size", "%" PRIuPTR "",
+ data->iov_len);
+ else {
+ const pgno_t number = *iptr++;
+ if (number >= MDBX_PNL_UM_MAX)
+ problem_add("entry", record_number, "wrong idl length", "%" PRIiPTR "",
+ number);
+ else if ((number + 1) * sizeof(pgno_t) != data->iov_len)
+ problem_add("entry", record_number, "mismatch idl length",
+ "%" PRIuSIZE " != %" PRIuSIZE "",
+ (number + 1) * sizeof(pgno_t), data->iov_len);
+ else {
+ freedb_pages += number;
+ if (envinfo.mi_latter_reader_txnid > txnid)
+ reclaimable_pages += number;
+
+ pgno_t prev =
+ MDBX_PNL_ASCENDING ? NUM_METAS - 1 : (pgno_t)envinfo.mi_last_pgno + 1;
+ pgno_t span = 1;
+ for (unsigned i = 0; i < number; ++i) {
+ const pgno_t pg = iptr[i];
+ if (pg < NUM_METAS || pg > envinfo.mi_last_pgno)
+ problem_add("entry", record_number, "wrong idl entry",
+ "%u < %" PRIaPGNO " < %" PRIu64 "", NUM_METAS, pg,
+ envinfo.mi_last_pgno);
+ else if (MDBX_PNL_DISORDERED(prev, pg)) {
+ bad = " [bad sequence]";
+ problem_add("entry", record_number, "bad sequence",
+ "%" PRIaPGNO " <> %" PRIaPGNO "", prev, pg);
+ }
+ prev = pg;
+ while (i + span < number &&
+ iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span)
+ : pgno_sub(pg, span)))
+ ++span;
+ }
+ if (verbose > 2 && !only_subdb) {
+ print(" transaction %" PRIaTXN ", %" PRIaPGNO
+ " pages, maxspan %" PRIaPGNO "%s\n",
+ txnid, number, span, bad);
+ if (verbose > 3) {
+ for (unsigned i = 0; i < number; i += span) {
+ const pgno_t pg = iptr[i];
+ for (span = 1;
+ i + span < number &&
+ iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span)
+ : pgno_sub(pg, span));
+ ++span)
+ ;
+ if (span > 1) {
+ print(" %9" PRIaPGNO "[%" PRIaPGNO "]\n", pg, span);
+ } else
+ print(" %9" PRIaPGNO "\n", pg);
+ }
+ }
+ }
+ }
+ }
+
+ return MDBX_SUCCESS;
+}
+
+static int handle_maindb(const uint64_t record_number, const MDBX_val *key,
+ const MDBX_val *data) {
+ char *name;
+ int rc;
+ size_t i;
+
+ name = key->iov_base;
+ for (i = 0; i < key->iov_len; ++i) {
+ if (name[i] < ' ')
+ return handle_userdb(record_number, key, data);
+ }
+
+ name = malloc(key->iov_len + 1);
+ memcpy(name, key->iov_base, key->iov_len);
+ name[key->iov_len] = '\0';
+ userdb_count++;
+
+ rc = process_db(~0u, name, handle_userdb, false);
+ free(name);
+ if (rc != MDBX_INCOMPATIBLE)
+ return rc;
+
+ return handle_userdb(record_number, key, data);
+}
+
+static int process_db(MDBX_dbi dbi, char *name, visitor *handler, bool silent) {
+ MDBX_cursor *mc;
+ MDBX_stat ms;
+ MDBX_val key, data;
+ MDBX_val prev_key, prev_data;
+ unsigned flags;
+ int rc, i;
+ struct problem *saved_list;
+ uint64_t problems_count;
+
+ uint64_t record_count = 0, dups = 0;
+ uint64_t key_bytes = 0, data_bytes = 0;
+
+ if (dbi == ~0u) {
+ rc = mdbx_dbi_open(txn, name, 0, &dbi);
+ if (rc) {
+ if (!name ||
+ rc !=
+ MDBX_INCOMPATIBLE) /* LY: mainDB's record is not a user's DB. */ {
+ error(" - mdbx_open '%s' failed, error %d %s\n", name ? name : "main",
+ rc, mdbx_strerror(rc));
+ }
+ return rc;
+ }
+ }
+
+ if (dbi >= CORE_DBS && name && only_subdb && strcmp(only_subdb, name)) {
+ if (verbose) {
+ print("Skip processing '%s'...\n", name);
+ fflush(NULL);
+ }
+ skipped_subdb++;
+ return MDBX_SUCCESS;
+ }
+
+ if (!silent && verbose) {
+ print("Processing '%s'...\n", name ? name : "main");
+ fflush(NULL);
+ }
+
+ rc = mdbx_dbi_flags(txn, dbi, &flags);
+ if (rc) {
+ error(" - mdbx_dbi_flags failed, error %d %s\n", rc, mdbx_strerror(rc));
+ return rc;
+ }
+
+ rc = mdbx_dbi_stat(txn, dbi, &ms, sizeof(ms));
+ if (rc) {
+ error(" - mdbx_dbi_stat failed, error %d %s\n", rc, mdbx_strerror(rc));
+ return rc;
+ }
+
+ if (!silent && verbose) {
+ print(" - dbi-id %d, flags:", dbi);
+ if (!flags)
+ print(" none");
+ else {
+ for (i = 0; dbflags[i].bit; i++)
+ if (flags & dbflags[i].bit)
+ print(" %s", dbflags[i].name);
+ }
+ print(" (0x%02X)\n", flags);
+ if (verbose > 1) {
+ print(" - page size %u, entries %" PRIu64 "\n", ms.ms_psize,
+ ms.ms_entries);
+ print(" - b-tree depth %u, pages: branch %" PRIu64 ", leaf %" PRIu64
+ ", overflow %" PRIu64 "\n",
+ ms.ms_depth, ms.ms_branch_pages, ms.ms_leaf_pages,
+ ms.ms_overflow_pages);
+ }
+ }
+
+ rc = mdbx_cursor_open(txn, dbi, &mc);
+ if (rc) {
+ error(" - mdbx_cursor_open failed, error %d %s\n", rc, mdbx_strerror(rc));
+ return rc;
+ }
+
+ saved_list = problems_push();
+ prev_key.iov_base = NULL;
+ prev_data.iov_len = 0;
+ rc = mdbx_cursor_get(mc, &key, &data, MDBX_FIRST);
+ while (rc == MDBX_SUCCESS) {
+ if (user_break) {
+ print(" - interrupted by signal\n");
+ fflush(NULL);
+ rc = MDBX_EINTR;
+ goto bailout;
+ }
+
+ if (key.iov_len > maxkeysize) {
+ problem_add("entry", record_count, "key length exceeds max-key-size",
+ "%" PRIuPTR " > %u", key.iov_len, maxkeysize);
+ } else if ((flags & MDBX_INTEGERKEY) && key.iov_len != sizeof(uint64_t) &&
+ key.iov_len != sizeof(uint32_t)) {
+ problem_add("entry", record_count, "wrong key length",
+ "%" PRIuPTR " != 4or8", key.iov_len);
+ }
+
+ if ((flags & MDBX_INTEGERDUP) && data.iov_len != sizeof(uint64_t) &&
+ data.iov_len != sizeof(uint32_t)) {
+ problem_add("entry", record_count, "wrong data length",
+ "%" PRIuPTR " != 4or8", data.iov_len);
+ }
+
+ if (prev_key.iov_base) {
+ if ((flags & MDBX_DUPFIXED) && prev_data.iov_len != data.iov_len) {
+ problem_add("entry", record_count, "different data length",
+ "%" PRIuPTR " != %" PRIuPTR "", prev_data.iov_len,
+ data.iov_len);
+ }
+
+ int cmp = mdbx_cmp(txn, dbi, &prev_key, &key);
+ if (cmp > 0) {
+ problem_add("entry", record_count, "broken ordering of entries", NULL);
+ } else if (cmp == 0) {
+ ++dups;
+ if (!(flags & MDBX_DUPSORT))
+ problem_add("entry", record_count, "duplicated entries", NULL);
+ else if (flags & MDBX_INTEGERDUP) {
+ cmp = mdbx_dcmp(txn, dbi, &prev_data, &data);
+ if (cmp > 0)
+ problem_add("entry", record_count,
+ "broken ordering of multi-values", NULL);
+ }
+ }
+ } else if (verbose) {
+ if (flags & MDBX_INTEGERKEY)
+ print(" - fixed key-size %" PRIuPTR "\n", key.iov_len);
+ if (flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED))
+ print(" - fixed data-size %" PRIuPTR "\n", data.iov_len);
+ }
+
+ if (handler) {
+ rc = handler(record_count, &key, &data);
+ if (rc)
+ goto bailout;
+ }
+
+ record_count++;
+ key_bytes += key.iov_len;
+ data_bytes += data.iov_len;
+
+ prev_key = key;
+ prev_data = data;
+ rc = mdbx_cursor_get(mc, &key, &data, MDBX_NEXT);
+ }
+ if (rc != MDBX_NOTFOUND)
+ error(" - mdbx_cursor_get failed, error %d %s\n", rc, mdbx_strerror(rc));
+ else
+ rc = 0;
+
+ if (record_count != ms.ms_entries)
+ problem_add("entry", record_count, "differentent number of entries",
+ "%" PRIuPTR " != %" PRIuPTR "", record_count, ms.ms_entries);
+bailout:
+ problems_count = problems_pop(saved_list);
+ if (!silent && verbose) {
+ print(" - summary: %" PRIu64 " records, %" PRIu64 " dups, %" PRIu64
+ " key's bytes, %" PRIu64 " data's "
+ "bytes, %" PRIu64 " problems\n",
+ record_count, dups, key_bytes, data_bytes, problems_count);
+ fflush(NULL);
+ }
+
+ mdbx_cursor_close(mc);
+ return rc || problems_count;
+}
+
+static void usage(char *prog) {
+ fprintf(stderr,
+ "usage: %s dbpath [-V] [-v] [-n] [-q] [-w] [-c] [-d] [-s subdb]\n"
+ " -V\t\tshow version\n"
+ " -v\t\tmore verbose, could be used multiple times\n"
+ " -n\t\tNOSUBDIR mode for open\n"
+ " -q\t\tbe quiet\n"
+ " -w\t\tlock DB for writing while checking\n"
+ " -d\t\tdisable page-by-page traversal of b-tree\n"
+ " -s subdb\tprocess a specific subdatabase only\n"
+ " -c\t\tforce cooperative mode (don't try exclusive)\n",
+ prog);
+ exit(EXIT_INTERRUPTED);
+}
+
+const char *meta_synctype(uint64_t sign) {
+ switch (sign) {
+ case MDBX_DATASIGN_NONE:
+ return "no-sync/legacy";
+ case MDBX_DATASIGN_WEAK:
+ return "weak";
+ default:
+ return "steady";
+ }
+}
+
+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.mi_meta0_txnid, envinfo.mi_meta0_sign,
+ envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, roolback2steady))
+ return meta_ot(envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign,
+ envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign,
+ roolback2steady)
+ ? 1
+ : 2;
+
+ return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign,
+ envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, roolback2steady)
+ ? 2
+ : 0;
+}
+
+static __inline int meta_tail(int head) {
+
+ if (head == 0)
+ return meta_ot(envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign,
+ envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, true)
+ ? 1
+ : 2;
+ if (head == 1)
+ return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign,
+ envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, true)
+ ? 0
+ : 2;
+ if (head == 2)
+ return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign,
+ envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, true)
+ ? 0
+ : 1;
+ assert(false);
+ return -1;
+}
+
+static int meta_steady(void) { return meta_recent(true); }
+
+static int meta_head(void) { return meta_recent(false); }
+
+void verbose_meta(int num, txnid_t txnid, uint64_t sign) {
+ print(" - meta-%d: %s %" PRIu64, num, meta_synctype(sign), txnid);
+ bool stay = true;
+
+ const int steady = meta_steady();
+ const int head = meta_head();
+ if (num == steady && num == head) {
+ print(", head");
+ stay = false;
+ } else if (num == steady) {
+ print(", head-steady");
+ stay = false;
+ } else if (num == head) {
+ print(", head-weak");
+ stay = false;
+ }
+ if (num == meta_tail(head)) {
+ print(", tail");
+ stay = false;
+ }
+ if (stay)
+ print(", stay");
+
+ if (txnid > envinfo.mi_recent_txnid &&
+ (exclusive || (envflags & MDBX_RDONLY) == 0))
+ print(", rolled-back %" PRIu64 " (%" PRIu64 " >>> %" PRIu64 ")",
+ txnid - envinfo.mi_recent_txnid, txnid, envinfo.mi_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");
+ __fallthrough;
+ case 0:
+ if (envinfo.mi_meta0_txnid != envinfo.mi_recent_txnid) {
+ print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64
+ ")\n",
+ 0, envinfo.mi_meta0_txnid, envinfo.mi_recent_txnid);
+ return 1;
+ }
+ break;
+ case 1:
+ if (envinfo.mi_meta1_txnid != envinfo.mi_recent_txnid) {
+ print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64
+ ")\n",
+ 1, envinfo.mi_meta1_txnid, envinfo.mi_recent_txnid);
+ return 1;
+ }
+ break;
+ case 2:
+ if (envinfo.mi_meta2_txnid != envinfo.mi_recent_txnid) {
+ print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64
+ ")\n",
+ 2, envinfo.mi_meta2_txnid, envinfo.mi_recent_txnid);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void print_size(const char *prefix, const uint64_t value,
+ const char *suffix) {
+ const char sf[] =
+ "KMGTPEZY"; /* LY: Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta! */
+ double k = 1024.0;
+ size_t i;
+ for (i = 0; sf[i + 1] && value / k > 1000.0; ++i)
+ k *= 1024;
+ print("%s%" PRIu64 " (%.2f %cb)%s", prefix, value, value / k, sf[i], suffix);
+}
+
+int main(int argc, char *argv[]) {
+ int i, rc;
+ char *prog = argv[0];
+ char *envname;
+ int problems_maindb = 0, problems_freedb = 0, problems_meta = 0;
+ int dont_traversal = 0;
+
+ double elapsed;
+#if defined(_WIN32) || defined(_WIN64)
+ uint64_t timestamp_start, timestamp_finish;
+ timestamp_start = GetTickCount64();
+#else
+ struct timespec timestamp_start, timestamp_finish;
+ if (clock_gettime(CLOCK_MONOTONIC, &timestamp_start)) {
+ rc = errno;
+ error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc));
+ return EXIT_FAILURE_SYS;
+ }
+#endif
+
+ walk.dbi_names[0] = "@gc";
+ atexit(pagemap_cleanup);
+
+ if (argc < 2) {
+ usage(prog);
+ }
+
+ while ((i = getopt(argc, argv, "Vvqnwcds:")) != EOF) {
+ switch (i) {
+ case 'V':
+ printf("%s (%s, build %s)\n", mdbx_version.git.describe,
+ mdbx_version.git.datetime, mdbx_build.datetime);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'n':
+ envflags |= MDBX_NOSUBDIR;
+ break;
+ case 'w':
+ envflags &= ~MDBX_RDONLY;
+ break;
+ case 'c':
+ exclusive = 0;
+ break;
+ case 'd':
+ dont_traversal = 1;
+ break;
+ case 's':
+ if (only_subdb && strcmp(only_subdb, optarg))
+ usage(prog);
+ only_subdb = optarg;
+ break;
+ default:
+ usage(prog);
+ }
+ }
+
+ if (optind != argc - 1)
+ usage(prog);
+
+#if defined(_WIN32) || defined(_WIN64)
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
+#else
+#ifdef SIGPIPE
+ signal(SIGPIPE, signal_handler);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, signal_handler);
+#endif
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+#endif /* !WINDOWS */
+
+ envname = argv[optind];
+ print("Running mdbx_chk for '%s' in %s mode...\n", envname,
+ (envflags & MDBX_RDONLY) ? "read-only" : "write-lock");
+ fflush(NULL);
+
+ rc = mdbx_env_create(&env);
+ if (rc) {
+ error("mdbx_env_create failed, error %d %s\n", rc, mdbx_strerror(rc));
+ return rc < 0 ? EXIT_FAILURE_MDB : EXIT_FAILURE_SYS;
+ }
+
+ rc = mdbx_env_set_maxdbs(env, MAX_DBI);
+ if (rc) {
+ error("mdbx_env_set_maxdbs failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto bailout;
+ }
+
+ rc = mdbx_env_open_ex(env, envname, envflags, 0664, &exclusive);
+ if (rc) {
+ error("mdbx_env_open failed, error %d %s\n", rc, mdbx_strerror(rc));
+ if (rc == MDBX_WANNA_RECOVERY && (envflags & MDBX_RDONLY))
+ print("Please run %s in the read-write mode (with '-w' option).\n", prog);
+ goto bailout;
+ }
+ if (verbose)
+ print(" - %s mode\n", exclusive ? "monopolistic" : "cooperative");
+
+ if (!(envflags & MDBX_RDONLY)) {
+ rc = mdbx_txn_begin(env, NULL, 0, &locktxn);
+ if (rc) {
+ error("mdbx_txn_begin(lock-write) failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto bailout;
+ }
+ }
+
+ rc = mdbx_env_get_maxkeysize(env);
+ if (rc < 0) {
+ error("mdbx_env_get_maxkeysize failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto bailout;
+ }
+ maxkeysize = rc;
+
+ rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
+ if (rc) {
+ error("mdbx_txn_begin(read-only) failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto bailout;
+ }
+
+ rc = mdbx_env_info(env, &envinfo, sizeof(envinfo));
+ if (rc) {
+ error("mdbx_env_info failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto bailout;
+ }
+
+ rc = mdbx_env_stat(env, &envstat, sizeof(envstat));
+ if (rc) {
+ error("mdbx_env_stat failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto bailout;
+ }
+
+ lastpgno = envinfo.mi_last_pgno + 1;
+ errno = 0;
+
+ if (verbose) {
+ print(" - pagesize %u (%u system), max keysize %" PRIuPTR
+ ", max readers %u\n",
+ envinfo.mi_dxb_pagesize, envinfo.mi_sys_pagesize, maxkeysize,
+ envinfo.mi_maxreaders);
+ print_size(" - mapsize ", envinfo.mi_mapsize, "\n");
+ if (envinfo.mi_geo.lower == envinfo.mi_geo.upper)
+ print_size(" - fixed datafile: ", envinfo.mi_geo.current, "");
+ else {
+ print_size(" - dynamic datafile: ", envinfo.mi_geo.lower, "");
+ print_size(" .. ", envinfo.mi_geo.upper, ", ");
+ print_size("+", envinfo.mi_geo.grow, ", ");
+ print_size("-", envinfo.mi_geo.shrink, "\n");
+ print_size(" - current datafile: ", envinfo.mi_geo.current, "");
+ }
+ printf(", %" PRIu64 " pages\n",
+ envinfo.mi_geo.current / envinfo.mi_dxb_pagesize);
+ print(" - transactions: recent %" PRIu64 ", latter reader %" PRIu64
+ ", lag %" PRIi64 "\n",
+ envinfo.mi_recent_txnid, envinfo.mi_latter_reader_txnid,
+ envinfo.mi_recent_txnid - envinfo.mi_latter_reader_txnid);
+
+ verbose_meta(0, envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign);
+ verbose_meta(1, envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign);
+ verbose_meta(2, envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign);
+ }
+
+ if (verbose)
+ print(" - performs check for meta-pages clashes\n");
+ if (meta_eq(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign,
+ envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign)) {
+ print(" - meta-%d and meta-%d are clashed\n", 0, 1);
+ ++problems_meta;
+ }
+ if (meta_eq(envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign,
+ envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign)) {
+ print(" - meta-%d and meta-%d are clashed\n", 1, 2);
+ ++problems_meta;
+ }
+ if (meta_eq(envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign,
+ envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign)) {
+ print(" - meta-%d and meta-%d are clashed\n", 2, 0);
+ ++problems_meta;
+ }
+
+ if (exclusive > 1) {
+ if (verbose)
+ print(" - performs full check recent-txn-id with meta-pages\n");
+ problems_meta += check_meta_head(true);
+ } else if (locktxn) {
+ if (verbose)
+ print(" - performs lite check recent-txn-id with meta-pages (not a "
+ "monopolistic mode)\n");
+ problems_meta += check_meta_head(false);
+ } else if (verbose) {
+ print(" - skip check recent-txn-id with meta-pages (monopolistic or "
+ "write-lock mode only)\n");
+ }
+
+ if (!dont_traversal) {
+ struct problem *saved_list;
+ uint64_t traversal_problems;
+ uint64_t empty_pages, lost_bytes;
+
+ print("Traversal b-tree by txn#%" PRIaTXN "...\n", txn->mt_txnid);
+ fflush(NULL);
+ walk.pagemap = calloc((size_t)lastpgno, sizeof(*walk.pagemap));
+ if (!walk.pagemap) {
+ rc = errno ? errno : MDBX_ENOMEM;
+ error("calloc failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto bailout;
+ }
+
+ saved_list = problems_push();
+ rc = mdbx_env_pgwalk(txn, pgvisitor, NULL);
+ traversal_problems = problems_pop(saved_list);
+
+ if (rc) {
+ if (rc == MDBX_EINTR && user_break) {
+ print(" - interrupted by signal\n");
+ fflush(NULL);
+ } else {
+ error("mdbx_env_pgwalk failed, error %d %s\n", rc, mdbx_strerror(rc));
+ }
+ goto bailout;
+ }
+
+ uint64_t n;
+ for (n = 0; n < lastpgno; ++n)
+ if (!walk.pagemap[n])
+ walk.dbi_pages[0] += 1;
+
+ empty_pages = lost_bytes = 0;
+ for (i = 1; i < MAX_DBI && walk.dbi_names[i]; ++i) {
+ empty_pages += walk.dbi_empty_pages[i];
+ lost_bytes += walk.dbi_lost_bytes[i];
+ }
+
+ if (verbose) {
+ uint64_t total_page_bytes = walk.pgcount * envstat.ms_psize;
+ print(" - dbi pages: %" PRIu64 " total", walk.pgcount);
+ if (verbose > 1)
+ for (i = 1; i < MAX_DBI && walk.dbi_names[i]; ++i)
+ print(", %s %" PRIu64 "", walk.dbi_names[i], walk.dbi_pages[i]);
+ print(", %s %" PRIu64 "\n", walk.dbi_names[0], walk.dbi_pages[0]);
+ if (verbose > 1) {
+ print(" - space info: total %" PRIu64 " bytes, payload %" PRIu64
+ " (%.1f%%), unused "
+ "%" PRIu64 " (%.1f%%)\n",
+ total_page_bytes, walk.total_payload_bytes,
+ walk.total_payload_bytes * 100.0 / total_page_bytes,
+ total_page_bytes - walk.total_payload_bytes,
+ (total_page_bytes - walk.total_payload_bytes) * 100.0 /
+ total_page_bytes);
+ for (i = 1; i < MAX_DBI && walk.dbi_names[i]; ++i) {
+ uint64_t dbi_bytes = walk.dbi_pages[i] * envstat.ms_psize;
+ print(" %s: subtotal %" PRIu64 " bytes (%.1f%%),"
+ " payload %" PRIu64 " (%.1f%%), unused %" PRIu64 " (%.1f%%)",
+ walk.dbi_names[i], dbi_bytes,
+ dbi_bytes * 100.0 / total_page_bytes, walk.dbi_payload_bytes[i],
+ walk.dbi_payload_bytes[i] * 100.0 / dbi_bytes,
+ dbi_bytes - walk.dbi_payload_bytes[i],
+ (dbi_bytes - walk.dbi_payload_bytes[i]) * 100.0 / dbi_bytes);
+ if (walk.dbi_empty_pages[i])
+ print(", %" PRIu64 " empty pages", walk.dbi_empty_pages[i]);
+ if (walk.dbi_lost_bytes[i])
+ print(", %" PRIu64 " bytes lost", walk.dbi_lost_bytes[i]);
+ print("\n");
+ }
+ }
+ print(" - summary: average fill %.1f%%",
+ walk.total_payload_bytes * 100.0 / total_page_bytes);
+ if (empty_pages)
+ print(", %" PRIuPTR " empty pages", empty_pages);
+ if (lost_bytes)
+ print(", %" PRIuPTR " bytes lost", lost_bytes);
+ print(", %" PRIuPTR " problems\n", traversal_problems);
+ }
+ } else if (verbose) {
+ print("Skipping b-tree walk...\n");
+ fflush(NULL);
+ }
+
+ if (!verbose)
+ print("Iterating DBIs...\n");
+ problems_maindb = process_db(~0u, /* MAIN_DBI */ NULL, NULL, false);
+ problems_freedb = process_db(FREE_DBI, "free", handle_freedb, false);
+
+ if (verbose) {
+ uint64_t value = envinfo.mi_mapsize / envstat.ms_psize;
+ double percent = value / 100.0;
+ print(" - pages info: %" PRIu64 " total", value);
+ value = envinfo.mi_geo.current / envinfo.mi_dxb_pagesize;
+ print(", backed %" PRIu64 " (%.1f%%)", value, value / percent);
+ print(", allocated %" PRIu64 " (%.1f%%)", lastpgno, lastpgno / percent);
+
+ if (verbose > 1) {
+ value = envinfo.mi_mapsize / envstat.ms_psize - lastpgno;
+ print(", remained %" PRIu64 " (%.1f%%)", value, value / percent);
+
+ value = lastpgno - freedb_pages;
+ print(", used %" PRIu64 " (%.1f%%)", value, value / percent);
+
+ print(", gc %" PRIu64 " (%.1f%%)", freedb_pages, freedb_pages / percent);
+
+ value = freedb_pages - reclaimable_pages;
+ print(", detained %" PRIu64 " (%.1f%%)", value, value / percent);
+
+ print(", reclaimable %" PRIu64 " (%.1f%%)", reclaimable_pages,
+ reclaimable_pages / percent);
+ }
+
+ value =
+ envinfo.mi_mapsize / envstat.ms_psize - lastpgno + reclaimable_pages;
+ print(", available %" PRIu64 " (%.1f%%)\n", value, value / percent);
+ }
+
+ if (problems_maindb == 0 && problems_freedb == 0) {
+ if (!dont_traversal && (exclusive || locktxn)) {
+ if (walk.pgcount != lastpgno - freedb_pages) {
+ error("used pages mismatch (%" PRIu64 " != %" PRIu64 ")\n",
+ walk.pgcount, lastpgno - freedb_pages);
+ }
+ if (walk.dbi_pages[0] != freedb_pages) {
+ error("gc pages mismatch (%" PRIu64 " != %" PRIu64 ")\n",
+ walk.dbi_pages[0], freedb_pages);
+ }
+ } else if (verbose) {
+ print(" - skip check used and gc pages (btree-traversal with "
+ "monopolistic or write-lock mode only)\n");
+ }
+
+ if (!process_db(MAIN_DBI, NULL, handle_maindb, true)) {
+ if (!userdb_count && verbose)
+ print(" - does not contain multiple databases\n");
+ }
+ }
+
+bailout:
+ if (txn)
+ mdbx_txn_abort(txn);
+ if (locktxn)
+ mdbx_txn_abort(locktxn);
+ if (env)
+ mdbx_env_close(env);
+ fflush(NULL);
+ if (rc) {
+ if (rc < 0)
+ return (user_break) ? EXIT_INTERRUPTED : EXIT_FAILURE_SYS;
+ return EXIT_FAILURE_MDB;
+ }
+
+#if defined(_WIN32) || defined(_WIN64)
+ timestamp_finish = GetTickCount64();
+ elapsed = (timestamp_finish - timestamp_start) * 1e-3;
+#else
+ if (clock_gettime(CLOCK_MONOTONIC, &timestamp_finish)) {
+ rc = errno;
+ error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc));
+ return EXIT_FAILURE_SYS;
+ }
+ elapsed = timestamp_finish.tv_sec - timestamp_start.tv_sec +
+ (timestamp_finish.tv_nsec - timestamp_start.tv_nsec) * 1e-9;
+#endif /* !WINDOWS */
+
+ total_problems += problems_meta;
+ if (total_problems || problems_maindb || problems_freedb) {
+ print("Total %" PRIu64 " error(s) is detected, elapsed %.3f seconds.\n",
+ total_problems, elapsed);
+ if (problems_meta || problems_maindb || problems_freedb)
+ return EXIT_FAILURE_CHECK_MAJOR;
+ return EXIT_FAILURE_CHECK_MINOR;
+ }
+ print("No error is detected, elapsed %.3f seconds\n", elapsed);
+ return EXIT_SUCCESS;
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.vcxproj b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.vcxproj
new file mode 100644
index 0000000000..d4cc420d36
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_chk.vcxproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{15030120-5F7F-48F9-ABE5-DFC814F2A4BE}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>mdbx_chk</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\dll.vcxproj">
+ <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="mdbx_chk.c" />
+ <ClCompile Include="wingetopt.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\mdbx.h" />
+ <ClInclude Include="wingetopt.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.1 b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.1
new file mode 100644
index 0000000000..825fb269e5
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.1
@@ -0,0 +1,57 @@
+.\" Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>.
+.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
+.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
+.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
+.TH MDBX_COPY 1 "2014/06/20" "LMDB 0.9.14"
+.SH NAME
+mdbx_copy \- MDBX environment copy tool
+.SH SYNOPSIS
+.B mdbx_copy
+[\c
+.BR \-V ]
+[\c
+.BR \-c ]
+[\c
+.BR \-n ]
+.B srcpath
+[\c
+.BR dstpath ]
+.SH DESCRIPTION
+The
+.B mdbx_copy
+utility copies an MDBX environment. The environment can
+be copied regardless of whether it is currently in use.
+No lockfile is created, since it gets recreated at need.
+
+If
+.I dstpath
+is specified it must be the path of an empty directory
+for storing the backup. Otherwise, the backup will be
+written to stdout.
+
+.SH OPTIONS
+.TP
+.BR \-V
+Write the library version number to the standard output, and exit.
+.TP
+.BR \-c
+Compact while copying. Only current data pages will be copied; freed
+or unused pages will be omitted from the copy. This option will
+slow down the backup process as it is more CPU-intensive.
+Currently it fails if the environment has suffered a page leak.
+.TP
+.BR \-n
+Open LDMB environment(s) which do not use subdirectories.
+
+.SH DIAGNOSTICS
+Exit status is zero if no errors occur.
+Errors result in a non-zero exit status and
+a diagnostic message being written to standard error.
+.SH CAVEATS
+This utility can trigger significant file size growth if run
+in parallel with write transactions, because pages which they
+free during copying cannot be reused until the copy is done.
+.SH "SEE ALSO"
+.BR mdbx_stat (1)
+.SH AUTHOR
+Howard Chu of Symas Corporation <http://www.symas.com>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.c
new file mode 100644
index 0000000000..6d57113418
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.c
@@ -0,0 +1,107 @@
+/* mdbx_copy.c - memory-mapped database backup tool */
+
+/*
+ * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>. */
+
+#ifdef _MSC_VER
+#if _MSC_VER > 1800
+#pragma warning(disable : 4464) /* relative include path contains '..' */
+#endif
+#pragma warning(disable : 4996) /* The POSIX name is deprecated... */
+#endif /* _MSC_VER (warnings) */
+
+#include "../bits.h"
+
+#if defined(_WIN32) || defined(_WIN64)
+#include "wingetopt.h"
+
+static volatile BOOL user_break;
+static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
+ (void)dwCtrlType;
+ user_break = true;
+ return true;
+}
+
+#else /* WINDOWS */
+
+static volatile sig_atomic_t user_break;
+static void signal_handler(int sig) {
+ (void)sig;
+ user_break = 1;
+}
+
+#endif /* !WINDOWS */
+
+int main(int argc, char *argv[]) {
+ int rc;
+ MDBX_env *env = NULL;
+ const char *progname = argv[0], *act;
+ unsigned flags = MDBX_RDONLY;
+ unsigned cpflags = 0;
+
+ for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
+ if (argv[1][1] == 'n' && argv[1][2] == '\0')
+ flags |= MDBX_NOSUBDIR;
+ else if (argv[1][1] == 'c' && argv[1][2] == '\0')
+ cpflags |= MDBX_CP_COMPACT;
+ else if (argv[1][1] == 'V' && argv[1][2] == '\0') {
+ printf("%s (%s, build %s)\n", mdbx_version.git.describe,
+ mdbx_version.git.datetime, mdbx_build.datetime);
+ exit(EXIT_SUCCESS);
+ } else
+ argc = 0;
+ }
+
+ if (argc < 2 || argc > 3) {
+ fprintf(stderr, "usage: %s [-V] [-c] [-n] srcpath [dstpath]\n", progname);
+ exit(EXIT_FAILURE);
+ }
+
+#if defined(_WIN32) || defined(_WIN64)
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
+#else
+#ifdef SIGPIPE
+ signal(SIGPIPE, signal_handler);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, signal_handler);
+#endif
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+#endif /* !WINDOWS */
+
+ act = "opening environment";
+ rc = mdbx_env_create(&env);
+ if (rc == MDBX_SUCCESS) {
+ rc = mdbx_env_open(env, argv[1], flags, 0640);
+ }
+ if (rc == MDBX_SUCCESS) {
+ act = "copying";
+ if (argc == 2) {
+ mdbx_filehandle_t fd;
+#if defined(_WIN32) || defined(_WIN64)
+ fd = GetStdHandle(STD_OUTPUT_HANDLE);
+#else
+ fd = fileno(stdout);
+#endif
+ rc = mdbx_env_copy2fd(env, fd, cpflags);
+ } else
+ rc = mdbx_env_copy(env, argv[2], cpflags);
+ }
+ if (rc)
+ fprintf(stderr, "%s: %s failed, error %d (%s)\n", progname, act, rc,
+ mdbx_strerror(rc));
+ mdbx_env_close(env);
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.vcxproj b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.vcxproj
new file mode 100644
index 0000000000..6910060fcb
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_copy.vcxproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{15030120-5F7F-48F9-ABE5-DFC814F2A4BD}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>mdbx_copy</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\dll.vcxproj">
+ <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="mdbx_copy.c" />
+ <ClCompile Include="wingetopt.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\mdbx.h" />
+ <ClInclude Include="wingetopt.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.1 b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.1
new file mode 100644
index 0000000000..f8dd62a1ce
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.1
@@ -0,0 +1,77 @@
+.\" Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>.
+.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
+.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
+.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
+.TH MDBX_DUMP 1 "2014/06/20" "LMDB 0.9.14"
+.SH NAME
+mdbx_dump \- MDBX environment export tool
+.SH SYNOPSIS
+.B mdbx_dump
+[\c
+.BR \-V ]
+[\c
+.BI \-f \ file\fR]
+[\c
+.BR \-l ]
+[\c
+.BR \-n ]
+[\c
+.BR \-p ]
+[\c
+.BR \-a \ |
+.BI \-s \ subdb\fR]
+.BR \ envpath
+.SH DESCRIPTION
+The
+.B mdbx_dump
+utility reads a database and writes its contents to the
+standard output using a portable flat-text format
+understood by the
+.BR mdbx_load (1)
+utility.
+.SH OPTIONS
+.TP
+.BR \-V
+Write the library version number to the standard output, and exit.
+.TP
+.BR \-f \ file
+Write to the specified file instead of to the standard output.
+.TP
+.BR \-l
+List the databases stored in the environment. Just the
+names will be listed, no data will be output.
+.TP
+.BR \-n
+Dump an MDBX database which does not use subdirectories.
+.TP
+.BR \-p
+If characters in either the key or data items are printing characters (as
+defined by isprint(3)), output them directly. This option permits users to
+use standard text editors and tools to modify the contents of databases.
+
+Note: different systems may have different notions about what characters
+are considered printing characters, and databases dumped in this manner may
+be less portable to external systems.
+.TP
+.BR \-a
+Dump all of the subdatabases in the environment.
+.TP
+.BR \-s \ subdb
+Dump a specific subdatabase. If no database is specified, only the main database is dumped.
+.SH DIAGNOSTICS
+Exit status is zero if no errors occur.
+Errors result in a non-zero exit status and
+a diagnostic message being written to standard error.
+
+Dumping and reloading databases that use user-defined comparison functions
+will result in new databases that use the default comparison functions.
+\fBIn this case it is quite likely that the reloaded database will be
+damaged beyond repair permitting neither record storage nor retrieval.\fP
+
+The only available workaround is to modify the source for the
+.BR mdbx_load (1)
+utility to load the database using the correct comparison functions.
+.SH "SEE ALSO"
+.BR mdbx_load (1)
+.SH AUTHOR
+Howard Chu of Symas Corporation <http://www.symas.com>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.c
new file mode 100644
index 0000000000..d0f9a91121
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.c
@@ -0,0 +1,336 @@
+/* mdbx_dump.c - memory-mapped database dump tool */
+
+/*
+ * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>. */
+
+#ifdef _MSC_VER
+#if _MSC_VER > 1800
+#pragma warning(disable : 4464) /* relative include path contains '..' */
+#endif
+#pragma warning(disable : 4996) /* The POSIX name is deprecated... */
+#endif /* _MSC_VER (warnings) */
+
+#include "../bits.h"
+#include <ctype.h>
+
+#define PRINT 1
+static int mode;
+
+typedef struct flagbit {
+ int bit;
+ char *name;
+} flagbit;
+
+flagbit dbflags[] = {{MDBX_REVERSEKEY, "reversekey"},
+ {MDBX_DUPSORT, "dupsort"},
+ {MDBX_INTEGERKEY, "integerkey"},
+ {MDBX_DUPFIXED, "dupfixed"},
+ {MDBX_INTEGERDUP, "integerdup"},
+ {MDBX_REVERSEDUP, "reversedup"},
+ {0, NULL}};
+
+#if defined(_WIN32) || defined(_WIN64)
+#include "wingetopt.h"
+
+static volatile BOOL user_break;
+static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
+ (void)dwCtrlType;
+ user_break = true;
+ return true;
+}
+
+#else /* WINDOWS */
+
+static volatile sig_atomic_t user_break;
+static void signal_handler(int sig) {
+ (void)sig;
+ user_break = 1;
+}
+
+#endif /* !WINDOWS */
+
+static const char hexc[] = "0123456789abcdef";
+
+static void dumpbyte(unsigned char c) {
+ putchar(hexc[c >> 4]);
+ putchar(hexc[c & 0xf]);
+}
+
+static void text(MDBX_val *v) {
+ unsigned char *c, *end;
+
+ putchar(' ');
+ c = v->iov_base;
+ end = c + v->iov_len;
+ while (c < end) {
+ if (isprint(*c) && *c != '\\') {
+ putchar(*c);
+ } else {
+ putchar('\\');
+ dumpbyte(*c);
+ }
+ c++;
+ }
+ putchar('\n');
+}
+
+static void dumpval(MDBX_val *v) {
+ unsigned char *c, *end;
+
+ putchar(' ');
+ c = v->iov_base;
+ end = c + v->iov_len;
+ while (c < end) {
+ dumpbyte(*c++);
+ }
+ putchar('\n');
+}
+
+/* Dump in BDB-compatible format */
+static int dumpit(MDBX_txn *txn, MDBX_dbi dbi, char *name) {
+ MDBX_cursor *mc;
+ MDBX_stat ms;
+ MDBX_val key, data;
+ MDBX_envinfo info;
+ unsigned int flags;
+ int rc, i;
+
+ rc = mdbx_dbi_flags(txn, dbi, &flags);
+ if (rc)
+ return rc;
+
+ rc = mdbx_dbi_stat(txn, dbi, &ms, sizeof(ms));
+ if (rc)
+ return rc;
+
+ rc = mdbx_env_info(mdbx_txn_env(txn), &info, sizeof(info));
+ if (rc)
+ return rc;
+
+ printf("VERSION=3\n");
+ printf("format=%s\n", mode & PRINT ? "print" : "bytevalue");
+ if (name)
+ printf("database=%s\n", name);
+ printf("type=btree\n");
+ printf("mapsize=%" PRIu64 "\n", info.mi_mapsize);
+ printf("maxreaders=%u\n", info.mi_maxreaders);
+
+ for (i = 0; dbflags[i].bit; i++)
+ if (flags & dbflags[i].bit)
+ printf("%s=1\n", dbflags[i].name);
+
+ printf("db_pagesize=%d\n", ms.ms_psize);
+ printf("HEADER=END\n");
+
+ rc = mdbx_cursor_open(txn, dbi, &mc);
+ if (rc)
+ return rc;
+
+ while ((rc = mdbx_cursor_get(mc, &key, &data, MDBX_NEXT)) == MDBX_SUCCESS) {
+ if (user_break) {
+ rc = MDBX_EINTR;
+ break;
+ }
+ if (mode & PRINT) {
+ text(&key);
+ text(&data);
+ } else {
+ dumpval(&key);
+ dumpval(&data);
+ }
+ }
+ printf("DATA=END\n");
+ if (rc == MDBX_NOTFOUND)
+ rc = MDBX_SUCCESS;
+
+ return rc;
+}
+
+static void usage(char *prog) {
+ fprintf(stderr,
+ "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n",
+ prog);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[]) {
+ int i, rc;
+ MDBX_env *env;
+ MDBX_txn *txn;
+ MDBX_dbi dbi;
+ char *prog = argv[0];
+ char *envname;
+ char *subname = NULL;
+ int alldbs = 0, envflags = 0, list = 0;
+
+ if (argc < 2) {
+ usage(prog);
+ }
+
+ /* -a: dump main DB and all subDBs
+ * -s: dump only the named subDB
+ * -n: use NOSUBDIR flag on env_open
+ * -p: use printable characters
+ * -f: write to file instead of stdout
+ * -V: print version and exit
+ * (default) dump only the main DB
+ */
+ while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) {
+ switch (i) {
+ case 'V':
+ printf("%s (%s, build %s)\n", mdbx_version.git.describe,
+ mdbx_version.git.datetime, mdbx_build.datetime);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'l':
+ list = 1;
+ /*FALLTHROUGH*/;
+ __fallthrough;
+ case 'a':
+ if (subname)
+ usage(prog);
+ alldbs++;
+ break;
+ case 'f':
+ if (freopen(optarg, "w", stdout) == NULL) {
+ fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'n':
+ envflags |= MDBX_NOSUBDIR;
+ break;
+ case 'p':
+ mode |= PRINT;
+ break;
+ case 's':
+ if (alldbs)
+ usage(prog);
+ subname = optarg;
+ break;
+ default:
+ usage(prog);
+ }
+ }
+
+ if (optind != argc - 1)
+ usage(prog);
+
+#if defined(_WIN32) || defined(_WIN64)
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
+#else
+#ifdef SIGPIPE
+ signal(SIGPIPE, signal_handler);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, signal_handler);
+#endif
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+#endif /* !WINDOWS */
+
+ envname = argv[optind];
+ rc = mdbx_env_create(&env);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ return EXIT_FAILURE;
+ }
+
+ if (alldbs || subname) {
+ mdbx_env_set_maxdbs(env, 2);
+ }
+
+ rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
+ if (rc) {
+ fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ rc = mdbx_dbi_open(txn, subname, 0, &dbi);
+ if (rc) {
+ fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ if (alldbs) {
+ MDBX_cursor *cursor;
+ MDBX_val key;
+ int count = 0;
+
+ rc = mdbx_cursor_open(txn, dbi, &cursor);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) {
+ if (user_break) {
+ rc = MDBX_EINTR;
+ break;
+ }
+ char *str;
+ MDBX_dbi db2;
+ if (memchr(key.iov_base, '\0', key.iov_len))
+ continue;
+ count++;
+ str = malloc(key.iov_len + 1);
+ memcpy(str, key.iov_base, key.iov_len);
+ str[key.iov_len] = '\0';
+ rc = mdbx_dbi_open(txn, str, 0, &db2);
+ if (rc == MDBX_SUCCESS) {
+ if (list) {
+ printf("%s\n", str);
+ list++;
+ } else {
+ rc = dumpit(txn, db2, str);
+ if (rc)
+ break;
+ }
+ mdbx_dbi_close(env, db2);
+ }
+ free(str);
+ if (rc)
+ continue;
+ }
+ mdbx_cursor_close(cursor);
+ if (!count) {
+ fprintf(stderr, "%s: %s does not contain multiple databases\n", prog,
+ envname);
+ rc = MDBX_NOTFOUND;
+ } else if (rc == MDBX_INCOMPATIBLE) {
+ /* LY: the record it not a named sub-db. */
+ rc = MDBX_SUCCESS;
+ }
+ } else {
+ rc = dumpit(txn, dbi, subname);
+ }
+ if (rc && rc != MDBX_NOTFOUND)
+ fprintf(stderr, "%s: %s: %s\n", prog, envname, mdbx_strerror(rc));
+
+ mdbx_dbi_close(env, dbi);
+txn_abort:
+ mdbx_txn_abort(txn);
+env_close:
+ mdbx_env_close(env);
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.vcxproj b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.vcxproj
new file mode 100644
index 0000000000..b44eb19328
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_dump.vcxproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{15030120-5F7F-48F9-ABE5-DFC814F2A4BC}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>mdbx_dump</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\dll.vcxproj">
+ <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="mdbx_dump.c" />
+ <ClCompile Include="wingetopt.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\mdbx.h" />
+ <ClInclude Include="wingetopt.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.1 b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.1
new file mode 100644
index 0000000000..ac04101c89
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.1
@@ -0,0 +1,79 @@
+.\" Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>.
+.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
+.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
+.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
+.TH MDBX_LOAD 1 "2014/06/20" "LMDB 0.9.14"
+.SH NAME
+mdbx_load \- MDBX environment import tool
+.SH SYNOPSIS
+.B mdbx_load
+[\c
+.BR \-V ]
+[\c
+.BI \-f \ file\fR]
+[\c
+.BR \-n ]
+[\c
+.BI \-s \ subdb\fR]
+[\c
+.BR \-N ]
+[\c
+.BR \-T ]
+.BR \ envpath
+.SH DESCRIPTION
+The
+.B mdbx_load
+utility reads from the standard input and loads it into the
+MDBX environment
+.BR envpath .
+
+The input to
+.B mdbx_load
+must be in the output format specified by the
+.BR mdbx_dump (1)
+utility or as specified by the
+.B -T
+option below.
+.SH OPTIONS
+.TP
+.BR \-V
+Write the library version number to the standard output, and exit.
+.TP
+.BR \-f \ file
+Read from the specified file instead of from the standard input.
+.TP
+.BR \-n
+Load an MDBX database which does not use subdirectories.
+.TP
+.BR \-s \ subdb
+Load a specific subdatabase. If no database is specified, data is loaded into the main database.
+.TP
+.BR \-N
+Don't overwrite existing records when loading into an already existing database; just skip them.
+.TP
+.BR \-T
+Load data from simple text files. The input must be paired lines of text, where the first
+line of the pair is the key item, and the second line of the pair is its corresponding
+data item.
+
+A simple escape mechanism, where newline and backslash (\\) characters are special, is
+applied to the text input. Newline characters are interpreted as record separators.
+Backslash characters in the text will be interpreted in one of two ways: If the backslash
+character precedes another backslash character, the pair will be interpreted as a literal
+backslash. If the backslash character precedes any other character, the two characters
+following the backslash will be interpreted as a hexadecimal specification of a single
+character; for example, \\0a is a newline character in the ASCII character set.
+
+For this reason, any backslash or newline characters that naturally occur in the text
+input must be escaped to avoid misinterpretation by
+.BR mdbx_load .
+
+.SH DIAGNOSTICS
+Exit status is zero if no errors occur.
+Errors result in a non-zero exit status and
+a diagnostic message being written to standard error.
+
+.SH "SEE ALSO"
+.BR mdbx_dump (1)
+.SH AUTHOR
+Howard Chu of Symas Corporation <http://www.symas.com>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.c
new file mode 100644
index 0000000000..19a0a3dfb5
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.c
@@ -0,0 +1,513 @@
+/* mdbx_load.c - memory-mapped database load tool */
+
+/*
+ * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>. */
+
+#ifdef _MSC_VER
+#if _MSC_VER > 1800
+#pragma warning(disable : 4464) /* relative include path contains '..' */
+#endif
+#pragma warning(disable : 4996) /* The POSIX name is deprecated... */
+#endif /* _MSC_VER (warnings) */
+
+#include "../bits.h"
+#include <ctype.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+#include "wingetopt.h"
+
+static volatile BOOL user_break;
+static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
+ (void)dwCtrlType;
+ user_break = true;
+ return true;
+}
+
+#else /* WINDOWS */
+
+static volatile sig_atomic_t user_break;
+static void signal_handler(int sig) {
+ (void)sig;
+ user_break = 1;
+}
+
+#endif /* !WINDOWS */
+
+#define PRINT 1
+#define NOHDR 2
+static int mode;
+
+static char *subname = NULL;
+static size_t lineno;
+static int version;
+
+static int dbi_flags;
+static char *prog;
+static int Eof;
+
+static MDBX_envinfo envinfo;
+static MDBX_val kbuf, dbuf;
+
+#define STRLENOF(s) (sizeof(s) - 1)
+
+typedef struct flagbit {
+ int bit;
+ char *name;
+ int len;
+} flagbit;
+
+#define S(s) s, STRLENOF(s)
+
+flagbit dbflags[] = {{MDBX_REVERSEKEY, S("reversekey")},
+ {MDBX_DUPSORT, S("dupsort")},
+ {MDBX_INTEGERKEY, S("integerkey")},
+ {MDBX_DUPFIXED, S("dupfixed")},
+ {MDBX_INTEGERDUP, S("integerdup")},
+ {MDBX_REVERSEDUP, S("reversedup")},
+ {0, NULL, 0}};
+
+static void readhdr(void) {
+ char *ptr;
+
+ dbi_flags = 0;
+ while (fgets(dbuf.iov_base, (int)dbuf.iov_len, stdin) != NULL) {
+ lineno++;
+ if (!strncmp(dbuf.iov_base, "db_pagesize=", STRLENOF("db_pagesize=")) ||
+ !strncmp(dbuf.iov_base, "duplicates=", STRLENOF("duplicates="))) {
+ /* LY: silently ignore information fields. */
+ continue;
+ } else if (!strncmp(dbuf.iov_base, "VERSION=", STRLENOF("VERSION="))) {
+ version = atoi((char *)dbuf.iov_base + STRLENOF("VERSION="));
+ if (version > 3) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported VERSION %d\n",
+ prog, lineno, version);
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp(dbuf.iov_base, "HEADER=END", STRLENOF("HEADER=END"))) {
+ break;
+ } else if (!strncmp(dbuf.iov_base, "format=", STRLENOF("format="))) {
+ if (!strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "print",
+ STRLENOF("print")))
+ mode |= PRINT;
+ else if (strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "bytevalue",
+ STRLENOF("bytevalue"))) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported FORMAT %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("FORMAT="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp(dbuf.iov_base, "database=", STRLENOF("database="))) {
+ ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ if (subname)
+ free(subname);
+ subname = strdup((char *)dbuf.iov_base + STRLENOF("database="));
+ } else if (!strncmp(dbuf.iov_base, "type=", STRLENOF("type="))) {
+ if (strncmp((char *)dbuf.iov_base + STRLENOF("type="), "btree",
+ STRLENOF("btree"))) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported type %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("type="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp(dbuf.iov_base, "mapaddr=", STRLENOF("mapaddr="))) {
+ int i;
+ ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ void *unused;
+ i = sscanf((char *)dbuf.iov_base + STRLENOF("mapaddr="), "%p", &unused);
+ if (i != 1) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapaddr %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("mapaddr="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp(dbuf.iov_base, "mapsize=", STRLENOF("mapsize="))) {
+ int i;
+ ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ i = sscanf((char *)dbuf.iov_base + STRLENOF("mapsize="), "%" PRIu64 "",
+ &envinfo.mi_mapsize);
+ if (i != 1) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapsize %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("mapsize="));
+ exit(EXIT_FAILURE);
+ }
+ } else if (!strncmp(dbuf.iov_base, "maxreaders=",
+ STRLENOF("maxreaders="))) {
+ int i;
+ ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len);
+ if (ptr)
+ *ptr = '\0';
+ i = sscanf((char *)dbuf.iov_base + STRLENOF("maxreaders="), "%u",
+ &envinfo.mi_maxreaders);
+ if (i != 1) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": invalid maxreaders %s\n", prog,
+ lineno, (char *)dbuf.iov_base + STRLENOF("maxreaders="));
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ int i;
+ for (i = 0; dbflags[i].bit; i++) {
+ if (!strncmp(dbuf.iov_base, dbflags[i].name, dbflags[i].len) &&
+ ((char *)dbuf.iov_base)[dbflags[i].len] == '=') {
+ if (((char *)dbuf.iov_base)[dbflags[i].len + 1] == '1')
+ dbi_flags |= dbflags[i].bit;
+ break;
+ }
+ }
+ if (!dbflags[i].bit) {
+ ptr = memchr(dbuf.iov_base, '=', dbuf.iov_len);
+ if (!ptr) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected format\n", prog,
+ lineno);
+ exit(EXIT_FAILURE);
+ } else {
+ *ptr = '\0';
+ fprintf(stderr,
+ "%s: line %" PRIiSIZE ": unrecognized keyword ignored: %s\n",
+ prog, lineno, (char *)dbuf.iov_base);
+ }
+ }
+ }
+ }
+}
+
+static void badend(void) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected end of input\n", prog,
+ lineno);
+}
+
+static int unhex(unsigned char *c2) {
+ int x, c;
+ x = *c2++ & 0x4f;
+ if (x & 0x40)
+ x -= 55;
+ c = x << 4;
+ x = *c2 & 0x4f;
+ if (x & 0x40)
+ x -= 55;
+ c |= x;
+ return c;
+}
+
+static int readline(MDBX_val *out, MDBX_val *buf) {
+ unsigned char *c1, *c2, *end;
+ size_t len, l2;
+ int c;
+
+ if (!(mode & NOHDR)) {
+ c = fgetc(stdin);
+ if (c == EOF) {
+ Eof = 1;
+ return EOF;
+ }
+ if (c != ' ') {
+ lineno++;
+ if (fgets(buf->iov_base, (int)buf->iov_len, stdin) == NULL) {
+ badend:
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ if (c == 'D' && !strncmp(buf->iov_base, "ATA=END", STRLENOF("ATA=END")))
+ return EOF;
+ goto badend;
+ }
+ }
+ if (fgets(buf->iov_base, (int)buf->iov_len, stdin) == NULL) {
+ Eof = 1;
+ return EOF;
+ }
+ lineno++;
+
+ c1 = buf->iov_base;
+ len = strlen((char *)c1);
+ l2 = len;
+
+ /* Is buffer too short? */
+ while (c1[len - 1] != '\n') {
+ buf->iov_base = realloc(buf->iov_base, buf->iov_len * 2);
+ if (!buf->iov_base) {
+ Eof = 1;
+ fprintf(stderr, "%s: line %" PRIiSIZE ": out of memory, line too long\n",
+ prog, lineno);
+ return EOF;
+ }
+ c1 = buf->iov_base;
+ c1 += l2;
+ if (fgets((char *)c1, (int)buf->iov_len + 1, stdin) == NULL) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ buf->iov_len *= 2;
+ len = strlen((char *)c1);
+ l2 += len;
+ }
+ c1 = c2 = buf->iov_base;
+ len = l2;
+ c1[--len] = '\0';
+ end = c1 + len;
+
+ if (mode & PRINT) {
+ while (c2 < end) {
+ if (*c2 == '\\') {
+ if (c2[1] == '\\') {
+ c1++;
+ c2 += 2;
+ } else {
+ if (c2 + 3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ *c1++ = (char)unhex(++c2);
+ c2 += 2;
+ }
+ } else {
+ /* copies are redundant when no escapes were used */
+ *c1++ = *c2++;
+ }
+ }
+ } else {
+ /* odd length not allowed */
+ if (len & 1) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ while (c2 < end) {
+ if (!isxdigit(*c2) || !isxdigit(c2[1])) {
+ Eof = 1;
+ badend();
+ return EOF;
+ }
+ *c1++ = (char)unhex(c2);
+ c2 += 2;
+ }
+ }
+ c2 = out->iov_base = buf->iov_base;
+ out->iov_len = c1 - c2;
+
+ return 0;
+}
+
+static void usage(void) {
+ fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n",
+ prog);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[]) {
+ int i, rc;
+ MDBX_env *env = NULL;
+ MDBX_txn *txn = NULL;
+ MDBX_cursor *mc = NULL;
+ MDBX_dbi dbi;
+ char *envname = NULL;
+ int envflags = 0, putflags = 0;
+
+ prog = argv[0];
+
+ if (argc < 2) {
+ usage();
+ }
+
+ /* -f: load file instead of stdin
+ * -n: use NOSUBDIR flag on env_open
+ * -s: load into named subDB
+ * -N: use NOOVERWRITE on puts
+ * -T: read plaintext
+ * -V: print version and exit
+ */
+ while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
+ switch (i) {
+ case 'V':
+ printf("%s (%s, build %s)\n", mdbx_version.git.describe,
+ mdbx_version.git.datetime, mdbx_build.datetime);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'f':
+ if (freopen(optarg, "r", stdin) == NULL) {
+ fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'n':
+ envflags |= MDBX_NOSUBDIR;
+ break;
+ case 's':
+ subname = strdup(optarg);
+ break;
+ case 'N':
+ putflags = MDBX_NOOVERWRITE | MDBX_NODUPDATA;
+ break;
+ case 'T':
+ mode |= NOHDR | PRINT;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc - 1)
+ usage();
+
+#if defined(_WIN32) || defined(_WIN64)
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
+#else
+#ifdef SIGPIPE
+ signal(SIGPIPE, signal_handler);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, signal_handler);
+#endif
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+#endif /* !WINDOWS */
+
+ dbuf.iov_len = 4096;
+ dbuf.iov_base = malloc(dbuf.iov_len);
+
+ if (!(mode & NOHDR))
+ readhdr();
+
+ envname = argv[optind];
+ rc = mdbx_env_create(&env);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ return EXIT_FAILURE;
+ }
+
+ mdbx_env_set_maxdbs(env, 2);
+
+ if (envinfo.mi_maxreaders)
+ mdbx_env_set_maxreaders(env, envinfo.mi_maxreaders);
+
+ if (envinfo.mi_mapsize) {
+ if (envinfo.mi_mapsize > SIZE_MAX) {
+ fprintf(stderr, "mdbx_env_set_mapsize failed, error %d %s\n", rc,
+ mdbx_strerror(MDBX_TOO_LARGE));
+ return EXIT_FAILURE;
+ }
+ mdbx_env_set_mapsize(env, (size_t)envinfo.mi_mapsize);
+ }
+
+#ifdef MDBX_FIXEDMAP
+ if (info.mi_mapaddr)
+ envflags |= MDBX_FIXEDMAP;
+#endif
+
+ rc = mdbx_env_open(env, envname, envflags, 0664);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ kbuf.iov_len = mdbx_env_get_maxkeysize(env) * 2 + 2;
+ kbuf.iov_base = malloc(kbuf.iov_len);
+
+ while (!Eof) {
+ if (user_break) {
+ rc = MDBX_EINTR;
+ break;
+ }
+
+ MDBX_val key, data;
+ int batch = 0;
+
+ rc = mdbx_txn_begin(env, NULL, 0, &txn);
+ if (rc) {
+ fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ rc = mdbx_dbi_open(txn, subname, dbi_flags | MDBX_CREATE, &dbi);
+ if (rc) {
+ fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ rc = mdbx_cursor_open(txn, dbi, &mc);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ while (1) {
+ rc = readline(&key, &kbuf);
+ if (rc) /* rc == EOF */
+ break;
+
+ rc = readline(&data, &dbuf);
+ if (rc) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": failed to read key value\n",
+ prog, lineno);
+ goto txn_abort;
+ }
+
+ rc = mdbx_cursor_put(mc, &key, &data, putflags);
+ if (rc == MDBX_KEYEXIST && putflags)
+ continue;
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_put failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ batch++;
+ if (batch == 100) {
+ rc = mdbx_txn_commit(txn);
+ if (rc) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog,
+ lineno, mdbx_strerror(rc));
+ goto env_close;
+ }
+ rc = mdbx_txn_begin(env, NULL, 0, &txn);
+ if (rc) {
+ fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+ rc = mdbx_cursor_open(txn, dbi, &mc);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ batch = 0;
+ }
+ }
+ rc = mdbx_txn_commit(txn);
+ txn = NULL;
+ if (rc) {
+ fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog, lineno,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+ mdbx_dbi_close(env, dbi);
+ if (!(mode & NOHDR))
+ readhdr();
+ }
+
+txn_abort:
+ mdbx_txn_abort(txn);
+env_close:
+ mdbx_env_close(env);
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.vcxproj b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.vcxproj
new file mode 100644
index 0000000000..6af6cc457c
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_load.vcxproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{15030120-5F7F-48F9-ABE5-DFC814F2A4BB}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>mdbx_load</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\dll.vcxproj">
+ <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="mdbx_load.c" />
+ <ClCompile Include="wingetopt.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\mdbx.h" />
+ <ClInclude Include="wingetopt.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.1 b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.1
new file mode 100644
index 0000000000..2056decb84
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.1
@@ -0,0 +1,66 @@
+.\" Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>.
+.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
+.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
+.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
+.TH MDBX_STAT 1 "2014/06/20" "LMDB 0.9.14"
+.SH NAME
+mdbx_stat \- MDBX environment status tool
+.SH SYNOPSIS
+.B mdbx_stat
+[\c
+.BR \-V ]
+[\c
+.BR \-e ]
+[\c
+.BR \-f [ f [ f ]]]
+[\c
+.BR \-n ]
+[\c
+.BR \-r [ r ]]
+[\c
+.BR \-a \ |
+.BI \-s \ subdb\fR]
+.BR \ envpath
+.SH DESCRIPTION
+The
+.B mdbx_stat
+utility displays the status of an MDBX environment.
+.SH OPTIONS
+.TP
+.BR \-V
+Write the library version number to the standard output, and exit.
+.TP
+.BR \-e
+Display information about the database environment.
+.TP
+.BR \-f
+Display information about the environment freelist.
+If \fB\-ff\fP is given, summarize each freelist entry.
+If \fB\-fff\fP is given, display the full list of page IDs in the freelist.
+.TP
+.BR \-n
+Display the status of an MDBX database which does not use subdirectories.
+.TP
+.BR \-r
+Display information about the environment reader table.
+Shows the process ID, thread ID, and transaction ID for each active
+reader slot. The process ID and transaction ID are in decimal, the
+thread ID is in hexadecimal. The transaction ID is displayed as "-"
+if the reader does not currently have a read transaction open.
+If \fB\-rr\fP is given, check for stale entries in the reader
+table and clear them. The reader table will be printed again
+after the check is performed.
+.TP
+.BR \-a
+Display the status of all of the subdatabases in the environment.
+.TP
+.BR \-s \ subdb
+Display the status of a specific subdatabase.
+.SH DIAGNOSTICS
+Exit status is zero if no errors occur.
+Errors result in a non-zero exit status and
+a diagnostic message being written to standard error.
+.SH "SEE ALSO"
+.BR mdbx_copy (1)
+.SH AUTHOR
+Howard Chu of Symas Corporation <http://www.symas.com>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.c
new file mode 100644
index 0000000000..249837c653
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.c
@@ -0,0 +1,385 @@
+/* mdbx_stat.c - memory-mapped database status tool */
+
+/*
+ * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * and other libmdbx authors: please see AUTHORS file.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>. */
+
+#ifdef _MSC_VER
+#if _MSC_VER > 1800
+#pragma warning(disable : 4464) /* relative include path contains '..' */
+#endif
+#pragma warning(disable : 4996) /* The POSIX name is deprecated... */
+#endif /* _MSC_VER (warnings) */
+
+#include "../bits.h"
+
+#if defined(_WIN32) || defined(_WIN64)
+#include "wingetopt.h"
+
+static volatile BOOL user_break;
+static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
+ (void)dwCtrlType;
+ user_break = true;
+ return true;
+}
+
+#else /* WINDOWS */
+
+static volatile sig_atomic_t user_break;
+static void signal_handler(int sig) {
+ (void)sig;
+ user_break = 1;
+}
+
+#endif /* !WINDOWS */
+
+static void prstat(MDBX_stat *ms) {
+ printf(" Pagesize: %u\n", ms->ms_psize);
+ printf(" Tree depth: %u\n", ms->ms_depth);
+ printf(" Branch pages: %" PRIu64 "\n", ms->ms_branch_pages);
+ printf(" Leaf pages: %" PRIu64 "\n", ms->ms_leaf_pages);
+ printf(" Overflow pages: %" PRIu64 "\n", ms->ms_overflow_pages);
+ printf(" Entries: %" PRIu64 "\n", ms->ms_entries);
+}
+
+static void usage(char *prog) {
+ fprintf(stderr,
+ "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n",
+ prog);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[]) {
+ int o, rc;
+ MDBX_env *env;
+ MDBX_txn *txn;
+ MDBX_dbi dbi;
+ MDBX_stat mst;
+ MDBX_envinfo mei;
+ char *prog = argv[0];
+ char *envname;
+ char *subname = NULL;
+ int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
+
+ if (argc < 2) {
+ usage(prog);
+ }
+
+ /* -a: print stat of main DB and all subDBs
+ * -s: print stat of only the named subDB
+ * -e: print env info
+ * -f: print freelist info
+ * -r: print reader info
+ * -n: use NOSUBDIR flag on env_open
+ * -V: print version and exit
+ * (default) print stat of only the main DB
+ */
+ while ((o = getopt(argc, argv, "Vaefnrs:")) != EOF) {
+ switch (o) {
+ case 'V':
+ printf("%s (%s, build %s)\n", mdbx_version.git.describe,
+ mdbx_version.git.datetime, mdbx_build.datetime);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'a':
+ if (subname)
+ usage(prog);
+ alldbs++;
+ break;
+ case 'e':
+ envinfo++;
+ break;
+ case 'f':
+ freinfo++;
+ break;
+ case 'n':
+ envflags |= MDBX_NOSUBDIR;
+ break;
+ case 'r':
+ rdrinfo++;
+ break;
+ case 's':
+ if (alldbs)
+ usage(prog);
+ subname = optarg;
+ break;
+ default:
+ usage(prog);
+ }
+ }
+
+ if (optind != argc - 1)
+ usage(prog);
+
+#if defined(_WIN32) || defined(_WIN64)
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
+#else
+#ifdef SIGPIPE
+ signal(SIGPIPE, signal_handler);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, signal_handler);
+#endif
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+#endif /* !WINDOWS */
+
+ envname = argv[optind];
+ rc = mdbx_env_create(&env);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ return EXIT_FAILURE;
+ }
+
+ if (alldbs || subname) {
+ mdbx_env_set_maxdbs(env, 4);
+ }
+
+ rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664);
+ if (rc) {
+ fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ if (envinfo) {
+ (void)mdbx_env_stat(env, &mst, sizeof(mst));
+ (void)mdbx_env_info(env, &mei, sizeof(mei));
+ printf("Environment Info\n");
+ printf(" Pagesize: %u\n", mst.ms_psize);
+ if (mei.mi_geo.lower != mei.mi_geo.upper) {
+ printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64
+ "/-%" PRIu64 "), %" PRIu64 "..%" PRIu64 " pages (+%" PRIu64
+ "/-%" PRIu64 ")\n",
+ mei.mi_geo.lower, mei.mi_geo.upper, mei.mi_geo.grow,
+ mei.mi_geo.shrink, mei.mi_geo.lower / mst.ms_psize,
+ mei.mi_geo.upper / mst.ms_psize, mei.mi_geo.grow / mst.ms_psize,
+ mei.mi_geo.shrink / mst.ms_psize);
+ printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n",
+ mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize);
+ } else {
+ printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n",
+ mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize);
+ }
+ printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n",
+ mei.mi_mapsize, mei.mi_mapsize / mst.ms_psize);
+ printf(" Number of pages used: %" PRIu64 "\n", mei.mi_last_pgno + 1);
+ printf(" Last transaction ID: %" PRIu64 "\n", mei.mi_recent_txnid);
+ printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n",
+ mei.mi_latter_reader_txnid,
+ mei.mi_latter_reader_txnid - mei.mi_recent_txnid);
+ printf(" Max readers: %u\n", mei.mi_maxreaders);
+ printf(" Number of readers used: %u\n", mei.mi_numreaders);
+ } else {
+ /* LY: zap warnings from gcc */
+ memset(&mst, 0, sizeof(mst));
+ memset(&mei, 0, sizeof(mei));
+ }
+
+ if (rdrinfo) {
+ printf("Reader Table Status\n");
+ rc = mdbx_reader_list(env, (MDBX_msg_func *)fputs, stdout);
+ if (rdrinfo > 1) {
+ int dead;
+ mdbx_reader_check(env, &dead);
+ printf(" %d stale readers cleared.\n", dead);
+ rc = mdbx_reader_list(env, (MDBX_msg_func *)fputs, stdout);
+ }
+ if (!(subname || alldbs || freinfo))
+ goto env_close;
+ }
+
+ rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
+ if (rc) {
+ fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto env_close;
+ }
+
+ if (freinfo) {
+ MDBX_cursor *cursor;
+ MDBX_val key, data;
+ pgno_t pages = 0, *iptr;
+ pgno_t reclaimable = 0;
+
+ printf("Freelist Status\n");
+ dbi = 0;
+ rc = mdbx_cursor_open(txn, dbi, &cursor);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst));
+ if (rc) {
+ fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ prstat(&mst);
+ while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) ==
+ MDBX_SUCCESS) {
+ if (user_break) {
+ rc = MDBX_EINTR;
+ break;
+ }
+ iptr = data.iov_base;
+ const pgno_t number = *iptr++;
+
+ pages += number;
+ if (envinfo && mei.mi_latter_reader_txnid > *(size_t *)key.iov_base)
+ reclaimable += number;
+
+ if (freinfo > 1) {
+ char *bad = "";
+ pgno_t prev =
+ MDBX_PNL_ASCENDING ? NUM_METAS - 1 : (pgno_t)mei.mi_last_pgno + 1;
+ pgno_t span = 1;
+ for (unsigned i = 0; i < number; ++i) {
+ pgno_t pg = iptr[i];
+ if (MDBX_PNL_DISORDERED(prev, pg))
+ bad = " [bad sequence]";
+ prev = pg;
+ while (i + span < number &&
+ iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span)
+ : pgno_sub(pg, span)))
+ ++span;
+ }
+ printf(" Transaction %" PRIaTXN ", %" PRIaPGNO
+ " pages, maxspan %" PRIaPGNO "%s\n",
+ *(txnid_t *)key.iov_base, number, span, bad);
+ if (freinfo > 2) {
+ for (unsigned i = 0; i < number; i += span) {
+ const pgno_t pg = iptr[i];
+ for (span = 1;
+ i + span < number &&
+ iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span)
+ : pgno_sub(pg, span));
+ ++span)
+ ;
+ if (span > 1)
+ printf(" %9" PRIaPGNO "[%" PRIaPGNO "]\n", pg, span);
+ else
+ printf(" %9" PRIaPGNO "\n", pg);
+ }
+ }
+ }
+ }
+ mdbx_cursor_close(cursor);
+
+ switch (rc) {
+ case MDBX_SUCCESS:
+ case MDBX_NOTFOUND:
+ break;
+ case MDBX_EINTR:
+ fprintf(stderr, "Interrupted by signal/user\n");
+ goto txn_abort;
+ default:
+ fprintf(stderr, "mdbx_cursor_get failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ if (envinfo) {
+ uint64_t value = mei.mi_mapsize / mst.ms_psize;
+ double percent = value / 100.0;
+ printf("Page Allocation Info\n");
+ printf(" Max pages: %" PRIu64 " 100%%\n", value);
+
+ value = mei.mi_last_pgno + 1;
+ printf(" Pages used: %" PRIu64 " %.1f%%\n", value, value / percent);
+
+ value = mei.mi_mapsize / mst.ms_psize - (mei.mi_last_pgno + 1);
+ printf(" Remained: %" PRIu64 " %.1f%%\n", value, value / percent);
+
+ value = mei.mi_last_pgno + 1 - pages;
+ printf(" Used now: %" PRIu64 " %.1f%%\n", value, value / percent);
+
+ value = pages;
+ printf(" Unallocated: %" PRIu64 " %.1f%%\n", value, value / percent);
+
+ value = pages - reclaimable;
+ printf(" Detained: %" PRIu64 " %.1f%%\n", value, value / percent);
+
+ value = reclaimable;
+ printf(" Reclaimable: %" PRIu64 " %.1f%%\n", value, value / percent);
+
+ value =
+ mei.mi_mapsize / mst.ms_psize - (mei.mi_last_pgno + 1) + reclaimable;
+ printf(" Available: %" PRIu64 " %.1f%%\n", value, value / percent);
+ } else
+ printf(" Free pages: %" PRIaPGNO "\n", pages);
+ }
+
+ rc = mdbx_dbi_open(txn, subname, 0, &dbi);
+ if (rc) {
+ fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc));
+ goto txn_abort;
+ }
+
+ rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst));
+ if (rc) {
+ fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ printf("Status of %s\n", subname ? subname : "Main DB");
+ prstat(&mst);
+
+ if (alldbs) {
+ MDBX_cursor *cursor;
+ MDBX_val key;
+
+ rc = mdbx_cursor_open(txn, dbi, &cursor);
+ if (rc) {
+ fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) {
+ char *str;
+ MDBX_dbi db2;
+ if (memchr(key.iov_base, '\0', key.iov_len))
+ continue;
+ str = malloc(key.iov_len + 1);
+ memcpy(str, key.iov_base, key.iov_len);
+ str[key.iov_len] = '\0';
+ rc = mdbx_dbi_open(txn, str, 0, &db2);
+ if (rc == MDBX_SUCCESS)
+ printf("Status of %s\n", str);
+ free(str);
+ if (rc)
+ continue;
+ rc = mdbx_dbi_stat(txn, db2, &mst, sizeof(mst));
+ if (rc) {
+ fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc,
+ mdbx_strerror(rc));
+ goto txn_abort;
+ }
+ prstat(&mst);
+ mdbx_dbi_close(env, db2);
+ }
+ mdbx_cursor_close(cursor);
+ }
+
+ if (rc == MDBX_NOTFOUND)
+ rc = MDBX_SUCCESS;
+
+ mdbx_dbi_close(env, dbi);
+txn_abort:
+ mdbx_txn_abort(txn);
+env_close:
+ mdbx_env_close(env);
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.vcxproj b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.vcxproj
new file mode 100644
index 0000000000..1adcefde89
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/mdbx_stat.vcxproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{15030120-5F7F-48F9-ABE5-DFC814F2A4BF}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>mdbx_stat</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\dll.vcxproj">
+ <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="mdbx_stat.c" />
+ <ClCompile Include="wingetopt.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\mdbx.h" />
+ <ClInclude Include="wingetopt.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.c b/plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.c
new file mode 100644
index 0000000000..1dd0d069fb
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.c
@@ -0,0 +1,95 @@
+/*
+ * POSIX getopt for Windows
+ *
+ * AT&T Public License
+ *
+ * Code given out at the 1985 UNIFORUM conference in Dallas.
+ */
+
+/*----------------------------------------------------------------------------*/
+/* Microsoft compiler generates a lot of warning for self includes... */
+
+#ifdef _MSC_VER
+#pragma warning(push, 1)
+#pragma warning(disable : 4548) /* expression before comma has no effect; \
+ expected expression with side - effect */
+#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \
+ * semantics are not enabled. Specify /EHsc */
+#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \
+ * mode specified; termination on exception is \
+ * not guaranteed. Specify /EHsc */
+#if !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+#endif /* _MSC_VER (warnings) */
+
+#include "wingetopt.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+/*----------------------------------------------------------------------------*/
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef EOF
+#define EOF (-1)
+#endif
+
+#define ERR(s, c) \
+ if (opterr) { \
+ fputs(argv[0], stderr); \
+ fputs(s, stderr); \
+ fputc(c, stderr); \
+ }
+
+int opterr = 1;
+int optind = 1;
+int optopt;
+char *optarg;
+
+int getopt(int argc, char *const argv[], const char *opts) {
+ static int sp = 1;
+ int c;
+ char *cp;
+
+ if (sp == 1) {
+ if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
+ return EOF;
+ else if (strcmp(argv[optind], "--") == 0) {
+ optind++;
+ return EOF;
+ }
+ }
+ optopt = c = argv[optind][sp];
+ if (c == ':' || (cp = strchr(opts, c)) == NULL) {
+ ERR(": illegal option -- ", c);
+ if (argv[optind][++sp] == '\0') {
+ optind++;
+ sp = 1;
+ }
+ return '?';
+ }
+ if (*++cp == ':') {
+ if (argv[optind][sp + 1] != '\0')
+ optarg = &argv[optind++][sp + 1];
+ else if (++optind >= argc) {
+ ERR(": option requires an argument -- ", c);
+ sp = 1;
+ return '?';
+ } else
+ optarg = argv[optind++];
+ sp = 1;
+ } else {
+ if (argv[optind][++sp] == '\0') {
+ sp = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+ return c;
+}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.h b/plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.h
new file mode 100644
index 0000000000..fdff368374
--- /dev/null
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/tools/wingetopt.h
@@ -0,0 +1,26 @@
+/*
+ * POSIX getopt for Windows
+ *
+ * AT&T Public License
+ *
+ * Code given out at the 1985 UNIFORUM conference in Dallas.
+ */
+
+#ifndef _WINGETOPT_H_
+#define _WINGETOPT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char *optarg;
+int getopt(int argc, char *const argv[], const char *optstring);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H_ */