From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH 07/12] vinyl: move vy_history to its own source file Date: Sun, 15 Apr 2018 22:55:20 +0300 Message-Id: <4aedbfc963dd58a7f450ddab1457b9f2a4053b58.1523820298.git.vdavydov.dev@gmail.com> In-Reply-To: References: In-Reply-To: References: To: kostja@tarantool.org Cc: tarantool-patches@freelists.org List-ID: So that it can be reused by vy_read_iterator. No functional changes, this patch just moves pieces of code. --- src/box/CMakeLists.txt | 1 + src/box/vy_history.c | 111 +++++++++++++++++++++++++++++++++++++ src/box/vy_history.h | 133 ++++++++++++++++++++++++++++++++++++++++++++ src/box/vy_point_lookup.c | 138 +--------------------------------------------- test/unit/CMakeLists.txt | 1 + 5 files changed, 247 insertions(+), 137 deletions(-) create mode 100644 src/box/vy_history.c create mode 100644 src/box/vy_history.h diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index ef7225d1..807ee566 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -84,6 +84,7 @@ add_library(box STATIC vy_cache.c vy_log.c vy_upsert.c + vy_history.c vy_read_set.c vy_scheduler.c request.c diff --git a/src/box/vy_history.c b/src/box/vy_history.c new file mode 100644 index 00000000..a11705a6 --- /dev/null +++ b/src/box/vy_history.c @@ -0,0 +1,111 @@ +/* + * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "vy_history.h" + +#include +#include +#include +#include + +#include "diag.h" +#include "fiber.h" +#include "tuple.h" +#include "iproto_constants.h" +#include "vy_stmt.h" +#include "vy_upsert.h" + +int +vy_history_append_stmt(struct vy_history *history, struct tuple *stmt) +{ + struct region *region = &fiber()->gc; + struct vy_history_node *node = region_alloc(region, sizeof(*node)); + if (node == NULL) { + diag_set(OutOfMemory, sizeof(*node), "region", + "struct vy_history_node"); + return -1; + } + node->is_refable = vy_stmt_is_refable(stmt); + if (node->is_refable) + tuple_ref(stmt); + node->stmt = stmt; + rlist_add_tail_entry(&history->stmts, node, link); + return 0; +} + +void +vy_history_cleanup(struct vy_history *history) +{ + struct vy_history_node *node; + rlist_foreach_entry(node, &history->stmts, link) { + if (node->is_refable) + tuple_unref(node->stmt); + } + rlist_create(&history->stmts); +} + +int +vy_history_apply(struct vy_history *history, const struct key_def *cmp_def, + struct tuple_format *format, int *upserts_applied, + struct tuple **ret) +{ + *ret = NULL; + *upserts_applied = 0; + if (rlist_empty(&history->stmts)) + return 0; + + struct tuple *curr_stmt = NULL; + struct vy_history_node *node = rlist_last_entry(&history->stmts, + struct vy_history_node, link); + if (vy_history_is_terminal(history)) { + if (vy_stmt_type(node->stmt) == IPROTO_DELETE) { + /* Ignore terminal delete */ + } else if (!node->is_refable) { + curr_stmt = vy_stmt_dup(node->stmt); + } else { + curr_stmt = node->stmt; + tuple_ref(curr_stmt); + } + node = rlist_prev_entry_safe(node, &history->stmts, link); + } + while (node != NULL) { + struct tuple *stmt = vy_apply_upsert(node->stmt, curr_stmt, + cmp_def, format, true); + ++*upserts_applied; + if (stmt == NULL) + return -1; + if (curr_stmt != NULL) + tuple_unref(curr_stmt); + curr_stmt = stmt; + node = rlist_prev_entry_safe(node, &history->stmts, link); + } + *ret = curr_stmt; + return 0; +} diff --git a/src/box/vy_history.h b/src/box/vy_history.h new file mode 100644 index 00000000..01f5364c --- /dev/null +++ b/src/box/vy_history.h @@ -0,0 +1,133 @@ +#ifndef INCLUDES_TARANTOOL_BOX_VY_HISTORY_H +#define INCLUDES_TARANTOOL_BOX_VY_HISTORY_H +/* + * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include "iproto_constants.h" +#include "vy_stmt.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +struct key_def; +struct tuple; +struct tuple_format; + +/** Key history. */ +struct vy_history { + /** + * List of statements sorted by LSN in descending order. + * Linked by vy_history_node::link. + */ + struct rlist stmts; +}; + +/** Key history node. */ +struct vy_history_node { + /** Link in a history list. */ + struct rlist link; + /** History statement. Referenced if @is_refable is set. */ + struct tuple *stmt; + /** + * Set if the statement stored in this node is refable, + * i.e. has a reference counter that can be incremented + * to pin the statement in memory. Refable statements are + * referenced by the history. It is a responsibility of + * the user of the history to track lifetime of unrefable + * statements. + * + * Note, we need to store this flag here, because by the + * time we clean up a history list, unrefable statements + * stored in it might have been deleted, thus making + * vy_stmt_is_refable() unusable. + */ + bool is_refable; +}; + +/** + * Initialize a history list. + */ +static inline void +vy_history_create(struct vy_history *history) +{ + rlist_create(&history->stmts); +} + +/** + * Return true if the history of a key contains terminal node in the end, + * i.e. REPLACE of DELETE statement. + */ +static inline bool +vy_history_is_terminal(struct vy_history *history) +{ + if (rlist_empty(&history->stmts)) + return false; + struct vy_history_node *node = rlist_last_entry(&history->stmts, + struct vy_history_node, link); + assert(vy_stmt_type(node->stmt) == IPROTO_REPLACE || + vy_stmt_type(node->stmt) == IPROTO_DELETE || + vy_stmt_type(node->stmt) == IPROTO_INSERT || + vy_stmt_type(node->stmt) == IPROTO_UPSERT); + return vy_stmt_type(node->stmt) != IPROTO_UPSERT; +} + +/** + * Append an (older) statement to a history list. + * Returns 0 on success, -1 on memory allocation error. + */ +int +vy_history_append_stmt(struct vy_history *history, struct tuple *stmt); + +/** + * Release all statements stored in the given history and + * reinitialize the history list. + */ +void +vy_history_cleanup(struct vy_history *history); + +/** + * Get a resultant statement from collected history. + */ +int +vy_history_apply(struct vy_history *history, const struct key_def *cmp_def, + struct tuple_format *format, int *upserts_applied, + struct tuple **ret); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* INCLUDES_TARANTOOL_BOX_VY_HISTORY_H */ diff --git a/src/box/vy_point_lookup.c b/src/box/vy_point_lookup.c index 7c9995ed..6994ebfd 100644 --- a/src/box/vy_point_lookup.c +++ b/src/box/vy_point_lookup.c @@ -45,101 +45,7 @@ #include "vy_mem.h" #include "vy_run.h" #include "vy_cache.h" -#include "vy_upsert.h" - -/** Key history. */ -struct vy_history { - /** - * List of statements sorted by LSN in descending order. - * Linked by vy_history_node::link. - */ - struct rlist stmts; -}; - -/** Key history node. */ -struct vy_history_node { - /** Link in a history list. */ - struct rlist link; - /** History statement. Referenced if @is_refable is set. */ - struct tuple *stmt; - /** - * Set if the statement stored in this node is refable, - * i.e. has a reference counter that can be incremented - * to pin the statement in memory. Refable statements are - * referenced by the history. It is a responsibility of - * the user of the history to track lifetime of unrefable - * statements. - * - * Note, we need to store this flag here, because by the - * time we clean up a history list, unrefable statements - * stored in it might have been deleted, thus making - * vy_stmt_is_refable() unusable. - */ - bool is_refable; -}; - -/** - * Initialize a history list. - */ -static void -vy_history_create(struct vy_history *history) -{ - rlist_create(&history->stmts); -} - -/** - * Append an (older) statement to a history list. - * Returns 0 on success, -1 on memory allocation error. - */ -static int -vy_history_append_stmt(struct vy_history *history, struct tuple *stmt) -{ - struct region *region = &fiber()->gc; - struct vy_history_node *node = region_alloc(region, sizeof(*node)); - if (node == NULL) { - diag_set(OutOfMemory, sizeof(*node), "region", - "struct vy_history_node"); - return -1; - } - node->is_refable = vy_stmt_is_refable(stmt); - if (node->is_refable) - tuple_ref(stmt); - node->stmt = stmt; - rlist_add_tail_entry(&history->stmts, node, link); - return 0; -} - -/** - * Release all statements stored in the given history and - * reinitialize the history list. - */ -static void -vy_history_cleanup(struct vy_history *history) -{ - struct vy_history_node *node; - rlist_foreach_entry(node, &history->stmts, link) - if (node->is_refable) - tuple_unref(node->stmt); - rlist_create(&history->stmts); -} - -/** - * Return true if the history of a key contains terminal node in the end, - * i.e. REPLACE of DELETE statement. - */ -static bool -vy_history_is_terminal(struct vy_history *history) -{ - if (rlist_empty(&history->stmts)) - return false; - struct vy_history_node *node = rlist_last_entry(&history->stmts, - struct vy_history_node, link); - assert(vy_stmt_type(node->stmt) == IPROTO_REPLACE || - vy_stmt_type(node->stmt) == IPROTO_DELETE || - vy_stmt_type(node->stmt) == IPROTO_INSERT || - vy_stmt_type(node->stmt) == IPROTO_UPSERT); - return vy_stmt_type(node->stmt) != IPROTO_UPSERT; -} +#include "vy_history.h" /** * Scan TX write set for given key. @@ -327,48 +233,6 @@ vy_point_lookup_scan_slices(struct vy_lsm *lsm, const struct vy_read_view **rv, return rc; } -/** - * Get a resultant statement from collected history. - */ -static int -vy_history_apply(struct vy_history *history, const struct key_def *cmp_def, - struct tuple_format *format, int *upserts_applied, - struct tuple **ret) -{ - *ret = NULL; - *upserts_applied = 0; - if (rlist_empty(&history->stmts)) - return 0; - - struct tuple *curr_stmt = NULL; - struct vy_history_node *node = rlist_last_entry(&history->stmts, - struct vy_history_node, link); - if (vy_history_is_terminal(history)) { - if (vy_stmt_type(node->stmt) == IPROTO_DELETE) { - /* Ignore terminal delete */ - } else if (!node->is_refable) { - curr_stmt = vy_stmt_dup(node->stmt); - } else { - curr_stmt = node->stmt; - tuple_ref(curr_stmt); - } - node = rlist_prev_entry_safe(node, &history->stmts, link); - } - while (node != NULL) { - struct tuple *stmt = vy_apply_upsert(node->stmt, curr_stmt, - cmp_def, format, true); - ++*upserts_applied; - if (stmt == NULL) - return -1; - if (curr_stmt != NULL) - tuple_unref(curr_stmt); - curr_stmt = stmt; - node = rlist_prev_entry_safe(node, &history->stmts, link); - } - *ret = curr_stmt; - return 0; -} - int vy_point_lookup(struct vy_lsm *lsm, struct vy_tx *tx, const struct vy_read_view **rv, diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 7e1c95ed..db270de6 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -160,6 +160,7 @@ add_executable(vy_point_lookup.test ${PROJECT_SOURCE_DIR}/src/box/vy_tx.c ${PROJECT_SOURCE_DIR}/src/box/vy_read_set.c ${PROJECT_SOURCE_DIR}/src/box/vy_upsert.c + ${PROJECT_SOURCE_DIR}/src/box/vy_history.c ${PROJECT_SOURCE_DIR}/src/box/vy_lsm.c ${PROJECT_SOURCE_DIR}/src/box/vy_cache.c ${PROJECT_SOURCE_DIR}/src/box/index_def.c -- 2.11.0