The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
rlm_cache_htrie.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program 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
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 4f0af6095cddb714036099eb8a2730be29d73f94 $
19 * @file rlm_cache_htrie.c
20 * @brief Simple htrie based cache.
21 *
22 * @copyright 2024 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
23 * @copyright 2014 The FreeRADIUS server project
24 */
25#include <freeradius-devel/server/base.h>
26#include <freeradius-devel/util/debug.h>
27#include <freeradius-devel/util/htrie.h>
28#include "../../rlm_cache.h"
29
30static int cf_htrie_type_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
31static int cf_htrie_key_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
32 call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule);
33
34typedef struct {
35 fr_htrie_t *cache; //!< Tree for looking up cache keys.
36 fr_heap_t *heap; //!< For managing entry expiry.
37
38 pthread_mutex_t mutex; //!< Protect the tree from multiple readers/writers.
40
41typedef struct {
42 fr_type_t ktype; //!< When htrie is "auto", we use this type to decide
43 ///< what type of tree to use.
44
45 fr_htrie_type_t htype; //!< The htrie type we'll be using
46 bool htrie_auto; //!< Whether the user wanted to automatically configure
47 ///< the htrie.
48
49 rlm_cache_htrie_mutable_t *mutable; //!< Mutable instance data.
51
52typedef struct {
53 rlm_cache_entry_t fields; //!< Entry data.
54 fr_heap_index_t heap_id; //!< Offset used for expiry heap.
56
58 { FR_CONF_OFFSET("type", rlm_cache_htrie_t, htype), .dflt = "auto",
62};
63
64/** Custom htrie type parsing function
65 *
66 * Sets a bool, so we known if the original type was "auto", so we can constantly re-evaluate
67 * the htrie type based on the key type.
68 */
69int cf_htrie_type_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
70{
71 rlm_cache_htrie_t *inst = talloc_get_type_abort(parent, rlm_cache_htrie_t);
72 int ret;
73
74 ret = cf_table_parse_int(ctx, out, parent, ci, rule);
75 if (unlikely(ret < 0)) return ret;
76
77 /*
78 * Record this now, so when we overwrite this
79 * value later, we know to keep checking the
80 * htrie type value for consistency.
81 */
82 if (*(int *)out == FR_HTRIE_AUTO) inst->htrie_auto = true;
83
84 return 0;
85}
86
87/** Custom key parsing function for checking compatibility of key types
88 *
89 * This function does two things:
90 * - It selects a htrie type based on the key type.
91 * - It checks that all keys are compatible with each other.
92 */
93static int cf_htrie_key_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
94 call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
95{
97 rlm_cache_htrie_t *inst = talloc_get_type_abort(parent->driver_submodule->data, rlm_cache_htrie_t);
98 tmpl_t *key_tmpl;
99 fr_type_t our_ktype, old_ktype;
100 bool set_type = false;
101
102 /*
103 * Call the standard pair parsing function
104 */
105 if (unlikely(call_env_parse_pair(ctx, &key_tmpl, t_rules, ci, cec, rule) < 0)) return -1;
106 our_ktype = tmpl_expanded_type(key_tmpl);
107
108 /*
109 * We need the user to tell us what the key type is for ambiguous expansions
110 */
111 if (fr_type_is_void(our_ktype)) {
112 cf_log_err(ci, "Key type is unspecified. Add a cast to set a specific type");
113 return -1;
114 }
115
116 /*
117 * If we don't have a key type already, then just set it to the first key type we see
118 */
119 if (fr_type_is_void(inst->ktype) || fr_type_is_null(inst->ktype)) {
120 inst->ktype = our_ktype;
121 set_type = true;
122 /*
123 * Check if we can cast this key type, to the key type we've already seen
124 */
125 } else if (!fr_type_cast(our_ktype, inst->ktype)) {
126 cf_log_err(ci, "Incompatible key types '%s' and '%s', cast to a more broadly compatible "
127 "type such as 'string'", fr_type_to_str(inst->ktype), fr_type_to_str(our_ktype));
128 return -1;
129 }
130
131 /*
132 * See if we should promote inst->ktype
133 */
134 old_ktype = inst->ktype;
135 inst->ktype = fr_type_promote(inst->ktype, our_ktype);
137
138 /*
139 * If we're not automatically determining the htrie type,
140 * or the ktype hasn't changed, then don't bother figuring
141 * out the htrie type.
142 */
143 if ((!inst->htrie_auto || (old_ktype == inst->ktype)) && !set_type) goto finish;
144
145 /*
146 * We need to figure out the htrie type based on the key type
147 */
148 inst->htype = fr_htrie_hint(inst->ktype);
149 if (inst->htype == FR_HTRIE_INVALID) {
150 cf_log_err(ci, "Invalid data type '%s' for htrie key. "
151 "Cast to another type, or manually specify 'type", fr_type_to_str(inst->ktype));
152 return -1;
153 }
154
155 cf_log_info(ci, "Automatically setting htrie type to '%s' based on key type '%s'",
157
158finish:
159 *(void **)out = key_tmpl;
160 return 0;
161}
162
163/** Compare two entries by expiry time
164 *
165 * There may be multiple entries with the same expiry time.
166 */
167static fr_cmp_ret_t cache_heap_cmp(void const *one, void const *two)
168{
169 rlm_cache_entry_t const *a = one, *b = two;
170
171 return fr_unix_time_cmp(a->expires, b->expires);
172}
173
174/** Custom allocation function for the driver
175 *
176 * Allows allocation of cache entry structures with additional fields.
177 *
178 * @copydetails cache_entry_alloc_t
179 */
181 request_t *request)
182{
184
185 c = talloc_zero(NULL, rlm_cache_htrie_entry_t);
186 if (!c) {
187 RERROR("Failed allocating cache entry");
188 return NULL;
189 }
190
191 return (rlm_cache_entry_t *)c;
192}
193
194/** Locate a cache entry
195 *
196 * @note handle not used except for sanity checks.
197 *
198 * @copydetails cache_entry_find_t
199 */
201 UNUSED rlm_cache_config_t const *config, void *instance,
202 request_t *request, UNUSED void *handle, fr_value_box_t const *key)
203{
204 rlm_cache_htrie_t *driver = talloc_get_type_abort(instance, rlm_cache_htrie_t);
205 rlm_cache_htrie_mutable_t *mutable = driver->mutable;
206 rlm_cache_entry_t find = {};
207
209
210 fr_assert(mutable->cache);
211
212 /*
213 * Clear out old entries
214 */
215 c = fr_heap_peek(mutable->heap);
216 if (c && (fr_unix_time_lt(c->expires, fr_time_to_unix_time(request->packet->timestamp)))) {
217 fr_heap_extract(&mutable->heap, c);
218 fr_htrie_delete(mutable->cache, c);
219 talloc_free(c);
220 }
221
222 fr_value_box_copy_shallow(NULL, &find.key, key);
223
224 /*
225 * Is there an entry for this key?
226 *
227 * A comparator error must not read as a miss: a miss
228 * triggers "insert as new", which would shadow the
229 * existing entry.
230 */
231 if (unlikely(fr_htrie_find((void **)&c, mutable->cache, &find) < 0)) {
232 RPEDEBUG("Cache lookup failed");
233 *out = NULL;
234 return CACHE_ERROR;
235 }
236 if (!c) {
237 *out = NULL;
238 return CACHE_MISS;
239 }
240 *out = c;
241
242 return CACHE_OK;
243}
244
245/** Free an entry and remove it from the data store
246 *
247 * @note handle not used except for sanity checks.
248 *
249 * @copydetails cache_entry_expire_t
250 */
252 request_t *request, UNUSED void *handle,
253 fr_value_box_t const *key)
254{
255 rlm_cache_htrie_t *driver = talloc_get_type_abort(instance, rlm_cache_htrie_t);
256 rlm_cache_htrie_mutable_t *mutable = driver->mutable;
257 rlm_cache_entry_t find = {};
259
260 if (!request) return CACHE_ERROR;
261
262 fr_value_box_copy_shallow(NULL, &find.key, key);
263
264 if (unlikely(fr_htrie_find((void **)&c, mutable->cache, &find) < 0)) {
265 RPEDEBUG("Cache lookup failed");
266 return CACHE_ERROR;
267 }
268 if (!c) return CACHE_MISS;
269
270 fr_heap_extract(&mutable->heap, c);
271 fr_htrie_delete(mutable->cache, c);
272 talloc_free(c);
273
274 return CACHE_OK;
275}
276
277/** Insert a new entry into the data store
278 *
279 * @note handle not used except for sanity checks.
280 *
281 * @copydetails cache_entry_insert_t
282 */
284 request_t *request, void *handle,
285 rlm_cache_entry_t const *c)
286{
287 cache_status_t status;
288
289 rlm_cache_htrie_t *driver = talloc_get_type_abort(instance, rlm_cache_htrie_t);
290 rlm_cache_htrie_mutable_t *mutable = driver->mutable;
291
292 fr_assert(handle == request);
293
294 if (!request) return CACHE_ERROR;
295
296 /*
297 * Allow overwriting
298 */
299 if (fr_htrie_insert(mutable->cache, c) != 0) {
300 status = cache_entry_expire(config, instance, request, handle, &c->key);
301 if ((status != CACHE_OK) && !fr_cond_assert(0)) return CACHE_ERROR;
302
303 if (fr_htrie_insert(mutable->cache, c) != 0) {
304 RERROR("Failed adding entry");
305
306 return CACHE_ERROR;
307 }
308 }
309
310 if (fr_heap_insert(&mutable->heap, UNCONST(rlm_cache_entry_t *, c)) < 0) {
311 fr_htrie_delete(mutable->cache, c);
312 RERROR("Failed adding entry to expiry heap");
313
314 return CACHE_ERROR;
315 }
316
317 return CACHE_OK;
318}
319
320/** Update the TTL of an entry
321 *
322 * @note handle not used except for sanity checks.
323 *
324 * @copydetails cache_entry_set_ttl_t
325 */
327 request_t *request, UNUSED void *handle,
329{
330 rlm_cache_htrie_t *driver = talloc_get_type_abort(instance, rlm_cache_htrie_t);
331 rlm_cache_htrie_mutable_t *mutable = driver->mutable;
332
333#ifdef NDEBUG
334 if (!request) return CACHE_ERROR;
335#endif
336
337 if (!fr_cond_assert(fr_heap_extract(&mutable->heap, c) == 0)) {
338 RERROR("Entry not in heap");
339 return CACHE_ERROR;
340 }
341
342 if (fr_heap_insert(&mutable->heap, c) < 0) {
343 fr_htrie_delete(mutable->cache, c); /* make sure we don't leak entries... */
344 RERROR("Failed updating entry TTL. Entry was forcefully expired");
345 return CACHE_ERROR;
346 }
347 return CACHE_OK;
348}
349
350/** Return the number of entries in the cache
351 *
352 * @note handle not used except for sanity checks.
353 *
354 * @copydetails cache_entry_count_t
355 */
356static uint64_t cache_entry_count(UNUSED rlm_cache_config_t const *config, void *instance,
357 request_t *request, UNUSED void *handle)
358{
359 rlm_cache_htrie_t *driver = talloc_get_type_abort(instance, rlm_cache_htrie_t);
360
361 if (!request) return CACHE_ERROR;
362
363 return fr_htrie_num_elements(driver->mutable->cache);
364}
365
366/** Lock the htrie
367 *
368 * @note handle not used except for sanity checks.
369 *
370 * @copydetails cache_acquire_t
371 */
372static int cache_acquire(void **handle, UNUSED rlm_cache_config_t const *config, void *instance,
373 request_t *request)
374{
375 rlm_cache_htrie_t *driver = talloc_get_type_abort(instance, rlm_cache_htrie_t);
376
377 pthread_mutex_lock(&driver->mutable->mutex);
378
379 *handle = request; /* handle is unused, this is just for sanity checking */
380
381 RDEBUG3("Mutex acquired");
382
383 return 0;
384}
385
386/** Release an entry unlocking any mutexes
387 *
388 * @note handle not used except for sanity checks.
389 *
390 * @copydetails cache_release_t
391 */
392static void cache_release(UNUSED rlm_cache_config_t const *config, void *instance, request_t *request,
394{
395 rlm_cache_htrie_t *driver = talloc_get_type_abort(instance, rlm_cache_htrie_t);
396
397 pthread_mutex_unlock(&driver->mutable->mutex);
398
399 RDEBUG3("Mutex released");
400}
401
402/** Cleanup a cache_htrie instance
403 *
404 */
405static int mod_detach(module_detach_ctx_t const *mctx)
406{
407 rlm_cache_htrie_t *driver = talloc_get_type_abort(mctx->mi->data, rlm_cache_htrie_t);
408 rlm_cache_htrie_mutable_t *mutable = driver->mutable;
409
410 if (!mutable) return 0;
411
412 if (mutable->cache) {
414
415 while ((c = fr_heap_peek(mutable->heap))) {
416 fr_heap_extract(&mutable->heap, c);
417 fr_htrie_delete(mutable->cache, c);
418 talloc_free(c);
419 }
420 }
421
422 pthread_mutex_destroy(&mutable->mutex);
423 talloc_free(mutable);
424
425 return 0;
426}
427
428static fr_cmp_ret_t _value_cmp(void const *a, void const *b) {
429 fr_value_box_t const *one = a;
430 fr_value_box_t const *two = b;
431 return fr_value_box_cmp(one, two);
432}
433
434/** Create a new cache_htrie instance
435 *
436 * @param[in] mctx Data required for instantiation.
437 * @return
438 * - 0 on success.
439 * - -1 on failure.
440 */
441static int mod_instantiate(module_inst_ctx_t const *mctx)
442{
443 rlm_cache_htrie_t *driver = talloc_get_type_abort(mctx->mi->data, rlm_cache_htrie_t);
445 int ret;
446
447 /*
448 * An instance with htype of FR_HTRIE_AUTO has not been used
449 * in any policy - so instantiation can be short circuited.
450 */
451 if (driver->htype == FR_HTRIE_AUTO) return 0;
452
453 MEM(mutable = talloc_zero(NULL, rlm_cache_htrie_mutable_t));
454
455 /*
456 * The cache.
457 */
458 mutable->cache = fr_htrie_alloc(mutable, driver->htype,
462 if (!mutable->cache) {
463 PERROR("Failed to create cache");
464 error:
465 talloc_free(mutable);
466 return -1;
467 }
468
469 /*
470 * The heap of entries to expire.
471 */
472 mutable->heap = fr_heap_talloc_alloc(mutable, cache_heap_cmp, rlm_cache_htrie_entry_t, heap_id, 0);
473 if (!mutable->heap) {
474 ERROR("Failed to create heap for the cache");
475 goto error;
476 }
477
478 if ((ret = pthread_mutex_init(&mutable->mutex, NULL)) < 0) {
479 ERROR("Failed initializing mutex: %s", fr_syserror(ret));
480 goto error;
481 }
482
483 driver->mutable = mutable;
484
485 return 0;
486}
487
490 .common = {
491 .magic = MODULE_MAGIC_INIT,
492 .name = "cache_htrie",
494 .instantiate = mod_instantiate,
495 .detach = mod_detach,
496 .inst_size = sizeof(rlm_cache_htrie_t),
497 .inst_type = "rlm_cache_htrie_t",
498 },
499 .alloc = cache_entry_alloc,
500
501 .find = cache_entry_find,
502 .insert = cache_entry_insert,
503 .expire = cache_entry_expire,
504 .set_ttl = cache_entry_set_ttl,
505 .count = cache_entry_count,
506
507 .acquire = cache_acquire,
508 .release = cache_release,
509
510 .key_parse = cf_htrie_key_parse
511};
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
int call_env_parse_pair(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_ctx_t const *cec, call_env_parser_t const *rule)
Standard function we use for parsing call env pairs.
Definition call_env.c:412
module_instance_t const * mi
Module instance that the callenv is registered to.
Definition call_env.h:229
Per method call config.
Definition call_env.h:180
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
Definition cf_parse.c:1724
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:669
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:623
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:280
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:606
Common header for all CONF_* types.
Definition cf_priv.h:54
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:345
#define cf_log_info(_cf, _fmt,...)
Definition cf_util.h:347
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:131
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
uint32_t(* fr_hash_t)(void const *)
Definition hash.h:36
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:149
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
Definition heap.c:259
unsigned int fr_heap_index_t
Definition heap.h:82
static void * fr_heap_peek(fr_heap_t *h)
Return the item from the top of the heap but don't pop it.
Definition heap.h:138
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init)
Creates a heap that verifies elements are of a specific talloc type.
Definition heap.h:117
The main heap structure.
Definition heap.h:68
talloc_free(hp)
size_t fr_htrie_type_table_len
Definition htrie.c:36
fr_table_num_sorted_t const fr_htrie_type_table[]
Definition htrie.c:30
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:95
fr_htrie_type_t
Definition htrie.h:58
@ FR_HTRIE_AUTO
Automatically choose the best type.
Definition htrie.h:63
@ FR_HTRIE_INVALID
Definition htrie.h:59
static fr_htrie_type_t fr_htrie_hint(fr_type_t type)
Definition htrie.h:180
static int fr_htrie_insert(fr_htrie_t *ht, void const *data)
Insert data into a htrie.
Definition htrie.h:123
static int fr_htrie_num_elements(fr_htrie_t *ht)
Return the number of elements in the htrie.
Definition htrie.h:155
static char const * fr_htrie_type_to_str(fr_htrie_type_t type)
Return a static string containing the type name.
Definition htrie.h:213
static int fr_htrie_delete(fr_htrie_t *ht, void const *data)
Delete data from a htrie, freeing it if free_data cb was passed to fr_htrie_alloc.
Definition htrie.h:147
static int fr_htrie_find(void **found, fr_htrie_t *ht, void const *data)
Find data in a htrie.
Definition htrie.h:115
A hash/rb/prefix trie abstraction.
Definition htrie.h:91
#define PERROR(_fmt,...)
Definition log.h:233
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RERROR(fmt,...)
Definition log.h:315
#define RPEDEBUG(fmt,...)
Definition log.h:393
fr_type_t
fr_cmp_ret_t
Result of an ordering comparison.
Definition misc.h:50
module_instance_t * mi
Module instance to detach.
Definition module_ctx.h:57
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for detach calls.
Definition module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
static const conf_parser_t config[]
Definition base.c:162
#define fr_assert(_expr)
Definition rad_assert.h:37
fr_value_box_t key
Key used to identify entry.
Definition rlm_cache.h:73
module_t common
Common fields for all loadable modules.
Definition rlm_cache.h:258
cache_status_t
Definition rlm_cache.h:39
@ CACHE_ERROR
Fatal error.
Definition rlm_cache.h:41
@ CACHE_OK
Cache entry found/updated.
Definition rlm_cache.h:42
@ CACHE_MISS
Cache entry notfound.
Definition rlm_cache.h:43
void rlm_cache_handle_t
Definition rlm_cache.h:35
fr_unix_time_t expires
When the entry expires.
Definition rlm_cache.h:76
Configuration for the rlm_cache module.
Definition rlm_cache.h:51
Definition rlm_cache.h:72
static int mod_detach(module_detach_ctx_t const *mctx)
Cleanup a cache_htrie instance.
static rlm_cache_entry_t * cache_entry_alloc(UNUSED rlm_cache_config_t const *config, UNUSED void *instance, request_t *request)
Custom allocation function for the driver.
static int cf_htrie_key_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
Custom key parsing function for checking compatibility of key types.
bool htrie_auto
Whether the user wanted to automatically configure the htrie.
fr_heap_t * heap
For managing entry expiry.
static int cf_htrie_type_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Custom htrie type parsing function.
rlm_cache_entry_t fields
Entry data.
static conf_parser_t driver_config[]
static fr_cmp_ret_t _value_cmp(void const *a, void const *b)
static uint64_t cache_entry_count(UNUSED rlm_cache_config_t const *config, void *instance, request_t *request, UNUSED void *handle)
Return the number of entries in the cache.
static int cache_acquire(void **handle, UNUSED rlm_cache_config_t const *config, void *instance, request_t *request)
Lock the htrie.
rlm_cache_htrie_mutable_t * mutable
Mutable instance data.
static void cache_release(UNUSED rlm_cache_config_t const *config, void *instance, request_t *request, UNUSED rlm_cache_handle_t *handle)
Release an entry unlocking any mutexes.
rlm_cache_driver_t rlm_cache_htrie
fr_htrie_t * cache
Tree for looking up cache keys.
static cache_status_t cache_entry_expire(UNUSED rlm_cache_config_t const *config, void *instance, request_t *request, UNUSED void *handle, fr_value_box_t const *key)
Free an entry and remove it from the data store.
static fr_cmp_ret_t cache_heap_cmp(void const *one, void const *two)
Compare two entries by expiry time.
static cache_status_t cache_entry_find(rlm_cache_entry_t **out, UNUSED rlm_cache_config_t const *config, void *instance, request_t *request, UNUSED void *handle, fr_value_box_t const *key)
Locate a cache entry.
pthread_mutex_t mutex
Protect the tree from multiple readers/writers.
fr_heap_index_t heap_id
Offset used for expiry heap.
static cache_status_t cache_entry_set_ttl(UNUSED rlm_cache_config_t const *config, void *instance, request_t *request, UNUSED void *handle, rlm_cache_entry_t *c)
Update the TTL of an entry.
static int mod_instantiate(module_inst_ctx_t const *mctx)
Create a new cache_htrie instance.
static cache_status_t cache_entry_insert(rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, rlm_cache_entry_t const *c)
Insert a new entry into the data store.
fr_htrie_type_t htype
The htrie type we'll be using.
fr_type_t ktype
When htrie is "auto", we use this type to decide what type of tree to use.
void * data
Module's instance data.
Definition module.h:293
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:206
fr_type_t tmpl_expanded_type(tmpl_t const *vpt)
Return the native data type of the expression.
Definition tmpl_eval.c:203
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
eap_aka_sim_process_conf_t * inst
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define talloc_get_type_abort_const
Definition talloc.h:117
static int8_t fr_unix_time_cmp(fr_unix_time_t a, fr_unix_time_t b)
Compare two fr_unix_time_t values.
Definition time.h:944
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
Definition time.h:688
#define fr_unix_time_lt(_a, _b)
Definition time.h:367
int(* fr_trie_key_t)(uint8_t **out, size_t *outlen, void const *data)
Definition trie.h:55
static fr_slen_t parent
Definition pair.h:858
bool fr_type_cast(fr_type_t dst, fr_type_t src)
Return if we're allowed to cast the types.
Definition types.c:352
fr_type_t fr_type_promote(fr_type_t a, fr_type_t b)
Return the promoted type.
Definition types.c:641
#define fr_type_is_void(_x)
Definition types.h:378
#define fr_type_is_null(_x)
Definition types.h:347
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:454
fr_cmp_ret_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:759
uint32_t fr_value_box_hash(fr_value_box_t const *vb)
Hash the contents of a value box.
Definition value.c:7114
void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
Perform a shallow copy of a value_box.
Definition value.c:4540
int fr_value_box_to_key(uint8_t **out, size_t *outlen, fr_value_box_t const *value)
Get a key from a value box.
Definition value.c:2498
static size_t char ** out
Definition value.h:1030