Commit 42cf2ff7 authored by Evan Hunt's avatar Evan Hunt
Browse files

3131. [func] Improve scalability by allocating one zone task

			per 100 zones at startup time, rather than using a
			fixed-size task table. [RT #24406]
parent 007eafcd
3131. [func] Improve scalability by allocating one zone task
per 100 zones at startup time, rather than using a
fixed-size task table. [RT #24406]
3130. [func] Support alternate methods for managing a dynamic
zone's serial number. Two methods are currently
defined using serial-update-method, "increment"
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.612 2011/06/17 07:05:01 each Exp $ */
/* $Id: server.c,v 1.613 2011/07/06 01:36:31 each Exp $ */
/*! \file */
......@@ -204,12 +204,14 @@ struct zonelistentry {
/*%
* Configuration context to retain for each view that allows
* new zones to be added at runtime
* new zones to be added at runtime.
*/
struct cfg_context {
isc_mem_t * mctx;
cfg_obj_t * config;
cfg_parser_t * parser;
cfg_obj_t * config;
cfg_parser_t * nzparser;
cfg_obj_t * nzconfig;
cfg_aclconfctx_t * actx;
};
......@@ -1545,8 +1547,7 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
* global defaults in 'config' used exclusively.
*/
static isc_result_t
configure_view(dns_view_t *view, cfg_parser_t* parser,
cfg_obj_t *config, cfg_obj_t *vconfig,
configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys,
isc_mem_t *mctx, cfg_aclconfctx_t *actx,
isc_boolean_t need_hints)
......@@ -1601,10 +1602,9 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
isc_boolean_t auto_root = ISC_FALSE;
ns_cache_t *nsc;
isc_boolean_t zero_no_soattl;
cfg_parser_t *newzones_parser = NULL;
cfg_obj_t *nzfconf = NULL;
dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
unsigned int query_timeout;
struct cfg_context *nzctx;
REQUIRE(DNS_VIEW_VALID(view));
......@@ -1710,6 +1710,10 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
(void)cfg_map_get(voptions, "zone", &zonelist);
else
(void)cfg_map_get(config, "zone", &zonelist);
/*
* Load zone configuration
*/
for (element = cfg_list_first(zonelist);
element != NULL;
element = cfg_list_next(element))
......@@ -1719,58 +1723,29 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
actx, ISC_FALSE));
}
/*
* Are we allowing zones to be added and deleted dynamically?
*/
obj = NULL;
result = ns_config_get(maps, "allow-new-zones", &obj);
if (result == ISC_R_SUCCESS) {
isc_boolean_t allow = cfg_obj_asboolean(obj);
struct cfg_context *cfg = NULL;
if (allow) {
cfg = isc_mem_get(view->mctx, sizeof(*cfg));
if (cfg == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
memset(cfg, 0, sizeof(*cfg));
isc_mem_attach(view->mctx, &cfg->mctx);
if (config != NULL)
cfg_obj_attach(config, &cfg->config);
cfg_parser_attach(parser, &cfg->parser);
cfg_aclconfctx_attach(actx, &cfg->actx);
}
dns_view_setnewzones(view, allow, cfg, newzone_cfgctx_destroy);
}
/*
* If we're allowing added zones, then load zone configuration
* from the newzone file for zones that were added during previous
* runs.
*/
if (view->new_zone_file != NULL) {
nzctx = view->new_zone_config;
if (nzctx != NULL && nzctx->nzconfig != NULL) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
"loading additional zones for view '%s'",
view->name);
CHECK(cfg_parser_create(view->mctx, ns_g_lctx,
&newzones_parser));
result = cfg_parse_file(newzones_parser, view->new_zone_file,
&cfg_type_newzones, &nzfconf);
if (result == ISC_R_SUCCESS) {
zonelist = NULL;
cfg_map_get(nzfconf, "zone", &zonelist);
for (element = cfg_list_first(zonelist);
element != NULL;
element = cfg_list_next(element))
{
const cfg_obj_t *zconfig =
cfg_listelt_value(element);
CHECK(configure_zone(config, zconfig, vconfig,
mctx, view, actx,
ISC_TRUE));
}
zonelist = NULL;
cfg_map_get(nzctx->nzconfig, "zone", &zonelist);
for (element = cfg_list_first(zonelist);
element != NULL;
element = cfg_list_next(element))
{
const cfg_obj_t *zconfig = cfg_listelt_value(element);
CHECK(configure_zone(config, zconfig, vconfig,
mctx, view, actx,
ISC_TRUE));
}
}
......@@ -2904,8 +2879,8 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
if (result == ISC_R_SUCCESS)
cfg_map_get(obj, "zone", &zonelist);
}
if (zonelist != NULL) {
if (zonelist != NULL) {
for (element = cfg_list_first(zonelist);
element != NULL;
element = cfg_list_next(element)) {
......@@ -2947,12 +2922,6 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
if (cache != NULL)
dns_cache_detach(&cache);
if (newzones_parser != NULL) {
if (nzfconf != NULL)
cfg_obj_destroy(newzones_parser, &nzfconf);
cfg_parser_destroy(&newzones_parser);
}
return (result);
}
......@@ -3157,21 +3126,16 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
return (result);
}
/*
* Create a new view and add it to the list.
*
* If 'vconfig' is NULL, create the default view.
*
* The view created is attached to '*viewp'.
*/
static isc_result_t
create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
dns_view_t **viewp)
get_viewinfo(const cfg_obj_t *vconfig, const char **namep,
dns_rdataclass_t *classp)
{
isc_result_t result;
isc_result_t result = ISC_R_SUCCESS;
const char *viewname;
dns_rdataclass_t viewclass;
dns_view_t *view = NULL;
REQUIRE(namep != NULL && *namep == NULL);
REQUIRE(classp != NULL);
if (vconfig != NULL) {
const cfg_obj_t *classobj = NULL;
......@@ -3180,11 +3144,63 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
classobj = cfg_tuple_get(vconfig, "class");
result = ns_config_getclass(classobj, dns_rdataclass_in,
&viewclass);
INSIST(result == ISC_R_SUCCESS);
} else {
viewname = "_default";
viewclass = dns_rdataclass_in;
}
*namep = viewname;
*classp = viewclass;
return (result);
}
/*
* Find a view based on its configuration info and attach to it.
*
* If 'vconfig' is NULL, attach to the default view.
*/
static isc_result_t
find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
dns_view_t **viewp)
{
isc_result_t result;
const char *viewname = NULL;
dns_rdataclass_t viewclass;
dns_view_t *view = NULL;
result = get_viewinfo(vconfig, &viewname, &viewclass);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
if (result != ISC_R_SUCCESS)
return (result);
*viewp = view;
return (ISC_R_SUCCESS);
}
/*
* Create a new view and add it to the list.
*
* If 'vconfig' is NULL, create the default view.
*
* The view created is attached to '*viewp'.
*/
static isc_result_t
create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
dns_view_t **viewp)
{
isc_result_t result;
const char *viewname = NULL;
dns_rdataclass_t viewclass;
dns_view_t *view = NULL;
result = get_viewinfo(vconfig, &viewname, &viewclass);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
if (result == ISC_R_SUCCESS)
return (ISC_R_EXISTS);
......@@ -4175,6 +4191,95 @@ configure_session_key(const cfg_obj_t **maps, ns_server_t *server,
return (result);
}
static isc_result_t
setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
cfg_parser_t *parser, cfg_aclconfctx_t *actx)
{
isc_result_t result = ISC_R_SUCCESS;
isc_boolean_t allow = ISC_FALSE;
struct cfg_context *nzcfg = NULL;
cfg_parser_t *nzparser = NULL;
cfg_obj_t *nzconfig = NULL;
const cfg_obj_t *maps[4];
const cfg_obj_t *options = NULL, *voptions = NULL;
const cfg_obj_t *nz = NULL;
int i = 0;
REQUIRE (config != NULL);
if (vconfig != NULL)
voptions = cfg_tuple_get(vconfig, "options");
if (voptions != NULL)
maps[i++] = voptions;
result = cfg_map_get(config, "options", &options);
if (result == ISC_R_SUCCESS)
maps[i++] = options;
maps[i++] = ns_g_defaults;
maps[i] = NULL;
result = ns_config_get(maps, "allow-new-zones", &nz);
if (result == ISC_R_SUCCESS)
allow = cfg_obj_asboolean(nz);
if (!allow) {
dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
return (ISC_R_SUCCESS);
}
nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg));
if (nzcfg == NULL) {
dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
return (ISC_R_NOMEMORY);
}
dns_view_setnewzones(view, allow, nzcfg, newzone_cfgctx_destroy);
memset(nzcfg, 0, sizeof(*nzcfg));
isc_mem_attach(view->mctx, &nzcfg->mctx);
cfg_obj_attach(config, &nzcfg->config);
cfg_parser_attach(parser, &nzcfg->parser);
cfg_aclconfctx_attach(actx, &nzcfg->actx);
/*
* Attempt to create a parser and parse the newzones
* file. If successful, preserve both; otherwise leave
* them NULL.
*/
result = cfg_parser_create(view->mctx, ns_g_lctx, &nzparser);
if (result == ISC_R_SUCCESS)
result = cfg_parse_file(nzparser, view->new_zone_file,
&cfg_type_newzones, &nzconfig);
if (result == ISC_R_SUCCESS) {
cfg_parser_attach(nzparser, &nzcfg->nzparser);
cfg_obj_attach(nzconfig, &nzcfg->nzconfig);
}
if (nzparser != NULL) {
if (nzconfig != NULL)
cfg_obj_destroy(nzparser, &nzconfig);
cfg_parser_destroy(&nzparser);
}
return (ISC_R_SUCCESS);
}
static int
count_zones(const cfg_obj_t *conf) {
const cfg_obj_t *zonelist = NULL;
const cfg_listelt_t *element;
int n = 0;
REQUIRE(conf != NULL);
cfg_map_get(conf, "zone", &zonelist);
for (element = cfg_list_first(zonelist);
element != NULL;
element = cfg_list_next(element))
n++;
return (n);
}
static isc_result_t
load_configuration(const char *filename, ns_server_t *server,
isc_boolean_t first_time)
......@@ -4206,6 +4311,8 @@ load_configuration(const char *filename, ns_server_t *server,
ns_cachelist_t cachelist, tmpcachelist;
unsigned int maxsocks;
ns_cache_t *nsc;
struct cfg_context *nzctx;
int num_zones = 0;
ISC_LIST_INIT(viewlist);
ISC_LIST_INIT(builtin_viewlist);
......@@ -4633,25 +4740,87 @@ load_configuration(const char *filename, ns_server_t *server,
*/
(void)configure_session_key(maps, server, ns_g_mctx);
/*
* Configure and freeze all explicit views. Explicit
* views that have zones were already created at parsing
* time, but views with no zones must be created here.
*/
views = NULL;
(void)cfg_map_get(config, "view", &views);
/*
* Create the views and count all the configured zones in
* order to correctly size the zone manager's task table.
* (We only count zones for configured views; the built-in
* "bind" view can be ignored as it only adds a negligible
* number of zones.)
*
* If we're allowing new zones, we need to be able to find the
* new zone file and count those as well. So we setup the new
* zone configuration context, but otherwise view configuration
* waits until after the zone manager's task list has been sized.
*/
for (element = cfg_list_first(views);
element != NULL;
element = cfg_list_next(element))
{
cfg_obj_t *vconfig = cfg_listelt_value(element);
const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options");
view = NULL;
CHECK(create_view(vconfig, &viewlist, &view));
INSIST(view != NULL);
CHECK(configure_view(view, conf_parser, config, vconfig,
&cachelist, bindkeys,
ns_g_mctx, ns_g_aclconfctx, ISC_TRUE));
num_zones += count_zones(voptions);
CHECK(setup_newzones(view, config, vconfig, conf_parser,
ns_g_aclconfctx));
nzctx = view->new_zone_config;
if (nzctx != NULL && nzctx->nzconfig != NULL)
num_zones += count_zones(nzctx->nzconfig);
dns_view_detach(&view);
}
/*
* If there were no explicit views then we do the default
* view here.
*/
if (views == NULL) {
CHECK(create_view(NULL, &viewlist, &view));
INSIST(view != NULL);
num_zones = count_zones(config);
CHECK(setup_newzones(view, config, NULL, conf_parser,
ns_g_aclconfctx));
nzctx = view->new_zone_config;
if (nzctx != NULL && nzctx->nzconfig != NULL)
num_zones += count_zones(nzctx->nzconfig);
dns_view_detach(&view);
}
/*
* Zones have been counted; set the zone manager task pool size.
*/
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
"sizing zone task pool based on %d zones", num_zones);
CHECK(dns_zonemgr_setsize(ns_g_server->zonemgr, num_zones));
/*
* Configure and freeze all explicit views. Explicit
* views that have zones were already created at parsing
* time, but views with no zones must be created here.
*/
for (element = cfg_list_first(views);
element != NULL;
element = cfg_list_next(element))
{
cfg_obj_t *vconfig = cfg_listelt_value(element);
view = NULL;
CHECK(find_view(vconfig, &viewlist, &view));
CHECK(configure_view(view, config, vconfig,
&cachelist, bindkeys, ns_g_mctx,
ns_g_aclconfctx, ISC_TRUE));
dns_view_freeze(view);
dns_view_detach(&view);
}
......@@ -4661,14 +4830,9 @@ load_configuration(const char *filename, ns_server_t *server,
* were no explicit views.
*/
if (views == NULL) {
/*
* No explicit views; there ought to be a default view.
* There may already be one created as a side effect
* of zone statements, or we may have to create one.
* In either case, we need to configure and freeze it.
*/
CHECK(create_view(NULL, &viewlist, &view));
CHECK(configure_view(view, conf_parser, config, NULL,
view = NULL;
CHECK(find_view(NULL, &viewlist, &view));
CHECK(configure_view(view, config, NULL,
&cachelist, bindkeys,
ns_g_mctx, ns_g_aclconfctx, ISC_TRUE));
dns_view_freeze(view);
......@@ -4688,7 +4852,7 @@ load_configuration(const char *filename, ns_server_t *server,
cfg_obj_t *vconfig = cfg_listelt_value(element);
CHECK(create_view(vconfig, &builtin_viewlist, &view));
CHECK(configure_view(view, conf_parser, config, vconfig,
CHECK(configure_view(view, config, vconfig,
&cachelist, bindkeys,
ns_g_mctx, ns_g_aclconfctx, ISC_FALSE));
dns_view_freeze(view);
......@@ -5311,6 +5475,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
ns_g_socketmgr, &server->zonemgr),
"dns_zonemgr_create");
CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000),
"dns_zonemgr_setsize");
server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
......@@ -5420,7 +5586,8 @@ ns_server_destroy(ns_server_t **serverp) {
if (server->server_id != NULL)
isc_mem_free(server->mctx, server->server_id);
dns_zonemgr_detach(&server->zonemgr);
if (server->zonemgr != NULL)
dns_zonemgr_detach(&server->zonemgr);
if (server->tkeyctx != NULL)
dns_tkeyctx_destroy(&server->tkeyctx);
......@@ -7589,6 +7756,11 @@ newzone_cfgctx_destroy(void **cfgp) {
cfg_obj_destroy(cfg->parser, &cfg->config);
cfg_parser_destroy(&cfg->parser);
}
if (cfg->nzparser != NULL) {
if (cfg->nzconfig != NULL)
cfg_obj_destroy(cfg->nzparser, &cfg->nzconfig);
cfg_parser_destroy(&cfg->nzparser);
}
isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg));
*cfgp = NULL;
......
This diff is collapsed.
......@@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl
esyscmd([sed "s/^/# /" COPYRIGHT])dnl
AC_DIVERT_POP()dnl
AC_REVISION($Revision: 1.526 $)
AC_REVISION($Revision: 1.527 $)
AC_INIT(lib/dns/name.c)
AC_PREREQ(2.59)
......@@ -3508,6 +3508,7 @@ AC_CONFIG_FILES([
lib/isc/include/Makefile
lib/isc/include/isc/Makefile
lib/isc/include/isc/platform.h
lib/isc/tests/Makefile
lib/isc/nls/Makefile
lib/isc/unix/Makefile
lib/isc/unix/include/Makefile
......
......@@ -3,3 +3,4 @@ Content-Type: application/X-atf-atffile; version="1"
prop: test-suite = bind9
tp: dns
tp: isc
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: zone.h,v 1.190 2011/07/01 02:25:48 marka Exp $ */
/* $Id: zone.h,v 1.191 2011/07/06 01:36:32 each Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
......@@ -1388,7 +1388,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
dns_zonemgr_t **zmgrp);
/*%<
* Create a zone manager.
* Create a zone manager. Note: the zone manager will not be able to
* manage any zones until dns_zonemgr_setsize() has been run.
*
* Requires:
*\li 'mctx' to be a valid memory context.
......@@ -1397,6 +1398,18 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
*\li 'zmgrp' to point to a NULL pointer.
*/
isc_result_t
dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones);
/*%<
* Set the size of the zone manager task pool. This must be run
* before zmgr can be used for managing zones. Currently, it can only
* be run once; the task pool cannot be resized.
*
* Requires:
*\li zmgr is a valid zone manager.
*\li zmgr->zonetasks has been initialized.
*/
isc_result_t
dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
/*%<
......
......@@ -12,7 +12,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.4 2011/07/01 02:25:48 marka Exp $
# $Id: Makefile.in,v 1.5 2011/07/06 01:36:32 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
......@@ -37,10 +37,12 @@ DNSDEPLIBS = ../libdns.@A@
LIBS = @LIBS@ @ATFLIBS@
OBJS = dnstest.@O@
SRCS = dnstest.c master_test.c time_test.c update_test.c
SRCS = dnstest.c master_test.c time_test.c update_test.c \
zonemgr_test.c
SUBDIRS =
TARGETS = master_test@EXEEXT@ time_test@EXEEXT@ update_test@EXEEXT@
TARGETS = master_test@EXEEXT@ time_test@EXEEXT@ update_test@EXEEXT@ \
zonemgr_test@EXEEXT@
@BIND9_MAKE_RULES@
......@@ -59,5 +61,10 @@ update_test@EXEEXT@: update_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
update_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
zonemgr_test@EXEEXT@: zonemgr_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
zonemgr_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
clean distclean::
rm -f ${TARGETS}
......@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dnstest.c,v 1.3 2011/03/01 23:48:07 tbox Exp $ */
/* $Id: dnstest.c,v 1.4 2011/07/06 01:36:32 each Exp $ */
/*! \file */
......@@ -25,7 +25,11 @@
#include <isc/entropy.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/os.h>
#include <isc/string.h>
#include <isc/socket.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
#include <dns/log.h>
......@@ -39,6 +43,10 @@