Новая версия со сменой лицензии, существенным расширением API,
добавлением функционала и внутренними переработками. В том числе,
с незначительным нарушением обратной совместимости API библиотеки.
Список нововведений, доработок и изменений слишком велик для размещения
здесь, но вся информация есть в файле
[ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).
```
git diff' stat: 157 files changed, 41949 insertions(+), 33741 deletions(-)
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
```
Падение происходило в случае когда:
- Некоторый процесс увеличивал размер БД с изменением геометрии (с
увеличением предельного размера БД и её отображения в ОЗУ), затем
задействовал страницу из добавленного сегмента в качестве корневой для
FreeDB/GC и/или MainDB и фиксировал транзакцию.
- Другой процесс, уже работавший с БД до изменения геометрии первым
процессом, запускал транзакцию чтения. Падение происходило при проверке
«когерентности» отображения страниц БД в ОЗУ, при проверке отметок
модификации внутри корневых страниц, так как в этом случае они были вне
границ текущего отображения БД в адресном пространстве этого процесса.
Похоже что в ходе какого-то рефакторинга потерялась соответствующая
проверка. Этот коммит добавляет её как временное решение, до переноса
проверки «когерентности» после изменения размера отображения (добавлено в
TODO).
Упомянутый флажок отсутствовал в пути разрушения транзакции при ошибке
её запуска. Из-за чего делалась попытка разрушить курсоры, что приводило
к падению отладочных сборок, так как в них соответствующий массив
намеренно заполнен некорректными указателями.
Временная подпорка для coherency_check(), которую в перспективе
следует заменить вместе с переделкой установки mod_txnid.
Суть проблемы:
- coherency_check() в качестве одного из критериев "когерентности"
проверяет условие meta.maindb.mod_txnid == maindb.root->txnid;
- при обновлении maindb.sequence высталяется DBI_DIRTY, что приведет
к обновлению meta.maindb.mod_txnid = current_txnid;
- однако, если в само дерево maindb обновление не вносились и оно
не пустое, то корневая страницы останеться с прежним txnid и из-за
этого ложно сработает coherency_check().
Временное (текущее) решение: Принудительно обновляем корневую
страницу в описанной выше ситуации. Это устраняет проблему, но и
не создает рисков регресса.
Итоговое решение, которое предстоит реализовать:
- изменить семантику установки/обновления mod_txnid, привязав его
строго к изменению b-tree, но не атрибутов;
- обновлять mod_txnid при фиксации вложенных транзакций;
- для dbi-хендлов пользовательских subDb (видимо) можно оставить
DBI_DIRTY в качестве признака необходимости обновления записи
subDb в MainDB, при этом взводить DBI_DIRTY вместе с обновлением
mod_txnid, в том числе при обновлении sequence.
- для MAIN_DBI при обновлении sequence не следует взводить DBI_DIRTY
и/или обновлять mod_txnid, а только взводить MDBX_TXN_DIRTY.
- альтернативно, можно перераспределить флажки-признаки dbi_state,
чтобы различать состояние dirty-tree и dirty-attributes.
Допускаем итерацию с не-вовлечением еще не-измененных страниц,
только когда страницы для объединения доступны справа и слева,
Т.е. допускаем итерацию для выбора лучшей альтернативы (справа или слева),
и избегаем этой итерации когда альтернативы нет.