negative cache design.

git-svn-id: file:///svn/unbound/trunk@1197 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-08-18 15:00:17 +00:00
parent 38396319c7
commit bcec1a7593
3 changed files with 177 additions and 20 deletions

View file

@ -166,7 +166,8 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
else if(fptr == &anchor_cmp) return 1;
else if(fptr == &canonical_tree_compare) return 1;
else if(fptr == &context_query_cmp) return 1;
else if(fptr == &val_neg_compare) return 1;
else if(fptr == &val_neg_data_compare) return 1;
else if(fptr == &val_neg_zone_compare) return 1;
return 0;
}

View file

@ -43,14 +43,23 @@
*/
#include "config.h"
#include "validator/val_neg.h"
#include "util/log.h"
#include "util/data/dname.h"
#include "util/log.h"
#include "util/net_help.h"
int val_neg_compare(const void* a, const void* b)
int val_neg_data_compare(const void* a, const void* b)
{
struct val_neg_data* x = (struct val_neg_data*)a;
struct val_neg_data* y = (struct val_neg_data*)b;
int m;
return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m);
}
int val_neg_zone_compare(const void* a, const void* b)
{
struct val_neg_zone* x = (struct val_neg_zone*)a;
struct val_neg_zone* y = (struct val_neg_zone*)b;
int m;
if(x->dclass != y->dclass) {
if(x->dclass < y->dclass)
return -1;
@ -67,8 +76,8 @@ struct val_neg_cache* val_neg_create()
log_err("Could not create neg cache: out of memory");
return NULL;
}
neg->max = 1024*1024; /* 1 M is about 5000(64bit)-10000(32) data */
rbtree_init(&neg->tree, &val_neg_compare);
neg->max = 1024*1024; /* 1 M is thousands of entries */
rbtree_init(&neg->tree, &val_neg_zone_compare);
lock_basic_init(&neg->lock);
lock_protect(&neg->lock, neg, sizeof(*neg));
return neg;
@ -94,7 +103,7 @@ void neg_cache_delete(struct val_neg_cache* neg)
struct val_neg_data* p, *np;
if(!neg) return;
lock_basic_destroy(&neg->lock);
/* delete all the elements */
/* delete all the zonedata elements */
p = neg->first;
while(p) {
np = p->next;
@ -102,17 +111,130 @@ void neg_cache_delete(struct val_neg_cache* neg)
free(p);
p = np;
}
/* delete all the zones in the tree */
/* TODO */
free(neg);
}
/**
* Create more space in negative cache
* The oldest elements are deleted until enough space is present.
* Empty zones are deleted.
* @param neg: negative cache.
* @param need: how many bytes are needed.
*/
static void neg_make_space(struct val_neg_cache* neg, size_t need)
{
/* delete elements until enough space or its empty */
while(neg->last && (neg->max - neg->use) < need) {
/* Delete data, zone */
/* update parent ptrs of items beneath it */
}
}
/**
* Find the given zone, from the SOA owner name and class
* @param neg: negative cache
* @param soa: what to look for.
* @return zone or NULL if not found.
*/
static struct val_neg_zone* neg_find_zone(struct val_neg_cache* neg,
struct ub_packed_rrset_key* soa)
{
struct val_neg_zone lookfor;
struct val_neg_zone* result;
lookfor.node.key = &lookfor;
lookfor.name = soa->rk.dname;
lookfor.len = soa->rk.dname_len;
lookfor.labs = dname_count_labels(lookfor.name);
lookfor.dclass = ntohs(soa->rk.rrset_class);
result = (struct val_neg_zone*)
rbtree_search(&neg->tree, lookfor.node.key);
return result;
}
/**
* Create a new zone.
* @param neg: negative cache
* @param soa: what to look for.
* @return zone or NULL if out of memory.
* Other data may be deleted to make room for the new zone.
*/
static struct val_neg_zone* neg_create_zone(struct val_neg_cache* neg,
struct ub_packed_rrset_key* soa)
{
struct val_neg_zone* zone;
size_t need;
/* make space */
need = sizeof(struct val_neg_zone) + soa->rk.dname_len;
neg_make_space(neg, need);
/* create new item */
zone = (struct val_neg_zone*)calloc(1, sizeof(*zone));
if(!zone) {
return NULL;
}
zone->node.key = zone;
zone->name = memdup(soa->rk.dname, soa->rk.dname_len);
if(!zone->name) {
return NULL;
}
zone->len = soa->rk.dname_len;
zone->labs = dname_count_labels(zone->name);
zone->dclass = ntohs(soa->rk.rrset_class);
zone->soa_hash = soa->entry.hash;
rbtree_init(&zone->tree, &val_neg_data_compare);
/* insert in tree */
(void)rbtree_insert(&neg->tree, &zone->node);
/* find zone->parent */
/* set this zone as parent for lower zones */
}
/** find zone name of message, returns the SOA record */
static struct ub_packed_rrset_key* reply_find_soa(struct reply_info* rep)
{
size_t i;
for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){
if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_SOA)
return rep->rrsets[i];
}
return NULL;
}
void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep)
{
size_t i;
struct ub_packed_rrset_key* soa;
struct val_neg_zone* zone;
/* find the zone name in message */
soa = reply_find_soa(rep);
if(!soa)
return;
/* find or create the zone entry */
lock_basic_lock(&neg->lock);
zone = neg_find_zone(neg, soa);
if(!zone) {
if(!(zone = neg_create_zone(neg, soa))) {
lock_basic_unlock(&neg->lock);
log_err("out of memory adding negative zone");
return;
}
}
/* insert the NSECs */
for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){
if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC)
continue;
/* insert the NSEC */
}
lock_basic_unlock(&neg->lock);
}
int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,

