2005-02-22 jrandom

* Adjusted (and fixed...) the timestamper change detection
    * Deal with a rare reordering bug at the beginning of a stream (so we
      don't drop it unnecessarily)
    * Cleaned up some dropped message handling in the router
    * Reduced job queue churn when dealing with a large number of tunnels by
      sharing an expiration job
    * Keep a separate list of the most recent CRIT messages (shown on the
      logs.jsp).  This way they don't get buried among any other messages.
    * For clarity, display the tunnel variance config as "Randomization" on
      the web console.
    * If lease republishing fails (boo! hiss!) try it again
    * Actually fix the negative jobLag in the right place (this time)
    * Allow reseeding when there are less than 10 known peer references
    * Lots of logging updates.
This commit is contained in:
jrandom
2005-02-22 07:07:29 +00:00
committed by zzz
parent 35fe7f8203
commit c17433cb93
24 changed files with 280 additions and 72 deletions

View File

@ -504,7 +504,11 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
* Pass off the error to the listener
*/
void propogateError(String msg, Throwable error) {
if (_log.shouldLog(Log.ERROR)) _log.error(getPrefix() + "Error occurred: " + msg, error);
if (_log.shouldLog(Log.ERROR))
_log.error(getPrefix() + "Error occurred: " + msg + " - " + error.getMessage());
if (_log.shouldLog(Log.WARN))
_log.warn(getPrefix() + " cause", error);
if (_sessionListener != null) _sessionListener.errorOccurred(this, msg, error);
}

View File

@ -57,8 +57,8 @@ class MessagePayloadMessageHandler extends HandlerImpl {
Payload payload = msg.getPayload();
byte[] data = _context.elGamalAESEngine().decrypt(payload.getEncryptedData(), session.getDecryptionKey());
if (data == null) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error decrypting the payload");
if (_log.shouldLog(Log.WARN))
_log.warn("Error decrypting the payload");
throw new DataFormatException("Unable to decrypt the payload");
}
payload.setUnencryptedData(data);

View File

@ -26,10 +26,10 @@ public class Timestamper implements Runnable {
private boolean _initialized;
private static final int DEFAULT_QUERY_FREQUENCY = 5*60*1000;
private static final String DEFAULT_SERVER_LIST = "pool.ntp.org, pool.ntp.org";
private static final String DEFAULT_SERVER_LIST = "pool.ntp.org, pool.ntp.org, pool.ntp.org";
private static final boolean DEFAULT_DISABLED = true;
/** how many times do we have to query if we are changing the clock? */
private static final int DEFAULT_CONCURRING_SERVERS = 2;
private static final int DEFAULT_CONCURRING_SERVERS = 3;
public static final String PROP_QUERY_FREQUENCY = "time.queryFrequencyMs";
public static final String PROP_SERVER_LIST = "time.sntpServerList";
@ -109,7 +109,7 @@ public class Timestamper implements Runnable {
if (_log.shouldLog(Log.INFO))
_log.info("Starting up timestamper");
boolean alreadyBitched = false;
boolean lastFailed = false;
try {
while (true) {
updateConfig();
@ -123,14 +123,16 @@ public class Timestamper implements Runnable {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Querying servers " + _servers);
try {
queryTime(serverList);
lastFailed = !queryTime(serverList);
} catch (IllegalArgumentException iae) {
if (!alreadyBitched)
if (!lastFailed)
_log.log(Log.CRIT, "Unable to reach any of the NTP servers - network disconnected?");
alreadyBitched = true;
lastFailed = true;
}
}
long sleepTime = _context.random().nextInt(_queryFrequency) + _queryFrequency;
if (lastFailed)
sleepTime = 30*1000;
try { Thread.sleep(sleepTime); } catch (InterruptedException ie) {}
}
} catch (Throwable t) {
@ -138,39 +140,64 @@ public class Timestamper implements Runnable {
}
}
private void queryTime(String serverList[]) throws IllegalArgumentException {
/**
* True if the time was queried successfully, false if it couldn't be
*/
private boolean queryTime(String serverList[]) throws IllegalArgumentException {
long found[] = new long[serverList.length];
long localTime = -1;
long now = -1;
long expectedDelta = 0;
for (int i = 0; i < _concurringServers; i++) {
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
localTime = _context.clock().now();
now = NtpClient.currentTime(serverList);
long delta = now - localTime;
found[i] = delta;
if (i == 0) {
if (Math.abs(delta) < MAX_VARIANCE) {
if (_log.shouldLog(Log.INFO))
_log.info("a single SNTP query was within the tolerance (" + delta + "ms)");
return;
return true;
} else {
// outside the tolerance, lets iterate across the concurring queries
expectedDelta = delta;
}
} else {
if (Math.abs(delta - expectedDelta) > MAX_VARIANCE) {
if (_log.shouldLog(Log.ERROR))
_log.error("SNTP client variance exceeded at query " + i + ". expected = " + expectedDelta + ", found = " + delta);
return;
if (_log.shouldLog(Log.ERROR)) {
StringBuffer err = new StringBuffer(96);
err.append("SNTP client variance exceeded at query ").append(i);
err.append(". expected = ");
err.append(expectedDelta);
err.append(", found = ");
err.append(delta);
err.append(" all deltas: ");
for (int j = 0; j < found.length; j++)
err.append(found[j]).append(' ');
_log.error(err.toString());
}
return false;
}
}
}
stampTime(now);
if (_log.shouldLog(Log.DEBUG)) {
StringBuffer buf = new StringBuffer(64);
buf.append("Deltas: ");
for (int i = 0; i < found.length; i++)
buf.append(found[i]).append(' ');
_log.debug(buf.toString());
}
return true;
}
/**
* Send an HTTP request to a given URL specifying the current time
*/
private void stampTime(long now) {
long before = _context.clock().now();
synchronized (_listeners) {
for (int i = 0; i < _listeners.size(); i++) {
UpdateListener lsnr = (UpdateListener)_listeners.get(i);
@ -178,7 +205,7 @@ public class Timestamper implements Runnable {
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Stamped the time as " + now);
_log.debug("Stamped the time as " + now + " (delta=" + (now-before) + ")");
}
/**

View File

@ -12,10 +12,12 @@ import net.i2p.I2PAppContext;
public class LogConsoleBuffer {
private I2PAppContext _context;
private List _buffer;
private List _critBuffer;
public LogConsoleBuffer(I2PAppContext context) {
_context = context;
_buffer = new ArrayList();
_critBuffer = new ArrayList();
}
void add(String msg) {
@ -26,6 +28,14 @@ public class LogConsoleBuffer {
_buffer.add(msg);
}
}
void addCritical(String msg) {
int lim = _context.logManager().getConsoleBufferSize();
synchronized (_critBuffer) {
while (_critBuffer.size() >= lim)
_critBuffer.remove(0);
_critBuffer.add(msg);
}
}
/**
* Retrieve the currently bufferd messages, earlier values were generated...
@ -38,4 +48,15 @@ public class LogConsoleBuffer {
return new ArrayList(_buffer);
}
}
/**
* Retrieve the currently bufferd crutucak messages, earlier values were generated...
* earlier. All values are strings with no formatting (as they are written
* in the logs)
*
*/
public List getMostRecentCriticalMessages() {
synchronized (_critBuffer) {
return new ArrayList(_critBuffer);
}
}
}

View File

@ -101,6 +101,8 @@ class LogWriter implements Runnable {
// we always add to the console buffer, but only sometimes write to stdout
_manager.getBuffer().add(val);
if (rec.getPriority() >= Log.CRIT)
_manager.getBuffer().addCritical(val);
if (_manager.getDisplayOnScreenLevel() <= rec.getPriority()) {
if (_manager.displayOnScreen()) {
System.out.print(val);