mirror of
https://github.com/isar/libmdbx.git
synced 2024-12-29 09:28:49 +08:00
mdbx: доработка/исправление и постоянная активация корректирующей обратной связи при обновлении GC.
При обновлении GC, с помещением/возвратом страниц, возникает рекурсивная зависимость, так как страницы, необходимые для CoW-модификации GC и размещения списков возвращаемых страниц, берутся/выделяются из этих-же списков и/или из GC. Эта рекуррентная зависимость разрешается путём подготовки необходимого запаса страниц и двух-стадийным заполнением списков, с повторением всего цикла при изменении ситуации/расклада, плюс применение некоторых эвристик и поправок. Кроме корректной работы, принципиально важным тут является минимизация количества повторов/рестартов процесса, в том числе исключение возможности бесконечного зацикливания. Существующая реализация многократно/итеративно дорабатывалась. Поэтому она неплохо обкатана и стабильна, но одновременно сложна и запутана. Тем не менее, до последнего момента для текущей реализации были известны условия/сценарии, в которых сходимость итеративного процесса обновления GC нарушалась и при фиксации транзакции возвращалась ошибка MDBX_PROBLEM. Эти условия/сценарии очень специфичны и далеки от реальных практических случаев, поэтому этот недостаток не мешал использованию библиотеки. Этим коммитом добавляется и активируется еще один механизм нацеленный на улучшение сходимости и минимизацию повторов/рестартов. Суть механизма в формировании и учета поправки, которая на следующем цикле позволит учесть все переходные процессы/затраты вне зависимости от их природы, и этим обеспечить моментальную сходимость. В текущем понимании, описанный выше недостаток полностью устраняется/исправляется этим коммитом.
This commit is contained in:
parent
acb15790b4
commit
6c56ed97bb
80
src/gc-put.c
80
src/gc-put.c
@ -454,6 +454,7 @@ static rid_t get_rid_for_reclaimed(MDBX_txn *txn, gcu_t *ctx,
|
|||||||
(MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) - ctx->reused_slot) *
|
(MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) - ctx->reused_slot) *
|
||||||
txn->env->maxgc_large1page) {
|
txn->env->maxgc_large1page) {
|
||||||
if (unlikely(ctx->rid <= MIN_TXNID)) {
|
if (unlikely(ctx->rid <= MIN_TXNID)) {
|
||||||
|
ctx->dense = true;
|
||||||
if (unlikely(MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) <=
|
if (unlikely(MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) <=
|
||||||
ctx->reused_slot)) {
|
ctx->reused_slot)) {
|
||||||
NOTICE("** restart: reserve depleted (reused_gc_slot %zu >= "
|
NOTICE("** restart: reserve depleted (reused_gc_slot %zu >= "
|
||||||
@ -480,10 +481,10 @@ static rid_t get_rid_for_reclaimed(MDBX_txn *txn, gcu_t *ctx,
|
|||||||
goto return_error;
|
goto return_error;
|
||||||
}
|
}
|
||||||
const txnid_t gc_first = unaligned_peek_u64(4, key.iov_base);
|
const txnid_t gc_first = unaligned_peek_u64(4, key.iov_base);
|
||||||
if (unlikely(gc_first <= MIN_TXNID)) {
|
if (unlikely(gc_first <= INITIAL_TXNID)) {
|
||||||
DEBUG("%s: no free GC's id(s) less than %" PRIaTXN
|
NOTICE("%s: no free GC's id(s) less than %" PRIaTXN
|
||||||
" (going dense-mode)",
|
" (going dense-mode)",
|
||||||
dbg_prefix(ctx), ctx->rid);
|
dbg_prefix(ctx), ctx->rid);
|
||||||
ctx->dense = true;
|
ctx->dense = true;
|
||||||
goto return_restart;
|
goto return_restart;
|
||||||
}
|
}
|
||||||
@ -590,19 +591,11 @@ int gc_update(MDBX_txn *txn, gcu_t *ctx) {
|
|||||||
txn->cursors[FREE_DBI] = &ctx->cursor;
|
txn->cursors[FREE_DBI] = &ctx->cursor;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
// tASSERT(txn, MDBX_PNL_GETSIZE(txn->tw.retired_pages) ||
|
|
||||||
// ctx->cleaned_slot <
|
|
||||||
// (txn->tw.gc.reclaimed ?
|
|
||||||
// MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) : 0)
|
|
||||||
// || ctx->cleaned_id < txn->tw.gc.last_reclaimed);
|
|
||||||
|
|
||||||
/* txn->tw.relist[] can grow and shrink during this call.
|
/* txn->tw.relist[] can grow and shrink during this call.
|
||||||
* txn->tw.gc.last_reclaimed and txn->tw.retired_pages[] can only grow.
|
* txn->tw.gc.last_reclaimed and txn->tw.retired_pages[] can only grow.
|
||||||
* But page numbers cannot disappear from txn->tw.retired_pages[]. */
|
* But page numbers cannot disappear from txn->tw.retired_pages[]. */
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
retry_clean_adj:
|
retry_clean_adj:
|
||||||
ctx->reserve_adj = 0;
|
ctx->reserve_adj = 0;
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
retry:
|
retry:
|
||||||
ctx->loop += ctx->prev_first_unallocated == txn->geo.first_unallocated;
|
ctx->loop += ctx->prev_first_unallocated == txn->geo.first_unallocated;
|
||||||
TRACE(">> restart, loop %u", ctx->loop);
|
TRACE(">> restart, loop %u", ctx->loop);
|
||||||
@ -629,7 +622,8 @@ retry:
|
|||||||
ctx->reserved = 0;
|
ctx->reserved = 0;
|
||||||
ctx->cleaned_slot = 0;
|
ctx->cleaned_slot = 0;
|
||||||
ctx->reused_slot = 0;
|
ctx->reused_slot = 0;
|
||||||
ctx->amount = ctx->fill_idx = ~0u;
|
ctx->amount = 0;
|
||||||
|
ctx->fill_idx = ~0u;
|
||||||
ctx->cleaned_id = 0;
|
ctx->cleaned_id = 0;
|
||||||
ctx->rid = txn->tw.gc.last_reclaimed;
|
ctx->rid = txn->tw.gc.last_reclaimed;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -746,9 +740,7 @@ retry:
|
|||||||
env->maxgc_large1page / 2)) {
|
env->maxgc_large1page / 2)) {
|
||||||
TRACE("%s: reclaimed-list changed %zu -> %zu, retry", dbg_prefix(ctx),
|
TRACE("%s: reclaimed-list changed %zu -> %zu, retry", dbg_prefix(ctx),
|
||||||
ctx->amount, MDBX_PNL_GETSIZE(txn->tw.relist));
|
ctx->amount, MDBX_PNL_GETSIZE(txn->tw.relist));
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
ctx->reserve_adj += ctx->reserved - MDBX_PNL_GETSIZE(txn->tw.relist);
|
ctx->reserve_adj += ctx->reserved - MDBX_PNL_GETSIZE(txn->tw.relist);
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
ctx->amount = MDBX_PNL_GETSIZE(txn->tw.relist);
|
ctx->amount = MDBX_PNL_GETSIZE(txn->tw.relist);
|
||||||
@ -772,7 +764,6 @@ retry:
|
|||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
const size_t left = ctx->amount - ctx->reserved - ctx->reserve_adj;
|
const size_t left = ctx->amount - ctx->reserved - ctx->reserve_adj;
|
||||||
TRACE("%s: amount %zu, reserved %zd, reserve_adj %zu, left %zd, "
|
TRACE("%s: amount %zu, reserved %zd, reserve_adj %zu, left %zd, "
|
||||||
"lifo-reclaimed-slots %zu, "
|
"lifo-reclaimed-slots %zu, "
|
||||||
@ -780,15 +771,6 @@ retry:
|
|||||||
dbg_prefix(ctx), ctx->amount, ctx->reserved, ctx->reserve_adj, left,
|
dbg_prefix(ctx), ctx->amount, ctx->reserved, ctx->reserve_adj, left,
|
||||||
txn->tw.gc.reclaimed ? MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) : 0,
|
txn->tw.gc.reclaimed ? MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) : 0,
|
||||||
ctx->reused_slot);
|
ctx->reused_slot);
|
||||||
#else
|
|
||||||
const size_t left = ctx->amount - ctx->reserved;
|
|
||||||
TRACE("%s: amount %zu, reserved %zd, left %zd, "
|
|
||||||
"lifo-reclaimed-slots %zu, "
|
|
||||||
"reused-gc-slots %zu",
|
|
||||||
dbg_prefix(ctx), ctx->amount, ctx->reserved, left,
|
|
||||||
txn->tw.gc.reclaimed ? MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) : 0,
|
|
||||||
ctx->reused_slot);
|
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
if (0 >= (intptr_t)left)
|
if (0 >= (intptr_t)left)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -911,9 +893,7 @@ retry:
|
|||||||
|
|
||||||
TRACE("%s", " >> filling");
|
TRACE("%s", " >> filling");
|
||||||
/* Fill in the reserved records */
|
/* Fill in the reserved records */
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
size_t excess_slots = 0;
|
size_t excess_slots = 0;
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
ctx->fill_idx =
|
ctx->fill_idx =
|
||||||
txn->tw.gc.reclaimed
|
txn->tw.gc.reclaimed
|
||||||
? MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) - ctx->reused_slot
|
? MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed) - ctx->reused_slot
|
||||||
@ -924,15 +904,17 @@ retry:
|
|||||||
tASSERT(txn, dpl_check(txn));
|
tASSERT(txn, dpl_check(txn));
|
||||||
if (ctx->amount) {
|
if (ctx->amount) {
|
||||||
MDBX_val key, data;
|
MDBX_val key, data;
|
||||||
key.iov_len = data.iov_len = 0; /* avoid MSVC warning */
|
key.iov_len = data.iov_len = 0;
|
||||||
key.iov_base = data.iov_base = nullptr;
|
key.iov_base = data.iov_base = nullptr;
|
||||||
|
|
||||||
size_t left = ctx->amount, excess = 0;
|
size_t left = ctx->amount, excess = 0;
|
||||||
if (txn->tw.gc.reclaimed == nullptr) {
|
if (txn->tw.gc.reclaimed == nullptr) {
|
||||||
tASSERT(txn, is_lifo(txn) == 0);
|
tASSERT(txn, is_lifo(txn) == 0);
|
||||||
rc = outer_first(&ctx->cursor, &key, &data);
|
rc = outer_first(&ctx->cursor, &key, &data);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||||
goto bailout;
|
if (rc != MDBX_NOTFOUND)
|
||||||
|
goto bailout;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tASSERT(txn, is_lifo(txn) != 0);
|
tASSERT(txn, is_lifo(txn) != 0);
|
||||||
}
|
}
|
||||||
@ -943,36 +925,29 @@ retry:
|
|||||||
MDBX_PNL_GETSIZE(txn->tw.relist));
|
MDBX_PNL_GETSIZE(txn->tw.relist));
|
||||||
if (txn->tw.gc.reclaimed == nullptr) {
|
if (txn->tw.gc.reclaimed == nullptr) {
|
||||||
tASSERT(txn, is_lifo(txn) == 0);
|
tASSERT(txn, is_lifo(txn) == 0);
|
||||||
fill_gc_id = unaligned_peek_u64(4, key.iov_base);
|
fill_gc_id =
|
||||||
|
key.iov_base ? unaligned_peek_u64(4, key.iov_base) : MIN_TXNID;
|
||||||
if (ctx->fill_idx == 0 || fill_gc_id > txn->tw.gc.last_reclaimed) {
|
if (ctx->fill_idx == 0 || fill_gc_id > txn->tw.gc.last_reclaimed) {
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
if (!left)
|
if (!left)
|
||||||
break;
|
break;
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
NOTICE("** restart: reserve depleted (fill_idx %zu, fill_id %" PRIaTXN
|
NOTICE("** restart: reserve depleted (fill_idx %zu, fill_id %" PRIaTXN
|
||||||
" > last_reclaimed %" PRIaTXN ", left %zu",
|
" > last_reclaimed %" PRIaTXN ", left %zu",
|
||||||
ctx->fill_idx, fill_gc_id, txn->tw.gc.last_reclaimed, left);
|
ctx->fill_idx, fill_gc_id, txn->tw.gc.last_reclaimed, left);
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
ctx->reserve_adj =
|
ctx->reserve_adj =
|
||||||
(ctx->reserve_adj > left) ? ctx->reserve_adj - left : 0;
|
(ctx->reserve_adj > left) ? ctx->reserve_adj - left : 0;
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
ctx->fill_idx -= 1;
|
ctx->fill_idx -= 1;
|
||||||
} else {
|
} else {
|
||||||
tASSERT(txn, is_lifo(txn) != 0);
|
tASSERT(txn, is_lifo(txn) != 0);
|
||||||
if (ctx->fill_idx >= MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed)) {
|
if (ctx->fill_idx >= MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed)) {
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
if (!left)
|
if (!left)
|
||||||
break;
|
break;
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
NOTICE("** restart: reserve depleted (fill_idx %zu >= "
|
NOTICE("** restart: reserve depleted (fill_idx %zu >= "
|
||||||
"gc.reclaimed %zu, left %zu",
|
"gc.reclaimed %zu, left %zu",
|
||||||
ctx->fill_idx, MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed), left);
|
ctx->fill_idx, MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed), left);
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
ctx->reserve_adj =
|
ctx->reserve_adj =
|
||||||
(ctx->reserve_adj > left) ? ctx->reserve_adj - left : 0;
|
(ctx->reserve_adj > left) ? ctx->reserve_adj - left : 0;
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
ctx->fill_idx += 1;
|
ctx->fill_idx += 1;
|
||||||
@ -1001,12 +976,10 @@ retry:
|
|||||||
excess += delta;
|
excess += delta;
|
||||||
TRACE("%s: chunk %zu > left %zu, @%" PRIaTXN, dbg_prefix(ctx), chunk,
|
TRACE("%s: chunk %zu > left %zu, @%" PRIaTXN, dbg_prefix(ctx), chunk,
|
||||||
left, fill_gc_id);
|
left, fill_gc_id);
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
if (!left) {
|
if (!left) {
|
||||||
excess_slots += 1;
|
excess_slots += 1;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
if ((ctx->loop < 5 && delta > (ctx->loop / 2)) ||
|
if ((ctx->loop < 5 && delta > (ctx->loop / 2)) ||
|
||||||
delta > env->maxgc_large1page)
|
delta > env->maxgc_large1page)
|
||||||
data.iov_len = (left + 1) * sizeof(pgno_t);
|
data.iov_len = (left + 1) * sizeof(pgno_t);
|
||||||
@ -1022,10 +995,8 @@ retry:
|
|||||||
NOTICE("** restart: reclaimed-list changed (%zu -> %zu, loose +%zu)",
|
NOTICE("** restart: reclaimed-list changed (%zu -> %zu, loose +%zu)",
|
||||||
ctx->amount, MDBX_PNL_GETSIZE(txn->tw.relist),
|
ctx->amount, MDBX_PNL_GETSIZE(txn->tw.relist),
|
||||||
txn->tw.loose_count);
|
txn->tw.loose_count);
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
if (ctx->loop < 5 || (ctx->loop > 10 && (ctx->loop & 1)))
|
if (ctx->loop < 5 || (ctx->loop > 10 && (ctx->loop & 1)))
|
||||||
goto retry_clean_adj;
|
goto retry_clean_adj;
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1061,23 +1032,16 @@ retry:
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
next:
|
next:
|
||||||
#else
|
|
||||||
if (left == 0)
|
|
||||||
break;
|
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
|
|
||||||
if (txn->tw.gc.reclaimed == nullptr) {
|
if (txn->tw.gc.reclaimed == nullptr) {
|
||||||
tASSERT(txn, is_lifo(txn) == 0);
|
tASSERT(txn, is_lifo(txn) == 0);
|
||||||
rc = outer_next(&ctx->cursor, &key, &data, MDBX_NEXT);
|
rc = outer_next(&ctx->cursor, &key, &data, MDBX_NEXT);
|
||||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
if (rc == MDBX_NOTFOUND && !left) {
|
if (rc == MDBX_NOTFOUND && !left) {
|
||||||
rc = MDBX_SUCCESS;
|
rc = MDBX_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1086,14 +1050,12 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (excess) {
|
if (excess) {
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
size_t n = excess, adj = excess;
|
size_t n = excess, adj = excess;
|
||||||
while (n >= env->maxgc_large1page)
|
while (n >= env->maxgc_large1page)
|
||||||
adj -= n /= env->maxgc_large1page;
|
adj -= n /= env->maxgc_large1page;
|
||||||
ctx->reserve_adj += adj;
|
ctx->reserve_adj += adj;
|
||||||
TRACE("%s: extra %zu reserved space, adj +%zu (%zu)", dbg_prefix(ctx),
|
TRACE("%s: extra %zu reserved space, adj +%zu (%zu)", dbg_prefix(ctx),
|
||||||
excess, adj, ctx->reserve_adj);
|
excess, adj, ctx->reserve_adj);
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1105,27 +1067,15 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
if (unlikely(excess_slots)) {
|
if (unlikely(excess_slots)) {
|
||||||
const bool will_retry = ctx->loop < 5 || excess_slots > 1;
|
const bool will_retry = ctx->loop < 5 || excess_slots > 1;
|
||||||
NOTICE("** %s: reserve excess (excess-slots %zu, filled-slot %zu, adj %zu, "
|
NOTICE("** %s: reserve excess (excess-slots %zu, filled-slot %zu, adj %zu, "
|
||||||
"loop %zu)",
|
"loop %u)",
|
||||||
will_retry ? "restart" : "ignore", excess_slots, ctx->fill_idx,
|
will_retry ? "restart" : "ignore", excess_slots, ctx->fill_idx,
|
||||||
ctx->reserve_adj, ctx->loop);
|
ctx->reserve_adj, ctx->loop);
|
||||||
if (will_retry)
|
if (will_retry)
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (unlikely(ctx->fill_idx != (txn->tw.gc.reclaimed
|
|
||||||
? MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed)
|
|
||||||
: 0))) {
|
|
||||||
const bool will_retry = ctx->loop < 9;
|
|
||||||
NOTICE("** %s: reserve excess (filled-idx %zu, loop %u)",
|
|
||||||
will_retry ? "restart" : "ignore", ctx->fill_idx, ctx->loop);
|
|
||||||
if (will_retry)
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
|
|
||||||
tASSERT(txn, txn->tw.gc.reclaimed == nullptr ||
|
tASSERT(txn, txn->tw.gc.reclaimed == nullptr ||
|
||||||
ctx->cleaned_slot == MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed));
|
ctx->cleaned_slot == MDBX_PNL_GETSIZE(txn->tw.gc.reclaimed));
|
||||||
|
12
src/gc.h
12
src/gc.h
@ -5,19 +5,11 @@
|
|||||||
|
|
||||||
#include "essentials.h"
|
#include "essentials.h"
|
||||||
|
|
||||||
#ifndef MDBX_ENABLE_GC_EXPERIMENTAL
|
|
||||||
#define MDBX_ENABLE_GC_EXPERIMENTAL 0
|
|
||||||
#elif !(MDBX_ENABLE_GC_EXPERIMENTAL == 0 || MDBX_ENABLE_GC_EXPERIMENTAL == 1)
|
|
||||||
#error MDBX_ENABLE_GC_EXPERIMENTAL must be defined as 0 or 1
|
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
|
|
||||||
typedef struct gc_update_context {
|
typedef struct gc_update_context {
|
||||||
unsigned loop;
|
unsigned loop;
|
||||||
pgno_t prev_first_unallocated;
|
pgno_t prev_first_unallocated;
|
||||||
bool dense;
|
bool dense;
|
||||||
#if MDBX_ENABLE_GC_EXPERIMENTAL
|
size_t reserve_adj;
|
||||||
intptr_t reserve_adj;
|
|
||||||
#endif /* MDBX_ENABLE_GC_EXPERIMENTAL */
|
|
||||||
size_t retired_stored;
|
size_t retired_stored;
|
||||||
size_t amount, reserved, cleaned_slot, reused_slot, fill_idx;
|
size_t amount, reserved, cleaned_slot, reused_slot, fill_idx;
|
||||||
txnid_t cleaned_id, rid;
|
txnid_t cleaned_id, rid;
|
||||||
@ -32,7 +24,7 @@ typedef struct gc_update_context {
|
|||||||
|
|
||||||
static inline int gc_update_init(MDBX_txn *txn, gcu_t *ctx) {
|
static inline int gc_update_init(MDBX_txn *txn, gcu_t *ctx) {
|
||||||
memset(ctx, 0, offsetof(gcu_t, cursor));
|
memset(ctx, 0, offsetof(gcu_t, cursor));
|
||||||
ctx->dense = txn->txnid < MIN_TXNID;
|
ctx->dense = txn->txnid <= MIN_TXNID;
|
||||||
#if MDBX_ENABLE_BIGFOOT
|
#if MDBX_ENABLE_BIGFOOT
|
||||||
ctx->bigfoot = txn->txnid;
|
ctx->bigfoot = txn->txnid;
|
||||||
#endif /* MDBX_ENABLE_BIGFOOT */
|
#endif /* MDBX_ENABLE_BIGFOOT */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user