resolver_cache.cc 7.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

// $Id$

Jelte Jansen's avatar
Jelte Jansen committed
17 18
#include <config.h>

zhanglikun's avatar
zhanglikun committed
19
#include "resolver_cache.h"
20 21 22
#include "dns/message.h"
#include "rrset_cache.h"
#include <string>
zhanglikun's avatar
zhanglikun committed
23
#include <algorithm>
24

25
using namespace isc::dns;
zhanglikun's avatar
zhanglikun committed
26
using namespace std;
27 28 29 30

namespace isc {
namespace cache {

31 32 33 34 35 36 37 38 39
ResolverClassCache::ResolverClassCache(const RRClass& cache_class) :
    cache_class_(cache_class)
{
    local_zone_data_ = LocalZoneDataPtr(new LocalZoneData(cache_class_.getCode()));
    rrsets_cache_ = RRsetCachePtr(new RRsetCache(RRSET_CACHE_DEFAULT_SIZE,
                                                 cache_class_.getCode()));
    messages_cache_ = MessageCachePtr(new MessageCache(rrsets_cache_,
                                      MESSAGE_CACHE_DEFAULT_SIZE,
                                      cache_class_.getCode()));
zhanglikun's avatar
zhanglikun committed
40 41
}

42 43 44 45 46 47 48 49 50 51 52
ResolverClassCache::ResolverClassCache(CacheSizeInfo cache_info) :
    cache_class_(cache_info.cclass)
{
    uint16_t klass = cache_class_.getCode();
    // TODO We should find one way to load local zone data.
    local_zone_data_ = LocalZoneDataPtr(new LocalZoneData(klass));
    rrsets_cache_ = RRsetCachePtr(new
                        RRsetCache(cache_info.rrset_cache_size, klass));
    messages_cache_ = MessageCachePtr(new MessageCache(rrsets_cache_,
                                      cache_info.message_cache_size,
                                      klass));
53 54
}

55 56 57 58
const RRClass&
ResolverClassCache::getClass() const {
    return cache_class_;
}
59

60
bool
61
ResolverClassCache::lookup(const isc::dns::Name& qname,
62 63
                      const isc::dns::RRType& qtype,
                      isc::dns::Message& response) const
64
{
zhanglikun's avatar
zhanglikun committed
65 66 67
    // message response should has question section already.
    if (response.beginQuestion() == response.endQuestion()) {
        isc_throw(MessageNoQuestionSection, "Message has no question section");
68
    }
69

zhanglikun's avatar
zhanglikun committed
70 71 72
    // First, query in local zone, if the rrset(qname, qtype, qclass) can be
    // found in local zone, generated reply message with only the rrset in
    // answer section.
73
    RRsetPtr rrset_ptr = local_zone_data_->lookup(qname, qtype);
zhanglikun's avatar
zhanglikun committed
74 75
    if (rrset_ptr) {
        response.addRRset(Message::SECTION_ANSWER, rrset_ptr);
76
        return (true);
77 78
    }

zhanglikun's avatar
zhanglikun committed
79
    // Search in class-specific message cache.
80
    return (messages_cache_->lookup(qname, qtype, response));
81 82 83
}

isc::dns::RRsetPtr
84 85
ResolverClassCache::lookup(const isc::dns::Name& qname,
               const isc::dns::RRType& qtype) const
86
{
87
    // Algorithm:
zhanglikun's avatar
zhanglikun committed
88 89
    // 1. Search in local zone data first,
    // 2. Then do search in rrsets_cache_.
90
    RRsetPtr rrset_ptr = local_zone_data_->lookup(qname, qtype);
91
    if (rrset_ptr) {
92
        return (rrset_ptr);
93
    } else {
94
        RRsetEntryPtr rrset_entry = rrsets_cache_->lookup(qname, qtype);
zhanglikun's avatar
zhanglikun committed
95
        if (rrset_entry) {
96
            return (rrset_entry->getRRset());
zhanglikun's avatar
zhanglikun committed
97
        } else {
98
            return (RRsetPtr());
zhanglikun's avatar
zhanglikun committed
99
        }
100
    }
zhanglikun's avatar
zhanglikun committed
101
}
102

103 104 105 106 107 108 109 110 111 112
bool
ResolverClassCache::update(const isc::dns::Message& msg) {
    return (messages_cache_->update(msg));
}

bool
ResolverClassCache::updateRRsetCache(const isc::dns::ConstRRsetPtr rrset_ptr,
                                RRsetCachePtr rrset_cache_ptr)
{
    RRsetTrustLevel level;
113 114
    if (rrset_ptr->getType() == RRType::A() || 
        rrset_ptr->getType() == RRType::AAAA()) {
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
        level = RRSET_TRUST_PRIM_GLUE;
    } else {
        level = RRSET_TRUST_PRIM_ZONE_NONGLUE;
    }

    rrset_cache_ptr->update((*rrset_ptr.get()), level);
    return (true);
}

bool
ResolverClassCache::update(const isc::dns::ConstRRsetPtr rrset_ptr) {
    // First update local zone, then update rrset cache.
    local_zone_data_->update((*rrset_ptr.get()));
    updateRRsetCache(rrset_ptr, rrsets_cache_);
    return (true);
}


ResolverCache::ResolverCache()
{
    class_caches_.push_back(new ResolverClassCache(RRClass::IN()));
}

ResolverCache::ResolverCache(std::vector<CacheSizeInfo> caches_info)
{
    for (int i = 0; i < caches_info.size(); ++i) {
        class_caches_.push_back(new ResolverClassCache(caches_info[i]));
    }
}

ResolverCache::~ResolverCache()
{
    for (int i = 0; i < class_caches_.size(); ++i) {
        delete class_caches_[i];
    }
}

bool
ResolverCache::lookup(const isc::dns::Name& qname,
                      const isc::dns::RRType& qtype,
                      const isc::dns::RRClass& qclass,
                      isc::dns::Message& response) const
{
    ResolverClassCache* cc = getClassCache(qclass);
    if (cc) {
        return (cc->lookup(qname, qtype, response));
    } else {
        return (false);
    }
}

isc::dns::RRsetPtr
ResolverCache::lookup(const isc::dns::Name& qname,
               const isc::dns::RRType& qtype,
               const isc::dns::RRClass& qclass) const
{
    ResolverClassCache* cc = getClassCache(qclass);
    if (cc) {
        return (cc->lookup(qname, qtype));
    } else {
        return (RRsetPtr());
    }
}

zhanglikun's avatar
zhanglikun committed
179
isc::dns::RRsetPtr
zhanglikun's avatar
zhanglikun committed
180
ResolverCache::lookupClosestRRset(const isc::dns::Name& qname,
zhanglikun's avatar
zhanglikun committed
181 182 183
                                  const isc::dns::RRType& qtype,
                                  const isc::dns::RRClass& qclass) const
{
184
    ResolverClassCache* cc = getClassCache(qclass);
185 186 187 188 189 190 191 192 193 194 195 196 197
    if (cc) {
        unsigned int count = qname.getLabelCount();
        unsigned int level = 0;
        while(level < count) {
            Name close_name = qname.split(level);
            RRsetPtr rrset_ptr = cc->lookup(close_name, qtype);
            if (rrset_ptr) {
                return (rrset_ptr);
            } else {
                ++level;
            }
        }
    }
zhanglikun's avatar
zhanglikun committed
198

199
    return (RRsetPtr());
200 201
}

202
bool
zhanglikun's avatar
zhanglikun committed
203
ResolverCache::update(const isc::dns::Message& msg) {
204
    QuestionIterator iter = msg.beginQuestion();
205
    RRClass c = (*iter)->getClass();
206
    ResolverClassCache* cc = getClassCache((*iter)->getClass());
207
    if (cc) {
208 209 210 211
        return (cc->update(msg));
    } else {
        return (false);
    }
212 213 214
}

bool
zhanglikun's avatar
zhanglikun committed
215
ResolverCache::update(const isc::dns::ConstRRsetPtr rrset_ptr) {
216
    ResolverClassCache* cc = getClassCache(rrset_ptr->getClass());
217
    if (cc) {
218 219 220 221
        return (cc->update(rrset_ptr));
    } else {
        return (false);
    }
222 223 224
}

void
zhanglikun's avatar
zhanglikun committed
225
ResolverCache::dump(const std::string&) {
226
    //TODO
227 228 229
}

void
zhanglikun's avatar
zhanglikun committed
230
ResolverCache::load(const std::string&) {
231
    //TODO
232 233
}

234 235 236 237 238 239 240 241 242 243
ResolverClassCache*
ResolverCache::getClassCache(const isc::dns::RRClass& cache_class) const {
    for (int i = 0; i < class_caches_.size(); ++i) {
        if (class_caches_[i]->getClass() == cache_class) {
            return class_caches_[i];
        }
    }
    return NULL;
}

244 245 246
} // namespace cache
} // namespace isc