Compare commits

...

102 Commits

Author SHA1 Message Date
Леонид Юрьев (Leonid Yuriev)
1fff1f67d5 mdbx: выпуск 0.12.13
Завершающий выпуск архивной ветки с исправлением обнаруженных ошибок и устранением недочетов.

`git diff' stat: 14 commits, 7 files changed, 256 insertions(+), 103 deletions(-)`

Это последний/консервирующий выпуск куста стабильных версий 0.12.x, спустя более двух лет после выпуска 0.12.1.

Значимые исправления:
---------------------

 - Исправлена обработка `MDBX_GET_MULTIPLE` в специальных случаях и одного значения у ключа в позиции курсора.

 - Устранена ошибка неверной обработки попытки запуска вложенной читающей транзакции.
   Теперь в таких ситуациях возвращается ошибка `MDBX_EINVAL`, так как вложенность
   поддерживается только для транзакций чтения-записи.

   Ошибка была внесена при рефакторинге, коммитом `2f2df1ee76ab137ee66d00af69a82a30dc0d6deb`
   чуть более 5 лет назад и долго оставалось не замеченной.

 - Поддержка получения boot_id при работе внутри LXC-контейнера.

   Из LXC-контейнера не доступен файл хостовой системы `/proc/sys/kernel/random/boot_id`.
   Вместо него, при каждом старте контейнера, создается и заполняется
   случайными данными собственный boot_id смонтированный через bind из `tmpfs`.
   https://github.com/lxc/lxc/issues/3027

   Ранее этот подставной/замещенный boot_id отбраковывался внутри libmdbx,
   так как файл располагается в `tmpfs`, а не в файловой системе `/proc`.
   В результате boot_id для проверки целостности БД не был доступен.
   Теперь при работе внутри LXC-контейнера такой bootid будет использоваться.

   Однако, полноценно работающий контроль по boot_id не возможен, так как при
   рестарте LXC-контейнера (но не хоста) boot_id будет меняться, хотя
   данные в unified page cache сохраняются.

   Таким образом, при рестарте LXC-контейнера без рестарта хоста, libmdbx придется
   откатить состояние БД до крайней точки устойчивой фиксации, что повлечет
   утрату данных пользователя в случаях когда они могли быть сохранены.
   Однако, улучшить ситуацию пока не представляется возможным, как минимум
   до доступности boot_id хостовой системы изнутри LXC-контейнера.

 - Доработан контроль длины ключа внутри `cursor_set()`.

   Ранее проверка внутри `cursor_set()` не позволяла искать ключи длиннее, чем можно поместить в таблицу.
   Однако, при поиске/позиционировании это не является ошибкой для таблиц с ключами переменного размера.

 - Теперь при попытке запуска вложенных транзакций в режиме `MDBX_WRITEMAP` производится
   логирование и возврат ошибки `MDBX_INCOMPATIBLE`.

 - Доработано использование `std::experimental::filesystem` для решения проблем со сборкой в старых компиляторах.

Более подробная информация и история предыдущих выпусков доступна в [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).

Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2025-02-28 23:34:52 +03:00
Леонид Юрьев (Leonid Yuriev)
b000f8c431 mdbx++: доработка использования std::experimental::filesystem. 2025-02-28 23:23:34 +03:00
Леонид Юрьев (Leonid Yuriev)
3baaf70249 mdbx: доработка osal_bootid() для LXC (backport).
Из LXC-контейнера не доступен файл хостовой системы "/proc/sys/kernel/random/boot_id".
Вместо него, при каждом старте контейнера, создается и заполняется
случайными данными собственный boot_id смонтированный через bind из tmpfs.
https://github.com/lxc/lxc/issues/3027

Поэтому полноценный контроль по boot_id не возможен, так как при
рестарте LXC-контейнера (но не хоста) boot_id будет меняться, хотя
данные в unified page cache сохраняются.

Таким образом, при рестарте LXC-контейнера, libmdbx будет производить
откат БД до крайней точки устойчивой фиксации, что может приводить к
утрате данных пользователя в случаях когда они могли быть сохранены.
Однако, улучшить ситуацию пока не представляется возможным, как минимум
до доступности boot_id хостовой системы изнутри LXC-контейнера.

Этот коммит частично улучшает ситуацию тем, что позволяет использовать
фейковый/замещенный boot_id размещенный в файловой системе с типом tmpfs
при работе внутри LXC-контейнера.
2025-02-28 22:38:43 +03:00
Леонид Юрьев (Leonid Yuriev)
4447793652 mdbx: логирование и возврат MDBX_INCOMPATIBLE при попытке запуска вложенных транзакций в режиме MDBX_WRITEMAP (backport). 2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
a5c5e77c03 mdbx: доработка контроля длины ключа внутри cursor_set() (backport).
Ранее проверка внутри cursor_set() не позволяла искать ключи длиннее чем можно поместить в таблицу,
что при поиске/позиционировании не является ошибкой для ключей переменного размера.
2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
40a474e9b3 mdbx: исправление несогласованности MDBX_DPL_PREALLOC_FOR_RADIXSORT и assert-проверки внутри dpl_bytes2size() (backport). 2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
cc56710a1d mdbx: понижение уровня логирования "reserve depleted" при обновлении GC (backport). 2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
ae981c4f9a mdbx-doc: исправление орфографии/опечатки в ChangeLog (backport). 2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
4f3c8423db mdbx-doc: корректировка описания значения по-умолчанию MDBX_opt_txn_dp_limit (backport). 2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
5cbe91a6ab mdbx: опечатки в комментариях (backport). 2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
d41ebfa399 mdbx: корректировка doxygen-комментариев (backport). 2025-02-28 22:38:40 +03:00
Леонид Юрьев (Leonid Yuriev)
42561e3b8e mdbx: удаление лишних проверок внутри mdbx_dbi_close() (backport). 2024-12-22 19:35:12 +03:00
Леонид Юрьев (Leonid Yuriev)
9803259cab mdbx: возврат MDBX_EINVAL при попытке запустить вложенную читающую транзакцию (backport). 2024-12-13 08:16:04 +03:00
Леонид Юрьев (Leonid Yuriev)
e754b442a2 mdbx: исправление GET_MULTIPLE для случая одного значения.
Регрессия была внесена коммитом d94f34b2c0.
2024-11-26 15:49:45 +03:00
Леонид Юрьев (Leonid Yuriev)
6cfb2935f6 mdbx: обновление патча для старых версий buildroot. 2024-10-27 22:38:34 +03:00
Леонид Юрьев (Leonid Yuriev)
b16c2570f0 mdbx: выпуск 0.12.12 "Доллежаль".
Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов,
в память о советском ученом-энергетике Николае Антоновиче Доллежаль в день 125-летия со дня его рождения.

Это последний выпуск куста стабильных версий 0.12.x, спустя более двух
лет после выпуска 0.12.1. Последующие выпуски 0.12.x будут формироваться
только в случае существенных проблем/ошибок, вероятность чего близка к
нулю. Для всех проектов находящихся в стадии активной разраборки
рекомендуется использовать ветку `master`.

Значимые исправления:
---------------------

 - Исправление упущенного `TXN_END_EOTDONE` при сбое старта читающей транзакции.
   Упомянутый флажок отсутствовал в пути разрушения транзакции при ошибке
   её запуска. Из-за чего делалась попытка разрушить курсоры, что приводило
   к падению **отладочных сборок**, так как в них соответствующий массив
   намеренно заполнен некорректными указателями.

 - Устранение возможности `SIGSEGV` внутри `coherency_check()` после
   изменения геометрии другим процессом с увеличением верхнего размера БД
   и увеличением БД больше предыдущего лимита.

 - Доработка `mdbx_close_dbi()` для возврата ошибки при попытке закрыть
   dbi-дескриптор таблицы, созданной и/или измененной в ещё выполняющейся
   транзакции. Такое преждевременное закрытие дескриптора является неверным
   использованием API и нарушением контракта/предусловий сформулированных
   в описании `mdbx_close_dbi()`. Однако, вместо возврата ошибки
   выполнялось некорректное закрытие дескриптора, что могло приводить к
   созданию таблицы с пустым именем, утечки страниц БД и/или нарушению
   структуры b-tree (неверной ссылкой на корень таблицы).
   Добавлен соответствующий тест `extra/early_close_dbi`.

Более подробная информация и история предыдущих выпусков доступна в [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).

git diff' stat: 6 commits, 5 files changed, 239 insertions(+), 6 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2024-10-27 11:07:49 +03:00
Леонид Юрьев (Leonid Yuriev)
ac8402283f mdbx-testing: добавление extra/early_close_dbi (backport). 2024-10-26 23:10:56 +03:00
Леонид Юрьев (Leonid Yuriev)
945899e4fd mdbx: доработка mdbx_close_dbi() для возврата ошибки при попытке закрыть dbi-хендл измененной в транзакции таблицы (backport). 2024-10-26 23:01:37 +03:00
Леонид Юрьев (Leonid Yuriev)
222150bb28 mdbx-testing: добавление теста пересоздания таблицы с другими флагами/опциями (backport). 2024-10-26 23:01:01 +03:00
Леонид Юрьев (Leonid Yuriev)
497aabcb2e mdbx: устранение возможности SIGSEGV внутри coherency_check() (backport).
Падение происходило в случае когда:

 - Некоторый процесс увеличивал размер БД с изменением геометрии (с
   увеличением предельного размера БД и её отображения в ОЗУ), затем
   задействовал страницу из добавленного сегмента в качестве корневой для
   FreeDB/GC и/или MainDB и фиксировал транзакцию.

 - Другой процесс, уже работавший с БД до изменения геометрии первым
   процессом, запускал транзакцию чтения. Падение происходило при проверке
   «когерентности» отображения страниц БД в ОЗУ, при проверке отметок
   модификации внутри корневых страниц, так как в этом случае они были вне
   границ текущего отображения БД в адресном пространстве этого процесса.

 Похоже что в ходе какого-то рефакторинга потерялась соответствующая
 проверка. Этот коммит добавляет такую проверку.
2024-08-07 21:22:57 +03:00
Леонид Юрьев (Leonid Yuriev)
cf6d441e1b mdbx: исправление упущенного TXN_END_EOTDONE при сбое старта читающей транзакции (backport).
Упомянутый флажок отсутствовал в пути разрушения транзакции при ошибке
её запуска. Из-за чего делалась попытка разрушить курсоры, что приводило
к падению отладочных сборок, так как в них соответствующий массив
намеренно заполнен некорректными указателями.
2024-08-07 19:29:57 +03:00
Леонид Юрьев (Leonid Yuriev)
a6a7a291c7 mdbx: выпуск 0.12.11 "Лиза и Соня"
Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов,
в память об убитых в Крыму девочках 2 и 9 лет.

Лиза и Соня погибли 23 Июня 2024 на глазах у родителей, в результате
удара по общественному городскому пляжу ракетами ATACMS с кассетными
боеприпасами. Всего пострадало более 150 граждан России, в том числе 27
детей. Ракеты были выпущенными украинскими бандеровцами/фашистами, но
полетные задания формировались и загружались военными США, а управление
и наведение ATACAMS невозможно без использования орбитальной группировки
военных спутников США.

Основные исправления:
---------------------

 - Исправление для ОС Windows нарезки `FILE_SEGMENT_ELEMENT`.
   Похоже что был потерян коммит входе работы над оптимизацией пути записи
   на диск в ОС Windows. В текущем понимании, вероятность проявления ошибки
   достаточно низкая, так как выявлена она была синтетическими тестами в
   ходе других доработок, а соответствующих сообщений/жалоб не поступало. К
   повреждению БД ошибка не приводила, так как сбой происходил до записи
   данных с возвратом `ERROR_INVALID_PARAMETER` из системного вызова, т.е.
   либо ошибка не проявлялась, либо транзакция не фиксировалась.

 - Устранение вероятности `SIGSEGV` при включении логирования
   уровня `MDBX_LOG_TRACE` в отладочных сборках.

 - Исправление генерации исключения `key_exists` в C++ API.

 - Исправление обработки курсоров, открытых в родительских транзакциях и
   закрытых до завершения вложенных транзакций. В описанной ситуации
   закрытые курсоры "воскрешались", что приводило к утечке памяти
   выделенной под такие курсоры.

 - Костыль для MSVC ARM/ARM64 для предотвращения ICE (Internal Compiler Error).

 - Устранение `MDBX_EINVAL` для случая вызова `mdbx_env_remove(".")`.

 - Исправление инверсии bool-результата `env::remove()`в C++ API.

Более подробная информация в [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).

git diff' stat: 29 commits, 14 files changed, 379 insertions(+), 151 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2024-07-23 13:14:14 +03:00
Леонид Юрьев (Leonid Yuriev)
a8ef8d7b72 mdbx: обновление ChangeLog. 2024-07-22 17:46:55 +03:00
Леонид Юрьев (Leonid Yuriev)
5c40f6983c mdbx: использование clang-format-19. 2024-07-22 14:53:28 +03:00
Леонид Юрьев (Leonid Yuriev)
cda8ebe0bd mdbx: проверка совместмости флагов GC/FreeDB (backport). 2024-07-22 14:53:28 +03:00
Леонид Юрьев (Leonid Yuriev)
f5bbadf3a5 mdbx: отмена корректировки assert-проверки внутри override_meta() (revert-backport).
This reverts commit a0b520fa32.
2024-07-22 12:33:16 +03:00
Леонид Юрьев (Leonid Yuriev)
58cad2995b mdbx: до-исправление коммита 796b7e44976132944847694fc8caa5b01c07a406 для отладочных сборок. 2024-07-21 23:20:10 +03:00
Леонид Юрьев (Leonid Yuriev)
37217cb199 mdbx-windows: исправление нарезки FILE_SEGMENT_ELEMENT (backport).
Ошибка слишком грубая.
Похоже при переработке I/O под Windows при `git pull --rebase` потерялся коммит.

К повреждению БД проблема не приводила, так как сбой происходил во время записи данных с возвратом ERROR_INVALID_PARAMETER из системного вызова.
2024-07-20 22:54:15 +03:00
Леонид Юрьев (Leonid Yuriev)
a0b520fa32 mdbx: корректировка assert-проверки внутри override_meta() (backport).
После доработок/рефакторинга условие проверки стало неверным.
2024-06-28 12:44:51 +03:00
Леонид Юрьев (Leonid Yuriev)
796b7e4497 mdbx: устранение вероятности SIGSEGV при включении логирования MDBX_LOG_TRACE в отладочных сборках (backport). 2024-06-26 12:26:16 +03:00
Леонид Юрьев (Leonid Yuriev)
341a8b8b5c mdbx++: исправление генерации исключения key_exists (backport).
Из-за совершенной при размножении кода ошибки, вместо отдельного
исключения `mdbx::key_exists` при ошибке `MDBX_KEYEXIST` вбрасывалось
исключении более общего/генерализированного типа `mdbx::exception`.
2024-06-13 11:12:12 +03:00
Леонид Юрьев (Leonid Yuriev)
ad0b13a544 mdbx-doc: исправление опечаток в README. 2024-06-04 12:48:48 +03:00
Леонид Юрьев (Leonid Yuriev)
ba42390a56 mdbx++: исправление append_u8() (backport).
Добавленные после предыдущего выпуска append-функции оказались ошибочны.
Алгоритмически там серия однотипных банальных ошибок (почти опечаток),
из-за которых добавляемые данные записывались в начало среза/slice, а не
в конец.

