2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 18:19:42 +00:00

4223. [func] Add support for setting max-cache-size to percentage

of available physical memory, set default to 90%.
			[RT #38442]
This commit is contained in:
Witold Krecicki 2015-09-28 11:08:50 +02:00
parent 98a7f8c7ae
commit e6d0a391f5
20 changed files with 396 additions and 29 deletions

1
.gitignore vendored
View File

@ -54,3 +54,4 @@ unit/atf-src/test-programs/cpp_helpers
unit/atf-src/test-programs/sh_helpers unit/atf-src/test-programs/sh_helpers
# ccc-analyzer store its results in .plist directories # ccc-analyzer store its results in .plist directories
*.plist/ *.plist/
*~

View File

@ -1,3 +1,7 @@
4223. [func] Add support for setting max-cache-size to percentage
of available physical memory, set default to 90%.
[RT #38442]
4222. [func] Bias IPv6 servers when selecting the next server to 4222. [func] Bias IPv6 servers when selecting the next server to
query. [RT #40836] query. [RT #40836]

View File

@ -368,6 +368,7 @@ do_authors_lookup(dns_sdblookup_t *lookup) {
"Bob Halley", "Bob Halley",
"Evan Hunt", "Evan Hunt",
"JINMEI Tatuya", "JINMEI Tatuya",
"Witold Krecicki",
"David Lawrence", "David Lawrence",
"Scott Mann", "Scott Mann",
"Danny Mayer", "Danny Mayer",

View File

@ -160,7 +160,7 @@ options {\n\
max-ncache-ttl 10800; /* 3 hours */\n\ max-ncache-ttl 10800; /* 3 hours */\n\
max-cache-ttl 604800; /* 1 week */\n\ max-cache-ttl 604800; /* 1 week */\n\
transfer-format many-answers;\n\ transfer-format many-answers;\n\
max-cache-size 0;\n\ max-cache-size 90%;\n\
check-names master fail;\n\ check-names master fail;\n\
check-names slave warn;\n\ check-names slave warn;\n\
check-names response ignore;\n\ check-names response ignore;\n\

View File

@ -37,6 +37,7 @@
#include <isc/hmacsha.h> #include <isc/hmacsha.h>
#include <isc/httpd.h> #include <isc/httpd.h>
#include <isc/lex.h> #include <isc/lex.h>
#include <isc/meminfo.h>
#include <isc/parseint.h> #include <isc/parseint.h>
#include <isc/portset.h> #include <isc/portset.h>
#include <isc/print.h> #include <isc/print.h>
@ -131,6 +132,10 @@
#define SIZE_MAX ((size_t)-1) #define SIZE_MAX ((size_t)-1)
#endif #endif
#ifndef SIZE_AS_PERCENT
#define SIZE_AS_PERCENT ((size_t)-2)
#endif
#ifdef TUNE_LARGE #ifdef TUNE_LARGE
#define RESOLVER_NTASKS 523 #define RESOLVER_NTASKS 523
#define UDPBUFFERS 32768 #define UDPBUFFERS 32768
@ -2400,6 +2405,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
isc_result_t result; isc_result_t result;
unsigned int cleaning_interval; unsigned int cleaning_interval;
size_t max_cache_size; size_t max_cache_size;
isc_uint32_t max_cache_size_percent = 0;
size_t max_acache_size; size_t max_acache_size;
size_t max_adb_size; size_t max_adb_size;
isc_uint32_t lame_ttl, fail_ttl; isc_uint32_t lame_ttl, fail_ttl;
@ -2685,6 +2691,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
str = cfg_obj_asstring(obj); str = cfg_obj_asstring(obj);
INSIST(strcasecmp(str, "unlimited") == 0); INSIST(strcasecmp(str, "unlimited") == 0);
max_cache_size = 0; max_cache_size = 0;
} else if (cfg_obj_ispercentage(obj)) {
max_cache_size = SIZE_AS_PERCENT;
max_cache_size_percent = cfg_obj_aspercentage(obj);
} else { } else {
isc_resourcevalue_t value; isc_resourcevalue_t value;
value = cfg_obj_asuint64(obj); value = cfg_obj_asuint64(obj);
@ -2701,6 +2710,26 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
max_cache_size = (size_t) value; max_cache_size = (size_t) value;
} }
if (max_cache_size == SIZE_AS_PERCENT) {
isc_uint64_t totalphys = isc_meminfo_totalphys();
max_cache_size = totalphys * max_cache_size_percent/100;
if (totalphys == 0) {
cfg_obj_log(obj, ns_g_lctx,
ISC_LOG_WARNING,
"Unable to determine amount of physical "
"memory, setting 'max-cache-size' to "
"unlimited");
} else {
cfg_obj_log(obj, ns_g_lctx,
ISC_LOG_INFO,
"'max-cache-size %d%%' "
"- setting to %luMB (out of %luMB)",
max_cache_size_percent,
max_cache_size / (1024*1024),
(unsigned long) totalphys / (1024*1024));
}
}
/* Check-names. */ /* Check-names. */
obj = NULL; obj = NULL;
result = ns_checknames_get(maps, "response", &obj); result = ns_checknames_get(maps, "response", &obj);

View File

@ -28,7 +28,7 @@ options {
listen-on { 10.53.0.2; }; listen-on { 10.53.0.2; };
listen-on-v6 { none; }; listen-on-v6 { none; };
notify yes; notify yes;
max-cache-size 10000; max-cache-size 80%;
disable-empty-zone 127.IN-ADDR.ARPA; disable-empty-zone 127.IN-ADDR.ARPA;
}; };

View File

@ -0,0 +1,3 @@
options {
max-cache-size 60%;
};

View File

@ -261,5 +261,12 @@ grep "zone shared.example/IN: loaded serial" < checkconf.out7 > /dev/null || ret
if [ $ret != 0 ]; then echo "I:failed"; ret=1; fi if [ $ret != 0 ]; then echo "I:failed"; ret=1; fi
status=`expr $status + $ret` status=`expr $status + $ret`
echo "I: check that named-checkconf prints max-cache-size <percentage> correctly"
ret=0
$CHECKCONF -p max-cache-size-good.conf > checkconf.out8 2>&1 || ret=1
grep "max-cache-size 60%;" checkconf.out8 > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; ret=1; fi
status=`expr $status + $ret`
echo "I:exit status: $status" echo "I:exit status: $status"
exit $status exit $status

View File

@ -2930,6 +2930,25 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
</para> </para>
</entry> </entry>
</row> </row>
<row rowsep="0">
<entry colname="1">
<para>
<varname>size_or_percent</varname>
</para>
</entry>
<entry colname="2">
<para>
<varname>size_spec</varname> or integer value
followed by '%' to represent percents.
</para>
<para>
The behaviour is exactly the same as
<varname>size_spec</varname>, but
<varname>size_or_percent</varname> allows also
to specify a positive integer value followed by
'%' sign to represent percents.
</entry>
</row>
<row rowsep="0"> <row rowsep="0">
<entry colname="1"> <entry colname="1">
<para> <para>
@ -4959,7 +4978,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional> <optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
<optional> additional-from-cache <replaceable>yes_or_no</replaceable> ; </optional> <optional> additional-from-cache <replaceable>yes_or_no</replaceable> ; </optional>
<optional> random-device <replaceable>path_name</replaceable> ; </optional> <optional> random-device <replaceable>path_name</replaceable> ; </optional>
<optional> max-cache-size <replaceable>size_spec</replaceable> ; </optional> <optional> max-cache-size <replaceable>size_or_percent</replaceable> ; </optional>
<optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional> <optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional>
<optional> filter-aaaa-on-v4 ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional> <optional> filter-aaaa-on-v4 ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional>
<optional> filter-aaaa-on-v6 ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional> <optional> filter-aaaa-on-v6 ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional>
@ -8747,7 +8766,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
<listitem> <listitem>
<para> <para>
The maximum amount of memory to use for the The maximum amount of memory to use for the
server's cache, in bytes. server's cache, in bytes or % of total physical memory.
When the amount of data in the cache When the amount of data in the cache
reaches this limit, the server will cause records to reaches this limit, the server will cause records to
expire prematurely based on an LRU based strategy so expire prematurely based on an LRU based strategy so
@ -8760,7 +8779,14 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
and reset to 2MB. and reset to 2MB.
In a server with multiple views, the limit applies In a server with multiple views, the limit applies
separately to the cache of each view. separately to the cache of each view.
The default is <userinput>unlimited</userinput>. The default is <userinput>90%</userinput>.
On systems where detection of amount of physical
memory is not supported values represented as %
fall back to unlimited.
Note that the detection of physical memory is done only
once at startup, so <command>named</command> will not
adjust the cache size if the amount of physical memory
is changed during runtime.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -178,12 +178,12 @@ options {
masterfile-format ( text | raw | map ); masterfile-format ( text | raw | map );
masterfile-style ( full | relative ); masterfile-style ( full | relative );
match-mapped-addresses <boolean>; match-mapped-addresses <boolean>;
max-acache-size <size_no_default>; max-acache-size ( unlimited | <sizeval> );
max-cache-size <size_no_default>; max-cache-size ( unlimited | default | <sizeval> | <percentage> );
max-cache-ttl <integer>; max-cache-ttl <integer>;
max-clients-per-query <integer>; max-clients-per-query <integer>;
max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete
max-journal-size <size_no_default>; max-journal-size ( unlimited | <sizeval> );
max-ncache-ttl <integer>; max-ncache-ttl <integer>;
max-recursion-depth <integer>; max-recursion-depth <integer>;
max-recursion-queries <integer>; max-recursion-queries <integer>;
@ -461,12 +461,12 @@ view <string> [ <class> ] {
match-clients { <address_match_element>; ... }; match-clients { <address_match_element>; ... };
match-destinations { <address_match_element>; ... }; match-destinations { <address_match_element>; ... };
match-recursive-only <boolean>; match-recursive-only <boolean>;
max-acache-size <size_no_default>; max-acache-size ( unlimited | <sizeval> );
max-cache-size <size_no_default>; max-cache-size ( unlimited | default | <sizeval> | <percentage> );
max-cache-ttl <integer>; max-cache-ttl <integer>;
max-clients-per-query <integer>; max-clients-per-query <integer>;
max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete
max-journal-size <size_no_default>; max-journal-size ( unlimited | <sizeval> );
max-ncache-ttl <integer>; max-ncache-ttl <integer>;
max-recursion-depth <integer>; max-recursion-depth <integer>;
max-recursion-queries <integer>; max-recursion-queries <integer>;
@ -645,7 +645,7 @@ view <string> [ <class> ] {
port <integer> ] ) [ key <string> ]; ... }; port <integer> ] ) [ key <string> ]; ... };
max-ixfr-log-size ( unlimited | default | max-ixfr-log-size ( unlimited | default |
<sizeval> ); // obsolete <sizeval> ); // obsolete
max-journal-size <size_no_default>; max-journal-size ( unlimited | <sizeval> );
max-refresh-time <integer>; max-refresh-time <integer>;
max-retry-time <integer>; max-retry-time <integer>;
max-transfer-idle-in <integer>; max-transfer-idle-in <integer>;
@ -746,7 +746,7 @@ zone <string> [ <class> ] {
<ipv4_address> [ port <integer> ] | <ipv6_address> [ port <ipv4_address> [ port <integer> ] | <ipv6_address> [ port
<integer> ] ) [ key <string> ]; ... }; <integer> ] ) [ key <string> ]; ... };
max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete
max-journal-size <size_no_default>; max-journal-size ( unlimited | <sizeval> );
max-refresh-time <integer>; max-refresh-time <integer>;
max-retry-time <integer>; max-retry-time <integer>;
max-transfer-idle-in <integer>; max-transfer-idle-in <integer>;

