package net.tomp2p.p2p; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureDone; import net.tomp2p.peers.Maintainable; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerStatatistic; public class MaintenanceTask extends TimerTask { private static final Logger LOG = LoggerFactory.getLogger(MaintenanceTask.class); private static final int MAX_PING = 5; private static final AtomicInteger COUNTER = new AtomicInteger(0); private Peer peer; private int intervalMillis = 1000; private List<Maintainable> maintainables = new ArrayList<Maintainable>(); private Map<BaseFuture, PeerAddress> runningFutures = new HashMap<BaseFuture, PeerAddress>(); private boolean shutdown = false; private final Object lock = new Object(); public void init(Peer peer, Timer timer) { synchronized (lock) { this.peer = peer; } timer.scheduleAtFixedRate(this, intervalMillis, intervalMillis); } @Override public void run() { synchronized (lock) { //make sure we only have 5 ping in parallel if (shutdown || COUNTER.get() > MAX_PING) { return; } for (Maintainable maintainable : maintainables) { PeerStatatistic peerStatatistic = maintainable.nextForMaintenance(runningFutures.values()); if(peerStatatistic == null) { continue; } BaseFuture future = peer.ping().setPeerAddress(peerStatatistic.getPeerAddress()).start(); LOG.debug("maintenance ping for " + peerStatatistic.getPeerAddress()); peer.notifyAutomaticFutures(future); runningFutures.put(future, peerStatatistic.getPeerAddress()); COUNTER.incrementAndGet(); future.addListener(new BaseFutureAdapter<BaseFuture>() { @Override public void operationComplete(BaseFuture future) throws Exception { synchronized (lock) { runningFutures.remove(future); COUNTER.decrementAndGet(); } } }); } } } public FutureDone<Void> shutdown() { cancel(); final FutureDone<Void> futureShutdown = new FutureDone<Void>(); synchronized (lock) { shutdown = true; final int max = runningFutures.size(); final AtomicInteger counter = new AtomicInteger(0); for (BaseFuture future : runningFutures.keySet()) { future.addListener(new BaseFutureAdapter<BaseFuture>() { @Override public void operationComplete(BaseFuture future) throws Exception { if (counter.incrementAndGet() == max) { futureShutdown.setDone(); } } }); } } return futureShutdown; } public int getIntervalMillis() { return intervalMillis; } public void setIntervalMillis(int intervalMillis) { this.intervalMillis = intervalMillis; } public void addMaintainable(Maintainable maintainable) { maintainables.add(maintainable); } }