value_pair_map_t *maps; //!< Attribute map applied to users
//!< and profiles.
+
+ DICT_ATTR *cache_ttl; //!< Control attribute,
+ //!< modifies cache TTL at
+ //!< runtime.
+ DICT_ATTR *cache_status_only; //!< Control attribute,
+ //!< modifies cache
+ //!< behaviour at runtime.
+ DICT_ATTR *cache_merge; //!< Control attribute,
+ //!< modifies cache
+ //!< behaviour at runtime.
+ DICT_ATTR *cache_entry_hits; //!< Attribute showing the
+ //!< number of hits on the
+ //!< cache entry.
#ifdef HAVE_PTHREAD_H
pthread_mutex_t cache_mutex;
#endif
rad_assert(request != NULL);
rad_assert(c != NULL);
+
+ vp = pairfind(request->config_items,
+ inst->cache_merge->attr,
+ inst->cache_merge->vendor,
+ TAG_ANY);
+ if (vp && (vp->vp_integer == 0)) {
+ RDEBUG2("Told not to merge entry into request");
+ return;
+ }
if (c->control) {
RDEBUG2("Merging cached control list:");
}
if (inst->stats) {
- vp = paircreate(PW_CACHE_ENTRY_HITS, 0, PW_TYPE_INTEGER);
+ vp = pairalloc(inst->cache_entry_hits);
rad_assert(vp != NULL);
vp->vp_integer = c->hits;
* Update the expiry time based on the TTL.
* A TTL of 0 means "delete from the cache".
*/
- vp = pairfind(request->config_items, PW_CACHE_TTL, 0, TAG_ANY);
+ vp = pairfind(request->config_items,
+ inst->cache_ttl->attr,
+ inst->cache_ttl->vendor,
+ TAG_ANY);
if (vp) {
if (vp->vp_integer == 0) goto delete;
VALUE_PAIR *vp, *found, **to_req, **to_cache, **from;
const DICT_ATTR *da;
+ int merge = TRUE;
REQUEST *context;
const value_pair_map_t *map;
/*
* TTL of 0 means "don't cache this entry"
*/
- vp = pairfind(request->config_items, PW_CACHE_TTL, 0, TAG_ANY);
+ vp = pairfind(request->config_items,
+ inst->cache_ttl->attr,
+ inst->cache_ttl->vendor,
+ TAG_ANY);
+
if (vp && (vp->vp_integer == 0)) return NULL;
- c = rad_malloc(sizeof(*c));
- memset(c, 0, sizeof(*c));
-
+ c = rad_calloc(sizeof(*c));
c->key = strdup(key);
c->created = c->expires = request->timestamp;
RDEBUG("Creating entry for \"%s\"", key);
- for (map = inst->maps; map != NULL; map = map->next)
- {
+ /*
+ * Check to see if we need to merge the entry into the request
+ */
+ vp = pairfind(request->config_items,
+ inst->cache_merge->attr,
+ inst->cache_merge->vendor,
+ TAG_ANY);
+ if (vp && (vp->vp_integer == 0)) {
+ merge = FALSE;
+ RDEBUG2("Told not to merge new entry into request");
+ }
+
+ for (map = inst->maps; map != NULL; map = map->next) {
rad_assert(map->dst && map->src);
/*
* - Map src and dst attributes differ
*/
to_req = NULL;
- if (!map->src->da || (map->src->list != map->dst->list) ||
- (map->src->da != map->dst->da))
- {
+ if (!merge || !map->src->da ||
+ (map->src->list != map->dst->list) ||
+ (map->src->da != map->dst->da)) {
context = request;
/*
* It's ok if the list isn't valid here...
rlm_cache_t *inst;
inst = rad_calloc(sizeof(*inst));
- inst->cs = conf;
+ inst->cs = conf;
+
+ /*
+ * The right way to resolve attribute numbers
+ */
+ if (!(
+ (inst->cache_ttl = dict_attrbyname("Cache-TTL")) &&
+ (inst->cache_status_only = dict_attrbyname("Cache-Status-Only")) &&
+ (inst->cache_merge = dict_attrbyname("Cache-Merge")) &&
+ (inst->cache_entry_hits = dict_attrbyname("Cache-Entry-Hits")))) {
+ radlog(L_ERR, "rlm_cache: Failed resolving dictionary "
+ "attributes, check dictionaries are up to date");
+ }
+
/*
* If the configuration parameters can't be parsed, then
* fail.
/*
* If yes, only return whether we found a valid cache entry
*/
- vp = pairfind(request->config_items, PW_CACHE_STATUS_ONLY, 0, TAG_ANY);
+ vp = pairfind(request->config_items,
+ inst->cache_status_only->attr,
+ inst->cache_status_only->vendor,
+ TAG_ANY);
if (vp && vp->vp_integer) {
rcode = c ? RLM_MODULE_OK:
RLM_MODULE_NOTFOUND;