2024-05-19 22:07:58 +03:00
|
|
|
|
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
/// \note Please refer to the COPYRIGHT file for explanations license change,
|
|
|
|
|
/// credits and acknowledgments.
|
|
|
|
|
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2024
|
2017-03-16 18:09:27 +03:00
|
|
|
|
|
|
|
|
|
#pragma once
|
2019-08-31 17:10:04 +03:00
|
|
|
|
|
2022-06-02 18:59:58 +03:00
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "essentials.h"
|
2019-09-05 11:57:52 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
typedef struct dp dp_t;
|
|
|
|
|
typedef struct dpl dpl_t;
|
|
|
|
|
typedef struct kvx kvx_t;
|
|
|
|
|
typedef struct meta_ptr meta_ptr_t;
|
|
|
|
|
typedef struct inner_cursor subcur_t;
|
|
|
|
|
typedef struct cursor_couple cursor_couple_t;
|
|
|
|
|
typedef struct defer_free_item defer_free_item_t;
|
2019-11-13 20:14:17 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
typedef struct troika {
|
|
|
|
|
uint8_t fsm, recent, prefer_steady, tail_and_flags;
|
|
|
|
|
#if MDBX_WORDBITS > 32 /* Workaround for false-positives from Valgrind */
|
|
|
|
|
uint32_t unused_pad;
|
2021-04-30 02:01:22 +03:00
|
|
|
|
#endif
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#define TROIKA_HAVE_STEADY(troika) ((troika)->fsm & 7u)
|
|
|
|
|
#define TROIKA_STRICT_VALID(troika) ((troika)->tail_and_flags & 64u)
|
|
|
|
|
#define TROIKA_VALID(troika) ((troika)->tail_and_flags & 128u)
|
|
|
|
|
#define TROIKA_TAIL(troika) ((troika)->tail_and_flags & 3u)
|
|
|
|
|
txnid_t txnid[NUM_METAS];
|
|
|
|
|
} troika_t;
|
|
|
|
|
|
|
|
|
|
typedef struct page_get_result {
|
|
|
|
|
page_t *page;
|
|
|
|
|
int err;
|
|
|
|
|
} pgr_t;
|
|
|
|
|
|
|
|
|
|
typedef struct node_search_result {
|
|
|
|
|
node_t *node;
|
|
|
|
|
bool exact;
|
|
|
|
|
} nsr_t;
|
|
|
|
|
|
|
|
|
|
typedef struct bind_reader_slot_result {
|
|
|
|
|
int err;
|
|
|
|
|
reader_slot_t *rslot;
|
|
|
|
|
} bsr_t;
|
|
|
|
|
|
|
|
|
|
#include "atomics-ops.h"
|
|
|
|
|
#include "proto.h"
|
|
|
|
|
#include "txl.h"
|
|
|
|
|
#include "unaligned.h"
|
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
|
#include "windows-import.h"
|
|
|
|
|
#endif /* Windows */
|
2021-04-30 02:01:22 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
enum signatures {
|
|
|
|
|
env_signature = INT32_C(0x1A899641),
|
|
|
|
|
txn_signature = INT32_C(0x13D53A31),
|
|
|
|
|
cur_signature_live = INT32_C(0x7E05D5B1),
|
|
|
|
|
cur_signature_ready4dispose = INT32_C(0x2817A047),
|
|
|
|
|
cur_signature_wait4eot = INT32_C(0x10E297A7)
|
2024-03-25 18:39:56 +03:00
|
|
|
|
};
|
|
|
|
|
|
2017-03-16 18:09:27 +03:00
|
|
|
|
/*----------------------------------------------------------------------------*/
|
2021-04-20 01:36:34 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* An dirty-page list item is an pgno/pointer pair. */
|
|
|
|
|
struct dp {
|
|
|
|
|
page_t *ptr;
|
|
|
|
|
pgno_t pgno, npages;
|
2021-04-20 01:36:34 +03:00
|
|
|
|
};
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
enum dpl_rules {
|
|
|
|
|
dpl_gap_edging = 2,
|
|
|
|
|
dpl_gap_mergesort = 16,
|
|
|
|
|
dpl_reserve_gap = dpl_gap_mergesort + dpl_gap_edging,
|
|
|
|
|
dpl_insertion_threshold = 42
|
|
|
|
|
};
|
2017-03-16 18:09:27 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* An DPL (dirty-page list) is a lazy-sorted array of MDBX_DPs. */
|
|
|
|
|
struct dpl {
|
|
|
|
|
size_t sorted;
|
|
|
|
|
size_t length;
|
|
|
|
|
/* number of pages, but not an entries. */
|
|
|
|
|
size_t pages_including_loose;
|
|
|
|
|
/* allocated size excluding the dpl_reserve_gap */
|
|
|
|
|
size_t detent;
|
|
|
|
|
/* dynamic size with holes at zero and after the last */
|
|
|
|
|
dp_t items[dpl_reserve_gap];
|
|
|
|
|
};
|
2017-06-21 01:19:04 +03:00
|
|
|
|
|
2017-05-24 13:59:50 +03:00
|
|
|
|
/*----------------------------------------------------------------------------*/
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* Internal structures */
|
2017-05-30 16:22:42 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* Comparing/ordering and length constraints */
|
|
|
|
|
typedef struct clc {
|
|
|
|
|
MDBX_cmp_func *cmp; /* comparator */
|
|
|
|
|
size_t lmin, lmax; /* min/max length constraints */
|
|
|
|
|
} clc_t;
|
2017-05-30 16:22:42 +03:00
|
|
|
|
|
2024-08-03 13:25:44 +03:00
|
|
|
|
/* Вспомогательная информация о table.
|
2019-09-02 13:23:39 +03:00
|
|
|
|
*
|
2024-05-19 22:07:58 +03:00
|
|
|
|
* Совокупность потребностей:
|
|
|
|
|
* 1. Для транзакций и основного курсора нужны все поля.
|
|
|
|
|
* 2. Для вложенного dupsort-курсора нужен компаратор значений, который изнутри
|
|
|
|
|
* курсора будет выглядеть как компаратор ключей. Плюс заглушка компаратора
|
|
|
|
|
* значений, которая не должна использоваться в штатных ситуациях, но
|
|
|
|
|
* требуется хотя-бы для отслеживания таких обращений.
|
|
|
|
|
* 3. Использование компараторов для курсора и вложенного dupsort-курсора
|
|
|
|
|
* должно выглядеть одинаково.
|
|
|
|
|
* 4. Желательно минимизировать объём данных размещаемых внутри вложенного
|
|
|
|
|
* dupsort-курсора.
|
|
|
|
|
* 5. Желательно чтобы объем всей структуры был степенью двойки.
|
2019-09-02 13:23:39 +03:00
|
|
|
|
*
|
2024-05-19 22:07:58 +03:00
|
|
|
|
* Решение:
|
|
|
|
|
* - не храним в dupsort-курсоре ничего лишнего, а только tree;
|
|
|
|
|
* - в курсоры помещаем только указатель на clc_t, который будет указывать
|
|
|
|
|
* на соответствующее clc-поле в общей kvx-таблице привязанной к env;
|
|
|
|
|
* - компаратор размещаем в начале clc_t, в kvx_t сначала размещаем clc
|
|
|
|
|
* для ключей, потом для значений, а имя БД в конце kvx_t.
|
|
|
|
|
* - тогда в курсоре clc[0] будет содержать информацию для ключей,
|
|
|
|
|
* а clc[1] для значений, причем компаратор значений для dupsort-курсора
|
|
|
|
|
* будет попадать на MDBX_val с именем, что приведет к SIGSEGV при попытке
|
|
|
|
|
* использования такого компаратора.
|
|
|
|
|
* - размер kvx_t становится равным 8 словам.
|
2019-09-02 13:23:39 +03:00
|
|
|
|
*
|
2024-05-19 22:07:58 +03:00
|
|
|
|
* Трюки и прочая экономия на списках:
|
|
|
|
|
* - не храним dbi внутри курсора, вместо этого вычисляем его как разницу между
|
|
|
|
|
* dbi_state курсора и началом таблицы dbi_state в транзакции. Смысл тут в
|
|
|
|
|
* экономии кол-ва полей при инициализации курсора. Затрат это не создает,
|
|
|
|
|
* так как dbi требуется для последующего доступа к массивам в транзакции,
|
|
|
|
|
* т.е. при вычислении dbi разыменовывается тот-же указатель на txn
|
|
|
|
|
* и читается та же кэш-линия с указателями. */
|
|
|
|
|
typedef struct clc2 {
|
|
|
|
|
clc_t k; /* для ключей */
|
|
|
|
|
clc_t v; /* для значений */
|
|
|
|
|
} clc2_t;
|
|
|
|
|
|
|
|
|
|
struct kvx {
|
|
|
|
|
clc2_t clc;
|
2024-08-03 13:25:44 +03:00
|
|
|
|
MDBX_val name; /* имя table */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
};
|
2017-03-16 18:09:27 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* Non-shared DBI state flags inside transaction */
|
|
|
|
|
enum dbi_state {
|
|
|
|
|
DBI_DIRTY = 0x01 /* DB was written in this txn */,
|
|
|
|
|
DBI_STALE = 0x02 /* Named-DB record is older than txnID */,
|
|
|
|
|
DBI_FRESH = 0x04 /* Named-DB handle opened in this txn */,
|
|
|
|
|
DBI_CREAT = 0x08 /* Named-DB handle created in this txn */,
|
|
|
|
|
DBI_VALID = 0x10 /* Handle is valid, see also DB_VALID */,
|
|
|
|
|
DBI_OLDEN = 0x40 /* Handle was closed/reopened outside txn */,
|
|
|
|
|
DBI_LINDO = 0x80 /* Lazy initialization done for DBI-slot */,
|
|
|
|
|
};
|
2017-03-16 18:09:27 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
enum txn_flags {
|
|
|
|
|
txn_ro_begin_flags = MDBX_TXN_RDONLY | MDBX_TXN_RDONLY_PREPARE,
|
|
|
|
|
txn_rw_begin_flags = MDBX_TXN_NOMETASYNC | MDBX_TXN_NOSYNC | MDBX_TXN_TRY,
|
|
|
|
|
txn_shrink_allowed = UINT32_C(0x40000000),
|
2024-07-09 16:04:01 +03:00
|
|
|
|
txn_parked = MDBX_TXN_PARKED,
|
|
|
|
|
txn_gc_drained = 0x40 /* GC was depleted up to oldest reader */,
|
2024-05-19 22:07:58 +03:00
|
|
|
|
txn_state_flags = MDBX_TXN_FINISHED | MDBX_TXN_ERROR | MDBX_TXN_DIRTY |
|
|
|
|
|
MDBX_TXN_SPILLS | MDBX_TXN_HAS_CHILD | MDBX_TXN_INVALID |
|
|
|
|
|
txn_gc_drained
|
|
|
|
|
};
|
2022-08-17 15:10:05 +03:00
|
|
|
|
|
2017-04-26 18:12:48 +03:00
|
|
|
|
/* A database transaction.
|
|
|
|
|
* Every operation requires a transaction handle. */
|
2017-05-23 21:36:09 +03:00
|
|
|
|
struct MDBX_txn {
|
2024-05-19 22:07:58 +03:00
|
|
|
|
int32_t signature;
|
|
|
|
|
uint32_t flags; /* Transaction Flags */
|
|
|
|
|
size_t n_dbi;
|
|
|
|
|
size_t owner; /* thread ID that owns this transaction */
|
|
|
|
|
|
|
|
|
|
MDBX_txn *parent; /* parent of a nested txn */
|
|
|
|
|
MDBX_txn *nested; /* nested txn under this txn,
|
|
|
|
|
set together with MDBX_TXN_HAS_CHILD */
|
|
|
|
|
geo_t geo;
|
2020-07-05 15:22:41 +03:00
|
|
|
|
|
2022-06-20 20:16:54 +03:00
|
|
|
|
/* The ID of this transaction. IDs are integers incrementing from
|
|
|
|
|
* INITIAL_TXNID. Only committed write transactions increment the ID. If a
|
|
|
|
|
* transaction aborts, the ID may be re-used by the next writer. */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
txnid_t txnid, front_txnid;
|
2021-04-14 01:41:42 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
MDBX_env *env; /* the DB environment */
|
|
|
|
|
tree_t *dbs; /* Array of tree_t records for each known DB */
|
2019-10-17 14:07:47 +03:00
|
|
|
|
|
mdbx: переработка инициализации, проверки и импорта dbi-хендлов в транзакциях.
Ранее инициализация в транзакциях структур данных, связанных с
dbi-хендлами и subDb, выполнялась непосредственно при запуске
транзакций. Что в сценариях с большим кол-вом dbi-дексприторов (например
libfpta) порождало заметные накладные расходы, которые расли линейно от
общего кол-ва открытых subDb, а не от реально используемых в транзакции.
При использовании одной-двух сотен хендлов, при старте каждой транзакции
могли копироваться и/или обнуляться десятки килобайт. Теперь этот
недостаток устранен.
Изменена схема инициализации, валидации и импорта хендлов открытых после
старта транзакции:
1) Инициализация теперь выполняется отложенна, а при старте транзации
обнуляется только массив с однобайтовыми статустами dbi-хендлов.
При этом доступнва опция сборки `MDBX_ENABLE_DBI_SPARSE`, при активации
которой используется битовая карты, что снижает объем инициализации
при старте транзакции в 8 раз (CHAR_BIT).
2) Переработана валидация dbi-хендлов на входах API, с уменьшением кол-ва
проверок и ветвлений до теоретического минимума.
3) Переработ импорт dbi-хендов открытых после старта транзакци, теперь
при этом не захватывается мьютекс.
2023-11-05 22:10:29 +03:00
|
|
|
|
#if MDBX_ENABLE_DBI_SPARSE
|
2024-05-19 22:07:58 +03:00
|
|
|
|
unsigned *__restrict dbi_sparse;
|
mdbx: переработка инициализации, проверки и импорта dbi-хендлов в транзакциях.
Ранее инициализация в транзакциях структур данных, связанных с
dbi-хендлами и subDb, выполнялась непосредственно при запуске
транзакций. Что в сценариях с большим кол-вом dbi-дексприторов (например
libfpta) порождало заметные накладные расходы, которые расли линейно от
общего кол-ва открытых subDb, а не от реально используемых в транзакции.
При использовании одной-двух сотен хендлов, при старте каждой транзакции
могли копироваться и/или обнуляться десятки килобайт. Теперь этот
недостаток устранен.
Изменена схема инициализации, валидации и импорта хендлов открытых после
старта транзакции:
1) Инициализация теперь выполняется отложенна, а при старте транзации
обнуляется только массив с однобайтовыми статустами dbi-хендлов.
При этом доступнва опция сборки `MDBX_ENABLE_DBI_SPARSE`, при активации
которой используется битовая карты, что снижает объем инициализации
при старте транзакции в 8 раз (CHAR_BIT).
2) Переработана валидация dbi-хендлов на входах API, с уменьшением кол-ва
проверок и ветвлений до теоретического минимума.
3) Переработ импорт dbi-хендов открытых после старта транзакци, теперь
при этом не захватывается мьютекс.
2023-11-05 22:10:29 +03:00
|
|
|
|
#endif /* MDBX_ENABLE_DBI_SPARSE */
|
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* Array of non-shared txn's flags of DBI.
|
|
|
|
|
* Модификатор __restrict тут полезен и безопасен в текущем понимании,
|
|
|
|
|
* так как пересечение возможно только с dbi_state курсоров,
|
|
|
|
|
* и происходит по-чтению до последующего изменения/записи. */
|
|
|
|
|
uint8_t *__restrict dbi_state;
|
2023-11-03 11:28:13 +03:00
|
|
|
|
|
|
|
|
|
/* Array of sequence numbers for each DB handle. */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
uint32_t *__restrict dbi_seqs;
|
|
|
|
|
|
|
|
|
|
/* Массив с головами односвязных списков отслеживания курсоров. */
|
|
|
|
|
MDBX_cursor **cursors;
|
2023-11-03 11:28:13 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* "Канареечные" маркеры/счетчики */
|
|
|
|
|
MDBX_canary canary;
|
|
|
|
|
|
|
|
|
|
/* User-settable context */
|
|
|
|
|
void *userctx;
|
2019-10-17 14:07:47 +03:00
|
|
|
|
|
2019-10-08 19:57:17 +03:00
|
|
|
|
union {
|
|
|
|
|
struct {
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* For read txns: This thread/txn's reader table slot, or nullptr. */
|
|
|
|
|
reader_slot_t *reader;
|
2019-10-08 19:57:17 +03:00
|
|
|
|
} to;
|
|
|
|
|
struct {
|
2024-05-19 22:07:58 +03:00
|
|
|
|
troika_t troika;
|
2020-11-09 01:38:46 +03:00
|
|
|
|
/* In write txns, array of cursors for each DB */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
pnl_t __restrict relist; /* Reclaimed GC pages */
|
|
|
|
|
struct {
|
|
|
|
|
/* The list of reclaimed txns from GC */
|
|
|
|
|
txl_t __restrict reclaimed;
|
|
|
|
|
txnid_t last_reclaimed; /* ID of last used record */
|
|
|
|
|
uint64_t time_acc;
|
|
|
|
|
} gc;
|
2021-01-18 17:34:54 +03:00
|
|
|
|
#if MDBX_ENABLE_REFUND
|
2019-10-17 10:08:49 +03:00
|
|
|
|
pgno_t loose_refund_wl /* FIXME: describe */;
|
2021-01-18 17:34:54 +03:00
|
|
|
|
#endif /* MDBX_ENABLE_REFUND */
|
2022-09-29 16:18:10 +03:00
|
|
|
|
/* a sequence to spilling dirty page with LRU policy */
|
|
|
|
|
unsigned dirtylru;
|
2019-10-17 10:08:49 +03:00
|
|
|
|
/* dirtylist room: Dirty array size - dirty pages visible to this txn.
|
|
|
|
|
* Includes ancestor txns' dirty pages not hidden by other txns'
|
|
|
|
|
* dirty/spilled pages. Thus commit(nested txn) has room to merge
|
2024-05-19 22:07:58 +03:00
|
|
|
|
* dirtylist into parent after freeing hidden parent pages. */
|
2022-09-29 16:18:10 +03:00
|
|
|
|
size_t dirtyroom;
|
2019-10-17 10:08:49 +03:00
|
|
|
|
/* For write txns: Modified pages. Sorted when not MDBX_WRITEMAP. */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
dpl_t *__restrict dirtylist;
|
2019-10-08 19:57:17 +03:00
|
|
|
|
/* The list of pages that became unused during this transaction. */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
pnl_t __restrict retired_pages;
|
2019-10-08 19:57:17 +03:00
|
|
|
|
/* The list of loose pages that became unused and may be reused
|
2024-05-19 22:07:58 +03:00
|
|
|
|
* in this transaction, linked through `page_next()`. */
|
|
|
|
|
page_t *__restrict loose_pages;
|
2019-10-08 19:57:17 +03:00
|
|
|
|
/* Number of loose pages (tw.loose_pages) */
|
2022-09-29 16:18:10 +03:00
|
|
|
|
size_t loose_count;
|
2022-11-13 20:59:31 +03:00
|
|
|
|
union {
|
|
|
|
|
struct {
|
|
|
|
|
size_t least_removed;
|
|
|
|
|
/* The sorted list of dirty pages we temporarily wrote to disk
|
|
|
|
|
* because the dirty list was full. page numbers in here are
|
|
|
|
|
* shifted left by 1, deleted slots have the LSB set. */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
pnl_t __restrict list;
|
2022-11-13 20:59:31 +03:00
|
|
|
|
} spilled;
|
|
|
|
|
size_t writemap_dirty_npages;
|
2022-12-14 11:43:22 +03:00
|
|
|
|
size_t writemap_spilled_npages;
|
2022-11-13 20:59:31 +03:00
|
|
|
|
};
|
2019-10-08 19:57:17 +03:00
|
|
|
|
} tw;
|
|
|
|
|
};
|
2017-03-16 18:09:27 +03:00
|
|
|
|
};
|
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#define CURSOR_STACK_SIZE (16 + MDBX_WORDBITS / 4)
|
|
|
|
|
|
|
|
|
|
struct MDBX_cursor {
|
|
|
|
|
int32_t signature;
|
|
|
|
|
union {
|
|
|
|
|
/* Тут некоторые трюки/заморочки с тем чтобы во всех основных сценариях
|
|
|
|
|
* проверять состояние курсора одной простой операцией сравнения,
|
|
|
|
|
* и при этом ни на каплю не усложнять код итерации стека курсора.
|
|
|
|
|
*
|
|
|
|
|
* Поэтому решение такое:
|
|
|
|
|
* - поля flags и top сделаны знаковыми, а их отрицательные значения
|
|
|
|
|
* используются для обозначения не-установленного/не-инициализированного
|
|
|
|
|
* состояния курсора;
|
|
|
|
|
* - для инвалидации/сброса курсора достаточно записать отрицательное
|
|
|
|
|
* значение в объединенное поле top_and_flags;
|
|
|
|
|
* - все проверки состояния сводятся к сравнению одного из полей
|
|
|
|
|
* flags/snum/snum_and_flags, которые в зависимости от сценария,
|
|
|
|
|
* трактуются либо как знаковые, либо как безнаковые. */
|
|
|
|
|
__anonymous_struct_extension__ struct {
|
|
|
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
|
|
|
int8_t flags;
|
|
|
|
|
/* индекс вершины стека, меньше нуля для не-инициализированного курсора */
|
|
|
|
|
int8_t top;
|
2019-10-22 00:31:15 +03:00
|
|
|
|
#else
|
2024-05-19 22:07:58 +03:00
|
|
|
|
int8_t top;
|
|
|
|
|
int8_t flags;
|
2019-10-22 00:31:15 +03:00
|
|
|
|
#endif
|
2024-05-19 22:07:58 +03:00
|
|
|
|
};
|
|
|
|
|
int16_t top_and_flags;
|
|
|
|
|
};
|
|
|
|
|
/* флаги проверки, в том числе биты для проверки типа листовых страниц. */
|
|
|
|
|
uint8_t checking;
|
|
|
|
|
|
|
|
|
|
/* Указывает на txn->dbi_state[] для DBI этого курсора.
|
|
|
|
|
* Модификатор __restrict тут полезен и безопасен в текущем понимании,
|
|
|
|
|
* так как пересечение возможно только с dbi_state транзакции,
|
|
|
|
|
* и происходит по-чтению до последующего изменения/записи. */
|
|
|
|
|
uint8_t *__restrict dbi_state;
|
|
|
|
|
/* Связь списка отслеживания курсоров в транзакции */
|
|
|
|
|
MDBX_txn *txn;
|
|
|
|
|
/* Указывает на tree->dbs[] для DBI этого курсора. */
|
|
|
|
|
tree_t *tree;
|
|
|
|
|
/* Указывает на env->kvs[] для DBI этого курсора. */
|
|
|
|
|
clc2_t *clc;
|
|
|
|
|
subcur_t *__restrict subcur;
|
|
|
|
|
page_t *pg[CURSOR_STACK_SIZE]; /* stack of pushed pages */
|
|
|
|
|
indx_t ki[CURSOR_STACK_SIZE]; /* stack of page indices */
|
|
|
|
|
MDBX_cursor *next;
|
|
|
|
|
/* Состояние на момент старта вложенной транзакции */
|
|
|
|
|
MDBX_cursor *backup;
|
|
|
|
|
};
|
2017-03-16 18:09:27 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
struct inner_cursor {
|
|
|
|
|
MDBX_cursor cursor;
|
|
|
|
|
tree_t nested_tree;
|
2017-03-16 18:09:27 +03:00
|
|
|
|
};
|
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
struct cursor_couple {
|
2018-08-29 19:15:59 +03:00
|
|
|
|
MDBX_cursor outer;
|
2024-05-19 22:07:58 +03:00
|
|
|
|
void *userctx; /* User-settable context */
|
|
|
|
|
subcur_t inner;
|
|
|
|
|
};
|
2018-08-29 19:15:59 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
struct defer_free_item {
|
|
|
|
|
struct defer_free_item *next;
|
2023-11-04 23:45:29 +03:00
|
|
|
|
uint64_t timestamp;
|
|
|
|
|
};
|
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
enum env_flags {
|
2019-10-22 22:31:06 +03:00
|
|
|
|
/* Failed to update the meta page. Probably an I/O error. */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
ENV_FATAL_ERROR = INT32_MIN /* 0x80000000 */,
|
2019-10-22 22:31:06 +03:00
|
|
|
|
/* Some fields are initialized. */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
ENV_ACTIVE = UINT32_C(0x20000000),
|
2019-10-22 22:31:06 +03:00
|
|
|
|
/* me_txkey is set */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
ENV_TXKEY = UINT32_C(0x10000000),
|
2020-08-01 19:13:17 +03:00
|
|
|
|
/* Legacy MDBX_MAPASYNC (prior v0.9) */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
DEPRECATED_MAPASYNC = UINT32_C(0x100000),
|
2022-07-24 21:20:22 +03:00
|
|
|
|
/* Legacy MDBX_COALESCE (prior v0.12) */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
DEPRECATED_COALESCE = UINT32_C(0x2000000),
|
|
|
|
|
ENV_INTERNAL_FLAGS = ENV_FATAL_ERROR | ENV_ACTIVE | ENV_TXKEY,
|
|
|
|
|
/* Only a subset of the mdbx_env flags can be changed
|
|
|
|
|
* at runtime. Changing other flags requires closing the
|
|
|
|
|
* environment and re-opening it with the new flags. */
|
|
|
|
|
ENV_CHANGEABLE_FLAGS = MDBX_SAFE_NOSYNC | MDBX_NOMETASYNC |
|
|
|
|
|
DEPRECATED_MAPASYNC | MDBX_NOMEMINIT |
|
|
|
|
|
DEPRECATED_COALESCE | MDBX_PAGEPERTURB | MDBX_ACCEDE |
|
|
|
|
|
MDBX_VALIDATION,
|
|
|
|
|
ENV_CHANGELESS_FLAGS = MDBX_NOSUBDIR | MDBX_RDONLY | MDBX_WRITEMAP |
|
|
|
|
|
MDBX_NOSTICKYTHREADS | MDBX_NORDAHEAD |
|
|
|
|
|
MDBX_LIFORECLAIM | MDBX_EXCLUSIVE,
|
|
|
|
|
ENV_USABLE_FLAGS = ENV_CHANGEABLE_FLAGS | ENV_CHANGELESS_FLAGS
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* The database environment. */
|
|
|
|
|
struct MDBX_env {
|
|
|
|
|
/* ----------------------------------------------------- mostly static part */
|
|
|
|
|
mdbx_atomic_uint32_t signature;
|
|
|
|
|
uint32_t flags;
|
|
|
|
|
unsigned ps; /* DB page size, initialized from me_os_psize */
|
|
|
|
|
osal_mmap_t dxb_mmap; /* The main data file */
|
|
|
|
|
#define lazy_fd dxb_mmap.fd
|
|
|
|
|
mdbx_filehandle_t dsync_fd, fd4meta;
|
2022-09-25 12:47:31 +03:00
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
2024-05-19 22:07:58 +03:00
|
|
|
|
HANDLE dxb_lock_event;
|
|
|
|
|
#endif /* Windows */
|
|
|
|
|
osal_mmap_t lck_mmap; /* The lock file */
|
|
|
|
|
lck_t *lck;
|
|
|
|
|
|
|
|
|
|
uint16_t leaf_nodemax; /* max size of a leaf-node */
|
|
|
|
|
uint16_t branch_nodemax; /* max size of a branch-node */
|
|
|
|
|
uint16_t subpage_limit;
|
|
|
|
|
uint16_t subpage_room_threshold;
|
|
|
|
|
uint16_t subpage_reserve_prereq;
|
|
|
|
|
uint16_t subpage_reserve_limit;
|
|
|
|
|
atomic_pgno_t mlocked_pgno;
|
|
|
|
|
uint8_t ps2ln; /* log2 of DB page size */
|
|
|
|
|
int8_t stuck_meta; /* recovery-only: target meta page or less that zero */
|
|
|
|
|
uint16_t merge_threshold, merge_threshold_gc; /* pages emptier than this are
|
|
|
|
|
candidates for merging */
|
|
|
|
|
unsigned max_readers; /* size of the reader table */
|
|
|
|
|
MDBX_dbi max_dbi; /* size of the DB table */
|
|
|
|
|
uint32_t pid; /* process ID of this env */
|
|
|
|
|
osal_thread_key_t me_txkey; /* thread-key for readers */
|
|
|
|
|
struct { /* path to the DB files */
|
2023-11-11 20:16:06 +03:00
|
|
|
|
pathchar_t *lck, *dxb, *specified;
|
|
|
|
|
void *buffer;
|
2024-05-19 22:07:58 +03:00
|
|
|
|
} pathname;
|
|
|
|
|
void *page_auxbuf; /* scratch area for DUPSORT put() */
|
|
|
|
|
MDBX_txn *basal_txn; /* preallocated write transaction */
|
|
|
|
|
kvx_t *kvs; /* array of auxiliary key-value properties */
|
|
|
|
|
uint8_t *__restrict dbs_flags; /* array of flags from tree_t.flags */
|
|
|
|
|
mdbx_atomic_uint32_t *dbi_seqs; /* array of dbi sequence numbers */
|
|
|
|
|
unsigned maxgc_large1page; /* Number of pgno_t fit in a single large page */
|
|
|
|
|
unsigned maxgc_per_branch;
|
|
|
|
|
uint32_t registered_reader_pid; /* have liveness lock in reader table */
|
|
|
|
|
void *userctx; /* User-settable context */
|
|
|
|
|
MDBX_hsr_func *hsr_callback; /* Callback for kicking laggard readers */
|
|
|
|
|
size_t madv_threshold;
|
2021-04-28 03:44:54 +03:00
|
|
|
|
|
2020-11-21 16:21:57 +03:00
|
|
|
|
struct {
|
|
|
|
|
unsigned dp_reserve_limit;
|
2020-11-21 17:53:17 +03:00
|
|
|
|
unsigned rp_augment_limit;
|
2020-12-02 15:18:54 +03:00
|
|
|
|
unsigned dp_limit;
|
|
|
|
|
unsigned dp_initial;
|
2023-11-29 00:35:25 +03:00
|
|
|
|
uint64_t gc_time_limit;
|
2021-01-22 23:52:03 +03:00
|
|
|
|
uint8_t dp_loose_limit;
|
2021-01-22 17:25:44 +03:00
|
|
|
|
uint8_t spill_max_denominator;
|
|
|
|
|
uint8_t spill_min_denominator;
|
2021-01-22 18:18:52 +03:00
|
|
|
|
uint8_t spill_parent4child_denominator;
|
2021-05-06 02:05:33 +03:00
|
|
|
|
unsigned merge_threshold_16dot16_percent;
|
2022-12-03 14:55:38 +03:00
|
|
|
|
#if !(defined(_WIN32) || defined(_WIN64))
|
|
|
|
|
unsigned writethrough_threshold;
|
|
|
|
|
#endif /* Windows */
|
2022-12-12 01:20:22 +03:00
|
|
|
|
bool prefault_write;
|
mdbx: доработка `rebalance()` ради уменьшения WAF.
После предыдущей серии доработок весной 2021 года, функция `rebalance()`
обеспечивала слияние мало заполненной страницы с менее заполненной
соседней, одновременно пытаясь не вовлекать соседних страниц, если те
еще не были скопированы/клонированы/изменены в текущей транзакции.
В целом, реализованная тактика представляется успешной. Однако, при
обновлении GC она иногда приводила к исчерпанию подготовленного резерва
извлеченных из GC страниц. Это не является проблемой, если не считать
вероятность срабатывания `assert(txn->mt_flags & MDBX_TXN_DRAINED_GC)`
в отладочных сборках.
Тем не менее, из этой ситуации можно сделать вывод, что поведение
`rebalance()`, как минимум, может быть обогащено опцией уменьшения WAF
ценой меньшей сбалансированности дерева. Технически при этом слияние
выполняется преимущественно с грязной страницей, если на ней достаточно
места и соседняя страница с другой стороны еще чистая.
Соответствующая опция в `enum MDBX_option_t` будет добавлена чуть позже.
2024-02-29 09:19:54 +03:00
|
|
|
|
bool prefer_waf_insteadof_balance; /* Strive to minimize WAF instead of
|
|
|
|
|
balancing pages fullment */
|
2024-05-20 14:36:50 +03:00
|
|
|
|
struct {
|
|
|
|
|
uint16_t limit;
|
|
|
|
|
uint16_t room_threshold;
|
|
|
|
|
uint16_t reserve_prereq;
|
|
|
|
|
uint16_t reserve_limit;
|
|
|
|
|
} subpage;
|
|
|
|
|
|
2021-04-27 23:08:52 +03:00
|
|
|
|
union {
|
|
|
|
|
unsigned all;
|
|
|
|
|
/* tracks options with non-auto values but tuned by user */
|
|
|
|
|
struct {
|
|
|
|
|
unsigned dp_limit : 1;
|
2022-12-08 15:35:41 +03:00
|
|
|
|
unsigned rp_augment_limit : 1;
|
2022-12-12 01:20:22 +03:00
|
|
|
|
unsigned prefault_write : 1;
|
2021-04-27 23:08:52 +03:00
|
|
|
|
} non_auto;
|
|
|
|
|
} flags;
|
2024-05-19 22:07:58 +03:00
|
|
|
|
} options;
|
2021-04-27 01:03:33 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* struct geo_in_bytes used for accepting db-geo params from user for the new
|
2021-04-27 01:03:33 +03:00
|
|
|
|
* database creation, i.e. when mdbx_env_set_geometry() was called before
|
|
|
|
|
* mdbx_env_open(). */
|
|
|
|
|
struct {
|
|
|
|
|
size_t lower; /* minimal size of datafile */
|
|
|
|
|
size_t upper; /* maximal size of datafile */
|
|
|
|
|
size_t now; /* current size of datafile */
|
|
|
|
|
size_t grow; /* step to grow datafile */
|
|
|
|
|
size_t shrink; /* threshold to shrink datafile */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
} geo_in_bytes;
|
2021-04-27 01:03:33 +03:00
|
|
|
|
|
|
|
|
|
#if MDBX_LOCKING == MDBX_LOCKING_SYSV
|
|
|
|
|
union {
|
|
|
|
|
key_t key;
|
|
|
|
|
int semid;
|
|
|
|
|
} me_sysv_ipc;
|
|
|
|
|
#endif /* MDBX_LOCKING == MDBX_LOCKING_SYSV */
|
2024-05-19 22:07:58 +03:00
|
|
|
|
bool incore;
|
|
|
|
|
bool prefault_write_activated;
|
2021-04-27 01:03:33 +03:00
|
|
|
|
|
2023-11-04 23:45:29 +03:00
|
|
|
|
#if MDBX_ENABLE_DBI_LOCKFREE
|
2024-05-19 22:07:58 +03:00
|
|
|
|
defer_free_item_t *defer_free;
|
2023-11-04 23:45:29 +03:00
|
|
|
|
#endif /* MDBX_ENABLE_DBI_LOCKFREE */
|
2021-04-27 01:03:33 +03:00
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------- debugging */
|
|
|
|
|
|
2017-06-14 23:33:13 +03:00
|
|
|
|
#if MDBX_DEBUG
|
2024-05-19 22:07:58 +03:00
|
|
|
|
MDBX_assert_func *assert_func; /* Callback for assertion failures */
|
2017-06-14 23:33:13 +03:00
|
|
|
|
#endif
|
2023-11-02 16:54:32 +03:00
|
|
|
|
#ifdef ENABLE_MEMCHECK
|
2024-05-19 22:07:58 +03:00
|
|
|
|
int valgrind_handle;
|
2019-10-10 22:11:28 +03:00
|
|
|
|
#endif
|
2023-11-02 16:54:32 +03:00
|
|
|
|
#if defined(ENABLE_MEMCHECK) || defined(__SANITIZE_ADDRESS__)
|
2024-05-19 22:07:58 +03:00
|
|
|
|
pgno_t poison_edge;
|
2023-11-02 16:54:32 +03:00
|
|
|
|
#endif /* ENABLE_MEMCHECK || __SANITIZE_ADDRESS__ */
|
2021-04-28 03:44:54 +03:00
|
|
|
|
|
2021-04-29 19:50:25 +03:00
|
|
|
|
#ifndef xMDBX_DEBUG_SPILLING
|
|
|
|
|
#define xMDBX_DEBUG_SPILLING 0
|
2021-04-28 18:03:35 +03:00
|
|
|
|
#endif
|
2021-04-29 19:50:25 +03:00
|
|
|
|
#if xMDBX_DEBUG_SPILLING == 2
|
2022-10-08 15:02:45 +03:00
|
|
|
|
size_t debug_dirtied_est, debug_dirtied_act;
|
2021-04-29 19:50:25 +03:00
|
|
|
|
#endif /* xMDBX_DEBUG_SPILLING */
|
2021-04-28 18:03:35 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* --------------------------------------------------- mostly volatile part */
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
MDBX_txn *txn; /* current write transaction */
|
|
|
|
|
osal_fastmutex_t dbi_lock;
|
|
|
|
|
unsigned n_dbi; /* number of DBs opened */
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
unsigned shadow_reserve_len;
|
|
|
|
|
page_t *__restrict shadow_reserve; /* list of malloc'ed blocks for re-use */
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
osal_ioring_t ioring;
|
2021-03-27 12:28:23 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
|
osal_srwlock_t remap_guard;
|
|
|
|
|
/* Workaround for LockFileEx and WriteFile multithread bug */
|
|
|
|
|
CRITICAL_SECTION windowsbug_lock;
|
|
|
|
|
char *pathname_char; /* cache of multi-byte representation of pathname
|
|
|
|
|
to the DB files */
|
2017-05-24 13:59:50 +03:00
|
|
|
|
#else
|
2024-05-19 22:07:58 +03:00
|
|
|
|
osal_fastmutex_t remap_guard;
|
2017-05-24 13:59:50 +03:00
|
|
|
|
#endif
|
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* ------------------------------------------------- stub for lck-less mode */
|
|
|
|
|
mdbx_atomic_uint64_t
|
|
|
|
|
lckless_placeholder[(sizeof(lck_t) + MDBX_CACHELINE_SIZE - 1) /
|
|
|
|
|
sizeof(mdbx_atomic_uint64_t)];
|
|
|
|
|
};
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/*----------------------------------------------------------------------------*/
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* pseudo-error code, not exposed outside libmdbx */
|
|
|
|
|
#define MDBX_NO_ROOT (MDBX_LAST_ADDED_ERRCODE + 33)
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
|
|
|
|
/* Number of slots in the reader table.
|
|
|
|
|
* This value was chosen somewhat arbitrarily. The 61 is a prime number,
|
|
|
|
|
* and such readers plus a couple mutexes fit into single 4KB page.
|
|
|
|
|
* Applications should set the table size using mdbx_env_set_maxreaders(). */
|
|
|
|
|
#define DEFAULT_READERS 61
|
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
enum db_flags {
|
|
|
|
|
DB_PERSISTENT_FLAGS = MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_INTEGERKEY |
|
|
|
|
|
MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP,
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/* mdbx_dbi_open() flags */
|
|
|
|
|
DB_USABLE_FLAGS = DB_PERSISTENT_FLAGS | MDBX_CREATE | MDBX_DB_ACCEDE,
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
DB_VALID = 0x80u /* DB handle is valid, for dbs_flags */,
|
|
|
|
|
DB_POISON = 0x7fu /* update pending */,
|
|
|
|
|
DB_INTERNAL_FLAGS = DB_VALID
|
|
|
|
|
};
|
2020-07-30 14:52:27 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#if !defined(__cplusplus) || CONSTEXPR_ENUM_FLAGS_OPERATIONS
|
|
|
|
|
MDBX_MAYBE_UNUSED static void static_checks(void) {
|
|
|
|
|
STATIC_ASSERT(MDBX_WORDBITS == sizeof(void *) * CHAR_BIT);
|
|
|
|
|
STATIC_ASSERT(UINT64_C(0x80000000) == (uint32_t)ENV_FATAL_ERROR);
|
|
|
|
|
STATIC_ASSERT_MSG(INT16_MAX - CORE_DBS == MDBX_MAX_DBI,
|
|
|
|
|
"Oops, MDBX_MAX_DBI or CORE_DBS?");
|
|
|
|
|
STATIC_ASSERT_MSG((unsigned)(MDBX_DB_ACCEDE | MDBX_CREATE) ==
|
|
|
|
|
((DB_USABLE_FLAGS | DB_INTERNAL_FLAGS) &
|
|
|
|
|
(ENV_USABLE_FLAGS | ENV_INTERNAL_FLAGS)),
|
|
|
|
|
"Oops, some flags overlapped or wrong");
|
|
|
|
|
STATIC_ASSERT_MSG((DB_INTERNAL_FLAGS & DB_USABLE_FLAGS) == 0,
|
|
|
|
|
"Oops, some flags overlapped or wrong");
|
|
|
|
|
STATIC_ASSERT_MSG((DB_PERSISTENT_FLAGS & ~DB_USABLE_FLAGS) == 0,
|
|
|
|
|
"Oops, some flags overlapped or wrong");
|
|
|
|
|
STATIC_ASSERT(DB_PERSISTENT_FLAGS <= UINT8_MAX);
|
|
|
|
|
STATIC_ASSERT_MSG((ENV_INTERNAL_FLAGS & ENV_USABLE_FLAGS) == 0,
|
|
|
|
|
"Oops, some flags overlapped or wrong");
|
2017-05-24 13:59:50 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
STATIC_ASSERT_MSG(
|
|
|
|
|
(txn_state_flags & (txn_rw_begin_flags | txn_ro_begin_flags)) == 0,
|
|
|
|
|
"Oops, some txn flags overlapped or wrong");
|
|
|
|
|
STATIC_ASSERT_MSG(
|
|
|
|
|
((txn_rw_begin_flags | txn_ro_begin_flags | txn_state_flags) &
|
|
|
|
|
txn_shrink_allowed) == 0,
|
|
|
|
|
"Oops, some txn flags overlapped or wrong");
|
2020-07-05 15:22:41 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
STATIC_ASSERT(sizeof(reader_slot_t) == 32);
|
|
|
|
|
#if MDBX_LOCKING > 0
|
|
|
|
|
STATIC_ASSERT(offsetof(lck_t, wrt_lock) % MDBX_CACHELINE_SIZE == 0);
|
|
|
|
|
STATIC_ASSERT(offsetof(lck_t, rdt_lock) % MDBX_CACHELINE_SIZE == 0);
|
|
|
|
|
#else
|
|
|
|
|
STATIC_ASSERT(offsetof(lck_t, cached_oldest) % MDBX_CACHELINE_SIZE == 0);
|
|
|
|
|
STATIC_ASSERT(offsetof(lck_t, rdt_length) % MDBX_CACHELINE_SIZE == 0);
|
|
|
|
|
#endif /* MDBX_LOCKING */
|
|
|
|
|
STATIC_ASSERT(offsetof(lck_t, rdt) % MDBX_CACHELINE_SIZE == 0);
|
2020-07-05 15:22:41 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#if FLEXIBLE_ARRAY_MEMBERS
|
|
|
|
|
STATIC_ASSERT(NODESIZE == offsetof(node_t, payload));
|
|
|
|
|
STATIC_ASSERT(PAGEHDRSZ == offsetof(page_t, entries));
|
|
|
|
|
#endif /* FLEXIBLE_ARRAY_MEMBERS */
|
|
|
|
|
STATIC_ASSERT(sizeof(clc_t) == 3 * sizeof(void *));
|
|
|
|
|
STATIC_ASSERT(sizeof(kvx_t) == 8 * sizeof(void *));
|
2020-07-05 15:22:41 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#if MDBX_WORDBITS == 64
|
|
|
|
|
#define KVX_SIZE_LN2 6
|
|
|
|
|
#else
|
|
|
|
|
#define KVX_SIZE_LN2 5
|
2020-07-05 15:22:41 +03:00
|
|
|
|
#endif
|
2024-05-19 22:07:58 +03:00
|
|
|
|
STATIC_ASSERT(sizeof(kvx_t) == (1u << KVX_SIZE_LN2));
|
2017-07-26 10:28:09 +03:00
|
|
|
|
}
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#endif /* Disabled for MSVC 19.0 (VisualStudio 2015) */
|
2017-07-26 10:19:05 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
/******************************************************************************/
|
2022-01-21 02:14:36 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "node.h"
|
2017-07-24 00:54:10 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "dbi.h"
|
2020-02-02 20:41:04 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "cogs.h"
|
2020-04-07 03:21:32 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "cursor.h"
|
2020-07-08 02:26:46 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "dpl.h"
|
2021-04-07 01:45:14 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "gc.h"
|
2020-07-08 02:26:46 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "lck.h"
|
2020-08-22 20:19:46 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "meta.h"
|
2021-07-16 14:59:37 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "page-iov.h"
|
2021-07-16 14:59:37 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "spill.h"
|
2023-04-24 20:59:18 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "page-ops.h"
|
2023-04-24 20:59:18 +03:00
|
|
|
|
|
2024-05-19 22:07:58 +03:00
|
|
|
|
#include "tls.h"
|
|
|
|
|
|
|
|
|
|
#include "walk.h"
|
|
|
|
|
|
|
|
|
|
#include "sort.h"
|