mdbx: truncate clk-file when DB closed in sync-state.

Change-Id: I2e2438606118e3aa3fa9d60811fea99994403d32
This commit is contained in:
Leonid Yuriev 2020-05-20 13:31:04 +03:00
parent 86a4085bf9
commit a2bdbc97dc
2 changed files with 73 additions and 32 deletions

View File

@ -477,8 +477,10 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_destroy(MDBX_env *env,
mdbx_assert(env, rc == 0);
if (rc == 0) {
const bool synced = env->me_lck_mmap.lck->mti_unsynced_pages == 0;
mdbx_munmap(&env->me_lck_mmap);
rc = ftruncate(env->me_lfd, 0) ? errno : 0;
if (synced)
rc = ftruncate(env->me_lfd, 0) ? errno : 0;
}
mdbx_jitter4testing(false);

View File

@ -344,13 +344,6 @@ mdbx_resume_threads_after_remap(mdbx_handle_array_t *array) {
* i.e. free/shared/exclusive x free/shared/exclusive == 9.
* Only 6 states of FSM are used, which 2 of ones are transitive.
*
* The mdbx_lck_seize() moves the locking-FSM from the initial free/unlocked
* state to the "exclusive write" (and returns MDBX_RESULT_TRUE) if possible,
* or to the "used" (and returns MDBX_RESULT_FALSE).
*
* The mdbx_lck_downgrade() moves the locking-FSM from "exclusive write"
* state to the "used" (i.e. shared) state.
*
* States:
* ?-? = free, i.e. unlocked
* S-? = used, i.e. shared lock
@ -361,6 +354,16 @@ mdbx_resume_threads_after_remap(mdbx_handle_array_t *array) {
* S-E = locked (transitive state)
* E-S
* E-E = exclusive-write, i.e. exclusive due (re)initialization
*
* The mdbx_lck_seize() moves the locking-FSM from the initial free/unlocked
* state to the "exclusive write" (and returns MDBX_RESULT_TRUE) if possible,
* or to the "used" (and returns MDBX_RESULT_FALSE).
*
* The mdbx_lck_downgrade() moves the locking-FSM from "exclusive write"
* state to the "used" (i.e. shared) state.
*
* The mdbx_lck_upgrade() moves the locking-FSM from "used" (i.e. shared)
* state to the "exclusive write" state.
*/
static void lck_unlock(MDBX_env *env) {
@ -406,30 +409,6 @@ static void lck_unlock(MDBX_env *env) {
}
}
MDBX_INTERNAL_FUNC int mdbx_lck_init(MDBX_env *env,
MDBX_env *inprocess_neighbor,
int global_uniqueness_flag) {
(void)env;
(void)inprocess_neighbor;
(void)global_uniqueness_flag;
return MDBX_SUCCESS;
}
MDBX_INTERNAL_FUNC int mdbx_lck_destroy(MDBX_env *env,
MDBX_env *inprocess_neighbor) {
(void)inprocess_neighbor;
/* LY: should unmap before releasing the locks to avoid race condition and
* STATUS_USER_MAPPED_FILE/ERROR_USER_MAPPED_FILE */
if (env->me_map)
mdbx_munmap(&env->me_dxb_mmap);
if (env->me_lck)
mdbx_munmap(&env->me_lck_mmap);
lck_unlock(env);
return MDBX_SUCCESS;
}
/* Seize state as 'exclusive-write' (E-E and returns MDBX_RESULT_TRUE)
* or as 'used' (S-? and returns MDBX_RESULT_FALSE).
* Oherwise returns an error. */
@ -553,6 +532,66 @@ MDBX_INTERNAL_FUNC int mdbx_lck_downgrade(MDBX_env *env) {
return MDBX_SUCCESS /* 5) now at S-? (used), done */;
}
MDBX_INTERNAL_FUNC int mdbx_lck_upgrade(MDBX_env *env) {
/* Transite from used state (S-?) to exclusive-write (E-E) */
assert(env->me_lfd != INVALID_HANDLE_VALUE);
if (env->me_flags & MDBX_EXCLUSIVE)
return MDBX_SUCCESS /* nope since files were must be opened non-shareable */
;
int rc;
/* 1) now on S-? (used), try S-E (locked) */
mdbx_jitter4testing(false);
if (!flock(env->me_lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_UPPER)) {
rc = GetLastError() /* 2) something went wrong, give up */;
mdbx_verbose("%s, err %u", "S-?(used) >> S-E(locked)", rc);
return rc;
}
/* 3) now on S-E (locked), transite to ?-E (middle) */
if (!funlock(env->me_lfd, LCK_LOWER))
mdbx_panic("%s(%s) failed: err %u", __func__, "S-E(locked) >> ?-E(middle)",
GetLastError());
/* 4) now on ?-E (middle), try E-E (exclusive-write) */
mdbx_jitter4testing(false);
if (!flock(env->me_lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER)) {
rc = GetLastError() /* 5) something went wrong, give up */;
mdbx_verbose("%s, err %u", "?-E(middle) >> E-E(exclusive-write)", rc);
return rc;
}
return MDBX_SUCCESS /* 6) now at E-E (exclusive-write), done */;
}
MDBX_INTERNAL_FUNC int mdbx_lck_init(MDBX_env *env,
MDBX_env *inprocess_neighbor,
int global_uniqueness_flag) {
(void)env;
(void)inprocess_neighbor;
(void)global_uniqueness_flag;
return MDBX_SUCCESS;
}
MDBX_INTERNAL_FUNC int mdbx_lck_destroy(MDBX_env *env,
MDBX_env *inprocess_neighbor) {
/* LY: should unmap before releasing the locks to avoid race condition and
* STATUS_USER_MAPPED_FILE/ERROR_USER_MAPPED_FILE */
if (env->me_map)
mdbx_munmap(&env->me_dxb_mmap);
if (env->me_lck) {
const bool synced = env->me_lck_mmap.lck->mti_unsynced_pages == 0;
mdbx_munmap(&env->me_lck_mmap);
if (synced && !inprocess_neighbor && env->me_lfd != INVALID_HANDLE_VALUE &&
mdbx_lck_upgrade(env) == MDBX_SUCCESS)
/* this will fail if LCK is used/mmapped by other process(es) */
mdbx_ftruncate(env->me_lfd, 0);
}
lck_unlock(env);
return MDBX_SUCCESS;
}
/*----------------------------------------------------------------------------*/
/* reader checking (by pid) */