View File

@ -37,9 +37,10 @@ CWARNINGS =
UNIXOBJS = @ISC_ISCIPV6_O@ @ISC_ISCPK11_API_O@ \ UNIXOBJS = @ISC_ISCIPV6_O@ @ISC_ISCPK11_API_O@ \
unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \ unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \
unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \ unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \
unix/interfaceiter.@O@ unix/keyboard.@O@ unix/net.@O@ \ unix/interfaceiter.@O@ unix/keyboard.@O@ unix/meminfo.@O@ \
unix/os.@O@ unix/resource.@O@ unix/socket.@O@ unix/stdio.@O@ \ unix/net.@O@ unix/os.@O@ unix/resource.@O@ unix/socket.@O@ \
unix/stdtime.@O@ unix/strerror.@O@ unix/syslog.@O@ unix/time.@O@ unix/stdio.@O@ unix/stdtime.@O@ unix/strerror.@O@ \
unix/syslog.@O@ unix/time.@O@
NLSOBJS = nls/msgcat.@O@ NLSOBJS = nls/msgcat.@O@
@ -48,8 +49,8 @@ THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@
THREADOBJS = @THREADOPTOBJS@ @ISC_THREAD_DIR@/thread.@O@ THREADOBJS = @THREADOPTOBJS@ @ISC_THREAD_DIR@/thread.@O@
WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \
win32/fsaccess.@O@ win32/once.@O@ win32/stdtime.@O@ \ win32/fsaccess.@O@ win32/meminfo.@O@ win32/once.@O@ \
win32/thread.@O@ win32/time.@O@ win32/stdtime.@O@ win32/thread.@O@ win32/time.@O@
# Alphabetically # Alphabetically
OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \ OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2015 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 ISC_MEMINFO_H
#define ISC_MEMINFO_H 1
#include <isc/types.h>
#include <isc/lang.h>
ISC_LANG_BEGINDECLS
isc_uint64_t
isc_meminfo_totalphys(void);
/*%<
* Return total available physical memory in bytes, or 0 if this cannot
* be determined
*/
ISC_LANG_ENDDECLS
#endif /* ISC_MEMINFO_H */

View File

@ -31,15 +31,15 @@ CWARNINGS =
# Alphabetically # Alphabetically
OBJS = @ISC_IPV6_O@ @ISC_PK11_API_O@ \ OBJS = @ISC_IPV6_O@ @ISC_PK11_API_O@ \
app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \ app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \
fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ meminfo.@O@ \
os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \ net.@O@ os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \
strerror.@O@ syslog.@O@ time.@O@ strerror.@O@ syslog.@O@ time.@O@
# Alphabetically # Alphabetically
SRCS = @ISC_IPV6_C@ @ISC_PK11_API_C@ \ SRCS = @ISC_IPV6_C@ @ISC_PK11_API_C@ \
app.c dir.c entropy.c errno2result.c file.c \ app.c dir.c entropy.c errno2result.c file.c \
fsaccess.c interfaceiter.c keyboard.c net.c \ fsaccess.c interfaceiter.c keyboard.c meminfo.c \
os.c resource.c socket.c stdio.c stdtime.c \ net.c os.c resource.c socket.c stdio.c stdtime.c \
strerror.c syslog.c time.c strerror.c syslog.c time.c
SUBDIRS = include SUBDIRS = include

40
lib/isc/unix/meminfo.c Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2015 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 <isc/meminfo.h>
#include <unistd.h>
#include <sys/sysctl.h>
isc_uint64_t
isc_meminfo_totalphys(void) {
#if defined(CTL_HW) && (defined(HW_PHYSMEM64) || defined(HW_MEMSIZE))
int mib[2];
mib[0] = CTL_HW;
#if defined(HW_MEMSIZE)
mib[1] = HW_MEMSIZE;
#elif defined(HW_PHYSMEM64)
mib[1] = HW_PHYSMEM64;
#endif
isc_uint64_t size = 0;
size_t len = sizeof(size);
if (sysctl(mib, 2, &size, &len, NULL, 0) == 0)
return (size);
#endif
#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
return ((size_t) (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE)));
#endif
return (0);
}

