}
}
node.clientCore.bandwidthStatsPutter.updateData(node);
HTMLNode pageNode;
// Synchronize to avoid problems with DecimalFormat.
synchronized(this) {
/* gather connection statistics */
PeerNodeStatus[] peerNodeStatuses = peers.getPeerNodeStatuses(true);
Arrays.sort(peerNodeStatuses, new Comparator<PeerNodeStatus>() {
@Override
public int compare(PeerNodeStatus firstNode, PeerNodeStatus secondNode) {
int statusDifference = firstNode.getStatusValue() - secondNode.getStatusValue();
if (statusDifference != 0) {
return statusDifference;
}
return 0;
}
});
int numberOfConnected = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_CONNECTED);
int numberOfRoutingBackedOff = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF);
int numberOfTooNew = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_TOO_NEW);
int numberOfTooOld = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_TOO_OLD);
int numberOfDisconnected = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_DISCONNECTED);
int numberOfNeverConnected = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED);
int numberOfDisabled = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_DISABLED);
int numberOfBursting = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_BURSTING);
int numberOfListening = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_LISTENING);
int numberOfListenOnly = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_LISTEN_ONLY);
int numberOfSeedServers = getCountSeedServers(peerNodeStatuses);
int numberOfSeedClients = getCountSeedClients(peerNodeStatuses);
int numberOfRoutingDisabled = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_ROUTING_DISABLED);
int numberOfClockProblem = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_CLOCK_PROBLEM);
int numberOfConnError = getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_CONN_ERROR);
int numberOfDisconnecting = PeerNodeStatus.getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_DISCONNECTING);
int numberOfNoLoadStats = PeerNodeStatus.getPeerStatusCount(peerNodeStatuses, PeerManager.PEER_NODE_STATUS_NO_LOAD_STATS);
PageNode page = ctx.getPageMaker().getPageNode(l10n("fullTitle"), ctx);
boolean advancedMode = ctx.isAdvancedModeEnabled();
pageNode = page.outer;
HTMLNode contentNode = page.content;
// FIXME! We need some nice images
final long now = System.currentTimeMillis();
double myLocation = node.getLocation();
final long nodeUptimeSeconds = (now - node.startupTime) / 1000;
if(ctx.isAllowedFullAccess())
contentNode.addChild(ctx.getAlertManager().createSummary());
double swaps = node.getSwaps();
double noSwaps = node.getNoSwaps();
HTMLNode overviewTable = contentNode.addChild("table", "class", "column");
HTMLNode overviewTableRow = overviewTable.addChild("tr");
HTMLNode nextTableCell = overviewTableRow.addChild("td", "class", "first");
// node version information box
HTMLNode versionInfobox = nextTableCell.addChild("div", "class", "infobox");
drawNodeVersionBox(versionInfobox);
// jvm stats box
HTMLNode jvmStatsInfobox = nextTableCell.addChild("div", "class", "infobox");
drawJVMStatsBox(jvmStatsInfobox, advancedMode);
// Statistic gathering box
HTMLNode statGatheringContent = ctx.getPageMaker().getInfobox("#", l10n("statisticGatheringTitle"), nextTableCell, "statistics-generating", true);
// Generate a Thread-Dump
if(node.isUsingWrapper()){
HTMLNode threadDumpForm = ctx.addFormChild(statGatheringContent, "/", "threadDumpForm");
threadDumpForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "getThreadDump", l10n("threadDumpButton")});
}
// Get logs
HTMLNode logsList = statGatheringContent.addChild("ul");
if(nodeConfig.config.get("logger").getBoolean("enabled"))
logsList.addChild("li").addChild("a", new String[]{ "href", "target"}, new String[]{ "/?latestlog", "_blank"}, l10n("getLogs"));
logsList.addChild("li").addChild("a", "href", TranslationToadlet.TOADLET_URL+"?getOverrideTranlationFile").addChild("#", NodeL10n.getBase().getString("TranslationToadlet.downloadTranslationsFile"));
logsList.addChild("li").addChild("a", "href", DiagnosticToadlet.TOADLET_URL).addChild("#", NodeL10n.getBase().getString("FProxyToadlet.diagnostic"));
if(advancedMode) {
// store size box
//HTMLNode storeSizeInfobox = nextTableCell.addChild("div", "class", "infobox");
HTMLNode storeSizeInfobox = contentNode.addChild("div","class", "infobox");
drawStoreSizeBox(storeSizeInfobox, myLocation, nodeUptimeSeconds);
if(numberOfConnected + numberOfRoutingBackedOff > 0) {
HTMLNode loadStatsInfobox = nextTableCell.addChild("div", "class", "infobox");
drawLoadBalancingBox(loadStatsInfobox, false);
loadStatsInfobox = nextTableCell.addChild("div", "class", "infobox");
drawLoadBalancingBox(loadStatsInfobox, true);
HTMLNode newLoadManagementBox = nextTableCell.addChild("div", "class", "infobox");
drawNewLoadManagementBox(newLoadManagementBox);
// Psuccess box
HTMLNode successRateBox = nextTableCell.addChild("div", "class", "infobox");
successRateBox.addChild("div", "class", "infobox-header", l10n("successRate"));
HTMLNode successRateContent = successRateBox.addChild("div", "class", "infobox-content");
stats.fillSuccessRateBox(successRateContent);
HTMLNode timeDetailBox = nextTableCell.addChild("div", "class", "infobox");
timeDetailBox.addChild("div", "class", "infobox-header", l10n("chkDetailTiming"));
HTMLNode timingsContent = timeDetailBox.addChild("div", "class", "infobox-content");
stats.fillDetailedTimingsBox(timingsContent);
HTMLNode byHTLBox = nextTableCell.addChild("div", "class", "infobox");
byHTLBox.addChild("div", "class", "infobox-header", l10n("successByHTLBulk"));
HTMLNode byHTLContent = byHTLBox.addChild("div", "class", "infobox-content");
stats.fillRemoteRequestHTLsBox(byHTLContent, false);
byHTLBox = nextTableCell.addChild("div", "class", "infobox");
byHTLBox.addChild("div", "class", "infobox-header", l10n("successByHTLRT"));
byHTLContent = byHTLBox.addChild("div", "class", "infobox-content");
stats.fillRemoteRequestHTLsBox(byHTLContent, true);
}
}
if(advancedMode || numberOfConnected + numberOfRoutingBackedOff > 0) {
// Activity box
nextTableCell = overviewTableRow.addChild("td", "class", "last");
HTMLNode activityInfobox = nextTableCell.addChild("div", "class", "infobox");
drawActivityBox(activityInfobox, advancedMode);
/* node status overview box */
if(advancedMode) {
HTMLNode overviewInfobox = nextTableCell.addChild("div", "class", "infobox");
drawOverviewBox(overviewInfobox, nodeUptimeSeconds, node.clientCore.bandwidthStatsPutter.getLatestUptimeData().totalUptime, now, swaps, noSwaps);
}
// Peer statistics box
HTMLNode peerStatsInfobox = nextTableCell.addChild("div", "class", "infobox");
drawPeerStatsBox(peerStatsInfobox, advancedMode, numberOfConnected, numberOfRoutingBackedOff,
numberOfTooNew, numberOfTooOld, numberOfDisconnected, numberOfNeverConnected, numberOfDisabled,
numberOfBursting, numberOfListening, numberOfListenOnly, numberOfSeedServers, numberOfSeedClients,
numberOfRoutingDisabled, numberOfClockProblem, numberOfConnError, numberOfDisconnecting, numberOfNoLoadStats, node);
// Bandwidth box
HTMLNode bandwidthInfobox = nextTableCell.addChild("div", "class", "infobox");
drawBandwidthBox(bandwidthInfobox, nodeUptimeSeconds, advancedMode);
}
if(advancedMode) {
// Peer routing backoff reason box
HTMLNode backoffReasonInfobox = nextTableCell.addChild("div", "class", "infobox");
backoffReasonInfobox.addChild("div", "class", "infobox-header", "Peer Backoff");
HTMLNode backoffReasonContent = backoffReasonInfobox.addChild("div", "class", "infobox-content");
HTMLNode curBackoffReasonInfobox = backoffReasonContent.addChild("div", "class", "infobox");
curBackoffReasonInfobox.addChild("div", "class", "infobox-header", "Current backoff reasons (bulk)");
HTMLNode curBackoffReasonContent = curBackoffReasonInfobox.addChild("div", "class", "infobox-content");
String [] routingBackoffReasons = peers.getPeerNodeRoutingBackoffReasons(false);
if(routingBackoffReasons.length == 0) {
curBackoffReasonContent.addChild("#", l10n("notBackedOff"));
} else {
HTMLNode reasonList = curBackoffReasonContent.addChild("ul");
for(String routingBackoffReason: routingBackoffReasons) {
int reasonCount = peers.getPeerNodeRoutingBackoffReasonSize(routingBackoffReason, false);
if(reasonCount > 0) {
reasonList.addChild("li", routingBackoffReason + '\u00a0' + reasonCount);
}
}
}
curBackoffReasonInfobox = backoffReasonContent.addChild("div", "class", "infobox");
curBackoffReasonInfobox.addChild("div", "class", "infobox-header", "Current backoff reasons (realtime)");
curBackoffReasonContent = curBackoffReasonInfobox.addChild("div", "class", "infobox-content");
routingBackoffReasons = peers.getPeerNodeRoutingBackoffReasons(true);
if(routingBackoffReasons.length == 0) {
curBackoffReasonContent.addChild("#", l10n("notBackedOff"));
} else {
HTMLNode reasonList = curBackoffReasonContent.addChild("ul");
for(String routingBackoffReason: routingBackoffReasons) {
int reasonCount = peers.getPeerNodeRoutingBackoffReasonSize(routingBackoffReason, true);
if(reasonCount > 0) {
reasonList.addChild("li", routingBackoffReason + '\u00a0' + reasonCount);
}
}
}
// Per backoff-type count and avg backoff lengths
// Mandatory backoff - bulk
HTMLNode mandatoryBackoffStatisticsTableBulk = backoffReasonInfobox.addChild("table", "border", "0");
HTMLNode row = mandatoryBackoffStatisticsTableBulk.addChild("tr");
row.addChild("th", l10n("mandatoryBackoffReason") + " (bulk)");
row.addChild("th", l10n("count"));
row.addChild("th", l10n("avgTime"));
row.addChild("th", l10n("totalTime"));
for(NodeStats.TimedStats entry : stats.getMandatoryBackoffStatistics(false)) {
row = mandatoryBackoffStatisticsTableBulk.addChild("tr");
row.addChild("td", entry.keyStr);
row.addChild("td", Long.toString(entry.count));
row.addChild("td", TimeUtil.formatTime(entry.avgTime, 2, true));
row.addChild("td", TimeUtil.formatTime(entry.totalTime, 2, true));
}
// Mandatory backoff - realtime
HTMLNode mandatoryBackoffStatisticsTableRT = backoffReasonInfobox.addChild("table", "border", "0");
row = mandatoryBackoffStatisticsTableRT.addChild("tr");
row.addChild("th", l10n("mandatoryBackoffReason") + " (realtime)");
row.addChild("th", l10n("count"));
row.addChild("th", l10n("avgTime"));
row.addChild("th", l10n("totalTime"));
for(NodeStats.TimedStats entry : stats.getMandatoryBackoffStatistics(true)) {
row = mandatoryBackoffStatisticsTableRT.addChild("tr");
row.addChild("td", entry.keyStr);
row.addChild("td", Long.toString(entry.count));
row.addChild("td", TimeUtil.formatTime(entry.avgTime, 2, true));
row.addChild("td", TimeUtil.formatTime(entry.totalTime, 2, true));
}
// Routing Backoff bulk
HTMLNode routingBackoffStatisticsTableBulk = backoffReasonInfobox.addChild("table", "border", "0");
row = routingBackoffStatisticsTableBulk.addChild("tr");
row.addChild("th", l10n("routingBackoffReason") + " (bulk)");
row.addChild("th", l10n("count"));
row.addChild("th", l10n("avgTime"));
row.addChild("th", l10n("totalTime"));
for(NodeStats.TimedStats entry : stats.getRoutingBackoffStatistics(false)) {
row = routingBackoffStatisticsTableBulk.addChild("tr");
row.addChild("td", entry.keyStr);
row.addChild("td", Long.toString(entry.count));
row.addChild("td", TimeUtil.formatTime(entry.avgTime, 2, true));
row.addChild("td", TimeUtil.formatTime(entry.totalTime, 2, true));
}
// Routing Backoff realtime
HTMLNode routingBackoffStatisticsTableRT = backoffReasonInfobox.addChild("table", "border", "0");
row = routingBackoffStatisticsTableRT.addChild("tr");
row.addChild("th", l10n("routingBackoffReason") + " (realtime)");
row.addChild("th", l10n("count"));
row.addChild("th", l10n("avgTime"));
row.addChild("th", l10n("totalTime"));
for(NodeStats.TimedStats entry : stats.getRoutingBackoffStatistics(true)) {
row = routingBackoffStatisticsTableRT.addChild("tr");
row.addChild("td", entry.keyStr);
row.addChild("td", Long.toString(entry.count));
row.addChild("td", TimeUtil.formatTime(entry.avgTime, 2, true));
row.addChild("td", TimeUtil.formatTime(entry.totalTime, 2, true));
}
// Transfer Backoff bulk
HTMLNode transferBackoffStatisticsTableBulk = backoffReasonInfobox.addChild("table", "border", "0");
row = transferBackoffStatisticsTableBulk.addChild("tr");
row.addChild("th", l10n("transferBackoffReason") + " (bulk)");
row.addChild("th", l10n("count"));
row.addChild("th", l10n("avgTime"));
row.addChild("th", l10n("totalTime"));
for(NodeStats.TimedStats entry : stats.getTransferBackoffStatistics(false)) {
row = transferBackoffStatisticsTableBulk.addChild("tr");
row.addChild("td", entry.keyStr);
row.addChild("td", Long.toString(entry.count));
row.addChild("td", TimeUtil.formatTime(entry.avgTime, 2, true));
row.addChild("td", TimeUtil.formatTime(entry.totalTime, 2, true));
}
// Transfer Backoff realtime
HTMLNode transferBackoffStatisticsTableRT = backoffReasonInfobox.addChild("table", "border", "0");
row = transferBackoffStatisticsTableRT.addChild("tr");
row.addChild("th", l10n("transferBackoffReason") + " (realtime)");
row.addChild("th", l10n("count"));
row.addChild("th", l10n("avgTime"));
row.addChild("th", l10n("totalTime"));
for(NodeStats.TimedStats entry : stats.getTransferBackoffStatistics(true)) {
row = transferBackoffStatisticsTableRT.addChild("tr");
row.addChild("td", entry.keyStr);
row.addChild("td", Long.toString(entry.count));
row.addChild("td", TimeUtil.formatTime(entry.avgTime, 2, true));
row.addChild("td", TimeUtil.formatTime(entry.totalTime, 2, true));
}
//Swap statistics box
HTMLNode locationSwapInfobox = nextTableCell.addChild("div", "class", "infobox");
drawSwapStatsBox(locationSwapInfobox, myLocation, nodeUptimeSeconds, swaps, noSwaps);
// unclaimedFIFOMessageCounts box
HTMLNode unclaimedFIFOMessageCountsInfobox = nextTableCell.addChild("div", "class", "infobox");
drawUnclaimedFIFOMessageCountsBox(unclaimedFIFOMessageCountsInfobox);
HTMLNode threadsPriorityInfobox = nextTableCell.addChild("div", "class", "infobox");
drawThreadPriorityStatsBox(threadsPriorityInfobox);
nextTableCell = overviewTableRow.addChild("td");
// thread usage box
HTMLNode threadUsageInfobox = nextTableCell.addChild("div", "class", "infobox");
threadUsageInfobox.addChild("div", "class", "infobox-header", "Thread usage");
HTMLNode threadUsageContent = threadUsageInfobox.addChild("div", "class", "infobox-content");
HTMLNode threadUsageList = threadUsageContent.addChild("ul");
getThreadNames(threadUsageList);
// rejection reasons box
drawRejectReasonsBox(nextTableCell, false);
drawRejectReasonsBox(nextTableCell, true);
OpennetManager om = node.getOpennet();
if(om != null) {
// opennet stats box
drawOpennetStatsBox(nextTableCell.addChild("div", "class", "infobox"), om);
if(node.isSeednode())
drawSeedStatsBox(nextTableCell.addChild("div", "class", "infobox"), om);
}
// peer distribution box
overviewTableRow = overviewTable.addChild("tr");
nextTableCell = overviewTableRow.addChild("td", "class", "first");
HTMLNode peerCircleInfobox = nextTableCell.addChild("div", "class", "infobox");
peerCircleInfobox.addChild("div", "class", "infobox-header", "Peer\u00a0Location\u00a0Distribution (w/pReject)");
HTMLNode peerCircleTable = peerCircleInfobox.addChild("div", "class", "infobox-content").addChild("table");
addPeerCircle(peerCircleTable, peerNodeStatuses, myLocation);
nextTableCell = overviewTableRow.addChild("td");
// node distribution box
HTMLNode nodeCircleInfobox = nextTableCell.addChild("div", "class", "infobox");
nodeCircleInfobox.addChild("div", "class", "infobox-header", "Node\u00a0Location\u00a0Distribution (w/Swap\u00a0Age)");
HTMLNode nodeCircleTable = nodeCircleInfobox.addChild("div", "class", "infobox-content").addChild("table");
addNodeCircle(nodeCircleTable, myLocation);
overviewTableRow = overviewTable.addChild("tr");
nextTableCell = overviewTableRow.addChild("td", "class", "first");
// specialisation box
int[] incomingRequestCountArray = new int[1];
int[] incomingRequestLocation = stats.getIncomingRequestLocation(incomingRequestCountArray);
int incomingRequestsCount = incomingRequestCountArray[0];
if(incomingRequestsCount > 0) {
HTMLNode nodeSpecialisationInfobox = nextTableCell.addChild("div", "class", "infobox");
nodeSpecialisationInfobox.addChild("div", "class", "infobox-header", "Incoming\u00a0Request\u00a0Distribution");
HTMLNode nodeSpecialisationTable = nodeSpecialisationInfobox.addChild("div", "class", "infobox-content").addChild("table");
addSpecialisation(nodeSpecialisationTable, myLocation, incomingRequestLocation);
}
nextTableCell = overviewTableRow.addChild("td");
int[] outgoingLocalRequestCountArray = new int[1];
int[] outgoingLocalRequestLocation = stats.getOutgoingLocalRequestLocation(outgoingLocalRequestCountArray);
int outgoingLocalRequestsCount = outgoingLocalRequestCountArray[0];
int[] outgoingRequestCountArray = new int[1];
int[] outgoingRequestLocation = stats.getOutgoingRequestLocation(outgoingRequestCountArray);
int outgoingRequestsCount = outgoingRequestCountArray[0];
if(outgoingLocalRequestsCount > 0 && outgoingRequestsCount > 0) {
HTMLNode nodeSpecialisationInfobox = nextTableCell.addChild("div", "class", "infobox");
nodeSpecialisationInfobox.addChild("div", "class", "infobox-header", "Outgoing\u00a0Request\u00a0Distribution");
HTMLNode nodeSpecialisationTable = nodeSpecialisationInfobox.addChild("div", "class", "infobox-content").addChild("table");
addCombinedSpecialisation(nodeSpecialisationTable, myLocation, outgoingLocalRequestLocation, outgoingRequestLocation);
}
overviewTableRow = overviewTable.addChild("tr");
nextTableCell = overviewTableRow.addChild("td", "class", "first");
// success rate per location
int[] locationSuccessRatesArray = stats.chkSuccessRatesByLocation.getPercentageArray(1000);
HTMLNode nodeSpecialisationInfobox = nextTableCell.addChild("div", "class", "infobox");
nodeSpecialisationInfobox.addChild("div", "class", "infobox-header", "Local\u00a0CHK\u00a0Success\u00a0Rates\u00a0By\u00a0Location");
HTMLNode nodeSpecialisationTable = nodeSpecialisationInfobox.addChild("div", "class", "infobox-content").addChild("table");
addSpecialisation(nodeSpecialisationTable, myLocation, locationSuccessRatesArray);
nextTableCell = overviewTableRow.addChild("td");
// FOAF link-length distribution box
HTMLNode foafLinkInfobox = nextTableCell.addChild("div", "class", "infobox");
foafLinkInfobox.addChild("div", "class", "infobox-header", "FOAF\u00a0Link-Length\u00a0Distribution");
HTMLNode foafLinkTable = foafLinkInfobox.addChild("div", "class", "infobox-content").addChild("table");
addFOAFLinkLengthHistogram(foafLinkTable, peerNodeStatuses);
}
}