v12-0005-Use-rt_node_ptr-to-reference-radix-tree-nodes.patch
application/octet-stream
Filename: v12-0005-Use-rt_node_ptr-to-reference-radix-tree-nodes.patch
Type: application/octet-stream
Part: 1
Patch
Format: format-patch
Series: patch v12-0005
Subject: Use rt_node_ptr to reference radix tree nodes.
| File | + | − |
|---|---|---|
| src/backend/lib/radixtree.c | 398 | 290 |
From f9bc757064a1dcbcfb98f9df2a497b510252c0d2 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Mon, 14 Nov 2022 11:44:17 +0900
Subject: [PATCH v12 5/7] Use rt_node_ptr to reference radix tree nodes.
---
src/backend/lib/radixtree.c | 688 +++++++++++++++++++++---------------
1 file changed, 398 insertions(+), 290 deletions(-)
diff --git a/src/backend/lib/radixtree.c b/src/backend/lib/radixtree.c
index 673cc5e46b..a97d86ae2b 100644
--- a/src/backend/lib/radixtree.c
+++ b/src/backend/lib/radixtree.c
@@ -145,6 +145,19 @@ typedef enum rt_size_class
#define RT_SIZE_CLASS_COUNT (RT_CLASS_256 + 1)
} rt_size_class;
+/*
+ * rt_pointer is a pointer compatible with a pointer to local memory and a
+ * pointer for DSA area (i.e. dsa_pointer). Since the radix tree node can be
+ * allocated in backend local memory as well as DSA area, we cannot use a
+ * C-pointer to rt_node (i.e. backend local memory address) for child pointers
+ * in inner nodes. Inner nodes need to use rt_pointer instead. We can get
+ * the backend local memory address of a node from a rt_pointer by using
+ * rt_pointer_decode().
+*/
+typedef uintptr_t rt_pointer;
+#define InvalidRTPointer ((rt_pointer) 0)
+#define RTPointerIsValid(x) (((rt_pointer) (x)) != InvalidRTPointer)
+
/* Common type for all nodes types */
typedef struct rt_node
{
@@ -170,8 +183,7 @@ typedef struct rt_node
/* Node kind, one per search/set algorithm */
uint8 kind;
} rt_node;
-#define NODE_IS_LEAF(n) (((rt_node *) (n))->shift == 0)
-#define NODE_IS_EMPTY(n) (((rt_node *) (n))->count == 0)
+#define RT_NODE_IS_LEAF(n) (((rt_node *) (n))->shift == 0)
#define VAR_NODE_HAS_FREE_SLOT(node) \
((node)->base.n.count < (node)->base.n.fanout)
#define FIXED_NODE_HAS_FREE_SLOT(node, class) \
@@ -235,7 +247,7 @@ typedef struct rt_node_inner_4
rt_node_base_4 base;
/* number of children depends on size class */
- rt_node *children[FLEXIBLE_ARRAY_MEMBER];
+ rt_pointer children[FLEXIBLE_ARRAY_MEMBER];
} rt_node_inner_4;
typedef struct rt_node_leaf_4
@@ -251,7 +263,7 @@ typedef struct rt_node_inner_32
rt_node_base_32 base;
/* number of children depends on size class */
- rt_node *children[FLEXIBLE_ARRAY_MEMBER];
+ rt_pointer children[FLEXIBLE_ARRAY_MEMBER];
} rt_node_inner_32;
typedef struct rt_node_leaf_32
@@ -267,7 +279,7 @@ typedef struct rt_node_inner_125
rt_node_base_125 base;
/* number of children depends on size class */
- rt_node *children[FLEXIBLE_ARRAY_MEMBER];
+ rt_pointer children[FLEXIBLE_ARRAY_MEMBER];
} rt_node_inner_125;
typedef struct rt_node_leaf_125
@@ -287,7 +299,7 @@ typedef struct rt_node_inner_256
rt_node_base_256 base;
/* Slots for 256 children */
- rt_node *children[RT_NODE_MAX_SLOTS];
+ rt_pointer children[RT_NODE_MAX_SLOTS];
} rt_node_inner_256;
typedef struct rt_node_leaf_256
@@ -301,6 +313,29 @@ typedef struct rt_node_leaf_256
uint64 values[RT_NODE_MAX_SLOTS];
} rt_node_leaf_256;
+/* rt_node_ptr is a data structure representing a pointer for a rt_node */
+typedef struct rt_node_ptr
+{
+ rt_pointer encoded;
+ rt_node *decoded;
+} rt_node_ptr;
+#define InvalidRTNodePtr \
+ (rt_node_ptr) {.encoded = InvalidRTPointer, .decoded = NULL}
+#define RTNodePtrIsValid(n) \
+ (!rt_node_ptr_eq((rt_node_ptr *) &(n), &(InvalidRTNodePtr)))
+
+/* Macros for rt_node_ptr to access the fields of rt_node */
+#define NODE_RAW(n) (n.decoded)
+#define NODE_IS_LEAF(n) (NODE_RAW(n)->shift == 0)
+#define NODE_IS_EMPTY(n) (NODE_COUNT(n) == 0)
+#define NODE_KIND(n) (NODE_RAW(n)->kind)
+#define NODE_COUNT(n) (NODE_RAW(n)->count)
+#define NODE_SHIFT(n) (NODE_RAW(n)->shift)
+#define NODE_CHUNK(n) (NODE_RAW(n)->chunk)
+#define NODE_FANOUT(n) (NODE_RAW(n)->fanout)
+#define NODE_HAS_FREE_SLOT(n) \
+ (NODE_COUNT(n) < rt_node_kind_info[NODE_KIND(n)].fanout)
+
/* Information for each size class */
typedef struct rt_size_class_elem
{
@@ -389,7 +424,7 @@ static rt_size_class kind_min_size_class[RT_NODE_KIND_COUNT] = {
*/
typedef struct rt_node_iter
{
- rt_node *node; /* current node being iterated */
+ rt_node_ptr node; /* current node being iterated */
int current_idx; /* current position. -1 for initial value */
} rt_node_iter;
@@ -410,7 +445,7 @@ struct radix_tree
{
MemoryContext context;
- rt_node *root;
+ rt_pointer root;
uint64 max_val;
uint64 num_keys;
@@ -424,27 +459,58 @@ struct radix_tree
};
static void rt_new_root(radix_tree *tree, uint64 key);
-static rt_node *rt_alloc_node(radix_tree *tree, rt_size_class size_class, bool inner);
-static inline void rt_init_node(rt_node *node, uint8 kind, rt_size_class size_class,
+
+static rt_node_ptr rt_alloc_node(radix_tree *tree, rt_size_class size_class, bool inner);
+static inline void rt_init_node(rt_node_ptr node, uint8 kind, rt_size_class size_class,
bool inner);
-static void rt_free_node(radix_tree *tree, rt_node *node);
+static void rt_free_node(radix_tree *tree, rt_node_ptr node);
static void rt_extend(radix_tree *tree, uint64 key);
-static inline bool rt_node_search_inner(rt_node *node, uint64 key, rt_action action,
- rt_node **child_p);
-static inline bool rt_node_search_leaf(rt_node *node, uint64 key, rt_action action,
+static inline bool rt_node_search_inner(rt_node_ptr node_ptr, uint64 key, rt_action action,
+ rt_pointer *child_p);
+static inline bool rt_node_search_leaf(rt_node_ptr node_ptr, uint64 key, rt_action action,
uint64 *value_p);
-static bool rt_node_insert_inner(radix_tree *tree, rt_node *parent, rt_node *node,
- uint64 key, rt_node *child);
-static bool rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
+static bool rt_node_insert_inner(radix_tree *tree, rt_node_ptr parent, rt_node_ptr node,
+ uint64 key, rt_node_ptr child);
+static bool rt_node_insert_leaf(radix_tree *tree, rt_node_ptr parent, rt_node_ptr node,
uint64 key, uint64 value);
-static inline rt_node *rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter);
+static inline bool rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter,
+ rt_node_ptr *child_p);
static inline bool rt_node_leaf_iterate_next(rt_iter *iter, rt_node_iter *node_iter,
uint64 *value_p);
-static void rt_update_iter_stack(rt_iter *iter, rt_node *from_node, int from);
+static void rt_update_iter_stack(rt_iter *iter, rt_node_ptr from_node, int from);
static inline void rt_iter_update_key(rt_iter *iter, uint8 chunk, uint8 shift);
/* verification (available only with assertion) */
-static void rt_verify_node(rt_node *node);
+static void rt_verify_node(rt_node_ptr node);
+
+/* Decode and encode functions of rt_pointer */
+static inline rt_node *
+rt_pointer_decode(rt_pointer encoded)
+{
+ return (rt_node *) encoded;
+}
+
+static inline rt_pointer
+rt_pointer_encode(rt_node *decoded)
+{
+ return (rt_pointer) decoded;
+}
+
+/* Return a rt_node_ptr created from the given encoded pointer */
+static inline rt_node_ptr
+rt_node_ptr_encoded(rt_pointer encoded)
+{
+ return (rt_node_ptr) {
+ .encoded = encoded,
+ .decoded = rt_pointer_decode(encoded),
+ };
+}
+
+static inline bool
+rt_node_ptr_eq(rt_node_ptr *a, rt_node_ptr *b)
+{
+ return (a->decoded == b->decoded) && (a->encoded == b->encoded);
+}
/*
* Return index of the first element in 'base' that equals 'key'. Return -1
@@ -593,10 +659,10 @@ node_32_get_insertpos(rt_node_base_32 *node, uint8 chunk)
/* Shift the elements right at 'idx' by one */
static inline void
-chunk_children_array_shift(uint8 *chunks, rt_node **children, int count, int idx)
+chunk_children_array_shift(uint8 *chunks, rt_pointer *children, int count, int idx)
{
memmove(&(chunks[idx + 1]), &(chunks[idx]), sizeof(uint8) * (count - idx));
- memmove(&(children[idx + 1]), &(children[idx]), sizeof(rt_node *) * (count - idx));
+ memmove(&(children[idx + 1]), &(children[idx]), sizeof(rt_pointer) * (count - idx));
}
static inline void
@@ -608,10 +674,10 @@ chunk_values_array_shift(uint8 *chunks, uint64 *values, int count, int idx)
/* Delete the element at 'idx' */
static inline void
-chunk_children_array_delete(uint8 *chunks, rt_node **children, int count, int idx)
+chunk_children_array_delete(uint8 *chunks, rt_pointer *children, int count, int idx)
{
memmove(&(chunks[idx]), &(chunks[idx + 1]), sizeof(uint8) * (count - idx - 1));
- memmove(&(children[idx]), &(children[idx + 1]), sizeof(rt_node *) * (count - idx - 1));
+ memmove(&(children[idx]), &(children[idx + 1]), sizeof(rt_pointer) * (count - idx - 1));
}
static inline void
@@ -623,12 +689,12 @@ chunk_values_array_delete(uint8 *chunks, uint64 *values, int count, int idx)
/* Copy both chunks and children/values arrays */
static inline void
-chunk_children_array_copy(uint8 *src_chunks, rt_node **src_children,
- uint8 *dst_chunks, rt_node **dst_children)
+chunk_children_array_copy(uint8 *src_chunks, rt_pointer *src_children,
+ uint8 *dst_chunks, rt_pointer *dst_children)
{
const int fanout = rt_size_class_info[RT_CLASS_4_FULL].fanout;
const Size chunk_size = sizeof(uint8) * fanout;
- const Size children_size = sizeof(rt_node *) * fanout;
+ const Size children_size = sizeof(rt_pointer) * fanout;
memcpy(dst_chunks, src_chunks, chunk_size);
memcpy(dst_children, src_children, children_size);
@@ -660,7 +726,7 @@ node_125_is_chunk_used(rt_node_base_125 *node, uint8 chunk)
static inline bool
node_inner_125_is_slot_used(rt_node_inner_125 *node, uint8 slot)
{
- Assert(!NODE_IS_LEAF(node));
+ Assert(!RT_NODE_IS_LEAF(node));
Assert(slot < node->base.n.fanout);
return (node->base.isset[WORDNUM(slot)] & ((bitmapword) 1 << BITNUM(slot))) != 0;
}
@@ -668,23 +734,23 @@ node_inner_125_is_slot_used(rt_node_inner_125 *node, uint8 slot)
static inline bool
node_leaf_125_is_slot_used(rt_node_leaf_125 *node, uint8 slot)
{
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
Assert(slot < node->base.n.fanout);
return (node->base.isset[WORDNUM(slot)] & ((bitmapword) 1 << BITNUM(slot))) != 0;
}
#endif
-static inline rt_node *
+static inline rt_pointer
node_inner_125_get_child(rt_node_inner_125 *node, uint8 chunk)
{
- Assert(!NODE_IS_LEAF(node));
+ Assert(!RT_NODE_IS_LEAF(node));
return node->children[node->base.slot_idxs[chunk]];
}
static inline uint64
node_leaf_125_get_value(rt_node_leaf_125 *node, uint8 chunk)
{
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
Assert(((rt_node_base_125 *) node)->slot_idxs[chunk] != RT_NODE_125_INVALID_IDX);
return node->values[node->base.slot_idxs[chunk]];
}
@@ -694,9 +760,9 @@ node_inner_125_delete(rt_node_inner_125 *node, uint8 chunk)
{
int slotpos = node->base.slot_idxs[chunk];
- Assert(!NODE_IS_LEAF(node));
+ Assert(!RT_NODE_IS_LEAF(node));
node->base.isset[WORDNUM(slotpos)] &= ~((bitmapword) 1 << BITNUM(slotpos));
- node->children[node->base.slot_idxs[chunk]] = NULL;
+ node->children[node->base.slot_idxs[chunk]] = InvalidRTPointer;
node->base.slot_idxs[chunk] = RT_NODE_125_INVALID_IDX;
}
@@ -705,7 +771,7 @@ node_leaf_125_delete(rt_node_leaf_125 *node, uint8 chunk)
{
int slotpos = node->base.slot_idxs[chunk];
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
node->base.isset[WORDNUM(slotpos)] &= ~((bitmapword) 1 << BITNUM(slotpos));
node->base.slot_idxs[chunk] = RT_NODE_125_INVALID_IDX;
}
@@ -737,11 +803,11 @@ node_125_find_unused_slot(bitmapword *isset)
}
static inline void
-node_inner_125_insert(rt_node_inner_125 *node, uint8 chunk, rt_node *child)
+node_inner_125_insert(rt_node_inner_125 *node, uint8 chunk, rt_pointer child)
{
int slotpos;
- Assert(!NODE_IS_LEAF(node));
+ Assert(!RT_NODE_IS_LEAF(node));
slotpos = node_125_find_unused_slot(node->base.isset);
Assert(slotpos < node->base.n.fanout);
@@ -756,7 +822,7 @@ node_leaf_125_insert(rt_node_leaf_125 *node, uint8 chunk, uint64 value)
{
int slotpos;
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
slotpos = node_125_find_unused_slot(node->base.isset);
Assert(slotpos < node->base.n.fanout);
@@ -767,16 +833,16 @@ node_leaf_125_insert(rt_node_leaf_125 *node, uint8 chunk, uint64 value)
/* Update the child corresponding to 'chunk' to 'child' */
static inline void
-node_inner_125_update(rt_node_inner_125 *node, uint8 chunk, rt_node *child)
+node_inner_125_update(rt_node_inner_125 *node, uint8 chunk, rt_pointer child)
{
- Assert(!NODE_IS_LEAF(node));
+ Assert(!RT_NODE_IS_LEAF(node));
node->children[node->base.slot_idxs[chunk]] = child;
}
static inline void
node_leaf_125_update(rt_node_leaf_125 *node, uint8 chunk, uint64 value)
{
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
node->values[node->base.slot_idxs[chunk]] = value;
}
@@ -786,21 +852,21 @@ node_leaf_125_update(rt_node_leaf_125 *node, uint8 chunk, uint64 value)
static inline bool
node_inner_256_is_chunk_used(rt_node_inner_256 *node, uint8 chunk)
{
- Assert(!NODE_IS_LEAF(node));
- return (node->children[chunk] != NULL);
+ Assert(!RT_NODE_IS_LEAF(node));
+ return RTPointerIsValid(node->children[chunk]);
}
static inline bool
node_leaf_256_is_chunk_used(rt_node_leaf_256 *node, uint8 chunk)
{
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
return (node->isset[RT_NODE_BITMAP_BYTE(chunk)] & RT_NODE_BITMAP_BIT(chunk)) != 0;
}
-static inline rt_node *
+static inline rt_pointer
node_inner_256_get_child(rt_node_inner_256 *node, uint8 chunk)
{
- Assert(!NODE_IS_LEAF(node));
+ Assert(!RT_NODE_IS_LEAF(node));
Assert(node_inner_256_is_chunk_used(node, chunk));
return node->children[chunk];
}
@@ -808,16 +874,16 @@ node_inner_256_get_child(rt_node_inner_256 *node, uint8 chunk)
static inline uint64
node_leaf_256_get_value(rt_node_leaf_256 *node, uint8 chunk)
{
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
Assert(node_leaf_256_is_chunk_used(node, chunk));
return node->values[chunk];
}
/* Set the child in the node-256 */
static inline void
-node_inner_256_set(rt_node_inner_256 *node, uint8 chunk, rt_node *child)
+node_inner_256_set(rt_node_inner_256 *node, uint8 chunk, rt_pointer child)
{
- Assert(!NODE_IS_LEAF(node));
+ Assert(!RT_NODE_IS_LEAF(node));
node->children[chunk] = child;
}
@@ -825,7 +891,7 @@ node_inner_256_set(rt_node_inner_256 *node, uint8 chunk, rt_node *child)
static inline void
node_leaf_256_set(rt_node_leaf_256 *node, uint8 chunk, uint64 value)
{
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
node->isset[RT_NODE_BITMAP_BYTE(chunk)] |= RT_NODE_BITMAP_BIT(chunk);
node->values[chunk] = value;
}
@@ -834,14 +900,14 @@ node_leaf_256_set(rt_node_leaf_256 *node, uint8 chunk, uint64 value)
static inline void
node_inner_256_delete(rt_node_inner_256 *node, uint8 chunk)
{
- Assert(!NODE_IS_LEAF(node));
- node->children[chunk] = NULL;
+ Assert(!RT_NODE_IS_LEAF(node));
+ node->children[chunk] = InvalidRTPointer;
}
static inline void
node_leaf_256_delete(rt_node_leaf_256 *node, uint8 chunk)
{
- Assert(NODE_IS_LEAF(node));
+ Assert(RT_NODE_IS_LEAF(node));
node->isset[RT_NODE_BITMAP_BYTE(chunk)] &= ~(RT_NODE_BITMAP_BIT(chunk));
}
@@ -877,29 +943,32 @@ rt_new_root(radix_tree *tree, uint64 key)
{
int shift = key_get_shift(key);
bool inner = shift > 0;
- rt_node *newnode;
+ rt_node_ptr newnode;
newnode = rt_alloc_node(tree, RT_CLASS_4_FULL, inner);
rt_init_node(newnode, RT_NODE_KIND_4, RT_CLASS_4_FULL, inner);
- newnode->shift = shift;
+ NODE_SHIFT(newnode) = shift;
+
tree->max_val = shift_get_max_val(shift);
- tree->root = newnode;
+ tree->root = newnode.encoded;
}
/*
* Allocate a new node with the given node kind.
*/
-static rt_node *
+static rt_node_ptr
rt_alloc_node(radix_tree *tree, rt_size_class size_class, bool inner)
{
- rt_node *newnode;
+ rt_node_ptr newnode;
if (inner)
- newnode = (rt_node *) MemoryContextAlloc(tree->inner_slabs[size_class],
- rt_size_class_info[size_class].inner_size);
+ newnode.decoded = (rt_node *) MemoryContextAlloc(tree->inner_slabs[size_class],
+ rt_size_class_info[size_class].inner_size);
else
- newnode = (rt_node *) MemoryContextAlloc(tree->leaf_slabs[size_class],
- rt_size_class_info[size_class].leaf_size);
+ newnode.decoded = (rt_node *) MemoryContextAlloc(tree->leaf_slabs[size_class],
+ rt_size_class_info[size_class].leaf_size);
+
+ newnode.encoded = rt_pointer_encode(newnode.decoded);
#ifdef RT_DEBUG
/* update the statistics */
@@ -911,20 +980,20 @@ rt_alloc_node(radix_tree *tree, rt_size_class size_class, bool inner)
/* Initialize the node contents */
static inline void
-rt_init_node(rt_node *node, uint8 kind, rt_size_class size_class, bool inner)
+rt_init_node(rt_node_ptr node, uint8 kind, rt_size_class size_class, bool inner)
{
if (inner)
- MemSet(node, 0, rt_size_class_info[size_class].inner_size);
+ MemSet(node.decoded, 0, rt_size_class_info[size_class].inner_size);
else
- MemSet(node, 0, rt_size_class_info[size_class].leaf_size);
+ MemSet(node.decoded, 0, rt_size_class_info[size_class].leaf_size);
- node->kind = kind;
- node->fanout = rt_size_class_info[size_class].fanout;
+ NODE_KIND(node) = kind;
+ NODE_FANOUT(node) = rt_size_class_info[size_class].fanout;
/* Initialize slot_idxs to invalid values */
if (kind == RT_NODE_KIND_125)
{
- rt_node_base_125 *n125 = (rt_node_base_125 *) node;
+ rt_node_base_125 *n125 = (rt_node_base_125 *) node.decoded;
memset(n125->slot_idxs, RT_NODE_125_INVALID_IDX, sizeof(n125->slot_idxs));
}
@@ -934,25 +1003,25 @@ rt_init_node(rt_node *node, uint8 kind, rt_size_class size_class, bool inner)
* and this is the max size class to it will never grow.
*/
if (kind == RT_NODE_KIND_256)
- node->fanout = 0;
+ NODE_FANOUT(node) = 0;
}
static inline void
-rt_copy_node(rt_node *newnode, rt_node *oldnode)
+rt_copy_node(rt_node_ptr newnode, rt_node_ptr oldnode)
{
- newnode->shift = oldnode->shift;
- newnode->chunk = oldnode->chunk;
- newnode->count = oldnode->count;
+ NODE_SHIFT(newnode) = NODE_SHIFT(oldnode);
+ NODE_CHUNK(newnode) = NODE_CHUNK(oldnode);
+ NODE_COUNT(newnode) = NODE_COUNT(oldnode);
}
/*
* Create a new node with 'new_kind' and the same shift, chunk, and
* count of 'node'.
*/
-static rt_node*
-rt_grow_node_kind(radix_tree *tree, rt_node *node, uint8 new_kind)
+static rt_node_ptr
+rt_grow_node_kind(radix_tree *tree, rt_node_ptr node, uint8 new_kind)
{
- rt_node *newnode;
+ rt_node_ptr newnode;
bool inner = !NODE_IS_LEAF(node);
newnode = rt_alloc_node(tree, kind_min_size_class[new_kind], inner);
@@ -964,12 +1033,12 @@ rt_grow_node_kind(radix_tree *tree, rt_node *node, uint8 new_kind)
/* Free the given node */
static void
-rt_free_node(radix_tree *tree, rt_node *node)
+rt_free_node(radix_tree *tree, rt_node_ptr node)
{
/* If we're deleting the root node, make the tree empty */
- if (tree->root == node)
+ if (tree->root == node.encoded)
{
- tree->root = NULL;
+ tree->root = InvalidRTPointer;
tree->max_val = 0;
}
@@ -980,7 +1049,7 @@ rt_free_node(radix_tree *tree, rt_node *node)
/* update the statistics */
for (i = 0; i < RT_SIZE_CLASS_COUNT; i++)
{
- if (node->fanout == rt_size_class_info[i].fanout)
+ if (NODE_FANOUT(node) == rt_size_class_info[i].fanout)
break;
}
@@ -993,29 +1062,30 @@ rt_free_node(radix_tree *tree, rt_node *node)
}
#endif
- pfree(node);
+ pfree(node.decoded);
}
/*
* Replace old_child with new_child, and free the old one.
*/
static void
-rt_replace_node(radix_tree *tree, rt_node *parent, rt_node *old_child,
- rt_node *new_child, uint64 key)
+rt_replace_node(radix_tree *tree, rt_node_ptr parent, rt_node_ptr old_child,
+ rt_node_ptr new_child, uint64 key)
{
- Assert(old_child->chunk == new_child->chunk);
- Assert(old_child->shift == new_child->shift);
+ Assert(NODE_CHUNK(old_child) == NODE_CHUNK(new_child));
+ Assert(NODE_SHIFT(old_child) == NODE_SHIFT(new_child));
- if (parent == old_child)
+ if (rt_node_ptr_eq(&parent, &old_child))
{
/* Replace the root node with the new large node */
- tree->root = new_child;
+ tree->root = new_child.encoded;
}
else
{
bool replaced PG_USED_FOR_ASSERTS_ONLY;
- replaced = rt_node_insert_inner(tree, NULL, parent, key, new_child);
+ replaced = rt_node_insert_inner(tree, InvalidRTNodePtr, parent, key,
+ new_child);
Assert(replaced);
}
@@ -1030,24 +1100,28 @@ static void
rt_extend(radix_tree *tree, uint64 key)
{
int target_shift;
- int shift = tree->root->shift + RT_NODE_SPAN;
+ rt_node *root = rt_pointer_decode(tree->root);
+ int shift = root->shift + RT_NODE_SPAN;
target_shift = key_get_shift(key);
/* Grow tree from 'shift' to 'target_shift' */
while (shift <= target_shift)
{
- rt_node_inner_4 *node;
+ rt_node_ptr node;
+ rt_node_inner_4 *n4;
+
+ node = rt_alloc_node(tree, RT_CLASS_4_FULL, true);
+ rt_init_node(node, RT_NODE_KIND_4, RT_CLASS_4_FULL, true);
- node = (rt_node_inner_4 *) rt_alloc_node(tree, RT_CLASS_4_FULL, true);
- rt_init_node((rt_node *) node, RT_NODE_KIND_4, RT_CLASS_4_FULL, true);
- node->base.n.shift = shift;
- node->base.n.count = 1;
- node->base.chunks[0] = 0;
- node->children[0] = tree->root;
+ n4 = (rt_node_inner_4 *) node.decoded;
+ n4->base.n.shift = shift;
+ n4->base.n.count = 1;
+ n4->base.chunks[0] = 0;
+ n4->children[0] = tree->root;
- tree->root->chunk = 0;
- tree->root = (rt_node *) node;
+ root->chunk = 0;
+ tree->root = node.encoded;
shift += RT_NODE_SPAN;
}
@@ -1060,21 +1134,22 @@ rt_extend(radix_tree *tree, uint64 key)
* Insert inner and leaf nodes from 'node' to bottom.
*/
static inline void
-rt_set_extend(radix_tree *tree, uint64 key, uint64 value, rt_node *parent,
- rt_node *node)
+rt_set_extend(radix_tree *tree, uint64 key, uint64 value, rt_node_ptr parent,
+ rt_node_ptr node)
{
- int shift = node->shift;
+ int shift = NODE_SHIFT(node);
while (shift >= RT_NODE_SPAN)
{
- rt_node *newchild;
+ rt_node_ptr newchild;
int newshift = shift - RT_NODE_SPAN;
bool inner = newshift > 0;
newchild = rt_alloc_node(tree, RT_CLASS_4_FULL, inner);
rt_init_node(newchild, RT_NODE_KIND_4, RT_CLASS_4_FULL, inner);
- newchild->shift = newshift;
- newchild->chunk = RT_GET_KEY_CHUNK(key, node->shift);
+ NODE_SHIFT(newchild) = newshift;
+ NODE_CHUNK(newchild) = RT_GET_KEY_CHUNK(key, NODE_SHIFT(node));
+
rt_node_insert_inner(tree, parent, node, key, newchild);
parent = node;
@@ -1094,17 +1169,18 @@ rt_set_extend(radix_tree *tree, uint64 key, uint64 value, rt_node *parent,
* pointer is set to child_p.
*/
static inline bool
-rt_node_search_inner(rt_node *node, uint64 key, rt_action action, rt_node **child_p)
+rt_node_search_inner(rt_node_ptr node, uint64 key, rt_action action,
+ rt_pointer *child_p)
{
- uint8 chunk = RT_GET_KEY_CHUNK(key, node->shift);
+ uint8 chunk = RT_GET_KEY_CHUNK(key, NODE_SHIFT(node));
bool found = false;
- rt_node *child = NULL;
+ rt_pointer child;
- switch (node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- rt_node_inner_4 *n4 = (rt_node_inner_4 *) node;
+ rt_node_inner_4 *n4 = (rt_node_inner_4 *) node.decoded;
int idx = node_4_search_eq((rt_node_base_4 *) n4, chunk);
if (idx < 0)
@@ -1122,7 +1198,7 @@ rt_node_search_inner(rt_node *node, uint64 key, rt_action action, rt_node **chil
}
case RT_NODE_KIND_32:
{
- rt_node_inner_32 *n32 = (rt_node_inner_32 *) node;
+ rt_node_inner_32 *n32 = (rt_node_inner_32 *) node.decoded;
int idx = node_32_search_eq((rt_node_base_32 *) n32, chunk);
if (idx < 0)
@@ -1138,7 +1214,7 @@ rt_node_search_inner(rt_node *node, uint64 key, rt_action action, rt_node **chil
}
case RT_NODE_KIND_125:
{
- rt_node_inner_125 *n125 = (rt_node_inner_125 *) node;
+ rt_node_inner_125 *n125 = (rt_node_inner_125 *) node.decoded;
if (!node_125_is_chunk_used((rt_node_base_125 *) n125, chunk))
break;
@@ -1154,7 +1230,7 @@ rt_node_search_inner(rt_node *node, uint64 key, rt_action action, rt_node **chil
}
case RT_NODE_KIND_256:
{
- rt_node_inner_256 *n256 = (rt_node_inner_256 *) node;
+ rt_node_inner_256 *n256 = (rt_node_inner_256 *) node.decoded;
if (!node_inner_256_is_chunk_used(n256, chunk))
break;
@@ -1171,7 +1247,7 @@ rt_node_search_inner(rt_node *node, uint64 key, rt_action action, rt_node **chil
/* update statistics */
if (action == RT_ACTION_DELETE && found)
- node->count--;
+ NODE_COUNT(node)--;
if (found && child_p)
*child_p = child;
@@ -1187,17 +1263,17 @@ rt_node_search_inner(rt_node *node, uint64 key, rt_action action, rt_node **chil
* to the value is set to value_p.
*/
static inline bool
-rt_node_search_leaf(rt_node *node, uint64 key, rt_action action, uint64 *value_p)
+rt_node_search_leaf(rt_node_ptr node, uint64 key, rt_action action, uint64 *value_p)
{
- uint8 chunk = RT_GET_KEY_CHUNK(key, node->shift);
+ uint8 chunk = RT_GET_KEY_CHUNK(key, NODE_SHIFT(node));
bool found = false;
uint64 value = 0;
- switch (node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node;
+ rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node.decoded;
int idx = node_4_search_eq((rt_node_base_4 *) n4, chunk);
if (idx < 0)
@@ -1215,7 +1291,7 @@ rt_node_search_leaf(rt_node *node, uint64 key, rt_action action, uint64 *value_p
}
case RT_NODE_KIND_32:
{
- rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node;
+ rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node.decoded;
int idx = node_32_search_eq((rt_node_base_32 *) n32, chunk);
if (idx < 0)
@@ -1231,7 +1307,7 @@ rt_node_search_leaf(rt_node *node, uint64 key, rt_action action, uint64 *value_p
}
case RT_NODE_KIND_125:
{
- rt_node_leaf_125 *n125 = (rt_node_leaf_125 *) node;
+ rt_node_leaf_125 *n125 = (rt_node_leaf_125 *) node.decoded;
if (!node_125_is_chunk_used((rt_node_base_125 *) n125, chunk))
break;
@@ -1247,7 +1323,7 @@ rt_node_search_leaf(rt_node *node, uint64 key, rt_action action, uint64 *value_p
}
case RT_NODE_KIND_256:
{
- rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node;
+ rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node.decoded;
if (!node_leaf_256_is_chunk_used(n256, chunk))
break;
@@ -1264,7 +1340,7 @@ rt_node_search_leaf(rt_node *node, uint64 key, rt_action action, uint64 *value_p
/* update statistics */
if (action == RT_ACTION_DELETE && found)
- node->count--;
+ NODE_COUNT(node)--;
if (found && value_p)
*value_p = value;
@@ -1274,19 +1350,19 @@ rt_node_search_leaf(rt_node *node, uint64 key, rt_action action, uint64 *value_p
/* Insert the child to the inner node */
static bool
-rt_node_insert_inner(radix_tree *tree, rt_node *parent, rt_node *node, uint64 key,
- rt_node *child)
+rt_node_insert_inner(radix_tree *tree, rt_node_ptr parent, rt_node_ptr node,
+ uint64 key, rt_node_ptr child)
{
- uint8 chunk = RT_GET_KEY_CHUNK(key, node->shift);
+ uint8 chunk = RT_GET_KEY_CHUNK(key, NODE_SHIFT(node));
bool chunk_exists = false;
Assert(!NODE_IS_LEAF(node));
- switch (node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- rt_node_inner_4 *n4 = (rt_node_inner_4 *) node;
+ rt_node_inner_4 *n4 = (rt_node_inner_4 *) node.decoded;
int idx;
idx = node_4_search_eq((rt_node_base_4 *) n4, chunk);
@@ -1294,25 +1370,27 @@ rt_node_insert_inner(radix_tree *tree, rt_node *parent, rt_node *node, uint64 ke
{
/* found the existing chunk */
chunk_exists = true;
- n4->children[idx] = child;
+ n4->children[idx] = child.encoded;
break;
}
if (unlikely(!VAR_NODE_HAS_FREE_SLOT(n4)))
{
+ rt_node_ptr new;
rt_node_inner_32 *new32;
- Assert(parent != NULL);
+
+ Assert(RTNodePtrIsValid(parent));
/* grow node from 4 to 32 */
- new32 = (rt_node_inner_32 *) rt_grow_node_kind(tree, (rt_node *) n4,
- RT_NODE_KIND_32);
+ new = rt_grow_node_kind(tree, node, RT_NODE_KIND_32);
+ new32 = (rt_node_inner_32 *) new.decoded;
+
chunk_children_array_copy(n4->base.chunks, n4->children,
new32->base.chunks, new32->children);
- Assert(parent != NULL);
- rt_replace_node(tree, parent, (rt_node *) n4, (rt_node *) new32,
- key);
- node = (rt_node *) new32;
+ Assert(RTNodePtrIsValid(parent));
+ rt_replace_node(tree, parent, node, new, key);
+ node = new;
}
else
{
@@ -1325,14 +1403,14 @@ rt_node_insert_inner(radix_tree *tree, rt_node *parent, rt_node *node, uint64 ke
count, insertpos);
n4->base.chunks[insertpos] = chunk;
- n4->children[insertpos] = child;
+ n4->children[insertpos] = child.encoded;
break;
}
}
/* FALLTHROUGH */
case RT_NODE_KIND_32:
{
- rt_node_inner_32 *n32 = (rt_node_inner_32 *) node;
+ rt_node_inner_32 *n32 = (rt_node_inner_32 *) node.decoded;
int idx;
idx = node_32_search_eq((rt_node_base_32 *) n32, chunk);
@@ -1340,45 +1418,52 @@ rt_node_insert_inner(radix_tree *tree, rt_node *parent, rt_node *node, uint64 ke
{
/* found the existing chunk */
chunk_exists = true;
- n32->children[idx] = child;
+ n32->children[idx] = child.encoded;
break;
}
if (unlikely(!VAR_NODE_HAS_FREE_SLOT(n32)))
{
- Assert(parent != NULL);
+ Assert(RTNodePtrIsValid(parent));
if (n32->base.n.count == rt_size_class_info[RT_CLASS_32_PARTIAL].fanout)
{
/* use the same node kind, but expand to the next size class */
const Size size = rt_size_class_info[RT_CLASS_32_PARTIAL].inner_size;
const int fanout = rt_size_class_info[RT_CLASS_32_FULL].fanout;
+ rt_node_ptr new;
rt_node_inner_32 *new32;
- new32 = (rt_node_inner_32 *) rt_alloc_node(tree, RT_CLASS_32_FULL, true);
+ new = rt_alloc_node(tree, RT_CLASS_32_FULL, true);
+ new32 = (rt_node_inner_32 *) new.decoded;
memcpy(new32, n32, size);
new32->base.n.fanout = fanout;
- rt_replace_node(tree, parent, (rt_node *) n32, (rt_node *) new32, key);
+ rt_replace_node(tree, parent, node, new, key);
- /* must update both pointers here */
- node = (rt_node *) new32;
+ /*
+ * Must update both pointers here since we update n32 and
+ * verify node.
+ */
+ node = new;
n32 = new32;
goto retry_insert_inner_32;
}
else
{
+ rt_node_ptr new;
rt_node_inner_125 *new125;
/* grow node from 32 to 125 */
- new125 = (rt_node_inner_125 *) rt_grow_node_kind(tree, (rt_node *) n32,
- RT_NODE_KIND_125);
+ new = rt_grow_node_kind(tree, node, RT_NODE_KIND_125);
+ new125 = (rt_node_inner_125 *) new.decoded;
+
for (int i = 0; i < n32->base.n.count; i++)
node_inner_125_insert(new125, n32->base.chunks[i], n32->children[i]);
- rt_replace_node(tree, parent, (rt_node *) n32, (rt_node *) new125, key);
- node = (rt_node *) new125;
+ rt_replace_node(tree, parent, node, new, key);
+ node = new;
}
}
else
@@ -1393,7 +1478,7 @@ retry_insert_inner_32:
count, insertpos);
n32->base.chunks[insertpos] = chunk;
- n32->children[insertpos] = child;
+ n32->children[insertpos] = child.encoded;
break;
}
}
@@ -1401,25 +1486,28 @@ retry_insert_inner_32:
/* FALLTHROUGH */
case RT_NODE_KIND_125:
{
- rt_node_inner_125 *n125 = (rt_node_inner_125 *) node;
+ rt_node_inner_125 *n125 = (rt_node_inner_125 *) node.decoded;
int cnt = 0;
if (node_125_is_chunk_used((rt_node_base_125 *) n125, chunk))
{
/* found the existing chunk */
chunk_exists = true;
- node_inner_125_update(n125, chunk, child);
+ node_inner_125_update(n125, chunk, child.encoded);
break;
}
if (unlikely(!VAR_NODE_HAS_FREE_SLOT(n125)))
{
+ rt_node_ptr new;
rt_node_inner_256 *new256;
- Assert(parent != NULL);
+
+ Assert(RTNodePtrIsValid(parent));
/* grow node from 125 to 256 */
- new256 = (rt_node_inner_256 *) rt_grow_node_kind(tree, (rt_node *) n125,
- RT_NODE_KIND_256);
+ new = rt_grow_node_kind(tree, node, RT_NODE_KIND_256);
+ new256 = (rt_node_inner_256 *) new.decoded;
+
for (int i = 0; i < RT_NODE_MAX_SLOTS && cnt < n125->base.n.count; i++)
{
if (!node_125_is_chunk_used((rt_node_base_125 *) n125, i))
@@ -1429,32 +1517,31 @@ retry_insert_inner_32:
cnt++;
}
- rt_replace_node(tree, parent, (rt_node *) n125, (rt_node *) new256,
- key);
- node = (rt_node *) new256;
+ rt_replace_node(tree, parent, node, new, key);
+ node = new;
}
else
{
- node_inner_125_insert(n125, chunk, child);
+ node_inner_125_insert(n125, chunk, child.encoded);
break;
}
}
/* FALLTHROUGH */
case RT_NODE_KIND_256:
{
- rt_node_inner_256 *n256 = (rt_node_inner_256 *) node;
+ rt_node_inner_256 *n256 = (rt_node_inner_256 *) node.decoded;
chunk_exists = node_inner_256_is_chunk_used(n256, chunk);
Assert(chunk_exists || FIXED_NODE_HAS_FREE_SLOT(n256, RT_CLASS_256));
- node_inner_256_set(n256, chunk, child);
+ node_inner_256_set(n256, chunk, child.encoded);
break;
}
}
/* Update statistics */
if (!chunk_exists)
- node->count++;
+ NODE_COUNT(node)++;
/*
* Done. Finally, verify the chunk and value is inserted or replaced
@@ -1467,19 +1554,19 @@ retry_insert_inner_32:
/* Insert the value to the leaf node */
static bool
-rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
+rt_node_insert_leaf(radix_tree *tree, rt_node_ptr parent, rt_node_ptr node,
uint64 key, uint64 value)
{
- uint8 chunk = RT_GET_KEY_CHUNK(key, node->shift);
+ uint8 chunk = RT_GET_KEY_CHUNK(key, NODE_SHIFT(node));
bool chunk_exists = false;
Assert(NODE_IS_LEAF(node));
- switch (node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node;
+ rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node.decoded;
int idx;
idx = node_4_search_eq((rt_node_base_4 *) n4, chunk);
@@ -1493,16 +1580,18 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
if (unlikely(!VAR_NODE_HAS_FREE_SLOT(n4)))
{
+ rt_node_ptr new;
rt_node_leaf_32 *new32;
- Assert(parent != NULL);
+
+ Assert(RTNodePtrIsValid(parent));
/* grow node from 4 to 32 */
- new32 = (rt_node_leaf_32 *) rt_grow_node_kind(tree, (rt_node *) n4,
- RT_NODE_KIND_32);
+ new = rt_grow_node_kind(tree, node, RT_NODE_KIND_32);
+ new32 = (rt_node_leaf_32 *) new.decoded;
chunk_values_array_copy(n4->base.chunks, n4->values,
new32->base.chunks, new32->values);
- rt_replace_node(tree, parent, (rt_node *) n4, (rt_node *) new32, key);
- node = (rt_node *) new32;
+ rt_replace_node(tree, parent, node, new, key);
+ node = new;
}
else
{
@@ -1522,7 +1611,7 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
/* FALLTHROUGH */
case RT_NODE_KIND_32:
{
- rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node;
+ rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node.decoded;
int idx;
idx = node_32_search_eq((rt_node_base_32 *) n32, chunk);
@@ -1536,45 +1625,51 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
if (unlikely(!VAR_NODE_HAS_FREE_SLOT(n32)))
{
- Assert(parent != NULL);
+ Assert(RTNodePtrIsValid(parent));
if (n32->base.n.count == rt_size_class_info[RT_CLASS_32_PARTIAL].fanout)
{
/* use the same node kind, but expand to the next size class */
const Size size = rt_size_class_info[RT_CLASS_32_PARTIAL].leaf_size;
const int fanout = rt_size_class_info[RT_CLASS_32_FULL].fanout;
+ rt_node_ptr new;
rt_node_leaf_32 *new32;
- new32 = (rt_node_leaf_32 *) rt_alloc_node(tree, RT_CLASS_32_FULL, false);
+ new = rt_alloc_node(tree, RT_CLASS_32_FULL, false);
+ new32 = (rt_node_leaf_32 *) new.decoded;
memcpy(new32, n32, size);
new32->base.n.fanout = fanout;
- rt_replace_node(tree, parent, (rt_node *) n32, (rt_node *) new32, key);
+ rt_replace_node(tree, parent, node, new, key);
- /* must update both pointers here */
- node = (rt_node *) new32;
+ /*
+ * Must update both pointers here since we update n32 and
+ * verify node.
+ */
+ node = new;
n32 = new32;
goto retry_insert_leaf_32;
}
else
{
+ rt_node_ptr new;
rt_node_leaf_125 *new125;
/* grow node from 32 to 125 */
- new125 = (rt_node_leaf_125 *) rt_grow_node_kind(tree, (rt_node *) n32,
- RT_NODE_KIND_125);
+ new = rt_grow_node_kind(tree, node, RT_NODE_KIND_125);
+ new125 = (rt_node_leaf_125 *) new.decoded;
+
for (int i = 0; i < n32->base.n.count; i++)
node_leaf_125_insert(new125, n32->base.chunks[i], n32->values[i]);
- rt_replace_node(tree, parent, (rt_node *) n32, (rt_node *) new125,
- key);
- node = (rt_node *) new125;
+ rt_replace_node(tree, parent, node, new, key);
+ node = new;
}
}
else
{
- retry_insert_leaf_32:
+retry_insert_leaf_32:
{
int insertpos = node_32_get_insertpos((rt_node_base_32 *) n32, chunk);
int count = n32->base.n.count;
@@ -1592,7 +1687,7 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
/* FALLTHROUGH */
case RT_NODE_KIND_125:
{
- rt_node_leaf_125 *n125 = (rt_node_leaf_125 *) node;
+ rt_node_leaf_125 *n125 = (rt_node_leaf_125 *) node.decoded;
int cnt = 0;
if (node_125_is_chunk_used((rt_node_base_125 *) n125, chunk))
@@ -1605,12 +1700,14 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
if (unlikely(!VAR_NODE_HAS_FREE_SLOT(n125)))
{
+ rt_node_ptr new;
rt_node_leaf_256 *new256;
- Assert(parent != NULL);
+
+ Assert(RTNodePtrIsValid(parent));
/* grow node from 125 to 256 */
- new256 = (rt_node_leaf_256 *) rt_grow_node_kind(tree, (rt_node *) n125,
- RT_NODE_KIND_256);
+ new = rt_grow_node_kind(tree, node, RT_NODE_KIND_256);
+ new256 = (rt_node_leaf_256 *) new.decoded;
for (int i = 0; i < RT_NODE_MAX_SLOTS && cnt < n125->base.n.count; i++)
{
if (!node_125_is_chunk_used((rt_node_base_125 *) n125, i))
@@ -1620,9 +1717,8 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
cnt++;
}
- rt_replace_node(tree, parent, (rt_node *) n125, (rt_node *) new256,
- key);
- node = (rt_node *) new256;
+ rt_replace_node(tree, parent, node, new, key);
+ node = new;
}
else
{
@@ -1633,7 +1729,7 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
/* FALLTHROUGH */
case RT_NODE_KIND_256:
{
- rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node;
+ rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node.decoded;
chunk_exists = node_leaf_256_is_chunk_used(n256, chunk);
Assert(chunk_exists || FIXED_NODE_HAS_FREE_SLOT(n256, RT_CLASS_256));
@@ -1645,7 +1741,7 @@ rt_node_insert_leaf(radix_tree *tree, rt_node *parent, rt_node *node,
/* Update statistics */
if (!chunk_exists)
- node->count++;
+ NODE_COUNT(node)++;
/*
* Done. Finally, verify the chunk and value is inserted or replaced
@@ -1669,7 +1765,7 @@ rt_create(MemoryContext ctx)
tree = palloc(sizeof(radix_tree));
tree->context = ctx;
- tree->root = NULL;
+ tree->root = InvalidRTPointer;
tree->max_val = 0;
tree->num_keys = 0;
@@ -1718,26 +1814,23 @@ rt_set(radix_tree *tree, uint64 key, uint64 value)
{
int shift;
bool updated;
- rt_node *node;
- rt_node *parent;
+ rt_node_ptr node;
+ rt_node_ptr parent;
/* Empty tree, create the root */
- if (!tree->root)
+ if (!RTPointerIsValid(tree->root))
rt_new_root(tree, key);
/* Extend the tree if necessary */
if (key > tree->max_val)
rt_extend(tree, key);
- Assert(tree->root);
-
- shift = tree->root->shift;
- node = parent = tree->root;
-
/* Descend the tree until a leaf node */
+ node = parent = rt_node_ptr_encoded(tree->root);
+ shift = NODE_SHIFT(node);
while (shift >= 0)
{
- rt_node *child;
+ rt_pointer child;
if (NODE_IS_LEAF(node))
break;
@@ -1749,7 +1842,7 @@ rt_set(radix_tree *tree, uint64 key, uint64 value)
}
parent = node;
- node = child;
+ node = rt_node_ptr_encoded(child);
shift -= RT_NODE_SPAN;
}
@@ -1770,21 +1863,21 @@ rt_set(radix_tree *tree, uint64 key, uint64 value)
bool
rt_search(radix_tree *tree, uint64 key, uint64 *value_p)
{
- rt_node *node;
+ rt_node_ptr node;
int shift;
Assert(value_p != NULL);
- if (!tree->root || key > tree->max_val)
+ if (!RTPointerIsValid(tree->root) || key > tree->max_val)
return false;
- node = tree->root;
- shift = tree->root->shift;
+ node = rt_node_ptr_encoded(tree->root);
+ shift = NODE_SHIFT(node);
/* Descend the tree until a leaf node */
while (shift >= 0)
{
- rt_node *child;
+ rt_pointer child;
if (NODE_IS_LEAF(node))
break;
@@ -1792,7 +1885,7 @@ rt_search(radix_tree *tree, uint64 key, uint64 *value_p)
if (!rt_node_search_inner(node, key, RT_ACTION_FIND, &child))
return false;
- node = child;
+ node = rt_node_ptr_encoded(child);
shift -= RT_NODE_SPAN;
}
@@ -1806,8 +1899,8 @@ rt_search(radix_tree *tree, uint64 key, uint64 *value_p)
bool
rt_delete(radix_tree *tree, uint64 key)
{
- rt_node *node;
- rt_node *stack[RT_MAX_LEVEL] = {0};
+ rt_node_ptr node;
+ rt_node_ptr stack[RT_MAX_LEVEL] = {0};
int shift;
int level;
bool deleted;
@@ -1819,12 +1912,12 @@ rt_delete(radix_tree *tree, uint64 key)
* Descend the tree to search the key while building a stack of nodes we
* visited.
*/
- node = tree->root;
- shift = tree->root->shift;
+ node = rt_node_ptr_encoded(tree->root);
+ shift = NODE_SHIFT(node);
level = -1;
while (shift > 0)
{
- rt_node *child;
+ rt_pointer child;
/* Push the current node to the stack */
stack[++level] = node;
@@ -1832,7 +1925,7 @@ rt_delete(radix_tree *tree, uint64 key)
if (!rt_node_search_inner(node, key, RT_ACTION_FIND, &child))
return false;
- node = child;
+ node = rt_node_ptr_encoded(child);
shift -= RT_NODE_SPAN;
}
@@ -1883,6 +1976,7 @@ rt_iter *
rt_begin_iterate(radix_tree *tree)
{
MemoryContext old_ctx;
+ rt_node_ptr root;
rt_iter *iter;
int top_level;
@@ -1892,17 +1986,18 @@ rt_begin_iterate(radix_tree *tree)
iter->tree = tree;
/* empty tree */
- if (!iter->tree->root)
+ if (!RTPointerIsValid(iter->tree) || !RTPointerIsValid(iter->tree->root))
return iter;
- top_level = iter->tree->root->shift / RT_NODE_SPAN;
+ root = rt_node_ptr_encoded(iter->tree->root);
+ top_level = NODE_SHIFT(root) / RT_NODE_SPAN;
iter->stack_len = top_level;
/*
* Descend to the left most leaf node from the root. The key is being
* constructed while descending to the leaf.
*/
- rt_update_iter_stack(iter, iter->tree->root, top_level);
+ rt_update_iter_stack(iter, root, top_level);
MemoryContextSwitchTo(old_ctx);
@@ -1913,14 +2008,15 @@ rt_begin_iterate(radix_tree *tree)
* Update each node_iter for inner nodes in the iterator node stack.
*/
static void
-rt_update_iter_stack(rt_iter *iter, rt_node *from_node, int from)
+rt_update_iter_stack(rt_iter *iter, rt_node_ptr from_node, int from)
{
int level = from;
- rt_node *node = from_node;
+ rt_node_ptr node = from_node;
for (;;)
{
rt_node_iter *node_iter = &(iter->stack[level--]);
+ bool found PG_USED_FOR_ASSERTS_ONLY;
node_iter->node = node;
node_iter->current_idx = -1;
@@ -1930,10 +2026,10 @@ rt_update_iter_stack(rt_iter *iter, rt_node *from_node, int from)
return;
/* Advance to the next slot in the inner node */
- node = rt_node_inner_iterate_next(iter, node_iter);
+ found = rt_node_inner_iterate_next(iter, node_iter, &node);
/* We must find the first children in the node */
- Assert(node);
+ Assert(found);
}
}
@@ -1950,7 +2046,7 @@ rt_iterate_next(rt_iter *iter, uint64 *key_p, uint64 *value_p)
for (;;)
{
- rt_node *child = NULL;
+ rt_node_ptr child = InvalidRTNodePtr;
uint64 value;
int level;
bool found;
@@ -1971,14 +2067,12 @@ rt_iterate_next(rt_iter *iter, uint64 *key_p, uint64 *value_p)
*/
for (level = 1; level <= iter->stack_len; level++)
{
- child = rt_node_inner_iterate_next(iter, &(iter->stack[level]));
-
- if (child)
+ if (rt_node_inner_iterate_next(iter, &(iter->stack[level]), &child))
break;
}
/* the iteration finished */
- if (!child)
+ if (!RTNodePtrIsValid(child))
return false;
/*
@@ -2010,18 +2104,19 @@ rt_iter_update_key(rt_iter *iter, uint8 chunk, uint8 shift)
* Advance the slot in the inner node. Return the child if exists, otherwise
* null.
*/
-static inline rt_node *
-rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter)
+static inline bool
+rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter, rt_node_ptr *child_p)
{
- rt_node *child = NULL;
+ rt_node_ptr node = node_iter->node;
+ rt_pointer child;
bool found = false;
uint8 key_chunk;
- switch (node_iter->node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- rt_node_inner_4 *n4 = (rt_node_inner_4 *) node_iter->node;
+ rt_node_inner_4 *n4 = (rt_node_inner_4 *) node.decoded;
node_iter->current_idx++;
if (node_iter->current_idx >= n4->base.n.count)
@@ -2034,7 +2129,7 @@ rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter)
}
case RT_NODE_KIND_32:
{
- rt_node_inner_32 *n32 = (rt_node_inner_32 *) node_iter->node;
+ rt_node_inner_32 *n32 = (rt_node_inner_32 *) node.decoded;
node_iter->current_idx++;
if (node_iter->current_idx >= n32->base.n.count)
@@ -2047,7 +2142,7 @@ rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter)
}
case RT_NODE_KIND_125:
{
- rt_node_inner_125 *n125 = (rt_node_inner_125 *) node_iter->node;
+ rt_node_inner_125 *n125 = (rt_node_inner_125 *) node.decoded;
int i;
for (i = node_iter->current_idx + 1; i < RT_NODE_MAX_SLOTS; i++)
@@ -2067,7 +2162,7 @@ rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter)
}
case RT_NODE_KIND_256:
{
- rt_node_inner_256 *n256 = (rt_node_inner_256 *) node_iter->node;
+ rt_node_inner_256 *n256 = (rt_node_inner_256 *) node.decoded;
int i;
for (i = node_iter->current_idx + 1; i < RT_NODE_MAX_SLOTS; i++)
@@ -2088,9 +2183,12 @@ rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter)
}
if (found)
- rt_iter_update_key(iter, key_chunk, node_iter->node->shift);
+ {
+ rt_iter_update_key(iter, key_chunk, NODE_SHIFT(node));
+ *child_p = rt_node_ptr_encoded(child);
+ }
- return child;
+ return found;
}
/*
@@ -2098,19 +2196,18 @@ rt_node_inner_iterate_next(rt_iter *iter, rt_node_iter *node_iter)
* is set to value_p, otherwise return false.
*/
static inline bool
-rt_node_leaf_iterate_next(rt_iter *iter, rt_node_iter *node_iter,
- uint64 *value_p)
+rt_node_leaf_iterate_next(rt_iter *iter, rt_node_iter *node_iter, uint64 *value_p)
{
- rt_node *node = node_iter->node;
+ rt_node_ptr node = node_iter->node;
bool found = false;
uint64 value;
uint8 key_chunk;
- switch (node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node_iter->node;
+ rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node.decoded;
node_iter->current_idx++;
if (node_iter->current_idx >= n4->base.n.count)
@@ -2123,7 +2220,7 @@ rt_node_leaf_iterate_next(rt_iter *iter, rt_node_iter *node_iter,
}
case RT_NODE_KIND_32:
{
- rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node_iter->node;
+ rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node.decoded;
node_iter->current_idx++;
if (node_iter->current_idx >= n32->base.n.count)
@@ -2136,7 +2233,7 @@ rt_node_leaf_iterate_next(rt_iter *iter, rt_node_iter *node_iter,
}
case RT_NODE_KIND_125:
{
- rt_node_leaf_125 *n125 = (rt_node_leaf_125 *) node_iter->node;
+ rt_node_leaf_125 *n125 = (rt_node_leaf_125 *) node.decoded;
int i;
for (i = node_iter->current_idx + 1; i < RT_NODE_MAX_SLOTS; i++)
@@ -2156,7 +2253,7 @@ rt_node_leaf_iterate_next(rt_iter *iter, rt_node_iter *node_iter,
}
case RT_NODE_KIND_256:
{
- rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node_iter->node;
+ rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node.decoded;
int i;
for (i = node_iter->current_idx + 1; i < RT_NODE_MAX_SLOTS; i++)
@@ -2178,7 +2275,7 @@ rt_node_leaf_iterate_next(rt_iter *iter, rt_node_iter *node_iter,
if (found)
{
- rt_iter_update_key(iter, key_chunk, node_iter->node->shift);
+ rt_iter_update_key(iter, key_chunk, NODE_SHIFT(node));
*value_p = value;
}
@@ -2215,16 +2312,16 @@ rt_memory_usage(radix_tree *tree)
* Verify the radix tree node.
*/
static void
-rt_verify_node(rt_node *node)
+rt_verify_node(rt_node_ptr node)
{
#ifdef USE_ASSERT_CHECKING
- Assert(node->count >= 0);
+ Assert(NODE_COUNT(node) >= 0);
- switch (node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- rt_node_base_4 *n4 = (rt_node_base_4 *) node;
+ rt_node_base_4 *n4 = (rt_node_base_4 *) node.decoded;
for (int i = 1; i < n4->n.count; i++)
Assert(n4->chunks[i - 1] < n4->chunks[i]);
@@ -2233,7 +2330,7 @@ rt_verify_node(rt_node *node)
}
case RT_NODE_KIND_32:
{
- rt_node_base_32 *n32 = (rt_node_base_32 *) node;
+ rt_node_base_32 *n32 = (rt_node_base_32 *) node.decoded;
for (int i = 1; i < n32->n.count; i++)
Assert(n32->chunks[i - 1] < n32->chunks[i]);
@@ -2242,7 +2339,7 @@ rt_verify_node(rt_node *node)
}
case RT_NODE_KIND_125:
{
- rt_node_base_125 *n125 = (rt_node_base_125 *) node;
+ rt_node_base_125 *n125 = (rt_node_base_125 *) node.decoded;
int cnt = 0;
for (int i = 0; i < RT_NODE_MAX_SLOTS; i++)
@@ -2252,10 +2349,10 @@ rt_verify_node(rt_node *node)
/* Check if the corresponding slot is used */
if (NODE_IS_LEAF(node))
- Assert(node_leaf_125_is_slot_used((rt_node_leaf_125 *) node,
+ Assert(node_leaf_125_is_slot_used((rt_node_leaf_125 *) n125,
n125->slot_idxs[i]));
else
- Assert(node_inner_125_is_slot_used((rt_node_inner_125 *) node,
+ Assert(node_inner_125_is_slot_used((rt_node_inner_125 *) n125,
n125->slot_idxs[i]));
cnt++;
@@ -2268,7 +2365,7 @@ rt_verify_node(rt_node *node)
{
if (NODE_IS_LEAF(node))
{
- rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node;
+ rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node.decoded;
int cnt = 0;
for (int i = 0; i < RT_NODE_NSLOTS_BITS(RT_NODE_MAX_SLOTS); i++)
@@ -2289,54 +2386,62 @@ rt_verify_node(rt_node *node)
void
rt_stats(radix_tree *tree)
{
+ rt_node *root = rt_pointer_decode(tree->root);
+
+ if (root == NULL)
+ return;
+
ereport(NOTICE, (errmsg("num_keys = " UINT64_FORMAT ", height = %d, n4 = %u, n15 = %u, n32 = %u, n125 = %u, n256 = %u",
- tree->num_keys,
- tree->root->shift / RT_NODE_SPAN,
- tree->cnt[RT_CLASS_4_FULL],
- tree->cnt[RT_CLASS_32_PARTIAL],
- tree->cnt[RT_CLASS_32_FULL],
- tree->cnt[RT_CLASS_125_FULL],
- tree->cnt[RT_CLASS_256])));
+ tree->num_keys,
+ root->shift / RT_NODE_SPAN,
+ tree->cnt[RT_CLASS_4_FULL],
+ tree->cnt[RT_CLASS_32_PARTIAL],
+ tree->cnt[RT_CLASS_32_FULL],
+ tree->cnt[RT_CLASS_125_FULL],
+ tree->cnt[RT_CLASS_256])));
}
static void
-rt_dump_node(rt_node *node, int level, bool recurse)
+rt_dump_node(rt_node_ptr node, int level, bool recurse)
{
- char space[125] = {0};
+ rt_node *n = node.decoded;
+ char space[128] = {0};
fprintf(stderr, "[%s] kind %d, fanout %d, count %u, shift %u, chunk 0x%X:\n",
NODE_IS_LEAF(node) ? "LEAF" : "INNR",
- (node->kind == RT_NODE_KIND_4) ? 4 :
- (node->kind == RT_NODE_KIND_32) ? 32 :
- (node->kind == RT_NODE_KIND_125) ? 125 : 256,
- node->fanout == 0 ? 256 : node->fanout,
- node->count, node->shift, node->chunk);
+
+ (n->kind == RT_NODE_KIND_4) ? 4 :
+ (n->kind == RT_NODE_KIND_32) ? 32 :
+ (n->kind == RT_NODE_KIND_125) ? 125 : 256,
+ n->fanout == 0 ? 256 : n->fanout,
+ n->count, n->shift, n->chunk);
if (level > 0)
sprintf(space, "%*c", level * 4, ' ');
- switch (node->kind)
+ switch (NODE_KIND(node))
{
case RT_NODE_KIND_4:
{
- for (int i = 0; i < node->count; i++)
+ for (int i = 0; i < NODE_COUNT(node); i++)
{
if (NODE_IS_LEAF(node))
{
- rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node;
+ rt_node_leaf_4 *n4 = (rt_node_leaf_4 *) node.decoded;
fprintf(stderr, "%schunk 0x%X value 0x" UINT64_FORMAT_HEX "\n",
space, n4->base.chunks[i], n4->values[i]);
}
else
{
- rt_node_inner_4 *n4 = (rt_node_inner_4 *) node;
+ rt_node_inner_4 *n4 = (rt_node_inner_4 *) node.decoded;
fprintf(stderr, "%schunk 0x%X ->",
space, n4->base.chunks[i]);
if (recurse)
- rt_dump_node(n4->children[i], level + 1, recurse);
+ rt_dump_node(rt_node_ptr_encoded(n4->children[i]),
+ level + 1, recurse);
else
fprintf(stderr, "\n");
}
@@ -2345,25 +2450,26 @@ rt_dump_node(rt_node *node, int level, bool recurse)
}
case RT_NODE_KIND_32:
{
- for (int i = 0; i < node->count; i++)
+ for (int i = 0; i < NODE_KIND(node); i++)
{
if (NODE_IS_LEAF(node))
{
- rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node;
+ rt_node_leaf_32 *n32 = (rt_node_leaf_32 *) node.decoded;
fprintf(stderr, "%schunk 0x%X value 0x" UINT64_FORMAT_HEX "\n",
space, n32->base.chunks[i], n32->values[i]);
}
else
{
- rt_node_inner_32 *n32 = (rt_node_inner_32 *) node;
+ rt_node_inner_32 *n32 = (rt_node_inner_32 *) node.decoded;
fprintf(stderr, "%schunk 0x%X ->",
space, n32->base.chunks[i]);
if (recurse)
{
- rt_dump_node(n32->children[i], level + 1, recurse);
+ rt_dump_node(rt_node_ptr_encoded(n32->children[i]),
+ level + 1, recurse);
}
else
fprintf(stderr, "\n");
@@ -2373,7 +2479,7 @@ rt_dump_node(rt_node *node, int level, bool recurse)
}
case RT_NODE_KIND_125:
{
- rt_node_base_125 *b125 = (rt_node_base_125 *) node;
+ rt_node_base_125 *b125 = (rt_node_base_125 *) node.decoded;
fprintf(stderr, "slot_idxs ");
for (int i = 0; i < RT_NODE_MAX_SLOTS; i++)
@@ -2385,7 +2491,7 @@ rt_dump_node(rt_node *node, int level, bool recurse)
}
if (NODE_IS_LEAF(node))
{
- rt_node_leaf_125 *n = (rt_node_leaf_125 *) node;
+ rt_node_leaf_125 *n = (rt_node_leaf_125 *) node.decoded;
fprintf(stderr, ", isset-bitmap:");
for (int i = 0; i < WORDNUM(128); i++)
@@ -2415,7 +2521,7 @@ rt_dump_node(rt_node *node, int level, bool recurse)
space, i);
if (recurse)
- rt_dump_node(node_inner_125_get_child(n125, i),
+ rt_dump_node(rt_node_ptr_encoded(node_inner_125_get_child(n125, i)),
level + 1, recurse);
else
fprintf(stderr, "\n");
@@ -2429,7 +2535,7 @@ rt_dump_node(rt_node *node, int level, bool recurse)
{
if (NODE_IS_LEAF(node))
{
- rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node;
+ rt_node_leaf_256 *n256 = (rt_node_leaf_256 *) node.decoded;
if (!node_leaf_256_is_chunk_used(n256, i))
continue;
@@ -2439,7 +2545,7 @@ rt_dump_node(rt_node *node, int level, bool recurse)
}
else
{
- rt_node_inner_256 *n256 = (rt_node_inner_256 *) node;
+ rt_node_inner_256 *n256 = (rt_node_inner_256 *) node.decoded;
if (!node_inner_256_is_chunk_used(n256, i))
continue;
@@ -2448,8 +2554,8 @@ rt_dump_node(rt_node *node, int level, bool recurse)
space, i);
if (recurse)
- rt_dump_node(node_inner_256_get_child(n256, i), level + 1,
- recurse);
+ rt_dump_node(rt_node_ptr_encoded(node_inner_256_get_child(n256, i)),
+ level + 1, recurse);
else
fprintf(stderr, "\n");
}
@@ -2462,7 +2568,7 @@ rt_dump_node(rt_node *node, int level, bool recurse)
void
rt_dump_search(radix_tree *tree, uint64 key)
{
- rt_node *node;
+ rt_node_ptr node;
int shift;
int level = 0;
@@ -2470,7 +2576,7 @@ rt_dump_search(radix_tree *tree, uint64 key)
elog(NOTICE, "max_val = " UINT64_FORMAT "(0x" UINT64_FORMAT_HEX ")",
tree->max_val, tree->max_val);
- if (!tree->root)
+ if (!RTPointerIsValid(tree->root))
{
elog(NOTICE, "tree is empty");
return;
@@ -2483,11 +2589,11 @@ rt_dump_search(radix_tree *tree, uint64 key)
return;
}
- node = tree->root;
- shift = tree->root->shift;
+ node = rt_node_ptr_encoded(tree->root);
+ shift = NODE_SHIFT(node);
while (shift >= 0)
{
- rt_node *child;
+ rt_pointer child;
rt_dump_node(node, level, false);
@@ -2504,7 +2610,7 @@ rt_dump_search(radix_tree *tree, uint64 key)
if (!rt_node_search_inner(node, key, RT_ACTION_FIND, &child))
break;
- node = child;
+ node = rt_node_ptr_encoded(child);
shift -= RT_NODE_SPAN;
level++;
}
@@ -2513,6 +2619,7 @@ rt_dump_search(radix_tree *tree, uint64 key)
void
rt_dump(radix_tree *tree)
{
+ rt_node_ptr root;
for (int i = 0; i < RT_SIZE_CLASS_COUNT; i++)
fprintf(stderr, "%s\tinner_size %zu\tinner_blocksize %zu\tleaf_size %zu\tleaf_blocksize %zu\n",
@@ -2523,12 +2630,13 @@ rt_dump(radix_tree *tree)
rt_size_class_info[i].leaf_blocksize);
fprintf(stderr, "max_val = " UINT64_FORMAT "\n", tree->max_val);
- if (!tree->root)
+ if (!RTPointerIsValid(tree->root))
{
fprintf(stderr, "empty tree\n");
return;
}
- rt_dump_node(tree->root, 0, true);
+ root = rt_node_ptr_encoded(tree->root);
+ rt_dump_node(root, 0, true);
}
#endif
--
2.31.1