]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/dns/rriterator.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / dns / rriterator.c
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
42 isc_result_t
43 dns_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
65 isc_result_t
66 dns_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
110 isc_result_t
111 dns_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
148 isc_result_t
149 dns_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
164 void
165 dns_rriterator_pause(dns_rriterator_t *it) {
166         REQUIRE(VALID_RRITERATOR(it));
167         RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
168 }
169
170 void
171 dns_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
182 void
183 dns_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 }