Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#463] New features for values, deque and ART #486

Merged
merged 1 commit into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading