]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2355. [func] Extend the number statistics counters available.
authorMark Andrews <marka@isc.org>
Thu, 3 Apr 2008 05:55:52 +0000 (05:55 +0000)
committerMark Andrews <marka@isc.org>
Thu, 3 Apr 2008 05:55:52 +0000 (05:55 +0000)
                        [RT #17590]

30 files changed:
CHANGES
bin/named/bind9.xsl
bin/named/bind9.xsl.h
bin/named/client.c
bin/named/convertxsl.pl
bin/named/include/named/server.h
bin/named/include/named/statschannel.h
bin/named/query.c
bin/named/server.c
bin/named/statschannel.c
bin/named/update.c
bin/named/xfrout.c
bin/named/zoneconf.c
lib/dns/adb.c
lib/dns/db.c
lib/dns/dispatch.c
lib/dns/include/dns/adb.h
lib/dns/include/dns/db.h
lib/dns/include/dns/dispatch.h
lib/dns/include/dns/stats.h
lib/dns/include/dns/types.h
lib/dns/include/dns/view.h
lib/dns/include/dns/zone.h
lib/dns/rbtdb.c
lib/dns/resolver.c
lib/dns/sdb.c
lib/dns/sdlz.c
lib/dns/stats.c
lib/dns/view.c
lib/dns/zone.c

diff --git a/CHANGES b/CHANGES
index 47ca261d6385b1bad7fc541b2ce0aca4aaffbcfd..db796547d2bf24e773aea25719abd6e56cf1c757 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+2355.  [func]          Extend the number statistics counters available.
+                       [RT #17590]
+
 2354.  [bug]           Failed to initialise sone rdatasetheader_t elements.
                        [RT #17927]
 
index 97d75806d603b7aedf606293be7e0a1b12989e74..c385289541da9932ace1ae56389f32803545b84a 100644 (file)
@@ -15,7 +15,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- $Id: bind9.xsl,v 1.15 2008/04/01 23:47:10 tbox Exp $ -->
+<!-- $Id: bind9.xsl,v 1.16 2008/04/03 05:55:51 marka Exp $ -->
 
 <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
@@ -55,6 +55,11 @@ tr.lrow {
        color: #ffffff;
 }
 
+td, th {
+       padding-right: 5px;
+       padding-left: 5px;
+}
+
 .header {
        background-color: teal;
        color: #ffffff;
@@ -99,21 +104,293 @@ tr.lrow {
        <br/>
 
        <table>
-         <tr class="rowh"><th colspan="2">Server statistics</th></tr>
-         <xsl:for-each select="server/counters/*">
+         <tr class="rowh"><th colspan="2">Incoming Requests</th></tr>
+         <xsl:for-each select="server/requests/opcode">
            <tr class="lrow">
-             <td><xsl:value-of select="name()"/></td>
-             <td><xsl:value-of select="."/></td>
+             <td><xsl:value-of select="name"/></td>
+             <td><xsl:value-of select="counter"/></td>
+           </tr>
+         </xsl:for-each>
+       </table>
+
+       <br/>
+
+       <table>
+         <tr class="rowh"><th colspan="2">Incoming Queries</th></tr>
+         <xsl:for-each select="server/queries-in/rdtype">
+           <tr class="lrow">
+             <td><xsl:value-of select="name"/></td>
+             <td><xsl:value-of select="counter"/></td>
            </tr>
          </xsl:for-each>
        </table>
 
-       <br/>   
+       <br/>
+
+       <xsl:for-each select="views/view">
+         <table>
+           <tr class="rowh">
+             <th colspan="2">Outgoing Queries from View <xsl:value-of select="name"/></th>
+           </tr>
+           <xsl:for-each select="rdtype">
+             <tr class="lrow">
+               <td><xsl:value-of select="name"/></td>
+               <td><xsl:value-of select="counter"/></td>
+             </tr>
+           </xsl:for-each>
+         </table>
+         <br/>
+       </xsl:for-each>
+
+       <br/>
+
+       <table>
+         <tr class="rowh"><th colspan="10">Server Statistics</th></tr>
+          <tr class="rowh">
+           <!-- The ordering of the following items must be consisten
+           with dns_nsstatscounter_xxx -->
+           <th>Requestv4</th>
+           <th>Requestv6</th>
+           <th>ReqEdns0</th>
+           <th>ReqBadEDNSVer</th>
+           <th>ReqTSIG</th>
+           <th>ReqSIG0</th>
+           <th>ReqBadSIG</th>
+           <th>ReqTCP</th>
+           <th>AuthQryRej</th>
+           <th>RecQryRej</th>
+         </tr>
+         <tr class="lrow">
+           <td><xsl:value-of select="server/nsstats/Requestv4"/></td>
+           <td><xsl:value-of select="server/nsstats/Requestv6"/></td>
+           <td><xsl:value-of select="server/nsstats/ReqEdns0"/></td>
+           <td><xsl:value-of select="server/nsstats/ReqBadEDNSVer"/></td>
+           <td><xsl:value-of select="server/nsstats/ReqTSIG"/></td>
+           <td><xsl:value-of select="server/nsstats/ReqSIG0"/></td>
+           <td><xsl:value-of select="server/nsstats/ReqBadSIG"/></td>
+           <td><xsl:value-of select="server/nsstats/ReqTCP"/></td>
+           <td><xsl:value-of select="server/nsstats/AuthQryRej"/></td>
+           <td><xsl:value-of select="server/nsstats/RecQryRej"/></td>
+         </tr>
+          <tr class="rowh">
+           <th>XfrRej</th>
+           <th>UpdateRej</th>
+           <th>Response</th>
+           <th>RespTruncated</th>
+           <th>RespEDNS0</th>
+           <th>RespTSIG</th>
+           <th>RespSIG0</th>
+           <th>QrySuccess</th>
+           <th>QryAuthAns</th>
+           <th>QryNoauthAns</th>
+         </tr>
+         <tr class="lrow">
+           <td><xsl:value-of select="server/nsstats/XfrRej"/></td>
+           <td><xsl:value-of select="server/nsstats/UpdateRej"/></td>
+           <td><xsl:value-of select="server/nsstats/Response"/></td>
+           <td><xsl:value-of select="server/nsstats/TruncatedResp"/></td>
+           <td><xsl:value-of select="server/nsstats/RespEDNS0"/></td>
+           <td><xsl:value-of select="server/nsstats/RespTSIG"/></td>
+           <td><xsl:value-of select="server/nsstats/RespSIG0"/></td>
+           <td><xsl:value-of select="server/nsstats/QrySuccess"/></td>
+           <td><xsl:value-of select="server/nsstats/QryAuthAns"/></td>
+           <td><xsl:value-of select="server/nsstats/QryNoauthAns"/></td>
+         </tr>
+          <tr class="rowh">
+           <th>QryReferral</th>
+           <th>QryNxrrset</th>
+           <th>QrySERVFAIL</th>
+           <th>QryFORMERR</th>
+           <th>QryNXDOMAIN</th>
+           <th>QryRecursion</th>
+           <th>QryDuplicate</th>
+           <th>QryDropped</th>
+           <th>QryFailure</th>
+           <th>XfrReqDone</th>
+         </tr>
+         <tr class="lrow">
+           <td><xsl:value-of select="server/nsstats/QryReferral"/></td>
+           <td><xsl:value-of select="server/nsstats/QryNxrrset"/></td>
+           <td><xsl:value-of select="server/nsstats/QrySERVFAIL"/></td>
+           <td><xsl:value-of select="server/nsstats/QryFORMERR"/></td>
+           <td><xsl:value-of select="server/nsstats/QryNXDOMAIN"/></td>
+           <td><xsl:value-of select="server/nsstats/QryRecursion"/></td>
+           <td><xsl:value-of select="server/nsstats/QryDuplicate"/></td>
+           <td><xsl:value-of select="server/nsstats/QryDropped"/></td>
+           <td><xsl:value-of select="server/nsstats/QryFailure"/></td>
+           <td><xsl:value-of select="server/nsstats/XfrReqDone"/></td>
+         </tr>
+          <tr class="rowh">
+           <th>UpdateReqFwd</th>
+           <th>UpdateRespFwd</th>
+           <th>UpdateFwdFail</th>
+           <th>UpdateDone</th>
+           <th>UpdateFail</th>
+           <th>UpdateBadPrereq</th>
+           <th>RespMismatch</th>
+           <th />
+           <th />
+           <th />
+         </tr>
+         <tr class="lrow">
+           <td><xsl:value-of select="server/nsstats/UpdateReqFwd"/></td>
+           <td><xsl:value-of select="server/nsstats/UpdateRespFwd"/></td>
+           <td><xsl:value-of select="server/nsstats/UpdateFwdFail"/></td>
+           <td><xsl:value-of select="server/nsstats/UpdateDone"/></td>
+           <td><xsl:value-of select="server/nsstats/UpdateFail"/></td>
+           <td><xsl:value-of select="server/nsstats/UpdateBadPrereq"/></td>
+           <td><xsl:value-of select="server/resstats/Mismatch"/></td>
+           <td />
+           <td />
+           <td />
+         </tr>
+       </table>
+
+       <br/>
+
+       <table>
+         <tr class="rowh"><th colspan="10">Zone Maintenance Statistics</th></tr>
+          <tr class="rowh">
+           <!-- The ordering of the following items must be consisten
+           with dns_zonestatscounter_xxx -->
+           <th>NotifyOutv4</th>
+           <th>NotifyOutv6</th>
+           <th>NotifyInv4</th>
+           <th>NotifyInv6</th>
+           <th>NotifyRej</th>
+           <th>SOAOutv4</th>
+           <th>SOAOutv6</th>
+           <th>AXFRReqv4</th>
+           <th>AXFRReqv6</th>
+           <th>IXFRReqv4</th>
+         </tr>
+         <tr class="lrow">
+           <td><xsl:value-of select="server/zonestats/NotifyOutv4"/></td>
+           <td><xsl:value-of select="server/zonestats/NotifyOutv6"/></td>
+           <td><xsl:value-of select="server/zonestats/NotifyInv4"/></td>
+           <td><xsl:value-of select="server/zonestats/NotifyInv6"/></td>
+           <td><xsl:value-of select="server/zonestats/NotifyRej"/></td>
+           <td><xsl:value-of select="server/zonestats/SOAOutv4"/></td>
+           <td><xsl:value-of select="server/zonestats/SOAOutv6"/></td>
+           <td><xsl:value-of select="server/zonestats/AXFRReqv4"/></td>
+           <td><xsl:value-of select="server/zonestats/AXFRReqv6"/></td>
+           <td><xsl:value-of select="server/zonestats/IXFRReqv4"/></td>
+         </tr>
+         <tr class="rowh">
+           <th>IXFRReqv6</th>
+           <th>XfrSuccess</th>
+           <th>XfrFail</th>
+           <th/>
+           <th/>
+           <th/>
+           <th/>
+           <th/>
+           <th/>
+           <th/>
+         </tr>
+         <tr class="lrow">
+           <td><xsl:value-of select="server/zonestats/IXFRReqv6"/></td>
+           <td><xsl:value-of select="server/zonestats/XfrSuccess"/></td>
+           <td><xsl:value-of select="server/zonestats/XfrFail"/></td>
+           <td/>
+           <td/>
+           <td/>
+           <td/>
+           <td/>
+           <td/>
+           <td/>
+         </tr>
+       </table>
+
+       <br/>
+
+       <xsl:for-each select="views/view">
+         <table>
+           <tr class="rowh">
+             <th colspan="10">Resolver Statistics for View <xsl:value-of select="name"/></th>
+           </tr>
+           <tr class="rowh">
+           <!-- The ordering of the following items must be consisten
+           with dns_resstatscounter_xxx -->
+             <th>Queryv4</th>
+             <th>Queryv6</th>
+             <th>Responsev4</th>
+             <th>Responsev6</th>
+             <th>NXDOMAIN</th>
+             <th>SERVFAIL</th>
+             <th>FORMERR</th>
+             <th>OtherError</th>
+             <th>EDNS0Fail</th>
+             <!-- this counter is not applicable to per-view stat,
+             but keep it for generating the description table used in
+             the statschannel.c.
+                 <th>Mismatch</th>  -->
+             <th>Truncated</th>
+           </tr>
+           <tr class="lrow">
+             <td><xsl:value-of select="resstats/Queryv4"/></td>
+             <td><xsl:value-of select="resstats/Queryv6"/></td>
+             <td><xsl:value-of select="resstats/Responsev4"/></td>
+             <td><xsl:value-of select="resstats/Responsev6"/></td>
+             <td><xsl:value-of select="resstats/NXDOMAIN"/></td>
+             <td><xsl:value-of select="resstats/SERVFAIL"/></td>
+             <td><xsl:value-of select="resstats/FORMERR"/></td>
+             <td><xsl:value-of select="resstats/OtherError"/></td>
+             <td><xsl:value-of select="resstats/EDNS0Fail"/></td>
+             <!--  <td><xsl:value-of select="resstats/Mismatch"/></td>  -->
+             <td><xsl:value-of select="resstats/Truncated"/></td>
+           </tr>
+           <tr class="rowh">
+             <th>Lame</th>
+             <th>Retry</th>
+             <th>GlueFetchv4</th>
+             <th>GlueFetchv6</th>
+             <th>GlueFetchv4Fail</th>
+             <th>GlueFetchv6Fail</th>
+             <th>ValAttempt</th>
+             <th>ValOk</th>
+             <th>ValNegOk</th>
+             <th>ValFail</th>
+           </tr>
+           <tr class="lrow">
+             <td><xsl:value-of select="resstats/Lame"/></td>
+             <td><xsl:value-of select="resstats/Retry"/></td>
+             <td><xsl:value-of select="resstats/GlueFetchv4"/></td>
+             <td><xsl:value-of select="resstats/GlueFetchv6"/></td>
+             <td><xsl:value-of select="resstats/GlueFetchv4Fail"/></td>
+             <td><xsl:value-of select="resstats/GlueFetchv6Fail"/></td>
+             <td><xsl:value-of select="resstats/ValAttempt"/></td>
+             <td><xsl:value-of select="resstats/ValOk"/></td>
+             <td><xsl:value-of select="resstats/ValNegOk"/></td>
+             <td><xsl:value-of select="resstats/ValFail"/></td>
+           </tr>
+          </table>
+         <br/>
+        </xsl:for-each>
+
+       <br/>
+
+       <xsl:for-each select="views/view">
+         <table>
+           <tr class="rowh">
+             <th colspan="2">Cache DB RRsets for View <xsl:value-of select="name"/></th>
+           </tr>
+           <xsl:for-each select="cache/rrset">
+             <tr class="lrow">
+               <td><xsl:value-of select="name"/></td>
+               <td><xsl:value-of select="counter"/></td>
+             </tr>
+           </xsl:for-each>
+         </table>
+         <br/>
+       </xsl:for-each>
+
+       <br/>
 
         <xsl:for-each select="views/view">
           <table>
             <tr class="rowh">
-              <th colspan="11">Zones for View <xsl:value-of select="name"/></th>
+              <th colspan="10">Zones for View <xsl:value-of select="name"/></th>
             </tr>
             <tr class="rowh">
               <th>Name</th>
@@ -123,10 +400,9 @@ tr.lrow {
               <th>Referral</th>
               <th>NXRRSET</th>
               <th>NXDOMAIN</th>
-              <th>Recursion</th>
               <th>Failure</th>
-              <th>Duplicate</th>
-              <th>Dropped</th>
+             <th>XfrReqDone</th>
+             <th>XfrRej</th>
             </tr>
             <xsl:for-each select="zones/zone">
               <tr class="lrow">
@@ -140,28 +416,25 @@ tr.lrow {
                   <xsl:value-of select="serial"/>
                 </td>
                 <td>
-                  <xsl:value-of select="counters/success"/>
-                </td>
-                <td>
-                  <xsl:value-of select="counters/referral"/>
+                  <xsl:value-of select="counters/QrySuccess"/>
                 </td>
                 <td>
-                  <xsl:value-of select="counters/nxrrset"/>
+                  <xsl:value-of select="counters/QryReferral"/>
                 </td>
                 <td>
-                  <xsl:value-of select="counters/nxdomain"/>
+                  <xsl:value-of select="counters/QryNxrrset"/>
                 </td>
                 <td>
-                  <xsl:value-of select="counters/recursion"/>
+                  <xsl:value-of select="counters/QryNXDOMAIN"/>
                 </td>
                 <td>
-                  <xsl:value-of select="counters/failure"/>
+                  <xsl:value-of select="counters/QryFailure"/>
                 </td>
                 <td>
-                  <xsl:value-of select="counters/duplicate"/>
+                  <xsl:value-of select="counters/XfrReqDone"/>
                 </td>
                 <td>
-                  <xsl:value-of select="counters/dropped"/>
+                  <xsl:value-of select="counters/XfrRej"/>
                 </td>
               </tr>
             </xsl:for-each>
index b26ca2cb5012486fbfe2ab6303a29a6a106af048..e409e20b384e12f520ff45663836a6d6c20ef4ae 100644 (file)
@@ -2,7 +2,7 @@
  * Generated by convertxsl.pl 1.11 2008/04/02 23:46:57 tbox Exp  
  * From bind9.xsl 1.15 2008/04/01 23:47:10 tbox Exp 
  */
-static char msg[] =
+static char xslmsg[] =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
        "<!--\n"
        " - Copyright (C) 2006-2008 Internet Systems Consortium, Inc. (\"ISC\")\n"
@@ -60,6 +60,11 @@ static char msg[] =
        " color: #ffffff;\n"
        "}\n"
        "\n"
+       "td, th {\n"
+       " padding-right: 5px;\n"
+       " padding-left: 5px;\n"
+       "}\n"
+       "\n"
        ".header {\n"
        " background-color: teal;\n"
        " color: #ffffff;\n"
@@ -104,21 +109,293 @@ static char msg[] =
        " <br/>\n"
        "\n"
        " <table>\n"
-       " <tr class=\"rowh\"><th colspan=\"2\">Server statistics</th></tr>\n"
-       " <xsl:for-each select=\"server/counters/*\">\n"
+       " <tr class=\"rowh\"><th colspan=\"2\">Incoming Requests</th></tr>\n"
+       " <xsl:for-each select=\"server/requests/opcode\">\n"
        " <tr class=\"lrow\">\n"
-       " <td><xsl:value-of select=\"name()\"/></td>\n"
-       " <td><xsl:value-of select=\".\"/></td>\n"
+       " <td><xsl:value-of select=\"name\"/></td>\n"
+       " <td><xsl:value-of select=\"counter\"/></td>\n"
+       " </tr>\n"
+       " </xsl:for-each>\n"
+       " </table>\n"
+       "\n"
+       " <br/>\n"
+       "\n"
+       " <table>\n"
+       " <tr class=\"rowh\"><th colspan=\"2\">Incoming Queries</th></tr>\n"
+       " <xsl:for-each select=\"server/queries-in/rdtype\">\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"name\"/></td>\n"
+       " <td><xsl:value-of select=\"counter\"/></td>\n"
+       " </tr>\n"
+       " </xsl:for-each>\n"
+       " </table>\n"
+       "\n"
+       " <br/>\n"
+       "\n"
+       " <xsl:for-each select=\"views/view\">\n"
+       " <table>\n"
+       " <tr class=\"rowh\">\n"
+       " <th colspan=\"2\">Outgoing Queries from View <xsl:value-of select=\"name\"/></th>\n"
+       " </tr>\n"
+       " <xsl:for-each select=\"rdtype\">\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"name\"/></td>\n"
+       " <td><xsl:value-of select=\"counter\"/></td>\n"
+       " </tr>\n"
+       " </xsl:for-each>\n"
+       " </table>\n"
+       " <br/>\n"
+       " </xsl:for-each>\n"
+       "\n"
+       " <br/>\n"
+       "\n"
+       " <table>\n"
+       " <tr class=\"rowh\"><th colspan=\"10\">Server Statistics</th></tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <!-- The ordering of the following items must be consisten\n"
+       " with dns_nsstatscounter_xxx -->\n"
+       " <th>Requestv4</th>\n"
+       " <th>Requestv6</th>\n"
+       " <th>ReqEdns0</th>\n"
+       " <th>ReqBadEDNSVer</th>\n"
+       " <th>ReqTSIG</th>\n"
+       " <th>ReqSIG0</th>\n"
+       " <th>ReqBadSIG</th>\n"
+       " <th>ReqTCP</th>\n"
+       " <th>AuthQryRej</th>\n"
+       " <th>RecQryRej</th>\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"server/nsstats/Requestv4\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/Requestv6\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/ReqEdns0\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/ReqBadEDNSVer\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/ReqTSIG\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/ReqSIG0\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/ReqBadSIG\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/ReqTCP\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/AuthQryRej\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/RecQryRej\"/></td>\n"
+       " </tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <th>XfrRej</th>\n"
+       " <th>UpdateRej</th>\n"
+       " <th>Response</th>\n"
+       " <th>RespTruncated</th>\n"
+       " <th>RespEDNS0</th>\n"
+       " <th>RespTSIG</th>\n"
+       " <th>RespSIG0</th>\n"
+       " <th>QrySuccess</th>\n"
+       " <th>QryAuthAns</th>\n"
+       " <th>QryNoauthAns</th>\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"server/nsstats/XfrRej\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/UpdateRej\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/Response\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/TruncatedResp\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/RespEDNS0\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/RespTSIG\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/RespSIG0\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QrySuccess\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryAuthAns\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryNoauthAns\"/></td>\n"
+       " </tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <th>QryReferral</th>\n"
+       " <th>QryNxrrset</th>\n"
+       " <th>QrySERVFAIL</th>\n"
+       " <th>QryFORMERR</th>\n"
+       " <th>QryNXDOMAIN</th>\n"
+       " <th>QryRecursion</th>\n"
+       " <th>QryDuplicate</th>\n"
+       " <th>QryDropped</th>\n"
+       " <th>QryFailure</th>\n"
+       " <th>XfrReqDone</th>\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryReferral\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryNxrrset\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QrySERVFAIL\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryFORMERR\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryNXDOMAIN\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryRecursion\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryDuplicate\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryDropped\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/QryFailure\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/XfrReqDone\"/></td>\n"
+       " </tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <th>UpdateReqFwd</th>\n"
+       " <th>UpdateRespFwd</th>\n"
+       " <th>UpdateFwdFail</th>\n"
+       " <th>UpdateDone</th>\n"
+       " <th>UpdateFail</th>\n"
+       " <th>UpdateBadPrereq</th>\n"
+       " <th>RespMismatch</th>\n"
+       " <th />\n"
+       " <th />\n"
+       " <th />\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"server/nsstats/UpdateReqFwd\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/UpdateRespFwd\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/UpdateFwdFail\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/UpdateDone\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/UpdateFail\"/></td>\n"
+       " <td><xsl:value-of select=\"server/nsstats/UpdateBadPrereq\"/></td>\n"
+       " <td><xsl:value-of select=\"server/resstats/Mismatch\"/></td>\n"
+       " <td />\n"
+       " <td />\n"
+       " <td />\n"
+       " </tr>\n"
+       " </table>\n"
+       "\n"
+       " <br/>\n"
+       "\n"
+       " <table>\n"
+       " <tr class=\"rowh\"><th colspan=\"10\">Zone Maintenance Statistics</th></tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <!-- The ordering of the following items must be consisten\n"
+       " with dns_zonestatscounter_xxx -->\n"
+       " <th>NotifyOutv4</th>\n"
+       " <th>NotifyOutv6</th>\n"
+       " <th>NotifyInv4</th>\n"
+       " <th>NotifyInv6</th>\n"
+       " <th>NotifyRej</th>\n"
+       " <th>SOAOutv4</th>\n"
+       " <th>SOAOutv6</th>\n"
+       " <th>AXFRReqv4</th>\n"
+       " <th>AXFRReqv6</th>\n"
+       " <th>IXFRReqv4</th>\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"server/zonestats/NotifyOutv4\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/NotifyOutv6\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/NotifyInv4\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/NotifyInv6\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/NotifyRej\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/SOAOutv4\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/SOAOutv6\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/AXFRReqv4\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/AXFRReqv6\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/IXFRReqv4\"/></td>\n"
+       " </tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <th>IXFRReqv6</th>\n"
+       " <th>XfrSuccess</th>\n"
+       " <th>XfrFail</th>\n"
+       " <th/>\n"
+       " <th/>\n"
+       " <th/>\n"
+       " <th/>\n"
+       " <th/>\n"
+       " <th/>\n"
+       " <th/>\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"server/zonestats/IXFRReqv6\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/XfrSuccess\"/></td>\n"
+       " <td><xsl:value-of select=\"server/zonestats/XfrFail\"/></td>\n"
+       " <td/>\n"
+       " <td/>\n"
+       " <td/>\n"
+       " <td/>\n"
+       " <td/>\n"
+       " <td/>\n"
+       " <td/>\n"
+       " </tr>\n"
+       " </table>\n"
+       "\n"
+       " <br/>\n"
+       "\n"
+       " <xsl:for-each select=\"views/view\">\n"
+       " <table>\n"
+       " <tr class=\"rowh\">\n"
+       " <th colspan=\"10\">Resolver Statistics for View <xsl:value-of select=\"name\"/></th>\n"
+       " </tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <!-- The ordering of the following items must be consisten\n"
+       " with dns_resstatscounter_xxx -->\n"
+       " <th>Queryv4</th>\n"
+       " <th>Queryv6</th>\n"
+       " <th>Responsev4</th>\n"
+       " <th>Responsev6</th>\n"
+       " <th>NXDOMAIN</th>\n"
+       " <th>SERVFAIL</th>\n"
+       " <th>FORMERR</th>\n"
+       " <th>OtherError</th>\n"
+       " <th>EDNS0Fail</th>\n"
+       " <!-- this counter is not applicable to per-view stat,\n"
+       " but keep it for generating the description table used in\n"
+       " the statschannel.c.\n"
+       " <th>Mismatch</th> -->\n"
+       " <th>Truncated</th>\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"resstats/Queryv4\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/Queryv6\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/Responsev4\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/Responsev6\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/NXDOMAIN\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/SERVFAIL\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/FORMERR\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/OtherError\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/EDNS0Fail\"/></td>\n"
+       " <!-- <td><xsl:value-of select=\"resstats/Mismatch\"/></td> -->\n"
+       " <td><xsl:value-of select=\"resstats/Truncated\"/></td>\n"
+       " </tr>\n"
+       " <tr class=\"rowh\">\n"
+       " <th>Lame</th>\n"
+       " <th>Retry</th>\n"
+       " <th>GlueFetchv4</th>\n"
+       " <th>GlueFetchv6</th>\n"
+       " <th>GlueFetchv4Fail</th>\n"
+       " <th>GlueFetchv6Fail</th>\n"
+       " <th>ValAttempt</th>\n"
+       " <th>ValOk</th>\n"
+       " <th>ValNegOk</th>\n"
+       " <th>ValFail</th>\n"
+       " </tr>\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"resstats/Lame\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/Retry\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/GlueFetchv4\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/GlueFetchv6\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/GlueFetchv4Fail\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/GlueFetchv6Fail\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/ValAttempt\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/ValOk\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/ValNegOk\"/></td>\n"
+       " <td><xsl:value-of select=\"resstats/ValFail\"/></td>\n"
+       " </tr>\n"
+       " </table>\n"
+       " <br/>\n"
+       " </xsl:for-each>\n"
+       "\n"
+       " <br/>\n"
+       "\n"
+       " <xsl:for-each select=\"views/view\">\n"
+       " <table>\n"
+       " <tr class=\"rowh\">\n"
+       " <th colspan=\"2\">Cache DB RRsets for View <xsl:value-of select=\"name\"/></th>\n"
+       " </tr>\n"
+       " <xsl:for-each select=\"cache/rrset\">\n"
+       " <tr class=\"lrow\">\n"
+       " <td><xsl:value-of select=\"name\"/></td>\n"
+       " <td><xsl:value-of select=\"counter\"/></td>\n"
        " </tr>\n"
        " </xsl:for-each>\n"
        " </table>\n"
+       " <br/>\n"
+       " </xsl:for-each>\n"
        "\n"
-       " <br/> \n"
+       " <br/>\n"
        "\n"
        " <xsl:for-each select=\"views/view\">\n"
        " <table>\n"
        " <tr class=\"rowh\">\n"
-       " <th colspan=\"11\">Zones for View <xsl:value-of select=\"name\"/></th>\n"
+       " <th colspan=\"10\">Zones for View <xsl:value-of select=\"name\"/></th>\n"
        " </tr>\n"
        " <tr class=\"rowh\">\n"
        " <th>Name</th>\n"
@@ -128,10 +405,9 @@ static char msg[] =
        " <th>Referral</th>\n"
        " <th>NXRRSET</th>\n"
        " <th>NXDOMAIN</th>\n"
-       " <th>Recursion</th>\n"
        " <th>Failure</th>\n"
-       " <th>Duplicate</th>\n"
-       " <th>Dropped</th>\n"
+       " <th>XfrReqDone</th>\n"
+       " <th>XfrRej</th>\n"
        " </tr>\n"
        " <xsl:for-each select=\"zones/zone\">\n"
        " <tr class=\"lrow\">\n"
@@ -145,28 +421,25 @@ static char msg[] =
        " <xsl:value-of select=\"serial\"/>\n"
        " </td>\n"
        " <td>\n"
-       " <xsl:value-of select=\"counters/success\"/>\n"
-       " </td>\n"
-       " <td>\n"
-       " <xsl:value-of select=\"counters/referral\"/>\n"
+       " <xsl:value-of select=\"counters/QrySuccess\"/>\n"
        " </td>\n"
        " <td>\n"
-       " <xsl:value-of select=\"counters/nxrrset\"/>\n"
+       " <xsl:value-of select=\"counters/QryReferral\"/>\n"
        " </td>\n"
        " <td>\n"
-       " <xsl:value-of select=\"counters/nxdomain\"/>\n"
+       " <xsl:value-of select=\"counters/QryNxrrset\"/>\n"
        " </td>\n"
        " <td>\n"
-       " <xsl:value-of select=\"counters/recursion\"/>\n"
+       " <xsl:value-of select=\"counters/QryNXDOMAIN\"/>\n"
        " </td>\n"
        " <td>\n"
-       " <xsl:value-of select=\"counters/failure\"/>\n"
+       " <xsl:value-of select=\"counters/QryFailure\"/>\n"
        " </td>\n"
        " <td>\n"
-       " <xsl:value-of select=\"counters/duplicate\"/>\n"
+       " <xsl:value-of select=\"counters/XfrReqDone\"/>\n"
        " </td>\n"
        " <td>\n"
-       " <xsl:value-of select=\"counters/dropped\"/>\n"
+       " <xsl:value-of select=\"counters/XfrRej\"/>\n"
        " </td>\n"
        " </tr>\n"
        " </xsl:for-each>\n"
@@ -348,3 +621,76 @@ static char msg[] =
        " </html>\n"
        " </xsl:template>\n"
        "</xsl:stylesheet>\n";
+static const char *nsstats_xmldesc[] = {       "Requestv4",
+       "Requestv6",
+       "ReqEdns0",
+       "ReqBadEDNSVer",
+       "ReqTSIG",
+       "ReqSIG0",
+       "ReqBadSIG",
+       "ReqTCP",
+       "AuthQryRej",
+       "RecQryRej",
+       "XfrRej",
+       "UpdateRej",
+       "Response",
+       "TruncatedResp",
+       "RespEDNS0",
+       "RespTSIG",
+       "RespSIG0",
+       "QrySuccess",
+       "QryAuthAns",
+       "QryNoauthAns",
+       "QryReferral",
+       "QryNxrrset",
+       "QrySERVFAIL",
+       "QryFORMERR",
+       "QryNXDOMAIN",
+       "QryRecursion",
+       "QryDuplicate",
+       "QryDropped",
+       "QryFailure",
+       "XfrReqDone",
+       "UpdateReqFwd",
+       "UpdateRespFwd",
+       "UpdateFwdFail",
+       "UpdateDone",
+       "UpdateFail",
+       "UpdateBadPrereq"
+};
+static const char *zonestats_xmldesc[] = {     "NotifyOutv4",
+       "NotifyOutv6",
+       "NotifyInv4",
+       "NotifyInv6",
+       "NotifyRej",
+       "SOAOutv4",
+       "SOAOutv6",
+       "AXFRReqv4",
+       "AXFRReqv6",
+       "IXFRReqv4",
+       "IXFRReqv6",
+       "XfrSuccess",
+       "XfrFail"
+};
+static const char *resstats_xmldesc[] = {      "Queryv4",
+       "Queryv6",
+       "Responsev4",
+       "Responsev6",
+       "NXDOMAIN",
+       "SERVFAIL",
+       "FORMERR",
+       "OtherError",
+       "EDNS0Fail",
+       "Mismatch",
+       "Truncated",
+       "Lame",
+       "Retry",
+       "GlueFetchv4",
+       "GlueFetchv6",
+       "GlueFetchv4Fail",
+       "GlueFetchv6Fail",
+       "ValAttempt",
+       "ValOk",
+       "ValNegOk",
+       "ValFail"
+};
index eab2fc18a13eba46c690d5118e0b723a54c2b058..3a6f2884f1ef5c5a2d5a47b4bb9e5c4e60288f28 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: client.c,v 1.255 2008/04/03 02:01:08 marka Exp $ */
+/* $Id: client.c,v 1.256 2008/04/03 05:55:51 marka Exp $ */
 
 #include <config.h>
 
@@ -41,6 +41,7 @@
 #include <dns/rdatalist.h>
 #include <dns/rdataset.h>
 #include <dns/resolver.h>
+#include <dns/stats.h>
 #include <dns/tsig.h>
 #include <dns/view.h>
 #include <dns/zone.h>
@@ -918,6 +919,7 @@ ns_client_send(ns_client_t *client) {
        unsigned char sendbuf[SEND_BUFFER_SIZE];
        unsigned int dnssec_opts;
        unsigned int preferred_glue;
+       isc_boolean_t opt_included = ISC_FALSE;
 
        REQUIRE(NS_CLIENT_VALID(client));
 
@@ -958,6 +960,7 @@ ns_client_send(ns_client_t *client) {
 
        if (client->opt != NULL) {
                result = dns_message_setopt(client->message, client->opt);
+               opt_included = ISC_TRUE;
                client->opt = NULL;
                if (result != ISC_R_SUCCESS)
                        goto done;
@@ -1013,6 +1016,26 @@ ns_client_send(ns_client_t *client) {
                result = client_sendpkg(client, &tcpbuffer);
        } else
                result = client_sendpkg(client, &buffer);
+
+       /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
+       dns_generalstats_increment(ns_g_server->nsstats,
+                                  dns_nsstatscounter_response);
+       if (opt_included) {
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_edns0out);
+       }
+       if (client->message->tsigkey != NULL) {
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_tsigout);
+       }
+       if (client->message->sig0key != NULL) {
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_sig0out);
+       }
+       if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_truncatedresp);
+
        if (result == ISC_R_SUCCESS)
                return;
 
@@ -1329,6 +1352,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
        isc_buffer_t tbuffer;
        dns_view_t *view;
        dns_rdataset_t *opt;
+       dns_name_t *signame;
        isc_boolean_t ra;       /* Recursion available. */
        isc_netaddr_t netaddr;
        isc_netaddr_t destaddr;
@@ -1486,6 +1510,20 @@ client_request(isc_task_t *task, isc_event_t *event) {
                }
        }
 
+       /*
+        * Update some statistics counters.  Don't count responses.
+        */
+       if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_requestv4);
+       } else {
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_requestv6);
+       }
+       if (TCP_CLIENT(client))
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_tcp);
+
        /*
         * Hash the incoming request here as it is after
         * dns_dispatch_importrecv().
@@ -1507,6 +1545,8 @@ client_request(isc_task_t *task, isc_event_t *event) {
                goto cleanup;
        }
 
+       dns_opcodestats_increment(ns_g_server->opcodestats,
+                                 client->message->opcode);
        switch (client->message->opcode) {
        case dns_opcode_query:
        case dns_opcode_update:
@@ -1554,6 +1594,8 @@ client_request(isc_task_t *task, isc_event_t *event) {
                 */
                client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
                if (client->ednsversion > 0) {
+                       dns_generalstats_increment(ns_g_server->nsstats,
+                                               dns_nsstatscounter_badednsver);
                        result = client_addopt(client);
                        if (result == ISC_R_SUCCESS)
                                result = DNS_R_BADVERS;
@@ -1578,6 +1620,9 @@ client_request(isc_task_t *task, isc_event_t *event) {
                        }
                }
 
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_edns0in);
+
                /*
                 * Create an OPT for our reply.
                 */
