package rocks.inspectit.shared.all.communication.valueobject;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import rocks.inspectit.shared.all.communication.DefaultData;
import rocks.inspectit.shared.all.communication.MethodSensorData;
import rocks.inspectit.shared.all.communication.data.ParameterContentData;
import rocks.inspectit.shared.all.communication.data.TimerData;
/**
* This value object is used to store the raw time measurements from the executed methods.
*
* @author Patrice Bouillet
*
*/
public class TimerRawVO extends MethodSensorData {
/**
* The serial version uid for this class.
*/
private static final long serialVersionUID = 6176694438175985136L;
/**
* The list which is holding one or more data container for the raw data. If the current data
* container is full a new one is created and added to the list.
*/
private List<TimerRawContainer> data = new ArrayList<TimerRawContainer>();
/**
* The current data container which is filled with raw data.
*/
private TimerRawContainer container;
/**
* If TimerData's charting should be set or not.
*/
private boolean charting;
/**
* The constructor creates the TimerRawVO object.
*
* @param timeStamp
* The timestamp.
* @param platformIdent
* The platform ident.
* @param sensorTypeIdent
* The sensor type ident.
* @param methodIdent
* The method ident.
* @param parameterContentData
* The parameter content data. Can be <code>null</code>.
* @param charting
* If TimerData's charting should be set or not.
*/
public TimerRawVO(Timestamp timeStamp, long platformIdent, long sensorTypeIdent, long methodIdent, List<ParameterContentData> parameterContentData, boolean charting) {
super(timeStamp, platformIdent, sensorTypeIdent, methodIdent, parameterContentData);
container = new TimerRawContainer();
this.charting = charting;
data.add(container);
}
/**
* Adds a new time value to the current data container.
*
* @param time
* The time value.
*/
public void add(double time) {
createContainerIfNecessary();
container.add(time);
}
/**
* Adds a new time and cpu time value to the current data container.
*
* @param time
* The time value.
* @param cpuTime
* The cpu time value.
*/
public void add(double time, double cpuTime) {
createContainerIfNecessary();
container.add(time, cpuTime);
}
/**
* Creates a new container if it is necessary.
*/
private void createContainerIfNecessary() {
if (container.isFull()) {
container = new TimerRawContainer();
data.add(container);
}
}
/**
* Returns the list with {@link TimerRawContainer} objects.
*
* @return The list with {@link TimerRawContainer} objects.
*/
public List<TimerRawContainer> getData() {
return Collections.unmodifiableList(data);
}
/**
* {@inheritDoc}
*/
@Override
public DefaultData finalizeData() {
TimerData timerData = new TimerData(getTimeStamp(), getPlatformIdent(), getSensorTypeIdent(), getMethodIdent());
timerData.setParameterContentData(getParameterContentData());
timerData.setCharting(charting);
double[] values;
double value;
double min = Double.MAX_VALUE;
double max = 0.0d;
int count = 0;
double duration = 0.0d;
double cpuMin = Double.MAX_VALUE;
double cpuMax = 0.0d;
double cpuDuration = 0.0d;
for (TimerRawContainer container : data) {
values = container.getData();
for (int j = 0; j < container.getCount(); j++) {
value = values[j];
duration += value;
if (value < min) {
min = value;
}
if (value > max) {
max = value;
}
}
count += container.getCount();
values = container.getCpuData();
if (null != values) {
for (int j = 0; j < container.getCount(); j++) {
value = values[j];
cpuDuration += value;
if (value < cpuMin) {
cpuMin = value;
}
if (value > cpuMax) {
cpuMax = value;
}
}
}
}
timerData.calculateMin(min);
timerData.calculateMax(max);
timerData.setCount(count);
timerData.setDuration(duration);
// TODO compute the variance
timerData.setVariance(-1);
if (Double.MAX_VALUE != cpuMin) {
timerData.calculateCpuMin(cpuMin);
timerData.calculateCpuMax(cpuMax);
timerData.setCpuDuration(cpuDuration);
}
return timerData;
}
/**
* Container to store the raw data.
*
* @author Patrice Bouillet
*
*/
public static class TimerRawContainer implements Serializable {
/**
* The serial version uid for this class.
*/
private static final long serialVersionUID = 7225384620786119269L;
/**
* The max amount this container is saving until it is full and no data can be accepted
* anymore.
*/
private static final int MAX_SIZE = 50;
/**
* Initializes a new data array with the specified MAX_SIZE.
*/
private double[] data = new double[MAX_SIZE];
/**
* Initializes a new cpu data array with the specified MAX_SIZE.
*/
private double[] cpuData = new double[MAX_SIZE];
/**
* The current position/count.
*/
private int count = 0;
/**
* Adds a new time value to the current data container.
*
* @param time
* The time value.
*/
public void add(double time) {
data[count] = time;
count++;
if (null != cpuData) {
cpuData = null; // NOPMD
}
}
/**
* Adds the given time and cpu time to this timer.
*
* @param time
* the elapsed time.
* @param cpuTime
* the cpu time.
*/
public void add(double time, double cpuTime) {
data[count] = time;
cpuData[count] = cpuTime;
count++;
}
/**
* Returns if this container is full.
*
* @return If this container is full.
*/
public boolean isFull() {
return count == (MAX_SIZE - 1);
}
/**
* Returns the current count.
*
* @return The current count.
*/
public int getCount() {
return count;
}
/**
* Return the double data array containing the measurements.
*
* @return The double data array.
*/
public double[] getData() {
return data;
}
/**
* Return the double cpu data array containing the measurements.
*
* @return The double cpu data array.
*/
public double[] getCpuData() {
return cpuData;
}
/**
* Returns a hash code value for the array.
*
* @param array
* the array to create a hash code value for
* @return a hash code value for the array
*/
private static int hashCode(double[] array) {
int prime = 31;
if (array == null) {
return 0;
}
int result = 1;
for (double element : array) {
long temp = Double.doubleToLongBits(element);
result = (prime * result) + (int) (temp ^ (temp >>> 32));
}
return result;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + count;
result = (prime * result) + TimerRawContainer.hashCode(cpuData);
result = (prime * result) + TimerRawContainer.hashCode(data);
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
TimerRawContainer other = (TimerRawContainer) obj;
if (count != other.count) {
return false;
}
if (!Arrays.equals(cpuData, other.cpuData)) {
return false;
}
if (!Arrays.equals(data, other.data)) {
return false;
}
return true;
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = (prime * result) + ((data == null) ? 0 : data.hashCode());
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
TimerRawVO other = (TimerRawVO) obj;
if (data == null) {
if (other.data != null) {
return false;
}
} else if (!data.equals(other.data)) {
return false;
}
return true;
}
}