package edu.sc.seis.sod;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.TimerTask;
import edu.iris.Fissures.IfNetwork.ChannelNotFound;
import edu.iris.Fissures.model.QuantityImpl;
import edu.iris.Fissures.network.ChannelIdUtil;
import edu.iris.Fissures.network.ChannelImpl;
import edu.iris.Fissures.network.NetworkAttrImpl;
import edu.iris.Fissures.network.NetworkIdUtil;
import edu.iris.Fissures.network.StationImpl;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.fissuresUtil.hibernate.ChannelGroup;
import edu.sc.seis.fissuresUtil.hibernate.ChannelSensitivity;
import edu.sc.seis.fissuresUtil.hibernate.InstrumentationBlob;
import edu.sc.seis.fissuresUtil.hibernate.NetworkDB;
import edu.sc.seis.fissuresUtil.sac.InvalidResponse;
import edu.sc.seis.sod.source.SodSourceException;
import edu.sc.seis.sod.source.network.LoadedNetworkSource;
import edu.sc.seis.sod.source.network.NetworkFinder;
public class RefreshNetworkArm extends TimerTask {
public RefreshNetworkArm(NetworkArm netArm) {
this.netArm = netArm;
InstrumentationBlob.setORB(CommonAccess.getORB());
}
public void run() {
logger.info("Refreshing Network Arm");
try {
List<NetworkAttrImpl> nets;
List<NetworkAttrImpl> needReload = new LinkedList<NetworkAttrImpl>();
synchronized(this) {
if (netArm.getInternalNetworkSource() instanceof NetworkFinder) {
((NetworkFinder)netArm.getInternalNetworkSource()).reset();
}
nets = netArm.getSuccessfulNetworksFromServer();
if (nets.size() == 0) {return;}
// maybe previous update has not yet finished, only reload nets
// not already in list???
for (NetworkAttrImpl net : nets) {
if (!isNetworkBeingReloaded(net.getDbid())) {
networksBeingReloaded.add(new Integer(net.getDbid()));
needReload.add(net);
logger.debug("Will Reload "+NetworkIdUtil.toString(net));
} else {
logger.info("net already in processing list, skipping..."+NetworkIdUtil.toString(net));
}
}
}
for (NetworkAttrImpl cacheNetwork : needReload) {
NetworkDB.getSingleton().put(cacheNetwork);
}
NetworkDB.commit();
while (needReload.size() != 0) {
// in case of comm failures, we move to the next network, but
// keep trying until all networks have been reloaded
Iterator<NetworkAttrImpl> it = needReload.iterator();
while (it.hasNext()) {
NetworkAttrImpl net = it.next();
if (processNetwork(net)) {
synchronized(this) {
networksBeingReloaded.remove(new Integer(net.getDbid()));
it.remove();
logger.debug("Successful reload of "+NetworkIdUtil.toStringNoDates(net));
// in case networkArm methods are waiting on this network to be refreshed
notifyAll();
if (Start.getWaveformRecipe() != null) {
// maybe worker threads need to run
wait(10);
}
}
} else {
logger.debug("reload not successful, will do again "+NetworkIdUtil.toStringNoDates(net));
}
}
Thread.sleep(1000); // don't retry over and over as fast as possible
}
netArm.finish();
} catch(Throwable t) {
Start.armFailure(netArm, t);
GlobalExceptionHandler.handle(t);
}
}
boolean processNetwork(NetworkAttrImpl net) {
logger.debug("refresh "+NetworkIdUtil.toString(net));
// how do we refresh instrumentation???
try {
StationImpl[] stas = netArm.getSuccessfulStationsFromServer(net);
List<StationImpl> allStations = new ArrayList<StationImpl>();
for (int s = 0; s < stas.length; s++) {
allStations.add(stas[s]);
}
synchronized(this) {
for (int s = 0; s < stas.length; s++) {
stationsBeingReloaded.add(stas[s].getDbid());
}
}
logger.info("found "+stas.length+" stations in "+NetworkIdUtil.toString(net));
if (Start.getWaveformRecipe() != null || netArm.getChannelSubsetters().size() != 0) {
for (int s = 0; s < stas.length; s++) {
LoadedNetworkSource loadSource = new LoadedNetworkSource(netArm.getInternalNetworkSource(), allStations, stas[s]);
processStation(loadSource, stas[s]);
synchronized(this) {
stationsBeingReloaded.remove(new Integer(stas[s].getDbid()));
}
}
} else {
logger.info("Not loading channels as no waveformArm or channel subsetters");
}
NetworkDB.commit(); // make sure session is clear
return true;
} catch(Throwable t) {
NetworkDB.rollback(); // oops
String netstr = "unknown";
try {
netstr = NetworkIdUtil.toString(net);
} catch(Throwable tt) {}
GlobalExceptionHandler.handle("Problem with network: " + netstr, t);
return false;
}
}
void processStation(LoadedNetworkSource loadSource, StationImpl sta) {
if (Start.getWaveformRecipe() instanceof MotionVectorArm) {
List<ChannelGroup> cg = netArm.getSuccessfulChannelGroupsFromServer(sta, loadSource);
// need to figure out how to update sensitivity/response, but only when it is actually used
// as this is a time consuming task
// for (ChannelGroup channelGroup : cg) {
// checkSensitivityLoaded(channelGroup, loadSource);
// }
} else {
List<ChannelImpl> chans = netArm.getSuccessfulChannelsFromServer(sta, loadSource);
// for (ChannelImpl channelImpl : chans) {
// checkSensitivityLoaded(channelImpl, loadSource);
// }
}
}
void checkSensitivityLoaded(ChannelGroup cg, LoadedNetworkSource loadSource) {
checkSensitivityLoaded(cg.getChannel1(), loadSource);
checkSensitivityLoaded(cg.getChannel2(), loadSource);
checkSensitivityLoaded(cg.getChannel3(), loadSource);
}
void checkSensitivityLoaded(ChannelImpl chan, LoadedNetworkSource loadSource) {
try {
QuantityImpl sens = loadSource.getSensitivity(chan);
} catch(SodSourceException e) {
logger.warn("Error getting Instrumentation for "+ChannelIdUtil.toStringFormatDates(chan.getId()));
NetworkDB.getSingleton().putSensitivity( ChannelSensitivity.createNonChannelSensitivity(chan));
} catch(ChannelNotFound e) {
logger.warn("No Instrumentation for "+ChannelIdUtil.toStringFormatDates(chan.getId()));
NetworkDB.getSingleton().putSensitivity( ChannelSensitivity.createNonChannelSensitivity(chan));
} catch(InvalidResponse e) {
logger.warn("Invalid Instrumentation for "+ChannelIdUtil.toStringFormatDates(chan.getId()));
NetworkDB.getSingleton().putSensitivity( ChannelSensitivity.createNonChannelSensitivity(chan));
}
}
public synchronized boolean isNetworkBeingReloaded(int dbid) {
if (dbid == 0) {
throw new IllegalArgumentException("dbid = 0 is not legal, Network must not be in db yet");
}
return networksBeingReloaded.contains(new Integer(dbid));
}
public synchronized boolean isStationBeingReloaded(int dbid) {
if (dbid == 0) {
throw new IllegalArgumentException("dbid = 0 is not legal, Station must not be in db yet");
}
return stationsBeingReloaded.contains(new Integer(dbid));
}
private List<Integer> networksBeingReloaded = new ArrayList<Integer>();
private List<Integer> stationsBeingReloaded = new ArrayList<Integer>();
NetworkArm netArm;
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(RefreshNetworkArm.class);
}