diff --git a/src/api-cursor.c b/src/api-cursor.c index ec87e4bd..cfe935f1 100644 --- a/src/api-cursor.c +++ b/src/api-cursor.c @@ -12,8 +12,7 @@ MDBX_cursor *mdbx_cursor_create(void *context) { couple->outer.signature = cur_signature_ready4dispose; couple->outer.next = &couple->outer; couple->userctx = context; - couple->outer.top_and_flags = z_poor_mark; - couple->inner.cursor.top_and_flags = z_poor_mark | z_inner; + cursor_reset(couple); VALGRIND_MAKE_MEM_DEFINED(&couple->outer.backup, sizeof(couple->outer.backup)); VALGRIND_MAKE_MEM_DEFINED(&couple->outer.tree, sizeof(couple->outer.tree)); VALGRIND_MAKE_MEM_DEFINED(&couple->outer.clc, sizeof(couple->outer.clc)); @@ -31,13 +30,15 @@ int mdbx_cursor_reset(MDBX_cursor *mc) { if (unlikely(!mc)) return LOG_IFERR(MDBX_EINVAL); - if (unlikely(mc->signature != cur_signature_ready4dispose && mc->signature != cur_signature_live)) - return LOG_IFERR(MDBX_EBADSIGN); + if (likely(mc->signature == cur_signature_live)) { + cursor_reset((cursor_couple_t *)mc); + return MDBX_SUCCESS; + } - cursor_couple_t *couple = (cursor_couple_t *)mc; - couple->outer.top_and_flags = z_poor_mark; - couple->inner.cursor.top_and_flags = z_poor_mark | z_inner; - return MDBX_SUCCESS; + if (likely(mc->signature == cur_signature_ready4dispose)) + return MDBX_SUCCESS; + + return LOG_IFERR(MDBX_EBADSIGN); } int mdbx_cursor_bind(MDBX_txn *txn, MDBX_cursor *mc, MDBX_dbi dbi) { @@ -112,7 +113,7 @@ int mdbx_cursor_unbind(MDBX_cursor *mc) { } mc->next = mc; } - be_poor(mc); + cursor_drown((cursor_couple_t *)mc); mc->signature = cur_signature_ready4dispose; return MDBX_SUCCESS; } @@ -221,10 +222,9 @@ int mdbx_txn_release_all_cursors_ex(const MDBX_txn *txn, bool unbind, size_t *co ENSURE(nullptr, mc->signature == cur_signature_live && (mc->next != mc) && !mc->backup); txn->cursors[i] = mc->next; mc->next = mc; - if (unbind) { - be_poor(mc); - mc->signature = cur_signature_ready4dispose; - } else { + mc->signature = cur_signature_ready4dispose; + cursor_drown((cursor_couple_t *)mc); + if (!unbind) { mc->signature = 0; osal_free(mc); } diff --git a/src/cursor.c b/src/cursor.c index bf12cd66..73da6a8b 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -218,7 +218,6 @@ int cursor_shadow(MDBX_cursor *mc, MDBX_txn *nested, const size_t dbi) { MDBX_cursor *cursor_eot(MDBX_cursor *mc, MDBX_txn *txn, const bool merge) { MDBX_cursor *const next = mc->next; - mc->next = mc; const unsigned stage = mc->signature; MDBX_cursor *const bk = mc->backup; ENSURE(txn->env, stage == cur_signature_live || (stage == cur_signature_wait4eot && bk)); @@ -253,6 +252,8 @@ MDBX_cursor *cursor_eot(MDBX_cursor *mc, MDBX_txn *txn, const bool merge) { osal_free(bk); } else { ENSURE(mc->txn->env, stage == cur_signature_live); + cursor_drown((cursor_couple_t *)mc); + mc->next = mc; mc->signature = cur_signature_ready4dispose /* Cursor may be reused */; } return next; diff --git a/src/cursor.h b/src/cursor.h index cfaca52e..d06bad3a 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -355,3 +355,19 @@ MDBX_MAYBE_UNUSED static inline void cursor_inner_refresh(const MDBX_cursor *mc, } MDBX_MAYBE_UNUSED MDBX_INTERNAL bool cursor_is_tracked(const MDBX_cursor *mc); + +static inline void cursor_reset(cursor_couple_t *couple) { + couple->outer.top_and_flags = z_fresh_mark; + couple->inner.cursor.top_and_flags = z_fresh_mark | z_inner; +} + +static inline void cursor_drown(cursor_couple_t *couple) { + couple->outer.top_and_flags = z_poor_mark; + couple->inner.cursor.top_and_flags = z_poor_mark | z_inner; + couple->outer.txn = nullptr; + couple->inner.cursor.txn = nullptr; + couple->outer.tree = nullptr; + /* сохраняем clc-указатель, так он используется для вычисления dbi в mdbx_cursor_renew(). */ + couple->outer.dbi_state = nullptr; + couple->inner.cursor.dbi_state = nullptr; +}