mdbx: добавление mdbx_env_resurrect_after_fork() в API.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2023-11-11 20:08:04 +03:00
parent a22ec56938
commit af4dfe541b
2 changed files with 78 additions and 36 deletions

5
mdbx.h
View File

@ -2895,6 +2895,11 @@ LIBMDBX_INLINE_API(int, mdbx_env_close, (MDBX_env * env)) {
return mdbx_env_close_ex(env, false); return mdbx_env_close_ex(env, false);
} }
#if !(defined(_WIN32) || defined(_WIN64))
/** FIXME */
LIBMDBX_API int mdbx_env_resurrect_after_fork(MDBX_env *env);
#endif /* Windows */
/** \brief Warming up options /** \brief Warming up options
* \ingroup c_settings * \ingroup c_settings
* \anchor warmup_flags * \anchor warmup_flags

View File

@ -3317,7 +3317,7 @@ static int __must_check_result read_header(MDBX_env *env, MDBX_meta *meta,
static int __must_check_result sync_locked(MDBX_env *env, unsigned flags, static int __must_check_result sync_locked(MDBX_env *env, unsigned flags,
MDBX_meta *const pending, MDBX_meta *const pending,
meta_troika_t *const troika); meta_troika_t *const troika);
static int env_close(MDBX_env *env); static int env_close(MDBX_env *env, bool resurrect_after_fork);
struct node_result { struct node_result {
MDBX_node *node; MDBX_node *node;
@ -15668,7 +15668,7 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname,
#endif /* ENABLE_MEMCHECK || __SANITIZE_ADDRESS__ */ #endif /* ENABLE_MEMCHECK || __SANITIZE_ADDRESS__ */
} else { } else {
bailout: bailout:
if (likely(env_close(env) == MDBX_SUCCESS)) { if (likely(env_close(env, false) == MDBX_SUCCESS)) {
env->me_flags = saved_me_flags; env->me_flags = saved_me_flags;
} else { } else {
rc = MDBX_PANIC; rc = MDBX_PANIC;
@ -15679,7 +15679,7 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname,
} }
/* Destroy resources from mdbx_env_open(), clear our readers & DBIs */ /* Destroy resources from mdbx_env_open(), clear our readers & DBIs */
__cold static int env_close(MDBX_env *env) { __cold static int env_close(MDBX_env *env, bool resurrect_after_fork) {
const unsigned flags = env->me_flags; const unsigned flags = env->me_flags;
env->me_flags &= ~ENV_INTERNAL_FLAGS; env->me_flags &= ~ENV_INTERNAL_FLAGS;
if (flags & MDBX_ENV_TXKEY) { if (flags & MDBX_ENV_TXKEY) {
@ -15724,6 +15724,7 @@ __cold static int env_close(MDBX_env *env) {
CloseHandle(env->me_data_lock_event); CloseHandle(env->me_data_lock_event);
env->me_data_lock_event = INVALID_HANDLE_VALUE; env->me_data_lock_event = INVALID_HANDLE_VALUE;
} }
eASSERT(env, !resurrect_after_fork);
if (env->me_pathname_char) { if (env->me_pathname_char) {
osal_free(env->me_pathname_char); osal_free(env->me_pathname_char);
env->me_pathname_char = nullptr; env->me_pathname_char = nullptr;
@ -15745,43 +15746,79 @@ __cold static int env_close(MDBX_env *env) {
env->me_lfd = INVALID_HANDLE_VALUE; env->me_lfd = INVALID_HANDLE_VALUE;
} }
if (env->me_dbxs) { if (!resurrect_after_fork) {
for (size_t i = CORE_DBS; i < env->me_numdbs; ++i) if (env->me_dbxs) {
if (env->me_dbxs[i].md_name.iov_len) for (size_t i = CORE_DBS; i < env->me_numdbs; ++i)
osal_free(env->me_dbxs[i].md_name.iov_base); if (env->me_dbxs[i].md_name.iov_len)
osal_free(env->me_dbxs); osal_free(env->me_dbxs[i].md_name.iov_base);
env->me_numdbs = CORE_DBS; osal_free(env->me_dbxs);
env->me_dbxs = nullptr; env->me_numdbs = CORE_DBS;
} env->me_dbxs = nullptr;
if (env->me_pbuf) { }
osal_memalign_free(env->me_pbuf); if (env->me_pbuf) {
env->me_pbuf = nullptr; osal_memalign_free(env->me_pbuf);
} env->me_pbuf = nullptr;
if (env->me_dbi_seqs) { }
osal_free(env->me_dbi_seqs); if (env->me_dbi_seqs) {
env->me_dbi_seqs = nullptr; osal_free(env->me_dbi_seqs);
} env->me_dbi_seqs = nullptr;
if (env->me_db_flags) { }
osal_free(env->me_db_flags); if (env->me_db_flags) {
env->me_db_flags = nullptr; osal_free(env->me_db_flags);
} env->me_db_flags = nullptr;
if (env->me_pathname.buffer) { }
osal_free(env->me_pathname.buffer); if (env->me_pathname.buffer) {
env->me_pathname.buffer = nullptr; osal_free(env->me_pathname.buffer);
} env->me_pathname.buffer = nullptr;
if (env->me_txn0) { }
dpl_free(env->me_txn0); if (env->me_txn0) {
txl_free(env->me_txn0->tw.lifo_reclaimed); dpl_free(env->me_txn0);
pnl_free(env->me_txn0->tw.retired_pages); txl_free(env->me_txn0->tw.lifo_reclaimed);
pnl_free(env->me_txn0->tw.spilled.list); pnl_free(env->me_txn0->tw.retired_pages);
pnl_free(env->me_txn0->tw.relist); pnl_free(env->me_txn0->tw.spilled.list);
osal_free(env->me_txn0); pnl_free(env->me_txn0->tw.relist);
env->me_txn0 = nullptr; osal_free(env->me_txn0);
env->me_txn0 = nullptr;
}
} }
env->me_stuck_meta = -1; env->me_stuck_meta = -1;
return rc; return rc;
} }
#if !(defined(_WIN32) || defined(_WIN64))
__cold int mdbx_env_resurrect_after_fork(MDBX_env *env) {
if (unlikely(!env))
return MDBX_EINVAL;
if (unlikely(env->me_signature.weak != MDBX_ME_SIGNATURE))
return MDBX_EBADSIGN;
if (unlikely(env->me_flags & MDBX_FATAL_ERROR))
return MDBX_PANIC;
const uint32_t new_pid = osal_getpid();
if (unlikely(env->me_pid == new_pid))
return MDBX_SUCCESS;
if (!atomic_cas32(&env->me_signature, MDBX_ME_SIGNATURE, ~MDBX_ME_SIGNATURE))
return MDBX_EBADSIGN;
if (env->me_txn)
txn_abort(env->me_txn0);
env->me_live_reader = 0;
int rc = env_close(env, true);
env->me_signature.weak = MDBX_ME_SIGNATURE;
if (likely(rc == MDBX_SUCCESS)) {
rc = env_open(env, 0);
if (unlikely(rc != MDBX_SUCCESS && env_close(env, false) != MDBX_SUCCESS)) {
rc = MDBX_PANIC;
env->me_flags |= MDBX_FATAL_ERROR;
}
}
return rc;
}
#endif /* Windows */
__cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) { __cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) {
MDBX_page *dp; MDBX_page *dp;
int rc = MDBX_SUCCESS; int rc = MDBX_SUCCESS;
@ -15834,7 +15871,7 @@ __cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) {
} }
eASSERT(env, env->me_signature.weak == 0); eASSERT(env, env->me_signature.weak == 0);
rc = env_close(env) ? MDBX_PANIC : rc; rc = env_close(env, false) ? MDBX_PANIC : rc;
ENSURE(env, osal_fastmutex_destroy(&env->me_dbi_lock) == MDBX_SUCCESS); ENSURE(env, osal_fastmutex_destroy(&env->me_dbi_lock) == MDBX_SUCCESS);
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
/* me_remap_guard don't have destructor (Slim Reader/Writer Lock) */ /* me_remap_guard don't have destructor (Slim Reader/Writer Lock) */