Update of /cvsroot/freenet/freenet/src/freenet/node/http/infolets In directory sc8-pr-cvs1:/tmp/cvs-serv4015/freenet/src/freenet/node/http/infolets
Modified Files: GeneralInfolet.java Log Message: Version.java 6284 Fix bug in LoadStats.java decayingTimeWeightedAverage. Put this node's average into the global pool, which is checkpointed. Initialize the average from the saved value. Change default half life to 1.2 hours. Other nodes don't receive updates much more frequently that that. Change mode lines from "tabwidth: 4" to "indent-tabs-mode: nil" since some developers don't use emacs so it is best to use no tabs at all in the text. (Their Java IDE must also wrap long lines in a legible manner, since they seem to regard long lines as more legible than manually wrapped and indented lines). Add configuration parameter tfTolerableQueueDelay to YThreadFactory, default 100ms. Core.java Mode line. Remove tabs. Add tfTolerableQueueDelay configurable parameter. NodeStatusServlet.java Mode line. Remove tabs. Print the "why" data from estimatedLoad, rejectingConnections, and rejectingRequests. Change "Active pooled jobs" to "Pooled threads running jobs" Change "Available threads" to "Pooled threads which are idle" Use NumberFormat instead of ad-hoc code. LoadStats.java Improve display of global stats: show which were rejected as outliers or as too old. Make the text only dump give same info as html dump. Carefully check the locking in LoadStats.java. In the first cut, putting localQueryTraffic into the checkpointed pool added a lock in a path that didn't have one before. Make all constant class members final. Eliminate volatile. JLS 2nd ed. gives useful semantics for volatile, but who knows if all JVM's do it right? Some old one's didn't. This code doesn't run often enough for the slight speed improvement (over synchronize) to matter. logDEBUG, logMINOR (LoadStats constructor) add myRef. Initialize local queries per hour from this node's entry in the global queries per hour. (receivedQuery) Do not call localQueryTraffic(), which can block on a synchronize and which does unnecessary stuff. Just grab the data and run queriesPerHour.average whenever timesPos wraps. (storeTraffic) move code which cannot get IOException out of the try/catch block. Remove the once in a lifetime call to checkpoint() since checkpoint() now calls storeTraffic() and hence we might already be inside checkpoint(). The checkpoint will be done soon enough (10 minutes). (QueryTrafficInfo) Name changed from LocalQueryTrafficInfo. Save the local queries per hour into the global queries per hour checkpointed list. Remove special case for early period when there is not much data, since the average localQueryTraffic starts from a saved value. Move the statistics calculations from checkpoint() into this class, so that the web page can show more information about those calculations. (localQueryTraffic) Remove special case for early period when there is not much data, since the average localQueryTraffic starts from a saved value. Never return a value less than 1.0. Avoids testing for divide by zero elsewhere. (DecayingTimeWeightedAverage) Fix a really stupid bug. Essentially, I had 1-(1/2)^(hl/dt) instead of (1/2)^(dt/hl). It was right at hl=dt, and at dt=0 (since (1/2)^oo = 0). But at dt < 0.2 hl, it gave no weight to the new data. Add initial value arg to constructor. Clean up the comments. (globalQueryTraffic) make synchronized since class member globalQueryTraffic is no longer marked volatile. (shouldReset) reference resetProbability() rather than the class member since class member is no longer volatile. Other cosmetic changes, use logMINOR to avoid logging call if unnecessary. (nextCheckpoing) make synchronized. lastCheckpoint is not volatile. (checkpoint) Move the statistics calculations to QueryTrafficInfo inner class constructor. Logging. lastCheckpoint reference must be synchronized. QueryTrafficInfo calls storeTraffic() to save the localQueryTraffic value into the checkpoint file, so storeTraffic() can't call checkpoint(). (dump) Print mostly the same data as dumpHtml. Use QueryTrafficInfo to get the values. (dumpHtml) Use QueryTrafficInfo. Include information about which samples were too old, too small, or too big. (LoadEntry inner class) Make all members final. Main.java Mode line, indenting. (main) Copy tfTolerableQueueDelay parameter into Node. Pass myRef to LoadStats constructor (startNode) Pass tfTolerableQueueDelay to YThreadFactory. Node.java Mode line. indenting. Add java.text.NumberFormat. Check numbers from diagnostics for isNaN. (static) Initialize NumberFormats. Change default lsHalfLifeHours to 1.2 so localQueryTraffic value does full decay in 12 hours. Reword some of the parameter descriptions and correct some errors. (rejectingConnections) Add an optional StringBuffer argument, which if non-null gets filled with details about why we are rejecting connections. (rejectingRequests) same thing. (estimatedLoad) same thing. Why the load is what it is. GeneralInfolet.java Mode line. Remove tabs. Print the "why" data from estimatedLoad, rejectingConnections, and rejectingRequests. Change "Active pooled jobs" to "Pooled threads running jobs" Change "Available threads" to "Pooled threads which are idle" Use NumberFormat instead of ad-hoc code. FNPFeedbackToken.java (storeData) Round the average before cast to long. YThreadFactory.java Add tfTolerableQueueDelay configurable parameter. Index: GeneralInfolet.java =================================================================== RCS file: /cvsroot/freenet/freenet/src/freenet/node/http/infolets/GeneralInfolet.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -w -r1.22 -r1.23 --- GeneralInfolet.java 24 Oct 2003 19:38:19 -0000 1.22 +++ GeneralInfolet.java 28 Oct 2003 05:10:00 -0000 1.23 @@ -1,3 +1,4 @@ +/* -*- Mode: java; c-basic-indent: 4; indent-tabs-mode: nil -*- */ package freenet.node.http.infolets; import freenet.node.http.*; import freenet.node.Node; @@ -7,6 +8,7 @@ import freenet.support.servlet.*; import freenet.Core; import java.io.PrintWriter; +import java.text.NumberFormat; /** * This is the Infolet which is displayed by default @@ -17,13 +19,40 @@ public class GeneralInfolet extends Infolet { private Node node; + private static final NumberFormat nfp; + private static final NumberFormat nf0; + private static final NumberFormat nf1; + private static final NumberFormat nf03; + private static final NumberFormat nf3; + static { + nfp = NumberFormat.getPercentInstance(); + nfp.setMinimumFractionDigits(0); + nfp.setMaximumFractionDigits(1); + nf0 = NumberFormat.getInstance(); + nf0.setMinimumFractionDigits(0); + nf0.setMaximumFractionDigits(0); + nf0.setGroupingUsed(false); + nf1 = NumberFormat.getInstance(); + nf1.setMaximumFractionDigits(1); + nf1.setMinimumFractionDigits(1); + nf1.setGroupingUsed(false); + nf03 = NumberFormat.getInstance(); + nf03.setMinimumFractionDigits(0); + nf03.setMaximumFractionDigits(3); + nf03.setGroupingUsed(false); + nf3 = NumberFormat.getInstance(); + nf3.setMaximumFractionDigits(3); + nf3.setMinimumFractionDigits(3); + nf3.setGroupingUsed(false); + } + HtmlTemplate titleBoxTemplate; /** - * Description of the Method + * Return long name of the infolet * - * @return Description of the Return Value + * @return String longName */ public String longName() { return "General Information"; @@ -31,9 +60,9 @@ /** - * Description of the Method + * Return short name of infolet * - * @return Description of the Return Value + * @return String shortName */ public String shortName() { return "general"; @@ -41,9 +70,9 @@ /** - * Description of the Method + * Initialize the node reference and create the title Box template * - * @param n Description of the Parameter + * @param n The Node object this page describes. */ public void init(Node n) { try { @@ -55,6 +84,11 @@ } + /** + * Create the General Information web page + * + * @param pw The PrintWriter where the page gets written. + */ public void toHtml(PrintWriter pw) { StringBuffer sb = new StringBuffer(500); sb.append("From here you can view information about what is going "); @@ -81,7 +115,7 @@ titleBoxTemplate.toHtml(pw); StringBuffer uptime = new StringBuffer(); - long deltat = (System.currentTimeMillis() - Node.startupTimeMs) / 1000; + long deltat = (System.currentTimeMillis() - Node.startupTimeMs + 500) / 1000; if (deltat < 60) { uptime.append(" < 1 minute "); @@ -127,11 +161,14 @@ // Thread load int jobs = node.activeJobs(); int available = node.availableThreads(); - float f = node.estimatedLoad(); + StringBuffer whyLoad = new StringBuffer(500); + float f = node.estimatedLoad(whyLoad); // It's not just thread based. There's also a hard // rate limit. - boolean rejectingRequests = node.rejectingRequests(); - boolean rejectingConnections = node.rejectingConnections(); + StringBuffer whyRejectingRequests = new StringBuffer(500); + boolean rejectingRequests = node.rejectingRequests(whyRejectingRequests); + StringBuffer whyRejectingConnections = new StringBuffer(500); + boolean rejectingConnections = node.rejectingConnections(whyRejectingConnections); String color = "black"; String comment = ""; @@ -149,12 +186,11 @@ int maximumThreads = node.getThreadFactory().maximumThreads(); if (maximumThreads > 0) { - float threadPoolLoad = (((float) jobs) / maximumThreads) * 100.0f; - msg += " (" + Float.toString(threadPoolLoad) + "%)"; + msg += " (" + nfp.format( ((float) jobs) / maximumThreads ) + ")"; } - sb.append("<tr><td nowrap>Active pooled jobs</td><td>" + msg + "</td></tr>"); - sb.append("<tr><td nowrap>Available threads</td><td>" + available + "</td></tr>"); + sb.append("<tr><td nowrap>Pooled threads running jobs</td><td>" + msg + "</td></tr>"); + sb.append("<tr><td nowrap>Pooled threads which are idle</td><td>" + available + "</td></tr>"); LimitCounter outboundRequestLimit = node.outboundRequestLimit; if(outboundRequestLimit != null) sb.append("<tr><td nowrap>Outbound request quota used</td><td>" + @@ -166,12 +202,20 @@ Diagnostics.MINUTE, Diagnostics.COUNT_CHANGE) / 60; - int limit = (int)(node.outputBandwidthLimit - /* * Node.lowLevelBWLimitFudgeFactor*/); - sb.append("<tr><td nowrap>Current upstream bandwidth usage</td><td>" + (int)sent+ - " bytes/second ("+(int)((float)(100*sent) / (float)limit)+"%)</td></tr>"); + double limit = node.outputBandwidthLimit; + sb.append("<tr><td nowrap>Current upstream bandwidth usage</td><td>" + nf0.format(sent) + + " bytes/second (" + nfp.format(sent / limit) + ")</td></tr>"); + } + if (rejectingConnections) { + sb.append("<tr><td>Reason for refusing connections:</td><td>"); + sb.append(whyRejectingConnections); + sb.append("</td></tr>"); + } + if (rejectingRequests) { + sb.append("<tr><td>Reason for QueryRejecting requests:</td><td>"); + sb.append(whyRejectingRequests); + sb.append("</td></tr>"); } - if (rejectingConnections || rejectingRequests) { sb.append("<tr><td></td><td>"); sb.append("It's normal for the node to sometimes reject connections or requests "); @@ -184,8 +228,8 @@ comment = " <font color=\"" + color + "\">" + comment + "</font><br>"; } - int x = (int)(f * 1000); - sb.append(msg + (x/10) + "." + x%10 + "%"+comment+"</td></tr>"); + sb.append(msg + nfp.format(f) + comment + "</td></tr>"); + sb.append("<tr><td>Reason for load:</td><td>" + whyLoad.toString() + "</td></tr>"); sb.append("</table>"); titleBoxTemplate.set("TITLE", "Load"); titleBoxTemplate.set("CONTENT", sb.toString()); _______________________________________________ cvs mailing list [EMAIL PROTECTED] http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs