Javadoc, imports, and (potentially) some indentation. Maybe it won't do anything.... who knows?

(shendaras)
This commit is contained in:
shendaras
2004-04-10 09:12:59 +00:00
committed by zzz
parent e3a86bb150
commit 99790695a2
6 changed files with 468 additions and 152 deletions

View File

@ -1,14 +1,14 @@
package net.i2p.heartbeat;
import net.i2p.data.Destination;
import net.i2p.data.DataFormatException;
import net.i2p.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.Log;
/**
* Define the configuration for testing against one particular peer as a client
*
@ -26,17 +26,63 @@ public class ClientConfig {
private String _comment;
private int _averagePeriods[];
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_PREFIX = "peer.";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_PEER = ".peer";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_STATFILE = ".statFile";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_STATDURATION = ".statDuration";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_STATFREQUENCY = ".statFrequency";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_SENDFREQUENCY = ".sendFrequency";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_SENDSIZE = ".sendSize";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_COMMENT = ".comment";
/**
* @seeRoutine ClientConfig#load
* @seeRoutine ClientConfig#store
*/
public static final String PROP_AVERAGEPERIODS = ".averagePeriods";
/**
* Default constructor...
*/
public ClientConfig() {
this(null, null, null, -1, -1, -1, -1, 0, null, null);
}
@ -65,64 +111,135 @@ public class ClientConfig {
_averagePeriods = averagePeriods;
}
/** peer to test against */
/** Retrieves the peer to test against
* @return the Destination (peer)
*/
public Destination getPeer() { return _peer; }
/**
* Sets the peer to test against
* @param peer the Destination (peer)
*/
public void setPeer(Destination peer) { _peer = peer; }
/** who we are when we test */
/**
* Retrieves who we are when we test
* @return the Destination (us)
*/
public Destination getUs() { return _us; }
/**
* Sets who we are when we test
* @param us the Destination (us)
*/
public void setUs(Destination us) { _us = us; }
/** location to write the current stats to */
/**
* Retrieves the location to write the current stats to
* @return the name of the file
*/
public String getStatFile() { return _statFile; }
/**
* Sets the name of the location we write the current stats to
* @param statFile the name of the file
*/
public void setStatFile(String statFile) { _statFile = statFile; }
/** how many minutes of statistics should be maintained within the window for this client? */
/**
* Retrieves how many minutes of statistics should be maintained within the window for this client
* @return the number of minutes
*/
public int getStatDuration() { return _statDuration; }
/**
* Sets how many minutes of statistics should be maintained within the window for this client
* @param durationMinutes the number of minutes
*/
public void setStatDuration(int durationMinutes) { _statDuration = durationMinutes; }
/** how frequenty the stats are written out (in seconds) */
/**
* Retrieves how frequently the stats are written out (in seconds)
* @return the frequency in seconds
*/
public int getStatFrequency() { return _statFrequency; }
/**
* Sets how frequently the stats are written out (in seconds)
* @param freqSeconds the frequency in seconds
*/
public void setStatFrequency(int freqSeconds) { _statFrequency = freqSeconds; }
/** how frequenty we send messages to the peer (in seconds) */
/**
* Retrieves how frequenty we send messages to the peer (in seconds)
* @return the frequency in seconds
*/
public int getSendFrequency() { return _sendFrequency; }
/**
* Sets how frequenty we send messages to the peer (in seconds)
* @param freqSeconds the frequency in seconds
*/
public void setSendFrequency(int freqSeconds) { _sendFrequency = freqSeconds; }
/**
* How many bytes should the ping messages be (min values ~700, max ~32KB)?
*
* Retrieves how many bytes the ping messages should be
* (min values ~700, max ~32KB)
* @return the size in bytes
*/
public int getSendSize() { return _sendSize; }
/**
* Sets how many bytes the ping messages should be
* (min values ~700, max ~32KB)
* @param numBytes the size in bytes
*/
public void setSendSize(int numBytes) { _sendSize = numBytes; }
/**
* Brief 1 line description of the test. Useful comments are along the lines
* of "The peer is located on a fast router and connection with 2 hop tunnels".
* Retrieves the brief, 1 line description of the test.
* Useful comments are along the lines of "The peer is located on a fast router and connection with 2 hop tunnels".
*
* @return the brief comment
*/
public String getComment() { return _comment; }
/**
* Sets a brief, 1 line description (comment) of the test.
* @param comment the brief comment
*/
public void setComment(String comment) { _comment = comment; }
/**
* Periods that the client's tests should be averaged over.
*
* Retrieves the periods that the client's tests should be averaged over.
* @return list of periods (in minutes) that the data should be averaged over, or null
*/
public int[] getAveragePeriods() { return _averagePeriods; }
/**
* Sets the periods that the client's tests should be averaged over.
* @param periods the list of periods (in minutes) that the data should be averaged over, or null
*/
public void setAveragePeriods(int periods[]) { _averagePeriods = periods; }
/**
* How many hops is this test engine configured to use for its outbound and inbound tunnels?
*
* Retrieves how many hops this test engine is configured to use for its outbound and inbound tunnels
* @return the number of hops
*/
public int getNumHops() { return _numHops; }
/**
* Sets how many hops this test engine is configured to use for its outbound and inbound tunnels
* @param numHops the number of hops
*/
public void setNumHops(int numHops) { _numHops = numHops; }
/**
* Load the client config from the properties specified, deriving the current
* config entry from the peer number.
*
* @param clientConfig the properties to load from
* @param peerNum the number associated with the peer
* @return true if it was loaded correctly, false if there were errors
*/
public boolean load(Properties clientConfig, int peerNum) {
@ -138,8 +255,9 @@ public class ClientConfig {
if ( (peerVal == null) || (statFileVal == null) || (statDurationVal == null) ||
(statFrequencyVal == null) || (sendFrequencyVal == null) || (sendSizeVal == null) ) {
if (_log.shouldLog(Log.DEBUG))
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("Peer number "+ peerNum + " does not exist");
}
return false;
}
@ -151,24 +269,28 @@ public class ClientConfig {
int sendSize = getInt(sendSizeVal);
if ( (duration <= 0) || (statFreq <= 0) || (sendFreq <= 0) || (sendSize <= 0) ) {
if (_log.shouldLog(Log.WARN))
if (_log.shouldLog(Log.WARN)) {
_log.warn("Invalid client config: duration [" + statDurationVal + "] stat frequency [" + statFrequencyVal +
"] send frequency [" + sendFrequencyVal + "] send size [" + sendSizeVal + "]");
}
return false;
}
statFileVal = statFileVal.trim();
if (statFileVal.length() <= 0) {
if (_log.shouldLog(Log.WARN))
if (_log.shouldLog(Log.WARN)) {
_log.warn("Stat file is blank for peer " + peerNum);
}
return false;
}
Destination d = new Destination();
d.fromBase64(peerVal);
if (commentVal == null)
if (commentVal == null) {
commentVal = "";
}
commentVal = commentVal.trim();
commentVal = commentVal.replace('\n', '_');
@ -178,13 +300,15 @@ public class ClientConfig {
while (tok.hasMoreTokens()) {
String periodVal = tok.nextToken();
int minutes = getInt(periodVal);
if (minutes > 0)
if (minutes > 0) {
periods.add(new Integer(minutes));
}
}
}
int avgPeriods[] = new int[periods.size()];
for (int i = 0; i < periods.size(); i++)
for (int i = 0; i < periods.size(); i++) {
avgPeriods[i] = ((Integer)periods.get(i)).intValue();
}
_comment = commentVal;
_statDuration = duration;
@ -205,6 +329,8 @@ public class ClientConfig {
* Store the client config to the properties specified, deriving the current
* config entry from the peer number.
*
* @param clientConfig the properties to store to
* @param peerNum the number associated with the peer
* @return true if it was stored correctly, false if there were errors
*/
public boolean store(Properties clientConfig, int peerNum) {
@ -214,8 +340,10 @@ public class ClientConfig {
}
String comment = _comment;
if (comment == null)
if (comment == null) {
comment = "";
}
comment = comment.trim();
comment = comment.replace('\n', '_');
@ -243,8 +371,9 @@ public class ClientConfig {
int i = Integer.parseInt(val);
return i;
} catch (NumberFormatException nfe) {
if (_log.shouldLog(Log.DEBUG))
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("Value [" + val + "] is not a valid integer");
}
return -1;
}
}

View File

@ -2,8 +2,8 @@ package net.i2p.heartbeat;
import net.i2p.data.Destination;
import net.i2p.util.Clock;
import net.i2p.util.Log;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Responsible for actually conducting the tests, coordinating the storing of the
@ -13,7 +13,7 @@ import net.i2p.util.I2PThread;
*/
class ClientEngine {
private static final Log _log = new Log(ClientEngine.class);
/** who can send our pings/ */
/** who can send our pings? */
private Heartbeat _heartbeat;
/** actual test state */
private PeerData _data;
@ -28,7 +28,8 @@ class ClientEngine {
/**
* Create a new engine that will send its pings through the given heartbeat
* system, and will coordinate the test according to the configuration specified.
*
* @param heartbeat the Heartbeat to send pings through
* @param config the Configuration to load configuration from =p
*/
public ClientEngine(Heartbeat heartbeat, ClientConfig config) {
_heartbeat = heartbeat;
@ -50,10 +51,18 @@ class ClientEngine {
t.setName("HeartbeatClient " + _id);
t.start();
}
/** who are we testing? */
/**
* Who are we testing?
* @return the Destination (peer) we're testing
*/
public Destination getPeer() { return _data.getConfig().getPeer(); }
/** what is our series identifier (used to locally identify a test) */
/**
* What is our series identifier (used to locally identify a test)
* @return the series identifier
*/
public int getSeriesNum() { return _id; }
/**
* receive notification from the heartbeat system that a pong was received in
* reply to a ping we have sent.
@ -74,6 +83,10 @@ class ClientEngine {
/** our actual heartbeat pumper - this drives the test */
private class ClientRunner implements Runnable {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
if (_log.shouldLog(Log.INFO))
_log.info("Starting engine talking to peer " + _data.getConfig().getPeer().calculateHash().toBase64());

View File

@ -1,18 +1,16 @@
package net.i2p.heartbeat;
import net.i2p.util.Log;
import net.i2p.util.Clock;
import net.i2p.data.Destination;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Iterator;
import java.util.Date;
import net.i2p.data.Destination;
import net.i2p.util.Log;
/**
* Main driver for the heartbeat engine, loading 0 or more tests, firing
@ -73,7 +71,10 @@ public class Heartbeat {
/** if there are no command line arguments, load the config from "heartbeat.config" */
public static final String CONFIG_FILE_DEFAULT = "heartbeat.config";
/** build up a new heartbeat manager, but don't actually do anything */
/**
* build up a new heartbeat manager, but don't actually do anything
* @param configFile the name of the configuration file
*/
public Heartbeat(String configFile) {
_configFile = configFile;
_clientConfigs = new HashMap();
@ -94,8 +95,9 @@ public class Heartbeat {
fin = new FileInputStream(_configFile);
props.load(fin);
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error reading the config data", ioe);
}
} finally {
if (fin != null) try { fin.close(); } catch (IOException ioe) {}
}
@ -119,18 +121,25 @@ public class Heartbeat {
_adapter.sendPing(peer, seriesNum, now, size);
}
/** load up the base data (I2CP config, etc) */
/**
* load up the base data (I2CP config, etc)
* @param props the properties to load from
*/
private void loadBaseConfig(Properties props) {
_adapter.loadConfig(props);
}
/** load up all of the test config data */
/**
* load up all of the test config data
* @param props the properties to load from
* */
private void loadClientConfigs(Properties props) {
int i = 0;
while (true) {
ClientConfig config = new ClientConfig();
if (!config.load(props, i))
if (!config.load(props, i)) {
break;
}
_clientConfigs.put(new Integer(i), config);
i++;
}
@ -174,14 +183,17 @@ public class Heartbeat {
* running any tests. <p />
*
* <code> <b>Usage: </b> Heartbeat [<i>configFileName</i>]</code> <p />
* @param args the list of args passed to the program from the command-line
*/
public static void main(String args[]) {
String configFile = CONFIG_FILE_DEFAULT;
if (args.length == 1)
if (args.length == 1) {
configFile = args[0];
}
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("Starting up with config file " + configFile);
}
Heartbeat heartbeat = new Heartbeat(configFile);
heartbeat.loadConfig();
heartbeat.connect();
@ -210,9 +222,10 @@ public class Heartbeat {
* @param data arbitrary payload data
*/
public void receivePing(Destination from, int seriesNum, Date sentOn, byte[] data) {
if (_adapter.getIsConnected())
if (_adapter.getIsConnected()) {
_adapter.sendPong(from, seriesNum, sentOn, data);
}
}
/**
* We received a pong, so find the right client engine and tell it about the pong.
@ -225,9 +238,10 @@ public class Heartbeat {
*/
public void receivePong(Destination from, int seriesNum, Date sentOn, Date replyOn, byte[] data) {
ClientEngine engine = (ClientEngine)_clientEngines.get(new Integer(seriesNum));
if (engine.getPeer().equals(from))
if (engine.getPeer().equals(from)) {
engine.receivePong(sentOn.getTime(), replyOn.getTime());
}
}
}
}

View File

@ -1,28 +1,26 @@
package net.i2p.heartbeat;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Date;
import java.util.Arrays;
import java.util.Date;
import java.util.Properties;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.client.I2PClientFactory;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PSessionListener;
import net.i2p.I2PException;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.Log;
import net.i2p.util.Clock;
import net.i2p.util.Log;
/**
* Tie-in to the I2P SDK for the Heartbeat system, talking to the I2PSession and
@ -69,6 +67,9 @@ class I2PAdapter {
/** by default, use 2 hop tunnels */
public static final int NUMHOPS_DEFAULT = 2;
/**
* Constructs an I2PAdapter . . .
*/
public I2PAdapter() {
_privateDestFile = null;
_i2cpHost = null;
@ -79,22 +80,40 @@ class I2PAdapter {
_numHops = 0;
}
/** who are we? */
/**
* who are we?
* @return the destination (us)
*/
public Destination getLocalDestination() { return _localDest; }
/** who gets notified when we receive a ping or a pong? */
/**
* who gets notified when we receive a ping or a pong?
* @return the event listener who gets notified
*/
public PingPongEventListener getListener() { return _listener; }
/**
* Sets who gets notified when we receive a ping or a pong
* @param listener the event listener to get notified
*/
public void setListener(PingPongEventListener listener) { _listener = listener; }
/** how many hops do we want in our tunnels? */
/**
* how many hops do we want in our tunnels?
* @return the number of hops
*/
public int getNumHops() { return _numHops; }
/** are we connected? */
/**
* are we connected?
* @return true or false . . .
*/
public boolean getIsConnected() { return _session != null; }
/**
* Read in all of the config data
*
* @param props the properties to load from
*/
void loadConfig(Properties props) {
String privDestFile = props.getProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT);
@ -106,16 +125,18 @@ class I2PAdapter {
try {
portNum = Integer.parseInt(port);
} catch (NumberFormatException nfe) {
if (_log.shouldLog(Log.WARN))
if (_log.shouldLog(Log.WARN)) {
_log.warn("Invalid I2CP port specified [" + port + "]");
}
portNum = I2CP_PORT_DEFAULT;
}
int hops = -1;
try {
hops = Integer.parseInt(numHops);
} catch (NumberFormatException nfe) {
if (_log.shouldLog(Log.WARN))
if (_log.shouldLog(Log.WARN)) {
_log.warn("Invalid # hops specified [" + numHops + "]");
}
hops = NUMHOPS_DEFAULT;
}
@ -125,20 +146,29 @@ class I2PAdapter {
_i2cpPort = portNum;
}
/** write out the config to the props */
/**
* write out the config to the props
* @param props the properties to write to
*/
void storeConfig(Properties props) {
if (_privateDestFile != null)
if (_privateDestFile != null) {
props.setProperty(DEST_FILE_PROP, _privateDestFile);
else
} else {
props.setProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT);
if (_i2cpHost != null)
}
if (_i2cpHost != null) {
props.setProperty(I2CP_HOST_PROP, _i2cpHost);
else
} else {
props.setProperty(I2CP_HOST_PROP, I2CP_HOST_DEFAULT);
if (_i2cpPort > 0)
}
if (_i2cpPort > 0) {
props.setProperty(I2CP_PORT_PROP, ""+_i2cpPort);
else
} else {
props.setProperty(I2CP_PORT_PROP, ""+I2CP_PORT_DEFAULT);
}
props.setProperty(NUMHOPS_PROP, ""+_numHops);
}
@ -170,23 +200,28 @@ class I2PAdapter {
baos.write(paddingData);
boolean sent = _session.sendMessage(peer, baos.toByteArray());
if (!sent) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error sending the ping to " + peer.calculateHash().toBase64() + " for series " + seriesNum);
}
} else {
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("Ping sent to " + peer.calculateHash().toBase64() + " for series " + seriesNum);
}
}
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error sending the ping", ioe);
}
} catch (DataFormatException dfe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error writing out the ping message", dfe);
}
} catch (I2PSessionException ise) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error writing out the ping message", ise);
}
}
}
/**
* send a pong message to the peer
@ -211,27 +246,33 @@ class I2PAdapter {
baos.write(data);
boolean sent = _session.sendMessage(peer, baos.toByteArray());
if (!sent) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error sending the pong to " + peer.calculateHash().toBase64() + " for series " + seriesNum + " which was sent on " + sentOn);
}
} else {
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("Pong sent to " + peer.calculateHash().toBase64() + " for series " + seriesNum + " which was sent on " + sentOn);
}
}
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error sending the ping", ioe);
}
} catch (DataFormatException dfe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error writing out the pong message", dfe);
}
} catch (I2PSessionException ise) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error writing out the pong message", ise);
}
}
}
/**
* We've received this data from I2P - parse it into a ping or a pong
* and notify accordingly
* @param data the data to handle
*/
private void handleMessage(byte data[]) {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
@ -248,35 +289,41 @@ class I2PAdapter {
int size = (int)DataHelper.readLong(bais, 2);
byte payload[] = new byte[size];
int read = DataHelper.read(bais, payload);
if (read != size)
if (read != size) {
throw new IOException("Malformed payload - read " + read + " instead of " + size);
}
if (_listener == null) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Listener isn't set, but we received a valid message of type " + type + " sent from " + from.calculateHash().toBase64());
}
return;
}
if (type == TYPE_PING) {
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("Ping received from " + from.calculateHash().toBase64() + " on series " + series + " sent on " + sentOn + " containing " + size + " bytes");
}
_listener.receivePing(from, series, sentOn, payload);
} else if (type == TYPE_PONG) {
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("Pong received from " + from.calculateHash().toBase64() + " on series " + series + " sent on " + sentOn + " with pong sent on " + receivedOn + " containing " + size + " bytes");
}
_listener.receivePong(from, series, sentOn, receivedOn, payload);
} else {
throw new IOException("Invalid message type " + type);
}
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error handling the message", ioe);
}
} catch (DataFormatException dfe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error parsing the message", dfe);
}
}
}
/**
@ -303,17 +350,20 @@ class I2PAdapter {
session.setSessionListener(lsnr);
session.connect();
_localDest = session.getMyDestination();
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("I2CP Session created and connected as " + _localDest.calculateHash().toBase64());
}
_session = session;
_i2pListener = lsnr;
} catch (I2PSessionException ise) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error connecting", ise);
}
return false;
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error loading the destionation", ioe);
}
return false;
} finally {
if (fin != null) try { fin.close(); } catch (IOException ioe) {}
@ -325,6 +375,8 @@ class I2PAdapter {
/**
* load, verify, or create a destination
*
* @param client the client
* @param destFile the file holding the destination
* @return the destination loaded, or null if there was an error
*/
private Destination verifyDestination(I2PClient client, File destFile) {
@ -335,8 +387,9 @@ class I2PAdapter {
fin = new FileInputStream(destFile);
us = new Destination();
us.readBytes(fin);
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("Existing destination loaded: [" + us.toBase64() + "]");
}
} catch (IOException ioe) {
if (fin != null) try { fin.close(); } catch (IOException ioe2) {}
fin = null;
@ -359,15 +412,18 @@ class I2PAdapter {
try {
fos = new FileOutputStream(destFile);
us = client.createDestination(fos);
if (_log.shouldLog(Log.INFO))
if (_log.shouldLog(Log.INFO)) {
_log.info("New destination created: [" + us.toBase64() + "]");
}
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error writing out the destination keys being created", ioe);
}
return null;
} catch (I2PException ie) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error creating the destination", ie);
}
return null;
} finally {
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
@ -378,6 +434,7 @@ class I2PAdapter {
/**
* I2PSession connect options
* @return the options as Properties
*/
private Properties getOptions() {
Properties props = new Properties();
@ -395,8 +452,9 @@ class I2PAdapter {
try {
_session.destroySession();
} catch (I2PSessionException ise) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Error destroying the session", ise);
}
}
_session = null;
}
@ -434,20 +492,34 @@ class I2PAdapter {
*
*/
private class I2PListener implements I2PSessionListener {
/* (non-Javadoc)
* @see net.i2p.client.I2PSessionListener#disconnected(net.i2p.client.I2PSession)
*/
public void disconnected(I2PSession session) {
if (_log.shouldLog(Log.ERROR))
if (_log.shouldLog(Log.ERROR)) {
_log.error("Session disconnected");
}
disconnect();
}
/* (non-Javadoc)
* @see net.i2p.client.I2PSessionListener#errorOccurred(net.i2p.client.I2PSession, java.lang.String, java.lang.Throwable)
*/
public void errorOccurred(I2PSession session, String message, Throwable error) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error occurred", error);
}
/* (non-Javadoc)
* @see net.i2p.client.I2PSessionListener#reportAbuse(net.i2p.client.I2PSession, int)
*/
public void reportAbuse(I2PSession session, int severity) {
if (_log.shouldLog(Log.ERROR))
_log.error("Abuse reported");
}
/* (non-Javadoc)
* @see net.i2p.client.I2PSessionListener#messageAvailable(net.i2p.client.I2PSession, int, long)
*/
public void messageAvailable(I2PSession session, int msgId, long size) {
try {
byte data[] = session.receiveMessage(msgId);

View File

@ -1,17 +1,17 @@
package net.i2p.heartbeat;
import net.i2p.util.Clock;
import net.i2p.util.Log;
import net.i2p.stat.Rate;
import net.i2p.stat.RateStat;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import net.i2p.stat.Rate;
import net.i2p.stat.RateStat;
import net.i2p.util.Clock;
import net.i2p.util.Log;
/**
* Contain the current window of data for a particular series of ping/pong stats
* sent to a peer. This should be periodically kept clean by calling cleanup()
@ -42,6 +42,10 @@ public class PeerData {
/** synchronize on this when updating _dataPoints or _pendingPings */
private Object _updateLock = new Object();
/**
* Creates a PeerData . . .
* @param config configuration to load from
*/
public PeerData(ClientConfig config) {
_peer = config;
_dataPoints = new TreeMap();
@ -54,7 +58,11 @@ public class PeerData {
_lostRate = new RateStat("lostRate", "How frequently we lose messages", "peer", getPeriods(config.getAveragePeriods()));
}
/** turn the periods (# minutes) into rate periods (# milliseconds) */
/**
* turn the periods (# minutes) into rate periods (# milliseconds)
* @param periods (in minutes)
* @return an array of periods (in milliseconds)
*/
private static long[] getPeriods(int periods[]) {
long rv[] = null;
if (periods == null) periods = new int[0];
@ -65,22 +73,48 @@ public class PeerData {
return rv;
}
/** how many pings are still outstanding? */
/**
* how many pings are still outstanding?
* @return the number of pings outstanding
*/
public int getPendingCount() { synchronized (_updateLock) { return _pendingPings.size(); } }
/** how many data points are available in the current window? */
/**
* how many data points are available in the current window?
* @return the number of datapoints available
*/
public int getDataPointCount() { synchronized (_updateLock) { return _dataPoints.size(); } }
/** when did this test begin? */
/**
* when did this test begin?
* @return when the test began
*/
public long getSessionStart() { return _sessionStart; }
/** how many pings have we sent for this test? */
/**
* how many pings have we sent for this test?
* @return the number of pings sent
*/
public long getLifetimeSent() { return _lifetimeSent; }
/** how many pongs have we received for this test? */
/**
* how many pongs have we received for this test?
* @return the number of pings received
*/
public long getLifetimeReceived() { return _lifetimeReceived; }
/**
* @return the client configuration
*/
public ClientConfig getConfig() { return _peer; }
/**
* What periods are we averaging the data over (in minutes)?
* @return the periods as an array of ints (in minutes)
*/
public int[] getAveragePeriods() { return (_peer.getAveragePeriods() != null ? _peer.getAveragePeriods() : new int[0]); }
/**
* average time to send over the given period.
*
@ -88,6 +122,7 @@ public class PeerData {
* @return milliseconds average, or -1 if we dont track that period
*/
public double getAverageSendTime(int period) { return getAverage(_sendRate, period); }
/**
* average time to receive over the given period.
*
@ -95,6 +130,7 @@ public class PeerData {
* @return milliseconds average, or -1 if we dont track that period
*/
public double getAverageReceiveTime(int period) { return getAverage(_receiveRate, period); }
/**
* number of lost messages over the given period.
*
@ -129,7 +165,7 @@ public class PeerData {
/**
* We have sent the peer a ping on this series (using the send time as given)
*
* @param dateSent when the ping was sent
*/
public void addPing(long dateSent) {
EventDataPoint sent = new EventDataPoint(dateSent);
@ -239,9 +275,17 @@ public class PeerData {
private long _pongSent;
private long _pongReceived;
/**
* Creates an EventDataPoint
*/
public EventDataPoint() {
this(-1);
}
/**
* Creates an EventDataPoint with pingtime associated with it =)
* @param pingSentOn the time a ping was sent
*/
public EventDataPoint(long pingSentOn) {
_wasPonged = false;
_pingSent = pingSentOn;
@ -249,20 +293,51 @@ public class PeerData {
_pongReceived = -1;
}
/** when did we send this ping? */
/**
* when did we send this ping?
* @return the time the ping was sent
*/
public long getPingSent() { return _pingSent; }
/**
* Set the time the ping was sent
* @param when time to set
*/
public void setPingSent(long when) { _pingSent = when; }
/** when did the peer receive the ping? */
/**
* when did the peer receive the ping?
* @return the time the ping was receieved
*/
public long getPongSent() { return _pongSent; }
/**
* Set the time the peer received the ping
* @param when the time to set
*/
public void setPongSent(long when) { _pongSent = when; }
/** when did we receive the peer's pong? */
/**
* when did we receive the peer's pong?
* @return the time we receieved the pong
*/
public long getPongReceived() { return _pongReceived; }
/**
* Set the time the peer's pong was receieved
* @param when the time to set
*/
public void setPongReceived(long when) { _pongReceived = when; }
/** did the peer reply in time? */
/**
* did the peer reply in time?
* @return true or false, whether we got a reply in time */
public boolean getWasPonged() { return _wasPonged; }
/**
* Set whether we receieved the peer's reply in time
* @param pong true or false
*/
public void setWasPonged(boolean pong) { _wasPonged = pong; }
}
}

View File

@ -1,18 +1,17 @@
package net.i2p.heartbeat;
import net.i2p.util.Log;
import net.i2p.util.Clock;
import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import net.i2p.util.Clock;
import net.i2p.util.Log;
/**
* Actually write out the stats for peer test
@ -24,6 +23,7 @@ class PeerDataWriter {
/**
* persist the peer state to the location specified in the peer config
*
* @param data the peer data to persist
* @return true if it was persisted correctly, false on error
*/
public boolean persist(PeerData data) {
@ -93,12 +93,25 @@ class PeerDataWriter {
}
private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK);
/**
* Converts a time (long) to text
* @param when the time to convert
* @return the textual representation
*/
public String getTime(long when) {
synchronized (_fmt) {
return _fmt.format(new Date(when));
}
}
private static final DecimalFormat _numFmt = new DecimalFormat("#0", new DecimalFormatSymbols(Locale.UK));
/**
* Converts a number (double) to text
* @param val the number to convert
* @return the textual representation
*/
public String getNum(double val) {
synchronized (_numFmt) {
return _numFmt.format(val);