@@ -1722,6 +1767,17 @@ client_request(isc_task_t *task, isc_event_t *event) {
        client->signer = NULL;
        dns_name_init(&client->signername, NULL);
        result = dns_message_signer(client->message, &client->signername);
+       if (result != ISC_R_NOTFOUND) {
+               signame = NULL;
+               if (dns_message_gettsig(client->message, &signame) != NULL) {
+                       dns_generalstats_increment(ns_g_server->nsstats,
+                                                  dns_nsstatscounter_tsigin);
+               } else {
+                       dns_generalstats_increment(ns_g_server->nsstats,
+                                                  dns_nsstatscounter_sig0in);
+               }
+                       
+       }
        if (result == ISC_R_SUCCESS) {
                ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
                              NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
@@ -1738,15 +1794,17 @@ client_request(isc_task_t *task, isc_event_t *event) {
        } else {
                char tsigrcode[64];
                isc_buffer_t b;
-               dns_name_t *name = NULL;
                dns_rcode_t status;
                isc_result_t tresult;
 
                /* There is a signature, but it is bad. */
-               if (dns_message_gettsig(client->message, &name) != NULL) {
+               dns_generalstats_increment(ns_g_server->nsstats,
+                                          dns_nsstatscounter_invalidsig);
+               signame = NULL;
+               if (dns_message_gettsig(client->message, &signame) != NULL) {
                        char namebuf[DNS_NAME_FORMATSIZE];
                        char cnamebuf[DNS_NAME_FORMATSIZE];
-                       dns_name_format(name, namebuf, sizeof(namebuf));
+                       dns_name_format(signame, namebuf, sizeof(namebuf));
                        status = client->message->tsigstatus;
                        isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
                        tresult = dns_tsigrcode_totext(status, &b);
index ea6a2d2d040c7092bfa31cb6e93c210776808bd4..6b4d2d70dfda9c6912e7d4b21ccb4d346a3ae4f5 100755 (executable)
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: convertxsl.pl,v 1.11 2008/04/02 23:46:57 tbox Exp $
+# $Id: convertxsl.pl,v 1.12 2008/04/03 05:55:51 marka Exp $
 
 use strict;
 use warnings;
 
-my $rev = '$Id: convertxsl.pl,v 1.11 2008/04/02 23:46:57 tbox Exp $';
+my $rev = '$Id: convertxsl.pl,v 1.12 2008/04/03 05:55:51 marka Exp $';
 $rev =~ s/\$//g;
 $rev =~ s/,v//g;
 $rev =~ s/Id: //;
 
 my $xsl = "unknown";
-
 my $lines = '';
+my (@nsstatsdesc, @zonestatsdesc, @resstatsdesc);
 
 while (<>) {
     chomp;
@@ -34,6 +34,13 @@ while (<>) {
     $xsl = $_ if (/<!-- .Id:.* -->/);
     # convert Id string to a form not recognisable by cvs.
     $_ =~ s/<!-- .Id:(.*). -->/<!-- \\045Id: $1\\045 -->/;
+    if (/server\/nsstats\/(\w+)\"/) {
+       push(@nsstatsdesc, $1);
+    } elsif (/server\/zonestats\/(\w+)\"/) {
+       push(@zonestatsdesc, $1);
+    } elsif (/\"resstats\/(\w+)\"/) {
+       push(@resstatsdesc, $1);
+    }
     s/[\ \t]+/ /g;
     s/\>\ \</\>\</g;
     s/\"/\\\"/g;
@@ -52,7 +59,31 @@ $xsl =~ s/ -->.*//;
 $xsl =~ s/,v//;
 
 print "/*\n * Generated by $rev \n * From $xsl\n */\n";
-print 'static char msg[] =',"\n";
+print 'static char xslmsg[] =',"\n";
 print $lines;
 
 print ';', "\n";
+
+print "static const char *nsstats_xmldesc[] = {";
+while (my $desc = shift(@nsstatsdesc)) {
+       print "\t\"$desc\"";
+       print "," if (@nsstatsdesc);
+       print "\n";
+}
+print "};\n";
+
+print "static const char *zonestats_xmldesc[] = {";
+while (my $desc = shift(@zonestatsdesc)) {
+       print "\t\"$desc\"";
+       print "," if (@zonestatsdesc);
+       print "\n";
+}
+print "};\n";
+
+print "static const char *resstats_xmldesc[] = {";
+while (my $desc = shift(@resstatsdesc)) {
+       print "\t\"$desc\"";
+       print "," if (@resstatsdesc);
+       print "\n";
+}
+print "};\n";
index 1bf0524472dcf3f5d593be8abb4b0b443c280ce3..d3a75fd93351cc43060f4b639bce4c8ae56df3e2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.h,v 1.92 2008/01/24 02:00:44 jinmei Exp $ */
+/* $Id: server.h,v 1.93 2008/04/03 05:55:51 marka Exp $ */
 
 #ifndef NAMED_SERVER_H
 #define NAMED_SERVER_H 1
@@ -91,7 +91,11 @@ struct ns_server {
        isc_boolean_t           flushonshutdown;
        isc_boolean_t           log_queries;    /*%< For BIND 8 compatibility */
 
-       dns_stats_t *           querystats;     /*%< Query statistics counters */
+       dns_stats_t *           nsstats;        /*%< Server statistics */
+       dns_stats_t *           rcvquerystats;  /*% Incoming query statistics */
+       dns_stats_t *           opcodestats;    /*%< Incoming message statistics */
+       dns_stats_t *           zonestats;      /*% Zone management statistics */
+       dns_stats_t *           resolverstats;  /*% Resolver statistics */
 
        ns_controls_t *         controls;       /*%< Control channels */
        unsigned int            dispatchgen;
@@ -105,6 +109,55 @@ struct ns_server {
 #define NS_SERVER_MAGIC                        ISC_MAGIC('S','V','E','R')
 #define NS_SERVER_VALID(s)             ISC_MAGIC_VALID(s, NS_SERVER_MAGIC)
 
+/*%
+ * Server statistics counters.  Used as dns_statscounter_t values.
+ */
+enum {
+       dns_nsstatscounter_requestv4 = 0,
+       dns_nsstatscounter_requestv6 = 1,
+       dns_nsstatscounter_edns0in = 2,
+       dns_nsstatscounter_badednsver = 3,
+       dns_nsstatscounter_tsigin = 4,
+       dns_nsstatscounter_sig0in = 5,
+       dns_nsstatscounter_invalidsig = 6,
+       dns_nsstatscounter_tcp = 7,
+
+       dns_nsstatscounter_authrej = 8,
+       dns_nsstatscounter_recurserej = 9,
+       dns_nsstatscounter_xfrrej = 10,
+       dns_nsstatscounter_updaterej = 11,
+
+       dns_nsstatscounter_response = 12,
+       dns_nsstatscounter_truncatedresp = 13,
+       dns_nsstatscounter_edns0out = 14,
+       dns_nsstatscounter_tsigout = 15,
+       dns_nsstatscounter_sig0out = 16,
+
+       dns_nsstatscounter_success = 17,
+       dns_nsstatscounter_authans = 18,
+       dns_nsstatscounter_nonauthans = 19,
+       dns_nsstatscounter_referral = 20,
+       dns_nsstatscounter_nxrrset = 21,
+       dns_nsstatscounter_servfail = 22,
+       dns_nsstatscounter_formerr = 23,
+       dns_nsstatscounter_nxdomain = 24,
+       dns_nsstatscounter_recursion = 25,
+       dns_nsstatscounter_duplicate = 26,
+       dns_nsstatscounter_dropped = 27,
+       dns_nsstatscounter_failure = 28,
+
+       dns_nsstatscounter_xfrdone = 29,
+
+       dns_nsstatscounter_updatereqfwd = 30,
+       dns_nsstatscounter_updaterespfwd = 31,
+       dns_nsstatscounter_updatefwdfail = 32,
+       dns_nsstatscounter_updatedone = 33,
+       dns_nsstatscounter_updatefail = 34,
+       dns_nsstatscounter_updatebadprereq = 35,
+
+       dns_nsstatscounter_max = 36
+};
+
 void
 ns_server_create(isc_mem_t *mctx, ns_server_t **serverp);
 /*%<
index 13c941ae0631386ffbcda99c7eca50c3507f2728..0c36d8c706cea8db42e6c4b74f42726831865562 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: statschannel.h,v 1.2 2008/01/17 00:15:13 jinmei Exp $ */
+/* $Id: statschannel.h,v 1.3 2008/04/03 05:55:51 marka Exp $ */
 
 #ifndef NAMED_STATSCHANNEL_H
 #define NAMED_STATSCHANNEL_H 1
@@ -52,4 +52,10 @@ ns_statschannels_shutdown(ns_server_t *server);
  * Initiate shutdown of all the statistics channel listeners.
  */
 
+isc_result_t
+ns_stats_dump(ns_server_t *server, FILE *fp);
+/*%<
+ * Dump statistics counters managed by the server to the file fp.
+ */
+
 #endif /* NAMED_STATSCHANNEL_H */
index 21c47f5ffc72b083110772b7a7eab398665f0021..ea5109a7f5fbeec8872a85141bc2292901b1222c 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: query.c,v 1.304 2008/04/01 01:37:24 marka Exp $ */
+/* $Id: query.c,v 1.305 2008/04/03 05:55:51 marka Exp $ */
 
 /*! \file */
 
@@ -128,35 +128,37 @@ static inline void
 inc_stats(ns_client_t *client, dns_statscounter_t counter) {
        dns_zone_t *zone = client->query.authzone;
 
-       REQUIRE(counter < DNS_STATS_NCOUNTERS);
-
-       dns_stats_incrementcounter(ns_g_server->querystats, counter);
+       dns_generalstats_increment(ns_g_server->nsstats, counter);
 
        if (zone != NULL) {
-               dns_stats_t *zonestats = dns_zone_getstats(zone);
+               dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
                if (zonestats != NULL)
-                       dns_stats_incrementcounter(zonestats, counter);
+                       dns_generalstats_increment(zonestats, counter);
        }
 }
 
 static void
 query_send(ns_client_t *client) {
        dns_statscounter_t counter;
+       if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0)
+               inc_stats(client, dns_nsstatscounter_nonauthans);
+       else
+               inc_stats(client, dns_nsstatscounter_authans);
        if (client->message->rcode == dns_rcode_noerror) {
                if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER])) {
                        if (client->query.isreferral) {
-                               counter = dns_statscounter_referral;
+                               counter = dns_nsstatscounter_referral;
                        } else {
-                               counter = dns_statscounter_nxrrset;
+                               counter = dns_nsstatscounter_nxrrset;
                        }
                } else {
-                       counter = dns_statscounter_success;
+                       counter = dns_nsstatscounter_success;
                }
        } else if (client->message->rcode == dns_rcode_nxdomain) {
-               counter = dns_statscounter_nxdomain;
+               counter = dns_nsstatscounter_nxdomain;
        } else {
                /* We end up here in case of YXDOMAIN, and maybe others */
-               counter = dns_statscounter_failure;
+               counter = dns_nsstatscounter_failure;
        }
        inc_stats(client, counter);
        ns_client_send(client);
@@ -164,18 +166,28 @@ query_send(ns_client_t *client) {
 
 static void
 query_error(ns_client_t *client, isc_result_t result) {
-       inc_stats(client, dns_statscounter_failure);
+       switch (result) {
+       case DNS_R_SERVFAIL:
+               inc_stats(client, dns_nsstatscounter_servfail);
+               break;
+       case DNS_R_FORMERR:
+               inc_stats(client, dns_nsstatscounter_formerr);
+               break;
+       default:
+               inc_stats(client, dns_nsstatscounter_failure);
+               break;
+       }
        ns_client_error(client, result);
 }
 
 static void
 query_next(ns_client_t *client, isc_result_t result) {
        if (result == DNS_R_DUPLICATE)
-               inc_stats(client, dns_statscounter_duplicate);
+               inc_stats(client, dns_nsstatscounter_duplicate);
        else if (result == DNS_R_DROP)
-               inc_stats(client, dns_statscounter_dropped);
+               inc_stats(client, dns_nsstatscounter_dropped);
        else
-               inc_stats(client, dns_statscounter_failure);
+               inc_stats(client, dns_nsstatscounter_failure);
        ns_client_next(client, result);
 }
 
@@ -2935,7 +2947,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
        dns_rdataset_t *rdataset, *sigrdataset;
        isc_sockaddr_t *peeraddr;
 
-       inc_stats(client, dns_statscounter_recursion);
+       inc_stats(client, dns_nsstatscounter_recursion);
 
        /*
         * We are about to recurse, which means that this client will
@@ -3494,6 +3506,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
        }
        if (result != ISC_R_SUCCESS) {
                if (result == DNS_R_REFUSED) {
+                       if (WANTRECURSION(client)) {
+                               inc_stats(client,
+                                         dns_nsstatscounter_recurserej);
+                       } else
+                               inc_stats(client, dns_nsstatscounter_authrej);
                        if (!PARTIALANSWER(client))
                                QUERY_ERROR(DNS_R_REFUSED);
                } else
@@ -4550,6 +4567,7 @@ ns_query_start(ns_client_t *client) {
        rdataset = ISC_LIST_HEAD(client->query.qname->list);
        INSIST(rdataset != NULL);
        qtype = rdataset->type;
+       dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
        if (dns_rdatatype_ismeta(qtype)) {
                switch (qtype) {
                case dns_rdatatype_any:
index fb018b6ce9ddc6da5c078f36f195ae8f31006998..b6dbd7370ecbbcae1018e03b051aaf0dfcc3173d 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.504 2008/04/03 02:01:08 marka Exp $ */
+/* $Id: server.c,v 1.505 2008/04/03 05:55:51 marka Exp $ */
 
 /*! \file */
 
@@ -942,6 +942,24 @@ check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv,
        isc_mem_free(mctx, argv);
 }
 
+static isc_result_t
+setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) {
+       isc_result_t result;
+       dns_stats_t *zoneqrystats;
+
+       zoneqrystats = NULL;
+       if (on) {
+               result = dns_generalstats_create(mctx, &zoneqrystats,
+                                                dns_nsstatscounter_max);
+               if (result != ISC_R_SUCCESS)
+                       return (result);
+       }
+       dns_zone_setrequeststats(zone, zoneqrystats);
+       if (zoneqrystats != NULL)
+               dns_stats_detach(&zoneqrystats);
+
+       return (ISC_R_SUCCESS);
+}
 
 /*
  * Configure 'view' according to 'vconfig', taking defaults from 'config'
@@ -998,6 +1016,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
        isc_boolean_t empty_zones_enable;
        const cfg_obj_t *disablelist = NULL;
        isc_uint32_t nqports, qports_updateinterval;
+       dns_stats_t *resstats = NULL;
+       dns_stats_t *resquerystats = NULL;
 
        REQUIRE(DNS_VIEW_VALID(view));
 
@@ -1142,6 +1162,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
         * Configure the view's cache.  Try to reuse an existing
         * cache if possible, otherwise create a new cache.
         * Note that the ADB is not preserved in either case.
+        * When a matching view is found, the associated statistics are
+        * also retrieved and reused.
         *
         * XXX Determining when it is safe to reuse a cache is
         * tricky.  When the view's configuration changes, the cached
@@ -1163,6 +1185,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                              "reusing existing cache");
                reused_cache = ISC_TRUE;
                dns_cache_attach(pview->cache, &cache);
+               dns_view_getresstats(pview, &resstats);
+               dns_view_getresquerystats(pview, &resquerystats);
                dns_view_detach(&pview);
        } else {
                CHECK(isc_mem_create(0, 0, &cmctx));
@@ -1344,6 +1368,15 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                                                      * 60));
        }
 
+       if (resstats == NULL) {
+               CHECK(dns_generalstats_create(mctx, &resstats,
+                                             dns_resstatscounter_max));
+       }
+       dns_view_setresstats(view, resstats);
+       if (resquerystats == NULL)
+               CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
+       dns_view_setresquerystats(view, resquerystats);
+       
        /*
         * Set the ADB cache size to 1/8th of the max-cache-size.
         */
@@ -1835,6 +1868,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                const char *empty_dbtype[4] =
                                    { "_builtin", "empty", NULL, NULL };
                int empty_dbtypec = 4;
+               isc_boolean_t zonestats_on;
 
                dns_fixedname_init(&fixed);
                name = dns_fixedname_name(&fixed);
@@ -1869,6 +1903,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                } else
                        empty_dbtype[3] = ".";
 
+               obj = NULL;
+               result = ns_config_get(maps, "zone-statistics", &obj);
+               INSIST(result == ISC_R_SUCCESS);
+               zonestats_on = cfg_obj_asboolean(obj);
+
                logit = ISC_TRUE;
                for (empty = empty_zones[empty_zone].zone;
                     empty != NULL;
@@ -1893,6 +1932,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                         */
                        (void)dns_view_findzone(view, name, &zone);
                        if (zone != NULL) {
+                               CHECK(setquerystats(zone, mctx, zonestats_on));
                                dns_zone_detach(&zone);
                                continue;
                        }
@@ -1943,6 +1983,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                                if (zone != NULL) {
                                        dns_zone_setview(zone, view);
                                        CHECK(dns_view_addzone(view, zone));
+                                       CHECK(setquerystats(zone, mctx,
+                                                           zonestats_on));
                                        dns_zone_detach(&zone);
                                        continue;
                                }
@@ -1954,6 +1996,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                        CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
                        dns_zone_setclass(zone, view->rdclass);
                        dns_zone_settype(zone, dns_zone_master);
+                       dns_zone_setstats(zone, ns_g_server->zonestats);
                        CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
                                                 empty_dbtype));
                        if (view->queryacl != NULL)
@@ -1964,6 +2007,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                        dns_zone_setnotifytype(zone, dns_notifytype_no);
                        dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS,
                                           ISC_TRUE);
+                       CHECK(setquerystats(zone, mctx, zonestats_on));
                        CHECK(dns_view_addzone(view, zone));
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
@@ -1982,6 +2026,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
                dns_dispatch_detach(&dispatch4);
        if (dispatch6 != NULL)
                dns_dispatch_detach(&dispatch6);
+       if (resstats != NULL)
+               dns_stats_detach(&resstats);
+       if (resquerystats != NULL)
+               dns_stats_detach(&resquerystats);
        if (order != NULL)
                dns_order_detach(&order);
        if (cmctx != NULL)
@@ -2430,6 +2478,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
                if (view->acache != NULL)
                        dns_zone_setacache(zone, view->acache);
                CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+               dns_zone_setstats(zone, ns_g_server->zonestats);
        }
 
        /*
@@ -3613,6 +3662,8 @@ run_server(isc_task_t *task, isc_event_t *event) {
                                          &ns_g_dispatchmgr),
                   "creating dispatch manager");
 
+       dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats);
+
        CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
                                          ns_g_socketmgr, ns_g_dispatchmgr,
                                          &server->interfacemgr),
@@ -3801,7 +3852,11 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
        server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
        CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
                   "isc_mem_strdup");
-       server->querystats = NULL;
+       server->nsstats = NULL;
+       server->rcvquerystats = NULL;
+       server->opcodestats = NULL;
+       server->zonestats = NULL;
+       server->resolverstats = NULL;
 
        server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
        CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
@@ -3818,8 +3873,24 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
        server->server_usehostname = ISC_FALSE;
        server->server_id = NULL;
 
-       CHECKFATAL(dns_stats_create(ns_g_mctx, &server->querystats),
-                  "dns_stats_create");
+       CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->nsstats,
+                                          dns_nsstatscounter_max),
+                  "dns_stats_create (server)");
+
+       CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx, 
+                                            &server->rcvquerystats),
+                  "dns_stats_create (rcvquery)");
+
+       CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),
+                  "dns_stats_create (opcode)");
+
+       CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->zonestats,
+                                          dns_zonestatscounter_max),
+                  "dns_stats_create (zone)");
+
+       CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->resolverstats,
+                                          dns_resstatscounter_max),
+                  "dns_stats_create (resolver)");
 
        server->flushonshutdown = ISC_FALSE;
        server->log_queries = ISC_FALSE;
@@ -3843,7 +3914,11 @@ ns_server_destroy(ns_server_t **serverp) {
 
        ns_controls_destroy(&server->controls);
 
-       dns_stats_destroy(server->mctx, &server->querystats);
+       dns_stats_detach(&server->nsstats);
+       dns_stats_detach(&server->rcvquerystats);
+       dns_stats_detach(&server->opcodestats);
+       dns_stats_detach(&server->zonestats);
+       dns_stats_detach(&server->resolverstats);
 
        isc_mem_free(server->mctx, server->statsfile);
        isc_mem_free(server->mctx, server->dumpfile);
@@ -4407,60 +4482,14 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
 isc_result_t
 ns_server_dumpstats(ns_server_t *server) {
        isc_result_t result;
-       dns_zone_t *zone, *next;
-       isc_stdtime_t now;
        FILE *fp = NULL;
-       int i;
-       int ncounters;
-       isc_uint64_t counters[DNS_STATS_NCOUNTERS];
-
-       isc_stdtime_get(&now);
 
        CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
                "could not open statistics dump file", server->statsfile);
 
-       ncounters = DNS_STATS_NCOUNTERS;
-       fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
-
-       dns_stats_copy(server->querystats, counters);
-       for (i = 0; i < ncounters; i++)
-               fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n",
-                       dns_statscounter_names[i], counters[i]);
-
-       zone = NULL;
-       for (result = dns_zone_first(server->zonemgr, &zone);
-            result == ISC_R_SUCCESS;
-            next = NULL, result = dns_zone_next(zone, &next), zone = next)
-       {
-               dns_stats_t *zonestats = dns_zone_getstats(zone);
-               if (zonestats != NULL) {
-                       char zonename[DNS_NAME_FORMATSIZE];
-                       dns_view_t *view;
-                       char *viewname;
-
-                       dns_stats_copy(zonestats, counters);
-                       dns_name_format(dns_zone_getorigin(zone),
-                                       zonename, sizeof(zonename));
-                       view = dns_zone_getview(zone);
-                       viewname = view->name;
-                       for (i = 0; i < ncounters; i++) {
-                               fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT
-                                       "u %s",
-                                       dns_statscounter_names[i],
-                                       counters[i],
-                                       zonename);
-                               if (strcmp(viewname, "_default") != 0)
-                                       fprintf(fp, " %s", viewname);
-                               fprintf(fp, "\n");
-                       }
-               }
-       }
-       if (result == ISC_R_NOMORE)
-               result = ISC_R_SUCCESS;
+       result = ns_stats_dump(server, fp);
        CHECK(result);
 
-       fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
-
  cleanup:
        if (fp != NULL)
                (void)isc_stdio_close(fp);
index 3bdef8bddf9fae3355bdae3168351b221e35337b..d3be8697277f093da6ae336f587491cea87a8f94 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: statschannel.c,v 1.6 2008/03/31 05:00:29 marka Exp $ */
+/* $Id: statschannel.c,v 1.7 2008/04/03 05:55:51 marka Exp $ */
 
 /*! \file */
 
 #include <isc/socket.h>
 #include <isc/task.h>
 
+#include <dns/db.h>
+#include <dns/opcode.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
 #include <dns/stats.h>
 #include <dns/view.h>
+#include <dns/zt.h>
 
 #include <named/log.h>
 #include <named/server.h>
 #include <named/statschannel.h>
 
+#include "bind9.xsl.h"
+
 struct ns_statschannel {
        /* Unlocked */
        isc_httpdmgr_t                          *httpdmgr;
@@ -51,6 +58,188 @@ struct ns_statschannel {
        ISC_LINK(struct ns_statschannel)        link;
 };
 
+typedef enum { statsformat_file, statsformat_xml } statsformat_t;
+
+typedef struct
+stats_dumparg {
+       statsformat_t   type;
+       void            *arg;           /* type dependent argument */
+       const char      **desc;         /* used for general statistics */
+       int             ncounters;      /* used for general statistics */
+} stats_dumparg_t;
+
+static void
+generalstat_dump(dns_statscounter_t counter, isc_uint64_t val, void *arg) {
+       stats_dumparg_t *dumparg = arg;
+       FILE *fp;
+#ifdef HAVE_LIBXML2
+       xmlTextWriterPtr writer;
+#endif
+
+       REQUIRE(counter < dumparg->ncounters);
+
+       switch (dumparg->type) {
+       case statsformat_file:
+               fp = dumparg->arg; 
+               fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val,
+                       dumparg->desc[counter]);
+               break;
+       case statsformat_xml:
+#ifdef HAVE_LIBXML2
+               writer = dumparg->arg;
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR
+                                         dumparg->desc[counter]);
+               xmlTextWriterWriteFormatString(writer,
+                                              "%" ISC_PRINT_QUADFORMAT "u",
+                                              val);
+               xmlTextWriterEndElement(writer);
+#endif
+               break;
+       }
+}
+
+static void
+rdtypestat_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) {
+       char typebuf[64];
+       const char *typestr;
+       stats_dumparg_t *dumparg = arg;
+       FILE *fp;
+#ifdef HAVE_LIBXML2
+       xmlTextWriterPtr writer;
+#endif
+
+       if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_OTHERTYPE)
+           == 0) {
+               dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
+                                    sizeof(typebuf));
+               typestr = typebuf;
+       } else
+               typestr = "Others";
+
+       switch (dumparg->type) {
+       case statsformat_file:
+               fp = dumparg->arg;
+               fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, typestr);
+               break;
+       case statsformat_xml:
+#ifdef HAVE_LIBXML2
+               writer = dumparg->arg;
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "rdtype");
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+               xmlTextWriterWriteString(writer, ISC_XMLCHAR typestr);
+               xmlTextWriterEndElement(writer); /* name */
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter");
+               xmlTextWriterWriteFormatString(writer,
+                                              "%" ISC_PRINT_QUADFORMAT "u",
+                                              val);
+               xmlTextWriterEndElement(writer); /* counter */
+
+               xmlTextWriterEndElement(writer); /* rdtype */
+#endif
+               break;
+       }
+}
+
+static void
+rdatasetstats_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) {
+       stats_dumparg_t *dumparg = arg;
+       FILE *fp;
+       char typebuf[64];
+       const char *typestr;
+       isc_boolean_t nxrrset = ISC_FALSE;
+#ifdef HAVE_LIBXML2
+       xmlTextWriterPtr writer;
+#endif
+
+       if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_NXDOMAIN)
+           != 0) {
+               typestr = "NXDOMAIN";
+       } else if ((DNS_RDATASTATSTYPE_ATTR(type) &
+                   DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0) {
+               typestr = "Others";
+       } else {
+               dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
+                                    sizeof(typebuf));
+               typestr = typebuf;
+       }
+
+       if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_NXRRSET)
+           != 0)
+               nxrrset = ISC_TRUE;
+
+       switch (dumparg->type) {
+       case statsformat_file:
+               fp = dumparg->arg;
+               fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s%s\n", val,
+                       nxrrset ? "!" : "", typestr);
+               break;
+       case statsformat_xml:
+#ifdef HAVE_LIBXML2
+               writer = dumparg->arg;
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "rrset");
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+               xmlTextWriterWriteFormatString(writer, "%s%s",
+                                              nxrrset ? "!" : "", typestr);
+               xmlTextWriterEndElement(writer); /* name */
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter");
+               xmlTextWriterWriteFormatString(writer,
+                                              "%" ISC_PRINT_QUADFORMAT "u",
+                                              val);
+               xmlTextWriterEndElement(writer); /* counter */
+
+               xmlTextWriterEndElement(writer); /* rrset */
+#endif
+               break;
+       }
+}
+
+static void
+opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) {
+       FILE *fp = arg;
+       isc_buffer_t b;
+       char codebuf[64];
+       stats_dumparg_t *dumparg = arg;
+#ifdef HAVE_LIBXML2
+       xmlTextWriterPtr writer;
+#endif
+
+       isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1);
+       dns_opcode_totext(code, &b);
+       codebuf[isc_buffer_usedlength(&b)] = '\0';
+
+       switch (dumparg->type) {
+       case statsformat_file:
+               fp = dumparg->arg;
+               fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, codebuf);
+               break;
+       case statsformat_xml:
+#ifdef HAVE_LIBXML2
+               writer = dumparg->arg;
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "opcode");
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+               xmlTextWriterWriteString(writer, ISC_XMLCHAR codebuf);
+               xmlTextWriterEndElement(writer); /* name */
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter");
+               xmlTextWriterWriteFormatString(writer,
+                                              "%" ISC_PRINT_QUADFORMAT "u",
+                                              val);
+               xmlTextWriterEndElement(writer); /* counter */
+
+               xmlTextWriterEndElement(writer); /* opcode */
+#endif
+               break;
+       }
+}
+
 #ifdef HAVE_LIBXML2
 
 /* XXXMLG below here sucks. */
