of available physical memory, set default to 90%.
[RT #38442]
unit/atf-src/test-programs/sh_helpers
# ccc-analyzer store its results in .plist directories
*.plist/
+*~
+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
query. [RT #40836]
"Bob Halley",
"Evan Hunt",
"JINMEI Tatuya",
+ "Witold Krecicki",
"David Lawrence",
"Scott Mann",
"Danny Mayer",
max-ncache-ttl 10800; /* 3 hours */\n\
max-cache-ttl 604800; /* 1 week */\n\
transfer-format many-answers;\n\
- max-cache-size 0;\n\
+ max-cache-size 90%;\n\
check-names master fail;\n\
check-names slave warn;\n\
check-names response ignore;\n\
#include <isc/hmacsha.h>
#include <isc/httpd.h>
#include <isc/lex.h>
+#include <isc/meminfo.h>
#include <isc/parseint.h>
#include <isc/portset.h>
#include <isc/print.h>
#define SIZE_MAX ((size_t)-1)
#endif
+#ifndef SIZE_AS_PERCENT
+#define SIZE_AS_PERCENT ((size_t)-2)
+#endif
+
#ifdef TUNE_LARGE
#define RESOLVER_NTASKS 523
#define UDPBUFFERS 32768
isc_result_t result;
unsigned int cleaning_interval;
size_t max_cache_size;
+ isc_uint32_t max_cache_size_percent = 0;
size_t max_acache_size;
size_t max_adb_size;
isc_uint32_t lame_ttl, fail_ttl;
str = cfg_obj_asstring(obj);
INSIST(strcasecmp(str, "unlimited") == 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 {
isc_resourcevalue_t value;
value = cfg_obj_asuint64(obj);
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. */
obj = NULL;
result = ns_checknames_get(maps, "response", &obj);
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
notify yes;
- max-cache-size 10000;
+ max-cache-size 80%;
disable-empty-zone 127.IN-ADDR.ARPA;
};
--- /dev/null
+options {
+ max-cache-size 60%;
+};
if [ $ret != 0 ]; then echo "I:failed"; ret=1; fi
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"
exit $status
</para>
</entry>
</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">
<entry colname="1">
<para>
<optional> additional-from-auth <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> 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> 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>
<listitem>
<para>
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
reaches this limit, the server will cause records to
expire prematurely based on an LRU based strategy so
and reset to 2MB.
In a server with multiple views, the limit applies
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>
</listitem>
</varlistentry>
masterfile-format ( text | raw | map );
masterfile-style ( full | relative );
match-mapped-addresses <boolean>;
- max-acache-size <size_no_default>;
- max-cache-size <size_no_default>;
+ max-acache-size ( unlimited | <sizeval> );
+ max-cache-size ( unlimited | default | <sizeval> | <percentage> );
max-cache-ttl <integer>;
max-clients-per-query <integer>;
max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete
- max-journal-size <size_no_default>;
+ max-journal-size ( unlimited | <sizeval> );
max-ncache-ttl <integer>;
max-recursion-depth <integer>;
max-recursion-queries <integer>;
match-clients { <address_match_element>; ... };
match-destinations { <address_match_element>; ... };
match-recursive-only <boolean>;
- max-acache-size <size_no_default>;
- max-cache-size <size_no_default>;
+ max-acache-size ( unlimited | <sizeval> );
+ max-cache-size ( unlimited | default | <sizeval> | <percentage> );
max-cache-ttl <integer>;
max-clients-per-query <integer>;
max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete
- max-journal-size <size_no_default>;
+ max-journal-size ( unlimited | <sizeval> );
max-ncache-ttl <integer>;
max-recursion-depth <integer>;
max-recursion-queries <integer>;
port <integer> ] ) [ key <string> ]; ... };
max-ixfr-log-size ( unlimited | default |
<sizeval> ); // obsolete
- max-journal-size <size_no_default>;
+ max-journal-size ( unlimited | <sizeval> );
max-refresh-time <integer>;
max-retry-time <integer>;
max-transfer-idle-in <integer>;
<ipv4_address> [ port <integer> ] | <ipv6_address> [ port
<integer> ] ) [ key <string> ]; ... };
max-ixfr-log-size ( unlimited | default | <sizeval> ); // obsolete
- max-journal-size <size_no_default>;
+ max-journal-size ( unlimited | <sizeval> );
max-refresh-time <integer>;
max-retry-time <integer>;
max-transfer-idle-in <integer>;
UNIXOBJS = @ISC_ISCIPV6_O@ @ISC_ISCPK11_API_O@ \
unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \
unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \
- unix/interfaceiter.@O@ unix/keyboard.@O@ unix/net.@O@ \
- unix/os.@O@ unix/resource.@O@ unix/socket.@O@ unix/stdio.@O@ \
- unix/stdtime.@O@ unix/strerror.@O@ unix/syslog.@O@ unix/time.@O@
+ unix/interfaceiter.@O@ unix/keyboard.@O@ unix/meminfo.@O@ \
+ unix/net.@O@ unix/os.@O@ unix/resource.@O@ unix/socket.@O@ \
+ unix/stdio.@O@ unix/stdtime.@O@ unix/strerror.@O@ \
+ unix/syslog.@O@ unix/time.@O@
NLSOBJS = nls/msgcat.@O@
THREADOBJS = @THREADOPTOBJS@ @ISC_THREAD_DIR@/thread.@O@
WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \
- win32/fsaccess.@O@ win32/once.@O@ win32/stdtime.@O@ \
- win32/thread.@O@ win32/time.@O@
+ win32/fsaccess.@O@ win32/meminfo.@O@ win32/once.@O@ \
+ win32/stdtime.@O@ win32/thread.@O@ win32/time.@O@
# Alphabetically
OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \
--- /dev/null
+/*
+ * 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 */
# Alphabetically
OBJS = @ISC_IPV6_O@ @ISC_PK11_API_O@ \
app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \
- fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \
- os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \
+ fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ meminfo.@O@ \
+ net.@O@ os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \
strerror.@O@ syslog.@O@ time.@O@
# Alphabetically
SRCS = @ISC_IPV6_C@ @ISC_PK11_API_C@ \
app.c dir.c entropy.c errno2result.c file.c \
- fsaccess.c interfaceiter.c keyboard.c net.c \
- os.c resource.c socket.c stdio.c stdtime.c \
+ fsaccess.c interfaceiter.c keyboard.c meminfo.c \
+ net.c os.c resource.c socket.c stdio.c stdtime.c \
strerror.c syslog.c time.c
SUBDIRS = include
--- /dev/null
+/*
+ * 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);
+}
CWARNINGS =
# Alphabetically
-OBJS = condition.@O@ dir.@O@ file.@O@ fsaccess.@O@ once.@O@ \
- stdtime.@O@ thread.@O@ time.@O@ @ISC_PK11_API_O@
+OBJS = condition.@O@ dir.@O@ file.@O@ meminfo.@O@ fsaccess.@O@ \
+ once.@O@ stdtime.@O@ thread.@O@ time.@O@ @ISC_PK11_API_O@
# 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@
SUBDIRS = include
--- /dev/null
+/*
+ * 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);
+}
\ No newline at end of file
* 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
cfg_map_get(const cfg_obj_t *mapobj, const char* name, const cfg_obj_t **obj);
/*%<
* \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
cfg_obj_isstring(const cfg_obj_t *obj);
/*%<
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_fixedpoint;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_percentage;
/*@}*/
/*@{*/
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_fixedpoint;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_percentage;
/*@}*/
isc_result_t
cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type);
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
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
cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
static cfg_type_t cfg_type_server_key_kludge;
static cfg_type_t cfg_type_size;
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_sockaddr6wild;
static cfg_type_t cfg_type_statschannels;
{ "nocookie-udp-size", &cfg_type_uint32, 0 },
{ "nosit-udp-size", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
{ "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-clients-per-query", &cfg_type_uint32, 0 },
{ "max-ncache-ttl", &cfg_type_uint32, 0 },
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).
*/
*/
static const char *sizenodefault_enums[] = { "unlimited", NULL };
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
};
+/*%
+ * 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
*/
first = ISC_FALSE;
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)
cfg_print_cstr(pctx, " | ");
cfg_doc_terminal(pctx, othertype);
cfg_rep_t cfg_rep_netprefix = { "netprefix", 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_percentage = { "percentage", free_noop };
/*
* Configuration type definitions.
"void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,
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
*/
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
*/