From 82a716847b4f34aac09f27cb9f6ae31843457d51 Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Fri, 28 Jul 2017 13:48:10 +0300 Subject: [PATCH] mdbx: fix/workaround mmap-resize for Windows. Change-Id: I58b5784f1309cd1e88af860828f561fe29f51ff0 --- src/mdbx.c | 20 ++++++++++++++------ src/osal.c | 46 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/mdbx.c b/src/mdbx.c index 467ac002..caefd6aa 100644 --- a/src/mdbx.c +++ b/src/mdbx.c @@ -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, diff --git a/src/osal.c b/src/osal.c index 381594a4..c3b50c92 100644 --- a/src/osal.c +++ b/src/osal.c @@ -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 }