mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-25 10:59:35 -05:00
add preliminary db support
This commit is contained in:
parent
2cd0c38115
commit
1ccbfca64a
5 changed files with 787 additions and 2 deletions
|
|
@ -12,10 +12,10 @@ CINCLUDES = -I${srcdir}/../isc/unix/include \
|
|||
CDEFINES =
|
||||
CWARNINGS =
|
||||
|
||||
OBJS = name.o rbt.o rdata.o rdatalist.o rdataset.o \
|
||||
OBJS = name.o db.o rbt.o rbtdb.o rdata.o rdatalist.o rdataset.o \
|
||||
result.o version.o rdataslab.o master.o
|
||||
|
||||
SUBDIRS = include
|
||||
SUBDIRS = includexo
|
||||
TARGETS = include/dns/enumtype.h include/dns/enumclass.h timestamp
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
|
|
|||
186
lib/dns/db.c
Normal file
186
lib/dns/db.c
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright (C) 1999 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
|
||||
#include "rbtdb.h"
|
||||
|
||||
dns_result_t
|
||||
dns_db_create(isc_mem_t *mctx, char *db_type, isc_boolean_t cache,
|
||||
dns_rdataclass_t class,
|
||||
unsigned int argc, char *argv[], dns_db_t **dbp)
|
||||
{
|
||||
/* find the create method for 'db_type', and call it. */
|
||||
|
||||
/* Temporary minor hack... */
|
||||
if (strcasecmp(db_type, "rbt") == 0)
|
||||
return (dns_rbtdb_create(mctx, cache, class, argc, argv,
|
||||
dbp));
|
||||
|
||||
return (DNS_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_attach(dns_db_t *source, dns_db_t **targetp) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(source));
|
||||
REQUIRE(targetp != NULL);
|
||||
|
||||
(source->methods->attach)(source, targetp);
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_detach(dns_db_t **dbp) {
|
||||
|
||||
REQUIRE(dbp != NULL);
|
||||
REQUIRE(DNS_DB_VALID(*dbp));
|
||||
|
||||
((*dbp)->methods->detach)(dbp);
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_shutdown(dns_db_t *db) {
|
||||
/*
|
||||
* db will go away when there are no open versions, no direct external
|
||||
* references, and no in-use nodes (i.e. indirect external references).
|
||||
*/
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
(db->methods->shutdown)(db);
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_destroy(dns_db_t **dbp) {
|
||||
|
||||
REQUIRE(dbp != NULL);
|
||||
REQUIRE(DNS_DB_VALID(*dbp));
|
||||
|
||||
((*dbp)->methods->shutdown)(*dbp);
|
||||
((*dbp)->methods->detach)(dbp);
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
dns_db_iscache(dns_db_t *db) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
return (db->cache);
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
dns_db_iszone(dns_db_t *db) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
return (!db->cache);
|
||||
}
|
||||
|
||||
/*
|
||||
* Version Operations.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
(db->methods->currentversion)(db, versionp);
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
return ((db->methods->newversion)(db, versionp));
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
(db->methods->closeversion)(db, versionp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Node Operations.
|
||||
*/
|
||||
|
||||
dns_result_t
|
||||
dns_db_findnode(dns_db_t *db, dns_name_t *name,
|
||||
isc_boolean_t create, dns_dbnode_t **nodep)
|
||||
{
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
return ((db->methods->findnode)(db, name, create, nodep));
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
(db->methods->attachnode)(db, source, targetp);
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
(db->methods->detachnode)(db, nodep);
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type, dns_rdataset_t *rdataset)
|
||||
{
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
return ((db->methods->findrdataset)(db, node, version, type,
|
||||
rdataset));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdataset_t *rdataset, dns_addmode_t mode)
|
||||
{
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
return ((db->methods->addrdataset)(db, node, version, rdataset, mode));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version, dns_rdatatype_t type)
|
||||
{
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
return ((db->methods->deleterdataset)(db, node, version, type));
|
||||
}
|
||||
|
||||
/* Need a node rdataset list iterator. */
|
||||
162
lib/dns/include/dns/db.h
Normal file
162
lib/dns/include/dns/db.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (C) 1999 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DNS_DB_H
|
||||
#define DNS_DB_H 1
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
||||
/*
|
||||
* DNS DB
|
||||
*
|
||||
* XXX Summary <TBS> XXX
|
||||
*
|
||||
* The dns_db_t type is like a "virtual class". To actually use
|
||||
* DBs, an implementation of the class is required.
|
||||
*
|
||||
* XXX <more> XXX
|
||||
*
|
||||
* MP:
|
||||
* Clients of this module must impose any required synchronization.
|
||||
*
|
||||
* Reliability:
|
||||
* No anticipated impact.
|
||||
*
|
||||
* Resources:
|
||||
* <TBS>
|
||||
*
|
||||
* Security:
|
||||
* No anticipated impact.
|
||||
*
|
||||
* Standards:
|
||||
* None.
|
||||
*/
|
||||
|
||||
#include <isc/boolean.h>
|
||||
#include <isc/mem.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
#include <dns/result.h>
|
||||
|
||||
typedef struct dns_dbmethods {
|
||||
void (*attach)(dns_db_t *source, dns_db_t **targetp);
|
||||
void (*detach)(dns_db_t **dbp);
|
||||
void (*shutdown)(dns_db_t *db);
|
||||
void (*currentversion)(dns_db_t *db,
|
||||
dns_dbversion_t **versionp);
|
||||
dns_result_t (*newversion)(dns_db_t *db,
|
||||
dns_dbversion_t **versionp);
|
||||
void (*closeversion)(dns_db_t *db,
|
||||
dns_dbversion_t **versionp);
|
||||
dns_result_t (*findnode)(dns_db_t *db, dns_name_t *name,
|
||||
isc_boolean_t create,
|
||||
dns_dbnode_t **nodep);
|
||||
void (*attachnode)(dns_db_t *db,
|
||||
dns_dbnode_t *source,
|
||||
dns_dbnode_t **targetp);
|
||||
void (*detachnode)(dns_db_t *db,
|
||||
dns_dbnode_t **targetp);
|
||||
dns_result_t (*findrdataset)(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version,
|
||||
dns_rdatatype_t type,
|
||||
dns_rdataset_t *rdataset);
|
||||
dns_result_t (*addrdataset)(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version,
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_addmode_t mode);
|
||||
dns_result_t (*deleterdataset)(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version,
|
||||
dns_rdatatype_t type);
|
||||
} dns_dbmethods_t;
|
||||
|
||||
#define DNS_DB_MAGIC 0x444E5344U /* DNSD. */
|
||||
#define DNS_DB_VALID(db) ((db) != NULL && \
|
||||
(db)->magic == DNS_DB_MAGIC)
|
||||
|
||||
/*
|
||||
* This structure is actually just the common prefix of a DNS db
|
||||
* implementation's version of a dns_db_t...
|
||||
*
|
||||
* Direct use of this structure by clients is forbidden. DB implementations
|
||||
* may change the structure. 'magic' must be DNS_DB_MAGIC for any of the
|
||||
* dns_db_ routines to work.
|
||||
*/
|
||||
struct dns_db {
|
||||
unsigned int magic;
|
||||
unsigned int impmagic;
|
||||
dns_dbmethods_t * methods;
|
||||
isc_boolean_t cache;
|
||||
dns_rdataclass_t class;
|
||||
};
|
||||
|
||||
dns_result_t
|
||||
dns_db_create(isc_mem_t *mctx, char *db_type, isc_boolean_t cache,
|
||||
dns_rdataclass_t class,
|
||||
unsigned int argc, char *argv[], dns_db_t **dbp);
|
||||
|
||||
void
|
||||
dns_db_attach(dns_db_t *source, dns_db_t **targetp);
|
||||
|
||||
void
|
||||
dns_db_detach(dns_db_t **dbp);
|
||||
|
||||
void
|
||||
dns_db_shutdown(dns_db_t *db);
|
||||
|
||||
void
|
||||
dns_db_destroy(dns_db_t **dbp);
|
||||
|
||||
isc_boolean_t
|
||||
dns_db_iscache(dns_db_t *db);
|
||||
|
||||
isc_boolean_t
|
||||
dns_db_iszone(dns_db_t *db);
|
||||
|
||||
void
|
||||
dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp);
|
||||
|
||||
dns_result_t
|
||||
dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp);
|
||||
|
||||
void
|
||||
dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp);
|
||||
|
||||
dns_result_t
|
||||
dns_db_findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
|
||||
dns_dbnode_t **nodep);
|
||||
|
||||
void
|
||||
dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp);
|
||||
|
||||
void
|
||||
dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep);
|
||||
|
||||
dns_result_t
|
||||
dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type, dns_rdataset_t *rdataset);
|
||||
|
||||
dns_result_t
|
||||
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdataset_t *rdataset, dns_addmode_t mode);
|
||||
|
||||
dns_result_t
|
||||
dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version, dns_rdatatype_t type);
|
||||
|
||||
#endif /* DNS_DB_H */
|
||||
401
lib/dns/rbtdb.c
Normal file
401
lib/dns/rbtdb.c
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
* Copyright (C) 1999 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/error.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/rwlock.h>
|
||||
|
||||
#include <dns/name.h>
|
||||
#include <dns/rbt.h>
|
||||
|
||||
#include "rbtdb.h"
|
||||
|
||||
/* Lame. Move util.h to <isc/util.h> */
|
||||
#include "../isc/util.h"
|
||||
|
||||
#define RBTDB_MAGIC 0x52424442U /* RBDB. */
|
||||
#define VALID_RBTDB(rbtdb) ((rbtdb) != NULL && \
|
||||
(rbtdb)->common.impmagic == \
|
||||
RBTDB_MAGIC)
|
||||
|
||||
#define DEFAULT_NODE_LOCK_COUNT 7
|
||||
|
||||
typedef struct {
|
||||
isc_mutex_t lock;
|
||||
unsigned int references;
|
||||
} node_lock;
|
||||
|
||||
typedef struct {
|
||||
/* Unlocked */
|
||||
dns_db_t common;
|
||||
isc_mem_t * mctx;
|
||||
isc_mutex_t lock;
|
||||
isc_rwlock_t tree_lock;
|
||||
unsigned int node_lock_count;
|
||||
node_lock * node_locks;
|
||||
/* Locked by lock */
|
||||
unsigned int references;
|
||||
isc_boolean_t shutting_down;
|
||||
/* Locked by tree_lock */
|
||||
dns_rbt_t * tree;
|
||||
} dns_rbtdb_t;
|
||||
|
||||
static void
|
||||
attach(dns_db_t *source, dns_db_t **targetp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)source;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
LOCK(&rbtdb->lock);
|
||||
REQUIRE(rbtdb->references > 0);
|
||||
rbtdb->references++;
|
||||
UNLOCK(&rbtdb->lock);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
static void
|
||||
free_rbtdb(dns_rbtdb_t *rbtdb) {
|
||||
unsigned int i;
|
||||
|
||||
if (rbtdb->tree != NULL)
|
||||
dns_rbt_destroy(&rbtdb->tree);
|
||||
for (i = 0; i < rbtdb->node_lock_count; i++)
|
||||
isc_mutex_destroy(&rbtdb->node_locks[i].lock);
|
||||
isc_mem_put(rbtdb->mctx, rbtdb->node_locks,
|
||||
rbtdb->node_lock_count * sizeof (node_lock));
|
||||
isc_rwlock_destroy(&rbtdb->tree_lock);
|
||||
isc_mutex_destroy(&rbtdb->lock);
|
||||
rbtdb->common.magic = 0;
|
||||
rbtdb->common.impmagic = 0;
|
||||
isc_mem_put(rbtdb->mctx, rbtdb, sizeof *rbtdb);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_free_rbtdb(dns_rbtdb_t *rbtdb) {
|
||||
isc_boolean_t want_free = ISC_TRUE;
|
||||
unsigned int i;
|
||||
|
||||
/* XXX check for open versions here */
|
||||
|
||||
/*
|
||||
* Even though there are no external direct references, there still
|
||||
* may be nodes in use.
|
||||
*/
|
||||
for (i = 0; i < rbtdb->node_lock_count; i++) {
|
||||
LOCK(&rbtdb->node_locks[i].lock);
|
||||
if (rbtdb->node_locks[i].references != 0)
|
||||
want_free = ISC_FALSE;
|
||||
UNLOCK(&rbtdb->node_locks[i].lock);
|
||||
}
|
||||
|
||||
if (want_free)
|
||||
free_rbtdb(rbtdb);
|
||||
}
|
||||
|
||||
static void
|
||||
detach(dns_db_t **dbp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(*dbp);
|
||||
isc_boolean_t maybe_free = ISC_FALSE;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
LOCK(&rbtdb->lock);
|
||||
REQUIRE(rbtdb->references > 0);
|
||||
rbtdb->references--;
|
||||
if (rbtdb->references == 0)
|
||||
maybe_free = ISC_TRUE;
|
||||
UNLOCK(&rbtdb->lock);
|
||||
|
||||
if (maybe_free)
|
||||
maybe_free_rbtdb(rbtdb);
|
||||
|
||||
dbp = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown(dns_db_t *db) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
LOCK(&rbtdb->lock);
|
||||
rbtdb->shutting_down = ISC_TRUE;
|
||||
UNLOCK(&rbtdb->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
REQUIRE(versionp != NULL && *versionp == NULL);
|
||||
|
||||
*versionp = NULL;
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
newversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
REQUIRE(versionp != NULL && *versionp == NULL);
|
||||
|
||||
return (DNS_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
static void
|
||||
closeversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
REQUIRE(versionp != NULL && *versionp != NULL);
|
||||
|
||||
*versionp = NULL;
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
|
||||
dns_dbnode_t **nodep) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
dns_rbtnode_t *node = NULL;
|
||||
dns_name_t foundname;
|
||||
unsigned int locknum;
|
||||
dns_result_t result;
|
||||
isc_rwlocktype_t locktype = isc_rwlocktype_read;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
dns_name_init(&foundname, NULL);
|
||||
RWLOCK(&rbtdb->tree_lock, locktype);
|
||||
node = dns_rbt_findnode(rbtdb->tree, name);
|
||||
again:
|
||||
if (node != NULL) {
|
||||
dns_rbt_namefromnode(node, &foundname);
|
||||
locknum = dns_name_hash(&foundname) % rbtdb->node_lock_count;
|
||||
LOCK(&rbtdb->node_locks[locknum].lock);
|
||||
if (node->references == 0)
|
||||
rbtdb->node_locks[locknum].references++;
|
||||
node->references++;
|
||||
UNLOCK(&rbtdb->node_locks[locknum].lock);
|
||||
} else {
|
||||
RWUNLOCK(&rbtdb->tree_lock, locktype);
|
||||
if (!create)
|
||||
return (DNS_R_NOTFOUND);
|
||||
locktype = isc_rwlocktype_write;
|
||||
/*
|
||||
* It would be nice to try to upgrade the lock instead of
|
||||
* unlocking then relocking.
|
||||
*/
|
||||
RWLOCK(&rbtdb->tree_lock, locktype);
|
||||
/* XXX rework once we have dns_rbt_addnode() */
|
||||
result = dns_rbt_addname(rbtdb->tree, name, NULL);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
RWUNLOCK(&rbtdb->tree_lock, locktype);
|
||||
return (result);
|
||||
}
|
||||
node = dns_rbt_findnode(rbtdb->tree, name);
|
||||
INSIST(node != NULL);
|
||||
goto again;
|
||||
}
|
||||
RWUNLOCK(&rbtdb->tree_lock, locktype);
|
||||
|
||||
*nodep = (dns_dbnode_t *)node;
|
||||
|
||||
return (DNS_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
dns_rbtnode_t *node = (dns_rbtnode_t *)source;
|
||||
unsigned int locknum;
|
||||
dns_name_t name;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
dns_name_init(&name, NULL);
|
||||
dns_rbt_namefromnode(node, &name);
|
||||
locknum = dns_name_hash(&name) % rbtdb->node_lock_count;
|
||||
LOCK(&rbtdb->node_locks[locknum].lock);
|
||||
INSIST(node->references != 0);
|
||||
node->references++;
|
||||
UNLOCK(&rbtdb->node_locks[locknum].lock);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
static void
|
||||
detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
dns_rbtnode_t *node;
|
||||
unsigned int locknum;
|
||||
dns_name_t name;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
REQUIRE(targetp != NULL && *targetp != NULL);
|
||||
|
||||
node = (dns_rbtnode_t *)(*targetp);
|
||||
dns_name_init(&name, NULL);
|
||||
dns_rbt_namefromnode(node, &name);
|
||||
locknum = dns_name_hash(&name) % rbtdb->node_lock_count;
|
||||
LOCK(&rbtdb->node_locks[locknum].lock);
|
||||
INSIST(node->references > 0);
|
||||
node->references--;
|
||||
if (node->references == 0) {
|
||||
INSIST(rbtdb->node_locks[locknum].references > 0);
|
||||
rbtdb->node_locks[locknum].references--;
|
||||
/* XXX other detach stuff here */
|
||||
}
|
||||
UNLOCK(&rbtdb->node_locks[locknum].lock);
|
||||
|
||||
*targetp = NULL;
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type, dns_rdataset_t *rdataset) {
|
||||
db = NULL;
|
||||
node = NULL;
|
||||
version = NULL;
|
||||
type = 0;
|
||||
rdataset = NULL;
|
||||
return (DNS_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdataset_t *rdataset, dns_addmode_t mode) {
|
||||
db = NULL;
|
||||
node = NULL;
|
||||
version = NULL;
|
||||
rdataset = NULL;
|
||||
mode = dns_addmode_replace;
|
||||
return (DNS_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type) {
|
||||
db = NULL;
|
||||
node = NULL;
|
||||
version = NULL;
|
||||
type = 0;
|
||||
return (DNS_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
static dns_dbmethods_t methods = {
|
||||
attach,
|
||||
detach,
|
||||
shutdown,
|
||||
currentversion,
|
||||
newversion,
|
||||
closeversion,
|
||||
findnode,
|
||||
attachnode,
|
||||
detachnode,
|
||||
findrdataset,
|
||||
addrdataset,
|
||||
deleterdataset
|
||||
};
|
||||
|
||||
dns_result_t
|
||||
dns_rbtdb_create(isc_mem_t *mctx, isc_boolean_t cache,
|
||||
dns_rdataclass_t class, unsigned int argc, char *argv[],
|
||||
dns_db_t **dbp)
|
||||
{
|
||||
dns_rbtdb_t *rbtdb;
|
||||
isc_result_t iresult;
|
||||
dns_result_t dresult;
|
||||
int i;
|
||||
|
||||
rbtdb = isc_mem_get(mctx, sizeof *rbtdb);
|
||||
if (rbtdb == NULL)
|
||||
return (DNS_R_NOMEMORY);
|
||||
memset(rbtdb, '\0', sizeof *rbtdb);
|
||||
rbtdb->common.methods = &methods;
|
||||
rbtdb->common.cache = cache;
|
||||
rbtdb->common.class = class;
|
||||
rbtdb->mctx = mctx;
|
||||
|
||||
iresult = isc_mutex_init(&rbtdb->lock);
|
||||
if (iresult != ISC_R_SUCCESS) {
|
||||
isc_mem_put(rbtdb->mctx, rbtdb, sizeof *rbtdb);
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_mutex_init() failed: %s",
|
||||
isc_result_totext(iresult));
|
||||
return (DNS_R_UNEXPECTED);
|
||||
}
|
||||
|
||||
iresult = isc_rwlock_init(&rbtdb->tree_lock, 0, 0);
|
||||
if (iresult != ISC_R_SUCCESS) {
|
||||
isc_mutex_destroy(&rbtdb->lock);
|
||||
isc_mem_put(rbtdb->mctx, rbtdb, sizeof *rbtdb);
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_rwlock_init() failed: %s",
|
||||
isc_result_totext(iresult));
|
||||
return (DNS_R_UNEXPECTED);
|
||||
}
|
||||
|
||||
if (rbtdb->node_lock_count == 0)
|
||||
rbtdb->node_lock_count = DEFAULT_NODE_LOCK_COUNT;
|
||||
rbtdb->node_locks = isc_mem_get(mctx, rbtdb->node_lock_count *
|
||||
sizeof (node_lock));
|
||||
for (i = 0; i < (int)(rbtdb->node_lock_count); i++) {
|
||||
iresult = isc_mutex_init(&rbtdb->node_locks[i].lock);
|
||||
if (iresult != ISC_R_SUCCESS) {
|
||||
i--;
|
||||
while (i >= 0) {
|
||||
isc_mutex_destroy(&rbtdb->node_locks[i].lock);
|
||||
i--;
|
||||
}
|
||||
isc_mem_put(mctx, rbtdb->node_locks,
|
||||
rbtdb->node_lock_count *
|
||||
sizeof (node_lock));
|
||||
isc_rwlock_destroy(&rbtdb->tree_lock);
|
||||
isc_mutex_destroy(&rbtdb->lock);
|
||||
isc_mem_put(rbtdb->mctx, rbtdb, sizeof *rbtdb);
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_mutex_init() failed: %s",
|
||||
isc_result_totext(iresult));
|
||||
return (DNS_R_UNEXPECTED);
|
||||
}
|
||||
rbtdb->node_locks[i].references = 0;
|
||||
}
|
||||
|
||||
dresult = dns_rbt_create(mctx, &rbtdb->tree);
|
||||
if (dresult != DNS_R_SUCCESS) {
|
||||
free_rbtdb(rbtdb);
|
||||
return (dresult);
|
||||
}
|
||||
|
||||
rbtdb->shutting_down = ISC_FALSE;
|
||||
rbtdb->references = 1;
|
||||
|
||||
/* XXX Version init here */
|
||||
|
||||
rbtdb->common.magic = DNS_DB_MAGIC;
|
||||
rbtdb->common.impmagic = RBTDB_MAGIC;
|
||||
|
||||
*dbp = (dns_db_t *)rbtdb;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
36
lib/dns/rbtdb.h
Normal file
36
lib/dns/rbtdb.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 1999 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DNS_RBTDB_H
|
||||
#define DNS_RBTDB_H 1
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
||||
/*
|
||||
* DNS Red-Black Tree DB Implementation
|
||||
*/
|
||||
|
||||
#include <dns/db.h>
|
||||
|
||||
dns_result_t
|
||||
dns_rbtdb_create(isc_mem_t *mctx, isc_boolean_t is_cache,
|
||||
dns_rdataclass_t class, unsigned int argc, char *argv[],
|
||||
dns_db_t **dbp);
|
||||
|
||||
#endif /* DNS_RBTDB_H */
|
||||
Loading…
Reference in a new issue