From ee25ba7f21361902fa8fde104a29d92b39c8db9c Mon Sep 17 00:00:00 2001
From: George Hazan <ghazan@miranda.im>
Date: Tue, 6 Nov 2018 13:07:56 +0300
Subject: merge with libmdbx trunk - fixes one rare problem with database
 shrinking

---
 libs/libmdbx/src/Makefile             |    9 +-
 libs/libmdbx/src/dll.vcxproj          |    2 +-
 libs/libmdbx/src/libmdbx.files        |    1 +
 libs/libmdbx/src/src/mdbx.c           |  296 +++++---
 libs/libmdbx/src/src/ntdll.def        | 1244 +++++++++++++++++++++++++++++++++
 libs/libmdbx/src/src/osal.c           |   13 +
 libs/libmdbx/src/src/osal.h           |    1 +
 libs/libmdbx/src/src/tools/mdbx_chk.c |   20 +-
 libs/libmdbx/src/test/CMakeLists.txt  |   51 +-
 libs/libmdbx/src/test/cases.cc        |    3 +-
 libs/libmdbx/src/test/config.h        |    5 +-
 libs/libmdbx/src/test/copy.cc         |   26 +
 libs/libmdbx/src/test/dead.cc         |   42 +-
 libs/libmdbx/src/test/gc.sh           |    1 +
 libs/libmdbx/src/test/hill.cc         |   18 +-
 libs/libmdbx/src/test/jitter.cc       |   16 +-
 libs/libmdbx/src/test/main.cc         |    4 +
 libs/libmdbx/src/test/osal-unix.cc    |    8 +-
 libs/libmdbx/src/test/osal-windows.cc |    6 +-
 libs/libmdbx/src/test/osal.h          |    3 +-
 libs/libmdbx/src/test/test.cc         |    7 +-
 libs/libmdbx/src/test/test.h          |   33 +-
 libs/libmdbx/src/test/test.vcxproj    |    3 +-
 libs/libmdbx/src/test/try.cc          |   19 +-
 24 files changed, 1562 insertions(+), 269 deletions(-)
 create mode 100644 libs/libmdbx/src/src/ntdll.def
 create mode 100644 libs/libmdbx/src/test/copy.cc

(limited to 'libs/libmdbx')

diff --git a/libs/libmdbx/src/Makefile b/libs/libmdbx/src/Makefile
index dabf2f98e7..11a6140f58 100644
--- a/libs/libmdbx/src/Makefile
+++ b/libs/libmdbx/src/Makefile
@@ -82,13 +82,16 @@ clean:
 	rm -rf $(TOOLS) mdbx_test @* *.[ao] *.[ls]o *~ tmp.db/* *.gcov *.log *.err src/*.o test/*.o
 
 check:	all
-	rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB)
+	rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \
+	&& ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy
 
 check-singleprocess:	all
-	rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --pathname=$(TESTDB) --dont-cleanup-after --hill | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB)
+	rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --pathname=$(TESTDB) --dont-cleanup-after --hill | tee -a $(TESTLOG) | tail -n 42) \
+	&& ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy
 
 check-fault:	all
-	rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --pathname=$(TESTDB) --inject-writefault=42 --dump-config --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) && ./mdbx_chk -vvn $(TESTDB)
+	rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --pathname=$(TESTDB) --inject-writefault=42 --dump-config --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \
+	&& ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy
 
 define core-rule
 $(patsubst %.c,%.o,$(1)): $(1) $(CORE_INC) mdbx.h Makefile
diff --git a/libs/libmdbx/src/dll.vcxproj b/libs/libmdbx/src/dll.vcxproj
index 812e1e65a8..c0743890ce 100644
--- a/libs/libmdbx/src/dll.vcxproj
+++ b/libs/libmdbx/src/dll.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
diff --git a/libs/libmdbx/src/libmdbx.files b/libs/libmdbx/src/libmdbx.files
index 38125146e4..653b03970e 100644
--- a/libs/libmdbx/src/libmdbx.files
+++ b/libs/libmdbx/src/libmdbx.files
@@ -3,6 +3,7 @@ README-RU.md
 pcrf_test/CMakeLists.txt
 src/tools/CMakeLists.txt
 test/CMakeLists.txt
+test/copy.cc
 tutorial/CMakeLists.txt
 tutorial/sample-mdbx.c
 AUTHORS
diff --git a/libs/libmdbx/src/src/mdbx.c b/libs/libmdbx/src/src/mdbx.c
index b0111895bf..4a34233184 100644
--- a/libs/libmdbx/src/src/mdbx.c
+++ b/libs/libmdbx/src/src/mdbx.c
@@ -5053,15 +5053,6 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta,
       continue;
     }
 
-    /* LY: check end_pgno */
-    if (page.mp_meta.mm_geo.now < page.mp_meta.mm_geo.lower ||
-        page.mp_meta.mm_geo.now > page.mp_meta.mm_geo.upper) {
-      mdbx_notice("meta[%u] has invalid end-pageno (%" PRIaPGNO "), skip it",
-                  meta_number, page.mp_meta.mm_geo.now);
-      rc = MDBX_CORRUPTED;
-      continue;
-    }
-
     /* LY: check last_pgno */
     if (page.mp_meta.mm_geo.next < MIN_PAGENO ||
         page.mp_meta.mm_geo.next - 1 > MAX_PAGENO) {
@@ -5075,6 +5066,7 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta,
     const uint64_t used_bytes =
         page.mp_meta.mm_geo.next * (uint64_t)page.mp_meta.mm_psize;
     if (used_bytes > *filesize) {
+      /* Here could be a race with DB-shrinking performed by other process */
       rc = mdbx_filesize(env->me_fd, filesize);
       if (unlikely(rc != MDBX_SUCCESS))
         return rc;
@@ -5118,10 +5110,20 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta,
                   "but size of used space still acceptable (%" PRIu64 ")",
                   meta_number, mapsize_max, used_bytes);
       page.mp_meta.mm_geo.upper = (pgno_t)(MAX_MAPSIZE / page.mp_meta.mm_psize);
-      if (page.mp_meta.mm_geo.now > page.mp_meta.mm_geo.upper)
-        page.mp_meta.mm_geo.now = page.mp_meta.mm_geo.upper;
     }
 
