From 1ccbfca64ae86ace521053773001cb995352f96f Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Thu, 28 Jan 1999 23:53:03 +0000 Subject: [PATCH] add preliminary db support --- lib/dns/Makefile.in | 4 +- lib/dns/db.c | 186 ++++++++++++++++++ lib/dns/include/dns/db.h | 162 ++++++++++++++++ lib/dns/rbtdb.c | 401 +++++++++++++++++++++++++++++++++++++++ lib/dns/rbtdb.h | 36 ++++ 5 files changed, 787 insertions(+), 2 deletions(-) create mode 100644 lib/dns/db.c create mode 100644 lib/dns/include/dns/db.h create mode 100644 lib/dns/rbtdb.c create mode 100644 lib/dns/rbtdb.h diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index a2b1d0f7c4..2120ca19d1 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -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@ diff --git a/lib/dns/db.c b/lib/dns/db.c new file mode 100644 index 0000000000..847cd03def --- /dev/null +++ b/lib/dns/db.c @@ -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 + +#include +#include + +#include + +#include + +#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. */ diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h new file mode 100644 index 0000000000..569732a4d3 --- /dev/null +++ b/lib/dns/include/dns/db.h @@ -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 XXX + * + * The dns_db_t type is like a "virtual class". To actually use + * DBs, an implementation of the class is required. + * + * XXX XXX + * + * MP: + * Clients of this module must impose any required synchronization. + * + * Reliability: + * No anticipated impact. + * + * Resources: + * + * + * Security: + * No anticipated impact. + * + * Standards: + * None. + */ + +#include +#include + +#include +#include + +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 */ diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c new file mode 100644 index 0000000000..31ebc99d32 --- /dev/null +++ b/lib/dns/rbtdb.c @@ -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 +#include + +#include +#include +#include +#include + +#include +#include + +#include "rbtdb.h" + +/* Lame. Move util.h to */ +#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); +} diff --git a/lib/dns/rbtdb.h b/lib/dns/rbtdb.h new file mode 100644 index 0000000000..b0d64dbdb3 --- /dev/null +++ b/lib/dns/rbtdb.h @@ -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_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 */