mirror of
https://github.com/isar/libmdbx.git
synced 2025-04-01 02:32:57 +08:00
mdbx: переработка проверки курсоров на входе API-функций с добавлением cursor_check()
(backport).
This commit is contained in:
parent
5fd319bbc2
commit
6c036add8b
@ -141,7 +141,7 @@ __cold int mdbx_env_warmup(const MDBX_env *env, const MDBX_txn *txn, MDBX_warmup
|
|||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
if (txn) {
|
if (txn) {
|
||||||
int err = check_txn(txn, MDBX_TXN_BLOCKED - MDBX_TXN_ERROR);
|
int err = check_txn(txn, MDBX_TXN_FINISHED | MDBX_TXN_ERROR);
|
||||||
if (unlikely(err != MDBX_SUCCESS))
|
if (unlikely(err != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(err);
|
return LOG_IFERR(err);
|
||||||
}
|
}
|
||||||
|
155
src/api-cursor.c
155
src/api-cursor.c
@ -27,18 +27,12 @@ int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *mc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_reset(MDBX_cursor *mc) {
|
int mdbx_cursor_reset(MDBX_cursor *mc) {
|
||||||
if (unlikely(!mc))
|
int rc = cursor_check(mc, MDBX_TXN_FINISHED);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (likely(mc->signature == cur_signature_live)) {
|
cursor_reset((cursor_couple_t *)mc);
|
||||||
cursor_reset((cursor_couple_t *)mc);
|
return MDBX_SUCCESS;
|
||||||
return MDBX_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (likely(mc->signature == cur_signature_ready4dispose))
|
|
||||||
return MDBX_SUCCESS;
|
|
||||||
|
|
||||||
return LOG_IFERR(MDBX_EBADSIGN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_bind(MDBX_txn *txn, MDBX_cursor *mc, MDBX_dbi dbi) {
|
int mdbx_cursor_bind(MDBX_txn *txn, MDBX_cursor *mc, MDBX_dbi dbi) {
|
||||||
@ -50,17 +44,17 @@ int mdbx_cursor_bind(MDBX_txn *txn, MDBX_cursor *mc, MDBX_dbi dbi) {
|
|||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
int rc = check_txn(txn, MDBX_TXN_FINISHED | MDBX_TXN_HAS_CHILD);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
return LOG_IFERR(rc);
|
|
||||||
|
|
||||||
rc = dbi_check(txn, dbi);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(dbi == FREE_DBI && !(txn->flags & MDBX_TXN_RDONLY)))
|
if (unlikely(dbi == FREE_DBI && !(txn->flags & MDBX_TXN_RDONLY)))
|
||||||
return LOG_IFERR(MDBX_EACCESS);
|
return LOG_IFERR(MDBX_EACCESS);
|
||||||
|
|
||||||
|
rc = dbi_check(txn, dbi);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(mc->backup)) /* Cursor from parent transaction */
|
if (unlikely(mc->backup)) /* Cursor from parent transaction */
|
||||||
LOG_IFERR(MDBX_EINVAL);
|
LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
@ -199,12 +193,11 @@ int mdbx_cursor_close2(MDBX_cursor *mc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_copy(const MDBX_cursor *src, MDBX_cursor *dest) {
|
int mdbx_cursor_copy(const MDBX_cursor *src, MDBX_cursor *dest) {
|
||||||
if (unlikely(!src))
|
int rc = cursor_check(src, MDBX_TXN_FINISHED | MDBX_TXN_HAS_CHILD);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
if (unlikely(src->signature != cur_signature_live))
|
return LOG_IFERR(rc);
|
||||||
return LOG_IFERR((src->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
int rc = mdbx_cursor_bind(src->txn, dest, cursor_dbi(src));
|
rc = mdbx_cursor_bind(src->txn, dest, cursor_dbi(src));
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -277,15 +270,16 @@ int mdbx_txn_release_all_cursors_ex(const MDBX_txn *txn, bool unbind, size_t *co
|
|||||||
|
|
||||||
int mdbx_cursor_compare(const MDBX_cursor *l, const MDBX_cursor *r, bool ignore_multival) {
|
int mdbx_cursor_compare(const MDBX_cursor *l, const MDBX_cursor *r, bool ignore_multival) {
|
||||||
const int incomparable = INT16_MAX + 1;
|
const int incomparable = INT16_MAX + 1;
|
||||||
|
|
||||||
if (unlikely(!l))
|
if (unlikely(!l))
|
||||||
return r ? -incomparable * 9 : 0;
|
return r ? -incomparable * 9 : 0;
|
||||||
else if (unlikely(!r))
|
else if (unlikely(!r))
|
||||||
return incomparable * 9;
|
return incomparable * 9;
|
||||||
|
|
||||||
if (unlikely(l->signature != cur_signature_live))
|
if (unlikely(cursor_check_pure(l) != MDBX_SUCCESS))
|
||||||
return (r->signature == cur_signature_live) ? -incomparable * 8 : 0;
|
return (cursor_check_pure(r) == MDBX_SUCCESS) ? -incomparable * 8 : 0;
|
||||||
if (unlikely(r->signature != cur_signature_live))
|
if (unlikely(cursor_check_pure(r) != MDBX_SUCCESS))
|
||||||
return (l->signature == cur_signature_live) ? incomparable * 8 : 0;
|
return (cursor_check_pure(l) == MDBX_SUCCESS) ? incomparable * 8 : 0;
|
||||||
|
|
||||||
if (unlikely(l->clc != r->clc)) {
|
if (unlikely(l->clc != r->clc)) {
|
||||||
if (l->txn->env != r->txn->env)
|
if (l->txn->env != r->txn->env)
|
||||||
@ -351,13 +345,7 @@ int mdbx_cursor_compare(const MDBX_cursor *l, const MDBX_cursor *r, bool ignore_
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_count_ex(const MDBX_cursor *mc, size_t *count, MDBX_stat *ns, size_t bytes) {
|
int mdbx_cursor_count_ex(const MDBX_cursor *mc, size_t *count, MDBX_stat *ns, size_t bytes) {
|
||||||
if (unlikely(mc == nullptr))
|
int rc = cursor_check_ro(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
|
||||||
|
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
int rc = check_txn(mc->txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
@ -407,11 +395,9 @@ int mdbx_cursor_count(const MDBX_cursor *mc, size_t *count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_on_first(const MDBX_cursor *mc) {
|
int mdbx_cursor_on_first(const MDBX_cursor *mc) {
|
||||||
if (unlikely(mc == nullptr))
|
int rc = cursor_check_pure(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
for (intptr_t i = 0; i <= mc->top; ++i) {
|
for (intptr_t i = 0; i <= mc->top; ++i) {
|
||||||
if (mc->ki[i])
|
if (mc->ki[i])
|
||||||
@ -422,11 +408,9 @@ int mdbx_cursor_on_first(const MDBX_cursor *mc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_on_first_dup(const MDBX_cursor *mc) {
|
int mdbx_cursor_on_first_dup(const MDBX_cursor *mc) {
|
||||||
if (unlikely(mc == nullptr))
|
int rc = cursor_check_pure(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
if (is_filled(mc) && mc->subcur) {
|
if (is_filled(mc) && mc->subcur) {
|
||||||
mc = &mc->subcur->cursor;
|
mc = &mc->subcur->cursor;
|
||||||
@ -440,11 +424,9 @@ int mdbx_cursor_on_first_dup(const MDBX_cursor *mc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_on_last(const MDBX_cursor *mc) {
|
int mdbx_cursor_on_last(const MDBX_cursor *mc) {
|
||||||
if (unlikely(mc == nullptr))
|
int rc = cursor_check_pure(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
for (intptr_t i = 0; i <= mc->top; ++i) {
|
for (intptr_t i = 0; i <= mc->top; ++i) {
|
||||||
size_t nkeys = page_numkeys(mc->pg[i]);
|
size_t nkeys = page_numkeys(mc->pg[i]);
|
||||||
@ -456,11 +438,9 @@ int mdbx_cursor_on_last(const MDBX_cursor *mc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_on_last_dup(const MDBX_cursor *mc) {
|
int mdbx_cursor_on_last_dup(const MDBX_cursor *mc) {
|
||||||
if (unlikely(mc == nullptr))
|
int rc = cursor_check_pure(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
if (is_filled(mc) && mc->subcur) {
|
if (is_filled(mc) && mc->subcur) {
|
||||||
mc = &mc->subcur->cursor;
|
mc = &mc->subcur->cursor;
|
||||||
@ -475,29 +455,18 @@ int mdbx_cursor_on_last_dup(const MDBX_cursor *mc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_eof(const MDBX_cursor *mc) {
|
int mdbx_cursor_eof(const MDBX_cursor *mc) {
|
||||||
if (unlikely(mc == nullptr))
|
int rc = cursor_check_pure(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
return is_eof(mc) ? MDBX_RESULT_TRUE : MDBX_RESULT_FALSE;
|
return is_eof(mc) ? MDBX_RESULT_TRUE : MDBX_RESULT_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, MDBX_cursor_op op) {
|
int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, MDBX_cursor_op op) {
|
||||||
if (unlikely(mc == nullptr))
|
int rc = cursor_check_ro(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
|
||||||
|
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
int rc = check_txn(mc->txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(cursor_dbi_changed(mc)))
|
|
||||||
return LOG_IFERR(MDBX_BAD_DBI);
|
|
||||||
|
|
||||||
return LOG_IFERR(cursor_ops(mc, key, data, op));
|
return LOG_IFERR(cursor_ops(mc, key, data, op));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -622,19 +591,13 @@ int mdbx_cursor_get_batch(MDBX_cursor *mc, size_t *count, MDBX_val *pairs, size_
|
|||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
if (unlikely(mc == nullptr || limit < 4 || limit > INTPTR_MAX - 2))
|
if (unlikely(limit < 4 || limit > INTPTR_MAX - 2))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
int rc = cursor_check_ro(mc);
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
int rc = check_txn(mc->txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(cursor_dbi_changed(mc)))
|
|
||||||
return LOG_IFERR(MDBX_BAD_DBI);
|
|
||||||
|
|
||||||
if (unlikely(mc->subcur))
|
if (unlikely(mc->subcur))
|
||||||
return LOG_IFERR(MDBX_INCOMPATIBLE) /* must be a non-dupsort table */;
|
return LOG_IFERR(MDBX_INCOMPATIBLE) /* must be a non-dupsort table */;
|
||||||
|
|
||||||
@ -703,11 +666,9 @@ bailout:
|
|||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int mdbx_cursor_set_userctx(MDBX_cursor *mc, void *ctx) {
|
int mdbx_cursor_set_userctx(MDBX_cursor *mc, void *ctx) {
|
||||||
if (unlikely(!mc))
|
int rc = cursor_check(mc, 0);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
if (unlikely(mc->signature != cur_signature_ready4dispose && mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR(MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
cursor_couple_t *couple = container_of(mc, cursor_couple_t, outer);
|
cursor_couple_t *couple = container_of(mc, cursor_couple_t, outer);
|
||||||
couple->userctx = ctx;
|
couple->userctx = ctx;
|
||||||
@ -745,21 +706,13 @@ MDBX_dbi mdbx_cursor_dbi(const MDBX_cursor *mc) {
|
|||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, MDBX_put_flags_t flags) {
|
int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, MDBX_put_flags_t flags) {
|
||||||
if (unlikely(mc == nullptr || key == nullptr || data == nullptr))
|
if (unlikely(key == nullptr || data == nullptr))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
int rc = cursor_check_rw(mc);
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
int rc = check_txn_rw(mc->txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(cursor_dbi_changed(mc)))
|
|
||||||
return LOG_IFERR(MDBX_BAD_DBI);
|
|
||||||
|
|
||||||
cASSERT(mc, cursor_is_tracked(mc));
|
|
||||||
|
|
||||||
/* Check this first so counter will always be zero on any early failures. */
|
/* Check this first so counter will always be zero on any early failures. */
|
||||||
if (unlikely(flags & MDBX_MULTIPLE)) {
|
if (unlikely(flags & MDBX_MULTIPLE)) {
|
||||||
if (unlikely(flags & MDBX_RESERVE))
|
if (unlikely(flags & MDBX_RESERVE))
|
||||||
@ -784,35 +737,21 @@ int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, MDBX_p
|
|||||||
data->iov_base = nullptr;
|
data->iov_base = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(mc->txn->flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
|
|
||||||
return LOG_IFERR((mc->txn->flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN);
|
|
||||||
|
|
||||||
return LOG_IFERR(cursor_put_checklen(mc, key, data, flags));
|
return LOG_IFERR(cursor_put_checklen(mc, key, data, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_cursor_del(MDBX_cursor *mc, MDBX_put_flags_t flags) {
|
int mdbx_cursor_del(MDBX_cursor *mc, MDBX_put_flags_t flags) {
|
||||||
if (unlikely(!mc))
|
int rc = cursor_check_rw(mc);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
|
||||||
|
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
int rc = check_txn_rw(mc->txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(cursor_dbi_changed(mc)))
|
|
||||||
return LOG_IFERR(MDBX_BAD_DBI);
|
|
||||||
|
|
||||||
return LOG_IFERR(cursor_del(mc, flags));
|
return LOG_IFERR(cursor_del(mc, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
__cold int mdbx_cursor_ignord(MDBX_cursor *mc) {
|
__cold int mdbx_cursor_ignord(MDBX_cursor *mc) {
|
||||||
if (unlikely(!mc))
|
int rc = cursor_check(mc, 0);
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
if (unlikely(mc->signature != cur_signature_live))
|
|
||||||
return LOG_IFERR((mc->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
mc->checking |= z_ignord;
|
mc->checking |= z_ignord;
|
||||||
if (mc->subcur)
|
if (mc->subcur)
|
||||||
|
@ -16,12 +16,6 @@ __hot static int cursor_diff(const MDBX_cursor *const __restrict x, const MDBX_c
|
|||||||
r->level = 0;
|
r->level = 0;
|
||||||
r->root_nkeys = 0;
|
r->root_nkeys = 0;
|
||||||
|
|
||||||
if (unlikely(x->signature != cur_signature_live))
|
|
||||||
return (x->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN;
|
|
||||||
|
|
||||||
if (unlikely(y->signature != cur_signature_live))
|
|
||||||
return (y->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN;
|
|
||||||
|
|
||||||
int rc = check_txn(x->txn, MDBX_TXN_BLOCKED);
|
int rc = check_txn(x->txn, MDBX_TXN_BLOCKED);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return rc;
|
return rc;
|
||||||
@ -146,12 +140,20 @@ __hot static ptrdiff_t estimate(const tree_t *tree, diff_t *const __restrict dr)
|
|||||||
* Range-Estimation API */
|
* Range-Estimation API */
|
||||||
|
|
||||||
__hot int mdbx_estimate_distance(const MDBX_cursor *first, const MDBX_cursor *last, ptrdiff_t *distance_items) {
|
__hot int mdbx_estimate_distance(const MDBX_cursor *first, const MDBX_cursor *last, ptrdiff_t *distance_items) {
|
||||||
if (unlikely(first == nullptr || last == nullptr || distance_items == nullptr))
|
if (unlikely(!distance_items))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
|
int rc = cursor_check_pure(first);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
|
rc = cursor_check_pure(last);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
*distance_items = 0;
|
*distance_items = 0;
|
||||||
diff_t dr;
|
diff_t dr;
|
||||||
int rc = cursor_diff(last, first, &dr);
|
rc = cursor_diff(last, first, &dr);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
@ -172,14 +174,10 @@ __hot int mdbx_estimate_distance(const MDBX_cursor *first, const MDBX_cursor *la
|
|||||||
|
|
||||||
__hot int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key, MDBX_val *data, MDBX_cursor_op move_op,
|
__hot int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key, MDBX_val *data, MDBX_cursor_op move_op,
|
||||||
ptrdiff_t *distance_items) {
|
ptrdiff_t *distance_items) {
|
||||||
if (unlikely(cursor == nullptr || distance_items == nullptr || move_op == MDBX_GET_CURRENT ||
|
if (unlikely(!distance_items || move_op == MDBX_GET_CURRENT || move_op == MDBX_GET_MULTIPLE))
|
||||||
move_op == MDBX_GET_MULTIPLE))
|
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
if (unlikely(cursor->signature != cur_signature_live))
|
int rc = cursor_check_ro(cursor);
|
||||||
return LOG_IFERR((cursor->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
|
|
||||||
|
|
||||||
int rc = check_txn(cursor->txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
@ -232,10 +230,6 @@ __hot int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key, MDBX_val
|
|||||||
|
|
||||||
__hot int mdbx_estimate_range(const MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *begin_key, const MDBX_val *begin_data,
|
__hot int mdbx_estimate_range(const MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *begin_key, const MDBX_val *begin_data,
|
||||||
const MDBX_val *end_key, const MDBX_val *end_data, ptrdiff_t *size_items) {
|
const MDBX_val *end_key, const MDBX_val *end_data, ptrdiff_t *size_items) {
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
return LOG_IFERR(rc);
|
|
||||||
|
|
||||||
if (unlikely(!size_items))
|
if (unlikely(!size_items))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
@ -248,6 +242,10 @@ __hot int mdbx_estimate_range(const MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val
|
|||||||
if (unlikely(begin_key == MDBX_EPSILON && end_key == MDBX_EPSILON))
|
if (unlikely(begin_key == MDBX_EPSILON && end_key == MDBX_EPSILON))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
|
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
cursor_couple_t begin;
|
cursor_couple_t begin;
|
||||||
/* LY: first, initialize cursor to refresh a DB in case it have DB_STALE */
|
/* LY: first, initialize cursor to refresh a DB in case it have DB_STALE */
|
||||||
rc = cursor_init(&begin.outer, txn, dbi);
|
rc = cursor_init(&begin.outer, txn, dbi);
|
||||||
|
@ -51,15 +51,15 @@ __cold int mdbx_dbi_dupsort_depthmask(const MDBX_txn *txn, MDBX_dbi dbi, uint32_
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_canary_get(const MDBX_txn *txn, MDBX_canary *canary) {
|
int mdbx_canary_get(const MDBX_txn *txn, MDBX_canary *canary) {
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
if (unlikely(canary == nullptr))
|
||||||
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
|
int rc = check_txn(txn, MDBX_TXN_BLOCKED - MDBX_TXN_PARKED);
|
||||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||||
memset(canary, 0, sizeof(*canary));
|
memset(canary, 0, sizeof(*canary));
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(canary == nullptr))
|
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
|
||||||
|
|
||||||
*canary = txn->canary;
|
*canary = txn->canary;
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -68,13 +68,13 @@ int mdbx_get(const MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *d
|
|||||||
DKBUF_DEBUG;
|
DKBUF_DEBUG;
|
||||||
DEBUG("===> get db %u key [%s]", dbi, DKEY_DEBUG(key));
|
DEBUG("===> get db %u key [%s]", dbi, DKEY_DEBUG(key));
|
||||||
|
|
||||||
|
if (unlikely(!key || !data))
|
||||||
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(!key || !data))
|
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
|
||||||
|
|
||||||
cursor_couple_t cx;
|
cursor_couple_t cx;
|
||||||
rc = cursor_init(&cx.outer, txn, dbi);
|
rc = cursor_init(&cx.outer, txn, dbi);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
@ -84,15 +84,12 @@ int mdbx_get(const MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *d
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_get_equal_or_great(const MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) {
|
int mdbx_get_equal_or_great(const MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) {
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
return LOG_IFERR(rc);
|
|
||||||
|
|
||||||
if (unlikely(!key || !data))
|
if (unlikely(!key || !data))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
if (unlikely(txn->flags & MDBX_TXN_BLOCKED))
|
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
||||||
return LOG_IFERR(MDBX_BAD_TXN);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
cursor_couple_t cx;
|
cursor_couple_t cx;
|
||||||
rc = cursor_init(&cx.outer, txn, dbi);
|
rc = cursor_init(&cx.outer, txn, dbi);
|
||||||
@ -106,13 +103,13 @@ int mdbx_get_ex(const MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data
|
|||||||
DKBUF_DEBUG;
|
DKBUF_DEBUG;
|
||||||
DEBUG("===> get db %u key [%s]", dbi, DKEY_DEBUG(key));
|
DEBUG("===> get db %u key [%s]", dbi, DKEY_DEBUG(key));
|
||||||
|
|
||||||
|
if (unlikely(!key || !data))
|
||||||
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
if (unlikely(!key || !data))
|
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
|
||||||
|
|
||||||
cursor_couple_t cx;
|
cursor_couple_t cx;
|
||||||
rc = cursor_init(&cx.outer, txn, dbi);
|
rc = cursor_init(&cx.outer, txn, dbi);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
@ -179,7 +176,7 @@ int mdbx_canary_put(MDBX_txn *txn, const MDBX_canary *canary) {
|
|||||||
* расположен в той-же странице памяти, в том числе для многостраничных
|
* расположен в той-же странице памяти, в том числе для многостраничных
|
||||||
* P_LARGE страниц с длинными данными. */
|
* P_LARGE страниц с длинными данными. */
|
||||||
int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
|
int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
int rc = check_txn(txn, MDBX_TXN_BLOCKED - MDBX_TXN_PARKED);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
@ -215,18 +212,15 @@ int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, const MDBX_val *data) {
|
int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, const MDBX_val *data) {
|
||||||
int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
return LOG_IFERR(rc);
|
|
||||||
|
|
||||||
if (unlikely(!key))
|
if (unlikely(!key))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
if (unlikely(dbi <= FREE_DBI))
|
if (unlikely(dbi <= FREE_DBI))
|
||||||
return LOG_IFERR(MDBX_BAD_DBI);
|
return LOG_IFERR(MDBX_BAD_DBI);
|
||||||
|
|
||||||
if (unlikely(txn->flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
|
int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED);
|
||||||
return LOG_IFERR((txn->flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
cursor_couple_t cx;
|
cursor_couple_t cx;
|
||||||
rc = cursor_init(&cx.outer, txn, dbi);
|
rc = cursor_init(&cx.outer, txn, dbi);
|
||||||
@ -254,10 +248,6 @@ int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, const MDBX_val *d
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data, MDBX_put_flags_t flags) {
|
int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data, MDBX_put_flags_t flags) {
|
||||||
int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED);
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
|
||||||
return LOG_IFERR(rc);
|
|
||||||
|
|
||||||
if (unlikely(!key || !data))
|
if (unlikely(!key || !data))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
@ -268,8 +258,9 @@ int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data, M
|
|||||||
MDBX_APPENDDUP | MDBX_CURRENT | MDBX_MULTIPLE)))
|
MDBX_APPENDDUP | MDBX_CURRENT | MDBX_MULTIPLE)))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
if (unlikely(txn->flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
|
int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED);
|
||||||
return LOG_IFERR((txn->flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
cursor_couple_t cx;
|
cursor_couple_t cx;
|
||||||
rc = cursor_init(&cx.outer, txn, dbi);
|
rc = cursor_init(&cx.outer, txn, dbi);
|
||||||
@ -330,10 +321,6 @@ int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data, M
|
|||||||
|
|
||||||
int mdbx_replace_ex(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *new_data, MDBX_val *old_data,
|
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) {
|
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 LOG_IFERR(rc);
|
|
||||||
|
|
||||||
if (unlikely(!key || !old_data || old_data == new_data))
|
if (unlikely(!key || !old_data || old_data == new_data))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
@ -350,6 +337,10 @@ int mdbx_replace_ex(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *
|
|||||||
MDBX_APPENDDUP | MDBX_CURRENT)))
|
MDBX_APPENDDUP | MDBX_CURRENT)))
|
||||||
return LOG_IFERR(MDBX_EINVAL);
|
return LOG_IFERR(MDBX_EINVAL);
|
||||||
|
|
||||||
|
int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
cursor_couple_t cx;
|
cursor_couple_t cx;
|
||||||
rc = cursor_init(&cx.outer, txn, dbi);
|
rc = cursor_init(&cx.outer, txn, dbi);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
@ -9,7 +9,7 @@ __attribute__((__no_sanitize_thread__, __noinline__))
|
|||||||
#endif
|
#endif
|
||||||
int mdbx_txn_straggler(const MDBX_txn *txn, int *percent)
|
int mdbx_txn_straggler(const MDBX_txn *txn, int *percent)
|
||||||
{
|
{
|
||||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
int rc = check_txn(txn, MDBX_TXN_BLOCKED - MDBX_TXN_PARKED);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR((rc > 0) ? -rc : rc);
|
return LOG_IFERR((rc > 0) ? -rc : rc);
|
||||||
|
|
||||||
@ -200,9 +200,13 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, M
|
|||||||
MDBX_txn *txn = nullptr;
|
MDBX_txn *txn = nullptr;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
/* Nested transactions: Max 1 child, write txns only, no writemap */
|
/* Nested transactions: Max 1 child, write txns only, no writemap */
|
||||||
rc = check_txn_rw(parent, MDBX_TXN_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED);
|
rc = check_txn(parent, MDBX_TXN_BLOCKED - MDBX_TXN_PARKED);
|
||||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
if (rc == MDBX_BAD_TXN && (parent->flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)) == 0) {
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
|
if (unlikely(parent->flags & (MDBX_TXN_RDONLY | MDBX_WRITEMAP))) {
|
||||||
|
rc = MDBX_BAD_TXN;
|
||||||
|
if ((parent->flags & MDBX_TXN_RDONLY) == 0) {
|
||||||
ERROR("%s mode is incompatible with nested transactions", "MDBX_WRITEMAP");
|
ERROR("%s mode is incompatible with nested transactions", "MDBX_WRITEMAP");
|
||||||
rc = MDBX_INCOMPATIBLE;
|
rc = MDBX_INCOMPATIBLE;
|
||||||
}
|
}
|
||||||
|
14
src/cogs.h
14
src/cogs.h
@ -416,10 +416,11 @@ static __always_inline int check_txn(const MDBX_txn *txn, int bad_bits) {
|
|||||||
return MDBX_EPERM;
|
return MDBX_EPERM;
|
||||||
|
|
||||||
if (unlikely(txn->flags & bad_bits)) {
|
if (unlikely(txn->flags & bad_bits)) {
|
||||||
|
if ((bad_bits & MDBX_TXN_RDONLY) && unlikely(txn->flags & MDBX_TXN_RDONLY))
|
||||||
|
return MDBX_EACCESS;
|
||||||
if ((bad_bits & MDBX_TXN_PARKED) == 0)
|
if ((bad_bits & MDBX_TXN_PARKED) == 0)
|
||||||
return MDBX_BAD_TXN;
|
return MDBX_BAD_TXN;
|
||||||
else
|
return txn_check_badbits_parked(txn, bad_bits);
|
||||||
return txn_check_badbits_parked(txn, bad_bits);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,14 +438,7 @@ static __always_inline int check_txn(const MDBX_txn *txn, int bad_bits) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int check_txn_rw(const MDBX_txn *txn, int bad_bits) {
|
static inline int check_txn_rw(const MDBX_txn *txn, int bad_bits) {
|
||||||
int err = check_txn(txn, bad_bits & ~MDBX_TXN_PARKED);
|
return check_txn(txn, (bad_bits | MDBX_TXN_RDONLY) & ~MDBX_TXN_PARKED);
|
||||||
if (unlikely(err))
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (unlikely(txn->flags & MDBX_TXN_RDONLY))
|
|
||||||
return MDBX_EACCESS;
|
|
||||||
|
|
||||||
return MDBX_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
30
src/cursor.c
30
src/cursor.c
@ -2329,3 +2329,33 @@ __hot int cursor_ops(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, const MDBX_
|
|||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cursor_check(const MDBX_cursor *mc, int txn_bad_bits) {
|
||||||
|
if (unlikely(mc == nullptr))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
|
if (unlikely(mc->signature != cur_signature_live)) {
|
||||||
|
if (mc->signature != cur_signature_ready4dispose)
|
||||||
|
return MDBX_EBADSIGN;
|
||||||
|
return (txn_bad_bits > MDBX_TXN_FINISHED) ? MDBX_EINVAL : MDBX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* проверяем что курсор в связном списке для отслеживания, исключение допускается только для read-only операций для
|
||||||
|
* служебных/временных курсоров на стеке. */
|
||||||
|
MDBX_MAYBE_UNUSED char stack_top[sizeof(void *)];
|
||||||
|
cASSERT(mc, cursor_is_tracked(mc) || (!(txn_bad_bits & MDBX_TXN_RDONLY) && stack_top < (char *)mc &&
|
||||||
|
(char *)mc - stack_top < (ptrdiff_t)globals.sys_pagesize * 4));
|
||||||
|
|
||||||
|
if (txn_bad_bits) {
|
||||||
|
int rc = check_txn(mc->txn, txn_bad_bits);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||||
|
cASSERT(mc, rc != MDBX_RESULT_TRUE);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(cursor_dbi_changed(mc)))
|
||||||
|
return MDBX_BAD_DBI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
}
|
||||||
|
15
src/cursor.h
15
src/cursor.h
@ -292,6 +292,21 @@ MDBX_NOTHROW_PURE_FUNCTION static inline bool check_leaf_type(const MDBX_cursor
|
|||||||
return (((page_type(mp) ^ mc->checking) & (z_branch | z_leaf | z_largepage | z_dupfix)) == 0);
|
return (((page_type(mp) ^ mc->checking) & (z_branch | z_leaf | z_largepage | z_dupfix)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MDBX_INTERNAL int cursor_check(const MDBX_cursor *mc, int txn_bad_bits);
|
||||||
|
|
||||||
|
/* без необходимости доступа к данным, без активации припаркованных транзакций. */
|
||||||
|
static inline int cursor_check_pure(const MDBX_cursor *mc) {
|
||||||
|
return cursor_check(mc, MDBX_TXN_BLOCKED - MDBX_TXN_PARKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* для чтения данных, с активацией припаркованных транзакций. */
|
||||||
|
static inline int cursor_check_ro(const MDBX_cursor *mc) { return cursor_check(mc, MDBX_TXN_BLOCKED); }
|
||||||
|
|
||||||
|
/* для записи данных. */
|
||||||
|
static inline int cursor_check_rw(const MDBX_cursor *mc) {
|
||||||
|
return cursor_check(mc, (MDBX_TXN_BLOCKED - MDBX_TXN_PARKED) | MDBX_TXN_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
MDBX_INTERNAL MDBX_cursor *cursor_eot(MDBX_cursor *mc, MDBX_txn *txn, const bool merge);
|
MDBX_INTERNAL MDBX_cursor *cursor_eot(MDBX_cursor *mc, MDBX_txn *txn, const bool merge);
|
||||||
MDBX_INTERNAL int cursor_shadow(MDBX_cursor *mc, MDBX_txn *nested, const size_t dbi);
|
MDBX_INTERNAL int cursor_shadow(MDBX_cursor *mc, MDBX_txn *nested, const size_t dbi);
|
||||||
|
|
||||||
|
@ -995,7 +995,10 @@ int txn_check_badbits_parked(const MDBX_txn *txn, int bad_bits) {
|
|||||||
* - но при распарковке поломанные транзакции завершаются.
|
* - но при распарковке поломанные транзакции завершаются.
|
||||||
* - получается что транзакцию можно припарковать, потом поломать вызвав
|
* - получается что транзакцию можно припарковать, потом поломать вызвав
|
||||||
* mdbx_txn_break(), но далее любое её использование приведет к завершению
|
* mdbx_txn_break(), но далее любое её использование приведет к завершению
|
||||||
* при распарковке. */
|
* при распарковке.
|
||||||
|
*
|
||||||
|
* Поэтому для припаркованных транзакций возвращается ошибка если не-включена
|
||||||
|
* авто-распарковка, либо есть другие плохие биты. */
|
||||||
if ((txn->flags & (bad_bits | MDBX_TXN_AUTOUNPARK)) != (MDBX_TXN_PARKED | MDBX_TXN_AUTOUNPARK))
|
if ((txn->flags & (bad_bits | MDBX_TXN_AUTOUNPARK)) != (MDBX_TXN_PARKED | MDBX_TXN_AUTOUNPARK))
|
||||||
return LOG_IFERR(MDBX_BAD_TXN);
|
return LOG_IFERR(MDBX_BAD_TXN);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user