blob: c2580e1793704e95c12dfe6cc0ec9640a295d221 [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
Frédéric Lécaille99de1d02019-06-07 10:58:20 +020039 de->len = strlen(s);
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020040 de->refcount = 1;
41
42 return de;
43
44 err:
45 free(de->value.key);
46 de->value.key = NULL;
Frédéric Lécaille99de1d02019-06-07 10:58:20 +020047 de->len = 0;
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020048 free(de);
49 return NULL;
50}
51
52/*
53 * Release the memory allocated for <de> dictionary entry.
54 */
55static void free_dict_entry(struct dict_entry *de)
56{
57 de->refcount = 0;
58 free(de->value.key);
59 de->value.key = NULL;
60 free(de);
61}
62
63/*
64 * Simple function to lookup dictionary entries with <s> as value.
65 */
66static struct dict_entry *__dict_lookup(struct dict *d, const char *s)
67{
68 struct dict_entry *de;
69 struct ebpt_node *node;
70
71 de = NULL;
72 node = ebis_lookup(&d->values, s);
73 if (node)
74 de = container_of(node, struct dict_entry, value);
75
76 return de;
77}
78
79/*
80 * Insert <node> node in <root> ebtree, deleting any already existing node with
81 * the same value.
82 */
83static struct ebpt_node *__dict_insert(struct eb_root *root, struct ebpt_node *node)
84{
85 struct ebpt_node *n;
86
87 n = ebis_insert(root, node);
88 if (n != node) {
89 ebpt_delete(n);
90 free_dict_entry(container_of(n, struct dict_entry, value));
91 ebis_insert(root, node);
92 }
93
94 return node;
95}
96
97/*
98 * Insert an entry in <d> dictionary with <s> as value. *
99 */
100struct dict_entry *dict_insert(struct dict *d, char *s)
101{
102 struct dict_entry *de;
103
104 HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
105 de = __dict_lookup(d, s);
106 HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
107 if (de)
108 return de;
109
110 de = new_dict_entry(s);
111 if (!de)
112 return NULL;
113
114 HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
115 __dict_insert(&d->values, &de->value);
116 HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
117
118 return de;
119}
120