[freenet-cvs] r12576 - trunk/freenet/src/freenet/clients/http

toad at freenetproject.org toad at freenetproject.org
Wed Apr 11 13:51:02 UTC 2007


Author: toad
Date: 2007-04-11 13:51:02 +0000 (Wed, 11 Apr 2007)
New Revision: 12576

Modified:
   trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
Log:
Refactor into subroutines for easier maintenance (shorter diffs!), make some stuff static

Modified: trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java	2007-04-11 13:30:58 UTC (rev 12575)
+++ trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java	2007-04-11 13:51:02 UTC (rev 12576)
@@ -30,7 +30,9 @@
 
 public class StatisticsToadlet extends Toadlet {
 
-	public class MyComparator implements Comparator {
+	static final NumberFormat thousendPoint = NumberFormat.getInstance();
+	
+	static class MyComparator implements Comparator {
 
 		public int compare(Object arg0, Object arg1) {
 			Object[] row0 = (Object[])arg0;
@@ -139,7 +141,6 @@
 		// FIXME! We need some nice images
 		final long now = System.currentTimeMillis();
 		final long nodeUptimeSeconds = (now - node.startupTime) / 1000;
-		final NumberFormat thousendPoint = NumberFormat.getInstance();
 
 		if(ctx.isAllowedFullAccess())
 			contentNode.addChild(core.alerts.createSummary());
@@ -153,44 +154,14 @@
 
 		// node version information box
 		HTMLNode versionInfobox = nextTableCell.addChild("div", "class", "infobox");
-		versionInfobox.addChild("div", "class", "infobox-header", "Node Version Information");
-		HTMLNode versionInfoboxContent = versionInfobox.addChild("div", "class", "infobox-content");
-		HTMLNode versionInfoboxList = versionInfoboxContent.addChild("ul");
-		versionInfoboxList.addChild("li", "Freenet " + Version.nodeVersion + " Build #" + Version.buildNumber() + " r" + Version.cvsRevision);
-		if(NodeStarter.extBuildNumber < NodeStarter.RECOMMENDED_EXT_BUILD_NUMBER)
-			versionInfoboxList.addChild("li", "Freenet-ext Build #" + NodeStarter.extBuildNumber + '(' + NodeStarter.RECOMMENDED_EXT_BUILD_NUMBER + ") r" + NodeStarter.extRevisionNumber);
-		else
-			versionInfoboxList.addChild("li", "Freenet-ext Build #" + NodeStarter.extBuildNumber + " r" + NodeStarter.extRevisionNumber);
-
+		
+		drawNodeVersionBox(versionInfobox);
+		
 		// jvm stats box
 		HTMLNode jvmStatsInfobox = nextTableCell.addChild("div", "class", "infobox");
-		jvmStatsInfobox.addChild("div", "class", "infobox-header", "JVM info");
-		HTMLNode jvmStatsInfoboxContent = jvmStatsInfobox.addChild("div", "class", "infobox-content");
-		HTMLNode jvmStatsList = jvmStatsInfoboxContent.addChild("ul");
-
-		Runtime rt = Runtime.getRuntime();
-		float freeMemory = (float) rt.freeMemory();
-		float totalMemory = (float) rt.totalMemory();
-		float maxMemory = (float) rt.maxMemory();
-
-		long usedJavaMem = (long)(totalMemory - freeMemory);
-		long allocatedJavaMem = (long)totalMemory;
-		long maxJavaMem = (long)maxMemory;
-		int availableCpus = rt.availableProcessors();
-
-		int threadCount = stats.getActiveThreadCount();
-
-		jvmStatsList.addChild("li", "Used Java memory:\u00a0" + SizeUtil.formatSize(usedJavaMem, true));
-		jvmStatsList.addChild("li", "Allocated Java memory:\u00a0" + SizeUtil.formatSize(allocatedJavaMem, true));
-		jvmStatsList.addChild("li", "Maximum Java memory:\u00a0" + SizeUtil.formatSize(maxJavaMem, true));
-		jvmStatsList.addChild("li", "Running threads:\u00a0" + thousendPoint.format(threadCount) + '/' + stats.getThreadLimit());
-		jvmStatsList.addChild("li", "Available CPUs:\u00a0" + availableCpus);
-		jvmStatsList.addChild("li", "JVM Vendor:\u00a0" + System.getProperty("java.vm.vendor"));
-		jvmStatsList.addChild("li", "JVM Version:\u00a0" + System.getProperty("java.vm.version"));
-		jvmStatsList.addChild("li", "OS Name:\u00a0" + System.getProperty("os.name"));
-		jvmStatsList.addChild("li", "OS Version:\u00a0" + System.getProperty("os.version"));
-		jvmStatsList.addChild("li", "OS Architecture:\u00a0" + System.getProperty("os.arch"));
-
+		
+		drawJVMStatsBox(jvmStatsInfobox);
+		
 		// Statistic gathering box
 		HTMLNode statGatheringBox =  nextTableCell.addChild(ctx.getPageMaker().getInfobox("Statistic gathering"));
 		// Generate a Thread-Dump
@@ -209,65 +180,9 @@
 		if(advancedModeEnabled) {
 			// store size box
 			HTMLNode storeSizeInfobox = nextTableCell.addChild("div", "class", "infobox");
-			storeSizeInfobox.addChild("div", "class", "infobox-header", "Store size");
-			HTMLNode storeSizeInfoboxContent = storeSizeInfobox.addChild("div", "class", "infobox-content");
-			HTMLNode storeSizeList = storeSizeInfoboxContent.addChild("ul");
-
-			final long fix32kb = 32 * 1024;
-
-			long cachedKeys = node.getChkDatacache().keyCount();
-			long cachedSize = cachedKeys * fix32kb;
-			long storeKeys = node.getChkDatastore().keyCount();
-			long storeSize = storeKeys * fix32kb;
-			long overallKeys = cachedKeys + storeKeys;
-			long overallSize = cachedSize + storeSize;
-
-//			long maxCachedKeys = node.getChkDatacache().getMaxKeys();
-//			long maxStoreKeys = node.getChkDatastore().getMaxKeys();
-			long maxOverallKeys = node.getMaxTotalKeys();
-			long maxOverallSize = maxOverallKeys * fix32kb;
-
-			long cachedStoreHits = node.getChkDatacache().hits();
-			long cachedStoreMisses = node.getChkDatacache().misses();
-			long cacheAccesses = cachedStoreHits + cachedStoreMisses;
-			long storeHits = node.getChkDatastore().hits();
-			long storeMisses = node.getChkDatastore().misses();
-			long storeAccesses = storeHits + storeMisses;
-			long overallAccesses = storeAccesses + cacheAccesses;
-
-			// REDFLAG Don't show database version because it's not possible to get it accurately.
-			// (It's a public static constant, so it will use the version from compile time of freenet.jar)
-
-			storeSizeList.addChild("li", 
-					"Cached keys:\u00a0" + thousendPoint.format(cachedKeys) + 
-					" (" + SizeUtil.formatSize(cachedSize, true) + ')');
-
-			storeSizeList.addChild("li", 
-					"Stored keys:\u00a0" + thousendPoint.format(storeKeys) + 
-					" (" + SizeUtil.formatSize(storeSize, true) + ')');
-
-			storeSizeList.addChild("li", 
-					"Overall size:\u00a0" + thousendPoint.format(overallKeys) + 
-					"\u00a0/\u00a0" + thousendPoint.format(maxOverallKeys) +
-					" (" + SizeUtil.formatSize(overallSize, true) + 
-					"\u00a0/\u00a0" + SizeUtil.formatSize(maxOverallSize, true) + 
-					")\u00a0(" + ((overallKeys*100)/maxOverallKeys) + "%)");
-
-			if(cacheAccesses > 0)
-				storeSizeList.addChild("li", 
-						"Cache hits:\u00a0" + thousendPoint.format(cachedStoreHits) + 
-						"\u00a0/\u00a0"+thousendPoint.format(cacheAccesses) +
-						"\u00a0(" + ((cachedStoreHits*100) / (cacheAccesses)) + "%)");
-
-			if(storeAccesses > 0)
-				storeSizeList.addChild("li", 
-						"Store hits:\u00a0" + thousendPoint.format(storeHits) + 
-						"\u00a0/\u00a0"+thousendPoint.format(storeAccesses) +
-						"\u00a0(" + ((storeHits*100) / (storeAccesses)) + "%)");
-
-			storeSizeList.addChild("li", 
-					"Avg. access rate:\u00a0" + thousendPoint.format(overallAccesses/nodeUptimeSeconds) + "/s");
-
+			
+			drawStoreSizeBox(storeSizeInfobox, nodeUptimeSeconds);
+			
 			if(numberOfConnected + numberOfRoutingBackedOff > 0) {
 				// Load balancing box
 				// Include overall window, and RTTs for each
@@ -297,169 +212,30 @@
 		}
 
 		if(numberOfConnected + numberOfRoutingBackedOff > 0) {			
-			/* node status values */
-			int bwlimitDelayTime = (int) stats.getBwlimitDelayTime();
-			int nodeAveragePingTime = (int) stats.getNodeAveragePingTime();
-			int networkSizeEstimateSession = stats.getNetworkSizeEstimate(-1);
-			int networkSizeEstimate24h = 0;
-			int networkSizeEstimate48h = 0;
-			double numberOfRemotePeerLocationsSeenInSwaps = (double)node.getNumberOfRemotePeerLocationsSeenInSwaps();
 
-			if(nodeUptimeSeconds > (24*60*60)) {  // 24 hours
-				networkSizeEstimate24h = stats.getNetworkSizeEstimate(now - (24*60*60*1000));  // 48 hours
-			}
-			if(nodeUptimeSeconds > (48*60*60)) {  // 48 hours
-				networkSizeEstimate48h = stats.getNetworkSizeEstimate(now - (48*60*60*1000));  // 48 hours
-			}
-			double routingMissDistance =  stats.routingMissDistance.currentValue();
-			double backedOffPercent =  stats.backedOffPercent.currentValue();
-			String nodeUptimeString = TimeUtil.formatTime(nodeUptimeSeconds * 1000);  // *1000 to convert to milliseconds
-
 			// Activity box
-			int numInserts = node.getNumInsertSenders();
-			int numCHKInserts = node.getNumCHKInserts();
-			int numSSKInserts = node.getNumSSKInserts();
-			int numRequests = node.getNumRequestSenders();
-			int numCHKRequests = node.getNumCHKRequests();
-			int numSSKRequests = node.getNumSSKRequests();
-			int numTransferringRequests = node.getNumTransferringRequestSenders();
-			int numTransferringRequestHandlers = node.getNumTransferringRequestHandlers();
-			int numARKFetchers = node.getNumARKFetchers();
-
 			nextTableCell = overviewTableRow.addChild("td", "class", "last");
 			HTMLNode activityInfobox = nextTableCell.addChild("div", "class", "infobox");
-			activityInfobox.addChild("div", "class", "infobox-header", "Current activity");
-			HTMLNode activityInfoboxContent = activityInfobox.addChild("div", "class", "infobox-content");
-			if ((numInserts == 0) && (numRequests == 0) && (numTransferringRequests == 0) && (numARKFetchers == 0)) {
-				activityInfoboxContent.addChild("#", "Your node is not processing any requests right now.");
-			} else {
-				HTMLNode activityList = activityInfoboxContent.addChild("ul");
-				if (numInserts > 0) {
-					activityList.addChild("li", "Inserts:\u00a0" + numInserts + "\u00a0senders\u00a0(CHK:\u00a0" + numCHKInserts+"\u00a0SSK:\u00a0" + numSSKInserts+"\u00a0locked)");
-				}
-				if (numRequests > 0) {
-					activityList.addChild("li", "Requests:\u00a0" + numRequests + "\u00a0senders\u00a0(CHK:\u00a0" + numCHKRequests+"\u00a0SSK:\u00a0" + numSSKRequests+"\u00a0locked)");
-				}
-				if (numTransferringRequests > 0 || numTransferringRequestHandlers > 0) {
-					activityList.addChild("li", "Transferring\u00a0Requests:\u00a0" + numTransferringRequests+"\u00a0senders\u00a0" + numTransferringRequestHandlers+"\u00a0handlers");
-				}
-				if (advancedModeEnabled) {
-					if (numARKFetchers > 0)
-						activityList.addChild("li", "ARK\u00a0Fetch\u00a0Requests:\u00a0" + numARKFetchers);
-					activityList.addChild("li", "FetcherByUSKSize:\u00a0" + node.clientCore.uskManager.getFetcherByUSKSize());
-					activityList.addChild("li", "BackgroundFetcherByUSKSize:\u00a0" + node.clientCore.uskManager.getBackgroundFetcherByUSKSize());
-					activityList.addChild("li", "temporaryBackgroundFetchersLRUSize:\u00a0" + node.clientCore.uskManager.getTemporaryBackgroundFetchersLRU());
-				}
-			}
+			
+			drawActivityBox(activityInfobox, advancedModeEnabled);
 
 			/* node status overview box */
 			if(advancedModeEnabled) {
 				HTMLNode overviewInfobox = nextTableCell.addChild("div", "class", "infobox");
-				overviewInfobox.addChild("div", "class", "infobox-header", "Node status overview");
-				HTMLNode overviewInfoboxContent = overviewInfobox.addChild("div", "class", "infobox-content");
-				HTMLNode overviewList = overviewInfoboxContent.addChild("ul");
-				overviewList.addChild("li", "bwlimitDelayTime:\u00a0" + bwlimitDelayTime + "ms");
-				overviewList.addChild("li", "nodeAveragePingTime:\u00a0" + nodeAveragePingTime + "ms");
-				overviewList.addChild("li", "networkSizeEstimateSession:\u00a0" + networkSizeEstimateSession + "\u00a0nodes");
-				if(nodeUptimeSeconds > (24*60*60)) {  // 24 hours
-					overviewList.addChild("li", "networkSizeEstimate24h:\u00a0" + networkSizeEstimate24h + "\u00a0nodes");
-				}
-				if(nodeUptimeSeconds > (48*60*60)) {  // 48 hours
-					overviewList.addChild("li", "networkSizeEstimate48h:\u00a0" + networkSizeEstimate48h + "\u00a0nodes");
-				}
-				if ((numberOfRemotePeerLocationsSeenInSwaps > 0.0) && ((swaps > 0.0) || (noSwaps > 0.0))) {
-					overviewList.addChild("li", "avrConnPeersPerNode:\u00a0" + fix6p6.format(numberOfRemotePeerLocationsSeenInSwaps/(swaps+noSwaps)) + "\u00a0peers");
-				}
-				overviewList.addChild("li", "nodeUptime:\u00a0" + nodeUptimeString);
-				overviewList.addChild("li", "routingMissDistance:\u00a0" + fix1p4.format(routingMissDistance));
-				overviewList.addChild("li", "backedOffPercent:\u00a0" + fix3p1pct.format(backedOffPercent));
-				overviewList.addChild("li", "pInstantReject:\u00a0" + fix3p1pct.format(stats.pRejectIncomingInstantly()));
-				overviewList.addChild("li", "unclaimedFIFOSize:\u00a0" + node.getUnclaimedFIFOSize());
+				drawOverviewBox(overviewInfobox, nodeUptimeSeconds, now, swaps, noSwaps);
 			}
 
 			// Peer statistics box
 			HTMLNode peerStatsInfobox = nextTableCell.addChild("div", "class", "infobox");
-			peerStatsInfobox.addChild("div", "class", "infobox-header", "Peer statistics");
-			HTMLNode peerStatsContent = peerStatsInfobox.addChild("div", "class", "infobox-content");
-			HTMLNode peerStatsList = peerStatsContent.addChild("ul");
-			if (numberOfConnected > 0) {
-				HTMLNode peerStatsConnectedListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsConnectedListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_connected", "Connected: We're successfully connected to these nodes", "border-bottom: 1px dotted; cursor: help;" }, "Connected");
-				peerStatsConnectedListItem.addChild("span", ":\u00a0" + numberOfConnected);
-			}
-			if (numberOfRoutingBackedOff > 0) {
-				HTMLNode peerStatsRoutingBackedOffListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsRoutingBackedOffListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_backed_off", (advancedModeEnabled ? "Connected but backed off: These peers are connected but we're backed off of them" : "Busy: These peers are connected but they're busy") + ", so the node is not routing requests to them", "border-bottom: 1px dotted; cursor: help;" }, advancedModeEnabled ? "Backed off" : "Busy");
-				peerStatsRoutingBackedOffListItem.addChild("span", ":\u00a0" + numberOfRoutingBackedOff);
-			}
-			if (numberOfTooNew > 0) {
-				HTMLNode peerStatsTooNewListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsTooNewListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_too_new", "Connected but too new: These peers' minimum mandatory build is higher than this node's build. This node is not routing requests to them", "border-bottom: 1px dotted; cursor: help;" }, "Too New");
-				peerStatsTooNewListItem.addChild("span", ":\u00a0" + numberOfTooNew);
-			}
-			if (numberOfTooOld > 0) {
-				HTMLNode peerStatsTooOldListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsTooOldListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_too_old", "Connected but too old: This node's minimum mandatory build is higher than these peers' build. This node is not routing requests to them", "border-bottom: 1px dotted; cursor: help;" }, "Too Old");
-				peerStatsTooOldListItem.addChild("span", ":\u00a0" + numberOfTooOld);
-			}
-			if (numberOfDisconnected > 0) {
-				HTMLNode peerStatsDisconnectedListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsDisconnectedListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_disconnected", "Not connected: No connection so far but this node is continuously trying to connect", "border-bottom: 1px dotted; cursor: help;" }, "Disconnected");
-				peerStatsDisconnectedListItem.addChild("span", ":\u00a0" + numberOfDisconnected);
-			}
-			if (numberOfNeverConnected > 0) {
-				HTMLNode peerStatsNeverConnectedListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsNeverConnectedListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_never_connected", "Never Connected: The node has never connected with these peers", "border-bottom: 1px dotted; cursor: help;" }, "Never Connected");
-				peerStatsNeverConnectedListItem.addChild("span", ":\u00a0" + numberOfNeverConnected);
-			}
-			if (numberOfDisabled > 0) {
-				HTMLNode peerStatsDisabledListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsDisabledListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_disabled", "Not connected and disabled: because the user has instructed to not connect to peers ", "border-bottom: 1px dotted; cursor: help;" }, "Disabled");
-				peerStatsDisabledListItem.addChild("span", ":\u00a0" + numberOfDisabled);
-			}
-			if (numberOfBursting > 0) {
-				HTMLNode peerStatsBurstingListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsBurstingListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_bursting", "Not connected and bursting: this node is, for a short period, trying to connect to these peers because the user has set BurstOnly on them", "border-bottom: 1px dotted; cursor: help;" }, "Bursting");
-				peerStatsBurstingListItem.addChild("span", ":\u00a0" + numberOfBursting);
-			}
-			if (numberOfListening > 0) {
-				HTMLNode peerStatsListeningListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsListeningListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_listening", "Not connected but listening: this node won't try to connect to these peers very often because the user has set BurstOnly on them", "border-bottom: 1px dotted; cursor: help;" }, "Listening");
-				peerStatsListeningListItem.addChild("span", ":\u00a0" + numberOfListening);
-			}
-			if (numberOfListenOnly > 0) {
-				HTMLNode peerStatsListenOnlyListItem = peerStatsList.addChild("li").addChild("span");
-				peerStatsListenOnlyListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_listen_only", "Not connected and listen only: this node won't try to connect to these peers at all because the user has set ListenOnly on them", "border-bottom: 1px dotted; cursor: help;" }, "Listen Only");
-				peerStatsListenOnlyListItem.addChild("span", ":\u00a0" + numberOfListenOnly);
-			}
+			
+			drawPeerStatsBox(peerStatsInfobox, advancedModeEnabled, numberOfConnected, numberOfRoutingBackedOff, 
+					numberOfTooNew, numberOfTooOld, numberOfDisconnected, numberOfNeverConnected, numberOfDisabled, 
+					numberOfBursting, numberOfListening, numberOfListenOnly);
 
 			// Bandwidth box
 			HTMLNode bandwidthInfobox = nextTableCell.addChild("div", "class", "infobox");
-			bandwidthInfobox.addChild("div", "class", "infobox-header", "Bandwidth");
-			HTMLNode bandwidthInfoboxContent = bandwidthInfobox.addChild("div", "class", "infobox-content");
-			HTMLNode bandwidthList = bandwidthInfoboxContent.addChild("ul");
-			long[] total = IOStatisticCollector.getTotalIO();
-			long total_output_rate = (total[0]) / nodeUptimeSeconds;
-			long total_input_rate = (total[1]) / nodeUptimeSeconds;
-			long totalPayload = node.getTotalPayloadSent();
-			long total_payload_rate = totalPayload / nodeUptimeSeconds;
-			int percent = (int) (100 * totalPayload / total[0]);
-			bandwidthList.addChild("li", "Total Output:\u00a0" + SizeUtil.formatSize(total[0]) + " (" + SizeUtil.formatSize(total_output_rate, true) + "ps)");
-			bandwidthList.addChild("li", "Payload Output:\u00a0" + SizeUtil.formatSize(totalPayload) + " (" + SizeUtil.formatSize(total_payload_rate, true) + "ps) ("+percent+"%)");
-			bandwidthList.addChild("li", "Total Input:\u00a0" + SizeUtil.formatSize(total[1]) + " (" + SizeUtil.formatSize(total_input_rate, true) + "ps)");
-			long[] rate = stats.getNodeIOStats();
-			long delta = (rate[5] - rate[2]) / 1000;
-			if(delta > 0) {
-				long output_rate = (rate[3] - rate[0]) / delta;
-				long input_rate = (rate[4] - rate[1]) / delta;
-				int outputBandwidthLimit = node.getOutputBandwidthLimit();
-				int inputBandwidthLimit = node.getInputBandwidthLimit();
-				if(inputBandwidthLimit == -1) {
-					inputBandwidthLimit = outputBandwidthLimit * 4;
-				}
-				bandwidthList.addChild("li", "Output Rate:\u00a0" + SizeUtil.formatSize(output_rate, true) + "ps (of\u00a0"+SizeUtil.formatSize(outputBandwidthLimit, true)+"ps)");
-				bandwidthList.addChild("li", "Input Rate:\u00a0" + SizeUtil.formatSize(input_rate, true) + "ps (of\u00a0"+SizeUtil.formatSize(inputBandwidthLimit, true)+"ps)");
-			}
+			
+			drawBandwidthBox(bandwidthInfobox, nodeUptimeSeconds);
 
 			if(advancedModeEnabled) {
 
@@ -481,88 +257,12 @@
 				}
 
 				//Swap statistics box
-				int startedSwaps = node.getStartedSwaps();
-				int swapsRejectedAlreadyLocked = node.getSwapsRejectedAlreadyLocked();
-				int swapsRejectedNowhereToGo = node.getSwapsRejectedNowhereToGo();
-				int swapsRejectedRateLimit = node.getSwapsRejectedRateLimit();
-				int swapsRejectedLoop = node.getSwapsRejectedLoop();
-				int swapsRejectedRecognizedID = node.getSwapsRejectedRecognizedID();
-				double locChangeSession = node.getLocationChangeSession();
-
 				HTMLNode locationSwapInfobox = nextTableCell.addChild("div", "class", "infobox");
-				locationSwapInfobox.addChild("div", "class", "infobox-header", "Location swaps");
-				HTMLNode locationSwapInfoboxContent = locationSwapInfobox.addChild("div", "class", "infobox-content");
-				HTMLNode locationSwapList = locationSwapInfoboxContent.addChild("ul");
-				if (swaps > 0.0) {
-					locationSwapList.addChild("li", "locChangeSession:\u00a0" + fix1p6sci.format(locChangeSession));
-					locationSwapList.addChild("li", "locChangePerSwap:\u00a0" + fix1p6sci.format(locChangeSession/swaps));
-				}
-				if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) {
-					locationSwapList.addChild("li", "locChangePerMinute:\u00a0" + fix1p6sci.format(locChangeSession/(double)(nodeUptimeSeconds/60.0)));
-				}
-				if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) {
-					locationSwapList.addChild("li", "swapsPerMinute:\u00a0" + fix1p6sci.format(swaps/(double)(nodeUptimeSeconds/60.0)));
-				}
-				if ((noSwaps > 0.0) && (nodeUptimeSeconds >= 60)) {
-					locationSwapList.addChild("li", "noSwapsPerMinute:\u00a0" + fix1p6sci.format(noSwaps/(double)(nodeUptimeSeconds/60.0)));
-				}
-				if ((swaps > 0.0) && (noSwaps > 0.0)) {
-					locationSwapList.addChild("li", "swapsPerNoSwaps:\u00a0" + fix1p6sci.format(swaps/noSwaps));
-				}
-				if (swaps > 0.0) {
-					locationSwapList.addChild("li", "swaps:\u00a0" + (int)swaps);
-				}
-				if (noSwaps > 0.0) {
-					locationSwapList.addChild("li", "noSwaps:\u00a0" + (int)noSwaps);
-				}
-				if (startedSwaps > 0) {
-					locationSwapList.addChild("li", "startedSwaps:\u00a0" + startedSwaps);
-				}
-				if (swapsRejectedAlreadyLocked > 0) {
-					locationSwapList.addChild("li", "swapsRejectedAlreadyLocked:\u00a0" + swapsRejectedAlreadyLocked);
-				}
-				if (swapsRejectedNowhereToGo > 0) {
-					locationSwapList.addChild("li", "swapsRejectedNowhereToGo:\u00a0" + swapsRejectedNowhereToGo);
-				}
-				if (swapsRejectedRateLimit > 0) {
-					locationSwapList.addChild("li", "swapsRejectedRateLimit:\u00a0" + swapsRejectedRateLimit);
-				}
-				if (swapsRejectedLoop > 0) {
-					locationSwapList.addChild("li", "swapsRejectedLoop:\u00a0" + swapsRejectedLoop);
-				}
-				if (swapsRejectedRecognizedID > 0) {
-					locationSwapList.addChild("li", "swapsRejectedRecognizedID:\u00a0" + swapsRejectedRecognizedID);
-				}			
+				drawSwapStatsBox(locationSwapInfobox, nodeUptimeSeconds, swaps, noSwaps);
 
 				// unclaimedFIFOMessageCounts box
-				Map unclaimedFIFOMessageCountsMap = node.getUSM().getUnclaimedFIFOMessageCounts();
-				STMessageCount[] unclaimedFIFOMessageCountsArray = new STMessageCount[unclaimedFIFOMessageCountsMap.size()];
-				int i = 0;
-				int totalCount = 0;
-				for (Iterator messageCounts = unclaimedFIFOMessageCountsMap.keySet().iterator(); messageCounts.hasNext(); ) {
-					String messageName = (String) messageCounts.next();
-					int messageCount = ((Integer) unclaimedFIFOMessageCountsMap.get(messageName)).intValue();
-					totalCount = totalCount + messageCount;
-					unclaimedFIFOMessageCountsArray[i++] = new STMessageCount( messageName, messageCount );
-				}
-				Arrays.sort(unclaimedFIFOMessageCountsArray, new Comparator() {
-					public int compare(Object first, Object second) {
-						STMessageCount firstCount = (STMessageCount) first;
-						STMessageCount secondCount = (STMessageCount) second;
-						return secondCount.messageCount - firstCount.messageCount;  // sort in descending order
-					}
-				});
 				HTMLNode unclaimedFIFOMessageCountsInfobox = nextTableCell.addChild("div", "class", "infobox");
-				unclaimedFIFOMessageCountsInfobox.addChild("div", "class", "infobox-header", "unclaimedFIFO Message Counts");
-				HTMLNode unclaimedFIFOMessageCountsInfoboxContent = unclaimedFIFOMessageCountsInfobox.addChild("div", "class", "infobox-content");
-				HTMLNode unclaimedFIFOMessageCountsList = unclaimedFIFOMessageCountsInfoboxContent.addChild("ul");
-				for (int countsArrayIndex = 0, countsArrayCount = unclaimedFIFOMessageCountsArray.length; countsArrayIndex < countsArrayCount; countsArrayIndex++) {
-					STMessageCount messageCountItem = (STMessageCount) unclaimedFIFOMessageCountsArray[countsArrayIndex];
-					int thisMessageCount = messageCountItem.messageCount;
-					double thisMessagePercentOfTotal = ((double) thisMessageCount) / ((double) totalCount);
-					unclaimedFIFOMessageCountsList.addChild("li", "" + messageCountItem.messageName + ":\u00a0" + thisMessageCount + "\u00a0(" + fix3p1pct.format(thisMessagePercentOfTotal) + ')');
-				}
-				unclaimedFIFOMessageCountsList.addChild("li", "Unclaimed Messages Considered:\u00a0" + totalCount);
+				drawUnclaimedFIFOMessageCountsBox(unclaimedFIFOMessageCountsInfobox);
 
 				// peer distribution box
 				overviewTableRow = overviewTable.addChild("tr");
@@ -584,6 +284,373 @@
 		this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
 	}
 
+	private void drawNodeVersionBox(HTMLNode versionInfobox) {
+		
+		versionInfobox.addChild("div", "class", "infobox-header", "Node Version Information");
+		HTMLNode versionInfoboxContent = versionInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode versionInfoboxList = versionInfoboxContent.addChild("ul");
+		versionInfoboxList.addChild("li", "Freenet " + Version.nodeVersion + " Build #" + Version.buildNumber() + " r" + Version.cvsRevision);
+		if(NodeStarter.extBuildNumber < NodeStarter.RECOMMENDED_EXT_BUILD_NUMBER)
+			versionInfoboxList.addChild("li", "Freenet-ext Build #" + NodeStarter.extBuildNumber + '(' + NodeStarter.RECOMMENDED_EXT_BUILD_NUMBER + ") r" + NodeStarter.extRevisionNumber);
+		else
+			versionInfoboxList.addChild("li", "Freenet-ext Build #" + NodeStarter.extBuildNumber + " r" + NodeStarter.extRevisionNumber);
+		
+	}
+
+	private void drawJVMStatsBox(HTMLNode jvmStatsInfobox) {
+		
+		jvmStatsInfobox.addChild("div", "class", "infobox-header", "JVM info");
+		HTMLNode jvmStatsInfoboxContent = jvmStatsInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode jvmStatsList = jvmStatsInfoboxContent.addChild("ul");
+
+		Runtime rt = Runtime.getRuntime();
+		float freeMemory = (float) rt.freeMemory();
+		float totalMemory = (float) rt.totalMemory();
+		float maxMemory = (float) rt.maxMemory();
+
+		long usedJavaMem = (long)(totalMemory - freeMemory);
+		long allocatedJavaMem = (long)totalMemory;
+		long maxJavaMem = (long)maxMemory;
+		int availableCpus = rt.availableProcessors();
+
+		int threadCount = stats.getActiveThreadCount();
+
+		jvmStatsList.addChild("li", "Used Java memory:\u00a0" + SizeUtil.formatSize(usedJavaMem, true));
+		jvmStatsList.addChild("li", "Allocated Java memory:\u00a0" + SizeUtil.formatSize(allocatedJavaMem, true));
+		jvmStatsList.addChild("li", "Maximum Java memory:\u00a0" + SizeUtil.formatSize(maxJavaMem, true));
+		jvmStatsList.addChild("li", "Running threads:\u00a0" + thousendPoint.format(threadCount) + '/' + stats.getThreadLimit());
+		jvmStatsList.addChild("li", "Available CPUs:\u00a0" + availableCpus);
+		jvmStatsList.addChild("li", "JVM Vendor:\u00a0" + System.getProperty("java.vm.vendor"));
+		jvmStatsList.addChild("li", "JVM Version:\u00a0" + System.getProperty("java.vm.version"));
+		jvmStatsList.addChild("li", "OS Name:\u00a0" + System.getProperty("os.name"));
+		jvmStatsList.addChild("li", "OS Version:\u00a0" + System.getProperty("os.version"));
+		jvmStatsList.addChild("li", "OS Architecture:\u00a0" + System.getProperty("os.arch"));
+		
+	}
+
+	private void drawStoreSizeBox(HTMLNode storeSizeInfobox, long nodeUptimeSeconds) {
+		
+		storeSizeInfobox.addChild("div", "class", "infobox-header", "Store size");
+		HTMLNode storeSizeInfoboxContent = storeSizeInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode storeSizeList = storeSizeInfoboxContent.addChild("ul");
+
+		final long fix32kb = 32 * 1024;
+
+		long cachedKeys = node.getChkDatacache().keyCount();
+		long cachedSize = cachedKeys * fix32kb;
+		long storeKeys = node.getChkDatastore().keyCount();
+		long storeSize = storeKeys * fix32kb;
+		long overallKeys = cachedKeys + storeKeys;
+		long overallSize = cachedSize + storeSize;
+
+//		long maxCachedKeys = node.getChkDatacache().getMaxKeys();
+//		long maxStoreKeys = node.getChkDatastore().getMaxKeys();
+		long maxOverallKeys = node.getMaxTotalKeys();
+		long maxOverallSize = maxOverallKeys * fix32kb;
+
+		long cachedStoreHits = node.getChkDatacache().hits();
+		long cachedStoreMisses = node.getChkDatacache().misses();
+		long cacheAccesses = cachedStoreHits + cachedStoreMisses;
+		long storeHits = node.getChkDatastore().hits();
+		long storeMisses = node.getChkDatastore().misses();
+		long storeAccesses = storeHits + storeMisses;
+		long overallAccesses = storeAccesses + cacheAccesses;
+
+		// REDFLAG Don't show database version because it's not possible to get it accurately.
+		// (It's a public static constant, so it will use the version from compile time of freenet.jar)
+
+		storeSizeList.addChild("li", 
+				"Cached keys:\u00a0" + thousendPoint.format(cachedKeys) + 
+				" (" + SizeUtil.formatSize(cachedSize, true) + ')');
+
+		storeSizeList.addChild("li", 
+				"Stored keys:\u00a0" + thousendPoint.format(storeKeys) + 
+				" (" + SizeUtil.formatSize(storeSize, true) + ')');
+
+		storeSizeList.addChild("li", 
+				"Overall size:\u00a0" + thousendPoint.format(overallKeys) + 
+				"\u00a0/\u00a0" + thousendPoint.format(maxOverallKeys) +
+				" (" + SizeUtil.formatSize(overallSize, true) + 
+				"\u00a0/\u00a0" + SizeUtil.formatSize(maxOverallSize, true) + 
+				")\u00a0(" + ((overallKeys*100)/maxOverallKeys) + "%)");
+
+		if(cacheAccesses > 0)
+			storeSizeList.addChild("li", 
+					"Cache hits:\u00a0" + thousendPoint.format(cachedStoreHits) + 
+					"\u00a0/\u00a0"+thousendPoint.format(cacheAccesses) +
+					"\u00a0(" + ((cachedStoreHits*100) / (cacheAccesses)) + "%)");
+
+		if(storeAccesses > 0)
+			storeSizeList.addChild("li", 
+					"Store hits:\u00a0" + thousendPoint.format(storeHits) + 
+					"\u00a0/\u00a0"+thousendPoint.format(storeAccesses) +
+					"\u00a0(" + ((storeHits*100) / (storeAccesses)) + "%)");
+
+		storeSizeList.addChild("li", 
+				"Avg. access rate:\u00a0" + thousendPoint.format(overallAccesses/nodeUptimeSeconds) + "/s");
+		
+	}
+
+	private void drawUnclaimedFIFOMessageCountsBox(HTMLNode unclaimedFIFOMessageCountsInfobox) {
+		
+		unclaimedFIFOMessageCountsInfobox.addChild("div", "class", "infobox-header", "unclaimedFIFO Message Counts");
+		HTMLNode unclaimedFIFOMessageCountsInfoboxContent = unclaimedFIFOMessageCountsInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode unclaimedFIFOMessageCountsList = unclaimedFIFOMessageCountsInfoboxContent.addChild("ul");
+		Map unclaimedFIFOMessageCountsMap = node.getUSM().getUnclaimedFIFOMessageCounts();
+		STMessageCount[] unclaimedFIFOMessageCountsArray = new STMessageCount[unclaimedFIFOMessageCountsMap.size()];
+		int i = 0;
+		int totalCount = 0;
+		for (Iterator messageCounts = unclaimedFIFOMessageCountsMap.keySet().iterator(); messageCounts.hasNext(); ) {
+			String messageName = (String) messageCounts.next();
+			int messageCount = ((Integer) unclaimedFIFOMessageCountsMap.get(messageName)).intValue();
+			totalCount = totalCount + messageCount;
+			unclaimedFIFOMessageCountsArray[i++] = new STMessageCount( messageName, messageCount );
+		}
+		Arrays.sort(unclaimedFIFOMessageCountsArray, new Comparator() {
+			public int compare(Object first, Object second) {
+				STMessageCount firstCount = (STMessageCount) first;
+				STMessageCount secondCount = (STMessageCount) second;
+				return secondCount.messageCount - firstCount.messageCount;  // sort in descending order
+			}
+		});
+		for (int countsArrayIndex = 0, countsArrayCount = unclaimedFIFOMessageCountsArray.length; countsArrayIndex < countsArrayCount; countsArrayIndex++) {
+			STMessageCount messageCountItem = (STMessageCount) unclaimedFIFOMessageCountsArray[countsArrayIndex];
+			int thisMessageCount = messageCountItem.messageCount;
+			double thisMessagePercentOfTotal = ((double) thisMessageCount) / ((double) totalCount);
+			unclaimedFIFOMessageCountsList.addChild("li", "" + messageCountItem.messageName + ":\u00a0" + thisMessageCount + "\u00a0(" + fix3p1pct.format(thisMessagePercentOfTotal) + ')');
+		}
+		unclaimedFIFOMessageCountsList.addChild("li", "Unclaimed Messages Considered:\u00a0" + totalCount);
+		
+	}
+
+	private void drawSwapStatsBox(HTMLNode locationSwapInfobox, long nodeUptimeSeconds, double swaps, double noSwaps) {
+		
+		locationSwapInfobox.addChild("div", "class", "infobox-header", "Location swaps");
+		int startedSwaps = node.getStartedSwaps();
+		int swapsRejectedAlreadyLocked = node.getSwapsRejectedAlreadyLocked();
+		int swapsRejectedNowhereToGo = node.getSwapsRejectedNowhereToGo();
+		int swapsRejectedRateLimit = node.getSwapsRejectedRateLimit();
+		int swapsRejectedLoop = node.getSwapsRejectedLoop();
+		int swapsRejectedRecognizedID = node.getSwapsRejectedRecognizedID();
+		double locChangeSession = node.getLocationChangeSession();
+
+		HTMLNode locationSwapInfoboxContent = locationSwapInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode locationSwapList = locationSwapInfoboxContent.addChild("ul");
+		if (swaps > 0.0) {
+			locationSwapList.addChild("li", "locChangeSession:\u00a0" + fix1p6sci.format(locChangeSession));
+			locationSwapList.addChild("li", "locChangePerSwap:\u00a0" + fix1p6sci.format(locChangeSession/swaps));
+		}
+		if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) {
+			locationSwapList.addChild("li", "locChangePerMinute:\u00a0" + fix1p6sci.format(locChangeSession/(double)(nodeUptimeSeconds/60.0)));
+		}
+		if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) {
+			locationSwapList.addChild("li", "swapsPerMinute:\u00a0" + fix1p6sci.format(swaps/(double)(nodeUptimeSeconds/60.0)));
+		}
+		if ((noSwaps > 0.0) && (nodeUptimeSeconds >= 60)) {
+			locationSwapList.addChild("li", "noSwapsPerMinute:\u00a0" + fix1p6sci.format(noSwaps/(double)(nodeUptimeSeconds/60.0)));
+		}
+		if ((swaps > 0.0) && (noSwaps > 0.0)) {
+			locationSwapList.addChild("li", "swapsPerNoSwaps:\u00a0" + fix1p6sci.format(swaps/noSwaps));
+		}
+		if (swaps > 0.0) {
+			locationSwapList.addChild("li", "swaps:\u00a0" + (int)swaps);
+		}
+		if (noSwaps > 0.0) {
+			locationSwapList.addChild("li", "noSwaps:\u00a0" + (int)noSwaps);
+		}
+		if (startedSwaps > 0) {
+			locationSwapList.addChild("li", "startedSwaps:\u00a0" + startedSwaps);
+		}
+		if (swapsRejectedAlreadyLocked > 0) {
+			locationSwapList.addChild("li", "swapsRejectedAlreadyLocked:\u00a0" + swapsRejectedAlreadyLocked);
+		}
+		if (swapsRejectedNowhereToGo > 0) {
+			locationSwapList.addChild("li", "swapsRejectedNowhereToGo:\u00a0" + swapsRejectedNowhereToGo);
+		}
+		if (swapsRejectedRateLimit > 0) {
+			locationSwapList.addChild("li", "swapsRejectedRateLimit:\u00a0" + swapsRejectedRateLimit);
+		}
+		if (swapsRejectedLoop > 0) {
+			locationSwapList.addChild("li", "swapsRejectedLoop:\u00a0" + swapsRejectedLoop);
+		}
+		if (swapsRejectedRecognizedID > 0) {
+			locationSwapList.addChild("li", "swapsRejectedRecognizedID:\u00a0" + swapsRejectedRecognizedID);
+		}			
+		
+	}
+
+	private void drawPeerStatsBox(HTMLNode peerStatsInfobox, boolean advancedModeEnabled, int numberOfConnected, 
+			int numberOfRoutingBackedOff, int numberOfTooNew, int numberOfTooOld, int numberOfDisconnected, 
+			int numberOfNeverConnected, int numberOfDisabled, int numberOfBursting, int numberOfListening, 
+			int numberOfListenOnly) {
+		
+		peerStatsInfobox.addChild("div", "class", "infobox-header", "Peer statistics");
+		HTMLNode peerStatsContent = peerStatsInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode peerStatsList = peerStatsContent.addChild("ul");
+		if (numberOfConnected > 0) {
+			HTMLNode peerStatsConnectedListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsConnectedListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_connected", "Connected: We're successfully connected to these nodes", "border-bottom: 1px dotted; cursor: help;" }, "Connected");
+			peerStatsConnectedListItem.addChild("span", ":\u00a0" + numberOfConnected);
+		}
+		if (numberOfRoutingBackedOff > 0) {
+			HTMLNode peerStatsRoutingBackedOffListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsRoutingBackedOffListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_backed_off", (advancedModeEnabled ? "Connected but backed off: These peers are connected but we're backed off of them" : "Busy: These peers are connected but they're busy") + ", so the node is not routing requests to them", "border-bottom: 1px dotted; cursor: help;" }, advancedModeEnabled ? "Backed off" : "Busy");
+			peerStatsRoutingBackedOffListItem.addChild("span", ":\u00a0" + numberOfRoutingBackedOff);
+		}
+		if (numberOfTooNew > 0) {
+			HTMLNode peerStatsTooNewListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsTooNewListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_too_new", "Connected but too new: These peers' minimum mandatory build is higher than this node's build. This node is not routing requests to them", "border-bottom: 1px dotted; cursor: help;" }, "Too New");
+			peerStatsTooNewListItem.addChild("span", ":\u00a0" + numberOfTooNew);
+		}
+		if (numberOfTooOld > 0) {
+			HTMLNode peerStatsTooOldListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsTooOldListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_too_old", "Connected but too old: This node's minimum mandatory build is higher than these peers' build. This node is not routing requests to them", "border-bottom: 1px dotted; cursor: help;" }, "Too Old");
+			peerStatsTooOldListItem.addChild("span", ":\u00a0" + numberOfTooOld);
+		}
+		if (numberOfDisconnected > 0) {
+			HTMLNode peerStatsDisconnectedListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsDisconnectedListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_disconnected", "Not connected: No connection so far but this node is continuously trying to connect", "border-bottom: 1px dotted; cursor: help;" }, "Disconnected");
+			peerStatsDisconnectedListItem.addChild("span", ":\u00a0" + numberOfDisconnected);
+		}
+		if (numberOfNeverConnected > 0) {
+			HTMLNode peerStatsNeverConnectedListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsNeverConnectedListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_never_connected", "Never Connected: The node has never connected with these peers", "border-bottom: 1px dotted; cursor: help;" }, "Never Connected");
+			peerStatsNeverConnectedListItem.addChild("span", ":\u00a0" + numberOfNeverConnected);
+		}
+		if (numberOfDisabled > 0) {
+			HTMLNode peerStatsDisabledListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsDisabledListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_disabled", "Not connected and disabled: because the user has instructed to not connect to peers ", "border-bottom: 1px dotted; cursor: help;" }, "Disabled");
+			peerStatsDisabledListItem.addChild("span", ":\u00a0" + numberOfDisabled);
+		}
+		if (numberOfBursting > 0) {
+			HTMLNode peerStatsBurstingListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsBurstingListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_bursting", "Not connected and bursting: this node is, for a short period, trying to connect to these peers because the user has set BurstOnly on them", "border-bottom: 1px dotted; cursor: help;" }, "Bursting");
+			peerStatsBurstingListItem.addChild("span", ":\u00a0" + numberOfBursting);
+		}
+		if (numberOfListening > 0) {
+			HTMLNode peerStatsListeningListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsListeningListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_listening", "Not connected but listening: this node won't try to connect to these peers very often because the user has set BurstOnly on them", "border-bottom: 1px dotted; cursor: help;" }, "Listening");
+			peerStatsListeningListItem.addChild("span", ":\u00a0" + numberOfListening);
+		}
+		if (numberOfListenOnly > 0) {
+			HTMLNode peerStatsListenOnlyListItem = peerStatsList.addChild("li").addChild("span");
+			peerStatsListenOnlyListItem.addChild("span", new String[] { "class", "title", "style" }, new String[] { "peer_listen_only", "Not connected and listen only: this node won't try to connect to these peers at all because the user has set ListenOnly on them", "border-bottom: 1px dotted; cursor: help;" }, "Listen Only");
+			peerStatsListenOnlyListItem.addChild("span", ":\u00a0" + numberOfListenOnly);
+		}
+		
+	}
+
+	private void drawActivityBox(HTMLNode activityInfobox, boolean advancedModeEnabled) {
+		
+		activityInfobox.addChild("div", "class", "infobox-header", "Current activity");
+		HTMLNode activityInfoboxContent = activityInfobox.addChild("div", "class", "infobox-content");
+		
+		int numInserts = node.getNumInsertSenders();
+		int numCHKInserts = node.getNumCHKInserts();
+		int numSSKInserts = node.getNumSSKInserts();
+		int numRequests = node.getNumRequestSenders();
+		int numCHKRequests = node.getNumCHKRequests();
+		int numSSKRequests = node.getNumSSKRequests();
+		int numTransferringRequests = node.getNumTransferringRequestSenders();
+		int numTransferringRequestHandlers = node.getNumTransferringRequestHandlers();
+		int numARKFetchers = node.getNumARKFetchers();
+
+		if ((numInserts == 0) && (numRequests == 0) && (numTransferringRequests == 0) && (numARKFetchers == 0)) {
+			activityInfoboxContent.addChild("#", "Your node is not processing any requests right now.");
+		} else {
+			HTMLNode activityList = activityInfoboxContent.addChild("ul");
+			if (numInserts > 0) {
+				activityList.addChild("li", "Inserts:\u00a0" + numInserts + "\u00a0senders\u00a0(CHK:\u00a0" + numCHKInserts+"\u00a0SSK:\u00a0" + numSSKInserts+"\u00a0locked)");
+			}
+			if (numRequests > 0) {
+				activityList.addChild("li", "Requests:\u00a0" + numRequests + "\u00a0senders\u00a0(CHK:\u00a0" + numCHKRequests+"\u00a0SSK:\u00a0" + numSSKRequests+"\u00a0locked)");
+			}
+			if (numTransferringRequests > 0 || numTransferringRequestHandlers > 0) {
+				activityList.addChild("li", "Transferring\u00a0Requests:\u00a0" + numTransferringRequests+"\u00a0senders\u00a0" + numTransferringRequestHandlers+"\u00a0handlers");
+			}
+			if (advancedModeEnabled) {
+				if (numARKFetchers > 0)
+					activityList.addChild("li", "ARK\u00a0Fetch\u00a0Requests:\u00a0" + numARKFetchers);
+				activityList.addChild("li", "FetcherByUSKSize:\u00a0" + node.clientCore.uskManager.getFetcherByUSKSize());
+				activityList.addChild("li", "BackgroundFetcherByUSKSize:\u00a0" + node.clientCore.uskManager.getBackgroundFetcherByUSKSize());
+				activityList.addChild("li", "temporaryBackgroundFetchersLRUSize:\u00a0" + node.clientCore.uskManager.getTemporaryBackgroundFetchersLRU());
+			}
+		}
+		
+	}
+
+	private void drawOverviewBox(HTMLNode overviewInfobox, long nodeUptimeSeconds, long now, double swaps, double noSwaps) {
+		
+		overviewInfobox.addChild("div", "class", "infobox-header", "Node status overview");
+		HTMLNode overviewInfoboxContent = overviewInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode overviewList = overviewInfoboxContent.addChild("ul");
+		/* node status values */
+		int bwlimitDelayTime = (int) stats.getBwlimitDelayTime();
+		int nodeAveragePingTime = (int) stats.getNodeAveragePingTime();
+		int networkSizeEstimateSession = stats.getNetworkSizeEstimate(-1);
+		int networkSizeEstimate24h = 0;
+		int networkSizeEstimate48h = 0;
+		double numberOfRemotePeerLocationsSeenInSwaps = (double)node.getNumberOfRemotePeerLocationsSeenInSwaps();
+
+		if(nodeUptimeSeconds > (24*60*60)) {  // 24 hours
+			networkSizeEstimate24h = stats.getNetworkSizeEstimate(now - (24*60*60*1000));  // 48 hours
+		}
+		if(nodeUptimeSeconds > (48*60*60)) {  // 48 hours
+			networkSizeEstimate48h = stats.getNetworkSizeEstimate(now - (48*60*60*1000));  // 48 hours
+		}
+		double routingMissDistance =  stats.routingMissDistance.currentValue();
+		double backedOffPercent =  stats.backedOffPercent.currentValue();
+		String nodeUptimeString = TimeUtil.formatTime(nodeUptimeSeconds * 1000);  // *1000 to convert to milliseconds
+		overviewList.addChild("li", "bwlimitDelayTime:\u00a0" + bwlimitDelayTime + "ms");
+		overviewList.addChild("li", "nodeAveragePingTime:\u00a0" + nodeAveragePingTime + "ms");
+		overviewList.addChild("li", "networkSizeEstimateSession:\u00a0" + networkSizeEstimateSession + "\u00a0nodes");
+		if(nodeUptimeSeconds > (24*60*60)) {  // 24 hours
+			overviewList.addChild("li", "networkSizeEstimate24h:\u00a0" + networkSizeEstimate24h + "\u00a0nodes");
+		}
+		if(nodeUptimeSeconds > (48*60*60)) {  // 48 hours
+			overviewList.addChild("li", "networkSizeEstimate48h:\u00a0" + networkSizeEstimate48h + "\u00a0nodes");
+		}
+		if ((numberOfRemotePeerLocationsSeenInSwaps > 0.0) && ((swaps > 0.0) || (noSwaps > 0.0))) {
+			overviewList.addChild("li", "avrConnPeersPerNode:\u00a0" + fix6p6.format(numberOfRemotePeerLocationsSeenInSwaps/(swaps+noSwaps)) + "\u00a0peers");
+		}
+		overviewList.addChild("li", "nodeUptime:\u00a0" + nodeUptimeString);
+		overviewList.addChild("li", "routingMissDistance:\u00a0" + fix1p4.format(routingMissDistance));
+		overviewList.addChild("li", "backedOffPercent:\u00a0" + fix3p1pct.format(backedOffPercent));
+		overviewList.addChild("li", "pInstantReject:\u00a0" + fix3p1pct.format(stats.pRejectIncomingInstantly()));
+		overviewList.addChild("li", "unclaimedFIFOSize:\u00a0" + node.getUnclaimedFIFOSize());
+		
+	}
+
+	private void drawBandwidthBox(HTMLNode bandwidthInfobox, long nodeUptimeSeconds) {
+		
+		bandwidthInfobox.addChild("div", "class", "infobox-header", "Bandwidth");
+		HTMLNode bandwidthInfoboxContent = bandwidthInfobox.addChild("div", "class", "infobox-content");
+		HTMLNode bandwidthList = bandwidthInfoboxContent.addChild("ul");
+		long[] total = IOStatisticCollector.getTotalIO();
+		long total_output_rate = (total[0]) / nodeUptimeSeconds;
+		long total_input_rate = (total[1]) / nodeUptimeSeconds;
+		long totalPayload = node.getTotalPayloadSent();
+		long total_payload_rate = totalPayload / nodeUptimeSeconds;
+		int percent = (int) (100 * totalPayload / total[0]);
+		bandwidthList.addChild("li", "Total Output:\u00a0" + SizeUtil.formatSize(total[0]) + " (" + SizeUtil.formatSize(total_output_rate, true) + "ps)");
+		bandwidthList.addChild("li", "Payload Output:\u00a0" + SizeUtil.formatSize(totalPayload) + " (" + SizeUtil.formatSize(total_payload_rate, true) + "ps) ("+percent+"%)");
+		bandwidthList.addChild("li", "Total Input:\u00a0" + SizeUtil.formatSize(total[1]) + " (" + SizeUtil.formatSize(total_input_rate, true) + "ps)");
+		long[] rate = stats.getNodeIOStats();
+		long delta = (rate[5] - rate[2]) / 1000;
+		if(delta > 0) {
+			long output_rate = (rate[3] - rate[0]) / delta;
+			long input_rate = (rate[4] - rate[1]) / delta;
+			int outputBandwidthLimit = node.getOutputBandwidthLimit();
+			int inputBandwidthLimit = node.getInputBandwidthLimit();
+			if(inputBandwidthLimit == -1) {
+				inputBandwidthLimit = outputBandwidthLimit * 4;
+			}
+			bandwidthList.addChild("li", "Output Rate:\u00a0" + SizeUtil.formatSize(output_rate, true) + "ps (of\u00a0"+SizeUtil.formatSize(outputBandwidthLimit, true)+"ps)");
+			bandwidthList.addChild("li", "Input Rate:\u00a0" + SizeUtil.formatSize(input_rate, true) + "ps (of\u00a0"+SizeUtil.formatSize(inputBandwidthLimit, true)+"ps)");
+		}
+		
+	}
+
 	// FIXME this should probably be moved to nodestats so it can be used by FCP??? would have to make ThreadBunch public :<
 	private void getThreadNames(HTMLNode threadUsageList) {
 		int count = 0;




More information about the cvs mailing list