From c1737c417d1247ad95b7022324ca445b610873ec Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Sat, 17 Apr 1999 01:36:42 +0000 Subject: [PATCH] db iterator support --- lib/dns/rbtdb.c | 227 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 163 insertions(+), 64 deletions(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 8ebacf08ed..1008a3382b 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -217,10 +217,12 @@ typedef struct rbtdb_dbiterator { dns_dbiterator_t common; isc_boolean_t paused; isc_boolean_t new_origin; - isc_boolean_t done; + isc_boolean_t tree_locked; + dns_result_t result; dns_fixedname_t name; dns_fixedname_t origin; dns_rbtnode_t *node; + dns_rbtnodechain_t chain; } rbtdb_dbiterator_t; @@ -1950,19 +1952,33 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { } static dns_result_t -createiterator(dns_db_t *db, dns_dbversion_t *version, - isc_boolean_t relative_names, dns_dbiterator_t **iteratorp) +createiterator(dns_db_t *db, isc_boolean_t relative_names, + dns_dbiterator_t **iteratorp) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - rbtdb_version_t *rbtversion = version; + rbtdb_dbiterator_t *rbtdbiter; REQUIRE(VALID_RBTDB(rbtdb)); - REQUIRE(rbtversion == NULL || !rbtversion->writer); - (void)relative_names; - (void)iteratorp; + rbtdbiter = isc_mem_get(rbtdb->common.mctx, sizeof *rbtdbiter); + if (rbtdbiter == NULL) + return (DNS_R_NOMEMORY); - return (DNS_R_NOTIMPLEMENTED); + rbtdbiter->common.methods = &dbiterator_methods; + dns_db_attach(db, &rbtdbiter->common.db); + rbtdbiter->common.relative_names = relative_names; + rbtdbiter->common.magic = DNS_DBITERATOR_MAGIC; + rbtdbiter->paused = ISC_FALSE; + rbtdbiter->tree_locked = ISC_FALSE; + rbtdbiter->result = DNS_R_SUCCESS; + dns_fixedname_init(&rbtdbiter->name); + dns_fixedname_init(&rbtdbiter->origin); + rbtdbiter->node = NULL; + dns_rbtnodechain_init(&rbtdbiter->chain, db->mctx); + + *iteratorp = (dns_dbiterator_t *)rbtdbiter; + + return (DNS_R_SUCCESS); } static dns_result_t @@ -2820,6 +2836,14 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) { LOCK(&rbtdb->node_locks[rbtnode->locknum].lock); + /* + * XXX FIX ME!!!! Someone might have added a new record of + * this type above us, and our next pointer won't be valid. + * What we should do is have our next pointer point up to our + * parent, and we should just skip any records whose type is the + * same as ours. + */ + for (header = header->next; header != NULL; header = top_next) { top_next = header->next; do { @@ -2873,58 +2897,123 @@ rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { * Database Iterator Methods */ -static inline dns_result_t -resume_iteration(rbtdb_dbiterator_t *rbtiterator) { - return (DNS_R_NOTIMPLEMENTED); -} +static inline void +unpause(rbtdb_dbiterator_t *rbtdbiter) { + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db; + dns_rbtnode_t *node = rbtdbiter->node; -static void -dbiterator_destroy(dns_dbiterator_t **iteratorp) { - - *iteratorp = NULL; -} - -static dns_result_t -dbiterator_first(dns_dbiterator_t *iterator) { - dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db; - rbtdb_dbiterator_t *rbtiterator = (rbtdb_dbiterator_t *)iterator; - dns_name_t *name = dns_fixedname_name(&rbtiterator->name); - dns_rbtnode_t *node = rbtiterator->node; - dns_result_t result; - - if (rbtiterator->paused) { - /* XXX what if not parked? */ + if (rbtdbiter->paused) { LOCK(&rbtdb->node_locks[node->locknum].lock); INSIST(node->references > 0); node->references--; if (node->references == 0) no_references(rbtdb, node, 0); UNLOCK(&rbtdb->node_locks[node->locknum].lock); - } else - RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); + rbtdbiter->paused = ISC_FALSE; + } +} - result = dns_name_concatenate(&rbtdb->common.origin, NULL, name, NULL); - if (result != DNS_R_SUCCESS) - return (result); - return (resume_iteration(rbtiterator)); +static inline void +resume_iteration(rbtdb_dbiterator_t *rbtdbiter) { + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db; + + REQUIRE(rbtdbiter->paused); + REQUIRE(!rbtdbiter->tree_locked); + + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + rbtdbiter->tree_locked = ISC_TRUE; + + unpause(rbtdbiter); +} + +static void +dbiterator_destroy(dns_dbiterator_t **iteratorp) { + rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)(*iteratorp); + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db; + + if (rbtdbiter->tree_locked) + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + + unpause(rbtdbiter); + + dns_db_detach(&rbtdbiter->common.db); + + dns_rbtnodechain_reset(&rbtdbiter->chain); + isc_mem_put(rbtdb->common.mctx, rbtdbiter, sizeof *rbtdbiter); + + *iteratorp = NULL; +} + +static dns_result_t +dbiterator_first(dns_dbiterator_t *iterator) { + dns_result_t result; + rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator; + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db; + dns_name_t *name, *origin; + + if (rbtdbiter->result != DNS_R_SUCCESS) + return (rbtdbiter->result); + + unpause(rbtdbiter); + + if (!rbtdbiter->tree_locked) { + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + rbtdbiter->tree_locked = ISC_TRUE; + } + + name = dns_fixedname_name(&rbtdbiter->name); + origin = dns_fixedname_name(&rbtdbiter->origin); + dns_rbtnodechain_reset(&rbtdbiter->chain); + result = dns_rbtnodechain_first(&rbtdbiter->chain, rbtdb->tree, name, + origin); + if (result != DNS_R_NEWORIGIN) { + INSIST(result != DNS_R_SUCCESS); + rbtdbiter->result = result; + rbtdbiter->node = NULL; + } else { + result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL, + NULL, &rbtdbiter->node); + if (result == DNS_R_SUCCESS) + rbtdbiter->new_origin = ISC_TRUE; + else { + rbtdbiter->result = result; + rbtdbiter->node = NULL; + } + } + + return (result); } static dns_result_t dbiterator_next(dns_dbiterator_t *iterator) { - rbtdb_dbiterator_t *rbtiterator = (rbtdb_dbiterator_t *)iterator; dns_result_t result; + rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator; + dns_name_t *name, *origin; - if (rbtiterator->done) - return (DNS_R_NOMORE); + REQUIRE(rbtdbiter->node != NULL); - if (rbtiterator->paused) { - result = resume_iteration(rbtiterator); - if (result != DNS_R_SUCCESS) - return (result); - } + if (rbtdbiter->result != DNS_R_SUCCESS) + return (rbtdbiter->result); - /* XXX move to next node */ - result = DNS_R_SUCCESS; + if (rbtdbiter->paused) + resume_iteration(rbtdbiter); + + name = dns_fixedname_name(&rbtdbiter->name); + origin = dns_fixedname_name(&rbtdbiter->origin); + result = dns_rbtnodechain_next(&rbtdbiter->chain, name, origin); + if (result == DNS_R_NEWORIGIN || result == DNS_R_SUCCESS) { + if (result == DNS_R_NEWORIGIN) + rbtdbiter->new_origin = ISC_TRUE; + else + rbtdbiter->new_origin = ISC_FALSE; + result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL, + NULL, &rbtdbiter->node); + if (result != DNS_R_SUCCESS) { + rbtdbiter->result = result; + rbtdbiter->node = NULL; + } + } else + rbtdbiter->result = result; return (result); } @@ -2934,21 +3023,21 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, dns_name_t *name) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db; - rbtdb_dbiterator_t *rbtiterator = (rbtdb_dbiterator_t *)iterator; - dns_rbtnode_t *node = rbtiterator->node; + rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator; + dns_rbtnode_t *node = rbtdbiter->node; dns_result_t result; - dns_name_t *nodename = dns_fixedname_name(&rbtiterator->name); - dns_name_t *origin = dns_fixedname_name(&rbtiterator->origin); + dns_name_t *nodename = dns_fixedname_name(&rbtdbiter->name); + dns_name_t *origin = dns_fixedname_name(&rbtdbiter->origin); - REQUIRE(!rbtiterator->done); + REQUIRE(rbtdbiter->result == DNS_R_SUCCESS); + REQUIRE(rbtdbiter->node != NULL); - if (rbtiterator->paused) { - result = resume_iteration(rbtiterator); - if (result != DNS_R_SUCCESS) - return (result); - } + if (rbtdbiter->paused) + resume_iteration(rbtdbiter); if (name != NULL) { + if (rbtdbiter->common.relative_names) + origin = NULL; result = dns_name_concatenate(nodename, origin, name, NULL); if (result != DNS_R_SUCCESS) return (result); @@ -2958,9 +3047,9 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, new_reference(rbtdb, node); UNLOCK(&rbtdb->node_locks[node->locknum].lock); - *nodep = rbtiterator->node; + *nodep = rbtdbiter->node; - if (rbtiterator->new_origin) + if (rbtdbiter->new_origin) return (DNS_R_NEWORIGIN); return (DNS_R_SUCCESS); } @@ -2968,25 +3057,35 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, static dns_result_t dbiterator_pause(dns_dbiterator_t *iterator) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db; - rbtdb_dbiterator_t *rbtiterator = (rbtdb_dbiterator_t *)iterator; - dns_rbtnode_t *node = rbtiterator->node; + rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator; + dns_rbtnode_t *node = rbtdbiter->node; - if (rbtiterator->paused) - return (DNS_R_SUCCESS); + if (rbtdbiter->result != DNS_R_SUCCESS) + return (rbtdbiter->result); + + REQUIRE(!rbtdbiter->paused); + REQUIRE(rbtdbiter->tree_locked); + REQUIRE(node != NULL); LOCK(&rbtdb->node_locks[node->locknum].lock); new_reference(rbtdb, node); UNLOCK(&rbtdb->node_locks[node->locknum].lock); - RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); + rbtdbiter->paused = ISC_TRUE; - return (DNS_R_NOTIMPLEMENTED); + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + rbtdbiter->tree_locked = ISC_FALSE; + + return (DNS_R_SUCCESS); } static dns_result_t dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { - rbtdb_dbiterator_t *rbtiterator = (rbtdb_dbiterator_t *)iterator; - dns_name_t *origin = dns_fixedname_name(&rbtiterator->origin); + rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator; + dns_name_t *origin = dns_fixedname_name(&rbtdbiter->origin); + + if (rbtdbiter->result != DNS_R_SUCCESS) + return (rbtdbiter->result); return (dns_name_concatenate(origin, NULL, name, NULL)); }