123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- // 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$
- #ifndef __RESOLVER_CACHE_H
- #define __RESOLVER_CACHE_H
- #include <map>
- #include <string>
- #include <boost/shared_ptr.hpp>
- #include <dns/rrclass.h>
- #include <dns/message.h>
- #include <exceptions/exceptions.h>
- #include "message_cache.h"
- #include "rrset_cache.h"
- #include "local_zone_data.h"
- namespace isc {
- namespace cache {
- class RRsetCache;
- //TODO a better proper default cache size
- #define MESSAGE_CACHE_DEFAULT_SIZE 10000
- #define RRSET_CACHE_DEFAULT_SIZE 20000
- /// \brief Cache Size Information.
- ///
- /// Used to initialize the size of class-specific rrset/message cache.
- struct CacheSizeInfo
- {
- public:
- /// \brief Constructor
- ///
- /// \param cls The RRClass code
- /// \param msg_cache_size The size for the message cache
- /// \param rst_cache_size The size for the RRset cache
- CacheSizeInfo(const isc::dns::RRClass& cls,
- uint32_t msg_cache_size,
- uint32_t rst_cache_size):
- cclass(cls),
- message_cache_size(msg_cache_size),
- rrset_cache_size(rst_cache_size)
- {}
- isc::dns::RRClass cclass; // class of the cache.
- uint32_t message_cache_size; // the size for message cache.
- uint32_t rrset_cache_size; // The size for rrset cache.
- };
- /// \brief Message has no question section.
- ///
- /// Thrown if the given message has no question section when looking up
- /// the message in cache.
- class MessageNoQuestionSection : public isc::Exception {
- public:
- MessageNoQuestionSection(const char*file, size_t line, const char*what) :
- isc::Exception(file, line, what)
- {}
- };
- /// \brief Class-specific Resolver Cache.
- ///
- /// The object of ResolverCache represents the cache of the resolver. It may hold
- /// a list of message/rrset cache which are in different class.
- ///
- /// \note Public interaction with the cache should be through ResolverCache,
- /// not directly with this one. (TODO: make this private/hidden/local to the .cc?)
- class ResolverClassCache {
- public:
- /// \brief Default Constructor.
- ///
- /// Only support for class "IN", and message cache size is
- /// MESSAGE_CACHE_DEFAULT_SIZE, rrset cache size is
- /// RRSET_CACHE_DEFAULT_SIZE
- ResolverClassCache(const isc::dns::RRClass& cache_class);
- /// \brief Construct Function.
- /// \param caches_size cache size information for each
- /// messages/rrsets of different classes.
- ResolverClassCache(CacheSizeInfo cache_info);
- /// \name Lookup Interfaces
- //@{
- /// \brief Look up message in cache.
- ///
- /// \param qname The query name to look up
- /// \param qtype The query type to look up
- /// \param response the query message (must be in RENDER mode)
- /// which has question section already (exception
- /// MessageNoQeustionSection will be thrown if it has
- /// no question section). If the message can be found
- /// in cache, rrsets for the message will be added to
- /// different sections(answer, authority, additional).
- /// \return return true if the message can be found, or else,
- /// return false.
- bool lookup(const isc::dns::Name& qname,
- const isc::dns::RRType& qtype,
- isc::dns::Message& response) const;
- /// \brief Look up rrset in cache.
- ///
- /// \param qname The query name to look up
- /// \param qtype The query type to look up
- ///
- /// \return return the shared_ptr of rrset if it can be found,
- /// or else, return NULL. When looking up, local zone
- /// data will be searched first, if not found, then
- /// search in rrset cache.
- ///
- /// \overload
- ///
- isc::dns::RRsetPtr lookup(const isc::dns::Name& qname,
- const isc::dns::RRType& qtype) const;
- /// \brief Update the message in the cache with the new one.
- ///
- /// \param msg The message to update
- ///
- /// \return return true if the message is updated successfully,
- /// or else, return false.
- ///
- /// \note the function doesn't do any message validation check,
- /// the user should make sure the message is valid, and of
- /// the right class
- bool update(const isc::dns::Message& msg);
- /// \brief Update the rrset in the cache with the new one.
- ///
- /// local zone data and rrset cache will be updated together.
- /// If the rrset doesn't exist in both of them, then the rrset
- /// will be added into both of them.
- ///
- /// \param rrset_ptr The RRset to update
- ///
- /// \return return false, if the class of the parameter rrset is
- /// allowed to be cached.
- ///
- /// \overload
- ///
- /// \note The class of the RRset must have been checked. It is not
- /// here.
- bool update(const isc::dns::ConstRRsetPtr rrset_ptr);
- /// \brief Get the RRClass this cache is for
- ///
- /// \return The RRClass of this cache
- const isc::dns::RRClass& getClass() const;
-
- private:
- /// \brief Update rrset cache.
- ///
- /// \param rrset_ptr The rrset to update with
- /// \param rrset_cache_ptr the rrset cache to update
- ///
- /// \return return true if the rrset is updated in the rrset cache,
- /// or else return false if failed.
- /// \param rrset_cache_ptr The rrset cache need to be updated.
- bool updateRRsetCache(const isc::dns::ConstRRsetPtr rrset_ptr,
- RRsetCachePtr rrset_cache_ptr);
- /// \brief Class this cache is for.
- const isc::dns::RRClass cache_class_;
- /// \brief map of message caches for configured classes(each message
- /// cache is class-specific)
- MessageCachePtr messages_cache_;
- /// \name rrset caches
- //@{
- /// \brief Local Zone data cache
- /// Cache for rrsets in local zones, rrsets
- /// in it never expire.
- LocalZoneDataPtr local_zone_data_;
- /// \brief cache the rrsets parsed from the received message.
- RRsetCachePtr rrsets_cache_;
- //@}
- };
- class ResolverCache {
- public:
- /// \brief Default Constructor.
- ///
- /// Right now, only support for class "IN", and message cache size is
- /// MESSAGE_CACHE_DEFAULT_SIZE, rrset cache size is
- /// RRSET_CACHE_DEFAULT_SIZE
- ResolverCache();
- /// \brief Construct Function.
- /// \param caches_size cache size information for each
- /// messages/rrsets of different classes.
- ResolverCache(std::vector<CacheSizeInfo> caches_size);
- /// \brief Destructor
- ~ResolverCache();
- /// \name Lookup Interfaces
- //@{
- /// \brief Look up message in cache.
- ///
- /// \param qname The query name to look up
- /// \param qtype The query type to look up
- /// \param qclass The query class to look up
- /// \param response the query message (must be in RENDER mode)
- /// which has question section already (exception
- /// MessageNoQeustionSection will be thrown if it has
- /// no question section). If the message can be found
- /// in cache, rrsets for the message will be added to
- /// different sections(answer, authority, additional).
- /// \return return true if the message can be found, or else,
- /// return false.
- bool lookup(const isc::dns::Name& qname,
- const isc::dns::RRType& qtype,
- const isc::dns::RRClass& qclass,
- isc::dns::Message& response) const;
- /// \brief Look up rrset in cache.
- ///
- /// \param qname The query name to look up
- /// \param qtype The query type to look up
- /// \param qclass The query class to look up
- ///
- /// \return return the shared_ptr of rrset if it can be found,
- /// or else, return NULL. When looking up, local zone
- /// data will be searched first, if not found, then
- /// search in rrset cache.
- ///
- /// \overload
- ///
- isc::dns::RRsetPtr lookup(const isc::dns::Name& qname,
- const isc::dns::RRType& qtype,
- const isc::dns::RRClass& qclass) const;
- /// \brief Look up closest rrset in cache.
- ///
- /// \param qname The query name to look up
- /// \param qtype The query type to look up
- /// \param qclass The query class to look up
- ///
- /// \return return the shared_ptr of rrset if it can be found in
- /// cache, or else return NULL.
- ///
- /// Currently the implementation is: search exact rrset
- /// label by lable, If the rrset can't be found, remove the last
- /// label, then search again. The efficiency may be very low when
- /// the name of rrset is very long but it's closest rrset's name
- /// is very short.
- /// If a good perfermance is needed when looking up the closest rrset,
- /// rrset cache structure(HashTable) should be redesigned. By using
- /// HashTable, it can only garantee the performance for looking
- /// up exact rrset.
- /// So here there is another question, which rrset looking up interface
- /// is used frequently? Exact or closest looking up.
- isc::dns::RRsetPtr lookupClosestRRset(const isc::dns::Name& qname,
- const isc::dns::RRType& qtype,
- const isc::dns::RRClass& qclass) const;
- //@}
- /// \brief Update the message in the cache with the new one.
- ///
- /// \param msg The message to update
- ///
- /// \return return true if the message is updated successfully,
- /// or else, return false.
- ///
- /// \note the function doesn't do any message validation check,
- /// the user should make sure the message is valid.
- bool update(const isc::dns::Message& msg);
- /// \brief Update the rrset in the cache with the new one.
- ///
- /// local zone data and rrset cache will be updated together.
- /// If the rrset doesn't exist in both of them, then the rrset
- /// will be added into both of them.
- ///
- /// \param rrset_ptr The RRset to update
- ///
- /// \return return false, if the class of the parameter rrset is
- /// allowed to be cached.
- ///
- /// \overload
- ///
- bool update(const isc::dns::ConstRRsetPtr rrset_ptr);
- /// \name Cache Serialization
- //@{
- /// \brief Dump the cache content to one file.
- ///
- /// \param file_name file to write to
- ///
- /// \todo It should can be dumped to one configured database.
- void dump(const std::string& file_name);
- /// \brief Load the cache from one file.
- ///
- /// \param file to load from
- ///
- /// \todo It should can be loaded from one configured database.
- void load(const std::string& file_name);
- //@}
- private:
- /// \brief Returns the class-specific subcache
- ///
- /// \param cache_class the class to get the subcache for
- /// \return The subcache, or NULL if there is no cache for this class
- ResolverClassCache* getClassCache(const isc::dns::RRClass& cache_class) const;
- /// The class-specific caches.
- /// TODO: I think we can optimize for IN, and always have that
- /// one directly available, use the vector for the rest?
- std::vector<ResolverClassCache*> class_caches_;
- };
- } // namespace cache
- } // namespace isc
- #endif // __RESOLVER_CACHE_H
|