propagate from branch 'i2p.i2p.zzz.test' (head ff7193c72f9811a641627eb08d5183b3f7af9306)

to branch 'i2p.i2p' (head b71194946fd76128f523e88f918a5c3a9b2c12e1)
This commit is contained in:
zzz
2009-02-01 01:31:24 +00:00
63 changed files with 482 additions and 436 deletions

View File

@ -40,6 +40,7 @@ import net.i2p.data.i2cp.MessagePayloadMessage;
import net.i2p.data.i2cp.SessionId;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@ -369,7 +370,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Notified availability for session " + _sessionId + ", message " + id);
}
SimpleTimer.getInstance().addEvent(new VerifyUsage(mid), 30*1000);
SimpleScheduler.getInstance().addEvent(new VerifyUsage(mid), 30*1000);
}
private class VerifyUsage implements SimpleTimer.TimedEvent {
private Long _msgId;

View File

@ -24,6 +24,7 @@ import net.i2p.data.PublicKey;
import net.i2p.data.SessionKey;
import net.i2p.data.SessionTag;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@ -70,7 +71,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
_inboundTagSets = new HashMap(1024);
context.statManager().createRateStat("crypto.sessionTagsExpired", "How many tags/sessions are expired?", "Encryption", new long[] { 10*60*1000, 60*60*1000, 3*60*60*1000 });
context.statManager().createRateStat("crypto.sessionTagsRemaining", "How many tags/sessions are remaining after a cleanup?", "Encryption", new long[] { 10*60*1000, 60*60*1000, 3*60*60*1000 });
SimpleTimer.getInstance().addEvent(new CleanupEvent(), 60*1000);
SimpleScheduler.getInstance().addPeriodicEvent(new CleanupEvent(), 60*1000);
}
private TransientSessionKeyManager() { this(null); }
@ -80,7 +81,6 @@ class TransientSessionKeyManager extends SessionKeyManager {
int expired = aggressiveExpire();
long expireTime = _context.clock().now() - beforeExpire;
_context.statManager().addRateData("crypto.sessionTagsExpired", expired, expireTime);
SimpleTimer.getInstance().addEvent(CleanupEvent.this, 60*1000);
}
}

View File

@ -344,8 +344,9 @@ public class DataHelper {
long rv = 0;
for (int i = 0; i < numBytes; i++) {
long cur = rawStream.read() & 0xFF;
long cur = rawStream.read();
if (cur == -1) throw new DataFormatException("Not enough bytes for the field");
cur &= 0xFF;
// we loop until we find a nonzero byte (or we reach the end)
if (cur != 0) {
// ok, data found, now iterate through it to fill the rv
@ -355,9 +356,10 @@ public class DataHelper {
cur = cur << shiftAmount;
rv += cur;
if (j + 1 < remaining) {
cur = rawStream.read() & 0xFF;
cur = rawStream.read();
if (cur == -1)
throw new DataFormatException("Not enough bytes for the field");
cur &= 0xFF;
}
}
break;

View File

@ -156,7 +156,7 @@ public class RequestLeaseSetMessage extends I2CPMessageImpl {
return buf.toString();
}
private class TunnelEndpoint {
private static class TunnelEndpoint {
private Hash _router;
private TunnelId _tunnelId;
@ -186,4 +186,4 @@ public class RequestLeaseSetMessage extends I2CPMessageImpl {
_tunnelId = tunnelId;
}
}
}
}

View File

@ -55,7 +55,7 @@ public final class ByteCache {
_maxCached = maxCachedEntries;
_entrySize = entrySize;
_lastOverflow = -1;
SimpleTimer.getInstance().addEvent(new Cleanup(), CLEANUP_FREQUENCY);
SimpleScheduler.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY);
_log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class);
}
@ -120,7 +120,6 @@ public final class ByteCache {
_log.debug("Removing " + toRemove + " cached entries of size " + _entrySize);
}
}
SimpleTimer.getInstance().addEvent(Cleanup.this, CLEANUP_FREQUENCY);
}
}
}

View File

