mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-06 19:04:12 +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. */
|
* This flag affects only at environment opening but can't be changed after. */
|
||||||
#define MDBX_EXCLUSIVE 0x400000u
|
#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.
|
/* MDBX_WRITEMAP = map data into memory with write permission.
|
||||||
*
|
*
|
||||||
* Use a writeable memory map unless MDBX_RDONLY is set. This uses fewer mallocs
|
* 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 ==
|
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE ==
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
mdbx_assert(env, (flags & ~(MDBX_TXN_BEGIN_FLAGS | MDBX_TXN_SPILLS |
|
||||||
|
MDBX_WRITEMAP)) == 0);
|
||||||
if (flags & MDBX_RDONLY) {
|
if (flags & MDBX_RDONLY) {
|
||||||
txn->mt_flags = MDBX_RDONLY | (env->me_flags & MDBX_NOTLS);
|
txn->mt_flags = MDBX_RDONLY | (env->me_flags & MDBX_NOTLS);
|
||||||
MDBX_reader *r = txn->to.reader;
|
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;
|
return MDBX_EPERM;
|
||||||
#endif /* Windows */
|
#endif /* Windows */
|
||||||
|
|
||||||
flags |= parent->mt_flags &
|
flags |= parent->mt_flags & (MDBX_TXN_BEGIN_FLAGS | MDBX_TXN_SPILLS);
|
||||||
(MDBX_TXN_BEGIN_FLAGS | MDBX_SHRINK_ALLOWED | MDBX_TXN_SPILLS);
|
|
||||||
/* Child txns save MDBX_pgstate and use own copy of cursors */
|
/* Child txns save MDBX_pgstate and use own copy of cursors */
|
||||||
size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1);
|
size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1);
|
||||||
size += tsize = sizeof(MDBX_txn);
|
size += tsize = sizeof(MDBX_txn);
|
||||||
@ -6515,7 +6516,7 @@ int mdbx_txn_commit(MDBX_txn *txn) {
|
|||||||
|
|
||||||
parent->mt_geo = txn->mt_geo;
|
parent->mt_geo = txn->mt_geo;
|
||||||
parent->mt_canary = txn->mt_canary;
|
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 */
|
/* Merge our cursors into parent's and close them */
|
||||||
mdbx_cursors_eot(txn, 1);
|
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. */
|
* environment and re-opening it with the new flags. */
|
||||||
#define CHANGEABLE \
|
#define CHANGEABLE \
|
||||||
(MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC | MDBX_NOMEMINIT | \
|
(MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC | MDBX_NOMEMINIT | \
|
||||||
MDBX_COALESCE | MDBX_PAGEPERTURB)
|
MDBX_COALESCE | MDBX_PAGEPERTURB | MDBX_ACCEDE)
|
||||||
#define CHANGELESS \
|
#define CHANGELESS \
|
||||||
(MDBX_NOSUBDIR | MDBX_RDONLY | MDBX_WRITEMAP | MDBX_NOTLS | MDBX_NORDAHEAD | \
|
(MDBX_NOSUBDIR | MDBX_RDONLY | MDBX_WRITEMAP | MDBX_NOTLS | MDBX_NORDAHEAD | \
|
||||||
MDBX_LIFORECLAIM | MDBX_EXCLUSIVE)
|
MDBX_LIFORECLAIM | MDBX_EXCLUSIVE)
|
||||||
@ -8711,18 +8712,22 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
|
|||||||
/* LY: silently ignore irrelevant flags when
|
/* LY: silently ignore irrelevant flags when
|
||||||
* we're only getting read access */
|
* we're only getting read access */
|
||||||
flags &= ~(MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOSYNC | MDBX_NOMETASYNC |
|
flags &= ~(MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOSYNC | MDBX_NOMETASYNC |
|
||||||
MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT);
|
MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT | MDBX_ACCEDE);
|
||||||
} else {
|
} else {
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
/* Temporary `workaround` for OpenBSD kernel's bug.
|
/* Temporary `workaround` for OpenBSD kernel's bug.
|
||||||
* See https://github.com/leo-yuriev/libmdbx/issues/67 */
|
* See https://github.com/leo-yuriev/libmdbx/issues/67 */
|
||||||
if ((flags & MDBX_WRITEMAP) == 0) {
|
if ((flags & MDBX_WRITEMAP) == 0) {
|
||||||
|
if (flags & MDBX_ACCEDE)
|
||||||
|
flags |= MDBX_WRITEMAP;
|
||||||
|
else {
|
||||||
mdbx_debug_log(MDBX_LOG_ERROR, __func__, __LINE__,
|
mdbx_debug_log(MDBX_LOG_ERROR, __func__, __LINE__,
|
||||||
"OpenBSD requires MDBX_WRITEMAP because of an internal "
|
"OpenBSD requires MDBX_WRITEMAP because of an internal "
|
||||||
"bug(s) in a file/buffer/page cache.\n");
|
"bug(s) in a file/buffer/page cache.\n");
|
||||||
rc = 42 /* ENOPROTOOPT */;
|
rc = 42 /* ENOPROTOOPT */;
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif /* __OpenBSD__ */
|
#endif /* __OpenBSD__ */
|
||||||
env->me_dirtylist = mdbx_calloc(MDBX_DPL_TXNFULL + 1, sizeof(MDBX_DP));
|
env->me_dirtylist = mdbx_calloc(MDBX_DPL_TXNFULL + 1, sizeof(MDBX_DP));
|
||||||
if (!env->me_dirtylist)
|
if (!env->me_dirtylist)
|
||||||
@ -8793,6 +8798,36 @@ int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
|
|||||||
goto bailout;
|
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);
|
const int dxb_rc = mdbx_setup_dxb(env, lck_rc);
|
||||||
if (MDBX_IS_ERROR(dxb_rc)) {
|
if (MDBX_IS_ERROR(dxb_rc)) {
|
||||||
rc = 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);
|
mdbx_debug("opened dbenv %p", (void *)env);
|
||||||
if (env->me_lck) {
|
if (env->me_lck) {
|
||||||
const unsigned mode_flags =
|
|
||||||
MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC;
|
|
||||||
if (lck_rc == MDBX_RESULT_TRUE) {
|
if (lck_rc == MDBX_RESULT_TRUE) {
|
||||||
env->me_lck->mti_envmode = env->me_flags & (mode_flags | MDBX_RDONLY);
|
env->me_lck->mti_envmode = env->me_flags & (mode_flags | MDBX_RDONLY);
|
||||||
rc = mdbx_lck_downgrade(env);
|
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);
|
rc = mdbx_reader_check0(env, false, NULL);
|
||||||
if (MDBX_IS_ERROR(rc))
|
if (MDBX_IS_ERROR(rc))
|
||||||
goto bailout;
|
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) {
|
if ((env->me_flags & MDBX_NOTLS) == 0) {
|
||||||
|
@ -968,7 +968,7 @@ int main(int argc, char *argv[]) {
|
|||||||
envflags &= ~MDBX_RDONLY;
|
envflags &= ~MDBX_RDONLY;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
envflags &= ~MDBX_EXCLUSIVE;
|
envflags = (envflags & ~MDBX_EXCLUSIVE) | MDBX_ACCEDE;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
dont_traversal = true;
|
dont_traversal = true;
|
||||||
@ -1031,7 +1031,7 @@ int main(int argc, char *argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
)) {
|
)) {
|
||||||
envflags &= ~MDBX_EXCLUSIVE;
|
envflags &= ~MDBX_EXCLUSIVE;
|
||||||
rc = mdbx_env_open(env, envname, envflags, 0664);
|
rc = mdbx_env_open(env, envname, envflags | MDBX_ACCEDE, 0664);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc) {
|
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[] = {
|
const struct option_verb mode_bits[] = {{"rdonly", MDBX_RDONLY},
|
||||||
{"rdonly", MDBX_RDONLY}, {"mapasync", MDBX_MAPASYNC},
|
{"mapasync", MDBX_MAPASYNC},
|
||||||
{"utterly", MDBX_UTTERLY_NOSYNC}, {"nosubdir", MDBX_NOSUBDIR},
|
{"utterly", MDBX_UTTERLY_NOSYNC},
|
||||||
{"nosync", MDBX_NOSYNC}, {"nometasync", MDBX_NOMETASYNC},
|
{"nosubdir", MDBX_NOSUBDIR},
|
||||||
{"writemap", MDBX_WRITEMAP}, {"notls", MDBX_NOTLS},
|
{"nosync", MDBX_NOSYNC},
|
||||||
{"nordahead", MDBX_NORDAHEAD}, {"nomeminit", MDBX_NOMEMINIT},
|
{"nometasync", MDBX_NOMETASYNC},
|
||||||
{"coalesce", MDBX_COALESCE}, {"lifo", MDBX_LIFORECLAIM},
|
{"writemap", MDBX_WRITEMAP},
|
||||||
{"perturb", MDBX_PAGEPERTURB}, {nullptr, 0}};
|
{"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[] = {
|
const struct option_verb table_bits[] = {
|
||||||
{"key.reverse", MDBX_REVERSEKEY},
|
{"key.reverse", MDBX_REVERSEKEY},
|
||||||
|
@ -124,7 +124,7 @@ void actor_params::set_defaults(const std::string &tmpdir) {
|
|||||||
|
|
||||||
pathname_db = tmpdir + "mdbx-test.db";
|
pathname_db = tmpdir + "mdbx-test.db";
|
||||||
mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOMEMINIT |
|
mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOMEMINIT |
|
||||||
MDBX_COALESCE | MDBX_LIFORECLAIM;
|
MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_ACCEDE;
|
||||||
table_flags = MDBX_DUPSORT;
|
table_flags = MDBX_DUPSORT;
|
||||||
|
|
||||||
size_lower = -1;
|
size_lower = -1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user