+    /* LY: check and silently put mm_geo.now into [geo.lower...geo.upper].
+     *
+     * Copy-with-compaction by previous version of libmfbx could produce DB-file
+     * less than meta.geo.lower bound, in case actual filling is low or no data
+     * at all. This is not a problem as there is no damage or loss of data.
+     * Therefore it is better not to consider such situation as an error, but
+     * silently correct it. */
+    if (page.mp_meta.mm_geo.now < page.mp_meta.mm_geo.lower)
+      page.mp_meta.mm_geo.now = page.mp_meta.mm_geo.lower;
+    if (page.mp_meta.mm_geo.now > page.mp_meta.mm_geo.upper)
+      page.mp_meta.mm_geo.now = page.mp_meta.mm_geo.upper;
+
     if (page.mp_meta.mm_geo.next > page.mp_meta.mm_geo.now) {
       mdbx_notice("meta[%u] next-pageno (%" PRIaPGNO
                   ") is beyond end-pgno (%" PRIaPGNO "), skip it",
@@ -6059,6 +6061,10 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
       }
 
       if (env->me_flags & MDBX_RDONLY) {
+        if (filesize_before_mmap % env->me_os_psize) {
+          mdbx_error("filesize should be rounded-up to system page");
+          return MDBX_WANNA_RECOVERY;
+        }
         mdbx_notice("ignore filesize mismatch in readonly-mode");
       } else {
         mdbx_info("resize datafile to %" PRIuSIZE " bytes, %" PRIaPGNO " pages",
@@ -11449,165 +11455,225 @@ done:
 }
 
 /* Copy environment with compaction. */
-static int __cold mdbx_env_compact(MDBX_env *env, mdbx_filehandle_t fd) {
-  MDBX_txn *txn = NULL;
-  mdbx_thread_t thr;
-  mdbx_copy ctx;
-  memset(&ctx, 0, sizeof(ctx));
-
-  int rc = mdbx_condmutex_init(&ctx.mc_condmutex);
-  if (unlikely(rc != MDBX_SUCCESS))
-    return rc;
-
-  const size_t buffer_size = pgno2bytes(env, NUM_METAS) + MDBX_WBUF * 2;
-  uint8_t *buffer = NULL;
-  rc = mdbx_memalign_alloc(env->me_os_psize, buffer_size, (void **)&buffer);
-  if (unlikely(rc != MDBX_SUCCESS))
-    goto done;
-
-  ctx.mc_wbuf[0] = buffer + pgno2bytes(env, NUM_METAS);
-  memset(ctx.mc_wbuf[0], 0, MDBX_WBUF * 2);
-  ctx.mc_wbuf[1] = ctx.mc_wbuf[0] + MDBX_WBUF;
-  ctx.mc_next_pgno = NUM_METAS;
-  ctx.mc_env = env;
-  ctx.mc_fd = fd;
-  rc = mdbx_thread_create(&thr, mdbx_env_copythr, &ctx);
-  if (unlikely(rc != MDBX_SUCCESS))
-    goto done;
-
-  rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
-  if (unlikely(rc != MDBX_SUCCESS))
-    goto finish;
-
+static int __cold mdbx_env_compact(MDBX_env *env, MDBX_txn *read_txn,
+                                   mdbx_filehandle_t fd, uint8_t *buffer) {
   MDBX_page *const meta = mdbx_init_metas(env, buffer);
+  /* copy canary sequenses if present */
+  if (read_txn->mt_canary.v) {
+    meta->mp_meta.mm_canary = read_txn->mt_canary;
+    meta->mp_meta.mm_canary.v = mdbx_meta_txnid_stable(env, &meta->mp_meta);
+  }
 
   /* Set metapage 1 with current main DB */
-  pgno_t new_root, root = txn->mt_dbs[MAIN_DBI].md_root;
-  if ((new_root = root) != P_INVALID) {
+  pgno_t new_root, root = read_txn->mt_dbs[MAIN_DBI].md_root;
+  if ((new_root = root) == P_INVALID) {
+    /* When the DB is empty, handle it specially to
+     * fix any breakage like page leaks from ITS#8174. */
+    meta->mp_meta.mm_dbs[MAIN_DBI].md_flags =
+        read_txn->mt_dbs[MAIN_DBI].md_flags;
+  } else {
     /* Count free pages + freeDB pages.  Subtract from last_pg
      * to find the new last_pg, which also becomes the new root. */
     pgno_t freecount = 0;
     MDBX_cursor mc;
     MDBX_val key, data;
 
-    rc = mdbx_cursor_init(&mc, txn, FREE_DBI);
+    int rc = mdbx_cursor_init(&mc, read_txn, FREE_DBI);
     if (unlikely(rc != MDBX_SUCCESS))
       return rc;
     while ((rc = mdbx_cursor_get(&mc, &key, &data, MDBX_NEXT)) == 0)
       freecount += *(pgno_t *)data.iov_base;
     if (unlikely(rc != MDBX_NOTFOUND))
-      goto finish;
+      return rc;
 
-    freecount += txn->mt_dbs[FREE_DBI].md_branch_pages +
-                 txn->mt_dbs[FREE_DBI].md_leaf_pages +
-                 txn->mt_dbs[FREE_DBI].md_overflow_pages;
+    freecount += read_txn->mt_dbs[FREE_DBI].md_branch_pages +
+                 read_txn->mt_dbs[FREE_DBI].md_leaf_pages +
+                 read_txn->mt_dbs[FREE_DBI].md_overflow_pages;
 
-    new_root = txn->mt_next_pgno - 1 - freecount;
-    meta->mp_meta.mm_geo.next = meta->mp_meta.mm_geo.now = new_root + 1;
-    meta->mp_meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
+    new_root = read_txn->mt_next_pgno - 1 - freecount;
+    meta->mp_meta.mm_geo.next = new_root + 1;
+    meta->mp_meta.mm_dbs[MAIN_DBI] = read_txn->mt_dbs[MAIN_DBI];
     meta->mp_meta.mm_dbs[MAIN_DBI].md_root = new_root;
-  } else {
-    /* When the DB is empty, handle it specially to
-     * fix any breakage like page leaks from ITS#8174. */
-    meta->mp_meta.mm_dbs[MAIN_DBI].md_flags = txn->mt_dbs[MAIN_DBI].md_flags;
-  }
 
-  /* copy canary sequenses if present */
-  if (txn->mt_canary.v) {
-    meta->mp_meta.mm_canary = txn->mt_canary;
-    meta->mp_meta.mm_canary.v = mdbx_meta_txnid_stable(env, &meta->mp_meta);
-  }
+    mdbx_copy ctx;
+    memset(&ctx, 0, sizeof(ctx));
+    rc = mdbx_condmutex_init(&ctx.mc_condmutex);
+    if (unlikely(rc != MDBX_SUCCESS))
+      return rc;
 
-  /* update signature */
-  meta->mp_meta.mm_datasync_sign = mdbx_meta_sign(&meta->mp_meta);
-  memcpy(ctx.mc_wbuf[0], buffer, ctx.mc_wlen[0] = pgno2bytes(env, NUM_METAS));
+    ctx.mc_wbuf[0] = buffer + pgno2bytes(env, NUM_METAS);
+    memset(ctx.mc_wbuf[0], 0, MDBX_WBUF * 2);
+    ctx.mc_wbuf[1] = ctx.mc_wbuf[0] + MDBX_WBUF;
+    ctx.mc_next_pgno = NUM_METAS;
+    ctx.mc_env = env;
+    ctx.mc_fd = fd;
+    ctx.mc_txn = read_txn;
+
+    mdbx_thread_t thread;
+    int thread_err = mdbx_thread_create(&thread, mdbx_env_copythr, &ctx);
+    if (likely(thread_err == MDBX_SUCCESS)) {
+      rc = mdbx_env_cwalk(&ctx, &root, 0);
+      mdbx_env_cthr_toggle(&ctx, 1 | MDBX_EOF);
+      thread_err = mdbx_thread_join(thread);
+      mdbx_condmutex_destroy(&ctx.mc_condmutex);
+    }
+    if (unlikely(thread_err != MDBX_SUCCESS))
+      return thread_err;
+    if (unlikely(rc != MDBX_SUCCESS))
+      return rc;
+    if (unlikely(ctx.mc_error != MDBX_SUCCESS))
+      return ctx.mc_error;
 
-  ctx.mc_txn = txn;
-  rc = mdbx_env_cwalk(&ctx, &root, 0);
-  if (rc == MDBX_SUCCESS && root != new_root) {
     if (root > new_root) {
       mdbx_error("post-compactification root %" PRIaPGNO
                  " GT expected %" PRIaPGNO " (source DB corrupted)",
                  root, new_root);
-      rc = MDBX_CORRUPTED; /* page leak or corrupt DB */
-    } else {
-      mdbx_error("post-compactification root %" PRIaPGNO
-                 " LT expected %" PRIaPGNO " (page leak(s) in source DB)",
-                 root, new_root);
-      /* fixup and rewrite metas */
-      meta->mp_meta.mm_dbs[MAIN_DBI].md_root = root;
-      meta->mp_meta.mm_geo.next = meta->mp_meta.mm_geo.now = root + 1;
-      meta->mp_meta.mm_datasync_sign = mdbx_meta_sign(&meta->mp_meta);
-      rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0);
+      return MDBX_CORRUPTED; /* page leak or corrupt DB */
     }
-  }
-
-finish:
-  if (rc != MDBX_SUCCESS)
-    ctx.mc_error = rc;
-  mdbx_env_cthr_toggle(&ctx, 1 | MDBX_EOF);
-  rc = mdbx_thread_join(thr);
-  mdbx_txn_abort(txn);
+    if (root < new_root) {
+      mdbx_notice("post-compactification root %" PRIaPGNO
+                  " LT expected %" PRIaPGNO " (page leak(s) in source DB)",
+                  root, new_root);
+      /* fixup meta */
+      meta->mp_meta.mm_dbs[MAIN_DBI].md_root = root;
+      meta->mp_meta.mm_geo.next = root + 1;
+    }
+  }
+
+  /* Calculate filesize taking in account shrink/growing thresholds */
+  if (meta->mp_meta.mm_geo.next > meta->mp_meta.mm_geo.now) {
+    const pgno_t aligned =
+        pgno_align2os_pgno(env, pgno_add(meta->mp_meta.mm_geo.next,
+                                         meta->mp_meta.mm_geo.grow -
+                                             meta->mp_meta.mm_geo.next %
+                                                 meta->mp_meta.mm_geo.grow));
+    meta->mp_meta.mm_geo.now = aligned;
+  } else if (meta->mp_meta.mm_geo.next < meta->mp_meta.mm_geo.now) {
+    meta->mp_meta.mm_geo.now = meta->mp_meta.mm_geo.next;
+    const pgno_t aligner = meta->mp_meta.mm_geo.grow
+                               ? meta->mp_meta.mm_geo.grow
+                               : meta->mp_meta.mm_geo.shrink;
+    const pgno_t aligned =
+        pgno_align2os_pgno(env, meta->mp_meta.mm_geo.next + aligner -
+                                    meta->mp_meta.mm_geo.next % aligner);
+    meta->mp_meta.mm_geo.now = aligned;
+  }
+
+  if (meta->mp_meta.mm_geo.now < meta->mp_meta.mm_geo.lower)
+    meta->mp_meta.mm_geo.now = meta->mp_meta.mm_geo.lower;
+  if (meta->mp_meta.mm_geo.now > meta->mp_meta.mm_geo.upper)
+    meta->mp_meta.mm_geo.now = meta->mp_meta.mm_geo.upper;
+
+  /* Update signature */
+  assert(meta->mp_meta.mm_geo.now >= meta->mp_meta.mm_geo.next);
+  meta->mp_meta.mm_datasync_sign = mdbx_meta_sign(&meta->mp_meta);
 
-done:
-  mdbx_memalign_free(buffer);
-  mdbx_condmutex_destroy(&ctx.mc_condmutex);
-  return rc ? rc : ctx.mc_error;
+  /* Extend file if required */
+  return (meta->mp_meta.mm_geo.now != meta->mp_meta.mm_geo.next)
+             ? mdbx_ftruncate(fd, pgno2bytes(env, meta->mp_meta.mm_geo.now))
+             : MDBX_SUCCESS;
 }
 
 /* Copy environment as-is. */
-static int __cold mdbx_env_copy_asis(MDBX_env *env, mdbx_filehandle_t fd) {
-  MDBX_txn *txn = NULL;
-
-  /* Do the lock/unlock of the reader mutex before starting the
-   * write txn.  Otherwise other read txns could block writers. */
-  int rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
-  if (unlikely(rc != MDBX_SUCCESS))
-    return rc;
-
+static int __cold mdbx_env_copy_asis(MDBX_env *env, MDBX_txn *read_txn,
+                                     mdbx_filehandle_t fd, uint8_t *buffer) {
   /* We must start the actual read txn after blocking writers */
-  rc = mdbx_txn_end(txn, MDBX_END_RESET_TMP);
+  int rc = mdbx_txn_end(read_txn, MDBX_END_RESET_TMP);
   if (unlikely(rc != MDBX_SUCCESS))
-    goto bailout; /* FIXME: or just return? */
+    return rc;
 
   /* Temporarily block writers until we snapshot the meta pages */
   rc = mdbx_txn_lock(env, false);
   if (unlikely(rc != MDBX_SUCCESS))
-    goto bailout;
+    return rc;
 
-  rc = mdbx_txn_renew0(txn, MDBX_RDONLY);
+  rc = mdbx_txn_renew0(read_txn, MDBX_RDONLY);
   if (unlikely(rc != MDBX_SUCCESS)) {
     mdbx_txn_unlock(env);
-    goto bailout;
+    return rc;
   }
 
-  rc = mdbx_write(fd, env->me_map, pgno2bytes(env, NUM_METAS));
-  MDBX_meta *const head = mdbx_meta_head(env);
+  /* Make a snapshot of meta-pages,
+   * but writing ones after the data was flushed */
+  memcpy(buffer, env->me_map, pgno2bytes(env, NUM_METAS));
+  MDBX_meta *const headcopy = /* LY: get pointer to the spanshot copy */
+      (MDBX_meta *)(buffer + ((uint8_t *)mdbx_meta_head(env) - env->me_map));
   const uint64_t size =
-      mdbx_roundup2(pgno2bytes(env, head->mm_geo.now), env->me_os_psize);
+      mdbx_roundup2(pgno2bytes(env, headcopy->mm_geo.now), env->me_os_psize);
   mdbx_txn_unlock(env);
 
-  if (likely(rc == MDBX_SUCCESS))
-    rc = mdbx_write(fd, env->me_map + pgno2bytes(env, NUM_METAS),
-                    pgno2bytes(env, txn->mt_next_pgno - NUM_METAS));
+  /* Update signature to steady */
+  headcopy->mm_datasync_sign = mdbx_meta_sign(headcopy);
+
+  /* Copy the data */
+  rc = mdbx_pwrite(fd, env->me_map + pgno2bytes(env, NUM_METAS),
+                   pgno2bytes(env, read_txn->mt_next_pgno - NUM_METAS),
+                   pgno2bytes(env, NUM_METAS));
 
   if (likely(rc == MDBX_SUCCESS))
     rc = mdbx_ftruncate(fd, size);
 
-bailout:
-  mdbx_txn_abort(txn);
   return rc;
 }
 
 int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
                             unsigned flags) {
-  if (flags & MDBX_CP_COMPACT)
-    return mdbx_env_compact(env, fd);
+  if (unlikely(!env))
+    return MDBX_EINVAL;
+
+  if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
+    return MDBX_EBADSIGN;
+
+  int rc = mdbx_fseek(fd, 0);
+  if (unlikely(rc != MDBX_SUCCESS))
+    return rc;
 
-  return mdbx_env_copy_asis(env, fd);
+  const size_t buffer_size = pgno2bytes(env, NUM_METAS) +
+                             ((flags & MDBX_CP_COMPACT) ? MDBX_WBUF * 2 : 0);
+  uint8_t *buffer = NULL;
+  rc = mdbx_memalign_alloc(env->me_os_psize, buffer_size, (void **)&buffer);
+  if (unlikely(rc != MDBX_SUCCESS))
+    return rc;
+
+  MDBX_txn *read_txn = NULL;
+  /* Do the lock/unlock of the reader mutex before starting the
+   * write txn.  Otherwise other read txns could block writers. */
+  rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &read_txn);
+  if (unlikely(rc != MDBX_SUCCESS)) {
+    mdbx_memalign_free(buffer);
+    return rc;
+  }
+
+  /* Firstly write a stub to meta-pages.
+   * Now we sure to incomplete copy will not be used. */
+  memset(buffer, -1, pgno2bytes(env, NUM_METAS));
+  rc = mdbx_write(fd, buffer, pgno2bytes(env, NUM_METAS));
+  if (likely(rc == MDBX_SUCCESS)) {
+    memset(buffer, 0, pgno2bytes(env, NUM_METAS));
+    rc = (flags & MDBX_CP_COMPACT)
+             ? mdbx_env_compact(env, read_txn, fd, buffer)
+             : mdbx_env_copy_asis(env, read_txn, fd, buffer);
+  }
+  mdbx_txn_abort(read_txn);
+
+  if (likely(rc == MDBX_SUCCESS))
+    rc = mdbx_filesync(fd, true);
+
+  /* Write actual meta */
+  if (likely(rc == MDBX_SUCCESS))
+    rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0);
+
+  mdbx_memalign_free(buffer);
+  return rc;
 }
 
 int __cold mdbx_env_copy(MDBX_env *env, const char *dest_path, unsigned flags) {
+  if (unlikely(!env || !dest_path))
+    return MDBX_EINVAL;
+
+  if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
+    return MDBX_EBADSIGN;
+
   char *dxb_pathname;
   mdbx_filehandle_t newfd = INVALID_HANDLE_VALUE;
 
@@ -13438,7 +13504,7 @@ __cold intptr_t mdbx_limits_dbsize_max(intptr_t pagesize) {
 
   const uint64_t limit = MAX_PAGENO * (uint64_t)pagesize;
   return (limit < (intptr_t)MAX_MAPSIZE) ? (intptr_t)limit
-                                         : (intptr_t)MAX_PAGESIZE;
+                                         : (intptr_t)MAX_MAPSIZE;
 }
 
 __cold intptr_t mdbx_limits_txnsize_max(intptr_t pagesize) {
diff --git a/libs/libmdbx/src/src/ntdll.def b/libs/libmdbx/src/src/ntdll.def
new file mode 100644
index 0000000000..e3a6e33c94
--- /dev/null
+++ b/libs/libmdbx/src/src/ntdll.def
@@ -0,0 +1,1244 @@
+LIBRARY ntdll
+EXPORTS
+CsrAllocateCaptureBuffer
+CsrAllocateMessagePointer
+CsrCaptureMessageBuffer
+CsrCaptureMessageMultiUnicodeStringsInPlace
+CsrCaptureMessageString
+CsrCaptureTimeout
+CsrClientCallServer
+CsrClientConnectToServer
+CsrFreeCaptureBuffer
+CsrGetProcessId
+CsrIdentifyAlertableThread
+CsrSetPriorityClass
+DbgBreakPoint
+DbgPrint
+DbgPrintEx
+DbgPrintReturnControlC
+DbgPrompt
+DbgQueryDebugFilterState
+DbgSetDebugFilterState
+DbgUiConnectToDbg
+DbgUiContinue
+DbgUiConvertStateChangeStructure
+DbgUiDebugActiveProcess
+DbgUiGetThreadDebugObject
+DbgUiIssueRemoteBreakin
+DbgUiRemoteBreakin
+DbgUiSetThreadDebugObject
+DbgUiStopDebugging
+DbgUiWaitStateChange
+DbgUserBreakPoint
+KiRaiseUserExceptionDispatcher
+KiUserApcDispatcher
+KiUserCallbackDispatcher
+KiUserExceptionDispatcher
+LdrAccessResource
+LdrAddRefDll
+LdrDisableThreadCalloutsForDll
+LdrEnumResources
+LdrEnumerateLoadedModules
+LdrFindEntryForAddress
+LdrFindResourceDirectory_U
+LdrFindResourceEx_U
+LdrFindResource_U
+LdrFlushAlternateResourceModules
+LdrGetDllHandle
+LdrGetDllHandleEx
+LdrGetProcedureAddress
+LdrInitShimEngineDynamic
+LdrInitializeThunk
+LdrLoadAlternateResourceModule
+LdrLoadDll
+LdrLockLoaderLock
+LdrProcessRelocationBlock
+LdrQueryImageFileExecutionOptions
+LdrQueryProcessModuleInformation
+LdrSetAppCompatDllRedirectionCallback
+LdrSetDllManifestProber
+LdrShutdownProcess
+LdrShutdownThread
+LdrUnloadAlternateResourceModule
+LdrUnloadDll
+LdrUnlockLoaderLock
+LdrVerifyImageMatchesChecksum
+NlsAnsiCodePage
+NlsMbCodePageTag
+NlsMbOemCodePageTag
+NtAcceptConnectPort
+NtAccessCheck
+NtAccessCheckAndAuditAlarm
+NtAccessCheckByType
+NtAccessCheckByTypeAndAuditAlarm
+NtAccessCheckByTypeResultList
+NtAccessCheckByTypeResultListAndAuditAlarm
+NtAccessCheckByTypeResultListAndAuditAlarmByHandle
+NtAddAtom
+NtAddBootEntry
+NtAdjustGroupsToken
+NtAdjustPrivilegesToken
+NtAlertResumeThread
+NtAlertThread
+NtAllocateLocallyUniqueId
+NtAllocateUserPhysicalPages
+NtAllocateUuids
+NtAllocateVirtualMemory
+NtAreMappedFilesTheSame
+NtAssignProcessToJobObject
+NtCallbackReturn
+NtCancelIoFile
+NtCancelTimer
+NtClearEvent
+NtClose
+NtCloseObjectAuditAlarm
+NtCompactKeys
+NtCompareTokens
+NtCompleteConnectPort
+NtCompressKey
+NtConnectPort
+NtContinue
+NtCreateDebugObject
+NtCreateDirectoryObject
+NtCreateEvent
+NtCreateEventPair
+NtCreateFile
+NtCreateIoCompletion
+NtCreateJobObject
+NtCreateJobSet
+NtCreateKey
+NtCreateKeyedEvent
+NtCreateMailslotFile
+NtCreateMutant
+NtCreateNamedPipeFile
+NtCreatePagingFile
+NtCreatePort
+NtCreateProcess
+NtCreateProcessEx
+NtCreateProfile
+NtCreateSection
+NtCreateSemaphore
+NtCreateSymbolicLinkObject
+NtCreateThread
+NtCreateTimer
+NtCreateToken
+NtCreateWaitablePort
+NtDebugActiveProcess
+NtDebugContinue
+NtDelayExecution
+NtDeleteAtom
+NtDeleteBootEntry
+NtDeleteFile
+NtDeleteKey
+NtDeleteObjectAuditAlarm
+NtDeleteValueKey
+NtDeviceIoControlFile
+NtDisplayString
+NtDuplicateObject
+NtDuplicateToken
+NtEnumerateBootEntries
+NtEnumerateKey
+NtEnumerateSystemEnvironmentValuesEx
+NtEnumerateValueKey
+NtExtendSection
+NtFilterToken
+NtFindAtom
+NtFlushBuffersFile
+NtFlushInstructionCache
+NtFlushKey
+NtFlushVirtualMemory
+NtFlushWriteBuffer
+NtFreeUserPhysicalPages
+NtFreeVirtualMemory
+NtFsControlFile
+NtGetContextThread
+NtGetDevicePowerState
+NtGetWriteWatch
+NtImpersonateAnonymousToken
+NtImpersonateClientOfPort
+NtImpersonateThread
+NtInitializeRegistry
+NtInitiatePowerAction
+NtIsProcessInJob
+NtIsSystemResumeAutomatic
+NtListenPort
+NtLoadDriver
+NtLoadKey
+NtLoadKey2
+NtLockFile
+NtLockProductActivationKeys
+NtLockRegistryKey
+NtLockVirtualMemory
+NtMakePermanentObject
+NtMakeTemporaryObject
+NtMapUserPhysicalPages
+NtMapUserPhysicalPagesScatter
+NtMapViewOfSection
+NtModifyBootEntry
+NtNotifyChangeDirectoryFile
+NtNotifyChangeKey
+NtNotifyChangeMultipleKeys
+NtOpenDirectoryObject
+NtOpenEvent
+NtOpenEventPair
+NtOpenFile
+NtOpenIoCompletion
+NtOpenJobObject
+NtOpenKey
+NtOpenKeyedEvent
+NtOpenMutant
+NtOpenObjectAuditAlarm
+NtOpenProcess
+NtOpenProcessToken
+NtOpenProcessTokenEx
+NtOpenSection
+NtOpenSemaphore
+NtOpenSymbolicLinkObject
+NtOpenThread
+NtOpenThreadToken
+NtOpenThreadTokenEx
+NtOpenTimer
+NtPlugPlayControl
+NtPowerInformation
+NtPrivilegeCheck
+NtPrivilegeObjectAuditAlarm
+NtPrivilegedServiceAuditAlarm
+NtProtectVirtualMemory
+NtPulseEvent
+NtQueryAttributesFile
+NtQueryBootEntryOrder
+NtQueryBootOptions
+NtQueryDebugFilterState
+NtQueryDefaultLocale
+NtQueryDefaultUILanguage
+NtQueryDirectoryFile
+NtQueryDirectoryObject
+NtQueryEaFile
+NtQueryEvent
+NtQueryFullAttributesFile
+NtQueryInformationAtom
+NtQueryInformationFile
+NtQueryInformationJobObject
+NtQueryInformationPort
+NtQueryInformationProcess
+NtQueryInformationThread
+NtQueryInformationToken
+NtQueryInstallUILanguage
+NtQueryIntervalProfile
+NtQueryIoCompletion
+NtQueryKey
+NtQueryMultipleValueKey
+NtQueryMutant
+NtQueryObject
+NtQueryOpenSubKeys
+NtQueryPerformanceCounter
+NtQueryPortInformationProcess
+NtQueryQuotaInformationFile
+NtQuerySection
+NtQuerySecurityObject
+NtQuerySemaphore
+NtQuerySymbolicLinkObject
+NtQuerySystemEnvironmentValue
+NtQuerySystemEnvironmentValueEx
+NtQuerySystemInformation
+NtQuerySystemTime
+NtQueryTimer
+NtQueryTimerResolution
+NtQueryValueKey
+NtQueryVirtualMemory
+NtQueryVolumeInformationFile
+NtQueueApcThread
+NtRaiseException
+NtRaiseHardError
+NtReadFile
+NtReadFileScatter
+NtReadRequestData
+NtReadVirtualMemory
+NtRegisterThreadTerminatePort
+NtReleaseKeyedEvent
+NtReleaseMutant
+NtReleaseSemaphore
+NtRemoveIoCompletion
+NtRemoveProcessDebug
+NtRenameKey
+NtReplaceKey
+NtReplyPort
+NtReplyWaitReceivePort
+NtReplyWaitReceivePortEx
+NtReplyWaitReplyPort
+NtRequestPort
+NtRequestWaitReplyPort
+NtResetEvent
+NtResetWriteWatch
+NtRestoreKey
+NtResumeProcess
+NtResumeThread
+NtSaveKey
+NtSaveKeyEx
+NtSaveMergedKeys
+NtSecureConnectPort
+NtSetBootEntryOrder
+NtSetBootOptions
+NtSetContextThread
+NtSetDebugFilterState
+NtSetDefaultHardErrorPort
+NtSetDefaultLocale
+NtSetDefaultUILanguage
+NtSetEaFile
+NtSetEvent
+NtSetEventBoostPriority
+NtSetHighEventPair
+NtSetHighWaitLowEventPair
+NtSetInformationDebugObject
+NtSetInformationFile
+NtSetInformationJobObject
+NtSetInformationKey
+NtSetInformationObject
+NtSetInformationProcess
+NtSetInformationThread
+NtSetInformationToken
+NtSetIntervalProfile
+NtSetIoCompletion
+NtSetLdtEntries
+NtSetLowEventPair
+NtSetLowWaitHighEventPair
+NtSetQuotaInformationFile
+NtSetSecurityObject
+NtSetSystemEnvironmentValue
+NtSetSystemEnvironmentValueEx
+NtSetSystemInformation
+NtSetSystemPowerState
+NtSetSystemTime
+NtSetThreadExecutionState
+NtSetTimer
+NtSetTimerResolution
+NtSetUuidSeed
+NtSetValueKey
+NtSetVolumeInformationFile
+NtShutdownSystem
+NtSignalAndWaitForSingleObject
+NtStartProfile
+NtStopProfile
+NtSuspendProcess
+NtSuspendThread
+NtSystemDebugControl
+NtTerminateJobObject
+NtTerminateProcess
+NtTerminateThread
+NtTestAlert
+NtTraceEvent
+NtTranslateFilePath
+NtUnloadDriver
+NtUnloadKey
+NtUnloadKeyEx
+NtUnlockFile
+NtUnlockVirtualMemory
+NtUnmapViewOfSection
+NtVdmControl
+NtWaitForDebugEvent
+NtWaitForKeyedEvent
+NtWaitForMultipleObjects
+NtWaitForSingleObject
+NtWaitHighEventPair
+NtWaitLowEventPair
+NtWriteFile
+NtWriteFileGather
+NtWriteRequestData
+NtWriteVirtualMemory
+NtYieldExecution
+PfxFindPrefix
+PfxInitialize
+PfxInsertPrefix
+PfxRemovePrefix
+RtlAbortRXact
+RtlAbsoluteToSelfRelativeSD
+RtlAcquirePebLock
+RtlAcquireResourceExclusive
+RtlAcquireResourceShared
+RtlActivateActivationContext
+RtlActivateActivationContextEx
+RtlActivateActivationContextUnsafeFast
+RtlAddAccessAllowedAce
+RtlAddAccessAllowedAceEx
+RtlAddAccessAllowedObjectAce
+RtlAddAccessDeniedAce
+RtlAddAccessDeniedAceEx
+RtlAddAccessDeniedObjectAce
+RtlAddAce
+RtlAddActionToRXact
+RtlAddAtomToAtomTable
+RtlAddAttributeActionToRXact
+RtlAddAuditAccessAce
+RtlAddAuditAccessAceEx
+RtlAddAuditAccessObjectAce
+RtlAddCompoundAce
+RtlAddRefActivationContext
+RtlAddRefMemoryStream
+RtlAddVectoredExceptionHandler
+RtlAddressInSectionTable
+RtlAdjustPrivilege
+RtlAllocateAndInitializeSid
+RtlAllocateHandle
+RtlAllocateHeap
+RtlAnsiCharToUnicodeChar
+RtlAnsiStringToUnicodeSize
+RtlAnsiStringToUnicodeString
+RtlAppendAsciizToString
+RtlAppendPathElement
+RtlAppendStringToString
+RtlAppendUnicodeStringToString
+RtlAppendUnicodeToString
+RtlApplicationVerifierStop
+RtlApplyRXact
+RtlApplyRXactNoFlush
+RtlAreAllAccessesGranted
+RtlAreAnyAccessesGranted
+RtlAreBitsClear
+RtlAreBitsSet
+RtlAssert
+RtlCancelTimer
+RtlCaptureContext
+RtlCaptureStackBackTrace
+RtlCharToInteger
+RtlCheckForOrphanedCriticalSections
+RtlCheckRegistryKey
+RtlClearAllBits
+RtlClearBits
+RtlCloneMemoryStream
+RtlCommitMemoryStream
+RtlCompactHeap
+RtlCompareMemory
+RtlCompareMemoryUlong
+RtlCompareString
+RtlCompareUnicodeString
+RtlCompressBuffer
+RtlComputeCrc32
+RtlComputeImportTableHash
+RtlComputePrivatizedDllName_U
+RtlConsoleMultiByteToUnicodeN
+RtlConvertExclusiveToShared
+RtlConvertSharedToExclusive
+RtlConvertSidToUnicodeString
+RtlConvertToAutoInheritSecurityObject
+RtlCopyLuid
+RtlCopyLuidAndAttributesArray
+RtlCopyMemoryStreamTo
+RtlCopyOutOfProcessMemoryStreamTo
+RtlCopySecurityDescriptor
+RtlCopySid
+RtlCopySidAndAttributesArray
+RtlCopyString
+RtlCopyUnicodeString
+RtlCreateAcl
+RtlCreateActivationContext
+RtlCreateAndSetSD
+RtlCreateAtomTable
+RtlCreateBootStatusDataFile
+RtlCreateEnvironment
+RtlCreateHeap
+RtlCreateProcessParameters
+RtlCreateQueryDebugBuffer
+RtlCreateRegistryKey
+RtlCreateSecurityDescriptor
+RtlCreateServiceSid
+RtlCreateSystemVolumeInformationFolder
+RtlCreateTagHeap
+RtlCreateTimer
+RtlCreateTimerQueue
+RtlCreateUnicodeString
+RtlCreateUnicodeStringFromAsciiz
+RtlCreateUserProcess
+RtlCreateUserSecurityObject
+RtlCreateUserThread
+RtlCustomCPToUnicodeN
+RtlCutoverTimeToSystemTime
+RtlDeNormalizeProcessParams
+RtlDeactivateActivationContext
+RtlDeactivateActivationContextUnsafeFast
+RtlDebugPrintTimes
+RtlDecodePointer
+RtlDecodeSystemPointer
+RtlDecompressBuffer
+RtlDecompressFragment
+RtlDefaultNpAcl
+RtlDelete
+RtlDeleteAce
+RtlDeleteAtomFromAtomTable
+RtlDeleteCriticalSection
+RtlDeleteElementGenericTable
+RtlDeleteElementGenericTableAvl
+RtlDeleteNoSplay
+RtlDeleteRegistryValue
+RtlDeleteResource
+RtlDeleteSecurityObject
+RtlDeleteTimer
+RtlDeleteTimerQueue
+RtlDeleteTimerQueueEx
+RtlDeregisterWait
+RtlDeregisterWaitEx
+RtlDestroyAtomTable
+RtlDestroyEnvironment
+RtlDestroyHandleTable
+RtlDestroyHeap
+RtlDestroyProcessParameters
+RtlDestroyQueryDebugBuffer
+RtlDetermineDosPathNameType_U
+RtlDllShutdownInProgress
+RtlDnsHostNameToComputerName
+RtlDoesFileExists_U
+RtlDosApplyFileIsolationRedirection_Ustr
+RtlDosPathNameToNtPathName_U
+RtlDosSearchPath_U
+RtlDosSearchPath_Ustr
+RtlDowncaseUnicodeChar
+RtlDowncaseUnicodeString
+RtlDumpResource
+RtlDuplicateUnicodeString
+RtlEmptyAtomTable
+RtlEnableEarlyCriticalSectionEventCreation
+RtlEncodePointer
+RtlEncodeSystemPointer
+RtlEnterCriticalSection
+RtlEnumProcessHeaps
+RtlEnumerateGenericTable
+RtlEnumerateGenericTableAvl
+RtlEnumerateGenericTableLikeADirectory
+RtlEnumerateGenericTableWithoutSplaying
+RtlEnumerateGenericTableWithoutSplayingAvl
+RtlEqualComputerName
+RtlEqualDomainName
+RtlEqualLuid
+RtlEqualPrefixSid
+RtlEqualSid
+RtlEqualString
+RtlEqualUnicodeString
+RtlEraseUnicodeString
+RtlExitUserThread
+RtlExpandEnvironmentStrings_U
+RtlFillMemory
+RtlFinalReleaseOutOfProcessMemoryStream
+RtlFindActivationContextSectionGuid
+RtlFindActivationContextSectionString
+RtlFindCharInUnicodeString
+RtlFindClearBits
+RtlFindClearBitsAndSet
+RtlFindClearRuns
+RtlFindLastBackwardRunClear
+RtlFindLeastSignificantBit
+RtlFindLongestRunClear
+RtlFindMessage
+RtlFindMostSignificantBit
+RtlFindNextForwardRunClear
+RtlFindSetBits
+RtlFindSetBitsAndClear
+RtlFirstEntrySList
+RtlFirstFreeAce
+RtlFlushSecureMemoryCache
+RtlFormatCurrentUserKeyPath
+RtlFormatMessage
+RtlFreeAnsiString
+RtlFreeHandle
+RtlFreeHeap
+RtlFreeOemString
+RtlFreeSid
+RtlFreeThreadActivationContextStack
+RtlFreeUnicodeString
+RtlGUIDFromString
+RtlGenerate8dot3Name
+RtlGetAce
+RtlGetActiveActivationContext
+RtlGetCallersAddress
+RtlGetCompressionWorkSpaceSize
+RtlGetControlSecurityDescriptor
+RtlGetCurrentDirectory_U
+RtlGetCurrentPeb
+RtlGetDaclSecurityDescriptor
+RtlGetElementGenericTable
+RtlGetElementGenericTableAvl
+RtlGetFrame
+RtlGetFullPathName_U
+RtlGetGroupSecurityDescriptor
+RtlGetLastNtStatus
+RtlGetLastWin32Error
+RtlGetLengthWithoutLastFullDosOrNtPathElement
+RtlGetLengthWithoutTrailingPathSeperators
+RtlGetLongestNtPathLength
+RtlGetNativeSystemInformation
+RtlGetNtGlobalFlags
+RtlGetNtProductType
+RtlGetNtVersionNumbers
+RtlGetOwnerSecurityDescriptor
+RtlGetProcessHeaps
+RtlGetSaclSecurityDescriptor
+RtlGetSecurityDescriptorRMControl
+RtlGetSetBootStatusData
+RtlGetUnloadEventTrace
+RtlGetUserInfoHeap
+RtlGetVersion
+RtlHashUnicodeString
+RtlIdentifierAuthoritySid
+RtlImageDirectoryEntryToData
+RtlImageNtHeader
+RtlImageRvaToSection
+RtlImageRvaToVa
+RtlImpersonateSelf
+RtlInitAnsiString
+RtlInitCodePageTable
+RtlInitMemoryStream
+RtlInitNlsTables
+RtlInitOutOfProcessMemoryStream
+RtlInitString
+RtlInitUnicodeString
+RtlInitUnicodeStringEx
+RtlInitializeAtomPackage
+RtlInitializeBitMap
+RtlInitializeContext
+RtlInitializeCriticalSection
+RtlInitializeCriticalSectionAndSpinCount
+RtlInitializeGenericTable
+RtlInitializeGenericTableAvl
+RtlInitializeHandleTable
+RtlInitializeRXact
+RtlInitializeResource
+RtlInitializeSListHead
+RtlInitializeSid
+RtlInsertElementGenericTable
+RtlInsertElementGenericTableAvl
+RtlInt64ToUnicodeString
+RtlIntegerToChar
+RtlIntegerToUnicodeString
+RtlInterlockedFlushSList
+RtlInterlockedPopEntrySList
+RtlInterlockedPushEntrySList
+RtlInterlockedPushListSList
+RtlIpv4AddressToStringA
+RtlIpv4AddressToStringExA
+RtlIpv4AddressToStringExW
+RtlIpv4AddressToStringW
+RtlIpv4StringToAddressA
+RtlIpv4StringToAddressExA
+RtlIpv4StringToAddressExW
+RtlIpv4StringToAddressW
+RtlIpv6AddressToStringA
+RtlIpv6AddressToStringExA
+RtlIpv6AddressToStringExW
+RtlIpv6AddressToStringW
+RtlIpv6StringToAddressA
+RtlIpv6StringToAddressExA
+RtlIpv6StringToAddressExW
+RtlIpv6StringToAddressW
+RtlIsActivationContextActive
+RtlIsDosDeviceName_U
+RtlIsGenericTableEmpty
+RtlIsGenericTableEmptyAvl
+RtlIsNameLegalDOS8Dot3
+RtlIsTextUnicode
+RtlIsThreadWithinLoaderCallout
+RtlIsValidHandle
+RtlIsValidIndexHandle
+RtlLargeIntegerToChar
+RtlLeaveCriticalSection
+RtlLengthRequiredSid
+RtlLengthSecurityDescriptor
+RtlLengthSid
+RtlLocalTimeToSystemTime
+RtlLockBootStatusData
+RtlLockHeap
+RtlLockMemoryStreamRegion
+RtlLogStackBackTrace
+RtlLookupAtomInAtomTable
+RtlLookupElementGenericTable
+RtlLookupElementGenericTableAvl
+RtlMakeSelfRelativeSD
+RtlMapGenericMask
+RtlMapSecurityErrorToNtStatus
+RtlMoveMemory
+RtlMultiAppendUnicodeStringBuffer
+RtlMultiByteToUnicodeN
+RtlMultiByteToUnicodeSize
+RtlNewInstanceSecurityObject
+RtlNewSecurityGrantedAccess
+RtlNewSecurityObject
+RtlNewSecurityObjectEx
+RtlNewSecurityObjectWithMultipleInheritance
+RtlNormalizeProcessParams
+RtlNtPathNameToDosPathName
+RtlNtStatusToDosError
+RtlNtStatusToDosErrorNoTeb
+RtlNumberGenericTableElements
+RtlNumberGenericTableElementsAvl
+RtlNumberOfClearBits
+RtlNumberOfSetBits
+RtlOemStringToUnicodeSize
+RtlOemStringToUnicodeString
+RtlOemToUnicodeN
+RtlOpenCurrentUser
+RtlPcToFileHeader
+RtlPinAtomInAtomTable
+RtlPopFrame
+RtlPrefixString
+RtlPrefixUnicodeString
+RtlProtectHeap
+RtlPushFrame
+RtlQueryAtomInAtomTable
+RtlQueryDepthSList
+RtlQueryEnvironmentVariable_U
+RtlQueryHeapInformation
+RtlQueryInformationAcl
+RtlQueryInformationActivationContext
+RtlQueryInformationActiveActivationContext
+RtlQueryInterfaceMemoryStream
+RtlQueryProcessBackTraceInformation
+RtlQueryProcessDebugInformation
+RtlQueryProcessHeapInformation
+RtlQueryProcessLockInformation
+RtlQueryRegistryValues
+RtlQuerySecurityObject
+RtlQueryTagHeap
+RtlQueryTimeZoneInformation
+RtlQueueApcWow64Thread
+RtlQueueWorkItem
+RtlRaiseException
+RtlRaiseStatus
+RtlRandom
+RtlRandomEx
+RtlReAllocateHeap
+RtlReadMemoryStream
+RtlReadOutOfProcessMemoryStream
+RtlRealPredecessor
+RtlRealSuccessor
+RtlRegisterSecureMemoryCacheCallback
+RtlRegisterWait
+RtlReleaseActivationContext
+RtlReleaseMemoryStream
+RtlReleasePebLock
+RtlReleaseResource
+RtlRemoteCall
+RtlRemoveVectoredExceptionHandler
+RtlResetRtlTranslations
+RtlRestoreLastWin32Error
+RtlRevertMemoryStream
+RtlRunDecodeUnicodeString
+RtlRunEncodeUnicodeString
+RtlSecondsSince1970ToTime
+RtlSecondsSince1980ToTime
+RtlSeekMemoryStream
+RtlSelfRelativeToAbsoluteSD
+RtlSelfRelativeToAbsoluteSD2
+RtlSetAllBits
+RtlSetAttributesSecurityDescriptor
+RtlSetBits
+RtlSetControlSecurityDescriptor
+RtlSetCriticalSectionSpinCount
+RtlSetCurrentDirectory_U
+RtlSetCurrentEnvironment
+RtlSetDaclSecurityDescriptor
+RtlSetEnvironmentVariable
+RtlSetGroupSecurityDescriptor
+RtlSetHeapInformation
+RtlSetInformationAcl
+RtlSetIoCompletionCallback
+RtlSetLastWin32Error
+RtlSetLastWin32ErrorAndNtStatusFromNtStatus
+RtlSetMemoryStreamSize
+RtlSetOwnerSecurityDescriptor
+RtlSetProcessIsCritical
+RtlSetSaclSecurityDescriptor
+RtlSetSecurityDescriptorRMControl
+RtlSetSecurityObject
+RtlSetSecurityObjectEx
+RtlSetThreadIsCritical
+RtlSetThreadPoolStartFunc
+RtlSetTimeZoneInformation
+RtlSetTimer
+RtlSetUserFlagsHeap
+RtlSetUserValueHeap
+RtlSizeHeap
+RtlSplay
+RtlStartRXact
+RtlStatMemoryStream
+RtlStringFromGUID
+RtlSubAuthorityCountSid
+RtlSubAuthoritySid
+RtlSubtreePredecessor
+RtlSubtreeSuccessor
+RtlSystemTimeToLocalTime
+RtlTimeFieldsToTime
+RtlTimeToElapsedTimeFields
+RtlTimeToSecondsSince1970
+RtlTimeToSecondsSince1980
+RtlTimeToTimeFields
+RtlTraceDatabaseAdd
+RtlTraceDatabaseCreate
+RtlTraceDatabaseDestroy
+RtlTraceDatabaseEnumerate
+RtlTraceDatabaseFind
+RtlTraceDatabaseLock
+RtlTraceDatabaseUnlock
+RtlTraceDatabaseValidate
+RtlTryEnterCriticalSection
+RtlUnhandledExceptionFilter
+RtlUnhandledExceptionFilter2
+RtlUnicodeStringToAnsiSize
+RtlUnicodeStringToAnsiString
+RtlUnicodeStringToCountedOemString
+RtlUnicodeStringToInteger
+RtlUnicodeStringToOemSize
+RtlUnicodeStringToOemString
+RtlUnicodeToCustomCPN
+RtlUnicodeToMultiByteN
+RtlUnicodeToMultiByteSize
+RtlUnicodeToOemN
+RtlUniform
+RtlUnlockBootStatusData
+RtlUnlockHeap
+RtlUnlockMemoryStreamRegion
+RtlUnwind
+RtlUpcaseUnicodeChar
+RtlUpcaseUnicodeString
+RtlUpcaseUnicodeStringToAnsiString
+RtlUpcaseUnicodeStringToCountedOemString
+RtlUpcaseUnicodeStringToOemString
+RtlUpcaseUnicodeToCustomCPN
+RtlUpcaseUnicodeToMultiByteN
+RtlUpcaseUnicodeToOemN
+RtlUpdateTimer
+RtlUpperChar
+RtlUpperString
+RtlValidAcl
+RtlValidRelativeSecurityDescriptor
+RtlValidSecurityDescriptor
+RtlValidSid
+RtlValidateHeap
+RtlValidateProcessHeaps
+RtlValidateUnicodeString
+RtlVerifyVersionInfo
+RtlWalkFrameChain
+RtlWalkHeap
+RtlWriteMemoryStream
+RtlWriteRegistryValue
+RtlZeroHeap
+RtlZeroMemory
+RtlZombifyActivationContext
+RtlpApplyLengthFunction
+RtlpEnsureBufferSize
+RtlpNotOwnerCriticalSection
+RtlpNtCreateKey
+RtlpNtEnumerateSubKey
+RtlpNtMakeTemporaryKey
+RtlpNtOpenKey
+RtlpNtQueryValueKey
+RtlpNtSetValueKey
+RtlpUnWaitCriticalSection
+RtlpWaitForCriticalSection
+RtlxAnsiStringToUnicodeSize
+RtlxOemStringToUnicodeSize
+RtlxUnicodeStringToAnsiSize
+RtlxUnicodeStringToOemSize
+VerSetConditionMask
+ZwAcceptConnectPort
+ZwAccessCheck
+ZwAccessCheckAndAuditAlarm
+ZwAccessCheckByType
+ZwAccessCheckByTypeAndAuditAlarm
+ZwAccessCheckByTypeResultList
+ZwAccessCheckByTypeResultListAndAuditAlarm
+ZwAccessCheckByTypeResultListAndAuditAlarmByHandle
+ZwAddAtom
+ZwAddBootEntry
+ZwAdjustGroupsToken
+ZwAdjustPrivilegesToken
+ZwAlertResumeThread
+ZwAlertThread
+ZwAllocateLocallyUniqueId
+ZwAllocateUserPhysicalPages
+ZwAllocateUuids
+ZwAllocateVirtualMemory
+ZwAreMappedFilesTheSame
+ZwAssignProcessToJobObject
+ZwCallbackReturn
+ZwCancelIoFile
+ZwCancelTimer
+ZwClearEvent
+ZwClose
+ZwCloseObjectAuditAlarm
+ZwCompactKeys
+ZwCompareTokens
+ZwCompleteConnectPort
+ZwCompressKey
+ZwConnectPort
+ZwContinue
+ZwCreateDebugObject
+ZwCreateDirectoryObject
+ZwCreateEvent
+ZwCreateEventPair
+ZwCreateFile
+ZwCreateIoCompletion
+ZwCreateJobObject
+ZwCreateJobSet
+ZwCreateKey
+ZwCreateKeyedEvent
+ZwCreateMailslotFile
+ZwCreateMutant
+ZwCreateNamedPipeFile
+ZwCreatePagingFile
+ZwCreatePort
+ZwCreateProcess
+ZwCreateProcessEx
+ZwCreateProfile
+ZwCreateSection
+ZwCreateSemaphore
+ZwCreateSymbolicLinkObject
+ZwCreateThread
+ZwCreateTimer
+ZwCreateToken
+ZwCreateWaitablePort
+ZwDebugActiveProcess
+ZwDebugContinue
+ZwDelayExecution
+ZwDeleteAtom
+ZwDeleteBootEntry
+ZwDeleteFile
+ZwDeleteKey
+ZwDeleteObjectAuditAlarm
+ZwDeleteValueKey
+ZwDeviceIoControlFile
+ZwDisplayString
+ZwDuplicateObject
+ZwDuplicateToken
+ZwEnumerateBootEntries
+ZwEnumerateKey
+ZwEnumerateSystemEnvironmentValuesEx
+ZwEnumerateValueKey
+ZwExtendSection
+ZwFilterToken
+ZwFindAtom
+ZwFlushBuffersFile
+ZwFlushInstructionCache
+ZwFlushKey
+ZwFlushVirtualMemory
+ZwFlushWriteBuffer
+ZwFreeUserPhysicalPages
+ZwFreeVirtualMemory
+ZwFsControlFile
+ZwGetContextThread
+ZwGetDevicePowerState
+ZwGetWriteWatch
+ZwImpersonateAnonymousToken
+ZwImpersonateClientOfPort
+ZwImpersonateThread
+ZwInitializeRegistry
+ZwInitiatePowerAction
+ZwIsProcessInJob
+ZwIsSystemResumeAutomatic
+ZwListenPort
+ZwLoadDriver
+ZwLoadKey
+ZwLoadKey2
+ZwLockFile
+ZwLockProductActivationKeys
+ZwLockRegistryKey
+ZwLockVirtualMemory
+ZwMakePermanentObject
+ZwMakeTemporaryObject
+ZwMapUserPhysicalPages
+ZwMapUserPhysicalPagesScatter
+ZwMapViewOfSection
+ZwModifyBootEntry
+ZwNotifyChangeDirectoryFile
+ZwNotifyChangeKey
+ZwNotifyChangeMultipleKeys
+ZwOpenDirectoryObject
+ZwOpenEvent
+ZwOpenEventPair
+ZwOpenFile
+ZwOpenIoCompletion
+ZwOpenJobObject
+ZwOpenKey
+ZwOpenKeyedEvent
+ZwOpenMutant
+ZwOpenObjectAuditAlarm
+ZwOpenProcess
+ZwOpenProcessToken
+ZwOpenProcessTokenEx
+ZwOpenSection
+ZwOpenSemaphore
+ZwOpenSymbolicLinkObject
+ZwOpenThread
+ZwOpenThreadToken
+ZwOpenThreadTokenEx
+ZwOpenTimer
+ZwPlugPlayControl
+ZwPowerInformation
+ZwPrivilegeCheck
+ZwPrivilegeObjectAuditAlarm
+ZwPrivilegedServiceAuditAlarm
+ZwProtectVirtualMemory
+ZwPulseEvent
+ZwQueryAttributesFile
+ZwQueryBootEntryOrder
+ZwQueryBootOptions
+ZwQueryDebugFilterState
+ZwQueryDefaultLocale
+ZwQueryDefaultUILanguage
+ZwQueryDirectoryFile
+ZwQueryDirectoryObject
+ZwQueryEaFile
+ZwQueryEvent
+ZwQueryFullAttributesFile
+ZwQueryInformationAtom
+ZwQueryInformationFile
+ZwQueryInformationJobObject
+ZwQueryInformationPort
+ZwQueryInformationProcess
+ZwQueryInformationThread
+ZwQueryInformationToken
+ZwQueryInstallUILanguage
+ZwQueryIntervalProfile
+ZwQueryIoCompletion
+ZwQueryKey
+ZwQueryMultipleValueKey
+ZwQueryMutant
+ZwQueryObject
+ZwQueryOpenSubKeys
+ZwQueryPerformanceCounter
+ZwQueryPortInformationProcess
+ZwQueryQuotaInformationFile
+ZwQuerySection
+ZwQuerySecurityObject
+ZwQuerySemaphore
+ZwQuerySymbolicLinkObject
+ZwQuerySystemEnvironmentValue
+ZwQuerySystemEnvironmentValueEx
+ZwQuerySystemInformation
+ZwQuerySystemTime
+ZwQueryTimer
+ZwQueryTimerResolution
+ZwQueryValueKey
+ZwQueryVirtualMemory
+ZwQueryVolumeInformationFile
+ZwQueueApcThread
+ZwRaiseException
+ZwRaiseHardError
+ZwReadFile
+ZwReadFileScatter
+ZwReadRequestData
+ZwReadVirtualMemory
+ZwRegisterThreadTerminatePort
+ZwReleaseKeyedEvent
+ZwReleaseMutant
+ZwReleaseSemaphore
+ZwRemoveIoCompletion
+ZwRemoveProcessDebug
+ZwRenameKey
+ZwReplaceKey
+ZwReplyPort
+ZwReplyWaitReceivePort
+ZwReplyWaitReceivePortEx
+ZwReplyWaitReplyPort
+ZwRequestPort
+ZwRequestWaitReplyPort
+ZwResetEvent
+ZwResetWriteWatch
+ZwRestoreKey
+ZwResumeProcess
+ZwResumeThread
+ZwSaveKey
+ZwSaveKeyEx
+ZwSaveMergedKeys
+ZwSecureConnectPort
+ZwSetBootEntryOrder
+ZwSetBootOptions
+ZwSetContextThread
+ZwSetDebugFilterState
+ZwSetDefaultHardErrorPort
+ZwSetDefaultLocale
+ZwSetDefaultUILanguage
+ZwSetEaFile
+ZwSetEvent
+ZwSetEventBoostPriority
+ZwSetHighEventPair
+ZwSetHighWaitLowEventPair
+ZwSetInformationDebugObject
+ZwSetInformationFile
+ZwSetInformationJobObject
+ZwSetInformationKey
+ZwSetInformationObject
+ZwSetInformationProcess
+ZwSetInformationThread
+ZwSetInformationToken
+ZwSetIntervalProfile
+ZwSetIoCompletion
+ZwSetLdtEntries
+ZwSetLowEventPair
+ZwSetLowWaitHighEventPair
+ZwSetQuotaInformationFile
+ZwSetSecurityObject
+ZwSetSystemEnvironmentValue
+ZwSetSystemEnvironmentValueEx
+ZwSetSystemInformation
+ZwSetSystemPowerState
+ZwSetSystemTime
+ZwSetThreadExecutionState
+ZwSetTimer
+ZwSetTimerResolution
+ZwSetUuidSeed
+ZwSetValueKey
+ZwSetVolumeInformationFile
+ZwShutdownSystem
+ZwSignalAndWaitForSingleObject
+ZwStartProfile
+ZwStopProfile
+ZwSuspendProcess
+ZwSuspendThread
+ZwSystemDebugControl
+ZwTerminateJobObject
+ZwTerminateProcess
+ZwTerminateThread
+ZwTestAlert
+ZwTraceEvent
+ZwTranslateFilePath
+ZwUnloadDriver
+ZwUnloadKey
+ZwUnloadKeyEx
+ZwUnlockFile
+ZwUnlockVirtualMemory
+ZwUnmapViewOfSection
+ZwVdmControl
+ZwWaitForDebugEvent
+ZwWaitForKeyedEvent
+ZwWaitForMultipleObjects
+ZwWaitForSingleObject
+ZwWaitHighEventPair
+ZwWaitLowEventPair
+ZwWriteFile
+ZwWriteFileGather
+ZwWriteRequestData
+ZwWriteVirtualMemory
+ZwYieldExecution
+__isascii
+__iscsym
+__iscsymf
+__toascii
+_alldiv
+_alldvrm
+_allmul
+_allrem
+_allshl
+_allshr
+_atoi64
+_aulldiv
+_aulldvrm
+_aullrem
+_aullshr
+_fltused
+_i64toa
+_i64tow
+_itoa
+_itow
+_lfind
+_ltoa
+_ltow
+_memccpy
+_memicmp
+_snprintf
+_snwprintf
+_splitpath
+_strcmpi
+_stricmp
+_strlwr
+_strnicmp
+_strupr
+_ui64toa
+_ui64tow
+_ultoa
+_ultow
+_vsnprintf
+_vsnwprintf
+_wcsicmp
+_wcslwr
+_wcsnicmp
+_wcsupr
+_wtoi
+_wtoi64
+_wtol
+abs
+atan
+atoi
+atol
+bsearch
+ceil
+cos
+fabs
+floor
+isalnum
+isalpha
+iscntrl
+isdigit
+isgraph
+islower
+isprint
+ispunct
+isspace
+isupper
+iswalpha
+iswctype
+iswdigit
+iswlower
+iswspace
+iswxdigit
+isxdigit
+labs
+log
+mbstowcs
+memchr
+memcmp
+memcpy
+memmove
+memset
+pow
+qsort
+sin
+sprintf
+sqrt
+sscanf
+strcat
+strchr
+strcmp
+strcpy
+strcspn
+strlen
+strncat
+strncmp
+strncpy
+strpbrk
+strrchr
+strspn
+strstr
+strtol
+strtoul
+swprintf
+tan
+tolower
+toupper
+towlower
+towupper
+vDbgPrintEx
+vDbgPrintExWithPrefix
+vsprintf
+wcscat
+wcschr
+wcscmp
+wcscpy
+wcscspn
+wcslen
+wcsncat
+wcsncmp
+wcsncpy
+wcspbrk
+wcsrchr
+wcsspn
+wcsstr
+wcstol
+wcstombs
+wcstoul
diff --git a/libs/libmdbx/src/src/osal.c b/libs/libmdbx/src/src/osal.c
index b39eea4be8..e5a1e69cb6 100644
--- a/libs/libmdbx/src/src/osal.c
+++ b/libs/libmdbx/src/src/osal.c
@@ -753,6 +753,19 @@ int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length) {
 #endif
 }
 
+int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos) {
+#if defined(_WIN32) || defined(_WIN64)
+  LARGE_INTEGER li;
+  li.QuadPart = pos;
+  return SetFilePointerEx(fd, li, NULL, FILE_BEGIN) ? MDBX_SUCCESS
+                                                    : GetLastError();
+#else
+  STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t),
+                    "libmdbx requires 64-bit file I/O on 64-bit systems");
+  return (lseek(fd, pos, SEEK_SET) < 0) ? errno : MDBX_SUCCESS;
+#endif
+}
+
 /*----------------------------------------------------------------------------*/
 
 int mdbx_thread_create(mdbx_thread_t *thread,
diff --git a/libs/libmdbx/src/src/osal.h b/libs/libmdbx/src/src/osal.h
index 50416d960c..9f9d1a4429 100644
--- a/libs/libmdbx/src/src/osal.h
+++ b/libs/libmdbx/src/src/osal.h
@@ -504,6 +504,7 @@ int mdbx_thread_join(mdbx_thread_t thread);
 int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync);
 int mdbx_filesize_sync(mdbx_filehandle_t fd);
 int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length);
