summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-11-25 15:45:50 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-11-25 15:45:50 +0300
commitf5e4db1c78db17956920f88cea5e6914ec668e24 (patch)
treec95b2037ddd70371d3c6b1b9d9264b944618871f
parentbc1277617376426080ca452f63a633c9e255fc4c (diff)
libmdbx: fix for changing database size
-rw-r--r--libs/libmdbx/src/src/mdbx.c73
1 files changed, 57 insertions, 16 deletions
diff --git a/libs/libmdbx/src/src/mdbx.c b/libs/libmdbx/src/src/mdbx.c
index 92e1b5c630..af03bdaa8d 100644
--- a/libs/libmdbx/src/src/mdbx.c
+++ b/libs/libmdbx/src/src/mdbx.c
@@ -1765,7 +1765,7 @@ static int mdbx_page_loose(MDBX_cursor *mc, MDBX_page *mp) {
mdbx_kill_page(txn->mt_env, mp);
mp->mp_flags = P_LOOSE | P_DIRTY;
VALGRIND_MAKE_MEM_UNDEFINED(mp, PAGEHDRSZ);
- VALGRIND_MAKE_MEM_DEFINED(&mp->mp_pgno, sizeof(pgno_t));
+ ASAN_UNPOISON_MEMORY_REGION(link, sizeof(*link));
*link = txn->mt_loose_pages;
txn->mt_loose_pages = mp;
txn->mt_loose_count++;
@@ -2246,19 +2246,21 @@ static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno,
env->me_dxb_mmap.current == env->me_dxb_mmap.filesize)
goto bailout;
- if ((env->me_flags & MDBX_RDONLY) || limit_bytes != env->me_dxb_mmap.length ||
- size_bytes < env->me_dxb_mmap.current) {
- /* Windows allows only extending a read-write section, but not a
- * corresponing mapped view. Therefore in other cases we must suspend
- * the local threads for safe remap. */
- array_onstack.limit = ARRAY_LENGTH(array_onstack.handles);
- array_onstack.count = 0;
- suspended = &array_onstack;
- rc = mdbx_suspend_threads_before_remap(env, &suspended);
- if (rc != MDBX_SUCCESS) {
- mdbx_error("failed suspend-for-remap: errcode %d", rc);
- goto bailout;
- }
+ /* 1) Windows allows only extending a read-write section, but not a
+ * corresponing mapped view. Therefore in other cases we must suspend
+ * the local threads for safe remap.
+ * 2) At least on Windows 10 1803 the entire mapped section is unavailable
+ * for short time during NtExtendSection() or VirtualAlloc() execution.
+ *
+ * THEREFORE LOCAL THREADS SUSPENDING IS ALWAYS REQUIRED!
+ */
+ array_onstack.limit = ARRAY_LENGTH(array_onstack.handles);
+ array_onstack.count = 0;
+ suspended = &array_onstack;
+ rc = mdbx_suspend_threads_before_remap(env, &suspended);
+ if (rc != MDBX_SUCCESS) {
+ mdbx_error("failed suspend-for-remap: errcode %d", rc);
+ goto bailout;
}
#else
/* Acquire guard to avoid collision between read and write txns
@@ -3347,6 +3349,13 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
}
}
txn->mt_owner = mdbx_thread_self();
+#if defined(_WIN32) || defined(_WIN64)
+ if ((txn->mt_flags & MDBX_TXN_RDONLY) != 0 && size > env->me_dbgeo.lower &&
+ env->me_dbgeo.shrink) {
+ txn->mt_flags |= MDBX_SHRINK_ALLOWED;
+ mdbx_srwlock_AcquireShared(&env->me_remap_guard);
+ }
+#endif
return MDBX_SUCCESS;
}
bailout:
@@ -3514,8 +3523,8 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
if (txn != env->me_txn0)
mdbx_free(txn);
} else {
- mdbx_assert(env,
- (txn->mt_flags & ~(MDBX_TXN_RDONLY | MDBX_TXN_WRITEMAP)) == 0);
+ mdbx_assert(env, (txn->mt_flags & ~(MDBX_TXN_RDONLY | MDBX_TXN_WRITEMAP |
+ MDBX_SHRINK_ALLOWED)) == 0);
txn->mt_signature = MDBX_MT_SIGNATURE;
*ret = txn;
mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO
@@ -3608,6 +3617,10 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
txn->mt_dbs[FREE_DBI].md_root);
if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)) {
+#if defined(_WIN32) || defined(_WIN64)
+ if (txn->mt_flags & MDBX_SHRINK_ALLOWED)
+ mdbx_srwlock_ReleaseShared(&env->me_remap_guard);
+#endif
if (txn->mt_ro_reader) {
txn->mt_ro_reader->mr_txnid = ~(txnid_t)0;
env->me_lck->mti_readers_refresh_flag = true;
@@ -5841,6 +5854,34 @@ LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower,
meta.mm_geo.shrink == bytes2pgno(env, env->me_dbgeo.shrink));
if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) {
+
+#if defined(_WIN32) || defined(_WIN64)
+ /* Was DB shrinking disabled before and now it will be enabled? */
+ if (meta.mm_geo.lower < meta.mm_geo.upper && meta.mm_geo.shrink &&
+ !(head->mm_geo.lower < head->mm_geo.upper && head->mm_geo.shrink)) {
+ rc = mdbx_rdt_lock(env);
+ if (unlikely(rc != MDBX_SUCCESS))
+ goto bailout;
+
+ /* Check if there are any reading threads that do not use the SRWL */
+ const mdbx_pid_t CurrentTid = GetCurrentThreadId();
+ const MDBX_reader *const begin = env->me_lck->mti_readers;
+ const MDBX_reader *const end = begin + env->me_lck->mti_numreaders;
+ for (const MDBX_reader *reader = begin; reader < end; ++reader) {
+ if (reader->mr_pid == env->me_pid && reader->mr_tid &&
+ reader->mr_tid != CurrentTid) {
+ /* At least one thread may don't use SRWL */
+ rc = MDBX_EPERM;
+ break;
+ }
+ }
+
+ mdbx_rdt_unlock(env);
+ if (unlikely(rc != MDBX_SUCCESS))
+ goto bailout;
+ }
+#endif
+
if (meta.mm_geo.now != head->mm_geo.now ||
meta.mm_geo.upper != head->mm_geo.upper) {
rc = mdbx_mapresize(env, meta.mm_geo.now, meta.mm_geo.upper);