mirror of
https://github.com/isar/libmdbx.git
synced 2025-02-02 05:58:22 +08:00
mdbx: refine mdbx_is_dirty().
This commit is contained in:
parent
d5b0e68326
commit
009618560f
35
src/mdbx.c
35
src/mdbx.c
@ -10257,38 +10257,45 @@ int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
|
|||||||
* что было исходно задумано, детали см в логике кода mdbx_page_touch().
|
* что было исходно задумано, детали см в логике кода mdbx_page_touch().
|
||||||
*
|
*
|
||||||
* Более того, в режиме БЕЗ WRITEMAP грязные страницы выделяются через
|
* Более того, в режиме БЕЗ WRITEMAP грязные страницы выделяются через
|
||||||
* malloc(), т.е. находятся вне mmap-диапазона.
|
* malloc(), т.е. находятся вне mmap-диапазона и тогда чтобы отличить
|
||||||
|
* действительно грязную страницу от указателя на данные пользователя
|
||||||
|
* следует сканировать dirtylist, что накладно.
|
||||||
*
|
*
|
||||||
* Тем не менее, однозначно страница "не грязная" если адрес находится
|
* Тем не менее, однозначно страница "не грязная" (не будет переписана
|
||||||
* внутри mmap-диапазона и в заголовке страницы нет флажка P_DIRTY. */
|
* во время транзакции) если адрес находится внутри mmap-диапазона
|
||||||
|
* и в заголовке страницы нет флажка P_DIRTY. */
|
||||||
if (env->me_map < (char *)page) {
|
if (env->me_map < (char *)page) {
|
||||||
const size_t used_size = env->me_psize * txn->mt_next_pgno;
|
const size_t used_size = env->me_psize * txn->mt_next_pgno;
|
||||||
if ((char *)page < env->me_map + used_size) {
|
if ((char *)page < env->me_map + used_size) {
|
||||||
/* страница внутри диапазона, смотрим на флажки */
|
/* страница внутри диапазона, смотрим на флажки */
|
||||||
if ((page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP)) == 0)
|
return (page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP))
|
||||||
return MDBX_RESULT_FALSE;
|
? MDBX_RESULT_TRUE
|
||||||
|
: MDBX_RESULT_FALSE;
|
||||||
}
|
}
|
||||||
/* Гипотетически здесь возможна ситуация, когда указатель адресует что-то
|
/* Гипотетически здесь возможна ситуация, когда указатель адресует что-то
|
||||||
* в пределах mmap, но за границей распределенных страниц. Это тяжелая
|
* в пределах mmap, но за границей распределенных страниц. Это тяжелая
|
||||||
* ошибка, к которой не возможно прийти без каких-то больших нарушений.
|
* ошибка, к которой не возможно прийти без каких-то больших нарушений.
|
||||||
* Поэтому не проверяем этот случай кроме как assert-ом, ибо бестолку. */
|
* Поэтому не проверяем этот случай кроме как assert-ом, на то что
|
||||||
/* if (!RUNNING_ON_VALGRIND)
|
* страница вне mmap-диаппазона. */
|
||||||
mdbx_tassert(txn, env->me_map + env->me_mapsize >= (char *)page); */
|
mdbx_tassert(txn, (char *)page >= env->me_map + env->me_mapsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Страница вне используемого mmap-диапазона, т.е. либо в функцию был
|
/* Страница вне используемого mmap-диапазона, т.е. либо в функцию был
|
||||||
* передан некорректный адрес, либо адрес в теневой странице, которая была
|
* передан некорректный адрес, либо адрес в теневой странице, которая была
|
||||||
* выделена посредством malloc().
|
* выделена посредством malloc().
|
||||||
*
|
*
|
||||||
* Поэтому всегда считаем что страница вне mmap-диапазона "грязная",
|
* Для WRITE_MAP режима такая страница однозначно "не грязная",
|
||||||
* не просматривая при этом списки грязных и spilled страниц у каких-либо
|
* а для режимов без 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,
|
int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user