Added Simple true/false storage class to the utilities

Added socketSoTimeout
CHANGED RetransmissionTimer is now public
FIXED SimpleTimer has a way to be stopped, and reap it's children
FIXED Lots of javadoc additions, where I could
CLEANUP all code that needed to catch the timeout exception for socketSoTimeout
This commit is contained in:
sponge
2008-09-25 23:59:01 +00:00
parent ee2fd32a97
commit dd7d993631
13 changed files with 540 additions and 146 deletions

View File

@ -5,22 +5,32 @@ import java.util.List;
import net.i2p.I2PAppContext;
class Executor implements Runnable {
private I2PAppContext _context;
private Log _log;
private List _readyEvents;
public Executor(I2PAppContext ctx, Log log, List events) {
private SimpleStore runn;
public Executor(I2PAppContext ctx, Log log, List events, SimpleStore x) {
_context = ctx;
_readyEvents = events;
runn = x;
}
public void run() {
while (true) {
while(runn.getAnswer()) {
SimpleTimer.TimedEvent evt = null;
synchronized (_readyEvents) {
if (_readyEvents.size() <= 0)
try { _readyEvents.wait(); } catch (InterruptedException ie) {}
if (_readyEvents.size() > 0)
if(_readyEvents.size() <= 0) {
try {
_readyEvents.wait();
} catch(InterruptedException ie) {
}
}
if(_readyEvents.size() > 0) {
evt = (SimpleTimer.TimedEvent)_readyEvents.remove(0);
}
}
if (evt != null) {
long before = _context.clock().now();
@ -30,17 +40,24 @@ class Executor implements Runnable {
log("wtf, event borked: " + evt, t);
}
long time = _context.clock().now() - before;
if ( (time > 1000) && (_log != null) && (_log.shouldLog(Log.WARN)) )
if((time > 1000) && (_log != null) && (_log.shouldLog(Log.WARN))) {
_log.warn("wtf, event execution took " + time + ": " + evt);
}
}
}
}
/**
*
* @param msg
* @param t
*/
private void log(String msg, Throwable t) {
synchronized (this) {
if (_log == null)
if(_log == null) {
_log = I2PAppContext.getGlobalContext().logManager().getLog(SimpleTimer.class);
}
}
_log.log(Log.CRIT, msg, t);
}
}

View File

@ -0,0 +1,35 @@
/*
* This is free software, do as you please.
*/
package net.i2p.util;
/**
*
* @author sponge
*/
public class SimpleStore {
private boolean answer;
SimpleStore(boolean x) {
answer=x;
}
/**
* set the answer
*
* @param x
*/
public void setAnswer(boolean x) {
answer = x;
}
/**
*
* @return boolean
*/
public boolean getAnswer() {
return answer;
}
}

View File

@ -16,8 +16,12 @@ import net.i2p.I2PAppContext;
*
*/
public class SimpleTimer {
private static final SimpleTimer _instance = new SimpleTimer();
public static SimpleTimer getInstance() { return _instance; }
public static SimpleTimer getInstance() {
return _instance;
}
private I2PAppContext _context;
private Log _log;
/** event time (Long) to event (TimedEvent) mapping */
@ -25,9 +29,21 @@ public class SimpleTimer {
/** event (TimedEvent) to event time (Long) mapping */
private Map _eventTimes;
private List _readyEvents;
private SimpleStore runn;
/**
*
*/
protected SimpleTimer() {
this("SimpleTimer");
}
protected SimpleTimer() { this("SimpleTimer"); }
/**
*
* @param name
*/
protected SimpleTimer(String name) {
runn = new SimpleStore(true);
_context = I2PAppContext.getGlobalContext();
_log = _context.logManager().getLog(SimpleTimer.class);
_events = new TreeMap();
@ -38,13 +54,28 @@ public class SimpleTimer {
runner.setDaemon(true);
runner.start();
for (int i = 0; i < 3; i++) {
I2PThread executor = new I2PThread(new Executor(_context, _log, _readyEvents));
I2PThread executor = new I2PThread(new Executor(_context, _log, _readyEvents, runn));
executor.setName(name + "Executor " + i);
executor.setDaemon(true);
executor.start();
}
}
/**
* Removes the SimpleTimer.
*/
public void removeSimpleTimer() {
synchronized(_events) {
runn.setAnswer(false);
_events.notifyAll();
}
}
/**
*
* @param event
* @param timeoutMs
*/
public void reschedule(TimedEvent event, long timeoutMs) {
addEvent(event, timeoutMs, false);
}
@ -55,9 +86,16 @@ public class SimpleTimer {
* for the earlier of the two timeouts, which may be before this stated
* timeout. If this is not the desired behavior, call removeEvent first.
*
* @param event
* @param timeoutMs
*/
public void addEvent(TimedEvent event, long timeoutMs) { addEvent(event, timeoutMs, true); }
public void addEvent(TimedEvent event, long timeoutMs) {
addEvent(event, timeoutMs, true);
}
/**
* @param event
* @param timeoutMs
* @param useEarliestTime if its already scheduled, use the earlier of the
* two timeouts, else use the later
*/
@ -86,8 +124,9 @@ public class SimpleTimer {
}
}
}
while (_events.containsKey(time))
while(_events.containsKey(time)) {
time = new Long(time.longValue() + 1);
}
_events.put(time, event);
_eventTimes.put(event, time);
@ -107,24 +146,33 @@ public class SimpleTimer {
_events.notifyAll();
}
if (time.longValue() > eventTime + 100) {
if (_log.shouldLog(Log.WARN))
_log.warn("Lots of timer congestion, had to push " + event + " back "
+ (time.longValue()-eventTime) + "ms (# events: " + totalEvents + ")");
if(_log.shouldLog(Log.WARN)) {
_log.warn("Lots of timer congestion, had to push " + event + " back " + (time.longValue() - eventTime) + "ms (# events: " + totalEvents + ")");
}
}
long timeToAdd = System.currentTimeMillis() - now;
if (timeToAdd > 50) {
if (_log.shouldLog(Log.WARN))
if(_log.shouldLog(Log.WARN)) {
_log.warn("timer contention: took " + timeToAdd + "ms to add a job with " + totalEvents + " queued");
}
}
}
/**
*
* @param evt
* @return
*/
public boolean removeEvent(TimedEvent evt) {
if (evt == null) return false;
if(evt == null) {
return false;
}
synchronized (_events) {
Long when = (Long)_eventTimes.remove(evt);
if (when != null)
if(when != null) {
_events.remove(when);
}
return null != when;
}
}
@ -133,6 +181,7 @@ public class SimpleTimer {
* Simple interface for events to be queued up and notified on expiration
*/
public interface TimedEvent {
/**
* the time requested has been reached (this call should NOT block,
* otherwise the whole SimpleTimer gets backed up)
@ -140,15 +189,15 @@ public class SimpleTimer {
*/
public void timeReached();
}
private long _occurredTime;
private long _occurredEventCount;
private TimedEvent _recentEvents[] = new TimedEvent[5];
// not used
// private TimedEvent _recentEvents[] = new TimedEvent[5];
private class SimpleTimerRunner implements Runnable {
public void run() {
List eventsToFire = new ArrayList(1);
while (true) {
while(runn.getAnswer()) {
try {
synchronized (_events) {
//if (_events.size() <= 0)
@ -158,8 +207,10 @@ public class SimpleTimer {
long now = System.currentTimeMillis();
long nextEventDelay = -1;
Object nextEvent = null;
while (true) {
if (_events.size() <= 0) break;
while(runn.getAnswer()) {
if(_events.size() <= 0) {
break;
}
Long when = (Long)_events.firstKey();
if (when.longValue() <= now) {
TimedEvent evt = (TimedEvent)_events.remove(when);
@ -175,16 +226,15 @@ public class SimpleTimer {
}
if (eventsToFire.size() <= 0) {
if (nextEventDelay != -1) {
if (_log.shouldLog(Log.DEBUG))
if(_log.shouldLog(Log.DEBUG)) {
_log.debug("Next event in " + nextEventDelay + ": " + nextEvent);
}
_events.wait(nextEventDelay);
} else {
_events.wait();
}
}
}
} catch (ThreadDeath td) {
return; // die
} catch (InterruptedException ie) {
// ignore
} catch (Throwable t) {
@ -200,8 +250,9 @@ public class SimpleTimer {
now = now - (now % 1000);
synchronized (_readyEvents) {
for (int i = 0; i < eventsToFire.size(); i++)
for(int i = 0; i < eventsToFire.size(); i++) {
_readyEvents.add(eventsToFire.get(i));
}
_readyEvents.notifyAll();
}