Changeset ea4dd12


Ignore:
Timestamp:
Sep 27, 2015 3:10:59 PM (6 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
3ea8b47
Parents:
a13552dd
Message:

SimpleTimer2:

  • Fix bug in forceReschedule() that caused subsequent uncaught IllegalStateException?; forceReschedule() is only used by streaming timers
  • Log uncaught exceptions
  • Enforce 5 second minimum delay for periodic events
  • atomic count
  • de-wtf
File:
1 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/util/SimpleTimer2.java

    ra13552dd rea4dd12  
    77import java.util.concurrent.TimeUnit;
    88import java.util.concurrent.ThreadFactory;
     9import java.util.concurrent.atomic.AtomicInteger;
    910
    1011import net.i2p.I2PAppContext;
     
    3940    private final ScheduledThreadPoolExecutor _executor;
    4041    private final String _name;
    41     private volatile int _count;
     42    private final AtomicInteger _count = new AtomicInteger();
    4243    private final int _threads;
    4344
     
    103104            if (t != null) { // shoudn't happen, caught in RunnableEvent.run()
    104105                Log log = I2PAppContext.getGlobalContext().logManager().getLog(SimpleTimer2.class);
    105                 log.log(Log.CRIT, "wtf, event borked: " + r, t);
     106                log.log(Log.CRIT, "event borked: " + r, t);
    106107            }
    107108        }
     
    111112        public Thread newThread(Runnable r) {
    112113            Thread rv = Executors.defaultThreadFactory().newThread(r);
    113             rv.setName(_name + ' ' + (++_count) + '/' + _threads);
     114            rv.setName(_name + ' ' + _count.incrementAndGet() + '/' + _threads);
    114115// Uncomment this to test threadgrouping, but we should be all safe now that the constructor preallocates!
    115116//            String name = rv.getThreadGroup().getName();
     
    165166     *
    166167     * @since 0.9.20
    167      * @param timeoutMs run first and subsequent iterations of this event every timeoutMs ms
     168     * @param timeoutMs run subsequent iterations of this event every timeoutMs ms, 5000 minimum
     169     * @throws IllegalArgumentException if timeoutMs less than 5000
    168170     */
    169171    public void addPeriodicEvent(final SimpleTimer.TimedEvent event, final long timeoutMs) {
     
    184186     * @since 0.9.20
    185187     * @param delay run the first iteration of this event after delay ms
    186      * @param timeoutMs run subsequent iterations of this event every timeoutMs ms
     188     * @param timeoutMs run subsequent iterations of this event every timeoutMs ms, 5000 minimum
     189     * @throws IllegalArgumentException if timeoutMs less than 5000
    187190     */
    188191    public void addPeriodicEvent(final SimpleTimer.TimedEvent event, final long delay,  final long timeoutMs) {
     
    287290            if (_log.shouldLog(Log.DEBUG))
    288291                _log.debug("Scheduling: " + this + " timeout = " + timeoutMs + " state: " + _state);
    289             if (timeoutMs <= 0 && _log.shouldLog(Log.WARN))
     292            if (timeoutMs <= 0) {
     293                if (_log.shouldLog(Log.WARN))
     294                    _log.warn("Timeout <= 0: " + this + " timeout = " + timeoutMs + " state: " + _state);
    290295                timeoutMs = 1; // otherwise we may execute before _future is updated, which is fine
    291296                               // except it triggers 'early execution' warning logging
     297            }
    292298
    293299            // always set absolute time of execution
     
    353359         */
    354360        public synchronized void forceReschedule(long timeoutMs) {
    355             cancel();
     361            // don't cancel while running!
     362            if (_state == TimedEventState.SCHEDULED)
     363                cancel();
    356364            schedule(timeoutMs);
    357365        }
    358366
    359         /** returns true if cancelled */
     367        /** @return true if cancelled */
    360368        public synchronized boolean cancel() {
    361369            // always clear
     
    379387
    380388        public void run() {
     389            try {
     390                run2();
     391            } catch (RuntimeException re) {
     392                _log.error("timer error", re);
     393                throw re;
     394            }
     395        }
     396
     397        private void run2() {
    381398            if (_log.shouldLog(Log.DEBUG))
    382399                _log.debug("Running: " + this);
     
    385402            synchronized(this) {
    386403                if (_rescheduleAfterRun)
    387                     throw new IllegalStateException("rescheduleAfterRun cannot be true here");
     404                    throw new IllegalStateException(this + " rescheduleAfterRun cannot be true here");
    388405               
    389406                switch(_state) {
     
    392409                  case IDLE:  // fall through
    393410                  case RUNNING:
    394                     throw new IllegalStateException("not possible to be in " + _state);
     411                    throw new IllegalStateException(this + " not possible to be in " + _state);
    395412                  case SCHEDULED: // proceed, switch to IDLE in case I need to reschedule
    396413                    _state = TimedEventState.IDLE;
     
    412429                delay = _future.getDelay(TimeUnit.MILLISECONDS);
    413430            else if (_log.shouldLog(Log.WARN))
    414                 _log.warn(_pool + " wtf, no _future " + this);
     431                _log.warn(_pool + " no _future " + this);
    415432            // This can be an incorrect warning especially after a schedule(0)
    416433            if (_log.shouldLog(Log.WARN) && delay > 100)
    417                 _log.warn(_pool + " wtf, early execution " + delay + ": " + this);
     434                _log.warn(_pool + " early execution " + delay + ": " + this);
    418435            else if (_log.shouldLog(Log.WARN) && delay < -1000)
    419                 _log.warn(" wtf, late execution " + (0 - delay) + ": " + this + _pool.debug());
     436                _log.warn(" late execution " + (0 - delay) + ": " + this + _pool.debug());
    420437            try {
    421438                timeReached();
     
    427444                      case SCHEDULED:  // fall through
    428445                      case IDLE:
    429                         throw new IllegalStateException("can't be " + _state);
     446                        throw new IllegalStateException(this + " can't be " + _state);
    430447                      case CANCELLED:
    431448                        break; // nothing
     
    442459            long time = System.currentTimeMillis() - before;
    443460            if (time > 500 && _log.shouldLog(Log.WARN))
    444                 _log.warn(_pool + " wtf, event execution took " + time + ": " + this);
     461                _log.warn(_pool + " event execution took " + time + ": " + this);
    445462            if (_log.shouldLog(Log.INFO)) {
    446463                 // this call is slow - iterates through a HashMap -
     
    471488    }
    472489
     490    /** warning - slow */
    473491    private String debug() {
    474492        _executor.purge();  // Remove cancelled tasks from the queue so we get a good queue size stat
     
    491509         *
    492510         * @param delay run the first iteration of this event after delay ms
    493          * @param timeoutMs run subsequent iterations of this event every timeoutMs ms
     511         * @param timeoutMs run subsequent iterations of this event every timeoutMs ms, 5000 minimum
     512         * @throws IllegalArgumentException if timeoutMs less than 5000
    494513         */
    495514        public PeriodicTimedEvent(SimpleTimer2 pool, long delay, long timeoutMs) {
    496515            super(pool, delay);
     516            if (timeoutMs < 5000)
     517                throw new IllegalArgumentException("timeout minimum 5000");
    497518            _timeoutMs = timeoutMs;
    498519        }
Note: See TracChangeset for help on using the changeset viewer.