1/* 2 * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19/*! \file */ 20 21/*** 22 *** Imports 23 ***/ 24 25#include <config.h> 26 27#include <isc/string.h> 28#include <isc/util.h> 29 30#include <dns/db.h> 31#include <dns/dbiterator.h> 32#include <dns/rdata.h> 33#include <dns/rdataset.h> 34#include <dns/rdatasetiter.h> 35#include <dns/result.h> 36#include <dns/rriterator.h> 37 38/*** 39 *** RRiterator methods 40 ***/ 41 42isc_result_t 43dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver, 44 isc_stdtime_t now) 45{ 46 isc_result_t result; 47 it->magic = RRITERATOR_MAGIC; 48 it->db = db; 49 it->dbit = NULL; 50 it->ver = ver; 51 it->now = now; 52 it->node = NULL; 53 result = dns_db_createiterator(it->db, 0, &it->dbit); 54 if (result != ISC_R_SUCCESS) 55 return (result); 56 it->rdatasetit = NULL; 57 dns_rdata_init(&it->rdata); 58 dns_rdataset_init(&it->rdataset); 59 dns_fixedname_init(&it->fixedname); 60 INSIST(! dns_rdataset_isassociated(&it->rdataset)); 61 it->result = ISC_R_SUCCESS; 62 return (it->result); 63} 64 65isc_result_t 66dns_rriterator_first(dns_rriterator_t *it) { 67 REQUIRE(VALID_RRITERATOR(it)); 68 /* Reset state */ 69 if (dns_rdataset_isassociated(&it->rdataset)) 70 dns_rdataset_disassociate(&it->rdataset); 71 if (it->rdatasetit != NULL) 72 dns_rdatasetiter_destroy(&it->rdatasetit); 73 if (it->node != NULL) 74 dns_db_detachnode(it->db, &it->node); 75 it->result = dns_dbiterator_first(it->dbit); 76 77 /* 78 * The top node may be empty when out of zone glue exists. 79 * Walk the tree to find the first node with data. 80 */ 81 while (it->result == ISC_R_SUCCESS) { 82 it->result = dns_dbiterator_current(it->dbit, &it->node, 83 dns_fixedname_name(&it->fixedname)); 84 if (it->result != ISC_R_SUCCESS) 85 return (it->result); 86 87 it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 88 it->now, &it->rdatasetit); 89 if (it->result != ISC_R_SUCCESS) 90 return (it->result); 91 92 it->result = dns_rdatasetiter_first(it->rdatasetit); 93 if (it->result != ISC_R_SUCCESS) { 94 /* 95 * This node is empty. Try next node. 96 */ 97 dns_rdatasetiter_destroy(&it->rdatasetit); 98 dns_db_detachnode(it->db, &it->node); 99 it->result = dns_dbiterator_next(it->dbit); 100 continue; 101 } 102 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 103 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 104 it->result = dns_rdataset_first(&it->rdataset); 105 return (it->result); 106 } 107 return (it->result); 108} 109 110isc_result_t 111dns_rriterator_nextrrset(dns_rriterator_t *it) { 112 REQUIRE(VALID_RRITERATOR(it)); 113 if (dns_rdataset_isassociated(&it->rdataset)) 114 dns_rdataset_disassociate(&it->rdataset); 115 it->result = dns_rdatasetiter_next(it->rdatasetit); 116 /* 117 * The while loop body is executed more than once 118 * only when an empty dbnode needs to be skipped. 119 */ 120 while (it->result == ISC_R_NOMORE) { 121 dns_rdatasetiter_destroy(&it->rdatasetit); 122 dns_db_detachnode(it->db, &it->node); 123 it->result = dns_dbiterator_next(it->dbit); 124 if (it->result == ISC_R_NOMORE) { 125 /* We are at the end of the entire database. */ 126 return (it->result); 127 } 128 if (it->result != ISC_R_SUCCESS) 129 return (it->result); 130 it->result = dns_dbiterator_current(it->dbit, &it->node, 131 dns_fixedname_name(&it->fixedname)); 132 if (it->result != ISC_R_SUCCESS) 133 return (it->result); 134 it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 135 it->now, &it->rdatasetit); 136 if (it->result != ISC_R_SUCCESS) 137 return (it->result); 138 it->result = dns_rdatasetiter_first(it->rdatasetit); 139 } 140 if (it->result != ISC_R_SUCCESS) 141 return (it->result); 142 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 143 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 144 it->result = dns_rdataset_first(&it->rdataset); 145 return (it->result); 146} 147 148isc_result_t 149dns_rriterator_next(dns_rriterator_t *it) { 150 REQUIRE(VALID_RRITERATOR(it)); 151 if (it->result != ISC_R_SUCCESS) 152 return (it->result); 153 154 INSIST(it->dbit != NULL); 155 INSIST(it->node != NULL); 156 INSIST(it->rdatasetit != NULL); 157 158 it->result = dns_rdataset_next(&it->rdataset); 159 if (it->result == ISC_R_NOMORE) 160 return (dns_rriterator_nextrrset(it)); 161 return (it->result); 162} 163 164void 165dns_rriterator_pause(dns_rriterator_t *it) { 166 REQUIRE(VALID_RRITERATOR(it)); 167 RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); 168} 169 170void 171dns_rriterator_destroy(dns_rriterator_t *it) { 172 REQUIRE(VALID_RRITERATOR(it)); 173 if (dns_rdataset_isassociated(&it->rdataset)) 174 dns_rdataset_disassociate(&it->rdataset); 175 if (it->rdatasetit != NULL) 176 dns_rdatasetiter_destroy(&it->rdatasetit); 177 if (it->node != NULL) 178 dns_db_detachnode(it->db, &it->node); 179 dns_dbiterator_destroy(&it->dbit); 180} 181 182void 183dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, 184 isc_uint32_t *ttl, dns_rdataset_t **rdataset, 185 dns_rdata_t **rdata) 186{ 187 REQUIRE(name != NULL && *name == NULL); 188 REQUIRE(VALID_RRITERATOR(it)); 189 REQUIRE(it->result == ISC_R_SUCCESS); 190 REQUIRE(rdataset == NULL || *rdataset == NULL); 191 REQUIRE(rdata == NULL || *rdata == NULL); 192 193 *name = dns_fixedname_name(&it->fixedname); 194 *ttl = it->rdataset.ttl; 195 196 dns_rdata_reset(&it->rdata); 197 dns_rdataset_current(&it->rdataset, &it->rdata); 198 199 if (rdataset != NULL) 200 *rdataset = &it->rdataset; 201 202 if (rdata != NULL) 203 *rdata = &it->rdata; 204} 205