The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
htrie.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /** hash / rb / patricia trees
18  *
19  * @file src/lib/util/htrie.c
20  *
21  * @copyright 2021 Network RADIUS SAS (legal@networkradius.com)
22  */
23 RCSID("$Id: efca3c5792829c563310161ae4feb280a12d3741 $")
24 
25 #include <freeradius-devel/util/debug.h>
26 #include <freeradius-devel/util/htrie.h>
27 #include <freeradius-devel/util/table.h>
28 
29 #define FUNC(_prefix, _op) ._op = (fr_htrie_ ##_op ## _t) fr_##_prefix##_## _op
30 
32  { L("auto"), FR_HTRIE_AUTO },
33  { L("hash"), FR_HTRIE_HASH },
34  { L("rb"), FR_HTRIE_RB },
35  { L("trie"), FR_HTRIE_TRIE },
36 };
38 
39 static fr_htrie_funcs_t const default_funcs[] = {
40  [FR_HTRIE_HASH] = {
42  FUNC(hash_table, find),
43  FUNC(hash_table, insert),
44  FUNC(hash_table, replace),
45  FUNC(hash_table, remove),
46  FUNC(hash_table, delete),
47  FUNC(hash_table, num_elements)
48  },
49  [FR_HTRIE_RB] = {
50  .match = (fr_htrie_find_t) fr_rb_find,
51  FUNC(rb, find),
52  FUNC(rb, insert),
53  FUNC(rb, replace),
54  FUNC(rb, remove),
55  FUNC(rb, delete),
56  FUNC(rb, num_elements)
57  },
58  [FR_HTRIE_TRIE] = {
59  .match = (fr_htrie_find_t) fr_trie_match,
60  FUNC(trie, find),
61  FUNC(trie, insert),
62  FUNC(trie, replace),
63  FUNC(trie, remove),
64  FUNC(trie, delete),
65  FUNC(trie, num_elements)
66  }
67 };
68 
69 /** An abstraction over our internal hashes, rb trees, and prefix tries
70  *
71  * This is useful where the data type being inserted into the tree
72  * is user controlled, and so we need to pick the most efficient structure
73  * for a given data type dynamically at runtime.
74  *
75  * @param[in] ctx to bind the htrie's lifetime to.
76  * @param[in] type One of:
77  * - FR_HTRIE_HASH
78  * - FR_HTRIE_RB
79  * - FR_HTRIE_TRIE
80  * @param[in] hash_data Used by FR_HTRIE_HASH to convert the
81  * data into a 32bit integer used for binning.
82  * @param[in] cmp_data Used to determine exact matched.
83  * @param[in] get_key Used by the prefix trie to extract a key
84  * from the data.
85  * @param[in] free_data The callback used to free the data if it is
86  * deleted or replaced. May be NULL in which
87  * case data will not be freed for these operations.
88  * @return
89  * - A new htrie on success.
90  * - NULL on failure, either missing functions or a memory allocation error.
91  */
92 fr_htrie_t *fr_htrie_alloc(TALLOC_CTX *ctx,
94  fr_hash_t hash_data,
95  fr_cmp_t cmp_data,
96  fr_trie_key_t get_key,
97  fr_free_t free_data)
98 {
99  fr_htrie_t *ht;
100 
101  ht = talloc_zero(ctx, fr_htrie_t);
102  if (unlikely(!ht)) {
103  fr_strerror_const("Failed allocating fr_htrie_t");
104  return NULL;
105  }
106  ht->type = type;
107 
108  switch (type) {
109  case FR_HTRIE_HASH:
110  if (!hash_data || !cmp_data) {
111  fr_strerror_const("hash_data and cmp_data must not be NULL for FR_HTRIE_HASH");
112  return NULL;
113  }
114 
115  ht->store = fr_hash_table_alloc(ht, hash_data, cmp_data, free_data);
116  if (unlikely(!ht->store)) {
117  error:
118  talloc_free(ht);
119  return NULL;
120  }
121  ht->funcs = default_funcs[type];
122  return ht;
123 
124  case FR_HTRIE_RB:
125  if (!cmp_data) {
126  fr_strerror_const("cmp_data must not be NULL for FR_HTRIE_RB");
127  return NULL;
128  }
129 
130  ht->store = fr_rb_alloc(ht, cmp_data, free_data);
131  if (unlikely(!ht->store)) goto error;
132  ht->funcs = default_funcs[type];
133  return ht;
134 
135  case FR_HTRIE_TRIE:
136  if (!get_key) {
137  fr_strerror_const("get_key must not be NULL for FR_HTRIE_TRIE");
138  return NULL;
139  }
140 
141  ht->store = fr_trie_alloc(ht, get_key, free_data);
142  if (unlikely(!ht->store)) goto error;
143  ht->funcs = default_funcs[type];
144  return ht;
145 
146  case FR_HTRIE_INVALID:
147  fr_assert_msg(0, "FR_TYPE_INVALID passed as htype");
148  return NULL;
149 
150  case FR_HTRIE_AUTO:
151  fr_assert_msg(0, "FR_HTRIE_AUTO must be resolved to a concrete htype value using fr_htrie_hint()");
152  return NULL;
153 
154  default:
155  return NULL;
156  }
157 }
#define RCSID(id)
Definition: build.h:481
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define unlikely(_x)
Definition: build.h:379
#define NUM_ELEMENTS(_t)
Definition: build.h:335
static fr_ring_buffer_t * rb
Definition: control_test.c:51
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition: debug.h:210
void * fr_hash_table_find(fr_hash_table_t *ht, void const *data)
uint32_t(* fr_hash_t)(void const *)
Definition: hash.h:36
#define fr_hash_table_alloc(_ctx, _hash_node, _cmp_node, _free_node)
Definition: hash.h:58
static fr_htrie_funcs_t const default_funcs[]
Definition: htrie.c:39
size_t fr_htrie_type_table_len
Definition: htrie.c:37
fr_htrie_t * fr_htrie_alloc(TALLOC_CTX *ctx, fr_htrie_type_t type, fr_hash_t hash_data, fr_cmp_t cmp_data, fr_trie_key_t get_key, fr_free_t free_data)
An abstraction over our internal hashes, rb trees, and prefix tries.
Definition: htrie.c:92
fr_table_num_sorted_t const fr_htrie_type_table[]
Definition: htrie.c:31
#define FUNC(_prefix, _op)
Definition: htrie.c:29
fr_htrie_type_t
Definition: htrie.h:49
@ FR_HTRIE_RB
Data is stored in a rb tree.
Definition: htrie.h:52
@ FR_HTRIE_TRIE
Data is stored in a prefix trie.
Definition: htrie.h:53
@ FR_HTRIE_HASH
Data is stored in a hash.
Definition: htrie.h:51
@ FR_HTRIE_AUTO
Automatically choose the best type.
Definition: htrie.h:54
@ FR_HTRIE_INVALID
Definition: htrie.h:50
void *(* fr_htrie_find_t)(void *ht, void const *data)
Definition: htrie.h:37
void * store
What we're using to store node data.
Definition: htrie.h:82
fr_htrie_type_t type
type of the htrie
Definition: htrie.h:81
fr_htrie_find_t match
exact prefix match
Definition: htrie.h:69
fr_htrie_funcs_t funcs
Function pointers for the various operations.
Definition: htrie.h:83
Which functions are used for the different operations.
Definition: htrie.h:67
A hash/rb/prefix trie abstraction.
Definition: htrie.h:80
talloc_free(reap)
int8_t(* fr_cmp_t)(void const *a, void const *b)
Definition: misc.h:38
void(* fr_free_t)(void *)
Definition: misc.h:39
#define fr_rb_alloc(_ctx, _data_cmp, _data_free)
Allocs a red black tree.
Definition: rb.h:223
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
fr_aka_sim_id_type_t type
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:49
fr_trie_t * fr_trie_alloc(TALLOC_CTX *ctx, fr_trie_key_t get_key, fr_free_t free_data)
Allocate a trie.
Definition: trie.c:741
int(* fr_trie_key_t)(uint8_t **out, size_t *outlen, void const *data)
Definition: trie.h:56
void * fr_trie_match(fr_trie_t *ft, void const *data)
#define fr_strerror_const(_msg)
Definition: strerror.h:223