mdbx: fix/workaround mmap-resize for Windows.

Change-Id: I58b5784f1309cd1e88af860828f561fe29f51ff0
This commit is contained in:
Leonid Yuriev 2017-07-28 13:48:10 +03:00 committed by Leo Yuriev
parent 128cc2d308
commit 82a716847b
2 changed files with 50 additions and 16 deletions

View File

@ -1601,18 +1601,21 @@ static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno,
mdbx_mresize(env->me_flags, &env->me_dxb_mmap, size_bytes, limit_bytes);
if (rc == MDBX_SUCCESS) {
if (env->me_txn) {
mdbx_tassert(env->me_txn, size_pgno >= env->me_txn->mt_next_pgno);
env->me_txn->mt_end_pgno = size_pgno;
}
env->me_dbgeo.now = size_bytes;
env->me_dbgeo.upper = limit_bytes;
} else {
} else if (rc != MDBX_RESULT_TRUE) {
mdbx_error("failed resize datafile/mapping: "
"present %" PRIuPTR " -> %" PRIuPTR ", "
"limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
rc);
return rc;
} else {
mdbx_notice("unable resize datafile/mapping: "
"present %" PRIuPTR " -> %" PRIuPTR ", "
"limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
rc);
}
#ifdef USE_VALGRIND
@ -1624,7 +1627,12 @@ static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno,
VALGRIND_CREATE_BLOCK(env->me_map, env->me_mapsize, "mdbx");
}
#endif
return rc;
if (env->me_txn) {
mdbx_tassert(env->me_txn, size_pgno >= env->me_txn->mt_next_pgno);
env->me_txn->mt_end_pgno = size_pgno;
}
return MDBX_SUCCESS;
}
/* Allocate page numbers and memory for writing. Maintain me_last_reclaimed,

View File

@ -892,9 +892,19 @@ int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
map->address = nullptr;
return ntstatus2errcode(rc);
}
assert(map->address != MAP_FAILED);
map->current = must;
uint64_t filesize;
rc = mdbx_filesize(map->fd, &filesize);
if (rc != MDBX_SUCCESS) {
NtClose(map->section);
NtUnmapViewOfSection(GetCurrentProcess(), map->address);
map->section = 0;
map->address = nullptr;
return rc;
}
map->current = (must < filesize) ? must : (size_t)filesize;
map->length = ViewSize;
return MDBX_SUCCESS;
#else
@ -931,8 +941,8 @@ int mdbx_munmap(mdbx_mmap_t *map) {
return MDBX_SUCCESS;
}
int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
assert(must <= limit);
int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t atleast, size_t limit) {
assert(atleast <= limit);
#if defined(_WIN32) || defined(_WIN64)
if (limit < map->length) {
/* Windows is unable shrinking a mapped section */
@ -947,18 +957,34 @@ int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
return ntstatus2errcode(rc);
map->length = limit;
}
if (must < map->current) {
if (atleast < map->current) {
/* Windows is unable shrinking a mapped file */
return MDBX_RESULT_TRUE;
uint8_t *ptr = (uint8_t *)map->address + atleast;
if (!VirtualFree(ptr, map->current - atleast, MEM_DECOMMIT))
return MDBX_RESULT_TRUE;
map->current = atleast;
int rc = mdbx_ftruncate(map->fd, atleast);
return (rc != MDBX_SUCCESS) ? MDBX_RESULT_TRUE : rc;
}
if (must > map->current) {
if (atleast > map->current) {
/* growth */
uint8_t *ptr = (uint8_t *)map->address + map->current;
if (ptr !=
VirtualAlloc(ptr, must - map->current, MEM_COMMIT,
VirtualAlloc(ptr, atleast - map->current, MEM_COMMIT,
(flags & MDBX_WRITEMAP) ? PAGE_READWRITE : PAGE_READONLY))
return GetLastError();
map->current = must;
map->current = atleast;
}
uint64_t filesize;
int rc = mdbx_filesize(map->fd, &filesize);
if (rc != MDBX_SUCCESS)
return rc;
if (filesize < atleast) {
rc = mdbx_ftruncate(map->fd, atleast);
if (rc != MDBX_SUCCESS)
return rc;
}
return MDBX_SUCCESS;
#else
@ -970,7 +996,7 @@ int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
map->address = ptr;
map->length = limit;
}
return mdbx_ftruncate(map->fd, must);
return mdbx_ftruncate(map->fd, atleast);
#endif
}