package edu.sc.seis.sod.source.seismogram;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.w3c.dom.Element;
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.SodUtil;
import edu.sc.seis.sod.Start;
public class BatchDataRequest implements SeismogramSourceLocator, Runnable {
ConstantSeismogramSourceLocator wrappedLocator;
static int NUM_LOADER_THREADS = 2;
Thread[] loader = new Thread[NUM_LOADER_THREADS];
int loaderSleep = 100 * NUM_LOADER_THREADS; // rate limit less than 10 per sec
public BatchDataRequest(SeismogramSourceLocator wrappedLocator) throws ConfigurationException {
if ( ! ( wrappedLocator instanceof ConstantSeismogramSourceLocator)) {
throw new ConfigurationException("Batch must be for constant source locator like FdsnDataSelect");
}
this.wrappedLocator = (ConstantSeismogramSourceLocator)wrappedLocator;
for (int i = 0; i < loader.length; i++) {
loader[i] = new Thread(this, "Batch SeismogramSource Loader "+(i+1));
loader[i].setDaemon(true);
loader[i].start();
}
}
public BatchDataRequest(Element config) throws MalformedURLException, URISyntaxException, ConfigurationException {
this((SeismogramSourceLocator)SodUtil.load(SodUtil.getFirstEmbeddedElement(config), "seismogram"));
}
public void run() {
while (!Start.isArmFailure()) {
if (nextBatch.isEmpty()) {
try {
synchronized(this) {
wait();
}
} catch(InterruptedException e) {}
} else {
List<PromiseSeismogramList> reqList = popNextBatch();
List<RequestFilter> rfList = new ArrayList<RequestFilter>();
for (PromiseSeismogramList batchProxy : reqList) {
rfList.addAll(batchProxy.getRequest());
}
SeismogramSource sSource = wrappedLocator.getSeismogramSource();
List<LocalSeismogramImpl> seisList;
try {
seisList = sSource.retrieveData(rfList);
for (PromiseSeismogramList batchProxy : reqList) {
batchProxy.finishRequest(seisList);
}
} catch(SeismogramSourceException e) {
for (PromiseSeismogramList batchProxy : reqList) {
batchProxy.seismogramSourceException(e);
}
}
try {
// rate limit
Thread.sleep(loaderSleep);
} catch(InterruptedException e) {
}
}
}
}
@Override
public SeismogramSource getSeismogramSource(CacheEvent event,
ChannelImpl channel,
RequestFilter[] infilters,
CookieJar cookieJar) throws Exception {
return new BatchSeismogramSource();
}
synchronized PromiseSeismogramList addRequestToBatch(List<RequestFilter> request) {
PromiseSeismogramList proxy = new PromiseSeismogramList(request);
nextBatch.add(proxy);
notifyAll();
return proxy;
}
synchronized List<PromiseSeismogramList> popNextBatch() {
List<PromiseSeismogramList> out = nextBatch;
nextBatch = new ArrayList<PromiseSeismogramList>();
return out;
}
List<PromiseSeismogramList> nextBatch = new ArrayList<PromiseSeismogramList>();
class BatchSeismogramSource implements PromiseSeismogramSource {
@Override
public List<RequestFilter> availableData(List<RequestFilter> request) throws SeismogramSourceException {
return request;
}
@Override
public List<LocalSeismogramImpl> retrieveData(List<RequestFilter> request) throws SeismogramSourceException {
PromiseSeismogramList batch = addRequestToBatch(request);
return batch.getResult();
}
@Override
public PromiseSeismogramList promiseRetrieveData(List<RequestFilter> request) {
return promiseRetrieveDataList(Collections.singletonList(request)).get(0);
}
@Override
public List<PromiseSeismogramList> promiseRetrieveDataList(List<List<RequestFilter>> request) {
List<PromiseSeismogramList> out = new ArrayList<PromiseSeismogramList>();
for (List<RequestFilter> r : request) {
out.add(addRequestToBatch(r));
}
return out;
}
}
}