zone_entry.h 6.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// 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.

#ifndef __ZONE_ENTRY_H
#define __ZONE_ENTRY_H

#include <string>
19
#include <vector>
20
#include <set>
21
#include <boost/shared_ptr.hpp>
22
#include <boost/enable_shared_from_this.hpp>
23

Michal Vaner's avatar
Michal Vaner committed
24
#include <dns/rrset.h>
25

26 27
#include <resolve/resolver_interface.h>

28
#include "locks.h"
29
#include "hash_key.h"
30
#include "nsas_entry.h"
31
#include "asiolink.h"
Michal Vaner's avatar
Michal Vaner committed
32
#include "fetchable.h"
Michal Vaner's avatar
Michal Vaner committed
33
#include "nsas_types.h"
34
#include "random_number_generator.h"
35

36 37 38
namespace isc {
namespace nsas {

39
class NameserverEntry;
40
class AddressRequestCallback;
41 42 43 44 45 46 47 48 49

/// \brief Zone Entry
///
/// The zone entry object describes a zone for which nameserver address
/// information is held.
///
/// Although the interface is simple, the internal processing is fairly
/// complicated, in that the class takes account of triggering fetches for
/// addresses of nameservers when the address records expire.
50 51
///
/// It uses shared_from_this in its methods. It must live inside a shared_ptr.
52

53
class ZoneEntry : public NsasEntry<ZoneEntry>, public Fetchable {
54 55
public:

Michal Vaner's avatar
Michal Vaner committed
56
    /**
Michal Vaner's avatar
Michal Vaner committed
57
     * \brief Constructor.
Michal Vaner's avatar
Michal Vaner committed
58
     *
Michal Vaner's avatar
Michal Vaner committed
59
     * It asks the resolver any needed questions to get the nameservers.
Michal Vaner's avatar
Michal Vaner committed
60 61 62 63 64
     *
     * \param resolver The resolver used to ask for IP addresses
     * \param name Name of the zone
     * \param class_code Class of this zone (zones of different classes have
     *     different objects.
65 66 67
     * \param nameserver_table Hashtable of NameServerEntry objects for
     *     this zone
     * \param namesever_lru LRU for the nameserver entries
Michal Vaner's avatar
Michal Vaner committed
68 69 70
     * \todo Move to cc file, include the lookup (if NSAS uses resolver for
     *     everything)
     */
71 72
    ZoneEntry(
        boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
Michal Vaner's avatar
Michal Vaner committed
73
        const std::string& name, const isc::dns::RRClass& class_code,
Michal Vaner's avatar
Michal Vaner committed
74
        boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table,
75
        boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru);
76 77

    /// \return Name of the zone
Michal Vaner's avatar
Michal Vaner committed
78
    std::string getName() const {
79 80 81 82
        return name_;
    }

    /// \return Class of zone
Michal Vaner's avatar
Michal Vaner committed
83
    const isc::dns::RRClass& getClass() const {
Michal Vaner's avatar
Michal Vaner committed
84
        return class_code_;
85 86 87 88
    }

