+3699. [bug] Improvements to statistics channel XSL stylesheet:
+ the stylesheet can now be cached by the browser;
+ section headers are omitted from the stats display
+ when there is no data in those sections to be
+ displayed; counters are now right-justified for
+ easier readability. (Only available with
+ configure --enable-newstats.) [RT #35117]
+
3698. [cleanup] Replaced all uses of memcpy() with memmove().
[RT #35120]
<!-- %Id: bind9.xsl,v 1.21 2009/01/27 23:47:54 tbox Exp % -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:output method="html" indent="yes" version="4.0"/>
- <xsl:template match="statistics[@version="3.0"]">
+ <xsl:template match="statistics[@version="3.3"]">
<html>
<head>
<xsl:if test="system-property('xsl:vendor')!='Transformiix'">
<!-- Non Mozilla specific markup -->
<script type="text/javascript" src="https://www.google.com/jsapi"/>
<script type="text/javascript">
-
+
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(loadGraphs);
var graphs=[];
-
- function drawChart(chart_title,target,data) {
+
+ function drawChart(chart_title,target,style,data) {
var data = google.visualization.arrayToDataTable(data);
var options = {
title: chart_title
};
-
- var chart = new google.visualization.BarChart(document.getElementById(target));
- chart.draw(data, options);
+
+ var chart;
+ if (style == "barchart") {
+ chart = new google.visualization.BarChart(document.getElementById(target));
+ chart.draw(data, options);
+ } else if (style == "piechart") {
+ chart = new google.visualization.PieChart(document.getElementById(target));
+ chart.draw(data, options);
+ }
}
-
+
function loadGraphs(){
- //alert("here we are!");
var g;
-
- // Server Incoming query Types
+
while(g = graphs.shift()){
// alert("going for: " + g.target);
if(g.data.length > 1){
- drawChart(g.title,g.target,g.data);
+ drawChart(g.title,g.target,g.style,g.data);
}
}
}
-
- // Server Incoming Queries Types
- graphs.push({
- 'title' : "Server Incoming Query Types",
- 'target': 'chart_incoming_qtypes',
- 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="qtype"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
- });
-
-
- // Server Incoming Requests
- graphs.push({
- 'title' : "Server Incoming Requests",
- 'target': 'chart_incoming_requests',
- 'data': [['Requests','Counter'],<xsl:for-each select="server/counters[@type="opcode"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]});
-
-
-
-
+
+ // Server Incoming Query Types
+ graphs.push({
+ 'title' : "Server Incoming Query Types",
+ 'target': 'chart_incoming_qtypes',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="qtype"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+
+ // Server Incoming Requests by opcode
+ graphs.push({
+ 'title' : "Server Incoming Requests by DNS Opcode",
+ 'target': 'chart_incoming_opcodes',
+ 'style': 'barchart',
+ 'data': [['Opcode','Counter'],<xsl:for-each select="server/counters[@type="opcode"]/counter[. > 0 or substring(@name,1,3) != 'RES']">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]});
</script>
</xsl:if>
<style type="text/css">
color: #000000;
font-size: 10pt;
}
-
+
.odd{
background-color: #f0f0f0;
}
-
+
.even{
background-color: #ffffff;
}
-
+
p.footer{
font-style:italic;
color: grey;
border: 1px solid grey;
width: 500px;
}
-
table.counters th {
+ text-align: right;
+ border: 1px solid grey;
+ width: 150px;
+ }
+ table.counters td {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.counters tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.info {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.info th {
text-align: center;
border: 1px solid grey;
- width: 120px;
- }
- table.counters td{
- text-align:center;
-
- }
-
- table.counters tr:hover{
+ width: 150px;
+ }
+ table.info td {
+ text-align: center;
+ }
+ table.info tr:hover{
background-color: #99ddff;
- }
-
+ }
+
+ table.tasks {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.tasks th {
+ text-align: center;
+ border: 1px solid grey;
+ width: 150px;
+ }
+ table.tasks td {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.tasks td:nth-child(2) {
+ text-align: center;
+ }
+ table.tasks td:nth-child(4) {
+ text-align: center;
+ }
+ table.tasks tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.netstat {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.netstat th {
+ text-align: center;
+ border: 1px solid grey;
+ width: 150px;
+ }
+ table.netstat td {
+ text-align: center;
+ }
+ table.netstat td:nth-child(4) {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.netstat td:nth-child(7) {
+ text-align: left;
+ }
+ table.netstat tr:hover{
+ background-color: #99ddff;
+ }
+
+ table.mctx {
+ border: 1px solid grey;
+ width: 500px;
+ }
+ table.mctx th {
+ text-align: center;
+ border: 1px solid grey;
+ }
+ table.mctx td {
+ text-align: right;
+ font-family: monospace;
+ }
+ table.mctx td:nth-child(-n+2) {
+ text-align: left;
+ width: 100px;
+ }
+ table.mctx tr:hover{
+ background-color: #99ddff;
+ }
+
.totals {
background-color: rgb(1,169,206);
color: #ffffff;
width:500px;
text-align:center;
}
-
+
h3 {
color: #444444;
font-size: 12pt;
width:500px;
text-align:center;
-
}
h4 {
color: rgb(1,169,206);
font-size: 10pt;
width:500px;
text-align:center;
-
}
.pie {
</div>
<hr/>
<h2>Server Times</h2>
- <table class="counters">
+ <table class="info">
<tr>
<th>Boot time:</th>
<td>
</td>
</tr>
<tr>
- <th>Sample time:</th>
+ <th>Current time:</th>
<td>
<xsl:value-of select="server/current-time"/>
</td>
</tr>
</table>
<br/>
- <h2>Incoming Requests</h2>
- <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
- <!-- Non Mozilla specific markup -->
- <div class="pie" id="chart_incoming_requests">[no incoming requests]</div>
- </xsl:if>
- <table class="counters">
- <xsl:for-each select="server/counters[@type="opcode"]/counter">
- <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:if test="server/counters[@type="opcode"]/counter[. > 0]">
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <h2>Incoming Requests by DNS Opcode</h2>
+ <!-- Non Mozilla specific markup -->
+ <div class="pie" id="chart_incoming_opcodes">
+ [cannot display chart]
+ </div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type="opcode"]/counter[. > 0 or substring(@name,1,3) != 'RES']">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <tr>
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
<tr>
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
+ <th class="totals">Total:</th>
+ <td class="totals">
+ <xsl:value-of select="sum(server/counters[@type="opcode"]/counter)"/>
</td>
</tr>
- </xsl:for-each>
- <tr>
- <th class="totals">Total:</th>
- <td class="totals">
- <xsl:value-of select="sum(server/counters[@type="opcode"]/counter)"/>
- </td>
- </tr>
- </table>
- <br/>
- <h3>Incoming Queries by Type</h3>
- <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
- <!-- Non Mozilla specific markup -->
- <div class="pie" id="chart_incoming_qtypes">[no incoming queries]</div>
+ </table>
+ <br/>
</xsl:if>
- <table class="counters">
- <xsl:for-each select="server/counters[@type="qtype"]/counter">
- <xsl:sort select="." data-type="number" order="descending"/>
- <xsl:variable name="css-class">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class}">
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
+ <xsl:if test="server/counters[@type="qtype"]/counter">
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <h3>Incoming Queries by Query Type</h3>
+ <div class="pie" id="chart_incoming_qtypes">
+ [cannot display chart]
+ </div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type="qtype"]/counter">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ <tr>
+ <th class="totals">Total:</th>
+ <td class="totals">
+ <xsl:value-of select="sum(server/counters[@type="qtype"]/counter)"/>
</td>
</tr>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="views/view[count(counters[@type="resqtype"]/counter) > 0]">
+ <h2>Outgoing Queries per view</h2>
+ <xsl:for-each select="views/view[count(counters[@type="resqtype"]/counter) > 0]">
+ <h3>View <xsl:value-of select="@name"/></h3>
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript">
+ graphs.push({
+ 'title': "Outgoing Queries for view: <xsl:value-of select="@name"/>",
+ 'target': 'chart_outgoing_queries_view_<xsl:value-of select="@name"/>',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="resqtype"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+ </script>
+ <xsl:variable name="target">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <div class="pie" id="chart_outgoing_queries_view_{$target}">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="counters[@type="resqtype"]/counter">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class1">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class1}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
</xsl:for-each>
- <tr>
- <th class="totals">Total:</th>
- <td class="totals">
- <xsl:value-of select="sum(server/counters[@type="qtype"]/counter)"/>
- </td>
- </tr>
- </table>
- <br/>
- <h2>Outgoing Queries per view</h2>
- <xsl:for-each select="views/view[count(counters[@type="resqtype"]/counter) > 0]">
- <h3>View <xsl:value-of select="@name"/></h3>
+ </xsl:if>
+ <xsl:if test="server/counters[@type="nsstat"]/counter[.>0]">
+ <h2>Server Statistics</h2>
<xsl:if test="system-property('xsl:vendor')!='Transformiix'">
<!-- Non Mozilla specific markup -->
<script type="text/javascript">
- graphs.push({
- 'title': "Outgoing queries for view: <xsl:value-of select="@name"/>",
- 'target': 'chart_outgoing_queries_view_<xsl:value-of select="@name"/>',
- 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="resqtype"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
- });
-
- </script>
- <xsl:variable name="target">
- <xsl:value-of select="@name"/>
- </xsl:variable>
- <div class="pie" id="chart_outgoing_queries_view_{$target}"/>
+ graphs.push({
+ 'title' : "Server Counters",
+ 'target': 'chart_server_nsstat_restype',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="nsstat"]/counter[.>0]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+ </script>
+ <div class="pie" id="chart_server_nsstat_restype">[no data to display]</div>
</xsl:if>
<table class="counters">
- <xsl:for-each select="counters[@type="resqtype"]/counter">
+ <xsl:for-each select="server/counters[@type="nsstat"]/counter[.>0]">
<xsl:sort select="." data-type="number" order="descending"/>
- <xsl:variable name="css-class1">
+ <xsl:variable name="css-class2">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">even</xsl:when>
<xsl:otherwise>odd</xsl:otherwise>
</xsl:choose>
</xsl:variable>
- <tr class="{$css-class1}">
+ <tr class="{$css-class2}">
<th>
<xsl:value-of select="@name"/>
</th>
</xsl:for-each>
</table>
<br/>
- </xsl:for-each>
- <h2>Server Statistics</h2>
- <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
- <!-- Non Mozilla specific markup -->
- <script type="text/javascript">
- graphs.push({
- 'title' : "Server Counters",
- 'target': 'chart_server_nsstat_restype',
- 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="nsstat"]/counter[.>0]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
- });
-
- </script>
- <div class="pie" id="chart_server_nsstat_restype"/>
</xsl:if>
- <table class="counters">
- <xsl:for-each select="server/counters[@type="nsstat"]/counter[.>0]">
- <xsl:sort select="." data-type="number" order="descending"/>
- <xsl:variable name="css-class2">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class2}">
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
- </td>
- </tr>
- </xsl:for-each>
- </table>
- <br/>
- <h2>Zone Maintenance Statistics</h2>
- <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
- <script type="text/javascript">
- graphs.push({
- 'title' : "Zone Maintenance Stats",
- 'target': 'chart_server_zone_maint',
- 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="zonestat"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
- });
-
- </script>
- <!-- Non Mozilla specific markup -->
- <div class="pie" id="chart_server_zone_maint"/>
+ <xsl:if test="server/counters[@type="zonestat"]/counter[.>0]">
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <h2>Zone Maintenance Statistics</h2>
+ <script type="text/javascript">
+ graphs.push({
+ 'title' : "Zone Maintenance Stats",
+ 'target': 'chart_server_zone_maint',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="zonestat"]/counter[.>0]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+ </script>
+ <!-- Non Mozilla specific markup -->
+ <div class="pie" id="chart_server_zone_maint">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="server/counters[@type="zonestat"]/counter">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class3">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class3}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
</xsl:if>
- <table class="counters">
- <xsl:for-each select="server/counters[@type="zonestat"]/counter">
- <xsl:sort select="." data-type="number" order="descending"/>
- <xsl:variable name="css-class3">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class3}">
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
- </td>
- </tr>
- </xsl:for-each>
- </table>
- <h2>Resolver Statistics (Common)</h2>
- <table class="counters">
- <xsl:for-each select="server/counters[@type="restat"]/counter">
- <xsl:sort select="." data-type="number" order="descending"/>
- <xsl:variable name="css-class4">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class4}">
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
- </td>
- </tr>
- </xsl:for-each>
- </table>
- <xsl:for-each select="views/view">
- <h3>Resolver Statistics for View <xsl:value-of select="@name"/></h3>
+ <xsl:if test="server/counters[@type="resstat"]/counter[.>0]">
+ <h2>Resolver Statistics (Common)</h2>
<table class="counters">
- <xsl:for-each select="counters[@type="resstats"]/counter[.>0]">
+ <xsl:for-each select="server/counters[@type="resstat"]/counter">
<xsl:sort select="." data-type="number" order="descending"/>
- <xsl:variable name="css-class5">
+ <xsl:variable name="css-class4">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">even</xsl:when>
<xsl:otherwise>odd</xsl:otherwise>
</xsl:choose>
</xsl:variable>
- <tr class="{$css-class5}">
+ <tr class="{$css-class4}">
<th>
<xsl:value-of select="@name"/>
</th>
</tr>
</xsl:for-each>
</table>
+ </xsl:if>
+ <xsl:for-each select="views/view">
+ <xsl:if test="counters[@type="resstats"]/counter[.>0]">
+ <h3>Resolver Statistics for View <xsl:value-of select="@name"/></h3>
+ <table class="counters">
+ <xsl:for-each select="counters[@type="resstats"]/counter[.>0]">
+ <xsl:sort select="." data-type="number" order="descending"/>
+ <xsl:variable name="css-class5">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class5}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
</xsl:for-each>
- <h3>Cache DB RRsets for View <xsl:value-of select="@name"/></h3>
+
<xsl:for-each select="views/view">
+ <xsl:if test="cache/rrset">
+ <h3>Cache DB RRsets for View <xsl:value-of select="@name"/></h3>
+ <table class="counters">
+ <xsl:for-each select="cache/rrset">
+ <xsl:variable name="css-class6">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class6}">
+ <th>
+ <xsl:value-of select="name"/>
+ </th>
+ <td>
+ <xsl:value-of select="counter"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:if test="server/counters[@type="sockstat"]/counter[.>0]">
+ <h2>Socket I/O Statistics</h2>
<table class="counters">
- <xsl:for-each select="cache/rrset">
- <xsl:variable name="css-class6">
+ <xsl:for-each select="server/counters[@type="sockstat"]/counter[.>0]">
+ <xsl:variable name="css-class7">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">even</xsl:when>
<xsl:otherwise>odd</xsl:otherwise>
</xsl:choose>
</xsl:variable>
- <tr class="{$css-class6}">
+ <tr class="{$css-class7}">
<th>
- <xsl:value-of select="name"/>
+ <xsl:value-of select="@name"/>
</th>
<td>
- <xsl:value-of select="counter"/>
+ <xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
</table>
<br/>
- </xsl:for-each>
- <h2>Socket I/O Statistics</h2>
- <table class="counters">
- <xsl:for-each select="server/counters[@type="sockstat"]/counter[.>0]">
- <xsl:variable name="css-class7">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
+ </xsl:if>
+ <xsl:if test="views/view[zones/zone/counters[@type="rcode"]/counter >0]">
+ <h2>Response Codes per view/zone</h2>
+ <xsl:for-each select="views/view[zones/zone/counters[@type="rcode"]/counter >0]">
+ <h3>View <xsl:value-of select="@name"/></h3>
+ <xsl:variable name="thisview">
+ <xsl:value-of select="@name"/>
</xsl:variable>
- <tr class="{$css-class7}">
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
- </td>
- </tr>
- </xsl:for-each>
- </table>
- <br/>
- <br/>
- <h2>Response Codes per view/zone</h2>
- <xsl:for-each select="views/view[zones/zone/counters[@type="rcode"]/counter >0]">
- <h3>View <xsl:value-of select="@name"/></h3>
- <xsl:variable name="thisview">
- <xsl:value-of select="@name"/>
- </xsl:variable>
- <xsl:for-each select="zones/zone">
- <xsl:if test="counters[@type="rcode"]/counter[. > 0]">
- <h4>Zone <xsl:value-of select="@name"/></h4>
- <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
- <!-- Non Mozilla specific markup -->
- <script type="text/javascript">
- graphs.push({
- 'title': "Response Codes for zone <xsl:value-of select="@name"/>",
- 'target': 'chart_rescode_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>',
- 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
- });
-
- </script>
- <xsl:variable name="target">
- <xsl:value-of select="@name"/>
- </xsl:variable>
- <div class="pie" id="chart_rescode_{$thisview}_{$target}"/>
+ <xsl:for-each select="zones/zone">
+ <xsl:if test="counters[@type="rcode"]/counter[. > 0]">
+ <h4>Zone <xsl:value-of select="@name"/></h4>
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript">
+ graphs.push({
+ 'title': "Response Codes for zone <xsl:value-of select="@name"/>",
+ 'target': 'chart_rescode_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+
+ </script>
+ <xsl:variable name="target">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <div class="pie" id="chart_rescode_{$thisview}_{$target}">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]">
+ <xsl:sort select="."/>
+ <xsl:variable name="css-class10">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class10}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
</xsl:if>
- <table class="counters">
- <xsl:for-each select="counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]">
- <xsl:sort select="."/>
- <xsl:variable name="css-class10">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class10}">
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
- </td>
- </tr>
- </xsl:for-each>
- </table>
- </xsl:if>
+ </xsl:for-each>
</xsl:for-each>
- </xsl:for-each>
- <h2>Received QTYPES per view/zone</h2>
- <xsl:for-each select="views/view[zones/zone/counters[@type="qtype"]/counter >0]">
- <h3>View <xsl:value-of select="@name"/></h3>
- <xsl:variable name="thisview2">
- <xsl:value-of select="@name"/>
- </xsl:variable>
- <xsl:for-each select="zones/zone">
- <xsl:if test="counters[@type="qtype"]/counter[count(.) > 0]">
- <h4>Zone <xsl:value-of select="@name"/></h4>
- <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
- <!-- Non Mozilla specific markup -->
- <script type="text/javascript">
- graphs.push({
- 'title': "Query Types for zone <xsl:value-of select="@name"/>",
- 'target': 'chart_qtype_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>',
- 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="qtype"]/counter[.>0 and @name != "QryAuthAns"]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
- });
-
- </script>
- <xsl:variable name="target">
- <xsl:value-of select="@name"/>
- </xsl:variable>
- <div class="pie" id="chart_qtype_{$thisview2}_{$target}"/>
+ </xsl:if>
+ <xsl:if test="views/view[zones/zone/counters[@type="qtype"]/counter >0]">
+ <h2>Received QTYPES per view/zone</h2>
+ <xsl:for-each select="views/view[zones/zone/counters[@type="qtype"]/counter >0]">
+ <h3>View <xsl:value-of select="@name"/></h3>
+ <xsl:variable name="thisview2">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <xsl:for-each select="zones/zone">
+ <xsl:if test="counters[@type="qtype"]/counter[count(.) > 0]">
+ <h4>Zone <xsl:value-of select="@name"/></h4>
+ <xsl:if test="system-property('xsl:vendor')!='Transformiix'">
+ <!-- Non Mozilla specific markup -->
+ <script type="text/javascript">
+ graphs.push({
+ 'title': "Query Types for zone <xsl:value-of select="@name"/>",
+ 'target': 'chart_qtype_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>',
+ 'style': 'barchart',
+ 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="qtype"]/counter[.>0 and @name != "QryAuthAns"]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]
+ });
+
+ </script>
+ <xsl:variable name="target">
+ <xsl:value-of select="@name"/>
+ </xsl:variable>
+ <div class="pie" id="chart_qtype_{$thisview2}_{$target}">[no data to display]</div>
+ </xsl:if>
+ <table class="counters">
+ <xsl:for-each select="counters[@type="qtype"]/counter">
+ <xsl:sort select="."/>
+ <xsl:variable name="css-class11">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class11}">
+ <th>
+ <xsl:value-of select="@name"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
</xsl:if>
- <table class="counters">
- <xsl:for-each select="counters[@type="qtype"]/counter">
- <xsl:sort select="."/>
- <xsl:variable name="css-class11">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class11}">
- <th>
- <xsl:value-of select="@name"/>
- </th>
- <td>
- <xsl:value-of select="."/>
- </td>
- </tr>
- </xsl:for-each>
- </table>
- </xsl:if>
+ </xsl:for-each>
</xsl:for-each>
- </xsl:for-each>
- <h2>Network Status</h2>
- <table class="counters">
- <tr>
- <th>ID</th>
- <th>Name</th>
- <th>Type</th>
- <th>References</th>
- <th>LocalAddress</th>
- <th>PeerAddress</th>
- <th>State</th>
- </tr>
- <xsl:for-each select="socketmgr/sockets/socket">
- <xsl:sort select="id"/>
- <xsl:variable name="css-class12">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class12}">
- <td>
- <xsl:value-of select="id"/>
- </td>
- <td>
- <xsl:value-of select="name"/>
- </td>
- <td>
- <xsl:value-of select="type"/>
- </td>
- <td>
- <xsl:value-of select="references"/>
- </td>
- <td>
- <xsl:value-of select="local-address"/>
- </td>
- <td>
- <xsl:value-of select="peer-address"/>
- </td>
- <td>
- <xsl:for-each select="states">
- <xsl:value-of select="."/>
- </xsl:for-each>
- </td>
+ </xsl:if>
+ <xsl:if test="socketmgr/sockets/socket">
+ <h2>Network Status</h2>
+ <table class="netstat">
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>Type</th>
+ <th>References</th>
+ <th>LocalAddress</th>
+ <th>PeerAddress</th>
+ <th>State</th>
</tr>
- </xsl:for-each>
- </table>
- <br/>
- <h2>Task Manager Configuration</h2>
- <table class="counters">
- <tr>
- <th class="even">Thread-Model</th>
- <td>
- <xsl:value-of select="taskmgr/thread-model/type"/>
- </td>
- </tr>
- <tr class="odd">
- <th>Worker Threads</th>
- <td>
- <xsl:value-of select="taskmgr/thread-model/worker-threads"/>
- </td>
- </tr>
- <tr class="even">
- <th>Default Quantum</th>
- <td>
- <xsl:value-of select="taskmgr/thread-model/default-quantum"/>
- </td>
- </tr>
- <tr class="odd">
- <th>Tasks Running</th>
- <td>
- <xsl:value-of select="taskmgr/thread-model/tasks-running"/>
- </td>
- </tr>
- </table>
- <br/>
- <h2>Tasks</h2>
- <table class="counters">
- <tr>
- <th>ID</th>
- <th>Name</th>
- <th>References</th>
- <th>State</th>
- <th>Quantum</th>
- </tr>
- <xsl:for-each select="taskmgr/tasks/task">
- <xsl:sort select="name"/>
- <xsl:variable name="css-class14">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class14}">
- <td>
- <xsl:value-of select="id"/>
- </td>
- <td>
- <xsl:value-of select="name"/>
- </td>
- <td>
- <xsl:value-of select="references"/>
- </td>
- <td>
- <xsl:value-of select="state"/>
- </td>
+ <xsl:for-each select="socketmgr/sockets/socket">
+ <xsl:sort select="id"/>
+ <xsl:variable name="css-class12">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class12}">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="type"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="local-address"/>
+ </td>
+ <td>
+ <xsl:value-of select="peer-address"/>
+ </td>
+ <td>
+ <xsl:for-each select="states">
+ <xsl:value-of select="."/>
+ </xsl:for-each>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="taskmgr/thread-model/type">
+ <h2>Task Manager Configuration</h2>
+ <table class="counters">
+ <tr>
+ <th class="even">Thread-Model</th>
<td>
- <xsl:value-of select="quantum"/>
+ <xsl:value-of select="taskmgr/thread-model/type"/>
</td>
</tr>
- </xsl:for-each>
- </table>
- <br/>
- <h2>Memory Usage Summary</h2>
- <table class="counters">
- <xsl:for-each select="memory/summary/*">
- <xsl:variable name="css-class13">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class13}">
- <th>
- <xsl:value-of select="name()"/>
- </th>
+ <tr class="odd">
+ <th>Worker Threads</th>
<td>
- <xsl:value-of select="."/>
+ <xsl:value-of select="taskmgr/thread-model/worker-threads"/>
</td>
</tr>
- </xsl:for-each>
- </table>
- <br/>
- <h2>Memory Contexts</h2>
- <table class="counters">
- <tr>
- <th>ID</th>
- <th>Name</th>
- <th>References</th>
- <th>TotalUse</th>
- <th>InUse</th>
- <th>MaxUse</th>
- <th>BlockSize</th>
- <th>Pools</th>
- <th>HiWater</th>
- <th>LoWater</th>
- </tr>
- <xsl:for-each select="memory/contexts/context">
- <xsl:sort select="total" data-type="number" order="descending"/>
- <xsl:variable name="css-class14">
- <xsl:choose>
- <xsl:when test="position() mod 2 = 0">even</xsl:when>
- <xsl:otherwise>odd</xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <tr class="{$css-class14}">
- <td>
- <xsl:value-of select="id"/>
- </td>
- <td>
- <xsl:value-of select="name"/>
- </td>
- <td>
- <xsl:value-of select="references"/>
- </td>
- <td>
- <xsl:value-of select="total"/>
- </td>
- <td>
- <xsl:value-of select="inuse"/>
- </td>
- <td>
- <xsl:value-of select="maxinuse"/>
- </td>
- <td>
- <xsl:value-of select="blocksize"/>
- </td>
- <td>
- <xsl:value-of select="pools"/>
- </td>
+ <tr class="even">
+ <th>Default Quantum</th>
<td>
- <xsl:value-of select="hiwater"/>
+ <xsl:value-of select="taskmgr/thread-model/default-quantum"/>
</td>
+ </tr>
+ <tr class="odd">
+ <th>Tasks Running</th>
<td>
- <xsl:value-of select="lowater"/>
+ <xsl:value-of select="taskmgr/thread-model/tasks-running"/>
</td>
</tr>
- </xsl:for-each>
- </table>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="taskmgr/tasks/task">
+ <h2>Tasks</h2>
+ <table class="tasks">
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>References</th>
+ <th>State</th>
+ <th>Quantum</th>
+ </tr>
+ <xsl:for-each select="taskmgr/tasks/task">
+ <xsl:sort select="name"/>
+ <xsl:variable name="css-class14">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class14}">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="state"/>
+ </td>
+ <td>
+ <xsl:value-of select="quantum"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="memory/summary">
+ <h2>Memory Usage Summary</h2>
+ <table class="counters">
+ <xsl:for-each select="memory/summary/*">
+ <xsl:variable name="css-class13">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class13}">
+ <th>
+ <xsl:value-of select="name()"/>
+ </th>
+ <td>
+ <xsl:value-of select="."/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:if>
+ <xsl:if test="memory/contexts/context">
+ <h2>Memory Contexts</h2>
+ <table class="mctx">
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>References</th>
+ <th>TotalUse</th>
+ <th>InUse</th>
+ <th>MaxUse</th>
+ <th>BlockSize</th>
+ <th>Pools</th>
+ <th>HiWater</th>
+ <th>LoWater</th>
+ </tr>
+ <xsl:for-each select="memory/contexts/context">
+ <xsl:sort select="total" data-type="number" order="descending"/>
+ <xsl:variable name="css-class14">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">even</xsl:when>
+ <xsl:otherwise>odd</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <tr class="{$css-class14}">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="total"/>
+ </td>
+ <td>
+ <xsl:value-of select="inuse"/>
+ </td>
+ <td>
+ <xsl:value-of select="maxinuse"/>
+ </td>
+ <td>
+ <xsl:value-of select="blocksize"/>
+ </td>
+ <td>
+ <xsl:value-of select="pools"/>
+ </td>
+ <td>
+ <xsl:value-of select="hiwater"/>
+ </td>
+ <td>
+ <xsl:value-of select="lowater"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:if>
<hr/>
<p class="footer">Internet Systems Consortium Inc.<br/><a href="http://www.isc.org">http://www.isc.org</a></p>
</body>
static char xslmsg[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!--\n"
- " - Copyright (C) 2006-2009 Internet Systems Consortium, Inc. (\"ISC\")\n"
+ " - Copyright (C) 2012, 2013 Internet Systems Consortium, Inc. (\"ISC\")\n"
" -\n"
" - Permission to use, copy, modify, and/or distribute this software for any\n"
" - purpose with or without fee is hereby granted, provided that the above\n"
" - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n"
" - PERFORMANCE OF THIS SOFTWARE.\n"
"-->\n"
+ "\n"
+ "<!-- $Id$ -->\n"
+ "\n"
"<!-- \045Id: bind9.xsl,v 1.21 2009/01/27 23:47:54 tbox Exp \045 -->\n"
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns=\"http://www.w3.org/1999/xhtml\" version=\"1.0\">\n"
" <xsl:output method=\"html\" indent=\"yes\" version=\"4.0\"/>\n"
- " <xsl:template match=\"statistics[@version="3.0"]\">\n"
+ " <xsl:template match=\"statistics[@version="3.3"]\">\n"
" <html>\n"
" <head>\n"
" <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
" <!-- Non Mozilla specific markup -->\n"
" <script type=\"text/javascript\" src=\"https://www.google.com/jsapi\"/>\n"
" <script type=\"text/javascript\">\n"
- " \n"
+ "\n"
" google.load(\"visualization\", \"1\", {packages:[\"corechart\"]});\n"
" google.setOnLoadCallback(loadGraphs);\n"
"\n"
" var graphs=[];\n"
- " \n"
- " function drawChart(chart_title,target,data) {\n"
+ "\n"
+ " function drawChart(chart_title,target,style,data) {\n"
" var data = google.visualization.arrayToDataTable(data);\n"
"\n"
" var options = {\n"
" title: chart_title\n"
" };\n"
- " \n"
- " var chart = new google.visualization.BarChart(document.getElementById(target));\n"
+ "\n"
+ " var chart;\n"
+ " if (style == \"barchart\") {\n"
+ " chart = new google.visualization.BarChart(document.getElementById(target));\n"
+ " chart.draw(data, options);\n"
+ " } else if (style == \"piechart\") {\n"
+ " chart = new google.visualization.PieChart(document.getElementById(target));\n"
" chart.draw(data, options);\n"
" }\n"
- " \n"
+ " }\n"
+ "\n"
" function loadGraphs(){\n"
- " //alert(\"here we are!\");\n"
" var g;\n"
- " \n"
- " // Server Incoming query Types\n"
+ "\n"
" while(g = graphs.shift()){\n"
" // alert(\"going for: \" + g.target);\n"
" if(g.data.length > 1){\n"
- " drawChart(g.title,g.target,g.data);\n"
+ " drawChart(g.title,g.target,g.style,g.data);\n"
" }\n"
" }\n"
" }\n"
- " \n"
- " // Server Incoming Queries Types \n"
+ "\n"
+ " // Server Incoming Query Types \n"
" graphs.push({\n"
" 'title' : \"Server Incoming Query Types\",\n"
" 'target': 'chart_incoming_qtypes',\n"
+ " 'style': 'barchart',\n"
" 'data': [['Type','Counter'],<xsl:for-each select=\"server/counters[@type="qtype"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n"
" });\n"
"\n"
- "\n"
- " // Server Incoming Requests \n"
+ " // Server Incoming Requests by opcode\n"
" graphs.push({\n"
- " 'title' : \"Server Incoming Requests\",\n"
- " 'target': 'chart_incoming_requests',\n"
- " 'data': [['Requests','Counter'],<xsl:for-each select=\"server/counters[@type="opcode"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]});\n"
- " \n"
- " \n"
- " \n"
- " \n"
+ " 'title' : \"Server Incoming Requests by DNS Opcode\",\n"
+ " 'target': 'chart_incoming_opcodes',\n"
+ " 'style': 'barchart',\n"
+ " 'data': [['Opcode','Counter'],<xsl:for-each select=\"server/counters[@type="opcode"]/counter[. > 0 or substring(@name,1,3) != 'RES']\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]});\n"
" </script>\n"
" </xsl:if>\n"
" <style type=\"text/css\">\n"
" color: #000000;\n"
" font-size: 10pt;\n"
" }\n"
- " \n"
+ "\n"
" .odd{\n"
" background-color: #f0f0f0;\n"
" }\n"
- " \n"
+ "\n"
" .even{\n"
" background-color: #ffffff;\n"
" }\n"
- " \n"
+ "\n"
" p.footer{\n"
" font-style:italic;\n"
" color: grey;\n"
" border: 1px solid grey;\n"
" width: 500px;\n"
" }\n"
- " \n"
" table.counters th {\n"
- " text-align: center;\n"
+ " text-align: right;\n"
" border: 1px solid grey;\n"
- " width: 120px;\n"
+ " width: 150px;\n"
" }\n"
- " table.counters td{\n"
- " text-align:center;\n"
- " \n"
+ " table.counters td {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
" }\n"
- " \n"
" table.counters tr:hover{\n"
" background-color: #99ddff;\n"
" }\n"
- " \n"
+ "\n"
+ " table.info {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.info th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " width: 150px;\n"
+ " }\n"
+ " table.info td {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.info tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " table.tasks {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.tasks th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " width: 150px;\n"
+ " }\n"
+ " table.tasks td {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
+ " }\n"
+ " table.tasks td:nth-child(2) {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.tasks td:nth-child(4) {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.tasks tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " table.netstat {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.netstat th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " width: 150px;\n"
+ " }\n"
+ " table.netstat td {\n"
+ " text-align: center;\n"
+ " }\n"
+ " table.netstat td:nth-child(4) {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
+ " }\n"
+ " table.netstat td:nth-child(7) {\n"
+ " text-align: left;\n"
+ " }\n"
+ " table.netstat tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
+ " table.mctx {\n"
+ " border: 1px solid grey;\n"
+ " width: 500px;\n"
+ " }\n"
+ " table.mctx th {\n"
+ " text-align: center;\n"
+ " border: 1px solid grey;\n"
+ " }\n"
+ " table.mctx td {\n"
+ " text-align: right;\n"
+ " font-family: monospace;\n"
+ " }\n"
+ " table.mctx td:nth-child(-n+2) {\n"
+ " text-align: left;\n"
+ " width: 100px;\n"
+ " }\n"
+ " table.mctx tr:hover{\n"
+ " background-color: #99ddff;\n"
+ " }\n"
+ "\n"
" .totals {\n"
" background-color: rgb(1,169,206);\n"
" color: #ffffff;\n"
" width:500px;\n"
" text-align:center;\n"
" }\n"
- " \n"
+ "\n"
" h3 {\n"
" color: #444444;\n"
" font-size: 12pt;\n"
" width:500px;\n"
" text-align:center;\n"
- " \n"
" }\n"
" h4 {\n"
" color: rgb(1,169,206);\n"
" font-size: 10pt;\n"
" width:500px;\n"
" text-align:center;\n"
- " \n"
" }\n"
"\n"
" .pie {\n"
" </div>\n"
" <hr/>\n"
" <h2>Server Times</h2>\n"
- " <table class=\"counters\">\n"
+ " <table class=\"info\">\n"
" <tr>\n"
" <th>Boot time:</th>\n"
" <td>\n"
" </td>\n"
" </tr>\n"
" <tr>\n"
- " <th>Sample time:</th>\n"
+ " <th>Current time:</th>\n"
" <td>\n"
" <xsl:value-of select=\"server/current-time\"/>\n"
" </td>\n"
" </tr>\n"
" </table>\n"
" <br/>\n"
- " <h2>Incoming Requests</h2>\n"
+ " <xsl:if test=\"server/counters[@type="opcode"]/counter[. > 0]\">\n"
" <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <h2>Incoming Requests by DNS Opcode</h2>\n"
" <!-- Non Mozilla specific markup -->\n"
- " <div class=\"pie\" id=\"chart_incoming_requests\">[graph incoming requests]</div>\n"
+ " <div class=\"pie\" id=\"chart_incoming_opcodes\">\n"
+ " [cannot display chart]\n"
+ " </div>\n"
" </xsl:if>\n"
" <table class=\"counters\">\n"
- " <xsl:for-each select=\"server/counters[@type="opcode"]/counter\">\n"
+ " <xsl:for-each select=\"server/counters[@type="opcode"]/counter[. > 0 or substring(@name,1,3) != 'RES']\">\n"
" <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
" <tr>\n"
" <th>\n"
" </tr>\n"
" </table>\n"
" <br/>\n"
- " <h3>Incoming Queries by Type</h3>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type="qtype"]/counter\">\n"
" <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
" <!-- Non Mozilla specific markup -->\n"
- " <div class=\"pie\" id=\"chart_incoming_qtypes\">[graph incoming qtypes]</div>\n"
+ " <h3>Incoming Queries by Query Type</h3>\n"
+ " <div class=\"pie\" id=\"chart_incoming_qtypes\">\n"
+ " [cannot display chart]\n"
+ " </div>\n"
" </xsl:if>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"server/counters[@type="qtype"]/counter\">\n"
" </tr>\n"
" </table>\n"
" <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"views/view[count(counters[@type="resqtype"]/counter) > 0]\">\n"
" <h2>Outgoing Queries per view</h2>\n"
" <xsl:for-each select=\"views/view[count(counters[@type="resqtype"]/counter) > 0]\">\n"
" <h3>View <xsl:value-of select=\"@name\"/></h3>\n"
" <!-- Non Mozilla specific markup -->\n"
" <script type=\"text/javascript\">\n"
" graphs.push({\n"
- " 'title': \"Outgoing queries for view: <xsl:value-of select=\"@name\"/>\",\n"
+ " 'title': \"Outgoing Queries for view: <xsl:value-of select=\"@name\"/>\",\n"
" 'target': 'chart_outgoing_queries_view_<xsl:value-of select=\"@name\"/>',\n"
+ " 'style': 'barchart',\n"
" 'data': [['Type','Counter'],<xsl:for-each select=\"counters[@type="resqtype"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n"
" });\n"
- " \n"
" </script>\n"
" <xsl:variable name=\"target\">\n"
" <xsl:value-of select=\"@name\"/>\n"
" </xsl:variable>\n"
- " <div class=\"pie\" id=\"chart_outgoing_queries_view_{$target}\"/>\n"
+ " <div class=\"pie\" id=\"chart_outgoing_queries_view_{$target}\">[no data to display]</div>\n"
" </xsl:if>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"counters[@type="resqtype"]/counter\">\n"
" </table>\n"
" <br/>\n"
" </xsl:for-each>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type="nsstat"]/counter[.>0]\">\n"
" <h2>Server Statistics</h2>\n"
" <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
" <!-- Non Mozilla specific markup -->\n"
" <script type=\"text/javascript\">\n"
" graphs.push({\n"
- " 'title' : \"Server Response Types\",\n"
+ " 'title' : \"Server Counters\",\n"
" 'target': 'chart_server_nsstat_restype',\n"
+ " 'style': 'barchart',\n"
" 'data': [['Type','Counter'],<xsl:for-each select=\"server/counters[@type="nsstat"]/counter[.>0]\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n"
" });\n"
- " \n"
" </script>\n"
- " <div class=\"pie\" id=\"chart_server_nsstat_restype\"/>\n"
+ " <div class=\"pie\" id=\"chart_server_nsstat_restype\">[no data to display]</div>\n"
" </xsl:if>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"server/counters[@type="nsstat"]/counter[.>0]\">\n"
" </xsl:for-each>\n"
" </table>\n"
" <br/>\n"
- " <h2>Zone Maintenance Statistics</h2>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type="zonestat"]/counter[.>0]\">\n"
" <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n"
+ " <h2>Zone Maintenance Statistics</h2>\n"
" <script type=\"text/javascript\">\n"
" graphs.push({\n"
" 'title' : \"Zone Maintenance Stats\",\n"
" 'target': 'chart_server_zone_maint',\n"
- " 'data': [['Type','Counter'],<xsl:for-each select=\"server/counters[@type="zonestat"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n"
+ " 'style': 'barchart',\n"
+ " 'data': [['Type','Counter'],<xsl:for-each select=\"server/counters[@type="zonestat"]/counter[.>0]\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n"
" });\n"
- "\n"
" </script>\n"
" <!-- Non Mozilla specific markup -->\n"
- " <div class=\"pie\" id=\"chart_server_zone_maint\"/>\n"
+ " <div class=\"pie\" id=\"chart_server_zone_maint\">[no data to display]</div>\n"
" </xsl:if>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"server/counters[@type="zonestat"]/counter\">\n"
" </tr>\n"
" </xsl:for-each>\n"
" </table>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"server/counters[@type="resstat"]/counter[.>0]\">\n"
" <h2>Resolver Statistics (Common)</h2>\n"
" <table class=\"counters\">\n"
- " <xsl:for-each select=\"server/counters[@type="restat"]/counter\">\n"
+ " <xsl:for-each select=\"server/counters[@type="resstat"]/counter\">\n"
" <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n"
" <xsl:variable name=\"css-class4\">\n"
" <xsl:choose>\n"
" </tr>\n"
" </xsl:for-each>\n"
" </table>\n"
+ " </xsl:if>\n"
" <xsl:for-each select=\"views/view\">\n"
+ " <xsl:if test=\"counters[@type="resstats"]/counter[.>0]\">\n"
" <h3>Resolver Statistics for View <xsl:value-of select=\"@name\"/></h3>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"counters[@type="resstats"]/counter[.>0]\">\n"
" </tr>\n"
" </xsl:for-each>\n"
" </table>\n"
+ " </xsl:if>\n"
" </xsl:for-each>\n"
- " <h3>Cache DB RRsets for View <xsl:value-of select=\"@name\"/></h3>\n"
+ "\n"
" <xsl:for-each select=\"views/view\">\n"
+ " <xsl:if test=\"cache/rrset\">\n"
+ " <h3>Cache DB RRsets for View <xsl:value-of select=\"@name\"/></h3>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"cache/rrset\">\n"
" <xsl:variable name=\"css-class6\">\n"
" </xsl:for-each>\n"
" </table>\n"
" <br/>\n"
+ " </xsl:if>\n"
" </xsl:for-each>\n"
+ "\n"
+ " <xsl:if test=\"server/counters[@type="sockstat"]/counter[.>0]\">\n"
" <h2>Socket I/O Statistics</h2>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"server/counters[@type="sockstat"]/counter[.>0]\">\n"
" </xsl:for-each>\n"
" </table>\n"
" <br/>\n"
- " <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"views/view[zones/zone/counters[@type="rcode"]/counter >0]\">\n"
" <h2>Response Codes per view/zone</h2>\n"
" <xsl:for-each select=\"views/view[zones/zone/counters[@type="rcode"]/counter >0]\">\n"
" <h3>View <xsl:value-of select=\"@name\"/></h3>\n"
" graphs.push({\n"
" 'title': \"Response Codes for zone <xsl:value-of select=\"@name\"/>\",\n"
" 'target': 'chart_rescode_<xsl:value-of select=\"../../@name\"/>_<xsl:value-of select=\"@name\"/>',\n"
+ " 'style': 'barchart',\n"
" 'data': [['Type','Counter'],<xsl:for-each select=\"counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n"
" });\n"
"\n"
" <xsl:variable name=\"target\">\n"
" <xsl:value-of select=\"@name\"/>\n"
" </xsl:variable>\n"
- " <div class=\"pie\" id=\"chart_rescode_{$thisview}_{$target}\"/>\n"
+ " <div class=\"pie\" id=\"chart_rescode_{$thisview}_{$target}\">[no data to display]</div>\n"
" </xsl:if>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]\">\n"
" </xsl:if>\n"
" </xsl:for-each>\n"
" </xsl:for-each>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"views/view[zones/zone/counters[@type="qtype"]/counter >0]\">\n"
" <h2>Received QTYPES per view/zone</h2>\n"
" <xsl:for-each select=\"views/view[zones/zone/counters[@type="qtype"]/counter >0]\">\n"
" <h3>View <xsl:value-of select=\"@name\"/></h3>\n"
" graphs.push({\n"
" 'title': \"Query Types for zone <xsl:value-of select=\"@name\"/>\",\n"
" 'target': 'chart_qtype_<xsl:value-of select=\"../../@name\"/>_<xsl:value-of select=\"@name\"/>',\n"
+ " 'style': 'barchart',\n"
" 'data': [['Type','Counter'],<xsl:for-each select=\"counters[@type="qtype"]/counter[.>0 and @name != "QryAuthAns"]\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n"
" });\n"
"\n"
" <xsl:variable name=\"target\">\n"
" <xsl:value-of select=\"@name\"/>\n"
" </xsl:variable>\n"
- " <div class=\"pie\" id=\"chart_qtype_{$thisview2}_{$target}\"/>\n"
+ " <div class=\"pie\" id=\"chart_qtype_{$thisview2}_{$target}\">[no data to display]</div>\n"
" </xsl:if>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"counters[@type="qtype"]/counter\">\n"
" </xsl:if>\n"
" </xsl:for-each>\n"
" </xsl:for-each>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"socketmgr/sockets/socket\">\n"
" <h2>Network Status</h2>\n"
- " <table class=\"counters\">\n"
+ " <table class=\"netstat\">\n"
" <tr>\n"
" <th>ID</th>\n"
" <th>Name</th>\n"
" </xsl:for-each>\n"
" </table>\n"
" <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"taskmgr/thread-model/type\">\n"
" <h2>Task Manager Configuration</h2>\n"
" <table class=\"counters\">\n"
" <tr>\n"
" </tr>\n"
" </table>\n"
" <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"taskmgr/tasks/task\">\n"
" <h2>Tasks</h2>\n"
- " <table class=\"counters\">\n"
+ " <table class=\"tasks\">\n"
" <tr>\n"
" <th>ID</th>\n"
" <th>Name</th>\n"
" </xsl:for-each>\n"
" </table>\n"
" <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"memory/summary\">\n"
" <h2>Memory Usage Summary</h2>\n"
" <table class=\"counters\">\n"
" <xsl:for-each select=\"memory/summary/*\">\n"
" </xsl:for-each>\n"
" </table>\n"
" <br/>\n"
+ " </xsl:if>\n"
+ " <xsl:if test=\"memory/contexts/context\">\n"
" <h2>Memory Contexts</h2>\n"
- " <table class=\"counters\">\n"
+ " <table class=\"mctx\">\n"
" <tr>\n"
" <th>ID</th>\n"
" <th>Name</th>\n"
" </tr>\n"
" </xsl:for-each>\n"
" </table>\n"
+ " </xsl:if>\n"
" <hr/>\n"
" <p class=\"footer\">Internet Systems Consortium Inc.<br/><a href=\"http://www.isc.org\">http://www.isc.org</a></p>\n"
" </body>\n"
ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.ver3.xsl\""));
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
- ISC_XMLCHAR "3.0"));
+ ISC_XMLCHAR "3.3"));
/* Set common fields for statistics dump */
dumparg.type = statsformat_xml;
if (dumparg.result != ISC_R_SUCCESS)
goto error;
}
+else fprintf(stderr, "WTF WHERE'S RESQUERYRSTATS\n");
TRY0(xmlTextWriterEndElement(writer));
- /* <resstats> */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
ISC_XMLCHAR "resstats"));
if (result != ISC_R_SUCCESS)
goto error;
}
- TRY0(xmlTextWriterEndElement(writer)); /* </resstats> */
+ TRY0(xmlTextWriterEndElement(writer));
cacherrstats = dns_db_getrrsetstats(view->cachedb);
if (cacherrstats != NULL) {
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
ISC_XMLCHAR "opcode"));
- dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
- 0);
+ dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
+ ISC_STATSDUMP_VERBOSE);
if (dumparg.result != ISC_R_SUCCESS)
goto error;
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server"));
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time"));
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime));
- TRY0(xmlTextWriterEndElement(writer));
+ TRY0(xmlTextWriterEndElement(writer)); /* boot-time */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time"));
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr));
- TRY0(xmlTextWriterEndElement(writer));
+ TRY0(xmlTextWriterEndElement(writer)); /* current-time */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "requests"));
dumparg.result = ISC_R_SUCCESS;
}
static isc_result_t
-render_index(const char *url, const char *querystring, void *arg,
+render_index(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
unsigned int *retcode, const char **retmsg, const char **mimetype,
isc_buffer_t *b, isc_httpdfree_t **freecb,
void **freecb_args)
isc_result_t result;
UNUSED(url);
+ UNUSED(urlinfo);
UNUSED(querystring);
+ UNUSED(headers);
result = generatexml(server, &msglen, &msg);
#endif /* HAVE_LIBXML2 */
static isc_result_t
-render_xsl(const char *url, const char *querystring, void *args,
- unsigned int *retcode, const char **retmsg, const char **mimetype,
- isc_buffer_t *b, isc_httpdfree_t **freecb,
- void **freecb_args)
+render_xsl(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers,
+ void *args, unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
{
+ isc_result_t result;
+
UNUSED(url);
UNUSED(querystring);
UNUSED(args);
+ *freecb = NULL;
+ *freecb_args = NULL;
+ *mimetype = "text/xslt+xml";
+
+ if (urlinfo->isstatic) {
+ isc_time_t when;
+ char *p = strcasestr(headers, "If-Modified-Since: ");
+
+ if (p != NULL) {
+ time_t t1, t2;
+ p += strlen("If-Modified-Since: ");
+ result = isc_time_parsehttptimestamp(p, &when);
+ if (result != ISC_R_SUCCESS)
+ goto send;
+
+ result = isc_time_secondsastimet(&when, &t1);
+ if (result != ISC_R_SUCCESS)
+ goto send;
+
+ result = isc_time_secondsastimet(&urlinfo->loadtime,
+ &t2);
+ if (result != ISC_R_SUCCESS)
+ goto send;
+
+ if (t1 < t2)
+ goto send;
+
+ *retcode = 304;
+ *retmsg = "Not modified";
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ send:
*retcode = 200;
*retmsg = "OK";
- *mimetype = "text/xslt+xml";
isc_buffer_reinit(b, xslmsg, strlen(xslmsg));
isc_buffer_add(b, strlen(xslmsg));
- *freecb = NULL;
- *freecb_args = NULL;
return (ISC_R_SUCCESS);
}
#include <isc/socket.h>
#include <isc/string.h>
#include <isc/task.h>
+#include <isc/time.h>
#include <isc/util.h>
#include <string.h>
#define HTTP_SENDGROW 1024
#define HTTP_SEND_MAXLEN 10240
-/*%
- * HTTP urls. These are the URLs we manage, and the function to call to
- * provide the data for it. We pass in the base url (so the same function
- * can handle multiple requests), and a structure to fill in to return a
- * result to the client. We also pass in a pointer to be filled in for
- * the data cleanup function.
- */
-struct isc_httpdurl {
- char *url;
- isc_httpdaction_t *action;
- void *action_arg;
- ISC_LINK(isc_httpdurl_t) link;
-};
-
#define HTTPD_CLOSE 0x0001 /* Got a Connection: close header */
#define HTTPD_FOUNDHOST 0x0002 /* Got a Host: header */
*/
char recvbuf[HTTP_RECVLEN]; /*%< receive buffer */
isc_uint32_t recvlen; /*%< length recv'd */
+ char *headers; /*%< set in process_request() */
unsigned int method;
char *url;
char *querystring;
static void httpdmgr_destroy(isc_httpdmgr_t *);
static isc_result_t grow_headerspace(isc_httpd_t *);
static void reset_client(isc_httpd_t *httpd);
-static isc_result_t render_404(const char *, const char *,
- void *,
- unsigned int *, const char **,
- const char **, isc_buffer_t *,
- isc_httpdfree_t **, void **);
-static isc_result_t render_500(const char *, const char *,
- void *,
- unsigned int *, const char **,
- const char **, isc_buffer_t *,
- isc_httpdfree_t **, void **);
+
+static isc_httpdaction_t render_404;
+static isc_httpdaction_t render_500;
static void
-destroy_client(isc_httpd_t **httpdp)
-{
+destroy_client(isc_httpd_t **httpdp) {
isc_httpd_t *httpd = *httpdp;
isc_httpdmgr_t *httpdmgr = httpd->mgr;
}
static void
-httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
-{
+httpdmgr_destroy(isc_httpdmgr_t *httpdmgr) {
isc_mem_t *mctx;
isc_httpdurl_t *url;
#define BUFLENOK(s) (httpd->recvbuf - (s) < HTTP_RECVLEN)
static isc_result_t
-process_request(isc_httpd_t *httpd, int length)
-{
+process_request(isc_httpd_t *httpd, int length) {
char *s;
char *p;
int delim;
httpd->recvlen += length;
httpd->recvbuf[httpd->recvlen] = 0;
+ httpd->headers = NULL;
/*
* If we don't find a blank line in our buffer, return that we need
p = s + 1;
s = p;
+ httpd->headers = s;
+
if (strstr(s, "Connection: close") != NULL)
httpd->flags |= HTTPD_CLOSE;
}
static void
-isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
-{
+isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
isc_result_t result;
isc_httpdmgr_t *httpdmgr = ev->ev_arg;
isc_httpd_t *httpd;
}
static isc_result_t
-render_404(const char *url, const char *querystring,
- void *arg,
+render_404(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
unsigned int *retcode, const char **retmsg,
const char **mimetype, isc_buffer_t *b,
isc_httpdfree_t **freecb, void **freecb_args)
static char msg[] = "No such URL.";
UNUSED(url);
+ UNUSED(urlinfo);
UNUSED(querystring);
+ UNUSED(headers);
UNUSED(arg);
*retcode = 404;
}
static isc_result_t
-render_500(const char *url, const char *querystring,
- void *arg,
+render_500(const char *url, isc_httpdurl_t *urlinfo,
+ const char *querystring, const char *headers, void *arg,
unsigned int *retcode, const char **retmsg,
const char **mimetype, isc_buffer_t *b,
isc_httpdfree_t **freecb, void **freecb_args)
static char msg[] = "Internal server failure.";
UNUSED(url);
+ UNUSED(urlinfo);
UNUSED(querystring);
+ UNUSED(headers);
UNUSED(arg);
*retcode = 500;
}
static void
-isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
-{
+isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
isc_region_t r;
isc_result_t result;
isc_httpd_t *httpd = ev->ev_arg;
url = ISC_LIST_NEXT(url, link);
}
if (url == NULL)
- result = httpd->mgr->render_404(httpd->url, httpd->querystring,
- NULL,
+ result = httpd->mgr->render_404(httpd->url, NULL,
+ httpd->querystring,
+ NULL, NULL,
&httpd->retcode,
&httpd->retmsg,
&httpd->mimetype,
&httpd->freecb,
&httpd->freecb_arg);
else
- result = url->action(httpd->url, httpd->querystring,
+ result = url->action(httpd->url, url,
+ httpd->querystring,
+ httpd->headers,
url->action_arg,
&httpd->retcode, &httpd->retmsg,
&httpd->mimetype, &httpd->bodybuffer,
&httpd->freecb, &httpd->freecb_arg);
if (result != ISC_R_SUCCESS) {
- result = httpd->mgr->render_500(httpd->url, httpd->querystring,
- NULL, &httpd->retcode,
+ result = httpd->mgr->render_500(httpd->url, url,
+ httpd->querystring,
+ NULL, NULL,
+ &httpd->retcode,
&httpd->retmsg,
&httpd->mimetype,
&httpd->bodybuffer,
isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
isc_httpd_addheader(httpd, "Date", datebuf);
isc_httpd_addheader(httpd, "Expires", datebuf);
- isc_httpd_addheader(httpd, "Last-Modified", datebuf);
- isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
- isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
+
+ if (url != NULL && url->isstatic) {
+ char loadbuf[32];
+ isc_time_formathttptimestamp(&url->loadtime,
+ loadbuf, sizeof(loadbuf));
+ isc_httpd_addheader(httpd, "Last-Modified", loadbuf);
+ isc_httpd_addheader(httpd, "Cache-Control: public", NULL);
+ } else {
+ isc_httpd_addheader(httpd, "Last-Modified", datebuf);
+ isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
+ isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
+ }
+
isc_httpd_addheader(httpd, "Server: libisc", NULL);
isc_httpd_addheaderuint(httpd, "Content-Length",
isc_buffer_usedlength(&httpd->bodybuffer));
}
void
-isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp)
-{
+isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) {
isc_httpdmgr_t *httpdmgr;
isc_httpd_t *httpd;
httpdmgr = *httpdmgrp;
}
static isc_result_t
-grow_headerspace(isc_httpd_t *httpd)
-{
+grow_headerspace(isc_httpd_t *httpd) {
char *newspace;
unsigned int newlen;
isc_region_t r;
}
isc_result_t
-isc_httpd_response(isc_httpd_t *httpd)
-{
+isc_httpd_response(isc_httpd_t *httpd) {
isc_result_t result;
unsigned int needlen;
}
isc_result_t
-isc_httpd_endheaders(isc_httpd_t *httpd)
-{
+isc_httpd_endheaders(isc_httpd_t *httpd) {
isc_result_t result;
while (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
}
static void
-isc_httpd_senddone(isc_task_t *task, isc_event_t *ev)
-{
+isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
isc_httpd_t *httpd = ev->ev_arg;
isc_region_t r;
isc_socketevent_t *sev = (isc_socketevent_t *)ev;
}
static void
-reset_client(isc_httpd_t *httpd)
-{
+reset_client(isc_httpd_t *httpd) {
/*
* Catch errors here. We MUST be in RECV mode, and we MUST NOT have
* any outstanding buffers. If we have buffers, we have a leak.
httpd->recvbuf[0] = 0;
httpd->recvlen = 0;
+ httpd->headers = NULL;
httpd->method = ISC_HTTPD_METHODUNKNOWN;
httpd->url = NULL;
httpd->querystring = NULL;
isc_result_t
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
isc_httpdaction_t *func, void *arg)
+{
+ return (isc_httpdmgr_addurl2(httpdmgr, url, ISC_FALSE, func, arg));
+}
+
+isc_result_t
+isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
+ isc_boolean_t isstatic,
+ isc_httpdaction_t *func, void *arg)
{
isc_httpdurl_t *item;
item->action = func;
item->action_arg = arg;
+ item->isstatic = isstatic;
+ isc_time_now(&item->loadtime);
+
ISC_LINK_INIT(item, link);
ISC_LIST_APPEND(httpdmgr->urls, item, link);
#include <isc/types.h>
#include <isc/mutex.h>
#include <isc/task.h>
+#include <isc/time.h>
+
+/*%
+ * HTTP urls. These are the URLs we manage, and the function to call to
+ * provide the data for it. We pass in the base url (so the same function
+ * can handle multiple requests), and a structure to fill in to return a
+ * result to the client. We also pass in a pointer to be filled in for
+ * the data cleanup function.
+ */
+struct isc_httpdurl {
+ char *url;
+ isc_httpdaction_t *action;
+ void *action_arg;
+ isc_boolean_t isstatic;
+ isc_time_t loadtime;
+ ISC_LINK(isc_httpdurl_t) link;
+};
#define HTTPD_EVENTCLASS ISC_EVENTCLASS(4300)
#define HTTPD_SHUTDOWN (HTTPD_EVENTCLASS + 0x0001)
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
isc_httpdaction_t *func, void *arg);
+isc_result_t
+isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
+ isc_boolean_t isstatic,
+ isc_httpdaction_t *func, void *arg);
+
isc_result_t
isc_httpd_response(isc_httpd_t *httpd);
/* The following cannot be listed alphabetically due to forward reference */
typedef isc_result_t (isc_httpdaction_t)(const char *url,
+ isc_httpdurl_t *urlinfo,
const char *querystring,
+ const char *headers,
void *arg,
unsigned int *retcode,
const char **retmsg,
*
*/
+isc_result_t
+isc_time_parsehttptimestamp(char *input, isc_time_t *t);
+/*%<
+ * Parse the time in 'input' into the isc_time_t pointed to by 't',
+ * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ *
+ * Requires:
+ *\li 'buf' and 't' are not NULL.
+ */
+
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
/*%<
INSIST(flen < len);
}
+isc_result_t
+isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
+ struct tm t_tm;
+ time_t when;
+ char *p;
+
+ REQUIRE(buf != NULL);
+ REQUIRE(t != NULL);
+ p = strptime(buf, "%a, %d %b %Y %H:%M:%S %Z", &t_tm);
+ if (p == NULL)
+ return (ISC_R_UNEXPECTED);
+ when = timegm(&t_tm);
+ if (when == -1)
+ return (ISC_R_UNEXPECTED);
+ isc_time_set(t, when, 0);
+ return (ISC_R_SUCCESS);
+}
+
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;