package edu.sc.seis.sod.source.event; import org.omg.CORBA.SystemException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; import edu.iris.Fissures.model.MicroSecondDate; import edu.iris.Fissures.model.TimeInterval; import edu.iris.Fissures.model.UnitImpl; import edu.sc.seis.fissuresUtil.cache.CacheEvent; import edu.sc.seis.fissuresUtil.cache.RetryStrategy; import edu.sc.seis.fissuresUtil.chooser.ClockUtil; import edu.sc.seis.fissuresUtil.database.NotFound; import edu.sc.seis.fissuresUtil.display.configuration.DOMHelper; import edu.sc.seis.fissuresUtil.time.MicroSecondTimeRange; import edu.sc.seis.sod.ConfigurationException; import edu.sc.seis.sod.QueryTime; import edu.sc.seis.sod.SodUtil; import edu.sc.seis.sod.Start; import edu.sc.seis.sod.hibernate.SodDB; import edu.sc.seis.sod.source.AbstractSource; public class EventFinder extends AbstractSource implements EventSource { public EventFinder(Element config) throws Exception { super(config, "IRIS_EventDC"); processConfig(config); if (getDNS().equals("edu/iris/dmc")) { System.err.println("WARNING: DHI servers will be turned off June 2013, switch to <fdsnEvent>"); } eventFinderId = eventFinderCount++; processConfig(config); refreshInterval = Start.getRunProps().getEventRefreshInterval(); lag = Start.getRunProps().getEventLag(); increment = Start.getRunProps().getEventQueryIncrement(); } protected void processConfig(Element config) throws ConfigurationException { dns = SodUtil.loadText(config, "dns", "edu/iris/dmc"); Element queryTimeEl = DOMHelper.extractElement(config, "originTimeRange"); if (queryTimeEl == null) { queryTimeEl = DOMHelper.extractElement(config, "networkTimeRange"); } eventTimeRange = ((MicroSecondTimeRangeSupplier) SodUtil.load(queryTimeEl, new String[] { "eventArm", "origin" })); querier = new EventDCQuerier(getName(), getDNS(), getRetries(), config); } public String getDescription() { return "EventFinder Source: "+getDNS()+" "+getUniqueName()+" "+eventTimeRange.getMSTR()+" "+querier.getMagRange().getMinValue(); } public boolean hasNext() { MicroSecondDate queryEnd = getEventTimeRange().getEndTime(); MicroSecondDate quitDate = queryEnd.add(lag); logger .debug(getUniqueName()+" Checking if more queries to the event server are in order. The quit date is " + quitDate + " the last query was for " + getQueryStart() + " and we're querying to " + queryEnd); return quitDate.equals(ClockUtil.now()) || quitDate.after(ClockUtil.now()) || !getQueryStart().equals(queryEnd); } private CacheEvent[] internalNext() { MicroSecondDate now = ClockUtil.now(); MicroSecondTimeRange queryTime = getQueryTime(); CacheEvent[] results = querier.query(queryTime); logger.debug("Retrieved"+results.length+" events for time range "+queryTime); if (caughtUpWithRealtime() && hasNext()) { sleepUntilTime = now.add(refreshInterval); logger.debug("set sleepUntilTime "+sleepUntilTime); resetQueryTimeForLag(); } updateQueryEdge(queryTime); return results; } public CacheEvent[] next() { int count = 0; SystemException latest; try { return internalNext(); } catch(SystemException t) { latest = t; } catch(OutOfMemoryError e) { throw new RuntimeException("Out of memory", e); } while(retryStrat.shouldRetry(latest, querier.getEventDC(), count++)) { try { CacheEvent[] result = internalNext(); retryStrat.serverRecovered(querier.getEventDC()); return result; } catch(SystemException t) { latest = t; } catch(OutOfMemoryError e) { throw new RuntimeException("Out of memory", e); } } throw latest; } protected void updateQueryEdge(MicroSecondTimeRange queryTime) { setQueryEdge(queryTime.getEndTime()); } public TimeInterval getWaitBeforeNext() { if (sleepUntilTime != null) { logger.debug(getUniqueName()+" "+"sleeping caught up, "+refreshInterval+" "+sleepUntilTime); return sleepUntilTime.subtract(ClockUtil.now()); } return new TimeInterval(0, UnitImpl.SECOND); } protected boolean caughtUpWithRealtime() { return ClockUtil.now().subtract(refreshInterval).before(getQueryStart()) || getQueryStart().add(new TimeInterval(10, UnitImpl.SECOND)).after(getEventTimeRange().getEndTime()); } public MicroSecondTimeRange getEventTimeRange() { return eventTimeRange.getMSTR(); } /** * @return - the next time to start asking for events */ protected MicroSecondDate getQueryStart() { try { return getQueryEdge(); } catch (edu.sc.seis.fissuresUtil.database.NotFound e) { logger.debug("the query times database didn't have an entry for our server/dns combo, just use the time in the config file"); setQueryEdge(getEventTimeRange().getBeginTime()); return getEventTimeRange().getBeginTime(); } } /** * @return - the next time range to be queried for events */ protected MicroSecondTimeRange getQueryTime() { MicroSecondDate queryStart = getQueryStart(); MicroSecondDate queryEnd = queryStart.add(increment); if (getEventTimeRange().getEndTime().before(queryEnd)) { queryEnd = getEventTimeRange().getEndTime(); } if (ClockUtil.now().before(queryEnd)) { queryEnd = ClockUtil.now(); } return new MicroSecondTimeRange(queryStart, queryEnd); } /** * Scoots the query time back by the event lag amount from the run * properties to the query start time at the earliest */ private void resetQueryTimeForLag() { MicroSecondDate newEdge = getQueryStart().subtract(lag); if (newEdge.before(getEventTimeRange().getBeginTime())) { setQueryEdge(getEventTimeRange().getBeginTime()); } else { setQueryEdge(newEdge); } } /** * @return - latest time queried */ protected MicroSecondDate getQueryEdge() throws NotFound { SodDB sdb = SodDB.getSingleton(); QueryTime t = sdb.getQueryTime(getUniqueName(), getDNS()); SodDB.commit(); if (t == null) {throw new NotFound();} return new MicroSecondDate(t.getTime()); } /** * sets the latest time queried */ protected void setQueryEdge(MicroSecondDate edge) { SodDB sdb = SodDB.getSingleton(); QueryTime qt = sdb.getQueryTime(getUniqueName(), getDNS()); if (qt != null) { qt.setTime( edge.getTimestamp()); SodDB.getSession().saveOrUpdate(qt); } else { sdb.putQueryTime(new QueryTime(getUniqueName(), getDNS(), edge.getTimestamp())); } SodDB.commit(); } private String getUniqueName() { return getName() + eventFinderId; } /** * returns the DNSName of the server. * The context under which the objectName is registered in the CORBA naming service. * * * @return a <code>String</code> value */ public String getDNS() { return dns; } // Unique among eventFinders and constant for this eventFinder for repeated // uses of the same recipe file private int eventFinderId; private static int eventFinderCount = 0; private EventDCQuerier querier; private MicroSecondTimeRangeSupplier eventTimeRange; private MicroSecondDate sleepUntilTime = null; private String dns; private static Logger logger = LoggerFactory.getLogger(EventFinder.class); protected TimeInterval increment, lag; protected TimeInterval refreshInterval = new TimeInterval(10, UnitImpl.MINUTE); private RetryStrategy retryStrat = Start.createRetryStrategy(getRetries()); }// EventFinder