2526. [func] New named option "attach-cache" that allows multiple

			views to share a single cache to save memory and
			improve lookup efficiency. [RT 18905]
parent 2cc6eb92
2526. [func] New named option "attach-cache" that allows multiple
views to share a single cache to save memory and
improve lookup efficiency. [RT 18905]
2525. [func] New logging category "query-errors" to provide detailed
internal information about query failures, especially
about server failures. [RT #19027]
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.h,v 1.93 2008/04/03 05:55:51 marka Exp $ */
/* $Id: server.h,v 1.94 2009/01/09 22:24:36 jinmei Exp $ */
#ifndef NAMED_SERVER_H
#define NAMED_SERVER_H 1
......@@ -91,6 +91,7 @@ struct ns_server {
isc_boolean_t flushonshutdown;
isc_boolean_t log_queries; /*%< For BIND 8 compatibility */
ns_cachelist_t cachelist; /*%< Possibly shared caches */
dns_stats_t * nsstats; /*%< Server statistics */
dns_stats_t * rcvquerystats; /*% Incoming query statistics */
dns_stats_t * opcodestats; /*%< Incoming message statistics */
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: types.h,v 1.29 2008/01/17 23:46:59 tbox Exp $ */
/* $Id: types.h,v 1.30 2009/01/09 22:24:36 jinmei Exp $ */
#ifndef NAMED_TYPES_H
#define NAMED_TYPES_H 1
......@@ -24,6 +24,8 @@
#include <dns/types.h>
typedef struct ns_cache ns_cache_t;
typedef ISC_LIST(ns_cache_t) ns_cachelist_t;
typedef struct ns_client ns_client_t;
typedef struct ns_clientmgr ns_clientmgr_t;
typedef struct ns_query ns_query_t;
......
This diff is collapsed.
......@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: statschannel.c,v 1.15 2008/12/18 02:23:27 marka Exp $ */
/* $Id: statschannel.c,v 1.16 2009/01/09 22:24:36 jinmei Exp $ */
/*! \file */
......@@ -28,6 +28,7 @@
#include <isc/socket.h>
#include <isc/task.h>
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/opcode.h>
#include <dns/rdataclass.h>
......@@ -635,7 +636,7 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "bind"));
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
ISC_XMLCHAR "2.0"));
ISC_XMLCHAR "2.1"));
/* Set common fields for statistics dump */
dumparg.type = statsformat_xml;
......@@ -674,11 +675,15 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
cachestats = dns_db_getrrsetstats(view->cachedb);
if (cachestats != NULL) {
xmlTextWriterStartElement(writer,
ISC_XMLCHAR "cache");
TRY0(xmlTextWriterStartElement(writer,
ISC_XMLCHAR "cache"));
TRY0(xmlTextWriterWriteAttribute(writer,
ISC_XMLCHAR "name",
ISC_XMLCHAR
dns_cache_getname(view->cache)));
dns_rdatasetstats_dump(cachestats, rdatasetstats_dump,
&dumparg, 0);
xmlTextWriterEndElement(writer); /* cache */
TRY0(xmlTextWriterEndElement(writer)); /* cache */
}
xmlTextWriterEndElement(writer); /* view */
......@@ -1220,7 +1225,15 @@ ns_stats_dump(ns_server_t *server, FILE *fp) {
if (strcmp(view->name, "_default") == 0)
fprintf(fp, "[View: default]\n");
else
fprintf(fp, "[View: %s]\n", view->name);
fprintf(fp, "[View: %s (Cache: %s)]\n", view->name,
dns_cache_getname(view->cache));
if (dns_view_iscacheshared(view)) {
/*
* Avoid dumping redundant statistics when the cache is
* shared.
*/
continue;
}
dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg,
0);
}
......
......@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- File: $Id: Bv9ARM-book.xml,v 1.385 2009/01/08 14:19:05 jreed Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.386 2009/01/09 22:24:36 jinmei Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
......@@ -4706,6 +4706,7 @@ category notify { null; };
</para>
<programlisting><command>options</command> {
<optional> attach-cache <replaceable>cache_name</replaceable>; </optional>
<optional> version <replaceable>version_string</replaceable>; </optional>
<optional> hostname <replaceable>hostname_string</replaceable>; </optional>
<optional> server-id <replaceable>server_id_string</replaceable>; </optional>
......@@ -4888,6 +4889,102 @@ category notify { null; };
<variablelist>
<varlistentry>
<term><command>attach-cache</command></term>
<listitem>
<para>
Allows multiple views to share a single cache
database.
Each view has its own cache database by default, but
if multiple views have the same operational policy
for name resolution and caching, those views can
share a single cache to save memory and possibly
improve resolution efficiency by using this option.
</para>
<para>
The <command>attach-cache</command> option
may also be specified in <command>view</command>
statements, in which case it overrides the
global <command>attach-cache</command> option.
</para>
<para>
The <replaceable>cache_name</replaceable> specifies
the cache to be shared.
When the <command>named</command> server configures
views which are supposed to share a cache, it
creates a cache with the specified name for the
first view of these sharing views.
The rest of the views will simply refer to the
already created cache.
</para>
<para>
One common configuration to share a cache would be to
allow all views to share a single cache.
This can be done by specifying
the <command>attach-cache</command> as a global
option with an arbitrary name.
</para>
<para>
Another possible operation is to allow a subset of
all views to share a cache while the others to
retain their own caches.
For example, if there are three views A, B, and C,
and only A and B should share a cache, specify the
<command>attach-cache</command> option as a view A (or
B)'s option, referring to the other view name:
</para>
<programlisting>
view "A" {
// this view has its own cache
...
};
view "B" {
// this view refers to A's cache
attach-cache "A";
};
view "C" {
// this view has its own cache
...
};
</programlisting>
<para>
Views that share a cache must have the same policy
on configurable parameters that may affect caching.
The current implementation requires the following
configurable options be consistent among these
views:
<command>check-names</command>,
<command>cleaning-interval</command>,
<command>dnssec-accept-expired</command>,
<command>dnssec-validation</command>,
<command>max-cache-ttl</command>,
<command>max-ncache-ttl</command>,
<command>max-cache-size</command>, and
<command>zero-no-soa-ttl</command>.
</para>
<para>
Note that there may be other parameters that may
cause confusion if they are inconsistent for
different views that share a single cache.
For example, if these views define different sets of
forwarders that can return different answers for the
same question, sharing the answer does not make
sense or could even be harmful.
It is administrator's responsibility to ensure
configuration differences in different views do
not cause disruption with a shared cache.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>directory</command></term>
<listitem>
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: cache.c,v 1.80 2008/09/24 02:46:22 marka Exp $ */
/* $Id: cache.c,v 1.81 2009/01/09 22:24:36 jinmei Exp $ */
/*! \file */
......@@ -122,6 +122,7 @@ struct dns_cache {
isc_mutex_t lock;
isc_mutex_t filelock;
isc_mem_t *mctx;
char *name;
/* Locked by 'lock'. */
int references;
......@@ -132,6 +133,7 @@ struct dns_cache {
char *db_type;
int db_argc;
char **db_argv;
isc_uint32_t size;
/* Locked by 'filelock'. */
char *filename;
......@@ -170,6 +172,16 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
const char *db_type, unsigned int db_argc, char **db_argv,
dns_cache_t **cachep)
{
return (dns_cache_create2(mctx, taskmgr, timermgr, rdclass, "",
db_type, db_argc, db_argv, cachep));
}
isc_result_t
dns_cache_create2(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
const char *cachename, const char *db_type,
unsigned int db_argc, char **db_argv, dns_cache_t **cachep)
{
isc_result_t result;
dns_cache_t *cache;
......@@ -178,6 +190,7 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
REQUIRE(cachep != NULL);
REQUIRE(*cachep == NULL);
REQUIRE(mctx != NULL);
REQUIRE(cachename != NULL);
cache = isc_mem_get(mctx, sizeof(*cache));
if (cache == NULL)
......@@ -186,6 +199,15 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
cache->mctx = NULL;
isc_mem_attach(mctx, &cache->mctx);
cache->name = NULL;
if (cachename != NULL) {
cache->name = isc_mem_strdup(mctx, cachename);
if (cache->name == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup_mem;
}
}
result = isc_mutex_init(&cache->lock);
if (result != ISC_R_SUCCESS)
goto cleanup_mem;
......@@ -266,6 +288,8 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
cleanup_lock:
DESTROYLOCK(&cache->lock);
cleanup_mem:
if (cache->name != NULL)
isc_mem_free(mctx, cache->name);
isc_mem_put(mctx, cache, sizeof(*cache));
isc_mem_detach(&mctx);
return (result);
......@@ -314,6 +338,9 @@ cache_free(dns_cache_t *cache) {
if (cache->db_type != NULL)
isc_mem_free(cache->mctx, cache->db_type);
if (cache->name != NULL)
isc_mem_free(cache->mctx, cache->name);
DESTROYLOCK(&cache->lock);
DESTROYLOCK(&cache->filelock);
cache->magic = 0;
......@@ -484,6 +511,26 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int t) {
UNLOCK(&cache->lock);
}
unsigned int
dns_cache_getcleaninginterval(dns_cache_t *cache) {
unsigned int t;
REQUIRE(VALID_CACHE(cache));
LOCK(&cache->lock);
t = cache->cleaner.cleaning_interval;
UNLOCK(&cache->lock);
return (t);
}
const char *
dns_cache_getname(dns_cache_t *cache) {
REQUIRE(VALID_CACHE(cache));
return (cache->name);
}
/*
* Initialize the cache cleaner object at *cleaner.
* Space for the object must be allocated by the caller.
......@@ -510,6 +557,7 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
cleaner->cleaning_timer = NULL;
cleaner->resched_event = NULL;
cleaner->overmem_event = NULL;
cleaner->cleaning_interval = 0; /* Initially turned off. */
result = dns_db_createiterator(cleaner->cache->db, ISC_FALSE,
&cleaner->iterator);
......@@ -538,7 +586,6 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
goto cleanup;
}
cleaner->cleaning_interval = 0; /* Initially turned off. */
result = isc_timer_create(timermgr, isc_timertype_inactive,
NULL, NULL, cleaner->task,
cleaning_timer_action, cleaner,
......@@ -940,6 +987,10 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) {
if (size != 0 && size < DNS_CACHE_MINSIZE)
size = DNS_CACHE_MINSIZE;
LOCK(&cache->lock);
cache->size = size;
UNLOCK(&cache->lock);
hiwater = size - (size >> 3); /* Approximately 7/8ths. */
lowater = size - (size >> 2); /* Approximately 3/4ths. */
......@@ -963,6 +1014,19 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) {
isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater);
}
isc_uint32_t
dns_cache_getcachesize(dns_cache_t *cache) {
isc_uint32_t size;
REQUIRE(VALID_CACHE(cache));
LOCK(&cache->lock);
size = cache->size;
UNLOCK(&cache->lock);
return (size);
}
/*
* The cleaner task is shutting down; do the necessary cleanup.
*/
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: cache.h,v 1.26 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: cache.h,v 1.27 2009/01/09 22:24:37 jinmei Exp $ */
#ifndef DNS_CACHE_H
#define DNS_CACHE_H 1
......@@ -65,8 +65,15 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
const char *db_type, unsigned int db_argc, char **db_argv,
dns_cache_t **cachep);
isc_result_t
dns_cache_create2(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
const char *cachename, const char *db_type,
unsigned int db_argc, char **db_argv, dns_cache_t **cachep);
/*%<
* Create a new DNS cache.
* Create a new DNS cache. dns_cache_create2() will create a named cache.
* dns_cache_create() is a backward compatible version that internally specifies
* an empty name.
*
* Requires:
*
......@@ -76,6 +83,8 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
* manager, or both are NULL. If NULL, no periodic cleaning of the
* cache will take place.
*
*\li 'cachename' is a valid string. This must not be NULL.
*
*\li 'cachep' is a valid pointer, and *cachep == NULL
*
* Ensures:
......@@ -217,12 +226,36 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int interval);
* Set the periodic cache cleaning interval to 'interval' seconds.
*/
unsigned int
dns_cache_getcleaninginterval(dns_cache_t *cache);
/*%<
* Get the periodic cache cleaning interval to 'interval' seconds.
*/
isc_uint32_t
dns_cache_getcachesize(dns_cache_t *cache);
/*%<
* Get the maximum cache size.
*/
const char *
dns_cache_getname(dns_cache_t *cache);
/*%<
* Get the cache name.
*/
void
dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size);
/*%<
* Set the maximum cache size. 0 means unlimited.
*/
isc_uint32_t
dns_cache_getcachesize(dns_cache_t *cache);
/*%<
* Get the maximum cache size.
*/
isc_result_t
dns_cache_flush(dns_cache_t *cache);
/*%<
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: view.h,v 1.113 2009/01/05 23:47:53 tbox Exp $ */
/* $Id: view.h,v 1.114 2009/01/09 22:24:37 jinmei Exp $ */
#ifndef DNS_VIEW_H
#define DNS_VIEW_H 1
......@@ -102,6 +102,7 @@ struct dns_view {
isc_event_t reqevent;
dns_stats_t * resstats;
dns_stats_t * resquerystats;
isc_boolean_t cacheshared;
/* Configurable data. */
dns_tsig_keyring_t * statickeys;
......@@ -308,8 +309,12 @@ dns_view_createresolver(dns_view_t *view,
void
dns_view_setcache(dns_view_t *view, dns_cache_t *cache);
void
dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared);
/*%<
* Set the view's cache database.
* Set the view's cache database. If 'shared' is true, this means the cache
* is created by another view and is shared with that view. dns_view_setcache()
* is a backward compatible version equivalent to setcache2(..., ISC_FALSE).
*
* Requires:
*
......@@ -726,8 +731,14 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp);
isc_result_t
dns_view_flushcache(dns_view_t *view);
isc_result_t
dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly);
/*%<
* Flush the view's cache (and ADB).
* Flush the view's cache (and ADB). If 'fixuponly' is true, it only updates
* the internal reference to the cache DB with omitting actual flush operation.
* 'fixuponly' is intended to be used for a view that shares a cache with
* a different view. dns_view_flushcache() is a backward compatible version
* that always sets fixuponly to false.
*
* Requires:
* 'view' is valid.
......@@ -876,4 +887,17 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp);
*\li 'statsp' != NULL && '*statsp' != NULL
*/
isc_boolean_t
dns_view_iscacheshared(dns_view_t *view);
/*%<
* Check if the view shares the cache created by another view.
*
* Requires:
* \li 'view' is valid.
*
* Returns:
*\li #ISC_TRUE if the cache is shared.
*\li #ISC_FALSE othewise.
*/
#endif /* DNS_VIEW_H */
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: view.c,v 1.150 2008/06/17 03:14:20 marka Exp $ */
/* $Id: view.c,v 1.151 2009/01/09 22:24:36 jinmei Exp $ */
/*! \file */
......@@ -154,6 +154,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->rootexclude = NULL;
view->resstats = NULL;
view->resquerystats = NULL;
view->cacheshared = ISC_FALSE;
/*
* Initialize configuration data with default values.
......@@ -626,9 +627,15 @@ dns_view_createresolver(dns_view_t *view,
void
dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
dns_view_setcache2(view, cache, ISC_FALSE);
}
void
dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
view->cacheshared = shared;
if (view->cache != NULL) {
if (view->acache != NULL)
dns_acache_putdb(view->acache, view->cachedb);
......@@ -643,6 +650,13 @@ dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
dns_acache_setdb(view->acache, view->cachedb);
}
isc_boolean_t
dns_view_iscacheshared(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
return (view->cacheshared);
}
void
dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
REQUIRE(DNS_VIEW_VALID(view));
......@@ -1278,15 +1292,22 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
isc_result_t
dns_view_flushcache(dns_view_t *view) {
return (dns_view_flushcache2(view, ISC_FALSE));
}
isc_result_t
dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) {
isc_result_t result;
REQUIRE(DNS_VIEW_VALID(view));
if (view->cachedb == NULL)
return (ISC_R_SUCCESS);
result = dns_cache_flush(view->cache);
if (result != ISC_R_SUCCESS)
return (result);
if (!fixuponly) {
result = dns_cache_flush(view->cache);
if (result != ISC_R_SUCCESS)
return (result);
}
if (view->acache != NULL)
dns_acache_putdb(view->acache, view->cachedb);
dns_db_detach(&view->cachedb);
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: namedconf.c,v 1.92 2008/09/27 23:35:31 jinmei Exp $ */
/* $Id: namedconf.c,v 1.93 2009/01/09 22:24:37 jinmei Exp $ */
/*! \file */
......@@ -797,6 +797,7 @@ view_clauses[] = {
{ "allow-recursion-on", &cfg_type_bracketed_aml, 0 },
{ "allow-v6-synthesis", &cfg_type_bracketed_aml,
CFG_CLAUSEFLAG_OBSOLETE },
{ "attach-cache", &cfg_type_astring, 0 },
{ "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT },
{ "cache-file", &cfg_type_qstring, 0 },
{ "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment