ctbrec-5.3.2-experimental/common/src/main/java/ctbrec/io/BandwidthMeter.java

111 lines
2.9 KiB
Java

package ctbrec.io;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BandwidthMeter {
public static final Duration MEASURE_TIMEFRAME = Duration.ofSeconds(10);
private static List<Record> records = new ArrayList<>(100);
private static Lock lock = new ReentrantLock(true);
private static List<Listener> listeners = new ArrayList<>();
private static Instant lastUpdate = Instant.EPOCH;
private BandwidthMeter() {
}
public static void add(long bytes) {
Record r = new Record(bytes);
lock.lock();
try {
records.add(r);
} finally {
lock.unlock();
}
Instant oneSecondAgo = Instant.now().minus(Duration.ofSeconds(1));
if (lastUpdate.isBefore(oneSecondAgo)) {
fireEvent(getThroughput(), MEASURE_TIMEFRAME);
lastUpdate = Instant.now();
}
}
public static void setThroughput(long bytes, Duration d) {
lock.lock();
try {
records.clear();
records.add(new Record(bytes));
} finally {
lock.unlock();
}
fireEvent(bytes, d);
}
private static void fireEvent(long throughput, Duration timeframe) {
for (Listener listener : listeners) {
listener.bandwidthCalculated(throughput, timeframe);
}
}
/**
* Get the throughput over the last 10 seconds
* @return throughput in bytes
*/
public static long getThroughput() {
return getThroughput(MEASURE_TIMEFRAME);
}
/**
* Get the throughput over the given duration
* @return throughput in bytes
*/
public static long getThroughput(Duration d) {
Instant now = Instant.now();
Instant measureStart = now.minus(d);
long throughput = 0;
lock.lock();
try {
for (Iterator<Record> iterator = records.iterator(); iterator.hasNext();) {
Record record = iterator.next();
if (record.timestamp.isBefore(measureStart)) {
iterator.remove();
} else {
throughput += record.bytes;
}
}
} finally {
lock.unlock();
}
return throughput;
}
public static void addListener(Listener l) {
listeners.add(l);
}
public static void removeListener(Listener l) {
listeners.remove(l);
}
private static class Record {
public Instant timestamp;
public long bytes;
public Record(long bytes) {
timestamp = Instant.now();
this.bytes = bytes;
}
}
@FunctionalInterface
public static interface Listener {
void bandwidthCalculated(long bytes, Duration timeframe);
}
}