Skip to content

Commit

Permalink
[#463]New features for values, deque and ART
Browse files Browse the repository at this point in the history
  • Loading branch information
Jubilee101 committed Dec 1, 2024
1 parent ae2a0ce commit f6f8bb0
Show file tree
Hide file tree
Showing 6 changed files with 371 additions and 30 deletions.
14 changes: 13 additions & 1 deletion src/include/art.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ int
pgagroal_art_create(struct art** tree);

/**
* inserts a new value into the art tree, note that the key is copied
* inserts a new value into the art tree,note that the key is copied while the value is sometimes not(depending on value type)
* @param t The tree
* @param key The key
* @param key_len The length of the key
Expand All @@ -85,6 +85,18 @@ pgagroal_art_create(struct art** tree);
int
pgagroal_art_insert(struct art* t, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type);

/**
* inserts a new ValueRef value into the art tree with a custom to_string and destroy data callback config
* @param t The tree
* @param key The key
* @param key_len The length of the key
* @param value The value data
* @param config The config
* @return 0 if the item was successfully inserted, otherwise 1
*/
int
pgagroal_art_insert_with_config(struct art* t, unsigned char* key, uint32_t key_len, uintptr_t value, struct value_config* config);

/**
* Check if a key exists in the ART tree
* @param t The tree
Expand Down
40 changes: 39 additions & 1 deletion src/include/deque.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef PGAGROAL_DEQUE_H
#define PGAGROAL_DEQUE_H

Expand Down Expand Up @@ -82,7 +83,7 @@ int
pgagroal_deque_create(bool thread_safe, struct deque** deque);

/**
* Add a node to deque's tail, the tag will be copied, but the data will not
* Add a node to deque's tail, the tag will be copied
* This function is thread safe
* @param deque The deque
* @param tag The tag,optional
Expand All @@ -93,6 +94,27 @@ pgagroal_deque_create(bool thread_safe, struct deque** deque);
int
pgagroal_deque_add(struct deque* deque, char* tag, uintptr_t data, enum value_type type);

/**
* Remove all the nodes with the given tag
* @param deque The deque
* @param tag The tag
* @return Number of nodes removed
*/
int
pgagroal_deque_remove(struct deque* deque, char* tag);

/**
* Add a node to deque's tail with custom to_string and data destroy callback,
* the type will be set to ValueRef
* This function is thread safe
* @param deque The deque
* @param tag The tag,optional
* @param data The data
* @return 0 if success, otherwise 1
*/
int
pgagroal_deque_add_with_config(struct deque* deque, char* tag, uintptr_t data, struct value_config* config);

/**
* Retrieve value and remove the node from deque's head.
* Note that if the value was copied into node,
Expand Down Expand Up @@ -128,6 +150,15 @@ pgagroal_deque_peek(struct deque* deque, char** tag);
uintptr_t
pgagroal_deque_get(struct deque* deque, char* tag);

/**
* Does the tag exists
* @param deque The deque
* @param tag The tag
* @return True if exists, otherwise false
*/
bool
pgagroal_deque_exists(struct deque* deque, char* tag);

/**
* Create a deque iterator
* @param deque The deque
Expand Down Expand Up @@ -182,6 +213,13 @@ pgagroal_deque_empty(struct deque* deque);
void
pgagroal_deque_list(struct deque* deque);

/**
* Sort the deque
* @param deque The deque
*/
void
pgagroal_deque_sort(struct deque* deque);

/**
* Convert what's inside deque to string
* @param deque The deque
Expand Down
27 changes: 25 additions & 2 deletions src/include/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,39 @@ struct value
data_to_string_cb to_string; /**< The callback to convert data to string */
};

/**
* @struct value_config
* Defines configuration for managing a value
*/
struct value_config
{
data_destroy_cb destroy_data; /**< The callback to destroy data */
data_to_string_cb to_string; /**< The callback to convert data to string */
};

/**
* Create a value based on the data and value type
* @param type The value type, use ValueRef if you are only storing pointers without the need to manage memory
* @param type The value type, use ValueRef if you are only storing pointers without the need to manage memory,
* use ValueMem if you are storing pointers to a chunk of memory that needs to and can be simply freed
* (meaning it can't have pointers to other malloced memories)
* @param data The value data, type cast it to uintptr_t before passing into function
* @param value [out] The value
* @return 0 on success, 1 if otherwise
*/
int
pgagroal_value_create(enum value_type type, uintptr_t data, struct value** value);

/**
* Create a value with a config for customized destroy or to_string callback,
* the type will default to ValueRef
* @param data The value data, type cast it to uintptr_t before passing into function
* @param config The configuration
* @param value [out] The value
* @return 0 on success, 1 if otherwise
*/
int
pgagroal_value_create_with_config(uintptr_t data, struct value_config* config, struct value** value);

