[PATCH v5 3/4] salad: introduce bps_tree_delete_identical routine
Vladimir Davydov
vdavydov.dev at gmail.com
Mon May 6 17:34:45 MSK 2019
On Mon, May 06, 2019 at 02:57:40PM +0300, Kirill Shcherbatov wrote:
> diff --git a/src/box/vy_mem.h b/src/box/vy_mem.h
> index 7df9a1817..35cca6334 100644
> --- a/src/box/vy_mem.h
> +++ b/src/box/vy_mem.h
> @@ -121,10 +121,10 @@ vy_mem_tree_cmp_key(struct vy_entry entry, struct vy_mem_tree_key *key,
> #define BPS_TREE_EXTENT_SIZE VY_MEM_TREE_EXTENT_SIZE
> #define BPS_TREE_COMPARE(a, b, cmp_def) vy_mem_tree_cmp(a, b, cmp_def)
> #define BPS_TREE_COMPARE_KEY(a, b, cmp_def) vy_mem_tree_cmp_key(a, b, cmp_def)
> +#define BPS_TREE_IDENTICAL(a, b) vy_entry_is_equal(a, b)
> #define bps_tree_elem_t struct vy_entry
> #define bps_tree_key_t struct vy_mem_tree_key *
> #define bps_tree_arg_t struct key_def *
> -#define BPS_TREE_NO_DEBUG
>
> #include <salad/bps_tree.h>
>
> @@ -136,7 +136,7 @@ vy_mem_tree_cmp_key(struct vy_entry entry, struct vy_mem_tree_key *key,
> #undef bps_tree_elem_t
> #undef bps_tree_key_t
> #undef bps_tree_arg_t
> -#undef BPS_TREE_NO_DEBUG
> +#undef BPS_TREE_IDENTICAL
>
> /** @endcond false */
>
> diff --git a/src/lib/salad/bps_tree.h b/src/lib/salad/bps_tree.h
> index 29eb8b81a..71e43e48a 100644
> --- a/src/lib/salad/bps_tree.h
> +++ b/src/lib/salad/bps_tree.h
> @@ -280,6 +280,7 @@
> */
> #ifndef BPS_TREE_IDENTICAL
> #define BPS_TREE_IDENTICAL(a, b) (a == b)
> +#define BPS_TREE_IDENTICAL_STD 1
This looks ugly. Let's require the caller to always define
BPS_TREE_IDENTICAL - it's not a big deal.
> #endif
>
> /**
> @@ -360,6 +361,7 @@ typedef uint32_t bps_tree_block_id_t;
> #define bps_tree_insert _api_name(insert)
> #define bps_tree_insert_get_iterator _api_name(insert_get_iterator)
> #define bps_tree_delete _api_name(delete)
> +#define bps_tree_delete_identical _api_name(delete_identical)
> #define bps_tree_size _api_name(size)
> #define bps_tree_mem_used _api_name(mem_used)
> #define bps_tree_random _api_name(random)
> @@ -4516,6 +4518,33 @@ bps_tree_delete(struct bps_tree *tree, bps_tree_elem_t elem)
> return 0;
> }
>
> +/**
> + * @brief Delete an identical element from a tree (unlike
> + * bps_tree_delete this routine relies on BPS_TREE_IDENTICAL
> + * instead of BPS_TREE_COMPARE).
> + * @param tree - pointer to a tree
> + * @param elem - the element tot delete
> + * @return - true on success or false if the element was not found in tree
I guess it should also return -1 if the element was found but not
deleted, in other words it should return 0 iff the element has been
deleted.
> + */
> +static inline int
> +bps_tree_delete_identical(struct bps_tree *tree, bps_tree_elem_t elem)
> +{
> + if (tree->root_id == (bps_tree_block_id_t)(-1))
> + return -1;
> + struct bps_inner_path_elem path[BPS_TREE_MAX_DEPTH];
> + struct bps_leaf_path_elem leaf_path_elem;
> + bool exact;
> + bps_tree_collect_path(tree, elem, path, &leaf_path_elem, &exact);
> +
> + if (!exact)
> + return -1;
> +
> + struct bps_leaf *leaf = leaf_path_elem.block;
> + if (BPS_TREE_IDENTICAL(leaf->elems[leaf_path_elem.insertion_point], elem))
> + bps_tree_process_delete_leaf(tree, &leaf_path_elem);
> + return 0;
> +}
> +
> /**
> * @brief Recursively find a maximum element in subtree.
> * Used only for debug purposes
> @@ -6054,6 +6083,7 @@ bps_tree_debug_check_internal_functions(bool assertme)
> #undef bps_tree_find
> #undef bps_tree_insert
> #undef bps_tree_delete
> +#undef bps_tree_delete_identical
> #undef bps_tree_size
> #undef bps_tree_mem_used
> #undef bps_tree_random
> @@ -6155,4 +6185,9 @@ bps_tree_debug_check_internal_functions(bool assertme)
> #undef bps_tree_debug_check_move_to_left_inner
> #undef bps_tree_debug_check_insert_and_move_to_right_inner
> #undef bps_tree_debug_check_insert_and_move_to_left_inner
> +
> +#if defined(BPS_TREE_IDENTICAL_STD)
> +#undef BPS_TREE_IDENTICAL
> +#endif
> +
> /* }}} */
> diff --git a/test/unit/bps_tree.cc b/test/unit/bps_tree.cc
> index 191dce95a..9132fad69 100644
> --- a/test/unit/bps_tree.cc
> +++ b/test/unit/bps_tree.cc
> @@ -60,6 +60,46 @@ compare(type_t a, type_t b);
> #undef bps_tree_key_t
> #undef bps_tree_arg_t
>
> +struct elem_t {
> + long info;
> + long marker;
> +};
> +
> +static bool
> +equal(const elem_t &a, const elem_t &b)
> +{
> + return a.info == b.info && a.marker == b.marker;
> +}
> +
> +static int compare(const elem_t &a, const elem_t &b)
> +{
> + return a.info < b.info ? -1 : a.info > b.info ? 1 : 0;
> +}
> +
> +static int compare_key(const elem_t &a, long b)
> +{
> + return a.info < b ? -1 : a.info > b ? 1 : 0;
> +}
> +
> +#define BPS_TREE_NAME struct_tree
> +#define BPS_TREE_BLOCK_SIZE 128 /* value is to low specially for tests */
> +#define BPS_TREE_EXTENT_SIZE 2048 /* value is to low specially for tests */
> +#define BPS_TREE_IDENTICAL(a, b) equal(a, b)
> +#define BPS_TREE_COMPARE(a, b, arg) compare(a, b)
> +#define BPS_TREE_COMPARE_KEY(a, b, arg) compare_key(a, b)
> +#define bps_tree_elem_t struct elem_t
> +#define bps_tree_key_t long
> +#define bps_tree_arg_t int
> +#include "salad/bps_tree.h"
> +#undef BPS_TREE_NAME
> +#undef BPS_TREE_BLOCK_SIZE
> +#undef BPS_TREE_EXTENT_SIZE
> +#undef BPS_TREE_COMPARE
> +#undef BPS_TREE_COMPARE_KEY
> +#undef bps_tree_elem_t
> +#undef bps_tree_key_t
> +#undef bps_tree_arg_t
> +
Could you please reuse the existing tree for the test rather than
introducing a new one?
> /* tree for approximate_count test */
> #define BPS_TREE_NAME approx
> #define BPS_TREE_BLOCK_SIZE 128 /* value is to low specially for tests */
> @@ -792,6 +832,25 @@ insert_get_iterator()
> footer();
> }
>
> +static void
> +delete_identical_check()
> +{
> + header();
> + struct_tree tree;
> + struct_tree_create(&tree, 0, extent_alloc, extent_free, &extents_count);
> + struct elem_t e1 = {1, 1};
> + struct_tree_insert(&tree, e1, NULL);
> + struct elem_t e2 = {1, 2};
> + struct_tree_delete_identical(&tree, e2);
> + if (struct_tree_find(&tree, 1) == NULL)
> + fail("skip the deletion of non-identical element", "false");
> + struct_tree_delete_identical(&tree, e1);
Please check the return value as well.
> + if (struct_tree_find(&tree, 1) != NULL)
> + fail("deletion of identical element completed", "false");
> + struct_tree_destroy(&tree);
> + footer();
> +}
> +
> int
> main(void)
> {
More information about the Tarantool-patches
mailing list