blob: fc0ac6f12da285b5d8d02e2756647ede620ec6c7 [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je.rep.impl.node;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import com.sleepycat.je.rep.utilint.NamedChannelWithTimeout;
/**
* The ChannelTimeoutTask ensures that all channels registered with it are
* periodically checked to ensure that they are active. The period roughly
* corresponds to a second, although intervening GC activity may expand this
* period considerably. Note that elapsedMs used for timeouts is always ticked
* up in 1 second increments. Thus multiple seconds of real time may correspond
* to a single second of "timer time" if the system is paricularly busy, or the
* gc has been particularly active.
*
* This property allows the underlying timeout implementation to compensate for
* GC pauses in which activity on the channel at the java level would have been
* suspended and thus reduces the number of false timeouts.
*/
public class ChannelTimeoutTask extends TimerTask {
private final long ONE_SECOND_MS = 1000l;
/* Elapsed time as measured by the timer task. It's always incremented
* in one second intervals.
*/
private long elapsedMs = 0;
private final List<NamedChannelWithTimeout> channels =
Collections.synchronizedList(new LinkedList<NamedChannelWithTimeout>());
/**
* Creates and schedules the timer task.
* @param timer the timer associated with this task
*/
public ChannelTimeoutTask(Timer timer) {
timer.schedule(this, ONE_SECOND_MS, ONE_SECOND_MS);
}
/**
* Runs once a second checking to see if a channel is still active. Each
* channel establishes its own timeout period using elapsedMs to check for
* timeouts. Inactive channels are removed from the list of registered
* channels.
*/
@Override
public void run() {
elapsedMs += ONE_SECOND_MS;
synchronized (channels) {
for (Iterator<NamedChannelWithTimeout> i = channels.iterator();
i.hasNext();) {
if (!i.next().isActive(elapsedMs)) {
i.remove();
}
}
}
}
/**
* Registers a channel so that the timer can make periodic calls to
* isActive(). Note that closing a channel renders it inactive and causes
* it to be removed from the list by the run() method. Consequently, there
* is no corresponding unregister operation.
*
* @param channel the channel being registered.
*/
public void register(NamedChannelWithTimeout channel) {
channels.add(channel);
}
}