/contrib/bind9/lib/dns/rriterator.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 204 lines · 145 code · 23 blank · 36 comment · 55 complexity · 605c49797c3f21a8d88156a8507503cb MD5 · raw file

  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. /* $Id$ */
  17. /*! \file */
  18. /***
  19. *** Imports
  20. ***/
  21. #include <config.h>
  22. #include <isc/string.h>
  23. #include <isc/util.h>
  24. #include <dns/db.h>
  25. #include <dns/dbiterator.h>
  26. #include <dns/rdata.h>
  27. #include <dns/rdataset.h>
  28. #include <dns/rdatasetiter.h>
  29. #include <dns/result.h>
  30. #include <dns/rriterator.h>
  31. /***
  32. *** RRiterator methods
  33. ***/
  34. isc_result_t
  35. dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
  36. isc_stdtime_t now)
  37. {
  38. isc_result_t result;
  39. it->magic = RRITERATOR_MAGIC;
  40. it->db = db;
  41. it->dbit = NULL;
  42. it->ver = ver;
  43. it->now = now;
  44. it->node = NULL;
  45. result = dns_db_createiterator(it->db, 0, &it->dbit);
  46. if (result != ISC_R_SUCCESS)
  47. return (result);
  48. it->rdatasetit = NULL;
  49. dns_rdata_init(&it->rdata);
  50. dns_rdataset_init(&it->rdataset);
  51. dns_fixedname_init(&it->fixedname);
  52. INSIST(! dns_rdataset_isassociated(&it->rdataset));
  53. it->result = ISC_R_SUCCESS;
  54. return (it->result);
  55. }
  56. isc_result_t
  57. dns_rriterator_first(dns_rriterator_t *it) {
  58. REQUIRE(VALID_RRITERATOR(it));
  59. /* Reset state */
  60. if (dns_rdataset_isassociated(&it->rdataset))
  61. dns_rdataset_disassociate(&it->rdataset);
  62. if (it->rdatasetit != NULL)
  63. dns_rdatasetiter_destroy(&it->rdatasetit);
  64. if (it->node != NULL)
  65. dns_db_detachnode(it->db, &it->node);
  66. it->result = dns_dbiterator_first(it->dbit);
  67. /*
  68. * The top node may be empty when out of zone glue exists.
  69. * Walk the tree to find the first node with data.
  70. */
  71. while (it->result == ISC_R_SUCCESS) {
  72. it->result = dns_dbiterator_current(it->dbit, &it->node,
  73. dns_fixedname_name(&it->fixedname));
  74. if (it->result != ISC_R_SUCCESS)
  75. return (it->result);
  76. it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
  77. it->now, &it->rdatasetit);
  78. if (it->result != ISC_R_SUCCESS)
  79. return (it->result);
  80. it->result = dns_rdatasetiter_first(it->rdatasetit);
  81. if (it->result != ISC_R_SUCCESS) {
  82. /*
  83. * This node is empty. Try next node.
  84. */
  85. dns_rdatasetiter_destroy(&it->rdatasetit);
  86. dns_db_detachnode(it->db, &it->node);
  87. it->result = dns_dbiterator_next(it->dbit);
  88. continue;
  89. }
  90. dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
  91. it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
  92. it->result = dns_rdataset_first(&it->rdataset);
  93. return (it->result);
  94. }
  95. return (it->result);
  96. }
  97. isc_result_t
  98. dns_rriterator_nextrrset(dns_rriterator_t *it) {
  99. REQUIRE(VALID_RRITERATOR(it));
  100. if (dns_rdataset_isassociated(&it->rdataset))
  101. dns_rdataset_disassociate(&it->rdataset);
  102. it->result = dns_rdatasetiter_next(it->rdatasetit);
  103. /*
  104. * The while loop body is executed more than once
  105. * only when an empty dbnode needs to be skipped.
  106. */
  107. while (it->result == ISC_R_NOMORE) {
  108. dns_rdatasetiter_destroy(&it->rdatasetit);
  109. dns_db_detachnode(it->db, &it->node);
  110. it->result = dns_dbiterator_next(it->dbit);
  111. if (it->result == ISC_R_NOMORE) {
  112. /* We are at the end of the entire database. */
  113. return (it->result);
  114. }
  115. if (it->result != ISC_R_SUCCESS)
  116. return (it->result);
  117. it->result = dns_dbiterator_current(it->dbit, &it->node,
  118. dns_fixedname_name(&it->fixedname));
  119. if (it->result != ISC_R_SUCCESS)
  120. return (it->result);
  121. it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
  122. it->now, &it->rdatasetit);
  123. if (it->result != ISC_R_SUCCESS)
  124. return (it->result);
  125. it->result = dns_rdatasetiter_first(it->rdatasetit);
  126. }
  127. if (it->result != ISC_R_SUCCESS)
  128. return (it->result);
  129. dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
  130. it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
  131. it->result = dns_rdataset_first(&it->rdataset);
  132. return (it->result);
  133. }
  134. isc_result_t
  135. dns_rriterator_next(dns_rriterator_t *it) {
  136. REQUIRE(VALID_RRITERATOR(it));
  137. if (it->result != ISC_R_SUCCESS)
  138. return (it->result);
  139. INSIST(it->dbit != NULL);
  140. INSIST(it->node != NULL);
  141. INSIST(it->rdatasetit != NULL);
  142. it->result = dns_rdataset_next(&it->rdataset);
  143. if (it->result == ISC_R_NOMORE)
  144. return (dns_rriterator_nextrrset(it));
  145. return (it->result);
  146. }
  147. void
  148. dns_rriterator_pause(dns_rriterator_t *it) {
  149. REQUIRE(VALID_RRITERATOR(it));
  150. RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
  151. }
  152. void
  153. dns_rriterator_destroy(dns_rriterator_t *it) {
  154. REQUIRE(VALID_RRITERATOR(it));
  155. if (dns_rdataset_isassociated(&it->rdataset))
  156. dns_rdataset_disassociate(&it->rdataset);
  157. if (it->rdatasetit != NULL)
  158. dns_rdatasetiter_destroy(&it->rdatasetit);
  159. if (it->node != NULL)
  160. dns_db_detachnode(it->db, &it->node);
  161. dns_dbiterator_destroy(&it->dbit);
  162. }
  163. void
  164. dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name,
  165. isc_uint32_t *ttl, dns_rdataset_t **rdataset,
  166. dns_rdata_t **rdata)
  167. {
  168. REQUIRE(name != NULL && *name == NULL);
  169. REQUIRE(VALID_RRITERATOR(it));
  170. REQUIRE(it->result == ISC_R_SUCCESS);
  171. REQUIRE(rdataset == NULL || *rdataset == NULL);
  172. REQUIRE(rdata == NULL || *rdata == NULL);
  173. *name = dns_fixedname_name(&it->fixedname);
  174. *ttl = it->rdataset.ttl;
  175. dns_rdata_reset(&it->rdata);
  176. dns_rdataset_current(&it->rdataset, &it->rdata);
  177. if (rdataset != NULL)
  178. *rdataset = &it->rdataset;
  179. if (rdata != NULL)
  180. *rdata = &it->rdata;
  181. }