@@ -58,8 +247,50 @@ struct ns_statschannel {
 #define TRY(a) do { result = (a); INSIST(result == ISC_R_SUCCESS); } while(0);
 #define TRY0(a) do { xmlrc = (a); INSIST(xmlrc >= 0); } while(0);
 
-#define NODES 8
-#define SPACES 3
+static isc_result_t
+zone_xmlrender(dns_zone_t *zone, void *arg) {
+       char buf[1024 + 32];    /* sufficiently large for zone name and class */
+       dns_rdataclass_t rdclass;
+       isc_uint32_t serial;
+       xmlTextWriterPtr writer = arg;
+       stats_dumparg_t dumparg;
+       dns_stats_t *zonestats;
+
+       xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone");
+
+       dns_zone_name(zone, buf, sizeof(buf));
+       xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+       xmlTextWriterWriteString(writer, ISC_XMLCHAR buf);
+       xmlTextWriterEndElement(writer);
+
+       rdclass = dns_zone_getclass(zone);
+       dns_rdataclass_format(rdclass, buf, sizeof(buf));
+       xmlTextWriterStartElement(writer, ISC_XMLCHAR "rdataclass");
+       xmlTextWriterWriteString(writer, ISC_XMLCHAR buf);
+       xmlTextWriterEndElement(writer);
+
+       serial = dns_zone_getserial(zone);
+       xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial");
+       xmlTextWriterWriteFormatString(writer, "%u", serial);
+       xmlTextWriterEndElement(writer);
+
+       dumparg.type = statsformat_xml;
+       dumparg.arg = writer;
+       dumparg.desc = nsstats_xmldesc;
+       dumparg.ncounters = dns_nsstatscounter_max;
+
+       zonestats = dns_zone_getrequeststats(zone);
+       if (zonestats != NULL) {
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters");
+               dns_generalstats_dump(zonestats, generalstat_dump,
+                                     &dumparg, DNS_STATSDUMP_VERBOSE);
+               xmlTextWriterEndElement(writer); /* counters */
+       }
+
+       xmlTextWriterEndElement(writer); /* zone */
+
+       return (ISC_R_SUCCESS);
+}
 
 static void
 generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
@@ -70,8 +301,8 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
        xmlDocPtr doc;
        int xmlrc;
        dns_view_t *view;
-       int i;
-       isc_uint64_t counters[DNS_STATS_NCOUNTERS];
+       stats_dumparg_t dumparg;
+       dns_stats_t *cachestats;
 
        isc_time_now(&now);
        isc_time_formatISO8601(&ns_g_boottime, boottime, sizeof boottime);
@@ -90,6 +321,10 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
        TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
                                         ISC_XMLCHAR "1.0"));
 
