mdbx: контроль отсутствия дубликатов LCK-файла с альтернативными именами.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2023-01-05 22:33:56 +03:00
parent 08fb7d5838
commit 61e77e7b70
4 changed files with 78 additions and 7 deletions

3
mdbx.h
View File

@ -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,

View File

@ -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) {

View File

@ -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)

View File

@ -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,