mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-19 19:18:20 +08:00
mdbx: рефакторинг txn_renew()
транзакций с вычленением txn_basal_start()
.
This commit is contained in:
parent
314b8ce1f0
commit
2c3b36da64
39
src/proto.h
39
src/proto.h
@ -39,16 +39,6 @@ static inline void dxb_sanitize_tail(MDBX_env *env, MDBX_txn *txn) {
|
||||
#endif /* ENABLE_MEMCHECK || __SANITIZE_ADDRESS__ */
|
||||
|
||||
/* txn.c */
|
||||
MDBX_INTERNAL bool txn_refund(MDBX_txn *txn);
|
||||
MDBX_INTERNAL txnid_t txn_snapshot_oldest(const MDBX_txn *const txn);
|
||||
MDBX_INTERNAL int txn_abort(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_renew(MDBX_txn *txn, unsigned flags);
|
||||
MDBX_INTERNAL int txn_ro_park(MDBX_txn *txn, bool autounpark);
|
||||
MDBX_INTERNAL int txn_ro_unpark(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_check_badbits_parked(const MDBX_txn *txn, int bad_bits);
|
||||
MDBX_INTERNAL void txn_done_cursors(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_shadow_cursors(const MDBX_txn *parent, const size_t dbi);
|
||||
|
||||
#define TXN_END_NAMES \
|
||||
{"committed", "pure-commit", "abort", "reset", "fail-begin", "fail-begin-nested", "ousted", nullptr}
|
||||
enum {
|
||||
@ -66,21 +56,36 @@ enum {
|
||||
TXN_END_FREE = 0x20 /* free txn unless it is env.basal_txn */,
|
||||
TXN_END_SLOT = 0x40 /* release any reader slot if NOSTICKYTHREADS */
|
||||
};
|
||||
MDBX_INTERNAL int txn_end(MDBX_txn *txn, unsigned mode);
|
||||
MDBX_INTERNAL MDBX_txn *txn_alloc(const MDBX_txn_flags_t flags, MDBX_env *env);
|
||||
MDBX_INTERNAL MDBX_txn *txn_basal_create(const size_t max_dbi);
|
||||
MDBX_INTERNAL void txn_basal_destroy(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_nested_create(MDBX_txn *parent, const MDBX_txn_flags_t flags);
|
||||
MDBX_INTERNAL void txn_nested_abort(MDBX_txn *nested);
|
||||
|
||||
struct commit_timestamp {
|
||||
uint64_t start, prep, gc, audit, write, sync, gc_cpu;
|
||||
};
|
||||
|
||||
MDBX_INTERNAL bool txn_refund(MDBX_txn *txn);
|
||||
MDBX_INTERNAL txnid_t txn_snapshot_oldest(const MDBX_txn *const txn);
|
||||
MDBX_INTERNAL int txn_check_badbits_parked(const MDBX_txn *txn, int bad_bits);
|
||||
MDBX_INTERNAL void txn_done_cursors(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_shadow_cursors(const MDBX_txn *parent, const size_t dbi);
|
||||
|
||||
MDBX_INTERNAL MDBX_txn *txn_alloc(const MDBX_txn_flags_t flags, MDBX_env *env);
|
||||
MDBX_INTERNAL int txn_abort(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_renew(MDBX_txn *txn, unsigned flags);
|
||||
MDBX_INTERNAL int txn_end(MDBX_txn *txn, unsigned mode);
|
||||
|
||||
MDBX_INTERNAL int txn_nested_create(MDBX_txn *parent, const MDBX_txn_flags_t flags);
|
||||
MDBX_INTERNAL void txn_nested_abort(MDBX_txn *nested);
|
||||
MDBX_INTERNAL int txn_nested_join(MDBX_txn *txn, struct commit_timestamp *ts);
|
||||
|
||||
MDBX_INTERNAL MDBX_txn *txn_basal_create(const size_t max_dbi);
|
||||
MDBX_INTERNAL void txn_basal_destroy(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_basal_start(MDBX_txn *txn, unsigned flags);
|
||||
MDBX_INTERNAL int txn_basal_commit(MDBX_txn *txn, struct commit_timestamp *ts);
|
||||
MDBX_INTERNAL int txn_basal_end(MDBX_txn *txn, unsigned mode);
|
||||
MDBX_INTERNAL int txn_ro_end(MDBX_txn *txn, unsigned mode);
|
||||
|
||||
MDBX_INTERNAL int txn_ro_park(MDBX_txn *txn, bool autounpark);
|
||||
MDBX_INTERNAL int txn_ro_unpark(MDBX_txn *txn);
|
||||
MDBX_INTERNAL int txn_ro_start(MDBX_txn *txn, unsigned flags);
|
||||
MDBX_INTERNAL int txn_ro_end(MDBX_txn *txn, unsigned mode);
|
||||
|
||||
/* env.c */
|
||||
MDBX_INTERNAL int env_open(MDBX_env *env, mdbx_mode_t mode);
|
||||
|
@ -89,6 +89,47 @@ __cold void txn_basal_destroy(MDBX_txn *txn) {
|
||||
osal_free(txn);
|
||||
}
|
||||
|
||||
int txn_basal_start(MDBX_txn *txn, unsigned flags) {
|
||||
MDBX_env *const env = txn->env;
|
||||
|
||||
txn->wr.troika = meta_tap(env);
|
||||
const meta_ptr_t head = meta_recent(env, &txn->wr.troika);
|
||||
uint64_t timestamp = 0;
|
||||
while ("workaround for https://libmdbx.dqdkfa.ru/dead-github/issues/269") {
|
||||
int err = coherency_fetch_head(txn, head, ×tamp);
|
||||
if (likely(err == MDBX_SUCCESS))
|
||||
break;
|
||||
if (unlikely(err != MDBX_RESULT_TRUE))
|
||||
return err;
|
||||
}
|
||||
eASSERT(env, meta_txnid(head.ptr_v) == txn->txnid);
|
||||
txn->txnid = safe64_txnid_next(txn->txnid);
|
||||
if (unlikely(txn->txnid > MAX_TXNID)) {
|
||||
ERROR("txnid overflow, raise %d", MDBX_TXN_FULL);
|
||||
return MDBX_TXN_FULL;
|
||||
}
|
||||
|
||||
tASSERT(txn, txn->dbs[FREE_DBI].flags == MDBX_INTEGERKEY);
|
||||
tASSERT(txn, check_table_flags(txn->dbs[MAIN_DBI].flags));
|
||||
txn->flags = flags;
|
||||
txn->nested = nullptr;
|
||||
txn->wr.loose_pages = nullptr;
|
||||
txn->wr.loose_count = 0;
|
||||
#if MDBX_ENABLE_REFUND
|
||||
txn->wr.loose_refund_wl = 0;
|
||||
#endif /* MDBX_ENABLE_REFUND */
|
||||
MDBX_PNL_SETSIZE(txn->wr.retired_pages, 0);
|
||||
txn->wr.spilled.list = nullptr;
|
||||
txn->wr.spilled.least_removed = 0;
|
||||
txn->wr.gc.time_acc = 0;
|
||||
txn->wr.gc.last_reclaimed = 0;
|
||||
if (txn->wr.gc.retxl)
|
||||
MDBX_PNL_SETSIZE(txn->wr.gc.retxl, 0);
|
||||
env->txn = txn;
|
||||
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
int txn_basal_end(MDBX_txn *txn, unsigned mode) {
|
||||
MDBX_env *const env = txn->env;
|
||||
tASSERT(txn, (txn->flags & (MDBX_TXN_FINISHED | txn_may_have_cursors)) == 0 && txn->owner);
|
||||
|
63
src/txn.c
63
src/txn.c
@ -70,6 +70,19 @@ int txn_abort(MDBX_txn *txn) {
|
||||
return txn_end(txn, TXN_END_ABORT | TXN_END_SLOT | TXN_END_FREE);
|
||||
}
|
||||
|
||||
static bool txn_check_overlapped(lck_t *const lck, const uint32_t pid, const uintptr_t tid) {
|
||||
const size_t snap_nreaders = atomic_load32(&lck->rdt_length, mo_AcquireRelease);
|
||||
for (size_t i = 0; i < snap_nreaders; ++i) {
|
||||
if (atomic_load32(&lck->rdt[i].pid, mo_Relaxed) == pid &&
|
||||
unlikely(atomic_load64(&lck->rdt[i].tid, mo_Relaxed) == tid)) {
|
||||
const txnid_t txnid = safe64_read(&lck->rdt[i].txnid);
|
||||
if (txnid >= MIN_TXNID && txnid <= MAX_TXNID)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int txn_renew(MDBX_txn *txn, unsigned flags) {
|
||||
MDBX_env *const env = txn->env;
|
||||
int rc;
|
||||
@ -90,17 +103,9 @@ int txn_renew(MDBX_txn *txn, unsigned flags) {
|
||||
/* not recovery mode */ env->stuck_meta >= 0))
|
||||
return MDBX_BUSY;
|
||||
lck_t *const lck = env->lck_mmap.lck;
|
||||
if (lck && (env->flags & MDBX_NOSTICKYTHREADS) == 0 && (globals.runtime_flags & MDBX_DBG_LEGACY_OVERLAP) == 0) {
|
||||
const size_t snap_nreaders = atomic_load32(&lck->rdt_length, mo_AcquireRelease);
|
||||
for (size_t i = 0; i < snap_nreaders; ++i) {
|
||||
if (atomic_load32(&lck->rdt[i].pid, mo_Relaxed) == env->pid &&
|
||||
unlikely(atomic_load64(&lck->rdt[i].tid, mo_Relaxed) == tid)) {
|
||||
const txnid_t txnid = safe64_read(&lck->rdt[i].txnid);
|
||||
if (txnid >= MIN_TXNID && txnid <= MAX_TXNID)
|
||||
return MDBX_TXN_OVERLAPPING;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lck && !(env->flags & MDBX_NOSTICKYTHREADS) && !(globals.runtime_flags & MDBX_DBG_LEGACY_OVERLAP) &&
|
||||
txn_check_overlapped(lck, env->pid, tid))
|
||||
return MDBX_TXN_OVERLAPPING;
|
||||
|
||||
/* Not yet touching txn == env->basal_txn, it may be active */
|
||||
jitter4testing(false);
|
||||
@ -118,41 +123,9 @@ int txn_renew(MDBX_txn *txn, unsigned flags) {
|
||||
}
|
||||
#endif /* Windows */
|
||||
|
||||
txn->wr.troika = meta_tap(env);
|
||||
const meta_ptr_t head = meta_recent(env, &txn->wr.troika);
|
||||
uint64_t timestamp = 0;
|
||||
while ("workaround for https://libmdbx.dqdkfa.ru/dead-github/issues/269") {
|
||||
rc = coherency_fetch_head(txn, head, ×tamp);
|
||||
if (likely(rc == MDBX_SUCCESS))
|
||||
break;
|
||||
if (unlikely(rc != MDBX_RESULT_TRUE))
|
||||
goto bailout;
|
||||
}
|
||||
eASSERT(env, meta_txnid(head.ptr_v) == txn->txnid);
|
||||
txn->txnid = safe64_txnid_next(txn->txnid);
|
||||
if (unlikely(txn->txnid > MAX_TXNID)) {
|
||||
rc = MDBX_TXN_FULL;
|
||||
ERROR("txnid overflow, raise %d", rc);
|
||||
rc = txn_basal_start(txn, flags);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
tASSERT(txn, txn->dbs[FREE_DBI].flags == MDBX_INTEGERKEY);
|
||||
tASSERT(txn, check_table_flags(txn->dbs[MAIN_DBI].flags));
|
||||
txn->flags = flags;
|
||||
txn->nested = nullptr;
|
||||
txn->wr.loose_pages = nullptr;
|
||||
txn->wr.loose_count = 0;
|
||||
#if MDBX_ENABLE_REFUND
|
||||
txn->wr.loose_refund_wl = 0;
|
||||
#endif /* MDBX_ENABLE_REFUND */
|
||||
MDBX_PNL_SETSIZE(txn->wr.retired_pages, 0);
|
||||
txn->wr.spilled.list = nullptr;
|
||||
txn->wr.spilled.least_removed = 0;
|
||||
txn->wr.gc.time_acc = 0;
|
||||
txn->wr.gc.last_reclaimed = 0;
|
||||
if (txn->wr.gc.retxl)
|
||||
MDBX_PNL_SETSIZE(txn->wr.gc.retxl, 0);
|
||||
env->txn = txn;
|
||||
}
|
||||
|
||||
txn->front_txnid = txn->txnid + ((flags & (MDBX_WRITEMAP | MDBX_RDONLY)) == 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user