Compare commits

..

111 Commits

Author SHA1 Message Date
Леонид Юрьев (Leonid Yuriev)
f5279769f1 mdbx: запечатка и уведомление об окончании поддержки.
Поддержка куста 0.12 завершена, ветка переведена в архив.
Каких-либо исправлений и тем более выпусков больше не будет.

The 0.12 hive is end-of-life, support has been terminated and the branch has been archived.
There will be no more fixes, much less releases.
2025-05-27 14:44:11 +03:00
Леонид Юрьев (Leonid Yuriev)
5b060c40a1 mdbx: переформатирование (косметика). 2025-04-20 22:25:51 +03:00
Леонид Юрьев (Leonid Yuriev)
e3ad208c71 mdbx: переупорядочивание атрибутов для совместимости с GCC-15 в режиме C23 (backport). 2025-04-20 00:31:44 +03:00
Леонид Юрьев (Leonid Yuriev)
dbf9313244 mdbx-tests: обнуление pid на входе в osal_actor_poll() (backport). 2025-04-20 00:31:28 +03:00
Леонид Юрьев (Leonid Yuriev)
d9c5e40360 mdbx-doc: исправление опечаток/повторов в комментариях. 2025-04-07 13:00:40 +03:00
Леонид Юрьев (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)
61a073687f mdbx: время учить Русский. 2024-03-19 15:56:37 +03:00
Леонид Юрьев (Leonid Yuriev)
3865e85248 mdbx: орфоргафия. 2024-03-16 20:45:35 +03:00
Леонид Юрьев (Leonid Yuriev)
c70ef83e4a mdbx: исправление опечатки равно/неравно в условии внутри update_gc().
Существенных последствий ошибки не было (иначе бы давно было замечено).
Но в определенных сценариях, сходимость требовала еще одного цикла
повтора внутри update_gc().
2024-03-15 06:10:10 +03:00
Леонид Юрьев (Leonid Yuriev)
8cc3dba7ae mdbx: merge branch master into stable. 2024-03-14 19:48:12 +03:00
Леонид Юрьев (Leonid Yuriev)
872bddaee6 mdbx: обновление патча для старых версий buildroot. 2024-03-14 19:46:38 +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
18 changed files with 892 additions and 269 deletions

View File

