111 lines
2.9 KiB
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);
|
|
}
|
|
}
|