@ -0,0 +1,164 @@
package net.i2p.util;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import net.i2p.I2PAppContext;
/**
* Simple event scheduler - toss an event on the queue and it gets fired at the
* appropriate time. The method that is fired however should NOT block (otherwise
* they b0rk the timer).
*
* This is like SimpleScheduler but addEvent() for an existing event adds a second
* job. Events cannot be cancelled or rescheduled.
*
* For events that cannot or will not be cancelled or rescheduled -
* for example, a call such as:
* SimpleTimer.getInstance().addEvent(new FooEvent(bar), timeoutMs);
* use SimpleScheduler instead to reduce lock contention in SimpleTimer...
*
* For periodic events, use addPeriodicEvent(). Unlike SimpleTimer,
* uncaught Exceptions will not prevent subsequent executions.
*
* @author zzz
*/
public class SimpleScheduler {
private static final SimpleScheduler _instance = new SimpleScheduler();
public static SimpleScheduler getInstance() { return _instance; }
private static final int THREADS = 4;
private I2PAppContext _context;
private Log _log;
private ScheduledThreadPoolExecutor _executor;
private String _name;
private int _count;
protected SimpleScheduler() { this("SimpleScheduler"); }
protected SimpleScheduler(String name) {
_context = I2PAppContext.getGlobalContext();
_log = _context.logManager().getLog(SimpleScheduler.class);
_name = name;
_count = 0;
_executor = new ScheduledThreadPoolExecutor(THREADS, new CustomThreadFactory());
}
/**
* Removes the SimpleScheduler.
*/
public void stop() {
_executor.shutdownNow();
}
/**
* Queue up the given event to be fired no sooner than timeoutMs from now.
*
* @param event
* @param timeoutMs
*/
public void addEvent(SimpleTimer.TimedEvent event, long timeoutMs) {
if (event == null)
throw new IllegalArgumentException("addEvent null");
RunnableEvent re = new RunnableEvent(event, timeoutMs);
re.schedule();
}
public void addPeriodicEvent(SimpleTimer.TimedEvent event, long timeoutMs) {
addPeriodicEvent(event, timeoutMs, timeoutMs);
}
/**
* Queue up the given event to be fired after initialDelay and every
* timeoutMs thereafter. The TimedEvent must not do its own rescheduling.
* As all Exceptions are caught in run(), these will not prevent
* subsequent executions (unlike SimpleTimer, where the TimedEvent does
* its own rescheduling)
*
* @param event
* @param initialDelay (ms)
* @param timeoutMs
*/
public void addPeriodicEvent(SimpleTimer.TimedEvent event, long initialDelay, long timeoutMs) {
if (event == null)
throw new IllegalArgumentException("addEvent null");
RunnableEvent re = new PeriodicRunnableEvent(event, initialDelay, timeoutMs);
re.schedule();
}
private class CustomThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread rv = Executors.defaultThreadFactory().newThread(r);
rv.setName(_name + ' ' + (++_count) + '/' + THREADS);
rv.setDaemon(true);
return rv;
}
}
/**
* Same as SimpleTimer.TimedEvent but use run() instead of timeReached(), and remembers the time
*/
private class RunnableEvent implements Runnable {
protected SimpleTimer.TimedEvent _timedEvent;
protected long _scheduled;
public RunnableEvent(SimpleTimer.TimedEvent t, long timeoutMs) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating w/ delay " + timeoutMs + " : " + t);
_timedEvent = t;
_scheduled = timeoutMs + System.currentTimeMillis();
}
public void schedule() {
_executor.schedule(this, _scheduled - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
public void run() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Running: " + _timedEvent);
long before = System.currentTimeMillis();
if (_log.shouldLog(Log.WARN) && before < _scheduled - 100)
_log.warn(_name + " wtf, early execution " + (_scheduled - before) + ": " + _timedEvent);
else if (_log.shouldLog(Log.WARN) && before > _scheduled + 1000)
_log.warn(" wtf, late execution " + (before - _scheduled) + ": " + _timedEvent + debug());
try {
_timedEvent.timeReached();
} catch (Throwable t) {
_log.log(Log.CRIT, _name + " wtf, event borked: " + _timedEvent, t);
}
long time = System.currentTimeMillis() - before;
if (time > 1000 && _log.shouldLog(Log.WARN))
_log.warn(_name + " wtf, event execution took " + time + ": " + _timedEvent);
long completed = _executor.getCompletedTaskCount();
if (_log.shouldLog(Log.INFO) && completed % 250 == 0)
_log.info(debug());
}
}
/** Run every timeoutMs. TimedEvent must not do its own reschedule via addEvent() */
private class PeriodicRunnableEvent extends RunnableEvent {
private long _timeoutMs;
private long _initialDelay;
public PeriodicRunnableEvent(SimpleTimer.TimedEvent t, long initialDelay, long timeoutMs) {
super(t, timeoutMs);
_initialDelay = initialDelay;
_timeoutMs = timeoutMs;
_scheduled = initialDelay + System.currentTimeMillis();
}
public void schedule() {
_executor.scheduleWithFixedDelay(this, _initialDelay, _timeoutMs, TimeUnit.MILLISECONDS);
}
public void run() {
super.run();
_scheduled = _timeoutMs + System.currentTimeMillis();
}
}
private String debug() {
return
" Pool: " + _name +
" Active: " + _executor.getActiveCount() + '/' + _executor.getPoolSize() +
" Completed: " + _executor.getCompletedTaskCount() +
" Queued: " + _executor.getQueue().size();
}
}