View File

@ -27,11 +27,11 @@ CDEFINES =
CWARNINGS = CWARNINGS =
# Alphabetically # Alphabetically
OBJS = condition.@O@ dir.@O@ file.@O@ fsaccess.@O@ once.@O@ \ OBJS = condition.@O@ dir.@O@ file.@O@ meminfo.@O@ fsaccess.@O@ \
stdtime.@O@ thread.@O@ time.@O@ @ISC_PK11_API_O@ once.@O@ stdtime.@O@ thread.@O@ time.@O@ @ISC_PK11_API_O@
# Alphabetically # Alphabetically
SRCS = condition.c dir.c file.c once.c fsaccess.c \ SRCS = condition.c dir.c file.c meminfo.c once.c fsaccess.c \
stdtime.c thread.c time.c @ISC_PK11_API_C@ stdtime.c thread.c time.c @ISC_PK11_API_C@
SUBDIRS = include SUBDIRS = include

27
lib/isc/win32/meminfo.c Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2015 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 <windows.h>
#include <isc/meminfo.h>
isc_uint64_t
isc_meminfo_totalphys(void) {
MEMORYSTATUSEX statex;
status.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
return ((size_t)statex.ullTotalPhys);
}

View File

@ -190,6 +190,18 @@ cfg_obj_ismap(const cfg_obj_t *obj);
* Return true iff 'obj' is of a map type. * Return true iff 'obj' is of a map type.
*/ */
isc_boolean_t
cfg_obj_isfixedpoint(const cfg_obj_t *obj);
/*%<
* Return true iff 'obj' is of a fixedpoint type.
*/
isc_boolean_t
cfg_obj_ispercentage(const cfg_obj_t *obj);
/*%<
* Return true iff 'obj' is of a percentage type.
*/
isc_result_t isc_result_t
cfg_map_get(const cfg_obj_t *mapobj, const char* name, const cfg_obj_t **obj); cfg_map_get(const cfg_obj_t *mapobj, const char* name, const cfg_obj_t **obj);
/*%< /*%<
@ -297,6 +309,18 @@ cfg_obj_asfixedpoint(const cfg_obj_t *obj);
* \li A 32-bit unsigned integer. * \li A 32-bit unsigned integer.
*/ */
isc_uint32_t
cfg_obj_aspercentage(const cfg_obj_t *obj);
/*%<
* Returns the value of a configuration object of percentage
*
* Requires:
* \li 'obj' points to a valid configuration object of percentage type.
*
* Returns:
* \li A 32-bit unsigned integer.
*/
isc_boolean_t isc_boolean_t
cfg_obj_isstring(const cfg_obj_t *obj); cfg_obj_isstring(const cfg_obj_t *obj);
/*%< /*%<

View File

@ -267,6 +267,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_sockaddr;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_netprefix; LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_netprefix;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_void; LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_void;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_fixedpoint; LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_fixedpoint;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_percentage;
/*@}*/ /*@}*/
/*@{*/ /*@{*/
@ -292,6 +293,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_void;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_token; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_token;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_unsupported; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_unsupported;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_fixedpoint; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_fixedpoint;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_percentage;
/*@}*/ /*@}*/
isc_result_t isc_result_t
@ -455,11 +457,19 @@ void
cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type); cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type);
isc_result_t isc_result_t
cfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); cfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret);
void void
cfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj); cfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj);
isc_result_t
cfg_parse_percentage(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret);
void
cfg_print_percentage(cfg_printer_t *pctx, const cfg_obj_t *obj);
isc_result_t isc_result_t
cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);

