diff --git a/src/cursor.c b/src/cursor.c index 4667652e..bf12cd66 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -216,17 +216,21 @@ int cursor_shadow(MDBX_cursor *mc, MDBX_txn *nested, const size_t dbi) { return MDBX_SUCCESS; } -void cursor_eot(MDBX_cursor *mc, const bool merge) { +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(mc->txn->env, stage == cur_signature_live || (stage == cur_signature_wait4eot && bk)); + ENSURE(txn->env, stage == cur_signature_live || (stage == cur_signature_wait4eot && bk)); + tASSERT(txn, mc->txn == txn); if (bk) { subcur_t *mx = mc->subcur; - cASSERT(mc, mc->txn->parent != nullptr); + tASSERT(txn, mc->txn->parent != nullptr); + tASSERT(txn, bk->txn == txn->parent); /* Zap: Using uninitialized memory '*mc->backup'. */ MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6001); ENSURE(mc->txn->env, bk->signature == cur_signature_live); - cASSERT(mc, mx == bk->subcur); + tASSERT(txn, mx == bk->subcur); if (merge) { /* Update pointers to parent txn */ mc->next = bk->next; @@ -235,24 +239,23 @@ void cursor_eot(MDBX_cursor *mc, const bool merge) { mc->tree = bk->tree; mc->dbi_state = bk->dbi_state; if (mx) { - mx->cursor.txn = mc->txn; - mx->cursor.dbi_state = mc->dbi_state; + mx->cursor.txn = bk->txn; + mx->cursor.dbi_state = bk->dbi_state; } } else { /* Restore from backup, i.e. rollback/abort nested txn */ *mc = *bk; + mc->signature = stage /* Promote (cur_signature_wait4eot) state to parent txn */; if (mx) *mx = *(subcur_t *)(bk + 1); } - if (stage == cur_signature_wait4eot /* Cursor was closed by user */) - mc->signature = stage /* Promote closed state to parent txn */; bk->signature = 0; osal_free(bk); } else { ENSURE(mc->txn->env, stage == cur_signature_live); mc->signature = cur_signature_ready4dispose /* Cursor may be reused */; - mc->next = mc; } + return next; } /*----------------------------------------------------------------------------*/ diff --git a/src/cursor.h b/src/cursor.h index 6d984084..cfaca52e 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -292,7 +292,7 @@ MDBX_NOTHROW_PURE_FUNCTION static inline bool check_leaf_type(const MDBX_cursor return (((page_type(mp) ^ mc->checking) & (z_branch | z_leaf | z_largepage | z_dupfix)) == 0); } -MDBX_INTERNAL void cursor_eot(MDBX_cursor *mc, const bool merge); +MDBX_INTERNAL MDBX_cursor *cursor_eot(MDBX_cursor *mc, MDBX_txn *txn, const bool merge); MDBX_INTERNAL int cursor_shadow(MDBX_cursor *mc, MDBX_txn *nested, const size_t dbi); MDBX_INTERNAL MDBX_cursor *cursor_cpstk(const MDBX_cursor *csrc, MDBX_cursor *cdst); diff --git a/src/dbi.h b/src/dbi.h index e9b16efe..2dffd5f7 100644 --- a/src/dbi.h +++ b/src/dbi.h @@ -101,7 +101,7 @@ static inline bool dbi_changed(const MDBX_txn *txn, const size_t dbi) { const MDBX_env *const env = txn->env; eASSERT(env, dbi_state(txn, dbi) & DBI_LINDO); const uint32_t snap_seq = atomic_load32(&env->dbi_seqs[dbi], mo_AcquireRelease); - return snap_seq != txn->dbi_seqs[dbi]; + return unlikely(snap_seq != txn->dbi_seqs[dbi]); } static inline int dbi_check(const MDBX_txn *txn, const size_t dbi) { diff --git a/src/txn.c b/src/txn.c index eb198965..a83cd9c8 100644 --- a/src/txn.c +++ b/src/txn.c @@ -13,11 +13,9 @@ void txn_done_cursors(MDBX_txn *txn, const bool merge) { MDBX_cursor *mc = txn->cursors[i]; if (mc) { txn->cursors[i] = nullptr; - do { - MDBX_cursor *const next = mc->next; - cursor_eot(mc, merge); - mc = next; - } while (mc); + do + mc = cursor_eot(mc, txn, merge); + while (mc); } } }