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