blob: 2da564b15f88cbc6926553d897a8a7489f366266 [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/*
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020080 * Insert an entry in <d> dictionary with <s> as value. *
81 */
82struct dict_entry *dict_insert(struct dict *d, char *s)
83{
84 struct dict_entry *de;
Frédéric Lécailleb5ecf032019-06-11 08:34:26 +020085 struct ebpt_node *n;
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020086
87 HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
88 de = __dict_lookup(d, s);
89 HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
90 if (de)
91 return de;
92
93 de = new_dict_entry(s);
94 if (!de)
95 return NULL;
96
97 HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
Frédéric Lécailleb5ecf032019-06-11 08:34:26 +020098 n = ebis_insert(&d->values, &de->value);
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020099 HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
Frédéric Lécailleb5ecf032019-06-11 08:34:26 +0200100 if (n != &de->value) {
101 free_dict_entry(de);
102 de = container_of(n, struct dict_entry, value);
103 }
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +0200104
105 return de;
106}
107