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 &lt;bombe at freenetproject.org&gt;
+ * @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)) + ")";
+       }
+
+}


Reply via email to