[RFC PATCH 5/7] btree.c: implement btree_iterate_keys

Ákos Uzonyi uzonyi.akos at gmail.com
Mon Jun 8 19:14:50 UTC 2020


---
 btree.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 btree.h |  5 ++--
 2 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/btree.c b/btree.c
index c105de36..7bdc687b 100644
--- a/btree.c
+++ b/btree.c
@@ -225,18 +225,11 @@ uint64_t
 btree_get_next_set_key(struct btree *b, uint64_t key)
 {
 }
-
-uint64_t
-btree_iterate_set_keys(struct btree *b, uint64_t start, uint64_t end,
-		       btree_iterate_fn fn, void *fn_data)
-{
-}
 #endif
 
-uint64_t
-btree_get(struct btree *b, uint64_t key)
+static uint64_t
+btree_data_block_get(struct btree *b, uint64_t *data, uint64_t key)
 {
-	uint64_t *data = btree_get_block(b, key, false);
 	size_t mask;
 	size_t pos;
 	size_t offs;
@@ -257,6 +250,69 @@ btree_get(struct btree *b, uint64_t key)
 	return (data[pos] >> offs) & (((uint64_t)1 << (1 << b->item_size_lg)) - 1);
 }
 
+uint64_t
+btree_get(struct btree *b, uint64_t key)
+{
+	return btree_data_block_get(b, btree_get_block(b, key, false), key);
+}
+
+static uint64_t
+btree_iterate_keys_block(struct btree *b, enum btree_iterate_flags flags,
+				btree_iterate_fn fn, void *fn_data,
+				uint64_t **block, uint64_t start, uint64_t end,
+				uint8_t depth, uint8_t max_depth)
+{
+	if (start > end)
+		return 0;
+
+	if ((block == BTREE_SET && !(flags & BTREE_ITERATE_KEYS_SET)) ||
+		(block == BTREE_UNSET && !(flags & BTREE_ITERATE_KEYS_UNSET)))
+		return 0;
+
+	if (block == BTREE_SET || block == BTREE_UNSET || depth == max_depth) {
+		for (uint64_t i = start; i <= end; i++)
+			fn(fn_data, i, btree_data_block_get(b, (uint64_t *) block, i));
+
+		return end - start + 1; //TODO: overflow
+	}
+
+	uint8_t parent_block_bit_off = depth == 0 ? b->key_size : btree_get_block_bit_offs(b, depth - 1, max_depth);
+	uint64_t first_key_in_block = start & (uint64_t) -1 << parent_block_bit_off;
+
+	uint8_t block_bit_off = btree_get_block_bit_offs(b, depth, max_depth);
+	uint8_t block_key_bits = parent_block_bit_off - block_bit_off;
+	uint64_t mask = ((uint64_t) 1 << (block_key_bits)) - 1;
+	uint64_t start_index = (start >> block_bit_off) & mask;
+	uint64_t end_index = (end >> block_bit_off) & mask;
+	uint64_t child_key_count = (uint64_t) 1 << block_bit_off;
+
+	uint64_t count = 0;
+
+	for (uint64_t i = start_index; i <= end_index; i++) {
+		uint64_t child_start = first_key_in_block + i * child_key_count;
+		uint64_t child_end = first_key_in_block + (i + 1) * child_key_count - 1;
+
+		if (child_start < start)
+			child_start = start;
+		if (child_end > end)
+			child_end = end;
+
+		count += btree_iterate_keys_block(b, flags, fn, fn_data,
+			(uint64_t **) block[i], child_start, child_end,
+			depth + 1, max_depth);
+	}
+
+	return count;
+}
+
+uint64_t btree_iterate_keys(struct btree *b, uint64_t start, uint64_t end,
+			    enum btree_iterate_flags flags, btree_iterate_fn fn,
+			    void *fn_data)
+{
+	return btree_iterate_keys_block(b, flags, fn, fn_data, b->data,
+		start, end, 0, btree_get_depth(b));
+}
+
 void
 btree_free_block(struct btree *b, uint64_t **block, uint8_t depth,
 		 int max_depth)
diff --git a/btree.h b/btree.h
index 0014caee..ed6e5249 100644
--- a/btree.h
+++ b/btree.h
@@ -48,6 +48,7 @@ struct btree {
 	uint8_t key_size;           /**< Key size, in bits, 1..64. */
 };
 
+typedef void (*btree_iterate_fn)(void *data, uint64_t key, uint64_t val);
 
 bool btree_check(uint8_t item_size_lg, uint8_t ptr_block_size_lg,
 		 uint8_t data_block_size_lg, uint8_t key_size);
@@ -74,11 +75,11 @@ int btree_interval_set(struct btree *b, uint64_t begin, uint64_t end,
 		       uint64_t val);
 
 uint64_t btree_get_next_set_key(struct btree *b, uint64_t key);
+#endif
+
 uint64_t btree_iterate_keys(struct btree *b, uint64_t start, uint64_t end,
 			    enum btree_iterate_flags flags, btree_iterate_fn fn,
 			    void *fn_data);
-#endif
-
 
 uint64_t btree_get(struct btree *b, uint64_t key);
 
-- 
2.26.2



More information about the Strace-devel mailing list