resolver_cache.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // $Id$
  15. #include "recursor_cache.h"
  16. #include "dns/message.h"
  17. #include "rrset_cache.h"
  18. #include <string>
  19. #include <algorithm>
  20. using namespace isc::dns;
  21. using namespace std;
  22. namespace isc {
  23. namespace cache {
  24. RecursorCache::RecursorCache() {
  25. uint16_t klass = 1; // class 'IN'
  26. class_supported_.push_back(klass);
  27. local_zone_data_[klass] = LocalZoneDataPtr(new LocalZoneData(klass));
  28. rrsets_cache_[klass] = RRsetCachePtr(new RRsetCache(RRSET_CACHE_DEFAULT_SIZE, klass));
  29. messages_cache_[klass] = MessageCachePtr(new MessageCache(rrsets_cache_[klass],
  30. MESSAGE_CACHE_DEFAULT_SIZE,
  31. klass));
  32. }
  33. RecursorCache::RecursorCache(std::vector<CacheSizeInfo> caches_size) {
  34. uint32_t index = 0;
  35. uint32_t size = caches_size.size();
  36. for (; index < size; ++index) {
  37. CacheSizeInfo* infop = &caches_size[index];
  38. uint16_t klass = infop->klass;
  39. class_supported_.push_back(klass);
  40. // TODO We should find one way to load local zone data.
  41. local_zone_data_[klass] = LocalZoneDataPtr(new LocalZoneData(klass));
  42. rrsets_cache_[klass] = RRsetCachePtr(new
  43. RRsetCache(infop->rrset_cache_size, klass));
  44. messages_cache_[klass] = MessageCachePtr(new MessageCache(rrsets_cache_[klass],
  45. infop->message_cache_size,
  46. klass));
  47. }
  48. // Sort the vector, so that binary_find can be used.
  49. sort(class_supported_.begin(), class_supported_.end());
  50. }
  51. bool
  52. RecursorCache::classIsSupported(uint16_t klass) const {
  53. return binary_search(class_supported_.begin(),
  54. class_supported_.end(), klass);
  55. }
  56. bool
  57. RecursorCache::lookup(const isc::dns::Name& qname,
  58. const isc::dns::RRType& qtype,
  59. const isc::dns::RRClass& qclass,
  60. isc::dns::Message& response) const
  61. {
  62. uint16_t class_code = qclass.getCode();
  63. if (!classIsSupported(class_code)) {
  64. return false;
  65. }
  66. // message response should has question section already.
  67. if (response.beginQuestion() == response.endQuestion()) {
  68. isc_throw(MessageNoQuestionSection, "Message has no question section");
  69. }
  70. // First, query in local zone, if the rrset(qname, qtype, qclass) can be
  71. // found in local zone, generated reply message with only the rrset in
  72. // answer section.
  73. RRsetPtr rrset_ptr = (local_zone_data_[class_code])->lookup(qname, qtype);
  74. if (rrset_ptr) {
  75. response.addRRset(Message::SECTION_ANSWER, rrset_ptr);
  76. return true;
  77. }
  78. // Search in class-specific message cache.
  79. return messages_cache_[class_code]->lookup(qname, qtype, response);
  80. }
  81. isc::dns::RRsetPtr
  82. RecursorCache::lookup(const isc::dns::Name& qname,
  83. const isc::dns::RRType& qtype,
  84. const isc::dns::RRClass& qclass) const
  85. {
  86. uint16_t klass = qclass.getCode();
  87. if (!classIsSupported(klass)) {
  88. return RRsetPtr();
  89. }
  90. // Algorithm:
  91. // 1. Search in local zone data first,
  92. // 2. Then do search in rrsets_cache_.
  93. RRsetPtr rrset_ptr = local_zone_data_[klass]->lookup(qname, qtype);
  94. if (rrset_ptr) {
  95. return rrset_ptr;
  96. } else {
  97. RRsetEntryPtr rrset_entry = rrsets_cache_[klass]->lookup(qname, qtype);
  98. if (rrset_entry) {
  99. return rrset_entry->getRRset();
  100. } else {
  101. return RRsetPtr();
  102. }
  103. }
  104. }
  105. isc::dns::RRsetPtr
  106. RecursorCache::lookupClosestRRset(const isc::dns::Name& qname,
  107. const isc::dns::RRType& qtype,
  108. const isc::dns::RRClass& qclass) const
  109. {
  110. unsigned int count = qname.getLabelCount();
  111. unsigned int level = 0;
  112. while(level < count) {
  113. Name close_name = qname.split(level);
  114. RRsetPtr rrset_ptr = lookup(close_name, qtype, qclass);
  115. if (rrset_ptr) {
  116. return rrset_ptr;
  117. } else {
  118. ++level;
  119. }
  120. }
  121. return RRsetPtr();
  122. }
  123. bool
  124. RecursorCache::update(const isc::dns::Message& msg) {
  125. QuestionIterator iter = msg.beginQuestion();
  126. uint16_t klass = (*iter)->getClass().getCode();
  127. if (!classIsSupported(klass)) {
  128. return false;
  129. }
  130. return messages_cache_[klass]->update(msg);
  131. }
  132. bool
  133. RecursorCache::updateRRsetCache(const isc::dns::ConstRRsetPtr rrset_ptr,
  134. RRsetCachePtr rrset_cache_ptr)
  135. {
  136. RRsetTrustLevel level;
  137. string typestr = rrset_ptr->getType().toText();
  138. if (typestr == "A" || typestr == "AAAA") {
  139. level = RRSET_TRUST_PRIM_GLUE;
  140. } else {
  141. level = RRSET_TRUST_PRIM_ZONE_NONGLUE;
  142. }
  143. rrset_cache_ptr->update((*rrset_ptr.get()), level);
  144. return true;
  145. }
  146. bool
  147. RecursorCache::update(const isc::dns::ConstRRsetPtr rrset_ptr) {
  148. uint16_t klass = rrset_ptr->getClass().getCode();
  149. if (!classIsSupported(klass)) {
  150. return false;
  151. }
  152. // First update local zone, then update rrset cache.
  153. local_zone_data_[klass]->update((*rrset_ptr.get()));
  154. updateRRsetCache(rrset_ptr, rrsets_cache_[klass]);
  155. return true;
  156. }
  157. void
  158. RecursorCache::dump(const std::string&) {
  159. //TODO
  160. }
  161. void
  162. RecursorCache::load(const std::string&) {
  163. //TODO
  164. }
  165. } // namespace cache
  166. } // namespace isc