mdbx: переработка проверки курсоров на входе API-функций с добавлением cursor_check() (backport).

This commit is contained in:
Леонид Юрьев (Leonid Yuriev)
2025-03-20 01:44:20 +03:00
parent 5fd319bbc2
commit 6c036add8b
9 changed files with 149 additions and 175 deletions

View File

@@ -27,18 +27,12 @@ int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *mc) {
}
int mdbx_cursor_reset(MDBX_cursor *mc) {
if (unlikely(!mc))
return LOG_IFERR(MDBX_EINVAL);
int rc = cursor_check(mc, MDBX_TXN_FINISHED);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
if (likely(mc->signature == cur_signature_live)) {
cursor_reset((cursor_couple_t *)mc);
return MDBX_SUCCESS;
}
if (likely(mc->signature == cur_signature_ready4dispose))
return MDBX_SUCCESS;
return LOG_IFERR(MDBX_EBADSIGN);
cursor_reset((cursor_couple_t *)mc);
return MDBX_SUCCESS;
}
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);
}
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
rc = dbi_check(txn, dbi);
int rc = check_txn(txn, MDBX_TXN_FINISHED | MDBX_TXN_HAS_CHILD);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
if (unlikely(dbi == FREE_DBI && !(txn->flags & MDBX_TXN_RDONLY)))
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 */
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) {
if (unlikely(!src))
return LOG_IFERR(MDBX_EINVAL);
if (unlikely(src->signature != cur_signature_live))
return LOG_IFERR((src->signature == cur_signature_ready4dispose) ? MDBX_EINVAL : MDBX_EBADSIGN);
int rc = cursor_check(src, MDBX_TXN_FINISHED | MDBX_TXN_HAS_CHILD);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
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))
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) {
const int incomparable = INT16_MAX + 1;
if (unlikely(!l))
return r ? -incomparable * 9 : 0;
else if (unlikely(!r))
return incomparable * 9;
if (unlikely(l->signature != cur_signature_live))
return (r->signature == cur_signature_live) ? -incomparable * 8 : 0;
if (unlikely(r->signature != cur_signature_live))
return (l->signature == cur_signature_live) ? incomparable * 8 : 0;
if (unlikely(cursor_check_pure(l) != MDBX_SUCCESS))
return (cursor_check_pure(r) == MDBX_SUCCESS) ? -incomparable * 8 : 0;
if (unlikely(cursor_check_pure(r) != MDBX_SUCCESS))
return (cursor_check_pure(l) == MDBX_SUCCESS) ? incomparable * 8 : 0;
if (unlikely(l->clc != r->clc)) {
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) {
if (unlikely(mc == nullptr))
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);
int rc = cursor_check_ro(mc);
if (unlikely(rc != MDBX_SUCCESS))
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) {
if (unlikely(mc == nullptr))
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 = cursor_check_pure(mc);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
for (intptr_t i = 0; i <= mc->top; ++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) {
if (unlikely(mc == nullptr))
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 = cursor_check_pure(mc);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
if (is_filled(mc) && mc->subcur) {
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) {
if (unlikely(mc == nullptr))
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 = cursor_check_pure(mc);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
for (intptr_t i = 0; i <= mc->top; ++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) {
if (unlikely(mc == nullptr))
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 = cursor_check_pure(mc);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
if (is_filled(mc) && mc->subcur) {
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) {
if (unlikely(mc == nullptr))
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 = cursor_check_pure(mc);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
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) {
if (unlikely(mc == nullptr))
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);
int rc = cursor_check_ro(mc);
if (unlikely(rc != MDBX_SUCCESS))
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));
}
@@ -622,19 +591,13 @@ int mdbx_cursor_get_batch(MDBX_cursor *mc, size_t *count, MDBX_val *pairs, size_
return LOG_IFERR(MDBX_EINVAL);
*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);
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);
int rc = cursor_check_ro(mc);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
if (unlikely(cursor_dbi_changed(mc)))
return LOG_IFERR(MDBX_BAD_DBI);
if (unlikely(mc->subcur))
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) {
if (unlikely(!mc))
return LOG_IFERR(MDBX_EINVAL);
if (unlikely(mc->signature != cur_signature_ready4dispose && mc->signature != cur_signature_live))
return LOG_IFERR(MDBX_EBADSIGN);
int rc = cursor_check(mc, 0);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
cursor_couple_t *couple = container_of(mc, cursor_couple_t, outer);
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) {
if (unlikely(mc == nullptr || key == nullptr || data == nullptr))
if (unlikely(key == nullptr || data == nullptr))
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);
int rc = cursor_check_rw(mc);
if (unlikely(rc != MDBX_SUCCESS))
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. */
if (unlikely(flags & MDBX_MULTIPLE)) {
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;
}
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));
}
int mdbx_cursor_del(MDBX_cursor *mc, MDBX_put_flags_t flags) {
if (unlikely(!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);
int rc = cursor_check_rw(mc);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
if (unlikely(cursor_dbi_changed(mc)))
return LOG_IFERR(MDBX_BAD_DBI);
return LOG_IFERR(cursor_del(mc, flags));
}
__cold int mdbx_cursor_ignord(MDBX_cursor *mc) {
if (unlikely(!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 = cursor_check(mc, 0);
if (unlikely(rc != MDBX_SUCCESS))
return LOG_IFERR(rc);
mc->checking |= z_ignord;
if (mc->subcur)