На POSIX-платформах внутри API копирования используются файловый
блокировки `fcntl(F_SETLK)` и `flock()`, так как только совместное
использование обеспечивает блокировку на всех платформах и файловых
системах, включая NFS и SMB.
Однако, в зависимости от платформы, версии ядра ОС, типа файловой
системы, а в случае NFS/SMB также от удаленной стороны, используемые
системные файловые блокировки могут не работать или конфликтовать между
собой (в частности на OSX).
Поэтому в этом коммите реализуется более гибкий подход. Если кратко,
то допускается отказ одной из блокировок при успехе другой:
- При успехе fcntl(F_SETLK) допускается EAGAIN/EWOULDBLOCK и EREMOTEIO от flock(),
если целевой файл на не-локальной файловой системе, а также на не-Linux платформах,
где одновременная блокировка может быть не разрешена fcntl(F_SETLK) и flock().
- При успехе flock() допускается ENOTSUP и REMOTEIO от fcntl(F_SETLK),
если целевой файл на не-локальной файловой системе.
В lockfree-пути открытия DBI-дескрипторов, при просмотре уже открытых
таблиц, пропускались элементы отличающиеся не только по имени, но также
и при несовпадении запрашиваемых флагов и актуальных флагов уже открытой
таблицы.
Если при этом уже было достигнуто (ранее заданное) максимальное
количество открытых DBI-дескрипторов, то возвращалась ошибка
`MDBX_DBS_FULL`, в том числе в ситуациях когда результат должен быть
другим.
Спасибо [Артёму Воротникову](https://github.com/vorot93) за сообщение о проблеме!
Запуск читающих и пишущих транзакций взаимно не блокируется. Однако,
внутри одного процесса, DBI-хендлы и атрибуты таблиц используются
совместно всеми транзакциями (в рамках экземпляра среды работы с БД).
Поэтому после изменения атрибутов таблиц, в том числе при первоначальном
чтении актуальных атрибутов MainDB, может возникать состояние гонок при
одновременном старте нескольких транзакций.
Этим коммитом исправляются недочеты в обработке ситуации таких гонок,
из-за чего могла возвращается неожиданная (с точки зрения пользователя)
ошибка `MDBX_BAD_DBI`.
Формально ошибка присутствовала начиная с коммита `e6af7d7c53428ca2892bcbf7eec1c2acee06fd44` от 2023-11-05.
Однако, до этого (исторически, как было унаследовано от LMDB)
отсутствовал какой-либо контроль смены атрибутов MainDB во время старта
и/или работы транзакций. Поэтому вместо возврата каких-либо ошибок
подобные состояние гонок и/или связанные с изменением атрибутов MainDB
оставались необработанными/незамеченными, либо проявлялись как редкие
неуловимые сбои пользовательских приложений.
Спасибо [Артёму Воротникову](https://github.com/vorot93) за сообщение о проблеме!
Ошибка/недоработка была с первой реализации resurrect-after-fork в
ноябре 2023, но оставалась не замеченной из-за отсутствия
CI-тестирования на платформе OSX/Mac (где нет поддержки разделяемых
мьютексов).
Ранее две страницы объединялись если были заполнены на 25% или менее, с образованием страницы заполненной на 50% или менее.
Теперь порог по-умолчанию установлен в 33%, что при объединении будет порождать страницу заполненную на 66%.
Вместо `MDBX_ENOMEM` был использован идентификатор `ENOMEM`,
что могло ломать сборку на не-POSIX/Windows платформах,
в зависимости от конфигурации и/или версии SDK.
В случае ошибки запуска транзакции (например из-за невозможности расширения отображения при увеличении БД в другом процессе),
сигнатура транзакции отсутствует, что вызывало срабатывание assert-проверки.
Первый выпуск в новом кусте/линейке версий с добавлением функционала, расширением API и внутренними переработками.
За перечнем доработок и изменений обращайтесь к [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).
git diff' stat: 166 files changed, 9467 insertions(+), 5597 deletions(-).
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
В экстремальных случаях, масштабирование одного операнда и 32-бит не хватает для предотвращения потери значимости расчетного коэффициента.
Поэтому здесь реализован переход на фиксированную точку 32-точка-32 с одним 64-битным делением и двумя полными умножениями 32*32->64.
Для 32-битных систем можно сделать чуть легче, заменив 64-битую арифметику масштабированием (адаптивным сдвигом) обоих операндов, но пока не вижу в этом смысла.