Compare commits

...

23 Commits

Author SHA1 Message Date
Леонид Юрьев (Leonid Yuriev)
a971c76aff v0.13.6 "Бузина".
Поддерживающий выпуск стабильной ветки с исправлением обнаруженных ошибок и устранением недочётов,
в память о погибшем украинском историке и писателе [Алесе Бузине](https://ru.ruwiki.ru/wiki/Бузина,_Олесь_Алексеевич).

За перечнем доработок и изменений обращайтесь к [ChangeLog](https://libmdbx.dqdkfa.ru/md__change_log.html).

git diff' stat: 15 files changed, 194 insertions(+), 36 deletions(-).
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
2025-04-22 11:53:23 +03:00
Леонид Юрьев (Leonid Yuriev)
b6f918aa1c mdbx: исправление опечатки в логировании (backport). 2025-04-22 11:17:39 +03:00
Леонид Юрьев (Leonid Yuriev)
ab2f661c97 mdbx: дополнение ChangeLog. 2025-04-20 00:01:59 +03:00
Леонид Юрьев (Leonid Yuriev)
5548ef20f6 mdbx: переупорядочивание атрибутов для совместимости с GCC-15 в режиме C23 (backport). 2025-04-19 23:44:07 +03:00
Леонид Юрьев (Leonid Yuriev)
679c1eb939 mdbx-tests: обнуление pid на входе в osal_actor_poll() (backport). 2025-04-19 23:43:43 +03:00
Леонид Юрьев (Leonid Yuriev)
76a588f91b mdbx: исправление возврата MDBX_BAD_TXN вместо MDBX_EINVAL из mdbx_cursor_unbind() в особых случаях (backport). 2025-04-19 23:42:59 +03:00
Леонид Юрьев (Leonid Yuriev)
6b5515908b mdbx: предотвращение возврата неожиданной ошибки MDBX_BUSY из mdbx_txn_lock(dont_wait=false) (backport). 2025-04-19 23:42:34 +03:00
Леонид Юрьев (Leonid Yuriev)
214fa153e2 mdbx: дополнение ChangeLog. 2025-04-10 16:54:13 +03:00
Леонид Юрьев (Leonid Yuriev)
819551ce13 mdbx-tests: расширение и доработка сценария extra/cursor-closing (backport). 2025-04-10 16:37:42 +03:00
Леонид Юрьев (Leonid Yuriev)
a22c0c5c48 mdbx: подсказка для Coverity для подавления ложно-положительных предупреждений (backport). 2025-04-10 16:35:53 +03:00
Леонид Юрьев (Leonid Yuriev)
9540cabf5f mdbx: возврат MDBX_EINVAL из mdbx_cursor_bind() при невозможности отвязки курсора от его текущей транзакции (backport). 2025-04-10 16:34:57 +03:00
Леонид Юрьев (Leonid Yuriev)
0e3b093eb5 mdbx: исправление неверной assert-проверки и микрооптимизация (backport).
В пути фиксации вложенных транзакций, условие в assert-проверке не было
корректным для случая, когда таблица уже существовала и её дескриптор
был открыт, использовался в завершаемой вложенной транзакции, но не
использовался в родительской.

Это исправление недочета также передаёт, уже загруженное из БД, кешируемое
состояние таблицы в родительскую транзакцию.
2025-04-10 16:34:19 +03:00
Леонид Юрьев (Leonid Yuriev)
5d38add405 mdbx: исправление ошибок merge/rebase (backport). 2025-04-10 16:33:10 +03:00
Леонид Юрьев (Leonid Yuriev)
b55a41f604 mdbx: дополнение ChangeLog. 2025-04-09 22:18:13 +03:00
Леонид Юрьев (Leonid Yuriev)
29bed7cf5d mdbx: игнорирование EAGAIN от flock() в случае копирования на NFS. 2025-04-09 22:18:07 +03:00
Леонид Юрьев (Leonid Yuriev)
8d0eceee9f mdbx: отключение использования copy_file_range() для ядер linux 5.3-5.18 включительно. 2025-04-07 05:28:16 +03:00
Леонид Юрьев (Leonid Yuriev)
56a6377622 mdbx: понижение уровня логирования для "skip update meta" (backport).
Спасибо [Илье Михееву](https://github.com/JkLondon) за сообщение о недочете.
2025-03-28 15:14:54 +03:00
Леонид Юрьев (Leonid Yuriev)
19dc93fc76 mdbx: дополнение ChangeLog. 2025-03-23 17:46:28 +03:00
Леонид Юрьев (Leonid Yuriev)
5f1d8dcb3e mdbx: уточнение типа адреса для донатов (backport). 2025-03-22 23:33:13 +03:00
Леонид Юрьев (Leonid Yuriev)
3d2b221256 mdbx++: вброс std::invalid_argument с явным сообщением "MDBX_EINVAL" (backport). 2025-03-22 23:32:57 +03:00
Леонид Юрьев (Leonid Yuriev)
ca1808d57f mdbx-test: расширение extra/cursor-closing (backport). 2025-03-22 23:32:57 +03:00
Леонид Юрьев (Leonid Yuriev)
aa98d6a88e mdbx: обновление NOTICE. 2025-03-22 23:31:47 +03:00
Леонид Юрьев (Leonid Yuriev)
b9b14f0061 mdbx: устранение регресса при использовании курсоров для DBI=0 в читающих транзакциях (hotfix).
В результате рефакторинга и ряда оптимизаций для завершения/гашения
курсоров в читающих и пишущих транзакций стал использоваться общий код.
Причем за основу, был взят соответствующий фрагмент относящийся к
пишущим транзакциям, в которых пользователю не позволяется
использоваться курсоры для DBI=0 и поэтому эта итераций пропускалась.

В результате, при завершении читающих транзакциях, курсоры связанные с
DBI=0 не завершались должным образом, а при их повторном использовании
или явном закрытии после завершения читающей транзакции происходило
обращение к уже освобожденной памяти. Если же такие курсоры
отсоединялись или закрывались до завершения читающей транзакции, то
ошибка не имела шансов на проявление.

Спасибо Илье Михееву (https://github.com/JkLondon) и команде Erigon (https://erigon.tech) за сообщения о проблеме.
2025-03-22 20:01:52 +03:00
15 changed files with 194 additions and 36 deletions

View File

@@ -4,6 +4,75 @@ ChangeLog
English version [by liar Google](https://libmdbx-dqdkfa-ru.translate.goog/md__change_log.html?_x_tr_sl=ru&_x_tr_tl=en)
and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/libmdbx.dqdkfa.ru/md__change_log.html).
## v0.13.6 "Бузина" от 2025-04-22.
Поддерживающий выпуск стабильной ветки с исправлением обнаруженных ошибок и устранением недочётов,
в память о погибшем украинском историке и писателе [Алесе Бузине](https://ru.ruwiki.ru/wiki/Бузина,_Олесь_Алексеевич).
Благодарности:
- [Erigon](https://erigon.tech/) за спонсорство.
- [Илье Михееву](https://t.me/IlyaMkhv) и команде [Erigon](https://github.com/erigontech) за сообщения о проблеме и тестирование.
- [Алексею Костюку (aka Keller)](https://t.me/keller18306) за сообщения о проблеме копирования на NFS.
Исправления:
- Устранён регресс при использовании курсоров для DBI=0 (aka GC/FreeDB) в читающих транзакциях.
В результате рефакторинга и ряда оптимизаций для завершения/гашения
курсоров в читающих и пишущих транзакций, стал использоваться общий код.
Причем за основу, был взят соответствующий фрагмент относящийся к
пишущим транзакциям, в которых пользователю не позволяется
использоваться курсоры для DBI=0 и поэтому эта итераций пропускалась.
В результате, при завершении читающих транзакциях, курсоры связанные с
DBI=0 не завершались должным образом, а при их повторном использовании
или явном закрытии после завершения читающей транзакции происходило
обращение к уже освобожденной памяти. Если же такие курсоры
отсоединялись или закрывались до завершения читающей транзакции, то
ошибка не имела шансов на проявление.
- Устранён регресс в виде ошибки `EAGAIN` при копировании БД на NFS и CIFS/SMB.
При доработках/развитии API в функции копирования был добавлен захват
файловой блокировки посредством как `fcntl()`, так и `flock()`. Однако,
в зависимости от версии локального ядра, версии удалённого сервера NFS и
опций монтирования, это могло приводить к возврату POSIX-ошибки `EAGAIN`
(`11` на большинстве платформ, включая Linux).
- Устранена ошибка merge/rebase внутри `mdbx_txn_release_all_cursors_ex()`,
что могло приводить к последующим неожиданным ошибкам `MDBX_EBADSIGN` и утечкам памяти.
Для проверки сценария дополнен соответствующий тест.
- Исправлена assert-проверка в пути завершения вложенных транзакций.
Для проверки сценария дополнен соответствующий тест.
- Устранена возможность возврата неожиданной ошибки `MDBX_BUSY` из `mdbx_txn_lock(dont_wait=false)`.
- Для совместимости с GCC 15.x в режиме C23 изменен порядок указания атрибутов функций.
Изменение поведения:
- При невозможности отвязки курсора от его текущей транзакции функция `mdbx_cursor_bind()`
теперь возвращает `MDBX_EINVAL` вместо `MDBX_BAD_TXN`.
Прочие доработки:
- Во избежание потенциальных проблем отключено использование `copy_file_range()` на ядрах Linux 5.3 - 5.18.
- Вброс `std::invalid_argument` теперь производится явным сообщением `MDBX_EINVAL`.
- Уточнен тип адреса для пожертвований.
Ethereum/ERC-20 позволяет перечислять не только ETH, но и другие валюты/токены, в том числе USDC.
- Дополнен тест курсоров extra/cursor-closing.
- В `NOTICE` обновлена информация о Github.
--------------------------------------------------------------------------------
## v0.13.5 "Труба" от 2025-03-21
Поддерживающий выпуск стабильной ветки с исправлением обнаруженных ошибок и устранением недочётов.
@@ -107,7 +176,7 @@ and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/libmdbx
поломать родительскую, сделав её продолжение невозможным. Если восстанавливать, то также следует «воскрешать» закрытые
курсоры, что неизбежно приведет к путанице, утечкам памяти и использованию после освобождения.
- В C++ API отменён вброс исключения при запросе транзакции у отсоединённого курсора посредством вывоза `mdbx::cursor::txn()`.
- В C++ API отменён вброс исключения при запросе транзакции у отсоединённого курсора посредством вызова `mdbx::cursor::txn()`.
Прочие доработки:

30
NOTICE
View File

@@ -8,16 +8,32 @@ documentation, C++ API description and links to the original git repo
with the source code. Questions, feedback and suggestions are welcome
to the Telegram' group https://t.me/libmdbx.
Donations are welcome to ETH `0xD104d8f8B2dC312aaD74899F83EBf3EEBDC1EA3A`.
Donations are welcome to the Ethereum/ERC-20 `0xD104d8f8B2dC312aaD74899F83EBf3EEBDC1EA3A`.
Всё будет хорошо!
Copyright 2015-2025 Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru>
SPDX-License-Identifier: Apache-2.0
For notes about the license change, credits and acknowledgments,
please refer to the COPYRIGHT file within original libmdbx source code
repository https://gitflic.ru/project/erthink/libmdbx
please refer to the COPYRIGHT file within libmdbx source.
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.
---
On 2022-04-15, without any warnings or following explanations, the
Github administration deleted _libmdbx_, my account and all other
projects (status 404). A few months later, without any involvement or
notification from/to me, the projects were restored/opened in the "public
read-only archive" status from some kind of incomplete backup. I regard
these actions of Github as malicious sabotage, and I consider the Github
service itself to have lost trust forever.
As a result of what has happened, I will never, under any circumstances,
post the primary sources (aka origins) of my projects on Github, or rely
in any way on the Github infrastructure.
Nevertheless, realizing that it is more convenient for users of
_libmdbx_ and other my projects to access ones on Github, I do not want
to restrict their freedom or create inconvenience, and therefore I place
mirrors (aka mirrors) of such repositories on Github since 2025. At the
same time, I would like to emphasize once again that these are only
mirrors that can be frozen, blocked or deleted at any time, as was the
case in 2022.

View File

@@ -9,7 +9,7 @@
> [5](https://libmdbx.dqdkfa.ru/tg-archive/messages5.html), [6](https://libmdbx.dqdkfa.ru/tg-archive/messages6.html), [7](https://libmdbx.dqdkfa.ru/tg-archive/messages7.html)).
> See the [ChangeLog](https://gitflic.ru/project/erthink/libmdbx/blob?file=ChangeLog.md) for `NEWS` and latest updates.
> Donations are welcome to ETH `0xD104d8f8B2dC312aaD74899F83EBf3EEBDC1EA3A`.
> Donations are welcome to the Ethereum/ERC-20 `0xD104d8f8B2dC312aaD74899F83EBf3EEBDC1EA3A`.
> Всё будет хорошо!

View File

@@ -571,11 +571,17 @@ retry_snap_meta:
uint8_t *const data_buffer = buffer + ceil_powerof2(meta_bytes, globals.sys_pagesize);
#if MDBX_USE_COPYFILERANGE
static bool copyfilerange_unavailable;
#if (defined(__linux__) || defined(__gnu_linux__))
if (globals.linux_kernel_version >= 0x05030000 && globals.linux_kernel_version < 0x05130000)
copyfilerange_unavailable = true;
#endif /* linux */
bool not_the_same_filesystem = false;
struct statfs statfs_info;
if (fstatfs(fd, &statfs_info) || statfs_info.f_type == /* ECRYPTFS_SUPER_MAGIC */ 0xf15f)
/* avoid use copyfilerange_unavailable() to ecryptfs due bugs */
not_the_same_filesystem = true;
if (!copyfilerange_unavailable) {
struct statfs statfs_info;
if (fstatfs(fd, &statfs_info) || statfs_info.f_type == /* ECRYPTFS_SUPER_MAGIC */ 0xf15f)
/* avoid use copyfilerange_unavailable() to ecryptfs due bugs */
not_the_same_filesystem = true;
}
#endif /* MDBX_USE_COPYFILERANGE */
for (size_t offset = meta_bytes; rc == MDBX_SUCCESS && offset < used_size;) {
@@ -760,14 +766,24 @@ __cold static int copy2pathname(MDBX_txn *txn, const pathchar_t *dest_path, MDBX
lock_op.l_whence = SEEK_SET;
lock_op.l_start = 0;
lock_op.l_len = OFF_T_MAX;
if (MDBX_FCNTL(newfd, MDBX_F_SETLK, &lock_op)
#if (defined(__linux__) || defined(__gnu_linux__)) && defined(LOCK_EX) && \
(!defined(__ANDROID_API__) || __ANDROID_API__ >= 24)
|| flock(newfd, LOCK_EX | LOCK_NB)
#endif /* Linux */
)
if (MDBX_FCNTL(newfd, MDBX_F_SETLK, &lock_op))
rc = errno;
}
#if defined(LOCK_EX) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 24)
if (rc == MDBX_SUCCESS && flock(newfd, LOCK_EX | LOCK_NB)) {
const int err_flock = errno, err_fs = osal_check_fs_local(newfd, 0);
if (err_flock != EAGAIN || err_fs != MDBX_EREMOTE) {
ERROR("%s flock(%" MDBX_PRIsPATH ") error %d, remote-fs check status %d", "unexpected", dest_path, err_flock,
err_fs);
rc = err_flock;
} else {
WARNING("%s flock(%" MDBX_PRIsPATH ") error %d, remote-fs check status %d", "ignore", dest_path, err_flock,
err_fs);
}
}
#endif /* LOCK_EX && ANDROID_API >= 24 */
#endif /* Windows / POSIX */
if (rc == MDBX_SUCCESS)

View File

@@ -63,7 +63,7 @@ int mdbx_cursor_bind(MDBX_txn *txn, MDBX_cursor *mc, MDBX_dbi dbi) {
return MDBX_SUCCESS;
rc = mdbx_cursor_unbind(mc);
if (unlikely(rc != MDBX_SUCCESS))
return rc;
return (rc == MDBX_BAD_TXN) ? MDBX_EINVAL : rc;
}
cASSERT(mc, mc->next == mc);
@@ -88,8 +88,16 @@ int mdbx_cursor_unbind(MDBX_cursor *mc) {
return LOG_IFERR(MDBX_EINVAL);
int rc = check_txn(mc->txn, MDBX_TXN_FINISHED | MDBX_TXN_HAS_CHILD);
if (unlikely(rc != MDBX_SUCCESS))
if (unlikely(rc != MDBX_SUCCESS)) {
for (const MDBX_txn *txn = mc->txn; rc == MDBX_BAD_TXN && check_txn(txn, MDBX_TXN_FINISHED) == MDBX_SUCCESS;
txn = txn->nested)
if (dbi_state(txn, cursor_dbi(mc)) == 0)
/* специальный случай: курсор прикреплён к родительской транзакции, но соответствующий dbi-дескриптор ещё
* не использовался во вложенной транзакции, т.е. курсор ещё не импортирован в дочернюю транзакцию и не имеет
* связанного сохранённого состояния (поэтому mc→backup равен nullptr). */
rc = MDBX_EINVAL;
return LOG_IFERR(rc);
}
if (unlikely(!mc->txn || mc->txn->signature != txn_signature)) {
ERROR("Wrong cursor's transaction %p 0x%x", __Wpedantic_format_voidptr(mc->txn), mc->txn ? mc->txn->signature : 0);
@@ -244,9 +252,8 @@ int mdbx_txn_release_all_cursors_ex(const MDBX_txn *txn, bool unbind, size_t *co
MDBX_cursor *bk = mc->backup;
mc->next = bk->next;
mc->backup = bk->backup;
mc->backup = nullptr;
bk->backup = nullptr;
bk->signature = 0;
bk = bk->next;
osal_free(bk);
} else {
mc->signature = cur_signature_ready4dispose;

View File

@@ -140,7 +140,7 @@ int mdbx_txn_lock(MDBX_env *env, bool dont_wait) {
if (unlikely(env->flags & MDBX_RDONLY))
return LOG_IFERR(MDBX_EACCESS);
if (unlikely(env->basal_txn->owner || (env->basal_txn->flags & MDBX_TXN_FINISHED) == 0))
if (dont_wait && unlikely(env->basal_txn->owner || (env->basal_txn->flags & MDBX_TXN_FINISHED) == 0))
return LOG_IFERR(MDBX_BUSY);
return LOG_IFERR(lck_txn_lock(env, dont_wait));

View File

@@ -545,15 +545,16 @@ int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency) {
/* Update parent's DBs array */
eASSERT(env, parent->n_dbi == txn->n_dbi);
TXN_FOREACH_DBI_ALL(txn, dbi) {
if (txn->dbi_state[dbi] & (DBI_CREAT | DBI_FRESH | DBI_DIRTY)) {
if (txn->dbi_state[dbi] != (parent->dbi_state[dbi] & ~(DBI_FRESH | DBI_CREAT | DBI_DIRTY))) {
eASSERT(env, (txn->dbi_state[dbi] & (DBI_CREAT | DBI_FRESH | DBI_DIRTY)) != 0 ||
(txn->dbi_state[dbi] | DBI_STALE) ==
(parent->dbi_state[dbi] & ~(DBI_FRESH | DBI_CREAT | DBI_DIRTY)));
parent->dbs[dbi] = txn->dbs[dbi];
/* preserve parent's status */
const uint8_t state = txn->dbi_state[dbi] | (parent->dbi_state[dbi] & (DBI_CREAT | DBI_FRESH | DBI_DIRTY));
DEBUG("dbi %zu dbi-state %s 0x%02x -> 0x%02x", dbi, (parent->dbi_state[dbi] != state) ? "update" : "still",
parent->dbi_state[dbi], state);
parent->dbi_state[dbi] = state;
} else {
eASSERT(env, txn->dbi_state[dbi] == (parent->dbi_state[dbi] & ~(DBI_FRESH | DBI_CREAT | DBI_DIRTY)));
}
}

View File

@@ -53,6 +53,7 @@ static inline size_t dbi_bitmap_ctz(const MDBX_txn *txn, intptr_t bmi) {
I = (I - 1) | (bitmap_chunk - 1); \
bitmap_item = TXN->dbi_sparse[(1 + I) / bitmap_chunk]; \
if (!bitmap_item) \
/* coverity[const_overflow] */ \
I += bitmap_chunk; \
continue; \
} else if ((bitmap_item & 1) == 0) { \

View File

@@ -1157,7 +1157,8 @@ int dxb_sync_locked(MDBX_env *env, unsigned flags, meta_t *const pending, troika
if (!head.is_steady && meta_is_steady(pending))
target = (meta_t *)head.ptr_c;
else {
WARNING("%s", "skip update meta");
NOTICE("skip update meta%" PRIaPGNO " for txn#%" PRIaTXN ", since it is already steady",
data_page(head.ptr_c)->pgno, head.txnid);
return MDBX_SUCCESS;
}
} else {

View File

@@ -373,7 +373,7 @@ __cold std::string error::message() const {
__cold void error::throw_exception() const {
switch (code()) {
case MDBX_EINVAL:
throw std::invalid_argument("mdbx");
throw std::invalid_argument("MDBX_EINVAL");
case MDBX_ENOMEM:
throw std::bad_alloc();
case MDBX_SUCCESS:

View File

@@ -1745,7 +1745,7 @@ MDBX_INTERNAL int osal_check_fs_incore(mdbx_filehandle_t handle) {
return MDBX_RESULT_FALSE;
}
static int osal_check_fs_local(mdbx_filehandle_t handle, int flags) {
MDBX_INTERNAL int osal_check_fs_local(mdbx_filehandle_t handle, int flags) {
#if defined(_WIN32) || defined(_WIN64)
if (globals.running_under_Wine && !(flags & MDBX_EXCLUSIVE))
return ERROR_NOT_CAPABLE /* workaround for Wine */;
@@ -2856,7 +2856,7 @@ __cold static LSTATUS mdbx_RegGetValue(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValu
}
#endif
__cold MDBX_MAYBE_UNUSED static bool bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
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;
for (unsigned i = 0; i < n; ++i) /* try parse an UUID in text form */ {

View File

@@ -481,6 +481,7 @@ MDBX_INTERNAL int osal_resume_threads_after_remap(mdbx_handle_array_t *array);
MDBX_INTERNAL int osal_msync(const osal_mmap_t *map, size_t offset, size_t length, enum osal_syncmode_bits mode_bits);
MDBX_INTERNAL int osal_check_fs_rdonly(mdbx_filehandle_t handle, const pathchar_t *pathname, int err);
MDBX_INTERNAL int osal_check_fs_incore(mdbx_filehandle_t handle);
MDBX_INTERNAL int osal_check_fs_local(mdbx_filehandle_t handle, int flags);
MDBX_MAYBE_UNUSED static inline uint32_t osal_getpid(void) {
STATIC_ASSERT(sizeof(mdbx_pid_t) <= sizeof(uint32_t));

View File

@@ -8,8 +8,7 @@ __hot txnid_t txn_snapshot_oldest(const MDBX_txn *const txn) {
}
void txn_done_cursors(MDBX_txn *txn, const bool merge) {
tASSERT(txn, txn->cursors[FREE_DBI] == nullptr);
TXN_FOREACH_DBI_FROM(txn, i, /* skip FREE_DBI */ 1) {
TXN_FOREACH_DBI_ALL(txn, i) {
MDBX_cursor *mc = txn->cursors[i];
if (mc) {
txn->cursors[i] = nullptr;

View File

@@ -172,9 +172,21 @@ mdbx::map_handle case1_cycle_dbi(std::deque<mdbx::map_handle> &dbi) {
void case1_read_cycle(mdbx::txn txn, std::deque<mdbx::map_handle> &dbi, std::vector<MDBX_cursor *> &pool,
mdbx::cursor pre, bool nested = false) {
for (auto c : pool)
mdbx::cursor(c).bind(txn, case1_cycle_dbi(dbi));
pre.bind(txn, case1_cycle_dbi(dbi));
if (nested) {
for (auto c : pool)
try {
mdbx::cursor(c).bind(txn, case1_cycle_dbi(dbi));
} catch (const std::invalid_argument &) {
}
try {
pre.bind(txn, case1_cycle_dbi(dbi));
} catch (const std::invalid_argument &) {
}
} else {
for (auto c : pool)
mdbx::cursor(c).bind(txn, case1_cycle_dbi(dbi));
pre.bind(txn, case1_cycle_dbi(dbi));
}
for (auto n = prng(3 + dbi.size()); n > 0; --n) {
auto c = txn.open_cursor(dbi[prng(dbi.size())]);
@@ -215,6 +227,16 @@ void case1_read_cycle(mdbx::txn txn, std::deque<mdbx::map_handle> &dbi, std::vec
switch (prng(nested ? 7 : 3)) {
case 0:
if (pre.txn()) {
if (nested)
try {
pre.unbind();
} catch (const std::invalid_argument &) {
return;
}
else
pre.unbind();
}
for (auto i = pool.begin(); i != pool.end();)
if (mdbx_cursor_txn(*i))
i = pool.erase(i);
@@ -253,6 +275,8 @@ void case1_write_cycle(mdbx::txn_managed txn, std::deque<mdbx::map_handle> &dbi,
if (prng(16) > 8)
case1_write_cycle(txn.start_nested(), dbi, pool, pre, true);
case1_read_cycle(txn, dbi, pool, pre, nested);
if (flipcoin())
txn.commit();
else
@@ -332,6 +356,27 @@ bool case1(mdbx::env env) {
//--------------------------------------------------------------------------------------------
bool case2(mdbx::env env) {
bool ok = true;
auto txn = env.start_write();
auto dbi = txn.create_map("case2", mdbx::key_mode::usual, mdbx::value_mode::single);
txn.commit_embark_read();
auto cursor1 = txn.open_cursor(dbi);
auto cursor2 = txn.open_cursor(0);
cursor1.move(mdbx::cursor::next, false);
cursor2.move(mdbx::cursor::next, false);
txn.commit_embark_read();
cursor2.bind(txn, dbi);
cursor1.bind(txn, 0);
cursor1.move(mdbx::cursor::last, false);
cursor2.move(mdbx::cursor::last, false);
return ok;
}
//--------------------------------------------------------------------------------------------
int doit() {
mdbx::path db_filename = "test-cursor-closing";
mdbx::env::remove(db_filename);
@@ -341,6 +386,7 @@ int doit() {
bool ok = case0(env);
ok = case1(env) && ok;
ok = case2(env) && ok;
if (ok) {
std::cout << "OK\n";

View File

@@ -510,6 +510,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);