v22-0006-Free-all-radix-tree-nodes-recursively.patch

text/x-patch

Filename: v22-0006-Free-all-radix-tree-nodes-recursively.patch
Type: text/x-patch
Part: 6
Message: Re: [PoC] Improve dead tuple storage for lazy vacuum

Patch

Format: format-patch
Series: patch v22-0006
Subject: Free all radix tree nodes recursively
File+
src/include/lib/radixtree.h 78 0
From fe4ed7bf8033453b1ba38b6d298aa519fbe5b9f8 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Fri, 20 Jan 2023 12:38:54 +0700
Subject: [PATCH v22 06/22] Free all radix tree nodes recursively

TODO: Consider adding more general functionality to DSA
to free all segments.
---
 src/include/lib/radixtree.h | 78 +++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h
index c08016de3a..98e4597eac 100644
--- a/src/include/lib/radixtree.h
+++ b/src/include/lib/radixtree.h
@@ -127,6 +127,7 @@
 #define RT_ALLOC_NODE RT_MAKE_NAME(alloc_node)
 #define RT_INIT_NODE RT_MAKE_NAME(init_node)
 #define RT_FREE_NODE RT_MAKE_NAME(free_node)
+#define RT_FREE_RECURSE RT_MAKE_NAME(free_recurse)
 #define RT_EXTEND RT_MAKE_NAME(extend)
 #define RT_SET_EXTEND RT_MAKE_NAME(set_extend)
 #define RT_SWITCH_NODE_KIND RT_MAKE_NAME(grow_node_kind)
@@ -1410,6 +1411,78 @@ RT_GET_HANDLE(RT_RADIX_TREE *tree)
 	Assert(tree->ctl->magic == RT_RADIX_TREE_MAGIC);
 	return tree->ctl->handle;
 }
+
+/*
+ * Recursively free all nodes allocated to the DSA area.
+ */
+static inline void
+RT_FREE_RECURSE(RT_RADIX_TREE *tree, RT_PTR_ALLOC ptr)
+{
+	RT_PTR_LOCAL node = RT_PTR_GET_LOCAL(tree, ptr);
+
+	check_stack_depth();
+	CHECK_FOR_INTERRUPTS();
+
+	/* The leaf node doesn't have child pointers */
+	if (NODE_IS_LEAF(node))
+	{
+		dsa_free(tree->dsa, ptr);
+		return;
+	}
+
+	switch (node->kind)
+	{
+		case RT_NODE_KIND_4:
+			{
+				RT_NODE_INNER_4 *n4 = (RT_NODE_INNER_4 *) node;
+
+				for (int i = 0; i < n4->base.n.count; i++)
+					RT_FREE_RECURSE(tree, n4->children[i]);
+
+				break;
+			}
+		case RT_NODE_KIND_32:
+			{
+				RT_NODE_INNER_32 *n32 = (RT_NODE_INNER_32 *) node;
+
+				for (int i = 0; i < n32->base.n.count; i++)
+					RT_FREE_RECURSE(tree, n32->children[i]);
+
+				break;
+			}
+		case RT_NODE_KIND_125:
+			{
+				RT_NODE_INNER_125 *n125 = (RT_NODE_INNER_125 *) node;
+
+				for (int i = 0; i < RT_NODE_MAX_SLOTS; i++)
+				{
+					if (!RT_NODE_125_IS_CHUNK_USED(&n125->base, i))
+						continue;
+
+					RT_FREE_RECURSE(tree, RT_NODE_INNER_125_GET_CHILD(n125, i));
+				}
+
+				break;
+			}
+		case RT_NODE_KIND_256:
+			{
+				RT_NODE_INNER_256 *n256 = (RT_NODE_INNER_256 *) node;
+
+				for (int i = 0; i < RT_NODE_MAX_SLOTS; i++)
+				{
+					if (!RT_NODE_INNER_256_IS_CHUNK_USED(n256, i))
+						continue;
+
+					RT_FREE_RECURSE(tree, RT_NODE_INNER_256_GET_CHILD(n256, i));
+				}
+
+				break;
+			}
+	}
+
+	/* Free the inner node */
+	dsa_free(tree->dsa, ptr);
+}
 #endif
 
 /*
@@ -1421,6 +1494,10 @@ RT_FREE(RT_RADIX_TREE *tree)
 #ifdef RT_SHMEM
 	Assert(tree->ctl->magic == RT_RADIX_TREE_MAGIC);
 
+	/* Free all memory used for radix tree nodes */
+	if (RT_PTR_ALLOC_IS_VALID(tree->ctl->root))
+		RT_FREE_RECURSE(tree, tree->ctl->root);
+
 	/*
 	 * Vandalize the control block to help catch programming error where
 	 * other backends access the memory formerly occupied by this radix tree.
@@ -2199,6 +2276,7 @@ RT_DUMP(RT_RADIX_TREE *tree)
 #undef RT_ALLOC_NODE
 #undef RT_INIT_NODE
 #undef RT_FREE_NODE
+#undef RT_FREE_RECURSE
 #undef RT_EXTEND
 #undef RT_SET_EXTEND
 #undef RT_SWITCH_NODE_KIND
-- 
2.39.0