+       /* Set common fields for statistics dump */
+       dumparg.type = statsformat_xml;
+       dumparg.arg = writer;
+
        /*
         * Start by rendering the views we know of here.  For each view we
         * know of, call its rendering function.
@@ -97,7 +332,43 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
        view = ISC_LIST_HEAD(server->viewlist);
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views"));
        while (view != NULL) {
-               dns_view_xmlrender(view, writer, ISC_XML_RENDERALL);
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "view");
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+               xmlTextWriterWriteString(writer, ISC_XMLCHAR view->name);
+               xmlTextWriterEndElement(writer);
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "zones");
+               dns_zt_apply(view->zonetable, ISC_FALSE, zone_xmlrender,
+                            writer);
+               xmlTextWriterEndElement(writer);
+
+               if (view->resquerystats != NULL) {
+                       dns_rdatatypestats_dump(view->resquerystats,
+                                               rdtypestat_dump, &dumparg, 0);
+               }
+
+               if (view->resstats != NULL) {
+                       xmlTextWriterStartElement(writer,
+                                                 ISC_XMLCHAR "resstats");
+                       dumparg.ncounters = dns_resstatscounter_max;
+                       dumparg.desc = resstats_xmldesc; /* auto-generated */
+                       dns_generalstats_dump(view->resstats, generalstat_dump,
+                                             &dumparg, DNS_STATSDUMP_VERBOSE);
+                       xmlTextWriterEndElement(writer); /* resstats */
+               }
+
+               cachestats = dns_db_getrrsetstats(view->cachedb);
+               if (cachestats != NULL) {
+                       xmlTextWriterStartElement(writer,
+                                                 ISC_XMLCHAR "cache");
+                       dns_rdatasetstats_dump(cachestats, rdatasetstats_dump,
+                                              &dumparg, 0);
+                       xmlTextWriterEndElement(writer); /* cache */
+               }
+
+               xmlTextWriterEndElement(writer); /* view */
+
                view = ISC_LIST_NEXT(view, link);
        }
        TRY0(xmlTextWriterEndElement(writer)); /* views */
@@ -117,17 +388,38 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time");
        xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr);
        xmlTextWriterEndElement(writer);
-       TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
-       dns_stats_copy(server->querystats, counters);
-       for (i = 0; i < DNS_STATS_NCOUNTERS; i++) {
-               xmlTextWriterStartElement(writer,
-                                       ISC_XMLCHAR dns_statscounter_names[i]);
-               xmlTextWriterWriteFormatString(writer,
-                                              "%" ISC_PRINT_QUADFORMAT "u",
-                                              counters[i]);
-               xmlTextWriterEndElement(writer);
-       }
-       xmlTextWriterEndElement(writer); /* counters */
+
+       TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "requests"));
+       dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
+                            0);
+       xmlTextWriterEndElement(writer); /* requests */
+
+       TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "queries-in"));
+       dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
+                               &dumparg, 0);
+       xmlTextWriterEndElement(writer); /* queries-in */
+
+       TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nsstats"));
+       dumparg.desc = nsstats_xmldesc; /* auto-generated in bind9.xsl.h */
+       dumparg.ncounters = dns_nsstatscounter_max;
+       dns_generalstats_dump(server->nsstats, generalstat_dump, &dumparg,
+                             DNS_STATSDUMP_VERBOSE);
+       xmlTextWriterEndElement(writer); /* nsstats */
+
+       TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zonestats"));
+       dumparg.desc = zonestats_xmldesc; /* auto-generated in bind9.xsl.h */
+       dumparg.ncounters = dns_zonestatscounter_max;
+       dns_generalstats_dump(server->zonestats, generalstat_dump, &dumparg,
+                             DNS_STATSDUMP_VERBOSE);
+       xmlTextWriterEndElement(writer); /* zonestats */
+
+       xmlTextWriterStartElement(writer, ISC_XMLCHAR "resstats");
+       dumparg.ncounters = dns_resstatscounter_max;
+       dumparg.desc = resstats_xmldesc;
+       dns_generalstats_dump(server->resolverstats, generalstat_dump,
+                             &dumparg, DNS_STATSDUMP_VERBOSE);
+       xmlTextWriterEndElement(writer); /* resstats */
+
        xmlTextWriterEndElement(writer); /* server */
 
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory"));
@@ -187,8 +479,6 @@ render_xsl(const char *url, const char *querystring, void *args,
           isc_buffer_t *b, isc_httpdfree_t **freecb,
           void **freecb_args)
 {
-#include "bind9.xsl.h"
-
        UNUSED(url);
        UNUSED(querystring);
        UNUSED(args);
@@ -196,8 +486,8 @@ render_xsl(const char *url, const char *querystring, void *args,
        *retcode = 200;
        *retmsg = "OK";
        *mimetype = "text/xslt+xml";
-       isc_buffer_reinit(b, msg, strlen(msg));
-       isc_buffer_add(b, strlen(msg));
+       isc_buffer_reinit(b, xslmsg, strlen(xslmsg));
+       isc_buffer_add(b, strlen(xslmsg));
        *freecb = NULL;
        *freecb_args = NULL;
 
@@ -533,3 +823,207 @@ ns_statschannels_shutdown(ns_server_t *server) {
                shutdown_listener(listener);
        }
 }
+
+/* name server statistics */
+static const char *nsstats_desc[] = {
+       "IPv4 requests received",         /* dns_nsstatscounter_requestv4 */
+       "IPv6 requests received",         /* dns_nsstatscounter_requestv6 */
+       "requests with EDNS(0) received", /* dns_nsstatscounter_edns0in */
+       "requests with unsupported EDNS "
+       "version received",             /* dns_nsstatscounter_badednsver */
+       "requests with TSIG received",    /* dns_nsstatscounter_tsigin */
+       "requests with SIG(0) received",  /* dns_nsstatscounter_sig0in */
+       "requests with invalid signature",/* dns_nsstatscounter_invalidsig */
+       "TCP requests received",          /* dns_nsstatscounter_tcp */
+
+       "auth queries rejected",          /* dns_nsstatscounter_authrej */
+       "recursive queries rejected",     /* dns_nsstatscounter_recurserej */
+       "transfer requests rejected",     /* dns_nsstatscounter_xfrrej */
+       "update requests rejected",       /* dns_nsstatscounter_updaterej */
+
+       "responses sent",                 /* dns_nsstatscounter_response */
+       "truncated responses sent",     /* dns_nsstatscounter_truncatedresp */
+       "responses with EDNS(0) sent",    /* dns_nsstatscounter_edns0out */
+       "responses with TSIG sent",       /* dns_nsstatscounter_tsigout */
+       "responses with SIG(0) sent",     /* dns_nsstatscounter_sig0out */
+
+       "queries resulted in successful answer",/* dns_nsstatscounter_success */
+       "queries resulted in "
+       "authoritative answer",         /* dns_nsstatscounter_authans */
+       "queries resulted in non "
+       "authoritative answer",         /* dns_nsstatscounter_nonauthans */
+       "queries resulted in referral answer", /* dns_nsstatscounter_referral */
+       "queries resulted in nxrrset",    /* dns_nsstatscounter_nxrrset */
+       "queries resulted in SERVFAIL",   /* dns_nsstatscounter_servfail */
+       "queries resulted in FORMERR",    /* dns_nsstatscounter_formerr */
+       "queries resulted in NXDOMAIN",   /* dns_nsstatscounter_nxdomain */
+       "queries caused recursion",       /* dns_nsstatscounter_recursion */
+       "duplicate queries received",     /* dns_nsstatscounter_duplicate */
+       "queries dropped",                /* dns_nsstatscounter_dropped */
+       "other query failures",           /* dns_nsstatscounter_failure */
+
+       "requested transfers completed",  /* dns_nsstatscounter_xfrdone */
+
+       "update requests forwarded",    /* dns_nsstatscounter_updatereqfwd */
+       "update responses forwarded",   /* dns_nsstatscounter_updaterespfwd */
+       "update forward failed",        /* dns_nsstatscounter_updatefwdfail */
+       "updates completed",            /* dns_nsstatscounter_updatedone */
+       "updates failed",               /* dns_nsstatscounter_updatefail */
+       "updates rejected due to "
+       "prerequisite failure"          /* dns_nsstatscounter_updatebadprereq */
+};
+
+/* resolver statistics */
+static const char *resstats_desc[] = {
+       "IPv4 queries sent",            /* dns_resstatscounter_queryv4 */
+       "IPv6 queries sent",            /* dns_resstatscounter_queryv6 */
+       "IPv4 responses received",      /* dns_resstatscounter_responsev4 */
+       "IPv6 responses received",      /* dns_resstatscounter_responsev6 */
+       "NXDOMAIN received",            /* dns_resstatscounter_nxdomain */
+       "SERVFAIL received",            /* dns_resstatscounter_servfail */
+       "FORMERR received",             /* dns_resstatscounter_formerr */
+       "other errors received",        /* dns_resstatscounter_othererror */
+       "EDNS(0) query failures",       /* dns_resstatscounter_edns0fail */
+       "mismatch responses received",  /* dns_resstatscounter_mismatch */
+       "truncated responses received", /* dns_resstatscounter_truncated */
+       "lame delegations received",    /* dns_resstatscounter_lame */
+       "query retries",                /* dns_resstatscounter_retry */
+       "IPv4 NS address fetches",      /* dns_resstatscounter_gluefetchv4 */
+       "IPv6 NS address fetches",      /* dns_resstatscounter_gluefetchv6 */
+       "IPv4 NS address fetch failed", /* dns_resstatscounter_gluefetchv4fail */
+       "IPv6 NS address fetch failed", /* dns_resstatscounter_gluefetchv6fail */
+       "DNSSEC validation attempted",  /* dns_resstatscounter_val */
+       "DNSSEC validation failed",     /* dns_resstatscounter_valfail */
+       "DNSSEC validation succeeded",  /* dns_resstatscounter_valsuccess */
+       "DNSSEC NX validation succeeded"/* dns_resstatscounter_valnegsuccess */
+};
+
+/* zone statistics */
+static const char *zonestats_desc[] = {
+       "IPv4 notifies sent",           /* dns_zonestatscounter_notifyoutv4 */
+       "IPv6 notifies sent",           /* dns_zonestatscounter_notifyoutv6 */
+       "IPv4 notifies received",       /* dns_zonestatscounter_notifyinv4 */
+       "IPv6 notifies received",       /* dns_zonestatscounter_notifyinv6 */
+       "notifies rejected",            /* dns_zonestatscounter_notifyrej */
+       "IPv4 SOA queries sent",        /* dns_zonestatscounter_soaoutv4 */
+       "IPv6 SOA queries sent",        /* dns_zonestatscounter_soaoutv6 */
+       "IPv4 AXFR requested",          /* dns_zonestatscounter_axfrreqv4 */
+       "IPv6 AXFR requested",          /* dns_zonestatscounter_axfrreqv6 */
+       "IPv4 IXFR requested",          /* dns_zonestatscounter_ixfrreqv4 */
+       "IPv6 IXFR requested",          /* dns_zonestatscounter_ixfrreqv6 */
+       "transfer requests succeeded",  /* dns_zonestatscounter_xfrsuccess */
+       "transfer requests failed"      /* dns_zonestatscounter_xfrfail */
+};
+
+isc_result_t
+ns_stats_dump(ns_server_t *server, FILE *fp) {
+       isc_stdtime_t now;
+       isc_result_t result;
+       dns_view_t *view;
+       dns_zone_t *zone, *next;
+       stats_dumparg_t dumparg;
+
+       /* Set common fields */
+       dumparg.type = statsformat_file;
+       dumparg.arg = fp;
+
+       isc_stdtime_get(&now);
+       fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
+
+       fprintf(fp, "++ Incoming Requests ++\n");
+       dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
+                            0);
+
+       fprintf(fp, "++ Incoming Queries ++\n");
+       dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
+                               &dumparg, 0);
+
+       fprintf(fp, "++ Outgoing Queries ++\n");
+       for (view = ISC_LIST_HEAD(server->viewlist);
+            view != NULL;
+            view = ISC_LIST_NEXT(view, link)) {
+               if (view->resquerystats == NULL)
+                       continue;
+               if (strcmp(view->name, "_default") == 0)
+                       fprintf(fp, "[View: default]\n");
+               else
+                       fprintf(fp, "[View: %s]\n", view->name);
+               dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump,
+                                       &dumparg, 0);
+       }
+
+       fprintf(fp, "++ Name Server Statistics ++\n");
+       dumparg.desc = nsstats_desc;
+       dumparg.ncounters = dns_nsstatscounter_max;
+       dns_generalstats_dump(server->nsstats, generalstat_dump, &dumparg, 0);
+       fprintf(fp, "++ Zone Maintenance Statistics ++\n");
+       dumparg.desc = zonestats_desc;
+       dumparg.ncounters = dns_zonestatscounter_max;
+       dns_generalstats_dump(server->zonestats, generalstat_dump, &dumparg, 0);
+
+       fprintf(fp, "++ Resolver Statistics ++\n");
+       fprintf(fp, "[Common]\n");
+       dumparg.desc = resstats_desc;
+       dumparg.ncounters = dns_resstatscounter_max;
+       dns_generalstats_dump(server->resolverstats, generalstat_dump, &dumparg,
+                             0);
+       for (view = ISC_LIST_HEAD(server->viewlist);
+            view != NULL;
+            view = ISC_LIST_NEXT(view, link)) {
+               if (view->resstats == NULL)
+                       continue;
+               if (strcmp(view->name, "_default") == 0)
+                       fprintf(fp, "[View: default]\n");
+               else
+                       fprintf(fp, "[View: %s]\n", view->name);
+               dns_generalstats_dump(view->resstats, generalstat_dump,
+                                     &dumparg, 0);
+       }
+
+       fprintf(fp, "++ Cache DB RRsets ++\n");
+       for (view = ISC_LIST_HEAD(server->viewlist);
+            view != NULL;
+            view = ISC_LIST_NEXT(view, link)) {
+               dns_stats_t *cachestats;
+
+               cachestats = dns_db_getrrsetstats(view->cachedb);
+               if (cachestats == NULL)
+                       continue;
+               if (strcmp(view->name, "_default") == 0)
+                       fprintf(fp, "[View: default]\n");
+               else
+                       fprintf(fp, "[View: %s]\n", view->name);
+               dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg,
+                                      0);
+       }
+
+       fprintf(fp, "++ Per Zone Query Statistics ++\n");
+       zone = NULL;
+       for (result = dns_zone_first(server->zonemgr, &zone);
+            result == ISC_R_SUCCESS;
+            next = NULL, result = dns_zone_next(zone, &next), zone = next)
+       {
+               dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
+               if (zonestats != NULL) {
+                       char zonename[DNS_NAME_FORMATSIZE];
+
+                       dns_name_format(dns_zone_getorigin(zone),
+                                       zonename, sizeof(zonename));
+                       view = dns_zone_getview(zone);
+
+                       fprintf(fp, "[%s", zonename);
+                       if (strcmp(view->name, "_default") != 0)
+                               fprintf(fp, " (view: %s)", view->name);
+                       fprintf(fp, "]\n");
+
+                       dumparg.desc = nsstats_desc;
+                       dumparg.ncounters = dns_nsstatscounter_max;
+                       dns_generalstats_dump(zonestats, generalstat_dump,
+                                             &dumparg, 0);
+               }
+       }
+
+       fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
+
+       return (ISC_R_SUCCESS); /* this function currently always succeeds */
+}
index 4d065429312b63d63e6869a999d72a17923e8de1..67b67b679dfc45e836d5ce47d760a23dbd9d3ddc 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: update.c,v 1.145 2008/04/02 02:37:41 marka Exp $ */
+/* $Id: update.c,v 1.146 2008/04/03 05:55:51 marka Exp $ */
 
 #include <config.h>
 
 #include <dns/rdatatype.h>
 #include <dns/soa.h>
 #include <dns/ssu.h>
+#include <dns/stats.h>
 #include <dns/view.h>
 #include <dns/zone.h>
 #include <dns/zt.h>
 
 #include <named/client.h>
 #include <named/log.h>
