Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
30ab0e64
Unverified
Commit
30ab0e64
authored
Sep 26, 2012
by
Michal 'vorner' Vaner
Browse files
Merge #2161
parents
77b10c70
050a4704
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
src/bin/auth/auth_srv.cc
View file @
30ab0e64
...
...
@@ -41,10 +41,7 @@
#include <asiodns/dns_service.h>
#include <datasrc/query.h>
#include <datasrc/data_source.h>
#include <datasrc/static_datasrc.h>
#include <datasrc/sqlite3_datasrc.h>
#include <datasrc/client_list.h>
#include <xfr/xfrout_client.h>
...
...
src/lib/datasrc/Makefile.am
View file @
30ab0e64
...
...
@@ -21,11 +21,7 @@ CLEANFILES += datasrc_config.h
CLEANFILES
+=
static.zone
lib_LTLIBRARIES
=
libb10-datasrc.la
libb10_datasrc_la_SOURCES
=
data_source.h data_source.cc
libb10_datasrc_la_SOURCES
+=
static_datasrc.h static_datasrc.cc
libb10_datasrc_la_SOURCES
+=
sqlite3_datasrc.h sqlite3_datasrc.cc
libb10_datasrc_la_SOURCES
+=
query.h query.cc
libb10_datasrc_la_SOURCES
+=
cache.h cache.cc
libb10_datasrc_la_SOURCES
=
data_source.h
libb10_datasrc_la_SOURCES
+=
rbnode_rrset.h
libb10_datasrc_la_SOURCES
+=
rbtree.h
libb10_datasrc_la_SOURCES
+=
zonetable.h zonetable.cc
...
...
src/lib/datasrc/cache.cc
deleted
100644 → 0
View file @
77b10c70
// 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.
#include <stdint.h>
#include <map>
#include <dns/question.h>
#include <dns/rrclass.h>
#include <dns/rrset.h>
#include <dns/rrtype.h>
#include <list>
#include <datasrc/cache.h>
#include <datasrc/logger.h>
using
namespace
std
;
using
namespace
isc
::
dns
;
namespace
isc
{
namespace
datasrc
{
/// \brief A \c CacheEntry object contains the data stored with
/// each \c CacheNode: a pointer to the cached RRset (empty in
/// the case of a negative cache entry), and a copy of the
/// query-response flags that were returned when the RRset
/// was originally looked up in the low-level data source.
class
CacheEntry
{
private:
/// The copy constructor and the assignment operator are intentionally
/// defined as private.
CacheEntry
(
const
CacheEntry
&
source
);
CacheEntry
&
operator
=
(
const
CacheEntry
&
source
);
public:
CacheEntry
(
RRsetPtr
r
,
uint32_t
f
)
:
rrset
(
r
),
flags
(
f
)
{};
RRsetPtr
rrset
;
uint32_t
flags
;
};
typedef
boost
::
shared_ptr
<
CacheEntry
>
CacheEntryPtr
;
/// \brief A \c CacheNode is a node in the \c HotCache LRU queue. It
/// contains a pointer to a \c CacheEntry, a reference to the \c Question
/// that we are answering, a lifespan during which this entry remains
/// valid, and pointers to the next and previous entries in the list.
class
CacheNode
{
private:
/// \name Constructors and Assignment Operator
///
/// Note: The copy constructor and the assignment operator are intentionally
/// defined as private.
//@{
CacheNode
(
const
CacheNode
&
source
);
CacheNode
&
operator
=
(
const
CacheNode
&
source
);
public:
/// \brief Constructor for positive cache entry.
///
/// \param rrset The \c RRset to cache.
/// \param flags The query response flags returned from the low-level
/// data source when this \c RRset was looked up.
/// \param lifespan How long the cache node is to be considered valid.
CacheNode
(
const
RRsetPtr
rrset
,
uint32_t
flags
,
time_t
lifespan
);
/// \brief Constructor for negative cache entry.
///
/// \param name Query name
/// \param rrclass Query class
/// \param rrtype Query type
/// \param flags Query response flags returned from the low-level
/// data source, indicating why this lookup failed (name not found,
/// type not found, etc).
/// \param lifespan How long the cache node is to be considered valid.
CacheNode
(
const
Name
&
name
,
const
RRClass
&
rrclass
,
const
RRType
&
rrtype
,
uint32_t
flags
,
time_t
lifespan
);
//@}
/// \name Getter and Setter Methods
//@{
/// \brief Returns a pointer to the cached RRset (or an empty
/// RRsetPtr for negative cache entries).
/// \return \c RRsetPtr
RRsetPtr
getRRset
()
const
{
return
(
entry
->
rrset
);
}
/// \brief Returns name associated with cached node
///
/// This is the name associated with the RRset if it is a positive
/// entry, and the associated question name if the RRSet is NULL
/// and this is a negative entry (together with an indication that
/// this is a negative entry).
string
getNodeName
()
const
{
if
(
getRRset
())
{
return
(
getRRset
()
->
getName
().
toText
());
}
return
(
std
::
string
(
"negative entry for "
)
+
question
.
toText
());
}
/// \brief Returns the query response flags associated with the data.
///
/// \return \c uint32_t
uint32_t
getFlags
()
const
{
return
(
entry
->
flags
);
}
/// \brief Is this record still valid?
///
/// \return True if the expiration time has not yet passed,
/// or false if it has.
bool
isValid
()
const
;
//@}
// An iterator referencing this entry in the LRU list. This
// permits unit-time removal using list::erase().
list
<
CacheNodePtr
>::
iterator
lru_entry_
;
/// The \c Question (name/rrclass/rrtype) answered by this cache node
const
isc
::
dns
::
Question
question
;
private:
// The cached RRset data
CacheEntryPtr
entry
;
// When this record should be discarded
time_t
expiry
;
};
// CacheNode constructor for a positive cache entry
CacheNode
::
CacheNode
(
const
RRsetPtr
rrset
,
const
uint32_t
flags
,
const
time_t
lifespan
)
:
question
(
Question
(
rrset
->
getName
(),
rrset
->
getClass
(),
rrset
->
getType
()))
{
const
time_t
now
=
time
(
NULL
);
expiry
=
now
+
lifespan
;
entry
=
CacheEntryPtr
(
new
CacheEntry
(
rrset
,
flags
));
}
// CacheNode constructor for a negative cache entry
CacheNode
::
CacheNode
(
const
Name
&
name
,
const
RRClass
&
rrclass
,
const
RRType
&
rrtype
,
const
uint32_t
flags
,
const
time_t
lifespan
)
:
question
(
Question
(
name
,
rrclass
,
rrtype
))
{
const
time_t
now
=
time
(
NULL
);
expiry
=
now
+
lifespan
;
entry
=
CacheEntryPtr
(
new
CacheEntry
(
RRsetPtr
(),
flags
));
}
// Returns true if the node has not yet expired.
bool
CacheNode
::
isValid
()
const
{
const
time_t
now
=
time
(
NULL
);
return
(
now
<
expiry
);
}
/// This class abstracts the implementation details for \c HotCache.
///
/// Each node inserted into the cache is placed at the head of a
/// doubly-linked list. Whenever that node is retrieved from the cache,
/// it is again moved to the head of the list. When the configured
/// number of slots in the cache has been exceeded, the least recently
/// used nodes will be removed from the tail of the list.
///
/// A pointer to each cache node is also placed in a \c std::map object,
/// keyed by \c isc::dns::Question. This allows retrieval of data in
/// (usually) logarithmic time. (Possible TODO item: replace this with a
/// hash table instead.)
class
HotCacheImpl
{
public:
HotCacheImpl
(
int
slots
,
bool
enabled
);
// The LRU list
list
<
CacheNodePtr
>
lru_
;
// Flag to indicate whether the cache is enabled
bool
enabled_
;
// The number of available slots in the LRU list. (If zero,
// then the list is unbounded; otherwise, items are removed
// from the tail of the list whenever it grows past slots_.)
int
slots_
;
// The number of items currently in the list.
int
count_
;
// Map from query tuple to cache node pointer, allowing fast retrieval
// of data without a linear search of the LRU list
std
::
map
<
Question
,
CacheNodePtr
>
map_
;
// Move a node to the front of the LRU list.
void
promote
(
CacheNodePtr
node
);
// Remove a node from the cache.
void
remove
(
ConstCacheNodePtr
node
);
// Insert a node into the cache (called by both cache() and ncache())
void
insert
(
CacheNodePtr
node
);
};
// HotCacheImpl constructor
HotCacheImpl
::
HotCacheImpl
(
int
slots
,
bool
enabled
)
:
enabled_
(
enabled
),
slots_
(
slots
),
count_
(
0
)
{
LOG_DEBUG
(
logger
,
DBG_TRACE_BASIC
,
DATASRC_CACHE_CREATE
);
}
// Insert a cache node into the cache
inline
void
HotCacheImpl
::
insert
(
const
CacheNodePtr
node
)
{
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_CACHE_INSERT
).
arg
(
node
->
getNodeName
());
std
::
map
<
Question
,
CacheNodePtr
>::
const_iterator
iter
;
iter
=
map_
.
find
(
node
->
question
);
if
(
iter
!=
map_
.
end
())
{
CacheNodePtr
old
=
iter
->
second
;
if
(
old
&&
old
->
isValid
())
{
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_CACHE_OLD_FOUND
)
.
arg
(
node
->
getNodeName
());
remove
(
old
);
}
}
lru_
.
push_front
(
node
);
node
->
lru_entry_
=
lru_
.
begin
();
map_
[
node
->
question
]
=
node
;
++
count_
;
if
(
slots_
!=
0
&&
count_
>
slots_
)
{
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_CACHE_FULL
);
remove
(
lru_
.
back
());
}
}
// Promote a node to the head of the LRU list
void
HotCacheImpl
::
promote
(
CacheNodePtr
node
)
{
if
(
!
node
)
{
return
;
}
if
(
node
->
lru_entry_
==
lru_
.
begin
())
{
return
;
}
lru_
.
splice
(
lru_
.
begin
(),
lru_
,
node
->
lru_entry_
);
// move node to front
node
->
lru_entry_
=
lru_
.
begin
();
}
// Remove a node from the LRU list and the map
void
HotCacheImpl
::
remove
(
ConstCacheNodePtr
node
)
{
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_CACHE_REMOVE
).
arg
(
node
->
getNodeName
());
lru_
.
erase
(
node
->
lru_entry_
);
map_
.
erase
(
node
->
question
);
--
count_
;
}
// HotCache constructor
HotCache
::
HotCache
(
const
int
slots
)
{
impl_
=
new
HotCacheImpl
(
slots
,
true
);
}
// HotCache destructor
HotCache
::~
HotCache
()
{
LOG_DEBUG
(
logger
,
DBG_TRACE_BASIC
,
DATASRC_CACHE_DESTROY
);
delete
impl_
;
}
// Add a positive entry to the cache
void
HotCache
::
addPositive
(
RRsetPtr
rrset
,
const
uint32_t
flags
,
const
time_t
lifespan
)
{
if
(
!
impl_
->
enabled_
)
{
return
;
}
impl_
->
insert
(
CacheNodePtr
(
new
CacheNode
(
rrset
,
flags
,
lifespan
)));
}
// Add a negative entry to the cache
void
HotCache
::
addNegative
(
const
Name
&
name
,
const
RRClass
&
rrclass
,
const
RRType
&
rrtype
,
const
uint32_t
flags
,
const
time_t
lifespan
)
{
if
(
!
impl_
->
enabled_
)
{
return
;
}
if
(
rrtype
==
RRType
::
ANY
()
||
rrclass
==
RRClass
::
ANY
())
{
return
;
}
impl_
->
insert
(
CacheNodePtr
(
new
CacheNode
(
name
,
rrclass
,
rrtype
,
flags
,
lifespan
)));
}
// Try to retrieve an entry from the cache, returning true if
// it was found and valid.
bool
HotCache
::
retrieve
(
const
Name
&
n
,
const
RRClass
&
c
,
const
RRType
&
t
,
RRsetPtr
&
rrset
,
uint32_t
&
flags
)
{
if
(
!
impl_
->
enabled_
)
{
return
(
false
);
}
std
::
map
<
Question
,
CacheNodePtr
>::
const_iterator
iter
;
iter
=
impl_
->
map_
.
find
(
Question
(
n
,
c
,
t
));
if
(
iter
==
impl_
->
map_
.
end
())
{
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_CACHE_NOT_FOUND
).
arg
(
n
);
return
(
false
);
}
CacheNodePtr
node
=
iter
->
second
;
if
(
node
->
isValid
())
{
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_CACHE_FOUND
).
arg
(
n
);
impl_
->
promote
(
node
);
rrset
=
node
->
getRRset
();
flags
=
node
->
getFlags
();
return
(
true
);
}
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_CACHE_EXPIRED
).
arg
(
n
);
impl_
->
remove
(
node
);
return
(
false
);
}
// Set the number of slots in the cache.
void
HotCache
::
setSlots
(
const
int
slots
)
{
impl_
->
slots_
=
slots
;
if
(
!
impl_
->
enabled_
)
{
return
;
}
logger
.
info
(
DATASRC_CACHE_SLOTS
).
arg
(
slots
).
arg
(
max
(
0
,
impl_
->
count_
-
slots
));
while
(
impl_
->
slots_
!=
0
&&
impl_
->
count_
>
impl_
->
slots_
)
{
impl_
->
remove
(
impl_
->
lru_
.
back
());
}
}
// Return the number of slots in the cache
int
HotCache
::
getSlots
()
const
{
return
(
impl_
->
slots_
);
}
/// Enable or disable the cache
void
HotCache
::
setEnabled
(
const
bool
e
)
{
impl_
->
enabled_
=
e
;
if
(
e
)
{
logger
.
info
(
DATASRC_CACHE_ENABLE
);
}
else
{
logger
.
info
(
DATASRC_CACHE_DISABLE
);
}
}
/// Indicate whether the cache is enabled
bool
HotCache
::
getEnabled
()
const
{
return
(
impl_
->
enabled_
);
}
// Return the number of entries in the cache
int
HotCache
::
getCount
()
const
{
return
(
impl_
->
count_
);
}
}
}
src/lib/datasrc/cache.h
deleted
100644 → 0
View file @
77b10c70
// 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 __CACHE_H
#define __CACHE_H
#include <time.h>
#include <boost/shared_ptr.hpp>
#include <dns/rrset.h>
namespace
isc
{
namespace
dns
{
class
Name
;
class
RRClass
;
class
RRType
;
}
namespace
datasrc
{
class
CacheNode
;
typedef
boost
::
shared_ptr
<
CacheNode
>
CacheNodePtr
;
typedef
boost
::
shared_ptr
<
const
CacheNode
>
ConstCacheNodePtr
;
class
HotCacheImpl
;
/// \brief A \c HotCache is a hot-spot cache for one or more data sources.
///
/// A \c HotCache must be instantiated prior to creating a \c Query.
/// The same instance should be passed to the constructor for all queries,
/// so that all of them will be using the same cache.
///
/// The cache may contain positive or negative entries, indicating
/// whether the data does or does not exist in the underlying data
/// source. Entries have a fixed and limited lifespan (currently
/// set to 30 seconds, see LIFESPAN_ below). If a cache entry is
/// found which has exceeded its lifespan, it will not be returned
/// to the caller--exactly as if it had not been found.
///
/// The current 30 second cache entry lifespan is experimental. A longer
/// lifespan would improve performance somewhat; however, longer-lived
/// cache entries are more likely to be incorrect in the event that
/// the underlying data source had been updated. Depending on the
/// frequency of queries and the frequency of updates, longer or
/// shorter lifespans may be desirable -- it's even possible
/// we may want the lifespan to be set differently depending on
/// the zone or the data source (i.e., with an infinite lifespan
/// for cached data from a static data source). Additional benchmarking
/// and analysis will be needed for this.
///
/// The cache may be configured with a number of available slots for
/// for entries. When set to a nonzero value, no more than that number
/// of entries can exist in the cache. If more entries are inserted,
/// old entries will be dropped in "least recently used" order. If
/// set to zero, the cache size is unlimited. The current default is
/// based on one thousand queries per second, times the number of seconds
/// in the cache lifespan: 30,000 slots.
///
/// Notes to developers: The current implementation of HotCache uses
/// a std::map (keyed by isc::dns::Question) to locate nodes, so access
/// will generally be in O(log n) time. (XXX: This might be faster if a
/// hash table were used instead.)
///
/// A linked list is also maintained to keep track of recent accesses
/// to cache entries; each time an entry is accessed, it is moved to the
/// head of the list; when entries need to be removed, they are taken
/// from the tail of the list. This operation is not locked. BIND 10
/// does not currently use threads, but if it ever does (or if libdatasrc
/// is ever used by a threaded application), this will need to be
/// revisited.
class
HotCache
{
private:
/// \name Static definitions
//@{
/// \brief Default validity period for cache entries
static
const
int
LIFESPAN_
=
30
;
/// \brief Default number of slots in cache
static
const
int
SLOTS_
=
1000
*
LIFESPAN_
;
//@}
/// \name Constructors, Assignment Operator and Destructor.
///
/// Note: The copy constructor and the assignment operator are intentionally
/// defined as private.
//@{
HotCache
(
const
HotCache
&
source
);
HotCache
&
operator
=
(
const
HotCache
&
source
);
public:
/// \brief Constructor for HotCache
///
/// \param slots The number of slots available in the cache.
HotCache
(
const
int
slots
=
SLOTS_
);
/// \brief Destructor for HotCache
~
HotCache
();
//@}
/// \name Cache Manipulation Methods
//@{
/// \brief Enter a positive cache entry.
///
/// If an entry already exists in the cache which matches the
/// name/class/type of the RRset being cached, then the old entry
/// is removed before the the new one is inserted. (XXX: This is
/// currently slightly inefficient; it would be quicker to keep the
/// existing node and simply update the rrset, flags, and lifespan.)
///
/// \param rrset The \c RRset to cache.
/// \param flags The query response flags returned from the low-level
/// data source when this \c RRset was looked up.
/// \param lifespan How long the cache node is to be considered valid;
/// defaulting to 30 seconds.
void
addPositive
(
isc
::
dns
::
RRsetPtr
rrset
,
uint32_t
flags
,
time_t
lifespan
=
LIFESPAN_
);
/// \brief Enter a negative cache entry.
///
/// In the case of a negative cache entry there is no \c RRset to
/// cache, so instead a null \c RRsetPtr will be stored. Since the
/// name, class, and type cannot be retrieved from an \c RRset, they
/// must be specified in the parameters.
///
/// If an entry already exists in the cache which matches the
/// specified name/class/type, then the old entry is removed
/// before the the new one is inserted. (XXX: As noted in the comments
/// for addPositive(), this is currently slightly inefficient.)
///
/// \param name Query name
/// \param rrclass Query class
/// \param rrtype Query type
/// \param flags Query response flags returned from the low-level
/// data source, indicating why this lookup failed (name not found,
/// type not found, etc).
/// \param lifespan How long the cache node is to be considered valid;
/// defaulting to 30 seconds.
///
/// Note: 'rrclass' and 'rrtype' must refer to a specific class and
/// type; it is not meaningful to cache type or class ANY. Currently,
/// this condition is silently ignored.
void
addNegative
(
const
isc
::
dns
::
Name
&
name
,
const
isc
::
dns
::
RRClass
&
rrclass
,
const
isc
::
dns
::
RRType
&
rrtype
,
uint32_t
flags
,
time_t
lifespan
=
LIFESPAN_
);
/// \brief Retrieve (and promote) a record from the cache
///
/// Retrieves a record from the cache matching the given
/// query-tuple. Returns true if one is found. If it is a
/// positive cache entry, then 'rrset' is set to the cached
/// RRset. For both positive and negative cache entries, 'flags'
/// is set to the query response flags. The cache entry is
/// then promoted to the head of the LRU queue. (NOTE: Because
/// of this, "retrieve" cannot be implemented as a const method.)
///
/// \param qname The query name
/// \param qclass The query class
/// \param qtype The query type
/// \param rrset Returns the RRset found, if any, to the caller
/// \param flags Returns the flags, if any, to the caller
///
/// \return \c bool, true if data was found in the cache, false if not.
bool
retrieve
(
const
isc
::
dns
::
Name
&
qname
,
const
isc
::
dns
::
RRClass
&
qclass
,
const
isc
::
dns
::
RRType
&
qtype
,
isc
::
dns
::
RRsetPtr
&
rrset
,
uint32_t
&
flags
);
//@}
/// \name Getter and Setter Methods
//@{
/// \brief Sets the number of slots in the cache.
///
/// If slots is set to zero, the cache can grow without any imposed
/// limit. If slots is to set a lower number than the cache currently
/// contains, then the least recently used records will be purged from
/// the cache until the total number of items in the cache equals slots.
void
setSlots
(
int
slots
);
/// \brief Returns the number of slots in the cache.
int
getSlots
()
const
;
/// \brief Enable or disable the cache
void
setEnabled
(
bool
e
);
/// \brief Indicate whether the cache is enabled
bool
getEnabled
()
const
;
/// \brief Returns the number of nodes currently stored in the cache.
///