mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-29 23:19:20 +08:00
mdbx: add MDBX_ACCEDE environment opening flag.
Change-Id: If0a08d6fce127f35ff2992988715b7dc1fdb70a9
This commit is contained in:
parent
cb8fac6f5f
commit
42d9e06598
16
mdbx.h
16
mdbx.h
@ -921,6 +921,22 @@ LIBMDBX_API const char *mdbx_dump_val(const MDBX_val *key, char *const buf,
|
||||
* This flag affects only at environment opening but can't be changed after. */
|
||||
#define MDBX_EXCLUSIVE 0x400000u
|
||||
|
||||
/* MDBX_ACCEDE = using database which already opened by another process(es).
|
||||
*
|
||||
* The MDBX_ACCEDE flag avoid MDBX_INCOMPATIBLE error while opening If the
|
||||
* database is already used by another process(es) and environment mode/flags
|
||||
* isn't compatible. In such cases, when using the MDBX_ACCEDE flag, instead of
|
||||
* the specified incompatible options, the mode in which the database is already
|
||||
* opened by other processes will be used, including MDBX_LIFORECLAIM,
|
||||
* MDBX_COALESCE and MDBX_NORDAHEAD. The MDBX_ACCEDE flag is useful to open a
|
||||
* database that already used by another process(es) and used mode/flags isn't
|
||||
* known.
|
||||
*
|
||||
* MDBX_ACCEDE has no effect if the current process is the only one either
|
||||
* opening the DB in read-only mode or other process(es) uses the DB in
|
||||
* read-only mode. */
|
||||
#define MDBX_ACCEDE 0x40000000u
|
||||
|
||||
/* MDBX_WRITEMAP = map data into memory with write permission.
|
||||
*
|
||||
* Use a writeable memory map unless MDBX_RDONLY is set. This uses fewer mallocs
|
||||
|
@ -4666,6 +4666,8 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
||||
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE ==
|
||||
0);
|
||||
|
||||
mdbx_assert(env, (flags & ~(MDBX_TXN_BEGIN_FLAGS | MDBX_TXN_SPILLS |
|
||||
MDBX_WRITEMAP)) == 0);
|
||||
if (flags & MDBX_RDONLY) {
|
||||
txn->mt_flags = MDBX_RDONLY | (env->me_flags & MDBX_NOTLS);
|
||||
MDBX_reader *r = txn->to.reader;
|
||||
@ -5018,8 +5020,7 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
|
||||
return MDBX_EPERM;
|
||||
#endif /* Windows */
|
||||
|
||||
flags |= parent->mt_flags &
|
||||
(MDBX_TXN_BEGIN_FLAGS | MDBX_SHRINK_ALLOWED | MDBX_TXN_SPILLS);
|
||||
flags |= parent->mt_flags & (MDBX_TXN_BEGIN_FLAGS | MDBX_TXN_SPILLS);
|
||||
/* Child txns save MDBX_pgstate and use own copy of cursors */
|
||||
size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1);
|
||||
size += tsize = sizeof(MDBX_txn);
|
||||
@ -6515,7 +6516,7 @@ int mdbx_txn_commit(MDBX_txn *txn) {
|
||||
|
||||
parent->mt_geo = txn->mt_geo;
|
||||
parent->mt_canary = txn->mt_canary;
|
||||
parent->mt_flags = txn->mt_flags;
|
||||
parent->mt_flags = txn->mt_flags | (parent->mt_flags & MDBX_SHRINK_ALLOWED);
|
||||
|
||||
/* Merge our cursors into parent's and close them */
|
||||
mdbx_cursors_eot(txn, 1);
|
||||
@ -8660,7 +8661,7 @@ __cold int mdbx_is_readahead_reasonable(size_t volume, intptr_t redundancy) {
|
||||
* environment and re-opening it with the new flags. */
|
||||
#define CHANGEABLE \
|
||||
(MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC | MDBX_NOMEMINIT | \
|
||||
MDBX_COALESCE | MDBX_PAGEPERTURB)
|
||||
MDBX_COALESCE | MDBX_PAGEPERTURB | MDBX_ACCEDE)
|
||||
#define CHANGELESS \
|
||||
(MDBX_NOSUBDIR | MDBX_RDONLY | MDBX_WRITEMAP | MDBX_NOTLS | MDBX_NORDAHEAD | \
|
||||
MDBX_LIFORECLAIM | MDBX_EXCLUSIVE)
|
||||
@ -8711,17 +8712,21 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
|
||||
/* LY: silently ignore irrelevant flags when
|
||||
* we're only getting read access */
|
||||
flags &= ~(MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOSYNC | MDBX_NOMETASYNC |
|
||||
MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT);
|
||||
MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT | MDBX_ACCEDE);
|
||||
} else {
|
||||
#ifdef __OpenBSD__
|
||||
/* Temporary `workaround` for OpenBSD kernel's bug.
|
||||
* See https://github.com/leo-yuriev/libmdbx/issues/67 */
|
||||
if ((flags & MDBX_WRITEMAP) == 0) {
|
||||
mdbx_debug_log(MDBX_LOG_ERROR, __func__, __LINE__,
|
||||
"OpenBSD requires MDBX_WRITEMAP because of an internal "
|
||||
"bug(s) in a file/buffer/page cache.\n");
|
||||
rc = 42 /* ENOPROTOOPT */;
|
||||
goto bailout;
|
||||
if (flags & MDBX_ACCEDE)
|
||||
flags |= MDBX_WRITEMAP;
|
||||
else {
|
||||
mdbx_debug_log(MDBX_LOG_ERROR, __func__, __LINE__,
|
||||
"OpenBSD requires MDBX_WRITEMAP because of an internal "
|
||||
"bug(s) in a file/buffer/page cache.\n");
|
||||
rc = 42 /* ENOPROTOOPT */;
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
#endif /* __OpenBSD__ */
|
||||
env->me_dirtylist = mdbx_calloc(MDBX_DPL_TXNFULL + 1, sizeof(MDBX_DP));
|
||||
@ -8793,6 +8798,36 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
const unsigned rigorous_flags = MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_MAPASYNC;
|
||||
const unsigned mode_flags = rigorous_flags | MDBX_NOMETASYNC |
|
||||
MDBX_LIFORECLAIM | MDBX_COALESCE | MDBX_NORDAHEAD;
|
||||
|
||||
if (env->me_lck && lck_rc != MDBX_RESULT_TRUE &&
|
||||
(env->me_flags & MDBX_RDONLY) == 0) {
|
||||
while (env->me_lck->mti_envmode == MDBX_RDONLY) {
|
||||
if (atomic_cas32(&env->me_lck->mti_envmode, MDBX_RDONLY,
|
||||
env->me_flags & mode_flags))
|
||||
break;
|
||||
atomic_yield();
|
||||
}
|
||||
|
||||
if (env->me_flags & MDBX_ACCEDE) {
|
||||
/* pickup current mode-flags, including MDBX_LIFORECLAIM |
|
||||
* MDBX_COALESCE | MDBX_NORDAHEAD */
|
||||
const unsigned diff =
|
||||
(env->me_lck->mti_envmode ^ env->me_flags) & mode_flags;
|
||||
mdbx_notice("accede mode-flags: 0x%X, 0x%X -> 0x%X", diff, env->me_flags,
|
||||
env->me_flags ^ diff);
|
||||
env->me_flags ^= diff;
|
||||
}
|
||||
|
||||
if ((env->me_lck->mti_envmode ^ env->me_flags) & rigorous_flags) {
|
||||
mdbx_error("%s", "current mode/flags incompatible with requested");
|
||||
rc = MDBX_INCOMPATIBLE;
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
|
||||
const int dxb_rc = mdbx_setup_dxb(env, lck_rc);
|
||||
if (MDBX_IS_ERROR(dxb_rc)) {
|
||||
rc = dxb_rc;
|
||||
@ -8801,8 +8836,6 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
|
||||
|
||||
mdbx_debug("opened dbenv %p", (void *)env);
|
||||
if (env->me_lck) {
|
||||
const unsigned mode_flags =
|
||||
MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC;
|
||||
if (lck_rc == MDBX_RESULT_TRUE) {
|
||||
env->me_lck->mti_envmode = env->me_flags & (mode_flags | MDBX_RDONLY);
|
||||
rc = mdbx_lck_downgrade(env);
|
||||
@ -8814,19 +8847,6 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
|
||||
rc = mdbx_reader_check0(env, false, NULL);
|
||||
if (MDBX_IS_ERROR(rc))
|
||||
goto bailout;
|
||||
if ((env->me_flags & MDBX_RDONLY) == 0) {
|
||||
while (env->me_lck->mti_envmode == MDBX_RDONLY) {
|
||||
if (atomic_cas32(&env->me_lck->mti_envmode, MDBX_RDONLY,
|
||||
env->me_flags & mode_flags))
|
||||
break;
|
||||
atomic_yield();
|
||||
}
|
||||
if ((env->me_lck->mti_envmode ^ env->me_flags) & mode_flags) {
|
||||
mdbx_error("%s", "current mode/flags incompatible with requested");
|
||||
rc = MDBX_INCOMPATIBLE;
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((env->me_flags & MDBX_NOTLS) == 0) {
|
||||
|
@ -968,7 +968,7 @@ int main(int argc, char *argv[]) {
|
||||
envflags &= ~MDBX_RDONLY;
|
||||
break;
|
||||
case 'c':
|
||||
envflags &= ~MDBX_EXCLUSIVE;
|
||||
envflags = (envflags & ~MDBX_EXCLUSIVE) | MDBX_ACCEDE;
|
||||
break;
|
||||
case 'd':
|
||||
dont_traversal = true;
|
||||
@ -1031,7 +1031,7 @@ int main(int argc, char *argv[]) {
|
||||
#endif
|
||||
)) {
|
||||
envflags &= ~MDBX_EXCLUSIVE;
|
||||
rc = mdbx_env_open(env, envname, envflags, 0664);
|
||||
rc = mdbx_env_open(env, envname, envflags | MDBX_ACCEDE, 0664);
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
|
@ -294,14 +294,21 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const struct option_verb mode_bits[] = {
|
||||
{"rdonly", MDBX_RDONLY}, {"mapasync", MDBX_MAPASYNC},
|
||||
{"utterly", MDBX_UTTERLY_NOSYNC}, {"nosubdir", MDBX_NOSUBDIR},
|
||||
{"nosync", MDBX_NOSYNC}, {"nometasync", MDBX_NOMETASYNC},
|
||||
{"writemap", MDBX_WRITEMAP}, {"notls", MDBX_NOTLS},
|
||||
{"nordahead", MDBX_NORDAHEAD}, {"nomeminit", MDBX_NOMEMINIT},
|
||||
{"coalesce", MDBX_COALESCE}, {"lifo", MDBX_LIFORECLAIM},
|
||||
{"perturb", MDBX_PAGEPERTURB}, {nullptr, 0}};
|
||||
const struct option_verb mode_bits[] = {{"rdonly", MDBX_RDONLY},
|
||||
{"mapasync", MDBX_MAPASYNC},
|
||||
{"utterly", MDBX_UTTERLY_NOSYNC},
|
||||
{"nosubdir", MDBX_NOSUBDIR},
|
||||
{"nosync", MDBX_NOSYNC},
|
||||
{"nometasync", MDBX_NOMETASYNC},
|
||||
{"writemap", MDBX_WRITEMAP},
|
||||
{"notls", MDBX_NOTLS},
|
||||
{"nordahead", MDBX_NORDAHEAD},
|
||||
{"nomeminit", MDBX_NOMEMINIT},
|
||||
{"coalesce", MDBX_COALESCE},
|
||||
{"lifo", MDBX_LIFORECLAIM},
|
||||
{"perturb", MDBX_PAGEPERTURB},
|
||||
{"accede", MDBX_ACCEDE},
|
||||
{nullptr, 0}};
|
||||
|
||||
const struct option_verb table_bits[] = {
|
||||
{"key.reverse", MDBX_REVERSEKEY},
|
||||
|
@ -124,7 +124,7 @@ void actor_params::set_defaults(const std::string &tmpdir) {
|
||||
|
||||
pathname_db = tmpdir + "mdbx-test.db";
|
||||
mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOMEMINIT |
|
||||
MDBX_COALESCE | MDBX_LIFORECLAIM;
|
||||
MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_ACCEDE;
|
||||
table_flags = MDBX_DUPSORT;
|
||||
|
||||
size_lower = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user