/**
* Destroy a value along with the data within
* @param value The value
Expand Down Expand Up @@ -146,4 +169,4 @@ pgagroal_value_to_float(uintptr_t val);
}
#endif

#endif
#endif
52 changes: 41 additions & 11 deletions src/libpgagroal/art.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static struct art_leaf*
node_get_minimum(struct art_node* node);

static void
create_art_leaf(struct art_leaf** leaf, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type);
create_art_leaf(struct art_leaf** leaf, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type, struct value_config* config);

static void
create_art_node(struct art_node** node, enum art_node_type type);
Expand Down Expand Up @@ -214,11 +214,12 @@ find_index(unsigned char ch, const unsigned char* keys, int length);
* @param key_len The length of the key
* @param value The value data
* @param type The value type
* @param config The config
* @param new If the key value is newly inserted (not replaced)
* @return Old value if the key exists, otherwise NULL
*/
static struct value*
art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t depth, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type, bool* new);
art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t depth, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type, struct value_config* config, bool* new);

/**
* Delete a value from a node recursively.
Expand Down Expand Up @@ -352,7 +353,28 @@ pgagroal_art_insert(struct art* t, unsigned char* key, uint32_t key_len, uintptr
// c'mon, at least create a tree first...
goto error;
}
old_val = art_node_insert(t->root, &t->root, 0, key, key_len, value, type, &new);
old_val = art_node_insert(t->root, &t->root, 0, key, key_len, value, type, NULL, &new);
pgagroal_value_destroy(old_val);
if (new)
{
t->size++;
}
return 0;
error:
return 1;
}

int
pgagroal_art_insert_with_config(struct art* t, unsigned char* key, uint32_t key_len, uintptr_t value, struct value_config* config)
{
struct value* old_val = NULL;
bool new = false;
if (t == NULL)
{
// c'mon, at least create a tree first...
goto error;
}
old_val = art_node_insert(t->root, &t->root, 0, key, key_len, value, ValueRef, config, &new);
pgagroal_value_destroy(old_val);
if (new)
{
Expand Down Expand Up @@ -407,12 +429,20 @@ min(uint32_t a, uint32_t b)
}

static void
create_art_leaf(struct art_leaf** leaf, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type)
create_art_leaf(struct art_leaf** leaf, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type, struct value_config* config)
{
struct art_leaf* l = NULL;
l = malloc(sizeof(struct art_leaf) + key_len);
memset(l, 0, sizeof(struct art_leaf) + key_len);
pgagroal_value_create(type, value, &l->value);
if (config != NULL)
{
pgagroal_value_create_with_config(value, config, &l->value);
}
else
{
pgagroal_value_create(type, value, &l->value);
}

l->key_len = key_len;
memcpy(l->key, key, key_len);
*leaf = l;
Expand Down Expand Up @@ -602,7 +632,7 @@ node_get_child(struct art_node* node, unsigned char ch)
}

static struct value*
art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t depth, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type, bool* new)
art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t depth, unsigned char* key, uint32_t key_len, uintptr_t value, enum value_type type, struct value_config* config, bool* new)
{
struct art_leaf* leaf = NULL;
struct art_leaf* min_leaf = NULL;
Expand All @@ -616,7 +646,7 @@ art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t dept
{
// Lazy expansion, skip creating an inner node since it currently will have only this one leaf.
// We will compare keys when reach leaf anyway, the path doesn't need to 100% match the key along the way
create_art_leaf(&leaf, key, key_len, value, type);
create_art_leaf(&leaf, key, key_len, value, type, config);
*node_ref = SET_LEAF(leaf);
*new = true;
return NULL;
Expand All @@ -639,7 +669,7 @@ art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t dept
// This way we inductively guarantee that all children to a parent share the same prefix even if it's only partially stored
leaf_key = GET_LEAF(node)->key;
create_art_node(&new_node, Node4);
create_art_leaf(&leaf, key, key_len, value, type);
create_art_leaf(&leaf, key, key_len, value, type, config);
// Get the diverging index after point of depth
for (idx = depth; idx < min(key_len, GET_LEAF(node)->key_len); idx++)
{
Expand Down Expand Up @@ -681,7 +711,7 @@ art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t dept
{
// case 2, split the node
create_art_node(&new_node, Node4);
create_art_leaf(&leaf, key, key_len, value, type);
create_art_leaf(&leaf, key, key_len, value, type, config);
new_node->prefix_len = diff_len;
memcpy(new_node->prefix, node->prefix, min(MAX_PREFIX_LEN, diff_len));
// We need to know if new bytes that were once outside the partial prefix range will now come into the range
Expand Down Expand Up @@ -727,12 +757,12 @@ art_node_insert(struct art_node* node, struct art_node** node_ref, uint32_t dept
{
node->num_children++;
}
return art_node_insert(*next, next, depth + 1, key, key_len, value, type, new);
return art_node_insert(*next, next, depth + 1, key, key_len, value, type, config, new);
}
else
{
// add a child to current node since the spot is available
create_art_leaf(&leaf, key, key_len, value, type);
create_art_leaf(&leaf, key, key_len, value, type, config);
node_add_child(node, node_ref, key[depth], SET_LEAF(leaf));
*new = true;
return NULL;
Expand Down
Loading

0 comments on commit f6f8bb0

Please sign in to comment.