package edu.sc.seis.sod.hibernate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import edu.iris.Fissures.IfNetwork.Channel;
import edu.iris.Fissures.IfNetwork.ChannelId;
import edu.iris.Fissures.model.TimeInterval;
import edu.iris.Fissures.model.UnitImpl;
import edu.iris.Fissures.network.ChannelIdUtil;
import edu.iris.Fissures.network.ChannelImpl;
import edu.iris.Fissures.network.NetworkAttrImpl;
import edu.iris.Fissures.network.StationImpl;
import edu.sc.seis.fissuresUtil.cache.CacheEvent;
import edu.sc.seis.fissuresUtil.chooser.ClockUtil;
import edu.sc.seis.fissuresUtil.database.ConnMgr;
import edu.sc.seis.fissuresUtil.hibernate.AbstractHibernateDB;
import edu.sc.seis.sod.AbstractEventChannelPair;
import edu.sc.seis.sod.AbstractEventPair;
import edu.sc.seis.sod.EventChannelPair;
import edu.sc.seis.sod.EventNetworkPair;
import edu.sc.seis.sod.EventStationPair;
import edu.sc.seis.sod.EventVectorPair;
import edu.sc.seis.sod.QueryTime;
import edu.sc.seis.sod.RunProperties;
import edu.sc.seis.sod.SodConfig;
import edu.sc.seis.sod.Stage;
import edu.sc.seis.sod.Standing;
import edu.sc.seis.sod.Start;
import edu.sc.seis.sod.Status;
import edu.sc.seis.sod.Version;
public class SodDB extends AbstractHibernateDB {
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(SodDB.class);
static String configFile = "edu/sc/seis/sod/hibernate/sod.hbm.xml";
/** database should use one of EventVectorPair or EventChannelPair. Using
* AbstractEventChannelPair results in very slow union in selects in hsqldb. By
* specifying which table we are using, the queries are several orders of magnitude
* faster and do not use huge amounts of memory, which matters a lot when the
* number of ecps becomes large.
*/
protected SodDB() {
} // only for singleton
public static void configHibernate(Configuration config) {
logger.debug("adding to HibernateUtil " + configFile);
config.addResource(configFile, SodDB.class.getClassLoader());
if(ConnMgr.getURL().startsWith("jdbc:hsql")) {
config.addSqlFunction("datediff",
new SQLFunctionTemplate(org.hibernate.type.StandardBasicTypes.LONG,
"datediff(?1, ?2, ?3)"));
config.addSqlFunction("milliseconds_between",
new SQLFunctionTemplate(org.hibernate.type.StandardBasicTypes.LONG,
"datediff('ms', ?1, ?2)"));
config.addSqlFunction("seconds_between",
new SQLFunctionTemplate(org.hibernate.type.StandardBasicTypes.LONG,
"datediff('ss', ?1, ?2)"));
} else if(ConnMgr.getURL().startsWith("jdbc:postgresql")) {
config.addSqlFunction("milliseconds_between",
new SQLFunctionTemplate(org.hibernate.type.StandardBasicTypes.LONG,
"extract(epoch from (?2 - ?1)) * 1000"));
config.addSqlFunction("seconds_between",
new SQLFunctionTemplate(org.hibernate.type.StandardBasicTypes.LONG,
"extract(epoch from (?2 - ?1))"));
}
}
public void reopenSuspendedEventChannelPairs(String processingRule, boolean vector) {
Stage[] stages = {Stage.EVENT_CHANNEL_POPULATION,
Stage.EVENT_STATION_SUBSETTER,
Stage.EVENT_CHANNEL_SUBSETTER,
Stage.REQUEST_SUBSETTER,
Stage.AVAILABLE_DATA_SUBSETTER,
Stage.DATA_RETRIEVAL,
Stage.PROCESSOR};
String stageList = " ( ";
for(int i = 0; i < stages.length; i++) {
stageList += stages[i].getVal()+", ";
}
stageList = stageList.substring(0, stageList.length() - 2);
stageList += " ) ";
Standing[] standings = {Standing.IN_PROG,
Standing.INIT,
Standing.SUCCESS};
String standingList = " ( ";
for(int i = 0; i < standings.length; i++) {
standingList += standings[i].getVal()+", ";
}
standingList = standingList.substring(0, standingList.length() - 2);
standingList += " ) ";
String query;
String setStmt;
if(processingRule.equals(RunProperties.AT_LEAST_ONCE)) {
setStmt = " stageInt = "+Stage.EVENT_CHANNEL_POPULATION.getVal()+", standingInt = "+Standing.INIT.getVal();
} else {
setStmt = " standingInt = "+Standing.SYSTEM_FAILURE.getVal();
}
String queryEnd = " set "+setStmt
+" WHERE status.stageInt in "+stageList+" AND status.standingInt in "+standingList
+" AND NOT (status.stageInt = "+Stage.PROCESSOR.getVal()+" AND status.standingInt = "+Standing.SUCCESS.getVal()+" ) "
+" AND NOT (status.stageInt = "+Stage.EVENT_STATION_SUBSETTER.getVal()+" AND status.standingInt = "+Standing.INIT.getVal()+" ) ";
query = "UPDATE "+EventChannelPair.class.getName()+queryEnd;
int out = getSession().createQuery(query).executeUpdate();
query = "UPDATE "+EventVectorPair.class.getName()+queryEnd;
out += getSession().createQuery(query).executeUpdate();
}
public EventNetworkPair createEventNetworkPair(StatefulEvent event, NetworkAttrImpl net) {
Session session = getSession();
EventNetworkPair enp = new EventNetworkPair(event,
(NetworkAttrImpl)session.merge(net),
Status.get(Stage.EVENT_CHANNEL_POPULATION,
Standing.INIT));
logger.debug("Put "+enp);
session.save(enp);
synchronized(enpToDo) {
enpToDo.offer(enp);
}
return enp;
}
public void offerEventNetworkPairs(List<EventNetworkPair> staPairList) {
for (EventNetworkPair pair : staPairList) {
synchronized(enpToDo) {
enpToDo.offer(pair);
}
}
}
public void offerEventStationPair(List<EventStationPair> staPairList) {
for (EventStationPair eventStationPair : staPairList) {
synchronized(espToDo) {
espToDo.offer(eventStationPair);
}
}
}
public void offerEventChannelPair(List<AbstractEventChannelPair> chanPairList) {
for (AbstractEventChannelPair ecp : chanPairList) {
synchronized(ecpToDo) {
ecpToDo.offer(ecp);
}
}
}
public List<EventStationPair> loadESPForNetwork(StatefulEvent event, NetworkAttrImpl net) {
if (espFromNet == null) { initHQLStmts(); }
Query query = getSession().createQuery(espFromNet);
query.setEntity("event", event);
query.setEntity("net", net);
return query.list();
}
public EventStationPair createEventStationPair(StatefulEvent event, StationImpl station) {
logger.debug("Put esp ("+event.getDbid()+",s "+station.getDbid()+") ");
Session session = getSession();
EventStationPair esp = new EventStationPair(event,
(StationImpl)session.merge(station),
Status.get(Stage.EVENT_CHANNEL_POPULATION,
Standing.INIT) );
session.save(esp);
synchronized(espToDo) {
espToDo.offer(esp);
}
return esp;
}
public EventChannelPair createEventChannelPair(StatefulEvent event, ChannelImpl chan, EventStationPair esp) {
Session session = getSession();
EventChannelPair eventChannelPair = new EventChannelPair(event,
(ChannelImpl)session.merge(chan),
esp);
logger.debug("Put "+eventChannelPair);
session.save(eventChannelPair);
return eventChannelPair;
}
public boolean isECPTodo() {
synchronized(ecpToDo) {
return ! ecpToDo.isEmpty();
}
}
public boolean isESPTodo() {
synchronized(espToDo) {
return ! espToDo.isEmpty();
}
}
public boolean isENPTodo() {
synchronized(enpToDo) {
return ! enpToDo.isEmpty();
}
}
/** next successful event-network to process from cache.
* Returns null if no more events in cache. */
public synchronized EventNetworkPair getNextENPFromCache() {
EventNetworkPair enp;
synchronized(enpToDo) {
List<EventNetworkPair> beingLoaded = new ArrayList<EventNetworkPair>();
enp = enpToDo.poll();
while (enp != null && Start.getNetworkArm().isBeingRefreshed(enp.getNetwork())) {
beingLoaded.add(enp);
enp = enpToDo.poll();
}
enpToDo.addAll(beingLoaded); // put ones being reloaded back on queue
}
if (enp != null) {
// might be new thread
// ok to use even though might not be committed as hibernate flushes
// due to native generator for id
return (EventNetworkPair)getSession().merge(enp);
}
return null;
}
/** next successful event-network to process. Returns null if no more events. */
public synchronized EventNetworkPair getNextENP() {
if ( ! isENPTodo()) {
populateENPToDo();
}
return getNextENPFromCache();
}
public synchronized void populateENPToDo() {
String q = "from "
+ EventNetworkPair.class.getName()
+ " e "
+ " left join fetch e.event "
+ " left join fetch e.network "
+ " where e.status.stageInt = "+Stage.EVENT_CHANNEL_POPULATION.getVal()
+" and e.status.standingInt = :standing";
Query query = getSession().createQuery(q);
query.setInteger("standing", Standing.INIT.getVal());
query.setMaxResults(100);
List<EventNetworkPair> result = query.list();
for (EventNetworkPair enpResult : result) {
synchronized(enpToDo) {
enpToDo.offer(enpResult);
}
}
}
/** next successful event-station to process from memory cache.
* Returns null if no more esp in memory. */
public synchronized EventStationPair getNextESPFromCache() {
EventStationPair esp;
synchronized(espToDo) {
esp = espToDo.poll();
}
if (esp != null) {
// might be new thread
// ok to use even though might not be committed as hibernate flushes
// due to native generator for id
return (EventStationPair)getSession().merge(esp);
}
return null;
}
/** next successful event-station to process. Returns null if no more events. */
public synchronized EventStationPair getNextESP() {
if (! isESPTodo()) {
populateESPToDo();
}
return getNextESPFromCache();
}
public synchronized void populateESPToDo() {
String q = "from "
+ EventStationPair.class.getName()
+ " e "
+ " left join fetch e.event "
+ " left join fetch e.station "
+ " left join fetch e.station.networkAttr "
+ " where e.status.stageInt = "+Stage.EVENT_CHANNEL_POPULATION.getVal()
+ " and e.status.standingInt = :standing ";
Query query = getSession().createQuery(q);
query.setInteger("standing", Standing.INIT.getVal());
query.setMaxResults(1000);
List<EventStationPair> result = query.list();
for (EventStationPair eventStationPair : result) {
synchronized(espToDo) {
espToDo.offer(eventStationPair);
}
}
}
public synchronized void populateECPToDo() {
logger.debug("populateECPToDo");
String q = "from "
+ getEcpClass().getName()
+ " e "
+ " left join fetch e.event ";
if (getEcpClass().equals(EventChannelPair.class)) {
q += " left join fetch e.channel "
+ " left join fetch e.channel.site "
+ " left join fetch e.channel.site.station "
+ " left join fetch e.channel.site.station.networkAttr ";
} else {
q += " left join fetch e.channelGroup "
+ " left join fetch e.channelGroup.channel1.site "
+ " left join fetch e.channelGroup.channel1.site.station "
+ " left join fetch e.channelGroup.channel1.site.station.networkAttr "
+ " left join fetch e.channelGroup.channel2.site "
+ " left join fetch e.channelGroup.channel2.site.station "
+ " left join fetch e.channelGroup.channel2.site.station.networkAttr "
+ " left join fetch e.channelGroup.channel3.site "
+ " left join fetch e.channelGroup.channel3.site.station "
+ " left join fetch e.channelGroup.channel3.site.station.networkAttr ";
}
q+= " where e.status.stageInt = "+Stage.EVENT_CHANNEL_POPULATION.getVal()
+ " and e.status.standingInt = :standing ";
Query query = getSession().createQuery(q);
query.setInteger("standing", Standing.INIT.getVal());
query.setMaxResults(1000);
List<AbstractEventChannelPair> result = query.list();
logger.info("populate ECP/EVP ToDo: "+result.size());
for (AbstractEventChannelPair ecp : result) {
synchronized(ecpToDo) {
ecpToDo.offer(ecp);
}
}
logger.debug("Done populateECPToDo "+result.size());
}
/** next successful event-station to process from memory cache.
* Returns null if no more esp in memory. */
public synchronized AbstractEventChannelPair getNextECPFromCache() {
AbstractEventChannelPair ecp;
synchronized(ecpToDo) {
ecp = ecpToDo.poll();
}
if (ecp != null) {
// might be new thread
// ok to use even though might not be committed as hibernate flushes
// due to native generator for id
return (AbstractEventChannelPair)getSession().merge(ecp);
}
return null;
}
/** next successful event-channel to process. Returns null if no more events. */
public AbstractEventChannelPair getNextECP() {
if ( ! isECPTodo()) {
populateECPToDo();
}
return getNextECPFromCache();
}
public AbstractEventChannelPair getNextRetryECPFromCache() {
AbstractEventChannelPair ecp;
synchronized(retryToDo) {
ecp = retryToDo.poll();
}
if (ecp != null) {
return (AbstractEventChannelPair)getSession().merge(ecp);
}
return null;
}
public boolean isRetryTodo() {
synchronized(retryToDo) {
return ! retryToDo.isEmpty();
}
}
public List<AbstractEventChannelPair> getRetryToDo() {
logger.debug("Getting retry from db");
String q = "from "
+ getEcpClass().getName()
+ " where (status.standingInt = "
+ Standing.RETRY.getVal()
+ " or status.standingInt = "
+ Standing.CORBA_FAILURE.getVal()
+ " ) and seconds_between(:now, lastQuery) > :minDelay "
+ " and numRetries < "+maxRetries
+" and (seconds_between(:now, lastQuery) > :maxDelay or seconds_between(:now, lastQuery) > power(:base, numRetries)) order by numRetries";
Query query = getSession().createQuery(q);
query.setTimestamp("now", ClockUtil.now().getTimestamp());
query.setFloat("base", retryBase);
query.setFloat("minDelay", (float)getMinRetryDelay().getValue(UnitImpl.SECOND));
query.setFloat("maxDelay", maxRetryDelay);
query.setMaxResults(10000);
logger.info("retry query: "+q);
List<AbstractEventChannelPair> result = query.list();
logger.debug("retry query: "+q);
return result;
}
public void populateRetryToDo() {
List<AbstractEventChannelPair> result = getRetryToDo();
for (AbstractEventChannelPair abstractEventChannelPair : result) {
synchronized(retryToDo) {
retryToDo.offer(abstractEventChannelPair);
}
}
logger.debug("Got "+result.size()+" retries from db.");
}
public int getNumWorkUnits(Standing standing) {
return getNumWorkUnits(standing, AbstractEventPair.class);
}
public int getNumEventNetworkWorkUnits(Standing standing) {
return getNumWorkUnits(standing, EventNetworkPair.class);
}
private int getNumWorkUnits(Standing standing, Class EventPairClass) {
String q = "select count(*) from " + EventPairClass.getName()
+ " e where e.status.stageInt = "+Stage.EVENT_CHANNEL_POPULATION.getVal()
+ " and e.status.standingInt = "+standing.getVal()
+ " and e.numRetries = 0";
Query query = getSession().createQuery(q);
query.setMaxResults(1);
List result = query.list();
if(result.size() > 0) {
return ((Number)result.get(0)).intValue();
}
return 0;
}
public EventChannelPair getECP(CacheEvent event, ChannelImpl chan) {
Query query = getSession().createQuery("from "
+ EventChannelPair.class.getName()
+ " where event = :event and channel = :channel");
query.setEntity("event", event);
query.setEntity("channel", chan);
query.setMaxResults(1);
List<EventChannelPair> result = query.list();
if(result.size() > 0) {
return result.get(0);
}
return null;
}
public EventVectorPair put(EventVectorPair eventVectorPair) {
Session session = getSession();
session.lock(eventVectorPair.getEvent(), LockMode.NONE);
Channel[] chan = eventVectorPair.getChannelGroup().getChannels();
for(int i = 0; i < chan.length; i++) {
session.lock(chan[i], LockMode.NONE);
}
session.saveOrUpdate(eventVectorPair);
return eventVectorPair;
}
/*
*
* RunProperties runProps = Start.getRunProps(); SERVER_RETRY_DELAY =
* runProps.getServerRetryDelay(); sodDb = new SodDB(); retries = new
* JDBCRetryQueue("waveform"); retries.setMaxRetries(5); int
* minRetriesOnAvailableData = 3;
* retries.setMinRetries(minRetriesOnAvailableData);
* retries.setMinRetryWait((TimeInterval)runProps.getMaxRetryDelay()
* .divideBy(minRetriesOnAvailableData));
* retries.setEventDataLag(runProps.getSeismogramLatency()); corbaFailures =
* new JDBCRetryQueue("corbaFailure"); corbaFailures.setMinRetryWait(new
* TimeInterval(2, UnitImpl.HOUR)); corbaFailures.setMaxRetries(10);
*/
TimeInterval minRetryDelay = new TimeInterval(2, UnitImpl.HOUR);
public TimeInterval getMinRetryDelay() {
return minRetryDelay;
}
float maxRetryDelay = (float)((TimeInterval)Start.getRunProps()
.getMaxRetryDelay()).getValue(UnitImpl.SECOND);
float seismogramLatency = (float)((TimeInterval)Start.getRunProps()
.getSeismogramLatency()).getValue(UnitImpl.SECOND);
int maxRetries = 5;
float retryBase = 2;
public int getMaxRetries() {
return maxRetries;
}
public int getNumSuccessful() {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + totalSuccess);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumSuccessful(CacheEvent event) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + successPerEvent);
query.setEntity("event", event);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumSuccessful(StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + success);
query.setEntity("sta", station);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumSuccessful(CacheEvent event, StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + successPerEventStation);
query.setEntity("sta", station);
query.setEntity("event", event);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumFailed(StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + failed);
query.setEntity("sta", station);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumFailed(CacheEvent event, StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + failedPerEventStation);
query.setEntity("sta", station);
query.setEntity("event", event);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumFailed(CacheEvent event) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + failedPerEvent);
query.setEntity("event", event);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumRetry(StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + retry);
query.setEntity("sta", station);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumRetry(CacheEvent event) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + retryPerEvent);
query.setEntity("event", event);
return ((Long)query.uniqueResult()).intValue();
}
public int getNumRetry(CacheEvent event, StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(COUNT + retryPerEventStation);
query.setEntity("sta", station);
query.setEntity("event", event);
return ((Long)query.uniqueResult()).intValue();
}
public List<AbstractEventChannelPair> getAll(CacheEvent event) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(eventBase);
query.setEntity("event", event);
return query.list();
}
public List<AbstractEventChannelPair> getSuccessful(CacheEvent event) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(successPerEvent);
query.setEntity("event", event);
return query.list();
}
public List<AbstractEventChannelPair> getSuccessful(StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(success);
query.setEntity("sta", station);
return query.list();
}
public List<AbstractEventChannelPair> getSuccessful(CacheEvent event,
StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(successPerEventStation);
query.setEntity("sta", station);
query.setEntity("event", event);
return query.list();
}
public List<AbstractEventChannelPair> getFailed(StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(failed);
query.setEntity("sta", station);
return query.list();
}
public List<AbstractEventChannelPair> getFailed(CacheEvent event,
StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(failedPerEventStation);
query.setEntity("sta", station);
query.setEntity("event", event);
return query.list();
}
public List<AbstractEventChannelPair> getFailed(CacheEvent event) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(failedPerEvent);
query.setEntity("event", event);
return query.list();
}
public List<AbstractEventChannelPair> getRetry(StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(retry);
query.setEntity("sta", station);
return query.list();
}
public List<AbstractEventChannelPair> getRetry(CacheEvent event) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(retryPerEvent);
query.setEntity("event", event);
return query.list();
}
public List<AbstractEventChannelPair> getRetry(CacheEvent event, StationImpl station) {
if (totalSuccess == null) { initHQLStmts(); }
Query query = getSession().createQuery(retryPerEventStation);
query.setEntity("sta", station);
query.setEntity("event", event);
return query.list();
}
public List<StationImpl> getStationsForEvent(CacheEvent event) {
String q = "select distinct ecp.esp.station from "
+ getEcpClass().getName()
+ " ecp where ecp.event = :event";
Query query = getSession().createQuery(q);
query.setEntity("event", event);
return query.list();
}
public List<StationImpl> getSuccessfulStationsForEvent(CacheEvent event) {
String q = "select distinct ecp.esp.station from "
+ getEcpClass().getName()
+ " ecp where ecp.event = :event and ecp.status.stageInt = "
+ Stage.PROCESSOR.getVal()+" and ecp.status.standingInt = "+ Standing.SUCCESS.getVal();
Query query = getSession().createQuery(q);
query.setEntity("event", event);
return query.list();
}
public List<StationImpl> getUnsuccessfulStationsForEvent(CacheEvent event) {
String q = "from " + StationImpl.class.getName()
+ " s where s not in ("
+ "select distinct ecp.esp.station from "
+ getEcpClass().getName()
+ " ecp where ecp.event = :event and ecp.status.stageInt = "
+ Stage.PROCESSOR.getVal()+" and ecp.status.standingInt = "+ Standing.SUCCESS.getVal()
+ " )";
Query query = getSession().createQuery(q);
query.setEntity("event", event);
return query.list();
}
public List<CacheEvent> getEventsForStation(StationImpl sta) {
String q = "select distinct ecp.event from "
+ getEcpClass().getName()
+ " ecp where ecp.esp.station = :sta ";
Query query = getSession().createQuery(q);
query.setEntity("sta", sta);
return query.list();
}
public List<CacheEvent> getSuccessfulEventsForStation(StationImpl sta) {
String q = "select distinct ecp.event from "
+ getEcpClass().getName()
+ " ecp where ecp.esp.station = :sta and ecp.status.stageInt = "
+ Stage.PROCESSOR.getVal()+" and ecp.status.standingInt = "+ Standing.SUCCESS.getVal();
Query query = getSession().createQuery(q);
query.setEntity("sta", sta);
return query.list();
}
public List<CacheEvent> getUnsuccessfulEventsForStation(StationImpl sta) {
String q = "from "
+ CacheEvent.class.getName()
+ " e where e not in ("
+ "select distinct ecp.event from "
+ getEcpClass().getName()
+ " ecp where ecp.esp.station = :sta and ecp.status.stageInt = "
+ Stage.PROCESSOR.getVal()+" and ecp.status.standingInt = "+ Standing.SUCCESS.getVal()
+ " )";
Query query = getSession().createQuery(q);
query.setEntity("sta", sta);
return query.list();
}
public long put(RecordSectionItem item) {
return ((Long)getSession().save(item)).longValue();
}
public RecordSectionItem getRecordSectionItemForEvent(CacheEvent event,
ChannelImpl channel) {
String q = "from "
+ RecordSectionItem.class.getName()
+ " where event = :event and channel = :channel";
Query query = getSession().createQuery(q);
query.setEntity("event", event);
query.setEntity("channel", channel);
Iterator it = query.iterate();
if(it.hasNext()) {
return (RecordSectionItem)it.next();
}
return null;
}
/** Finds the recordsectionids for this event */
public List<String> getRecordSectionId(CacheEvent event) {
String q = "select distinct recordSectionId from "+ RecordSectionItem.class.getName()
+ " where event = :event";
Query query = getSession().createQuery(q);
query.setEntity("event", event);
return query.list();
}
/** Finds the recordsection orientationids for this event */
public List<String> getRecordSectionOrientations(CacheEvent event) {
String q = "select distinct orientationId from "+ RecordSectionItem.class.getName()
+ " where event = :event";
Query query = getSession().createQuery(q);
query.setEntity("event", event);
return query.list();
}
public RecordSectionItem getRecordSectionItem(String orientationId,
String recordSectionId,
CacheEvent event,
ChannelImpl channel) {
String q = "from "
+ RecordSectionItem.class.getName()
+ " where event = :event and channel = :channel and orientationId = :orientationId and recordSectionId = :recsecid";
Query query = getSession().createQuery(q);
query.setEntity("event", event);
query.setEntity("channel", channel);
query.setString("orientationId", orientationId);
query.setString("recsecid", recordSectionId);
Iterator it = query.iterate();
if(it.hasNext()) {
return (RecordSectionItem)it.next();
}
return null;
}
public List<StationImpl> getStationsForRecordSection(String orientationId,
String recordSectionId,
CacheEvent event,
boolean best) {
Query q = getSession().createQuery("select distinct channel.site.station from "
+ RecordSectionItem.class.getName()
+ " where recordSectionId = :recsecid and orientationId = :orientationId and event = :event and inBest = :best");
q.setEntity("event", event);
q.setString("recsecid", recordSectionId);
q.setString("orientationId", orientationId);
q.setBoolean("best", best);
return q.list();
}
public List<ChannelImpl> getChannelsForRecordSection(String orientationId,
CacheEvent event,
boolean best) {
Query q = getSession().createQuery("select distinct channel from "
+ RecordSectionItem.class.getName()
+ " where orientationId = :orientationId and event = :event and inBest = :best");
q.setEntity("event", event);
q.setString("orientationId", orientationId);
q.setBoolean("best", best);
return q.list();
}
public List<RecordSectionItem> getBestForRecordSection(String orientationId,
String recordSectionId,
CacheEvent event) {
Query q = getSession().createQuery("from "
+ RecordSectionItem.class.getName()
+ " where inBest = true and event = :event and orientationid = :orientationid and recordSectionId = :recsecid");
q.setEntity("event", event);
q.setString("orientationid", orientationId);
q.setString("recsecid", recordSectionId);
return q.list();
}
public boolean updateBestForRecordSection(String orientationId,
String recordSectionId,
CacheEvent event,
ChannelId[] channelIds) {
String msg = "updateBestForRecordSection("+ orientationId+", "+ recordSectionId+", "+ event+", "+channelIds.length;
String chanIdStr = "";
for (int i = 0; i < channelIds.length; i++) {
msg+= " "+channelIds[i].network_id.network_code+"."+channelIds[i].station_code;
chanIdStr += " "+ChannelIdUtil.toStringNoDates(channelIds[i]);
}
logger.debug(msg);
logger.debug("RecordSection chan ids: "+chanIdStr);
List<RecordSectionItem> best = getBestForRecordSection(orientationId,
recordSectionId,
event);
msg = "Cur Best RecordSection: "+ orientationId+", "+ recordSectionId+", "+ event+", "+best.size();
for (RecordSectionItem rs : best) {
msg += " "+rs.getChannel().getId().network_id.network_code+"."+rs.getChannel().getId().station_code;
}
logger.debug(msg);
HashMap<String, ChannelId> removes = new HashMap<String, ChannelId>();
Iterator<RecordSectionItem> it = best.iterator();
while(it.hasNext()) {
ChannelId cId = it.next().channel.get_id();
removes.put(ChannelIdUtil.toString(cId), cId);
}
HashMap<String, ChannelId> adders = new HashMap<String, ChannelId>();
logger.debug("RecordSection updating "+channelIds.length+" recordSectionItems for "+recordSectionId+" for event "+event);
for(int i = 0; i < channelIds.length; i++) {
logger.debug("RecordSection channelid: "+ChannelIdUtil.toString(channelIds[i]));
adders.put(ChannelIdUtil.toString(channelIds[i]), channelIds[i]);
}
Iterator<String> chanIt = adders.keySet().iterator();
while(chanIt.hasNext()) {
String cId = chanIt.next();
if(removes.containsKey(cId)) {
// in both, so no change
removes.remove(cId);
chanIt.remove();
}
}
Query q;
if(removes.size() == 0 && adders.size() == 0) {
logger.debug("RecordSection No adds and no removes");
return false;
}
q = getSession().createQuery("from "
+ RecordSectionItem.class.getName()
+ " where inBest = true and event = :event and recordSectionId = :recsecid and orientationid = :orientationid and "
+ MATCH_CHANNEL_CODES);
chanIt = removes.keySet().iterator();
while(chanIt.hasNext()) {
ChannelId c = removes.get(chanIt.next());
logger.debug("RecordSection remove: " + q + " " + event.getDbid() + " "
+ recordSectionId + " " + c.channel_code + " "
+ c.site_code + " " + c.station_code + " "
+ c.network_id.network_code);
q.setEntity("event", event);
q.setString("orientationid", orientationId);
q.setString("recsecid", recordSectionId);
q.setString("chanCode", c.channel_code);
q.setString("siteCode", c.site_code);
q.setString("staCode", c.station_code);
q.setString("netCode", c.network_id.network_code);
Iterator dbit = q.iterate();
while(dbit.hasNext()) {
RecordSectionItem item = (RecordSectionItem)dbit.next();
logger.debug("RecordSection update false for "+ChannelIdUtil.toString(item.getChannel().get_id()));
item.setInBest(false);
getSession().update(item);
}
}
q = getSession().createQuery("from "
+ RecordSectionItem.class.getName()
+ " where inBest = false and event = :event and recordSectionId = :recsecid and orientationid = :orientationid and "
+ MATCH_CHANNEL_CODES);
chanIt = adders.keySet().iterator();
logger.debug("RecordSection adds.size()="+adders.size());
while(chanIt.hasNext()) {
ChannelId c = adders.get(chanIt.next());
logger.debug("RecordSection adds " + event.getDbid() + " "
+ recordSectionId + " " + c.channel_code + " "
+ c.site_code + " " + c.station_code + " "
+ c.network_id.network_code);
q.setEntity("event", event);
q.setString("orientationid", orientationId);
q.setString("recsecid", recordSectionId);
q.setString("chanCode", c.channel_code);
q.setString("siteCode", c.site_code);
q.setString("staCode", c.station_code);
q.setString("netCode", c.network_id.network_code);
Iterator dbit = q.iterate();
while(dbit.hasNext()) {
RecordSectionItem item = (RecordSectionItem)dbit.next();
logger.debug("RecordSection update true for "+ChannelIdUtil.toString(item.getChannel().get_id()));
item.setInBest(true);
getSession().saveOrUpdate(item);
}
}
best = getBestForRecordSection(orientationId,
recordSectionId,
event);
msg = "after update Best RecordSection: "+ orientationId+", "+ recordSectionId+", "+ event+", "+best.size();
for (RecordSectionItem rs : best) {
msg += " "+rs.getChannel().getId().network_id.network_code+"."+rs.getChannel().getId().station_code;
}
logger.debug(msg);
return true;
}
public List<RecordSectionItem> getRecordSectionItemList(String orientationId,
String recordSectionId,
CacheEvent event) {
Query q = getSession().createQuery("from "
+ RecordSectionItem.class.getName()
+ " where event = :event and orientationid = :orientationid and recordSectionId = :recsecid");
q.setEntity("event", event);
q.setString("orientationid", orientationId);
q.setString("recsecid", recordSectionId);
return q.list();
}
private static final String MATCH_CHANNEL_CODES = " channel.id.channel_code = :chanCode and channel.id.site_code = :siteCode and "
+ "channel.id.station_code = :staCode and channel.site.station.networkAttr.id.network_code = :netCode";
public List<RecordSectionItem> recordSectionsForEvent(CacheEvent event) {
Query q = getSession().createQuery("from "
+ RecordSectionItem.class.getName() + " where event = :event");
q.setEntity("event", event);
return q.list();
}
public int putConfig(SodConfig sodConfig) {
Integer dbid = (Integer)getSession().save(sodConfig);
return dbid.intValue();
}
public SodConfig getCurrentConfig() {
String q = "From edu.sc.seis.sod.SodConfig c ORDER BY c.time desc";
Query query = getSession().createQuery(q);
query.setMaxResults(1);
List<SodConfig> result = query.list();
if(result.size() > 0) {
return result.get(0);
}
return null;
}
public SodConfig getConfig(int configid) {
return (SodConfig)getSession().get(edu.sc.seis.sod.SodConfig.class, configid);
}
public QueryTime getQueryTime(String serverName, String serverDNS) {
String q = "From edu.sc.seis.sod.QueryTime q WHERE q.serverName = :serverName AND q.serverDNS = :serverDNS";
Query query = getSession().createQuery(q);
query.setString("serverName", serverName);
query.setString("serverDNS", serverDNS);
query.setMaxResults(1);
List<QueryTime> result = query.list();
if(result.size() > 0) {
return result.get(0);
}
return null;
}
public int putQueryTime(QueryTime qtime) {
QueryTime indb = getQueryTime(qtime.getServerName(), qtime.getServerDNS());
if (indb != null) {
indb.setTime(qtime.getTime());
getSession().saveOrUpdate(indb);
return indb.getDbid();
} else {
Integer dbid = (Integer)getSession().save(qtime);
return dbid.intValue();
}
}
public Version getDBVersion() {
String q = "From edu.sc.seis.sod.Version ORDER BY dbid desc";
Session session = getSession();
Query query = getSession().createQuery(q);
query.setMaxResults(1);
List result = query.list();
if(result.size() > 0) {
Version out = (Version)result.get(0);
return out;
}
Version v = Version.current();
session.save(v);
return v;
}
protected Version putDBVersion() {
Version v = getDBVersion();
Version current = Version.current();
current.setDbid(v.getDbid());
getSession().merge(current);
commit();
return current;
}
private Queue<AbstractEventChannelPair> retryToDo = new LinkedList<AbstractEventChannelPair>();
private Queue<EventNetworkPair> enpToDo = new LinkedList<EventNetworkPair>();
private Queue<EventStationPair> espToDo = new LinkedList<EventStationPair>();
private Queue<AbstractEventChannelPair> ecpToDo = new LinkedList<AbstractEventChannelPair>();
private String retry, failed, success, successPerEvent,
failedPerEvent, retryPerEvent, successPerEventStation,
failedPerEventStation, retryPerEventStation, totalSuccess,
eventBase;
private static final String COUNT = "SELECT COUNT(*) ";
public void initHQLStmts() {
String baseStatement = "FROM "+getEcpClass().getName()+" ecp WHERE ";
String staBase = baseStatement + " ecp.esp.station = :sta ";
String staEventBase = baseStatement
+ " ecp.esp.station = :sta and ecp.event = :event ";
Status pass = Status.get(Stage.PROCESSOR, Standing.SUCCESS);
String PROCESS_SUCCESS = " ecp.status.stageInt = "
+ pass.getStageInt()+" AND ecp.status.standingInt = "+pass.getStandingInt();
eventBase = baseStatement + " ecp.event = :event ";
success = staBase + " AND "+PROCESS_SUCCESS;
String failReq = " AND ecp.status.standingInt in (" + Standing.REJECT.getVal() + " , "+Standing.SYSTEM_FAILURE.getVal()+")";
failed = staBase + failReq;
String retryReq = " AND ecp.status.standingInt in (" + Standing.RETRY.getVal() + " , "+Standing.CORBA_FAILURE.getVal()+")";
retry = staBase + retryReq ;
successPerEvent = eventBase + " AND "+PROCESS_SUCCESS;
failedPerEvent = eventBase + failReq;
retryPerEvent = eventBase + retryReq;
successPerEventStation = staEventBase + " AND "+PROCESS_SUCCESS;
failedPerEventStation = staEventBase + failReq;
retryPerEventStation = staEventBase + retryReq;
totalSuccess = baseStatement + " "+PROCESS_SUCCESS;
espFromNet = "FROM "+EventStationPair.class.getName()+" esp WHERE "
+" esp.event = :event and esp.station.networkAttr = :net";
}
private String espFromNet;
public static Class<? extends AbstractEventChannelPair> discoverDbEcpClass() {
Class<? extends AbstractEventChannelPair> out;
try {
String q = "from " + EventVectorPair.class.getName();
Query query = getSession().createQuery(q);
query.setMaxResults(1);
List<EventChannelPair> result = query.list();
if(result.size() > 0) {
return EventVectorPair.class;
} else {
return EventChannelPair.class;
}
} catch(Throwable e) {
logger.warn("Exception in SodDB.discoverDbEcpClass()", e);
throw new RuntimeException("Exception in SodDB.discoverDbEcpClass()", e);
} finally {
rollback();
}
}
public static void setDefaultEcpClass(Class<? extends AbstractEventChannelPair> ecpClass) {
if (ecpClass == null) {throw new IllegalArgumentException("ECP Class cannot be null");}
SodDB.defaultEcpClass = ecpClass;
if (singleton != null && singleton.ecpClass != null && singleton.ecpClass != ecpClass) {
throw new RuntimeException("Setting ecpClass but session is already open with different ecpClass: set("+ecpClass+") != "+singleton.ecpClass);
}
}
public static Class<? extends AbstractEventChannelPair> defaultEcpClass = null;
public Class<? extends AbstractEventChannelPair> ecpClass = null;
public Class<? extends AbstractEventChannelPair> getEcpClass() {
if (ecpClass == null) {
if (defaultEcpClass == null) {
defaultEcpClass = discoverDbEcpClass();
}
ecpClass = defaultEcpClass;
}
return ecpClass;
}
public static SodDB getSingleton() {
synchronized(SodDB.class) {
if(singleton == null) {
singleton = new SodDB();
}
}
return singleton;
}
private static SodDB singleton;
}