diff options
author | George Hazan <ghazan@miranda.im> | 2018-09-19 14:56:53 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2018-09-19 14:56:53 +0300 |
commit | d5c92952533f3e1bfb06ad7f231dacc03e6a260b (patch) | |
tree | 852c9df36e6c4f6a3befea6bce4ea3398a4f25d9 /libs/libmdbx/src | |
parent | e81977a4318e54def5a842d2d7388b95aee7cb7d (diff) |
merge of libmdbx code cleaning
Diffstat (limited to 'libs/libmdbx/src')
-rw-r--r-- | libs/libmdbx/src/src/bits.h | 141 | ||||
-rw-r--r-- | libs/libmdbx/src/src/mdbx.c | 254 | ||||
-rw-r--r-- | libs/libmdbx/src/src/tools/mdbx_chk.c | 4 |
3 files changed, 206 insertions, 193 deletions
diff --git a/libs/libmdbx/src/src/bits.h b/libs/libmdbx/src/src/bits.h index f3f0bcea97..d1c27bc5ab 100644 --- a/libs/libmdbx/src/src/bits.h +++ b/libs/libmdbx/src/src/bits.h @@ -863,7 +863,7 @@ void mdbx_panic(const char *fmt, ...) #else #define mdbx_debug_enabled(type) (0) #define mdbx_audit_enabled() (0) -#ifndef NDEBUG +#if !defined(NDEBUG) || defined(MDBX_FORCE_ASSERT) #define mdbx_assert_enabled() (1) #else #define mdbx_assert_enabled() (0) @@ -969,17 +969,8 @@ void mdbx_panic(const char *fmt, ...) /* assert(3) variant in transaction context */ #define mdbx_tassert(txn, expr) mdbx_assert((txn)->mt_env, expr) -static __inline void mdbx_jitter4testing(bool tiny) { -#ifndef NDEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - /*----------------------------------------------------------------------------*/ -/* Internal prototypes and inlines */ +/* Internal prototypes */ int mdbx_reader_check0(MDBX_env *env, int rlocked, int *dead); int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin, @@ -990,24 +981,6 @@ void mdbx_rthc_global_init(void); void mdbx_rthc_global_dtor(void); void mdbx_rthc_thread_dtor(void *ptr); -static __inline bool mdbx_is_power2(size_t x) { return (x & (x - 1)) == 0; } - -static __inline size_t mdbx_roundup2(size_t value, size_t granularity) { - assert(mdbx_is_power2(granularity)); - return (value + granularity - 1) & ~(granularity - 1); -} - -static __inline unsigned mdbx_log2(size_t value) { - assert(mdbx_is_power2(value)); - - unsigned log = 0; - while (value > 1) { - log += 1; - value >>= 1; - } - return log; -} - #define MDBX_IS_ERROR(rc) \ ((rc) != MDBX_RESULT_TRUE && (rc) != MDBX_RESULT_FALSE) @@ -1155,71 +1128,12 @@ typedef struct MDBX_node { * This is node header plus key plus data size. */ #define LEAFSIZE(k, d) (NODESIZE + (k)->iov_len + (d)->iov_len) -/* Address of node i in page p */ -static __inline MDBX_node *NODEPTR(MDBX_page *p, unsigned i) { - assert(NUMKEYS(p) > (unsigned)(i)); - return (MDBX_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEHDRSZ); -} - /* Address of the key for the node */ #define NODEKEY(node) (void *)((node)->mn_data) /* Address of the data for a node */ #define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize) -/* Get the page number pointed to by a branch node */ -static __inline pgno_t NODEPGNO(const MDBX_node *node) { - pgno_t pgno; - if (UNALIGNED_OK) { - pgno = node->mn_ksize_and_pgno; - if (sizeof(pgno_t) > 4) - pgno &= MAX_PAGENO; - } else { - pgno = node->mn_lo | ((pgno_t)node->mn_hi << 16); - if (sizeof(pgno_t) > 4) - pgno |= ((uint64_t)node->mn_flags) << 32; - } - return pgno; -} - -/* Set the page number in a branch node */ -static __inline void SETPGNO(MDBX_node *node, pgno_t pgno) { - assert(pgno <= MAX_PAGENO); - - if (UNALIGNED_OK) { - if (sizeof(pgno_t) > 4) - pgno |= ((uint64_t)node->mn_ksize) << 48; - node->mn_ksize_and_pgno = pgno; - } else { - node->mn_lo = (uint16_t)pgno; - node->mn_hi = (uint16_t)(pgno >> 16); - if (sizeof(pgno_t) > 4) - node->mn_flags = (uint16_t)((uint64_t)pgno >> 32); - } -} - -/* Get the size of the data in a leaf node */ -static __inline size_t NODEDSZ(const MDBX_node *node) { - size_t size; - if (UNALIGNED_OK) { - size = node->mn_dsize; - } else { - size = node->mn_lo | ((size_t)node->mn_hi << 16); - } - return size; -} - -/* Set the size of the data for a leaf node */ -static __inline void SETDSZ(MDBX_node *node, size_t size) { - assert(size < INT_MAX); - if (UNALIGNED_OK) { - node->mn_dsize = (uint32_t)size; - } else { - node->mn_lo = (uint16_t)size; - node->mn_hi = (uint16_t)(size >> 16); - } -} - /* The size of a key in a node */ #define NODEKSZ(node) ((node)->mn_ksize) @@ -1272,19 +1186,8 @@ static __inline void SETDSZ(MDBX_node *node, size_t size) { #define mdbx_cmp2int(a, b) (((a) > (b)) - ((b) > (a))) #endif -static __inline size_t pgno2bytes(const MDBX_env *env, pgno_t pgno) { - mdbx_assert(env, (1u << env->me_psize2log) == env->me_psize); - return ((size_t)pgno) << env->me_psize2log; -} - -static __inline MDBX_page *pgno2page(const MDBX_env *env, pgno_t pgno) { - return (MDBX_page *)(env->me_map + pgno2bytes(env, pgno)); -} - -static __inline pgno_t bytes2pgno(const MDBX_env *env, size_t bytes) { - mdbx_assert(env, (env->me_psize >> env->me_psize2log) == 1); - return (pgno_t)(bytes >> env->me_psize2log); -} +/* Do not spill pages to disk if txn is getting full, may fail instead */ +#define MDBX_NOSPILL 0x8000 static __inline pgno_t pgno_add(pgno_t base, pgno_t augend) { assert(base <= MAX_PAGENO); @@ -1296,33 +1199,11 @@ static __inline pgno_t pgno_sub(pgno_t base, pgno_t subtrahend) { return (subtrahend < base - MIN_PAGENO) ? base - subtrahend : MIN_PAGENO; } -static __inline size_t pgno_align2os_bytes(const MDBX_env *env, pgno_t pgno) { - return mdbx_roundup2(pgno2bytes(env, pgno), env->me_os_psize); -} - -static __inline pgno_t pgno_align2os_pgno(const MDBX_env *env, pgno_t pgno) { - return bytes2pgno(env, pgno_align2os_bytes(env, pgno)); +static __inline void mdbx_jitter4testing(bool tiny) { +#ifndef NDEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif } - -/* Do not spill pages to disk if txn is getting full, may fail instead */ -#define MDBX_NOSPILL 0x8000 - -/* Perform act while tracking temporary cursor mn */ -#define WITH_CURSOR_TRACKING(mn, act) \ - do { \ - mdbx_cassert(&(mn), \ - mn.mc_txn->mt_cursors != NULL /* must be not rdonly txt */); \ - MDBX_cursor mc_dummy, *tracked, \ - **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \ - if ((mn).mc_flags & C_SUB) { \ - mc_dummy.mc_flags = C_INITIALIZED; \ - mc_dummy.mc_xcursor = (MDBX_xcursor *)&(mn); \ - tracked = &mc_dummy; \ - } else { \ - tracked = &(mn); \ - } \ - tracked->mc_next = *tp; \ - *tp = tracked; \ - { act; } \ - *tp = tracked->mc_next; \ - } while (0) diff --git a/libs/libmdbx/src/src/mdbx.c b/libs/libmdbx/src/src/mdbx.c index 9cfeba8809..e8be0832f1 100644 --- a/libs/libmdbx/src/src/mdbx.c +++ b/libs/libmdbx/src/src/mdbx.c @@ -37,7 +37,134 @@ #include "./bits.h" +/*----------------------------------------------------------------------------*/ +/* Internal inlines */ + +#undef assert +#define assert(expr) mdbx_assert(NULL, expr) + +static __inline bool mdbx_is_power2(size_t x) { return (x & (x - 1)) == 0; } + +static __inline size_t mdbx_roundup2(size_t value, size_t granularity) { + assert(mdbx_is_power2(granularity)); + return (value + granularity - 1) & ~(granularity - 1); +} + +static __inline unsigned mdbx_log2(size_t value) { + assert(mdbx_is_power2(value)); + + unsigned log = 0; + while (value > 1) { + log += 1; + value >>= 1; + } + return log; +} + +/* Address of node i in page p */ +static __inline MDBX_node *NODEPTR(MDBX_page *p, unsigned i) { + assert(NUMKEYS(p) > (unsigned)(i)); + return (MDBX_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEHDRSZ); +} + +/* Get the page number pointed to by a branch node */ +static __inline pgno_t NODEPGNO(const MDBX_node *node) { + pgno_t pgno; + if (UNALIGNED_OK) { + pgno = node->mn_ksize_and_pgno; + if (sizeof(pgno_t) > 4) + pgno &= MAX_PAGENO; + } else { + pgno = node->mn_lo | ((pgno_t)node->mn_hi << 16); + if (sizeof(pgno_t) > 4) + pgno |= ((uint64_t)node->mn_flags) << 32; + } + return pgno; +} + +/* Set the page number in a branch node */ +static __inline void SETPGNO(MDBX_node *node, pgno_t pgno) { + assert(pgno <= MAX_PAGENO); + + if (UNALIGNED_OK) { + if (sizeof(pgno_t) > 4) + pgno |= ((uint64_t)node->mn_ksize) << 48; + node->mn_ksize_and_pgno = pgno; + } else { + node->mn_lo = (uint16_t)pgno; + node->mn_hi = (uint16_t)(pgno >> 16); + if (sizeof(pgno_t) > 4) + node->mn_flags = (uint16_t)((uint64_t)pgno >> 32); + } +} + +/* Get the size of the data in a leaf node */ +static __inline size_t NODEDSZ(const MDBX_node *node) { + size_t size; + if (UNALIGNED_OK) { + size = node->mn_dsize; + } else { + size = node->mn_lo | ((size_t)node->mn_hi << 16); + } + return size; +} + +/* Set the size of the data for a leaf node */ +static __inline void SETDSZ(MDBX_node *node, size_t size) { + assert(size < INT_MAX); + if (UNALIGNED_OK) { + node->mn_dsize = (uint32_t)size; + } else { + node->mn_lo = (uint16_t)size; + node->mn_hi = (uint16_t)(size >> 16); + } +} + +static __inline size_t pgno2bytes(const MDBX_env *env, pgno_t pgno) { + mdbx_assert(env, (1u << env->me_psize2log) == env->me_psize); + return ((size_t)pgno) << env->me_psize2log; +} + +static __inline MDBX_page *pgno2page(const MDBX_env *env, pgno_t pgno) { + return (MDBX_page *)(env->me_map + pgno2bytes(env, pgno)); +} + +static __inline pgno_t bytes2pgno(const MDBX_env *env, size_t bytes) { + mdbx_assert(env, (env->me_psize >> env->me_psize2log) == 1); + return (pgno_t)(bytes >> env->me_psize2log); +} + +static __inline size_t pgno_align2os_bytes(const MDBX_env *env, pgno_t pgno) { + return mdbx_roundup2(pgno2bytes(env, pgno), env->me_os_psize); +} + +static __inline pgno_t pgno_align2os_pgno(const MDBX_env *env, pgno_t pgno) { + return bytes2pgno(env, pgno_align2os_bytes(env, pgno)); +} + +/* Perform act while tracking temporary cursor mn */ +#define WITH_CURSOR_TRACKING(mn, act) \ + do { \ + mdbx_cassert(&(mn), \ + mn.mc_txn->mt_cursors != NULL /* must be not rdonly txt */); \ + MDBX_cursor mc_dummy, *tracked, \ + **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \ + if ((mn).mc_flags & C_SUB) { \ + mc_dummy.mc_flags = C_INITIALIZED; \ + mc_dummy.mc_xcursor = (MDBX_xcursor *)&(mn); \ + tracked = &mc_dummy; \ + } else { \ + tracked = &(mn); \ + } \ + tracked->mc_next = *tp; \ + *tp = tracked; \ + { act; } \ + *tp = tracked->mc_next; \ + } while (0) + +/*----------------------------------------------------------------------------*/ /* LY: temporary workaround for Elbrus's memcmp() bug. */ + #if defined(__e2k__) && !__GLIBC_PREREQ(2, 24) int __hot mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2, size_t n) { @@ -2127,9 +2254,9 @@ static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno, bailout: if (rc == MDBX_SUCCESS) { #if defined(_WIN32) || defined(_WIN64) - assert(size_bytes == env->me_dxb_mmap.current); - assert(size_bytes <= env->me_dxb_mmap.filesize); - assert(limit_bytes == env->me_dxb_mmap.length); + mdbx_assert(env, size_bytes == env->me_dxb_mmap.current); + mdbx_assert(env, size_bytes <= env->me_dxb_mmap.filesize); + mdbx_assert(env, limit_bytes == env->me_dxb_mmap.length); #endif env->me_dbgeo.now = size_bytes; env->me_dbgeo.upper = limit_bytes; @@ -2232,7 +2359,7 @@ static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp, if (likely(flags & MDBX_ALLOC_CACHE)) { /* If there are any loose pages, just use them */ - assert(mp && num); + mdbx_assert(env, mp && num); if (likely(num == 1 && txn->mt_loose_pages)) { np = txn->mt_loose_pages; txn->mt_loose_pages = NEXT_LOOSE_PAGE(np); @@ -2563,7 +2690,7 @@ static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp, *mp = NULL; txn->mt_flags |= MDBX_TXN_ERROR; } - assert(rc); + mdbx_assert(env, rc != MDBX_SUCCESS); return rc; } @@ -2841,7 +2968,7 @@ static int mdbx_env_sync_ex(MDBX_env *env, int force, int nonblock) { env->me_sync_pending > pgno2bytes(env, 16 /* FIXME: define threshold */) && (flags & MDBX_NOSYNC) == 0) { - assert(((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); + mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); const size_t usedbytes = pgno_align2os_bytes(env, head->mm_geo.next); mdbx_txn_unlock(env); @@ -3057,7 +3184,7 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) { mdbx_rdt_unlock(env); if (likely(env->me_flags & MDBX_ENV_TXKEY)) { - assert(env->me_live_reader == env->me_pid); + mdbx_assert(env, env->me_live_reader == env->me_pid); mdbx_thread_rthc_set(env->me_txkey, r); } } @@ -3176,7 +3303,7 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) { return MDBX_SUCCESS; } bailout: - assert(rc != MDBX_SUCCESS); + mdbx_tassert(txn, rc != MDBX_SUCCESS); mdbx_txn_end(txn, MDBX_END_SLOT | MDBX_END_FAIL_BEGIN); return rc; } @@ -3386,7 +3513,7 @@ static void mdbx_dbis_update(MDBX_txn *txn, int keep) { if (ptr) { env->me_dbxs[i].md_name.iov_len = 0; mdbx_compiler_barrier(); - assert(env->me_dbflags[i] == 0); + mdbx_assert(env, env->me_dbflags[i] == 0); env->me_dbiseqs[i]++; env->me_dbxs[i].md_name.iov_base = NULL; free(ptr); @@ -3506,8 +3633,8 @@ int mdbx_txn_reset(MDBX_txn *txn) { /* LY: don't close DBI-handles in MDBX mode */ int rc = mdbx_txn_end(txn, MDBX_END_RESET | MDBX_END_UPDATE); if (rc == MDBX_SUCCESS) { - assert(txn->mt_signature == MDBX_MT_SIGNATURE); - assert(txn->mt_owner == 0); + mdbx_tassert(txn, txn->mt_signature == MDBX_MT_SIGNATURE); + mdbx_tassert(txn, txn->mt_owner == 0); } return rc; } @@ -3680,40 +3807,18 @@ static int mdbx_update_gc(MDBX_txn *txn) { if (unlikely(rc != MDBX_SUCCESS)) goto bailout; - txnid_t reclaiming_head_id = env->me_last_reclaimed; - if (unlikely(reclaiming_head_id == 0)) { - reclaiming_head_id = mdbx_find_oldest(txn) - 1; - MDBX_val key; - rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_FIRST); - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc != MDBX_NOTFOUND) - goto bailout; - } else if (unlikely(key.iov_len != sizeof(txnid_t))) { - rc = MDBX_CORRUPTED; - goto bailout; - } else { - txnid_t first_pg; - memcpy(&first_pg, key.iov_base, sizeof(txnid_t)); - if (reclaiming_head_id >= first_pg) - reclaiming_head_id = first_pg - 1; - } - } - retry: mdbx_trace(" >> restart"); mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); - unsigned settled = 0, cleaned_gc_slot = 0, reused_gc_slots = 0, - filled_gc_slot = ~0u; - txnid_t cleaned_gc_id = 0, head_gc_id = env->me_last_reclaimed - ? env->me_last_reclaimed - : reclaiming_head_id; - if (unlikely(/* paranoia */ ++loop > 42)) { mdbx_error("too more loops %u, bailout", loop); rc = MDBX_PROBLEM; goto bailout; } + unsigned settled = 0, cleaned_gc_slot = 0, reused_gc_slots = 0, + filled_gc_slot = ~0u; + txnid_t cleaned_gc_id = 0, head_gc_id = env->me_last_reclaimed; while (1) { /* Come back here after each Put() in case befree-list changed */ MDBX_val key, data; @@ -3729,9 +3834,11 @@ retry: /* LY: cleanup reclaimed records. */ do { cleaned_gc_id = txn->mt_lifo_reclaimed[++cleaned_gc_slot]; - assert(cleaned_gc_slot > 0 && cleaned_gc_id < *env->me_oldest); - head_gc_id = - (head_gc_id > cleaned_gc_id) ? cleaned_gc_id : head_gc_id; + mdbx_tassert(txn, + cleaned_gc_slot > 0 && cleaned_gc_id < *env->me_oldest); + head_gc_id = (!head_gc_id || head_gc_id > cleaned_gc_id) + ? cleaned_gc_id + : head_gc_id; key.iov_base = &cleaned_gc_id; key.iov_len = sizeof(cleaned_gc_id); rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_SET); @@ -3752,7 +3859,7 @@ retry: goto bailout; } while (cleaned_gc_slot < MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); mdbx_txl_sort(txn->mt_lifo_reclaimed); - assert(MDBX_PNL_LAST(txn->mt_lifo_reclaimed) == head_gc_id); + mdbx_tassert(txn, MDBX_PNL_LAST(txn->mt_lifo_reclaimed) == head_gc_id); } } else { /* If using records from freeDB which we have not yet deleted, @@ -3982,10 +4089,29 @@ retry: if (0 >= (int)left) break; + if (unlikely(head_gc_id == 0)) { + head_gc_id = mdbx_find_oldest(txn) - 1; + if (txn->mt_lifo_reclaimed == NULL) { + rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_FIRST); + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc != MDBX_NOTFOUND) + goto bailout; + } else if (unlikely(key.iov_len != sizeof(txnid_t))) { + rc = MDBX_CORRUPTED; + goto bailout; + } else { + txnid_t first_txn; + memcpy(&first_txn, key.iov_base, sizeof(txnid_t)); + if (head_gc_id >= first_txn) + head_gc_id = first_txn - 1; + } + } + } + const unsigned prefer_max_scatter = 257; txnid_t reservation_gc_id; if (lifo) { - assert(txn->mt_lifo_reclaimed != NULL); + mdbx_tassert(txn, txn->mt_lifo_reclaimed != NULL); if (unlikely(!txn->mt_lifo_reclaimed)) { txn->mt_lifo_reclaimed = mdbx_txl_alloc(); if (unlikely(!txn->mt_lifo_reclaimed)) { @@ -4014,7 +4140,9 @@ retry: /* LY: freedb is empty, will look any free txn-id in high2low order. */ do { --head_gc_id; - mdbx_assert(env, MDBX_PNL_LAST(txn->mt_lifo_reclaimed) > head_gc_id); + mdbx_assert(env, + MDBX_PNL_IS_EMPTY(txn->mt_lifo_reclaimed) || + MDBX_PNL_LAST(txn->mt_lifo_reclaimed) > head_gc_id); rc = mdbx_txl_append(&txn->mt_lifo_reclaimed, head_gc_id); if (unlikely(rc != MDBX_SUCCESS)) goto bailout; @@ -4039,7 +4167,7 @@ retry: } const unsigned i = (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) - reused_gc_slots; - assert(i > 0 && i <= MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); + mdbx_tassert(txn, i > 0 && i <= MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); reservation_gc_id = txn->mt_lifo_reclaimed[i]; mdbx_trace("%s: take @%" PRIaTXN " from lifo-reclaimed[%u]", dbg_prefix_mode, reservation_gc_id, i); @@ -4051,8 +4179,8 @@ retry: } ++reused_gc_slots; - assert(txn->mt_lifo_reclaimed == NULL || - MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) <= INT16_MAX); + mdbx_tassert(txn, txn->mt_lifo_reclaimed == NULL || + MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) <= INT16_MAX); unsigned chunk = left; if (unlikely(chunk > env->me_maxgc_ov1page)) { const unsigned avail_gs_slots = @@ -4100,7 +4228,7 @@ retry: } } } - assert(chunk > 0); + mdbx_tassert(txn, chunk > 0); mdbx_trace("%s: head_gc_id %" PRIaTXN ", reused_gc_slot %u, reservation-id " "%" PRIaTXN, @@ -4359,7 +4487,7 @@ static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep) { continue; } pgno = dl[i].pgno; - assert(pgno >= MIN_PAGENO); + mdbx_tassert(txn, pgno >= MIN_PAGENO); /* clear dirty flag */ dp->mp_flags &= ~P_DIRTY; dp->mp_validator = 0 /* TODO */; @@ -4730,7 +4858,7 @@ fail: * before mapping it into memory. */ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta, uint64_t *filesize) { - assert(offsetof(MDBX_page, mp_meta) == PAGEHDRSZ); + STATIC_ASSERT(offsetof(MDBX_page, mp_meta) == PAGEHDRSZ); int rc = mdbx_filesize(env->me_fd, filesize); if (unlikely(rc != MDBX_SUCCESS)) @@ -5906,7 +6034,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) { break; if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) { - assert(META_IS_STEADY(&meta) && !META_IS_STEADY(head)); + mdbx_assert(env, META_IS_STEADY(&meta) && !META_IS_STEADY(head)); if (env->me_flags & MDBX_RDONLY) { mdbx_error("rollback needed: (from head %" PRIaTXN " to steady %" PRIaTXN "), but unable in read-only mode", @@ -6040,8 +6168,8 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) { /* Open and/or initialize the lock region for the environment. */ static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname, mode_t mode) { - assert(env->me_fd != INVALID_HANDLE_VALUE); - assert(env->me_lfd == INVALID_HANDLE_VALUE); + mdbx_assert(env, env->me_fd != INVALID_HANDLE_VALUE); + mdbx_assert(env, env->me_lfd == INVALID_HANDLE_VALUE); const int open_flags = (env->me_flags & MDBX_EXCLUSIVE) ? O_RDWR : O_RDWR | O_CREAT; @@ -7766,7 +7894,7 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, mc->mc_ki[mc->mc_top] = (uint16_t)nkeys; return MDBX_NOTFOUND; } - assert(nkeys > 0); + mdbx_cassert(mc, nkeys > 0); rc = MDBX_SUCCESS; if (IS_LEAF2(mp)) { @@ -8390,7 +8518,7 @@ int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, if ((rc2 = mdbx_ovpage_free(mc, omp)) != MDBX_SUCCESS) return rc2; } else if (data->iov_len == olddata.iov_len) { - assert(EVEN(key->iov_len) == EVEN(leaf->mn_ksize)); + mdbx_cassert(mc, EVEN(key->iov_len) == EVEN(leaf->mn_ksize)); /* same size, just replace it. Note that we could * also reuse this node if the new data is smaller, * but instead we opt to shrink the node in that case. */ @@ -8406,8 +8534,8 @@ int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, mdbx_cassert(mc, key->iov_len < UINT16_MAX); leaf->mn_ksize = (uint16_t)key->iov_len; memcpy(NODEKEY(leaf), key->iov_base, key->iov_len); - assert((char *)NODEKEY(leaf) + NODEDSZ(leaf) < - (char *)(mc->mc_pg[mc->mc_top]) + env->me_psize); + mdbx_cassert(mc, (char *)NODEKEY(leaf) + NODEDSZ(leaf) < + (char *)(mc->mc_pg[mc->mc_top]) + env->me_psize); goto fix_parent; } @@ -11666,14 +11794,16 @@ static int mdbx_dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags, if (!txn->mt_dbxs[dbi].md_cmp || MDBX_DEBUG) { if (!keycmp) keycmp = mdbx_default_keycmp(user_flags); - assert(!txn->mt_dbxs[dbi].md_cmp || txn->mt_dbxs[dbi].md_cmp == keycmp); + mdbx_tassert(txn, !txn->mt_dbxs[dbi].md_cmp || + txn->mt_dbxs[dbi].md_cmp == keycmp); txn->mt_dbxs[dbi].md_cmp = keycmp; } if (!txn->mt_dbxs[dbi].md_dcmp || MDBX_DEBUG) { if (!datacmp) datacmp = mdbx_default_datacmp(user_flags); - assert(!txn->mt_dbxs[dbi].md_dcmp || txn->mt_dbxs[dbi].md_dcmp == datacmp); + mdbx_tassert(txn, !txn->mt_dbxs[dbi].md_dcmp || + txn->mt_dbxs[dbi].md_dcmp == datacmp); txn->mt_dbxs[dbi].md_dcmp = datacmp; } @@ -11788,7 +11918,7 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags, if (env->me_dbflags[i] & MDBX_VALID) { txn->mt_dbs[i].md_flags = env->me_dbflags[i] & PERSISTENT_FLAGS; txn->mt_dbflags[i] = DB_VALID | DB_USRVALID | DB_STALE; - assert(txn->mt_dbxs[i].md_cmp != NULL); + mdbx_tassert(txn, txn->mt_dbxs[i].md_cmp != NULL); } } txn->mt_numdbs = env->me_numdbs; @@ -11817,7 +11947,7 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags, MDBX_db db_dummy; if (unlikely(rc)) { /* MDBX_NOTFOUND and MDBX_CREATE: Create new DB */ - assert(rc == MDBX_NOTFOUND); + mdbx_tassert(txn, rc == MDBX_NOTFOUND); memset(&db_dummy, 0, sizeof(db_dummy)); db_dummy.md_root = P_INVALID; db_dummy.md_flags = user_flags & PERSISTENT_FLAGS; @@ -11840,7 +11970,7 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags, env->me_dbflags[slot] = 0; rc = mdbx_dbi_bind(txn, slot, user_flags, keycmp, datacmp); if (unlikely(rc != MDBX_SUCCESS)) { - assert((dbflag & DB_CREAT) == 0); + mdbx_tassert(txn, (dbflag & DB_CREAT) == 0); bailout: free(namedup); } else { @@ -12256,7 +12386,7 @@ int __cold mdbx_reader_check(MDBX_env *env, int *dead) { * MDBX_SUCCESS - done * Otherwise errcode. */ int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) { - assert(rdt_locked >= 0); + mdbx_assert(env, rdt_locked >= 0); if (unlikely(env->me_pid != mdbx_getpid())) { env->me_flags |= MDBX_FATAL_ERROR; @@ -13172,7 +13302,7 @@ int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result, if (unlikely(new < increment)) return MDBX_RESULT_TRUE; - assert(new > dbs->md_seq); + mdbx_tassert(txn, new > dbs->md_seq); dbs->md_seq = new; txn->mt_flags |= MDBX_TXN_DIRTY; txn->mt_dbflags[dbi] |= DB_DIRTY; diff --git a/libs/libmdbx/src/src/tools/mdbx_chk.c b/libs/libmdbx/src/src/tools/mdbx_chk.c index e3ffe3acfe..d11bef54c9 100644 --- a/libs/libmdbx/src/src/tools/mdbx_chk.c +++ b/libs/libmdbx/src/src/tools/mdbx_chk.c @@ -421,7 +421,9 @@ static int handle_freedb(const uint64_t record_number, const MDBX_val *key, (number + 1) * sizeof(pgno_t), data->iov_len); number = data->iov_len / sizeof(pgno_t) - 1; } else if (data->iov_len - (number + 1) * sizeof(pgno_t) > - sizeof(pgno_t) * 2) + /* LY: allow gap upto half of page. it is ok + * and better than shink-and-retry inside mdbx_update_gc() */ + envstat.ms_psize / 2) problem_add("entry", record_number, "extra idl space", "%" PRIuSIZE " < %" PRIuSIZE " (minor, not a trouble)", (number + 1) * sizeof(pgno_t), data->iov_len); |