summaryrefslogtreecommitdiff
path: root/utils.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-09-07 14:37:18 +0200
committerFelix Fietkau <nbd@openwrt.org>2011-09-07 14:37:18 +0200
commit69b2dcb92b8402b9c6df4d6a041a890fe6468e18 (patch)
treec0acc6b30947ac7c8499d6d2f402abf837c9008c /utils.c
parent3fa53680c85a6e029a3e7b4d673bffee4795fa52 (diff)
downloadnetifd-69b2dcb92b8402b9c6df4d6a041a890fe6468e18.tar.gz
add code for versioned lists and use it to manage addresses and routes
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c66
1 files changed, 65 insertions, 1 deletions
diff --git a/utils.c b/utils.c
index cf0718a..15f0525 100644
--- a/utils.c
+++ b/utils.c
@@ -1,8 +1,72 @@
#include <string.h>
#include "utils.h"
-int avl_strcmp(const void *k1, const void *k2, void *ptr)
+int
+avl_strcmp(const void *k1, const void *k2, void *ptr)
{
return strcmp(k1, k2);
}
+static int
+vlist_cmp(const void *k1, const void *k2, void *ptr)
+{
+ struct vlist_tree *vl = ptr;
+ return memcmp(k1, k2, vl->data_len);
+}
+
+void
+__vlist_init(struct vlist_tree *tree, vlist_update_cb update, int offset, int len)
+{
+ tree->data_offset = offset;
+ tree->data_len = len;
+ tree->update = update;
+ tree->version = 1;
+
+ avl_init(&tree->avl, vlist_cmp, 0, tree);
+}
+
+void
+vlist_delete(struct vlist_tree *tree, struct vlist_node *node)
+{
+ avl_delete(&tree->avl, &node->avl);
+ tree->update(tree, NULL, node);
+}
+
+void
+vlist_add(struct vlist_tree *tree, struct vlist_node *node)
+{
+ struct vlist_node *old_node = NULL;
+ struct avl_node *anode;
+
+ node->avl.key = (char *) node + tree->data_offset;
+ node->version = tree->version;
+
+ anode = avl_find(&tree->avl, (char *) node + tree->data_offset);
+ if (anode) {
+ old_node = container_of(anode, struct vlist_node, avl);
+ avl_delete(&tree->avl, anode);
+ }
+
+ avl_insert(&tree->avl, &node->avl);
+ tree->update(tree, node, old_node);
+}
+
+void
+vlist_flush(struct vlist_tree *tree)
+{
+ struct vlist_node *node, *tmp;
+
+ avl_for_each_element_safe(&tree->avl, node, avl, tmp) {
+ if (node->version == tree->version)
+ continue;
+
+ vlist_delete(tree, node);
+ }
+}
+
+void
+vlist_flush_all(struct vlist_tree *tree)
+{
+ tree->version++;
+ vlist_flush(tree);
+}