View File

@ -133,6 +133,7 @@ static cfg_type_t cfg_type_server;
static cfg_type_t cfg_type_server_key_kludge; static cfg_type_t cfg_type_server_key_kludge;
static cfg_type_t cfg_type_size; static cfg_type_t cfg_type_size;
static cfg_type_t cfg_type_sizenodefault; static cfg_type_t cfg_type_sizenodefault;
static cfg_type_t cfg_type_sizeorpercent;
static cfg_type_t cfg_type_sockaddr4wild; static cfg_type_t cfg_type_sockaddr4wild;
static cfg_type_t cfg_type_sockaddr6wild; static cfg_type_t cfg_type_sockaddr6wild;
static cfg_type_t cfg_type_statschannels; static cfg_type_t cfg_type_statschannels;
@ -1595,7 +1596,7 @@ view_clauses[] = {
{ "nocookie-udp-size", &cfg_type_uint32, 0 }, { "nocookie-udp-size", &cfg_type_uint32, 0 },
{ "nosit-udp-size", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE }, { "nosit-udp-size", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
{ "max-acache-size", &cfg_type_sizenodefault, 0 }, { "max-acache-size", &cfg_type_sizenodefault, 0 },
{ "max-cache-size", &cfg_type_sizenodefault, 0 }, { "max-cache-size", &cfg_type_sizeorpercent, 0 },
{ "max-cache-ttl", &cfg_type_uint32, 0 }, { "max-cache-ttl", &cfg_type_uint32, 0 },
{ "max-clients-per-query", &cfg_type_uint32, 0 }, { "max-clients-per-query", &cfg_type_uint32, 0 },
{ "max-ncache-ttl", &cfg_type_uint32, 0 }, { "max-ncache-ttl", &cfg_type_uint32, 0 },
@ -2065,6 +2066,56 @@ parse_sizeval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (result); return (result);
} }
static isc_result_t
parse_sizeval_percent(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
char *endp;
isc_result_t result;
cfg_obj_t *obj = NULL;
isc_uint64_t val;
isc_uint32_t percent;
UNUSED(type);
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type != isc_tokentype_string) {
result = ISC_R_UNEXPECTEDTOKEN;
goto cleanup;
}
percent = isc_string_touint64(TOKEN_STRING(pctx), &endp, 10);
if (*endp == '%' && *(endp+1) == 0) {
CHECK(cfg_create_obj(pctx, &cfg_type_percentage, &obj));
obj->value.uint32 = percent;
*ret = obj;
return (ISC_R_SUCCESS);
} else {
CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
obj->value.uint64 = val;
*ret = obj;
return (ISC_R_SUCCESS);
}
cleanup:
cfg_parser_error(pctx, CFG_LOG_NEAR, "expected integer and optional unit or percent");
return (result);
}
static void
doc_sizeval_percent(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type);
cfg_print_cstr(pctx, "( ");
cfg_doc_terminal(pctx, &cfg_type_size);
cfg_print_cstr(pctx, " | ");
cfg_doc_terminal(pctx, &cfg_type_percentage);
cfg_print_cstr(pctx, " )");
}
/*% /*%
* A size value (number + optional unit). * A size value (number + optional unit).
*/ */
@ -2097,10 +2148,42 @@ static cfg_type_t cfg_type_size = {
*/ */
static const char *sizenodefault_enums[] = { "unlimited", NULL }; static const char *sizenodefault_enums[] = { "unlimited", NULL };
static cfg_type_t cfg_type_sizenodefault = { static cfg_type_t cfg_type_sizenodefault = {
"size_no_default", parse_size, cfg_print_ustring, cfg_doc_terminal, "size_no_default", parse_size, cfg_print_ustring, doc_size,
&cfg_rep_string, sizenodefault_enums &cfg_rep_string, sizenodefault_enums
}; };
/*%
* A size in absolute values or percents.
*/
static cfg_type_t cfg_type_sizeval_percent = {
"sizeval_percent", parse_sizeval_percent, cfg_print_ustring,
doc_sizeval_percent, &cfg_rep_string, NULL
};
/*%
* A size in absolute values or percents, or "unlimited", or "default"
*/
static isc_result_t
parse_size_or_percent(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
return (parse_enum_or_other(pctx, type, &cfg_type_sizeval_percent,
ret));
}
static void
doc_parse_size_or_percent(cfg_printer_t *pctx, const cfg_type_t *type) {
doc_enum_or_other(pctx, type, &cfg_type_sizeval_percent);
}
static const char *sizeorpercent_enums[] = { "unlimited", "default", NULL };
static cfg_type_t cfg_type_sizeorpercent = {
"size_or_percent", parse_size_or_percent, cfg_print_ustring,
doc_parse_size_or_percent, &cfg_rep_string, sizeorpercent_enums
};
/*% /*%
* optional_keyvalue * optional_keyvalue
*/ */
@ -2170,7 +2253,13 @@ doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *enumtype,
first = ISC_FALSE; first = ISC_FALSE;
cfg_print_cstr(pctx, *p); cfg_print_cstr(pctx, *p);
} }
if (othertype != &cfg_type_void) { if (othertype == &cfg_type_sizeval_percent) {
if (!first)
cfg_print_cstr(pctx, " | ");
cfg_doc_terminal(pctx, &cfg_type_sizeval);
cfg_print_cstr(pctx, " | ");
cfg_doc_terminal(pctx, &cfg_type_percentage);
} else if (othertype != &cfg_type_void) {
if (!first) if (!first)
cfg_print_cstr(pctx, " | "); cfg_print_cstr(pctx, " | ");
cfg_doc_terminal(pctx, othertype); cfg_doc_terminal(pctx, othertype);

View File

@ -123,6 +123,7 @@ cfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };
cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop }; cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };
cfg_rep_t cfg_rep_void = { "void", free_noop }; cfg_rep_t cfg_rep_void = { "void", free_noop };
cfg_rep_t cfg_rep_fixedpoint = { "fixedpoint", free_noop }; cfg_rep_t cfg_rep_fixedpoint = { "fixedpoint", free_noop };
cfg_rep_t cfg_rep_percentage = { "percentage", free_noop };
/* /*
* Configuration type definitions. * Configuration type definitions.
@ -650,6 +651,69 @@ cfg_type_t cfg_type_void = {
"void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void, "void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,
NULL }; NULL };
/*
* percentage
*/
isc_result_t
cfg_parse_percentage(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
char *endp;
isc_result_t result;
cfg_obj_t *obj = NULL;
isc_uint32_t percent;
UNUSED(type);
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type != isc_tokentype_string) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected percentage");
return (ISC_R_UNEXPECTEDTOKEN);
}
percent = isc_string_touint64(TOKEN_STRING(pctx), &endp, 10);
if (*endp != '%' || *(endp+1) != 0) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected percentage");
return (ISC_R_UNEXPECTEDTOKEN);
}
CHECK(cfg_create_obj(pctx, &cfg_type_percentage, &obj));
obj->value.uint32 = percent;
*ret = obj;
cleanup:
return (result);
}
void
cfg_print_percentage(cfg_printer_t *pctx, const cfg_obj_t *obj) {
char buf[64];
int n;
n = snprintf(buf, sizeof(buf), "%u%%", obj->value.uint32);
INSIST(n > 0 && (size_t)n < sizeof(buf));
cfg_print_chars(pctx, buf, strlen(buf));
}
isc_uint32_t
cfg_obj_aspercentage(const cfg_obj_t *obj) {
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_percentage);
return (obj->value.uint32);
}
cfg_type_t cfg_type_percentage = {
"percentage", cfg_parse_percentage, cfg_print_percentage,
cfg_doc_terminal, &cfg_rep_percentage, NULL
};
isc_boolean_t
cfg_obj_ispercentage(const cfg_obj_t *obj) {
REQUIRE(obj != NULL);
return (ISC_TF(obj->type->rep == &cfg_rep_percentage));
}
/* /*
* Fixed point * Fixed point
*/ */
@ -724,6 +788,12 @@ cfg_type_t cfg_type_fixedpoint = {
cfg_doc_terminal, &cfg_rep_fixedpoint, NULL cfg_doc_terminal, &cfg_rep_fixedpoint, NULL
}; };
isc_boolean_t
cfg_obj_isfixedpoint(const cfg_obj_t *obj) {
REQUIRE(obj != NULL);
return (ISC_TF(obj->type->rep == &cfg_rep_fixedpoint));
}
/* /*
* uint32 * uint32
*/ */