mdbx: добавление ошибки MDBX_BACKLOG_DEPLETED и соответствующей логики в page_alloc_slowpath().

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2022-12-08 12:58:56 +03:00
parent 4b27c4c7c9
commit fd7aaf5f35
4 changed files with 32 additions and 6 deletions

6
mdbx.h
View File

@ -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,

View File

@ -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 | | | | | | | <= |

View File

@ -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;
}

View File

@ -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) & \