[PATCH v5 3/4] salad: introduce bps_tree_delete_identical routine
Kirill Shcherbatov
kshcherbatov at tarantool.org
Mon May 6 14:57:40 MSK 2019
A new routine bps_tree_delete_identical performs an element
deletion if and only if the found element is identical
to the routine argument.
Needed for #1257
---
src/box/vy_cache.h | 4 +--
src/box/vy_mem.h | 4 +--
src/lib/salad/bps_tree.h | 35 +++++++++++++++++++++++
test/unit/bps_tree.cc | 60 +++++++++++++++++++++++++++++++++++++++
test/unit/bps_tree.result | 2 ++
5 files changed, 101 insertions(+), 4 deletions(-)
diff --git a/src/box/vy_cache.h b/src/box/vy_cache.h
index a04290475..1f0143059 100644
--- a/src/box/vy_cache.h
+++ b/src/box/vy_cache.h
@@ -97,7 +97,7 @@ vy_cache_tree_key_cmp(struct vy_cache_node *a, struct vy_entry b,
#define bps_tree_elem_t struct vy_cache_node *
#define bps_tree_key_t struct vy_entry
#define bps_tree_arg_t struct key_def *
-#define BPS_TREE_NO_DEBUG
+#define BPS_TREE_IDENTICAL(a, b) vy_entry_is_equal(a->entry, b->entry)
#include "salad/bps_tree.h"
@@ -109,7 +109,7 @@ vy_cache_tree_key_cmp(struct vy_cache_node *a, struct vy_entry b,
#undef bps_tree_elem_t
#undef bps_tree_key_t
#undef bps_tree_arg_t
-#undef BPS_TREE_NO_DEBUG
+#undef BPS_TREE_IDENTICAL
/**
* Environment of the cache
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
#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
+ */
+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
+
/* 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);
+ if (struct_tree_find(&tree, 1) != NULL)
+ fail("deletion of identical element completed", "false");
+ struct_tree_destroy(&tree);
+ footer();
+}
+
int
main(void)
{
@@ -806,4 +865,5 @@ main(void)
if (extents_count != 0)
fail("memory leak!", "true");
insert_get_iterator();
+ delete_identical_check();
}
diff --git a/test/unit/bps_tree.result b/test/unit/bps_tree.result
index 8e1c3d4b6..dc21bf340 100644
--- a/test/unit/bps_tree.result
+++ b/test/unit/bps_tree.result
@@ -280,3 +280,5 @@ Count: 10575
*** approximate_count: done ***
*** insert_get_iterator ***
*** insert_get_iterator: done ***
+ *** delete_identical_check ***
+ *** delete_identical_check: done ***
--
2.21.0
More information about the Tarantool-patches
mailing list