0894c65dff1130adbe3dcf2ea290cc2728c70b8d
[project/netifd.git] / utils.c
1 /*
2  * netifd - network interface daemon
3  * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2
7  * as published by the Free Software Foundation
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14 #include <string.h>
15 #include <stdlib.h>
16 #include "utils.h"
17
18 void
19 vlist_init(struct vlist_tree *tree, avl_tree_comp cmp, vlist_update_cb update)
20 {
21         tree->update = update;
22         tree->version = 1;
23
24         avl_init(&tree->avl, cmp, 0, tree);
25 }
26
27 void
28 vlist_delete(struct vlist_tree *tree, struct vlist_node *node)
29 {
30         if (!tree->no_delete)
31                 avl_delete(&tree->avl, &node->avl);
32         tree->update(tree, NULL, node);
33 }
34
35 void
36 vlist_add(struct vlist_tree *tree, struct vlist_node *node, void *key)
37 {
38         struct vlist_node *old_node = NULL;
39         struct avl_node *anode;
40
41         node->avl.key = key;
42         node->version = tree->version;
43
44         anode = avl_find(&tree->avl, key);
45         if (anode) {
46                 old_node = container_of(anode, struct vlist_node, avl);
47                 if (tree->keep_old || tree->no_delete) {
48                         old_node->version = tree->version;
49                         goto update_only;
50                 }
51
52                 avl_delete(&tree->avl, anode);
53         }
54
55         avl_insert(&tree->avl, &node->avl);
56
57 update_only:
58         tree->update(tree, node, old_node);
59 }
60
61 void
62 vlist_flush(struct vlist_tree *tree)
63 {
64         struct vlist_node *node, *tmp;
65
66         avl_for_each_element_safe(&tree->avl, node, avl, tmp) {
67                 if ((node->version == tree->version || node->version == -1) &&
68                     tree->version != -1)
69                         continue;
70
71                 vlist_delete(tree, node);
72         }
73 }
74
75 void
76 vlist_flush_all(struct vlist_tree *tree)
77 {
78         tree->version = -1;
79         vlist_flush(tree);
80 }
81
82
83 void
84 __vlist_simple_init(struct vlist_simple_tree *tree, int offset)
85 {
86         INIT_LIST_HEAD(&tree->list);
87         tree->version = 1;
88         tree->head_offset = offset;
89 }
90
91 void
92 vlist_simple_delete(struct vlist_simple_tree *tree, struct vlist_simple_node *node)
93 {
94         char *ptr;
95
96         list_del(&node->list);
97         ptr = (char *) node - tree->head_offset;
98         free(ptr);
99 }
100
101 void
102 vlist_simple_flush(struct vlist_simple_tree *tree)
103 {
104         struct vlist_simple_node *n, *tmp;
105
106         list_for_each_entry_safe(n, tmp, &tree->list, list) {
107                 if ((n->version == tree->version || n->version == -1) &&
108                     tree->version != -1)
109                         continue;
110
111                 vlist_simple_delete(tree, n);
112         }
113 }
114
115 void
116 vlist_simple_replace(struct vlist_simple_tree *dest, struct vlist_simple_tree *old)
117 {
118         struct vlist_simple_node *n, *tmp;
119
120         vlist_simple_update(dest);
121         list_for_each_entry_safe(n, tmp, &old->list, list) {
122                 list_del(&n->list);
123                 vlist_simple_add(dest, n);
124         }
125         vlist_simple_flush(dest);
126 }
127
128 void
129 vlist_simple_flush_all(struct vlist_simple_tree *tree)
130 {
131         tree->version = -1;
132         vlist_simple_flush(tree);
133 }