blob: 777530a20cee6472575b9abc7d3c0304cf99ddc5 [file] [log] [blame]
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +02001#include <string.h>
2
3#include <proto/dict.h>
4
5#include <eb32tree.h>
6#include <ebistree.h>
7
8struct dict *new_dict(const char *name)
9{
10 struct dict *dict;
11
12 dict = malloc(sizeof *dict);
13 if (!dict)
14 return NULL;
15
16 dict->name = name;
17 dict->values = EB_ROOT_UNIQUE;
18 HA_RWLOCK_INIT(&dict->rwlock);
19
20 return dict;
21}
22
23/*
24 * Allocate a new dictionary entry with <s> as string value which is strdup()'ed.
25 * Returns the new allocated entry if succeeded, NULL if not.
26 */
27static struct dict_entry *new_dict_entry(char *s)
28{
29 struct dict_entry *de;
30
31 de = calloc(1, sizeof *de);
32 if (!de)
33 return NULL;
34
35 de->value.key = strdup(s);
36 if (!de->value.key)
37 goto err;
38
39 de->refcount = 1;
40
41 return de;
42
43 err:
44 free(de->value.key);
45 de->value.key = NULL;
46 free(de);
47 return NULL;
48}
49
50/*
51 * Release the memory allocated for <de> dictionary entry.
52 */
53static void free_dict_entry(struct dict_entry *de)
54{
55 de->refcount = 0;
56 free(de->value.key);
57 de->value.key = NULL;
58 free(de);
59}
60
61/*
62 * Simple function to lookup dictionary entries with <s> as value.
63 */
64static struct dict_entry *__dict_lookup(struct dict *d, const char *s)
65{
66 struct dict_entry *de;
67 struct ebpt_node *node;
68
69 de = NULL;
70 node = ebis_lookup(&d->values, s);
71 if (node)
72 de = container_of(node, struct dict_entry, value);
73
74 return de;
75}
76
77/*
78 * Insert <node> node in <root> ebtree, deleting any already existing node with
79 * the same value.
80 */
81static struct ebpt_node *__dict_insert(struct eb_root *root, struct ebpt_node *node)
82{
83 struct ebpt_node *n;
84
85 n = ebis_insert(root, node);
86 if (n != node) {
87 ebpt_delete(n);
88 free_dict_entry(container_of(n, struct dict_entry, value));
89 ebis_insert(root, node);
90 }
91
92 return node;
93}
94
95/*
96 * Insert an entry in <d> dictionary with <s> as value. *
97 */
98struct dict_entry *dict_insert(struct dict *d, char *s)
99{
100 struct dict_entry *de;
101
102 HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
103 de = __dict_lookup(d, s);
104 HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
105 if (de)
106 return de;
107
108 de = new_dict_entry(s);
109 if (!de)
110 return NULL;
111
112 HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
113 __dict_insert(&d->values, &de->value);
114 HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
115
116 return de;
117}
118