mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-30 22:47:16 +08:00
mdbx: добавление ошибки MDBX_BACKLOG_DEPLETED
и соответствующей логики в page_alloc_slowpath()
.
This commit is contained in:
parent
4b27c4c7c9
commit
fd7aaf5f35
6
mdbx.h
6
mdbx.h
@ -1926,6 +1926,12 @@ enum MDBX_error_t {
|
||||
/** Overlapping read and write transactions for the current thread */
|
||||
MDBX_TXN_OVERLAPPING = -30415,
|
||||
|
||||
/** Внутренняя ошибка возвращаемая в случае нехватки запаса свободных страниц
|
||||
* при обновлении GC. Используется как вспомогательное средство для отладки.
|
||||
* \note С точки зрения пользователя семантически
|
||||
* равнозначна \ref MDBX_PROBLEM. */
|
||||
MDBX_BACKLOG_DEPLETED = -30414,
|
||||
|
||||
/* The last of MDBX-added error codes */
|
||||
MDBX_LAST_ADDED_ERRCODE = MDBX_TXN_OVERLAPPING,
|
||||
|
||||
|
@ -5,7 +5,7 @@ N | MASK | ENV | TXN | DB | PUT | DBI | NOD
|
||||
2 |0000 0004|ALLOC_NEW |TXN_DIRTY |DUPSORT | |DBI_FRESH |F_DUPDATA|P_OVERFLOW| |
|
||||
3 |0000 0008|ALLOC_SLOT |TXN_SPILLS |INTEGERKEY| |DBI_CREAT | |P_META | |
|
||||
4 |0000 0010|ALLOC_FAKE |TXN_HAS_CHILD |DUPFIXED |NOOVERWRITE|DBI_VALID | |P_BAD | |
|
||||
5 |0000 0020| | |INTEGERDUP|NODUPDATA |DBI_USRVALID| |P_LEAF2 | |
|
||||
5 |0000 0020| |TXN_DRAINED_GC|INTEGERDUP|NODUPDATA |DBI_USRVALID| |P_LEAF2 | |
|
||||
6 |0000 0040| | |REVERSEDUP|CURRENT |DBI_DUPDATA | |P_SUBP | |
|
||||
7 |0000 0080| | | |ALLDUPS |DBI_AUDITED | | | |
|
||||
8 |0000 0100| _MAY_MOVE | | | | | | | <= |
|
||||
|
26
src/core.c
26
src/core.c
@ -6750,10 +6750,12 @@ static __inline bool is_gc_usable(MDBX_txn *txn, const MDBX_cursor *mc,
|
||||
!(mc->mc_flags & C_GCU))
|
||||
return false;
|
||||
|
||||
/* avoid (recursive) search inside empty tree and while tree is
|
||||
updating, https://libmdbx.dqdkfa.ru/dead-github/issues/31 */
|
||||
if (txn->mt_dbs[FREE_DBI].md_entries == 0)
|
||||
/* avoid search inside empty tree and while tree is updating,
|
||||
https://libmdbx.dqdkfa.ru/dead-github/issues/31 */
|
||||
if (unlikely(txn->mt_dbs[FREE_DBI].md_entries == 0)) {
|
||||
txn->mt_flags |= MDBX_TXN_DRAINED_GC;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -7090,8 +7092,10 @@ static pgr_t page_alloc_slowpath(const MDBX_cursor *const mc, const size_t num,
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
if (unlikely(!is_gc_usable(txn, mc, flags)))
|
||||
if (unlikely(!is_gc_usable(txn, mc, flags))) {
|
||||
eASSERT(env, txn->mt_flags & MDBX_TXN_DRAINED_GC);
|
||||
goto no_gc;
|
||||
}
|
||||
|
||||
eASSERT(env, (flags & (MDBX_ALLOC_COALESCE | MDBX_ALLOC_LIFO |
|
||||
MDBX_ALLOC_SHOULD_SCAN)) == 0);
|
||||
@ -7178,6 +7182,7 @@ next_gc:;
|
||||
if (unlikely(id >= detent))
|
||||
goto depleted_gc;
|
||||
}
|
||||
txn->mt_flags &= ~MDBX_TXN_DRAINED_GC;
|
||||
|
||||
/* Reading next GC record */
|
||||
MDBX_val data;
|
||||
@ -7326,9 +7331,12 @@ scan:
|
||||
}
|
||||
|
||||
depleted_gc:
|
||||
TRACE("%s: last id #%" PRIaTXN ", re-len %zu", "gc-depleted", id,
|
||||
MDBX_PNL_GETSIZE(txn->tw.relist));
|
||||
ret.err = MDBX_NOTFOUND;
|
||||
if (flags & MDBX_ALLOC_SHOULD_SCAN)
|
||||
goto scan;
|
||||
txn->mt_flags |= MDBX_TXN_DRAINED_GC;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@ -7431,6 +7439,14 @@ depleted_gc:
|
||||
|
||||
no_gc:
|
||||
eASSERT(env, pgno == 0);
|
||||
#ifndef MDBX_ENABLE_BACKLOG_DEPLETED
|
||||
#define MDBX_ENABLE_BACKLOG_DEPLETED 0
|
||||
#endif /* MDBX_ENABLE_BACKLOG_DEPLETED*/
|
||||
if (MDBX_ENABLE_BACKLOG_DEPLETED &&
|
||||
unlikely(!(txn->mt_flags & MDBX_TXN_DRAINED_GC))) {
|
||||
ret.err = MDBX_BACKLOG_DEPLETED;
|
||||
goto fail;
|
||||
}
|
||||
if (flags & MDBX_ALLOC_RESERVE) {
|
||||
ret.err = MDBX_NOTFOUND;
|
||||
goto fail;
|
||||
@ -9915,6 +9931,8 @@ static int gcu_prepare_backlog(MDBX_txn *txn, gcu_context_t *ctx) {
|
||||
(size_t)txn->mt_dbs[FREE_DBI].md_leaf_pages,
|
||||
(size_t)txn->mt_dbs[FREE_DBI].md_overflow_pages,
|
||||
(size_t)txn->mt_dbs[FREE_DBI].md_entries);
|
||||
tASSERT(txn,
|
||||
err != MDBX_NOTFOUND || (txn->mt_flags & MDBX_TXN_DRAINED_GC) != 0);
|
||||
return (err != MDBX_NOTFOUND) ? err : MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1013,9 +1013,11 @@ struct MDBX_txn {
|
||||
/* Additional flag for sync_locked() */
|
||||
#define MDBX_SHRINK_ALLOWED UINT32_C(0x40000000)
|
||||
|
||||
#define MDBX_TXN_DRAINED_GC 0x20 /* GC was depleted up to oldest reader */
|
||||
|
||||
#define TXN_FLAGS \
|
||||
(MDBX_TXN_FINISHED | MDBX_TXN_ERROR | MDBX_TXN_DIRTY | MDBX_TXN_SPILLS | \
|
||||
MDBX_TXN_HAS_CHILD | MDBX_TXN_INVALID)
|
||||
MDBX_TXN_HAS_CHILD | MDBX_TXN_INVALID | MDBX_TXN_DRAINED_GC)
|
||||
|
||||
#if (TXN_FLAGS & (MDBX_TXN_RW_BEGIN_FLAGS | MDBX_TXN_RO_BEGIN_FLAGS)) || \
|
||||
((MDBX_TXN_RW_BEGIN_FLAGS | MDBX_TXN_RO_BEGIN_FLAGS | TXN_FLAGS) & \
|
||||
|
Loading…
x
Reference in New Issue
Block a user