Исходные ошибки были выявлены тестами в другом проекте и исправлены
почти сразу, но плохой код всё-таки попал в stable-ветку.
Предположительно я спутал ветки и/или tmux-окна, и взял в stable-ветку не
исправленный коммит. Удивительно, что плохой код в devel-ветке не
нарушил работу части новых тестов. Поэтому проблема некоторое время
оставалась не замеченной.
2024-06-04 10:56:15 +03:00
Леонид Юрьев (Leonid Yuriev)
07cfe65ea0 mdbx: исправление закрытия курсоров при завершении вложенных транзакций (backport). 2024-05-25 18:17:10 +03:00
Леонид Юрьев (Leonid Yuriev)
75fd4ecf54 mdbx-testing: костыль для MSVC ARM/ARM64 для предотвращения ICE (backport). 2024-05-22 01:21:10 +03:00
Леонид Юрьев (Leonid Yuriev)
97b0b0192e mdbx-windows: чистка результатов FormatMessageA() от концевых переводов строк (backport). 2024-05-21 18:29:22 +03:00
Леонид Юрьев (Leonid Yuriev)
12e6c631f1 mdbx: уточнение макроса __always_inline для особо яблочных компиляторов (backport). 2024-05-20 18:26:45 +03:00
Леонид Юрьев (Leonid Yuriev)
458f713c53 mdbx++: использование \n вместо std::endl (backport). 2024-05-20 18:24:47 +03:00
Леонид Юрьев (Leonid Yuriev)
a5ed725ae3 mdbx: явное обноление txn и dbi_state у вложенных курсоров для вложенных транзакций. 2024-05-18 13:12:08 +03:00
Леонид Юрьев (Leonid Yuriev)
dd9ba2c769 mdbx: проверка на ноль дополнительных и пока не используемых полей в meta-страницах. 2024-05-13 21:18:30 +03:00
Леонид Юрьев (Leonid Yuriev)
d1565fd326 mdbx: отключение уже ненужной отладки внутри txn_merge() (backport). 2024-04-15 08:18:08 +03:00
Леонид Юрьев (Leonid Yuriev)
e3d4cd5758 mdbx: исправление условий для MDBX_DEPRECATED (backport). 2024-04-04 15:24:10 +03:00
Леонид Юрьев (Leonid Yuriev)
2d2cec094e mdbx: устранение MDBX_EINVAL в случае mdbx_env_remove(".") (backport). 2024-04-04 15:24:04 +03:00
Леонид Юрьев (Leonid Yuriev)
41ebd6dcf3 mdbx++: исправление инверсии bool-результата env::remove() (backport). 2024-04-04 15:15:46 +03:00
Леонид Юрьев (Leonid Yuriev)
f40b2fc164 mdbx++: больше __cold для редко-используемых функций (backport). 2024-04-04 15:15:46 +03:00
Леонид Юрьев (Leonid Yuriev)
8f32f4ac98 mdbx++: buffer::append_bytes() (backport). 2024-04-04 15:15:46 +03:00
Леонид Юрьев (Leonid Yuriev)
c1d3afcbe1 mdbx++: добавление buffer::clear_and_reserve() (backport). 2024-04-04 15:15:46 +03:00
Леонид Юрьев (Leonid Yuriev)
5721296e16 mdbx: опечатки и орфография в ChangeLog. 2024-03-28 11:37:23 +03:00
Леонид Юрьев (Leonid Yuriev)
04f1200c3d mdbx-doc: исправление опечатки в MDBX_ENV_JUST_DELETE (backport). 2024-03-22 00:28:03 +03:00
Леонид Юрьев (Leonid Yuriev)
dfcd652e5c mdbx: не взводим MDBX_FATAL_ERROR для не-активной среды при проверке MDBX_ENV_CHECKPID (backport). 2024-03-21 13:22:33 +03:00
Леонид Юрьев (Leonid Yuriev)
25089e6491 mdbx: merge branch master into stable. 2024-03-21 01:10:00 +03:00
Леонид Юрьев (Leonid Yuriev)
8cc3dba7ae mdbx: merge branch master into stable. 2024-03-14 19:48:12 +03:00
Леонид Юрьев (Leonid Yuriev)
4f770999a8 mdbx: merge branch master into stable. 2023-12-12 10:15:27 +03:00
Леонид Юрьев (Leonid Yuriev)
93429d3a23 mdbx: merge branch master into stable. 2023-10-23 18:15:26 +03:00
Леонид Юрьев (Leonid Yuriev)
3d187abc1b mdbx: merge branch master into stable. 2023-06-18 17:18:16 +03:00
Леонид Юрьев (Leonid Yuriev)
4151e0e348 mdbx: merge branch master into stable. 2023-04-18 16:29:05 +03:00
Леонид Юрьев (Leonid Yuriev)
c81b007587 mdbx: merge branch master into stable.
Ветка 0.12 считается готовой к продуктовому использованию,
получает статус стабильной и далее будет получать только исправление ошибок.

