blob: 50fe1eb8252a6a7f5fd1ba197353f79707538294 [file] [log] [blame]
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +02001#include <string.h>
2
Willy Tarreau8d2b7772020-05-27 10:58:19 +02003#include <import/eb32tree.h>
4#include <import/ebistree.h>
Willy Tarreau3afc4c42020-06-03 18:23:19 +02005#include <haproxy/dict.h>
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +02006
7struct dict *new_dict(const char *name)
8{
9 struct dict *dict;
10
11 dict = malloc(sizeof *dict);
12 if (!dict)
13 return NULL;
14
15 dict->name = name;
16 dict->values = EB_ROOT_UNIQUE;
17 HA_RWLOCK_INIT(&dict->rwlock);
18
19 return dict;
20}
21
22/*
23 * Allocate a new dictionary entry with <s> as string value which is strdup()'ed.
24 * Returns the new allocated entry if succeeded, NULL if not.
25 */
26static struct dict_entry *new_dict_entry(char *s)
27{
28 struct dict_entry *de;
29
30 de = calloc(1, sizeof *de);
31 if (!de)
32 return NULL;
33
34 de->value.key = strdup(s);
35 if (!de->value.key)
36 goto err;
37
Frédéric Lécaille99de1d02019-06-07 10:58:20 +020038 de->len = strlen(s);
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020039 de->refcount = 1;
40
41 return de;
42
43 err:
44 free(de->value.key);
45 de->value.key = NULL;
Frédéric Lécaille99de1d02019-06-07 10:58:20 +020046 de->len = 0;
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020047 free(de);
48 return NULL;
49}
50
51/*
52 * Release the memory allocated for <de> dictionary entry.
53 */
54static void free_dict_entry(struct dict_entry *de)
55{
56 de->refcount = 0;
57 free(de->value.key);
58 de->value.key = NULL;
59 free(de);
60}
61
62/*
63 * Simple function to lookup dictionary entries with <s> as value.
64 */
65static struct dict_entry *__dict_lookup(struct dict *d, const char *s)
66{
67 struct dict_entry *de;
68 struct ebpt_node *node;
69
70 de = NULL;
71 node = ebis_lookup(&d->values, s);
72 if (node)
73 de = container_of(node, struct dict_entry, value);
74
75 return de;
76}
77
78/*
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020079 * Insert an entry in <d> dictionary with <s> as value. *
80 */
81struct dict_entry *dict_insert(struct dict *d, char *s)
82{
83 struct dict_entry *de;
Frédéric Lécailleb5ecf032019-06-11 08:34:26 +020084 struct ebpt_node *n;
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020085
86 HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
87 de = __dict_lookup(d, s);
88 HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
89 if (de)
90 return de;
91
92 de = new_dict_entry(s);
93 if (!de)
94 return NULL;
95
96 HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
Frédéric Lécailleb5ecf032019-06-11 08:34:26 +020097 n = ebis_insert(&d->values, &de->value);
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +020098 HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
Frédéric Lécailleb5ecf032019-06-11 08:34:26 +020099 if (n != &de->value) {
100 free_dict_entry(de);
101 de = container_of(n, struct dict_entry, value);
102 }
Frédéric Lécaille4a3fef82019-05-28 14:47:17 +0200103
104 return de;
105}
106