    /// \return Return Hash Key
    virtual HashKey hashKey() const {
Michal Vaner's avatar
Michal Vaner committed
89
        return HashKey(name_, class_code_);
90
    }
91

92
    /**
Michal Vaner's avatar
Michal Vaner committed
93
     * \short Put another callback inside.
Michal Vaner's avatar
Michal Vaner committed
94
     *
Michal Vaner's avatar
Michal Vaner committed
95 96
     * This callback is either executed right away, if it is possible,
     * or queued for later.
Michal Vaner's avatar
Michal Vaner committed
97
     *
Michal Vaner's avatar
Michal Vaner committed
98
     * \param callback The callback itself.
Michal Vaner's avatar
Michal Vaner committed
99
     * \param family Which address family is acceptable as an answer?
100
     */
Michal Vaner's avatar
Michal Vaner committed
101
    void addCallback(boost::shared_ptr<AddressRequestCallback>
102
        callback, AddressFamily family);
103

Michal Vaner's avatar
Michal Vaner committed
104 105 106
    /// \short Protected members, so they can be accessed by tests.
    //@{
protected:
Michal Vaner's avatar
Michal Vaner committed
107
    // TODO Read-Write lock?
108 109
    typedef boost::shared_ptr<NameserverEntry> NameserverPtr;
    typedef std::vector<NameserverPtr> NameserverVector;
110
    NameserverVector nameservers_; ///< Nameservers
111 112
    // Which nameservers didn't have any of our callbacks yet
    std::set<NameserverPtr> nameservers_not_asked_;
Michal Vaner's avatar
Michal Vaner committed
113 114 115 116 117 118 119
    /*
     * Callbacks. For each fimily type one vector, so we can process
     * them separately.
     */
    std::vector<boost::shared_ptr<AddressRequestCallback> >
        callbacks_[ADDR_REQ_MAX];
    time_t          expiry_;    ///< Expiry time of this entry, 0 means not set
Michal Vaner's avatar
Michal Vaner committed
120 121
    //}@
private:
122
    mutable isc::locks::recursive_mutex    mutex_;///< Mutex protecting this zone entry
Michal Vaner's avatar
Michal Vaner committed
123
    std::string     name_;      ///< Canonical zone name
Michal Vaner's avatar
Michal Vaner committed
124
    isc::dns::RRClass        class_code_; ///< Class code
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    /**
     * \short Process all the callbacks that can be processed
     *
     * The purpose of this funtion is to ask all nameservers for their IP
     * addresses and execute all callbacks that can be executed. It is
     * called whenever new callback appears and there's a chance it could
     * be answered or when new information is available (list of nameservers,
     * nameserver is unreachable or has an address).
     * \param family Which is the interesting address family where the change
     *     happened. ADDR_REQ_MAX means it could be any of them and it will
     *     trigger processing of all callbacks no matter what their family
     *     was.
     * \param nameserver Pass a nameserver if the change was triggered by
     *     the nameserver (if it wasn't triggered by a nameserver, pass empty
     *     pointer). This one will be accepted even with 0 TTL, the information
     *     just arrived and we are allowed to use it just now.
     * \todo With the recursive locks now, we might want to simplify executing
     *     callbacks (here and other functions as well);
     */
    void process(AddressFamily family,
        const boost::shared_ptr<NameserverEntry>& nameserver);
Michal Vaner's avatar
Michal Vaner committed
146
    // Resolver we use
147
    boost::shared_ptr<isc::resolve::ResolverInterface> resolver_;
Michal Vaner's avatar
Michal Vaner committed
148 149 150 151
    // We store the nameserver table and lru, so we can look up when there's
    // update
    boost::shared_ptr<HashTable<NameserverEntry> > nameserver_table_;
    boost::shared_ptr<LruList<NameserverEntry> > nameserver_lru_;
152
    // Resolver callback class, documentation with the class declaration
Michal Vaner's avatar
Michal Vaner committed
153 154 155
    class ResolverCallback;
    // It has direct access to us
    friend class ResolverCallback;
156 157 158 159 160
    // Guard class to eliminate missing finally
    class ProcessGuard;
    friend class ProcessGuard;
    // Are we in the process method?
    bool in_process_[ADDR_REQ_MAX];
161
    // Callback from nameserver entry (documented with the class)
162 163
    class NameserverCallback;
    // And it can get into our internals as well (call process)
Michal Vaner's avatar
Michal Vaner committed
164
    friend class NameserverCallback;
165 166
    // This dispatches callbacks of given family with failures
    void dispatchFailures(AddressFamily family);
167 168 169
    // Put a callback into the nameserver entry. Same ADDR_REQ_MAX means for
    // all families
    void insertCallback(NameserverPtr nameserver, AddressFamily family);
170 171 172
    // A random generator for this zone entry
    // TODO: A more global one? Per thread one?
    WeightedRandomIntegerGenerator address_selector;
173
};
174 175 176

} // namespace nsas
} // namespace isc
Michal Vaner's avatar
Michal Vaner committed
177

178
#endif // __ZONE_ENTRY_H