mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 18:14:12 +08:00
mdbx: рефакторинг и микро-оптимизация cursor_next|_prev()
для dupsort-узлов.
- меньше сравнений и переходов. - вложенный курсор всегда сбрасывается/очищается при переходе с dupsort-узла.
This commit is contained in:
parent
225f548339
commit
10abf73191
65
src/core.c
65
src/core.c
@ -3391,7 +3391,8 @@ static int __must_check_result cursor_last(MDBX_cursor *mc, MDBX_val *key,
|
|||||||
static int __must_check_result cursor_init(MDBX_cursor *mc, const MDBX_txn *txn,
|
static int __must_check_result cursor_init(MDBX_cursor *mc, const MDBX_txn *txn,
|
||||||
size_t dbi);
|
size_t dbi);
|
||||||
static int __must_check_result cursor_xinit0(MDBX_cursor *mc);
|
static int __must_check_result cursor_xinit0(MDBX_cursor *mc);
|
||||||
static int __must_check_result cursor_xinit1(MDBX_cursor *mc, MDBX_node *node,
|
static int __must_check_result cursor_xinit1(MDBX_cursor *mc,
|
||||||
|
const MDBX_node *node,
|
||||||
const MDBX_page *mp);
|
const MDBX_page *mp);
|
||||||
static int __must_check_result cursor_xinit2(MDBX_cursor *mc,
|
static int __must_check_result cursor_xinit2(MDBX_cursor *mc,
|
||||||
MDBX_xcursor *src_mx,
|
MDBX_xcursor *src_mx,
|
||||||
@ -16616,39 +16617,41 @@ static int cursor_sibling(MDBX_cursor *mc, int dir) {
|
|||||||
/* Move the cursor to the next data item. */
|
/* Move the cursor to the next data item. */
|
||||||
static int cursor_next(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
static int cursor_next(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
||||||
MDBX_cursor_op op) {
|
MDBX_cursor_op op) {
|
||||||
MDBX_page *mp;
|
assert(op == MDBX_NEXT || op == MDBX_NEXT_DUP || op == MDBX_NEXT_NODUP);
|
||||||
MDBX_node *node;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (unlikely(mc->mc_flags & C_DEL) && op == MDBX_NEXT_DUP)
|
if (unlikely(mc->mc_flags & C_DEL) && op == MDBX_NEXT_DUP)
|
||||||
return MDBX_NOTFOUND;
|
return MDBX_NOTFOUND;
|
||||||
|
|
||||||
if (unlikely(!(mc->mc_flags & C_INITIALIZED)))
|
if (unlikely(!(mc->mc_flags & C_INITIALIZED))) {
|
||||||
|
if (unlikely(mc->mc_flags & C_SUB))
|
||||||
|
return MDBX_NOTFOUND;
|
||||||
return cursor_first(mc, key, data);
|
return cursor_first(mc, key, data);
|
||||||
|
}
|
||||||
|
|
||||||
mp = mc->mc_pg[mc->mc_top];
|
const MDBX_page *mp = mc->mc_pg[mc->mc_top];
|
||||||
if (unlikely(mc->mc_flags & C_EOF)) {
|
if (unlikely(mc->mc_flags & C_EOF)) {
|
||||||
if (mc->mc_ki[mc->mc_top] + (size_t)1 >= page_numkeys(mp))
|
if (mc->mc_ki[mc->mc_top] + (size_t)1 >= page_numkeys(mp))
|
||||||
return MDBX_NOTFOUND;
|
return MDBX_NOTFOUND;
|
||||||
mc->mc_flags ^= C_EOF;
|
mc->mc_flags ^= C_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc->mc_db->md_flags & MDBX_DUPSORT) {
|
if (mc->mc_xcursor) {
|
||||||
node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
if (op != MDBX_NEXT_NODUP) {
|
||||||
|
const MDBX_node *node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
||||||
if (node_flags(node) & F_DUPDATA) {
|
if (node_flags(node) & F_DUPDATA) {
|
||||||
if (op == MDBX_NEXT || op == MDBX_NEXT_DUP) {
|
|
||||||
rc = cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_NEXT);
|
rc = cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_NEXT);
|
||||||
if (op != MDBX_NEXT || rc != MDBX_NOTFOUND) {
|
if (likely(rc == MDBX_SUCCESS)) {
|
||||||
if (likely(rc == MDBX_SUCCESS))
|
|
||||||
get_key_optional(node, key);
|
get_key_optional(node, key);
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
}
|
||||||
|
if (unlikely(rc != MDBX_NOTFOUND))
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
if (op != MDBX_NEXT)
|
||||||
} else {
|
|
||||||
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
|
|
||||||
if (op == MDBX_NEXT_DUP)
|
|
||||||
return MDBX_NOTFOUND;
|
return MDBX_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("cursor_next: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno,
|
DEBUG("cursor_next: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno,
|
||||||
@ -16692,7 +16695,7 @@ skip:
|
|||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
const MDBX_node *node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
||||||
if (node_flags(node) & F_DUPDATA) {
|
if (node_flags(node) & F_DUPDATA) {
|
||||||
rc = cursor_xinit1(mc, node, mp);
|
rc = cursor_xinit1(mc, node, mp);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
@ -16713,40 +16716,41 @@ skip:
|
|||||||
/* Move the cursor to the previous data item. */
|
/* Move the cursor to the previous data item. */
|
||||||
static int cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
static int cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
||||||
MDBX_cursor_op op) {
|
MDBX_cursor_op op) {
|
||||||
MDBX_page *mp;
|
assert(op == MDBX_PREV || op == MDBX_PREV_DUP || op == MDBX_PREV_NODUP);
|
||||||
MDBX_node *node;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (unlikely(mc->mc_flags & C_DEL) && op == MDBX_PREV_DUP)
|
if (unlikely(mc->mc_flags & C_DEL) && op == MDBX_PREV_DUP)
|
||||||
return MDBX_NOTFOUND;
|
return MDBX_NOTFOUND;
|
||||||
|
|
||||||
if (unlikely(!(mc->mc_flags & C_INITIALIZED))) {
|
if (unlikely(!(mc->mc_flags & C_INITIALIZED))) {
|
||||||
|
if (unlikely(mc->mc_flags & C_SUB))
|
||||||
|
return MDBX_NOTFOUND;
|
||||||
rc = cursor_last(mc, key, data);
|
rc = cursor_last(mc, key, data);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return rc;
|
return rc;
|
||||||
mc->mc_ki[mc->mc_top]++;
|
mc->mc_ki[mc->mc_top]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp = mc->mc_pg[mc->mc_top];
|
const MDBX_page *mp = mc->mc_pg[mc->mc_top];
|
||||||
if ((mc->mc_db->md_flags & MDBX_DUPSORT) &&
|
if (mc->mc_xcursor) {
|
||||||
mc->mc_ki[mc->mc_top] < page_numkeys(mp)) {
|
if (op != MDBX_PREV_NODUP) {
|
||||||
node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
if (likely(mc->mc_ki[mc->mc_top] < page_numkeys(mp))) {
|
||||||
|
const MDBX_node *node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
||||||
if (node_flags(node) & F_DUPDATA) {
|
if (node_flags(node) & F_DUPDATA) {
|
||||||
if (op == MDBX_PREV || op == MDBX_PREV_DUP) {
|
|
||||||
rc = cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_PREV);
|
rc = cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_PREV);
|
||||||
if (op != MDBX_PREV || rc != MDBX_NOTFOUND) {
|
|
||||||
if (likely(rc == MDBX_SUCCESS)) {
|
if (likely(rc == MDBX_SUCCESS)) {
|
||||||
get_key_optional(node, key);
|
get_key_optional(node, key);
|
||||||
mc->mc_flags &= ~C_EOF;
|
mc->mc_flags &= ~C_EOF;
|
||||||
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
if (unlikely(rc != MDBX_NOTFOUND))
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
if (op != MDBX_PREV)
|
||||||
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
|
|
||||||
if (op == MDBX_PREV_DUP)
|
|
||||||
return MDBX_NOTFOUND;
|
return MDBX_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("cursor_prev: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno,
|
DEBUG("cursor_prev: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno,
|
||||||
@ -16782,8 +16786,7 @@ static int cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
const MDBX_node *node = page_node(mp, mc->mc_ki[mc->mc_top]);
|
||||||
|
|
||||||
if (node_flags(node) & F_DUPDATA) {
|
if (node_flags(node) & F_DUPDATA) {
|
||||||
rc = cursor_xinit1(mc, node, mp);
|
rc = cursor_xinit1(mc, node, mp);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
@ -17234,6 +17237,8 @@ static __hot int cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
cASSERT(mc, !mc->mc_xcursor || !(mc->mc_xcursor->mx_cursor.mc_flags &
|
||||||
|
C_INITIALIZED));
|
||||||
rc = node_read(mc, node, data, mp);
|
rc = node_read(mc, node, data, mp);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
return rc;
|
return rc;
|
||||||
@ -19025,7 +19030,7 @@ static int cursor_xinit0(MDBX_cursor *mc) {
|
|||||||
* [in] mc The main cursor whose sorted-dups cursor is to be initialized.
|
* [in] mc The main cursor whose sorted-dups cursor is to be initialized.
|
||||||
* [in] node The data containing the MDBX_db record for the sorted-dup database.
|
* [in] node The data containing the MDBX_db record for the sorted-dup database.
|
||||||
*/
|
*/
|
||||||
static int cursor_xinit1(MDBX_cursor *mc, MDBX_node *node,
|
static int cursor_xinit1(MDBX_cursor *mc, const MDBX_node *node,
|
||||||
const MDBX_page *mp) {
|
const MDBX_page *mp) {
|
||||||
MDBX_xcursor *mx = mc->mc_xcursor;
|
MDBX_xcursor *mx = mc->mc_xcursor;
|
||||||
if (!MDBX_DISABLE_VALIDATION && unlikely(mx == nullptr)) {
|
if (!MDBX_DISABLE_VALIDATION && unlikely(mx == nullptr)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user