package com.tesora.dve.server.statistics;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import com.tesora.dve.server.statistics.TimingValue;
public class RollingStatisticsAccumulator implements StatisticsAccumulator {
final int quantumSize; // in ms
final int accumSize;
int[] statAccum;
int[] statCount;
long lastDatumQuantum;
boolean debugMode = false;
public RollingStatisticsAccumulator(int accumSize, int quantumSize) {
this.accumSize = accumSize;
this.quantumSize = quantumSize;
statAccum = new int[accumSize];
statCount = new int[accumSize];
for (int i = 0; i < accumSize; ++i) {
statAccum[i] = 0;
statCount[i] = 0;
}
lastDatumQuantum = System.currentTimeMillis() / quantumSize;
}
@Override
public void addDatum(int responseTimeMS) {
long datumQuantum = transitionRollingCounter();
if (debugMode)
System.out.println("Datum position is " + datumQuantum % accumSize);
statAccum[(int) (datumQuantum%accumSize)] += (responseTimeMS == 0) ? 1 : responseTimeMS;
statCount[(int) (datumQuantum%accumSize)] += 1;
lastDatumQuantum = datumQuantum;
}
@Override
public float getAverageTime() {
transitionRollingCounter();
float avg = 0;
int accum = 0;
int count = 0;
for (int i = 0; i < accumSize; ++i) {
accum += statAccum[i];
count += statCount[i];
}
if (count > 0)
avg = accum / count;
return avg / 1000;
}
@Override
public float getAverageValue() {
transitionRollingCounter();
float accum = 0;
for (int i = 0; i < accumSize; ++i) {
if (statCount[i] > 0)
accum += (statAccum[i] / statCount[i]);
}
return accum / accumSize;
}
@Override
public int getTransactionsPerSecond() {
transitionRollingCounter();
int count = 0;
for (int i = 0; i < accumSize; ++i ) {
count += statCount[i];
}
return count * 1000 / quantumSize;
}
public int getQuantumSize() {
return quantumSize;
}
public int getAccumSize() {
return accumSize;
}
long transitionRollingCounter() {
long datumQuantum = System.currentTimeMillis() / quantumSize;
if (debugMode)
System.out.println(datumQuantum + " " + lastDatumQuantum);
if (datumQuantum - lastDatumQuantum > accumSize)
lastDatumQuantum = datumQuantum - accumSize;
while (lastDatumQuantum < datumQuantum) {
++lastDatumQuantum;
if (debugMode)
System.out.println("lastDatum position is " + lastDatumQuantum % accumSize);
statAccum[(int) (lastDatumQuantum%accumSize)] = 0;
statCount[(int) (lastDatumQuantum%accumSize)] = 0;
}
return datumQuantum;
}
@Override
public boolean isDebugMode() {
return debugMode;
}
@Override
public void setDebugMode(boolean debugMode) {
this.debugMode = debugMode;
}
@Override
public TimingValue getTimingValue() {
return new TimingValue(getAverageTime(), getTransactionsPerSecond());
}
}