/*
* Copyright 2004 - 2008 Christian Sprajc, Dennis Waldherr. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
package de.dal33t.powerfolder.transfer;
import java.util.Map;
import java.util.TimerTask;
import java.util.WeakHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import de.dal33t.powerfolder.event.ListenerSupportFactory;
import de.dal33t.powerfolder.util.logging.Loggable;
/**
* A BandwidthProvider can be used to periodically assign BandwidthLimiters a
* given amount of bandwidth. It uses a one Thread solution to perform this.
* $Id$
*
* @author Dennis "Dante" Waldherr
* @version $Revision: 1.5 $
*/
public class BandwidthProvider extends Loggable {
// ms between bandwidth "pushs"
public static final int PERIOD = 1000;
private final Map<BandwidthLimiter, Long> limits = new WeakHashMap<BandwidthLimiter, Long>();
private ScheduledExecutorService scheduledES;
private ScheduledFuture<?> task;
private final BandwidthStatsListener statListenerSupport = ListenerSupportFactory
.createListenerSupport(BandwidthStatsListener.class);
public BandwidthProvider() {
scheduledES = Executors.newScheduledThreadPool(1);
}
public void start() {
task = scheduledES.scheduleAtFixedRate(new TimerTask() {
public void run() {
synchronized (limits) {
for (Map.Entry<BandwidthLimiter, Long> me : limits
.entrySet())
{
BandwidthLimiter limiter = me.getKey();
if (limiter == null) {
continue;
}
// Set new limit and distribute the stat from the
// previous period.
Long value = me.getValue();
BandwidthStat stat = limiter.setAvailable(value > 0
? PERIOD * value / 1000
: BandwidthLimiter.UNLIMITED);
statListenerSupport.handleBandwidthStat(stat);
}
}
}
}, 0, PERIOD, TimeUnit.MILLISECONDS);
}
public void shutdown() {
if (task != null) {
task.cancel(true);
}
scheduledES.shutdownNow();
}
/**
* Sets the bps for the given limiter.
*
* @param limiter
* @param bps
* the number of bandwidth per second to apply. 0 will set the
* limiter to unlimited bandwidth. If you want to stop granting
* bandwidth, remove the limiter. If the parameter is negativ,
* nothing happens.
*/
public void setLimitBPS(BandwidthLimiter limiter, long bps) {
if (bps >= 0) {
synchronized (limits) {
limits.put(limiter, bps);
}
logFiner("Bandwidth limiter " + limiter + " initalized, max CPS: " + bps);
}
}
/**
* Returns the limit for a given limiter.
*
* @param limiter
* @return the bps limit for the given limiter
*/
public long getLimitBPS(BandwidthLimiter limiter) {
synchronized (limits) {
try {
return limits.get(limiter);
} catch (NullPointerException npe) {
return -1;
}
}
}
/**
* Removes a limiter from getting bandwidth pushed. (This class only holds
* weak references to BandwidthLimiters, so even if you don't call this
* method the limiters get removed as soon as the garbage collector clears
* them)
*
* @param limiter
* the limiter to remove
*/
public void removeLimiter(BandwidthLimiter limiter) {
synchronized (limits) {
limits.remove(limiter);
}
}
public void addBandwidthStatListener(BandwidthStatsListener listener) {
ListenerSupportFactory.addListener(statListenerSupport, listener);
}
public void removeBandwidthStatListener(BandwidthStatsListener listener) {
ListenerSupportFactory.addListener(statListenerSupport, listener);
}
}