From 02b56e185f5712cc08a3d990d6a8f3e908d595ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Mon, 31 Mar 2025 23:28:31 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20`rkl=5Ffind()`=20=D0=B8=20`rkl=5Fmer?= =?UTF-8?q?ge()`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/rkl.c | 69 ++++++++++++++++++++++++++++++++++++++++--------------- src/rkl.h | 9 ++++---- 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/rkl.c b/src/rkl.c index 76c6a018..78115026 100644 --- a/src/rkl.c +++ b/src/rkl.c @@ -118,17 +118,11 @@ int rkl_copy(const rkl_t *src, rkl_t *dst) { size_t rkl_len(const rkl_t *rkl) { return rkl_empty(rkl) ? 0 : rkl->solid_end - rkl->solid_begin + rkl->list_length; } -__hot bool rkl_find(const rkl_t *rkl, txnid_t id, rkl_iter_t *iter) { +__hot bool rkl_contain(const rkl_t *rkl, txnid_t id) { assert(rkl_check(rkl)); - if (!rkl_empty(rkl)) { - if (id >= rkl->solid_begin && id < rkl->solid_end) { - if (iter) { - *iter = rkl_iterator(rkl, false); - iter->pos = iter->solid_offset + id - rkl->solid_begin; - } - return true; - } - + if (id >= rkl->solid_begin && id < rkl->solid_end) + return true; + if (rkl->list_length) { const txnid_t *it = rkl_bsearch(rkl->list, rkl->list_length, id); const txnid_t *const end = rkl->list + rkl->list_length; assert(it >= rkl->list && it <= end); @@ -136,13 +130,32 @@ __hot bool rkl_find(const rkl_t *rkl, txnid_t id, rkl_iter_t *iter) { assert(RKL_ORDERED(it[-1], id)); if (it != end) { assert(!RKL_ORDERED(it[0], id)); - if (*it == id) { - if (iter) { - *iter = rkl_iterator(rkl, false); - iter->pos = it - rkl->list; - } - return true; - } + return *it == id; + } + } + return false; +} + +__hot bool rkl_find(const rkl_t *rkl, txnid_t id, rkl_iter_t *iter) { + assert(rkl_check(rkl)); + *iter = rkl_iterator(rkl, false); + if (id >= rkl->solid_begin) { + if (id < rkl->solid_end) { + iter->pos = iter->solid_offset + (unsigned)(id - rkl->solid_begin); + return true; + } + iter->pos = (unsigned)(rkl->solid_end - rkl->solid_begin); + } + if (rkl->list_length) { + const txnid_t *it = rkl_bsearch(rkl->list, rkl->list_length, id); + const txnid_t *const end = rkl->list + rkl->list_length; + assert(it >= rkl->list && it <= end); + if (it != rkl->list) + assert(RKL_ORDERED(it[-1], id)); + iter->pos += (unsigned)(it - rkl->list); + if (it != end) { + assert(!RKL_ORDERED(it[0], id)); + return *it == id; } } return false; @@ -366,7 +379,6 @@ txnid_t rkl_pop(rkl_t *rkl, const bool highest_not_lowest) { txnid_t rkl_lowest(const rkl_t *rkl) { if (rkl->list_length) return (solid_empty(rkl) || rkl->list[0] < rkl->solid_begin) ? rkl->list[0] : rkl->solid_begin; - return !solid_empty(rkl) ? rkl->solid_begin : INVALID_TXNID; } @@ -374,10 +386,29 @@ txnid_t rkl_highest(const rkl_t *rkl) { if (rkl->list_length) return (solid_empty(rkl) || rkl->list[rkl->list_length - 1] >= rkl->solid_end) ? rkl->list[rkl->list_length - 1] : rkl->solid_end - 1; - return !solid_empty(rkl) ? rkl->solid_end - 1 : 0; } +int rkl_merge(rkl_t *dst, const rkl_t *src, bool ignore_duplicates) { + if (src->list_length) { + size_t i = src->list_length; + do { + int err = rkl_push(dst, src->list[i - 1], false); + if (unlikely(err != MDBX_SUCCESS) && (!ignore_duplicates || err != MDBX_RESULT_TRUE)) + return err; + } while (--i); + } + + txnid_t id = src->solid_begin; + while (id < src->solid_end) { + int err = rkl_push(dst, id, false); + if (unlikely(err != MDBX_SUCCESS) && (!ignore_duplicates || err != MDBX_RESULT_TRUE)) + return err; + ++id; + } + return MDBX_SUCCESS; +} + rkl_iter_t rkl_iterator(const rkl_t *rkl, const bool reverse) { rkl_iter_t iter = {.rkl = rkl, .pos = reverse ? rkl_len(rkl) : 0, .solid_offset = 0}; if (!solid_empty(rkl) && rkl->list_length) { diff --git a/src/rkl.h b/src/rkl.h index b4f76858..b7e8b7cd 100644 --- a/src/rkl.h +++ b/src/rkl.h @@ -50,6 +50,7 @@ MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION static inline txnid_t rkl_edge(cons MDBX_MAYBE_UNUSED MDBX_INTERNAL __must_check_result int rkl_push(rkl_t *rkl, const txnid_t id, const bool known_continuous); MDBX_MAYBE_UNUSED MDBX_INTERNAL txnid_t rkl_pop(rkl_t *rkl, const bool highest_not_lowest); +MDBX_MAYBE_UNUSED MDBX_INTERNAL __must_check_result int rkl_merge(rkl_t *dst, const rkl_t *src, bool ignore_duplicates); /* Итератор для rkl. * Обеспечивает изоляцию внутреннего устройства rkl от остального кода, чем существенно его упрощает. @@ -63,11 +64,9 @@ typedef struct MDBX_rkl_iter { MDBX_MAYBE_UNUSED MDBX_INTERNAL __must_check_result rkl_iter_t rkl_iterator(const rkl_t *rkl, const bool reverse); MDBX_MAYBE_UNUSED MDBX_INTERNAL __must_check_result txnid_t rkl_turn(rkl_iter_t *iter, const bool reverse); MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION MDBX_INTERNAL size_t rkl_left(rkl_iter_t *iter, const bool reverse); -MDBX_MAYBE_UNUSED MDBX_INTERNAL __must_check_result bool rkl_find(const rkl_t *rkl, const txnid_t id, rkl_iter_t *iter); -MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION __must_check_result static inline bool rkl_contain(const rkl_t *rkl, - txnid_t id) { - return rkl_find(rkl, id, nullptr); -} +MDBX_MAYBE_UNUSED MDBX_INTERNAL bool rkl_find(const rkl_t *rkl, const txnid_t id, rkl_iter_t *iter); +MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION __must_check_result MDBX_INTERNAL bool rkl_contain(const rkl_t *rkl, + txnid_t id); typedef struct MDBX_rkl_hole { txnid_t begin;