package edu.sc.seis.sod; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import edu.iris.Fissures.Location; import edu.iris.Fissures.IfEvent.NoPreferredOrigin; import edu.iris.Fissures.network.ChannelIdUtil; import edu.iris.Fissures.network.ChannelImpl; import edu.iris.Fissures.network.StationIdUtil; import edu.iris.Fissures.network.StationImpl; import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler; import edu.sc.seis.fissuresUtil.hibernate.ChannelGroup; import edu.sc.seis.sod.hibernate.SodDB; import edu.sc.seis.sod.hibernate.StatefulEvent; import edu.sc.seis.sod.status.StringTree; import edu.sc.seis.sod.status.StringTreeLeaf; import edu.sc.seis.sod.subsetter.EventEffectiveTimeOverlap; import edu.sc.seis.sod.subsetter.eventStation.EventStationSubsetter; public class EventStationPair extends CookieEventPair { /** for hibernate */ protected EventStationPair() {} public EventStationPair(StatefulEvent event, StationImpl station) { this(event, station, Status.get(Stage.EVENT_CHANNEL_POPULATION, Standing.INIT)); } public EventStationPair(StatefulEvent event, StationImpl station, Status status) { super(event, status); setStation(station); } public void run() { SodDB sodDb = SodDB.getSingleton(); logger.debug("Begin EventStationPair (e="+getEvent().getDbid()+",s="+getStationDbId()+") "+this); // make sure origin and station not lazy Location l = getEvent().getOrigin().getLocation(); l = getStation().getLocation(); // don't bother with station if effective time does not // overlap event time try { EventEffectiveTimeOverlap overlap = new EventEffectiveTimeOverlap(getEvent()); Map<String, Serializable> cookies = new HashMap<String, Serializable>(); StringTree accepted = new StringTreeLeaf(this, false); try { EventStationSubsetter esSub = Start.getWaveformRecipe().getEventStationSubsetter(); synchronized(esSub) { accepted = esSub.accept(getEvent(), getStation(), new CookieJar(this, cookies)); } } catch(Throwable e) { if(e instanceof org.omg.CORBA.SystemException) { update(e, Status.get(Stage.EVENT_STATION_SUBSETTER, Standing.CORBA_FAILURE)); updateRetries(); failLogger.info("Network or server problem, SOD will continue to retry this item periodically: (" + e.getClass().getName() + ") " + this); logger.debug(this.toString(), e); } else { update(e, Status.get(Stage.EVENT_STATION_SUBSETTER, Standing.SYSTEM_FAILURE)); failLogger.warn(this.toString(), e); } SodDB.commit(); logger.debug("Finish (fail) EStaP: " + this); return; } if(!accepted.isSuccess()) { update(Status.get(Stage.EVENT_STATION_SUBSETTER, Standing.REJECT)); SodDB.commit(); failLogger.info(this + " " + accepted.toString()); return; } SodDB.commit(); SodDB.getSession().update(this); List<AbstractEventPair> chanPairs = new ArrayList<AbstractEventPair>(); if(Start.getWaveformRecipe() instanceof MotionVectorArm) { List<ChannelGroup> chanGroups = Start.getNetworkArm().getSuccessfulChannelGroups(getStation()); if(chanGroups.size() == 0) { logger.info("No successful channel groups for " + this); } List<ChannelGroup> overlapList = new ArrayList<ChannelGroup>(); for(ChannelGroup cg : chanGroups) { if(overlap.overlaps(cg.getChannels()[0])) { overlapList.add(cg); } else { failLogger.info(ChannelIdUtil.toString(cg.getChannels()[0].get_id()) + "'s channel effective time does not overlap the event time"); } } for(ChannelGroup cg : overlapList) { // use Standing.IN_PROG as we are going to do event-channel // processing here // don't want another thread to pull the ECP from the DB logger.debug("Put EventVectorPair (" + getEventDbId() + ", cg " + cg.getDbid() + " (" + ((ChannelImpl)cg.getChannel1()).getDbid() + " " + ((ChannelImpl)cg.getChannel2()).getDbid() + " " + ((ChannelImpl)cg.getChannel3()).getDbid()); EventVectorPair p = new EventVectorPair(getEvent(), cg, Status.get(Stage.EVENT_CHANNEL_POPULATION, Standing.IN_PROG), this); chanPairs.add(p); sodDb.put(p); } } else { List<ChannelImpl> channels = Start.getNetworkArm().getSuccessfulChannels(getStation()); if(channels.size() == 0) { logger.info("No successful channels for " + this); } List<ChannelImpl> overlapList = new ArrayList<ChannelImpl>(); for(ChannelImpl c : channels) { if(overlap.overlaps(c)) { overlapList.add(c); } else { failLogger.info(ChannelIdUtil.toString(c.getId()) + "'s channel effective time does not overlap the event time"); } logger.info(ChannelIdUtil.toString(c.getId()) + "' passed"); } for(ChannelImpl c : overlapList) { // use Standing.IN_PROG as we are going to do event-channel // processing here // don't want another thread to pull the ECP from the DB EventChannelPair p = sodDb.createEventChannelPair(getEvent(), c, this); p.update(Status.get(Stage.EVENT_CHANNEL_POPULATION, Standing.IN_PROG)); chanPairs.add(p); } } update(Status.get(Stage.EVENT_CHANNEL_POPULATION, Standing.SUCCESS)); SodDB.commit(); // run channel pairs now for(AbstractEventPair pair : chanPairs) { SodDB.getSession().update(pair); SodDB.getSession().update(this); pair.run(); SodDB.commit(); } logger.debug("End EventStationPair (e="+getEvent().getDbid()+",s="+getStationDbId()+") "+this); } catch(NoPreferredOrigin e) { // should never happen GlobalExceptionHandler.handle(e); SodDB.getSession().update(this); update(Status.get(Stage.EVENT_CHANNEL_POPULATION, Standing.SYSTEM_FAILURE)); SodDB.commit(); return; } finally { SodDB.commit(); } } /** * sets the status on this event network pair to be status and notifies its * parent */ public void update(Status status) { // this is weird, but calling the setter allows hibernate to autodetect // a modified object setStatus(status); if (Start.getWaveformRecipe() != null) { // might be null if not a real SOD run, ie unit tests or using SOD from another app Start.getWaveformRecipe().setStatus(this); } } public boolean equals(Object o) { if(!(o instanceof EventStationPair)) return false; EventStationPair ecp = (EventStationPair)o; if(ecp.getEventDbId() == getEventDbId() && ecp.getStationDbId() == getStationDbId()) { return true; } return false; } public int hashCode() { int code = 47 * getStationDbId(); code += 23 * getEventDbId(); return code; } public String toString() { return "EventStationPair: (" + getDbid() + " -> "+getEvent().getDbid()+","+getStationDbId()+") " + getEvent() + " " + StationIdUtil.toStringFormatDates(getStation()) + " " + getStatus(); } public int getStationDbId() { return station.getDbid(); } public StationImpl getStation() { return station; } /** for use by hibernate */ protected void setStation(StationImpl sta) { this.station = sta; } private StationImpl station; private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(EventStationPair.class); }