mirror of
https://github.com/isar/libmdbx.git
synced 2025-12-15 04:32:21 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b12e7323f | ||
|
|
45aa39c68b | ||
|
|
d02bdcf2bd | ||
|
|
5561cec9c5 | ||
|
|
ff6674b377 | ||
|
|
ca6f04c52a | ||
|
|
db6cf469c9 | ||
|
|
d516e903d4 | ||
|
|
7aaae2ecd5 | ||
|
|
bf1c753be3 | ||
|
|
79edab2adf | ||
|
|
37792cc568 | ||
|
|
e8d2a5bd09 | ||
|
|
2c2612ba23 | ||
|
|
60b483025c | ||
|
|
2abf80a199 | ||
|
|
4fd21d2f7b |
84
ChangeLog.md
84
ChangeLog.md
@@ -5,6 +5,86 @@ English version [by Google](https://gitflic-ru.translate.goog/project/erthink/li
|
||||
and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/gitflic.ru/project/erthink/libmdbx/blob?file=ChangeLog.md).
|
||||
|
||||
|
||||
## v0.12.7 "Артек" от 2023-06-16
|
||||
|
||||
Стабилизирующий выпуск с исправлением обнаруженных ошибок и устранением
|
||||
недочетов, в день основания международного детского центра [«Арте́к»](https://ru.wikipedia.org/wiki/Артек).
|
||||
|
||||
```
|
||||
14 files changed, 222 insertions(+), 56 deletions(-)
|
||||
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
|
||||
```
|
||||
|
||||
Исправления и доработки:
|
||||
|
||||
- Исправление опечатки в имени переменной внутри `mdbx_env_turn_for_recovery()`,
|
||||
что приводило к неверному поведению в некоторых ситуациях.
|
||||
|
||||
С точки зрения пользователя, с учетом актуальных сценариев использования
|
||||
утилиты `mdbx_chk`, был только один специфический/редкий сценарий
|
||||
проявления ошибки/проблемы - когда выполнялась проверка и активация
|
||||
слабой/weak мета-страницы с НЕ-последней транзакцией после системной
|
||||
аварии машины, где БД использовалась в хрупком/небезопасном режиме.
|
||||
В сценарии, при успешной проверке целевой страницы и её последующей
|
||||
активации выводилось сообщение об ошибке, связанной со срабатыванием
|
||||
механизма контроля не-когерентности кэша файловой системы и отображенных
|
||||
в ОЗУ данных БД. При этом БД успешно восстанавливалось и не было
|
||||
каких-либо негативных последствия, кроме самого сообщения об ошибке.
|
||||
|
||||
Технически же ошибка проявлялась при "переключении" на мета-страницу,
|
||||
когда у хотя-бы одной из двух других мета-страниц номер транзакции был
|
||||
больше:
|
||||
|
||||
* Если содержимое других мета-страниц было корректным, а номера
|
||||
связанных транзакций были больше, то результирующий номер транзакции в
|
||||
целевой/активируемой мета-страницы устанавливается без учета этих
|
||||
мета-страниц и мог быть меньше-или-равным.
|
||||
|
||||
* В результате, если такие мета-страницы были в статусе слабых/weak, то
|
||||
при закрытии БД после переключения могла срабатывать защита от
|
||||
не-когерентности unified buffer/page cache, а в отладочных сборках могла
|
||||
срабатывать assert-проверка.
|
||||
|
||||
* Если же такие мета-страницы были в статусе сильных/steady, то
|
||||
переключение на новую мета-страницу могло не давать эффекта либо
|
||||
приводить к появлению двух мета-страниц с одинаковым номером транзакции,
|
||||
что является ошибочной ситуацией.
|
||||
|
||||
- Обходное решение проблем сборки посредством GCC с использование опций `-m32 -arch=i686 -Ofast`.
|
||||
Проблема обусловлена ошибкой GCC, из-за которой конструкция `__attribute__((__target__("sse2")))`
|
||||
не включает полноценное использование инструкций SSE и SSE2, если это не было сделано посредством
|
||||
опций командной строки, но была использована опция `-Ofast`. В результате сборка заканчивалась
|
||||
сообщением об ошибке:
|
||||
`error: inlining failed in call to 'always_inline' '_mm_movemask_ps': target specific option mismatch`
|
||||
|
||||
- Доработка режима "восстановления" БД и переключения на заданную мета-страницу:
|
||||
* Устранение обновления без необходимости мета-страницы с увеличением номера транзакции;
|
||||
* Устранение вывода (логирования) бессмысленного/лишнего предупреждения о пропуске обновления геометрии БД;
|
||||
* Более ожидаемое и безопасное поведение при проверке БД с указанием целевой мета-страницы в режиме чтения-записи.
|
||||
|
||||
Теперь при открытии БД посредством `mdbx_env_open_for_recovery()` не
|
||||
выполняется неявное изменение/обновление БД, в том числе при закрытии
|
||||
БД. Это позволяет обезопасить БД (снизить шанс её разрушения) если
|
||||
пользователь при попытке восстановления, либо просто в качестве
|
||||
эксперимента, задал утилите `mdbx_chk` неверную или опасную комбинацию
|
||||
параметров. При этом обычная проверка, как и явное переключение
|
||||
мета-страниц, работают по-прежнему.
|
||||
|
||||
Мелочи:
|
||||
|
||||
- Незначительное уточнение CMake-пробника для `std::filesystem`,
|
||||
проверяющего необходимость линковки с дополнительными библиотеками C++.
|
||||
- Устранение минорных предупреждений старых компиляторов в тестах.
|
||||
- Устранение причины ложно-позитивного предупреждения новых версий GCC в C++ API.
|
||||
- Исправление ссылки на репозиторий бенчмарка ioarena.
|
||||
- Добавление перекрестных ссылок в doxygen-документацию по C++ API.
|
||||
- Уточнение ограничений в разделе [Restrictions & Caveats](https://libmdbx.dqdkfa.ru/intro.html#restrictions).
|
||||
- Исправление ссылок на описание `mdbx_canary_put()`.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
## v0.12.6 "ЦСКА" от 2023-04-29
|
||||
|
||||
Стабилизирующий выпуск с исправлением обнаруженных ошибок и устранением
|
||||
@@ -354,7 +434,7 @@ Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
|
||||
суммарный размер пары ключ-значение.
|
||||
|
||||
- Реализовано использование асинхронной (overlapped) записи в Windows,
|
||||
включая использования небуфферизированного ввода-вывода и `WriteGather()`.
|
||||
включая использования небуферизированного ввода-вывода и `WriteGather()`.
|
||||
Это позволяет сократить накладные расходы и частично обойти проблемы
|
||||
Windows с низкой производительностью ввода-вывода, включая большие
|
||||
задержки `FlushFileBuffers()`. Новый код также обеспечивает консолидацию
|
||||
@@ -483,7 +563,7 @@ New:
|
||||
- Added the `gcrtime_seconds16dot16` counter to the "Page Operation Statistics" that accumulates time spent for GC searching and reclaiming.
|
||||
- Copy-with-compactification now clears/zeroes unused gaps inside database pages.
|
||||
- The `C` and `C++` APIs has been extended and/or refined to simplify using `wchar_t` pathnames.
|
||||
On Windows the `mdbx_env_openW()`, ``mdbx_env_get_pathW()`()`, `mdbx_env_copyW()`, `mdbx_env_open_for_recoveryW()` are available for now,
|
||||
On Windows the `mdbx_env_openW()`, `mdbx_env_get_pathW()`, `mdbx_env_copyW()`, `mdbx_env_open_for_recoveryW()` are available for now,
|
||||
but the `mdbx_env_get_path()` has been replaced in favor of `mdbx_env_get_pathW()`.
|
||||
- Added explicit error message for Buildroot's Microblaze toolchain maintainers.
|
||||
- Added `MDBX_MANAGE_BUILD_FLAGS` build options for CMake.
|
||||
|
||||
@@ -277,7 +277,7 @@ the user's point of view.
|
||||
> and up to 30% faster when _libmdbx_ compiled with specific build options
|
||||
> which downgrades several runtime checks to be match with LMDB behaviour.
|
||||
>
|
||||
> These and other results could be easily reproduced with [ioArena](https://abf.io/erthink/ioarena.git) just by `make bench-quartet` command,
|
||||
> These and other results could be easily reproduced with [ioArena](https://abf.io/erthink/ioarena) just by `make bench-quartet` command,
|
||||
> including comparisons with [RockDB](https://en.wikipedia.org/wiki/RocksDB)
|
||||
> and [WiredTiger](https://en.wikipedia.org/wiki/WiredTiger).
|
||||
|
||||
@@ -659,7 +659,7 @@ Bindings
|
||||
Performance comparison
|
||||
======================
|
||||
|
||||
All benchmarks were done in 2015 by [IOArena](https://abf.io/erthink/ioarena.git)
|
||||
All benchmarks were done in 2015 by [IOArena](https://abf.io/erthink/ioarena)
|
||||
and multiple [scripts](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015)
|
||||
runs on Lenovo Carbon-2 laptop, i7-4600U 2.1 GHz (2 physical cores, 4 HyperThreading cores), 8 Gb RAM,
|
||||
SSD SAMSUNG MZNTD512HAGL-000L1 (DXT23L0Q) 512 Gb.
|
||||
|
||||
@@ -1039,9 +1039,15 @@ macro(probe_libcxx_filesystem)
|
||||
#endif
|
||||
|
||||
int main(int argc, const char*argv[]) {
|
||||
fs::path probe(argv[0]);
|
||||
std::string str(argv[0]);
|
||||
fs::path probe(str);
|
||||
if (argc != 1) throw fs::filesystem_error(std::string("fake"), std::error_code());
|
||||
return fs::is_directory(probe.relative_path());
|
||||
int r = fs::is_directory(probe.relative_path());
|
||||
for (auto const& i : fs::directory_iterator(probe)) {
|
||||
++r;
|
||||
(void)i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
]])
|
||||
set(LIBCXX_FILESYSTEM "")
|
||||
|
||||
@@ -35,10 +35,11 @@ or debugging of a client application while retaining an active read
|
||||
transaction. LMDB this results in `MDB_MAP_FULL` error and subsequent write
|
||||
performance degradation.
|
||||
|
||||
MDBX mostly solve "long-lived" readers issue by using the Handle-Slow-Readers
|
||||
\ref MDBX_hsr_func callback which allows to abort long-lived read transactions,
|
||||
and using the \ref MDBX_LIFORECLAIM mode which addresses subsequent performance degradation.
|
||||
The "next" version of libmdbx (\ref MithrilDB) will completely solve this.
|
||||
MDBX mostly solve "long-lived" readers issue by using the
|
||||
Handle-Slow-Readers \ref MDBX_hsr_func callback which allows to abort
|
||||
long-lived read transactions, and using the \ref MDBX_LIFORECLAIM mode
|
||||
which addresses subsequent performance degradation. The "next" version
|
||||
of libmdbx (\ref MithrilDB) will completely solve this.
|
||||
|
||||
- Avoid suspending a process with active transactions. These would then be
|
||||
"long-lived" as above.
|
||||
@@ -80,6 +81,19 @@ list of pages to be retired.
|
||||
|
||||
Both of these issues will be addressed in MithrilDB.
|
||||
|
||||
#### Since v0.12.1 and later
|
||||
Some aspects related to GC have been refined and improved, in particular:
|
||||
|
||||
- The search for free consecutive/adjacent pages through GC has been
|
||||
significantly speeded, including acceleration using
|
||||
NOEN/SSE2/AVX2/AVX512 instructions.
|
||||
|
||||
- The `Big Foot` feature which significantly reduces GC overhead for
|
||||
processing large lists of retired pages from huge transactions. Now
|
||||
libmdbx avoid creating large chunks of PNLs (page number lists) which
|
||||
required a long sequences of free pages, aka large/overflow pages. Thus
|
||||
avoiding searching, allocating and storing such sequences inside GC.
|
||||
|
||||
|
||||
## Space reservation
|
||||
An MDBX database configuration will often reserve considerable unused
|
||||
@@ -87,6 +101,10 @@ memory address space and maybe file size for future growth. This does
|
||||
not use actual memory or disk space, but users may need to understand
|
||||
the difference so they won't be scared off.
|
||||
|
||||
However, on 64-bit systems with a relative small amount of RAM, such
|
||||
reservation can deplete system resources (trigger ENOMEM error, etc)
|
||||
when setting an inadequately large upper DB size using \ref
|
||||
mdbx_env_set_geometry() or \ref mdbx::env::geometry. So just avoid this.
|
||||
|
||||
## Remote filesystems
|
||||
Do not use MDBX databases on remote filesystems, even between processes
|
||||
|
||||
6
mdbx.h
6
mdbx.h
@@ -4031,7 +4031,7 @@ LIBMDBX_API int mdbx_txn_renew(MDBX_txn *txn);
|
||||
/** \brief The fours integers markers (aka "canary") associated with the
|
||||
* environment.
|
||||
* \ingroup c_crud
|
||||
* \see mdbx_canary_set()
|
||||
* \see mdbx_canary_put()
|
||||
* \see mdbx_canary_get()
|
||||
*
|
||||
* The `x`, `y` and `z` values could be set by \ref mdbx_canary_put(), while the
|
||||
@@ -4069,10 +4069,10 @@ LIBMDBX_API int mdbx_canary_put(MDBX_txn *txn, const MDBX_canary *canary);
|
||||
/** \brief Returns fours integers markers (aka "canary") associated with the
|
||||
* environment.
|
||||
* \ingroup c_crud
|
||||
* \see mdbx_canary_set()
|
||||
* \see mdbx_canary_put()
|
||||
*
|
||||
* \param [in] txn A transaction handle returned by \ref mdbx_txn_begin().
|
||||
* \param [in] canary The address of an MDBX_canary structure where the
|
||||
* \param [in] canary The address of an \ref MDBX_canary structure where the
|
||||
* information will be copied.
|
||||
*
|
||||
* \returns A non-zero error value on failure and 0 on success. */
|
||||
|
||||
10
mdbx.h++
10
mdbx.h++
@@ -3000,7 +3000,11 @@ public:
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/// Database geometry for size management.
|
||||
/// \brief Database geometry for size management.
|
||||
/// \see env_managed::create_parameters
|
||||
/// \see env_managed::env_managed(const ::std::string &pathname, const
|
||||
/// create_parameters &, const operate_parameters &, bool accede)
|
||||
|
||||
struct LIBMDBX_API_TYPE geometry {
|
||||
enum : int64_t {
|
||||
default_value = -1, ///< Means "keep current or use default"
|
||||
@@ -3659,6 +3663,8 @@ public:
|
||||
bool accede = true);
|
||||
|
||||
/// \brief Additional parameters for creating a new database.
|
||||
/// \see env_managed(const ::std::string &pathname, const create_parameters &,
|
||||
/// const operate_parameters &, bool accede)
|
||||
struct create_parameters {
|
||||
env::geometry geometry;
|
||||
mdbx_mode_t file_mode_bits{0640};
|
||||
@@ -5134,7 +5140,7 @@ inline filehandle env::get_filehandle() const {
|
||||
}
|
||||
|
||||
inline MDBX_env_flags_t env::get_flags() const {
|
||||
unsigned bits;
|
||||
unsigned bits = 0;
|
||||
error::success_or_throw(::mdbx_env_get_flags(handle_, &bits));
|
||||
return MDBX_env_flags_t(bits);
|
||||
}
|
||||
|
||||
115
src/core.c
115
src/core.c
@@ -835,6 +835,9 @@ atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value,
|
||||
enum MDBX_memory_order order) {
|
||||
STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8);
|
||||
#if MDBX_64BIT_ATOMIC
|
||||
#if __GNUC_PREREQ(11, 0)
|
||||
STATIC_ASSERT(__alignof__(MDBX_atomic_uint64_t) >= sizeof(uint64_t));
|
||||
#endif /* GNU C >= 11 */
|
||||
#ifdef MDBX_HAVE_C11ATOMICS
|
||||
assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p)));
|
||||
atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order));
|
||||
@@ -6469,27 +6472,47 @@ MDBX_MAYBE_UNUSED static __always_inline size_t __builtin_clzl(size_t value) {
|
||||
#define MDBX_ATTRIBUTE_TARGET(target) __attribute__((__target__(target)))
|
||||
#endif /* MDBX_ATTRIBUTE_TARGET */
|
||||
|
||||
#if defined(__SSE2__)
|
||||
#ifndef MDBX_GCC_FASTMATH_i686_SIMD_WORKAROUND
|
||||
/* Workaround for GCC's bug with `-m32 -march=i686 -Ofast`
|
||||
* gcc/i686-buildroot-linux-gnu/12.2.0/include/xmmintrin.h:814:1:
|
||||
* error: inlining failed in call to 'always_inline' '_mm_movemask_ps':
|
||||
* target specific option mismatch */
|
||||
#if !defined(__FAST_MATH__) || !__FAST_MATH__ || !defined(__GNUC__) || \
|
||||
defined(__e2k__) || defined(__clang__) || defined(__amd64__) || \
|
||||
defined(__SSE2__)
|
||||
#define MDBX_GCC_FASTMATH_i686_SIMD_WORKAROUND 0
|
||||
#else
|
||||
#define MDBX_GCC_FASTMATH_i686_SIMD_WORKAROUND 1
|
||||
#endif
|
||||
#endif /* MDBX_GCC_FASTMATH_i686_SIMD_WORKAROUND */
|
||||
|
||||
#if defined(__SSE2__) && defined(__SSE__)
|
||||
#define MDBX_ATTRIBUTE_TARGET_SSE2 /* nope */
|
||||
#elif (defined(_M_IX86_FP) && _M_IX86_FP >= 2) || defined(__amd64__)
|
||||
#define __SSE2__
|
||||
#define MDBX_ATTRIBUTE_TARGET_SSE2 /* nope */
|
||||
#elif defined(MDBX_ATTRIBUTE_TARGET) && defined(__ia32__)
|
||||
#define MDBX_ATTRIBUTE_TARGET_SSE2 MDBX_ATTRIBUTE_TARGET("sse2")
|
||||
#elif defined(MDBX_ATTRIBUTE_TARGET) && defined(__ia32__) && \
|
||||
!MDBX_GCC_FASTMATH_i686_SIMD_WORKAROUND
|
||||
#define MDBX_ATTRIBUTE_TARGET_SSE2 MDBX_ATTRIBUTE_TARGET("sse,sse2")
|
||||
#endif /* __SSE2__ */
|
||||
|
||||
#if defined(__AVX2__)
|
||||
#define MDBX_ATTRIBUTE_TARGET_AVX2 /* nope */
|
||||
#elif defined(MDBX_ATTRIBUTE_TARGET) && defined(__ia32__)
|
||||
#define MDBX_ATTRIBUTE_TARGET_AVX2 MDBX_ATTRIBUTE_TARGET("avx2")
|
||||
#elif defined(MDBX_ATTRIBUTE_TARGET) && defined(__ia32__) && \
|
||||
!MDBX_GCC_FASTMATH_i686_SIMD_WORKAROUND
|
||||
#define MDBX_ATTRIBUTE_TARGET_AVX2 MDBX_ATTRIBUTE_TARGET("sse,sse2,avx,avx2")
|
||||
#endif /* __AVX2__ */
|
||||
|
||||
#if defined(MDBX_ATTRIBUTE_TARGET_AVX2)
|
||||
#if defined(__AVX512BW__)
|
||||
#define MDBX_ATTRIBUTE_TARGET_AVX512BW /* nope */
|
||||
#elif defined(MDBX_ATTRIBUTE_TARGET) && defined(__ia32__) && \
|
||||
!MDBX_GCC_FASTMATH_i686_SIMD_WORKAROUND && \
|
||||
(__GNUC_PREREQ(6, 0) || __CLANG_PREREQ(5, 0))
|
||||
#define MDBX_ATTRIBUTE_TARGET_AVX512BW MDBX_ATTRIBUTE_TARGET("avx512bw")
|
||||
#define MDBX_ATTRIBUTE_TARGET_AVX512BW \
|
||||
MDBX_ATTRIBUTE_TARGET("sse,sse2,avx,avx2,avx512bw")
|
||||
#endif /* __AVX512BW__ */
|
||||
#endif /* MDBX_ATTRIBUTE_TARGET_AVX2 for MDBX_ATTRIBUTE_TARGET_AVX512BW */
|
||||
|
||||
#ifdef MDBX_ATTRIBUTE_TARGET_SSE2
|
||||
MDBX_ATTRIBUTE_TARGET_SSE2 static __always_inline unsigned
|
||||
@@ -6563,6 +6586,15 @@ diffcmp2mask_avx2(const pgno_t *const ptr, const ptrdiff_t offset,
|
||||
return _mm256_movemask_ps(*(const __m256 *)&cmp);
|
||||
}
|
||||
|
||||
MDBX_ATTRIBUTE_TARGET_AVX2 static __always_inline unsigned
|
||||
diffcmp2mask_sse2avx(const pgno_t *const ptr, const ptrdiff_t offset,
|
||||
const __m128i pattern) {
|
||||
const __m128i f = _mm_loadu_si128((const __m128i *)ptr);
|
||||
const __m128i l = _mm_loadu_si128((const __m128i *)(ptr + offset));
|
||||
const __m128i cmp = _mm_cmpeq_epi32(_mm_sub_epi32(f, l), pattern);
|
||||
return _mm_movemask_ps(*(const __m128 *)&cmp);
|
||||
}
|
||||
|
||||
MDBX_MAYBE_UNUSED __hot MDBX_ATTRIBUTE_TARGET_AVX2 static pgno_t *
|
||||
scan4seq_avx2(pgno_t *range, const size_t len, const size_t seq) {
|
||||
assert(seq > 0 && len > seq);
|
||||
@@ -6608,7 +6640,7 @@ scan4seq_avx2(pgno_t *range, const size_t len, const size_t seq) {
|
||||
}
|
||||
#endif /* __SANITIZE_ADDRESS__ */
|
||||
if (range - 3 > detent) {
|
||||
mask = diffcmp2mask_sse2(range - 3, offset, *(const __m128i *)&pattern);
|
||||
mask = diffcmp2mask_sse2avx(range - 3, offset, *(const __m128i *)&pattern);
|
||||
if (mask)
|
||||
return range + 28 - __builtin_clz(mask);
|
||||
range -= 4;
|
||||
@@ -6682,7 +6714,7 @@ scan4seq_avx512bw(pgno_t *range, const size_t len, const size_t seq) {
|
||||
range -= 8;
|
||||
}
|
||||
if (range - 3 > detent) {
|
||||
mask = diffcmp2mask_sse2(range - 3, offset, *(const __m128i *)&pattern);
|
||||
mask = diffcmp2mask_sse2avx(range - 3, offset, *(const __m128i *)&pattern);
|
||||
if (mask)
|
||||
return range + 28 - __builtin_clz(mask);
|
||||
range -= 4;
|
||||
@@ -8086,13 +8118,9 @@ retry:;
|
||||
}
|
||||
|
||||
const bool inside_txn = (env->me_txn0->mt_owner == osal_thread_self());
|
||||
meta_ptr_t head;
|
||||
if (inside_txn | locked)
|
||||
head = meta_recent(env, &env->me_txn0->tw.troika);
|
||||
else {
|
||||
const meta_troika_t troika = meta_tap(env);
|
||||
head = meta_recent(env, &troika);
|
||||
}
|
||||
const meta_troika_t troika =
|
||||
(inside_txn | locked) ? env->me_txn0->tw.troika : meta_tap(env);
|
||||
const meta_ptr_t head = meta_recent(env, &troika);
|
||||
const uint64_t unsynced_pages =
|
||||
atomic_load64(&env->me_lck->mti_unsynced_pages, mo_Relaxed);
|
||||
if (unsynced_pages == 0) {
|
||||
@@ -8105,10 +8133,19 @@ retry:;
|
||||
if (!inside_txn && locked && (env->me_flags & MDBX_WRITEMAP) &&
|
||||
unlikely(head.ptr_c->mm_geo.next >
|
||||
bytes2pgno(env, env->me_dxb_mmap.current))) {
|
||||
rc = dxb_resize(env, head.ptr_c->mm_geo.next, head.ptr_c->mm_geo.now,
|
||||
head.ptr_c->mm_geo.upper, implicit_grow);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
|
||||
if (unlikely(env->me_stuck_meta >= 0) &&
|
||||
troika.recent != (uint8_t)env->me_stuck_meta) {
|
||||
NOTICE("skip %s since wagering meta-page (%u) is mispatch the recent "
|
||||
"meta-page (%u)",
|
||||
"sync datafile", env->me_stuck_meta, troika.recent);
|
||||
rc = MDBX_RESULT_TRUE;
|
||||
} else {
|
||||
rc = dxb_resize(env, head.ptr_c->mm_geo.next, head.ptr_c->mm_geo.now,
|
||||
head.ptr_c->mm_geo.upper, implicit_grow);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t autosync_threshold =
|
||||
@@ -8187,6 +8224,14 @@ retry:;
|
||||
eASSERT(env, inside_txn || locked);
|
||||
eASSERT(env, !inside_txn || (flags & MDBX_SHRINK_ALLOWED) == 0);
|
||||
|
||||
if (!head.is_steady && unlikely(env->me_stuck_meta >= 0) &&
|
||||
troika.recent != (uint8_t)env->me_stuck_meta) {
|
||||
NOTICE("skip %s since wagering meta-page (%u) is mispatch the recent "
|
||||
"meta-page (%u)",
|
||||
"sync datafile", env->me_stuck_meta, troika.recent);
|
||||
rc = MDBX_RESULT_TRUE;
|
||||
goto bailout;
|
||||
}
|
||||
if (!head.is_steady || ((flags & MDBX_SAFE_NOSYNC) == 0 && unsynced_pages)) {
|
||||
DEBUG("meta-head %" PRIaPGNO ", %s, sync_pending %" PRIu64,
|
||||
data_page(head.ptr_c)->mp_pgno, durable_caption(head.ptr_c),
|
||||
@@ -13732,8 +13777,9 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
mdbx_is_readahead_reasonable(used_bytes, 0) == MDBX_RESULT_TRUE;
|
||||
#endif /* MDBX_ENABLE_MADVISE */
|
||||
|
||||
err = osal_mmap(env->me_flags, &env->me_dxb_mmap, env->me_dbgeo.now,
|
||||
env->me_dbgeo.upper, lck_rc ? MMAP_OPTION_TRUNCATE : 0);
|
||||
err = osal_mmap(
|
||||
env->me_flags, &env->me_dxb_mmap, env->me_dbgeo.now, env->me_dbgeo.upper,
|
||||
(lck_rc && env->me_stuck_meta < 0) ? MMAP_OPTION_TRUNCATE : 0);
|
||||
if (unlikely(err != MDBX_SUCCESS))
|
||||
return err;
|
||||
|
||||
@@ -13933,7 +13979,12 @@ __cold static int setup_dxb(MDBX_env *env, const int lck_rc,
|
||||
}
|
||||
|
||||
const meta_ptr_t recent = meta_recent(env, &troika);
|
||||
if (memcmp(&header.mm_geo, &recent.ptr_c->mm_geo, sizeof(header.mm_geo))) {
|
||||
if (/* не учитываем различия в geo.next */
|
||||
header.mm_geo.grow_pv != recent.ptr_c->mm_geo.grow_pv ||
|
||||
header.mm_geo.shrink_pv != recent.ptr_c->mm_geo.shrink_pv ||
|
||||
header.mm_geo.lower != recent.ptr_c->mm_geo.lower ||
|
||||
header.mm_geo.upper != recent.ptr_c->mm_geo.upper ||
|
||||
header.mm_geo.now != recent.ptr_c->mm_geo.now) {
|
||||
if ((env->me_flags & MDBX_RDONLY) != 0 ||
|
||||
/* recovery mode */ env->me_stuck_meta >= 0) {
|
||||
WARNING("skipped update meta.geo in %s mode: from l%" PRIaPGNO
|
||||
@@ -14383,8 +14434,12 @@ __cold static int __must_check_result override_meta(MDBX_env *env,
|
||||
if (unlikely(MDBX_IS_ERROR(rc)))
|
||||
return MDBX_PROBLEM;
|
||||
|
||||
if (shape && memcmp(model, shape, sizeof(MDBX_meta)) == 0)
|
||||
if (shape && memcmp(model, shape, sizeof(MDBX_meta)) == 0) {
|
||||
NOTICE("skip overriding meta-%zu since no changes "
|
||||
"for txnid #%" PRIaTXN,
|
||||
target, txnid);
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
if (env->me_flags & MDBX_WRITEMAP) {
|
||||
#if MDBX_ENABLE_PGOP_STAT
|
||||
@@ -14438,14 +14493,16 @@ __cold int mdbx_env_turn_for_recovery(MDBX_env *env, unsigned target) {
|
||||
MDBX_EXCLUSIVE))
|
||||
return MDBX_EPERM;
|
||||
|
||||
const MDBX_meta *target_meta = METAPAGE(env, target);
|
||||
txnid_t new_txnid = safe64_txnid_next(constmeta_txnid(target_meta));
|
||||
for (size_t n = 0; n < NUM_METAS; ++n) {
|
||||
const MDBX_meta *const target_meta = METAPAGE(env, target);
|
||||
txnid_t new_txnid = constmeta_txnid(target_meta);
|
||||
if (new_txnid < MIN_TXNID)
|
||||
new_txnid = MIN_TXNID;
|
||||
for (unsigned n = 0; n < NUM_METAS; ++n) {
|
||||
if (n == target)
|
||||
continue;
|
||||
MDBX_meta meta = *METAPAGE(env, target);
|
||||
if (validate_meta(env, &meta, pgno2page(env, n), (pgno_t)n, nullptr) !=
|
||||
MDBX_SUCCESS) {
|
||||
MDBX_page *const page = pgno2page(env, n);
|
||||
MDBX_meta meta = *page_meta(page);
|
||||
if (validate_meta(env, &meta, page, n, nullptr) != MDBX_SUCCESS) {
|
||||
int err = override_meta(env, n, 0, nullptr);
|
||||
if (unlikely(err != MDBX_SUCCESS))
|
||||
return err;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Copyright 2015-2023 Leonid Yuriev <leo@yuriev.ru>.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_CHK 1 "2023-04-29" "MDBX 0.12.6"
|
||||
.TH MDBX_CHK 1 "2023-06-16" "MDBX 0.12.7"
|
||||
.SH NAME
|
||||
mdbx_chk \- MDBX checking tool
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_COPY 1 "2023-04-29" "MDBX 0.12.6"
|
||||
.TH MDBX_COPY 1 "2023-06-16" "MDBX 0.12.7"
|
||||
.SH NAME
|
||||
mdbx_copy \- MDBX environment copy tool
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" Copyright 2021-2023 Leonid Yuriev <leo@yuriev.ru>.
|
||||
.\" Copyright 2014-2021 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_DROP 1 "2023-04-29" "MDBX 0.12.6"
|
||||
.TH MDBX_DROP 1 "2023-06-16" "MDBX 0.12.7"
|
||||
.SH NAME
|
||||
mdbx_drop \- MDBX database delete tool
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_DUMP 1 "2023-04-29" "MDBX 0.12.6"
|
||||
.TH MDBX_DUMP 1 "2023-06-16" "MDBX 0.12.7"
|
||||
.SH NAME
|
||||
mdbx_dump \- MDBX environment export tool
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_LOAD 1 "2023-04-29" "MDBX 0.12.6"
|
||||
.TH MDBX_LOAD 1 "2023-06-16" "MDBX 0.12.7"
|
||||
.SH NAME
|
||||
mdbx_load \- MDBX environment import tool
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" Copyright 2015,2016 Peter-Service R&D LLC <http://billing.ru/>.
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.TH MDBX_STAT 1 "2023-04-29" "MDBX 0.12.6"
|
||||
.TH MDBX_STAT 1 "2023-06-16" "MDBX 0.12.7"
|
||||
.SH NAME
|
||||
mdbx_stat \- MDBX environment status tool
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include <unistd.h>
|
||||
|
||||
static int dump(MDBX_cursor *cur) {
|
||||
MDBX_val key = {};
|
||||
MDBX_val data = {};
|
||||
MDBX_val key = {NULL, 0};
|
||||
MDBX_val data = {NULL, 0};
|
||||
int rc = mdbx_cursor_get(cur, &key, &data, MDBX_FIRST);
|
||||
|
||||
while (rc == 0) {
|
||||
@@ -25,15 +25,14 @@ static int dump(MDBX_cursor *cur) {
|
||||
}
|
||||
|
||||
static int clear(MDBX_cursor *cur) {
|
||||
MDBX_val key = {};
|
||||
MDBX_val data = {};
|
||||
MDBX_val key = {NULL, 0};
|
||||
MDBX_val data = {NULL, 0};
|
||||
int rc = mdbx_cursor_get(cur, &key, &data, MDBX_FIRST);
|
||||
|
||||
while (rc == 0) {
|
||||
rc = mdbx_cursor_del(cur, MDBX_ALLDUPS);
|
||||
if (rc) {
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
rc = mdbx_cursor_get(cur, &key, &data, MDBX_NEXT);
|
||||
}
|
||||
return (rc == MDBX_NOTFOUND) ? 0 : rc;
|
||||
|
||||
Reference in New Issue
Block a user