mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 02:14:13 +08:00
mdbx: avoid MDBX_TXN_FULL
while searching for a large multi-page region.
Resolves https://github.com/erthink/libmdbx/issues/123 but with TODO: - provide a user-configurable threshold instead of currently hard-coded default (MDBX_PNL_MAX/2). Change-Id: Ia7bfd5f8d36e027444d234e3c3aabe4832313466
This commit is contained in:
parent
8a7caec54a
commit
55d190bad9
@ -1,8 +1,8 @@
|
||||
N | MASK | ENV | TXN | DB | PUT | DBI | NODE | PAGE |
|
||||
--|---------|-----------|--------------|----------|-----------|------------|---------|----------|
|
||||
0 |0000 0001| |TXN_FINISHED | | |DBI_DIRTY |F_BIGDATA|P_BRANCH
|
||||
1 |0000 0002| |TXN_ERROR |REVERSEKEY| |DBI_STALE |F_SUBDATA|P_LEAF
|
||||
2 |0000 0004| |TXN_DIRTY |DUPSORT | |DBI_FRESH |F_DUPDATA|P_OVERFLOW
|
||||
0 |0000 0001|ALLOC_CACHE|TXN_FINISHED | | |DBI_DIRTY |F_BIGDATA|P_BRANCH
|
||||
1 |0000 0002|ALLOC_GC |TXN_ERROR |REVERSEKEY| |DBI_STALE |F_SUBDATA|P_LEAF
|
||||
2 |0000 0004|ALLOC_NEW |TXN_DIRTY |DUPSORT | |DBI_FRESH |F_DUPDATA|P_OVERFLOW
|
||||
3 |0000 0008| |TXN_SPILLS |INTEGERKEY| |DBI_CREAT | |P_META
|
||||
4 |0000 0010| |TXN_HAS_CHILD |DUPFIXED |NOOVERWRITE|DBI_VALID | |P_DIRTY
|
||||
5 |0000 0020| | |INTEGERDUP|NODUPDATA |DBI_USRVALID| |P_LEAF2
|
||||
|
26
src/core.c
26
src/core.c
@ -5108,12 +5108,6 @@ skip_cache:
|
||||
const unsigned wanna_range = num - 1;
|
||||
|
||||
while (true) { /* hsr-kick retry loop */
|
||||
/* If our dirty list is already full, we can't do anything */
|
||||
if (unlikely(txn->tw.dirtyroom == 0)) {
|
||||
rc = MDBX_TXN_FULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
MDBX_cursor_couple recur;
|
||||
for (MDBX_cursor_op op = MDBX_FIRST;;
|
||||
op = (flags & MDBX_LIFORECLAIM) ? MDBX_PREV : MDBX_NEXT) {
|
||||
@ -5154,6 +5148,11 @@ skip_cache:
|
||||
}
|
||||
|
||||
if (op == MDBX_FIRST) { /* 1st iteration, setup cursor, etc */
|
||||
if (unlikely(txn->tw.dirtyroom < txn->mt_dbs[FREE_DBI].md_depth) &&
|
||||
!(txn->mt_dbistate[FREE_DBI] & DBI_DIRTY)) {
|
||||
/* If our dirty list is already full, we can't touch GC */
|
||||
flags &= ~MDBX_ALLOC_GC;
|
||||
}
|
||||
if (unlikely(!(flags & MDBX_ALLOC_GC)))
|
||||
break /* reclaiming is prohibited for now */;
|
||||
|
||||
@ -5264,6 +5263,21 @@ skip_cache:
|
||||
goto fail;
|
||||
}
|
||||
const unsigned gc_len = MDBX_PNL_SIZE(gc_pnl);
|
||||
/* TODO: provide a user-configurable threshold */
|
||||
const unsigned threshold_2_stop_gc_reclaiming = MDBX_PNL_MAX / 2;
|
||||
if (unlikely(gc_len + MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) >
|
||||
threshold_2_stop_gc_reclaiming)) {
|
||||
/* Stop reclaiming to avoid overflow the page list.
|
||||
* This is a rare case while search for a continuously multi-page region
|
||||
* in a large database. https://github.com/erthink/libmdbx/issues/123 */
|
||||
flags -= MDBX_ALLOC_GC;
|
||||
if (unlikely(flags == 0)) {
|
||||
/* Oh, we can't do anything */
|
||||
rc = MDBX_TXN_FULL;
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
rc = mdbx_pnl_need(&txn->tw.reclaimed_pglist, gc_len);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto fail;
|
||||
|
Loading…
x
Reference in New Issue
Block a user