/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.util.stats;
import java.util.Iterator;
import java.util.LinkedList;
/**
* Maintains a list of {@link DataPoint}s which all lie within a specific
* time range. This class is useful for storing 'the last 30 minutes of data'
* and rolling the oldest data points off.
*
* This class relies on datapoints being placed into the collector in
* time-sorted order.
*/
public class TimeWindowCollector {
private final LinkedList _dataPoints = new LinkedList();
private final long _windowSize;
private boolean _hasRolled = false;
/**
* @param windowSize The size of the window (in millis) that all the
* encapsulated datapoints should be within.
*/
public TimeWindowCollector(long windowSize) {
_windowSize = windowSize;
}
/**
* Add a new datapoint to the collection -- does not roll off old
* datapoints.
*/
public void addPoint(long time, double value) {
addPoint(new DataPoint(time, value));
}
/**
* @see #addPoint(long, double)
*/
public void addPoint(DataPoint pt) {
synchronized (_dataPoints) {
_dataPoints.add(pt);
}
}
/**
* Returns true if data has been rolled off the back of the time-window.
* (i.e. removeOldPoints() has been invoked and removed something)
*/
public boolean hasRolled() {
synchronized (_dataPoints) {
return _hasRolled;
}
}
/**
* Get a sum of all the encapsulated data points
*/
public double getSum() {
double res = 0.0;
synchronized (_dataPoints) {
for (Iterator i=_dataPoints.iterator(); i.hasNext(); ) {
DataPoint pt = (DataPoint)i.next();
res += pt.getValue();
}
}
return res;
}
/**
* Remove old datapoints. This method uses the time of the most recent
* datapoint as the end of the time range.
*
* All datapoints older than datapoints[-1] - windowSize will be removed.
*/
public void removeOldPoints() {
synchronized (_dataPoints) {
if (_dataPoints.isEmpty())
return;
DataPoint last = (DataPoint)_dataPoints.getLast();
removeOldPoints(last.getTime());
}
}
/**
* Remove old datapoints.
*
* All datapoints older than currentTime - windowSize will be removed.
*/
public void removeOldPoints(long currentTime) {
long oldestTimeAllowed = currentTime - _windowSize;
synchronized (_dataPoints) {
for (Iterator i=_dataPoints.iterator(); i.hasNext(); ) {
DataPoint pt = (DataPoint)i.next();
if (pt.getTime() < oldestTimeAllowed) {
i.remove();
_hasRolled = true;
} else {
break;
}
}
}
}
}