From 1684d17b0f82782748de932558045342cf4d085f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Thu, 9 Feb 2023 17:19:25 +0300 Subject: [PATCH] =?UTF-8?q?mdbx-windows:=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5?= =?UTF-8?q?=D1=80=D0=B6=D0=BA=D0=B0=20char-=D0=B2=D0=B5=D1=80=D1=81=D0=B8?= =?UTF-8?q?=D0=B8=20`mdbx=5Fenv=5Fget=5Fpath()`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mdbx.h | 3 +-- src/core.c | 68 +++++++++++++++++++++++++++++++++++++++---------- src/internals.h | 2 ++ 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/mdbx.h b/mdbx.h index 76a42d48..190e4113 100644 --- a/mdbx.h +++ b/mdbx.h @@ -3003,9 +3003,8 @@ LIBMDBX_API int mdbx_env_get_flags(const MDBX_env *env, unsigned *flags); * \returns A non-zero error value on failure and 0 on success, * some possible errors are: * \retval MDBX_EINVAL An invalid parameter was specified. */ -#if !(defined(_WIN32) || defined(_WIN64)) LIBMDBX_API int mdbx_env_get_path(const MDBX_env *env, const char **dest); -#else +#if defined(_WIN32) || defined(_WIN64) LIBMDBX_API int mdbx_env_get_pathW(const MDBX_env *env, const wchar_t **dest); #endif /* Windows */ diff --git a/src/core.c b/src/core.c index 42727794..f9f3d35e 100644 --- a/src/core.c +++ b/src/core.c @@ -14779,6 +14779,9 @@ __cold int mdbx_env_open(MDBX_env *env, const char *pathname, if (likely(rc == MDBX_SUCCESS)) { rc = mdbx_env_openW(env, pathnameW, flags, mode); osal_free(pathnameW); + if (rc == MDBX_SUCCESS) + /* force to make cache of the multi-byte pathname representation */ + mdbx_env_get_path(env, &pathname); } return rc; } @@ -15334,6 +15337,12 @@ __cold static int env_close(MDBX_env *env) { osal_free(env->me_pathname); env->me_pathname = nullptr; } +#if defined(_WIN32) || defined(_WIN64) + if (env->me_pathname_char) { + osal_free(env->me_pathname_char); + env->me_pathname_char = nullptr; + } +#endif /* Windows */ if (env->me_txn0) { dpl_free(env->me_txn0); txl_free(env->me_txn0->tw.lifo_reclaimed); @@ -21929,19 +21938,7 @@ __cold int mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func) { #endif } -#if !(defined(_WIN32) || defined(_WIN64)) -__cold int mdbx_env_get_path(const MDBX_env *env, const char **arg) { - int rc = check_env(env, true); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!arg)) - return MDBX_EINVAL; - - *arg = env->me_pathname; - return MDBX_SUCCESS; -} -#else +#if defined(_WIN32) || defined(_WIN64) __cold int mdbx_env_get_pathW(const MDBX_env *env, const wchar_t **arg) { int rc = check_env(env, true); if (unlikely(rc != MDBX_SUCCESS)) @@ -21955,6 +21952,51 @@ __cold int mdbx_env_get_pathW(const MDBX_env *env, const wchar_t **arg) { } #endif /* Windows */ +__cold int mdbx_env_get_path(const MDBX_env *env, const char **arg) { + int rc = check_env(env, true); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + if (unlikely(!arg)) + return MDBX_EINVAL; + +#if defined(_WIN32) || defined(_WIN64) + if (!env->me_pathname_char) { + *arg = nullptr; + DWORD flags = /* WC_ERR_INVALID_CHARS */ 0x80; + size_t mb_len = WideCharToMultiByte(CP_THREAD_ACP, flags, env->me_pathname, + -1, nullptr, 0, nullptr, nullptr); + rc = mb_len ? MDBX_SUCCESS : (int)GetLastError(); + if (rc == ERROR_INVALID_FLAGS) { + mb_len = WideCharToMultiByte(CP_THREAD_ACP, flags = 0, env->me_pathname, + -1, nullptr, 0, nullptr, nullptr); + rc = mb_len ? MDBX_SUCCESS : (int)GetLastError(); + } + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + char *const mb_pathname = osal_malloc(mb_len); + if (!mb_pathname) + return MDBX_ENOMEM; + if (mb_len != (size_t)WideCharToMultiByte(CP_THREAD_ACP, flags, + env->me_pathname, -1, mb_pathname, + (int)mb_len, nullptr, nullptr)) { + rc = (int)GetLastError(); + osal_free(mb_pathname); + return rc; + } + if (env->me_pathname_char || + InterlockedCompareExchangePointer( + (PVOID volatile *)&env->me_pathname_char, mb_pathname, nullptr)) + osal_free(mb_pathname); + } + *arg = env->me_pathname_char; +#else + *arg = env->me_pathname; +#endif /* Windows */ + return MDBX_SUCCESS; +} + __cold int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *arg) { int rc = check_env(env, true); if (unlikely(rc != MDBX_SUCCESS)) diff --git a/src/internals.h b/src/internals.h index b5b8ead6..06cfbfd3 100644 --- a/src/internals.h +++ b/src/internals.h @@ -1463,6 +1463,8 @@ struct MDBX_env { osal_srwlock_t me_remap_guard; /* Workaround for LockFileEx and WriteFile multithread bug */ CRITICAL_SECTION me_windowsbug_lock; + char *me_pathname_char; /* cache of multi-byte representation of pathname + to the DB files */ #else osal_fastmutex_t me_remap_guard; #endif