]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4223. [func] Add support for setting max-cache-size to percentage
authorWitold Krecicki <wpk@isc.org>
Mon, 28 Sep 2015 09:08:50 +0000 (11:08 +0200)
committerWitold Krecicki <wpk@isc.org>
Mon, 28 Sep 2015 09:08:50 +0000 (11:08 +0200)
of available physical memory, set default to 90%.
[RT #38442]

20 files changed:
.gitignore
CHANGES
bin/named/builtin.c
bin/named/config.c
bin/named/server.c
bin/tests/system/cacheclean/ns2/named.conf
bin/tests/system/checkconf/max-cache-size-good.conf [new file with mode: 0644]
bin/tests/system/checkconf/tests.sh
doc/arm/Bv9ARM-book.xml
doc/misc/options
lib/isc/Makefile.in
lib/isc/include/isc/meminfo.h [new file with mode: 0644]
lib/isc/unix/Makefile.in
lib/isc/unix/meminfo.c [new file with mode: 0644]
lib/isc/win32/Makefile.in
lib/isc/win32/meminfo.c [new file with mode: 0644]
lib/isccfg/include/isccfg/cfg.h
lib/isccfg/include/isccfg/grammar.h
lib/isccfg/namedconf.c
lib/isccfg/parser.c

index 052e7b9636ca95a4fb640d6ba0edc8543d370560..e8d7aa4873d8b32971fcc6275ae3c66f625014e6 100644 (file)
@@ -54,3 +54,4 @@ unit/atf-src/test-programs/cpp_helpers
 unit/atf-src/test-programs/sh_helpers
 # ccc-analyzer store its results in .plist directories
 *.plist/
+*~
diff --git a/CHANGES b/CHANGES
index 66a58e87c079509ed31b0102bd032193e5aff9b3..82c58c19cca2de75ee989754ca0ed1cfaaff0f9d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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
                        query. [RT #40836]
 
index e55e95422235b04b6e0cab3b0ceddb3f818629af..96d624a21b43edc083636d6c57d0d661a835c16d 100644 (file)
@@ -368,6 +368,7 @@ do_authors_lookup(dns_sdblookup_t *lookup) {
                "Bob Halley",
                "Evan Hunt",
                "JINMEI Tatuya",
+               "Witold Krecicki",
                "David Lawrence",
                "Scott Mann",
                "Danny Mayer",
index fbc6c18acb351631b1791a475420dda15f2a6c46..aed352316bc72f94e633d7d60c4b67b56f1ca936 100644 (file)
@@ -160,7 +160,7 @@ options {\n\
        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\
index 2dbafe89395da10f57ebfbeb7b90244080f7b45e..4c54419c4b8deb458d4a4e9eb3dcccc44a4f98e2 100644 (file)
@@ -37,6 +37,7 @@
 #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
@@ -2400,6 +2405,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
        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;
@@ -2685,6 +2691,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
                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);
@@ -2701,6 +2710,26 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
                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);
index f9aab1af39092935eb238f0fb61ae6b065e50041..accfda855879a8f1fadac078c5c3d50e38527e23 100644 (file)
@@ -28,7 +28,7 @@ options {
        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;
 };
 
diff --git a/bin/tests/system/checkconf/max-cache-size-good.conf b/bin/tests/system/checkconf/max-cache-size-good.conf
new file mode 100644 (file)
index 0000000..952b022
--- /dev/null
@@ -0,0 +1,3 @@
+options {
+       max-cache-size 60%;
+};
index 031f6fe5de443e109003250637153cb4a6972861..4324c582c9fd64d9adcabb9eceb3d7163cbb4514 100644 (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
 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
index 393317f75b48732412380c9567b6645f1b9d7824..651988717a57b7c4ac6e277b8d46c6f08b9febb6 100644 (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>
              </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>
@@ -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-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>
@@ -8747,7 +8766,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
              <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
@@ -8760,7 +8779,14 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
                  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>
index fa5a610a572b4cd6c937274fbd412998bf770bb0..d345d8db5d5a56194c161ad7aafacbc5887af823 100644 (file)
@@ -178,12 +178,12 @@ options {
         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>;
@@ -461,12 +461,12 @@ view <string> [ <class> ] {
         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>;
@@ -645,7 +645,7 @@ view <string> [ <class> ] {
                     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>;
@@ -746,7 +746,7 @@ zone <string> [ <class> ] {
             <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>;
index 5d088987e580b6285ff4d37e204adc8b387111eb..9702b8d171f5af881262f48ac332b2f225b44576 100644 (file)
@@ -37,9 +37,10 @@ CWARNINGS =
 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@
 
@@ -48,8 +49,8 @@ THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@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@ \
diff --git a/lib/isc/include/isc/meminfo.h b/lib/isc/include/isc/meminfo.h
new file mode 100644 (file)
index 0000000..3291a17
--- /dev/null
@@ -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 */
index 5a63cfe5d35043b83bf20eef27f653a29f5cde61..71150ae0a55b4cf6d5922b9e9284b1f65a973bf9 100644 (file)
@@ -31,15 +31,15 @@ CWARNINGS =
 # 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
diff --git a/lib/isc/unix/meminfo.c b/lib/isc/unix/meminfo.c
new file mode 100644 (file)
index 0000000..07f0f72
--- /dev/null
@@ -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);
+}
index 97439a44a4e13ab43f0a95688af1f3bb48cf94c8..9e2934467ede305967025d8142cb4eff3152fe2a 100644 (file)
@@ -27,11 +27,11 @@ CDEFINES =
 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
diff --git a/lib/isc/win32/meminfo.c b/lib/isc/win32/meminfo.c
new file mode 100644 (file)
index 0000000..aa259f2
--- /dev/null
@@ -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);
+}
\ No newline at end of file
index 57b04f7a7aa74beb46589f1a4d4e53e60e1eaeb0..c52a41f28f867c776243e859678fd1549a42684a 100644 (file)
@@ -190,6 +190,18 @@ cfg_obj_ismap(const cfg_obj_t *obj);
  * 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);
 /*%<
@@ -297,6 +309,18 @@ cfg_obj_asfixedpoint(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);
 /*%<
index cc54fcc386df4398eb45863b8ad41b7a2d7defea..2546a6ca032d70cf4b4b6cee2d6a114b01181b32 100644 (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_void;
 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_unsupported;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_fixedpoint;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_percentage;
 /*@}*/
 
 isc_result_t
@@ -455,11 +457,19 @@ void
 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);
 
index ce2db8c5ace41c8d657a658581fef56cae3ef4a7..7569bada16597c15253c45f674b921b059ca29cf 100644 (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_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;
@@ -1595,7 +1596,7 @@ view_clauses[] = {
        { "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 },
@@ -2065,6 +2066,56 @@ parse_sizeval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        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).
  */
@@ -2097,10 +2148,42 @@ static cfg_type_t cfg_type_size = {
  */
 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
  */
@@ -2170,7 +2253,13 @@ doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *enumtype,
                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);
index 17b5c628c3aa4cfd621006c631629684460e808f..4e1eb477ce80f4616af77122b01f18a0104c6b95 100644 (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_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.
@@ -650,6 +651,69 @@ cfg_type_t cfg_type_void = {
        "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
  */
@@ -724,6 +788,12 @@ cfg_type_t cfg_type_fixedpoint = {
        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
  */