diff --git a/src/mdbx.c b/src/mdbx.c index 16294080..6e204553 100644 --- a/src/mdbx.c +++ b/src/mdbx.c @@ -10257,38 +10257,45 @@ int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) { * что было исходно задумано, детали см в логике кода mdbx_page_touch(). * * Более того, в режиме БЕЗ WRITEMAP грязные страницы выделяются через - * malloc(), т.е. находятся вне mmap-диапазона. + * malloc(), т.е. находятся вне mmap-диапазона и тогда чтобы отличить + * действительно грязную страницу от указателя на данные пользователя + * следует сканировать dirtylist, что накладно. * - * Тем не менее, однозначно страница "не грязная" если адрес находится - * внутри mmap-диапазона и в заголовке страницы нет флажка P_DIRTY. */ + * Тем не менее, однозначно страница "не грязная" (не будет переписана + * во время транзакции) если адрес находится внутри mmap-диапазона + * и в заголовке страницы нет флажка P_DIRTY. */ if (env->me_map < (char *)page) { const size_t used_size = env->me_psize * txn->mt_next_pgno; if ((char *)page < env->me_map + used_size) { - /* страница внутри диапазона, смотрим на флажки */ - if ((page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP)) == 0) - return MDBX_RESULT_FALSE; + /* страница внутри диапазона, смотрим на флажки */ + return (page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP)) + ? MDBX_RESULT_TRUE + : MDBX_RESULT_FALSE; } /* Гипотетически здесь возможна ситуация, когда указатель адресует что-то * в пределах mmap, но за границей распределенных страниц. Это тяжелая * ошибка, к которой не возможно прийти без каких-то больших нарушений. - * Поэтому не проверяем этот случай кроме как assert-ом, ибо бестолку. */ - /* if (!RUNNING_ON_VALGRIND) - mdbx_tassert(txn, env->me_map + env->me_mapsize >= (char *)page); */ + * Поэтому не проверяем этот случай кроме как assert-ом, на то что + * страница вне mmap-диаппазона. */ + mdbx_tassert(txn, (char *)page >= env->me_map + env->me_mapsize); } /* Страница вне используемого mmap-диапазона, т.е. либо в функцию был * передан некорректный адрес, либо адрес в теневой странице, которая была * выделена посредством malloc(). * - * Поэтому всегда считаем что страница вне mmap-диапазона "грязная", - * не просматривая при этом списки грязных и spilled страниц у каких-либо - * транзакций. Такая логика имеет ряд преимуществ: + * Для WRITE_MAP режима такая страница однозначно "не грязная", + * а для режимов без WRITE_MAP следует просматривать списки dirty + * и spilled страниц у каких-либо транзакций (в том числе дочерних). + * + * Поэтому для WRITE_MAP возвращаем false, а для остальных режимов + * всегда true. Такая логика имеет ряд преимуществ: * - не тратим время на просмотр списков; - * - результат всегда безопасен (может быть ложно-положительным, но - * не ложно-отрицательным); + * - результат всегда безопасен (может быть ложно-положительным, + * но не ложно-отрицательным); * - результат не зависит от вложенности транзакций и от относительного * положения переданной транзакции в этой рекурсии. */ - return MDBX_RESULT_TRUE; + return (env->me_flags & MDBX_WRITEMAP) ? MDBX_RESULT_FALSE : MDBX_RESULT_TRUE; } int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,