Author: bombe
Date: 2006-08-10 06:24:42 +0000 (Thu, 10 Aug 2006)
New Revision: 10015
Added:
trunk/freenet/src/freenet/node/PeerNodeStatus.java
Modified:
trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/PeerManager.java
trunk/freenet/src/freenet/node/PeerNode.java
Log:
fix race conditions when creating darknet connections page
Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
2006-08-10 02:16:18 UTC (rev 10014)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
2006-08-10 06:24:42 UTC (rev 10015)
@@ -22,6 +22,7 @@
import freenet.node.FSParseException;
import freenet.node.Node;
import freenet.node.PeerNode;
+import freenet.node.PeerNodeStatus;
import freenet.support.HTMLNode;
import freenet.support.MultiValueTable;
import freenet.support.SimpleFieldSet;
@@ -63,10 +64,10 @@
* @param status The status to count
* @return The number of peers that have the specified status.
*/
- private int getPeerStatusCount(int[] peerNodeStatuses, int status) {
+ private int getPeerStatusCount(PeerNodeStatus[] peerNodeStatuses, int
status) {
int count = 0;
for (int peerIndex = 0, peerCount = peerNodeStatuses.length;
peerIndex < peerCount; peerIndex++) {
- if (peerNodeStatuses[peerIndex] == status) {
+ if (peerNodeStatuses[peerIndex].getStatusValue() ==
status) {
count++;
}
}
@@ -87,13 +88,13 @@
final boolean advancedEnabled =
node.getToadletContainer().isAdvancedDarknetEnabled();
/* gather connection statistics */
- PeerNode[] peerNodes = node.getDarknetConnections();
+ PeerNodeStatus[] peerNodeStatuses = node.getPeerNodeStatuses();
- Arrays.sort(peerNodes, new Comparator() {
+ Arrays.sort(peerNodeStatuses, new Comparator() {
public int compare(Object first, Object second) {
- PeerNode firstNode = (PeerNode) first;
- PeerNode secondNode = (PeerNode) second;
- int statusDifference =
firstNode.getPeerNodeStatus() - secondNode.getPeerNodeStatus();
+ PeerNodeStatus firstNode = (PeerNodeStatus)
first;
+ PeerNodeStatus secondNode = (PeerNodeStatus)
second;
+ int statusDifference =
firstNode.getStatusValue() - secondNode.getStatusValue();
if (statusDifference != 0) {
return statusDifference;
}
@@ -101,12 +102,6 @@
}
});
- /* copy peer node statuses for consistent display. */
- int[] peerNodeStatuses = new int[peerNodes.length];
- for (int peerIndex = 0, peerCount = peerNodes.length; peerIndex
< peerCount; peerIndex++) {
- peerNodeStatuses[peerIndex] =
peerNodes[peerIndex].getPeerNodeStatus();
- }
-
int numberOfConnected = getPeerStatusCount(peerNodeStatuses,
Node.PEER_NODE_STATUS_CONNECTED);
int numberOfRoutingBackedOff =
getPeerStatusCount(peerNodeStatuses, Node.PEER_NODE_STATUS_ROUTING_BACKED_OFF);
int numberOfTooNew = getPeerStatusCount(peerNodeStatuses,
Node.PEER_NODE_STATUS_TOO_NEW);
@@ -265,7 +260,7 @@
}
HTMLNode peerTableInfoboxContent =
peerTableInfobox.addChild("div", "class", "infobox-content");
- if (peerNodes.length == 0) {
+ if (peerNodeStatuses.length == 0) {
peerTableInfoboxContent.addChild("#", "Freenet can not
work as you have not added any peers so far. Please go to the ");
peerTableInfoboxContent.addChild("a", "href", "/",
"node homepage");
peerTableInfoboxContent.addChild("#", " and read the
top infobox to see how it is done.");
@@ -287,67 +282,67 @@
}
peerTableHeaderRow.addChild("th").addChild("span", new
String[] { "title", "style" }, new String[] { "How long since the node
connected or was last seen", "border-bottom: 1px dotted; cursor: help;" },
"Connected\u00a0/\u00a0Idle");
- for (int peerIndex = 0, peerCount = peerNodes.length;
peerIndex < peerCount; peerIndex++) {
- PeerNode peerNode = peerNodes[peerIndex];
+ for (int peerIndex = 0, peerCount =
peerNodeStatuses.length; peerIndex < peerCount; peerIndex++) {
+ PeerNodeStatus peerNodeStatus =
peerNodeStatuses[peerIndex];
HTMLNode peerRow = peerTable.addChild("tr");
// check box column
- peerRow.addChild("td", "class",
"peer-marker").addChild("input", new String[] { "type", "name" }, new String[]
{ "checkbox", "node_" + peerNode.hashCode() });
+ peerRow.addChild("td", "class",
"peer-marker").addChild("input", new String[] { "type", "name" }, new String[]
{ "checkbox", "node_" + peerNodeStatus.hashCode() });
// status column
- String statusString =
peerNode.getPeerNodeStatusString();
- if (!advancedEnabled &&
(peerNode.getPeerNodeStatus() == Node.PEER_NODE_STATUS_ROUTING_BACKED_OFF)) {
+ String statusString =
peerNodeStatus.getStatusName();
+ if (!advancedEnabled &&
(peerNodeStatus.getStatusValue() == Node.PEER_NODE_STATUS_ROUTING_BACKED_OFF)) {
statusString = "BUSY";
}
- peerRow.addChild("td", "class",
"peer-status").addChild("span", "class",
peerNode.getPeerNodeStatusCSSClassName(), statusString +
(peerNode.isFetchingARK() ? "*" : ""));
+ peerRow.addChild("td", "class",
"peer-status").addChild("span", "class", peerNodeStatus.getStatusCSSName(),
statusString + (peerNodeStatus.isFetchingARK() ? "*" : ""));
// name column
- if (peerNode.isConnected() &&
(Integer.parseInt(peerNode.getSimpleVersion()) > 476)) {
- peerRow.addChild("td", "class",
"peer-name").addChild("a", "href", "/send_n2ntm/?peernode_hashcode=" +
peerNode.hashCode(), peerNode.getName());
+ if ((peerNodeStatus.getStatusValue() ==
Node.PEER_NODE_STATUS_CONNECTED) &&
(Integer.parseInt(peerNodeStatus.getSimpleVersion()) > 476)) {
+ peerRow.addChild("td", "class",
"peer-name").addChild("a", "href", "/send_n2ntm/?peernode_hashcode=" +
peerNodeStatus.hashCode(), peerNodeStatus.getName());
} else {
- peerRow.addChild("td", "class",
"peer-name").addChild("#", peerNode.getName());
+ peerRow.addChild("td", "class",
"peer-name").addChild("#", peerNodeStatus.getName());
}
// address column
if (advancedEnabled) {
String pingTime = "";
- if (peerNode.isConnected()) {
- pingTime = " (" +
String.valueOf((int) peerNode.averagePingTime()) + "ms)";
+ if (peerNodeStatus.getStatusValue() ==
Node.PEER_NODE_STATUS_CONNECTED) {
+ pingTime = " (" + (int)
peerNodeStatus.getAveragePingTime() + "ms)";
}
- peerRow.addChild("td", "class",
"peer-address").addChild("#", ((peerNode.getDetectedPeer() != null) ?
(peerNode.getDetectedPeer().toString()) : ("(unknown address)")) + pingTime);
+ peerRow.addChild("td", "class",
"peer-address").addChild("#", ((peerNodeStatus.getPeerAddress() != null) ?
(peerNodeStatus.getPeerAddress() + peerNodeStatus.getPeerPort()) : ("(unknown
address)")) + pingTime);
}
// version column
- if (peerNode.publicReverseInvalidVersion()) {
- peerRow.addChild("td", "class",
"peer-version").addChild("span", "class", "peer_too_new", advancedEnabled ?
peerNode.getVersion() : peerNode.getSimpleVersion());
+ if
(peerNodeStatus.isPublicReverseInvalidVersion()) {
+ peerRow.addChild("td", "class",
"peer-version").addChild("span", "class", "peer_too_new", advancedEnabled ?
peerNodeStatus.getVersion() : peerNodeStatus.getSimpleVersion());
} else {
- peerRow.addChild("td", "class",
"peer-version").addChild("#", advancedEnabled ? peerNode.getVersion() :
peerNode.getSimpleVersion());
+ peerRow.addChild("td", "class",
"peer-version").addChild("#", advancedEnabled ? peerNodeStatus.getVersion() :
peerNodeStatus.getSimpleVersion());
}
// location column
if (advancedEnabled) {
- peerRow.addChild("td", "class",
"peer-location", String.valueOf(peerNode.getLocation().getValue()));
+ peerRow.addChild("td", "class",
"peer-location", String.valueOf(peerNodeStatus.getLocation()));
}
// backoff column
if (advancedEnabled) {
HTMLNode backoffCell =
peerRow.addChild("td", "class", "peer-backoff");
- backoffCell.addChild("#",
fix1.format(peerNode.backedOffPercent.currentValue()));
- int backoff = (int)
(Math.max(peerNode.getRoutingBackedOffUntil() - now, 0));
+ backoffCell.addChild("#",
fix1.format(peerNodeStatus.getBackedOffPercent()));
+ int backoff = (int)
(Math.max(peerNodeStatus.getRoutingBackedOffUntil() - now, 0));
// Don't list the backoff as zero
before it's actually zero
if ((backoff > 0) && (backoff < 1000)) {
backoff = 1000;
}
- backoffCell.addChild("#", " " +
String.valueOf(backoff / 1000) + "/" +
String.valueOf(peerNode.getRoutingBackoffLength() / 1000));
- backoffCell.addChild("#",
(peerNode.getLastBackoffReason() == null) ? "" : ("/" +
(peerNode.getLastBackoffReason())));
+ backoffCell.addChild("#", " " +
String.valueOf(backoff / 1000) + "/" +
String.valueOf(peerNodeStatus.getRoutingBackoffLength() / 1000));
+ backoffCell.addChild("#",
(peerNodeStatus.getLastBackoffReason() == null) ? "" : ("/" +
(peerNodeStatus.getLastBackoffReason())));
}
// idle column
- long idle = peerNode.timeLastRoutable();
- if(peerNode.isRoutable()) {
- idle =
peerNode.timeLastConnectionCompleted();
- } else if(peerNodeStatuses[peerIndex] ==
Node.PEER_NODE_STATUS_NEVER_CONNECTED) {
- idle = peerNode.getPeerAddedTime();
+ long idle =
peerNodeStatus.getTimeLastRoutable();
+ if (peerNodeStatus.getStatusValue() ==
Node.PEER_NODE_STATUS_CONNECTED) {
+ idle =
peerNodeStatus.getTimeLastConnectionCompleted();
+ } else if (peerNodeStatus.getStatusValue() ==
Node.PEER_NODE_STATUS_NEVER_CONNECTED) {
+ idle =
peerNodeStatus.getPeerAddedTime();
}
peerRow.addChild("td", "class", "peer-idle",
idleToString(now, idle));
@@ -362,18 +357,18 @@
countHeaderRow.addChild("th",
"Outgoing");
List messageNames = new ArrayList();
Map messageCounts = new HashMap();
- for (Iterator incomingMessages =
peerNode.getLocalNodeReceivedMessagesFromStatistic().keySet().iterator();
incomingMessages.hasNext(); ) {
+ for (Iterator incomingMessages =
peerNodeStatus.getLocalMessagesReceived().keySet().iterator();
incomingMessages.hasNext(); ) {
String messageName = (String)
incomingMessages.next();
messageNames.add(messageName);
- Long messageCount = (Long)
peerNode.getLocalNodeReceivedMessagesFromStatistic().get(messageName);
+ Long messageCount = (Long)
peerNodeStatus.getLocalMessagesReceived().get(messageName);
messageCounts.put(messageName,
new Long[] { messageCount, new Long(0) });
}
- for (Iterator outgoingMessages =
peerNode.getLocalNodeSentMessagesToStatistic().keySet().iterator();
outgoingMessages.hasNext(); ) {
+ for (Iterator outgoingMessages =
peerNodeStatus.getLocalMessagesSent().keySet().iterator();
outgoingMessages.hasNext(); ) {
String messageName = (String)
outgoingMessages.next();
if
(!messageNames.contains(messageName)) {
messageNames.add(messageName);
}
- Long messageCount = (Long)
peerNode.getLocalNodeSentMessagesToStatistic().get(messageName);
+ Long messageCount = (Long)
peerNodeStatus.getLocalMessagesSent().get(messageName);
Long[] existingCounts =
(Long[]) messageCounts.get(messageName);
if (existingCounts == null) {
messageCounts.put(messageName, new Long[] { new Long(0), messageCount });
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2006-08-10 02:16:18 UTC (rev
10014)
+++ trunk/freenet/src/freenet/node/Node.java 2006-08-10 06:24:42 UTC (rev
10015)
@@ -3783,6 +3783,14 @@
PeerManager pm = peers;
return pm.myPeers;
}
+
+ public PeerNodeStatus[] getPeerNodeStatuses() {
+ PeerNodeStatus[] peerNodeStatuses = new
PeerNodeStatus[peers.myPeers.length];
+ for (int peerIndex = 0, peerCount = peers.myPeers.length;
peerIndex < peerCount; peerIndex++) {
+ peerNodeStatuses[peerIndex] =
peers.myPeers[peerIndex].getStatus();
+ }
+ return peerNodeStatuses;
+ }
public void registerIPDetectorPlugin(FredPluginIPDetector detector) {
ipDetectorManager.register(detector);
Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java 2006-08-10 02:16:18 UTC
(rev 10014)
+++ trunk/freenet/src/freenet/node/PeerManager.java 2006-08-10 06:24:42 UTC
(rev 10015)
@@ -523,7 +523,7 @@
String[] status = new String[peers.length];
for(int i=0;i<peers.length;i++) {
PeerNode pn = peers[i];
- status[i] = pn.getStatus();
+ status[i] = pn.getStatus().toString();
Version.seenVersion(pn.getVersion());
}
Arrays.sort(status);
Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java 2006-08-10 02:16:18 UTC
(rev 10014)
+++ trunk/freenet/src/freenet/node/PeerNode.java 2006-08-10 06:24:42 UTC
(rev 10015)
@@ -1628,10 +1628,11 @@
}
}
- public String getStatus() {
- return getPeerNodeStatusString() + " " + getPeer()+" "+getName()+"
"+getLocation().getValue()+" "+getVersion()+" backoff:
"+getRoutingBackoffLength()+" ("+(Math.max(getRoutingBackedOffUntil() -
System.currentTimeMillis(),0))+")";
+ public synchronized PeerNodeStatus getStatus() {
+ PeerNodeStatus peerNodeStatus = new PeerNodeStatus(this);
+ return peerNodeStatus;
}
-
+
public String getTMCIPeerInfo() {
long now = System.currentTimeMillis();
int idle = -1;
@@ -1644,7 +1645,7 @@
}
public String getFreevizOutput() {
- return getStatus()+"|"+ Base64.encode(identity);
+ return getStatus().toString()+"|"+ Base64.encode(identity);
}
public synchronized String getVersion(){
Added: trunk/freenet/src/freenet/node/PeerNodeStatus.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNodeStatus.java 2006-08-10 02:16:18 UTC
(rev 10014)
+++ trunk/freenet/src/freenet/node/PeerNodeStatus.java 2006-08-10 06:24:42 UTC
(rev 10015)
@@ -0,0 +1,275 @@
+package freenet.node;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import freenet.clients.http.DarknetConnectionsToadlet;
+
+/**
+ * Contains various status information for a {@link PeerNode}. Used e.g. in
+ * {@link DarknetConnectionsToadlet} to reduce race-conditions while creating
+ * the page.
+ *
+ * @author David 'Bombe' Roden <bombe at freenetproject.org>
+ * @version $Id$
+ */
+public class PeerNodeStatus {
+
+ private final String name;
+
+ private final String peerAddress;
+
+ private final int peerPort;
+
+ private final int statusValue;
+
+ private final String statusName;
+
+ private final String statusCSSName;
+
+ private final double location;
+
+ private final String version;
+
+ private final String simpleVersion;
+
+ private final int routingBackoffLength;
+
+ private final long routingBackedOffUntil;
+
+ private final boolean burstOnly;
+
+ private final boolean listening;
+
+ private final boolean disabled;
+
+ private final boolean connected;
+
+ private final boolean isFetchingARK;
+
+ private final double averagePingTime;
+
+ private final boolean publicReverseInvalidVersion;
+
+ private final double backedOffPercent;
+
+ private String lastBackoffReason;
+
+ private long timeLastRoutable;
+
+ private long timeLastConnectionCompleted;
+
+ private long peerAddedTime;
+
+ private Map localMessagesReceived;
+
+ private Map localMessagesSent;
+
+ public PeerNodeStatus(PeerNode peerNode) {
+ this.name = peerNode.getName();
+ this.peerAddress = (peerNode.getDetectedPeer() != null) ?
peerNode.getDetectedPeer().getFreenetAddress().toString() : null;
+ this.peerPort = (peerNode.getDetectedPeer() != null) ?
peerNode.getDetectedPeer().getPort() : -1;
+ this.statusValue = peerNode.getPeerNodeStatus();
+ this.statusName = peerNode.getPeerNodeStatusString();
+ this.statusCSSName = peerNode.getPeerNodeStatusCSSClassName();
+ this.location = peerNode.getLocation().getValue();
+ this.version = peerNode.getVersion();
+ this.simpleVersion = peerNode.getSimpleVersion();
+ this.routingBackoffLength = peerNode.getRoutingBackoffLength();
+ this.routingBackedOffUntil =
peerNode.getRoutingBackedOffUntil();
+ this.burstOnly = peerNode.isBurstOnly();
+ this.listening = peerNode.isListenOnly();
+ this.disabled = peerNode.isDisabled();
+ this.connected = peerNode.isConnected();
+ this.isFetchingARK = peerNode.isFetchingARK();
+ this.averagePingTime = peerNode.averagePingTime();
+ this.publicReverseInvalidVersion =
peerNode.publicReverseInvalidVersion();
+ this.backedOffPercent =
peerNode.backedOffPercent.currentValue();
+ this.lastBackoffReason = peerNode.getLastBackoffReason();
+ this.timeLastRoutable = peerNode.timeLastRoutable();
+ this.timeLastConnectionCompleted =
peerNode.timeLastConnectionCompleted();
+ this.peerAddedTime = peerNode.getPeerAddedTime();
+ this.localMessagesReceived = new
Hashtable(peerNode.getLocalNodeReceivedMessagesFromStatistic());
+ this.localMessagesSent = new
Hashtable(peerNode.getLocalNodeSentMessagesToStatistic());
+ }
+
+ /**
+ * @return the localMessagesReceived
+ */
+ public Map getLocalMessagesReceived() {
+ return localMessagesReceived;
+ }
+
+ /**
+ * @return the localMessagesSent
+ */
+ public Map getLocalMessagesSent() {
+ return localMessagesSent;
+ }
+
+ /**
+ * @return the peerAddedTime
+ */
+ public long getPeerAddedTime() {
+ return peerAddedTime;
+ }
+
+ /**
+ * @return the timeLastConnectionCompleted
+ */
+ public long getTimeLastConnectionCompleted() {
+ return timeLastConnectionCompleted;
+ }
+
+ /**
+ * @return the backedOffPercent
+ */
+ public double getBackedOffPercent() {
+ return backedOffPercent;
+ }
+
+ /**
+ * @return the lastBackoffReason
+ */
+ public String getLastBackoffReason() {
+ return lastBackoffReason;
+ }
+
+ /**
+ * @return the timeLastRoutable
+ */
+ public long getTimeLastRoutable() {
+ return timeLastRoutable;
+ }
+
+ /**
+ * @return the publicReverseInvalidVersion
+ */
+ public boolean isPublicReverseInvalidVersion() {
+ return publicReverseInvalidVersion;
+ }
+
+ /**
+ * @return the averagePingTime
+ */
+ public double getAveragePingTime() {
+ return averagePingTime;
+ }
+
+ /**
+ * @return the getRoutingBackedOffUntil
+ */
+ public long getRoutingBackedOffUntil() {
+ return routingBackedOffUntil;
+ }
+
+ /**
+ * @return the location
+ */
+ public double getLocation() {
+ return location;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the peerAddress
+ */
+ public String getPeerAddress() {
+ return peerAddress;
+ }
+
+ /**
+ * @return the peerPort
+ */
+ public int getPeerPort() {
+ return peerPort;
+ }
+
+ /**
+ * @return the routingBackoffLength
+ */
+ public int getRoutingBackoffLength() {
+ return routingBackoffLength;
+ }
+
+ /**
+ * @return the statusCSSName
+ */
+ public String getStatusCSSName() {
+ return statusCSSName;
+ }
+
+ /**
+ * @return the statusName
+ */
+ public String getStatusName() {
+ return statusName;
+ }
+
+ /**
+ * @return the statusValue
+ */
+ public int getStatusValue() {
+ return statusValue;
+ }
+
+ /**
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * @return the burstOnly
+ */
+ public boolean isBurstOnly() {
+ return burstOnly;
+ }
+
+ /**
+ * @return the connected
+ */
+ public boolean isConnected() {
+ return connected;
+ }
+
+ /**
+ * @return the disabled
+ */
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ /**
+ * @return the isFetchingARK
+ */
+ public boolean isFetchingARK() {
+ return isFetchingARK;
+ }
+
+ /**
+ * @return the listening
+ */
+ public boolean isListening() {
+ return listening;
+ }
+
+ /**
+ * @return the simpleVersion
+ */
+ public String getSimpleVersion() {
+ return simpleVersion;
+ }
+
+ public String toString() {
+ return statusName + " " + peerAddress + ":" + peerPort + " " +
name + " " + location + " " + version + " backoff: " + routingBackoffLength + "
(" + (Math.max(routingBackedOffUntil - System.currentTimeMillis(), 0)) + ")";
+ }
+
+}