mirror of
https://github.com/isar/libmdbx.git
synced 2025-08-20 07:49:27 +08:00
mdbx++: Initial C++ API (some extra methods are not implemented).
Change-Id: I0478d0c94dcd12b52916e87815e5731817407c3c
This commit is contained in:
123
src/core.c
123
src/core.c
@@ -3045,11 +3045,9 @@ static __always_inline void mdbx_dpl_clear(MDBX_DPL dl) {
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef MDBX_ALLOY
|
||||
uint8_t mdbx_runtime_flags = MDBX_RUNTIME_FLAGS_INIT;
|
||||
uint8_t mdbx_loglevel = MDBX_DEBUG;
|
||||
MDBX_debug_func *mdbx_debug_logger;
|
||||
#endif /* MDBX_ALLOY */
|
||||
|
||||
static bool mdbx_refund(MDBX_txn *txn);
|
||||
static __must_check_result int mdbx_page_retire(MDBX_cursor *mc, MDBX_page *mp);
|
||||
@@ -3199,7 +3197,7 @@ static MDBX_cmp_func cmp_lexical, cmp_reverse, cmp_int_align4, cmp_int_align2,
|
||||
static __inline MDBX_cmp_func *get_default_keycmp(unsigned flags);
|
||||
static __inline MDBX_cmp_func *get_default_datacmp(unsigned flags);
|
||||
|
||||
static const char *__mdbx_strerr(int errnum) {
|
||||
__cold const char *mdbx_liberr2str(int errnum) {
|
||||
/* Table of descriptions for MDBX errors */
|
||||
static const char *const tbl[] = {
|
||||
"MDBX_KEYEXIST: Key/data pair already exists",
|
||||
@@ -3272,14 +3270,14 @@ static const char *__mdbx_strerr(int errnum) {
|
||||
}
|
||||
|
||||
const char *__cold mdbx_strerror_r(int errnum, char *buf, size_t buflen) {
|
||||
const char *msg = __mdbx_strerr(errnum);
|
||||
const char *msg = mdbx_liberr2str(errnum);
|
||||
if (!msg && buflen > 0 && buflen < INT_MAX) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
const DWORD size = FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
|
||||
errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen,
|
||||
NULL);
|
||||
return size ? buf : NULL;
|
||||
return size ? buf : "FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM) failed";
|
||||
#elif defined(_GNU_SOURCE) && defined(__GLIBC__)
|
||||
/* GNU-specific */
|
||||
if (errnum > 0)
|
||||
@@ -3311,7 +3309,7 @@ const char *__cold mdbx_strerror(int errnum) {
|
||||
static char buf[1024];
|
||||
return mdbx_strerror_r(errnum, buf, sizeof(buf));
|
||||
#else
|
||||
const char *msg = __mdbx_strerr(errnum);
|
||||
const char *msg = mdbx_liberr2str(errnum);
|
||||
if (!msg) {
|
||||
if (errnum > 0)
|
||||
msg = strerror(errnum);
|
||||
@@ -3327,13 +3325,17 @@ const char *__cold mdbx_strerror(int errnum) {
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64) /* Bit of madness for Windows */
|
||||
const char *mdbx_strerror_r_ANSI2OEM(int errnum, char *buf, size_t buflen) {
|
||||
const char *msg = __mdbx_strerr(errnum);
|
||||
const char *msg = mdbx_liberr2str(errnum);
|
||||
if (!msg && buflen > 0 && buflen < INT_MAX) {
|
||||
const DWORD size = FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
|
||||
errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen,
|
||||
NULL);
|
||||
if (size && CharToOemBuffA(buf, buf, size))
|
||||
if (!size)
|
||||
msg = "FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM) failed";
|
||||
else if (!CharToOemBuffA(buf, buf, size))
|
||||
msg = "CharToOemBuffA() failed";
|
||||
else
|
||||
msg = buf;
|
||||
}
|
||||
return msg;
|
||||
@@ -9802,7 +9804,7 @@ static int __cold mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
|
||||
|
||||
/* Open and/or initialize the lock region for the environment. */
|
||||
static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
|
||||
mode_t mode) {
|
||||
mdbx_mode_t mode) {
|
||||
mdbx_assert(env, env->me_lazy_fd != INVALID_HANDLE_VALUE);
|
||||
mdbx_assert(env, env->me_lfd == INVALID_HANDLE_VALUE);
|
||||
|
||||
@@ -10137,7 +10139,7 @@ static uint32_t merge_sync_flags(const uint32_t a, const uint32_t b) {
|
||||
}
|
||||
|
||||
int __cold mdbx_env_open(MDBX_env *env, const char *pathname,
|
||||
MDBX_env_flags_t flags, mode_t mode) {
|
||||
MDBX_env_flags_t flags, mdbx_mode_t mode) {
|
||||
int rc = check_env(env);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return rc;
|
||||
@@ -10198,7 +10200,7 @@ int __cold mdbx_env_open(MDBX_env *env, const char *pathname,
|
||||
return rc;
|
||||
|
||||
/* auto-create directory if requested */
|
||||
const mode_t dir_mode =
|
||||
const mdbx_mode_t dir_mode =
|
||||
(/* inherit read/write permissions for group and others */ mode &
|
||||
(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) |
|
||||
/* always add read/write/search for owner */ S_IRWXU |
|
||||
@@ -11184,7 +11186,7 @@ int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data) {
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
MDBX_cursor_couple cx;
|
||||
rc = mdbx_cursor_init(&cx.outer, txn, dbi);
|
||||
@@ -11195,8 +11197,8 @@ int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data) {
|
||||
return mdbx_cursor_set(&cx.outer, (MDBX_val *)key, data, MDBX_SET, &exact);
|
||||
}
|
||||
|
||||
int mdbx_get_nearest(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
|
||||
MDBX_val *data) {
|
||||
int mdbx_get_equal_or_great(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
|
||||
MDBX_val *data) {
|
||||
DKBUF;
|
||||
mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key));
|
||||
|
||||
@@ -11208,7 +11210,7 @@ int mdbx_get_nearest(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
|
||||
return MDBX_BAD_TXN;
|
||||
@@ -11248,7 +11250,7 @@ int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
MDBX_cursor_couple cx;
|
||||
rc = mdbx_cursor_init(&cx.outer, txn, dbi);
|
||||
@@ -13416,7 +13418,7 @@ int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cursor **ret) {
|
||||
return rc;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_VALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(dbi == FREE_DBI && !F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)))
|
||||
return MDBX_EACCESS;
|
||||
@@ -13458,7 +13460,7 @@ int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *mc) {
|
||||
return rc;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, mc->mc_dbi, DBI_VALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(mc->mc_backup))
|
||||
return MDBX_EINVAL;
|
||||
@@ -14934,7 +14936,7 @@ int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
|
||||
return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN;
|
||||
@@ -15476,7 +15478,7 @@ int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(flags & ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE |
|
||||
MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT)))
|
||||
@@ -16126,7 +16128,7 @@ int __cold mdbx_env_copy(MDBX_env *env, const char *dest_path,
|
||||
mdbx_filehandle_t newfd;
|
||||
rc = mdbx_openfile(MDBX_OPEN_COPY, env, dest_path, &newfd,
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
(mode_t)-1
|
||||
(mdbx_mode_t)-1
|
||||
#else
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
|
||||
#endif
|
||||
@@ -16308,7 +16310,7 @@ int __cold mdbx_dbi_dupsort_depthmask(MDBX_txn *txn, MDBX_dbi dbi,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_VALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
MDBX_cursor_couple cx;
|
||||
rc = mdbx_cursor_init(&cx.outer, txn, dbi);
|
||||
@@ -16781,7 +16783,7 @@ int __cold mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *dest,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_VALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
const size_t size_before_modtxnid = offsetof(MDBX_stat, ms_mod_txnid);
|
||||
if (unlikely(bytes != sizeof(MDBX_stat)) && bytes != size_before_modtxnid)
|
||||
@@ -16823,7 +16825,7 @@ int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) {
|
||||
return rc;
|
||||
|
||||
if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
rc = mdbx_fastmutex_acquire(&env->me_dbi_lock);
|
||||
if (likely(rc == MDBX_SUCCESS)) {
|
||||
@@ -16843,7 +16845,7 @@ int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_VALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
*flags = txn->mt_dbs[dbi].md_flags & DB_PERSISTENT_FLAGS;
|
||||
*state =
|
||||
@@ -16955,7 +16957,7 @@ int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, bool del) {
|
||||
return rc;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(TXN_DBI_CHANGED(txn, dbi)))
|
||||
return MDBX_BAD_DBI;
|
||||
@@ -16966,7 +16968,7 @@ int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, bool del) {
|
||||
return rc;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID))) {
|
||||
rc = MDBX_EINVAL;
|
||||
rc = MDBX_BAD_DBI;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
@@ -17024,7 +17026,7 @@ int mdbx_set_compare(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) {
|
||||
return rc;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
txn->mt_dbxs[dbi].md_cmp = cmp;
|
||||
return MDBX_SUCCESS;
|
||||
@@ -17036,7 +17038,7 @@ int mdbx_set_dupsort(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) {
|
||||
return rc;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
txn->mt_dbxs[dbi].md_dcmp = cmp;
|
||||
return MDBX_SUCCESS;
|
||||
@@ -18096,7 +18098,7 @@ int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *begin_key,
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
MDBX_cursor_couple begin;
|
||||
/* LY: first, initialize cursor to refresh a DB in case it have DB_STALE */
|
||||
@@ -18253,24 +18255,27 @@ int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *begin_key,
|
||||
* - внешняя аллокация курсоров, в том числе на стеке (без malloc).
|
||||
* - получения статуса страницы по адресу (знать о P_DIRTY).
|
||||
*/
|
||||
int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key,
|
||||
MDBX_val *new_data, MDBX_val *old_data,
|
||||
MDBX_put_flags_t flags) {
|
||||
|
||||
int mdbx_replace_ex(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key,
|
||||
MDBX_val *new_data, MDBX_val *old_data,
|
||||
MDBX_put_flags_t flags, MDBX_preserve_func preserver,
|
||||
void *preserver_context) {
|
||||
int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return rc;
|
||||
|
||||
if (unlikely(!key || !old_data || old_data == new_data))
|
||||
if (unlikely(!key || !old_data || old_data == new_data || !preserver))
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(old_data->iov_base == NULL && old_data->iov_len))
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(new_data == NULL && !(flags & MDBX_CURRENT)))
|
||||
if (unlikely(new_data == NULL &&
|
||||
(flags & (MDBX_CURRENT | MDBX_RESERVE)) != MDBX_CURRENT))
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(flags & ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE |
|
||||
MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT)))
|
||||
@@ -18360,14 +18365,11 @@ int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key,
|
||||
}
|
||||
|
||||
if (IS_DIRTY(page)) {
|
||||
if (unlikely(old_data->iov_len < present_data.iov_len)) {
|
||||
old_data->iov_base = NULL;
|
||||
old_data->iov_len = present_data.iov_len;
|
||||
rc = MDBX_RESULT_TRUE;
|
||||
rc = preserver ? preserver(preserver_context, old_data,
|
||||
present_data.iov_base, present_data.iov_len)
|
||||
: MDBX_SUCCESS;
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
}
|
||||
memcpy(old_data->iov_base, present_data.iov_base, present_data.iov_len);
|
||||
old_data->iov_len = present_data.iov_len;
|
||||
} else {
|
||||
*old_data = present_data;
|
||||
}
|
||||
@@ -18384,6 +18386,25 @@ bailout:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int default_value_preserver(void *context, MDBX_val *target,
|
||||
const void *src, size_t bytes) {
|
||||
(void)context;
|
||||
if (unlikely(target->iov_len < bytes)) {
|
||||
target->iov_base = nullptr;
|
||||
target->iov_len = bytes;
|
||||
return MDBX_RESULT_TRUE;
|
||||
}
|
||||
memcpy(target->iov_base, src, target->iov_len = bytes);
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key,
|
||||
MDBX_val *new_data, MDBX_val *old_data,
|
||||
MDBX_put_flags_t flags) {
|
||||
return mdbx_replace_ex(txn, dbi, key, new_data, old_data, flags,
|
||||
default_value_preserver, nullptr);
|
||||
}
|
||||
|
||||
/* Функция сообщает находится ли указанный адрес в "грязной" странице у
|
||||
* заданной пишущей транзакции. В конечном счете это позволяет избавиться от
|
||||
* лишнего копирования данных из НЕ-грязных страниц.
|
||||
@@ -18411,21 +18432,21 @@ int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return rc;
|
||||
|
||||
if (txn->mt_flags & MDBX_TXN_RDONLY)
|
||||
return MDBX_RESULT_FALSE;
|
||||
|
||||
const MDBX_env *env = txn->mt_env;
|
||||
const ptrdiff_t offset = (uint8_t *)ptr - env->me_map;
|
||||
if (offset >= 0) {
|
||||
const pgno_t pgno = bytes2pgno(env, offset);
|
||||
if (likely(pgno < txn->mt_next_pgno)) {
|
||||
if (txn->mt_flags & MDBX_TXN_RDONLY)
|
||||
return MDBX_RESULT_FALSE;
|
||||
|
||||
const MDBX_page *page = pgno2page(env, pgno);
|
||||
if (unlikely(page->mp_pgno != pgno)) {
|
||||
/* The ptr pointed into middle of a large page,
|
||||
* not to the beginning of a data. */
|
||||
return MDBX_EINVAL;
|
||||
}
|
||||
if (unlikely(page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP)))
|
||||
if (unlikely(page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP | P_META)))
|
||||
return MDBX_RESULT_TRUE;
|
||||
if (likely(txn->tw.spill_pages == nullptr))
|
||||
return MDBX_RESULT_FALSE;
|
||||
@@ -18435,7 +18456,7 @@ int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
|
||||
if ((size_t)offset < env->me_dxb_mmap.limit) {
|
||||
/* Указатель адресует что-то в пределах mmap, но за границей
|
||||
* распределенных страниц. Такое может случится если mdbx_is_dirty()
|
||||
* вызывает после операции, в ходе которой гразная страница попала
|
||||
* вызывается после операции, в ходе которой грязная страница попала
|
||||
* в loose и затем была возвращена в нераспределенное пространство. */
|
||||
return MDBX_RESULT_TRUE;
|
||||
}
|
||||
@@ -18445,7 +18466,7 @@ int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
|
||||
* передан некорректный адрес, либо адрес в теневой странице, которая была
|
||||
* выделена посредством malloc().
|
||||
*
|
||||
* Для WRITE_MAP режима такая страница однозначно "не грязная",
|
||||
* Для режима WRITE_MAP режима страница однозначно "не грязная",
|
||||
* а для режимов без WRITE_MAP следует просматривать списки dirty
|
||||
* и spilled страниц у каких-либо транзакций (в том числе дочерних).
|
||||
*
|
||||
@@ -18466,7 +18487,7 @@ int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,
|
||||
return rc;
|
||||
|
||||
if (unlikely(!mdbx_txn_dbi_exists(txn, dbi, DBI_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(TXN_DBI_CHANGED(txn, dbi)))
|
||||
return MDBX_BAD_DBI;
|
||||
@@ -18856,7 +18877,7 @@ int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
|
||||
return MDBX_EBADSIGN;
|
||||
|
||||
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_BAD_DBI;
|
||||
|
||||
if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
|
||||
return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN;
|
||||
|
@@ -116,7 +116,8 @@
|
||||
#endif /* __noop */
|
||||
|
||||
#ifndef __fallthrough
|
||||
# if defined(__cplusplus) && __has_cpp_attribute(fallthrough)
|
||||
# if defined(__cplusplus) && (__has_cpp_attribute(fallthrough) && \
|
||||
(!defined(__clang__) || __clang__ > 4)) || __cplusplus >= 201703L
|
||||
# define __fallthrough [[fallthrough]]
|
||||
# elif __GNUC_PREREQ(8, 0) && defined(__cplusplus) && __cplusplus >= 201103L
|
||||
# define __fallthrough [[fallthrough]]
|
||||
@@ -151,7 +152,9 @@
|
||||
#endif /* __prefetch */
|
||||
|
||||
#ifndef __noreturn
|
||||
# if defined(__GNUC__) || __has_attribute(__noreturn__)
|
||||
# ifdef _Noreturn
|
||||
# define __noreturn _Noreturn
|
||||
# elif defined(__GNUC__) || __has_attribute(__noreturn__)
|
||||
# define __noreturn __attribute__((__noreturn__))
|
||||
# elif defined(_MSC_VER)
|
||||
# define __noreturn __declspec(noreturn)
|
||||
|
@@ -48,7 +48,7 @@
|
||||
#endif
|
||||
#if MDBX_DISABLE_GNU_SOURCE
|
||||
#undef _GNU_SOURCE
|
||||
#elif defined(__linux__) || defined(__gnu_linux__)
|
||||
#elif (defined(__linux__) || defined(__gnu_linux__)) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
#pragma warning(disable : 4366) /* the result of the unary '&' operator may be unaligned */
|
||||
#pragma warning(disable : 4200) /* nonstandard extension used: zero-sized array in struct/union */
|
||||
#pragma warning(disable : 4204) /* nonstandard extension used: non-constant aggregate initializer */
|
||||
#pragma warning(disable : 4505) /* unreferenced local function has been removed */
|
||||
#endif /* _MSC_VER (warnings) */
|
||||
|
||||
#if defined(MDBX_TOOLS)
|
||||
@@ -127,6 +128,16 @@
|
||||
# warning "libmdbx don't compatible with ThreadSanitizer, you will get a lot of false-positive issues."
|
||||
#endif /* __SANITIZE_THREAD__ */
|
||||
|
||||
#if __has_warning("-Wnested-anon-types")
|
||||
# if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||
# elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic ignored "-Wnested-anon-types"
|
||||
# else
|
||||
# pragma warning disable "nested-anon-types"
|
||||
# endif
|
||||
#endif /* -Wnested-anon-types */
|
||||
|
||||
#if __has_warning("-Wconstant-logical-operand")
|
||||
# if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
||||
@@ -155,6 +166,10 @@
|
||||
/* *INDENT-ON* */
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "osal.h"
|
||||
|
||||
#define mdbx_sourcery_anchor XCONCAT(mdbx_sourcery_, MDBX_BUILD_SOURCERY)
|
||||
@@ -216,6 +231,7 @@ typedef uint64_t txnid_t;
|
||||
#define PRIaTXN PRIi64
|
||||
#define MIN_TXNID UINT64_C(1)
|
||||
#define MAX_TXNID (SAFE64_INVALID_THRESHOLD - 1)
|
||||
#define INITIAL_TXNID (MIN_TXNID + NUM_METAS - 1)
|
||||
#define INVALID_TXNID UINT64_MAX
|
||||
/* LY: for testing non-atomic 64-bit txnid on 32-bit arches.
|
||||
* #define MDBX_TXNID_STEP (UINT32_MAX / 3) */
|
||||
@@ -1019,14 +1035,9 @@ struct MDBX_env {
|
||||
#define MDBX_RUNTIME_FLAGS_INIT \
|
||||
((MDBX_DEBUG) > 0) * MDBX_DBG_ASSERT + ((MDBX_DEBUG) > 1) * MDBX_DBG_AUDIT
|
||||
|
||||
#ifdef MDBX_ALLOY
|
||||
static uint8_t mdbx_runtime_flags = MDBX_RUNTIME_FLAGS_INIT;
|
||||
static uint8_t mdbx_loglevel = MDBX_DEBUG;
|
||||
#else
|
||||
extern uint8_t mdbx_runtime_flags;
|
||||
extern uint8_t mdbx_loglevel;
|
||||
#endif /* MDBX_ALLOY */
|
||||
MDBX_INTERNAL_VAR MDBX_debug_func *mdbx_debug_logger;
|
||||
extern MDBX_debug_func *mdbx_debug_logger;
|
||||
|
||||
MDBX_INTERNAL_FUNC void mdbx_debug_log(int type, const char *function, int line,
|
||||
const char *fmt, ...)
|
||||
@@ -1067,15 +1078,15 @@ MDBX_INTERNAL_FUNC void mdbx_debug_log(int type, const char *function, int line,
|
||||
#define mdbx_panic(fmt, ...) \
|
||||
__android_log_assert("panic", "mdbx", fmt, __VA_ARGS__)
|
||||
#else
|
||||
MDBX_INTERNAL_FUNC void mdbx_panic(const char *fmt, ...) __printf_args(1, 2);
|
||||
void mdbx_panic(const char *fmt, ...) __printf_args(1, 2);
|
||||
#endif
|
||||
|
||||
#if !MDBX_DEBUG && defined(__ANDROID_API__)
|
||||
#define mdbx_assert_fail(env, msg, func, line) \
|
||||
__android_log_assert(msg, "mdbx", "%s:%u", func, line)
|
||||
#else
|
||||
MDBX_INTERNAL_FUNC void mdbx_assert_fail(const MDBX_env *env, const char *msg,
|
||||
const char *func, int line);
|
||||
void mdbx_assert_fail(const MDBX_env *env, const char *msg, const char *func,
|
||||
int line);
|
||||
#endif
|
||||
|
||||
#define mdbx_debug_extra(fmt, ...) \
|
||||
@@ -1318,7 +1329,7 @@ typedef struct MDBX_node {
|
||||
MDBX_INTEGERDUP | MDBX_REVERSEDUP)
|
||||
|
||||
/* mdbx_dbi_open() flags */
|
||||
#define DB_USABLE_FLAGS (DB_PERSISTENT_FLAGS | MDBX_CREATE | MDBX_ACCEDE)
|
||||
#define DB_USABLE_FLAGS (DB_PERSISTENT_FLAGS | MDBX_CREATE | MDBX_DB_ACCEDE)
|
||||
|
||||
#define DB_VALID 0x8000 /* DB handle is valid, for me_dbflags */
|
||||
#define DB_INTERNAL_FLAGS DB_VALID
|
||||
@@ -1402,13 +1413,19 @@ ceil_powerof2(size_t value, size_t granularity) {
|
||||
MDBX_LIFORECLAIM | MDBX_EXCLUSIVE)
|
||||
#define ENV_USABLE_FLAGS (ENV_CHANGEABLE_FLAGS | ENV_CHANGELESS_FLAGS)
|
||||
|
||||
#if !(defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER == 1900)
|
||||
static __maybe_unused void static_checks(void) {
|
||||
STATIC_ASSERT_MSG(INT16_MAX - CORE_DBS == MDBX_MAX_DBI,
|
||||
"Oops, MDBX_MAX_DBI or CORE_DBS?");
|
||||
STATIC_ASSERT_MSG((MDBX_ACCEDE | MDBX_CREATE) ==
|
||||
STATIC_ASSERT_MSG((unsigned)(MDBX_DB_ACCEDE | MDBX_CREATE) ==
|
||||
((DB_USABLE_FLAGS | DB_INTERNAL_FLAGS) &
|
||||
(ENV_USABLE_FLAGS | ENV_INTERNAL_FLAGS)),
|
||||
"Oops, some flags overlapped or wrong");
|
||||
STATIC_ASSERT_MSG((ENV_INTERNAL_FLAGS & ENV_USABLE_FLAGS) == 0,
|
||||
"Oops, some flags overlapped or wrong");
|
||||
}
|
||||
#endif /* Disabled for MSVC 19.0 (VisualStudio 2015) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
1065
src/mdbx.c++
Normal file
1065
src/mdbx.c++
Normal file
File diff suppressed because it is too large
Load Diff
@@ -199,9 +199,8 @@ __extern_C void __assert(const char *function, const char *file, int line,
|
||||
|
||||
#if !defined(__ANDROID_API__) || MDBX_DEBUG
|
||||
|
||||
MDBX_INTERNAL_FUNC void __cold mdbx_assert_fail(const MDBX_env *env,
|
||||
const char *msg,
|
||||
const char *func, int line) {
|
||||
void __cold mdbx_assert_fail(const MDBX_env *env, const char *msg,
|
||||
const char *func, int line) {
|
||||
#if MDBX_DEBUG
|
||||
if (env && env->me_assert_func) {
|
||||
env->me_assert_func(env, msg, func, line);
|
||||
@@ -241,7 +240,7 @@ MDBX_INTERNAL_FUNC void __cold mdbx_assert_fail(const MDBX_env *env,
|
||||
|
||||
#if !defined(__ANDROID_API__)
|
||||
|
||||
MDBX_INTERNAL_FUNC __cold void mdbx_panic(const char *fmt, ...) {
|
||||
__cold void mdbx_panic(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
@@ -514,7 +513,7 @@ MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname) {
|
||||
MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
|
||||
const MDBX_env *env, const char *pathname,
|
||||
mdbx_filehandle_t *fd,
|
||||
mode_t unix_mode_bits) {
|
||||
mdbx_mode_t unix_mode_bits) {
|
||||
*fd = INVALID_HANDLE_VALUE;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@@ -596,7 +596,7 @@ enum mdbx_openfile_purpose {
|
||||
MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
|
||||
const MDBX_env *env, const char *pathname,
|
||||
mdbx_filehandle_t *fd,
|
||||
mode_t unix_mode_bits);
|
||||
mdbx_mode_t unix_mode_bits);
|
||||
MDBX_INTERNAL_FUNC int mdbx_closefile(mdbx_filehandle_t fd);
|
||||
MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname);
|
||||
MDBX_INTERNAL_FUNC int mdbx_is_pipe(mdbx_filehandle_t fd);
|
||||
|
Reference in New Issue
Block a user