From: Vladimir Davydov <vdavydov.dev@gmail.com> To: kostja.osipov@gmail.com Cc: tarantool-patches@freelists.org Subject: [PATCH 07/13] vinyl: propagate tuple comparison hints to read iterator Date: Tue, 2 Apr 2019 20:33:44 +0300 [thread overview] Message-ID: <92bf17d61f69c18f907fe9041027ab43df8910f9.1554225074.git.vdavydov.dev@gmail.com> (raw) In-Reply-To: <cover.1554225074.git.vdavydov.dev@gmail.com> In-Reply-To: <cover.1554225074.git.vdavydov.dev@gmail.com> This patch propagates hints from source iterators (mem, run, txw, cache) to the read iterator code. Now, source iterators take and return comparison hints along with statements. The read iterator uses the hints to speed up tuple comparisons. Apart from speeding up lookups, this is also needed for multikey index support, because multikey indexes will reuse hints to store offsets of indexed array entries. --- src/box/vy_cache.c | 28 ++++---- src/box/vy_cache.h | 11 +-- src/box/vy_history.c | 9 ++- src/box/vy_history.h | 15 ++-- src/box/vy_mem.c | 16 ++--- src/box/vy_mem.h | 7 +- src/box/vy_point_lookup.c | 53 ++++++++------ src/box/vy_read_iterator.c | 170 +++++++++++++++++++++++++++------------------ src/box/vy_read_iterator.h | 5 ++ src/box/vy_run.c | 47 ++++++++----- src/box/vy_run.h | 5 +- src/box/vy_tx.c | 22 +++--- src/box/vy_tx.h | 6 +- test/unit/vy_cache.c | 12 ++-- test/unit/vy_mem.c | 22 +++--- 15 files changed, 255 insertions(+), 173 deletions(-) diff --git a/src/box/vy_cache.c b/src/box/vy_cache.c index 8fafd648..a4a767bc 100644 --- a/src/box/vy_cache.c +++ b/src/box/vy_cache.c @@ -431,15 +431,16 @@ vy_cache_add(struct vy_cache *cache, struct tuple *stmt, } struct tuple * -vy_cache_get(struct vy_cache *cache, const struct tuple *key) +vy_cache_get(struct vy_cache *cache, const struct tuple *key, + hint_t hint, hint_t *ret_hint) { - hint_t hint = vy_stmt_hint(key, cache->cmp_def); struct vy_cache_tree_key tree_key; tree_key = vy_cache_tree_key(key, hint); struct vy_cache_entry **entry = vy_cache_tree_find(&cache->cache_tree, &tree_key); if (entry == NULL) return NULL; + *ret_hint = (*entry)->hint; return (*entry)->stmt; } @@ -732,20 +733,19 @@ vy_cache_iterator_next(struct vy_cache_iterator *itr, if (itr->curr_stmt != NULL) { vy_stmt_counter_acct_tuple(&itr->cache->stat.get, itr->curr_stmt); - return vy_history_append_stmt(history, itr->curr_stmt); + return vy_history_append_stmt(history, itr->curr_stmt, + itr->curr_hint); } return 0; } NODISCARD int vy_cache_iterator_skip(struct vy_cache_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history, bool *stop) { assert(!itr->search_started || itr->version == itr->cache->version); - hint_t last_hint = last_stmt == NULL ? HINT_NONE : - vy_stmt_hint(last_stmt, itr->cache->cmp_def); /* * Check if the iterator is already positioned * at the statement following last_stmt. @@ -768,22 +768,20 @@ vy_cache_iterator_skip(struct vy_cache_iterator *itr, if (itr->curr_stmt != NULL) { vy_stmt_counter_acct_tuple(&itr->cache->stat.get, itr->curr_stmt); - return vy_history_append_stmt(history, itr->curr_stmt); + return vy_history_append_stmt(history, itr->curr_stmt, + itr->curr_hint); } return 0; } NODISCARD int vy_cache_iterator_restore(struct vy_cache_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history, bool *stop) { if (!itr->search_started || itr->version == itr->cache->version) return 0; - hint_t last_hint = last_stmt == NULL ? HINT_NONE : - vy_stmt_hint(last_stmt, itr->cache->cmp_def); - /* Check if the iterator position is still valid. */ bool pos_invalid = false; struct vy_cache_tree *tree = &itr->cache->cache_tree; @@ -865,7 +863,8 @@ vy_cache_iterator_restore(struct vy_cache_iterator *itr, if (itr->curr_stmt != NULL) { vy_stmt_counter_acct_tuple(&itr->cache->stat.get, itr->curr_stmt); - if (vy_history_append_stmt(history, itr->curr_stmt) != 0) + if (vy_history_append_stmt(history, itr->curr_stmt, + itr->curr_hint) != 0) return -1; } return 1; @@ -884,12 +883,13 @@ vy_cache_iterator_close(struct vy_cache_iterator *itr) void vy_cache_iterator_open(struct vy_cache_iterator *itr, struct vy_cache *cache, enum iterator_type iterator_type, - const struct tuple *key, const struct vy_read_view **rv) + const struct tuple *key, hint_t hint, + const struct vy_read_view **rv) { itr->cache = cache; itr->iterator_type = iterator_type; itr->key = key; - itr->hint = vy_stmt_hint(key, cache->cmp_def); + itr->hint = hint; itr->read_view = rv; itr->curr_stmt = NULL; diff --git a/src/box/vy_cache.h b/src/box/vy_cache.h index 4fcdb747..d256f32c 100644 --- a/src/box/vy_cache.h +++ b/src/box/vy_cache.h @@ -228,7 +228,8 @@ vy_cache_add(struct vy_cache *cache, struct tuple *stmt, * @return A tuple equal to key or NULL if not found. */ struct tuple * -vy_cache_get(struct vy_cache *cache, const struct tuple *key); +vy_cache_get(struct vy_cache *cache, const struct tuple *key, + hint_t hint, hint_t *ret_hint); /** * Invalidate possibly cached value due to its overwriting @@ -282,12 +283,14 @@ struct vy_cache_iterator { * @param cache - the cache. * @param iterator_type - iterator type (EQ, GT, GE, LT, LE or ALL) * @param key - search key data in terms of vinyl, vy_stmt_compare argument + * @param hint - comparison hint of the search key * @param vlsn - LSN visibility, iterator shows values with lsn <= vlsn */ void vy_cache_iterator_open(struct vy_cache_iterator *itr, struct vy_cache *cache, enum iterator_type iterator_type, - const struct tuple *key, const struct vy_read_view **rv); + const struct tuple *key, hint_t hint, + const struct vy_read_view **rv); /** * Advance a cache iterator to the next key. @@ -308,7 +311,7 @@ vy_cache_iterator_next(struct vy_cache_iterator *itr, */ NODISCARD int vy_cache_iterator_skip(struct vy_cache_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history, bool *stop); /** @@ -319,7 +322,7 @@ vy_cache_iterator_skip(struct vy_cache_iterator *itr, */ NODISCARD int vy_cache_iterator_restore(struct vy_cache_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history, bool *stop); /** diff --git a/src/box/vy_history.c b/src/box/vy_history.c index b45c6d51..2cbc1695 100644 --- a/src/box/vy_history.c +++ b/src/box/vy_history.c @@ -43,7 +43,8 @@ #include "vy_upsert.h" int -vy_history_append_stmt(struct vy_history *history, struct tuple *stmt) +vy_history_append_stmt(struct vy_history *history, + struct tuple *stmt, hint_t hint) { assert(history->pool->objsize == sizeof(struct vy_history_node)); struct vy_history_node *node = mempool_alloc(history->pool); @@ -56,6 +57,7 @@ vy_history_append_stmt(struct vy_history *history, struct tuple *stmt) if (node->is_refable) tuple_ref(stmt); node->stmt = stmt; + node->hint = hint; rlist_add_tail_entry(&history->stmts, node, link); return 0; } @@ -74,9 +76,11 @@ vy_history_cleanup(struct vy_history *history) int vy_history_apply(struct vy_history *history, struct key_def *cmp_def, - bool keep_delete, int *upserts_applied, struct tuple **ret) + bool keep_delete, int *upserts_applied, + struct tuple **ret, hint_t *ret_hint) { *ret = NULL; + *ret_hint = HINT_NONE; *upserts_applied = 0; if (rlist_empty(&history->stmts)) return 0; @@ -84,6 +88,7 @@ vy_history_apply(struct vy_history *history, struct key_def *cmp_def, struct tuple *curr_stmt = NULL; struct vy_history_node *node = rlist_last_entry(&history->stmts, struct vy_history_node, link); + *ret_hint = node->hint; if (vy_history_is_terminal(history)) { if (!keep_delete && vy_stmt_type(node->stmt) == IPROTO_DELETE) { /* diff --git a/src/box/vy_history.h b/src/box/vy_history.h index 458ea749..94070415 100644 --- a/src/box/vy_history.h +++ b/src/box/vy_history.h @@ -64,6 +64,8 @@ struct vy_history_node { struct rlist link; /** History statement. Referenced if @is_refable is set. */ struct tuple *stmt; + /** Comparison hint of the history statement. */ + hint_t hint; /** * Set if the statement stored in this node is refable, * i.e. has a reference counter that can be incremented @@ -114,13 +116,16 @@ vy_history_is_terminal(struct vy_history *history) * key history or NULL if the history is empty. */ static inline struct tuple * -vy_history_last_stmt(struct vy_history *history) +vy_history_last_stmt(struct vy_history *history, hint_t *hint) { - if (rlist_empty(&history->stmts)) + if (rlist_empty(&history->stmts)) { + *hint = HINT_NONE; return NULL; + } /* Newest statement is at the head of the list. */ struct vy_history_node *node = rlist_first_entry(&history->stmts, struct vy_history_node, link); + *hint = node->hint; return node->stmt; } @@ -139,7 +144,8 @@ vy_history_splice(struct vy_history *dst, struct vy_history *src) * Returns 0 on success, -1 on memory allocation error. */ int -vy_history_append_stmt(struct vy_history *history, struct tuple *stmt); +vy_history_append_stmt(struct vy_history *history, + struct tuple *stmt, hint_t hint); /** * Release all statements stored in the given history and @@ -155,7 +161,8 @@ vy_history_cleanup(struct vy_history *history); */ int vy_history_apply(struct vy_history *history, struct key_def *cmp_def, - bool keep_delete, int *upserts_applied, struct tuple **ret); + bool keep_delete, int *upserts_applied, + struct tuple **ret, hint_t *ret_hint); #if defined(__cplusplus) } /* extern "C" */ diff --git a/src/box/vy_mem.c b/src/box/vy_mem.c index 220751d4..aea0ecfb 100644 --- a/src/box/vy_mem.c +++ b/src/box/vy_mem.c @@ -467,7 +467,8 @@ vy_mem_iterator_seek(struct vy_mem_iterator *itr, const struct tuple *last_key, void vy_mem_iterator_open(struct vy_mem_iterator *itr, struct vy_mem_iterator_stat *stat, struct vy_mem *mem, enum iterator_type iterator_type, - const struct tuple *key, const struct vy_read_view **rv) + const struct tuple *key, hint_t hint, + const struct vy_read_view **rv) { itr->stat = stat; @@ -476,7 +477,7 @@ vy_mem_iterator_open(struct vy_mem_iterator *itr, struct vy_mem_iterator_stat *s itr->iterator_type = iterator_type; itr->key = key; - itr->hint = vy_stmt_hint(key, mem->cmp_def); + itr->hint = hint; itr->read_view = rv; itr->curr_pos = vy_mem_tree_invalid_iterator(); @@ -574,7 +575,7 @@ vy_mem_iterator_get_history(struct vy_mem_iterator *itr, do { struct tuple *stmt = (struct tuple *)itr->curr.stmt; vy_stmt_counter_acct_tuple(&itr->stat->get, stmt); - if (vy_history_append_stmt(history, stmt) != 0) + if (vy_history_append_stmt(history, stmt, itr->curr.hint) != 0) return -1; if (vy_history_is_terminal(history)) break; @@ -594,14 +595,11 @@ vy_mem_iterator_next(struct vy_mem_iterator *itr, NODISCARD int vy_mem_iterator_skip(struct vy_mem_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history) { assert(!itr->search_started || itr->version == itr->mem->version); - hint_t last_hint = last_stmt == NULL ? HINT_NONE : - vy_stmt_hint(last_stmt, itr->mem->cmp_def); - /* * Check if the iterator is already positioned * at the statement following last_stmt. @@ -621,14 +619,12 @@ vy_mem_iterator_skip(struct vy_mem_iterator *itr, NODISCARD int vy_mem_iterator_restore(struct vy_mem_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history) { if (!itr->search_started || itr->version == itr->mem->version) return 0; - hint_t last_hint = last_stmt == NULL ? HINT_NONE : - vy_stmt_hint(last_stmt, itr->mem->cmp_def); vy_mem_iterator_seek(itr, last_stmt, last_hint); vy_history_cleanup(history); diff --git a/src/box/vy_mem.h b/src/box/vy_mem.h index 160bf5e1..f31deaed 100644 --- a/src/box/vy_mem.h +++ b/src/box/vy_mem.h @@ -407,7 +407,8 @@ struct vy_mem_iterator { void vy_mem_iterator_open(struct vy_mem_iterator *itr, struct vy_mem_iterator_stat *stat, struct vy_mem *mem, enum iterator_type iterator_type, - const struct tuple *key, const struct vy_read_view **rv); + const struct tuple *key, hint_t hint, + const struct vy_read_view **rv); /** * Advance a mem iterator to the next key. @@ -425,7 +426,7 @@ vy_mem_iterator_next(struct vy_mem_iterator *itr, */ NODISCARD int vy_mem_iterator_skip(struct vy_mem_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history); /** @@ -436,7 +437,7 @@ vy_mem_iterator_skip(struct vy_mem_iterator *itr, */ NODISCARD int vy_mem_iterator_restore(struct vy_mem_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history); /** diff --git a/src/box/vy_point_lookup.c b/src/box/vy_point_lookup.c index aa0625fb..25125662 100644 --- a/src/box/vy_point_lookup.c +++ b/src/box/vy_point_lookup.c @@ -65,7 +65,7 @@ vy_point_lookup_scan_txw(struct vy_lsm *lsm, struct vy_tx *tx, return 0; vy_stmt_counter_acct_tuple(&lsm->stat.txw.iterator.get, txv->stmt); - return vy_history_append_stmt(history, txv->stmt); + return vy_history_append_stmt(history, txv->stmt, txv->hint); } /** @@ -74,16 +74,18 @@ vy_point_lookup_scan_txw(struct vy_lsm *lsm, struct vy_tx *tx, */ static int vy_point_lookup_scan_cache(struct vy_lsm *lsm, const struct vy_read_view **rv, - struct tuple *key, struct vy_history *history) + struct tuple *key, hint_t hint, + struct vy_history *history) { lsm->cache.stat.lookup++; - struct tuple *stmt = vy_cache_get(&lsm->cache, key); + hint_t stmt_hint; + struct tuple *stmt = vy_cache_get(&lsm->cache, key, hint, &stmt_hint); if (stmt == NULL || vy_stmt_lsn(stmt) > (*rv)->vlsn) return 0; vy_stmt_counter_acct_tuple(&lsm->cache.stat.get, stmt); - return vy_history_append_stmt(history, stmt); + return vy_history_append_stmt(history, stmt, stmt_hint); } /** @@ -92,12 +94,12 @@ vy_point_lookup_scan_cache(struct vy_lsm *lsm, const struct vy_read_view **rv, */ static int vy_point_lookup_scan_mem(struct vy_lsm *lsm, struct vy_mem *mem, - const struct vy_read_view **rv, - struct tuple *key, struct vy_history *history) + const struct vy_read_view **rv, struct tuple *key, + hint_t hint, struct vy_history *history) { struct vy_mem_iterator mem_itr; vy_mem_iterator_open(&mem_itr, &lsm->stat.memory.iterator, - mem, ITER_EQ, key, rv); + mem, ITER_EQ, key, hint, rv); struct vy_history mem_history; vy_history_create(&mem_history, &lsm->env->history_node_pool); int rc = vy_mem_iterator_next(&mem_itr, &mem_history); @@ -113,16 +115,17 @@ vy_point_lookup_scan_mem(struct vy_lsm *lsm, struct vy_mem *mem, */ static int vy_point_lookup_scan_mems(struct vy_lsm *lsm, const struct vy_read_view **rv, - struct tuple *key, struct vy_history *history) + struct tuple *key, hint_t hint, + struct vy_history *history) { assert(lsm->mem != NULL); - int rc = vy_point_lookup_scan_mem(lsm, lsm->mem, rv, key, history); + int rc = vy_point_lookup_scan_mem(lsm, lsm->mem, rv, key, hint, history); struct vy_mem *mem; rlist_foreach_entry(mem, &lsm->sealed, in_sealed) { if (rc != 0 || vy_history_is_terminal(history)) return rc; - rc = vy_point_lookup_scan_mem(lsm, mem, rv, key, history); + rc = vy_point_lookup_scan_mem(lsm, mem, rv, key, hint, history); } return 0; } @@ -134,7 +137,7 @@ vy_point_lookup_scan_mems(struct vy_lsm *lsm, const struct vy_read_view **rv, static int vy_point_lookup_scan_slice(struct vy_lsm *lsm, struct vy_slice *slice, const struct vy_read_view **rv, struct tuple *key, - struct vy_history *history) + hint_t hint, struct vy_history *history) { /* * The format of the statement must be exactly the space @@ -143,7 +146,7 @@ vy_point_lookup_scan_slice(struct vy_lsm *lsm, struct vy_slice *slice, */ struct vy_run_iterator run_itr; vy_run_iterator_open(&run_itr, &lsm->stat.disk.iterator, slice, - ITER_EQ, key, rv, lsm->cmp_def, lsm->key_def, + ITER_EQ, key, hint, rv, lsm->cmp_def, lsm->key_def, lsm->disk_format); struct vy_history slice_history; vy_history_create(&slice_history, &lsm->env->history_node_pool); @@ -185,8 +188,8 @@ vy_point_lookup_scan_slices(struct vy_lsm *lsm, const struct vy_read_view **rv, int rc = 0; for (i = 0; i < slice_count; i++) { if (rc == 0 && !vy_history_is_terminal(history)) - rc = vy_point_lookup_scan_slice(lsm, slices[i], - rv, key, history); + rc = vy_point_lookup_scan_slice(lsm, slices[i], rv, + key, hint, history); vy_slice_unpin(slices[i]); } return rc; @@ -219,12 +222,12 @@ vy_point_lookup(struct vy_lsm *lsm, struct vy_tx *tx, if (rc != 0 || vy_history_is_terminal(&history)) goto done; - rc = vy_point_lookup_scan_cache(lsm, rv, key, &history); + rc = vy_point_lookup_scan_cache(lsm, rv, key, hint, &history); if (rc != 0 || vy_history_is_terminal(&history)) goto done; restart: - rc = vy_point_lookup_scan_mems(lsm, rv, key, &mem_history); + rc = vy_point_lookup_scan_mems(lsm, rv, key, hint, &mem_history); if (rc != 0 || vy_history_is_terminal(&mem_history)) goto done; @@ -276,7 +279,7 @@ restart: * matching the search key. */ vy_history_cleanup(&mem_history); - rc = vy_point_lookup_scan_mems(lsm, rv, key, &mem_history); + rc = vy_point_lookup_scan_mems(lsm, rv, key, hint, &mem_history); if (rc != 0) goto done; if (vy_history_is_terminal(&mem_history)) @@ -288,9 +291,10 @@ done: vy_history_splice(&history, &disk_history); if (rc == 0) { + hint_t unused; int upserts_applied; - rc = vy_history_apply(&history, lsm->cmp_def, - false, &upserts_applied, ret); + rc = vy_history_apply(&history, lsm->cmp_def, false, + &upserts_applied, ret, &unused); lsm->stat.upsert.applied += upserts_applied; } vy_history_cleanup(&history); @@ -323,11 +327,13 @@ vy_point_lookup_mem(struct vy_lsm *lsm, const struct vy_read_view **rv, struct vy_history history; vy_history_create(&history, &lsm->env->history_node_pool); - rc = vy_point_lookup_scan_cache(lsm, rv, key, &history); + hint_t hint = vy_stmt_hint(key, lsm->cmp_def); + + rc = vy_point_lookup_scan_cache(lsm, rv, key, hint, &history); if (rc != 0 || vy_history_is_terminal(&history)) goto done; - rc = vy_point_lookup_scan_mems(lsm, rv, key, &history); + rc = vy_point_lookup_scan_mems(lsm, rv, key, hint, &history); if (rc != 0 || vy_history_is_terminal(&history)) goto done; @@ -335,9 +341,10 @@ vy_point_lookup_mem(struct vy_lsm *lsm, const struct vy_read_view **rv, goto out; done: if (rc == 0) { + hint_t unused; int upserts_applied; - rc = vy_history_apply(&history, lsm->cmp_def, - true, &upserts_applied, ret); + rc = vy_history_apply(&history, lsm->cmp_def, true, + &upserts_applied, ret, &unused); lsm->stat.upsert.applied += upserts_applied; } out: diff --git a/src/box/vy_read_iterator.c b/src/box/vy_read_iterator.c index f1d8c8e4..b96a5d19 100644 --- a/src/box/vy_read_iterator.c +++ b/src/box/vy_read_iterator.c @@ -141,24 +141,28 @@ vy_read_iterator_unpin_slices(struct vy_read_iterator *itr) */ static bool vy_read_iterator_range_is_done(struct vy_read_iterator *itr, - struct tuple *next_key) + struct tuple *next_key, hint_t next_hint) { struct vy_range *range = itr->curr_range; struct key_def *cmp_def = itr->lsm->cmp_def; int dir = iterator_direction(itr->iterator_type); if (dir > 0 && range->end != NULL && - (next_key == NULL || vy_stmt_compare(next_key, range->end, - cmp_def) >= 0) && + (next_key == NULL || + vy_stmt_compare_hinted(next_key, next_hint, range->end, + range->end_hint, cmp_def) >= 0) && (itr->iterator_type != ITER_EQ || - vy_stmt_compare(itr->key, range->end, cmp_def) >= 0)) + vy_stmt_compare_hinted(itr->key, itr->hint, range->end, + range->end_hint, cmp_def) >= 0)) return true; if (dir < 0 && range->begin != NULL && - (next_key == NULL || vy_stmt_compare(next_key, range->begin, - cmp_def) < 0) && + (next_key == NULL || + vy_stmt_compare_hinted(next_key, next_hint, range->begin, + range->begin_hint, cmp_def) < 0) && (itr->iterator_type != ITER_REQ || - vy_stmt_compare(itr->key, range->begin, cmp_def) <= 0)) + vy_stmt_compare_hinted(itr->key, itr->hint, range->begin, + range->begin_hint, cmp_def) <= 0)) return true; return false; @@ -176,7 +180,8 @@ vy_read_iterator_range_is_done(struct vy_read_iterator *itr, */ static inline int vy_read_iterator_cmp_stmt(struct vy_read_iterator *itr, - const struct tuple *a, const struct tuple *b) + const struct tuple *a, hint_t a_hint, + const struct tuple *b, hint_t b_hint) { if (a == NULL && b != NULL) return 1; @@ -185,7 +190,7 @@ vy_read_iterator_cmp_stmt(struct vy_read_iterator *itr, if (a == NULL && b == NULL) return 0; return iterator_direction(itr->iterator_type) * - vy_stmt_compare(a, b, itr->lsm->cmp_def); + vy_stmt_compare_hinted(a, a_hint, b, b_hint, itr->lsm->cmp_def); } /** @@ -194,9 +199,8 @@ vy_read_iterator_cmp_stmt(struct vy_read_iterator *itr, */ static bool vy_read_iterator_is_exact_match(struct vy_read_iterator *itr, - struct tuple *stmt) + struct tuple *stmt, hint_t hint) { - struct tuple *key = itr->key; enum iterator_type type = itr->iterator_type; struct key_def *cmp_def = itr->lsm->cmp_def; @@ -208,8 +212,9 @@ vy_read_iterator_is_exact_match(struct vy_read_iterator *itr, return itr->last_stmt == NULL && stmt != NULL && (type == ITER_EQ || type == ITER_REQ || type == ITER_GE || type == ITER_LE) && - vy_stmt_is_full_key(key, cmp_def) && - vy_stmt_compare(stmt, key, cmp_def) == 0; + vy_stmt_is_full_key(itr->key, cmp_def) && + vy_stmt_compare_hinted(stmt, hint, itr->key, + itr->hint, cmp_def) == 0; } /** @@ -222,14 +227,18 @@ vy_read_iterator_is_exact_match(struct vy_read_iterator *itr, static void vy_read_iterator_evaluate_src(struct vy_read_iterator *itr, struct vy_read_src *src, - struct tuple **next_key, bool *stop) + struct tuple **next_key, hint_t *next_hint, + bool *stop) { uint32_t src_id = src - itr->src; - struct tuple *stmt = vy_history_last_stmt(&src->history); - int cmp = vy_read_iterator_cmp_stmt(itr, stmt, *next_key); + hint_t hint; + struct tuple *stmt = vy_history_last_stmt(&src->history, &hint); + int cmp = vy_read_iterator_cmp_stmt(itr, stmt, hint, + *next_key, *next_hint); if (cmp < 0) { assert(stmt != NULL); *next_key = stmt; + *next_hint = hint; itr->front_id++; } if (cmp <= 0) @@ -238,7 +247,7 @@ vy_read_iterator_evaluate_src(struct vy_read_iterator *itr, itr->skipped_src = MAX(itr->skipped_src, src_id + 1); if (cmp < 0 && vy_history_is_terminal(&src->history) && - vy_read_iterator_is_exact_match(itr, stmt)) { + vy_read_iterator_is_exact_match(itr, stmt, hint)) { itr->skipped_src = src_id + 1; *stop = true; } @@ -270,7 +279,8 @@ vy_read_iterator_evaluate_src(struct vy_read_iterator *itr, static NODISCARD int vy_read_iterator_scan_txw(struct vy_read_iterator *itr, - struct tuple **next_key, bool *stop) + struct tuple **next_key, hint_t *next_hint, + bool *stop) { struct vy_read_src *src = &itr->src[itr->txw_src]; struct vy_txw_iterator *src_itr = &src->txw_iterator; @@ -281,11 +291,11 @@ vy_read_iterator_scan_txw(struct vy_read_iterator *itr, assert(itr->txw_src < itr->skipped_src); int rc = vy_txw_iterator_restore(src_itr, itr->last_stmt, - &src->history); + itr->last_hint, &src->history); if (rc == 0) { if (!src->is_started) { rc = vy_txw_iterator_skip(src_itr, itr->last_stmt, - &src->history); + itr->last_hint, &src->history); } else if (src->front_id == itr->prev_front_id) { rc = vy_txw_iterator_next(src_itr, &src->history); } @@ -294,24 +304,27 @@ vy_read_iterator_scan_txw(struct vy_read_iterator *itr, if (rc < 0) return -1; - vy_read_iterator_evaluate_src(itr, src, next_key, stop); + vy_read_iterator_evaluate_src(itr, src, next_key, next_hint, stop); return 0; } static NODISCARD int vy_read_iterator_scan_cache(struct vy_read_iterator *itr, - struct tuple **next_key, bool *stop) + struct tuple **next_key, hint_t *next_hint, + bool *stop) { bool is_interval = false; struct vy_read_src *src = &itr->src[itr->cache_src]; struct vy_cache_iterator *src_itr = &src->cache_iterator; int rc = vy_cache_iterator_restore(src_itr, itr->last_stmt, - &src->history, &is_interval); + itr->last_hint, &src->history, + &is_interval); if (rc == 0) { if (!src->is_started || itr->cache_src >= itr->skipped_src) { rc = vy_cache_iterator_skip(src_itr, itr->last_stmt, - &src->history, &is_interval); + itr->last_hint, &src->history, + &is_interval); } else if (src->front_id == itr->prev_front_id) { rc = vy_cache_iterator_next(src_itr, &src->history, &is_interval); @@ -321,7 +334,7 @@ vy_read_iterator_scan_cache(struct vy_read_iterator *itr, if (rc < 0) return -1; - vy_read_iterator_evaluate_src(itr, src, next_key, stop); + vy_read_iterator_evaluate_src(itr, src, next_key, next_hint, stop); if (is_interval) { itr->skipped_src = itr->cache_src + 1; *stop = true; @@ -331,7 +344,8 @@ vy_read_iterator_scan_cache(struct vy_read_iterator *itr, static NODISCARD int vy_read_iterator_scan_mem(struct vy_read_iterator *itr, uint32_t mem_src, - struct tuple **next_key, bool *stop) + struct tuple **next_key, hint_t *next_hint, + bool *stop) { int rc; struct vy_read_src *src = &itr->src[mem_src]; @@ -339,11 +353,12 @@ vy_read_iterator_scan_mem(struct vy_read_iterator *itr, uint32_t mem_src, assert(mem_src >= itr->mem_src && mem_src < itr->disk_src); - rc = vy_mem_iterator_restore(src_itr, itr->last_stmt, &src->history); + rc = vy_mem_iterator_restore(src_itr, itr->last_stmt, itr->last_hint, + &src->history); if (rc == 0) { if (!src->is_started || mem_src >= itr->skipped_src) { rc = vy_mem_iterator_skip(src_itr, itr->last_stmt, - &src->history); + itr->last_hint, &src->history); } else if (src->front_id == itr->prev_front_id) { rc = vy_mem_iterator_next(src_itr, &src->history); } @@ -352,13 +367,14 @@ vy_read_iterator_scan_mem(struct vy_read_iterator *itr, uint32_t mem_src, if (rc < 0) return -1; - vy_read_iterator_evaluate_src(itr, src, next_key, stop); + vy_read_iterator_evaluate_src(itr, src, next_key, next_hint, stop); return 0; } static NODISCARD int vy_read_iterator_scan_disk(struct vy_read_iterator *itr, uint32_t disk_src, - struct tuple **next_key, bool *stop) + struct tuple **next_key, hint_t *next_hint, + bool *stop) { int rc = 0; struct vy_read_src *src = &itr->src[disk_src]; @@ -368,7 +384,7 @@ vy_read_iterator_scan_disk(struct vy_read_iterator *itr, uint32_t disk_src, if (!src->is_started || disk_src >= itr->skipped_src) rc = vy_run_iterator_skip(src_itr, itr->last_stmt, - &src->history); + itr->last_hint, &src->history); else if (src->front_id == itr->prev_front_id) rc = vy_run_iterator_next(src_itr, &src->history); src->is_started = true; @@ -376,7 +392,7 @@ vy_read_iterator_scan_disk(struct vy_read_iterator *itr, uint32_t disk_src, if (rc < 0) return -1; - vy_read_iterator_evaluate_src(itr, src, next_key, stop); + vy_read_iterator_evaluate_src(itr, src, next_key, next_hint, stop); return 0; } @@ -387,21 +403,22 @@ vy_read_iterator_scan_disk(struct vy_read_iterator *itr, uint32_t disk_src, */ static NODISCARD int vy_read_iterator_restore_mem(struct vy_read_iterator *itr, - struct tuple **next_key) + struct tuple **next_key, hint_t *next_hint) { int rc; int cmp; struct vy_read_src *src = &itr->src[itr->mem_src]; - rc = vy_mem_iterator_restore(&src->mem_iterator, - itr->last_stmt, &src->history); + rc = vy_mem_iterator_restore(&src->mem_iterator, itr->last_stmt, + itr->last_hint, &src->history); if (rc < 0) return -1; /* memory allocation error */ if (rc == 0) return 0; /* nothing changed */ - struct tuple *stmt = vy_history_last_stmt(&src->history); - cmp = vy_read_iterator_cmp_stmt(itr, stmt, *next_key); + hint_t hint; + struct tuple *stmt = vy_history_last_stmt(&src->history, &hint); + cmp = vy_read_iterator_cmp_stmt(itr, stmt, hint, *next_key, *next_hint); if (cmp > 0) { /* * Memory trees are append-only so if the @@ -417,6 +434,7 @@ vy_read_iterator_restore_mem(struct vy_read_iterator *itr, * candidate for the next key. */ *next_key = stmt; + *next_hint = hint; itr->front_id++; } else { /* @@ -475,17 +493,19 @@ restart: */ bool stop = false; struct tuple *next_key = NULL; - if (vy_read_iterator_scan_txw(itr, &next_key, &stop) != 0) + hint_t next_hint = HINT_NONE; + if (vy_read_iterator_scan_txw(itr, &next_key, &next_hint, &stop) != 0) return -1; if (stop) goto done; - if (vy_read_iterator_scan_cache(itr, &next_key, &stop) != 0) + if (vy_read_iterator_scan_cache(itr, &next_key, &next_hint, &stop) != 0) return -1; if (stop) goto done; for (uint32_t i = itr->mem_src; i < itr->disk_src; i++) { - if (vy_read_iterator_scan_mem(itr, i, &next_key, &stop) != 0) + if (vy_read_iterator_scan_mem(itr, i, &next_key, &next_hint, + &stop) != 0) return -1; if (stop) goto done; @@ -494,7 +514,8 @@ rescan_disk: /* The following code may yield as it needs to access disk. */ vy_read_iterator_pin_slices(itr); for (uint32_t i = itr->disk_src; i < itr->src_count; i++) { - if (vy_read_iterator_scan_disk(itr, i, &next_key, &stop) != 0) { + if (vy_read_iterator_scan_disk(itr, i, &next_key, &next_hint, + &stop) != 0) { vy_read_iterator_unpin_slices(itr); return -1; } @@ -531,13 +552,13 @@ rescan_disk: * as it is owned exclusively by the current fiber so the only * source to check is the active in-memory tree. */ - if (vy_read_iterator_restore_mem(itr, &next_key) != 0) + if (vy_read_iterator_restore_mem(itr, &next_key, &next_hint) != 0) return -1; /* * Scan the next range in case we transgressed the current * range's boundaries. */ - if (vy_read_iterator_range_is_done(itr, next_key)) { + if (vy_read_iterator_range_is_done(itr, next_key, next_hint)) { vy_read_iterator_next_range(itr); goto rescan_disk; } @@ -545,8 +566,9 @@ done: #ifndef NDEBUG /* Check that the statement meets search criteria. */ if (next_key != NULL) { - int cmp = vy_stmt_compare(next_key, itr->key, - itr->lsm->cmp_def); + int cmp = vy_stmt_compare_hinted(next_key, next_hint, + itr->key, itr->hint, + itr->lsm->cmp_def); cmp *= iterator_direction(itr->iterator_type); if (itr->iterator_type == ITER_GT || itr->iterator_type == ITER_LT) @@ -559,12 +581,13 @@ done: * and respects statement order. */ if (itr->last_stmt != NULL && next_key != NULL) { - assert(vy_read_iterator_cmp_stmt(itr, next_key, - itr->last_stmt) > 0); + assert(vy_read_iterator_cmp_stmt(itr, next_key, next_hint, + itr->last_stmt, itr->last_hint) > 0); } #endif if (itr->need_check_eq && next_key != NULL && - vy_stmt_compare(next_key, itr->key, itr->lsm->cmp_def) != 0) + vy_stmt_compare_hinted(next_key, next_hint, itr->key, itr->hint, + itr->lsm->cmp_def) != 0) itr->front_id++; return 0; } @@ -578,7 +601,7 @@ vy_read_iterator_add_tx(struct vy_read_iterator *itr) struct vy_txw_iterator_stat *stat = &itr->lsm->stat.txw.iterator; struct vy_read_src *sub_src = vy_read_iterator_add_src(itr); vy_txw_iterator_open(&sub_src->txw_iterator, stat, itr->tx, itr->lsm, - iterator_type, itr->key); + iterator_type, itr->key, itr->hint); } static void @@ -589,7 +612,7 @@ vy_read_iterator_add_cache(struct vy_read_iterator *itr) struct vy_read_src *sub_src = vy_read_iterator_add_src(itr); vy_cache_iterator_open(&sub_src->cache_iterator, &itr->lsm->cache, iterator_type, - itr->key, itr->read_view); + itr->key, itr->hint, itr->read_view); } static void @@ -604,14 +627,15 @@ vy_read_iterator_add_mem(struct vy_read_iterator *itr) assert(lsm->mem != NULL); sub_src = vy_read_iterator_add_src(itr); vy_mem_iterator_open(&sub_src->mem_iterator, &lsm->stat.memory.iterator, - lsm->mem, iterator_type, itr->key, itr->read_view); + lsm->mem, iterator_type, itr->key, itr->hint, + itr->read_view); /* Add sealed in-memory indexes. */ struct vy_mem *mem; rlist_foreach_entry(mem, &lsm->sealed, in_sealed) { sub_src = vy_read_iterator_add_src(itr); vy_mem_iterator_open(&sub_src->mem_iterator, - &lsm->stat.memory.iterator, - mem, iterator_type, itr->key, + &lsm->stat.memory.iterator, mem, + iterator_type, itr->key, itr->hint, itr->read_view); } } @@ -633,7 +657,7 @@ vy_read_iterator_add_disk(struct vy_read_iterator *itr) struct vy_read_src *sub_src = vy_read_iterator_add_src(itr); vy_run_iterator_open(&sub_src->run_iterator, &lsm->stat.disk.iterator, slice, - iterator_type, itr->key, + iterator_type, itr->key, itr->hint, itr->read_view, lsm->cmp_def, lsm->key_def, lsm->disk_format); } @@ -688,7 +712,9 @@ vy_read_iterator_open(struct vy_read_iterator *itr, struct vy_lsm *lsm, itr->tx = tx; itr->iterator_type = iterator_type; itr->key = key; + itr->hint = vy_stmt_hint(key, lsm->cmp_def); itr->read_view = rv; + itr->last_hint = HINT_NONE; if (vy_stmt_is_empty_key(key)) { /* @@ -730,9 +756,15 @@ vy_read_iterator_restore(struct vy_read_iterator *itr) { vy_read_iterator_cleanup(itr); - const struct tuple *key = itr->last_stmt != NULL ? - itr->last_stmt : itr->key; - hint_t hint = vy_stmt_hint(key, itr->lsm->cmp_def); + hint_t hint; + const struct tuple *key; + if (itr->last_stmt != NULL) { + key = itr->last_stmt; + hint = itr->last_hint; + } else { + key = itr->key; + hint = itr->hint; + } itr->mem_list_version = itr->lsm->mem_list_version; itr->range_tree_version = itr->lsm->range_tree_version; @@ -778,13 +810,17 @@ vy_read_iterator_next_range(struct vy_read_iterator *itr) * We could skip an entire range due to the cache. * Make sure the next statement falls in the range. */ - if (dir > 0 && (range->end == NULL || - vy_stmt_compare(itr->last_stmt, range->end, - cmp_def) < 0)) + if (dir > 0 && + (range->end == NULL || + vy_stmt_compare_hinted(itr->last_stmt, itr->last_hint, + range->end, range->end_hint, + cmp_def) < 0)) break; - if (dir < 0 && (range->begin == NULL || - vy_stmt_compare(itr->last_stmt, range->begin, - cmp_def) > 0)) + if (dir < 0 && + (range->begin == NULL || + vy_stmt_compare_hinted(itr->last_stmt, itr->last_hint, + range->begin, range->begin_hint, + cmp_def) > 0)) break; } itr->curr_range = range; @@ -805,7 +841,7 @@ vy_read_iterator_next_range(struct vy_read_iterator *itr) */ static NODISCARD int vy_read_iterator_apply_history(struct vy_read_iterator *itr, - struct tuple **ret) + struct tuple **ret, hint_t *ret_hint) { struct vy_lsm *lsm = itr->lsm; struct vy_history history; @@ -822,7 +858,7 @@ vy_read_iterator_apply_history(struct vy_read_iterator *itr, int upserts_applied = 0; int rc = vy_history_apply(&history, lsm->cmp_def, - true, &upserts_applied, ret); + true, &upserts_applied, ret, ret_hint); lsm->stat.upsert.applied += upserts_applied; vy_history_cleanup(&history); @@ -865,13 +901,14 @@ vy_read_iterator_next(struct vy_read_iterator *itr, struct tuple **result) struct vy_lsm *lsm = itr->lsm; struct tuple *stmt; + hint_t hint; if (itr->last_stmt == NULL) lsm->stat.lookup++; /* first iteration */ next_key: if (vy_read_iterator_advance(itr) != 0) return -1; - if (vy_read_iterator_apply_history(itr, &stmt) != 0) + if (vy_read_iterator_apply_history(itr, &stmt, &hint) != 0) return -1; if (vy_read_iterator_track_read(itr, stmt) != 0) return -1; @@ -879,6 +916,7 @@ next_key: if (itr->last_stmt != NULL) tuple_unref(itr->last_stmt); itr->last_stmt = stmt; + itr->last_hint = hint; if (stmt != NULL && vy_stmt_type(stmt) == IPROTO_DELETE) { /* diff --git a/src/box/vy_read_iterator.h b/src/box/vy_read_iterator.h index baab8859..d8251372 100644 --- a/src/box/vy_read_iterator.h +++ b/src/box/vy_read_iterator.h @@ -34,6 +34,7 @@ #include <stdint.h> #include <stdbool.h> +#include "key_def.h" #include "iterator_type.h" #include "trivia/util.h" @@ -55,6 +56,8 @@ struct vy_read_iterator { enum iterator_type iterator_type; /** Search key. */ struct tuple *key; + /** Comparison hint of the search key. */ + hint_t hint; /** Read view the iterator lives in. */ const struct vy_read_view **read_view; /** @@ -64,6 +67,8 @@ struct vy_read_iterator { bool need_check_eq; /** Last statement returned by vy_read_iterator_next(). */ struct tuple *last_stmt; + /** Comparison hint of the last statement. */ + hint_t last_hint; /** * Last statement added to the tuple cache by * vy_read_iterator_cache_add(). diff --git a/src/box/vy_run.c b/src/box/vy_run.c index 9608e207..897ece2a 100644 --- a/src/box/vy_run.c +++ b/src/box/vy_run.c @@ -1184,12 +1184,14 @@ vy_run_iterator_next_pos(struct vy_run_iterator *itr, * Affects: curr_loaded_page, curr_pos */ static NODISCARD int -vy_run_iterator_find_lsn(struct vy_run_iterator *itr, struct tuple **ret) +vy_run_iterator_find_lsn(struct vy_run_iterator *itr, + struct tuple **ret, hint_t *ret_hint) { struct vy_slice *slice = itr->slice; struct key_def *cmp_def = itr->cmp_def; *ret = NULL; + *ret_hint = HINT_NONE; assert(itr->search_started); assert(itr->curr_stmt != NULL); @@ -1261,6 +1263,7 @@ vy_run_iterator_find_lsn(struct vy_run_iterator *itr, struct tuple **ret) } vy_stmt_counter_acct_tuple(&itr->stat->get, itr->curr_stmt); *ret = itr->curr_stmt; + *ret_hint = itr->curr_hint; return 0; } @@ -1333,7 +1336,7 @@ vy_run_iterator_do_seek(struct vy_run_iterator *itr, */ static NODISCARD int vy_run_iterator_seek(struct vy_run_iterator *itr, const struct tuple *last_key, - hint_t last_hint, struct tuple **ret) + hint_t last_hint, struct tuple **ret, hint_t *ret_hint) { struct key_def *cmp_def = itr->cmp_def; struct vy_slice *slice = itr->slice; @@ -1343,6 +1346,7 @@ vy_run_iterator_seek(struct vy_run_iterator *itr, const struct tuple *last_key, enum iterator_type iterator_type = itr->iterator_type; *ret = NULL; + *ret_hint = HINT_NONE; assert(itr->search_started); /* Check the bloom filter on the first iteration. */ @@ -1452,7 +1456,7 @@ vy_run_iterator_seek(struct vy_run_iterator *itr, const struct tuple *last_key, goto not_found; /* Skip statements invisible from the iterator read view. */ - return vy_run_iterator_find_lsn(itr, ret); + return vy_run_iterator_find_lsn(itr, ret, ret_hint); not_found: if (check_bloom) @@ -1469,7 +1473,8 @@ void vy_run_iterator_open(struct vy_run_iterator *itr, struct vy_run_iterator_stat *stat, struct vy_slice *slice, enum iterator_type iterator_type, - const struct tuple *key, const struct vy_read_view **rv, + const struct tuple *key, hint_t hint, + const struct vy_read_view **rv, struct key_def *cmp_def, struct key_def *key_def, struct tuple_format *format) { @@ -1481,7 +1486,7 @@ vy_run_iterator_open(struct vy_run_iterator *itr, itr->iterator_type = iterator_type; itr->key = key; - itr->hint = vy_stmt_hint(key, cmp_def); + itr->hint = hint; itr->read_view = rv; itr->curr_stmt = NULL; @@ -1508,13 +1513,16 @@ vy_run_iterator_open(struct vy_run_iterator *itr, * Returns 0 on success, -1 on memory allocation or IO error. */ static NODISCARD int -vy_run_iterator_next_key(struct vy_run_iterator *itr, struct tuple **ret) +vy_run_iterator_next_key(struct vy_run_iterator *itr, struct tuple **ret, + hint_t *ret_hint) { *ret = NULL; + *ret_hint = HINT_NONE; if (!itr->search_started) { itr->search_started = true; - return vy_run_iterator_seek(itr, NULL, HINT_NONE, ret); + return vy_run_iterator_seek(itr, NULL, HINT_NONE, + ret, ret_hint); } if (itr->curr_stmt == NULL) return 0; @@ -1548,7 +1556,7 @@ vy_run_iterator_next_key(struct vy_run_iterator *itr, struct tuple **ret) vy_run_iterator_stop(itr); return 0; } - return vy_run_iterator_find_lsn(itr, ret); + return vy_run_iterator_find_lsn(itr, ret, ret_hint); } /** @@ -1557,9 +1565,11 @@ vy_run_iterator_next_key(struct vy_run_iterator *itr, struct tuple **ret) * Returns 0 on success, -1 on memory allocation or IO error. */ static NODISCARD int -vy_run_iterator_next_lsn(struct vy_run_iterator *itr, struct tuple **ret) +vy_run_iterator_next_lsn(struct vy_run_iterator *itr, struct tuple **ret, + hint_t *ret_hint) { *ret = NULL; + *ret_hint = HINT_NONE; assert(itr->search_started); assert(itr->curr_stmt != NULL); @@ -1592,6 +1602,7 @@ next: vy_stmt_counter_acct_tuple(&itr->stat->get, itr->curr_stmt); *ret = itr->curr_stmt; + *ret_hint = itr->curr_hint; return 0; } @@ -1600,15 +1611,16 @@ vy_run_iterator_next(struct vy_run_iterator *itr, struct vy_history *history) { vy_history_cleanup(history); + hint_t hint; struct tuple *stmt; - if (vy_run_iterator_next_key(itr, &stmt) != 0) + if (vy_run_iterator_next_key(itr, &stmt, &hint) != 0) return -1; while (stmt != NULL) { - if (vy_history_append_stmt(history, stmt) != 0) + if (vy_history_append_stmt(history, stmt, hint) != 0) return -1; if (vy_history_is_terminal(history)) break; - if (vy_run_iterator_next_lsn(itr, &stmt) != 0) + if (vy_run_iterator_next_lsn(itr, &stmt, &hint) != 0) return -1; } return 0; @@ -1616,11 +1628,9 @@ vy_run_iterator_next(struct vy_run_iterator *itr, NODISCARD int vy_run_iterator_skip(struct vy_run_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history) { - hint_t last_hint = last_stmt == NULL ? HINT_NONE : - vy_stmt_hint(last_stmt, itr->cmp_def); /* * Check if the iterator is already positioned * at the statement following last_stmt. @@ -1635,16 +1645,17 @@ vy_run_iterator_skip(struct vy_run_iterator *itr, vy_history_cleanup(history); itr->search_started = true; + hint_t hint; struct tuple *stmt; - if (vy_run_iterator_seek(itr, last_stmt, last_hint, &stmt) != 0) + if (vy_run_iterator_seek(itr, last_stmt, last_hint, &stmt, &hint) != 0) return -1; while (stmt != NULL) { - if (vy_history_append_stmt(history, stmt) != 0) + if (vy_history_append_stmt(history, stmt, hint) != 0) return -1; if (vy_history_is_terminal(history)) break; - if (vy_run_iterator_next_lsn(itr, &stmt) != 0) + if (vy_run_iterator_next_lsn(itr, &stmt, &hint) != 0) return -1; } return 0; diff --git a/src/box/vy_run.h b/src/box/vy_run.h index 369221ff..9f517978 100644 --- a/src/box/vy_run.h +++ b/src/box/vy_run.h @@ -530,7 +530,8 @@ void vy_run_iterator_open(struct vy_run_iterator *itr, struct vy_run_iterator_stat *stat, struct vy_slice *slice, enum iterator_type iterator_type, - const struct tuple *key, const struct vy_read_view **rv, + const struct tuple *key, hint_t hint, + const struct vy_read_view **rv, struct key_def *cmp_def, struct key_def *key_def, struct tuple_format *format); @@ -550,7 +551,7 @@ vy_run_iterator_next(struct vy_run_iterator *itr, */ NODISCARD int vy_run_iterator_skip(struct vy_run_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history); /** diff --git a/src/box/vy_tx.c b/src/box/vy_tx.c index 596c7ed0..d8d7c905 100644 --- a/src/box/vy_tx.c +++ b/src/box/vy_tx.c @@ -1159,14 +1159,14 @@ vy_txw_iterator_open(struct vy_txw_iterator *itr, struct vy_txw_iterator_stat *stat, struct vy_tx *tx, struct vy_lsm *lsm, enum iterator_type iterator_type, - const struct tuple *key) + const struct tuple *key, hint_t hint) { itr->stat = stat; itr->tx = tx; itr->lsm = lsm; itr->iterator_type = iterator_type; itr->key = key; - itr->hint = vy_stmt_hint(key, lsm->cmp_def); + itr->hint = hint; itr->version = UINT32_MAX; itr->curr_txv = NULL; itr->search_started = false; @@ -1269,21 +1269,20 @@ out: if (itr->curr_txv != NULL) { vy_stmt_counter_acct_tuple(&itr->stat->get, itr->curr_txv->stmt); - return vy_history_append_stmt(history, itr->curr_txv->stmt); + return vy_history_append_stmt(history, itr->curr_txv->stmt, + itr->curr_txv->hint); } return 0; } NODISCARD int vy_txw_iterator_skip(struct vy_txw_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history) { assert(!itr->search_started || itr->version == itr->tx->write_set_version); - hint_t last_hint = last_stmt == NULL ? HINT_NONE : - vy_stmt_hint(last_stmt, itr->lsm->cmp_def); /* * Check if the iterator is already positioned * at the statement following last_stmt. @@ -1305,29 +1304,28 @@ vy_txw_iterator_skip(struct vy_txw_iterator *itr, if (itr->curr_txv != NULL) { vy_stmt_counter_acct_tuple(&itr->stat->get, itr->curr_txv->stmt); - return vy_history_append_stmt(history, itr->curr_txv->stmt); + return vy_history_append_stmt(history, itr->curr_txv->stmt, + itr->curr_txv->hint); } return 0; } NODISCARD int vy_txw_iterator_restore(struct vy_txw_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history) { if (!itr->search_started || itr->version == itr->tx->write_set_version) return 0; - hint_t last_hint = last_stmt == NULL ? HINT_NONE : - vy_stmt_hint(last_stmt, itr->lsm->cmp_def); - vy_txw_iterator_seek(itr, last_stmt, last_hint); vy_history_cleanup(history); if (itr->curr_txv != NULL) { vy_stmt_counter_acct_tuple(&itr->stat->get, itr->curr_txv->stmt); - if (vy_history_append_stmt(history, itr->curr_txv->stmt) != 0) + if (vy_history_append_stmt(history, itr->curr_txv->stmt, + itr->curr_txv->hint) != 0) return -1; } return 1; diff --git a/src/box/vy_tx.h b/src/box/vy_tx.h index 907957ae..f3b9eacc 100644 --- a/src/box/vy_tx.h +++ b/src/box/vy_tx.h @@ -442,7 +442,7 @@ vy_txw_iterator_open(struct vy_txw_iterator *itr, struct vy_txw_iterator_stat *stat, struct vy_tx *tx, struct vy_lsm *lsm, enum iterator_type iterator_type, - const struct tuple *key); + const struct tuple *key, hint_t hint); /** * Advance a txw iterator to the next key. @@ -460,7 +460,7 @@ vy_txw_iterator_next(struct vy_txw_iterator *itr, */ NODISCARD int vy_txw_iterator_skip(struct vy_txw_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history); /** @@ -471,7 +471,7 @@ vy_txw_iterator_skip(struct vy_txw_iterator *itr, */ int vy_txw_iterator_restore(struct vy_txw_iterator *itr, - const struct tuple *last_stmt, + const struct tuple *last_stmt, hint_t last_hint, struct vy_history *history); /** diff --git a/test/unit/vy_cache.c b/test/unit/vy_cache.c index d46d6c3f..d88ffc1a 100644 --- a/test/unit/vy_cache.c +++ b/test/unit/vy_cache.c @@ -85,16 +85,18 @@ test_basic() struct vy_read_view rv; rv.vlsn = INT64_MAX; const struct vy_read_view *rv_p = &rv; - vy_cache_iterator_open(&itr, &cache, ITER_GE, select_all, &rv_p); + vy_cache_iterator_open(&itr, &cache, ITER_GE, + select_all, HINT_NONE, &rv_p); /* Start iterator and make several steps. */ + hint_t hint; struct tuple *ret; bool unused; struct vy_history history; vy_history_create(&history, &history_node_pool); for (int i = 0; i < 4; ++i) vy_cache_iterator_next(&itr, &history, &unused); - ret = vy_history_last_stmt(&history); + ret = vy_history_last_stmt(&history, &hint); ok(vy_stmt_are_same(ret, &chain1[3], format), "next_key * 4"); @@ -115,9 +117,11 @@ test_basic() * must be chain1[1]. */ struct tuple *last_stmt = vy_new_simple_stmt(format, &chain1[0]); - ok(vy_cache_iterator_restore(&itr, last_stmt, &history, &unused) >= 0, + hint_t last_hint = vy_stmt_hint(last_stmt, key_def); + ok(vy_cache_iterator_restore(&itr, last_stmt, last_hint, + &history, &unused) >= 0, "restore"); - ret = vy_history_last_stmt(&history); + ret = vy_history_last_stmt(&history, &hint); ok(vy_stmt_are_same(ret, &chain1[1], format), "restore on position after last"); tuple_unref(last_stmt); diff --git a/test/unit/vy_mem.c b/test/unit/vy_mem.c index 798c7a99..4453e076 100644 --- a/test/unit/vy_mem.c +++ b/test/unit/vy_mem.c @@ -100,11 +100,13 @@ test_iterator_restore_after_insertion() end = mp_encode_uint(end, restore_on_value); struct tuple *restore_on_key = vy_stmt_new_replace(format, data, end); vy_stmt_set_lsn(restore_on_key, 100); + hint_t restore_on_hint = vy_stmt_hint(restore_on_key, key_def); end = data; end = mp_encode_array(end, 1); end = mp_encode_uint(end, restore_on_value_reverse); struct tuple *restore_on_key_reverse = vy_stmt_new_replace(format, data, end); vy_stmt_set_lsn(restore_on_key_reverse, 100); + hint_t restore_on_hint_reverse = vy_stmt_hint(restore_on_key_reverse, key_def); bool wrong_output = false; int i_fail = 0; @@ -187,13 +189,14 @@ test_iterator_restore_after_insertion() rv.vlsn = 100; const struct vy_read_view *prv = &rv; vy_mem_iterator_open(&itr, &stats, mem, - direct ? ITER_GE : ITER_LE, select_key, - &prv); + direct ? ITER_GE : ITER_LE, + select_key, HINT_NONE, &prv); + hint_t hint; struct tuple *t; struct vy_history history; vy_history_create(&history, &history_node_pool); int rc = vy_mem_iterator_next(&itr, &history); - t = vy_history_last_stmt(&history); + t = vy_history_last_stmt(&history, &hint); assert(rc == 0); size_t j = 0; while (t != NULL) { @@ -214,7 +217,7 @@ test_iterator_restore_after_insertion() else if(!direct && val <= middle_value) break; int rc = vy_mem_iterator_next(&itr, &history); - t = vy_history_last_stmt(&history); + t = vy_history_last_stmt(&history, &hint); assert(rc == 0); } if (t == NULL && j != expected_count) @@ -266,10 +269,13 @@ test_iterator_restore_after_insertion() } if (direct) - rc = vy_mem_iterator_restore(&itr, restore_on_key, &history); + rc = vy_mem_iterator_restore(&itr, restore_on_key, + restore_on_hint, &history); else - rc = vy_mem_iterator_restore(&itr, restore_on_key_reverse, &history); - t = vy_history_last_stmt(&history); + rc = vy_mem_iterator_restore(&itr, restore_on_key_reverse, + restore_on_hint_reverse, + &history); + t = vy_history_last_stmt(&history, &hint); j = 0; while (t != NULL) { @@ -286,7 +292,7 @@ test_iterator_restore_after_insertion() } j++; int rc = vy_mem_iterator_next(&itr, &history); - t = vy_history_last_stmt(&history); + t = vy_history_last_stmt(&history, &hint); assert(rc == 0); } if (j != expected_count) -- 2.11.0
next prev parent reply other threads:[~2019-04-02 17:33 UTC|newest] Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-02 17:33 [PATCH 00/13] Incorporate tuple comparison hints into Vinyl Vladimir Davydov 2019-04-02 17:33 ` [PATCH 01/13] vinyl: store tuple comparison hints in memory tree Vladimir Davydov 2019-04-04 8:53 ` Konstantin Osipov 2019-04-04 9:09 ` Vladimir Davydov 2019-04-04 9:48 ` Konstantin Osipov 2019-04-02 17:33 ` [PATCH 02/13] vinyl: store tuple comparison hints in cache tree Vladimir Davydov 2019-04-04 11:39 ` Konstantin Osipov 2019-04-02 17:33 ` [PATCH 03/13] vinyl: store tuple comparison hints in tx write set Vladimir Davydov 2019-04-04 11:41 ` Konstantin Osipov 2019-04-04 12:21 ` Vladimir Davydov 2019-04-04 12:40 ` Konstantin Osipov 2019-04-04 17:28 ` Vladimir Davydov 2019-04-02 17:33 ` [PATCH 04/13] vinyl: store tuple comparison hints in tx read set Vladimir Davydov 2019-04-04 11:42 ` Konstantin Osipov 2019-04-04 12:08 ` Vladimir Davydov 2019-04-02 17:33 ` [PATCH 05/13] vinyl: store tuple comparison hints in range tree Vladimir Davydov 2019-04-02 17:33 ` [PATCH 06/13] vinyl: store tuple comparison hints in page index Vladimir Davydov 2019-04-02 17:33 ` Vladimir Davydov [this message] 2019-04-04 11:43 ` [PATCH 07/13] vinyl: propagate tuple comparison hints to read iterator Konstantin Osipov 2019-04-02 17:33 ` [PATCH 08/13] vinyl: propagate tuple comparison hints to write iterator Vladimir Davydov 2019-04-04 11:47 ` Konstantin Osipov 2019-04-02 17:33 ` [PATCH 09/13] vinyl: forward tuple comparison hints to memory tree Vladimir Davydov 2019-04-04 12:10 ` Konstantin Osipov 2019-04-02 17:33 ` [PATCH 10/13] vinyl: forward tuple comparison hints to cache tree Vladimir Davydov 2019-04-04 12:11 ` Konstantin Osipov 2019-04-02 17:33 ` [PATCH 11/13] vinyl: forward tuple comparison hints to read iterator Vladimir Davydov 2019-04-04 12:12 ` Konstantin Osipov 2019-04-02 17:33 ` [PATCH 12/13] vinyl: forward tuple comparison hints to tx read set Vladimir Davydov 2019-04-04 12:12 ` Konstantin Osipov 2019-04-02 17:33 ` [PATCH 13/13] Make tuple comparison hints mandatory Vladimir Davydov 2019-04-04 12:21 ` Konstantin Osipov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=92bf17d61f69c18f907fe9041027ab43df8910f9.1554225074.git.vdavydov.dev@gmail.com \ --to=vdavydov.dev@gmail.com \ --cc=kostja.osipov@gmail.com \ --cc=tarantool-patches@freelists.org \ --subject='Re: [PATCH 07/13] vinyl: propagate tuple comparison hints to read iterator' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox