package edu.sc.seis.sod.source.seismogram;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import edu.iris.Fissures.IfSeismogramDC.RequestFilter;
import edu.iris.Fissures.network.ChannelImpl;
import edu.iris.Fissures.seismogramDC.LocalSeismogramImpl;
import edu.sc.seis.fissuresUtil.cache.CacheEvent;
import edu.sc.seis.sod.ConfigurationException;
import edu.sc.seis.sod.CookieJar;
import edu.sc.seis.sod.SodElement;
import edu.sc.seis.sod.SodUtil;
public class DownloadStatistics implements SeismogramSourceLocator {
public DownloadStatistics(Element config) throws ConfigurationException {
NodeList childNodes = config.getChildNodes();
Node node;
for (int counter = 0; counter < childNodes.getLength(); counter++) {
node = childNodes.item(counter);
if (node instanceof Element) {
SodElement sodElement = (SodElement)SodUtil.load((Element)node, new String[] {"seismogram"});
if (sodElement instanceof SeismogramSourceLocator) {
wrapped = (SeismogramSourceLocator)sodElement;
}
} // end of else
}
Timer t = new Timer("Download Stats", true);
t.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(summarizeStats());
}
},
5000,
5000);
runBegin = System.currentTimeMillis();
}
@Override
public SeismogramSource getSeismogramSource(final CacheEvent event,
final ChannelImpl channel,
final RequestFilter[] infilters,
final CookieJar cookieJar) throws Exception {
return new SeismogramSource() {
SeismogramSource wrappedSource = wrapped.getSeismogramSource(event, channel, infilters, cookieJar);
@Override
public List<RequestFilter> availableData(List<RequestFilter> request) throws SeismogramSourceException {
return wrappedSource.availableData(request);
}
@Override
public List<LocalSeismogramImpl> retrieveData(List<RequestFilter> request) throws SeismogramSourceException {
ElapsedTime elapsed = new ElapsedTime();
List<LocalSeismogramImpl> out = wrappedSource.retrieveData(request);
elapsed.end();
int dataPoints = 0;
for (LocalSeismogramImpl ls : out) {
dataPoints += ls.getNumPoints();
}
elapsed.setNpts(dataPoints);
addElapsed(elapsed);
return out;
}
};
}
void addElapsed(ElapsedTime elapsed) {
synchronized (lastDownloads) {
totalPoints += elapsed.npts;
lastDownloads.addFirst(elapsed);
if (lastDownloads.size() > maxElapsedListSize) {
lastDownloads.removeLast();
}
if (best == null || elapsed.getKiloSamplesPerSec() > best.getKiloSamplesPerSec()) {
best = elapsed;
}
if (worst == null || elapsed.getKiloSamplesPerSec() < worst.getKiloSamplesPerSec()) {
worst = elapsed;
}
}
}
public String summarizeStats() {
long timeTotal = 0;
int nptsTotal = 0;
long wallTime;
long totalRunTime = System.currentTimeMillis()-runBegin;
synchronized (lastDownloads) {
for (ElapsedTime e : lastDownloads) {
timeTotal += e.getElapsed();
nptsTotal += e.npts;
}
wallTime = lastDownloads.getFirst().end-lastDownloads.getLast().begin;
}
String out = "Last "+maxElapsedListSize+": download="+nptsTotal*1f/timeTotal+" wall="+nptsTotal*1f/wallTime+"\n";
out += "Best: "+best.getKiloSamplesPerSec()+" Worst: "+worst.getKiloSamplesPerSec()+"\n";
out += "Total Runtime: "+totalRunTime*1f/totalPoints+" over "+totalRunTime/1000+" sec";
return out;
}
ElapsedTime best, worst;
LinkedList<ElapsedTime> lastDownloads = new LinkedList<ElapsedTime>();
int maxElapsedListSize = 10;
long runBegin;
long totalPoints = 0;
SeismogramSourceLocator wrapped;
}
class ElapsedTime {
ElapsedTime() {
this .begin = System.currentTimeMillis();
}
void end() {
end = System.currentTimeMillis();
}
void setNpts(int npts) {
this.npts = npts;
}
long begin;
long end;
int npts;
long getElapsed() {
return end-begin;
}
float getKiloSamplesPerSec() {
return 1.0f*(npts)/(end-begin); // samples per millisec == kilo per sec
}
}