rt-find-callback-interface.patch.nocfbot
application/octet-stream
Filename: rt-find-callback-interface.patch.nocfbot
Type: application/octet-stream
Part: 0
diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h
index aca9984ecb..87131cc59b 100644
--- a/src/include/lib/radixtree.h
+++ b/src/include/lib/radixtree.h
@@ -216,6 +216,9 @@
#define RT_CLASS_16_HI RT_MAKE_NAME(class_32_max)
#define RT_CLASS_48 RT_MAKE_NAME(class_48)
#define RT_CLASS_256 RT_MAKE_NAME(class_256)
+#define RT_VALUE_CALLBACK RT_MAKE_NAME(value_callback)
+
+typedef void (*RT_VALUE_CALLBACK) (RT_VALUE_TYPE * value, void * caller_data);
/* generate forward declarations necessary to use the radix tree */
#ifdef RT_DECLARE
@@ -239,7 +242,7 @@ RT_SCOPE RT_RADIX_TREE *RT_CREATE(MemoryContext ctx, Size max_bytes);
#endif
RT_SCOPE void RT_FREE(RT_RADIX_TREE * tree);
-RT_SCOPE RT_VALUE_TYPE *RT_FIND(RT_RADIX_TREE * tree, uint64 key);
+RT_SCOPE bool RT_FIND(RT_RADIX_TREE * tree, uint64 key, RT_VALUE_CALLBACK val_callback, void * val_data);
#ifdef RT_VARLEN_VALUE
RT_SCOPE bool RT_SET(RT_RADIX_TREE * tree, uint64 key, RT_VALUE_TYPE * value_p,
@@ -264,7 +267,6 @@ RT_SCOPE void RT_STATS(RT_RADIX_TREE * tree);
#endif /* RT_DECLARE */
-
/* generate implementation of the radix tree */
#ifdef RT_DEFINE
@@ -1018,26 +1020,31 @@ RT_NODE_SEARCH(RT_NODE * node, uint8 chunk)
}
/*
- * Search the given key in the radix tree. Return the pointer to the value if found,
- * otherwise return NULL.
+ * Search the given key in the radix tree.
+ * If found, execute callback find_cb and return true,
+ * otherwise return false.
*
* Since the function returns the slot (to support variable-length values), the caller
* needs to maintain control until it's finished with the value.
*/
-RT_SCOPE RT_VALUE_TYPE *
-RT_FIND(RT_RADIX_TREE * tree, uint64 key)
+RT_SCOPE bool
+RT_FIND(RT_RADIX_TREE * tree, uint64 key, RT_VALUE_CALLBACK val_callback, void * val_data)
{
RT_NODE_PTR node;
RT_PTR_ALLOC *slot = NULL;
+ RT_VALUE_TYPE *value;
int shift;
#ifdef RT_SHMEM
Assert(tree->ctl->magic == RT_RADIX_TREE_MAGIC);
#endif
+ RT_LOCK_SHARED(tree);
+
if (!RT_PTR_ALLOC_IS_VALID(tree->ctl->root) || key > tree->ctl->max_val)
{
- return NULL;
+ RT_UNLOCK(tree);
+ return false;
}
node.alloc = tree->ctl->root;
@@ -1050,7 +1057,10 @@ RT_FIND(RT_RADIX_TREE * tree, uint64 key)
RT_PTR_SET_LOCAL(tree, &node);
slot = RT_NODE_SEARCH(node.local, RT_GET_KEY_CHUNK(key, shift));
if (slot == NULL)
- return NULL;
+ {
+ RT_UNLOCK(tree);
+ return false;
+ }
node.alloc = *slot;
shift -= RT_SPAN;
@@ -1058,13 +1068,19 @@ RT_FIND(RT_RADIX_TREE * tree, uint64 key)
if (RT_VALUE_IS_EMBEDDABLE)
{
- return (RT_VALUE_TYPE *) slot;
+ value = (RT_VALUE_TYPE *) slot;
}
else
{
RT_PTR_SET_LOCAL(tree, &node);
- return (RT_VALUE_TYPE *) node.local;
+ value = (RT_VALUE_TYPE *) node.local;
}
+
+ val_callback(value, val_data);
+
+ RT_UNLOCK(tree);
+
+ return true;
}
/***************** INSERTION *****************/
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index d5ca139b18..64a52276b6 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -116,10 +116,15 @@ static const test_spec test_specs[] = {
#define RT_DEFINE
#define RT_USE_DELETE
#define RT_VALUE_TYPE TestValueType
-/* #define RT_SHMEM */
+#define RT_SHMEM
#define RT_DEBUG
#include "lib/radixtree.h"
+static void
+rt_copy_value_callback(TestValueType *value, void * caller_data)
+{
+ memcpy((TestValueType*) caller_data, value, sizeof(TestValueType));
+}
/*
* Return the number of keys in the radix tree.
@@ -140,6 +145,7 @@ test_empty(void)
rt_radix_tree *radixtree;
rt_iter *iter;
uint64 key;
+ TestValueType v;
TestValueType *val;
#ifdef RT_SHMEM
@@ -154,13 +160,13 @@ test_empty(void)
radixtree = rt_create(CurrentMemoryContext, work_mem);
#endif
- if (rt_find(radixtree, 0) != NULL)
+ if (rt_find(radixtree, 0, rt_copy_value_callback, &v))
elog(ERROR, "rt_find on empty tree found a value");
- if (rt_find(radixtree, 1) != NULL)
+ if (rt_find(radixtree, 1, rt_copy_value_callback, &v))
elog(ERROR, "rt_find on empty tree found a value");
- if (rt_find(radixtree, PG_UINT64_MAX) != NULL)
+ if (rt_find(radixtree, PG_UINT64_MAX, rt_copy_value_callback, &v))
elog(ERROR, "rt_find on empty tree found a value");
if (rt_delete(radixtree, 0))
@@ -236,15 +242,16 @@ test_basic(int children, int height, bool reverse)
/* look up keys */
for (int i = 0; i < children; i++)
{
- TestValueType *value;
+ TestValueType value;
+ bool found;
- value = rt_find(radixtree, keys[i]);
+ found = rt_find(radixtree, keys[i], rt_copy_value_callback, (void *) &value);
- if (value == NULL)
+ if (!found)
elog(ERROR, "could not find key 0x" UINT64_HEX_FORMAT, keys[i]);
- if (*value != (TestValueType) keys[i])
+ if (value != (TestValueType) keys[i])
elog(ERROR, "rt_find returned 0x" UINT64_HEX_FORMAT ", expected " UINT64_HEX_FORMAT,
- *value, (TestValueType) keys[i]);
+ value, (TestValueType) keys[i]);
}
/* update keys */
@@ -267,14 +274,16 @@ test_basic(int children, int height, bool reverse)
/* look up keys after deleting and re-inserting */
for (int i = 0; i < children; i++)
{
- TestValueType *value;
+ TestValueType value;
+ bool found;
+
+ found = rt_find(radixtree, keys[i], rt_copy_value_callback, (void *) &value);
- value = rt_find(radixtree, keys[i]);
- if (value == NULL)
+ if (!found)
elog(ERROR, "could not find key 0x" UINT64_HEX_FORMAT, keys[i]);
- if (*value != (TestValueType) keys[i])
+ if (value != (TestValueType) keys[i])
elog(ERROR, "rt_find returned 0x" UINT64_HEX_FORMAT ", expected " UINT64_HEX_FORMAT,
- *value, (TestValueType) keys[i]);
+ value, (TestValueType) keys[i]);
}
/* iterate over the tree */
@@ -311,10 +320,11 @@ test_basic(int children, int height, bool reverse)
}
for (int i = 0; i < children; i++)
{
- TestValueType *value;
+ TestValueType value;
+ bool found;
- value = rt_find(radixtree, keys[i]);
- if (value != NULL)
+ found = rt_find(radixtree, keys[i], rt_copy_value_callback, (void *) &value);
+ if (found)
elog(ERROR, "found deleted key 0x" UINT64_HEX_FORMAT, keys[i]);
}
@@ -336,15 +346,17 @@ check_search_on_node(rt_radix_tree *radixtree, uint8 shift, int start, int end)
for (int i = start; i <= end; i++)
{
uint64 key = ((uint64) i << shift);
- TestValueType *val;
+ TestValueType val;
+ bool found;
+
+ found = rt_find(radixtree, key, rt_copy_value_callback, (void *) &val);
- val = rt_find(radixtree, key);
- if (val == NULL)
+ if (!found)
elog(ERROR, "key 0x" UINT64_HEX_FORMAT " is not found on node-%d",
key, end);
- if (*val != (TestValueType) key)
+ if (val != (TestValueType) key)
elog(ERROR, "rt_find with key 0x" UINT64_HEX_FORMAT " returns 0x" UINT64_HEX_FORMAT ", expected 0x" UINT64_HEX_FORMAT,
- key, *val, key);
+ key, val, key);
}
}
@@ -620,7 +632,7 @@ test_pattern(const test_spec * spec)
bool found;
bool expected;
uint64 x;
- TestValueType *v;
+ TestValueType v;
/*
* Pick next value to probe at random. We limit the probes to the
@@ -647,14 +659,13 @@ test_pattern(const test_spec * spec)
}
/* Is it present according to rt_search() ? */
- v = rt_find(radixtree, x);
- found = (v != NULL);
+ found = rt_find(radixtree, x, rt_copy_value_callback, (void*) &v);
if (found != expected)
elog(ERROR, "mismatch at 0x" UINT64_HEX_FORMAT ": %d vs %d", x, found, expected);
- if (found && (*v != (TestValueType) x))
+ if (found && (v != (TestValueType) x))
elog(ERROR, "found 0x" UINT64_HEX_FORMAT ", expected 0x" UINT64_HEX_FORMAT,
- *v, x);
+ v, x);
}
endtime = GetCurrentTimestamp();
if (rt_test_stats)
@@ -715,7 +726,8 @@ test_pattern(const test_spec * spec)
for (n = 0; n < 1; n++)
{
uint64 x;
- TestValueType *v;
+ TestValueType v;
+ bool found;
/*
* Pick next value to probe at random. We limit the probes to the
@@ -727,15 +739,15 @@ test_pattern(const test_spec * spec)
x = pg_prng_uint64_range(&pg_global_prng_state, 0, last_int + 1000);
/* Is it present according to rt_find() ? */
- v = rt_find(radixtree, x);
+ found = rt_find(radixtree, x, rt_copy_value_callback, (void*) &v);
- if (!v)
+ if (!found)
continue;
/* If the key is found, delete it and check again */
if (!rt_delete(radixtree, x))
elog(ERROR, "could not delete key 0x" UINT64_HEX_FORMAT, x);
- if (rt_find(radixtree, x) != NULL)
+ if (rt_find(radixtree, x, rt_copy_value_callback, (void*) &v))
elog(ERROR, "found deleted key 0x" UINT64_HEX_FORMAT, x);
if (rt_delete(radixtree, x))
elog(ERROR, "deleted already-deleted key 0x" UINT64_HEX_FORMAT, x);