The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
rlm_cache.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or (at
6 * your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/*
19 * $Id: 3208cbcdb9230e1d1449ddefe50e7ec4dbffc609 $
20 * @file rlm_cache.h
21 * @brief Cache values and merge them back into future requests.
22 *
23 * @copyright 2014 The FreeRADIUS server project
24 * @copyright 2014 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25 */
26RCSIDH(rlm_cache_h, "$Id: 3208cbcdb9230e1d1449ddefe50e7ec4dbffc609 $")
27
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/dl_module.h>
30#include <freeradius-devel/server/map.h>
31#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
32
34
35typedef void rlm_cache_handle_t;
36
37#define MAX_ATTRMAP 128
38
39typedef enum {
40 CACHE_RECONNECT = -2, //!< Handle needs to be reconnected
41 CACHE_ERROR = -1, //!< Fatal error
42 CACHE_OK = 0, //!< Cache entry found/updated
43 CACHE_MISS = 1, //!< Cache entry notfound
44 CACHE_YIELD = 2, //!< The driver has pushed an async
46
47/** Configuration for the rlm_cache module
48 *
49 * This is separate from the #rlm_cache_t struct, to limit driver's visibility of
50 * rlm_cache instance data.
51 */
52typedef struct {
53 fr_time_delta_t ttl; //!< How long an entry is valid for.
54 uint32_t max_entries; //!< Maximum entries allowed.
55 int32_t epoch; //!< Time after which entries are considered valid.
56 bool stats; //!< Generate statistics.
58
59/*
60 * Define a structure for our module configuration.
61 *
62 * These variables do not need to be in a structure, but it's
63 * a lot cleaner to do so, and a pointer to the structure can
64 * be used as the instance handle.
65 */
66typedef struct {
67 rlm_cache_config_t config; //!< Must come first because of icky hacks.
68
69 module_instance_t *driver_submodule; //!< Driver's instance data.
70 rlm_cache_driver_t const *driver; //!< Driver's exported interface.
72
73typedef struct {
74 fr_value_box_t key; //!< Key used to identify entry.
75 long long int hits; //!< How many times the entry has been retrieved.
76 fr_unix_time_t created; //!< When the entry was created.
77 fr_unix_time_t expires; //!< When the entry expires.
78
79 map_list_t maps; //!< Head of the maps list.
81
82/** Allocate a new cache entry
83 *
84 */
85typedef rlm_cache_entry_t *(*cache_entry_alloc_t)(rlm_cache_config_t const *config, void *instance, request_t *request);
86
87/** Free a cache entry
88 *
89 * @note This callback is optional, but the driver assume responsibility for freeing the
90 * cache_entry_t on #cache_entry_expire_t.
91 *
92 * If the driver does not need to keep a local copy of the cache entry, it should provide
93 * a callback to free the memory previously allocated for the cache entry by
94 * #cache_entry_find_t or by rlm_cache.
95 *
96 * @param c entry to free.
97 */
99
100/** Retrieve an entry from the cache
101 *
102 * If a cache entry is found, but the cache entry needs to be deserialized, the driver
103 * is expected to allocate an appropriately sized #rlm_cache_entry_t, perform the deserialisation,
104 * and write a pointer to the new entry to out, returning #CACHE_OK.
105 *
106 * If the #rlm_cache_handle_t is inviable, the driver should return #CACHE_RECONNECT, to have
107 * it reinitialised/reconnected.
108 *
109 * @param[out] out Where to write a pointer to the retrieved entry (if there was one).
110 * @param[out] rctx_out Where to write a pointer to a resume context for async drivers.
111 * @param[in] config for this instance of the rlm_cache module.
112 * @param[in] instance Driver specific instance data.
113 * @param[in] request The current request.
114 * @param[in] handle the driver gave us when we called #cache_acquire_t, or NULL if no
115 * #cache_acquire_t callback was provided.
116 * @param[in] key to use to lookup cache entry
117 * @return
118 * - #CACHE_RECONNECT - If handle needs to be reinitialised/reconnected.
119 * - #CACHE_ERROR - If the lookup couldn't be completed.
120 * - #CACHE_OK - Lookup was successful.
121 * - #CACHE_MISS - No cached entry was found.
122 * - #CACHE_YIELD - The driver has initiated an async lookup and yielded.
123 */
125 void *instance, request_t *request, void *handle,
126 fr_value_box_t const *key);
127
128/** Resume retrieving a cache entry
129 *
130 * To be called during resumption when a driver replies with CACHE_YIELD
131 * after a call to `find`.
132 *
133 * @param[out] out Where to write a pointer to the retrieved entry (if there was one).
134 * @param[in] config for this instance of the rlm_cache module.
135 * @param[in] instance Driver specific instance data.
136 * @param[in] request The current request.
137 * @param[in] handle the driver gave us when we called #cache_acquire_t, or NULL if no
138 * #cache_acquire_t callback was provided.
139 * @param[in] rctx Resume context returned by call to `find`.
140 * @return
141 * - #CACHE_RECONNECT - If handle needs to be reinitialised/reconnected.
142 * - #CACHE_ERROR - If the lookup couldn't be completed.
143 * - #CACHE_OK - Lookup was successful.
144 * - #CACHE_MISS - No cached entry was found.
145 * - #CACHE_YIELD - The driver has initiated another async operation and yielded.
146 */
148 void *instance, request_t *request, void *handle, void *rctx);
149
150/** Insert an entry into the cache
151 *
152 * Serialize (if necessary) the entry passed to us, and write it to the cache with
153 * the key c->key.
154 *
155 * The cache entry should not be freed by the driver, irrespective of success or failure.
156 * If the entry needs to be freed after insertion because a local copy should not be kept,
157 * the driver should provide a #cache_entry_free_t callback.
158 *
159 * If the #rlm_cache_handle_t is inviable, the driver should return #CACHE_RECONNECT, to have
160 * it reinitialised/reconnected.
161 *
162 * @note This callback is not optional.
163 *
164 * @note This callback *must* overwrite existing cache entries on insert.
165 *
166 * @param rctx_out Where to write a pointer to a resume context for async drivers.
167 * @param config for this instance of the rlm_cache module.
168 * @param instance Driver specific instance data.
169 * @param request The current request.
170 * @param handle the driver gave us when we called #cache_acquire_t, or NULL if no
171 * #cache_acquire_t callback was provided.
172 * @param c to insert.
173 * @return
174 * - #CACHE_RECONNECT - If handle needs to be reinitialised/reconnected.
175 * - #CACHE_ERROR - If the insert couldn't be completed.
176 * - #CACHE_OK - If the insert was successful.
177 * - #CACHE_YIELD - The driver has initiated an async insert and yielded.
178 */
179typedef cache_status_t (*cache_entry_insert_t)(void **rctx_out, rlm_cache_config_t const *config, void *instance,
180 request_t *request, void *handle,
181 rlm_cache_entry_t const *c);
182
183/** Resume inserting a cache entry
184 *
185 * To be called during resumption when a driver replies with CACHE_YIELD
186 * after a call to `insert`
187 *
188 * @param out Where to write a pointer to the entry which was inserted.
189 * @param config for this instance of the rlm_cache module.
190 * @param instance Driver specific instance data.
191 * @param request The current request.
192 * @param handle the driver gave us when we called #cache_acquire_t, or NULL if no
193 * #cache_acquire_t callback was provided.
194 * @param rctx Resume context returned by call to `insert`
195 * @return
196 * - #CACHE_RECONNECT - If handle needs to be reinitialised/reconnected.
197 * - #CACHE_ERROR - If the insert couldn't be completed.
198 * - #CACHE_OK - If the insert was successful.
199 * - #CACHE_YIELD - The driver has initiated another async operation and yeilded.
200 */
202 void *instance, request_t *request, void *handle, void *rctx);
203
204/** Remove an entry from the cache
205 *
206 * @note This callback is not optional.
207 *
208 * @param[out] rctx_out Where to write a pointer to a resume context for async drivers.
209 * @param[in] config for this instance of the rlm_cache module.
210 * @param[in] instance Driver specific instance data.
211 * @param[in] request The current request.
212 * @param[in] handle the driver gave us when we called #cache_acquire_t, or NULL if no
213 * #cache_acquire_t callback was provided.
214 * @param[in] key of entry to expire.
215 * @return
216 * - #CACHE_RECONNECT - If handle needs to be reinitialised/reconnected.
217 * - #CACHE_ERROR - If the entry couldn't be expired.
218 * - #CACHE_OK - If the entry was expired.
219 * - #CACHE_MISS - If the entry didn't exist, so couldn't be expired.
220 * - #CACHE_YIELD - The driver has initiated an async expire and yielded.
221 */
222typedef cache_status_t (*cache_entry_expire_t)(void **rctx_out, rlm_cache_config_t const *config, void *instance,
223 request_t *request, void *handle,
224 fr_value_box_t const *key);
225
226/** Resume removing a cache entry
227 *
228 * @param[in] config for this instance of the rlm_cache module.
229 * @param[in] instance Driver specific instance data.
230 * @param[in] request The current request.
231 * @param[in] handle the driver gave us when we called #cache_acquire_t, or NULL if no
232 * #cache_acquire_t callback was provided.
233 * @param[in] rctx Resume context returned by call to `expire`
234 * @return
235 * - #CACHE_RECONNECT - If handle needs to be reinitialised/reconnected.
236 * - #CACHE_ERROR - If the entry couldn't be expired.
237 * - #CACHE_OK - If the entry was expired.
238 * - #CACHE_MISS - If the entry didn't exist, so couldn't be expired.
239 * - #CACHE_YIELD - The driver has initiated another async operation and yielded.
240 */
242 request_t *request, void *handle, void *rctx);
243
244/** Update the ttl of an entry in the cache
245 *
246 * @note This callback optional. If it's not specified the cache code will expire and
247 * recreate the entry with a new TTL.
248 *
249 * If the #rlm_cache_handle_t is inviable, the driver should return #CACHE_RECONNECT, to have
250 * it reinitialised/reconnected.
251 *
252 * @param[in] config for this instance of the rlm_cache module.
253 * @param[in] instance Driver specific instance data.
254 * @param[in] request The current request.
255 * @param[in] handle the driver gave us when we called #cache_acquire_t, or NULL if no
256 * #cache_acquire_t callback was provided.
257 * @param[in] c to update the TTL of. c->ttl will have been set to the new value.
258 * @return
259 * - #CACHE_RECONNECT - If handle needs to be reinitialised/reconnected.
260 * - #CACHE_ERROR - If the entry TTL couldn't be updated.
261 * - #CACHE_OK - If the entry's TTL was updated.
262 */
264 request_t *request, void *handle,
266
267/** Get the number of entries in the cache
268 *
269 * @note This callback is optional. Though max_entries will not be enforced if it is not provided.
270 *
271 * @param[in] config for this instance of the rlm_cache module.
272 * @param[in] instance Driver specific instance data.
273 * @param[in] request The current request.
274 * @param handle the driver gave us when we called #cache_acquire_t, or NULL if no
275 * #cache_acquire_t callback was provided.
276 * @return number of entries in the cache.
277 */
278typedef uint64_t (*cache_entry_count_t)(rlm_cache_config_t const *config, void *instance,
279 request_t *request, void *handle);
280
281/** Acquire a handle to access the cache
282 *
283 * @note This callback is optional. If it's not provided the handle argument to other callbacks
284 * will be NULL.
285 *
286 * @param[out] handle Where to write pointer to handle to access the cache with.
287 * @param[in] config for this instance of the rlm_cache module.
288 * @param[in] instance Driver specific instance data.
289 * @param[in] request The current request.
290 * @return
291 * - 0 on success.
292 * - -1 on failure.
293 */
294typedef int (*cache_acquire_t)(void **handle, rlm_cache_config_t const *config, void *instance,
295 request_t *request);
296
297/** Release a previously acquired handle
298 *
299 * @note This callback is optional.
300 *
301 * @param[in] config for this instance of the rlm_cache module.
302 * @param[in] instance Driver specific instance data.
303 * @param[in] request The current request.
304 * @param[in] handle to release.
305 */
306typedef void (*cache_release_t)(rlm_cache_config_t const *config, void *instance, request_t *request,
307 rlm_cache_handle_t *handle);
308
309/** Reconnect a previously acquired handle
310 *
311 * @note This callback is optional.
312 *
313 * @param[in,out] handle to reinitialise/reconnect.
314 * @param[in] config for this instance of the rlm_cache module.
315 * @param[in] instance Driver specific instance data.
316 * @param[in] request The current request.
317
318 * @return
319 * - 0 on success.
320 * - -1 on failure.
321 */
323 void *instance, request_t *request);
324
325/** Cancel an async cache request
326 *
327 * To be called during request cancellation for outstanding cache requests
328 *
329 * @param[in] config for this instance of the rlm_cache module.
330 * @param[in] instance Driver specific instance data.
331 * @param[in] request The current request.
332 * @param[in] handle the driver gave us when we called #cache_acquire_t, or NULL if no
333 * #cache_acquire_t callback was provided.
334 * @param[in] rctx Resume context returned by call to the function which started the async request.
335 */
336typedef void (*cache_entry_request_cancel_t)(rlm_cache_config_t const *config, void *instance, request_t *request,
337 void *handle, void *rctx);
338
339
341 module_t common; //!< Common fields for all loadable modules.
342
343 cache_entry_alloc_t alloc; //!< (optional) Allocate a new entry.
344 cache_entry_free_t free; //!< (optional) Free memory used by an entry.
345
346 cache_entry_find_t find; //!< Retrieve an existing cache entry.
347 cache_entry_find_resume_t find_resume; //!< Resume an async find.
348 cache_entry_request_cancel_t find_cancel; //!< Cancel an async find.
349 cache_entry_insert_t insert; //!< Add a new entry.
350 cache_entry_insert_resume_t insert_resume; //!< Resume an async insert.
351 cache_entry_request_cancel_t insert_cancel; //!< Cancel an async insert.
352 cache_entry_expire_t expire; //!< Remove an old entry.
353 cache_entry_expire_resume_t expire_resume; //!< Resume an async expire.
354 cache_entry_request_cancel_t expire_cancel; //!< Cancel an async expire.
355 cache_entry_set_ttl_t set_ttl; //!< (Optional) Update the TTL of an entry.
356 cache_entry_count_t count; //!< (Optional) Number of entries currently in
357 //!< the cache.
358
359 cache_acquire_t acquire; //!< (optional) Acquire exclusive access to a resource
360 //!< used to retrieve the cache entry.
361 cache_release_t release; //!< (optional) Release access to resource acquired
362 //!< with acquire callback.
363 cache_reconnect_t reconnect; //!< (optional) Re-initialise resource.
364
365 call_env_parse_pair_t key_parse; //!< (optional) custom key parser. Allows the driver
366 ///< to have complete control over how the key is
367 ///< parsed. If not provided, the default key parser
368 ///< will be used. data will be set to the submodule's
369 ///< instance data, NOT the #rlm_cache_t.
370};
#define RCSIDH(h, id)
Definition build.h:561
int(* call_env_parse_pair_t)(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
Callback for performing custom parsing of a CONF_PAIR.
Definition call_env.h:151
unsigned int uint32_t
static const conf_parser_t config[]
Definition base.c:162
cache_status_t(* cache_entry_find_t)(rlm_cache_entry_t **out, void **rctx_out, rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, fr_value_box_t const *key)
Retrieve an entry from the cache.
Definition rlm_cache.h:124
uint32_t max_entries
Maximum entries allowed.
Definition rlm_cache.h:54
cache_entry_find_t find
Retrieve an existing cache entry.
Definition rlm_cache.h:346
cache_entry_insert_resume_t insert_resume
Resume an async insert.
Definition rlm_cache.h:350
cache_status_t(* cache_entry_expire_t)(void **rctx_out, rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, fr_value_box_t const *key)
Remove an entry from the cache.
Definition rlm_cache.h:222
int32_t epoch
Time after which entries are considered valid.
Definition rlm_cache.h:55
cache_entry_insert_t insert
Add a new entry.
Definition rlm_cache.h:349
module_instance_t * driver_submodule
Driver's instance data.
Definition rlm_cache.h:69
cache_status_t(* cache_entry_set_ttl_t)(rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, rlm_cache_entry_t *c)
Update the ttl of an entry in the cache.
Definition rlm_cache.h:263
fr_time_delta_t ttl
How long an entry is valid for.
Definition rlm_cache.h:53
cache_entry_expire_t expire
Remove an old entry.
Definition rlm_cache.h:352
cache_entry_set_ttl_t set_ttl
(Optional) Update the TTL of an entry.
Definition rlm_cache.h:355
cache_entry_request_cancel_t expire_cancel
Cancel an async expire.
Definition rlm_cache.h:354
bool stats
Generate statistics.
Definition rlm_cache.h:56
cache_entry_alloc_t alloc
(optional) Allocate a new entry.
Definition rlm_cache.h:343
fr_value_box_t key
Key used to identify entry.
Definition rlm_cache.h:74
map_list_t maps
Head of the maps list.
Definition rlm_cache.h:79
uint64_t(* cache_entry_count_t)(rlm_cache_config_t const *config, void *instance, request_t *request, void *handle)
Get the number of entries in the cache.
Definition rlm_cache.h:278
fr_unix_time_t created
When the entry was created.
Definition rlm_cache.h:76
rlm_cache_config_t config
Must come first because of icky hacks.
Definition rlm_cache.h:67
void(* cache_entry_free_t)(rlm_cache_entry_t *c)
Free a cache entry.
Definition rlm_cache.h:98
cache_entry_request_cancel_t insert_cancel
Cancel an async insert.
Definition rlm_cache.h:351
int(* cache_reconnect_t)(rlm_cache_handle_t **handle, rlm_cache_config_t const *config, void *instance, request_t *request)
Reconnect a previously acquired handle.
Definition rlm_cache.h:322
cache_status_t(* cache_entry_insert_resume_t)(rlm_cache_entry_t **out, rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, void *rctx)
Resume inserting a cache entry.
Definition rlm_cache.h:201
rlm_cache_driver_t const * driver
Driver's exported interface.
Definition rlm_cache.h:70
long long int hits
How many times the entry has been retrieved.
Definition rlm_cache.h:75
cache_release_t release
(optional) Release access to resource acquired with acquire callback.
Definition rlm_cache.h:361
cache_entry_free_t free
(optional) Free memory used by an entry.
Definition rlm_cache.h:344
void(* cache_release_t)(rlm_cache_config_t const *config, void *instance, request_t *request, rlm_cache_handle_t *handle)
Release a previously acquired handle.
Definition rlm_cache.h:306
cache_entry_find_resume_t find_resume
Resume an async find.
Definition rlm_cache.h:347
cache_status_t(* cache_entry_insert_t)(void **rctx_out, rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, rlm_cache_entry_t const *c)
Insert an entry into the cache.
Definition rlm_cache.h:179
cache_entry_expire_resume_t expire_resume
Resume an async expire.
Definition rlm_cache.h:353
cache_entry_count_t count
(Optional) Number of entries currently in the cache.
Definition rlm_cache.h:356
cache_entry_request_cancel_t find_cancel
Cancel an async find.
Definition rlm_cache.h:348
cache_status_t(* cache_entry_find_resume_t)(rlm_cache_entry_t **out, rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, void *rctx)
Resume retrieving a cache entry.
Definition rlm_cache.h:147
int(* cache_acquire_t)(void **handle, rlm_cache_config_t const *config, void *instance, request_t *request)
Acquire a handle to access the cache.
Definition rlm_cache.h:294
rlm_cache_entry_t *(* cache_entry_alloc_t)(rlm_cache_config_t const *config, void *instance, request_t *request)
Allocate a new cache entry.
Definition rlm_cache.h:85
module_t common
Common fields for all loadable modules.
Definition rlm_cache.h:341
cache_status_t
Definition rlm_cache.h:39
@ CACHE_ERROR
Fatal error.
Definition rlm_cache.h:41
@ CACHE_RECONNECT
Handle needs to be reconnected.
Definition rlm_cache.h:40
@ CACHE_YIELD
The driver has pushed an async.
Definition rlm_cache.h:44
@ CACHE_OK
Cache entry found/updated.
Definition rlm_cache.h:42
@ CACHE_MISS
Cache entry notfound.
Definition rlm_cache.h:43
cache_reconnect_t reconnect
(optional) Re-initialise resource.
Definition rlm_cache.h:363
call_env_parse_pair_t key_parse
(optional) custom key parser.
Definition rlm_cache.h:365
void rlm_cache_handle_t
Definition rlm_cache.h:35
fr_unix_time_t expires
When the entry expires.
Definition rlm_cache.h:77
void(* cache_entry_request_cancel_t)(rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, void *rctx)
Cancel an async cache request.
Definition rlm_cache.h:336
cache_acquire_t acquire
(optional) Acquire exclusive access to a resource used to retrieve the cache entry.
Definition rlm_cache.h:359
cache_status_t(* cache_entry_expire_resume_t)(rlm_cache_config_t const *config, void *instance, request_t *request, void *handle, void *rctx)
Resume removing a cache entry.
Definition rlm_cache.h:241
Configuration for the rlm_cache module.
Definition rlm_cache.h:52
Definition rlm_cache.h:73
Module instance data.
Definition module.h:287
Struct exported by a rlm_* module.
Definition module.h:203
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"Unix" time.
Definition time.h:95
static size_t char ** out
Definition value.h:1030