+#include <named/server.h>
 #include <named/update.h>
 
 /*! \file
                           msg, isc_result_totext(result));     \
                if (result != ISC_R_SUCCESS) goto failure;      \
        } while (0)
+#define PREREQFAILC(code, msg) \
+       do {                                                    \
+               inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+               FAILC(code, msg);                               \
+       } while (0)
 
 #define FAILN(code, name, msg) \
        do {                                                            \
                }                                                       \
                if (result != ISC_R_SUCCESS) goto failure;              \
        } while (0)
+#define PREREQFAILN(code, name, msg) \
+       do {                                                            \
+               inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+               FAILN(code, name, msg);                                 \
+       } while (0)
 
 #define FAILNT(code, name, type, msg) \
        do {                                                            \
                }                                                       \
                if (result != ISC_R_SUCCESS) goto failure;              \
        } while (0)
+#define PREREQFAILNT(code, name, type, msg)                            \
+       do {                                                            \
+               inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+               FAILNT(code, name, type, msg);                          \
+       } while (0)
+
 /*%
  * Fail unconditionally and log as a server error.
  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
@@ -247,6 +265,20 @@ update_log(ns_client_t *client, dns_zone_t *zone,
                      namebuf, classbuf, message);
 }
 
+/*%
+ * Increment updated-related statistics counters.
+ */
+static inline void
+inc_stats(dns_zone_t *zone, dns_statscounter_t counter) {
+       dns_generalstats_increment(ns_g_server->nsstats, counter);
+
+       if (zone != NULL) {
+               dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
+               if (zonestats != NULL)
+                       dns_generalstats_increment(zonestats, counter);
+       }
+}
+
 /*%
  * Override the default acl logging when checking whether a client
  * can update the zone or whether we can forward the request to the
@@ -2393,6 +2425,10 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) {
        return;
 
  failure:
+       if (result == DNS_R_REFUSED) {
+               INSIST(dns_zone_gettype(zone) == dns_zone_slave);
+               inc_stats(zone, dns_nsstatscounter_updaterej);
+       }
        /*
         * We failed without having sent an update event to the zone.
         * We are still in the client task context, so we can
@@ -2646,54 +2682,59 @@ update_action(isc_task_t *task, isc_event_t *event) {
                               &name, &rdata, &covers, &ttl, &update_class);
 
                if (ttl != 0)
-                       FAILC(DNS_R_FORMERR, "prerequisite TTL is not zero");
+                       PREREQFAILC(DNS_R_FORMERR,
+                                   "prerequisite TTL is not zero");
 
                if (! dns_name_issubdomain(name, zonename))
-                       FAILN(DNS_R_NOTZONE, name,
-                               "prerequisite name is out of zone");
+                       PREREQFAILN(DNS_R_NOTZONE, name,
+                                   "prerequisite name is out of zone");
 
                if (update_class == dns_rdataclass_any) {
                        if (rdata.length != 0)
-                               FAILC(DNS_R_FORMERR,
+                               PREREQFAILC(DNS_R_FORMERR,
                                      "class ANY prerequisite "
                                      "RDATA is not empty");
                        if (rdata.type == dns_rdatatype_any) {
                                CHECK(name_exists(db, ver, name, &flag));
                                if (! flag) {
-                                       FAILN(DNS_R_NXDOMAIN, name,
-                                             "'name in use' prerequisite "
-                                             "not satisfied");
+                                       PREREQFAILN(DNS_R_NXDOMAIN, name,
+                                                   "'name in use' "
+                                                   "prerequisite not "
+                                                   "satisfied");
                                }
                        } else {
                                CHECK(rrset_exists(db, ver, name,
                                                   rdata.type, covers, &flag));
                                if (! flag) {
                                        /* RRset does not exist. */
-                                       FAILNT(DNS_R_NXRRSET, name, rdata.type,
+                                       PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type,
                                        "'rrset exists (value independent)' "
                                        "prerequisite not satisfied");
                                }
                        }
                } else if (update_class == dns_rdataclass_none) {
                        if (rdata.length != 0)
-                               FAILC(DNS_R_FORMERR,
-                                     "class NONE prerequisite "
-                                     "RDATA is not empty");
+                               PREREQFAILC(DNS_R_FORMERR,
+                                           "class NONE prerequisite "
+                                           "RDATA is not empty");
                        if (rdata.type == dns_rdatatype_any) {
                                CHECK(name_exists(db, ver, name, &flag));
                                if (flag) {
-                                       FAILN(DNS_R_YXDOMAIN, name,
-                                             "'name not in use' prerequisite "
-                                             "not satisfied");
+                                       PREREQFAILN(DNS_R_YXDOMAIN, name,
+                                                   "'name not in use' "
+                                                   "prerequisite not "
+                                                   "satisfied");
                                }
                        } else {
                                CHECK(rrset_exists(db, ver, name,
                                                   rdata.type, covers, &flag));
                                if (flag) {
                                        /* RRset exists. */
-                                       FAILNT(DNS_R_YXRRSET, name, rdata.type,
-                                              "'rrset does not exist' "
-                                              "prerequisite not satisfied");
+                                       PREREQFAILNT(DNS_R_YXRRSET, name,
+                                                    rdata.type,
+                                                    "'rrset does not exist' "
+                                                    "prerequisite not "
+                                                    "satisfied");
                                }
                        }
                } else if (update_class == zoneclass) {
@@ -2706,7 +2747,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
                                FAIL(ISC_R_UNEXPECTED);
                        }
                } else {
-                       FAILC(DNS_R_FORMERR, "malformed prerequisite");
+                       PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite");
                }
        }
        if (result != ISC_R_NOMORE)
@@ -3209,6 +3250,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
        goto common;
 
  failure:
+       if (result == DNS_R_REFUSED)
+               inc_stats(zone, dns_nsstatscounter_updaterej);
+
        /*
         * The reason for failure should have been logged at this point.
         */
@@ -3231,11 +3275,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
        if (ssutable != NULL)
                dns_ssutable_detach(&ssutable);
 
-       if (zone != NULL)
-               dns_zone_detach(&zone);
-
        isc_task_detach(&task);
        uev->result = result;
+       if (zone != NULL)
+               INSIST(uev->zone == zone); /* we use this later */
        uev->ev_type = DNS_EVENT_UPDATEDONE;
        uev->ev_action = updatedone_action;
        isc_task_send(client->task, &event);
@@ -3253,6 +3296,19 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
        INSIST(task == client->task);
 
        INSIST(client->nupdates > 0);
+       switch (uev->result) {
+       case ISC_R_SUCCESS:
+               inc_stats(uev->zone, dns_nsstatscounter_updatedone);
+               break;
+       case DNS_R_REFUSED:
+               inc_stats(uev->zone, dns_nsstatscounter_updaterej);
+               break;
+       default:
+               inc_stats(uev->zone, dns_nsstatscounter_updatefail);
+               break;
+       }
+       if (uev->zone != NULL)
+               dns_zone_detach(&uev->zone);
        client->nupdates--;
        respond(client, uev->result);
        isc_event_free(&event);
@@ -3281,17 +3337,21 @@ static void
 forward_callback(void *arg, isc_result_t result, dns_message_t *answer) {
        update_event_t *uev = arg;
        ns_client_t *client = uev->ev_arg;
+       dns_zone_t *zone = uev->zone;
 
        if (result != ISC_R_SUCCESS) {
                INSIST(answer == NULL);
                uev->ev_type = DNS_EVENT_UPDATEDONE;
                uev->ev_action = forward_fail;
+               inc_stats(zone, dns_nsstatscounter_updatefwdfail);
        } else {
                uev->ev_type = DNS_EVENT_UPDATEDONE;
                uev->ev_action = forward_done;
                uev->answer = answer;
+               inc_stats(zone, dns_nsstatscounter_updaterespfwd);
        }
        isc_task_send(client->task, ISC_EVENT_PTR(&uev));
+       dns_zone_detach(&zone);
 }
 
 static void
@@ -3322,8 +3382,10 @@ forward_action(isc_task_t *task, isc_event_t *event) {
                uev->ev_type = DNS_EVENT_UPDATEDONE;
                uev->ev_action = forward_fail;
                isc_task_send(client->task, &event);
-       }
-       dns_zone_detach(&zone);
+               inc_stats(zone, dns_nsstatscounter_updatefwdfail);
+               dns_zone_detach(&zone);
+       } else
+               inc_stats(zone, dns_nsstatscounter_updatereqfwd);
        isc_task_detach(&task);
 }
 
index 6cc8f7064ac36360de7bf3d733985bcb974515cc..cde32ff98e9632b420e0c010108f23c139f641be 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: xfrout.c,v 1.126 2007/06/18 23:47:19 tbox Exp $ */
+/* $Id: xfrout.c,v 1.127 2008/04/03 05:55:51 marka Exp $ */
 
 #include <config.h>
 
@@ -40,6 +40,7 @@
 #include <dns/rdatasetiter.h>
 #include <dns/result.h>
 #include <dns/soa.h>
+#include <dns/stats.h>
 #include <dns/timer.h>
 #include <dns/tsig.h>
 #include <dns/view.h>
@@ -148,6 +149,16 @@ db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
 static void
 db_rr_iterator_destroy(db_rr_iterator_t *it);
 
+static inline void
+inc_stats(dns_zone_t *zone, dns_statscounter_t counter) {
+       dns_generalstats_increment(ns_g_server->nsstats, counter);
+       if (zone != NULL) {
+               dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
+               if (zonestats != NULL)
+                       dns_generalstats_increment(zonestats, counter);
+       }
+}
+
 static isc_result_t
 db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
                    isc_stdtime_t now)
@@ -818,6 +829,7 @@ typedef struct {
        dns_name_t              *qname;         /* Question name of request */
        dns_rdatatype_t         qtype;          /* dns_rdatatype_{a,i}xfr */
        dns_rdataclass_t        qclass;
+       dns_zone_t              *zone;          /* (necessary for stats) */
        dns_db_t                *db;
        dns_dbversion_t         *ver;
        isc_quota_t             *quota;
@@ -841,7 +853,7 @@ typedef struct {
 static isc_result_t
 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
                  unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
-                 dns_rdataclass_t qclass,
+                 dns_rdataclass_t qclass, dns_zone_t *zone,
                  dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
                  rrstream_t *stream, dns_tsigkey_t *tsigkey,
                  isc_buffer_t *lasttsig,
@@ -1211,8 +1223,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
 #ifdef DLZ
        if (is_dlz)
                CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
-                                       reqtype, question_class, db, ver, quota,
-                                       stream, dns_message_gettsigkey(request),
+                                       reqtype, question_class, zone, db, ver,
+                                       quota, stream,
+                                       dns_message_gettsigkey(request),
                                        tsigbuf,
                                        3600,
                                        3600,
@@ -1222,8 +1235,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
        else
 #endif
                CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
-                                       reqtype, question_class, db, ver, quota,
-                                       stream, dns_message_gettsigkey(request),
+                                       reqtype, question_class, zone, db, ver,
+                                       quota, stream,
+                                       dns_message_gettsigkey(request),
                                        tsigbuf,
                                        dns_zone_getmaxxfrout(zone),
                                        dns_zone_getidleout(zone),
@@ -1261,6 +1275,8 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
        result = ISC_R_SUCCESS;
 
  failure:
+       if (result == DNS_R_REFUSED)
+               inc_stats(zone, dns_nsstatscounter_xfrrej);
        if (quota != NULL)
                isc_quota_detach(&quota);
        if (current_soa_tuple != NULL)
@@ -1291,7 +1307,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
 static isc_result_t
 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
                  dns_name_t *qname, dns_rdatatype_t qtype,
-                 dns_rdataclass_t qclass,
+                 dns_rdataclass_t qclass, dns_zone_t *zone,
                  dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
                  rrstream_t *stream, dns_tsigkey_t *tsigkey,
                  isc_buffer_t *lasttsig, unsigned int maxtime,
@@ -1314,8 +1330,10 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
        xfr->qname = qname;
        xfr->qtype = qtype;
        xfr->qclass = qclass;
+       xfr->zone = NULL;
        xfr->db = NULL;
        xfr->ver = NULL;
+       dns_zone_attach(zone, &xfr->zone);
        dns_db_attach(db, &xfr->db);
        dns_db_attachversion(db, ver, &xfr->ver);
        xfr->end_of_stream = ISC_FALSE;
@@ -1691,6 +1709,8 @@ xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
                isc_quota_detach(&xfr->quota);
        if (xfr->ver != NULL)
                dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
+       if (xfr->zone != NULL)
+               dns_zone_detach(&xfr->zone);
        if (xfr->db != NULL)
                dns_db_detach(&xfr->db);
 
@@ -1724,6 +1744,7 @@ xfrout_senddone(isc_task_t *task, isc_event_t *event) {
                sendstream(xfr);
        } else {
                /* End of zone transfer stream. */
+               inc_stats(xfr->zone, dns_nsstatscounter_xfrdone);
                xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
                ns_client_next(xfr->client, ISC_R_SUCCESS);
                xfrout_ctx_destroy(&xfr);
index db16b500403508b4ddd5fcad860c5656390f7cda..9cc6b5e25e5b3cc36ef35fb1c1cf253348460e47 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zoneconf.c,v 1.143 2008/04/02 02:37:41 marka Exp $ */
+/* $Id: zoneconf.c,v 1.144 2008/04/03 05:55:51 marka Exp $ */
 
 /*% */
 
@@ -34,6 +34,7 @@
 #include <dns/name.h>
 #include <dns/rdatatype.h>
 #include <dns/ssu.h>
+#include <dns/stats.h>
 #include <dns/view.h>
 #include <dns/zone.h>
 
@@ -365,6 +366,8 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
        isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE;
        isc_boolean_t ixfrdiff;
        dns_masterformat_t masterformat;
+       dns_stats_t *zoneqrystats;
+       isc_boolean_t zonestats_on;
        int seconds;
 
        i = 0;
@@ -493,7 +496,15 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
        obj = NULL;
        result = ns_config_get(maps, "zone-statistics", &obj);
        INSIST(result == ISC_R_SUCCESS);
-       RETERR(dns_zone_setstatistics(zone, cfg_obj_asboolean(obj)));
+       zonestats_on = cfg_obj_asboolean(obj);
+       zoneqrystats = NULL;
+       if (zonestats_on) {
+               RETERR(dns_generalstats_create(mctx, &zoneqrystats,
+                                              dns_nsstatscounter_max));
+       }
+       dns_zone_setrequeststats(zone, zoneqrystats);
+       if (zoneqrystats != NULL)
+               dns_stats_detach(&zoneqrystats);
 
        /*
         * Configure master functionality.  This applies
index 2be4d4bc8ae598f5ab640c4e432959c7655f771b..205ce990ffb1c9e3f2fc9ab99361e2d14d58e5f7 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: adb.c,v 1.236 2008/03/20 19:23:42 jinmei Exp $ */
+/* $Id: adb.c,v 1.237 2008/04/03 05:55:51 marka Exp $ */
 
 /*! \file
  *
@@ -55,6 +55,7 @@
 #include <dns/rdatatype.h>
 #include <dns/resolver.h>
 #include <dns/result.h>
+#include <dns/stats.h>
 
 #define DNS_ADB_MAGIC             ISC_MAGIC('D', 'a', 'd', 'b')
 #define DNS_ADB_VALID(x)          ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
@@ -498,6 +499,15 @@ DP(int level, const char *format, ...) {
        va_end(args);
 }
 
+/*%
+ * Increment resolver-related statistics counters.
+ */
+static inline void
+inc_stats(dns_adb_t *adb, dns_statscounter_t counter) {
+       if (adb->view->resstats != NULL)
+               dns_generalstats_increment(adb->view->resstats, counter);
+}
+
 static inline dns_ttl_t
 ttlclamp(dns_ttl_t ttl) {
        if (ttl < ADB_CACHE_MINIMUM)
@@ -3394,6 +3404,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
                                name->fetch_err = FIND_ERR_NXDOMAIN;
                        else
                                name->fetch_err = FIND_ERR_NXRRSET;
+                       inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
                } else {
                        DP(NCACHE_LEVEL, "adb fetch name %p: "
                           "caching negative entry for AAAA (ttl %u)",
@@ -3404,6 +3415,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
                                name->fetch6_err = FIND_ERR_NXDOMAIN;
                        else
                                name->fetch6_err = FIND_ERR_NXRRSET;
+                       inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
                }
                goto out;
        }
@@ -3443,9 +3455,11 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
                if (address_type == DNS_ADBFIND_INET) {
                        name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
                        name->fetch_err = FIND_ERR_FAILURE;
+                       inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
                } else {
                        name->expire_v6 = ISC_MIN(name->expire_v6, now + 300);
                        name->fetch6_err = FIND_ERR_FAILURE;
+                       inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
                }
                goto out;
        }
@@ -3530,10 +3544,13 @@ fetch_name(dns_adbname_t *adbname,
        if (result != ISC_R_SUCCESS)
                goto cleanup;
 
-       if (type == dns_rdatatype_a)
+        if (type == dns_rdatatype_a) {
                adbname->fetch_a = fetch;
-       else
+               inc_stats(adb, dns_resstatscounter_gluefetchv4);
+        } else {
                adbname->fetch_aaaa = fetch;
+               inc_stats(adb, dns_resstatscounter_gluefetchv6);
+       }
        fetch = NULL;  /* Keep us from cleaning this up below. */
 
  cleanup:
index 7d4d038d11dcdda246e158539580aba1549066ee..5539962dc19670400789ff157c0ee8c65e964544 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: db.c,v 1.86 2008/04/01 23:47:10 tbox Exp $ */
+/* $Id: db.c,v 1.87 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -859,6 +859,16 @@ dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
        return (ISC_R_NOTFOUND);
 }
 
+dns_stats_t *
+dns_db_getrrsetstats(dns_db_t *db) {
+       REQUIRE(DNS_DB_VALID(db));
+
+       if (db->methods->getrrsetstats != NULL)
+               return ((db->methods->getrrsetstats)(db));
+
+       return (NULL);
+}
+
 isc_result_t
 dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
                      isc_stdtime_t resign)
index 4d310b673fb132d3c8f443e6b88fb6459d131f4b..d75c45a39d785fbd03efd69c1464022dffa28ac0 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dispatch.c,v 1.138 2008/04/03 02:01:08 marka Exp $ */
+/* $Id: dispatch.c,v 1.139 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -40,6 +40,7 @@
 #include <dns/log.h>
 #include <dns/message.h>
 #include <dns/portlist.h>
+#include <dns/stats.h>
 #include <dns/tcpmsg.h>
 #include <dns/types.h>
 
@@ -71,6 +72,7 @@ struct dns_dispatchmgr {
        isc_mem_t                      *mctx;
        dns_acl_t                      *blackhole;
        dns_portlist_t                 *portlist;
+       dns_stats_t                    *stats;
 
        /* Locked by "lock". */
        isc_mutex_t                     lock;
@@ -652,6 +654,8 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
                     bucket, (resp == NULL ? "not found" : "found"));
 
        if (resp == NULL) {
+               dns_generalstats_increment(mgr->stats,
+                                          dns_resstatscounter_mismatch);
                free_buffer(disp, ev->region.base, ev->region.length);
                goto unlock;
        }
@@ -1056,6 +1060,9 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
        if (mgr->portlist != NULL)
                dns_portlist_detach(&mgr->portlist);
 
+       if (mgr->stats != NULL)
+               dns_stats_detach(&mgr->stats);
+
        isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
        isc_mem_detach(&mctx);
 }
@@ -1110,6 +1117,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
 
        mgr->blackhole = NULL;
        mgr->portlist = NULL;
+       mgr->stats = NULL;
 
        result = isc_mutex_init(&mgr->lock);
        if (result != ISC_R_SUCCESS)
@@ -1305,6 +1313,15 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
                destroy_mgr(&mgr);
 }
 
+void
+dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, dns_stats_t *stats) {
+       REQUIRE(VALID_DISPATCHMGR(mgr));
+       REQUIRE(ISC_LIST_EMPTY(mgr->list));
+       REQUIRE(mgr->stats == NULL);
+
+       dns_stats_attach(stats, &mgr->stats);
+}
+
 static isc_boolean_t
 blacklisted(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
            isc_sockaddr_t *sockaddrp)
index 0e8fc997cdccc66b9f04fc99a3bacef5709254a9..4a3ecdb9604a549a4caf247b735ed11f2e4618ec 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: adb.h,v 1.83 2007/06/19 23:47:16 tbox Exp $ */
+/* $Id: adb.h,v 1.84 2008/04/03 05:55:52 marka Exp $ */
 
 #ifndef DNS_ADB_H
 #define DNS_ADB_H 1
@@ -629,7 +629,6 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name);
  *\li  'name' is valid.
  */
 
-
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_ADB_H */
index 6c5163ae1fbc6d520a79900508ed32db6d010923..05115325a2f76a5a8aba3f75d5a457ec7bc6e6f3 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: db.h,v 1.91 2008/04/01 23:47:10 tbox Exp $ */
+/* $Id: db.h,v 1.92 2008/04/03 05:55:52 marka Exp $ */
 
 #ifndef DNS_DB_H
 #define DNS_DB_H 1
@@ -157,6 +157,7 @@ typedef struct dns_dbmethods {
        void            (*resigned)(dns_db_t *db, dns_rdataset_t *rdataset,
                                           dns_dbversion_t *version);
        isc_boolean_t   (*isdnssec)(dns_db_t *db);
+       dns_stats_t     *(*getrrsetstats)(dns_db_t *db);
 } dns_dbmethods_t;
 
 typedef isc_result_t
@@ -1388,6 +1389,21 @@ dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset,
  */
 
 
+dns_stats_t *
+dns_db_getrrsetstats(dns_db_t *db);
+/*%<
+ * Get statistics information counting RRsets stored in the DB, when available.
+ * The statistics may not be available depending on the DB implementation.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database (zone or cache).
+ *
+ * Returns:
+ * \li when available, a pointer to a statistics object created by
+ *     dns_rdatasetstats_create(); otherwise NULL.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_DB_H */
index 71922d7780da42d450ad14d008013cb952f9949a..1891f0ab4a6a53e2d04bddd0996b0332fa6c1487 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dispatch.h,v 1.56 2007/06/26 02:52:15 marka Exp $ */
+/* $Id: dispatch.h,v 1.57 2008/04/03 05:55:52 marka Exp $ */
 
 #ifndef DNS_DISPATCH_H
 #define DNS_DISPATCH_H 1
