mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 22:45:39 +00:00
store node lock number; rdataset methods; find and add rdatasets
This commit is contained in:
212
lib/dns/rbtdb.c
212
lib/dns/rbtdb.c
@@ -27,6 +27,7 @@
|
|||||||
#include <dns/rbt.h>
|
#include <dns/rbt.h>
|
||||||
#include <dns/master.h>
|
#include <dns/master.h>
|
||||||
#include <dns/rdataslab.h>
|
#include <dns/rdataslab.h>
|
||||||
|
#include <dns/rdata.h>
|
||||||
|
|
||||||
#include "rbtdb.h"
|
#include "rbtdb.h"
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ typedef struct rdatasetheader {
|
|||||||
* both head and tail pointers. We only have a head pointer in
|
* both head and tail pointers. We only have a head pointer in
|
||||||
* the node to save space.
|
* the node to save space.
|
||||||
*/
|
*/
|
||||||
|
unsigned int version;
|
||||||
struct rdatasetheader *prev;
|
struct rdatasetheader *prev;
|
||||||
struct rdatasetheader *next;
|
struct rdatasetheader *next;
|
||||||
} rdatasetheader_t;
|
} rdatasetheader_t;
|
||||||
@@ -71,6 +73,22 @@ typedef struct {
|
|||||||
dns_rbt_t * tree;
|
dns_rbt_t * tree;
|
||||||
} dns_rbtdb_t;
|
} dns_rbtdb_t;
|
||||||
|
|
||||||
|
static dns_result_t disassociate(dns_rdataset_t *rdatasetp);
|
||||||
|
static dns_result_t first(dns_rdataset_t *rdataset);
|
||||||
|
static dns_result_t next(dns_rdataset_t *rdataset);
|
||||||
|
static void current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
|
||||||
|
|
||||||
|
static dns_rdatasetmethods_t rdataset_methods = {
|
||||||
|
disassociate,
|
||||||
|
first,
|
||||||
|
next,
|
||||||
|
current
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DB Routines
|
||||||
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
attach(dns_db_t *source, dns_db_t **targetp) {
|
attach(dns_db_t *source, dns_db_t **targetp) {
|
||||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)source;
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)source;
|
||||||
@@ -207,8 +225,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
|
|||||||
node = dns_rbt_findnode(rbtdb->tree, name);
|
node = dns_rbt_findnode(rbtdb->tree, name);
|
||||||
again:
|
again:
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
dns_rbt_namefromnode(node, &foundname);
|
locknum = node->locknum;
|
||||||
locknum = dns_name_hash(&foundname) % rbtdb->node_lock_count;
|
|
||||||
LOCK(&rbtdb->node_locks[locknum].lock);
|
LOCK(&rbtdb->node_locks[locknum].lock);
|
||||||
if (node->references == 0)
|
if (node->references == 0)
|
||||||
rbtdb->node_locks[locknum].references++;
|
rbtdb->node_locks[locknum].references++;
|
||||||
@@ -232,6 +249,11 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
|
|||||||
}
|
}
|
||||||
node = dns_rbt_findnode(rbtdb->tree, name);
|
node = dns_rbt_findnode(rbtdb->tree, name);
|
||||||
INSIST(node != NULL);
|
INSIST(node != NULL);
|
||||||
|
node->dirty = 0;
|
||||||
|
node->references = 0;
|
||||||
|
dns_rbt_namefromnode(node, &foundname);
|
||||||
|
node->locknum = dns_name_hash(&foundname) %
|
||||||
|
rbtdb->node_lock_count;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
RWUNLOCK(&rbtdb->tree_lock, locktype);
|
RWUNLOCK(&rbtdb->tree_lock, locktype);
|
||||||
@@ -245,18 +267,14 @@ static void
|
|||||||
attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
|
attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
|
||||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
dns_rbtnode_t *node = (dns_rbtnode_t *)source;
|
dns_rbtnode_t *node = (dns_rbtnode_t *)source;
|
||||||
unsigned int locknum;
|
|
||||||
dns_name_t name;
|
|
||||||
|
|
||||||
REQUIRE(VALID_RBTDB(rbtdb));
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
|
||||||
dns_name_init(&name, NULL);
|
LOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||||
dns_rbt_namefromnode(node, &name);
|
INSIST(node->references > 0);
|
||||||
locknum = dns_name_hash(&name) % rbtdb->node_lock_count;
|
|
||||||
LOCK(&rbtdb->node_locks[locknum].lock);
|
|
||||||
INSIST(node->references != 0);
|
|
||||||
node->references++;
|
node->references++;
|
||||||
UNLOCK(&rbtdb->node_locks[locknum].lock);
|
INSIST(node->references != 0); /* Catch overflow. */
|
||||||
|
UNLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||||
|
|
||||||
*targetp = source;
|
*targetp = source;
|
||||||
}
|
}
|
||||||
@@ -265,38 +283,81 @@ static void
|
|||||||
detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
|
detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
|
||||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
dns_rbtnode_t *node;
|
dns_rbtnode_t *node;
|
||||||
unsigned int locknum;
|
|
||||||
dns_name_t name;
|
|
||||||
|
|
||||||
REQUIRE(VALID_RBTDB(rbtdb));
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
REQUIRE(targetp != NULL && *targetp != NULL);
|
REQUIRE(targetp != NULL && *targetp != NULL);
|
||||||
|
|
||||||
node = (dns_rbtnode_t *)(*targetp);
|
node = (dns_rbtnode_t *)(*targetp);
|
||||||
dns_name_init(&name, NULL);
|
LOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||||
dns_rbt_namefromnode(node, &name);
|
|
||||||
locknum = dns_name_hash(&name) % rbtdb->node_lock_count;
|
|
||||||
LOCK(&rbtdb->node_locks[locknum].lock);
|
|
||||||
INSIST(node->references > 0);
|
INSIST(node->references > 0);
|
||||||
node->references--;
|
node->references--;
|
||||||
if (node->references == 0) {
|
if (node->references == 0) {
|
||||||
INSIST(rbtdb->node_locks[locknum].references > 0);
|
INSIST(rbtdb->node_locks[node->locknum].references > 0);
|
||||||
rbtdb->node_locks[locknum].references--;
|
rbtdb->node_locks[node->locknum].references--;
|
||||||
/* XXX other detach stuff here */
|
/* XXX other detach stuff here */
|
||||||
}
|
}
|
||||||
UNLOCK(&rbtdb->node_locks[locknum].lock);
|
UNLOCK(&rbtdb->node_locks[node->locknum].lock);
|
||||||
|
|
||||||
*targetp = NULL;
|
*targetp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dns_result_t
|
static dns_result_t
|
||||||
findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||||
dns_rdatatype_t type, dns_rdataset_t *rdataset) {
|
dns_rdatatype_t type, dns_rdataset_t *rdataset)
|
||||||
db = NULL;
|
{
|
||||||
node = NULL;
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
version = NULL;
|
dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
|
||||||
type = 0;
|
rdatasetheader_t *header;
|
||||||
rdataset = NULL;
|
unsigned char *raw;
|
||||||
return (DNS_R_NOTIMPLEMENTED);
|
unsigned int count;
|
||||||
|
|
||||||
|
(void)version;
|
||||||
|
|
||||||
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||||
|
REQUIRE(rdataset->methods == NULL);
|
||||||
|
|
||||||
|
LOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||||
|
for (header = rbtnode->data; header != NULL; header = header->next) {
|
||||||
|
/* XXX version */
|
||||||
|
if (header->type == type)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (header != NULL) {
|
||||||
|
INSIST(rbtnode->references > 0);
|
||||||
|
rbtnode->references++;
|
||||||
|
INSIST(rbtnode->references != 0); /* Catch overflow. */
|
||||||
|
|
||||||
|
rdataset->methods = &rdataset_methods;
|
||||||
|
rdataset->class = rbtdb->common.class;
|
||||||
|
rdataset->type = header->type;
|
||||||
|
rdataset->ttl = header->ttl;
|
||||||
|
rdataset->private1 = rbtdb;
|
||||||
|
rdataset->private2 = rbtnode;
|
||||||
|
raw = (unsigned char *)header + sizeof *header;
|
||||||
|
rdataset->private3 = raw;
|
||||||
|
count = raw[0] * 256 + raw[1];
|
||||||
|
raw += 2;
|
||||||
|
if (count == 0) {
|
||||||
|
rdataset->private4 = (void *)0;
|
||||||
|
rdataset->private5 = NULL;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The private4 field is the number of rdata beyond
|
||||||
|
* the cursor position, so we decrement the total
|
||||||
|
* count by one before storing it.
|
||||||
|
*/
|
||||||
|
count--;
|
||||||
|
rdataset->private4 = (void *)count;
|
||||||
|
rdataset->private5 = raw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||||
|
|
||||||
|
if (header == NULL)
|
||||||
|
return (DNS_R_NOTFOUND);
|
||||||
|
|
||||||
|
return (DNS_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dns_result_t
|
static dns_result_t
|
||||||
@@ -304,10 +365,14 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
dns_rdataset_t *rdataset, dns_addmode_t mode)
|
dns_rdataset_t *rdataset, dns_addmode_t mode)
|
||||||
{
|
{
|
||||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
|
dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
|
||||||
isc_region_t region;
|
isc_region_t region;
|
||||||
rdatasetheader_t *header;
|
rdatasetheader_t *header, *newheader;
|
||||||
dns_result_t result;
|
dns_result_t result;
|
||||||
|
|
||||||
|
(void)version;
|
||||||
|
(void)mode;
|
||||||
|
|
||||||
REQUIRE(VALID_RBTDB(rbtdb));
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||||||
@@ -315,10 +380,19 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
sizeof (rdatasetheader_t));
|
sizeof (rdatasetheader_t));
|
||||||
if (result != DNS_R_SUCCESS)
|
if (result != DNS_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
header = (rdatasetheader_t *)region.base;
|
newheader = (rdatasetheader_t *)region.base;
|
||||||
header->ttl = rdataset->ttl;
|
newheader->ttl = rdataset->ttl;
|
||||||
header->type = rdataset->type;
|
newheader->type = rdataset->type;
|
||||||
/* XXX Lock node, add to list */
|
newheader->version = 0; /* XXX version */
|
||||||
|
newheader->prev = NULL;
|
||||||
|
|
||||||
|
LOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||||
|
header = rbtnode->data;
|
||||||
|
newheader->next = header;
|
||||||
|
if (header != NULL)
|
||||||
|
header->prev = newheader;
|
||||||
|
rbtnode->data = newheader;
|
||||||
|
UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||||
|
|
||||||
return (DNS_R_SUCCESS);
|
return (DNS_R_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -390,6 +464,9 @@ dns_rbtdb_create(isc_mem_t *mctx, dns_name_t *base, isc_boolean_t cache,
|
|||||||
int i;
|
int i;
|
||||||
isc_region_t r1, r2;
|
isc_region_t r1, r2;
|
||||||
|
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
rbtdb = isc_mem_get(mctx, sizeof *rbtdb);
|
rbtdb = isc_mem_get(mctx, sizeof *rbtdb);
|
||||||
if (rbtdb == NULL)
|
if (rbtdb == NULL)
|
||||||
return (DNS_R_NOMEMORY);
|
return (DNS_R_NOMEMORY);
|
||||||
@@ -418,6 +495,8 @@ dns_rbtdb_create(isc_mem_t *mctx, dns_name_t *base, isc_boolean_t cache,
|
|||||||
return (DNS_R_UNEXPECTED);
|
return (DNS_R_UNEXPECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INSIST(rbtdb->node_lock_count < (1 << DNS_RBT_LOCKLENGTH));
|
||||||
|
|
||||||
if (rbtdb->node_lock_count == 0)
|
if (rbtdb->node_lock_count == 0)
|
||||||
rbtdb->node_lock_count = DEFAULT_NODE_LOCK_COUNT;
|
rbtdb->node_lock_count = DEFAULT_NODE_LOCK_COUNT;
|
||||||
rbtdb->node_locks = isc_mem_get(mctx, rbtdb->node_lock_count *
|
rbtdb->node_locks = isc_mem_get(mctx, rbtdb->node_lock_count *
|
||||||
@@ -479,3 +558,74 @@ dns_rbtdb_create(isc_mem_t *mctx, dns_name_t *base, isc_boolean_t cache,
|
|||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slabbed Rdataset Methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
static dns_result_t
|
||||||
|
disassociate(dns_rdataset_t *rdataset) {
|
||||||
|
dns_db_t *db = rdataset->private1;
|
||||||
|
dns_dbnode_t *node = rdataset->private2;
|
||||||
|
|
||||||
|
detachnode(db, &node);
|
||||||
|
|
||||||
|
return (DNS_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static dns_result_t
|
||||||
|
first(dns_rdataset_t *rdataset) {
|
||||||
|
unsigned char *raw = rdataset->private3;
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
count = raw[0] * 256 + raw[1];
|
||||||
|
if (count == 0) {
|
||||||
|
rdataset->private5 = NULL;
|
||||||
|
return (DNS_R_NOMORE);
|
||||||
|
}
|
||||||
|
raw += 2;
|
||||||
|
/*
|
||||||
|
* The private4 field is the number of rdata beyond the cursor
|
||||||
|
* position, so we decrement the total count by one before storing
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
|
count--;
|
||||||
|
rdataset->private4 = (void *)count;
|
||||||
|
rdataset->private5 = raw;
|
||||||
|
|
||||||
|
return (DNS_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static dns_result_t
|
||||||
|
next(dns_rdataset_t *rdataset) {
|
||||||
|
unsigned int count;
|
||||||
|
unsigned int length;
|
||||||
|
unsigned char *raw;
|
||||||
|
|
||||||
|
count = (unsigned int)rdataset->private4;
|
||||||
|
if (count == 0)
|
||||||
|
return (DNS_R_NOMORE);
|
||||||
|
count--;
|
||||||
|
rdataset->private4 = (void *)count;
|
||||||
|
raw = rdataset->private5;
|
||||||
|
length = raw[0] * 256 + raw[1];
|
||||||
|
raw += length + 2;
|
||||||
|
rdataset->private5 = raw;
|
||||||
|
|
||||||
|
return (DNS_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
|
||||||
|
unsigned char *raw = rdataset->private5;
|
||||||
|
isc_region_t r;
|
||||||
|
|
||||||
|
REQUIRE(raw != NULL);
|
||||||
|
|
||||||
|
r.length = raw[0] * 256 + raw[1];
|
||||||
|
raw += 2;
|
||||||
|
r.base = raw;
|
||||||
|
dns_rdata_fromregion(rdata, rdataset->class, rdataset->type, &r);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user