Coverage Report

Created: 2025-11-24 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/src/dict.c
Line
Count
Source
1
#include <string.h>
2
3
#include <import/eb32tree.h>
4
#include <import/ebistree.h>
5
#include <haproxy/dict.h>
6
#include <haproxy/thread.h>
7
8
struct dict *new_dict(const char *name)
9
0
{
10
0
  struct dict *dict;
11
12
0
  dict = malloc(sizeof *dict);
13
0
  if (!dict)
14
0
    return NULL;
15
16
0
  dict->name     = name;
17
0
  dict->values   = EB_ROOT_UNIQUE;
18
0
  HA_RWLOCK_INIT(&dict->rwlock);
19
20
0
  return dict;
21
0
}
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
 */
27
static struct dict_entry *new_dict_entry(char *s)
28
0
{
29
0
  struct dict_entry *de;
30
31
0
  de = calloc(1, sizeof *de);
32
0
  if (!de)
33
0
    return NULL;
34
35
0
  de->value.key = strdup(s);
36
0
  if (!de->value.key)
37
0
    goto err;
38
39
0
  de->len = strlen(s);
40
0
  de->refcount = 1;
41
42
0
  return de;
43
44
0
 err:
45
0
  ha_free(&de->value.key);
46
0
  de->len = 0;
47
0
  free(de);
48
0
  return NULL;
49
0
}
50
51
/*
52
 * Release the memory allocated for <de> dictionary entry.
53
 */
54
static void free_dict_entry(struct dict_entry *de)
55
0
{
56
0
  de->refcount = 0;
57
0
  ha_free(&de->value.key);
58
0
  free(de);
59
0
}
60
61
/*
62
 * Simple function to lookup dictionary entries with <s> as value.
63
 */
64
static struct dict_entry *__dict_lookup(struct dict *d, const char *s)
65
0
{
66
0
  struct dict_entry *de;
67
0
  struct ebpt_node *node;
68
69
0
  de = NULL;
70
0
  node = ebis_lookup(&d->values, s);
71
0
  if (node)
72
0
    de = container_of(node, struct dict_entry, value);
73
74
0
  return de;
75
0
}
76
77
/*
78
 * Insert an entry in <d> dictionary with <s> as value. *
79
 */
80
struct dict_entry *dict_insert(struct dict *d, char *s)
81
0
{
82
0
  struct dict_entry *de;
83
0
  struct ebpt_node *n;
84
85
0
  HA_RWLOCK_RDLOCK(DICT_LOCK, &d->rwlock);
86
0
  de = __dict_lookup(d, s);
87
0
  HA_RWLOCK_RDUNLOCK(DICT_LOCK, &d->rwlock);
88
0
  if (de) {
89
0
    HA_ATOMIC_INC(&de->refcount);
90
0
    return de;
91
0
  }
92
93
0
  de = new_dict_entry(s);
94
0
  if (!de)
95
0
    return NULL;
96
97
0
  HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
98
0
  n = ebis_insert(&d->values, &de->value);
99
0
  HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
100
0
  if (n != &de->value) {
101
0
    free_dict_entry(de);
102
0
    de = container_of(n, struct dict_entry, value);
103
0
  }
104
105
0
  return de;
106
0
}
107
108
109
/*
110
 * Unreference a dict entry previously acquired with <dict_insert>.
111
 * If this is the last live reference to the entry, it is
112
 * removed from the dictionary.
113
 */
114
void dict_entry_unref(struct dict *d, struct dict_entry *de)
115
0
{
116
0
  if (!de)
117
0
    return;
118
119
0
  if (HA_ATOMIC_SUB_FETCH(&de->refcount, 1) != 0)
120
0
    return;
121
122
0
  HA_RWLOCK_WRLOCK(DICT_LOCK, &d->rwlock);
123
0
  ebpt_delete(&de->value);
124
0
  HA_RWLOCK_WRUNLOCK(DICT_LOCK, &d->rwlock);
125
126
0
  free_dict_entry(de);
127
0
}