mirror of
https://github.com/isar/libmdbx.git
synced 2025-07-20 15:44:44 +08:00
mdbx: косметический рефакторинг txn_renew()
.
This commit is contained in:
parent
0c70b548e8
commit
e9d47291b0
216
src/txn.c
216
src/txn.c
@ -214,114 +214,116 @@ int txn_renew(MDBX_txn *txn, unsigned flags) {
|
|||||||
if (unlikely(env->flags & ENV_FATAL_ERROR)) {
|
if (unlikely(env->flags & ENV_FATAL_ERROR)) {
|
||||||
WARNING("%s", "environment had fatal error, must shutdown!");
|
WARNING("%s", "environment had fatal error, must shutdown!");
|
||||||
rc = MDBX_PANIC;
|
rc = MDBX_PANIC;
|
||||||
} else {
|
goto bailout;
|
||||||
const size_t size_bytes = pgno2bytes(env, txn->geo.end_pgno);
|
|
||||||
const size_t used_bytes = pgno2bytes(env, txn->geo.first_unallocated);
|
|
||||||
const size_t required_bytes = (txn->flags & MDBX_TXN_RDONLY) ? used_bytes : size_bytes;
|
|
||||||
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
|
||||||
if (unlikely(required_bytes > env->dxb_mmap.current)) {
|
|
||||||
/* Размер БД (для пишущих транзакций) или используемых данных (для
|
|
||||||
* читающих транзакций) больше предыдущего/текущего размера внутри
|
|
||||||
* процесса, увеличиваем. Сюда также попадает случай увеличения верхней
|
|
||||||
* границы размера БД и отображения. В читающих транзакциях нельзя
|
|
||||||
* изменять размер файла, который может быть больше необходимого этой
|
|
||||||
* транзакции. */
|
|
||||||
if (txn->geo.upper > MAX_PAGENO + 1 || bytes2pgno(env, pgno2bytes(env, txn->geo.upper)) != txn->geo.upper) {
|
|
||||||
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
|
|
||||||
goto bailout;
|
|
||||||
}
|
|
||||||
rc = dxb_resize(env, txn->geo.first_unallocated, txn->geo.end_pgno, txn->geo.upper, implicit_grow);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
goto bailout;
|
|
||||||
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
|
||||||
} else if (unlikely(size_bytes < env->dxb_mmap.current)) {
|
|
||||||
/* Размер БД меньше предыдущего/текущего размера внутри процесса, можно
|
|
||||||
* уменьшить, но всё сложнее:
|
|
||||||
* - размер файла согласован со всеми читаемыми снимками на момент
|
|
||||||
* коммита последней транзакции;
|
|
||||||
* - в читающей транзакции размер файла может быть больше и него нельзя
|
|
||||||
* изменять, в том числе менять madvise (меньша размера файла нельзя,
|
|
||||||
* а за размером нет смысла).
|
|
||||||
* - в пишущей транзакции уменьшать размер файла можно только после
|
|
||||||
* проверки размера читаемых снимков, но в этом нет смысла, так как
|
|
||||||
* это будет сделано при фиксации транзакции.
|
|
||||||
*
|
|
||||||
* В сухом остатке, можно только установить dxb_mmap.current равным
|
|
||||||
* размеру файла, а это проще сделать без вызова dxb_resize() и усложения
|
|
||||||
* внутренней логики.
|
|
||||||
*
|
|
||||||
* В этой тактике есть недостаток: если пишущите транзакции не регулярны,
|
|
||||||
* и при завершении такой транзакции файл БД остаётся не-уменьшеным из-за
|
|
||||||
* читающих транзакций использующих предыдущие снимки. */
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
imports.srwl_AcquireShared(&env->remap_guard);
|
|
||||||
#else
|
|
||||||
rc = osal_fastmutex_acquire(&env->remap_guard);
|
|
||||||
#endif
|
|
||||||
if (likely(rc == MDBX_SUCCESS)) {
|
|
||||||
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
|
||||||
rc = osal_filesize(env->dxb_mmap.fd, &env->dxb_mmap.filesize);
|
|
||||||
if (likely(rc == MDBX_SUCCESS)) {
|
|
||||||
eASSERT(env, env->dxb_mmap.filesize >= required_bytes);
|
|
||||||
if (env->dxb_mmap.current > env->dxb_mmap.filesize)
|
|
||||||
env->dxb_mmap.current =
|
|
||||||
(env->dxb_mmap.limit < env->dxb_mmap.filesize) ? env->dxb_mmap.limit : (size_t)env->dxb_mmap.filesize;
|
|
||||||
}
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
imports.srwl_ReleaseShared(&env->remap_guard);
|
|
||||||
#else
|
|
||||||
int err = osal_fastmutex_release(&env->remap_guard);
|
|
||||||
if (unlikely(err) && likely(rc == MDBX_SUCCESS))
|
|
||||||
rc = err;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
goto bailout;
|
|
||||||
}
|
|
||||||
eASSERT(env, pgno2bytes(env, txn->geo.first_unallocated) <= env->dxb_mmap.current);
|
|
||||||
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
|
||||||
if (txn->flags & MDBX_TXN_RDONLY) {
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if (((used_bytes > env->geo_in_bytes.lower && env->geo_in_bytes.shrink) ||
|
|
||||||
(globals.running_under_Wine &&
|
|
||||||
/* under Wine acquisition of remap_guard is always required,
|
|
||||||
* since Wine don't support section extending,
|
|
||||||
* i.e. in both cases unmap+map are required. */
|
|
||||||
used_bytes < env->geo_in_bytes.upper && env->geo_in_bytes.grow)) &&
|
|
||||||
/* avoid recursive use SRW */ (txn->flags & MDBX_NOSTICKYTHREADS) == 0) {
|
|
||||||
txn->flags |= txn_shrink_allowed;
|
|
||||||
imports.srwl_AcquireShared(&env->remap_guard);
|
|
||||||
}
|
|
||||||
#endif /* Windows */
|
|
||||||
} else {
|
|
||||||
tASSERT(txn, txn == env->basal_txn);
|
|
||||||
|
|
||||||
if (env->options.need_dp_limit_adjust)
|
|
||||||
env_options_adjust_dp_limit(env);
|
|
||||||
if ((txn->flags & MDBX_WRITEMAP) == 0 || MDBX_AVOID_MSYNC) {
|
|
||||||
rc = dpl_alloc(txn);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
goto bailout;
|
|
||||||
txn->wr.dirtyroom = txn->env->options.dp_limit;
|
|
||||||
txn->wr.dirtylru = MDBX_DEBUG ? UINT32_MAX / 3 - 42 : 0;
|
|
||||||
} else {
|
|
||||||
tASSERT(txn, txn->wr.dirtylist == nullptr);
|
|
||||||
txn->wr.dirtylist = nullptr;
|
|
||||||
txn->wr.dirtyroom = MAX_PAGENO;
|
|
||||||
txn->wr.dirtylru = 0;
|
|
||||||
}
|
|
||||||
eASSERT(env, txn->wr.writemap_dirty_npages == 0);
|
|
||||||
eASSERT(env, txn->wr.writemap_spilled_npages == 0);
|
|
||||||
|
|
||||||
MDBX_cursor *const gc = ptr_disp(txn, sizeof(MDBX_txn));
|
|
||||||
rc = cursor_init(gc, txn, FREE_DBI);
|
|
||||||
if (rc != MDBX_SUCCESS)
|
|
||||||
goto bailout;
|
|
||||||
tASSERT(txn, txn->cursors[FREE_DBI] == nullptr);
|
|
||||||
}
|
|
||||||
dxb_sanitize_tail(env, txn);
|
|
||||||
return MDBX_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t size_bytes = pgno2bytes(env, txn->geo.end_pgno);
|
||||||
|
const size_t used_bytes = pgno2bytes(env, txn->geo.first_unallocated);
|
||||||
|
const size_t required_bytes = (txn->flags & MDBX_TXN_RDONLY) ? used_bytes : size_bytes;
|
||||||
|
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
||||||
|
if (unlikely(required_bytes > env->dxb_mmap.current)) {
|
||||||
|
/* Размер БД (для пишущих транзакций) или используемых данных (для
|
||||||
|
* читающих транзакций) больше предыдущего/текущего размера внутри
|
||||||
|
* процесса, увеличиваем. Сюда также попадает случай увеличения верхней
|
||||||
|
* границы размера БД и отображения. В читающих транзакциях нельзя
|
||||||
|
* изменять размер файла, который может быть больше необходимого этой
|
||||||
|
* транзакции. */
|
||||||
|
if (txn->geo.upper > MAX_PAGENO + 1 || bytes2pgno(env, pgno2bytes(env, txn->geo.upper)) != txn->geo.upper) {
|
||||||
|
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
|
goto bailout;
|
||||||
|
}
|
||||||
|
rc = dxb_resize(env, txn->geo.first_unallocated, txn->geo.end_pgno, txn->geo.upper, implicit_grow);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
goto bailout;
|
||||||
|
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
||||||
|
} else if (unlikely(size_bytes < env->dxb_mmap.current)) {
|
||||||
|
/* Размер БД меньше предыдущего/текущего размера внутри процесса, можно
|
||||||
|
* уменьшить, но всё сложнее:
|
||||||
|
* - размер файла согласован со всеми читаемыми снимками на момент
|
||||||
|
* коммита последней транзакции;
|
||||||
|
* - в читающей транзакции размер файла может быть больше и него нельзя
|
||||||
|
* изменять, в том числе менять madvise (меньша размера файла нельзя,
|
||||||
|
* а за размером нет смысла).
|
||||||
|
* - в пишущей транзакции уменьшать размер файла можно только после
|
||||||
|
* проверки размера читаемых снимков, но в этом нет смысла, так как
|
||||||
|
* это будет сделано при фиксации транзакции.
|
||||||
|
*
|
||||||
|
* В сухом остатке, можно только установить dxb_mmap.current равным
|
||||||
|
* размеру файла, а это проще сделать без вызова dxb_resize() и усложения
|
||||||
|
* внутренней логики.
|
||||||
|
*
|
||||||
|
* В этой тактике есть недостаток: если пишущите транзакции не регулярны,
|
||||||
|
* и при завершении такой транзакции файл БД остаётся не-уменьшеным из-за
|
||||||
|
* читающих транзакций использующих предыдущие снимки. */
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
imports.srwl_AcquireShared(&env->remap_guard);
|
||||||
|
#else
|
||||||
|
rc = osal_fastmutex_acquire(&env->remap_guard);
|
||||||
|
#endif
|
||||||
|
if (likely(rc == MDBX_SUCCESS)) {
|
||||||
|
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
||||||
|
rc = osal_filesize(env->dxb_mmap.fd, &env->dxb_mmap.filesize);
|
||||||
|
if (likely(rc == MDBX_SUCCESS)) {
|
||||||
|
eASSERT(env, env->dxb_mmap.filesize >= required_bytes);
|
||||||
|
if (env->dxb_mmap.current > env->dxb_mmap.filesize)
|
||||||
|
env->dxb_mmap.current =
|
||||||
|
(env->dxb_mmap.limit < env->dxb_mmap.filesize) ? env->dxb_mmap.limit : (size_t)env->dxb_mmap.filesize;
|
||||||
|
}
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
imports.srwl_ReleaseShared(&env->remap_guard);
|
||||||
|
#else
|
||||||
|
int err = osal_fastmutex_release(&env->remap_guard);
|
||||||
|
if (unlikely(err) && likely(rc == MDBX_SUCCESS))
|
||||||
|
rc = err;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
goto bailout;
|
||||||
|
}
|
||||||
|
eASSERT(env, pgno2bytes(env, txn->geo.first_unallocated) <= env->dxb_mmap.current);
|
||||||
|
eASSERT(env, env->dxb_mmap.limit >= env->dxb_mmap.current);
|
||||||
|
if (txn->flags & MDBX_TXN_RDONLY) {
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
if (((used_bytes > env->geo_in_bytes.lower && env->geo_in_bytes.shrink) ||
|
||||||
|
(globals.running_under_Wine &&
|
||||||
|
/* under Wine acquisition of remap_guard is always required,
|
||||||
|
* since Wine don't support section extending,
|
||||||
|
* i.e. in both cases unmap+map are required. */
|
||||||
|
used_bytes < env->geo_in_bytes.upper && env->geo_in_bytes.grow)) &&
|
||||||
|
/* avoid recursive use SRW */ (txn->flags & MDBX_NOSTICKYTHREADS) == 0) {
|
||||||
|
txn->flags |= txn_shrink_allowed;
|
||||||
|
imports.srwl_AcquireShared(&env->remap_guard);
|
||||||
|
}
|
||||||
|
#endif /* Windows */
|
||||||
|
} else {
|
||||||
|
tASSERT(txn, txn == env->basal_txn);
|
||||||
|
|
||||||
|
if (env->options.need_dp_limit_adjust)
|
||||||
|
env_options_adjust_dp_limit(env);
|
||||||
|
if ((txn->flags & MDBX_WRITEMAP) == 0 || MDBX_AVOID_MSYNC) {
|
||||||
|
rc = dpl_alloc(txn);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
goto bailout;
|
||||||
|
txn->wr.dirtyroom = txn->env->options.dp_limit;
|
||||||
|
txn->wr.dirtylru = MDBX_DEBUG ? UINT32_MAX / 3 - 42 : 0;
|
||||||
|
} else {
|
||||||
|
tASSERT(txn, txn->wr.dirtylist == nullptr);
|
||||||
|
txn->wr.dirtylist = nullptr;
|
||||||
|
txn->wr.dirtyroom = MAX_PAGENO;
|
||||||
|
txn->wr.dirtylru = 0;
|
||||||
|
}
|
||||||
|
eASSERT(env, txn->wr.writemap_dirty_npages == 0);
|
||||||
|
eASSERT(env, txn->wr.writemap_spilled_npages == 0);
|
||||||
|
|
||||||
|
MDBX_cursor *const gc = ptr_disp(txn, sizeof(MDBX_txn));
|
||||||
|
rc = cursor_init(gc, txn, FREE_DBI);
|
||||||
|
if (rc != MDBX_SUCCESS)
|
||||||
|
goto bailout;
|
||||||
|
tASSERT(txn, txn->cursors[FREE_DBI] == nullptr);
|
||||||
|
}
|
||||||
|
dxb_sanitize_tail(env, txn);
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
tASSERT(txn, rc != MDBX_SUCCESS);
|
tASSERT(txn, rc != MDBX_SUCCESS);
|
||||||
txn_end(txn, TXN_END_SLOT | TXN_END_FAIL_BEGIN);
|
txn_end(txn, TXN_END_SLOT | TXN_END_FAIL_BEGIN);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user