Поддерживающий выпуск с исправлением обнаруженных ошибок и устранением недочетов
в память Героя России гвардии майора Дмитрия Семёнова с позывным "СЭМ".
Значимые исправления и доработки:
---------------------------------
- Устранение унаследованной от LMDB ошибки приводящей к повреждению БД при использовании `MDBX_DUPFIXED`.
- Исправление ложной ошибки `MDBX_CORRUPTED (-30796)` в сценарии работы
в режиме `MDBX_DUPFIXED` и нечетной длинной мульти-значений.
- Исправление недочета корректировки сопутствующих курсоров при разделении страницы
по сценарию добавления пустой страницы слева.
- Доработка `rebalance()` ради уменьшения WAF.
- Исправление assert-проверки внутри `check_txn()` для случая завершенных транзакций в режиме `MDBX_NO_TLS`.
Последствий ошибки, кроме срабатывания assert-проверки в отладочных сборках, нет.
- Устранение ошибки при открытии БД на файловой системе только-для-чтения.
- Удалены излишне строгие проверки в утилите `mdbx_chk`, которые
приводили к ложно-позитивным ошибкам при проверке БД после серии
последних доработок.
Более подробная информация в [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).
git diff' stat: 19 commits, 57 files changed, 751 insertions(+), 331 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Стабилизирующий выпуск с исправлением обнаруженных ошибок и устранением недочетов.
Исправления и доработки:
------------------------
- Ликвидация зависимости от ранее удаленной опции `MDBX_ENABLE_PREFAULT`, из-за
чего опция `MDBX_ENABLE_MINCORE` не включалась автоматически, что приводило
к не-активации соответствующего улучшения и не-достижению декларируемого уровня
производительности в сценариях использования в режиме `MDBX_WRITEMAP`.
- Исправление авто-установки `MDBX_ENV_CHECKPID` при отключении использования
функционала `madvise()` посредством опции сборки `MDBX_ENABLE_MADVISE=0`.
Из-за чего при поддержке системой `madvise(MADV_DONTFORK)` не включался контроль pid.
- Добавлена проверка переданного ключа на `NULL` при обработке `MDBX_GET_MULTIPLE`.
- Добавлена проверка номеров корневых страниц в `coherency_check()`.
- Обеспечен `const` для начала и конца диапазона в аргументах `mdbx_estimate_range()`.
- Из разрабатываемой версии перенесены не-нарушающие совместимости доработки C++ API:
- добавлен тип `mdbx::cursor::estimation_result`, а поведение методов
`cursor::estimate()` унифицировано с `cursor::move()`;
- для предотвращения незаметного неверного использования API, для инициализации
возвращаемых по ссылке срезов, вместо пустых срезов задействован `slice::invalid()`;
- добавлены дополнительные C++ операторы преобразования к типам C API;
- для совместимости со старыми стандартами C++ и старыми версиями STL перенесены
в public классы `buffer::move_assign_alloc` и `buffer::copy_assign_alloc`;
- добавлен тип `mdbx::default_buffer`;
- для срезов и буферов добавлены методы `hex_decode()`, `base64_decode()`, `base58_decode()`;
- добавлен тип `mdbx::comparator` и функций `mdbx::default_comparator()`;
- добавлены статические методы `buffer::hex()`, `base64()`, `base58()`;
- для транзакций и курсоров добавлены методы `get_/set_context`;
- добавлен метод `cursor::clone()`;
- Поддержка base58 приведена в соответствии с черновиком RFC.
- Переработка/исправление `to_hex()` и `from_hex()`.
- Уменьшение `MDBX_opt_rp_augment_limit` по умолчанию до 1/3 от текущего количества страниц в БД.
Более подробная информация в [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).
git diff' stat: 32 commits, 8 files changed, 667 insertions(+), 401 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Стабилизирующий выпуск с исправлением обнаруженных ошибок и устранением недочетов,
в день 100-летия со дня рождения выдающегося советского и российского ученого и конструктора [Влади́мира Фёдоровича У́ткина](https://ru.wikipedia.org/wiki/Уткин,_Владимир_Фёдорович).
Исправления и доработки:
------------------------
- Устранение регресса/ошибки в пути обработки `put(MDBX_MULTIPLE)` при пакетном/оптовом
помещении в БД множественных значений одного ключа (aka multi-value или dupsort).
Проявление проблемы зависит от компилятора и опций оптимизации/кодогенерации, но с большой вероятностью возвращется
ошибка `MDBX_BAD_VALSIZE` (`-30781`), а в отладочных сборках срабатывает проверка `cASSERT(mc, !"Invalid key-size")`.
Сценарии приводящие к другим проявлениям на данный момент не известны.
- Реализована перезапись в `mdbx_put(MDBX_CURRENT)` всех текущих мульти-значений ключа
при отсутствии флага `MDBX_NOOVERWRITE`. Ранее в такой ситуации возвращалась ошибка `MDBX_EMULTIVAL`.
В текущем понимании новое поведение более удобно и не создаёт проблем совместимости с ранее написанным кодом.
- Добавлена возможность использовать `mdbx_cursor_get(MDBX_GET_MULTIPLE)` без предварительной установки
курсора, совмещая операцию пакетного получения данных с позиционированием курсора на передаваемый ключ.
- Микрооптимизация и рефакторинг `cursor_put_nochecklen()` в продолжение исправления
регресса/ошибки в пути обработки `put(MDBX_MULTIPLE)`.
- Уточнение формулировок в описании API, в том числе пояснений о `SIGSEGV`
и недопустимости прямого изменения данных.
Более подробная информация в [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).
git diff' stat: 24 commits, 18 files changed, 624 insertions(+), 94 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Достаточно запутано:
- Внутри `update_gc()` используется создание записей с резервированием
посредством `put(MDBX_RESERVE)` в циклах с ранним выходом и последующим
заполнением.
- При этом в случае раннего выхода (из цикла из-за изменения набора
страниц) зарезервированное место в добавленных записях остается
незаполненным/неиницилизированным (подкрашенным в Valgrind или ASAN).
- Чтение этих незаполненных/неиницилизированных данных штатно не
происходит, но в отладочных сборках при включении детального уровне
логирования выполняется отладочный вывод значений ключей и данных при
позиционировании курсоров.
- В свою очередь, `update_gc()` либо удаляет, либо заполняет
зарезервированные записи, но для этого требуется позиционирование
курсора, что в отладочных сборках приводит к чтению
незаполненных/неиницилизированных записей и печали Valgrind/ASAN.
Теперь внутри `update_gc()` в отладочных сборках с поддержкой Valgrind
или ASAN место в резервируемых записях явно инициализируется.
- Обеспечении терминирующего нуля даже при нехватке буфера и
опосредованных предупреждений Valgrind из-за чтения внутри strlen()
неинициализированных данных при последующем логировании/печати.
- Ускорение за счет отказа от использования snpruintf().
Стабилизирующий выпуск с исправлением обнаруженных ошибок и устранением недочетов,
в день основания международного детского центра [«Арте́к»](https://ru.wikipedia.org/wiki/Артек).
Исправления и доработки:
------------------------
- Исправление опечатки в имени переменной внутри `mdbx_env_turn_for_recovery()`.
- Обходное решение проблем сборки посредством GCC с использование опций `-m32 -arch=i686 -Ofast`.
- Доработка режима "восстановления" БД и переключения на заданную мета-страницу.
Более подробная информация в [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).
Мелочи:
-------
- Незначительное уточнение CMake-пробника для `std::filesystem`,
проверяющего необходимость линковки с дополнительными библиотеками C++.
- Устранение минорных предупреждений старых компиляторов в тестах.
- Устранение причины ложно-позитивного предупреждения новых версий GCC в C++ API.
- Исправление ссылки на репозиторий бенчмарка ioarena.
- Добавление перекрестных ссылок в doxygen-документацию по C++ API.
- Уточнение ограничений в разделе [Restrictions & Caveats](https://libmdbx.dqdkfa.ru/intro.html#restrictions).
- Исправление ссылок на описание `mdbx_canary_put()`.
14 files changed, 222 insertions(+), 56 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Стабилизирующий выпуск с исправлением обнаруженных ошибок и устранением
недочетов, в день 100-летнего юбилея спортивного клуба [«ЦСКА»](https://ru.wikipedia.org/wiki/Центральный_спортивный_клуб_Армии).
Мелочи:
-------
- Обновление патча для старых версий buildroot.
- Использование clang-format-16.
- Использование `enum`-типов вместо `int` для устранения предупреждений GCC 13,
что могло ломать сборку в Fedora 38.
14 files changed, 117 insertions(+), 83 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Стабилизирующий выпуск с исправлением обнаруженных ошибок и устранением
недочетов, в день 100-летнего юбилея спортивного общества [«Динамо»](https://ru.wikipedia.org/wiki/Динамо_(спортивное_общество)).
Благодарности:
--------------
- Max <maxc0d3r@protonmail.com> за сообщение о проблеме экспорта из DSO/DLL
устаревших функций API.
- [`@calvin3721`](https://t.me/calvin3721) за сообщение о проблеме работы
`MainDB` с флагами не по-умолчанию.
Исправления:
------------
- Поправлен экспорт из DSO/DLL устаревших функций,
которые заменены на inline в текущем API.
- Устранено использование неверного компаратора при создании или пересоздании
`MainDB` с флагами/опциями предполагающим использование специфического
компаратора (не по-умолчанию).
Мелочи:
-------
- Удалена дублирующая диагностика внутри `node_read_bigdata()`.
- Исправлены ссылки в описании `mdbx_env_set_geometry()`.
- Добавлен отдельный тест `extra/upsert_alldups` для специфического
сценария замены/перезаписи одним значением всех multi-значений
соответствующих ключу, т.е. замена всех «дубликатов» одним значением.
- В C++ API добавлены варианты `buffer::key_from()` с явным именованием по типу данных.
- Добавлен отдельный тест `extra/maindb_ordinal` для специфического
сценария создания `MainDB` с флагами требующими использования
компаратора не по-умолчанию.
- Рефакторинг проверки "когерентности" мета-страниц.
- Корректировка `osal_vasprintf()` для устранения предупреждений статических анализаторов.
16 files changed, 686 insertions(+), 247 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Стабилизирующий выпуск с исправлением обнаруженных ошибок, устранением
недочетов и технических долгов. Ветка 0.12 считается готовой к
продуктовому использованию, получает статус стабильной и далее будет
получать только исправление ошибок. Разработка будет продолжена в ветке
0.13, а ветка 0.11 становится архивной.
Благодарности:
--------------
- Max <maxc0d3r@protonmail.com> за сообщение о проблеме ERROR_SHARING_VIOLATION
в режиме MDBX_EXCLUSIVE на Windows.
- Alisher Ashyrov <https://t.me/a1is43ras4> за сообщение о проблеме
с assert-проверкой и содействие в отладке.
- Masatoshi Fukunaga <https://gitflic.ru/user/mah0x211> за сообщение о проблеме
`put(MDBX_UPSERT+MDBX_ALLDUPS)` для случая замены всех значений в subDb.
Исправления (без корректировок новых функций):
----------------------------------------------
- Устранен регресс после коммита 474391c83c,
приводящий к возврату ERROR_SHARING_VIOLATION в Windows при открытии БД
в режиме MDBX_EXCLUSIVE для чтения-записи.
- Добавлено ограничение размера отображения при коротком read-only файле, для
предотвращения ошибки ERROR_NOT_ENOUGH_MEMORY в Windows, которая возникает
в этом случае и совсем не информативна для пользователя.
- Произведен рефакторинг `dxb_resize()`, в том числе, для устранения срабатывания
assert-проверки `size_bytes == env->me_dxb_mmap.current` в специфических
многопоточных сценариях использования. Проверка срабатывала только в
отладочных сборках, при специфическом наложении во времени читающей и
пишущей транзакции в разных потоках, одновременно с изменением размера БД.
Кроме срабатывание проверки, каких-либо других последствий не возникало.
- Устранена проблема в `put(MDBX_UPSERT+MDBX_ALLDUPS)` для случая замены
всех значений единственного ключа в subDb. В ходе этой операции subDb
становится полностью пустой, без каких-либо страниц и именно эта
ситуация не была учтена в коде, что приводило к повреждению БД
при фиксации такой транзакции.
- Устранена излишняя assert-проверка внутри `override_meta()`.
Что в отладочных сборках могло приводить к ложным срабатываниям
при восстановлении БД, в том числе при автоматическом откате слабых
мета-страниц.
- Скорректированы макросы `__cold`/`__hot`, в том числе для устранения проблемы
`error: inlining failed in call to ‘always_inline FOO(...)’: target specific option mismatch`
при сборке посредством GCC >10.x для SH4.
Ликвидация технических долгов и мелочи:
---------------------------------------
- Исправлены многочисленные опечатки в документации.
- Доработан тест для полной стохастической проверки `MDBX_EKEYMISMATCH` в режиме `MDBX_APPEND`.
- Расширены сценарии запуска `mdbx_chk` из CMake-тестов для проверки как в обычном,
так и эксклюзивном режимах чтения-записи.
- Уточнены спецификаторы `const` и `noexcept` для нескольких методов в C++ API.
- Устранено использование стека под буферы для `wchar`-преобразования путей.
- Для Windows добавлена функция `mdbx_env_get_path()` для получения пути к БД
в формате многобайтных символов.
- Добавлены doxygen-описания для API с широкими символами.
- Устранены предупреждения статического анализатора MSVC,
все они были несущественные, либо ложные.
- Устранено ложное предупреждение GCC при сборке для SH4.
- Добавлена поддержка ASAN (Address Sanitizer) при сборке посредством MSVC.
- Расширен набор перебираемых режимов в скрипте `test/long_stochastic.sh`,
добавлена опция `--extra`.
- В C++ API добавлена поддержка расширенных опций времени выполнения `mdbx::extra_runtime_option`,
аналогично `enum MDBX_option_t` из C API.
- Вывод всех счетчиков page-operations в `mdbx_stat`.
63 files changed, 1161 insertions(+), 569 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
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.
В том числе, для устранения срабатывания assert-проверки
`size_bytes == env->me_dxb_mmap.current` в специфических многопоточных
сценариях использования.
Проверка срабатывала только в отладочных сборках, при специфическом
наложении во времени читающей и пишущей транзакции в разных потоках,
одновременно с изменением размера БД.
Кроме срабатывание проверки, каких-либо других последствий не возникало.
Цель в предотвращении ошибки ERROR_NOT_ENOUGH_MEMORY в Windows, которая
совсем не информативна для пользователя и возникает в этом случае (когда
файл открыт read-only и короче запрошенного размера).
Выпуск с существенными доработками и новой функциональностью в память о закрытом open-source проекте "Акула".
Благодарности:
--------------
- [Alex Sharov](https://t.me/AskAlexSharov) и команде [Erigon](https://github.com/ledgerwatch/erigon) за тестирование.
- [Simon Leier](https://t.me/leisim) за сообщение о сбоях и тестирование.
Новое:
------
- Использование адреса [https://libmdbx.dqdkfa.ru/dead-github](https://libmdbx.dqdkfa.ru/dead-github)
для отсылки к сохранённым в web.archive.org копиям ресурсов, уничтоженных администрацией Github.
- Реализована prefault-запись при выделении страниц для read-write отображений.
Это приводит к кратному снижению системных издержек и существенному увеличению
производительности в соответствующих сценариях использования, когда:
- размер БД и объём данных существенно больше ОЗУ;
- используется режим `MDBX_WRITEMAP`;
- не-мелкие транзакции (по ходу транзакции выделяется многие сотни или тысячи страниц).
В режиме `MDBX_WRITEMAP` выделение/переиспользование страниц приводит
к page-fault и чтению страницы с диска, даже если содержимое страницы
не нужно (будет перезаписано). Это является следствием работы подсистемы
виртуальной памяти, а штатный способ лечения через `MADV_REMOVE`
работает не на всех ФС и обычно дороже получаемой экономии.
Теперь в libmdbx используется "упреждающая запись" таких страниц,
которая на системах с [unified page cache](https://www.opennet.ru/base/dev/ubc.txt.html)
приводит к "вталкиванию" данных, устраняя необходимость чтения с диска при
обращении к такой странице памяти.
Новый функционал работает в согласованности с автоматическим управлением read-ahead
и кэшем статуса присутствия страниц в ОЗУ, посредством [mincore()](https://man7.org/linux/man-pages/man2/mincore.2.html).
- Добавлена опция `MDBX_opt_prefault_write_enable` для возможности принудительного
включения/выключения prefault-записи.
- Реализован динамический выбор между сквозной записью на диск и обычной записью
с последующим [fdatasync()](https://man7.org/linux/man-pages/man3/fdatasync.3p.html)
управляемый опцией `MDBX_opt_writethrough_threshold`.
В долговечных (durable) режимах данные на диск могут быть сброшены двумя способами:
- сквозной записью через файловый дескриптор открытый с `O_DSYNC`;
- обычной записью с последующим вызовом `fdatasync()`.
Первый способ выгоднее при записи малого количества страниц и/или если
канал взаимодействия с диском/носителем имеет близкую к нулю задержку.
Второй способ выгоднее если требуется записать много страниц и/или канал
взаимодействия имеет весомую задержку (датацентры, облака). Добавленная
опция `MDBX_opt_writethrough_threshold` позволяет во время выполнения
задать порог для динамического выбора способа записи в зависимости от
объема и конкретных условия использования.
- Автоматическая установка `MDBX_opt_rp_augment_limit` в зависимости от размера БД.
- Запрещение разного режима `MDBX_WRITEMAP` между процессами в режимах
с отложенной/ленивой записью, так как в этом случае невозможно
обеспечить сброс данных на диск во всех случаях на всех поддерживаемых платформах.
- Добавлена опция сборки `MDBX_MMAP_USE_MS_ASYNC` позволяющая отключить
использование системного вызова `msync(MS_ASYNC)`, в использовании
которого нет необходимости на подавляющем большинстве актуальных ОС.
По-умолчанию `MDBX_MMAP_USE_MS_ASYNC=0` (выключено) на Linux и других
системах с unified page cache. Такое поведение (без использования
`msync(MS_ASYNC)`) соответствует неизменяемой (hardcoded) логике LMDB. В
результате, в простых/наивных бенчмарках, libmdbx опережает LMDB
примерна также как при реальном применении.
На всякий случай стоит еще раз отметить/напомнить, что на Windows
предположительно libmdbx будет отставать от LMDB в сценариях с
множеством мелких транзакций, так как libmdbx осознанно использует на
Windows файловые блокировки, которые медленные (плохо реализованы в ядре
ОС), но позволяют застраховать пользователей от массы неверных действий
приводящих к повреждению БД.
- Поддержка не-печатных имен для subDb.
- Добавлен явный выбор `tls_model("local-dynamic")` для обзода проблемы
`relocation R_X86_64_TPOFF32 against FOO cannot be used with -shared`
из-за ошибки в CLANG приводящей к использованию неверного режима `ls_model`.
- Изменение тактики слияния страниц при удалении.
Теперь слияние выполняется преимущественно с уже измененной/грязной страницей.
Если же справа и слева обе страницы с одинаковым статусом,
то с наименее заполненной, как прежде. В сценариях с массивным удалением
это позволяет увеличить производительность до 50%.
- Добавлен контроль отсутствия LCK-файлов с альтернативным именованием.
Исправления (без корректировок новых функций):
----------------------------------------------
- Изменение размера отображения если это требуется для сброса данных на
диск при вызове `mdbx_env_sync()` из параллельного потока выполнения вне
работающей транзакции.
- Исправление регресса после коммита db72763de0 от 2022-10-08
в логике возврата грязных страниц в режиме `MDBX_WRITEMAP`, из-за чего
освободившиеся страницы использовались не немедленно, а попадали в
retired-список совершаемой транзакции и происходил необоснованный рост
размера транзакции.
- Устранение SIGSEGV или ошибочного вызова `free()` в ситуациях
повторного открытия среды посредством `mdbx_env_open()`.
- Устранение ошибки совершенной в коммите fe20de136c от 2022-09-18,
в результате чего на Linux в режиме `MDBX_WRITEMAP` никогда не вызывался `msync()`.
Проблема существует только в релизе 0.12.2.
- Добавление подсчета грязных страниц в `MDBX_WRITEMAP` для предоставления посредством `mdbx_txn_info()`
актуальной информации об объеме изменений в процессе транзакций чтения-записи.
- Исправление несущественной опечатки в условиях `#if` определения порядка байт.
- Исправление сборки для случая `MDBX_PNL_ASCENDING=1`.
Ликвидация технических долгов и мелочи:
---------------------------------------
- Доработка поддержки авто-слияния записей GC внутри `page_alloc_slowpath()`.
- Устранение несущественных предупреждений Coverity.
- Использование единого курсора для поиска в GC.
- Переработка внутренних флагов связанных с выделением страниц из GC.
- Доработка подготовки резерва перед обновлением GC при включенном BigFoot.
- Оптимизация `pnl_merge()` для случаев неперекрывающихся объединяемых списков.
- Оптимизация поддержки отсортированного списка страниц в `dpl_append()`.
- Ускорение работы `mdbx_chk` при обработке пользовательских записей в `@MAIN`.
- Переработка LRU-отметок для спиллинга.
- Переработка контроля "некогерентности" Unified page cache для уменьшения накладных расходов.
- Рефакторинг и микрооптимизация.
20 files changed, 4504 insertions(+), 2924 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>