libsysprof: update radix tree sources

This commit is contained in:
Christian Hergert
2023-01-26 11:03:39 -08:00
parent 1e1a719895
commit 7c378668e1
2 changed files with 33 additions and 53 deletions

View File

@ -1,6 +1,6 @@
/* Rax -- A radix tree implementation.
*
* Version 1.1 -- 3 December 2019
* Version 1.2 -- 7 February 2019
*
* Copyright (c) 2017-2019, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
@ -61,7 +61,7 @@ void raxDebugShowNode(const char *msg, raxNode *n);
#ifdef RAX_DEBUG_MSG
#define debugf(...) \
if (raxDebugMsg) { \
printf("%s:%s:%d:\t", __FILE__, __FUNCTION__, __LINE__); \
printf("%s:%s:%d:\t", __FILE__, __func__, __LINE__); \
printf(__VA_ARGS__); \
fflush(stdout); \
}
@ -154,7 +154,7 @@ static inline void raxStackFree(raxStack *ts) {
* 'nodesize'. The padding is needed to store the child pointers to aligned
* addresses. Note that we add 4 to the node size because the node has a four
* bytes header. */
#define raxPadding(nodesize) ((sizeof(void*)-((nodesize+4) % sizeof(void*))) & (sizeof(void*)-1))
#define raxPadding(nodesize) ((sizeof(void*)-(((nodesize)+4) % sizeof(void*))) & (sizeof(void*)-1))
/* Return the pointer to the last child pointer in a node. For the compressed
* nodes this is the only child pointer. */
@ -182,7 +182,7 @@ static inline void raxStackFree(raxStack *ts) {
)
/* Allocate a new non compressed node with the specified number of children.
* If datafiled is true, the allocation is made large enough to hold the
* If datafield is true, the allocation is made large enough to hold the
* associated data pointer.
* Returns the new node pointer. On out of memory NULL is returned. */
raxNode *raxNewNode(size_t children, int datafield) {
@ -259,7 +259,7 @@ raxNode *raxAddChild(raxNode *n, unsigned char c, raxNode **childptr, raxNode **
size_t curlen = raxNodeCurrentLength(n);
n->size++;
size_t newlen = raxNodeCurrentLength(n);
n->size--; /* For now restore the orignal size. We'll update it only on
n->size--; /* For now restore the original size. We'll update it only on
success at the end. */
/* Alloc the new child we will link to 'n'. */
@ -352,8 +352,8 @@ raxNode *raxAddChild(raxNode *n, unsigned char c, raxNode **childptr, raxNode **
* we don't need to do anything if there was already some padding to use. In
* that case the final destination of the pointers will be the same, however
* in our example there was no pre-existing padding, so we added one byte
* plus thre bytes of padding. After the next memmove() things will look
* like thata:
* plus three bytes of padding. After the next memmove() things will look
* like that:
*
* [HDR*][abde][....][Aptr][Bptr][....][Dptr][Eptr]|AUXP|
*/
@ -487,8 +487,8 @@ static inline size_t raxLowWalk(rax *rax, unsigned char *s, size_t len, raxNode
if (h->iscompr) j = 0; /* Compressed node only child is at index 0. */
memcpy(&h,children+j,sizeof(h));
parentlink = children+j;
j = 0; /* If the new node is compressed and we do not
iterate again (since i == l) set the split
j = 0; /* If the new node is non compressed and we do not
iterate again (since i == len) set the split
position to 0 to signal this node represents
the searched key. */
}
@ -554,7 +554,7 @@ int raxGenericInsert(rax *rax, unsigned char *s, size_t len, void *data, void **
*
* Splitting a compressed node have a few possible cases.
* Imagine that the node 'h' we are currently at is a compressed
* node contaning the string "ANNIBALE" (it means that it represents
* node containing the string "ANNIBALE" (it means that it represents
* nodes A -> N -> N -> I -> B -> A -> L -> E with the only child
* pointer of this node pointing at the 'E' node, because remember that
* we have characters at the edges of the graph, not inside the nodes
@ -628,7 +628,7 @@ int raxGenericInsert(rax *rax, unsigned char *s, size_t len, void *data, void **
*
* 3b. IF $SPLITPOS != 0:
* Trim the compressed node (reallocating it as well) in order to
* contain $splitpos characters. Change chilid pointer in order to link
* contain $splitpos characters. Change child pointer in order to link
* to the split node. If new compressed node len is just 1, set
* iscompr to 0 (layout is the same). Fix parent's reference.
*
@ -653,7 +653,7 @@ int raxGenericInsert(rax *rax, unsigned char *s, size_t len, void *data, void **
* Let $SPLITPOS be the zero-based index at which, in the
* compressed node array of characters, we stopped iterating because
* there were no more keys character to match. So in the example of
* the node "ANNIBALE", addig the string "ANNI", the $SPLITPOS is 4.
* the node "ANNIBALE", adding the string "ANNI", the $SPLITPOS is 4.
*
* 1. Save the current compressed node $NEXT pointer (the pointer to the
* child element, that is always present in compressed nodes).
@ -666,7 +666,7 @@ int raxGenericInsert(rax *rax, unsigned char *s, size_t len, void *data, void **
*
* 3. Trim the current node to contain the first $SPLITPOS characters.
* As usually if the new node length is just 1, set iscompr to 0.
* Take the iskey / associated value as it was in the orignal node.
* Take the iskey / associated value as it was in the original node.
* Fix the parent's reference.
*
* 4. Set the postfix node as the only child pointer of the trimmed
@ -905,9 +905,9 @@ int raxInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old) {
return raxGenericInsert(rax,s,len,data,old,1);
}
/* Non overwriting insert function: this if an element with the same key
/* Non overwriting insert function: if an element with the same key
* exists, the value is not updated and the function returns 0.
* This is a just a wrapper for raxGenericInsert(). */
* This is just a wrapper for raxGenericInsert(). */
int raxTryInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old) {
return raxGenericInsert(rax,s,len,data,old,0);
}
@ -1082,7 +1082,7 @@ int raxRemove(rax *rax, unsigned char *s, size_t len, void **old) {
}
} else if (h->size == 1) {
/* If the node had just one child, after the removal of the key
* further compression with adjacent nodes is pontentially possible. */
* further compression with adjacent nodes is potentially possible. */
trycompress = 1;
}
@ -1102,9 +1102,9 @@ int raxRemove(rax *rax, unsigned char *s, size_t len, void **old) {
* We try to navigate upward till there are other nodes that can be
* compressed, when we reach the upper node which is not a key and has
* a single child, we scan the chain of children to collect the
* compressable part of the tree, and replace the current node with the
* compressible part of the tree, and replace the current node with the
* new one, fixing the child pointer to reference the first non
* compressable node.
* compressible node.
*
* Example of case "1". A tree stores the keys "FOO" = 1 and
* "FOOBAR" = 2:
@ -1270,6 +1270,7 @@ void raxStart(raxIterator *it, rax *rt) {
* is a low level function used to implement the iterator, not callable by
* the user. Returns 0 on out of memory, otherwise 1 is returned. */
int raxIteratorAddChars(raxIterator *it, unsigned char *s, size_t len) {
if (len == 0) return 1;
if (it->key_max < it->key_len+len) {
unsigned char *old = (it->key == it->key_static_string) ? NULL :
it->key;
@ -1329,7 +1330,7 @@ int raxIteratorNextStep(raxIterator *it, int noup) {
if (!noup && children) {
debugf("GO DEEPER\n");
/* Seek the lexicographically smaller key in this subtree, which
* is the first one found always going torwards the first child
* is the first one found always going towards the first child
* of every successive node. */
if (!raxStackPush(&it->stack,it->node)) return 0;
raxNode **cp = raxNodeFirstChildPtr(it->node);
@ -1341,14 +1342,14 @@ int raxIteratorNextStep(raxIterator *it, int noup) {
if (it->node_cb && it->node_cb(&it->node))
memcpy(cp,&it->node,sizeof(it->node));
/* For "next" step, stop every time we find a key along the
* way, since the key is lexicograhically smaller compared to
* way, since the key is lexicographically smaller compared to
* what follows in the sub-children. */
if (it->node->iskey) {
it->data = raxGetData(it->node);
return 1;
}
} else {
/* If we finished exporing the previous sub-tree, switch to the
/* If we finished exploring the previous sub-tree, switch to the
* new one: go upper until a node is found where there are
* children representing keys lexicographically greater than the
* current key. */
@ -1409,7 +1410,7 @@ int raxIteratorNextStep(raxIterator *it, int noup) {
}
/* Seek the greatest key in the subtree at the current node. Return 0 on
* out of memory, otherwise 1. This is an helper function for different
* out of memory, otherwise 1. This is a helper function for different
* iteration functions below. */
int raxSeekGreatest(raxIterator *it) {
while(it->node->size) {
@ -1510,7 +1511,7 @@ int raxIteratorPrevStep(raxIterator *it, int noup) {
int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len) {
int eq = 0, lt = 0, gt = 0, first = 0, last = 0;
it->stack.items = 0; /* Just resetting. Intialized by raxStart(). */
it->stack.items = 0; /* Just resetting. Initialized by raxStart(). */
it->flags |= RAX_ITER_JUST_SEEKED;
it->flags &= ~RAX_ITER_EOF;
it->key_len = 0;
@ -1576,30 +1577,8 @@ int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len) {
} else if (lt || gt) {
/* Exact key not found or eq flag not set. We have to set as current
* key the one represented by the node we stopped at, and perform
* a next/prev operation to seek. To reconstruct the key at this node
* we start from the parent and go to the current node, accumulating
* the characters found along the way. */
if (!raxStackPush(&it->stack,it->node)) return 0;
for (size_t j = 1; j < it->stack.items; j++) {
raxNode *parent = it->stack.stack[j-1];
raxNode *child = it->stack.stack[j];
if (parent->iscompr) {
if (!raxIteratorAddChars(it,parent->data,parent->size))
return 0;
} else {
raxNode **cp = raxNodeFirstChildPtr(parent);
unsigned char *p = parent->data;
while(1) {
raxNode *aux;
memcpy(&aux,cp,sizeof(aux));
if (aux == child) break;
cp++;
p++;
}
if (!raxIteratorAddChars(it,p,1)) return 0;
}
}
raxStackPop(&it->stack);
* a next/prev operation to seek. */
raxIteratorAddChars(it, ele, i-splitpos);
/* We need to set the iterator in the correct state to call next/prev
* step in order to seek the desired element. */
@ -1731,7 +1710,7 @@ int raxPrev(raxIterator *it) {
* tree, expect a disappointing distribution. A random walk produces good
* random elements if the tree is not sparse, however in the case of a radix
* tree certain keys will be reported much more often than others. At least
* this function should be able to expore every possible element eventually. */
* this function should be able to explore every possible element eventually. */
int raxRandomWalk(raxIterator *it, size_t steps) {
if (it->rt->numele == 0) {
it->flags |= RAX_ITER_EOF;
@ -1768,6 +1747,7 @@ int raxRandomWalk(raxIterator *it, size_t steps) {
if (n->iskey) steps--;
}
it->node = n;
it->data = raxGetData(it->node);
return 1;
}
@ -1824,7 +1804,7 @@ uint64_t raxSize(rax *rax) {
/* ----------------------------- Introspection ------------------------------ */
/* This function is mostly used for debugging and learning purposes.
* It shows an ASCII representation of a tree on standard output, outling
* It shows an ASCII representation of a tree on standard output, outline
* all the nodes and the contained keys.
*
* The representation is as follow:
@ -1834,7 +1814,7 @@ uint64_t raxSize(rax *rax) {
* [abc]=0x12345678 (node is a key, pointing to value 0x12345678)
* [] (a normal empty node)
*
* Children are represented in new idented lines, each children prefixed by
* Children are represented in new indented lines, each children prefixed by
* the "`-(x)" string, where "x" is the edge byte.
*
* [abc]
@ -1891,7 +1871,7 @@ void raxShow(rax *rax) {
/* Used by debugnode() macro to show info about a given node. */
void raxDebugShowNode(const char *msg, raxNode *n) {
if (raxDebugMsg == 0) return;
printf("%s: %p [%.*s] key:%d size:%d children:",
printf("%s: %p [%.*s] key:%u size:%u children:",
msg, (void*)n, (int)n->size, (char*)n->data, n->iskey, n->size);
int numcld = n->iscompr ? 1 : n->size;
raxNode **cldptr = raxNodeLastChildPtr(n) - (numcld-1);

View File

@ -58,7 +58,7 @@
* successive nodes having a single child are "compressed" into the node
* itself as a string of characters, each representing a next-level child,
* and only the link to the node representing the last character node is
* provided inside the representation. So the above representation is turend
* provided inside the representation. So the above representation is turned
* into:
*
* ["foo"] ""
@ -123,7 +123,7 @@ typedef struct raxNode {
* nodes).
*
* If the node has an associated key (iskey=1) and is not NULL
* (isnull=0), then after the raxNode pointers poiting to the
* (isnull=0), then after the raxNode pointers pointing to the
* children, an additional value pointer is present (as you can see
* in the representation above as "value-ptr" field).
*/