@@ -206,7 +206,20 @@ dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr);
  *\li  mgr is a valid dispatchmgr
  */
 
-
+void
+dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, dns_stats_t *stats);
+/*%<
+ * Sets statistics counter for the dispatchmgr.  This function is expected to
+ * be called only on zone creation (when necessary).
+ * Once installed, it cannot be removed or replaced.  Also, there is no
+ * interface to get the installed stats from the zone; the caller must keep the
+ * stats to reference (e.g. dump) it later.
+ *
+ * Requires:
+ *\li  mgr is a valid dispatchmgr with no managed dispatch.
+ *\li  stats is a valid statistics supporting resolver statistics counters
+ *     (see dns/stats.h).
+ */
 
 isc_result_t
 dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
index 9134e1fbbefba0171994138a06672ca1902bcf62..5831e9d06456befdaadaaea45b4b2b1bdef65d8f 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stats.h,v 1.15 2008/01/24 23:47:00 tbox Exp $ */
+/* $Id: stats.h,v 1.16 2008/04/03 05:55:52 marka Exp $ */
 
 #ifndef DNS_STATS_H
 #define DNS_STATS_H 1
 #include <dns/types.h>
 
 /*%
- * Query statistics counter types.
+ * Statistics counters.  Used as dns_statscounter_t values.
  */
-typedef enum {
+enum {
+       /*%
+        * Resolver statistics counters.
+        */
+       dns_resstatscounter_queryv4 = 0,
+       dns_resstatscounter_queryv6 = 1,
+       dns_resstatscounter_responsev4 = 2,
+       dns_resstatscounter_responsev6 = 3,
+       dns_resstatscounter_nxdomain = 4,
+       dns_resstatscounter_servfail = 5,
+       dns_resstatscounter_formerr = 6,
+       dns_resstatscounter_othererror = 7,
+       dns_resstatscounter_edns0fail = 8,
+       dns_resstatscounter_mismatch = 9,
+       dns_resstatscounter_truncated = 10,
+       dns_resstatscounter_lame = 11,
+       dns_resstatscounter_retry = 12,
+       dns_resstatscounter_gluefetchv4 = 13,
+       dns_resstatscounter_gluefetchv6 = 14,
+       dns_resstatscounter_gluefetchv4fail = 15,
+       dns_resstatscounter_gluefetchv6fail = 16,
+       dns_resstatscounter_val = 17,
+       dns_resstatscounter_valsuccess = 18,
+       dns_resstatscounter_valnegsuccess = 19,
+       dns_resstatscounter_valfail = 20,
+
+       dns_resstatscounter_max = 21,
+
+       /*%
+        * Zone statistics counters.
+        */
+       dns_zonestatscounter_notifyoutv4 = 0,
+       dns_zonestatscounter_notifyoutv6 = 1,
+       dns_zonestatscounter_notifyinv4 = 2,
+       dns_zonestatscounter_notifyinv6 = 3,
+       dns_zonestatscounter_notifyrej = 4,
+       dns_zonestatscounter_soaoutv4 = 5,
+       dns_zonestatscounter_soaoutv6 = 6,
+       dns_zonestatscounter_axfrreqv4 = 7,
+       dns_zonestatscounter_axfrreqv6 = 8,
+       dns_zonestatscounter_ixfrreqv4 = 9,
+       dns_zonestatscounter_ixfrreqv6 = 10,
+       dns_zonestatscounter_xfrsuccess = 11,
+       dns_zonestatscounter_xfrfail = 12,
+
+       dns_zonestatscounter_max = 13,
+
+       /*%
+       * Query statistics counters (obsolete).
+       */
        dns_statscounter_success = 0,    /*%< Successful lookup */
        dns_statscounter_referral = 1,   /*%< Referral result */
        dns_statscounter_nxrrset = 2,    /*%< NXRRSET result */
@@ -35,64 +84,254 @@ typedef enum {
        dns_statscounter_recursion = 4,  /*%< Recursion was used */
        dns_statscounter_failure = 5,    /*%< Some other failure */
        dns_statscounter_duplicate = 6,  /*%< Duplicate query */
-       dns_statscounter_dropped = 7     /*%< Duplicate query */
-} dns_statscounter_t;
+       dns_statscounter_dropped = 7     /*%< Duplicate query (dropped) */
+};
 
 #define DNS_STATS_NCOUNTERS 8
 
+/*%<
+ * Flag(s) for dns_xxxstats_dump().
+ */
+#define DNS_STATSDUMP_VERBOSE  0x00000001 /*%< dump 0-value counters */
+
+/*%<
+ * (Obsoleted)
+ */
 LIBDNS_EXTERNAL_DATA extern const char *dns_statscounter_names[];
 
+/*%
+ * Attributes for statistics counters of RRset and Rdatatype types.
+ *
+ * _OTHERTYPE
+ *     The rdata type is not explicitly supported and the corresponding counter
+ *     is counted for other such types, too.  When this attribute is set,
+ *     the base type is of no use.
+ *
+ * _NXRRSET
+ *     RRset type counters only.  Indicates the RRset is non existent.
+ *
+ * _NXDOMAIN
+ *     RRset type counters only.  Indicates a non existent name.  When this
+ *     attribute is set, the base type is of no use.
+ */
+#define DNS_RDATASTATSTYPE_ATTR_OTHERTYPE      0x0001
+#define DNS_RDATASTATSTYPE_ATTR_NXRRSET                0x0002
+#define DNS_RDATASTATSTYPE_ATTR_NXDOMAIN       0x0004
+
+/*%<
+ * Conversion macros among dns_rdatatype_t, attributes and dns_statscounter_t.
+ */
+#define DNS_RDATASTATSTYPE_BASE(type)  ((dns_rdatatype_t)((type) & 0xFFFF))
+#define DNS_RDATASTATSTYPE_ATTR(type)  ((type) >> 16)
+#define DNS_RDATASTATSTYPE_VALUE(b, a) (((a) << 16) | (b))
+
+/*%<
+ * Types of dump callbacks.
+ */
+typedef void (*dns_generalstats_dumper_t)(dns_statscounter_t, isc_uint64_t,
+                                         void *);
+typedef void (*dns_rdatatypestats_dumper_t)(dns_rdatastatstype_t, isc_uint64_t,
+                                           void *);
+typedef void (*dns_opcodestats_dumper_t)(dns_opcode_t, isc_uint64_t, void *);
+
 isc_result_t
-dns_stats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters);
 /*%<
- * Create a statistics counter structure.
+ * Create a statistics counter structure of general type.  It counts a general
+ * set of counters indexed by an ID between 0 and ncounters -1.
  *
  * Requires:
+ *\li  'mctx' must be a valid memory context.
  *
+ *\li  'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li  ISC_R_SUCCESS   -- all ok
+ *
+ *\li  anything else   -- failure
+ */
+
+isc_result_t
+dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per rdatatype.
+ *
+ * Requires:
  *\li  'mctx' must be a valid memory context.
  *
  *\li  'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li  ISC_R_SUCCESS   -- all ok
+ *
+ *\li  anything else   -- failure
  */
 
-void
-dns_stats_destroy(isc_mem_t *mctx, dns_stats_t **statsp);
+isc_result_t
+dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp);
 /*%<
- * Destroy a statistics counter structure.
+ * Create a statistics counter structure per RRset.
  *
  * Requires:
+ *\li  'mctx' must be a valid memory context.
+ *
+ *\li  'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li  ISC_R_SUCCESS   -- all ok
+ *
+ *\li  anything else   -- failure
+ */
+
+isc_result_t
+dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per opcode.
  *
+ * Requires:
  *\li  'mctx' must be a valid memory context.
  *
- *\li  'statsp' != NULL and '*statsp' be valid dns_stats_t.
+ *\li  'statsp' != NULL && '*statsp' == NULL.
  *
- * Ensures:
+ * Returns:
+ *\li  ISC_R_SUCCESS   -- all ok
  *
- *\li  '*statsp' == NULL
+ *\li  anything else   -- failure
  */
 
 void
-dns_stats_incrementcounter(dns_stats_t *stat, dns_statscounter_t counter);
+dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp);
 /*%<
- * Increment a counter field of 'stat' specified by 'counter'.
+ * Attach to a statistics set.
  *
  * Requires:
+ *\li  'stats' is a valid dns_stats_t.
  *
- *\li  'stat' be a valid dns_stats_t.
+ *\li  'statsp' != NULL && '*statsp' == NULL
+ */
+
+void
+dns_stats_detach(dns_stats_t **statsp);
+/*%<
+ * Detaches from the statistics set.
  *
- *\li  counter < DNS_STATS_NCOUNTERS
+ * Requires:
+ *\li  'statsp' != NULL and '*statsp' is a valid dns_stats_t.
+ */
+
+void
+dns_generalstats_increment(dns_stats_t *stats, dns_statscounter_t counter);
+/*%<
+ * Increment the counter-th counter of stats. 
+ *
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ *
+ *\li  counter is less than the maximum available ID for the stats specified
+ *     on creation.
  */
 
 void
-dns_stats_copy(dns_stats_t *src, isc_uint64_t *dst);
+dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type);
 /*%<
- * Copy statistics counter fields of 'src' to the 'dst' array.
+ * Increment the statistics counter for 'type'.
  *
  * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_rdatatypestats_create().
+ */
+
+void
+dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
+/*%<
+ * Increment the statistics counter for 'rrsettype'.
  *
- *\li  'src' be a valid dns_stats_t.
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
+ */
+
+void
+dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
+/*%<
+ * Decrement the statistics counter for 'rrsettype'.
  *
- *\li  'dst' be sufficiently large to store DNS_STATS_NCOUNTERS 64-bit
- *     integers.
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
+ */
+
+void
+dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code);
+/*%<
+ * Increment the statistics counter for 'code'.
+ *
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_opcodestats_create().
+ */
+
+void
+dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
+                     void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way.  For each counter
+ * in stats, dump_fn is called with its current value and the given argument
+ * arg.  By default counters that have a value of 0 is skipped; if options has
+ * the DNS_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+                       void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way.  For each counter
+ * in stats, dump_fn is called with the corresponding type in the form of
+ * dns_rdatastatstype_t, the current counter value and the given argument
+ * arg.  By default counters that have a value of 0 is skipped; if options has
+ * the DNS_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+                      void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way.  For each counter
+ * in stats, dump_fn is called with the corresponding type in the form of
+ * dns_rdatastatstype_t, the current counter value and the given argument
+ * arg.  By default counters that have a value of 0 is skipped; if options has
+ * the DNS_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
+                    void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way.  For each counter
+ * in stats, dump_fn is called with the corresponding opcode, the current
+ * counter value and the given argument arg.  By default counters that have a
+ * value of 0 is skipped; if options has the DNS_STATSDUMP_VERBOSE flag, even
+ * such counters are dumped.
+ *
+ * Requires:
+ *\li  'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_stats_incrementcounter(dns_stats_t *stat, dns_statscounter_t counter);
+/*%<
+ * Increment a counter field of 'stat' specified by 'counter'.
+ *
+ * Requires:
+ *
+ *\li  'stat' be a valid dns_stats_t.
+ *
+ *\li  counter < DNS_STATS_NCOUNTERS
  */
 
 isc_result_t
@@ -101,7 +340,7 @@ dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp);
  * Allocate an array of query statistics counters from the memory
  * context 'mctx'.
  *
- * This function is obsoleted.  Use dns_stats_create() instead.
+ * This function is obsoleted.  Use dns_xxxstats_create() instead.
  */
 
 void
index 6ead6a9c3679d72c6076c07eaa8c30f6db8801ab..705cfb091beecac08a2233631939405ed702eafb 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: types.h,v 1.128 2008/01/24 23:47:00 tbox Exp $ */
+/* $Id: types.h,v 1.129 2008/04/03 05:55:52 marka Exp $ */
 
 #ifndef DNS_TYPES_H
 #define DNS_TYPES_H 1
@@ -107,6 +107,8 @@ typedef struct dns_signature                        dns_signature_t;
 typedef struct dns_ssurule                     dns_ssurule_t;
 typedef struct dns_ssutable                    dns_ssutable_t;
 typedef struct dns_stats                       dns_stats_t;
+typedef int                                    dns_statscounter_t;
+typedef isc_uint32_t                           dns_rdatastatstype_t;
 typedef struct dns_tkeyctx                     dns_tkeyctx_t;
 typedef isc_uint16_t                           dns_trust_t;
 typedef struct dns_tsig_keyring                        dns_tsig_keyring_t;
index 7b95cc9aef784e70cac8a6b6292a465843811aa1..8b08da8611da6c39531da755f76e9158c607349b 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.h,v 1.108 2008/04/03 02:01:08 marka Exp $ */
+/* $Id: view.h,v 1.109 2008/04/03 05:55:52 marka Exp $ */
 
 #ifndef DNS_VIEW_H
 #define DNS_VIEW_H 1
@@ -70,7 +70,6 @@
 #include <isc/refcount.h>
 #include <isc/rwlock.h>
 #include <isc/stdtime.h>
-#include <isc/xml.h>
 
 #include <dns/acl.h>
 #include <dns/fixedname.h>
@@ -101,6 +100,8 @@ struct dns_view {
        isc_event_t                     resevent;
        isc_event_t                     adbevent;
        isc_event_t                     reqevent;
+       dns_stats_t *                   resstats;
+       dns_stats_t *                   resquerystats;
 
        /* Configurable data. */
        dns_tsig_keyring_t *            statickeys;
@@ -820,11 +821,55 @@ dns_view_freezezones(dns_view_t *view, isc_boolean_t freeze);
  * \li 'view' is valid.
  */
 
-#ifdef HAVE_LIBXML2
+void
+dns_view_setresstats(dns_view_t *view, dns_stats_t *stats);
+/*%<
+ * Set a general resolver statistics counter set 'stats' for 'view'.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li  stats is a valid statistics supporting resolver statistics counters
+ *     (see dns/stats.h).
+ */
 
-isc_result_t
-dns_view_xmlrender(dns_view_t *view, xmlTextWriterPtr xml, int flags);
+void
+dns_view_getresstats(dns_view_t *view, dns_stats_t **statsp);
+/*%<
+ * Get the general statistics counter set for 'view'.  If a statistics set is
+ * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
+ * untouched.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li  'statsp' != NULL && '*statsp' != NULL 
+ */
 
-#endif
+void
+dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats);
+/*%<
+ * Set a statistics counter set of rdata type, 'stats', for 'view'.  Once the
+ * statistic set is installed, view's resolver will count outgoing queries
+ * per rdata type.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li  stats is a valid statistics created by dns_rdatatypestats_create().
+ */
+
+void
+dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp);
+/*%<
+ * Get the rdatatype statistics counter set for 'view'.  If a statistics set is
+ * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
+ * untouched.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li  'statsp' != NULL && '*statsp' != NULL 
+ */
 
 #endif /* DNS_VIEW_H */
index d5b80e364ef3dda905c2ae3bbc6bc06a3c2b2a0d..2158cc6a437e327177b1b227194998b584489ffd 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.h,v 1.158 2008/04/02 02:37:42 marka Exp $ */
+/* $Id: zone.h,v 1.159 2008/04/03 05:55:52 marka Exp $ */
 
 #ifndef DNS_ZONE_H
 #define DNS_ZONE_H 1
@@ -31,7 +31,6 @@
 #include <isc/formatcheck.h>
 #include <isc/lang.h>
 #include <isc/rwlock.h>
-#include <isc/xml.h>
 
 #include <dns/masterdump.h>
 #include <dns/types.h>
@@ -148,6 +147,15 @@ dns_zone_getclass(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+isc_uint32_t
+dns_zone_getserial(dns_zone_t *zone);
+/*%<
+ *     Returns the current serial number of the zone.
+ *
+ * Requires:
+ *\li  'zone' to be a valid zone.
+ */
+
 void
 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type);
 /*%<
@@ -1502,28 +1510,55 @@ dns_zone_isforced(dns_zone_t *zone);
 isc_result_t
 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on);
 /*%<
- *      Make the zone keep or not keep an array of statistics
- *     counter.
- *
- * Requires:
- *   \li   zone be a valid zone.
+ * This function is obsoleted by dns_zone_setrequeststats().
  */
 
 isc_uint64_t *
 dns_zone_getstatscounters(dns_zone_t *zone);
 /*%<
- * This function is obsoleted by dns_zone_getstats().
+ * This function is obsoleted by dns_zone_getrequeststats().
+ */
+
+void
+dns_zone_setstats(dns_zone_t *zone, dns_stats_t *stats);
+/*%<
+ * Set a general zone-maintenance statistics set 'stats' for 'zone'.  This
+ * function is expected to be called only on zone creation (when necessary).
+ * Once installed, it cannot be removed or replaced.  Also, there is no
+ * interface to get the installed stats from the zone; the caller must keep the
+ * stats to reference (e.g. dump) it later.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone and does not have a statistics set already
+ *     installed.
+ *
+ *\li  stats is a valid statistics supporting zone statistics counters
+ *     (see dns/stats.h).
+ */
+
+void
+dns_zone_setrequeststats(dns_zone_t *zone, dns_stats_t *stats);
+/*%<
+ * Set an additional statistics set to zone.  It is attached in the zone
+ * but is not counted in the zone module; only the caller updates the counters.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ *
+ *\li  stats is a valid statistics.
  */
 
 dns_stats_t *
-dns_zone_getstats(dns_zone_t *zone);
+dns_zone_getrequeststats(dns_zone_t *zone);
 /*%<
+ * Get the additional statistics for zone, if one is installed.
+ *
  * Requires:
- *      zone be a valid zone.
+ * \li 'zone' to be a valid zone.
  *
  * Returns:
- * \li     A pointer to the zone's array of statistics counters,
- *     or NULL if it has none.
+ * \li when available, a pointer to the statistics set installed in zone;
+ *     otherwise NULL.
  */
 
 void
@@ -1688,13 +1723,6 @@ dns_zone_getprivatetype(dns_zone_t *zone);
  * will not be permanent.
  */
 
-#ifdef HAVE_LIBXML2
-
-isc_result_t
-dns_zone_xmlrender(dns_zone_t *zone, xmlTextWriterPtr xml, int flags);
-
-#endif
-
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_ZONE_H */
index 35d2241abee2d80f165fc1ba6f498423aad01fa4..e4e2552c778343e39f841c8a854543fab9ffab86 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rbtdb.c,v 1.256 2008/04/03 04:00:38 marka Exp $ */
+/* $Id: rbtdb.c,v 1.257 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -57,6 +57,7 @@
 #include <dns/rdatasetiter.h>
 #include <dns/rdataslab.h>
 #include <dns/result.h>
+#include <dns/stats.h>
 #include <dns/view.h>
 #include <dns/zone.h>
 #include <dns/zonekey.h>
@@ -277,6 +278,7 @@ typedef ISC_LIST(dns_rbtnode_t)         rbtnodelist_t;
 #define RDATASET_ATTR_RETAIN            0x0008
 #define RDATASET_ATTR_NXDOMAIN          0x0010
 #define RDATASET_ATTR_RESIGN            0x0020
+#define RDATASET_ATTR_STATCOUNT         0x0040
 #define RDATASET_ATTR_CACHE             0x1000 /* for debug */
 #define RDATASET_ATTR_CANCELED          0x2000 /* for debug */
 
@@ -399,6 +401,7 @@ typedef struct {
        unsigned int                    node_lock_count;
        rbtdb_nodelock_t *              node_locks;
        dns_rbtnode_t *                 origin_node;
+       dns_stats_t *                   rrsetstats; /* cache DB only */
        /* Locked by lock. */
        unsigned int                    active;
        isc_refcount_t                  references;
@@ -661,6 +664,32 @@ free_rbtdb_callback(isc_task_t *task, isc_event_t *event) {
        free_rbtdb(rbtdb, ISC_TRUE, event);
 }
 
+static void
+update_rrsetstats(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+                 isc_boolean_t increment)
+{
+       dns_rdatastatstype_t statattributes = 0;
+       dns_rdatastatstype_t base = 0;
+       dns_rdatastatstype_t type;
+
+       /* At the moment we count statistics only for cache DB */
+       INSIST(IS_CACHE(rbtdb));
+
+       if (NXDOMAIN(header))
+               statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN;
+       else if (RBTDB_RDATATYPE_BASE(header->type) == 0) {
+               statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET;
+               base = RBTDB_RDATATYPE_EXT(header->type);
+       } else
+               base = RBTDB_RDATATYPE_BASE(header->type);
+
+       type = DNS_RDATASTATSTYPE_VALUE(base, statattributes);
+       if (increment)
+               dns_rdatasetstats_increment(rbtdb->rrsetstats, type);
+       else
+               dns_rdatasetstats_decrement(rbtdb->rrsetstats, type);
+}
+
 static void
 set_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) {
        int idx;
@@ -887,6 +916,9 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
                            sizeof(isc_heap_t *));
        }
 
+       if (rbtdb->rrsetstats != NULL)
+               dns_stats_detach(&rbtdb->rrsetstats);
+
        isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,
                    rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
        isc_rwlock_destroy(&rbtdb->tree_lock);