+int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos);
 int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length);
 int mdbx_openfile(const char *pathname, int flags, mode_t mode,
                   mdbx_filehandle_t *fd, bool exclusive);
diff --git a/libs/libmdbx/src/src/tools/mdbx_chk.c b/libs/libmdbx/src/src/tools/mdbx_chk.c
index 6614bdb219..31119ba66e 100644
--- a/libs/libmdbx/src/src/tools/mdbx_chk.c
+++ b/libs/libmdbx/src/src/tools/mdbx_chk.c
@@ -97,7 +97,7 @@ const char *only_subdb;
 
 struct problem {
   struct problem *pr_next;
-  uint64_t count;
+  size_t count;
   const char *caption;
 };
 
@@ -221,8 +221,8 @@ static struct problem *problems_push(void) {
   return p;
 }
 
-static uint64_t problems_pop(struct problem *list) {
-  uint64_t count = 0;
+static size_t problems_pop(struct problem *list) {
+  size_t count = 0;
 
   if (problems_list) {
     int i;
@@ -231,7 +231,7 @@ static uint64_t problems_pop(struct problem *list) {
     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,
+      print("%s%s (%" PRIuPTR ")", i ? ", " : "", problems_list->caption,
             problems_list->count);
       mdbx_free(problems_list);
       problems_list = p;
@@ -267,7 +267,7 @@ static int pgvisitor(uint64_t pgno, unsigned pgnumber, void *ctx, int deep,
   else
     problem_add("deep", deep, "unknown area", "%s", dbi_name);
 
-  const uint64_t page_bytes = payload_bytes + header_bytes + unused_bytes;
+  const size_t page_bytes = payload_bytes + header_bytes + unused_bytes;
   walk.pgcount += pgnumber;
 
   const char *pagetype_caption;
@@ -351,7 +351,7 @@ static int pgvisitor(uint64_t pgno, unsigned pgnumber, void *ctx, int deep,
   if (pgnumber) {
     if (page_bytes != page_size) {
       problem_add("page", pgno, "misused",
-                  "%s-page: %" PRIu64 " != %" PRIu64 " (%" PRIuPTR
+                  "%s-page: %" PRIuPTR " != %" PRIuPTR " (%" PRIuPTR
                   "h + %" PRIuPTR "p + %" PRIuPTR "u)",
                   pagetype_caption, page_size, page_bytes, header_bytes,
                   payload_bytes, unused_bytes);
@@ -689,7 +689,7 @@ static int process_db(MDBX_dbi dbi_handle, char *dbi_name, visitor *handler,
 
   if (record_count != ms.ms_entries)
     problem_add("entry", record_count, "differentent number of entries",
-                "%" PRIuPTR " != %" PRIuPTR, record_count, ms.ms_entries);
+                "%" PRIu64 " != %" PRIu64, record_count, ms.ms_entries);
 bailout:
   problems_count = problems_pop(saved_list);
   if (!silent && verbose) {
@@ -1088,7 +1088,7 @@ int main(int argc, char *argv[]) {
 
   if (!dont_traversal) {
     struct problem *saved_list;
-    uint64_t traversal_problems;
+    size_t traversal_problems;
     uint64_t empty_pages, lost_bytes;
 
     print("Traversal b-tree by txn#%" PRIaTXN "...\n", txn->mt_txnid);
@@ -1181,9 +1181,9 @@ int main(int argc, char *argv[]) {
       print(" - summary: average fill %.1f%%",
             walk.total_payload_bytes * 100.0 / total_page_bytes);
       if (empty_pages)
-        print(", %" PRIuPTR " empty pages", empty_pages);
+        print(", %" PRIu64 " empty pages", empty_pages);
       if (lost_bytes)
-        print(", %" PRIuPTR " bytes lost", lost_bytes);
+        print(", %" PRIu64 " bytes lost", lost_bytes);
       print(", %" PRIuPTR " problems\n", traversal_problems);
     }
   } else if (verbose) {
diff --git a/libs/libmdbx/src/test/CMakeLists.txt b/libs/libmdbx/src/test/CMakeLists.txt
index 3ed01bddf9..ca7dd794cd 100644
--- a/libs/libmdbx/src/test/CMakeLists.txt
+++ b/libs/libmdbx/src/test/CMakeLists.txt
@@ -1,34 +1,35 @@
-set(TARGET mdbx_test)
+set(TARGET mdbx_test)
 project(${TARGET})
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-declarations")
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-cast-qual")
 
 add_executable(${TARGET}
-        base.h
-        cases.cc
-        chrono.cc
-        chrono.h
-        config.cc
-        config.h
-        dead.cc
-        hill.cc
-        jitter.cc
-        keygen.cc
-        keygen.h
-        log.cc
-        log.h
-        main.cc
-        osal.h
-        osal-unix.cc
-        test.cc
-        test.h
-        try.cc
-        utils.cc
-        utils.h
-)
+  base.h
+  cases.cc
+  chrono.cc
+  chrono.h
+  config.cc
+  config.h
+  copy.cc
+  dead.cc
+  hill.cc
+  jitter.cc
+  keygen.cc
+  keygen.h
+  log.cc
+  log.h
+  main.cc
+  osal.h
+  osal-unix.cc
+  test.cc
+  test.h
+  try.cc
+  utils.cc
+  utils.h
+  )
 
 target_link_libraries(${TARGET}
-        mdbx
-        )
+  mdbx
+  )
 
diff --git a/libs/libmdbx/src/test/cases.cc b/libs/libmdbx/src/test/cases.cc
index 4f4306d58e..13d475763a 100644
--- a/libs/libmdbx/src/test/cases.cc
+++ b/libs/libmdbx/src/test/cases.cc
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -68,6 +68,7 @@ void testcase_setup(const char *casename, actor_params &params,
     configure_actor(last_space_id, ac_jitter, nullptr, params);
     configure_actor(last_space_id, ac_hill, nullptr, params);
     configure_actor(last_space_id, ac_try, nullptr, params);
+    configure_actor(last_space_id, ac_copy, nullptr, params);
     log_notice("<<< testcase_setup(%s): done", casename);
   } else {
     failure("unknown testcase `%s`", casename);
diff --git a/libs/libmdbx/src/test/config.h b/libs/libmdbx/src/test/config.h
index 2d0fede046..1886a8ea57 100644
--- a/libs/libmdbx/src/test/config.h
+++ b/libs/libmdbx/src/test/config.h
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -26,7 +26,8 @@ enum actor_testcase {
   ac_deadread,
   ac_deadwrite,
   ac_jitter,
-  ac_try
+  ac_try,
+  ac_copy
 };
 
 enum actor_status {
diff --git a/libs/libmdbx/src/test/copy.cc b/libs/libmdbx/src/test/copy.cc
new file mode 100644
index 0000000000..e239d41e34
--- /dev/null
+++ b/libs/libmdbx/src/test/copy.cc
@@ -0,0 +1,26 @@
+#include "test.h"
+
+void testcase_copy::copy_db(const bool with_compaction) {
+  int err = osal_removefile(copy_pathname);
+  if (err != MDBX_SUCCESS && err != MDBX_ENOFILE)
+    failure_perror("mdbx_removefile()", err);
+
+  err = mdbx_env_copy(db_guard.get(), copy_pathname.c_str(),
+                      with_compaction ? MDBX_CP_COMPACT : 0);
+  if (unlikely(err != MDBX_SUCCESS))
+    failure_perror(with_compaction ? "mdbx_env_copy(MDBX_CP_COMPACT)"
+                                   : "mdbx_env_copy(MDBX_CP_ASIS)",
+                   err);
+}
+
+bool testcase_copy::run() {
+  jitter_delay();
+  db_open();
+  assert(!txn_guard);
+  const bool order = flipcoin();
+  jitter_delay();
+  copy_db(order);
+  jitter_delay();
+  copy_db(!order);
+  return true;
+}
diff --git a/libs/libmdbx/src/test/dead.cc b/libs/libmdbx/src/test/dead.cc
index ee13fbd0ae..3dd1ee7b24 100644
--- a/libs/libmdbx/src/test/dead.cc
+++ b/libs/libmdbx/src/test/dead.cc
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -14,50 +14,22 @@
 
 #include "test.h"
 
-bool testcase_deadread::setup() {
-  log_trace(">> setup");
-  if (!inherited::setup())
-    return false;
-
-  log_trace("<< setup");
-  return true;
-}
-
 bool testcase_deadread::run() {
   db_open();
   txn_begin(true);
+  cursor_guard.reset();
+  txn_guard.reset();
+  db_guard.reset();
   return true;
 }
 
-bool testcase_deadread::teardown() {
-  log_trace(">> teardown");
-  cursor_guard.release();
-  txn_guard.release();
-  db_guard.release();
-  return inherited::teardown();
-}
-
 //-----------------------------------------------------------------------------
 
-bool testcase_deadwrite::setup() {
-  log_trace(">> setup");
-  if (!inherited::setup())
-    return false;
-
-  log_trace("<< setup");
-  return true;
-}
-
 bool testcase_deadwrite::run() {
   db_open();
   txn_begin(false);
+  cursor_guard.reset();
+  txn_guard.reset();
+  db_guard.reset();
   return true;
 }
-
-bool testcase_deadwrite::teardown() {
-  log_trace(">> teardown");
-  cursor_guard.release();
-  txn_guard.release();
-  db_guard.release();
-  return inherited::teardown();
-}
diff --git a/libs/libmdbx/src/test/gc.sh b/libs/libmdbx/src/test/gc.sh
index be6991a48f..76c7a9a51c 100644
--- a/libs/libmdbx/src/test/gc.sh
+++ b/libs/libmdbx/src/test/gc.sh
@@ -25,6 +25,7 @@ function probe {
 	rm -f ${TESTDB_PREFIX}* \
 		&& ./mdbx_test --pathname=${TESTDB_PREFIX}db "$@" | lz4 > ${TESTDB_PREFIX}log.lz4 \
 		&& ./mdbx_chk -nvvv ${TESTDB_PREFIX}db | tee ${TESTDB_PREFIX}chk \
+		&& ./mdbx_chk -nvvv ${TESTDB_PREFIX}db-copy | tee ${TESTDB_PREFIX}chk-copy \
 		|| (echo "FAILED"; exit 1)
 }
 
diff --git a/libs/libmdbx/src/test/hill.cc b/libs/libmdbx/src/test/hill.cc
index 10cb308942..856aeb9356 100644
--- a/libs/libmdbx/src/test/hill.cc
+++ b/libs/libmdbx/src/test/hill.cc
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -14,17 +14,6 @@
 
 #include "test.h"
 
-bool testcase_hill::setup() {
-  log_trace(">> setup");
-  if (!inherited::setup())
-    return false;
-
-  /* TODO */
-
-  log_trace("<< setup");
-  return true;
-}
-
 bool testcase_hill::run() {
   db_open();
 
@@ -225,8 +214,3 @@ bool testcase_hill::run() {
   }
   return true;
 }
-
-bool testcase_hill::teardown() {
-  log_trace(">> teardown");
-  return inherited::teardown();
-}
diff --git a/libs/libmdbx/src/test/jitter.cc b/libs/libmdbx/src/test/jitter.cc
index 2551400443..48f9bd998e 100644
--- a/libs/libmdbx/src/test/jitter.cc
+++ b/libs/libmdbx/src/test/jitter.cc
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -14,15 +14,6 @@
 
 #include "test.h"
 
-bool testcase_jitter::setup() {
-  log_trace(">> setup");
-  if (!inherited::setup())
-    return false;
-
-  log_trace("<< setup");
-  return true;
-}
-
 bool testcase_jitter::run() {
   while (should_continue()) {
     jitter_delay();
@@ -66,8 +57,3 @@ bool testcase_jitter::run() {
   }
   return true;
 }
-
-bool testcase_jitter::teardown() {
-  log_trace(">> teardown");
-  return inherited::teardown();
-}
diff --git a/libs/libmdbx/src/test/main.cc b/libs/libmdbx/src/test/main.cc
index 3384311b3b..275b7b136b 100644
--- a/libs/libmdbx/src/test/main.cc
+++ b/libs/libmdbx/src/test/main.cc
@@ -337,6 +337,10 @@ int main(int argc, char *const argv[]) {
       configure_actor(last_space_id, ac_deadwrite, value, params);
       continue;
     }
+    if (config::parse_option(argc, argv, narg, "copy", nullptr)) {
+      configure_actor(last_space_id, ac_copy, value, params);
+      continue;
+    }
     if (config::parse_option(argc, argv, narg, "failfast",
                              global::config::failfast))
       continue;
diff --git a/libs/libmdbx/src/test/osal-unix.cc b/libs/libmdbx/src/test/osal-unix.cc
index 6661ae42c8..6e6d7a1c5c 100644
--- a/libs/libmdbx/src/test/osal-unix.cc
+++ b/libs/libmdbx/src/test/osal-unix.cc
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -184,7 +184,7 @@ void osal_killall_actors(void) {
 int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
   struct timespec ts;
   ts.tv_nsec = 0;
-  ts.tv_sec = timeout;
+  ts.tv_sec = (timeout > INT_MAX) ? INT_MAX : timeout;
 retry:
   int status, options = WNOHANG;
 #ifdef WUNTRACED
@@ -301,3 +301,7 @@ std::string osal_tempdir(void) {
     return "/dev/shm/";
   return "";
 }
+
+int osal_removefile(const std::string &pathname) {
+  return unlink(pathname.c_str()) ? errno : MDBX_SUCCESS;
+}
diff --git a/libs/libmdbx/src/test/osal-windows.cc b/libs/libmdbx/src/test/osal-windows.cc
index 7d59f657c2..f7f1de56e0 100644
--- a/libs/libmdbx/src/test/osal-windows.cc
+++ b/libs/libmdbx/src/test/osal-windows.cc
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -405,3 +405,7 @@ std::string osal_tempdir(void) {
   DWORD len = GetTempPathA(sizeof(buf), buf);
   return std::string(buf, len);
 }
+
+int osal_removefile(const std::string &pathname) {
+  return DeleteFileA(pathname.c_str()) ? MDBX_SUCCESS : GetLastError();
+}
diff --git a/libs/libmdbx/src/test/osal.h b/libs/libmdbx/src/test/osal.h
index c27282a656..3ccc7bbec1 100644
--- a/libs/libmdbx/src/test/osal.h
+++ b/libs/libmdbx/src/test/osal.h
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -32,6 +32,7 @@ void osal_udelay(unsigned us);
 void osal_yield(void);
 bool osal_istty(int fd);
 std::string osal_tempdir(void);
+int osal_removefile(const std::string &pathname);
 
 #ifdef _MSC_VER
 #ifndef STDIN_FILENO
diff --git a/libs/libmdbx/src/test/test.cc b/libs/libmdbx/src/test/test.cc
index b9663c2a09..6bba425a67 100644
--- a/libs/libmdbx/src/test/test.cc
+++ b/libs/libmdbx/src/test/test.cc
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -31,6 +31,8 @@ const char *testcase2str(const actor_testcase testcase) {
     return "jitter";
   case ac_try:
     return "try";
+  case ac_copy:
+    return "copy";
   }
 }
 
@@ -453,6 +455,9 @@ bool test_execute(const actor_config &config) {
     case ac_try:
       test.reset(new testcase_try(config, pid));
       break;
+    case ac_copy:
+      test.reset(new testcase_copy(config, pid));
+      break;
     default:
       test.reset(new testcase(config, pid));
       break;
diff --git a/libs/libmdbx/src/test/test.h b/libs/libmdbx/src/test/test.h
index 4b10a40fef..d145ec2e38 100644
--- a/libs/libmdbx/src/test/test.h
+++ b/libs/libmdbx/src/test/test.h
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
  * and other libmdbx authors: please see AUTHORS file.
  * All rights reserved.
@@ -152,56 +152,47 @@ public:
 };
 
 class testcase_hill : public testcase {
-  typedef testcase inherited;
-
 public:
   testcase_hill(const actor_config &config, const mdbx_pid_t pid)
       : testcase(config, pid) {}
-  bool setup();
   bool run();
-  bool teardown();
 };
 
 class testcase_deadread : public testcase {
-  typedef testcase inherited;
-
 public:
   testcase_deadread(const actor_config &config, const mdbx_pid_t pid)
       : testcase(config, pid) {}
-  bool setup();
   bool run();
-  bool teardown();
 };
 
 class testcase_deadwrite : public testcase {
-  typedef testcase inherited;
-
 public:
   testcase_deadwrite(const actor_config &config, const mdbx_pid_t pid)
       : testcase(config, pid) {}
-  bool setup();
   bool run();
-  bool teardown();
 };
 
 class testcase_jitter : public testcase {
-  typedef testcase inherited;
-
 public:
   testcase_jitter(const actor_config &config, const mdbx_pid_t pid)
       : testcase(config, pid) {}
-  bool setup();
   bool run();
-  bool teardown();
 };
 
 class testcase_try : public testcase {
-  typedef testcase inherited;
-
 public:
   testcase_try(const actor_config &config, const mdbx_pid_t pid)
       : testcase(config, pid) {}
-  bool setup();
   bool run();
-  bool teardown();
+};
+
+class testcase_copy : public testcase {
+  const std::string copy_pathname;
+  void copy_db(const bool with_compaction);
+
+public:
+  testcase_copy(const actor_config &config, const mdbx_pid_t pid)
+      : testcase(config, pid),
+        copy_pathname(config.params.pathname_db + "-copy") {}
+  bool run();
 };
diff --git a/libs/libmdbx/src/test/test.vcxproj b/libs/libmdbx/src/test/test.vcxproj
index a8c21d38c5..b47bc7a813 100644
--- a/libs/libmdbx/src/test/test.vcxproj
+++ b/libs/libmdbx/src/test/test.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -184,6 +184,7 @@
     <ClCompile Include="cases.cc" />
     <ClCompile Include="chrono.cc" />
     <ClCompile Include="config.cc" />
+    <ClCompile Include="copy.cc" />
     <ClCompile Include="dead.cc" />
     <ClCompile Include="hill.cc" />
     <ClCompile Include="try.cc" />
diff --git a/libs/libmdbx/src/test/try.cc b/libs/libmdbx/src/test/try.cc
index 1deae71d31..150abd36de 100644
--- a/libs/libmdbx/src/test/try.cc
+++ b/libs/libmdbx/src/test/try.cc
@@ -1,13 +1,4 @@
-#include "test.h"
-
-bool testcase_try::setup() {
-  log_trace(">> setup");
-  if (!inherited::setup())
-    return false;
-
-  log_trace("<< setup");
-  return true;
-}
+#include "test.h"
 
 bool testcase_try::run() {
   db_open();
@@ -27,11 +18,3 @@ bool testcase_try::run() {
   txn_guard.reset(txn);
   return true;
 }
-
-bool testcase_try::teardown() {
-  log_trace(">> teardown");
-  cursor_guard.release();
-  txn_guard.release();
-  db_guard.release();
-  return inherited::teardown();
-}
-- 
cgit v1.2.3