diff --git a/mdbx/mdbx.c b/mdbx/mdbx.c index 9124214..f8f2b9a 100644 --- a/mdbx/mdbx.c +++ b/mdbx/mdbx.c @@ -3,7 +3,7 @@ #define xMDBX_ALLOY 1 /* alloyed build */ -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1145,7 +1145,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT @@ -18189,11 +18189,13 @@ __cold int mdbx_enumerate_subdb(const MDBX_txn *txn, MDBX_subdb_enum_func *func, stat_get(tree, &stat, sizeof(stat)); rc = func(ctx, txn, &name, tree->flags, &stat, dbi); if (rc != MDBX_SUCCESS) - break; + goto bailout; } - txn->cursors[MAIN_DBI] = cx.outer.next; + rc = (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; - return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; +bailout: + txn->cursors[MAIN_DBI] = cx.outer.next; + return rc; } /// \copyright SPDX-License-Identifier: Apache-2.0 /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 @@ -29290,11 +29292,10 @@ MDBX_INTERNAL int osal_ioring_add(osal_ioring_t *ior, const size_t offset, item->sgv[0].Buffer = PtrToPtr64(data); for (size_t i = 1; i < segments; ++i) { data = ptr_disp(data, ior->pagesize); - item->sgv[slots_used].Buffer = PtrToPtr64(data); + item->sgv[i].Buffer = PtrToPtr64(data); } - item->sgv[slots_used].Buffer = 0; + item->sgv[slots_used = segments].Buffer = 0; assert((item->single.iov_len & ior_WriteFile_flag) == 0); - slots_used = segments; } ior->last_bytes = bytes; ior_last_sgvcnt(ior, item) = slots_used; @@ -29358,6 +29359,17 @@ MDBX_INTERNAL void osal_ioring_walk(osal_ioring_t *ior, iov_ctx_t *ctx, } } +#if defined(_WIN32) || defined(_WIN64) +static pgno_t safe_get_pgno(const page_t* page) { + SIZE_T NumberOfBytesRead = 0; + pgno_t pgno = P_INVALID; + if (ReadProcessMemory(GetCurrentProcess(), &page->pgno, &pgno, sizeof(pgno), &NumberOfBytesRead) + && NumberOfBytesRead == sizeof(pgno)) + return pgno; + return P_INVALID; +} +#endif + MDBX_INTERNAL osal_ioring_write_result_t osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { osal_ioring_write_result_t r = {MDBX_SUCCESS, 0}; @@ -29399,12 +29411,12 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { } else { r.err = (int)GetLastError(); if (unlikely(r.err != ERROR_IO_PENDING)) { - ERROR("%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + void *data = Ptr64ToPtr(item->sgv[0].Buffer); + ERROR("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "WriteFileGather", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, - bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), - r.err); + item - ior->pool, data, safe_get_pgno((page_t *)data), bytes, + item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); goto bailout_rc; } assert(wait_for > ior->event_pool + ior->event_stack); @@ -29421,22 +29433,23 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { r.err = (int)GetLastError(); switch (r.err) { default: - ERROR("%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "WriteFileEx", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, - bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), - r.err); + item - ior->pool, item->single.iov_base, + safe_get_pgno((page_t *)item->single.iov_base), bytes, + item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); goto bailout_rc; case ERROR_NOT_FOUND: case ERROR_USER_MAPPED_FILE: case ERROR_LOCK_VIOLATION: - WARNING( - "%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", - "WriteFileEx", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, bytes, - item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); + WARNING("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", + "WriteFileEx", fd, __Wpedantic_format_voidptr(item), + item - ior->pool, item->single.iov_base, + safe_get_pgno((page_t *)item->single.iov_base), bytes, + item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), + r.err); SleepEx(0, true); goto retry; case ERROR_INVALID_USER_BUFFER: @@ -29454,10 +29467,11 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if (!WriteFile(fd, item->single.iov_base, (DWORD)bytes, &written, &item->ov)) { r.err = (int)GetLastError(); - ERROR("%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "WriteFile", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, bytes, + item - ior->pool, item->single.iov_base, + safe_get_pgno((page_t *)item->single.iov_base), bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); goto bailout_rc; } else if (unlikely(written != bytes)) { @@ -29511,7 +29525,9 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { assert(ior->async_waiting == ior->async_completed); for (ior_item_t *item = ior->pool; item <= ior->last;) { size_t i = 1, bytes = item->single.iov_len - ior_WriteFile_flag; + void *data = item->single.iov_base; if (bytes & ior_WriteFile_flag) { + data = Ptr64ToPtr(item->sgv[0].Buffer); bytes = ior->pagesize; /* Zap: Reading invalid data from 'item->sgv' */ MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); @@ -29522,11 +29538,10 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if (!HasOverlappedIoCompleted(&item->ov)) { DWORD written = 0; if (unlikely(!GetOverlappedResult(fd, &item->ov, &written, true))) { - ERROR("%s: item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "GetOverlappedResult", __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, - bytes, + item - ior->pool, data, safe_get_pgno((page_t *)data), bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), (int)GetLastError()); goto bailout_geterr; @@ -29544,10 +29559,10 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if ((r.err & 0x80000000) && GetOverlappedResult(nullptr, &item->ov, &written, true)) r.err = (int)GetLastError(); - ERROR("%s: item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "Result", __Wpedantic_format_voidptr(item), item - ior->pool, - ((page_t *)item->single.iov_base)->pgno, bytes, + data, safe_get_pgno((page_t *)data), bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), (int)GetLastError()); goto bailout_rc; @@ -32040,6 +32055,10 @@ __cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages, #include #endif /* sys/random.h */ +#if defined(_WIN32) || defined(_WIN64) +#include +#endif /* Windows */ + MDBX_INTERNAL bin128_t osal_guid(const MDBX_env *env) { struct { uint64_t begin, end, cputime; @@ -40268,9 +40287,9 @@ __dll_export 0, 13, 0, - 76, - {"2024-07-12T11:43:12+03:00", "3bd50abdfc8d371f58405b04bffa3155cf40536a", "32df0ad1ebcb7d36ec744c94d8fa134873e7f011", - "v0.13.0-76-g32df0ad1"}, + 86, + {"2024-07-19T21:26:39+03:00", "e20ca6a79c305ac06cad8a8ef3752cf58bccc9d1", "22776ad5bbc3a409bb0be8c28ffb8065a6bc6287", + "v0.13.0-86-g22776ad5"}, sourcery}; __dll_export diff --git a/mdbx/mdbx.h b/mdbx/mdbx.h index 5a956e6..95caf47 100644 --- a/mdbx/mdbx.h +++ b/mdbx/mdbx.h @@ -4270,9 +4270,10 @@ LIBMDBX_API int mdbx_txn_reset(MDBX_txn *txn); * или перезапущена в любой момент посредством \ref mdbx_txn_abort(), * \ref mdbx_txn_reset() и \ref mdbx_txn_renew(), соответственно. * - * \see long-lived-read * \see mdbx_txn_unpark() * \see mdbx_txn_flags() + * \see mdbx_env_set_hsr() + * \see Long-lived read transactions * * \param [in] txn Транзакция чтения запущенная посредством * \ref mdbx_txn_begin(). @@ -4293,9 +4294,9 @@ LIBMDBX_API int mdbx_txn_park(MDBX_txn *txn, bool autounpark); * её перезапуск аналогично \ref mdbx_txn_renew(), либо транзакция сбрасывается * и возвращается код ошибки \ref MDBX_OUSTED. * - * \see long-lived-read * \see mdbx_txn_park() * \see mdbx_txn_flags() + * \see Long-lived read transactions * * \param [in] txn Транзакция чтения запущенная посредством * \ref mdbx_txn_begin() и затем припаркованная @@ -4583,17 +4584,24 @@ typedef int(MDBX_subdb_enum_func)(void *ctx, const MDBX_txn *txn, const struct MDBX_stat *stat, MDBX_dbi dbi) MDBX_CXX17_NOEXCEPT; -/** \brief Enumerate the entries in the reader lock table. +/** \brief Перечисляет пользовательские именнованные таблицы. + * + * Производит перечисление пользовательских именнованных таблиц, вызывая + * специфицируемую пользователем функцию-визитер для каждой именованной таблицы. + * Перечисление продолжается до исчерпания именованных таблиц, либо до возврата + * отличного от нуля результата из заданной пользователем функции, которое будет + * сразу возвращено в качестве результата. + * * \ingroup c_statinfo * \see MDBX_subdb_enum_func * * \param [in] txn Транзакция запущенная посредством * \ref mdbx_txn_begin(). - * \param [in] func Указатель на пользовательскую функцию-перечислитель + * \param [in] func Указатель на пользовательскую функцию * с сигнатурой \ref MDBX_subdb_enum_func, * которая будет вызвана для каждой таблицы. * \param [in] ctx Указатель на некоторый контект, который будет передан - * в функцию-перечислитель как есть. + * в функцию `func()` как есть. * * \returns Ненулевое значение кода ошибки, либо 0 при успешном выполнении. */ LIBMDBX_API int mdbx_enumerate_subdb(const MDBX_txn *txn, @@ -6120,6 +6128,7 @@ LIBMDBX_API int mdbx_thread_unregister(const MDBX_env *env); * with a "long-lived" read transactions. * \see mdbx_env_set_hsr() * \see mdbx_env_get_hsr() + * \see mdbx_txn_park() * \see Long-lived read transactions * * Using this callback you can choose how to resolve the situation: @@ -6194,6 +6203,7 @@ typedef int(MDBX_hsr_func)(const MDBX_env *env, const MDBX_txn *txn, * * \see MDBX_hsr_func * \see mdbx_env_get_hsr() + * \see mdbx_txn_park() * \see Long-lived read transactions * * \param [in] env An environment handle returned @@ -6209,6 +6219,7 @@ LIBMDBX_API int mdbx_env_set_hsr(MDBX_env *env, MDBX_hsr_func *hsr_callback); * recycled. * \see MDBX_hsr_func * \see mdbx_env_set_hsr() + * \see mdbx_txn_park() * \see Long-lived read transactions * * \param [in] env An environment handle returned by \ref mdbx_env_create(). diff --git a/mdbxdist/ChangeLog.md b/mdbxdist/ChangeLog.md index c003df5..4a04210 100644 --- a/mdbxdist/ChangeLog.md +++ b/mdbxdist/ChangeLog.md @@ -38,6 +38,16 @@ and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/gitflic использования блокировок, управляемый опцией сборки `MDBX_ENABLE_DBI_LOCKFREE`, которая включена по-умолчанию. + - Поддержка "парковки" читающих транзакций с их вытеснением ради + переработки старых MVCC-снимков и предотвращения проблем вызываемых + приостановкой переработки мусора. Механизм парковки и вытеснения + припаркованных транзакций является как дополнением, так и более простой + в использовании альтернативой обратному вызову + [Handle-Slow-Readers](https://libmdbx.dqdkfa.ru/group__c__err.html#ga2cb11b56414c282fe06dd942ae6cade6). + Для удобства функции `mdbx_txn_park()` и `mdbx_txn_unpack()` имеют + дополнительные аргументы, позволяющие запросить автоматическую + "распарковку" припаркованных и перезапуск вытесненных транзакций. + - Расширение API позиционирования курсоров более удобными и очевидными операциями по аналогии условиям `<`, `<=`, `==`, `>=`, `>` как для ключей, так и для пар ключ-значение. @@ -65,6 +75,9 @@ and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/gitflic - Функция `mdbx_preopen_snapinfo()` для получения информации о БД без её открытия. + - Функция `mdbx_enumerate_subdb()` для получение информации + об именованных пользовательских таблицах. + - Поддержка функций логирования обратного вызова без функционала `vprintf()`, что существенно облегчает использование логирования в привязках к другим языкам программирования. @@ -75,13 +88,17 @@ and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/gitflic - Опция `MDBX_opt_prefer_waf_insteadof_balance`. - - Опции `MDBX_opt_subpage_limit`, `MDBX_opt_subpage_room_threshold`, `MDBX_opt_subpage_reserve_prereq`, `MDBX_opt_subpage_reserve_limit`. + - Опции `MDBX_opt_subpage_limit`, `MDBX_opt_subpage_room_threshold`, + `MDBX_opt_subpage_reserve_prereq`, `MDBX_opt_subpage_reserve_limit`. - Управление основной блокировкой lock/unlock/upgrade/downgrade для координации пишущих транзакций. - Функции `mdbx_limits_keysize_min()` и `mdbx_limits_valsize_min()` для получения нижней границы длины ключей и значений. + - Для идентификации БД добавлен UUID доступный в поле `mi_dxbid` структуры `MDBX_envinfo`, + получаемой посредством `mdbx_env_info_ex()`. + - Расширение и доработка C++ API: - добавлен тип `mdbx::cursor::estimation_result`, а поведение методов @@ -97,7 +114,8 @@ and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/gitflic - добавлены статические методы `buffer::hex()`, `base64()`, `base58()`; - для транзакций и курсоров добавлены методы `get_/set_context`; - добавлен метод `cursor::clone()`; - - поддержка base58 переработана и приведена в соответствии с черновиком RFC, в текущем понимании теперь это одна из самых высокопроизводительных реализаций; + - поддержка base58 переработана и приведена в соответствии с черновиком RFC, + в текущем понимании теперь это одна из самых высокопроизводительных реализаций base58; - переработка `to_hex()` и `from_hex()`. Нарушение совместимости: diff --git a/mdbxdist/VERSION.txt b/mdbxdist/VERSION.txt index 6593bde..a0c49cc 100644 --- a/mdbxdist/VERSION.txt +++ b/mdbxdist/VERSION.txt @@ -1 +1 @@ -0.13.0.76 +0.13.0.86 diff --git a/mdbxdist/mdbx.c b/mdbxdist/mdbx.c index 9124214..f8f2b9a 100644 --- a/mdbxdist/mdbx.c +++ b/mdbxdist/mdbx.c @@ -3,7 +3,7 @@ #define xMDBX_ALLOY 1 /* alloyed build */ -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1145,7 +1145,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT @@ -18189,11 +18189,13 @@ __cold int mdbx_enumerate_subdb(const MDBX_txn *txn, MDBX_subdb_enum_func *func, stat_get(tree, &stat, sizeof(stat)); rc = func(ctx, txn, &name, tree->flags, &stat, dbi); if (rc != MDBX_SUCCESS) - break; + goto bailout; } - txn->cursors[MAIN_DBI] = cx.outer.next; + rc = (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; - return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; +bailout: + txn->cursors[MAIN_DBI] = cx.outer.next; + return rc; } /// \copyright SPDX-License-Identifier: Apache-2.0 /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 @@ -29290,11 +29292,10 @@ MDBX_INTERNAL int osal_ioring_add(osal_ioring_t *ior, const size_t offset, item->sgv[0].Buffer = PtrToPtr64(data); for (size_t i = 1; i < segments; ++i) { data = ptr_disp(data, ior->pagesize); - item->sgv[slots_used].Buffer = PtrToPtr64(data); + item->sgv[i].Buffer = PtrToPtr64(data); } - item->sgv[slots_used].Buffer = 0; + item->sgv[slots_used = segments].Buffer = 0; assert((item->single.iov_len & ior_WriteFile_flag) == 0); - slots_used = segments; } ior->last_bytes = bytes; ior_last_sgvcnt(ior, item) = slots_used; @@ -29358,6 +29359,17 @@ MDBX_INTERNAL void osal_ioring_walk(osal_ioring_t *ior, iov_ctx_t *ctx, } } +#if defined(_WIN32) || defined(_WIN64) +static pgno_t safe_get_pgno(const page_t* page) { + SIZE_T NumberOfBytesRead = 0; + pgno_t pgno = P_INVALID; + if (ReadProcessMemory(GetCurrentProcess(), &page->pgno, &pgno, sizeof(pgno), &NumberOfBytesRead) + && NumberOfBytesRead == sizeof(pgno)) + return pgno; + return P_INVALID; +} +#endif + MDBX_INTERNAL osal_ioring_write_result_t osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { osal_ioring_write_result_t r = {MDBX_SUCCESS, 0}; @@ -29399,12 +29411,12 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { } else { r.err = (int)GetLastError(); if (unlikely(r.err != ERROR_IO_PENDING)) { - ERROR("%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + void *data = Ptr64ToPtr(item->sgv[0].Buffer); + ERROR("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "WriteFileGather", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, - bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), - r.err); + item - ior->pool, data, safe_get_pgno((page_t *)data), bytes, + item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); goto bailout_rc; } assert(wait_for > ior->event_pool + ior->event_stack); @@ -29421,22 +29433,23 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { r.err = (int)GetLastError(); switch (r.err) { default: - ERROR("%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "WriteFileEx", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, - bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), - r.err); + item - ior->pool, item->single.iov_base, + safe_get_pgno((page_t *)item->single.iov_base), bytes, + item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); goto bailout_rc; case ERROR_NOT_FOUND: case ERROR_USER_MAPPED_FILE: case ERROR_LOCK_VIOLATION: - WARNING( - "%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", - "WriteFileEx", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, bytes, - item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); + WARNING("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", + "WriteFileEx", fd, __Wpedantic_format_voidptr(item), + item - ior->pool, item->single.iov_base, + safe_get_pgno((page_t *)item->single.iov_base), bytes, + item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), + r.err); SleepEx(0, true); goto retry; case ERROR_INVALID_USER_BUFFER: @@ -29454,10 +29467,11 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if (!WriteFile(fd, item->single.iov_base, (DWORD)bytes, &written, &item->ov)) { r.err = (int)GetLastError(); - ERROR("%s: fd %p, item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: fd %p, item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "WriteFile", fd, __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, bytes, + item - ior->pool, item->single.iov_base, + safe_get_pgno((page_t *)item->single.iov_base), bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), r.err); goto bailout_rc; } else if (unlikely(written != bytes)) { @@ -29511,7 +29525,9 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { assert(ior->async_waiting == ior->async_completed); for (ior_item_t *item = ior->pool; item <= ior->last;) { size_t i = 1, bytes = item->single.iov_len - ior_WriteFile_flag; + void *data = item->single.iov_base; if (bytes & ior_WriteFile_flag) { + data = Ptr64ToPtr(item->sgv[0].Buffer); bytes = ior->pagesize; /* Zap: Reading invalid data from 'item->sgv' */ MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); @@ -29522,11 +29538,10 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if (!HasOverlappedIoCompleted(&item->ov)) { DWORD written = 0; if (unlikely(!GetOverlappedResult(fd, &item->ov, &written, true))) { - ERROR("%s: item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "GetOverlappedResult", __Wpedantic_format_voidptr(item), - item - ior->pool, ((page_t *)item->single.iov_base)->pgno, - bytes, + item - ior->pool, data, safe_get_pgno((page_t *)data), bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), (int)GetLastError()); goto bailout_geterr; @@ -29544,10 +29559,10 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if ((r.err & 0x80000000) && GetOverlappedResult(nullptr, &item->ov, &written, true)) r.err = (int)GetLastError(); - ERROR("%s: item %p (%zu), pgno %u, bytes %zu, offset %" PRId64 - ", err %d", + ERROR("%s: item %p (%zu), addr %p pgno %u, bytes %zu," + " offset %" PRId64 ", err %d", "Result", __Wpedantic_format_voidptr(item), item - ior->pool, - ((page_t *)item->single.iov_base)->pgno, bytes, + data, safe_get_pgno((page_t *)data), bytes, item->ov.Offset + ((uint64_t)item->ov.OffsetHigh << 32), (int)GetLastError()); goto bailout_rc; @@ -32040,6 +32055,10 @@ __cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages, #include #endif /* sys/random.h */ +#if defined(_WIN32) || defined(_WIN64) +#include +#endif /* Windows */ + MDBX_INTERNAL bin128_t osal_guid(const MDBX_env *env) { struct { uint64_t begin, end, cputime; @@ -40268,9 +40287,9 @@ __dll_export 0, 13, 0, - 76, - {"2024-07-12T11:43:12+03:00", "3bd50abdfc8d371f58405b04bffa3155cf40536a", "32df0ad1ebcb7d36ec744c94d8fa134873e7f011", - "v0.13.0-76-g32df0ad1"}, + 86, + {"2024-07-19T21:26:39+03:00", "e20ca6a79c305ac06cad8a8ef3752cf58bccc9d1", "22776ad5bbc3a409bb0be8c28ffb8065a6bc6287", + "v0.13.0-86-g22776ad5"}, sourcery}; __dll_export diff --git a/mdbxdist/mdbx.c++ b/mdbxdist/mdbx.c++ index aaf3dda..aa27e16 100644 --- a/mdbxdist/mdbx.c++ +++ b/mdbxdist/mdbx.c++ @@ -2,7 +2,7 @@ /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1144,7 +1144,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT diff --git a/mdbxdist/mdbx.h b/mdbxdist/mdbx.h index 5a956e6..95caf47 100644 --- a/mdbxdist/mdbx.h +++ b/mdbxdist/mdbx.h @@ -4270,9 +4270,10 @@ LIBMDBX_API int mdbx_txn_reset(MDBX_txn *txn); * или перезапущена в любой момент посредством \ref mdbx_txn_abort(), * \ref mdbx_txn_reset() и \ref mdbx_txn_renew(), соответственно. * - * \see long-lived-read * \see mdbx_txn_unpark() * \see mdbx_txn_flags() + * \see mdbx_env_set_hsr() + * \see Long-lived read transactions * * \param [in] txn Транзакция чтения запущенная посредством * \ref mdbx_txn_begin(). @@ -4293,9 +4294,9 @@ LIBMDBX_API int mdbx_txn_park(MDBX_txn *txn, bool autounpark); * её перезапуск аналогично \ref mdbx_txn_renew(), либо транзакция сбрасывается * и возвращается код ошибки \ref MDBX_OUSTED. * - * \see long-lived-read * \see mdbx_txn_park() * \see mdbx_txn_flags() + * \see Long-lived read transactions * * \param [in] txn Транзакция чтения запущенная посредством * \ref mdbx_txn_begin() и затем припаркованная @@ -4583,17 +4584,24 @@ typedef int(MDBX_subdb_enum_func)(void *ctx, const MDBX_txn *txn, const struct MDBX_stat *stat, MDBX_dbi dbi) MDBX_CXX17_NOEXCEPT; -/** \brief Enumerate the entries in the reader lock table. +/** \brief Перечисляет пользовательские именнованные таблицы. + * + * Производит перечисление пользовательских именнованных таблиц, вызывая + * специфицируемую пользователем функцию-визитер для каждой именованной таблицы. + * Перечисление продолжается до исчерпания именованных таблиц, либо до возврата + * отличного от нуля результата из заданной пользователем функции, которое будет + * сразу возвращено в качестве результата. + * * \ingroup c_statinfo * \see MDBX_subdb_enum_func * * \param [in] txn Транзакция запущенная посредством * \ref mdbx_txn_begin(). - * \param [in] func Указатель на пользовательскую функцию-перечислитель + * \param [in] func Указатель на пользовательскую функцию * с сигнатурой \ref MDBX_subdb_enum_func, * которая будет вызвана для каждой таблицы. * \param [in] ctx Указатель на некоторый контект, который будет передан - * в функцию-перечислитель как есть. + * в функцию `func()` как есть. * * \returns Ненулевое значение кода ошибки, либо 0 при успешном выполнении. */ LIBMDBX_API int mdbx_enumerate_subdb(const MDBX_txn *txn, @@ -6120,6 +6128,7 @@ LIBMDBX_API int mdbx_thread_unregister(const MDBX_env *env); * with a "long-lived" read transactions. * \see mdbx_env_set_hsr() * \see mdbx_env_get_hsr() + * \see mdbx_txn_park() * \see Long-lived read transactions * * Using this callback you can choose how to resolve the situation: @@ -6194,6 +6203,7 @@ typedef int(MDBX_hsr_func)(const MDBX_env *env, const MDBX_txn *txn, * * \see MDBX_hsr_func * \see mdbx_env_get_hsr() + * \see mdbx_txn_park() * \see Long-lived read transactions * * \param [in] env An environment handle returned @@ -6209,6 +6219,7 @@ LIBMDBX_API int mdbx_env_set_hsr(MDBX_env *env, MDBX_hsr_func *hsr_callback); * recycled. * \see MDBX_hsr_func * \see mdbx_env_set_hsr() + * \see mdbx_txn_park() * \see Long-lived read transactions * * \param [in] env An environment handle returned by \ref mdbx_env_create(). diff --git a/mdbxdist/mdbx_chk.c b/mdbxdist/mdbx_chk.c index dcedd4d..cc854dc 100644 --- a/mdbxdist/mdbx_chk.c +++ b/mdbxdist/mdbx_chk.c @@ -16,7 +16,7 @@ /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1158,7 +1158,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT diff --git a/mdbxdist/mdbx_copy.c b/mdbxdist/mdbx_copy.c index ce1d116..ab2a74e 100644 --- a/mdbxdist/mdbx_copy.c +++ b/mdbxdist/mdbx_copy.c @@ -18,7 +18,7 @@ /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1160,7 +1160,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT diff --git a/mdbxdist/mdbx_drop.c b/mdbxdist/mdbx_drop.c index c2e8ce7..b82b97b 100644 --- a/mdbxdist/mdbx_drop.c +++ b/mdbxdist/mdbx_drop.c @@ -18,7 +18,7 @@ /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1160,7 +1160,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT diff --git a/mdbxdist/mdbx_dump.c b/mdbxdist/mdbx_dump.c index 6f72da4..38bac51 100644 --- a/mdbxdist/mdbx_dump.c +++ b/mdbxdist/mdbx_dump.c @@ -18,7 +18,7 @@ /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1160,7 +1160,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT diff --git a/mdbxdist/mdbx_load.c b/mdbxdist/mdbx_load.c index e1dfa99..4780e32 100644 --- a/mdbxdist/mdbx_load.c +++ b/mdbxdist/mdbx_load.c @@ -18,7 +18,7 @@ /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1160,7 +1160,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT diff --git a/mdbxdist/mdbx_stat.c b/mdbxdist/mdbx_stat.c index bffe386..5463c50 100644 --- a/mdbxdist/mdbx_stat.c +++ b/mdbxdist/mdbx_stat.c @@ -18,7 +18,7 @@ /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 -#define MDBX_BUILD_SOURCERY d79e72327b34c872db0c1e8bde5a171c679a0abe4bf48a8fafb5c6e131edfef6_v0_13_0_76_g32df0ad1 +#define MDBX_BUILD_SOURCERY 8a7ed0d2f8aeb7b9717769da24fc25220b34661de75b717be86738f994901302_v0_13_0_86_g22776ad5 #define LIBMDBX_INTERNALS @@ -1160,7 +1160,7 @@ typedef CRITICAL_SECTION osal_fastmutex_t; #if !defined(_MSC_VER) && !defined(__try) #define __try -#define __except(COND) if (false) +#define __except(COND) if (/* (void)(COND), */ false) #endif /* stub for MSVC's __try/__except */ #if MDBX_WITHOUT_MSVC_CRT