Разработка будет продолжена в ветке 0.13, а ветка 0.11 становится архивной.
2023-03-04 00:00:24 +03:00
Леонид Юрьев (Leonid Yuriev)
b415265d16 mdbx: release v0.11.14 (Sergey Kapitsa)
The stable bugfix release in memory of [Sergey Kapitsa](https://en.wikipedia.org/wiki/Sergey_Kapitsa) on his 95th birthday.

Fixes:
------

 - backport: Fixed insignificant typo of `||` inside `#if` byte-order condition.

 - backport: Fixed `SIGSEGV` or an erroneous call to `free()` in situations where
   errors occur when reopening by `mdbx_env_open()` of a previously used
   environment.

 - backport: Fixed `cursor_put_nochecklen()` internals for case when dupsort'ed named subDb
   contains a single key with multiple values (aka duplicates), which are replaced
   with a single value by put-operation with the `MDBX_UPSERT+MDBX_ALLDUPS` flags.
   In this case, the database becomes completely empty, without any pages.
   However exactly this condition was not considered and thus wasn't handled correctly.
   See [issue#8](https://gitflic.ru/project/erthink/libmdbx/issue/8) for more information.

 - backport: Fixed extra assertion inside `override_meta()`, which could
   lead to false-positive failing of the assertion in a debug builds during
   DB recovery and auto-rollback.

 - backport: Refined the `__cold`/`__hot` macros to avoid the
   `error: inlining failed in call to ‘always_inline FOO(...)’: target specific option mismatch`
   issue during build using GCC >10.x for SH4 arch.

Minors:
-------

 - backport: Using the https://libmdbx.dqdkfa.ru/dead-github
   for resources deleted by the Github' administration.
 - backport: Fixed English typos.
 - backport: Fixed proto of `__asan_default_options()`.
 - backport: Fixed doxygen-description of C++ API, especially of C++20 concepts.
 - backport: Refined `const` and `noexcept` for few C++ API methods.
 - backport: Fixed copy&paste typo of "Getting started".
 - backport: Update MithrilDB status.
 - backport: Resolve false-posirive `used uninitialized` warning from GCC >10.x
   while build for SH4 arch.

22 files changed, 250 insertions(+), 174 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2023-02-14 15:10:41 +03:00
Леонид Юрьев (Leonid Yuriev)
257a534fbe mdbx: update ChangeLog. 2023-02-13 21:35:20 +03:00
Леонид Юрьев (Leonid Yuriev)
33b5aeb768 mdbx: refine __cold/__hot macros (backport).
В том числе для устранения проблемы
`error: inlining failed in call to ‘always_inline FOO(...)’: target specific option mismatch`
при сборке посредством GCC >10.x для SH4.
2023-02-13 21:35:20 +03:00
Леонид Юрьев (Leonid Yuriev)
f532e907e9 mdbx: fix false-positive SH4 GCC warning (backport). 2023-02-13 21:35:20 +03:00
Леонид Юрьев (Leonid Yuriev)
60736dbabb mdbx: fix English typos (backport).
Thanks to Dimitris Apostolou <dimitris.apostolou@icloud.com>
2023-02-13 21:35:20 +03:00
Леонид Юрьев (Leonid Yuriev)
24df8073ac mdbx: fix extra assertion inside override_meta() (backport). 2023-02-13 21:35:20 +03:00
Леонид Юрьев (Leonid Yuriev)
d504ca1747 mdbx: fix proto of __asan_default_options() (backport). 2023-02-13 21:35:14 +03:00
Леонид Юрьев (Leonid Yuriev)
b7ace5b216 mdbx-doc: fix doxygen-description of C++ API, especially of C++20 concepts (backport). 2023-02-13 21:28:33 +03:00
Леонид Юрьев (Leonid Yuriev)
2fabac18c0 mdbx++: refine const and noexcept for few C++ API methods (backport). 2023-02-13 21:27:55 +03:00
Леонид Юрьев (Leonid Yuriev)
51789f3605 mdbx: fix put(MDBX_UPSERT+MDBX_ALLDUPS) for case of replacement all values of a single key inside dupsorted subDb (backport).
Fixed cursor_put_nochecklen() internals for case when dupsort'ed named subDb
contains a single key with multiple values (aka duplicates), which are replaced
with a single value by put-operation with the `MDBX_UPSERT+MDBX_ALLDUPS` flags.

In this case, the database becomes completely empty, without any pages.
However exactly this condition was not considered and
thus wasn't handled correctly.

Fixes https://gitflic.ru/project/erthink/libmdbx/issue/8

Thanks Masatoshi Fukunaga <https://gitflic.ru/user/mah0x211> for reporting.
2023-02-13 21:27:55 +03:00
Леонид Юрьев (Leonid Yuriev)
6899142872 mdbx: remove extra assertion (backport).
The removed assertion could be triggered in debug builds when a reading
and writing transactions are overlapped simultaneously with a change of DB
size.

There were no other negative consequences.
2023-02-13 21:27:44 +03:00
Леонид Юрьев (Leonid Yuriev)
c44c8132e4 mdbx-doc: fix copy&paste typo of "Getting started" (backport). 2023-02-13 21:27:10 +03:00
Леонид Юрьев (Leonid Yuriev)
d376feb7bc mdbx: update MithrilDB status (backport). 2023-02-13 21:26:49 +03:00
Леонид Юрьев (Leonid Yuriev)
47851135f3 mdbx-doc: using the https://libmdbx.dqdkfa.ru/dead-github for resources deleted by the Github' administration (backport). 2022-12-03 06:23:31 +03:00
Леонид Юрьев (Leonid Yuriev)
6139443ef1 mdbx: fix SIGSEGV/invalid-deref/invalid-free inside env_close() when mdbx_env_open() failed in re-open case (backport).
Thanks to [@leisim](https://t.me/leisim) for [reporting](https://t.me/libmdbx/3946) this issue.
2022-12-03 05:48:30 +03:00
Jan Biedermann
30f292d496 mdbx: fix typo of || inside #if byte-order condition (backport).
https://gitflic.ru/project/erthink/libmdbx/merge-request/4
2022-12-03 05:47:36 +03:00
Леонид Юрьев (Leonid Yuriev)
d6b47c7bd1 mdbx: release v0.11.13 (Swashplate)
The stable bugfix release in memory of [Boris Yuryev](https://ru.wikipedia.org/wiki/Юрьев,_Борис_Николаевич) on his 133rd birthday.

Fixes:
------

 - Fixed builds with older libc versions after using `fcntl64()` (backport).
 - Fixed builds with  older `stdatomic.h` versions,
   where the `ATOMIC_*_LOCK_FREE` macros mistakenly redefined using functions (backport).
 - Added workaround for `mremap()` defect to avoid assertion failure (backport).
 - Workaround for `encryptfs` bug(s) in the `copy_file_range` implementation  (backport).
 - Fixed unexpected `MDBX_BUSY` from `mdbx_env_set_option()`, `mdbx_env_set_syncbytes()`
   and `mdbx_env_set_syncperiod()` (backport).
 - CMake requirements lowered to version 3.0.2 (backport).
 - Added admonition of insecure for RISC-V (backport).

Minors:
-------

 - Minor clarification output of `--help` for `mdbx_test` (backport).
 - Added admonition of insecure for RISC-V (backport).
 - Stochastic scripts and CMake files synchronized with the `devel` branch.
 - Use `--dont-check-ram-size` for small-tests make-targets (backport).

30 files changed, 405 insertions(+), 136 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2022-11-10 13:07:28 +03:00
Леонид Юрьев (Leonid Yuriev)
8f0c5bc7c7 mdbx: update ChangeLog. 2022-11-10 12:11:11 +03:00
Леонид Юрьев (Leonid Yuriev)
29eab4afdd mdbx-make: use --dont-check-ram-size for small-tests targets (backport). 2022-11-10 12:09:34 +03:00
Леонид Юрьев (Leonid Yuriev)
12717aac8c mdbx-test: sync stochastic scripts with devel branch. 2022-11-10 10:57:16 +03:00
Леонид Юрьев (Leonid Yuriev)
e992da9efe mdbx-cmake: синхронизация CMake-файлов. 2022-11-10 01:10:39 +03:00
Леонид Юрьев (Leonid Yuriev)
d7e4cb2e22 mdbx: add admonition of insecure for RISC-V (backport). 2022-11-10 01:10:39 +03:00
Леонид Юрьев (Leonid Yuriev)
af1d01ffb3 mdbx-windows: уточнение проверок макросов MinGW и устранение предупреждений (backport). 2022-11-10 01:10:39 +03:00
Леонид Юрьев (Leonid Yuriev)
cce052e869 mdbx-cmake: совместимость с CMake 3.0.2 для CI на старых системах (backport). 2022-11-10 00:48:54 +03:00
Леонид Юрьев (Leonid Yuriev)
094c2f345d mdbx: переименование packages/rpm (backport). 2022-11-10 00:48:54 +03:00
Леонид Юрьев (Leonid Yuriev)
7b2eee91af mdbx: добавлено описание параметров MDBX_debug_func и MDBX_debug_func (backport). 2022-11-10 00:48:54 +03:00
Леонид Юрьев (Leonid Yuriev)
d863629387 mdbx-test: минорное уточнение подсказки --help (backport). 2022-11-10 00:48:54 +03:00
Леонид Юрьев (Leonid Yuriev)
1b3b6e4479 mdbx: исправление неожиданного MDBX_BUSY из mdbx_env_set_option() (backport). 2022-11-10 00:48:54 +03:00
Леонид Юрьев (Leonid Yuriev)
5dcc0171fa mdbx-windows: попытка борьбы с ложно-положительными конфликтами LockFileEx() (backport). 2022-11-10 00:48:54 +03:00
Леонид Юрьев (Leonid Yuriev)
425730c2b3 mdbx: чуток апостофов для имен в doxygen-комментариях (backport). 2022-11-07 16:44:00 +03:00
Леонид Юрьев (Leonid Yuriev)
471e854551 mdbx: workaround for encryptfs's copy_file_range() bug(s) (backport).
Выяснилось что утилита `mdbx_copy` и функции `mdbx_env_copy()` могут
создавать ПРОБЛЕМЫ если целевой файл расположен в encryptfs (такая
файловая система в Linux).

При этом может быть четыре исхода в зависимости от версии ядра и
положения звезд на небе:
 - всё хорошо;
 - плохие данные в копии без возврата ошибок;
 - ошибка EINVAL(22) при копировании;
 - oops или зависание ядра, отвал смонтированной encryptfs и т.п.

В текущем понимании, причина обусловлена ошибой в коде fs, которая
проявляется при использовании системного вызова `copy_file_range`.
2022-11-07 16:44:00 +03:00
Леонид Юрьев (Leonid Yuriev)
1bd0eb35bc mdbx-cmake: исправление для совместимости с CMake 3.8 (backport). 2022-11-07 16:43:32 +03:00
Леонид Юрьев (Leonid Yuriev)
6fdae12996 mdbx: workaround for mremap() defect (backport).
Есть основание полагать, что mremap() может возвращать MAP_FAILED, но НЕ
устанавливать errno в некоторых пограничных ситуациях. Например, когда
системных ресурсов не хватает на актуализацию/копирование/клонирование
состояния отображения на финальной стадии, в том числе из-за раскраски
исходного отображения разными флагами через madvise().
2022-10-14 14:05:44 +03:00
Леонид Юрьев (Leonid Yuriev)
2684c89d91 mdbx: workaround for older stdatomic.h versions, where the ATOMIC_*_LOCK_FREE macros mistakenly redefined using functions (backport). 2022-10-14 14:05:16 +03:00
Леонид Юрьев (Leonid Yuriev)
7b60363a31 mdbx: fix builds with older libc versions after using fcntl64() (backport). 2022-10-14 14:01:02 +03:00
Леонид Юрьев (Leonid Yuriev)
290630f118 mdbx: release v0.11.12 (Эребуни)
The stable bugfix release.

Fixes:
------

 - Fixed static assertion failure on platforms where the `off_t` type is wider
   than corresponding fields of `struct flock` used for file locking (backport).
   Now _libmdbx_ will use `fcntl64(F_GETLK64/F_SETLK64/F_SETLKW64)` if available.
 - Fixed assertion check inside `page_retire_ex()` (backport).

Minors:
-------

 - Fixed `-Wint-to-pointer-cast` warnings while casting to `mdbx_tid_t` (backport).
 - Removed needless `LockFileEx()` inside `mdbx_env_copy()` (backport).

11 files changed, 96 insertions(+), 49 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2022-10-12 21:11:47 +03:00
Леонид Юрьев (Leonid Yuriev)
bdcc345455 mdbx: minor fix assertion check inside page_retire_ex() (backport). 2022-10-12 21:00:35 +03:00
Леонид Юрьев (Leonid Yuriev)
db9e2c6f07 mdbx: using fcntl64(F_GETLK64/F_SETLK64/F_SETLKW64) when available (backport).
This fixes issues (static assertion failure, etc) on platforms where the
`off_t` type is wider than corresponding fields of `struct flock`.
2022-10-12 20:59:05 +03:00
Леонид Юрьев (Leonid Yuriev)
50e9e0e561 mdbx-windows: drop needless LockFileEx() inside mdbx_env_copy() (backport). 2022-10-12 18:32:56 +03:00
Леонид Юрьев (Leonid Yuriev)
8505203080 mdbx: avoid -Wint-to-pointer-cast warnings while casting to mdbx_tid_t (backport). 2022-10-12 18:32:49 +03:00
Леонид Юрьев (Leonid Yuriev)
50ba4bc2f2 mdbx: release v0.11.11 (Тендра-1790)
The stable bugfix release.
It is planned that this will be the last release of the v0.11 branch.

Fixes:
------

 - Fixed an extra check for `MDBX_APPENDDUP` inside `mdbx_cursor_put()` which could result in returning `MDBX_EKEYMISMATCH` for valid cases.
 - Fixed an extra ensure/assertion check of `oldest_reader` inside `mdbx_txn_end()`.
 - Fixed derived C++ builds by removing `MDBX_INTERNAL_FUNC` for `mdbx_w2mb()` and `mdbx_mb2w()`.

10 files changed, 38 insertions(+), 21 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2022-09-11 14:33:56 +03:00
Леонид Юрьев (Leonid Yuriev)
cf6576984d mdbx: update ChangeLog. 2022-09-11 13:08:21 +03:00
Леонид Юрьев (Leonid Yuriev)
4f3e1a60f1 mdbx: remove MDBX_INTERNAL_FUNC from mdbx_w2mb() and mdbx_mb2w() for C++ API. 2022-09-11 13:04:49 +03:00
Леонид Юрьев (Leonid Yuriev)
04f60af669 mdbx: minor fix extra ensure/assertion check of oldest_reader inside txn_end(). 2022-09-09 19:56:48 +03:00
Леонид Юрьев (Leonid Yuriev)
c6cd642ff1 mdbx: fix extra check for MDBX_APPENDDUP. 2022-09-09 19:48:24 +03:00
17 changed files with 856 additions and 252 deletions

View File

@@ -4,6 +4,177 @@ ChangeLog
English version [by Google](https://gitflic-ru.translate.goog/project/erthink/libmdbx/blob?file=ChangeLog.md&_x_tr_sl=ru&_x_tr_tl=en)
and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/gitflic.ru/project/erthink/libmdbx/blob?file=ChangeLog.md).
## v0.12.13 от 2025-02-28
Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов.
Это последний/консервирующий выпуск куста стабильных версий 0.12.x, спустя более двух
лет после выпуска 0.12.1.
```
git diff' stat: 14 commits, 7 files changed, 256 insertions(+), 103 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
```
Значимые исправления:
- Исправлена обработка `MDBX_GET_MULTIPLE` в специальных случаях и одного значения у ключа в позиции курсора.
- Устранена ошибка неверной обработки попытки запуска вложенной читающей транзакции.
Теперь в таких ситуациях возвращается ошибка `MDBX_EINVAL`, так как вложенность
поддерживается только для транзакций чтения-записи.
Ошибка была внесена при рефакторинге, коммитом `2f2df1ee76ab137ee66d00af69a82a30dc0d6deb`
чуть более 5 лет назад и долго оставалось не замеченной.
- Поддержка получения boot_id при работе внутри LXC-контейнера.
Из LXC-контейнера не доступен файл хостовой системы `/proc/sys/kernel/random/boot_id`.
Вместо него, при каждом старте контейнера, создается и заполняется
случайными данными собственный boot_id смонтированный через bind из `tmpfs`.
https://github.com/lxc/lxc/issues/3027
Ранее этот подставной/замещенный boot_id отбраковывался внутри libmdbx,
так как файл располагается в `tmpfs`, а не в файловой системе `/proc`.
В результате boot_id для проверки целостности БД не был доступен.
Теперь при работе внутри LXC-контейнера такой bootid будет использоваться.
Однако, полноценно работающий контроль по boot_id не возможен, так как при
рестарте LXC-контейнера (но не хоста) boot_id будет меняться, хотя
данные в unified page cache сохраняются.
Таким образом, при рестарте LXC-контейнера без рестарта хоста, libmdbx придется
откатить состояние БД до крайней точки устойчивой фиксации, что повлечет
утрату данных пользователя в случаях когда они могли быть сохранены.
Однако, улучшить ситуацию пока не представляется возможным, как минимум
до доступности boot_id хостовой системы изнутри LXC-контейнера.
- Доработан контроль длины ключа внутри `cursor_set()`.
Ранее проверка внутри `cursor_set()` не позволяла искать ключи длиннее, чем можно поместить в таблицу.
Однако, при поиске/позиционировании это не является ошибкой для таблиц с ключами переменного размера.
- Теперь при попытке запуска вложенных транзакций в режиме `MDBX_WRITEMAP` производится
логирование и возврат ошибки `MDBX_INCOMPATIBLE`.
- Доработано использование `std::experimental::filesystem` для решения проблем со сборкой в старых компиляторах.
--------------------------------------------------------------------------------
## v0.12.12 "Доллежаль" от 2024-10-27
Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов,
в память о советском ученом-энергетике Николае Антоновиче Доллежаль в день 125-летия со дня его рождения.
Это последний выпуск куста стабильных версий 0.12.x, спустя более двух
лет после выпуска 0.12.1. Последующие выпуски 0.12.x будут формироваться
только в случае существенных проблем/ошибок, вероятность чего близка к
нулю. Для всех проектов находящихся в стадии активной разраборки
рекомендуется использовать ветку `master`.
```
git diff' stat: 6 commits, 5 files changed, 239 insertions(+), 6 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
```
Значимые исправления:
- Исправление упущенного `TXN_END_EOTDONE` при сбое старта читающей транзакции.
Упомянутый флажок отсутствовал в пути разрушения транзакции при ошибке
её запуска. Из-за чего делалась попытка разрушить курсоры, что приводило
к падению **отладочных сборок**, так как в них соответствующий массив
намеренно заполнен некорректными указателями.
- Устранение возможности `SIGSEGV` внутри `coherency_check()` после
изменения геометрии другим процессом с увеличением верхнего размера БД
и увеличением БД больше предыдущего лимита.
- Доработка `mdbx_close_dbi()` для возврата ошибки при попытке закрыть
dbi-дескриптор таблицы, созданной и/или измененной в ещё выполняющейся
транзакции. Такое преждевременное закрытие дескриптора является неверным
использованием API и нарушением контракта/предусловий сформулированных
в описании `mdbx_close_dbi()`. Однако, вместо возврата ошибки
выполнялось некорректное закрытие дескриптора, что могло приводить к
созданию таблицы с пустым именем, утечки страниц БД и/или нарушению
структуры b-tree (неверной ссылкой на корень таблицы).
Добавлен соответствующий тест `extra/early_close_dbi`.
--------------------------------------------------------------------------------
## v0.12.11 "Лиза и Соня" от 2024-07-23
Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов,
в память об убитых в Крыму девочках 2 и 9 лет.
Лиза и Соня погибли 23 Июня 2024 на глазах у родителей, в результате
удара по общественному городскому пляжу ракетами ATACMS с кассетными
боеприпасами. Всего пострадало более 150 граждан России, в том числе 27
детей. Ракеты были выпущенными украинскими бандеровцами/фашистами, но
полетные задания формировались и загружались военными США, а управление
и наведение ATACAMS невозможно без использования орбитальной группировки
военных спутников США.
```
git diff' stat: 29 commits, 14 files changed, 379 insertions(+), 151 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
```
Значимые исправления:
- Исправление для ОС Windows нарезки `FILE_SEGMENT_ELEMENT`.
Похоже что был потерян коммит входе работы над оптимизацией пути записи
на диск в ОС Windows. В текущем понимании, вероятность проявления ошибки
достаточно низкая, так как выявлена она была синтетическими тестами в
ходе других доработок, а соответствующих сообщений/жалоб не поступало. К
повреждению БД ошибка не приводила, так как сбой происходил до записи
данных с возвратом `ERROR_INVALID_PARAMETER` из системного вызова, т.е.
либо ошибка не проявлялась, либо транзакция не фиксировалась.
- Устранение вероятности `SIGSEGV` при включении логирования
уровня `MDBX_LOG_TRACE` в отладочных сборках.
- Исправление генерации исключения `key_exists` в C++ API.
- Исправление опечаток в документации и README.
- Исправление обработки курсоров, открытых в родительских транзакциях и
закрытых до завершения вложенных транзакций. В описанной ситуации
закрытые курсоры "воскрешались", что приводило к утечке памяти
выделенной под такие курсоры.
- Костыль для MSVC ARM/ARM64 для предотвращения ICE (Internal Compiler Error).
- Устранение `MDBX_EINVAL` для случая вызова `mdbx_env_remove(".")`.
- Исправление инверсии bool-результата `env::remove()` в C++ API.
- Исправление опечатки `равно`/`неравно` в условии внутри
`update_gc()`. Существенных последствий ошибки не было, но в
определенных сценариях, сходимость требовала еще одного цикла повтора
внутри update_gc().
Прочие доработки:
- Проверка совместимости флагов GC/FreeDB на случай их изменения в будущих версиях.
- Очистка сообщений `FormatMessageA()` от концевых переводов строк.
- Уточнение макроса `__always_inline` для особо яблочных версий CLANG.
- Использование `\n` вместо `std::endl` в C++ API для разделения строк в кодировщиках данных.
- Проверка дополнительных и пока не используемых полей в meta-страницах.
- Отключение ненужной отладки внутри `txn_merge()`.
- Исправление условий и привязки к версиям компиляторов при формировании макроса `MDBX_DEPRECATED`.
- Больше атрибутов `__cold` для редко-используемых функций (backport).
- Добавление методов `buffer::append_bytes()` и `buffer::clear_and_reserve()`.
- Отключение установки признака фатальной ошибки для не-активной среды при отличии идентификатора процесса.
--------------------------------------------------------------------------------
## v0.12.10 "СЭМ" от 2024-03-12
Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов
@@ -35,7 +206,7 @@ Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
вероятность проявления близка к нулю, а сценарий такого проявления найти не удалось.
В MDBX ошибка присутствовала с момента отделения проекта от LMDB,
где эта ошибка присутствует более 11 лети, по настоящее время.
где эта ошибка присутствует более 11 лет, по настоящее время.
- Исправление ложной ошибки `MDBX_CORRUPTED (-30796)` в сценарии работы
в режиме `MDBX_DUPFIXED` и нечетной длиной мульти-значений.
@@ -46,7 +217,7 @@ Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
- Доработка `rebalance()` ради уменьшения WAF. Новый функционал, включая
контролируемую пользователем опцию `enum MDBX_option_t`, будет доступен
в выпусках ветки `0.13.x`, а в этом выпуске доработка сводится к тактике
не-вовленичения чистой страницы при нехватке запаса страниц в ходе обновления GC,
не-вовлечения чистой страницы при нехватке запаса страниц в ходе обновления GC,
за счет ухудшения баланса дерева страниц.
- Устранение упущения приводящего к нелогичной ситуации
@@ -169,7 +340,7 @@ Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
- Устранение регресса/ошибки в пути обработки `put(MDBX_MULTIPLE)` при пакетном/оптовом
помещении в БД множественных значений одного ключа (aka multi-value или dupsort).
Проявление проблемы зависит от компилятора и опций оптимизации/кодогенерации, но с большой вероятностью возвращется
Проявление проблемы зависит от компилятора и опций оптимизации/кодогенерации, но с большой вероятностью возвращается
ошибка `MDBX_BAD_VALSIZE` (`-30781`), а в отладочных сборках срабатывает проверка `cASSERT(mc, !"Invalid key-size")`.
Сценарии приводящие к другим проявлениям на данный момент не известны.
@@ -1827,7 +1998,7 @@ Deprecated functions and flags:
- Rework `MADV_DONTNEED` threshold.
- Fix `mdbx_chk` utility for don't checking some numbers if walking on the B-tree was disabled.
- Use page's mp_txnid for basic integrity checking.
- Add `MDBX_FORCE_ASSERTIONS` built-time option.
- Add `MDBX_FORCE_ASSERTIONS` build-time option.
- Rework `MDBX_DBG_DUMP` to avoid performance degradation.
- Rename `MDBX_NOSYNC` to `MDBX_SAFE_NOSYNC` for clarity.
- Interpret `ERROR_ACCESS_DENIED` from `OpenProcess()` as 'process exists'.

View File

@@ -2,15 +2,14 @@
### Время учить Русский
Начиная с 2021 года наблюдается устойчивые тенденции к распространению
недостоверной информации о _libmdbx_ в странах ~~НАТО~~,
политизированной критика, а также отказу от использования библиотеки в
пользу LMDB, несмотря на явные проблемы с одной стороны и преимущества с
другой. Поэтому начиная с 17 марта 2024 года прекращается
документирование и сопровождение проекта на английском языке. Новый
функционал будет документироваться только на русском языке, однако,
целенаправленного переписывания/перевода документации пока не
планируется.
Начиная с 2021 года наблюдаются устойчивые тенденции к распространению
недостоверной информации о _libmdbx_ в странах НАТО, политизированной
критики, а также отказу от использования библиотеки в пользу LMDB,
несмотря на явные проблемы с одной стороны и преимущества с другой.
Поэтому, начиная с 17 марта 2024 года, прекращается документирование и
сопровождение проекта на английском языке. Новая функциональность будет
документироваться только на русском языке, однако, целенаправленного
переписывания/перевода документации пока не планируется.
### The origin has been migrated to [GitFlic](https://gitflic.ru/project/erthink/libmdbx)
Since on 2022-04-15 the Github administration, without any warning

20
mdbx.h
View File

@@ -343,13 +343,14 @@ typedef mode_t mdbx_mode_t;
#ifdef __deprecated
#define MDBX_DEPRECATED __deprecated
#elif defined(DOXYGEN) || \
(defined(__cplusplus) && __cplusplus >= 201603L && \
__has_cpp_attribute(maybe_unused) && \
__has_cpp_attribute(maybe_unused) >= 201603L) || \
(defined(__cplusplus) && __cplusplus >= 201403L && \
__has_cpp_attribute(deprecated) && \
__has_cpp_attribute(deprecated) >= 201309L) || \
(!defined(__cplusplus) && defined(__STDC_VERSION__) && \
__STDC_VERSION__ > 202005L)
__STDC_VERSION__ >= 202304L)
#define MDBX_DEPRECATED [[deprecated]]
#elif defined(__GNUC__) || __has_attribute(__deprecated__)
#elif (defined(__GNUC__) && __GNUC__ > 5) || \
(__has_attribute(__deprecated__) && !defined(__GNUC__))
#define MDBX_DEPRECATED __attribute__((__deprecated__))
#elif defined(_MSC_VER)
#define MDBX_DEPRECATED __declspec(deprecated)
@@ -2161,7 +2162,8 @@ enum MDBX_option_t {
* spill to disk instead.
*
* The `MDBX_opt_txn_dp_limit` controls described threshold for the current
* process. Default is 65536, it is usually enough for most cases. */
* process. Default is 1/42 of the sum of whole and currently available RAM
* size, which the same ones are reported by \ref mdbx_get_sysraminfo(). */
MDBX_opt_txn_dp_limit,
/** \brief Controls the in-process initial allocation size for dirty pages
@@ -2389,7 +2391,7 @@ enum MDBX_env_delete_mode_t {
/** \brief Just delete the environment's files and directory if any.
* \note On POSIX systems, processes already working with the database will
* continue to work without interference until it close the environment.
* \note On Windows, the behavior of `MDB_ENV_JUST_DELETE` is different
* \note On Windows, the behavior of `MDBX_ENV_JUST_DELETE` is different
* because the system does not support deleting files that are currently
* memory mapped. */
MDBX_ENV_JUST_DELETE = 0,
@@ -5037,7 +5039,7 @@ LIBMDBX_API int mdbx_cursor_del(MDBX_cursor *cursor, MDBX_put_flags_t flags);
* sorted duplicate data items \ref MDBX_DUPSORT.
*
* \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open().
* \param [out] pcount Address where the count will be stored.
* \param [out] count Address where the count will be stored.
*
* \returns A non-zero error value on failure and 0 on success,
* some possible errors are:
@@ -5045,7 +5047,7 @@ LIBMDBX_API int mdbx_cursor_del(MDBX_cursor *cursor, MDBX_put_flags_t flags);
* by current thread.
* \retval MDBX_EINVAL Cursor is not initialized, or an invalid parameter
* was specified. */
LIBMDBX_API int mdbx_cursor_count(const MDBX_cursor *cursor, size_t *pcount);
LIBMDBX_API int mdbx_cursor_count(const MDBX_cursor *cursor, size_t *count);
/** \brief Determines whether the cursor is pointed to a key-value pair or not,
* i.e. was not positioned or points to the end of data.

160
mdbx.h++
View File

@@ -78,11 +78,34 @@
#include <string_view>
#endif
#if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L
#include <filesystem>
#ifndef MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM
#ifdef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
#define MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM 1
#elif defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \
__cplusplus >= 201703L
#define MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM 0
#elif (!defined(_MSC_VER) || __cplusplus >= 201403L || \
(defined(_MSC_VER) && \
defined(_SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING) && \
__cplusplus >= 201403L))
#if defined(__cpp_lib_experimental_filesystem) && \
__cpp_lib_experimental_filesystem >= 201406L
#define MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM 1
#elif defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L && \
__has_include(<experimental/filesystem>)
#define MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM 1
#else
#define MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM 0
#endif
#else
#define MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM 0
#endif
#endif /* MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM */
#if MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM
#include <experimental/filesystem>
#elif defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L
#include <filesystem>
#endif
#if __cplusplus >= 201103L
@@ -370,13 +393,21 @@ template <class ALLOCATOR = default_allocator>
using string = ::std::basic_string<char, ::std::char_traits<char>, ALLOCATOR>;
using filehandle = ::mdbx_filehandle_t;
#if defined(DOXYGEN) || \
#if MDBX_USING_CXX_EXPERIMETAL_FILESYSTEM
#ifdef _MSC_VER
namespace filesystem = ::std::experimental::filesystem::v1;
#else
namespace filesystem = ::std::experimental::filesystem;
#endif
#define MDBX_STD_FILESYSTEM_PATH ::mdbx::filesystem::path
#elif defined(DOXYGEN) || \
(defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \
defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L && \
(!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || \
__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) && \
(!defined(__IPHONE_OS_VERSION_MIN_REQUIRED) || \
__IPHONE_OS_VERSION_MIN_REQUIRED >= 130100))
__IPHONE_OS_VERSION_MIN_REQUIRED >= 130100)) && \
(!defined(_MSC_VER) || __cplusplus >= 201703L)
namespace filesystem = ::std::filesystem;
/// \brief Defined if `mdbx::filesystem::path` is available.
/// \details If defined, it is always `mdbx::filesystem::path`,
@@ -385,10 +416,6 @@ namespace filesystem = ::std::filesystem;
/// Nonetheless `MDBX_STD_FILESYSTEM_PATH` not defined if the `::mdbx::path`
/// is fallbacked to c `std::string` or `std::wstring`.
#define MDBX_STD_FILESYSTEM_PATH ::mdbx::filesystem::path
#elif defined(__cpp_lib_experimental_filesystem) && \
__cpp_lib_experimental_filesystem >= 201406L
namespace filesystem = ::std::experimental::filesystem;
#define MDBX_STD_FILESYSTEM_PATH ::mdbx::filesystem::path
#endif /* MDBX_STD_FILESYSTEM_PATH */
#ifdef MDBX_STD_FILESYSTEM_PATH
@@ -1825,7 +1852,6 @@ private:
const size_t old_capacity = bin_.capacity();
const size_t new_capacity =
bin::advise_capacity(old_capacity, wanna_capacity);
assert(new_capacity >= wanna_capacity);
if (MDBX_LIKELY(new_capacity == old_capacity))
MDBX_CXX20_LIKELY {
assert(bin_.is_inplace() ==
@@ -1991,7 +2017,13 @@ private:
return *this;
}
MDBX_CXX20_CONSTEXPR void clear() { reshape<true>(0, 0, nullptr, 0); }
MDBX_CXX20_CONSTEXPR void *clear() {
return reshape<true>(0, 0, nullptr, 0);
}
MDBX_CXX20_CONSTEXPR void *clear_and_reserve(size_t whole_capacity,
size_t headroom) {
return reshape<false>(whole_capacity, headroom, nullptr, 0);
}
MDBX_CXX20_CONSTEXPR void resize(size_t capacity, size_t headroom,
slice &content) {
content.iov_base =
@@ -2250,14 +2282,16 @@ public:
buffer(const char *c_str, bool make_reference,
const allocator_type &allocator = allocator_type())
: buffer(::mdbx::slice(c_str), make_reference, allocator) {}
: buffer(::mdbx::slice(c_str), make_reference, allocator){}
#if defined(DOXYGEN) || \
(defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L)
template <class CHAR, class T>
buffer(const ::std::basic_string_view<CHAR, T> &view, bool make_reference,
const allocator_type &allocator = allocator_type())
: buffer(::mdbx::slice(view), make_reference, allocator) {}
template <class CHAR, class T>
buffer(const ::std::basic_string_view<CHAR, T> &view,
bool make_reference,
const allocator_type &allocator = allocator_type())
: buffer(::mdbx::slice(view), make_reference, allocator) {
}
#endif /* __cpp_lib_string_view >= 201606L */
MDBX_CXX20_CONSTEXPR
@@ -2283,15 +2317,16 @@ public:
MDBX_CXX20_CONSTEXPR
buffer(const char *c_str, const allocator_type &allocator = allocator_type())
: buffer(::mdbx::slice(c_str), allocator) {}
: buffer(::mdbx::slice(c_str), allocator){}
#if defined(DOXYGEN) || \
(defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L)
template <class CHAR, class T>
MDBX_CXX20_CONSTEXPR
buffer(const ::std::basic_string_view<CHAR, T> &view,
const allocator_type &allocator = allocator_type())
: buffer(::mdbx::slice(view), allocator) {}
template <class CHAR, class T>
MDBX_CXX20_CONSTEXPR
buffer(const ::std::basic_string_view<CHAR, T> &view,
const allocator_type &allocator = allocator_type())
: buffer(::mdbx::slice(view), allocator) {
}
#endif /* __cpp_lib_string_view >= 201606L */
buffer(size_t head_room, size_t tail_room,
@@ -2652,9 +2687,11 @@ public:
}
/// \brief Clears the contents and storage.
void clear() noexcept {
slice_.clear();
silo_.clear();
void clear() noexcept { slice_.assign(silo_.clear(), size_t(0)); }
/// \brief Clears the contents and reserve storage.
void clear_and_reserve(size_t whole_capacity, size_t headroom = 0) noexcept {
slice_.assign(silo_.clear_and_reserve(whole_capacity, headroom), size_t(0));
}
/// \brief Reduces memory usage by freeing unused storage space.
@@ -2742,7 +2779,7 @@ public:
buffer &append(const void *src, size_t bytes) {
if (MDBX_UNLIKELY(tailroom() < check_length(bytes)))
MDBX_CXX20_UNLIKELY reserve_tailroom(bytes);
memcpy(slice_.byte_ptr() + size(), src, bytes);
memcpy(end_byte_ptr(), src, bytes);
slice_.iov_len += bytes;
return *this;
}
@@ -2808,6 +2845,79 @@ public:
return append_producer(from_base64(data, ignore_spaces));
}
buffer &append_u8(uint_fast8_t u8) {
if (MDBX_UNLIKELY(tailroom() < 1))
MDBX_CXX20_UNLIKELY reserve_tailroom(1);
*slice_.end_byte_ptr() = uint8_t(u8);
slice_.iov_len += 1;
return *this;
}
buffer &append_byte(uint_fast8_t byte) { return append_u8(byte); }
buffer &append_u16(uint_fast16_t u16) {
if (MDBX_UNLIKELY(tailroom() < 2))
MDBX_CXX20_UNLIKELY reserve_tailroom(2);
const auto ptr = slice_.end_byte_ptr();
ptr[0] = uint8_t(u16);
ptr[1] = uint8_t(u16 >> 8);
slice_.iov_len += 2;
return *this;
}
buffer &append_u24(uint_fast32_t u24) {
if (MDBX_UNLIKELY(tailroom() < 3))
MDBX_CXX20_UNLIKELY reserve_tailroom(3);
const auto ptr = slice_.end_byte_ptr();
ptr[0] = uint8_t(u24);
ptr[1] = uint8_t(u24 >> 8);
ptr[2] = uint8_t(u24 >> 16);
slice_.iov_len += 3;
return *this;
}
buffer &append_u32(uint_fast32_t u32) {
if (MDBX_UNLIKELY(tailroom() < 4))
MDBX_CXX20_UNLIKELY reserve_tailroom(4);
const auto ptr = slice_.end_byte_ptr();
ptr[0] = uint8_t(u32);
ptr[1] = uint8_t(u32 >> 8);
ptr[2] = uint8_t(u32 >> 16);
ptr[3] = uint8_t(u32 >> 24);
slice_.iov_len += 4;
return *this;
}
buffer &append_u48(uint_fast64_t u48) {
if (MDBX_UNLIKELY(tailroom() < 6))
MDBX_CXX20_UNLIKELY reserve_tailroom(6);
const auto ptr = slice_.end_byte_ptr();
ptr[0] = uint8_t(u48);
ptr[1] = uint8_t(u48 >> 8);
ptr[2] = uint8_t(u48 >> 16);
ptr[3] = uint8_t(u48 >> 24);
ptr[4] = uint8_t(u48 >> 32);
ptr[5] = uint8_t(u48 >> 40);
slice_.iov_len += 6;
return *this;
}
buffer &append_u64(uint_fast64_t u64) {
if (MDBX_UNLIKELY(tailroom() < 8))
MDBX_CXX20_UNLIKELY reserve_tailroom(8);
const auto ptr = slice_.end_byte_ptr();
ptr[0] = uint8_t(u64);
ptr[1] = uint8_t(u64 >> 8);
ptr[2] = uint8_t(u64 >> 16);
ptr[3] = uint8_t(u64 >> 24);
ptr[4] = uint8_t(u64 >> 32);
ptr[5] = uint8_t(u64 >> 40);
ptr[6] = uint8_t(u64 >> 48);
ptr[7] = uint8_t(u64 >> 56);
slice_.iov_len += 8;
return *this;
}
//----------------------------------------------------------------------------
template <size_t SIZE>

View File

@@ -1,8 +1,8 @@
From 22732cf074188912caea6da6795c36098efb7eb5 Mon Sep 17 00:00:00 2001
From 40efe497b511c322470aa9c084fe4c1759788c57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?=
=?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= <leo@yuriev.ru>
Date: Mon, 23 Oct 2023 18:07:13 +0300
Subject: [PATCH] package/libmdbx: new package (library/database).
Date: Sun, 27 Oct 2024 22:34:19 +0300
Subject: [PATCH 1/1] package/libmdbx: new package (library/database).
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@@ -15,8 +15,9 @@ This patch adds libmdbx:
in terms of reliability, features and performance.
- more information at https://gitflic.ru/project/erthink/libmdbx
The v0.12.10 "SEM" is stable release of _libmdbx_ branch with new superior features,
in memory of the Hero of Russia Guard Major Dmitry Semenov with the call sign "SEM".
The 0.12.12 "Dollezhal" is stable release of _libmdbx_ branch in memory
of the Soviet energy scientist Nikolai Antonovich Dollezhal on the 125th
anniversary of his birth.
The complete ChangeLog: https://gitflic.ru/project/erthink/libmdbx/blob?file=ChangeLog.md
@@ -111,18 +112,18 @@ index 0000000000..a9a4ac45c5
+ !BR2_TOOLCHAIN_GCC_AT_LEAST_4_4
diff --git a/package/libmdbx/libmdbx.hash b/package/libmdbx/libmdbx.hash
new file mode 100644
index 0000000000..1dbdef7c69
index 0000000000..222e7caf5c
--- /dev/null
+++ b/package/libmdbx/libmdbx.hash
@@ -0,0 +1,5 @@
+# Hashes from: https://libmdbx.dqdkfa.ru/release/SHA256SUMS
+sha256 4637e06768a9a8fc7577e6e458e045ad1f9a8baee74996a3c88bc0ad64cbcf67 libmdbx-amalgamated-0.12.10.tar.xz
+sha256 19c0eb33e1ed43ca2a94dceb06dd31946432d16f30a9751d3701c67efa22eb1a libmdbx-amalgamated-0.12.12.tar.xz
+
+# Locally calculated
+sha256 310fe25c858a9515fc8c8d7d1f24a67c9496f84a91e0a0e41ea9975b1371e569 LICENSE
diff --git a/package/libmdbx/libmdbx.mk b/package/libmdbx/libmdbx.mk
new file mode 100644
index 0000000000..36df45b64f
index 0000000000..da4a53913f
--- /dev/null
+++ b/package/libmdbx/libmdbx.mk
@@ -0,0 +1,42 @@
@@ -132,7 +133,7 @@ index 0000000000..36df45b64f
+#
+################################################################################
+
+LIBMDBX_VERSION = 0.12.10
+LIBMDBX_VERSION = 0.12.12
+LIBMDBX_SOURCE = libmdbx-amalgamated-$(LIBMDBX_VERSION).tar.xz
+LIBMDBX_SITE = https://libmdbx.dqdkfa.ru/release
+LIBMDBX_SUPPORTS_IN_SOURCE_BUILD = NO
@@ -169,5 +170,5 @@ index 0000000000..36df45b64f
+
+$(eval $(cmake-package))
--
2.43.2
2.47.0

View File

@@ -88,6 +88,10 @@
#define __has_extension(x) (0)
#endif
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
#if __has_feature(thread_sanitizer)
#define __SANITIZE_THREAD__ 1
#endif
@@ -501,7 +505,7 @@ __extern_C key_t ftok(const char *, int);
#ifndef container_of
#define container_of(ptr, type, member) \
((type *)((char *)(ptr)-offsetof(type, member)))
((type *)((char *)(ptr) - offsetof(type, member)))
#endif /* container_of */
/*----------------------------------------------------------------------------*/
@@ -512,7 +516,7 @@ __extern_C key_t ftok(const char *, int);
#elif defined(_MSC_VER)
#define __always_inline __forceinline
#else
#define __always_inline
#define __always_inline __inline
#endif
#endif /* __always_inline */

View File

@@ -428,7 +428,7 @@ node_largedata_pgno(const MDBX_node *const __restrict node) {
* max(DATALEN_NO_OVERFLOW, sizeof(MDBX_db));
*/
#define PAGEROOM(pagesize) ((pagesize)-PAGEHDRSZ)
#define PAGEROOM(pagesize) ((pagesize) - PAGEHDRSZ)
#define EVEN_FLOOR(n) ((n) & ~(size_t)1)
#define BRANCH_NODE_MAX(pagesize) \
(EVEN_FLOOR((PAGEROOM(pagesize) - sizeof(indx_t) - NODESIZE) / (3 - 1) - \
@@ -2761,12 +2761,11 @@ static __always_inline size_t dpl_size2bytes(ptrdiff_t size) {
static __always_inline size_t dpl_bytes2size(const ptrdiff_t bytes) {
size_t size = (bytes - sizeof(MDBX_dpl)) / sizeof(MDBX_dp);
assert(size > CURSOR_STACK + MDBX_DPL_RESERVE_GAP &&
size <= MDBX_PGL_LIMIT + MDBX_PNL_GRANULATE);
size -= MDBX_DPL_RESERVE_GAP;
#if MDBX_DPL_PREALLOC_FOR_RADIXSORT
size >>= 1;
#endif /* MDBX_DPL_PREALLOC_FOR_RADIXSORT */
assert(size > CURSOR_STACK && size <= MDBX_PGL_LIMIT + MDBX_PNL_GRANULATE);
return size;
}
@@ -3187,9 +3186,9 @@ static __always_inline int __must_check_result dpl_append(MDBX_txn *txn,
STATIC_ASSERT(sizeof(MDBX_dp) == sizeof(__uint128_t));
((__uint128_t *)i)[1] = *(volatile __uint128_t *)i;
#else
i[1].ptr = i->ptr;
i[1].pgno = i->pgno;
i[1].npages = i->npages;
i[1].ptr = i->ptr;
i[1].pgno = i->pgno;
i[1].npages = i->npages;
#endif
--i;
}
@@ -3485,10 +3484,13 @@ __cold const char *mdbx_strerror_r(int errnum, char *buf, size_t buflen) {
const char *msg = mdbx_liberr2str(errnum);
if (!msg && buflen > 0 && buflen < INT_MAX) {
#if defined(_WIN32) || defined(_WIN64)
const DWORD size = FormatMessageA(
DWORD size = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen,
NULL);
while (size && buf[size - 1] <= ' ')
--size;
buf[size] = 0;
return size ? buf : "FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM) failed";
#elif defined(_GNU_SOURCE) && defined(__GLIBC__)
/* GNU-specific */
@@ -3539,10 +3541,13 @@ __cold const char *mdbx_strerror(int errnum) {
const char *mdbx_strerror_r_ANSI2OEM(int errnum, char *buf, size_t buflen) {
const char *msg = mdbx_liberr2str(errnum);
if (!msg && buflen > 0 && buflen < INT_MAX) {
const DWORD size = FormatMessageA(
DWORD size = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen,
NULL);
while (size && buf[size - 1] <= ' ')
--size;
buf[size] = 0;
if (!size)
msg = "FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM) failed";
else if (!CharToOemBuffA(buf, buf, size))
@@ -3606,19 +3611,26 @@ __cold void debug_log(int level, const char *function, int line,
va_end(args);
}
/* Dump a key in ascii or hexadecimal. */
const char *mdbx_dump_val(const MDBX_val *key, char *const buf,
/* Dump a val in ascii or hexadecimal. */
const char *mdbx_dump_val(const MDBX_val *val, char *const buf,
const size_t bufsize) {
if (!key)
if (!val)
return "<null>";
if (!key->iov_len)
if (!val->iov_len)
return "<empty>";
if (!buf || bufsize < 4)
return nullptr;
if (!val->iov_base) {
int len = snprintf(buf, bufsize, "<nullptr.%zu>", val->iov_len);
assert(len > 0 && (size_t)len < bufsize);
(void)len;
return buf;
}
bool is_ascii = true;
const uint8_t *const data = key->iov_base;
for (size_t i = 0; i < key->iov_len; i++)
const uint8_t *const data = val->iov_base;
for (size_t i = 0; i < val->iov_len; i++)
if (data[i] < ' ' || data[i] > '~') {
is_ascii = false;
break;
@@ -3627,14 +3639,14 @@ const char *mdbx_dump_val(const MDBX_val *key, char *const buf,
if (is_ascii) {
int len =
snprintf(buf, bufsize, "%.*s",
(key->iov_len > INT_MAX) ? INT_MAX : (int)key->iov_len, data);
(val->iov_len > INT_MAX) ? INT_MAX : (int)val->iov_len, data);
assert(len > 0 && (size_t)len < bufsize);
(void)len;
} else {
char *const detent = buf + bufsize - 2;
char *ptr = buf;
*ptr++ = '<';
for (size_t i = 0; i < key->iov_len && ptr < detent; i++) {
for (size_t i = 0; i < val->iov_len && ptr < detent; i++) {
const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
*ptr++ = hex[data[i] >> 4];
@@ -3774,7 +3786,9 @@ MDBX_MAYBE_UNUSED static bool cursor_is_tracked(const MDBX_cursor *mc) {
} \
tracked->mc_next = *tracking_head; \
*tracking_head = tracked; \
{ act; } \
{ \
act; \
} \
*tracking_head = tracked->mc_next; \
} while (0)
@@ -6926,7 +6940,7 @@ __hot static pgno_t relist_get_single(MDBX_txn *txn) {
* диском будет более кучным, а у страниц ближе к концу БД будет больше шансов
* попасть под авто-компактификацию. Частично эта тактика уже реализована, но
* для её эффективности требуется явно приоритезировать выделение страниц:
* - поддерживать для relist, для ближних и для дальних страниц;
* - поддерживать два relist, для ближних и для дальних страниц;
* - использовать страницы из дальнего списка, если первый пуст,
* а второй слишком большой, либо при пустой GC.
*
@@ -6934,11 +6948,11 @@ __hot static pgno_t relist_get_single(MDBX_txn *txn) {
* регионы будут линейными, что принципиально ускоряет запись на HDD.
* Одновременно, в среднем это не повлияет на чтение, точнее говоря, если
* порядок чтения не совпадает с порядком изменения (иначе говоря, если
* чтение не коррклирует с обновлениями и/или вставками) то не повлияет, иначе
* чтение не коррелирует с обновлениями и/или вставками) то не повлияет, иначе
* может ускорить. Однако, последовательности в среднем достаточно редки.
* Поэтому для эффективности требуется аккумулировать и поддерживать в ОЗУ
* огромные списки страниц, а затем сохранять их обратно в БД. Текущий формат
* БД (без битовых карт) для этого крайне не удачен. Поэтому эта тактика не
* БД (без сжатых битовых карт) для этого крайне не удачен. Поэтому эта тактика не
* имеет шансов быть успешной без смены формата БД (Mithril).
*
* 3. Стараться экономить последовательности страниц. Это позволяет избегать
@@ -6947,7 +6961,7 @@ __hot static pgno_t relist_get_single(MDBX_txn *txn) {
* информации от приложения библиотека не может знать насколько
* востребованными будут последовательности в ближайшей перспективе, а
* экономия последовательностей "на всякий случай" не только затратна
* сама-по-себе, но и работает во вред.
* сама-по-себе, но и работает во вред (добавляет хаоса).
*
* Поэтому:
* - в TODO добавляется разделение relist на «ближние» и «дальние» страницы,
@@ -8274,7 +8288,7 @@ static __inline int check_env(const MDBX_env *env, const bool wanna_active) {
if (wanna_active) {
#if MDBX_ENV_CHECKPID
if (unlikely(env->me_pid != osal_getpid())) {
if (unlikely(env->me_pid != osal_getpid()) && env->me_pid) {
((MDBX_env *)env)->me_flags |= MDBX_FATAL_ERROR;
return MDBX_PANIC;
}
@@ -8327,7 +8341,8 @@ static int cursor_shadow(MDBX_txn *parent, MDBX_txn *nested) {
MDBX_xcursor *mx = mc->mc_xcursor;
if (mx != NULL) {
*(MDBX_xcursor *)(bk + 1) = *mx;
mx->mx_cursor.mc_txn = nested;
mx->mx_cursor.mc_txn = mc->mc_txn;
mx->mx_cursor.mc_dbistate = mc->mc_dbistate;
}
mc->mc_next = nested->mt_cursors[i];
nested->mt_cursors[i] = mc;
@@ -8364,9 +8379,7 @@ static void cursors_eot(MDBX_txn *txn, const bool merge) {
MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6001);
ENSURE(txn->mt_env, bk->mc_signature == MDBX_MC_LIVE);
tASSERT(txn, mx == bk->mc_xcursor);
if (stage == MDBX_MC_WAIT4EOT /* Cursor was closed by user */)
mc->mc_signature = stage /* Promote closed state to parent txn */;
else if (merge) {
if (merge) {
/* Restore pointers to parent txn */
mc->mc_next = bk->mc_next;
mc->mc_backup = bk->mc_backup;
@@ -8374,11 +8387,8 @@ static void cursors_eot(MDBX_txn *txn, const bool merge) {
mc->mc_db = bk->mc_db;
mc->mc_dbistate = bk->mc_dbistate;
if (mx) {
if (mx != bk->mc_xcursor) {
*bk->mc_xcursor = *mx;
mx = bk->mc_xcursor;
}
mx->mx_cursor.mc_txn = bk->mc_txn;
mx->mx_cursor.mc_txn = mc->mc_txn;
mx->mx_cursor.mc_dbistate = mc->mc_dbistate;
}
} else {
/* Restore from backup, i.e. rollback/abort nested txn */
@@ -8388,6 +8398,8 @@ static void cursors_eot(MDBX_txn *txn, const bool merge) {
}
bk->mc_signature = 0;
osal_free(bk);
if (stage == MDBX_MC_WAIT4EOT /* Cursor was closed by user */)
mc->mc_signature = stage /* Promote closed state to parent txn */;
} else {
ENSURE(txn->mt_env, stage == MDBX_MC_LIVE);
mc->mc_signature = MDBX_MC_READY4CLOSE /* Cursor may be reused */;
@@ -8690,7 +8702,9 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid,
: "(wagering meta)");
ok = false;
}
if (likely(freedb_root && freedb_mod_txnid)) {
if (likely(freedb_root && freedb_mod_txnid &&
(size_t)ptr_dist(env->me_dxb_mmap.base, freedb_root) <
env->me_dxb_mmap.limit)) {
VALGRIND_MAKE_MEM_DEFINED(freedb_root, sizeof(freedb_root->mp_txnid));
MDBX_ASAN_UNPOISON_MEMORY_REGION(freedb_root,
sizeof(freedb_root->mp_txnid));
@@ -8706,7 +8720,9 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid,
ok = false;
}
}
if (likely(maindb_root && maindb_mod_txnid)) {
if (likely(maindb_root && maindb_mod_txnid &&
(size_t)ptr_dist(env->me_dxb_mmap.base, maindb_root) <
env->me_dxb_mmap.limit)) {
VALGRIND_MAKE_MEM_DEFINED(maindb_root, sizeof(maindb_root->mp_txnid));
MDBX_ASAN_UNPOISON_MEMORY_REGION(maindb_root,
sizeof(maindb_root->mp_txnid));
@@ -9153,9 +9169,10 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
}
#endif /* Windows */
} else {
if (unlikely(txn->mt_dbs[FREE_DBI].md_flags != MDBX_INTEGERKEY)) {
ERROR("unexpected/invalid db-flags 0x%u for GC/FreeDB",
txn->mt_dbs[FREE_DBI].md_flags);
if (unlikely((txn->mt_dbs[FREE_DBI].md_flags & DB_PERSISTENT_FLAGS) !=
MDBX_INTEGERKEY)) {
ERROR("unexpected/invalid db-flags 0x%x for %s",
txn->mt_dbs[FREE_DBI].md_flags, "GC/FreeDB");
rc = MDBX_INCOMPATIBLE;
goto bailout;
}
@@ -9174,7 +9191,7 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
}
bailout:
tASSERT(txn, rc != MDBX_SUCCESS);
txn_end(txn, MDBX_END_SLOT | MDBX_END_FAIL_BEGIN);
txn_end(txn, MDBX_END_SLOT | MDBX_END_EOTDONE | MDBX_END_FAIL_BEGIN);
return rc;
}
@@ -9267,7 +9284,7 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags,
*ret = NULL;
if (unlikely((flags & ~MDBX_TXN_RW_BEGIN_FLAGS) &&
(flags & ~MDBX_TXN_RO_BEGIN_FLAGS)))
(parent || (flags & ~MDBX_TXN_RO_BEGIN_FLAGS))))
return MDBX_EINVAL;
int rc = check_env(env, true);
@@ -9285,8 +9302,13 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags,
/* Nested transactions: Max 1 child, write txns only, no writemap */
rc = check_txn_rw(parent,
MDBX_TXN_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED);
if (unlikely(rc != MDBX_SUCCESS))
if (unlikely(rc != MDBX_SUCCESS)) {
if (rc == MDBX_BAD_TXN && (parent->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)) == 0) {
ERROR("%s mode is incompatible with nested transactions", "MDBX_WRITEMAP");
rc = MDBX_INCOMPATIBLE;
}
return rc;
}
if (env->me_options.spill_parent4child_denominator) {
/* Spill dirty-pages of parent to provide dirtyroom for child txn */
@@ -10797,10 +10819,10 @@ retry:
if (unlikely(ctx->rid <= MIN_TXNID)) {
if (unlikely(MDBX_PNL_GETSIZE(txn->tw.lifo_reclaimed) <=
ctx->reused_slot)) {
NOTICE("** restart: reserve depleted (reused_gc_slot %zu >= "
"lifo_reclaimed %zu" PRIaTXN,
ctx->reused_slot,
MDBX_PNL_GETSIZE(txn->tw.lifo_reclaimed));
VERBOSE("** restart: reserve depleted (reused_gc_slot %zu >= "
"lifo_reclaimed %zu" PRIaTXN,
ctx->reused_slot,
MDBX_PNL_GETSIZE(txn->tw.lifo_reclaimed));
goto retry;
}
break;
@@ -11035,7 +11057,7 @@ retry:
tASSERT(txn, ctx->lifo == 0);
fill_gc_id = unaligned_peek_u64(4, key.iov_base);
if (ctx->filled_slot-- == 0 || fill_gc_id > txn->tw.last_reclaimed) {
NOTICE(
VERBOSE(
"** restart: reserve depleted (filled_slot %zu, fill_id %" PRIaTXN
" > last_reclaimed %" PRIaTXN,
ctx->filled_slot, fill_gc_id, txn->tw.last_reclaimed);
@@ -11044,9 +11066,9 @@ retry:
} else {
tASSERT(txn, ctx->lifo != 0);
if (++ctx->filled_slot > MDBX_PNL_GETSIZE(txn->tw.lifo_reclaimed)) {
NOTICE("** restart: reserve depleted (filled_gc_slot %zu > "
"lifo_reclaimed %zu" PRIaTXN,
ctx->filled_slot, MDBX_PNL_GETSIZE(txn->tw.lifo_reclaimed));
VERBOSE("** restart: reserve depleted (filled_gc_slot %zu > "
"lifo_reclaimed %zu" PRIaTXN,
ctx->filled_slot, MDBX_PNL_GETSIZE(txn->tw.lifo_reclaimed));
goto retry;
}
fill_gc_id = txn->tw.lifo_reclaimed[ctx->filled_slot];
@@ -11473,7 +11495,7 @@ static __inline void txn_merge(MDBX_txn *const parent, MDBX_txn *const txn,
}
++w;
}
NOTICE("squash to begin for extending-merge %zu -> %zu", d, w - 1);
VERBOSE("squash to begin for extending-merge %zu -> %zu", d, w - 1);
d = w - 1;
continue;
}
@@ -11515,7 +11537,7 @@ static __inline void txn_merge(MDBX_txn *const parent, MDBX_txn *const txn,
}
--w;
}
NOTICE("squash to end for shrinking-merge %zu -> %zu", d, w + 1);
VERBOSE("squash to end for shrinking-merge %zu -> %zu", d, w + 1);
d = w + 1;
continue;
}
@@ -12232,6 +12254,22 @@ static int validate_meta(MDBX_env *env, MDBX_meta *const meta,
return MDBX_RESULT_TRUE;
}
if (unlikely(meta->mm_extra_flags != 0)) {
WARNING("meta[%u] has unsupported %s 0x%x, skip it", meta_number,
"extra-flags", meta->mm_extra_flags);
return MDBX_RESULT_TRUE;
}
if (unlikely(meta->mm_validator_id != 0)) {
WARNING("meta[%u] has unsupported %s 0x%x, skip it", meta_number,
"validator-id", meta->mm_validator_id);
return MDBX_RESULT_TRUE;
}
if (unlikely(meta->mm_extra_pagehdr != 0)) {
WARNING("meta[%u] has unsupported %s 0x%x, skip it", meta_number,
"extra-pageheader", meta->mm_extra_pagehdr);
return MDBX_RESULT_TRUE;
}
/* LY: check signature as a checksum */
if (META_IS_STEADY(meta) &&
unlikely(unaligned_peek_u64(4, &meta->mm_sign) != meta_sign(meta))) {
@@ -12397,12 +12435,12 @@ static int validate_meta(MDBX_env *env, MDBX_meta *const meta,
meta->mm_dbs[FREE_DBI].md_entries ||
meta->mm_dbs[FREE_DBI].md_leaf_pages ||
meta->mm_dbs[FREE_DBI].md_overflow_pages)) {
WARNING("meta[%u] has false-empty %s, skip it", meta_number, "GC");
WARNING("meta[%u] has false-empty %s, skip it", meta_number, "GC/FreeDB");
return MDBX_CORRUPTED;
}
} else if (unlikely(meta->mm_dbs[FREE_DBI].md_root >= meta->mm_geo.next)) {
WARNING("meta[%u] has invalid %s-root %" PRIaPGNO ", skip it", meta_number,
"GC", meta->mm_dbs[FREE_DBI].md_root);
"GC/FreeDB", meta->mm_dbs[FREE_DBI].md_root);
return MDBX_CORRUPTED;
}
@@ -12424,7 +12462,7 @@ static int validate_meta(MDBX_env *env, MDBX_meta *const meta,
if (unlikely(meta->mm_dbs[FREE_DBI].md_mod_txnid > txnid)) {
WARNING("meta[%u] has wrong md_mod_txnid %" PRIaTXN " for %s, skip it",
meta_number, meta->mm_dbs[FREE_DBI].md_mod_txnid, "GC");
meta_number, meta->mm_dbs[FREE_DBI].md_mod_txnid, "GC/FreeDB");
return MDBX_CORRUPTED;
}
@@ -12434,6 +12472,13 @@ static int validate_meta(MDBX_env *env, MDBX_meta *const meta,
return MDBX_CORRUPTED;
}
if (unlikely((meta->mm_dbs[FREE_DBI].md_flags & DB_PERSISTENT_FLAGS) !=
MDBX_INTEGERKEY)) {
WARNING("meta[%u] has unexpected/invalid db-flags 0x%x for %s", meta_number,
meta->mm_dbs[FREE_DBI].md_flags, "GC/FreeDB");
return MDBX_INCOMPATIBLE;
}
return MDBX_SUCCESS;
}
@@ -14865,7 +14910,10 @@ __cold int mdbx_env_deleteW(const wchar_t *pathname,
err = MDBX_SUCCESS;
}
if (err == MDBX_SUCCESS && !(dummy_env->me_flags & MDBX_NOSUBDIR)) {
if (err == MDBX_SUCCESS && !(dummy_env->me_flags & MDBX_NOSUBDIR) &&
(/* pathname != "." */ pathname[0] != '.' || pathname[1] != 0) &&
(/* pathname != ".." */ pathname[0] != '.' || pathname[1] != '.' ||
pathname[2] != 0)) {
err = osal_removedirectory(pathname);
if (err == MDBX_SUCCESS)
rc = MDBX_SUCCESS;
@@ -16477,7 +16525,8 @@ cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, MDBX_cursor_op op) {
struct cursor_set_result ret;
ret.exact = false;
if (unlikely(key->iov_len < mc->mc_dbx->md_klen_min ||
key->iov_len > mc->mc_dbx->md_klen_max)) {
(key->iov_len > mc->mc_dbx->md_klen_max &&
(mc->mc_dbx->md_klen_min == mc->mc_dbx->md_klen_max || MDBX_DEBUG || MDBX_FORCE_ASSERTIONS)))) {
cASSERT(mc, !"Invalid key-size");
ret.err = MDBX_BAD_VALSIZE;
return ret;
@@ -16943,10 +16992,8 @@ static __hot int cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
}
rc = MDBX_SUCCESS;
if (unlikely(C_INITIALIZED != (mc->mc_xcursor->mx_cursor.mc_flags &
(C_INITIALIZED | C_EOF)))) {
rc = MDBX_NOTFOUND;
(C_INITIALIZED | C_EOF))))
break;
}
goto fetch_multiple;
case MDBX_NEXT_MULTIPLE:
if (unlikely(!data))
@@ -16962,8 +17009,6 @@ static __hot int cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
page_numkeys(mx->mc_pg[mx->mc_top]) * mx->mc_db->md_xsize;
data->iov_base = page_data(mx->mc_pg[mx->mc_top]);
mx->mc_ki[mx->mc_top] = (indx_t)page_numkeys(mx->mc_pg[mx->mc_top]) - 1;
} else {
rc = MDBX_NOTFOUND;
}
}
break;
@@ -17323,9 +17368,11 @@ static __hot int cursor_put_nochecklen(MDBX_cursor *mc, const MDBX_val *key,
int err;
DKBUF_DEBUG;
MDBX_env *const env = mc->mc_txn->mt_env;
if (LOG_ENABLED(MDBX_LOG_DEBUG) && (flags & MDBX_RESERVE))
data->iov_base = nullptr;
DEBUG("==> put db %d key [%s], size %" PRIuPTR ", data [%s] size %" PRIuPTR,
DDBI(mc), DKEY_DEBUG(key), key->iov_len,
DVAL_DEBUG((flags & MDBX_RESERVE) ? nullptr : data), data->iov_len);
DDBI(mc), DKEY_DEBUG(key), key->iov_len, DVAL_DEBUG(data),
data->iov_len);
if ((flags & MDBX_CURRENT) != 0 && (mc->mc_flags & C_SUB) == 0) {
if (unlikely(flags & (MDBX_APPEND | MDBX_NOOVERWRITE)))
@@ -23083,14 +23130,31 @@ int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) {
if (unlikely(dbi >= env->me_maxdbs))
return MDBX_BAD_DBI;
if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs))
return MDBX_BAD_DBI;
rc = osal_fastmutex_acquire(&env->me_dbi_lock);
if (likely(rc == MDBX_SUCCESS)) {
rc = (dbi < env->me_maxdbs && (env->me_dbflags[dbi] & DB_VALID))
? dbi_close_locked(env, dbi)
: MDBX_BAD_DBI;
retry:
rc = MDBX_BAD_DBI;
if (dbi < env->me_maxdbs && (env->me_dbflags[dbi] & DB_VALID)) {
const MDBX_txn *const hazard = env->me_txn;
osal_compiler_barrier();
if (env->me_txn0 && (env->me_txn0->mt_flags & MDBX_TXN_FINISHED) == 0) {
if (env->me_txn0->mt_dbistate[dbi] & (DBI_DIRTY | DBI_CREAT))
goto bailout_dirty_dbi;
osal_memory_barrier();
if (unlikely(hazard != env->me_txn))
goto retry;
if (hazard != env->me_txn0 && hazard &&
(hazard->mt_flags & MDBX_TXN_FINISHED) == 0 &&
hazard->mt_signature == MDBX_MT_SIGNATURE &&
(hazard->mt_dbistate[dbi] & (DBI_DIRTY | DBI_CREAT)))
goto bailout_dirty_dbi;
osal_compiler_barrier();
if (unlikely(hazard != env->me_txn))
goto retry;
}
rc = dbi_close_locked(env, dbi);
}
bailout_dirty_dbi:
ENSURE(env, osal_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
}
return rc;

View File

@@ -90,8 +90,8 @@
#endif
#if _MSC_VER > 1914
#pragma warning( \
disable : 5105) /* winbase.h(9531): warning C5105: macro expansion \
producing 'defined' has undefined behavior */
disable : 5105) /* winbase.h(9531): warning C5105: macro expansion \
producing 'defined' has undefined behavior */
#endif
#if _MSC_VER > 1930
#pragma warning(disable : 6235) /* <expression> is always a constant */
@@ -120,8 +120,8 @@
#pragma warning(disable : 4204) /* nonstandard extension used: non-constant \
aggregate initializer */
#pragma warning( \
disable : 4505) /* unreferenced local function has been removed */
#endif /* _MSC_VER (warnings) */
disable : 4505) /* unreferenced local function has been removed */
#endif /* _MSC_VER (warnings) */
#if defined(__GNUC__) && __GNUC__ < 9
#pragma GCC diagnostic ignored "-Wattributes"
@@ -684,7 +684,7 @@ typedef struct MDBX_page {
#define P_LOOSE 0x4000u /* page was dirtied then freed, can be reused */
#define P_FROZEN 0x8000u /* used for retire page with known status */
#define P_ILL_BITS \
((uint16_t) ~(P_BRANCH | P_LEAF | P_LEAF2 | P_OVERFLOW | P_SPILLED))
((uint16_t)~(P_BRANCH | P_LEAF | P_LEAF2 | P_OVERFLOW | P_SPILLED))
uint16_t mp_flags;
union {
uint32_t mp_pages; /* number of overflow pages */
@@ -1303,8 +1303,8 @@ struct MDBX_cursor {
#define C_SUB 0x04 /* Cursor is a sub-cursor */
#define C_DEL 0x08 /* last op was a cursor_del */
#define C_UNTRACK 0x10 /* Un-track cursor when closing */
#define C_GCU \
0x20 /* Происходит подготовка к обновлению GC, поэтому \
#define C_GCU \
0x20 /* Происходит подготовка к обновлению GC, поэтому \
* можно брать страницы из GC даже для FREE_DBI */
uint8_t mc_flags;

View File

@@ -691,16 +691,16 @@ __cold MDBX_INTERNAL_FUNC int osal_lck_init(MDBX_env *env,
if LCK already opened/used inside current process */
;
/* FIXME: Unfortunately, there is no other reliable way but to long testing
* on each platform. On the other hand, behavior like FreeBSD is incorrect
* and we can expect it to be rare. Moreover, even on FreeBSD without
* additional in-process initialization, the probability of an problem
* occurring is vanishingly small, and the symptom is a return of EINVAL
* while locking a mutex. In other words, in the worst case, the problem
* results in an EINVAL error at the start of the transaction, but NOT data
* loss, nor database corruption, nor other fatal troubles. Thus, the code
* below I am inclined to think the workaround for erroneous platforms (like
* FreeBSD), rather than a defect of libmdbx. */
/* FIXME: Unfortunately, there is no other reliable way but to long testing
* on each platform. On the other hand, behavior like FreeBSD is incorrect
* and we can expect it to be rare. Moreover, even on FreeBSD without
* additional in-process initialization, the probability of an problem
* occurring is vanishingly small, and the symptom is a return of EINVAL
* while locking a mutex. In other words, in the worst case, the problem
* results in an EINVAL error at the start of the transaction, but NOT data
* loss, nor database corruption, nor other fatal troubles. Thus, the code
* below I am inclined to think the workaround for erroneous platforms (like
* FreeBSD), rather than a defect of libmdbx. */
#if defined(__FreeBSD__)
/* seems that shared mutexes on FreeBSD required in-process initialization */
(void)global_uniqueness_flag;

View File

@@ -15,10 +15,14 @@
#endif /* MinGW */
/* Workaround for MSVC' header `extern "C"` vs `std::` redefinition bug */
#if defined(_MSC_VER) && defined(__SANITIZE_ADDRESS__) && \
!defined(_DISABLE_VECTOR_ANNOTATION)
#if defined(_MSC_VER)
#if defined(__SANITIZE_ADDRESS__) && !defined(_DISABLE_VECTOR_ANNOTATION)
#define _DISABLE_VECTOR_ANNOTATION
#endif /* _DISABLE_VECTOR_ANNOTATION */
#ifndef _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
#endif /* #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING */
#endif /* _MSC_VER */
#include "../mdbx.h++"
@@ -247,6 +251,21 @@ struct temp_buffer {
} // namespace
#ifndef MDBX_CXX_ENDL
/* Манипулятор std::endl выталкивате буфферизированый вывод, что здесь не
* требуется.
*
* Кроме этого, при сборке libmdbx для символов по-умолчанию выключается
* видимость вне DSO, из-за чего обращение к std::endl иногда укачивает
* линковщики, если комплятор ошибочно формируют direct access к global weak
* symbol, коим является std::endl. */
#if 0
#define MDBX_CXX_ENDL ::std::endl
#else
#define MDBX_CXX_ENDL "\n"
#endif
#endif /* MDBX_CXX_ENDL */
//------------------------------------------------------------------------------
namespace mdbx {
@@ -395,6 +414,7 @@ __cold void error::throw_exception() const {
CASE_EXCEPTION(incompatible_operation, MDBX_INCOMPATIBLE);
CASE_EXCEPTION(internal_page_full, MDBX_PAGE_FULL);
CASE_EXCEPTION(internal_problem, MDBX_PROBLEM);
CASE_EXCEPTION(key_exists, MDBX_KEYEXIST);
CASE_EXCEPTION(key_mismatch, MDBX_EKEYMISMATCH);
CASE_EXCEPTION(max_maps_reached, MDBX_DBS_FULL);
CASE_EXCEPTION(max_readers_reached, MDBX_READERS_FULL);
@@ -663,7 +683,7 @@ char *to_hex::write_bytes(char *__restrict const dest, size_t dest_size) const {
unsigned width = 0;
for (const auto end = source.end_byte_ptr(); src != end; ++src) {
if (wrap_width && width >= wrap_width) {
out << ::std::endl;
out << MDBX_CXX_ENDL;
width = 0;
}
const int8_t hi = *src >> 4;
@@ -858,7 +878,7 @@ char *to_base58::write_bytes(char *__restrict const dest,
while (MDBX_LIKELY(begin < end) && *begin == 0) {
out.put('1');
if (wrap_width && ++width >= wrap_width) {
out << ::std::endl;
out << MDBX_CXX_ENDL;
width = 0;
}
++begin;
@@ -872,7 +892,7 @@ char *to_base58::write_bytes(char *__restrict const dest,
for (size_t i = 0; i < chunk.length(); ++i) {
out.put(chunk.char_ptr()[i]);
if (wrap_width && ++width >= wrap_width) {
out << ::std::endl;
out << MDBX_CXX_ENDL;
width = 0;
}
}
@@ -1049,7 +1069,7 @@ char *to_base64::write_bytes(char *__restrict const dest,
src += 3;
out.write(&buf.front(), 4);
if (wrap_width && (width += 4) >= wrap_width && left) {
out << ::std::endl;
out << MDBX_CXX_ENDL;
width = 0;
}
continue;
@@ -1283,7 +1303,7 @@ bool env::is_pristine() const {
bool env::is_empty() const { return get_stat().ms_leaf_pages == 0; }
env &env::copy(filehandle fd, bool compactify, bool force_dynamic_size) {
__cold env &env::copy(filehandle fd, bool compactify, bool force_dynamic_size) {
error::success_or_throw(
::mdbx_env_copy2fd(handle_, fd,
(compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
@@ -1292,8 +1312,8 @@ env &env::copy(filehandle fd, bool compactify, bool force_dynamic_size) {
return *this;
}
env &env::copy(const char *destination, bool compactify,
bool force_dynamic_size) {
__cold env &env::copy(const char *destination, bool compactify,
bool force_dynamic_size) {
error::success_or_throw(
::mdbx_env_copy(handle_, destination,
(compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
@@ -1302,14 +1322,14 @@ env &env::copy(const char *destination, bool compactify,
return *this;
}
env &env::copy(const ::std::string &destination, bool compactify,
bool force_dynamic_size) {
__cold env &env::copy(const ::std::string &destination, bool compactify,
bool force_dynamic_size) {
return copy(destination.c_str(), compactify, force_dynamic_size);
}
#if defined(_WIN32) || defined(_WIN64)
env &env::copy(const wchar_t *destination, bool compactify,
bool force_dynamic_size) {
__cold env &env::copy(const wchar_t *destination, bool compactify,
bool force_dynamic_size) {
error::success_or_throw(
::mdbx_env_copyW(handle_, destination,
(compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
@@ -1325,13 +1345,13 @@ env &env::copy(const ::std::wstring &destination, bool compactify,
#endif /* Windows */
#ifdef MDBX_STD_FILESYSTEM_PATH
env &env::copy(const MDBX_STD_FILESYSTEM_PATH &destination, bool compactify,
bool force_dynamic_size) {
__cold env &env::copy(const MDBX_STD_FILESYSTEM_PATH &destination,
bool compactify, bool force_dynamic_size) {
return copy(destination.native(), compactify, force_dynamic_size);
}
#endif /* MDBX_STD_FILESYSTEM_PATH */
path env::get_path() const {
__cold path env::get_path() const {
#if defined(_WIN32) || defined(_WIN64)
const wchar_t *c_wstr;
error::success_or_throw(::mdbx_env_get_pathW(handle_, &c_wstr));
@@ -1345,29 +1365,30 @@ path env::get_path() const {
#endif
}
bool env::remove(const char *pathname, const remove_mode mode) {
return error::boolean_or_throw(
__cold bool env::remove(const char *pathname, const remove_mode mode) {
return !error::boolean_or_throw(
::mdbx_env_delete(pathname, MDBX_env_delete_mode_t(mode)));
}
bool env::remove(const ::std::string &pathname, const remove_mode mode) {
__cold bool env::remove(const ::std::string &pathname, const remove_mode mode) {
return remove(pathname.c_str(), mode);
}
#if defined(_WIN32) || defined(_WIN64)
bool env::remove(const wchar_t *pathname, const remove_mode mode) {
return error::boolean_or_throw(
__cold bool env::remove(const wchar_t *pathname, const remove_mode mode) {
return !error::boolean_or_throw(
::mdbx_env_deleteW(pathname, MDBX_env_delete_mode_t(mode)));
}
bool env::remove(const ::std::wstring &pathname, const remove_mode mode) {
__cold bool env::remove(const ::std::wstring &pathname,
const remove_mode mode) {
return remove(pathname.c_str(), mode);
}
#endif /* Windows */
#ifdef MDBX_STD_FILESYSTEM_PATH
bool env::remove(const MDBX_STD_FILESYSTEM_PATH &pathname,
const remove_mode mode) {
__cold bool env::remove(const MDBX_STD_FILESYSTEM_PATH &pathname,
const remove_mode mode) {
return remove(pathname.native(), mode);
}
#endif /* MDBX_STD_FILESYSTEM_PATH */
@@ -1381,13 +1402,13 @@ static inline MDBX_env *create_env() {
return ptr;
}
env_managed::~env_managed() noexcept {
__cold env_managed::~env_managed() noexcept {
if (MDBX_UNLIKELY(handle_))
MDBX_CXX20_UNLIKELY error::success_or_panic(
::mdbx_env_close(handle_), "mdbx::~env()", "mdbx_env_close");
}
void env_managed::close(bool dont_sync) {
__cold void env_managed::close(bool dont_sync) {
const error rc =
static_cast<MDBX_error_t>(::mdbx_env_close_ex(handle_, dont_sync));
switch (rc.code()) {
@@ -1537,7 +1558,7 @@ void txn_managed::commit(commit_latency *latency) {
//------------------------------------------------------------------------------
bool txn::drop_map(const char *name, bool throw_if_absent) {
__cold bool txn::drop_map(const char *name, bool throw_if_absent) {
map_handle map;
const int err = ::mdbx_dbi_open(handle_, name, MDBX_DB_ACCEDE, &map.dbi);
switch (err) {
@@ -1554,7 +1575,7 @@ bool txn::drop_map(const char *name, bool throw_if_absent) {
}
}
bool txn::clear_map(const char *name, bool throw_if_absent) {
__cold bool txn::clear_map(const char *name, bool throw_if_absent) {
map_handle map;
const int err = ::mdbx_dbi_open(handle_, name, MDBX_DB_ACCEDE, &map.dbi);
switch (err) {
@@ -1630,21 +1651,20 @@ __cold ::std::ostream &operator<<(::std::ostream &out,
const char *suffix;
} static const scales[] = {
#if MDBX_WORDBITS > 32
{env_managed::geometry::EiB, "EiB"},
{env_managed::geometry::EB, "EB"},
{env_managed::geometry::PiB, "PiB"},
{env_managed::geometry::PB, "PB"},
{env_managed::geometry::TiB, "TiB"},
{env_managed::geometry::TB, "TB"},
{env_managed::geometry::EiB, "EiB"},
{env_managed::geometry::EB, "EB"},
{env_managed::geometry::PiB, "PiB"},
{env_managed::geometry::PB, "PB"},
{env_managed::geometry::TiB, "TiB"},
{env_managed::geometry::TB, "TB"},
#endif
{env_managed::geometry::GiB, "GiB"},
{env_managed::geometry::GB, "GB"},
{env_managed::geometry::MiB, "MiB"},
{env_managed::geometry::MB, "MB"},
{env_managed::geometry::KiB, "KiB"},
{env_managed::geometry::kB, "kB"},
{1, " bytes"}
};
{env_managed::geometry::GiB, "GiB"},
{env_managed::geometry::GB, "GB"},
{env_managed::geometry::MiB, "MiB"},
{env_managed::geometry::MB, "MB"},
{env_managed::geometry::KiB, "KiB"},
{env_managed::geometry::kB, "kB"},
{1, " bytes"}};
for (const auto i : scales)
if (bytes % i.one == 0)

View File

@@ -766,11 +766,10 @@ MDBX_INTERNAL_FUNC 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;
@@ -3012,6 +3011,29 @@ __cold static LSTATUS mdbx_RegGetValue(HKEY hKey, LPCSTR lpSubKey,
}
#endif
static size_t hamming_weight(size_t v) {
const size_t m1 = (size_t)UINT64_C(0x5555555555555555);
const size_t m2 = (size_t)UINT64_C(0x3333333333333333);
const size_t m4 = (size_t)UINT64_C(0x0f0f0f0f0f0f0f0f);
const size_t h01 = (size_t)UINT64_C(0x0101010101010101);
v -= (v >> 1) & m1;
v = (v & m2) + ((v >> 2) & m2);
v = (v + (v >> 4)) & m4;
return (v * h01) >> (sizeof(v) * 8 - 8);
}
static inline size_t hw64(uint64_t v) {
size_t r = hamming_weight((size_t)v);
if (sizeof(v) > sizeof(r))
r += hamming_weight((size_t)(v >> sizeof(r) * 4 >> sizeof(r) * 4));
return r;
}
static bool check_uuid(bin128_t uuid) {
size_t hw = hw64(uuid.x) + hw64(uuid.y) + hw64(uuid.x ^ uuid.y);
return (hw >> 6) == 1;
}
__cold MDBX_MAYBE_UNUSED static bool
bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
if (n > 31) {
@@ -3045,7 +3067,7 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
s->y += aligned.y;
} else
bootid_collect(s, p, n);
return true;
return check_uuid(*s);
}
if (n)
@@ -3053,28 +3075,53 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
return false;
}
__cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
bin128_t bin = {{0, 0}};
#if defined(__linux__) || defined(__gnu_linux__)
__cold static bool is_inside_lxc(void) {
bool inside_lxc = false;
FILE *mounted = setmntent("/proc/mounts", "r");
if (mounted) {
const struct mntent *ent;
while (nullptr != (ent = getmntent(mounted))) {
if (strcmp(ent->mnt_fsname, "lxcfs") == 0 &&
strncmp(ent->mnt_dir, "/proc/", 6) == 0) {
inside_lxc = true;
break;
}
}
endmntent(mounted);
}
return inside_lxc;
}
__cold static bool proc_read_uuid(const char *path, bin128_t *target) {
const int fd = open(path, O_RDONLY | O_NOFOLLOW);
if (fd != -1) {
struct statfs fs;
char buf[42];
const ssize_t len =
(fstatfs(fd, &fs) == 0 &&
(fs.f_type == /* procfs */ 0x9FA0 ||
(fs.f_type == /* tmpfs */ 0x1021994 && is_inside_lxc())))
? read(fd, buf, sizeof(buf))
: -1;
const int err = close(fd);
assert(err == 0);
(void)err;
if (len > 0)
return bootid_parse_uuid(target, buf, len);
}
return false;
}
#endif /* Linux */
__cold bin128_t osal_bootid(void) {
bin128_t uuid = {{0, 0}};
bool got_machineid = false, got_boottime = false, got_bootseq = false;
#if defined(__linux__) || defined(__gnu_linux__)
{
const int fd =
open("/proc/sys/kernel/random/boot_id", O_RDONLY | O_NOFOLLOW);
if (fd != -1) {
struct statfs fs;
char buf[42];
const ssize_t len =
(fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0)
? read(fd, buf, sizeof(buf))
: -1;
const int err = close(fd);
assert(err == 0);
(void)err;
if (len > 0 && bootid_parse_uuid(&bin, buf, len))
return bin;
}
}
if (proc_read_uuid("/proc/sys/kernel/random/boot_id", &uuid))
return uuid;
#endif /* Linux */
#if defined(__APPLE__) || defined(__MACH__)
@@ -3082,16 +3129,15 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
char buf[42];
size_t len = sizeof(buf);
if (!sysctlbyname("kern.bootsessionuuid", buf, &len, nullptr, 0) &&
bootid_parse_uuid(&bin, buf, len))
return bin;
bootid_parse_uuid(&uuid, buf, len))
return uuid;
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
__MAC_OS_X_VERSION_MIN_REQUIRED > 1050
uuid_t uuid;
uuid_t hostuuid;
struct timespec wait = {0, 1000000000u / 42};
if (!gethostuuid(uuid, &wait) &&
bootid_parse_uuid(&bin, uuid, sizeof(uuid)))
got_machineid = true;
if (!gethostuuid(hostuuid, &wait))
got_machineid = bootid_parse_uuid(&uuid, hostuuid, sizeof(hostuuid));
#endif /* > 10.5 */
struct timeval boottime;
@@ -3129,7 +3175,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
"MachineGuid", &buf.MachineGuid,
&len) == ERROR_SUCCESS &&
len < sizeof(buf))
got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len);
got_machineid = bootid_parse_uuid(&uuid, &buf.MachineGuid, len);
if (!got_machineid) {
/* again, Windows is madness */
@@ -3147,7 +3193,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
"DigitalProductId", &buf.DigitalProductId,
&len) == ERROR_SUCCESS &&
len > 42 && len < sizeof(buf)) {
bootid_collect(&bin, &buf.DigitalProductId, len);
bootid_collect(&uuid, &buf.DigitalProductId, len);
got_machineid = true;
}
len = sizeof(buf);
@@ -3155,7 +3201,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
"DigitalProductId", &buf.DigitalProductId,
&len) == ERROR_SUCCESS &&
len > 42 && len < sizeof(buf)) {
bootid_collect(&bin, &buf.DigitalProductId, len);
bootid_collect(&uuid, &buf.DigitalProductId, len);
got_machineid = true;
}
len = sizeof(buf);
@@ -3163,7 +3209,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
"DigitalProductId", &buf.DigitalProductId,
&len) == ERROR_SUCCESS &&
len > 42 && len < sizeof(buf)) {
bootid_collect(&bin, &buf.DigitalProductId, len);
bootid_collect(&uuid, &buf.DigitalProductId, len);
got_machineid = true;
}
}
@@ -3175,7 +3221,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BootId",
&buf.BootId, &len) == ERROR_SUCCESS &&
len > 1 && len < sizeof(buf)) {
bootid_collect(&bin, &buf.BootId, len);
bootid_collect(&uuid, &buf.BootId, len);
got_bootseq = true;
}
@@ -3183,7 +3229,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BaseTime",
&buf.BaseTime, &len) == ERROR_SUCCESS &&
len >= sizeof(buf.BaseTime) && buf.BaseTime) {
bootid_collect(&bin, &buf.BaseTime, len);
bootid_collect(&uuid, &buf.BaseTime, len);
got_boottime = true;
}
@@ -3199,7 +3245,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
buf.SysTimeOfDayInfoHacked.BootTime.QuadPart -
buf.SysTimeOfDayInfoHacked.BootTimeBias;
if (UnbiasedBootTime) {
bootid_collect(&bin, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
bootid_collect(&uuid, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
got_boottime = true;
}
}
@@ -3207,7 +3253,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
if (!got_boottime) {
uint64_t boottime = windows_bootime();
if (boottime) {
bootid_collect(&bin, &boottime, sizeof(boottime));
bootid_collect(&uuid, &boottime, sizeof(boottime));
got_boottime = true;
}
}
@@ -3224,8 +3270,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
(int *)
#endif
mib,
ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0)
got_machineid = bootid_parse_uuid(&bin, buf, len);
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
got_machineid = bootid_parse_uuid(&uuid, buf, len);
}
#endif /* CTL_HW && HW_UUID */
@@ -3239,8 +3285,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
(int *)
#endif
mib,
ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0)
got_machineid = bootid_parse_uuid(&bin, buf, len);
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
got_machineid = bootid_parse_uuid(&uuid, buf, len);
}
#endif /* CTL_KERN && KERN_HOSTUUID */
@@ -3248,16 +3294,33 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
if (!got_machineid) {
char buf[42];
size_t len = sizeof(buf);
if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, NULL, 0) == 0)
got_machineid = bootid_parse_uuid(&bin, buf, len);
if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, nullptr, 0) == 0)
got_machineid = bootid_parse_uuid(&uuid, buf, len);
}
#endif /* __NetBSD__ */
#if !(defined(_WIN32) || defined(_WIN64))
if (!got_machineid) {
int fd = open("/etc/machine-id", O_RDONLY);
if (fd == -1)
fd = open("/var/lib/dbus/machine-id", O_RDONLY);
if (fd != -1) {
char buf[42];
const ssize_t len = read(fd, buf, sizeof(buf));
const int err = close(fd);
assert(err == 0);
(void)err;
if (len > 0)
got_machineid = bootid_parse_uuid(&uuid, buf, len);
}
}
#endif /* !Windows */
#if _XOPEN_SOURCE_EXTENDED
if (!got_machineid) {
const int hostid = gethostid();
if (hostid > 0) {
bootid_collect(&bin, &hostid, sizeof(hostid));
const long hostid = gethostid();
if (hostid != 0 && hostid != -1) {
bootid_collect(&uuid, &hostid, sizeof(hostid));
got_machineid = true;
}
}
@@ -3265,8 +3328,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
if (!got_machineid) {
lack:
bin.x = bin.y = 0;
return bin;
uuid.x = uuid.y = 0;
return uuid;
}
/*--------------------------------------------------------------------------*/
@@ -3281,9 +3344,9 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
(int *)
#endif
mib,
ARRAY_LENGTH(mib), &boottime, &len, NULL, 0) == 0 &&
ARRAY_LENGTH(mib), &boottime, &len, nullptr, 0) == 0 &&
len == sizeof(boottime) && boottime.tv_sec) {
bootid_collect(&bin, &boottime, len);
bootid_collect(&uuid, &boottime, len);
got_boottime = true;
}
}
@@ -3300,11 +3363,11 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
switch (kn->data_type) {
case KSTAT_DATA_INT32:
case KSTAT_DATA_UINT32:
bootid_collect(&bin, &kn->value, sizeof(int32_t));
bootid_collect(&uuid, &kn->value, sizeof(int32_t));
got_boottime = true;
case KSTAT_DATA_INT64:
case KSTAT_DATA_UINT64:
bootid_collect(&bin, &kn->value, sizeof(int64_t));
bootid_collect(&uuid, &kn->value, sizeof(int64_t));
got_boottime = true;
}
}
@@ -3320,12 +3383,12 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
const struct utmpx id = {.ut_type = BOOT_TIME};
const struct utmpx *entry = getutxid(&id);
if (entry) {
bootid_collect(&bin, entry, sizeof(*entry));
bootid_collect(&uuid, entry, sizeof(*entry));
got_boottime = true;
while (unlikely((entry = getutxid(&id)) != nullptr)) {
/* have multiple reboot records, assuming we can distinguish next
* bootsession even if RTC is wrong or absent */
bootid_collect(&bin, entry, sizeof(*entry));
bootid_collect(&uuid, entry, sizeof(*entry));
got_bootseq = true;
}
}
@@ -3354,7 +3417,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
goto lack;
}
return bin;
return uuid;
}
__cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
@@ -3399,16 +3462,15 @@ __cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
#elif defined(HW_USERMEM) || defined(HW_PHYSMEM64) || defined(HW_MEMSIZE) || \
defined(HW_PHYSMEM)
size_t ram, len = sizeof(ram);
static const int mib[] = {
CTL_HW,
static const int mib[] = {CTL_HW,
#if defined(HW_USERMEM)
HW_USERMEM
HW_USERMEM
#elif defined(HW_PHYSMEM64)
HW_PHYSMEM64
HW_PHYSMEM64
#elif defined(HW_MEMSIZE)
HW_MEMSIZE
HW_MEMSIZE
#else
HW_PHYSMEM
HW_PHYSMEM
#endif
};
if (sysctl(
@@ -3449,12 +3511,11 @@ __cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
#elif defined(VM_TOTAL) || defined(VM_METER)
struct vmtotal info;
size_t len = sizeof(info);
static const int mib[] = {
CTL_VM,
static const int mib[] = {CTL_VM,
#if defined(VM_TOTAL)
VM_TOTAL
VM_TOTAL
#elif defined(VM_METER)
VM_METER
VM_METER
#endif
};
if (sysctl(

View File

@@ -91,6 +91,20 @@ if(UNIX AND NOT SUBPROJECT)
set_target_properties(test_extra_dupfixed_multiple PROPERTIES
CXX_STANDARD ${MDBX_CXX_STANDARD} CXX_STANDARD_REQUIRED ON)
endif()
add_executable(test_extra_dbi extra/dbi.c++)
target_include_directories(test_extra_dbi PRIVATE "${PROJECT_SOURCE_DIR}")
target_link_libraries(test_extra_dbi ${TOOL_MDBX_LIB})
if(MDBX_CXX_STANDARD)
set_target_properties(test_extra_dbi PROPERTIES
CXX_STANDARD ${MDBX_CXX_STANDARD} CXX_STANDARD_REQUIRED ON)
endif()
add_executable(test_extra_early_close_dbi extra/early_close_dbi.c++)
target_include_directories(test_extra_early_close_dbi PRIVATE "${PROJECT_SOURCE_DIR}")
target_link_libraries(test_extra_early_close_dbi ${TOOL_MDBX_LIB})
if(MDBX_CXX_STANDARD)
set_target_properties(test_extra_early_close_dbi PROPERTIES
CXX_STANDARD ${MDBX_CXX_STANDARD} CXX_STANDARD_REQUIRED ON)
endif()
endif()
endif()
@@ -176,6 +190,7 @@ else()
if(MDBX_BUILD_CXX)
add_test(NAME extra_maindb_ordinal COMMAND test_extra_maindb_ordinal)
add_test(NAME extra_dupfixed_multiple COMMAND test_extra_dupfixed_multiple)
add_test(NAME extra_dbi COMMAND test_extra_dbi)
endif()
endif()

View File

@@ -42,7 +42,16 @@ uint32_t us2fractional(uint32_t us) {
}
uint32_t fractional2us(uint32_t fractional) {
#if !(defined(_M_ARM) || defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64))
/* Смеяться или плакать, но все существующие на май 2024 компиляторы Microsoft
* для ARM/ARM64, уже порядка 10 лет, падают на этом коде из-за внтутренней
* ошибке (aka ICE). */
return uint32_t((fractional * uint64_t(USEC_PER_SEC)) >> 32);
#else
static_assert(USEC_PER_SEC % 16 == 0, "WTF?");
/* Crutch for MSVC ARM/ARM64 compilers to avoid internal compiler error. */
return UInt32x32To64(fractional, USEC_PER_SEC / 16) >> 28;
#endif
}
#ifndef MSEC_PER_SEC

38
test/extra/dbi.c++ Normal file
View File

@@ -0,0 +1,38 @@
#include "mdbx.h++"
#include <iostream>
static void logger(MDBX_log_level_t loglevel, const char *function, int line,
const char *fmt, va_list args) noexcept {
(void)loglevel;
fprintf(stdout, "%s:%u ", function, line);
vfprintf(stdout, fmt, args);
}
int main(int argc, const char *argv[]) {
(void)argc;
(void)argv;
mdbx_setup_debug(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger);
mdbx::path path = "test-dbi";
mdbx::env::remove(path);
mdbx::env::operate_parameters operateParameters(100, 10);
mdbx::env_managed::create_parameters createParameters;
{
mdbx::env_managed env2(path, createParameters, operateParameters);
mdbx::txn_managed txn2 = env2.start_write(false);
/* mdbx::map_handle testHandle2 = */ txn2.create_map(
"fap1", mdbx::key_mode::reverse, mdbx::value_mode::single);
txn2.commit();
}
mdbx::env_managed env(path, createParameters, operateParameters);
mdbx::txn_managed txn = env.start_write(false);
/* mdbx::map_handle testHandle = */ txn.create_map(
"fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
txn.commit();
std::cout << "OK\n";
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,110 @@
#include "mdbx.h++"
#include <cstring>
static const char *const testkey = "testkey";
static uint64_t testval = 11;
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
mdbx::path db_filename = "test-early_close_dbi";
mdbx::env_managed::remove(db_filename);
MDBX_env *environment;
MDBX_MAYBE_UNUSED int err = mdbx_env_create(&environment);
assert(err == MDBX_SUCCESS);
err = mdbx_env_set_option(environment, MDBX_opt_max_db, 2);
assert(err == MDBX_SUCCESS);
err = mdbx_env_set_option(environment, MDBX_opt_max_readers, 2);
assert(err == MDBX_SUCCESS);
// status = mdbx_env_set_option(environment, MDBX_opt_prefault_write_enable,
// 1); assert(err == MDBX_SUCCESS);
intptr_t lowerbound(0), size(0), upperbound(mdbx::env::geometry::GiB / 2);
intptr_t step(128 * mdbx::env::geometry::MiB),
shrink(256 * mdbx::env::geometry::MiB), pagesize(-1);
err =
#ifdef _WIN32
mdbx_env_set_geometryW
#else
mdbx_env_set_geometry
#endif
(environment, lowerbound, size, upperbound, step, shrink, pagesize);
assert(err == MDBX_SUCCESS);
MDBX_env_flags_t flags(MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_LIFORECLAIM |
MDBX_NORDAHEAD);
err = mdbx_env_open(environment, db_filename.c_str(), flags, 0644);
assert(err == MDBX_SUCCESS);
// ---
MDBX_txn *transaction;
err = mdbx_txn_begin(environment, nullptr, MDBX_TXN_READWRITE, &transaction);
assert(err == MDBX_SUCCESS);
MDBX_dbi textindex;
err = mdbx_dbi_open(transaction, "testdb", MDBX_DB_DEFAULTS, &textindex);
assert(err == MDBX_NOTFOUND);
err = mdbx_dbi_open(transaction, "testdb", MDBX_CREATE, &textindex);
assert(err == MDBX_SUCCESS);
MDBX_val mdbxkey{(void *)testkey, std::strlen(testkey)}, mdbxval{};
err = mdbx_get(transaction, textindex, &mdbxkey, &mdbxval);
assert(err == MDBX_NOTFOUND);
unsigned dbi_flags, dbi_state;
err = mdbx_dbi_flags_ex(transaction, textindex, &dbi_flags, &dbi_state);
assert(err == MDBX_SUCCESS);
assert((dbi_state & (MDBX_DBI_CREAT | MDBX_DBI_DIRTY)) != 0);
err = mdbx_dbi_close(environment, textindex);
assert(err != MDBX_SUCCESS);
err = mdbx_txn_commit(transaction);
assert(err == MDBX_SUCCESS);
// ---
err = mdbx_txn_begin(environment, nullptr, MDBX_TXN_READWRITE, &transaction);
assert(err == MDBX_SUCCESS);
MDBX_val mdbxput{&testval, sizeof(uint64_t)};
err = mdbx_put(transaction, textindex, &mdbxkey, &mdbxput, MDBX_NOOVERWRITE);
assert(err == MDBX_SUCCESS);
err = mdbx_get(transaction, textindex, &mdbxkey, &mdbxval);
assert(err == MDBX_SUCCESS);
assert(testval == *reinterpret_cast<uint64_t *>(mdbxval.iov_base));
err = mdbx_put(transaction, textindex, &mdbxkey, &mdbxput, MDBX_NOOVERWRITE);
assert(err == MDBX_KEYEXIST);
err = mdbx_get(transaction, textindex, &mdbxkey, &mdbxval);
assert(err == MDBX_SUCCESS);
assert(testval == *reinterpret_cast<uint64_t *>(mdbxval.iov_base));
err = mdbx_dbi_flags_ex(transaction, textindex, &dbi_flags, &dbi_state);
assert(err == MDBX_SUCCESS);
assert((dbi_state & MDBX_DBI_DIRTY) != 0);
err = mdbx_dbi_close(environment, textindex);
assert(err != MDBX_SUCCESS);
err = mdbx_txn_commit(transaction);
assert(err == MDBX_SUCCESS);
// ---
err = mdbx_txn_begin(environment, nullptr, MDBX_TXN_RDONLY, &transaction);
assert(err == MDBX_SUCCESS);
err = mdbx_get(transaction, textindex, &mdbxkey, &mdbxval);
assert(err == MDBX_SUCCESS);
assert(testval == *reinterpret_cast<uint64_t *>(mdbxval.iov_base));
err = mdbx_dbi_close(environment, textindex);
assert(err == MDBX_SUCCESS);
err = mdbx_txn_commit(transaction);
assert(err == MDBX_SUCCESS);
err = mdbx_env_close_ex(environment, true);
assert(err == MDBX_SUCCESS);
return 0;
}

View File

@@ -34,7 +34,7 @@
#define IP_PRINTF_ARG_HOST(addr) \
(int)((addr) >> 24), (int)((addr) >> 16 & 0xff), (int)((addr) >> 8 & 0xff), \
(int)((addr)&0xff)
(int)((addr) & 0xff)
char opt_db_path[PATH_MAX] = "./mdbx_bench2";
static MDBX_env *env;

View File

@@ -41,7 +41,7 @@
#if _MSC_FULL_VER < 190024215
#pragma message( \
"It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.")
"It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.")
#endif
#define bswap64(v) _byteswap_uint64(v)