/* This code is part of Freenet. It is distributed under the GNU General
* Public License, version 2 (or at your option any later version). See
* http://www.gnu.org/ for further details of the GPL. */
package freenet.node;
import java.net.InetAddress;
import java.util.Map;
import freenet.clients.http.DarknetConnectionsToadlet;
import freenet.io.comm.FreenetInetAddress;
import freenet.io.comm.Peer;
import freenet.io.xfer.PacketThrottle;
import freenet.node.PeerNode.IncomingLoadSummaryStats;
/**
* 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@freenetproject.org>
* @version $Id$
*/
public class PeerNodeStatus {
/** This is the preferred string form of the address. */
private final String peerAddress;
/** This one is always an IP address or null. */
private final String peerAddressNumerical;
/** This one is always an IP address or null. */
private final byte[] peerAddressBytes;
private final int peerPort;
private final int statusValue;
private final String statusName;
private final String statusCSSName;
private final double location;
private final double[] peersLocation;
private final String version;
private final int simpleVersion;
private final long routingBackoffLengthRT;
private final long routingBackoffLengthBulk;
private final long routingBackedOffUntilRT;
private final long routingBackedOffUntilBulk;
private final boolean connected;
private final boolean routable;
private final boolean isFetchingARK;
private final boolean isOpennet;
private final double averagePingTime;
private final double averagePingTimeCorrected;
private final boolean publicInvalidVersion;
private final boolean publicReverseInvalidVersion;
private final double backedOffPercentRT;
private final double backedOffPercentBulk;
private String lastBackoffReasonRT;
private String lastBackoffReasonBulk;
private long timeLastRoutable;
private long timeLastConnectionCompleted;
private long peerAddedTime;
private Map<String,Long> localMessagesReceived;
private Map<String,Long> localMessagesSent;
private final int hashCode;
private final double pReject;
private long totalBytesIn;
private long totalBytesOut;
private long totalBytesInSinceStartup;
private long totalBytesOutSinceStartup;
private double percentTimeRoutableConnection;
private PacketThrottle throttle;
private long clockDelta;
private final boolean recordStatus;
private final boolean isSeedServer;
private final boolean isSeedClient;
private final boolean isSearchable;
private final long resendBytesSent;
private final int reportedUptimePercentage;
private final double selectionRate;
private final long messageQueueLengthBytes;
private final long messageQueueLengthTime;
// int's because that's what they are transferred as
public final IncomingLoadSummaryStats incomingLoadStatsRealTime;
public final IncomingLoadSummaryStats incomingLoadStatsBulk;
public final boolean hasFullNoderef;
PeerNodeStatus(PeerNode peerNode, boolean noHeavy) {
Peer p = peerNode.getPeer();
if(p == null) {
peerAddress = null;
peerAddressNumerical = null;
peerAddressBytes = null;
peerPort = -1;
} else {
FreenetInetAddress a = p.getFreenetAddress();
peerAddress = a.toString();
InetAddress i = a.getAddress(false);
if(i != null) {
peerAddressNumerical = i.getHostAddress();
peerAddressBytes = i.getAddress();
} else {
peerAddressNumerical = null;
peerAddressBytes = null;
}
peerPort = p.getPort();
}
this.selectionRate = peerNode.selectionRate();
this.statusValue = peerNode.getPeerNodeStatus();
this.statusName = peerNode.getPeerNodeStatusString();
this.statusCSSName = peerNode.getPeerNodeStatusCSSClassName();
this.location = peerNode.getLocation();
this.peersLocation = peerNode.getPeersLocation();
this.version = peerNode.getVersion();
this.simpleVersion = peerNode.getSimpleVersion();
this.routingBackoffLengthRT = peerNode.getRoutingBackoffLength(true);
this.routingBackoffLengthBulk = peerNode.getRoutingBackoffLength(false);
this.routingBackedOffUntilRT = peerNode.getRoutingBackedOffUntil(true);
this.routingBackedOffUntilBulk = peerNode.getRoutingBackedOffUntil(false);
this.connected = peerNode.isConnected();
this.routable = peerNode.isRoutable();
this.isFetchingARK = peerNode.isFetchingARK();
this.isOpennet = peerNode.isOpennet();
this.averagePingTime = peerNode.averagePingTime();
this.averagePingTimeCorrected = peerNode.averagePingTimeCorrected();
this.publicInvalidVersion = peerNode.publicInvalidVersion();
this.publicReverseInvalidVersion = peerNode.publicReverseInvalidVersion();
this.backedOffPercentRT = peerNode.backedOffPercentRT.currentValue();
this.backedOffPercentBulk = peerNode.backedOffPercentBulk.currentValue();
this.lastBackoffReasonRT = peerNode.getLastBackoffReason(true);
this.lastBackoffReasonBulk = peerNode.getLastBackoffReason(false);
this.timeLastRoutable = peerNode.timeLastRoutable();
this.timeLastConnectionCompleted = peerNode.timeLastConnectionCompleted();
this.peerAddedTime = peerNode.getPeerAddedTime();
if(!noHeavy) {
this.localMessagesReceived = peerNode.getLocalNodeReceivedMessagesFromStatistic();
this.localMessagesSent = peerNode.getLocalNodeSentMessagesToStatistic();
} else {
this.localMessagesReceived = null;
this.localMessagesSent = null;
}
this.hashCode = peerNode.hashCode;
this.pReject = peerNode.getPRejected();
this.totalBytesIn = peerNode.getTotalInputBytes();
this.totalBytesOut = peerNode.getTotalOutputBytes();
this.totalBytesInSinceStartup = peerNode.getTotalInputSinceStartup();
this.totalBytesOutSinceStartup = peerNode.getTotalOutputSinceStartup();
this.percentTimeRoutableConnection = peerNode.getPercentTimeRoutableConnection();
this.throttle = peerNode.getThrottle();
this.clockDelta = peerNode.getClockDelta();
this.recordStatus = peerNode.recordStatus();
this.isSeedClient = peerNode instanceof SeedClientPeerNode;
this.isSeedServer = peerNode instanceof SeedServerPeerNode;
this.isSearchable = peerNode.isRealConnection();
this.resendBytesSent = peerNode.getResendBytesSent();
this.reportedUptimePercentage = peerNode.getUptime();
messageQueueLengthBytes = peerNode.getMessageQueueLengthBytes();
messageQueueLengthTime = peerNode.getProbableSendQueueTime();
incomingLoadStatsRealTime = peerNode.getIncomingLoadStats(true);
incomingLoadStatsBulk = peerNode.getIncomingLoadStats(false);
hasFullNoderef = peerNode.hasFullNoderef();
}
public long getMessageQueueLengthBytes() {
return messageQueueLengthBytes;
}
public long getMessageQueueLengthTime() {
return messageQueueLengthTime;
}
/**
* @return the localMessagesReceived
*/
public Map<String, Long> getLocalMessagesReceived() {
return localMessagesReceived;
}
/**
* @return the localMessagesSent
*/
public Map<String, Long> getLocalMessagesSent() {
return localMessagesSent;
}
/**
* @return the peerAddedTime
*/
public long getPeerAddedTime() {
return peerAddedTime;
}
/**
* Counts the peers in <code>peerNodes</code> that have the specified
* status.
* @param peerNodeStatuses The peer nodes' statuses
* @param status The status to count
* @return The number of peers that have the specified status.
*/
public static int getPeerStatusCount(PeerNodeStatus[] peerNodeStatuses, int status) {
int count = 0;
for (PeerNodeStatus peerNodeStatus: peerNodeStatuses) {
if (peerNodeStatus.getStatusValue() == status) {
count++;
}
}
return count;
}
/**
* @return the timeLastConnectionCompleted
*/
public long getTimeLastConnectionCompleted() {
return timeLastConnectionCompleted;
}
/**
* @return the backedOffPercent
*/
public double getBackedOffPercent(boolean realTime) {
return realTime ? backedOffPercentRT : backedOffPercentBulk;
}
/**
* @return the lastBackoffReason
*/
public String getLastBackoffReason(boolean realTime) {
return realTime ? lastBackoffReasonRT : lastBackoffReasonBulk;
}
/**
* @return the timeLastRoutable
*/
public long getTimeLastRoutable() {
return timeLastRoutable;
}
/**
* @return the publicInvalidVersion
*/
public boolean isPublicInvalidVersion() {
return publicInvalidVersion;
}
/**
* @return the publicReverseInvalidVersion
*/
public boolean isPublicReverseInvalidVersion() {
return publicReverseInvalidVersion;
}
/**
* @return the averagePingTime
*/
public double getAveragePingTime() {
return averagePingTime;
}
/**
* @return The ping time for purposes of retransmissions.
*/
public double getAveragePingTimeCorrected() {
return averagePingTimeCorrected;
}
/**
* @return the getRoutingBackedOffUntil
*/
public long getRoutingBackedOffUntil(boolean realTime) {
return realTime ? routingBackedOffUntilRT : routingBackedOffUntilBulk;
}
/**
* @return the location
*/
public double getLocation() {
return location;
}
public double[] getPeersLocation() {
return peersLocation;
}
/**
* @return the peerAddress, in its preferred string format.
*/
public String getPeerAddress() {
return peerAddress;
}
/**
* @return the peer address, in numerical form, or null if not known.
*/
public String getPeerAddressNumerical() {
return peerAddressNumerical;
}
/**
* @return the peer address, as raw bytes, or null if not known.
*/
public byte[] getPeerAddressBytes() {
return peerAddressBytes;
}
/**
* @return the peerPort
*/
public int getPeerPort() {
return peerPort;
}
/**
* @return the routingBackoffLength
*/
public long getRoutingBackoffLength(boolean realTime) {
return realTime ? routingBackoffLengthRT : routingBackoffLengthBulk;
}
/**
* @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 connected
*/
public boolean isConnected() {
return connected;
}
/**
* @return the routable
*/
public boolean isRoutable() {
return routable;
}
/**
* @return the isFetchingARK
*/
public boolean isFetchingARK() {
return isFetchingARK;
}
/**
* @return the isOpennet
*/
public boolean isOpennet() {
return isOpennet;
}
/**
* @return the simpleVersion
*/
public int getSimpleVersion() {
return simpleVersion;
}
@Override
public String toString() {
return statusName + ' ' + peerAddress + ':' + peerPort + ' ' + location + ' ' + version + " RT backoff: " + routingBackoffLengthRT + " (" + (Math.max(routingBackedOffUntilRT - System.currentTimeMillis(), 0)) + " ) bulk backoff: " + routingBackoffLengthBulk + " (" + (Math.max(routingBackedOffUntilBulk - System.currentTimeMillis(), 0)) + ')';
}
@Override
public int hashCode() {
return hashCode;
}
public double getPReject() {
return pReject;
}
public long getTotalInputBytes() {
return totalBytesIn;
}
public long getTotalOutputBytes() {
return totalBytesOut;
}
public long getTotalInputSinceStartup() {
return totalBytesInSinceStartup;
}
public long getTotalOutputSinceStartup() {
return totalBytesOutSinceStartup;
}
public double getPercentTimeRoutableConnection() {
return percentTimeRoutableConnection;
}
public PacketThrottle getThrottle() {
return throttle;
}
public long getClockDelta() {
return clockDelta;
}
public boolean recordStatus() {
return recordStatus;
}
public boolean isSeedServer() {
return isSeedServer;
}
public boolean isSeedClient() {
return isSeedClient;
}
public boolean isSearchable() {
return isSearchable;
}
public long getResendBytesSent() {
return resendBytesSent;
}
public int getReportedUptimePercentage() {
return reportedUptimePercentage;
}
public double getSelectionRate() {
return selectionRate;
}
}