@@ -4,6 +4,181 @@ 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).
Поддержка куста 0.12 завершена, ветка переведена в архив. Каких-либо исправлений и тем более выпусков больше не будет.
The 0.12 hive is end-of-life, support has been terminated and the branch has been archived. There will be no more fixes, much less releases.
## 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
Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов
@@ -17,7 +192,7 @@ Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Благодарности:
- [Dvir H](https://t.me/Dvirsw) за [сообщение](https://t.me/libmdbx/5368)
об ошибке `MDBX_CORRUPTED` в сценарии работы в режиме `MDBX_DUPFIXED` и нечетной длинной
об ошибке `MDBX_CORRUPTED` в сценарии работы в режиме `MDBX_DUPFIXED` и нечетной длиной
мульти-значений, с предоставлением точного минимального сценария воспроизведения.
Значимые исправления и доработки:
@@ -35,10 +210,10 @@ Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
вероятность проявления близка к нулю, а сценарий такого проявления найти не удалось.
В MDBX ошибка присутствовала с момента отделения проекта от LMDB,
где эта ошибка присутствует более 11 лети, по настоящее время.
где эта ошибка присутствует более 11 лет, по настоящее время.
- Исправление ложной ошибки `MDBX_CORRUPTED (-30796)` в сценарии работы
в режиме `MDBX_DUPFIXED` и нечетной длинной мульти-значений.
в режиме `MDBX_DUPFIXED` и нечетной длиной мульти-значений.
- Исправление недочета корректировки сопутствующих курсоров при разделении страницы
по сценарию добавления пустой страницы слева.
@@ -46,7 +221,7 @@ Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
- Доработка `rebalance()` ради уменьшения WAF. Новый функционал, включая
контролируемую пользователем опцию `enum MDBX_option_t`, будет доступен
в выпусках ветки `0.13.x`, а в этом выпуске доработка сводится к тактике
не-вовленичения чистой страницы при нехватке запаса страниц в ходе обновления GC,
не-вовлечения чистой страницы при нехватке запаса страниц в ходе обновления GC,
за счет ухудшения баланса дерева страниц.
- Устранение упущения приводящего к нелогичной ситуации
@@ -169,7 +344,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 +2002,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

@@ -1,7 +1,18 @@
<!-- Required extensions: pymdownx.betterem, pymdownx.tilde, pymdownx.emoji, pymdownx.tasklist, pymdownx.superfences -->
### Время учить Русский
Начиная с 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
Since on 2022-04-15 the Github administration, without any warning
nor explanation, deleted _libmdbx_ along with a lot of other projects,
simultaneously blocking access for many developers.
For the same reason ~~Github~~ is blacklisted forever.
@@ -10,7 +21,7 @@ GitFlic's developers plan to support other languages,
including English 和 中文, in the near future.
### Основной репозиторий перемещен на [GitFlic](https://gitflic.ru/project/erthink/libmdbx)
так как 15 апреля 2022 администрация Github без предупреждения и
Так как 15 апреля 2022 администрация Github без предупреждения и
объяснения причин удалила _libmdbx_ вместе с массой других проектов,
одновременно заблокировав доступ многим разработчикам.
По этой же причине ~~Github~~ навсегда занесен в черный список.

28
mdbx.h
View File

@@ -136,7 +136,7 @@ are only a few cases of changing data.
| _DELETING_|||
|Key is absent → Error since no such key |\ref mdbx_del() or \ref mdbx_replace()|Error \ref MDBX_NOTFOUND|
|Key exist → Delete by key |\ref mdbx_del() with the parameter `data = NULL`|Deletion|
|Key exist → Delete by key with with data matching check|\ref mdbx_del() with the parameter `data` filled with the value which should be match for deletion|Deletion or \ref MDBX_NOTFOUND if the value does not match|
|Key exist → Delete by key with data matching check|\ref mdbx_del() with the parameter `data` filled with the value which should be match for deletion|Deletion or \ref MDBX_NOTFOUND if the value does not match|
|Delete at the current cursor position |\ref mdbx_cursor_del() with \ref MDBX_CURRENT flag|Deletion|
|Extract (read & delete) value by the key |\ref mdbx_replace() with zero flag and parameter `new_data = NULL`|Returning a deleted value|
@@ -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)
@@ -1413,7 +1414,7 @@ enum MDBX_env_flags_t {
* \ref mdbx_env_set_syncbytes() and \ref mdbx_env_set_syncperiod() functions
* could be very useful with `MDBX_SAFE_NOSYNC` flag.
*
* The number and volume of of disk IOPs with MDBX_SAFE_NOSYNC flag will
* The number and volume of disk IOPs with MDBX_SAFE_NOSYNC flag will
* exactly the as without any no-sync flags. However, you should expect a
* larger process's [work set](https://bit.ly/2kA2tFX) and significantly worse
* a [locality of reference](https://bit.ly/2mbYq2J), due to the more
@@ -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.
@@ -5264,7 +5266,7 @@ LIBMDBX_API int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,
* This returns a comparison as if the two data items were keys in the
* specified database.
*
* \warning There ss a Undefined behavior if one of arguments is invalid.
* \warning There is a Undefined behavior if one of arguments is invalid.
*
* \param [in] txn A transaction handle returned by \ref mdbx_txn_begin().
* \param [in] dbi A database handle returned by \ref mdbx_dbi_open().
@@ -5289,7 +5291,7 @@ mdbx_get_keycmp(MDBX_db_flags_t flags);
* This returns a comparison as if the two items were data items of the
* specified database.
*
* \warning There ss a Undefined behavior if one of arguments is invalid.
* \warning There is a Undefined behavior if one of arguments is invalid.
*
* \param [in] txn A transaction handle returned by \ref mdbx_txn_begin().
* \param [in] dbi A database handle returned by \ref mdbx_dbi_open().

162
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
@@ -851,7 +878,7 @@ struct LIBMDBX_API_TYPE slice : public ::MDBX_val {
/// \brief Checks whether the content of the slice is printable.
/// \param [in] disable_utf8 By default if `disable_utf8` is `false` function
/// checks that content bytes are printable ASCII-7 characters or a valid UTF8
/// sequences. Otherwise, if if `disable_utf8` is `true` function checks that
/// sequences. Otherwise, if `disable_utf8` is `true` function checks that
/// content bytes are printable extended 8-bit ASCII codes.
MDBX_NOTHROW_PURE_FUNCTION bool
is_printable(bool disable_utf8 = false) const noexcept;
@@ -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 3efdf07a80f750c23de126ac80e78fb0545a1b63 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
@@ -13,11 +13,11 @@ This patch adds libmdbx:
focused on creating unique lightweight solutions.
- libmdbx surpasses the legendary LMDB (Lightning Memory-Mapped Database)
in terms of reliability, features and performance.
- https://gitflic.ru/project/erthink/libmdbx
- more information at https://gitflic.ru/project/erthink/libmdbx
The v0.12.8 "Vladimir Utkin" is stable release of frontward _libmdbx_
branch with new superior features on the day of 100 anniversary of the birth
of the outstanding Soviet and Russian scientist and engineer Vladimir Fedorovich Utkin.
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
@@ -112,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..82cf28d6a9
index 0000000000..222e7caf5c
--- /dev/null
+++ b/package/libmdbx/libmdbx.hash
@@ -0,0 +1,5 @@
+# Hashes from: https://libmdbx.dqdkfa.ru/release/SHA256SUMS
+sha256 c78c56c53708bbfc519bf53ebf520d1f09d30ee6427a4bedf713316696e671d0 libmdbx-amalgamated-0.12.8.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..d198fe5b22
index 0000000000..da4a53913f
--- /dev/null
+++ b/package/libmdbx/libmdbx.mk
@@ -0,0 +1,42 @@
@@ -133,7 +133,7 @@ index 0000000000..d198fe5b22
+#
+################################################################################
+
+LIBMDBX_VERSION = 0.12.8
+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
@@ -170,5 +170,5 @@ index 0000000000..d198fe5b22
+
+$(eval $(cmake-package))
--
2.42.0
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;
}
@@ -3233,10 +3232,8 @@ static int cursor_touch(MDBX_cursor *const mc, const MDBX_val *key,
const MDBX_val *data);
#define MDBX_END_NAMES \
{ \
"committed", "empty-commit", "abort", "reset", "reset-tmp", "fail-begin", \
"fail-beginchild" \
}
{"committed", "empty-commit", "abort", "reset", \
"reset-tmp", "fail-begin", "fail-beginchild"}
enum {
/* txn_end operation number, for logging */
MDBX_END_COMMITTED,
@@ -3485,10 +3482,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 +3539,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 +3609,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 +3637,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 +3784,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 +6938,7 @@ __hot static pgno_t relist_get_single(MDBX_txn *txn) {
* диском будет более кучным, а у страниц ближе к концу БД будет больше шансов
* попасть под авто-компактификацию. Частично эта тактика уже реализована, но
* для её эффективности требуется явно приоритезировать выделение страниц:
* - поддерживать для relist, для ближних и для дальних страниц;
* - поддерживать два relist, для ближних и для дальних страниц;
* - использовать страницы из дальнего списка, если первый пуст,
* а второй слишком большой, либо при пустой GC.
*
@@ -6934,12 +6946,12 @@ __hot static pgno_t relist_get_single(MDBX_txn *txn) {
* регионы будут линейными, что принципиально ускоряет запись на HDD.
* Одновременно, в среднем это не повлияет на чтение, точнее говоря, если
* порядок чтения не совпадает с порядком изменения (иначе говоря, если
* чтение не коррклирует с обновлениями и/или вставками) то не повлияет, иначе
* чтение не коррелирует с обновлениями и/или вставками) то не повлияет, иначе
* может ускорить. Однако, последовательности в среднем достаточно редки.
* Поэтому для эффективности требуется аккумулировать и поддерживать в ОЗУ
* огромные списки страниц, а затем сохранять их обратно в БД. Текущий формат
* БД (без битовых карт) для этого крайне не удачен. Поэтому эта тактика не
* имеет шансов быть успешной без смены формата БД (Mithril).
* БД (без сжатых битовых карт) для этого крайне не удачен. Поэтому эта
* тактика не имеет шансов быть успешной без смены формата БД (Mithril).
*
* 3. Стараться экономить последовательности страниц. Это позволяет избегать
* лишнего чтения/поиска в GC при более-менее постоянном размещении и/или
@@ -6947,7 +6959,7 @@ __hot static pgno_t relist_get_single(MDBX_txn *txn) {
* информации от приложения библиотека не может знать насколько
* востребованными будут последовательности в ближайшей перспективе, а
* экономия последовательностей "на всякий случай" не только затратна
* сама-по-себе, но и работает во вред.
* сама-по-себе, но и работает во вред (добавляет хаоса).
*
* Поэтому:
* - в TODO добавляется разделение relist на «ближние» и «дальние» страницы,
@@ -8274,7 +8286,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 +8339,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 +8377,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 +8385,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 +8396,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 +8700,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 +8718,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 +9167,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 +9189,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 +9282,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 +9300,15 @@ 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 */
@@ -10568,7 +10590,7 @@ retry:
if (unlikely(!ctx->retired_stored)) {
/* Make sure last page of GC is touched and on retired-list */
rc = cursor_last(&ctx->cursor, nullptr, nullptr);
if (likely(rc != MDBX_SUCCESS))
if (likely(rc == MDBX_SUCCESS))
rc = gcu_touch(ctx);
if (unlikely(rc != MDBX_SUCCESS) && rc != MDBX_NOTFOUND)
goto bailout;
@@ -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,9 @@ 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 +16993,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 +17010,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 +17369,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 +23131,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 */
@@ -891,7 +891,7 @@ typedef struct MDBX_reader {
/* The header for the reader table (a memory-mapped lock file). */
typedef struct MDBX_lockinfo {
/* Stamp identifying this as an MDBX file.
* It must be set to MDBX_MAGIC with with MDBX_LOCK_VERSION. */
* It must be set to MDBX_MAGIC with MDBX_LOCK_VERSION. */
uint64_t mti_magic_and_version;
/* Format of this lock file. Must be set to MDBX_LOCK_FORMAT. */
@@ -1303,7 +1303,7 @@ 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 \
#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

@@ -157,13 +157,14 @@ __extern_C void __assert2(const char *file, int line, const char *function,
__assert2(file, line, function, assertion)
#elif defined(__UCLIBC__)
__extern_C void __assert(const char *, const char *, unsigned int, const char *)
MDBX_NORETURN __extern_C void __assert(const char *, const char *, unsigned int,
const char *)
#ifdef __THROW
__THROW
#else
__nothrow
#endif /* __THROW */
MDBX_NORETURN;
;
#define __assert_fail(assertion, file, line, function) \
__assert(assertion, file, line, function)
@@ -171,14 +172,15 @@ __extern_C void __assert(const char *, const char *, unsigned int, const char *)
/* workaround for avoid musl libc wrong prototype */ ( \
defined(__GLIBC__) || defined(__GNU_LIBRARY__))
/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 1.x-3.x */
__extern_C void __assert_fail(const char *assertion, const char *file,
unsigned line, const char *function)
MDBX_NORETURN __extern_C void __assert_fail(const char *assertion,
const char *file, unsigned line,
const char *function)
#ifdef __THROW
__THROW
#else
__nothrow
#endif /* __THROW */
MDBX_NORETURN;
;
#elif defined(__APPLE__) || defined(__MACH__)
__extern_C void __assert_rtn(const char *function, const char *file, int line,
@@ -214,12 +216,12 @@ __extern_C __dead void __assert13(const char *file, int line,
__assert13(file, line, function, assertion)
#elif defined(__FreeBSD__) || defined(__BSD__) || defined(__bsdi__) || \
defined(__DragonFly__)
__extern_C void __assert(const char *function, const char *file, int line,
const char *assertion) /* __nothrow */
MDBX_NORETURN __extern_C void __assert(const char *function, const char *file,
int line,
const char *assertion) /* __nothrow */
#ifdef __dead2
__dead2
#else
MDBX_NORETURN
#endif /* __dead2 */
#ifdef __disable_tail_calls
__disable_tail_calls
@@ -766,11 +768,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,7 +3013,30 @@ __cold static LSTATUS mdbx_RegGetValue(HKEY hKey, LPCSTR lpSubKey,
}
#endif
__cold MDBX_MAYBE_UNUSED static bool
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;
}
MDBX_MAYBE_UNUSED __cold static bool
bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
if (n > 31) {
unsigned bits = 0;
@@ -3045,7 +3069,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 +3077,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 +3131,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 +3177,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 +3195,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 +3203,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 +3211,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 +3223,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 +3231,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 +3247,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 +3255,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 +3272,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 +3287,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 +3296,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 +3330,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 +3346,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 +3365,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 +3385,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 +3419,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 +3464,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 +3513,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

@@ -522,6 +522,7 @@ int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
options |= WCONTINUED;
#endif
pid = 0;
while (sigalarm_tail == sigalarm_head) {
int status;
pid = waitpid(0, &status, options);

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)