package com.limegroup.gnutella; import org.limewire.collection.Buffer; /** * A helper class for implementing the BandwidthTracker interface */ public class BandwidthTrackerImpl { private static final int HISTORY_SIZE=10; /** Keep 10 clicks worth of data, which we can then average to get a more * accurate moving time average. * INVARIANT: snapShots[0]==measuredBandwidth.floatValue() */ private final Buffer<Float> snapShots = new Buffer<Float>(HISTORY_SIZE); /** * Number of times we've been bandwidth measured. */ private int numMeasures = 0; /** * Overall average throughput */ private float averageBandwidth = 0; /** * The cached getMeasuredBandwidth value. */ private float cachedBandwidth = 0; private long lastTime; /** The most recent measured bandwidth. DO NOT DELETE THIS; it exists * for backwards serialization reasons. */ private float measuredBandwidth; /** The last amount read */ private long lastAmountRead64; /** * Measures the data throughput since the last call to measureBandwidth, * assuming this has read amountRead bytes. This value can be read by * calling getMeasuredBandwidth. * * @param amountRead the cumulative amount read from this, in BYTES. * Should be larger than the argument passed in the last call to * measureBandwidth(..). */ public synchronized void measureBandwidth(long amountRead) { long currentTime=System.currentTimeMillis(); //We always discard the first sample, and any others until after //progress is made. //This prevents sudden bandwidth spikes when resuming //uploads and downloads. Remember that bytes/msec=KB/sec. if (lastAmountRead64==0 || currentTime==lastTime) { measuredBandwidth=0.f; } else { measuredBandwidth=(float)(amountRead-lastAmountRead64) / (float)(currentTime-lastTime); //Ensure positive! measuredBandwidth=Math.max(measuredBandwidth, 0.f); } lastTime=currentTime; lastAmountRead64=amountRead; averageBandwidth = (averageBandwidth*numMeasures + measuredBandwidth) / ++numMeasures; snapShots.add(new Float(measuredBandwidth)); cachedBandwidth = 0; } /** @see BandwidthTracker#getMeasuredBandwidth */ public synchronized float getMeasuredBandwidth() throws InsufficientDataException { if(cachedBandwidth != 0) return cachedBandwidth; int size = snapShots.getSize(); if (size < 3 ) throw new InsufficientDataException(); float total = 0; for(Float f : snapShots) total += f.floatValue(); cachedBandwidth = total/size; return cachedBandwidth; } /** * Returns the average overall bandwidth consumed. */ public synchronized float getAverageBandwidth() { if(snapShots.getSize() < 3) return 0f; return averageBandwidth; } }