mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 03:34:12 +08:00
mdbx: refine & rename internal xyz
to troika
.
This commit is contained in:
parent
b759dfafd7
commit
b617f25eaa
266
src/core.c
266
src/core.c
@ -3125,7 +3125,7 @@ static int __must_check_result read_header(MDBX_env *env, MDBX_meta *meta,
|
||||
const mdbx_mode_t mode_bits);
|
||||
static int __must_check_result sync_locked(MDBX_env *env, unsigned flags,
|
||||
MDBX_meta *const pending,
|
||||
meta_xyz_t *const xyz);
|
||||
meta_troika_t *const troika);
|
||||
static int env_close(MDBX_env *env);
|
||||
|
||||
struct node_result {
|
||||
@ -5057,10 +5057,9 @@ static __inline bool meta_choice_steady(txnid_t a_txnid, bool a_steady,
|
||||
return meta_cmp2steady(meta_cmp2int(a_txnid, b_txnid, 1), a_steady, b_steady);
|
||||
}
|
||||
|
||||
MDBX_MAYBE_UNUSED static __inline uint8_t meta_cmp2pack(uint8_t c01,
|
||||
uint8_t c02,
|
||||
uint8_t c12, bool s0,
|
||||
bool s1, bool s2) {
|
||||
MDBX_MAYBE_UNUSED static uint8_t meta_cmp2pack(uint8_t c01, uint8_t c02,
|
||||
uint8_t c12, bool s0, bool s1,
|
||||
bool s2) {
|
||||
assert(c01 < 3 && c02 < 3 && c12 < 3);
|
||||
/* assert(s0 < 2 && s1 < 2 && s2 < 2); */
|
||||
const uint8_t recent = meta_cmp2recent(c01, s0, s1)
|
||||
@ -5085,7 +5084,14 @@ MDBX_MAYBE_UNUSED static __inline uint8_t meta_cmp2pack(uint8_t c01,
|
||||
return tail | recent << 2 | prefer_steady << 4 | strict << 6 | valid << 7;
|
||||
}
|
||||
|
||||
static const uint8_t xyz_fsm_map[2 * 2 * 2 * 3 * 3 * 3] = {
|
||||
static __inline void meta_troika_unpack(meta_troika_t *troika,
|
||||
const uint8_t packed) {
|
||||
troika->recent = (packed >> 2) & 3;
|
||||
troika->prefer_steady = (packed >> 4) & 3;
|
||||
troika->tail_and_flags = packed & 0xC3;
|
||||
}
|
||||
|
||||
static const uint8_t troika_fsm_map[2 * 2 * 2 * 3 * 3 * 3] = {
|
||||
232, 201, 216, 216, 232, 233, 232, 232, 168, 201, 216, 152, 168, 233, 232,
|
||||
168, 233, 201, 216, 201, 233, 233, 232, 233, 168, 201, 152, 216, 232, 169,
|
||||
232, 168, 168, 193, 152, 152, 168, 169, 232, 168, 169, 193, 152, 194, 233,
|
||||
@ -5102,27 +5108,24 @@ static const uint8_t xyz_fsm_map[2 * 2 * 2 * 3 * 3 * 3] = {
|
||||
214, 228, 198, 212, 214, 150, 194, 214, 150, 164, 193, 212, 150, 194, 194,
|
||||
210, 194, 225, 193, 210, 194};
|
||||
|
||||
__hot static meta_xyz_t meta_tap(const MDBX_env *env) {
|
||||
__hot static meta_troika_t meta_tap(const MDBX_env *env) {
|
||||
meta_snap_t snap;
|
||||
meta_xyz_t r;
|
||||
meta_troika_t troika;
|
||||
snap = meta_snap(METAPAGE(env, 0));
|
||||
r.txnid[0] = snap.txnid;
|
||||
r.fsm = (uint8_t)snap.is_steady << 0;
|
||||
troika.txnid[0] = snap.txnid;
|
||||
troika.fsm = (uint8_t)snap.is_steady << 0;
|
||||
snap = meta_snap(METAPAGE(env, 1));
|
||||
r.txnid[1] = snap.txnid;
|
||||
r.fsm += (uint8_t)snap.is_steady << 1;
|
||||
r.fsm += meta_cmp2int(r.txnid[0], r.txnid[1], 8);
|
||||
troika.txnid[1] = snap.txnid;
|
||||
troika.fsm += (uint8_t)snap.is_steady << 1;
|
||||
troika.fsm += meta_cmp2int(troika.txnid[0], troika.txnid[1], 8);
|
||||
snap = meta_snap(METAPAGE(env, 2));
|
||||
r.txnid[2] = snap.txnid;
|
||||
r.fsm += (uint8_t)snap.is_steady << 2;
|
||||
r.fsm += meta_cmp2int(r.txnid[0], r.txnid[2], 8 * 3);
|
||||
r.fsm += meta_cmp2int(r.txnid[1], r.txnid[2], 8 * 3 * 3);
|
||||
troika.txnid[2] = snap.txnid;
|
||||
troika.fsm += (uint8_t)snap.is_steady << 2;
|
||||
troika.fsm += meta_cmp2int(troika.txnid[0], troika.txnid[2], 8 * 3);
|
||||
troika.fsm += meta_cmp2int(troika.txnid[1], troika.txnid[2], 8 * 3 * 3);
|
||||
|
||||
const uint8_t xyz = xyz_fsm_map[r.fsm];
|
||||
r.recent = (xyz >> 2) & 3;
|
||||
r.prefer_steady = (xyz >> 4) & 3;
|
||||
r.tail_and_flags = xyz & 0xC3;
|
||||
return r;
|
||||
meta_troika_unpack(&troika, troika_fsm_map[troika.fsm]);
|
||||
return troika;
|
||||
}
|
||||
|
||||
static txnid_t recent_committed_txnid(const MDBX_env *env) {
|
||||
@ -5132,47 +5135,51 @@ static txnid_t recent_committed_txnid(const MDBX_env *env) {
|
||||
return (m0 > m1) ? ((m0 > m2) ? m0 : m2) : ((m1 > m2) ? m1 : m2);
|
||||
}
|
||||
|
||||
static __inline bool meta_eq(const meta_xyz_t *z, unsigned y, unsigned x) {
|
||||
assert(y < NUM_METAS && x < NUM_METAS);
|
||||
return z->txnid[y] == z->txnid[x] && !(((z->fsm >> y) ^ (z->fsm >> x)) & 1);
|
||||
static __inline bool meta_eq(const meta_troika_t *troika, unsigned a,
|
||||
unsigned b) {
|
||||
assert(a < NUM_METAS && b < NUM_METAS);
|
||||
return troika->txnid[a] == troika->txnid[b] &&
|
||||
(((troika->fsm >> a) ^ (troika->fsm >> b)) & 1) == 0;
|
||||
}
|
||||
|
||||
static unsigned meta_eq_mask(const meta_xyz_t *xyz) {
|
||||
return meta_eq(xyz, 0, 1) | meta_eq(xyz, 1, 2) << 1 | meta_eq(xyz, 2, 0) << 2;
|
||||
static unsigned meta_eq_mask(const meta_troika_t *troika) {
|
||||
return meta_eq(troika, 0, 1) | meta_eq(troika, 1, 2) << 1 |
|
||||
meta_eq(troika, 2, 0) << 2;
|
||||
}
|
||||
|
||||
__hot static bool meta_should_retry(const MDBX_env *env, meta_xyz_t *xyz) {
|
||||
const meta_xyz_t prev = *xyz;
|
||||
*xyz = meta_tap(env);
|
||||
return prev.fsm != xyz->fsm || prev.txnid[0] != xyz->txnid[0] ||
|
||||
prev.txnid[1] != xyz->txnid[1] || prev.txnid[2] != xyz->txnid[2];
|
||||
__hot static bool meta_should_retry(const MDBX_env *env,
|
||||
meta_troika_t *troika) {
|
||||
const meta_troika_t prev = *troika;
|
||||
*troika = meta_tap(env);
|
||||
return prev.fsm != troika->fsm || prev.txnid[0] != troika->txnid[0] ||
|
||||
prev.txnid[1] != troika->txnid[1] || prev.txnid[2] != troika->txnid[2];
|
||||
}
|
||||
|
||||
static __always_inline meta_ptr_t meta_recent(const MDBX_env *env,
|
||||
const meta_xyz_t *xyz) {
|
||||
const meta_troika_t *troika) {
|
||||
meta_ptr_t r;
|
||||
r.txnid = xyz->txnid[xyz->recent];
|
||||
r.ptr_v = METAPAGE(env, xyz->recent);
|
||||
r.is_steady = (xyz->fsm >> xyz->recent) & 1;
|
||||
r.txnid = troika->txnid[troika->recent];
|
||||
r.ptr_v = METAPAGE(env, troika->recent);
|
||||
r.is_steady = (troika->fsm >> troika->recent) & 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
static __always_inline meta_ptr_t meta_prefer_steady(const MDBX_env *env,
|
||||
const meta_xyz_t *xyz) {
|
||||
static __always_inline meta_ptr_t
|
||||
meta_prefer_steady(const MDBX_env *env, const meta_troika_t *troika) {
|
||||
meta_ptr_t r;
|
||||
r.txnid = xyz->txnid[xyz->prefer_steady];
|
||||
r.ptr_v = METAPAGE(env, xyz->prefer_steady);
|
||||
r.is_steady = (xyz->fsm >> xyz->prefer_steady) & 1;
|
||||
r.txnid = troika->txnid[troika->prefer_steady];
|
||||
r.ptr_v = METAPAGE(env, troika->prefer_steady);
|
||||
r.is_steady = (troika->fsm >> troika->prefer_steady) & 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
static __always_inline meta_ptr_t meta_tail(const MDBX_env *env,
|
||||
const meta_xyz_t *xyz) {
|
||||
const uint8_t tail = xyz->tail_and_flags & 3;
|
||||
const meta_troika_t *troika) {
|
||||
const uint8_t tail = troika->tail_and_flags & 3;
|
||||
meta_ptr_t r;
|
||||
r.txnid = xyz->txnid[tail];
|
||||
r.txnid = troika->txnid[tail];
|
||||
r.ptr_v = METAPAGE(env, tail);
|
||||
r.is_steady = (xyz->fsm >> tail) & 1;
|
||||
r.is_steady = (troika->fsm >> tail) & 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -5250,7 +5257,7 @@ static txnid_t find_oldest_reader(MDBX_env *const env, const txnid_t steady) {
|
||||
|
||||
static txnid_t txn_oldest_reader(const MDBX_txn *const txn) {
|
||||
return find_oldest_reader(txn->mt_env,
|
||||
txn->tw.xyz.txnid[txn->tw.xyz.prefer_steady]);
|
||||
txn->tw.troika.txnid[txn->tw.troika.prefer_steady]);
|
||||
}
|
||||
|
||||
/* Find largest mvcc-snapshot still referenced. */
|
||||
@ -5775,10 +5782,10 @@ __cold static int wipe_steady(MDBX_txn *txn, const txnid_t last_steady) {
|
||||
/* force oldest refresh */
|
||||
atomic_store32(&env->me_lck->mti_readers_refresh_flag, true, mo_Relaxed);
|
||||
tASSERT(txn, (txn->mt_flags & MDBX_TXN_RDONLY) == 0);
|
||||
txn->tw.xyz = meta_tap(env);
|
||||
txn->tw.troika = meta_tap(env);
|
||||
for (MDBX_txn *scan = txn->mt_env->me_txn0; scan; scan = scan->mt_child)
|
||||
if (scan != txn)
|
||||
scan->tw.xyz = txn->tw.xyz;
|
||||
scan->tw.troika = txn->tw.troika;
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
@ -6541,8 +6548,8 @@ static pgr_t page_alloc_slowpath(MDBX_cursor *mc, const pgno_t num, int flags) {
|
||||
const size_t next = (size_t)pgno + num;
|
||||
|
||||
if (flags & MDBX_ALLOC_GC) {
|
||||
const meta_ptr_t recent = meta_recent(env, &txn->tw.xyz);
|
||||
const meta_ptr_t prefer_steady = meta_prefer_steady(env, &txn->tw.xyz);
|
||||
const meta_ptr_t recent = meta_recent(env, &txn->tw.troika);
|
||||
const meta_ptr_t prefer_steady = meta_prefer_steady(env, &txn->tw.troika);
|
||||
/* does reclaiming stopped at the last steady point? */
|
||||
if (recent.ptr_c != prefer_steady.ptr_c && prefer_steady.is_steady &&
|
||||
detent == prefer_steady.txnid + 1) {
|
||||
@ -6571,7 +6578,7 @@ static pgr_t page_alloc_slowpath(MDBX_cursor *mc, const pgno_t num, int flags) {
|
||||
ret.err = wipe_steady(txn, detent);
|
||||
DEBUG("gc-wipe-steady, rc %d", ret.err);
|
||||
eASSERT(env, prefer_steady.ptr_c !=
|
||||
meta_prefer_steady(env, &txn->tw.xyz).ptr_c);
|
||||
meta_prefer_steady(env, &txn->tw.troika).ptr_c);
|
||||
} else if ((flags & MDBX_ALLOC_NEW) == 0 ||
|
||||
(autosync_threshold &&
|
||||
atomic_load32(&env->me_lck->mti_unsynced_pages,
|
||||
@ -6587,10 +6594,10 @@ static pgr_t page_alloc_slowpath(MDBX_cursor *mc, const pgno_t num, int flags) {
|
||||
/* make steady checkpoint. */
|
||||
MDBX_meta meta = *recent.ptr_c;
|
||||
ret.err = sync_locked(env, env->me_flags & MDBX_WRITEMAP, &meta,
|
||||
&txn->tw.xyz);
|
||||
&txn->tw.troika);
|
||||
DEBUG("gc-make-steady, rc %d", ret.err);
|
||||
eASSERT(env, prefer_steady.ptr_c !=
|
||||
meta_prefer_steady(env, &txn->tw.xyz).ptr_c);
|
||||
meta_prefer_steady(env, &txn->tw.troika).ptr_c);
|
||||
}
|
||||
if (likely(ret.err != MDBX_RESULT_TRUE)) {
|
||||
if (unlikely(ret.err != MDBX_SUCCESS))
|
||||
@ -7033,10 +7040,10 @@ retry:;
|
||||
const bool inside_txn = (env->me_txn0->mt_owner == osal_thread_self());
|
||||
meta_ptr_t head;
|
||||
if (inside_txn | locked)
|
||||
head = meta_recent(env, &env->me_txn0->tw.xyz);
|
||||
head = meta_recent(env, &env->me_txn0->tw.troika);
|
||||
else {
|
||||
const meta_xyz_t xyz = meta_tap(env);
|
||||
head = meta_recent(env, &xyz);
|
||||
const meta_troika_t troika = meta_tap(env);
|
||||
head = meta_recent(env, &troika);
|
||||
}
|
||||
const pgno_t unsynced_pages =
|
||||
atomic_load32(&env->me_lck->mti_unsynced_pages, mo_Relaxed);
|
||||
@ -7109,7 +7116,7 @@ retry:;
|
||||
#if MDBX_ENABLE_PGOP_STAT
|
||||
env->me_lck->mti_pgop_stat.wops.weak += wops;
|
||||
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||
env->me_txn0->tw.xyz = meta_tap(env);
|
||||
env->me_txn0->tw.troika = meta_tap(env);
|
||||
eASSERT(env, !env->me_txn && !env->me_txn0->mt_child);
|
||||
goto retry;
|
||||
}
|
||||
@ -7127,7 +7134,7 @@ retry:;
|
||||
data_page(head.ptr_c)->mp_pgno, durable_caption(head.ptr_c),
|
||||
unsynced_pages);
|
||||
MDBX_meta meta = *head.ptr_c;
|
||||
rc = sync_locked(env, flags, &meta, &env->me_txn0->tw.xyz);
|
||||
rc = sync_locked(env, flags, &meta, &env->me_txn0->tw.troika);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
}
|
||||
@ -7344,7 +7351,7 @@ static void txn_valgrind(MDBX_env *env, MDBX_txn *txn) {
|
||||
pgno_t last = MAX_PAGENO + 1;
|
||||
if (env->me_txn0 && env->me_txn0->mt_owner == osal_thread_self()) {
|
||||
/* inside write-txn */
|
||||
last = meta_recent(env, &env->me_txn0->xyz).ptr_v->mm_geo.next;
|
||||
last = meta_recent(env, &env->me_txn0->troika).ptr_v->mm_geo.next;
|
||||
} else if (env->me_flags & MDBX_RDONLY) {
|
||||
/* read-only mode, no write-txn, no wlock mutex */
|
||||
last = NUM_METAS;
|
||||
@ -7721,11 +7728,11 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
|
||||
/* Seek & fetch the last meta */
|
||||
uint64_t timestamp = 0;
|
||||
unsigned loop = 0;
|
||||
meta_xyz_t xyz = meta_tap(env);
|
||||
meta_troika_t troika = meta_tap(env);
|
||||
while (1) {
|
||||
const meta_ptr_t head =
|
||||
likely(env->me_stuck_meta < 0)
|
||||
? /* regular */ meta_recent(env, &xyz)
|
||||
? /* regular */ meta_recent(env, &troika)
|
||||
: /* recovery mode */ meta_ptr(env, env->me_stuck_meta);
|
||||
if (likely(r)) {
|
||||
safe64_reset(&r->mr_txnid, false);
|
||||
@ -7760,7 +7767,7 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
|
||||
|
||||
if (unlikely(env->me_stuck_meta >= 0))
|
||||
break;
|
||||
if (unlikely(meta_should_retry(env, &xyz) ||
|
||||
if (unlikely(meta_should_retry(env, &troika) ||
|
||||
head.txnid < atomic_load64(&env->me_lck->mti_oldest_reader,
|
||||
mo_AcquireRelease))) {
|
||||
if (unlikely(++loop > 42)) {
|
||||
@ -7843,8 +7850,8 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
|
||||
}
|
||||
#endif /* Windows */
|
||||
|
||||
txn->tw.xyz = meta_tap(env);
|
||||
const meta_ptr_t head = meta_recent(env, &txn->tw.xyz);
|
||||
txn->tw.troika = meta_tap(env);
|
||||
const meta_ptr_t head = meta_recent(env, &txn->tw.troika);
|
||||
uint64_t timestamp = 0;
|
||||
while (
|
||||
"workaround for todo4recovery://erased_by_github/libmdbx/issues/269") {
|
||||
@ -8197,7 +8204,7 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags,
|
||||
txn->mt_numdbs = parent->mt_numdbs;
|
||||
txn->mt_owner = parent->mt_owner;
|
||||
memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db));
|
||||
txn->tw.xyz = parent->tw.xyz;
|
||||
txn->tw.troika = parent->tw.troika;
|
||||
/* Copy parent's mt_dbistate, but clear DB_NEW */
|
||||
for (unsigned i = 0; i < txn->mt_numdbs; i++)
|
||||
txn->mt_dbistate[i] =
|
||||
@ -8274,17 +8281,17 @@ int mdbx_txn_info(const MDBX_txn *txn, MDBX_txn_info *info, bool scan_rlt) {
|
||||
if (txn->mt_flags & MDBX_TXN_RDONLY) {
|
||||
meta_ptr_t head;
|
||||
uint64_t head_retired;
|
||||
meta_xyz_t xyz = meta_tap(env);
|
||||
meta_troika_t troika = meta_tap(env);
|
||||
do {
|
||||
/* fetch info from volatile head */
|
||||
head = meta_recent(env, &xyz);
|
||||
head = meta_recent(env, &troika);
|
||||
head_retired =
|
||||
unaligned_peek_u64_volatile(4, head.ptr_v->mm_pages_retired);
|
||||
info->txn_space_limit_soft = pgno2bytes(env, head.ptr_v->mm_geo.now);
|
||||
info->txn_space_limit_hard = pgno2bytes(env, head.ptr_v->mm_geo.upper);
|
||||
info->txn_space_leftover =
|
||||
pgno2bytes(env, head.ptr_v->mm_geo.now - head.ptr_v->mm_geo.next);
|
||||
} while (unlikely(meta_should_retry(env, &xyz)));
|
||||
} while (unlikely(meta_should_retry(env, &troika)));
|
||||
|
||||
info->txn_reader_lag = head.txnid - info->txn_id;
|
||||
info->txn_space_dirty = info->txn_space_retired = 0;
|
||||
@ -8672,8 +8679,8 @@ static int txn_end(MDBX_txn *txn, const unsigned mode) {
|
||||
(parent->mt_flags & MDBX_TXN_HAS_CHILD) != 0);
|
||||
eASSERT(env, pnl_check_allocated(txn->tw.reclaimed_pglist,
|
||||
txn->mt_next_pgno - MDBX_ENABLE_REFUND));
|
||||
eASSERT(env,
|
||||
memcmp(&txn->tw.xyz, &parent->tw.xyz, sizeof(meta_xyz_t)) == 0);
|
||||
eASSERT(env, memcmp(&txn->tw.troika, &parent->tw.troika,
|
||||
sizeof(meta_troika_t)) == 0);
|
||||
|
||||
if (txn->tw.lifo_reclaimed) {
|
||||
eASSERT(env, MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) >=
|
||||
@ -10530,7 +10537,7 @@ int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency) {
|
||||
ts_3 = latency ? osal_monotime() : 0;
|
||||
|
||||
if (likely(rc == MDBX_SUCCESS)) {
|
||||
const meta_ptr_t head = meta_recent(env, &txn->tw.xyz);
|
||||
const meta_ptr_t head = meta_recent(env, &txn->tw.troika);
|
||||
MDBX_meta meta;
|
||||
memcpy(meta.mm_magic_and_version, head.ptr_c->mm_magic_and_version, 8);
|
||||
meta.mm_extra_flags = head.ptr_c->mm_extra_flags;
|
||||
@ -10555,7 +10562,7 @@ int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency) {
|
||||
meta_set_txnid(env, &meta, commit_txnid);
|
||||
|
||||
rc = sync_locked(env, env->me_flags | txn->mt_flags | MDBX_SHRINK_ALLOWED,
|
||||
&meta, &txn->tw.xyz);
|
||||
&meta, &txn->tw.troika);
|
||||
}
|
||||
ts_4 = latency ? osal_monotime() : 0;
|
||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||
@ -11012,12 +11019,12 @@ static size_t madvise_threshold(const MDBX_env *env,
|
||||
#endif /* MDBX_ENABLE_MADVISE */
|
||||
|
||||
static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending,
|
||||
meta_xyz_t *const xyz) {
|
||||
meta_troika_t *const troika) {
|
||||
eASSERT(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0);
|
||||
const MDBX_meta *const meta0 = METAPAGE(env, 0);
|
||||
const MDBX_meta *const meta1 = METAPAGE(env, 1);
|
||||
const MDBX_meta *const meta2 = METAPAGE(env, 2);
|
||||
const meta_ptr_t head = meta_recent(env, xyz);
|
||||
const meta_ptr_t head = meta_recent(env, troika);
|
||||
int rc;
|
||||
|
||||
eASSERT(env,
|
||||
@ -11122,7 +11129,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending,
|
||||
const pgno_t bottom =
|
||||
(aligned > pending->mm_geo.lower) ? aligned : pending->mm_geo.lower;
|
||||
if (pending->mm_geo.now > bottom) {
|
||||
if (XYZ_HAVE_STEADY(xyz))
|
||||
if (TROIKA_HAVE_STEADY(troika))
|
||||
/* force steady, but only if steady-checkpoint is present */
|
||||
flags &= MDBX_WRITEMAP | MDBX_SHRINK_ALLOWED;
|
||||
shrink = pending->mm_geo.now - bottom;
|
||||
@ -11154,7 +11161,8 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending,
|
||||
enum osal_syncmode_bits mode_bits = MDBX_SYNC_NONE;
|
||||
if ((flags & MDBX_SAFE_NOSYNC) == 0) {
|
||||
mode_bits = MDBX_SYNC_DATA;
|
||||
if (pending->mm_geo.next > meta_prefer_steady(env, xyz).ptr_c->mm_geo.now)
|
||||
if (pending->mm_geo.next >
|
||||
meta_prefer_steady(env, troika).ptr_c->mm_geo.now)
|
||||
mode_bits |= MDBX_SYNC_SIZE;
|
||||
if (flags & MDBX_NOMETASYNC)
|
||||
mode_bits |= MDBX_SYNC_IODQ;
|
||||
@ -11204,10 +11212,10 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending,
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
const unsigned xyz_tail = xyz->tail_and_flags & 3;
|
||||
ENSURE(env, xyz_tail < NUM_METAS && xyz_tail != xyz->recent &&
|
||||
xyz_tail != xyz->prefer_steady);
|
||||
target = (MDBX_meta *)meta_tail(env, xyz).ptr_c;
|
||||
const unsigned troika_tail = troika->tail_and_flags & 3;
|
||||
ENSURE(env, troika_tail < NUM_METAS && troika_tail != troika->recent &&
|
||||
troika_tail != troika->prefer_steady);
|
||||
target = (MDBX_meta *)meta_tail(env, troika).ptr_c;
|
||||
}
|
||||
|
||||
/* LY: step#2 - update meta-page. */
|
||||
@ -11336,10 +11344,10 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending,
|
||||
(uint32_t)pending->unsafe_txnid -
|
||||
((flags & MDBX_NOMETASYNC) ? UINT32_MAX / 3 : 0);
|
||||
|
||||
*xyz = meta_tap(env);
|
||||
*troika = meta_tap(env);
|
||||
for (MDBX_txn *txn = env->me_txn0; txn; txn = txn->mt_child)
|
||||
if (xyz != &txn->tw.xyz)
|
||||
txn->tw.xyz = *xyz;
|
||||
if (troika != &txn->tw.troika)
|
||||
txn->tw.troika = *troika;
|
||||
|
||||
/* LY: shrink datafile if needed */
|
||||
if (unlikely(shrink)) {
|
||||
@ -11587,10 +11595,10 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
if (unlikely(err != MDBX_SUCCESS))
|
||||
return err;
|
||||
need_unlock = true;
|
||||
env->me_txn0->tw.xyz = meta_tap(env);
|
||||
env->me_txn0->tw.troika = meta_tap(env);
|
||||
eASSERT(env, !env->me_txn && !env->me_txn0->mt_child);
|
||||
env->me_txn0->mt_txnid =
|
||||
env->me_txn0->tw.xyz.txnid[env->me_txn0->tw.xyz.recent];
|
||||
env->me_txn0->tw.troika.txnid[env->me_txn0->tw.troika.recent];
|
||||
txn_oldest_reader(env->me_txn0);
|
||||
}
|
||||
|
||||
@ -11599,7 +11607,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
pagesize = env->me_psize;
|
||||
const MDBX_geo *const geo =
|
||||
inside_txn ? &env->me_txn->mt_geo
|
||||
: &meta_recent(env, &env->me_txn0->tw.xyz).ptr_c->mm_geo;
|
||||
: &meta_recent(env, &env->me_txn0->tw.troika).ptr_c->mm_geo;
|
||||
if (size_lower < 0)
|
||||
size_lower = pgno2bytes(env, geo->lower);
|
||||
if (size_now < 0)
|
||||
@ -11813,7 +11821,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
const MDBX_geo *current_geo;
|
||||
if (!inside_txn) {
|
||||
eASSERT(env, need_unlock);
|
||||
const meta_ptr_t head = meta_recent(env, &env->me_txn0->tw.xyz);
|
||||
const meta_ptr_t head = meta_recent(env, &env->me_txn0->tw.troika);
|
||||
|
||||
uint64_t timestamp = 0;
|
||||
while ("workaround for "
|
||||
@ -11909,7 +11917,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
env->me_txn->mt_flags |= MDBX_TXN_DIRTY;
|
||||
} else {
|
||||
meta.mm_geo = new_geo;
|
||||
rc = sync_locked(env, env->me_flags, &meta, &env->me_txn0->tw.xyz);
|
||||
rc = sync_locked(env, env->me_flags, &meta, &env->me_txn0->tw.troika);
|
||||
}
|
||||
|
||||
if (likely(rc == MDBX_SUCCESS)) {
|
||||
@ -12189,7 +12197,7 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
: env->me_dxb_mmap.limit);
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
|
||||
meta_xyz_t xyz = meta_tap(env);
|
||||
meta_troika_t troika = meta_tap(env);
|
||||
eASSERT(env, !env->me_txn && !env->me_txn0);
|
||||
//-------------------------------- validate/rollback head & steady meta-pages
|
||||
if (unlikely(env->me_stuck_meta >= 0)) {
|
||||
@ -12204,7 +12212,7 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
}
|
||||
} else /* not recovery mode */
|
||||
while (1) {
|
||||
const unsigned meta_clash_mask = meta_eq_mask(&xyz);
|
||||
const unsigned meta_clash_mask = meta_eq_mask(&troika);
|
||||
if (unlikely(meta_clash_mask)) {
|
||||
ERROR("meta-pages are clashed: mask 0x%d", meta_clash_mask);
|
||||
return MDBX_CORRUPTED;
|
||||
@ -12213,7 +12221,7 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
if (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE) {
|
||||
/* non-exclusive mode,
|
||||
* meta-pages should be validated by a first process opened the DB */
|
||||
if (xyz.recent == xyz.prefer_steady)
|
||||
if (troika.recent == troika.prefer_steady)
|
||||
break;
|
||||
|
||||
if (!env->me_lck_mmap.lck) {
|
||||
@ -12231,8 +12239,8 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
eASSERT(env, lck_rc == MDBX_RESULT_TRUE);
|
||||
/* exclusive mode */
|
||||
|
||||
const meta_ptr_t recent = meta_recent(env, &xyz);
|
||||
const meta_ptr_t prefer_steady = meta_prefer_steady(env, &xyz);
|
||||
const meta_ptr_t recent = meta_recent(env, &troika);
|
||||
const meta_ptr_t prefer_steady = meta_prefer_steady(env, &troika);
|
||||
MDBX_meta clone;
|
||||
if (prefer_steady.is_steady) {
|
||||
err = validate_meta_copy(env, prefer_steady.ptr_c, &clone);
|
||||
@ -12309,9 +12317,9 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
pgno, recent.txnid, err);
|
||||
return err;
|
||||
}
|
||||
xyz = meta_tap(env);
|
||||
troika = meta_tap(env);
|
||||
ENSURE(env, 0 == meta_txnid(recent.ptr_v));
|
||||
ENSURE(env, 0 == meta_eq_mask(&xyz));
|
||||
ENSURE(env, 0 == meta_eq_mask(&troika));
|
||||
}
|
||||
|
||||
if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) {
|
||||
@ -12330,7 +12338,7 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
env->me_dxb_mmap.current, header.mm_geo.now);
|
||||
}
|
||||
|
||||
const meta_ptr_t recent = meta_recent(env, &xyz);
|
||||
const meta_ptr_t recent = meta_recent(env, &troika);
|
||||
if (memcmp(&header.mm_geo, &recent.ptr_c->mm_geo, sizeof(header.mm_geo))) {
|
||||
if ((env->me_flags & MDBX_RDONLY) != 0 ||
|
||||
/* recovery mode */ env->me_stuck_meta >= 0) {
|
||||
@ -12367,7 +12375,7 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
ENSURE(env, header.unsafe_txnid == recent.txnid);
|
||||
meta_set_txnid(env, &header, next_txnid);
|
||||
err = sync_locked(env, env->me_flags | MDBX_SHRINK_ALLOWED, &header,
|
||||
&xyz);
|
||||
&troika);
|
||||
if (err) {
|
||||
ERROR("error %d, while updating meta.geo: "
|
||||
"from l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO
|
||||
@ -12411,7 +12419,7 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
"updating db-format signature for", n, txnid, err);
|
||||
return err;
|
||||
}
|
||||
xyz = meta_tap(env);
|
||||
troika = meta_tap(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13341,8 +13349,8 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname,
|
||||
|
||||
#if MDBX_DEBUG
|
||||
if (rc == MDBX_SUCCESS) {
|
||||
const meta_xyz_t xyz = meta_tap(env);
|
||||
const meta_ptr_t head = meta_recent(env, &xyz);
|
||||
const meta_troika_t troika = meta_tap(env);
|
||||
const meta_ptr_t head = meta_recent(env, &troika);
|
||||
const MDBX_db *db = &head.ptr_c->mm_dbs[MAIN_DBI];
|
||||
|
||||
DEBUG("opened database version %u, pagesize %u",
|
||||
@ -19784,13 +19792,13 @@ __cold static int env_copy_asis(MDBX_env *env, MDBX_txn *read_txn,
|
||||
|
||||
jitter4testing(false);
|
||||
const size_t meta_bytes = pgno2bytes(env, NUM_METAS);
|
||||
const meta_xyz_t xyz = meta_tap(env);
|
||||
const meta_troika_t troika = meta_tap(env);
|
||||
/* Make a snapshot of meta-pages,
|
||||
* but writing ones after the data was flushed */
|
||||
memcpy(buffer, env->me_map, meta_bytes);
|
||||
MDBX_meta *const headcopy = /* LY: get pointer to the snapshot copy */
|
||||
(MDBX_meta *)(buffer +
|
||||
((uint8_t *)meta_recent(env, &xyz).ptr_c - env->me_map));
|
||||
((uint8_t *)meta_recent(env, &troika).ptr_c - env->me_map));
|
||||
mdbx_txn_unlock(env);
|
||||
|
||||
if (flags & MDBX_CP_FORCE_DYNAMIC_SIZE)
|
||||
@ -20361,22 +20369,22 @@ __cold static int fetch_envinfo_ex(const MDBX_env *env, const MDBX_txn *txn,
|
||||
if (unlikely(env->me_flags & MDBX_FATAL_ERROR))
|
||||
return MDBX_PANIC;
|
||||
|
||||
meta_xyz_t holder;
|
||||
meta_xyz_t const *xyz;
|
||||
meta_troika_t holder;
|
||||
meta_troika_t const *troika;
|
||||
if (txn && !(txn->mt_flags & MDBX_TXN_RDONLY))
|
||||
xyz = &txn->tw.xyz;
|
||||
troika = &txn->tw.troika;
|
||||
else {
|
||||
holder = meta_tap(env);
|
||||
xyz = &holder;
|
||||
troika = &holder;
|
||||
}
|
||||
|
||||
const meta_ptr_t head = meta_recent(env, xyz);
|
||||
const meta_ptr_t head = meta_recent(env, troika);
|
||||
arg->mi_recent_txnid = head.txnid;
|
||||
arg->mi_meta0_txnid = xyz->txnid[0];
|
||||
arg->mi_meta0_txnid = troika->txnid[0];
|
||||
arg->mi_meta0_sign = unaligned_peek_u64(4, meta0->mm_sign);
|
||||
arg->mi_meta1_txnid = xyz->txnid[1];
|
||||
arg->mi_meta1_txnid = troika->txnid[1];
|
||||
arg->mi_meta1_sign = unaligned_peek_u64(4, meta1->mm_sign);
|
||||
arg->mi_meta2_txnid = xyz->txnid[2];
|
||||
arg->mi_meta2_txnid = troika->txnid[2];
|
||||
arg->mi_meta2_sign = unaligned_peek_u64(4, meta2->mm_sign);
|
||||
if (likely(bytes > size_before_bootid)) {
|
||||
memcpy(&arg->mi_bootid.meta0, &meta0->mm_bootid, 16);
|
||||
@ -21131,12 +21139,12 @@ __cold int mdbx_reader_list(const MDBX_env *env, MDBX_reader_list_func *func,
|
||||
size_t bytes_retained = 0;
|
||||
uint64_t lag = 0;
|
||||
if (txnid) {
|
||||
meta_xyz_t xyz = meta_tap(env);
|
||||
meta_troika_t troika = meta_tap(env);
|
||||
retry_header:;
|
||||
const meta_ptr_t head = meta_recent(env, &xyz);
|
||||
const meta_ptr_t head = meta_recent(env, &troika);
|
||||
const uint64_t head_pages_retired =
|
||||
unaligned_peek_u64_volatile(4, head.ptr_v->mm_pages_retired);
|
||||
if (unlikely(meta_should_retry(env, &xyz) ||
|
||||
if (unlikely(meta_should_retry(env, &troika) ||
|
||||
head_pages_retired !=
|
||||
unaligned_peek_u64_volatile(
|
||||
4, head.ptr_v->mm_pages_retired)))
|
||||
@ -21337,7 +21345,7 @@ __cold static txnid_t kick_longlived_readers(MDBX_env *env,
|
||||
int retry = 0;
|
||||
do {
|
||||
const txnid_t steady =
|
||||
env->me_txn->tw.xyz.txnid[env->me_txn->tw.xyz.prefer_steady];
|
||||
env->me_txn->tw.troika.txnid[env->me_txn->tw.troika.prefer_steady];
|
||||
env->me_lck->mti_readers_refresh_flag.weak = /* force refresh */ true;
|
||||
oldest = find_oldest_reader(env, steady);
|
||||
eASSERT(env, oldest < env->me_txn0->mt_txnid);
|
||||
@ -21376,7 +21384,7 @@ __cold static txnid_t kick_longlived_readers(MDBX_env *env,
|
||||
stucked->mr_snapshot_pages_retired.weak != hold_retired)
|
||||
continue;
|
||||
|
||||
const meta_ptr_t head = meta_recent(env, &env->me_txn->tw.xyz);
|
||||
const meta_ptr_t head = meta_recent(env, &env->me_txn->tw.troika);
|
||||
const txnid_t gap = (head.txnid - laggard) / xMDBX_TXNID_STEP;
|
||||
const uint64_t head_retired =
|
||||
unaligned_peek_u64(4, head.ptr_c->mm_pages_retired);
|
||||
@ -21463,16 +21471,16 @@ int mdbx_txn_straggler(const MDBX_txn *txn, int *percent)
|
||||
}
|
||||
|
||||
txnid_t lag;
|
||||
meta_xyz_t xyz = meta_tap(env);
|
||||
meta_troika_t troika = meta_tap(env);
|
||||
do {
|
||||
const meta_ptr_t head = meta_recent(env, &xyz);
|
||||
const meta_ptr_t head = meta_recent(env, &troika);
|
||||
if (percent) {
|
||||
const pgno_t maxpg = head.ptr_v->mm_geo.now;
|
||||
*percent =
|
||||
(int)((head.ptr_v->mm_geo.next * UINT64_C(100) + maxpg / 2) / maxpg);
|
||||
}
|
||||
lag = (head.txnid - txn->mt_txnid) / xMDBX_TXNID_STEP;
|
||||
} while (unlikely(meta_should_retry(env, &xyz)));
|
||||
} while (unlikely(meta_should_retry(env, &troika)));
|
||||
|
||||
return (lag > INT_MAX) ? INT_MAX : (int)lag;
|
||||
}
|
||||
@ -23091,13 +23099,15 @@ __cold void global_ctor(void) {
|
||||
const uint8_t c01 = (i / (8 * 1)) % 3;
|
||||
const uint8_t c02 = (i / (8 * 3)) % 3;
|
||||
const uint8_t c12 = (i / (8 * 9)) % 3;
|
||||
const uint8_t xyz = meta_cmp2pack(c01, c02, c12, s0, s1, s2);
|
||||
|
||||
const uint8_t recent = (xyz >> 2) & 3;
|
||||
const uint8_t prefer_steady = (xyz >> 4) & 3;
|
||||
const uint8_t tail = xyz & 3;
|
||||
const bool strict = (xyz & 64) != 0;
|
||||
const bool valid = (xyz & 128) != 0;
|
||||
const uint8_t packed = meta_cmp2pack(c01, c02, c12, s0, s1, s2);
|
||||
meta_troika_t troika;
|
||||
troika.fsm = (uint8_t)i;
|
||||
meta_troika_unpack(&troika, packed);
|
||||
|
||||
const uint8_t tail = TROIKA_TAIL(&troika);
|
||||
const bool strict = TROIKA_STRICT_VALID(&troika);
|
||||
const bool valid = TROIKA_VALID(&troika);
|
||||
|
||||
const uint8_t recent_chk = meta_cmp2recent(c01, s0, s1)
|
||||
? (meta_cmp2recent(c02, s0, s2) ? 0 : 2)
|
||||
@ -23118,13 +23128,13 @@ __cold void global_ctor(void) {
|
||||
c01 != 1 || s0 != s1 || c02 != 1 || s0 != s2 || c12 != 1 || s1 != s2;
|
||||
const bool strict_chk = (c01 != 1 || s0 != s1) && (c02 != 1 || s0 != s2) &&
|
||||
(c12 != 1 || s1 != s2);
|
||||
assert(recent == recent_chk);
|
||||
assert(prefer_steady == prefer_steady_chk);
|
||||
assert(troika.recent == recent_chk);
|
||||
assert(troika.prefer_steady == prefer_steady_chk);
|
||||
assert(tail == tail_chk);
|
||||
assert(valid == valid_chk);
|
||||
assert(strict == strict_chk);
|
||||
// printf(" %d, ", xyz);
|
||||
assert(xyz_fsm_map[i] == xyz);
|
||||
// printf(" %d, ", packed);
|
||||
assert(troika_fsm_map[troika.fsm] == packed);
|
||||
}
|
||||
#endif /* MDBX_DEBUG*/
|
||||
|
||||
|
@ -920,12 +920,14 @@ typedef struct MDBX_dbx {
|
||||
md_vlen_max; /* min/max value/data length for the database */
|
||||
} MDBX_dbx;
|
||||
|
||||
typedef struct xyz {
|
||||
typedef struct troika {
|
||||
uint8_t fsm, recent, prefer_steady, tail_and_flags;
|
||||
#define XYZ_HAVE_STEADY(xyz) ((xyz)->fsm & 7)
|
||||
#define XYZ_VALID(xyz) ((xyz)->tail_pgno_and_flags & 128)
|
||||
#define TROIKA_HAVE_STEADY(troika) ((troika)->fsm & 7)
|
||||
#define TROIKA_STRICT_VALID(troika) ((troika)->tail_and_flags & 64)
|
||||
#define TROIKA_VALID(troika) ((troika)->tail_and_flags & 128)
|
||||
#define TROIKA_TAIL(troika) ((troika)->tail_and_flags & 3)
|
||||
txnid_t txnid[NUM_METAS];
|
||||
} meta_xyz_t;
|
||||
} meta_troika_t;
|
||||
|
||||
/* A database transaction.
|
||||
* Every operation requires a transaction handle. */
|
||||
@ -1000,7 +1002,7 @@ struct MDBX_txn {
|
||||
MDBX_reader *reader;
|
||||
} to;
|
||||
struct {
|
||||
meta_xyz_t xyz;
|
||||
meta_troika_t troika;
|
||||
/* In write txns, array of cursors for each DB */
|
||||
pgno_t *reclaimed_pglist; /* Reclaimed GC pages */
|
||||
txnid_t last_reclaimed; /* ID of last used record */
|
||||
|
Loading…
x
Reference in New Issue
Block a user