@@ -1198,6 +1230,11 @@ free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset)
        unsigned int size;
        int idx;
 
+       if (EXISTS(rdataset) &&
+           (rdataset->attributes & RDATASET_ATTR_STATCOUNT) != 0) {
+               update_rrsetstats(rbtdb, rdataset, ISC_FALSE);
+       }
+
 #ifdef LRU_DEBUG
        /*
         * for debug: statistics update.
@@ -5583,6 +5620,11 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
                  isc_rwlocktype_write);
 
+       if (rbtdb->rrsetstats != NULL) {
+               newheader->attributes |= RDATASET_ATTR_STATCOUNT;
+               update_rrsetstats(rbtdb, newheader, ISC_TRUE);
+       }
+
 #ifdef LRU_DEBUG
        /* for debug: statistics update */
        if (IS_CACHE(rbtdb) && rdataset->rdclass == dns_rdataclass_in) {
@@ -6282,6 +6324,16 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
        RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
 }
 
+static dns_stats_t *
+getrrsetstats(dns_db_t *db) {
+       dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+
+       REQUIRE(VALID_RBTDB(rbtdb));
+       REQUIRE(IS_CACHE(rbtdb)); /* current restriction */
+
+       return (rbtdb->rrsetstats);
+}
+
 static dns_dbmethods_t zone_methods = {
        attach,
        detach,
@@ -6316,6 +6368,7 @@ static dns_dbmethods_t zone_methods = {
        getsigningtime,
        resigned,
        isdnssec,
+       NULL
 };
 
 static dns_dbmethods_t cache_methods = {
@@ -6351,7 +6404,8 @@ static dns_dbmethods_t cache_methods = {
        NULL,
        NULL,
        NULL,
-       isdnssec
+       isdnssec,
+       getrrsetstats
 };
 
 isc_result_t
@@ -6415,12 +6469,16 @@ dns_rbtdb_create
                goto cleanup_tree_lock;
        }
 
+       rbtdb->rrsetstats = NULL;
        if (IS_CACHE(rbtdb)) {
+               result = dns_rdatasetstats_create(mctx, &rbtdb->rrsetstats);
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup_node_locks;
                rbtdb->rdatasets = isc_mem_get(mctx, rbtdb->node_lock_count *
                                               sizeof(rdatasetheaderlist_t));
                if (rbtdb->rdatasets == NULL) {
                        result = ISC_R_NOMEMORY;
-                       goto cleanup_node_locks;
+                       goto cleanup_rrsetstats;
                }
                for (i = 0; i < (int)rbtdb->node_lock_count; i++)
                        ISC_LIST_INIT(rbtdb->rdatasets[i]);
@@ -6603,6 +6661,9 @@ dns_rbtdb_create
        if (rbtdb->rdatasets != NULL)
                isc_mem_put(mctx, rbtdb->rdatasets, rbtdb->node_lock_count *
                            sizeof(rdatasetheaderlist_t));
+ cleanup_rrsetstats:
+       if (rbtdb->rrsetstats != NULL)
+               dns_stats_detach(&rbtdb->rrsetstats);
 
  cleanup_node_locks:
        isc_mem_put(mctx, rbtdb->node_locks,
index 9b827c8482b9554ee856ad9c9c9735fe6f895d60..5d6bc1a0738d5f3b0756e7d00a1959e4f37300f4 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.364 2008/04/03 02:01:08 marka Exp $ */
+/* $Id: resolver.c,v 1.365 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -54,6 +54,7 @@
 #include <dns/resolver.h>
 #include <dns/result.h>
 #include <dns/rootns.h>
+#include <dns/stats.h>
 #include <dns/tsig.h>
 #include <dns/validator.h>
 
@@ -419,6 +420,15 @@ static void maybe_destroy(fetchctx_t *fctx);
 static void timer_dump(isc_task_t *task, isc_event_t *ev);
 #endif
 
+/*%
+ * Increment resolver-related statistics counters.
+ */
+static inline void
+inc_stats(dns_resolver_t *res, dns_statscounter_t counter) {
+       if (res->view->resstats != NULL)
+               dns_generalstats_increment(res->view->resstats, counter);
+}
+
 static isc_result_t
 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
          dns_rdatatype_t type, dns_rdataset_t *rdataset,
@@ -445,6 +455,7 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
                                      valoptions, task, validated, valarg,
                                      &validator);
        if (result == ISC_R_SUCCESS) {
+               inc_stats(fctx->res, dns_resstatscounter_val);
                if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
                        INSIST(fctx->validator == NULL);
                        fctx->validator  = validator;
@@ -1304,6 +1315,13 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
 
        ISC_LIST_APPEND(fctx->queries, query, link);
        query->fctx->nqueries++;
+       if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
+               inc_stats(res, dns_resstatscounter_queryv4);
+       else
+               inc_stats(res, dns_resstatscounter_queryv6);
+       if (res->view->resquerystats != NULL)
+               dns_rdatatypestats_increment(res->view->resquerystats,
+                                            fctx->type);
 
        return (ISC_R_SUCCESS);
 
@@ -2667,6 +2685,9 @@ fctx_try(fetchctx_t *fctx) {
 
        REQUIRE(!ADDRWAIT(fctx));
 
+       if (fctx->restarts > 0)
+               inc_stats(fctx->res, dns_resstatscounter_retry);
+
        addrinfo = fctx_nextaddress(fctx);
        if (addrinfo == NULL) {
                /*
@@ -3597,6 +3618,7 @@ validated(isc_task_t *task, isc_event_t *event) {
 
        if (vevent->result != ISC_R_SUCCESS) {
                FCTXTRACE("validation failed");
+               inc_stats(fctx->res, dns_resstatscounter_valfail);
                result = ISC_R_NOTFOUND;
                if (vevent->rdataset != NULL)
                        result = dns_db_findnode(fctx->cache, vevent->name,
@@ -3631,6 +3653,8 @@ validated(isc_task_t *task, isc_event_t *event) {
                dns_rdatatype_t covers;
                FCTXTRACE("nonexistence validation OK");
 
+               inc_stats(fctx->res, dns_resstatscounter_valnegsuccess);
+
                if (fctx->rmessage->rcode == dns_rcode_nxdomain)
                        covers = dns_rdatatype_any;
                else
@@ -3658,7 +3682,8 @@ validated(isc_task_t *task, isc_event_t *event) {
                if (result != ISC_R_SUCCESS)
                        goto noanswer_response;
                goto answer_response;
-       }
+       } else
+               inc_stats(fctx->res, dns_resstatscounter_valsuccess);
 
        FCTXTRACE("validation OK");
 
@@ -5616,6 +5641,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
 
        QTRACE("response");
 
+       if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
+               inc_stats(fctx->res, dns_resstatscounter_responsev4);
+       else
+               inc_stats(fctx->res, dns_resstatscounter_responsev6);
+
        (void)isc_timer_touch(fctx->timer);
 
        keep_trying = ISC_FALSE;
@@ -5717,6 +5747,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                                                        query->addrinfo,
                                                        DNS_FETCHOPT_NOEDNS0,
                                                        DNS_FETCHOPT_NOEDNS0);
+                                       inc_stats(fctx->res,
+                                                dns_resstatscounter_edns0fail);
                                } else {
                                        broken_server = result;
                                        keep_trying = ISC_TRUE;
@@ -5745,6 +5777,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                                                    query->addrinfo,
                                                    DNS_FETCHOPT_NOEDNS0,
                                                    DNS_FETCHOPT_NOEDNS0);
+                               inc_stats(fctx->res,
+                                                dns_resstatscounter_edns0fail);
                        } else {
                                broken_server = DNS_R_UNEXPECTEDRCODE;
                                keep_trying = ISC_TRUE;
@@ -5800,6 +5834,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                truncated = ISC_TRUE;
 
        if (truncated) {
+               inc_stats(fctx->res, dns_resstatscounter_truncated);
                if ((options & DNS_FETCHOPT_TCP) != 0) {
                        broken_server = DNS_R_TRUNCATEDTCP;
                        keep_trying = ISC_TRUE;
@@ -5820,6 +5855,26 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                goto done;
        }
 
+       /*
+        * Update statistics about erroneous responses.
+        */
+       if (message->rcode != dns_rcode_noerror) {
+               switch (message->rcode) {
+               case dns_rcode_nxdomain:
+                       inc_stats(fctx->res, dns_resstatscounter_nxdomain);
+                       break;
+               case dns_rcode_servfail:
+                       inc_stats(fctx->res, dns_resstatscounter_servfail);
+                       break;
+               case dns_rcode_formerr:
+                       inc_stats(fctx->res, dns_resstatscounter_formerr);
+                       break;
+               default:
+                       inc_stats(fctx->res, dns_resstatscounter_othererror);
+                       break;
+               }
+       }
+
        /*
         * Is the remote server broken, or does it dislike us?
         */
@@ -5845,6 +5900,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                                dns_adb_changeflags(fctx->adb, query->addrinfo,
                                                    DNS_FETCHOPT_NOEDNS0,
                                                    DNS_FETCHOPT_NOEDNS0);
+                       inc_stats(fctx->res, dns_resstatscounter_edns0fail);
                } else if (message->rcode == dns_rcode_formerr) {
                        if (ISFORWARDER(query->addrinfo)) {
                                /*
@@ -5918,6 +5974,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
         */
        if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
            is_lame(fctx)) {
+               inc_stats(fctx->res, dns_resstatscounter_lame);
                log_lame(fctx, query->addrinfo);
                result = dns_adb_marklame(fctx->adb, query->addrinfo,
                                          &fctx->name, fctx->type,
index c3284803d62761048bd94a468dd8bcf0359f8449..a0db9957042226ec94f395e0f7def3e0d927dbdb 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sdb.c,v 1.63 2008/04/01 01:37:25 marka Exp $ */
+/* $Id: sdb.c,v 1.64 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -1251,6 +1251,7 @@ static dns_dbmethods_t sdb_methods = {
        NULL,
        NULL,
        NULL,
+       NULL,
        NULL
 };
 
index 9992cf242669d03633e820f4543163b400a6a34a..8fbb5971bce917ffea56714071b157f58f96535b 100644 (file)
@@ -50,7 +50,7 @@
  * USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sdlz.c,v 1.16 2008/04/01 23:47:10 tbox Exp $ */
+/* $Id: sdlz.c,v 1.17 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -1055,6 +1055,7 @@ static dns_dbmethods_t sdlzdb_methods = {
        NULL,
        NULL,
        NULL,
+       NULL,
        NULL
 };
 
index db4e436252d50d039cb029cc9c7cc34107ba5578..deb9b089fdbd1512b226f7a61089f9a642c4d5ff 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stats.c,v 1.14 2008/01/24 23:47:00 tbox Exp $ */
+/* $Id: stats.c,v 1.15 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
 #include <string.h>
 
 #include <isc/atomic.h>
+#include <isc/buffer.h>
+#include <isc/magic.h>
 #include <isc/mem.h>
 #include <isc/platform.h>
+#include <isc/print.h>
 #include <isc/rwlock.h>
 #include <isc/util.h>
 
+#include <dns/opcode.h>
+#include <dns/rdatatype.h>
 #include <dns/stats.h>
 
-LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
-       {
-       "success",
-       "referral",
-       "nxrrset",
-       "nxdomain",
-       "recursion",
-       "failure",
-       "duplicate",
-       "dropped"
-       };
+#define DNS_STATS_MAGIC                        ISC_MAGIC('D', 's', 't', 't')
+#define DNS_STATS_VALID(x)             ISC_MAGIC_VALID(x, DNS_STATS_MAGIC)
+
+/*%
+ * Statistics types.
+ */
+typedef enum {
+       dns_statstype_general = 0,
+       dns_statstype_rdtype = 1,
+       dns_statstype_rdataset = 2,
+       dns_statstype_opcode = 3
+} dns_statstype_t;
+
+/*%
+ * It doesn't make sense to have 2^16 counters for all possible types since
+ * most of them won't be used.  We have counters for the first 256 types and
+ * those explicitly supported in the rdata implementation.
+ * XXXJT: this introduces tight coupling with the rdata implementation.
+ * Ideally, we should have rdata handle this type of details.
+ */
+enum {
+       /* For 0-255, we use the rdtype value as counter indices */
+       rdtypecounter_dlv = 256,        /* for dns_rdatatype_dlv */
+       rdtypecounter_others = 257,     /* anything else */
+       rdtypecounter_max = 258,
+       /* The following are used for rdataset */
+       rdtypenxcounter_max = rdtypecounter_max * 2,
+       rdtypecounter_nxdomain = rdtypenxcounter_max,
+       rdatasettypecounter_max = rdtypecounter_nxdomain + 1
+};
 
 #ifndef DNS_STATS_USEMULTIFIELDS
 #if defined(ISC_RWLOCK_USEATOMIC) && defined(ISC_PLATFORM_HAVEXADD) && !defined(ISC_PLATFORM_HAVEXADDQ)
@@ -61,15 +85,42 @@ typedef isc_uint64_t dns_stat_t;
 #endif
 
 struct dns_stats {
-       /* XXXJT: do we need a magic? */
+       /*% Unlocked */
+       unsigned int    magic;
+       dns_statstype_t type;
+       isc_mem_t       *mctx;
+       int             ncounters;
+
+       isc_mutex_t     lock;
+       unsigned int    references; /* locked by lock */
+
+       /*%
+        * Locked by counterlock or unlocked if efficient rwlock is not
+        * available.
+        */
 #ifdef ISC_RWLOCK_USEATOMIC
-       isc_rwlock_t    lock;
+       isc_rwlock_t    counterlock;
 #endif
-       dns_stat_t      counters[DNS_STATS_NCOUNTERS];
+       dns_stat_t      *counters;
+
+       /*%
+        * We don't want to lock the counters while we are dumping, so we first
+        * copy the current counter values into a local array.  This buffer
+        * will be used as the copy destination.  It's allocated on creation
+        * of the stats structure so that the dump operation won't fail due
+        * to memory allocation failure.
+        * XXX: this approach is weird for non-threaded build because the
+        * additional memory and the copy overhead could be avoided.  We prefer
+        * simplicity here, however, under the assumption that this function
+        * should be only rarely called. 
+        */
+       isc_uint64_t    *copiedcounters;
 };
 
-isc_result_t
-dns_stats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+static isc_result_t
+create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
+            dns_stats_t **statsp)
+{
        dns_stats_t *stats;
        isc_result_t result = ISC_R_SUCCESS;
 
@@ -78,51 +129,108 @@ dns_stats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
        stats = isc_mem_get(mctx, sizeof(*stats));
        if (stats == NULL)
                return (ISC_R_NOMEMORY);
+       
+       result = isc_mutex_init(&stats->lock);
+       if (result != ISC_R_SUCCESS)
+               goto clean_stats;
+
+       stats->counters = isc_mem_get(mctx, sizeof(dns_stat_t) * ncounters);
+       if (stats->counters == NULL) {
+               result = ISC_R_NOMEMORY;
+               goto clean_mutex;
+       }
+       stats->copiedcounters = isc_mem_get(mctx,
+                                           sizeof(isc_uint64_t) * ncounters);
+       if (stats->copiedcounters == NULL) {
+               result = ISC_R_NOMEMORY;
+               goto clean_counters;
+       }
 
 #ifdef ISC_RWLOCK_USEATOMIC
-       result = isc_rwlock_init(&stats->lock, 0, 0);
-       if (result != ISC_R_SUCCESS) {
-               isc_mem_put(mctx, stats, sizeof(*stats));
-               return (result);
-       }
+       result = isc_rwlock_init(&stats->counterlock, 0, 0);
+       if (result != ISC_R_SUCCESS)
+               goto clean_copiedcounters;
 #endif
 
-       memset(stats->counters, 0, sizeof(dns_stat_t) * DNS_STATS_NCOUNTERS);
+       stats->type = type;
+       stats->references = 1;
+       memset(stats->counters, 0, sizeof(dns_stat_t) * ncounters);
+       stats->mctx = NULL;
+       isc_mem_attach(mctx, &stats->mctx);
+       stats->ncounters = ncounters;
+       stats->magic = DNS_STATS_MAGIC;
 
        *statsp = stats;
 
+       return (result);
+
+clean_counters:
+       isc_mem_put(mctx, stats->counters, sizeof(dns_stat_t) * ncounters);
+
+#ifdef ISC_RWLOCK_USEATOMIC
+clean_copiedcounters:
+       isc_mem_put(mctx, stats->copiedcounters,
+                   sizeof(dns_stat_t) * ncounters);
+#endif
+
+clean_mutex:
+       DESTROYLOCK(&stats->lock);
+
+clean_stats:
+       isc_mem_put(mctx, stats, sizeof(*stats));
+
        return (result);
 }
 
 void
-dns_stats_destroy(isc_mem_t *mctx, dns_stats_t **statsp) {
+dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) {
+       REQUIRE(DNS_STATS_VALID(stats));
+       REQUIRE(statsp != NULL && *statsp == NULL);
+
+       LOCK(&stats->lock);
+       stats->references++;
+       UNLOCK(&stats->lock);
+
+       *statsp = stats;
+}
+
+void
+dns_stats_detach(dns_stats_t **statsp) {
        dns_stats_t *stats;
 
-       REQUIRE(statsp != NULL && *statsp != NULL);
+       REQUIRE(statsp != NULL && DNS_STATS_VALID(*statsp));
 
        stats = *statsp;
+       *statsp = NULL;
 
+       LOCK(&stats->lock);
+       stats->references--;
+       UNLOCK(&stats->lock);
+
+       if (stats->references == 0) {
+               isc_mem_put(stats->mctx, stats->copiedcounters,
+                           sizeof(dns_stat_t) * stats->ncounters);
+               isc_mem_put(stats->mctx, stats->counters,
+                           sizeof(dns_stat_t) * stats->ncounters);
+               DESTROYLOCK(&stats->lock);
 #ifdef ISC_RWLOCK_USEATOMIC
-       isc_rwlock_destroy(&stats->lock);
+               isc_rwlock_destroy(&stats->counterlock);
 #endif
-       isc_mem_put(mctx, stats, sizeof(*stats));
-
-       *statsp = NULL;
+               isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
+       }
 }
 
-void
-dns_stats_incrementcounter(dns_stats_t *stats, dns_statscounter_t counter) {
+static inline void
+incrementcounter(dns_stats_t *stats, int counter) {
        isc_int32_t prev;
 
-       REQUIRE(counter < DNS_STATS_NCOUNTERS);
-
 #ifdef ISC_RWLOCK_USEATOMIC
        /*
         * We use a "read" lock to prevent other threads from reading the
         * counter while we "writing" a counter field.  The write access itself
         * is protected by the atomic operation.
         */
-       isc_rwlock_lock(&stats->lock, isc_rwlocktype_read);
+       isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
 #endif
 
 #if DNS_STATS_USEMULTIFIELDS
@@ -146,40 +254,296 @@ dns_stats_incrementcounter(dns_stats_t *stats, dns_statscounter_t counter) {
 #endif
 
 #ifdef ISC_RWLOCK_USEATOMIC
-       isc_rwlock_unlock(&stats->lock, isc_rwlocktype_read);
+       isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
 #endif
 }
 
-void
-dns_stats_copy(dns_stats_t *src, isc_uint64_t *dst) {
-       int i;
+static inline void
+decrementcounter(dns_stats_t *stats, int counter) {
+       isc_int32_t prev;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+       isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+
+#if DNS_STATS_USEMULTIFIELDS
+       prev = isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].lo, -1);
+       if (prev == 0)
+               isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi,
+                               -1);
+#elif defined(ISC_PLATFORM_HAVEXADDQ)
+       UNUSED(prev);
+       isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], -1);
+#else
+       UNUSED(prev);
+       stats->counters[counter]--;
+#endif
 
+#ifdef ISC_RWLOCK_USEATOMIC
+       isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+}
+
+static void
+copy_counters(dns_stats_t *stats) {
+       int i;
+       
 #ifdef ISC_RWLOCK_USEATOMIC
        /*
         * We use a "write" lock before "reading" the statistics counters as
         * an exclusive lock.
         */
-       isc_rwlock_lock(&src->lock, isc_rwlocktype_write);
+       isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
 #endif
 
 #if DNS_STATS_USEMULTIFIELDS
-       for (i = 0; i < DNS_STATS_NCOUNTERS; i++) {
-               dst[i] = ((isc_uint64_t)src->counters[i].hi) << 32 |
-                       src->counters[i].lo;
+       for (i = 0; i < stats->ncounters; i++) {
+               stats->copiedcounters[i] =
+                               (isc_uint64_t)(stats->counters[i].hi) << 32 |
+                               stats->counters[i].lo;
        }
 #else
        UNUSED(i);
-       memcpy(dst, src->counters, DNS_STATS_NCOUNTERS * sizeof(dst[0]));
+       memcpy(stats->copiedcounters, stats->counters,
+              stats->ncounters * sizeof(dns_stat_t));
 #endif
 
 #ifdef ISC_RWLOCK_USEATOMIC
-       isc_rwlock_unlock(&src->lock, isc_rwlocktype_write);
+       isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
 #endif
 }
 
+/*%
+ * Create methods
+ */
+isc_result_t
+dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters) {
+       REQUIRE(statsp != NULL && *statsp == NULL);
+
+       return (create_stats(mctx, dns_statstype_general, ncounters, statsp));
+}
+
+isc_result_t
+dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+       REQUIRE(statsp != NULL && *statsp == NULL);
+
+       return (create_stats(mctx, dns_statstype_rdtype, rdtypecounter_max,
+                            statsp));
+}
+
+isc_result_t
+dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+       REQUIRE(statsp != NULL && *statsp == NULL);
+
+       return (create_stats(mctx, dns_statstype_rdataset,
+                            (rdtypecounter_max * 2) + 1, statsp));
+}
+
+isc_result_t
+dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+       REQUIRE(statsp != NULL && *statsp == NULL);
+
+       return (create_stats(mctx, dns_statstype_opcode, 16, statsp));
+}
+
+/*%
+ * Increment/Decrement methods
+ */
+void
+dns_generalstats_increment(dns_stats_t *stats, dns_statscounter_t counter) {
+       REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
+       REQUIRE(counter < stats->ncounters);
+
+       incrementcounter(stats, (int)counter);
+}
+
+void
+dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type) {
+       int counter;
+
+       REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
+
+       if (type == dns_rdatatype_dlv)
+               counter = rdtypecounter_dlv;
+       else if (type > dns_rdatatype_any)
+               counter = rdtypecounter_others;
+       else
+               counter = (int)type;
+
+       incrementcounter(stats, counter);
+}
+
+static inline void
+update_rdatasetstats(dns_stats_t *stats, dns_rdatastatstype_t rrsettype,
+                    isc_boolean_t increment)
+{
+       int counter;
+       dns_rdatatype_t rdtype;
+
+       if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
+            DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) {
+               counter = rdtypecounter_nxdomain;
+       } else {
+               rdtype = DNS_RDATASTATSTYPE_BASE(rrsettype);
+               if (rdtype == dns_rdatatype_dlv)
+                       counter = (int)rdtypecounter_dlv;
+               else if (rdtype > dns_rdatatype_any)
+                       counter = (int)rdtypecounter_others;
+               else
+                       counter = (int)rdtype;
+
+               if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
+                    DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0)
+                       counter += rdtypecounter_max;
+       }
+
+       if (increment)
+               incrementcounter(stats, counter);
+       else
+               decrementcounter(stats, counter);
+}
+
+void
+dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
+{
+       REQUIRE(DNS_STATS_VALID(stats) &&
+               stats->type == dns_statstype_rdataset);
+
+       update_rdatasetstats(stats, rrsettype, ISC_TRUE);
+}
+
+void
+dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
+{
+       REQUIRE(DNS_STATS_VALID(stats) &&
+               stats->type == dns_statstype_rdataset);
+
+       update_rdatasetstats(stats, rrsettype, ISC_FALSE);
+}
+void
+dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) {
+       REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
+
+       incrementcounter(stats, (int)code);
+}
+
+/*%
+ * Dump methods
+ */
+void
+dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
+                     void *arg, unsigned int options)
+{
+       int i;
+
+       REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
+
+       copy_counters(stats);
+
+       for (i = 0; i < stats->ncounters; i++) {
+               if ((options & DNS_STATSDUMP_VERBOSE) == 0 &&
+                   stats->copiedcounters[i] == 0)
+                               continue;
+               dump_fn(i, stats->copiedcounters[i], arg);
+       }
+}
+
+static void
+dump_rdentry(dns_stats_t *stats, int counter, int rdcounter,
+            dns_rdatastatstype_t attributes,
+            dns_rdatatypestats_dumper_t dump_fn, void * arg,
+            unsigned int options)
+{
+       dns_rdatatype_t rdtype = dns_rdatatype_none; /* sentinel */
+       dns_rdatastatstype_t type;
+
+       if ((options & DNS_STATSDUMP_VERBOSE) == 0 &&
+           stats->copiedcounters[counter] == 0)
+               return;
+       if (rdcounter == rdtypecounter_others)
+               attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
+       else {
+               if (rdcounter == rdtypecounter_dlv)
+                       rdtype = dns_rdatatype_dlv;
+               else
+                       rdtype = (dns_rdatatype_t)rdcounter;
+       }
+       type = DNS_RDATASTATSTYPE_VALUE((dns_rdatastatstype_t)rdtype,
+                                       attributes);
+       dump_fn(type, stats->copiedcounters[counter], arg);
+}
+
+void
+dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+                       void *arg, unsigned int options)
+{
+       int i;
+
+       REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
+
+       copy_counters(stats);
+
+       for (i = 0; i < stats->ncounters; i++)
+               dump_rdentry(stats, i, i, 0, dump_fn, arg, options);
+}
+
+void
+dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+                      void *arg, unsigned int options)
+{
+       int i;
+
+       REQUIRE(DNS_STATS_VALID(stats) &&
+               stats->type == dns_statstype_rdataset);
+
+       copy_counters(stats);
+
+       for (i = 0; i < rdtypecounter_max; i++)
+               dump_rdentry(stats, i, i, 0, dump_fn, arg, options);
+       for (i = rdtypecounter_max; i < rdtypenxcounter_max; i++) {
+               dump_rdentry(stats, i, i - rdtypecounter_max,
+                            DNS_RDATASTATSTYPE_ATTR_NXRRSET,
+                            dump_fn, arg, options);
+       }
+       dump_rdentry(stats, rdtypecounter_nxdomain, 0,
+                    DNS_RDATASTATSTYPE_ATTR_NXDOMAIN, dump_fn, arg, options);
+
+       INSIST(i < stats->ncounters);
+}
+
+void
+dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
+                    void *arg, unsigned int options)
+{
+       int i;
+
+       REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
+
+       copy_counters(stats);
+
+       for (i = 0; i < stats->ncounters; i++) {
+               if ((options & DNS_STATSDUMP_VERBOSE) == 0 &&
+                   stats->copiedcounters[i] == 0)
+                               continue;
+               dump_fn((dns_opcode_t)i, stats->copiedcounters[i], arg);
+       }
+}
+
 /***
- *** Obsolete functions follow
+ *** Obsolete variables and functions follow:
  ***/
+LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
+       {
+       "success",
+       "referral",
+       "nxrrset",
+       "nxdomain",
+       "recursion",
+       "failure",
+       "duplicate",
+       "dropped"
+       };
+
 isc_result_t
 dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
        int i;
index 3a4489b8b2970ad6caacdcd9c9cf132eb0323267..cd740c79efa6bd2158c6fb7b3fbda9fcf1fa7fa8 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.145 2008/04/01 23:47:10 tbox Exp $ */
+/* $Id: view.c,v 1.146 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -25,7 +25,6 @@
 #include <isc/string.h>                /* Required for HP/UX (and others?) */
 #include <isc/task.h>
 #include <isc/util.h>
-#include <isc/xml.h>
 
 #include <dns/acache.h>
 #include <dns/acl.h>
@@ -44,6 +43,7 @@
 #include <dns/request.h>
 #include <dns/resolver.h>
 #include <dns/result.h>
+#include <dns/stats.h>
 #include <dns/tsig.h>
 #include <dns/zone.h>
 #include <dns/zt.h>
@@ -152,6 +152,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->delonly = NULL;
        view->rootdelonly = ISC_FALSE;
        view->rootexclude = NULL;
+       view->resstats = NULL;
+       view->resquerystats = NULL;
 
        /*
         * Initialize configuration data with default values.
@@ -332,6 +334,10 @@ destroy(dns_view_t *view) {
                            sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
                view->rootexclude = NULL;
        }
+       if (view->resstats != NULL)
+               dns_stats_detach(&view->resstats);
+       if (view->resquerystats != NULL)
+               dns_stats_detach(&view->resquerystats);
        dns_keytable_detach(&view->trustedkeys);
        dns_keytable_detach(&view->secroots);
        dns_fwdtable_destroy(&view->fwdtable);
@@ -1408,46 +1414,38 @@ dns_view_freezezones(dns_view_t *view, isc_boolean_t value) {
        return (dns_zt_freezezones(view->zonetable, value));
 }
 
-#ifdef HAVE_LIBXML2
-
-struct xmlarg {
-       int flags;
-       xmlTextWriterPtr xml;
-};
-
-static isc_result_t
-zone_xmlrender(dns_zone_t *zone, void *arg) {
-       struct xmlarg *xmlarg = arg;
+void
+dns_view_setresstats(dns_view_t *view, dns_stats_t *stats) {
+       REQUIRE(DNS_VIEW_VALID(view));
+       REQUIRE(!view->frozen);
+       REQUIRE(view->resstats == NULL);
 
-       return (dns_zone_xmlrender(zone, xmlarg->xml, xmlarg->flags));
+       dns_stats_attach(stats, &view->resstats);
 }
 
-isc_result_t
-dns_view_xmlrender(dns_view_t *view, xmlTextWriterPtr xml, int flags)
-{
-       struct xmlarg xmlargs;
-
-       xmlargs.flags = flags;
-       xmlargs.xml = xml;
-
-       /* XXXMLG render config data here */
+void
+dns_view_getresstats(dns_view_t *view, dns_stats_t **statsp) {
+       REQUIRE(DNS_VIEW_VALID(view));
+       REQUIRE(statsp != NULL && *statsp == NULL);
 
-       if ((flags & ISC_XML_RENDERSTATS) != 0) {
-               xmlTextWriterStartElement(xml, ISC_XMLCHAR "view");
+       if (view->resstats != NULL)
+               dns_stats_attach(view->resstats, statsp);
+}
 
-               xmlTextWriterStartElement(xml, ISC_XMLCHAR "name");
-               xmlTextWriterWriteString(xml, ISC_XMLCHAR view->name);
-               xmlTextWriterEndElement(xml);
+void
+dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
+       REQUIRE(DNS_VIEW_VALID(view));
+       REQUIRE(!view->frozen);
+       REQUIRE(view->resquerystats == NULL);
 
-               xmlTextWriterStartElement(xml, ISC_XMLCHAR "zones");
-               dns_zt_apply(view->zonetable, ISC_FALSE, zone_xmlrender,
-                            &xmlargs);
-               xmlTextWriterEndElement(xml);
+       dns_stats_attach(stats, &view->resquerystats);
+}
 
-               xmlTextWriterEndElement(xml);
-       }
+void
+dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
+       REQUIRE(DNS_VIEW_VALID(view));
+       REQUIRE(statsp != NULL && *statsp == NULL);
 
-       return (ISC_R_SUCCESS);
+       if (view->resquerystats != NULL)
+               dns_stats_attach(view->resquerystats, statsp);
 }
-
-#endif /* HAVE_LIBXML2 */
index 8bc32041884f47718aace8f80e6a5510a56150ba..680187913ff1fef4fb68f53b2e8c3c352ed47f88 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.c,v 1.477 2008/04/03 02:01:08 marka Exp $ */
+/* $Id: zone.c,v 1.478 2008/04/03 05:55:52 marka Exp $ */
 
 /*! \file */
 
@@ -34,7 +34,6 @@
 #include <isc/taskpool.h>
 #include <isc/timer.h>
 #include <isc/util.h>
-#include <isc/xml.h>
 
 #include <dns/acache.h>
 #include <dns/acl.h>
@@ -264,9 +263,15 @@ struct dns_zone {
        ISC_LINK(dns_zone_t)    statelink;
        dns_zonelist_t          *statelist;
        /*%
-        * Optional per-zone statistics counters (NULL if not present).
+        * Statistics counters about zone management.
         */
-       dns_stats_t             *counters;
+       dns_stats_t             *stats;
+       /*%
+        * Optional per-zone statistics counters.  Counted outside of this
+        * module.
+        */
+       isc_boolean_t           requeststats_on;
+       dns_stats_t             *requeststats;
        isc_uint32_t            notifydelay;
        dns_isselffunc_t        isself;
        void                    *isselfarg;
@@ -592,6 +597,15 @@ static const char *dbargv_default[] = { "rbt" };
                } \
        } while (0)
 
+/*%
+ * Increment resolver-related statistics counters.  Zone must be locked.
+ */
+static inline void
+inc_stats(dns_zone_t *zone, dns_statscounter_t counter) {
+       if (zone->stats != NULL)
+               dns_generalstats_increment(zone->stats, counter);
+}
+
 /***
  ***   Public functions.
  ***/
@@ -712,7 +726,9 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->checkns = NULL;
        ISC_LINK_INIT(zone, statelink);
        zone->statelist = NULL;
-       zone->counters = NULL;
+       zone->stats = NULL;
+       zone->requeststats_on = ISC_FALSE;
+       zone->requeststats = NULL;
        zone->notifydelay = 5;
        zone->isself = NULL;
        zone->isselfarg = NULL;
@@ -797,8 +813,10 @@ zone_free(dns_zone_t *zone) {
        if (zone->journal != NULL)
                isc_mem_free(zone->mctx, zone->journal);
        zone->journal = NULL;
-       if (zone->counters != NULL)
-               dns_stats_destroy(zone->mctx, &zone->counters);
+       if (zone->stats != NULL)
+               dns_stats_detach(&zone->stats);
+       if (zone->requeststats != NULL)
+               dns_stats_detach(&zone->requeststats);
        if (zone->db != NULL)
                zone_detachdb(zone);
        if (zone->acache != NULL)
@@ -876,7 +894,7 @@ dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
 }
 
 dns_rdataclass_t
-dns_zone_getclass(dns_zone_t *zone){
+dns_zone_getclass(dns_zone_t *zone) {
        REQUIRE(DNS_ZONE_VALID(zone));
 
        return (zone->rdclass);
@@ -891,6 +909,19 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
        UNLOCK_ZONE(zone);
 }
 
+isc_uint32_t
+dns_zone_getserial(dns_zone_t *zone) {
+       isc_uint32_t serial;
+
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       serial = zone->serial;
+       UNLOCK_ZONE(zone);
+
+       return (serial);
+}
+
 /*
  *     Single shot.
  */
@@ -5288,6 +5319,16 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
                                        timeout * 3, timeout,
                                        notify->zone->task, notify_done,
                                        notify, &notify->request);
+       if (result == ISC_R_SUCCESS) {
+               if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
+                       inc_stats(notify->zone,
+                                 dns_zonestatscounter_notifyoutv4);
+               } else {
+                       inc_stats(notify->zone,
+                                 dns_zonestatscounter_notifyoutv6);
+               }
+       }
+
  cleanup_key:
        if (key != NULL)
                dns_tsigkey_detach(&key);
@@ -6561,6 +6602,11 @@ soa_query(isc_task_t *task, isc_event_t *event) {
                              "dns_request_createvia2() failed: %s",
                              dns_result_totext(result));
                goto cleanup;
+       } else {
+               if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
+                       inc_stats(zone, dns_zonestatscounter_soaoutv4);
+               else
+                       inc_stats(zone, dns_zonestatscounter_soaoutv6);
        }
        cancel = ISC_FALSE;
 
@@ -7219,6 +7265,10 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
         *  We only handle NOTIFY (SOA) at the present.
         */
        LOCK_ZONE(zone);
+       if (isc_sockaddr_pf(from) == PF_INET)
+               inc_stats(zone, dns_zonestatscounter_notifyinv4);
+       else
+               inc_stats(zone, dns_zonestatscounter_notifyinv6);
        if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
            dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
                                 dns_rdatatype_soa, dns_rdatatype_none,
@@ -7273,6 +7323,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
                UNLOCK_ZONE(zone);
                dns_zone_log(zone, ISC_LOG_INFO,
                             "refused notify from non-master: %s", fromtext);
+               inc_stats(zone, dns_zonestatscounter_notifyrej);
                return (DNS_R_REFUSED);
        }
 
@@ -8241,6 +8292,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
                                             dns_result_totext(result));
                }
 
+               inc_stats(zone, dns_zonestatscounter_xfrsuccess);
                break;
 
        case DNS_R_BADIXFR:
@@ -8275,6 +8327,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
                        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
                        again = ISC_TRUE;
                }
+               inc_stats(zone, dns_zonestatscounter_xfrfail);
                break;
        }
        zone_settimer(zone, &now);
@@ -8578,6 +8631,21 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
                                   zone->tsigkey, zone->mctx,
                                   zone->zmgr->timermgr, zone->zmgr->socketmgr,
                                   zone->task, zone_xfrdone, &zone->xfr);
+       if (result == ISC_R_SUCCESS) {
+               LOCK_ZONE(zone);
+               if (xfrtype == dns_rdatatype_axfr) {
+                       if (isc_sockaddr_pf(&masteraddr) == PF_INET)
+                               inc_stats(zone, dns_zonestatscounter_axfrreqv4);
+                       else
+                               inc_stats(zone, dns_zonestatscounter_axfrreqv6);
+               } else if (xfrtype == dns_rdatatype_ixfr) {
+                       if (isc_sockaddr_pf(&masteraddr) == PF_INET)
+                               inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
+                       else
+                               inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
+               }
+               UNLOCK_ZONE(zone);
+       }
  cleanup:
        /*
         * Any failure in this function is handled like a failed
@@ -9569,35 +9637,66 @@ dns_zone_isforced(dns_zone_t *zone) {
 
 isc_result_t
 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
-       isc_result_t result = ISC_R_SUCCESS;
-
-       LOCK_ZONE(zone);
-       if (on) {
-               if (zone->counters != NULL)
-                       goto done;
-               result = dns_stats_create(zone->mctx, &zone->counters);
-       } else {
-               if (zone->counters == NULL)
-                       goto done;
-               dns_stats_destroy(zone->mctx, &zone->counters);
-       }
- done:
-       UNLOCK_ZONE(zone);
-       return (result);
+       /*
+        * This function is obsoleted.
+        */
+       UNUSED(zone);
+       UNUSED(on);
+       return (ISC_R_NOTIMPLEMENTED);
 }
 
 isc_uint64_t *
 dns_zone_getstatscounters(dns_zone_t *zone) {
        /*
-        * This function is obsoleted by dns_zone_getstats().
+        * This function is obsoleted.
         */
        UNUSED(zone);
        return (NULL);
 }
 
+void
+dns_zone_setstats(dns_zone_t *zone, dns_stats_t *stats) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       REQUIRE(zone->stats == NULL);
+
+       LOCK_ZONE(zone);
+       zone->stats = NULL;
+       dns_stats_attach(stats, &zone->stats);
+       UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setrequeststats(dns_zone_t *zone, dns_stats_t *stats) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       if (zone->requeststats_on && stats == NULL)
+               zone->requeststats_on = ISC_FALSE;
+       else if (!zone->requeststats_on && stats != NULL) {
+               if (zone->requeststats == NULL) {
+                       dns_stats_attach(stats, &zone->requeststats);
+                       zone->requeststats_on = ISC_TRUE;
+               }
+       }
+       UNLOCK_ZONE(zone);
+
+       return;
+}
+
 dns_stats_t *
-dns_zone_getstats(dns_zone_t *zone) {
-       return (zone->counters);
+dns_zone_getrequeststats(dns_zone_t *zone) {
+       /*
+        * We don't lock zone for efficiency reason.  This is not catastrophic
+        * because requeststats must always be valid when requeststats_on is
+        * true.
+        * Some counters may be incremented while requeststats_on is becoming
+        * false, or some cannot be incremented just after the statistics are
+        * installed, but it shouldn't matter much in practice.
+        */
+       if (zone->requeststats_on)
+               return (zone->requeststats);
+       else
+               return (NULL);
 }
 
 void
@@ -9908,50 +10007,3 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid) {
        }
        return (result);
 }
-
-#ifdef HAVE_LIBXML2
-
-isc_result_t
-dns_zone_xmlrender(dns_zone_t *zone, xmlTextWriterPtr xml, int flags)
-{
-       int i;
-
-       /* XXXMLG render config data here */
-
-       if ((flags & ISC_XML_RENDERSTATS) != 0) {
-               xmlTextWriterStartElement(xml, ISC_XMLCHAR "zone");
-
-               xmlTextWriterStartElement(xml, ISC_XMLCHAR "name");
-               xmlTextWriterWriteString(xml, ISC_XMLCHAR zone->strname);
-               xmlTextWriterEndElement(xml);
-
-               xmlTextWriterStartElement(xml, ISC_XMLCHAR "rdataclass");
-               xmlTextWriterWriteString(xml, ISC_XMLCHAR zone->strrdclass);
-               xmlTextWriterEndElement(xml);
-
-               xmlTextWriterStartElement(xml, ISC_XMLCHAR "serial");
-               xmlTextWriterWriteFormatString(xml, "%u", zone->serial);
-               xmlTextWriterEndElement(xml);
-
-               if (zone->counters != NULL) {
-                       isc_uint64_t counters[DNS_STATS_NCOUNTERS];
-
-                       xmlTextWriterStartElement(xml, ISC_XMLCHAR "counters");
-                       dns_stats_copy(zone->counters, counters);
-                       for (i = 0 ; i < DNS_STATS_NCOUNTERS ; i++) {
-                               xmlTextWriterStartElement(xml,
-                                       ISC_XMLCHAR dns_statscounter_names[i]);
-                               xmlTextWriterWriteFormatString(xml,
-                                              "%" ISC_PRINT_QUADFORMAT "u",
-                                              counters[i]);
-                               xmlTextWriterEndElement(xml);
-                       }
-                       xmlTextWriterEndElement(xml); /* counters */
-               }
-               xmlTextWriterEndElement(xml); /* zone */
-       }
-
-       return (ISC_R_SUCCESS);
-}
-
-#endif /* HAVE_LIBXML2 */