From 61e77e7b70e347abbfc230784169c4181a932b12 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, 5 Jan 2023 22:33:56 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D1=83=D0=B1=D0=BB=D0=B8=D0=BA=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=20LCK-=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=20=D1=81=20?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D1=82=D0=B5=D1=80=D0=BD=D0=B0=D1=82=D0=B8?= =?UTF-8?q?=D0=B2=D0=BD=D1=8B=D0=BC=D0=B8=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mdbx.h | 3 +++ src/core.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- src/osal.c | 27 +++++++++++++++++++++++++++ src/osal.h | 5 +++++ 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/mdbx.h b/mdbx.h index 8d8621de..77251ab9 100644 --- a/mdbx.h +++ b/mdbx.h @@ -1932,6 +1932,9 @@ enum MDBX_error_t { * равнозначна \ref MDBX_PROBLEM. */ MDBX_BACKLOG_DEPLETED = -30414, + /** Alternative/Duplicate LCK-file is exists and should be removed manually */ + MDBX_DUPLICATED_CLK = -30413, + /* The last of MDBX-added error codes */ MDBX_LAST_ADDED_ERRCODE = MDBX_TXN_OVERLAPPING, diff --git a/src/core.c b/src/core.c index b04cbc23..1a3ab15d 100644 --- a/src/core.c +++ b/src/core.c @@ -3471,6 +3471,9 @@ __cold const char *mdbx_liberr2str(int errnum) { case MDBX_TXN_OVERLAPPING: return "MDBX_TXN_OVERLAPPING: Overlapping read and write transactions for" " the current thread"; + case MDBX_DUPLICATED_CLK: + return "MDBX_DUPLICATED_CLK: Alternative/Duplicate LCK-file is exists, " + "please keep one and remove unused other"; default: return NULL; } @@ -14461,6 +14464,17 @@ typedef struct { size_t ent_len; } MDBX_handle_env_pathname; +__cold static int check_alternative_lck_absent(const pathchar_t *lck_pathname) { + int err = osal_fileexists(lck_pathname); + if (unlikely(err != MDBX_RESULT_FALSE)) { + if (err == MDBX_RESULT_TRUE) + err = MDBX_DUPLICATED_CLK; + ERROR("Alternative/Duplicate LCK-file '%" MDBX_PRIsPATH "' error %d", + lck_pathname, err); + } + return err; +} + __cold static int handle_env_pathname(MDBX_handle_env_pathname *ctx, const pathchar_t *pathname, MDBX_env_flags_t *flags, @@ -14562,23 +14576,45 @@ __cold static int handle_env_pathname(MDBX_handle_env_pathname *ctx, return MDBX_ENOMEM; ctx->dxb = ctx->buffer_for_free; + ctx->lck = ctx->dxb + ctx->ent_len + dxb_name_len + 1; + pathchar_t *const buf = ctx->buffer_for_free; + rc = MDBX_SUCCESS; if (ctx->ent_len) { - ctx->lck = ctx->dxb + ctx->ent_len + 1; + memcpy(buf, pathname, sizeof(pathchar_t) * pathname_len); + if (*flags & MDBX_NOSUBDIR) { + const pathchar_t *const lck_ext = + osal_fileext(lck_name, ARRAY_LENGTH(lck_name)); + if (lck_ext) { + pathchar_t *pathname_ext = osal_fileext(buf, pathname_len); + memcpy(pathname_ext ? pathname_ext : buf + pathname_len, lck_ext, + sizeof(pathchar_t) * (ARRAY_END(lck_name) - lck_ext)); + rc = check_alternative_lck_absent(buf); + } + } else { + memcpy(buf + ctx->ent_len, dxb_name, sizeof(dxb_name)); + memcpy(buf + ctx->ent_len + dxb_name_len, lock_suffix, + sizeof(lock_suffix)); + rc = check_alternative_lck_absent(buf); + } + memcpy(ctx->dxb, pathname, sizeof(pathchar_t) * (ctx->ent_len + 1)); + memcpy(ctx->lck, pathname, sizeof(pathchar_t) * ctx->ent_len); if (*flags & MDBX_NOSUBDIR) { memcpy(ctx->lck + ctx->ent_len, lock_suffix, sizeof(lock_suffix)); } else { - ctx->lck += dxb_name_len; - memcpy(ctx->lck + ctx->ent_len, lck_name, sizeof(lck_name)); memcpy(ctx->dxb + ctx->ent_len, dxb_name, sizeof(dxb_name)); + memcpy(ctx->lck + ctx->ent_len, lck_name, sizeof(lck_name)); } - memcpy(ctx->lck, pathname, sizeof(pathchar_t) * ctx->ent_len); } else { - ctx->lck = ctx->dxb + dxb_name_len; - memcpy(ctx->lck, lck_name + 1, sizeof(lck_name) - sizeof(pathchar_t)); + assert(!(*flags & MDBX_NOSUBDIR)); + memcpy(buf, dxb_name + 1, sizeof(dxb_name) - sizeof(pathchar_t)); + memcpy(buf + dxb_name_len - 1, lock_suffix, sizeof(lock_suffix)); + rc = check_alternative_lck_absent(buf); + memcpy(ctx->dxb, dxb_name + 1, sizeof(dxb_name) - sizeof(pathchar_t)); + memcpy(ctx->lck, lck_name + 1, sizeof(lck_name) - sizeof(pathchar_t)); } - return MDBX_SUCCESS; + return rc; } __cold int mdbx_env_delete(const char *pathname, MDBX_env_delete_mode_t mode) { diff --git a/src/osal.c b/src/osal.c index e2abfa0a..5e7606c1 100644 --- a/src/osal.c +++ b/src/osal.c @@ -1185,6 +1185,33 @@ MDBX_INTERNAL_FUNC int osal_removedirectory(const pathchar_t *pathname) { #endif } +MDBX_INTERNAL_FUNC int osal_fileexists(const pathchar_t *pathname) { +#if defined(_WIN32) || defined(_WIN64) + if (GetFileAttributesW(pathname) != INVALID_FILE_ATTRIBUTES) + return MDBX_RESULT_TRUE; + int err = GetLastError(); + return (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + ? MDBX_RESULT_FALSE + : err; +#else + if (access(pathname, F_OK) == 0) + return MDBX_RESULT_TRUE; + int err = errno; + return (err == ENOENT || err == ENOTDIR) ? MDBX_RESULT_FALSE : err; +#endif +} + +MDBX_INTERNAL_FUNC pathchar_t *osal_fileext(const pathchar_t *pathname, + size_t len) { + const pathchar_t *ext = nullptr; + for (size_t i = 0; i < len && pathname[i]; i++) + if (pathname[i] == '.') + ext = pathname + i; + else if (osal_isdirsep(pathname[i])) + ext = nullptr; + return (pathchar_t *)ext; +} + MDBX_INTERNAL_FUNC bool osal_pathequal(const pathchar_t *l, const pathchar_t *r, size_t len) { #if defined(_WIN32) || defined(_WIN64) diff --git a/src/osal.h b/src/osal.h index b362d4b6..90173bc4 100644 --- a/src/osal.h +++ b/src/osal.h @@ -225,8 +225,10 @@ osal_syspagesize(void) { #if defined(_WIN32) || defined(_WIN64) typedef wchar_t pathchar_t; +#define MDBX_PRIsPATH "ls" #else typedef char pathchar_t; +#define MDBX_PRIsPATH "s" #endif typedef struct osal_mmap { @@ -559,6 +561,9 @@ MDBX_MAYBE_UNUSED static __inline bool osal_isdirsep(pathchar_t c) { MDBX_INTERNAL_FUNC bool osal_pathequal(const pathchar_t *l, const pathchar_t *r, size_t len); +MDBX_INTERNAL_FUNC pathchar_t *osal_fileext(const pathchar_t *pathname, + size_t len); +MDBX_INTERNAL_FUNC int osal_fileexists(const pathchar_t *pathname); MDBX_INTERNAL_FUNC int osal_openfile(const enum osal_openfile_purpose purpose, const MDBX_env *env, const pathchar_t *pathname,