/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.core.util.counters.impl;
import org.mule.runtime.core.util.counters.CounterFactory.Type;
import java.security.InvalidParameterException;
import java.util.Iterator;
import java.util.LinkedList;
public class RatePerUnit extends AggregateCounter {
private static class Sample {
private double value;
private long time;
public Sample(double value, long time) {
this.value = value;
this.time = time;
}
/**
* @return the time of the sample
*/
public long getTime() {
return time;
}
/**
* @return the value of the sample
*/
public double getValue() {
return value;
}
}
private final LinkedList<Sample> samples;
private final long unit;
private final long length;
private final long baseTime;
public RatePerUnit(String name, String p, Type type, AbstractCounter base) {
super(name, type, base);
if (type == Type.RATE_PER_SECOND) {
unit = 1000;
} else if (type == Type.RATE_PER_MINUTE) {
unit = 60 * 1000;
} else if (type == Type.RATE_PER_HOUR) {
unit = 60 * 60 * 1000;
} else {
throw new InvalidParameterException();
}
long newLength = 0;
try {
newLength = Long.parseLong(p);
} catch (Exception e) {
newLength = 0;
} finally {
if (newLength <= 0) {
newLength = 128;
}
length = newLength;
}
samples = new LinkedList<Sample>();
baseTime = System.currentTimeMillis();
}
@Override
public double nextValue() {
if (samples.isEmpty()) {
return 0.0;
} else {
double total = 0.0;
long current = getTime();
Iterator<Sample> it = samples.iterator();
Sample sample = null;
while (it.hasNext()) {
sample = it.next();
if (current - sample.time > length) {
break;
}
total += sample.value;
}
return total / (1 + current - (sample != null ? sample.time : 0));
}
}
@Override
public void doCompute() {
Sample l = samples.isEmpty() ? null : (Sample) samples.getFirst();
long t = getTime();
if (l == null || t > l.time) {
Sample s = new Sample(this.getBase().nextValue(), t);
samples.addFirst(s);
} else {
l.value += getBase().nextValue();
}
while (samples.size() > length) {
samples.removeLast();
}
}
protected long getTime() {
return (System.currentTimeMillis() - baseTime) / unit;
}
}