View file

@ -62,7 +62,7 @@ struct val_neg_cache {
* Because we use a rbtree for the data (quick lookup), we need
* a big lock */
lock_basic_t lock;
/** The data rbtree for NSEC. contents of type val_neg_data */
/** The zone rbtree. contents of type val_neg_zone */
rbtree_t tree;
/** the first and last in linked list of LRU of val_neg_data */
struct val_neg_data* first;
@ -74,6 +74,36 @@ struct val_neg_cache {
size_t max;
};
/**
* Per Zone aggressive negative caching data.
*/
struct val_neg_zone {
/** rbtree node element, key is this struct: the name */
rbnode_t node;
/** name; the key */
uint8_t* name;
/** length of name */
size_t len;
/** labels in name */
int labs;
/** pointer to parent zone in the negative cache */
struct val_neg_zone* parent;
/** type of zone ; NSEC */
/** hash of zonename, SOA type, class, for lookup of SOA rrset */
hashvalue_t soa_hash;
/** tree of NSEC data for this zone, sort by NSEC owner name */
rbtree_t tree;
/** the children that have NULL as a parent ptr */
struct val_neg_data* child_first, *child_last;
/** class of node; host order */
uint16_t dclass;
};
/**
* Data element for aggressive negative caching.
*/
@ -89,23 +119,22 @@ struct val_neg_data {
/** pointer to parent node in the negative cache */
struct val_neg_data* parent;
/** linked list of items that have this one as parent, children */
struct val_neg_data* child_first, *child_last;
/** next and previous siblings in the list of childprent with the
* same value for the parent pointer */
struct val_neg_data* sibling_next, *sibling_prev;
/** the zone that this denial is part of */
struct val_neg_zone* zone;
/** previous in LRU */
struct val_neg_data* prev;
/** next in LRU (next element was less recently used) */
struct val_neg_data* next;
/** reference to NSEC rrset (parent side of a zone cut) */
struct rrset_ref nsec_above;
/** reference to SOA record for zone of nsec_above */
struct rrset_ref soa_above;
/** reference to NSEC rrset (child side of a zone cut - or elsewhere) */
struct rrset_ref nsec_below;
/** reference to SOA record for zone of nsec_below */
struct rrset_ref soa_below;
/** class of node; host order */
uint16_t dclass;
/** hash of denial rrset: owner name, NSEC, class, for rrset lookup*/
hashvalue_t nsec_hash;
};
/**
@ -138,7 +167,12 @@ void neg_cache_delete(struct val_neg_cache* neg);
/**
* Comparison function for rbtree val neg data elements
*/
int val_neg_compare(const void* a, const void* b);
int val_neg_data_compare(const void* a, const void* b);
/**
* Comparison function for rbtree val neg zone elements
*/
int val_neg_zone_compare(const void* a, const void* b);
/**
* Insert NSECs from this message into the negative cache for reference.