Issue #2726: Edex graceful shutdown.

Refactored to use inheritance and separate logic where possible.
             Addressed comments.

Change-Id: I9e62414cd83121575bdf99a3b47466a7585bedb6

Former-commit-id: 6e015b3f61c20635077d6e8271e9b763e5a32fe1
This commit is contained in:
Richard Peter 2014-03-19 14:23:52 -05:00
parent 7e8e756798
commit dbba727f3d
206 changed files with 3562 additions and 2865 deletions

View file

@ -31,6 +31,7 @@ import org.eclipse.ui.statushandlers.StatusManager;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.message.WsId;
import com.raytheon.uf.common.util.SystemUtil;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
/**
@ -49,7 +50,7 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
* Aug 27, 2013 2295 bkowal Removed the jms server property; added
* jms connection string
* Feb 17, 2014 2812 njensen getHostName() now uses getWsId()'s hostname
*
* Mar 20, 2014 2726 rjpeter Moved host processing to SystemUtil.
* </pre>
*
* @author chammack
@ -252,21 +253,13 @@ public final class VizApp {
private static String host = null;
/**
* Gets the host name from the WsId of the host machine calling the function
* Gets the host name of the machine calling the function
*
* @return
*/
public static synchronized String getHostName() {
if (host == null) {
host = getWsId().getHostName();
if (host == null) {
String hostname = System.getenv("HOSTNAME");
if (hostname != null && hostname.trim().length() > 0) {
host = hostname;
} else {
host = "localhost";
}
}
host = SystemUtil.getHostName();
}
return host;
}

View file

@ -233,7 +233,6 @@
<UTILITYDIR>utilityDir</UTILITYDIR>
<STATICDIR>staticDir</STATICDIR>
<SITENAME>sitename</SITENAME>
<GFESMARTINIT>gfeSmartInitEnable</GFESMARTINIT>
<LOGDIR>logDir</LOGDIR>
<FXADEBUGSAVEBADTEXTFILES>fxaDebugSaveBadTextFiles</FXADEBUGSAVEBADTEXTFILES>
<ARCHIVEDIR>archiveDir</ARCHIVEDIR>

View file

@ -48,7 +48,6 @@
<shareDir>${env:edex.home}/data/share</shareDir>
<utilityDir>${env:edex.home}/data/utility</utilityDir>
<staticDir>${env:edex.home}/data/static</staticDir>
<gfeSmartInitEnable>true</gfeSmartInitEnable>
<fxaDebugSaveBadTextFiles>false</fxaDebugSaveBadTextFiles>
<svcBackupDir>${env:edex.home}/../GFESuite/</svcBackupDir>
<mhsData>/data/fxa/mhs</mhsData>

View file

@ -1,7 +0,0 @@
# The following properties are used to define the EDEX system configuration.
# Modifying these values will affect system performance.
smartinit.threadpoolsize=3
# smartinit.threads should be 2 less than smartinit.threadpoolszie
# to account for reading from the notify topic and the manual queue
smartinit.threads=1

View file

@ -1,7 +0,0 @@
# The following properties are used to define the EDEX system configuration.
# Modifying these values will affect system performance.
smartinit.threadpoolsize=4
# smartinit.threads should be 2 less than smartinit.threadpoolszie
# to account for reading from the notify topic and the manual queue
smartinit.threads=2

View file

@ -3,14 +3,14 @@
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<!-- Separated out database specific beans to seperate file so they can be loaded by themselves if necessary -->
<import resource="file:///${edex.home}/conf/spring/edex-db.xml"/>
<!-- Separated out database specific beans to separate file so they can be loaded by themselves if necessary -->
<import resource="file:///${edex.home}/conf/spring/edex-db.xml"/>
<!-- specify the connection to the broker (qpid) -->
<!-- MaxPrefetch set at 0, due to DataPool routers getting messages backed up behind long running tasks -->
<bean id="amqConnectionFactory" class="org.apache.qpid.client.AMQConnectionFactory">
@ -24,7 +24,7 @@
<!-- After resource has been closed by thread keep it allocated for another 2 minutes in case thread needs it again -->
<property name="resourceRetention" value="120000"/>
</bean>
<bean id="genericThreadPool"
class="com.raytheon.uf.edex.esb.camel.spring.JmsThreadPoolTaskExecutor">
<property name="corePoolSize" value="0" />
@ -64,12 +64,14 @@
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="cacheLevelName" value="CACHE_NONE"/>
<property name="recoveryInterval" value="10000"/>
<property name="requestTimeout" value="5000"/>
<property name="requestTimeout" value="5000"/>
<!-- If this is false, while stopping we will reject messages that have already been pulled from qpid, essentially losing the message -->
<property name="acceptMessagesWhileStopping" value="true"/>
<!-- receiveTimeout is amount of time thread waits to receive a message before recycling -->
<!-- receiveTimeout also affects how fast a JMSConsumer will shut down, because the
thread may be stuck polling for the duration of receiveTimeout before shutting down -->
<property name="receiveTimeout" value="10000"/>
<property name="receiveTimeout" value="5000"/>
<property name="transacted" value="false"/>
<!-- force maxMessagesPerTask so that the threads don't keep disconnecting and reconnecting.
@ -80,7 +82,7 @@
<property name="destinationResolver" ref="qpidNoDurableResolver" />
<property name="disableReplyTo" value="true" />
<property name="deliveryPersistent" value="false"/>
<!--
<property name="transacted" value="true" />
<property name="acknowledgementModeName" value="TRANSACTED"/>
@ -98,28 +100,27 @@
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
-->
<bean id="httpClient" class="com.raytheon.uf.common.comm.HttpClient" factory-method="getInstance">
<property name="maxConnectionsPerHost" value="${PYPIES_MAX_CONN}"/>
<!-- value in milliseconds to allow socket to timeout, don't allow this to be zero, bad things could happen -->
<property name="socketTimeout" value="180000"/>
<property name="compressRequests" value="false"/>
<property name="gzipResponseHandling" value="false"/>
<property name="socketTimeout" value="180000"/>
<property name="compressRequests" value="false"/>
<property name="gzipResponseHandling" value="false"/>
</bean>
<bean id="pypiesStoreProps" class="com.raytheon.uf.common.pypies.PypiesProperties">
<property name="address" value="${PYPIES_SERVER}" />
<property name="address" value="${PYPIES_SERVER}" />
</bean>
<bean id="pypiesDataStoreFactory" class="com.raytheon.uf.common.pypies.PyPiesDataStoreFactory">
<bean id="pypiesDataStoreFactory" class="com.raytheon.uf.common.pypies.PyPiesDataStoreFactory" depends-on="httpClient">
<constructor-arg ref="pypiesStoreProps" />
</bean>
<bean id="dataStoreFactory" class="com.raytheon.uf.common.datastorage.DataStoreFactory" factory-method="getInstance">
<!-- Get instance of DataStoreFactory and set underlying factory to use -->
<property name="underlyingFactory" ref="pypiesDataStoreFactory"/>
</bean>
<bean id="initialcorePropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName">
@ -136,53 +137,84 @@
<bean id="processUtil" class="com.raytheon.uf.edex.esb.camel.ProcessUtil"/>
<bean id="setIngestHeaderFields" class="com.raytheon.uf.edex.esb.camel.SetIngestHeaderFields"/>
<bean id="uuidGenerator" class="com.raytheon.uf.edex.esb.camel.UUIDGenerator"/>
<bean id="messageUtil" class="com.raytheon.uf.edex.esb.camel.MessageProducer" />
<bean id="messageProducer" class="com.raytheon.uf.edex.esb.camel.MessageProducer" />
<bean id="camelContextAdmin" class="com.raytheon.uf.edex.esb.camel.CamelContextAdmin" />
<bean id="util" class="com.raytheon.uf.edex.core.EDEXUtil">
<property name="messageProducer" ref="messageUtil" />
<property name="contextAdmin" ref="camelContextAdmin" />
<!-- ContextManager to manage dependencies so routes startup in right order.
Clustered routes will start on a box if there has not been a lock for that route in the last 60 seconds.
Anyone using the clustered routes should ensure that timeToLive on jms messages are at least 1 minute-->
<bean id="contextManager"
class="com.raytheon.uf.edex.esb.camel.context.ContextManager"
factory-method="getInstance">
<property name="timeOutMillis" value="60000"/>
</bean>
<bean id="initSystem" class="com.raytheon.edex.plugin.InitializerBean" />
<bean id="util" class="com.raytheon.uf.edex.core.EDEXUtil">
<property name="messageProducer" ref="messageProducer" />
<property name="contextAdmin" ref="camelContextAdmin" />
</bean>
<bean id="defaultPathProvider" class="com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider"/>
<bean id="commonDbPluginProperties" class="com.raytheon.uf.edex.database.DatabasePluginProperties">
<property name="pluginFQN" value="com.raytheon.uf.edex.database" />
<property name="database" value="metadata" />
<property name="forceCheck" value="true" />
</bean>
<bean
id="dbPluginRegistry"
class="com.raytheon.uf.edex.database.DatabasePluginRegistry"
factory-method="getInstance"
init-method="init"
depends-on="metadataTxManager">
<property name="initialListeners">
<list>
<!-- This causes database tables to be initialized when a db plugin is registered -->
<bean class="com.raytheon.uf.edex.database.schema.SchemaManager" factory-method="getInstance"/>
</list>
</property>
<property name="initialProperties">
<list>
<!-- Creates the initial tables so other plugins can be loaded -->
<ref bean="commonDbPluginProperties"/>
</list>
</property>
</bean>
<!-- The pluginDefaults are the values that a data plugin will use for
some plugin properties if they are not specified in the individual
plugin's Spring XML configuration -->
<bean id="pluginDefaults" class="com.raytheon.uf.common.dataplugin.defaults.PluginPropertyDefaults">
<property name="database" value="metadata" />
<property name="initializer" value="com.raytheon.edex.plugin.DefaultPluginInitializer" />
<property name="dao" value="com.raytheon.edex.db.dao.DefaultPluginDao" />
<property name="initialRetentionTime" value="24" />
<property name="pathProvider" ref="defaultPathProvider"/>
</bean>
<bean id="pluginDefaults" class="com.raytheon.uf.common.dataplugin.PluginProperties">
<property name="database" value="metadata" />
<property name="initializer" value="com.raytheon.edex.plugin.DefaultPluginInitializer" />
<property name="dao" value="com.raytheon.edex.db.dao.DefaultPluginDao" />
<property name="initialRetentionTime" value="24" />
<property name="pathProvider" ref="defaultPathProvider"/>
</bean>
<!-- This causes database tables to be initialized when a db plugin is registered -->
<bean id="schemaManager" class="com.raytheon.uf.edex.database.schema.SchemaManager"
factory-method="getInstance" />
<bean factory-bean="dbPluginRegistry" factory-method="addListener">
<constructor-arg><ref bean="schemaManager"/></constructor-arg>
<bean
id="pluginRegistry"
class="com.raytheon.uf.edex.core.dataplugin.PluginRegistry"
factory-method="getInstance"
depends-on="util, dataStoreFactory">
<property name="defaultPluginProperties" ref="pluginDefaults"/>
<property name="initialListeners">
<list>
<!-- This causes the data plugin's database tables to be created when a plugin is registered -->
<ref bean="dbPluginRegistry"/>
<!-- This causes the data plugin's initializer to get called when a plugin is registered -->
<bean class="com.raytheon.edex.plugin.PluginInitialSetup"/>
</list>
</property>
</bean>
<!-- This causes the data plugin's database tables to be created when a plugin is registered -->
<bean id="dbPluginRegistryListenerAdded" factory-bean="pluginRegistry" factory-method="addListener">
<constructor-arg><ref bean="dbPluginRegistry"/></constructor-arg>
</bean>
<!-- This causes the data plugin's initializer to get called when a plugin
is registered -->
<bean id="pluginSetup" class="com.raytheon.edex.plugin.PluginInitialSetup" />
<bean factory-bean="pluginRegistry" factory-method="addListener" depends-on="dbPluginRegistryListenerAdded">
<constructor-arg><ref bean="pluginSetup"/></constructor-arg>
</bean>
<bean id="stringToFile" class="com.raytheon.uf.edex.esb.camel.StringToFile"/>
<bean id="extractWMOHeader" class="com.raytheon.uf.common.util.header.WMOHeaderRemover"/>
<bean id="dataUnzipper" class="com.raytheon.uf.common.util.DataUnzipper"/>
<bean id="dataUnzipper" class="com.raytheon.uf.common.util.DataUnzipper"/>
<bean id="errorHandler" class="org.apache.camel.builder.LoggingErrorHandlerBuilder"/>
<!-- sets default settings of log component across all of edex -->
<!-- if log component beans are created and the exchangeFormatter property is set, they can't process URI parameters -->
<!-- this bean needs to be named 'logFormatter' for the log component to find it in the context -->
@ -193,38 +225,10 @@
<property name="showStackTrace" value="true" />
</bean>
<bean id="serializationUtil" class="com.raytheon.uf.common.serialization.SerializationUtil" />
<bean id="serializationUtil" class="com.raytheon.uf.common.serialization.SerializationUtil" />
<bean id="pluginRegistry" class="com.raytheon.uf.edex.core.dataplugin.PluginRegistry" factory-method="getInstance"/>
<bean id="dbPluginRegistry" class="com.raytheon.uf.edex.database.DatabasePluginRegistry" factory-method="getInstance"/>
<bean id="commonDbPluginProperties" class="com.raytheon.uf.edex.database.DatabasePluginProperties">
<property name="pluginFQN" value="com.raytheon.uf.edex.database" />
<property name="database" value="metadata" />
<property name="forceCheck" value="true" />
</bean>
<bean id="commonDbRegistered" factory-bean="dbPluginRegistry" factory-method="register"
depends-on="metadataTxManager">
<constructor-arg value="com.raytheon.uf.edex.database"/>
<constructor-arg ref="commonDbPluginProperties"/>
</bean>
<bean id="CamelBeanParameterMappingStrategy"
class="com.raytheon.uf.edex.esb.camel.EDEXParameterMappingStrategy" />
<!-- ContextManager to start camel context last. Ensures items such as distribution aren't started before all the listening routes are up -->
<bean id="contextManager"
class="com.raytheon.uf.edex.esb.camel.context.ContextManager"
factory-method="getInstance">
</bean>
<!-- Clustered routes will start on a box if there has not been a lock for that route in the last 60 seconds.
Anyone using the clustered routes should ensure that timeToLive on jms messages are at least 1 minute -->
<bean id="clusteredCamelContextMgr"
class="com.raytheon.uf.edex.esb.camel.context.ClusteredContextManager"
factory-method="getInstance">
<property name="timeOutMillis" value="60000"/>
</bean>
class="com.raytheon.uf.edex.esb.camel.EDEXParameterMappingStrategy" />
<!-- Serialization Pool -->
<bean id="baosPool" class="com.raytheon.uf.common.util.ByteArrayOutputStreamPool" factory-method="getInstance">
@ -248,7 +252,7 @@
<from uri="jms-generic:topic:edex.alerts.utility" />
<bean ref="edexLocalizationObserver" method="fileUpdated"/>
</route>
<!-- Route to send alerts to alertviz -->
<route id="alertVizNotify">
<from uri="vm:edex.alertVizNotification" />
@ -263,13 +267,6 @@
<to uri="jms-generic:topic:edex.alarms.msg" />
</route>
<!-- Route to send geospatial data update notification -->
<route id="geospatialUpdateNotify">
<from uri="vm:edex.geospatialUpdateNotification" />
<bean ref="serializationUtil" method="transformToThrift" />
<to uri="jms-generic:topic:edex.geospatialUpdate.msg" />
</route>
<!-- Route to periodically close any unused jms resources that have been pooled -->
<route id="jmsPooledResourceChecker">
<from uri="timer://jmsPooledResourceCheck?period=60s" />
@ -281,16 +278,15 @@
</doCatch>
</doTry>
</route>
</camelContext>
</camelContext>
<camelContext
id="clusteredCamel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<route id="monitorClusteredContexts">
<from uri="timer://monitorClusterContexts?fixedRate=true&amp;period=20000"/>
<doTry>
<bean ref="clusteredCamelContextMgr" method="checkClusteredContexts" />
<bean ref="contextManager" method="checkClusteredContexts" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:monitorClusteredContexts?level=ERROR"/>
@ -298,10 +294,6 @@
</doTry>
</route>
</camelContext>
<bean factory-bean="contextManager"
factory-method="register">
<constructor-arg ref="clusteredCamel"/>
</bean>
<!-- Redirect geotools log -->
<bean class="com.raytheon.uf.common.geospatial.LogRedirector" factory-method="setGeotoolsLogFactory">
@ -314,7 +306,6 @@
<property name="locations">
<list>
<value>file:${edex.home}/conf/spring/cron.properties</value>
<value>file:${edex.home}/conf/spring/${edex.arch}/architecture.properties</value>
</list>
</property>
</bean>
@ -322,11 +313,11 @@
<!-- Holds the registry of request routers by server key -->
<bean id="handlerRegistry" class="com.raytheon.uf.edex.auth.HandlerRegistry"
factory-method="getInstance" />
<bean id="requestRouterRegistry"
class="com.raytheon.uf.common.serialization.comm.RequestRouter"
factory-method="getRouterRegistry" />
<!-- Server Request routers -->
<bean id="serverPrivilegedRequestHandler"
class="com.raytheon.uf.edex.auth.req.ServerPrivilegedRequestHandler">
@ -341,7 +332,7 @@
<util:constant id="requestServerKey"
static-field="com.raytheon.uf.common.auth.RequestConstants.REQUEST_SERVER" />
<bean id="requestServiceRouter" class="com.raytheon.uf.edex.auth.ServerRequestRouter">
<!-- This bean will cause all RequestRouter.route(request) calls
to be processed internally to EDEX -->
@ -353,14 +344,10 @@
<constructor-arg ref="requestServiceRouter" />
</bean>
<!-- needed for camel quartz component workaround when JMX is disabled -->
<bean id="managementNameLifecycleStrategy"
class="com.raytheon.uf.edex.esb.camel.quartz.ManagementNameLifecycleStrategy" />
<!-- quartz component configuration.
Single scheduler used by all endpoints so there is only one threadpool.
Thread pool configured in edex/config/resources/quartz.properties -->
Single scheduler used by all endpoints so there is only one threadpool.
Thread pool configured in edex/config/resources/quartz.properties.
Requires work around in ContextManager.postProcessBeanFactory when JMX is disabled -->
<bean id="quartzSchedulerFactory" class="org.quartz.impl.StdSchedulerFactory">
<constructor-arg value="quartz.properties" />
</bean>
@ -376,5 +363,4 @@
class="com.raytheon.uf.edex.esb.camel.cluster.quartz.ClusteredQuartzComponent">
<property name="scheduler" ref="quartzScheduler" />
</bean>
</beans>

View file

@ -160,6 +160,10 @@ wrapper.app.parameter.2=start
wrapper.ping.timeout=300
# jvm will be hard killed after 5 minutes of trying to shutdown
wrapper.jvm_exit.timeout=0
wrapper.shutdown.timeout=300
#********************************************************************
# Monitor the Application
#********************************************************************

View file

@ -23,8 +23,6 @@ export MAX_MEM=1300 # in Meg
export MAX_PERM_SIZE=128m
export EDEX_JMX_PORT=1616
export EDEX_DEBUG_PORT=5005
export JMS_POOL_MIN=64
export JMS_POOL_MAX=128
export METADATA_POOL_MIN=5
export METADATA_POOL_MAX=50
export METADATA_POOL_TIMEOUT=300

View file

@ -21,8 +21,6 @@
export INIT_MEM=256 # in Meg
export MAX_MEM=1792 # in Meg
export JMS_POOL_MIN=16
export JMS_POOL_MAX=32
export METADATA_POOL_MIN=15
export METADATA_POOL_MAX=30
export EDEX_DEBUG_PORT=5008

View file

@ -21,8 +21,6 @@
export INIT_MEM=128 # in Meg
export MAX_MEM=512 # in Meg
export JMS_POOL_MIN=4
export JMS_POOL_MAX=16
export METADATA_POOL_MIN=4
export METADATA_POOL_MAX=10
export EDEX_DEBUG_PORT=5007

View file

@ -29,8 +29,6 @@ export SERIALIZE_STREAM_INIT_SIZE_MB=2
export SERIALIZE_STREAM_MAX_SIZE_MB=8
export JMS_POOL_MIN=16
export JMS_POOL_MAX=32
export EDEX_DEBUG_PORT=5005
export EDEX_JMX_PORT=1616
export MGMT_PORT=9601

View file

@ -29,8 +29,6 @@ export SERIALIZE_STREAM_INIT_SIZE_MB=2
export SERIALIZE_STREAM_MAX_SIZE_MB=8
export JMS_POOL_MIN=8
export JMS_POOL_MAX=24
export EDEX_DEBUG_PORT=5005
export EDEX_JMX_PORT=1616
export MGMT_PORT=9601

View file

@ -20,8 +20,8 @@
depends-on="metadataTxManager">
<constructor-arg value="com.raytheon.edex.autobldsrv"/>
<constructor-arg ref="subscriptionDbPluginProperties"/>
</bean>
<camelContext id="subscription-common-camel"
</bean>
<camelContext id="subscription-common-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<route id="subscriptionNotify">
@ -34,7 +34,7 @@
</doCatch>
</doTry>
</route>
<!-- LDAD (watch/warn) triggered script runner, internal use only -->
<route id="ldadWatchWarnDirect">
<from uri="direct-vm:ldadWatchWarnDirect"/>

View file

@ -5,13 +5,13 @@
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="subscription" class="com.raytheon.edex.services.SubscribeManager"/>
<camelContext id="subscription-camel"
xmlns="http://camel.apache.org/schema/spring"
<camelContext id="subscription-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<endpoint id="subscriptionHTTP_from"
uri="jetty:http://0.0.0.0:${HTTP_PORT}/services/subscribe?disableStreamCache=true" />
<!-- SubscriptionSrv routes -->
uri="jetty:http://0.0.0.0:${HTTP_PORT}/services/subscribe?disableStreamCache=true" />
<!-- SubscriptionSrv routes -->
<route id="subscriptionHTTP">
<from uri="ref:subscriptionHTTP_from" />
<bean ref="subscription" method="processRequest"/>

View file

@ -8,14 +8,14 @@
<bean id="timerScriptRunner" class="com.raytheon.edex.services.ScriptRunner" >
<property name="type" value="timer" />
</bean>
<!-- define the bean that handles data arrival script running -->
<!--
<bean id="dataScriptRunner" class="com.raytheon.edex.services.ScriptRunner">
<property name="type" value="data" />
</bean>
-->
<camelContext id="subscription-camel"
<camelContext id="subscription-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">

View file

@ -1,72 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This class is instantiated on startup by the ESB spring container context
* before any other beans. Therefore, any system level initialization activities
* may be placed here.
* <p>
* The basic functionality of this class will initialize all the plugins
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 02/06/09 1990 bphillip Initial creation
* </pre>
*
* @author bphillip
* @version 1.0
*/
public class InitializerBean {
/** The logger */
protected transient Log logger = LogFactory.getLog(getClass());
/**
* Creates a new Initializer bean
* <p>
* This bean should never be explicitly instantiated
*/
public InitializerBean() {
// Check to see if the plugin version table exists. If not, the schema
// needs to be exported to the database
/*
* pvd = new PluginVersionDao(); if (!pvd.isDbInitialized()) {
* logger.warn("Databases have not been initialized...");
* logger.info("Initializing Databases...");
* logger.info("Exporting common table ddls...");
* SchemaManager.getInstance().createCommonTables();
* logger.info("Running setup scripts..."); try {
* SchemaManager.getInstance().runCommonScripts(); } catch
* (PluginException e) { logger.fatal("ERROR RUNNING COMMON SCRIPTS!",
* e); }
*
* }
*/
logger.info("Database initialization complete!");
}
}

View file

@ -4,7 +4,7 @@
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="binlightningDecoder"
class="com.raytheon.edex.plugin.binlightning.BinLightningDecoder" />
class="com.raytheon.edex.plugin.binlightning.BinLightningDecoder" />
<bean id="binlightningDistRegistry" factory-bean="distributionSrv"
factory-method="register">
@ -12,16 +12,14 @@
<constructor-arg value="jms-durable:queue:Ingest.binlightning" />
</bean>
<bean id="binlightningCamelRegistered" factory-bean="clusteredCamelContextMgr"
factory-method="register" depends-on="persistCamelRegistered">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredBinLightningRoutes" />
</bean>
</bean>
<camelContext id="clusteredBinLightningRoutes"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
<!--
errorHandlerRef="errorHandler">
<!--
<endpoint id="binlightningFileEndpoint"
uri="file:${edex.home}/data/sbn/binlightning?noop=true&amp;idempotent=false" />

View file

@ -11,15 +11,9 @@
<constructor-arg value="jms-durable:queue:Ingest.bufrmos" />
</bean>
<bean id="bufrmosCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="bufrmos-camel"/>
</bean>
<camelContext id="bufrmos-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="bufrmosFileEndpoint"
uri="file:${edex.home}/data/sbn/bufrmos?noop=true&amp;idempotent=false" />

View file

@ -14,11 +14,6 @@
<constructor-arg value="jms-durable:queue:Ingest.bufrua" />
</bean>
<bean id="bufruaCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="bufrua-camel"/>
</bean>
<bean id="raobListener" class="com.raytheon.edex.plugin.bufrua.ingest.RAOBSubscriber" />
<bean factory-bean="ndmProc" factory-method="registerListener">
@ -36,8 +31,7 @@
<camelContext id="bufrua-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="bufruaFileEndpoint" uri="file:${edex.home}/data/sbn/bufrua?noop=true&amp;idempotent=false"/>

View file

@ -12,14 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.ccfp" />
</bean>
<bean id="ccfpCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ccfp-camel"/>
</bean>
<camelContext id="ccfp-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="ccfpFileEndpoint" uri="file:${edex.home}/data/sbn/ccfp?noop=true&amp;idempotent=false" />

View file

@ -2,4 +2,5 @@ source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/
res/,\
resources/

View file

@ -28,7 +28,7 @@
</bean>
<bean id="gfeSiteActivation" class="com.raytheon.edex.plugin.gfe.config.GFESiteActivation" factory-method="getInstance"
depends-on="commonTimeRegistered, gfeRegistered">
depends-on="commonTimeRegistered, gfeDbRegistered">
</bean>
<bean id="gfeNotifyFilter" class="com.raytheon.edex.plugin.gfe.server.notify.GfeNotificationFilter"/>
@ -36,7 +36,6 @@
<bean id="ifpServer" class="com.raytheon.edex.plugin.gfe.server.IFPServer.Wrapper"/>
<camelContext id="gfe-common-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<route id="gfeNotify">
<from uri="vm:edex.gfeNotification?size=5000"/>
<doTry>

View file

@ -344,19 +344,14 @@
<!-- ISC Send Beans -->
<bean id="iscSendQueue" class="com.raytheon.edex.plugin.gfe.isc.IscSendQueue" factory-method="getInstance"/>
<bean id="iscSendThreadPool" class="com.raytheon.uf.edex.esb.camel.spring.JmsThreadPoolTaskExecutor">
<property name="corePoolSize" value="1" />
<property name="maxPoolSize" value="1" />
</bean>
<bean id="iscSendSrvCfg" class="com.raytheon.edex.plugin.gfe.isc.SendIscSrvConfig">
<property name="executor" ref="iscSendThreadPool"/>
<!-- Threads should be same size as the iscSendThreadPool -->
<property name="threads" value="1"/>
<bean id="sendIscSrv" class="com.raytheon.edex.plugin.gfe.isc.SendIscSrv" depends-on="gfeDbRegistered, gfeSitesActiveRequest">
<property name="runningTimeOutMillis" value="300000"/>
<property name="threadSleepInterval" value="5000"/>
</bean>
<bean depends-on="gfeDbRegistered, gfeSitesActiveRequest" id="sendIscSrv" class="com.raytheon.edex.plugin.gfe.isc.SendIscSrv">
<constructor-arg ref="iscSendSrvCfg"/>
<bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
<constructor-arg ref="gfe-request-camel"/>
<constructor-arg ref="sendIscSrv"/>
</bean>
<!-- End ISC Send Beans -->
@ -420,6 +415,7 @@
<endpoint id="exportDigitalDataCron" uri="clusteredquartz://gfe/exportDigitalData/?cron=${gfe.cron}"/>
<endpoint id="gfeLogPurgeCron" uri="clusteredquartz://gfe/purgeGfeLogs/?cron=${purge.logs.cron}"/>
<endpoint id="svcbuLogPurgeCron" uri="clusteredquartz://gfe/purgeSvcbuLogs/?cron=${purge.svcbu.logs.cron}"/>
<endpoint id="iscSendLauncher" uri="timer://iscSendThread?repeatCount=1"/>
<route id="exportDigitalData">
<from uri="exportDigitalDataCron"/>
@ -488,11 +484,16 @@
</doCatch>
</doTry>
</route>
<!-- Thread runs for life of context -->
<route id="iscSendThread">
<from ref="iscSendLauncher"/>
<bean ref="sendIscSrv" method="run"/>
</route>
</camelContext>
<!-- ISC Send Routes -->
<camelContext id="clusteredGfeIscRoutes" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler"
autoStartup="false">
<camelContext id="clusteredGfeIscRoutes" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<route id="iscSendJobQueueAggr">
<from uri="jms-durable:queue:iscSendNotification" />
@ -512,7 +513,7 @@
</route>
</camelContext>
<bean factory-bean="clusteredCamelContextMgr" factory-method="register">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredGfeIscRoutes"/>
</bean>
</beans>

View file

@ -4,24 +4,20 @@
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="smartInitQueue" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitQueue" factory-method="createQueue"/>
<bean id="smartInitThreadPool" class="com.raytheon.uf.edex.esb.camel.spring.JmsThreadPoolTaskExecutor">
<property name="corePoolSize" value="${smartinit.threads}" />
<property name="maxPoolSize" value="${smartinit.threads}" />
<bean id="gfeSitesActiveIngest" factory-bean="siteAwareRegistry" factory-method="register" depends-on="smartInitQueue">
<constructor-arg ref="gfeSiteActivation"/>
</bean>
<bean id="smartInitSrvCfg" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitSrvConfig">
<property name="executor" ref="smartInitThreadPool"/>
<property name="threads" value="${smartinit.threads}"/>
<bean id="smartInitSrv" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitSrv" depends-on="gfeDbRegistered, gfeSitesActiveIngest">
<property name="pendingInitMinTimeMillis" value="120000"/>
<property name="runningInitTimeOutMillis" value="600000"/>
<property name="threadSleepInterval" value="30000"/>
</bean>
<bean depends-on="smartInitQueue" id="gfeSitesActiveIngest" factory-bean="siteAwareRegistry" factory-method="register">
<constructor-arg ref="gfeSiteActivation"/>
</bean>
<bean depends-on="gfeDbRegistered, gfeSitesActiveIngest" id="smartInitSrv" class="com.raytheon.edex.plugin.gfe.smartinit.SmartInitSrv">
<constructor-arg ref="smartInitSrvCfg"/>
<bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
<constructor-arg ref="gfe-camel-spring"/>
<constructor-arg ref="smartInitSrv"/>
</bean>
<bean id="spcWatch" class="com.raytheon.edex.plugin.gfe.spc.SPCWatchSrv"/>
@ -29,8 +25,10 @@
<bean id="wclWatch" class="com.raytheon.edex.plugin.gfe.wcl.WCLWatchSrv"/>
<bean id="vtecChangeListener" class="com.raytheon.edex.plugin.gfe.server.notify.VTECTableChangeListener"/>
<camelContext id="gfe-camel-spring" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<endpoint id="smartInitLauncher" uri="timer://smartInitThread?repeatCount=${smartinit.threads}"/>
<route id="SPCWatch">
<from uri="vm:gfe.spcWatch"/>
<doTry>
@ -72,6 +70,12 @@
<bean ref="smartInitQueue" method="fireSmartInit"/>
</route>
<!-- Thread runs for life of context -->
<route id="smartInitThread">
<from ref="smartInitLauncher"/>
<bean ref="smartInitSrv" method="run"/>
</route>
<route id="gfeIngestNotification">
<!-- Data from plugin notification -->
<from
@ -103,7 +107,7 @@
</camelContext>
<camelContext id="clusteredGfeIngestRoutes" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<!-- Smart Init Routes -->
<!-- main route now handled through the gfeIngestNotification -->
@ -134,7 +138,7 @@
</camelContext>
<bean factory-bean="clusteredCamelContextMgr" factory-method="register">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredGfeIngestRoutes"/>
</bean>
</beans>

View file

@ -0,0 +1,2 @@
# The number of smart init threads to use
smartinit.threads=2

View file

@ -59,20 +59,21 @@ import com.raytheon.uf.edex.site.notify.SendSiteActivationNotifications;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 9, 2009 njensen Initial creation
* Oct 26, 2010 #6811 jclark changed listener type
* Apr 06, 2012 #457 dgilling Clear site's ISCSendRecords on
* site deactivation.
* Jul 12, 2012 15162 ryu added check for invalid db at activation
* Dec 11, 2012 14360 ryu log a clean message in case of
* missing configuration (no stack trace).
* Feb 15, 2013 1638 mschenke Moved sending of site notification messages to edex plugin
* Feb 28, 2013 #1447 dgilling Enable active table fetching on site
* activation.
* Mar 20, 2013 #1774 randerso Changed to use GFED2DDao
* May 02, 2013 #1969 randerso Moved updateDbs method into IFPGridDatabase
* Jun 13, 2013 #2044 randerso Refactored to use IFPServer
* Oct 16, 2013 #2475 dgilling Better error handling for IRT activation.
* Jul 9, 2009 njensen Initial creation
* Oct 26, 2010 #6811 jclark changed listener type
* Apr 06, 2012 #457 dgilling Clear site's ISCSendRecords on
* site deactivation.
* Jul 12, 2012 15162 ryu added check for invalid db at activation
* Dec 11, 2012 14360 ryu log a clean message in case of
* missing configuration (no stack trace).
* Feb 15, 2013 1638 mschenke Moved sending of site notification messages to edex plugin
* Feb 28, 2013 #1447 dgilling Enable active table fetching on site
* activation.
* Mar 20, 2013 #1774 randerso Changed to use GFED2DDao
* May 02, 2013 #1969 randerso Moved updateDbs method into IFPGridDatabase
* Jun 13, 2013 #2044 randerso Refactored to use IFPServer
* Oct 16, 2013 #2475 dgilling Better error handling for IRT activation.
* Mar 21, 2014 2726 rjpeter Updated wait for running loop.
* </pre>
*
* @author njensen
@ -87,14 +88,8 @@ public class GFESiteActivation implements ISiteActivationListener {
private static final String INIT_TASK_DETAILS = "Initialization:";
private static final String SMART_INIT_TASK_DETAILS = "SmartInit:";
private static final int LOCK_TASK_TIMEOUT = 180000;
// don't rerun the smart init fire if they have been run in the last 30
// minutes
private static final int SMART_INIT_TIMEOUT = 1800000;
private static GFESiteActivation instance = new GFESiteActivation();
private boolean intialized = false;
@ -297,7 +292,7 @@ public class GFESiteActivation implements ISiteActivationListener {
statusHandler.info("IFPServerConfigManager initializing...");
config = IFPServerConfigManager.initializeSite(siteID);
statusHandler.info("Activating IFPServer...");
IFPServer ifpServer = IFPServer.activateServer(siteID, config);
IFPServer.activateServer(siteID, config);
} finally {
statusHandler
.handle(Priority.INFO,
@ -345,16 +340,7 @@ public class GFESiteActivation implements ISiteActivationListener {
@Override
public void run() {
long startTime = System.currentTimeMillis();
// wait for system startup or at least 3 minutes
while (!EDEXUtil.isRunning()
|| (System.currentTimeMillis() > (startTime + 180000))) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
}
}
EDEXUtil.waitForRunning();
Map<String, Object> fetchATConfig = new HashMap<String, Object>();
fetchATConfig.put("siteId", configRef.getSiteID().get(0));

View file

@ -1,267 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.isc;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jep.JepException;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager;
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.edex.plugin.gfe.server.database.GridDatabase;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.GridHistoryUpdateNotification;
import com.raytheon.uf.common.message.WsId;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.core.EDEXUtil;
/**
* Class to for running the isc scripts
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 07/06/09 1995 bphillip Initial release
* 04/06/12 #457 dgilling Move call to delete records
* from queue into run().
* 04/23/13 #1949 rjpeter Move setting of lastSentTime to dao
* and removed initial delay.
* 06/13/13 2044 randerso Refactored to use IFPServer
* </pre>
*
* @author bphillip
* @version 1
*/
public class IscSendJob implements Runnable {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(IscSendJob.class);
/** Date format for formatting dates for use with iscExtract script */
private static final SimpleDateFormat ISC_EXTRACT_DATE = new SimpleDateFormat(
"yyyyMMdd_HHmm");
private final Map<String, IscSendScript> scripts;
private int runningTimeOutMillis;
private int threadSleepInterval;
/**
* Constructs a new IscSendJob
*
* @param siteID
* the site ID
*
* @param cmdQueue
*/
public IscSendJob() {
scripts = new HashMap<String, IscSendScript>();
runningTimeOutMillis = 300000;
threadSleepInterval = 30000;
}
@Override
public void run() {
while (!EDEXUtil.isRunning()) {
try {
Thread.sleep(threadSleepInterval);
} catch (Throwable t) {
// ignore
}
}
try {
// run forever
while (true) {
IscSendRecord record = SendIscTransactions
.getNextSendJob(runningTimeOutMillis);
if (record != null) {
runIscSend(record);
SendIscTransactions.removeSendJob(record);
} else {
try {
Thread.sleep(threadSleepInterval);
} catch (Exception e) {
// ignore
}
}
}
} finally {
// Make sure OS resources are released at thread death
for (IscSendScript script : scripts.values()) {
script.dispose();
}
}
}
private void runIscSend(IscSendRecord request) {
try {
ParmID id = request.getParmID();
TimeRange tr = request.getTimeRange();
String xmlDest = request.getXmlDest();
String siteId = id.getDbId().getSiteId();
if (!GFESiteActivation.getInstance().getActiveSites()
.contains(siteId)) {
statusHandler.warn("Attempted to send " + id
+ " for deactivated site " + siteId + ".");
return;
}
statusHandler.info("Starting isc for " + id.toString() + " "
+ tr.toString() + " " + xmlDest);
Map<String, Object> cmd = new HashMap<String, Object>();
cmd.put("parmNames", Arrays.asList(id.getParmName()));
cmd.put("databaseName", id.getDbId().getModelId());
cmd.put("startTime", ISC_EXTRACT_DATE.format(tr.getStart()));
cmd.put("endTime", ISC_EXTRACT_DATE.format(tr.getEnd()));
// destination server XML, might be empty
// the -D switch is a file location containing the xml
// information
if (!xmlDest.isEmpty()) {
cmd.put("destinations", xmlDest);
}
try {
IFPServerConfig config = IFPServerConfigManager
.getServerConfig(siteId);
// IRT table address
cmd.put("irtTableAddressA", config.iscRoutingTableAddress()
.get("ANCF"));
cmd.put("irtTableAddressB", config.iscRoutingTableAddress()
.get("BNCF"));
// xmt script
cmd.put("transmitScript", config.transmitScript());
// our server host, port, protocol, our mhs id, and our site id
cmd.put("ourServerHost", config.getServerHost());
cmd.put("ourServerPort", String.valueOf(config.getRpcPort()));
cmd.put("ourServerProtocol",
String.valueOf(config.getProtocolVersion()));
cmd.put("ourMHSid", config.getMhsid());
cmd.put("ourSiteID", config.getSiteID().get(0));
} catch (GfeConfigurationException e) {
statusHandler.error(
"Unable to retrieve site configuration for site "
+ siteId, e);
return;
}
try {
IscSendScript script = scripts.get(siteId);
if (script == null) {
script = IscSendScriptFactory
.constructIscSendScript(siteId);
scripts.put(siteId, script);
}
script.execute(cmd);
} catch (JepException e) {
statusHandler.error("Error executing iscExtract.", e);
return;
}
try {
DatabaseID dbId = id.getDbId();
IFPServer ifpServer = IFPServer.getActiveServer(dbId
.getSiteId());
if (ifpServer != null) {
GridDatabase gridDb = ifpServer.getGridParmMgr()
.getDatabase(dbId);
if (gridDb != null) {
ServerResponse<Map<TimeRange, List<GridDataHistory>>> sr = gridDb
.updateSentTime(id, tr, new Date());
if (sr.isOkay()) {
WsId wsId = new WsId(InetAddress.getLocalHost(),
"ISC", "ISC");
List<GridHistoryUpdateNotification> notifications = new ArrayList<GridHistoryUpdateNotification>(
1);
Map<TimeRange, List<GridDataHistory>> histories = sr
.getPayload();
notifications
.add(new GridHistoryUpdateNotification(id,
histories, wsId, siteId));
SendNotifications.send(notifications);
} else {
statusHandler
.error("Error updating last sent times in GFERecords: "
+ sr.getMessages());
}
} else {
// no such database exists
statusHandler
.error("Error processing ISC send request for :"
+ dbId
+ ", the database does not exist.");
}
} else {
// no active server for request
statusHandler
.error("Error processing ISC send request for :"
+ dbId + ", no active IFPServer for site.");
}
} catch (Exception e) {
statusHandler.error(
"Error updating last sent times in GFERecords.", e);
}
} catch (Throwable t) {
statusHandler.error("Exception in ISCSendJob: ", t);
}
}
public int getRunningTimeOutMillis() {
return runningTimeOutMillis;
}
public void setRunningTimeOutMillis(int runningTimeOutMillis) {
this.runningTimeOutMillis = runningTimeOutMillis;
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -19,7 +19,33 @@
**/
package com.raytheon.edex.plugin.gfe.isc;
import java.util.concurrent.Executor;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jep.JepException;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager;
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.edex.plugin.gfe.server.database.GridDatabase;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.GridHistoryUpdateNotification;
import com.raytheon.uf.common.message.WsId;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.core.EdexTimerBasedThread;
/**
* Service that runs ISC send jobs. Along with IscSendQueue, this class roughly
@ -31,28 +57,183 @@ import java.util.concurrent.Executor;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 20, 2011 dgilling Initial creation
*
* Oct 20, 2011 dgilling Initial creation
* May 19, 2014 2726 rjpeter Integrate IscSendJob for graceful shutdown.
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class SendIscSrv {
public class SendIscSrv extends EdexTimerBasedThread {
private final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SendIscSrv.class);
private final SendIscSrvConfig cfg;
protected int runningTimeOutMillis;
private final Executor executor;
/** Date format for formatting dates for use with iscExtract script */
protected static final SimpleDateFormat ISC_EXTRACT_DATE = new SimpleDateFormat(
"yyyyMMdd_HHmm");
public SendIscSrv(SendIscSrvConfig config) {
this.cfg = config;
this.executor = config.getExecutor();
for (int i = 0; i < cfg.getThreads(); i++) {
IscSendJob thread = new IscSendJob();
thread.setRunningTimeOutMillis(cfg.getRunningTimeOutMillis());
thread.setThreadSleepInterval(cfg.getThreadSleepInterval());
executor.execute(thread);
protected final ThreadLocal<Map<String, IscSendScript>> scripts = new ThreadLocal<Map<String, IscSendScript>>() {
@Override
protected Map<String, IscSendScript> initialValue() {
return new HashMap<String, IscSendScript>();
}
};
public SendIscSrv() {
}
public int getRunningTimeOutMillis() {
return runningTimeOutMillis;
}
public void setRunningTimeOutMillis(int runningTimeOutMillis) {
this.runningTimeOutMillis = runningTimeOutMillis;
}
@Override
public String getThreadGroupName() {
return "iscSendThreadPool";
}
@Override
public void process() throws Exception {
IscSendRecord record = null;
do {
record = SendIscTransactions.getNextSendJob(runningTimeOutMillis);
if (record != null) {
runIscSend(record);
SendIscTransactions.removeSendJob(record);
}
} while (record != null);
}
@Override
public void dispose() {
super.dispose();
// Make sure OS resources are released at thread death
for (IscSendScript script : scripts.get().values()) {
script.dispose();
}
}
private void runIscSend(IscSendRecord request) {
try {
ParmID id = request.getParmID();
TimeRange tr = request.getTimeRange();
String xmlDest = request.getXmlDest();
String siteId = id.getDbId().getSiteId();
if (!GFESiteActivation.getInstance().getActiveSites()
.contains(siteId)) {
statusHandler.warn("Attempted to send " + id
+ " for deactivated site " + siteId + ".");
return;
}
statusHandler.info("Starting isc for " + id.toString() + " "
+ tr.toString() + " " + xmlDest);
Map<String, Object> cmd = new HashMap<String, Object>();
cmd.put("parmNames", Arrays.asList(id.getParmName()));
cmd.put("databaseName", id.getDbId().getModelId());
cmd.put("startTime", ISC_EXTRACT_DATE.format(tr.getStart()));
cmd.put("endTime", ISC_EXTRACT_DATE.format(tr.getEnd()));
// destination server XML, might be empty
// the -D switch is a file location containing the xml
// information
if (!xmlDest.isEmpty()) {
cmd.put("destinations", xmlDest);
}
try {
IFPServerConfig config = IFPServerConfigManager
.getServerConfig(siteId);
// IRT table address
cmd.put("irtTableAddressA", config.iscRoutingTableAddress()
.get("ANCF"));
cmd.put("irtTableAddressB", config.iscRoutingTableAddress()
.get("BNCF"));
// xmt script
cmd.put("transmitScript", config.transmitScript());
// our server host, port, protocol, our mhs id, and our site id
cmd.put("ourServerHost", config.getServerHost());
cmd.put("ourServerPort", String.valueOf(config.getRpcPort()));
cmd.put("ourServerProtocol",
String.valueOf(config.getProtocolVersion()));
cmd.put("ourMHSid", config.getMhsid());
cmd.put("ourSiteID", config.getSiteID().get(0));
} catch (GfeConfigurationException e) {
statusHandler.error(
"Unable to retrieve site configuration for site "
+ siteId, e);
return;
}
try {
IscSendScript script = scripts.get().get(siteId);
if (script == null) {
script = IscSendScriptFactory
.constructIscSendScript(siteId);
scripts.get().put(siteId, script);
}
script.execute(cmd);
} catch (JepException e) {
statusHandler.error("Error executing iscExtract.", e);
return;
}
try {
DatabaseID dbId = id.getDbId();
IFPServer ifpServer = IFPServer.getActiveServer(dbId
.getSiteId());
if (ifpServer != null) {
GridDatabase gridDb = ifpServer.getGridParmMgr()
.getDatabase(dbId);
if (gridDb != null) {
ServerResponse<Map<TimeRange, List<GridDataHistory>>> sr = gridDb
.updateSentTime(id, tr, new Date());
if (sr.isOkay()) {
WsId wsId = new WsId(null, "ISC", "ISC");
List<GridHistoryUpdateNotification> notifications = new ArrayList<GridHistoryUpdateNotification>(
1);
Map<TimeRange, List<GridDataHistory>> histories = sr
.getPayload();
notifications
.add(new GridHistoryUpdateNotification(id,
histories, wsId, siteId));
SendNotifications.send(notifications);
} else {
statusHandler
.error("Error updating last sent times in GFERecords: "
+ sr.getMessages());
}
} else {
// no such database exists
statusHandler
.error("Error processing ISC send request for :"
+ dbId
+ ", the database does not exist.");
}
} else {
// no active server for request
statusHandler
.error("Error processing ISC send request for :"
+ dbId + ", no active IFPServer for site.");
}
} catch (Exception e) {
statusHandler.error(
"Error updating last sent times in GFERecords.", e);
}
} catch (Throwable t) {
statusHandler.error("Exception in SendIscSrv: ", t);
}
}
}

View file

@ -1,82 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.isc;
import java.util.concurrent.Executor;
/**
* Send ISC service configuration.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 20, 2011 dgilling Initial creation
* Apr 30, 2013 1949 rjpeter Removed initial delay.
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class SendIscSrvConfig {
protected int threads;
protected Executor executor;
protected int runningTimeOutMillis;
protected int threadSleepInterval;
public int getThreads() {
return threads;
}
public void setThreads(int threads) {
this.threads = threads;
}
public Executor getExecutor() {
return executor;
}
public void setExecutor(Executor executor) {
this.executor = executor;
}
public int getRunningTimeOutMillis() {
return runningTimeOutMillis;
}
public void setRunningTimeOutMillis(int runningTimeOutMillis) {
this.runningTimeOutMillis = runningTimeOutMillis;
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -25,13 +25,9 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import jep.JepException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.plugin.gfe.server.IFPServer;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
import com.raytheon.uf.common.localization.IPathManager;
@ -39,10 +35,10 @@ import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.props.EnvProperties;
import com.raytheon.uf.edex.core.props.PropertiesFactory;
import com.raytheon.uf.edex.core.EdexTimerBasedThread;
/**
* Service that runs smart inits
@ -58,168 +54,154 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory;
* Aug 24, 2013 #1949 rjpeter Updated start up logic
* Jun 13, 2013 #2044 randerso Refactored to use IFPServer,
* added support to run init for all valid times
* Mar 14, 2014 2726 rjpeter Implement graceful shutdown.
* </pre>
*
* @author njensen
* @version 1.0
*/
public class SmartInitSrv {
public class SmartInitSrv extends EdexTimerBasedThread {
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SmartInitSrv.class);
private final Map<Long, SmartInitScript> cachedInterpreters = new HashMap<Long, SmartInitScript>();
private static boolean enabled = true;
protected int pendingInitMinTimeMillis = 120000;
protected final SmartInitSrvConfig cfg;
protected int runningInitTimeOutMillis = 600000;
protected final Executor executor;
static {
EnvProperties env = PropertiesFactory.getInstance().getEnvProperties();
enabled = Boolean.parseBoolean(env.getEnvValue("GFESMARTINIT"));
public SmartInitSrv() {
}
public SmartInitSrv(SmartInitSrvConfig config) {
cfg = config;
this.executor = config.getExecutor();
for (int i = 0; i < cfg.getThreads(); i++) {
SmartInitThread thread = new SmartInitThread();
thread.pendingInitMinTimeMillis = cfg.getPendingInitMinTimeMillis();
thread.runningInitTimeOutMillis = cfg.getRunningInitTimeOutMillis();
thread.threadSleepInterval = cfg.getThreadSleepInterval();
executor.execute(thread);
}
@Override
public String getThreadGroupName() {
return "smartInitThreadPool";
}
protected class SmartInitThread implements Runnable {
// default of 2 minutes
private int pendingInitMinTimeMillis = 120000;
private int runningInitTimeOutMillis = 600000;
private int threadSleepInterval = 30000;
private final transient Log logger = LogFactory.getLog(getClass());
@Override
public void run() {
try {
// Wait for server to come fully up due to route dependencies
while (!EDEXUtil.isRunning()) {
try {
Thread.sleep(threadSleepInterval);
} catch (InterruptedException e) {
// ignore
}
}
// run forever
while (true) {
SmartInitRecord record = SmartInitTransactions
.getSmartInitToRun(pendingInitMinTimeMillis,
runningInitTimeOutMillis);
if (record != null) {
runSmartInit(record);
} else {
try {
Thread.sleep(threadSleepInterval);
} catch (Exception e) {
// ignore
}
}
}
} finally {
// Make sure OS resources are released at thread death
SmartInitScript script = cachedInterpreters.remove(Thread
.currentThread().getId());
script.dispose();
@Override
public void process() throws Exception {
SmartInitRecord record = null;
do {
record = SmartInitTransactions.getSmartInitToRun(
pendingInitMinTimeMillis, runningInitTimeOutMillis);
if (record != null) {
runSmartInit(record);
}
}
} while (record != null);
}
public void runSmartInit(SmartInitRecord record) {
if (enabled) {
@Override
public void dispose() {
super.dispose();
// Make sure OS resources are released at thread death
SmartInitScript script = cachedInterpreters.remove(Thread
.currentThread().getId());
if (script != null) {
script.dispose();
}
}
public void runSmartInit(SmartInitRecord record) {
try {
SmartInitScript initScript = null;
List<String> sitePathsAdded = new ArrayList<String>(2);
String init = record.getSmartInit();
String dbName = record.getDbName()
+ (record.isManual() ? ":1" : ":0");
Date validTime = record.getId().getValidTime();
if (SmartInitRecord.ALL_TIMES.equals(validTime)) {
validTime = null;
}
DatabaseID db = new DatabaseID(record.getDbName());
if (IFPServer.getActiveSites().contains(db.getSiteId())) {
try {
SmartInitScript initScript = null;
List<String> sitePathsAdded = new ArrayList<String>(2);
long id = Thread.currentThread().getId();
initScript = cachedInterpreters.get(id);
String init = record.getSmartInit();
String dbName = record.getDbName()
+ (record.isManual() ? ":1" : ":0");
Date validTime = record.getId().getValidTime();
if (SmartInitRecord.ALL_TIMES.equals(validTime)) {
validTime = null;
if (initScript == null) {
initScript = SmartInitFactory.constructInit();
cachedInterpreters.put(id, initScript);
}
DatabaseID db = new DatabaseID(record.getDbName());
if (IFPServer.getActiveSites().contains(db.getSiteId())) {
try {
long id = Thread.currentThread().getId();
initScript = cachedInterpreters.get(id);
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathMgr.getContextForSite(
LocalizationType.EDEX_STATIC, db.getSiteId());
LocalizationContext baseCtx = pathMgr.getContext(
LocalizationType.EDEX_STATIC,
LocalizationLevel.BASE);
if (initScript == null) {
initScript = SmartInitFactory.constructInit();
cachedInterpreters.put(id, initScript);
}
IPathManager pathMgr = PathManagerFactory
.getPathManager();
LocalizationContext ctx = pathMgr
.getContextForSite(
LocalizationType.EDEX_STATIC,
db.getSiteId());
LocalizationContext baseCtx = pathMgr.getContext(
LocalizationType.EDEX_STATIC,
LocalizationLevel.BASE);
File file = pathMgr.getFile(ctx, "smartinit");
if ((file != null) && file.exists()) {
initScript.addSitePath(file.getPath(), pathMgr
.getFile(baseCtx, "smartinit")
.getPath());
sitePathsAdded.add(file.getPath());
}
file = pathMgr.getFile(ctx,
FileUtil.join("config", "gfe"));
if ((file != null) && file.exists()) {
initScript.addSitePath(
file.getPath(),
pathMgr.getFile(baseCtx,
FileUtil.join("config", "gfe"))
File file = pathMgr.getFile(ctx, "smartinit");
if ((file != null) && file.exists()) {
initScript
.addSitePath(file.getPath(),
pathMgr.getFile(baseCtx, "smartinit")
.getPath());
sitePathsAdded.add(file.getPath());
}
HashMap<String, Object> argMap = new HashMap<String, Object>();
argMap.put("dbName", dbName);
argMap.put("model", init);
argMap.put("validTime", validTime);
initScript.execute(argMap);
} catch (Throwable e) {
logger.error("Error running smart init for "
+ record.getId(), e);
} finally {
try {
for (String path : sitePathsAdded) {
initScript.removeSitePath(path);
}
} catch (JepException e) {
this.logger
.error("Error cleaning up smart init interpreter's sys.path",
e);
}
}
} else {
this.logger.warn("Site " + db.getSiteId()
+ " has been disabled. Smart init for "
+ record.getDbName()
+ " will not be processed.");
sitePathsAdded.add(file.getPath());
}
file = pathMgr.getFile(ctx, FileUtil.join("config", "gfe"));
if ((file != null) && file.exists()) {
initScript.addSitePath(
file.getPath(),
pathMgr.getFile(baseCtx,
FileUtil.join("config", "gfe"))
.getPath());
sitePathsAdded.add(file.getPath());
}
HashMap<String, Object> argMap = new HashMap<String, Object>();
argMap.put("dbName", dbName);
argMap.put("model", init);
argMap.put("validTime", validTime);
initScript.execute(argMap);
} catch (Throwable e) {
statusHandler.error("Error running smart init for "
+ record.getId(), e);
} finally {
try {
for (String path : sitePathsAdded) {
initScript.removeSitePath(path);
}
} catch (JepException e) {
statusHandler
.error("Error cleaning up smart init interpreter's sys.path",
e);
}
} catch (Throwable t) {
this.logger.error("Error in SmartInitSrv", t);
}
SmartInitTransactions.removeSmartInit(record);
} else {
statusHandler.warn("Site " + db.getSiteId()
+ " has been disabled. Smart init for "
+ record.getDbName() + " will not be processed.");
}
} catch (Throwable t) {
statusHandler.error("Error in SmartInitSrv", t);
}
SmartInitTransactions.removeSmartInit(record);
}
@Override
public void postStop() {
SmartInitQueue.getQueue().fireSmartInit();
super.postStop();
}
public int getPendingInitMinTimeMillis() {
return pendingInitMinTimeMillis;
}
public void setPendingInitMinTimeMillis(int pendingInitMinTimeMillis) {
this.pendingInitMinTimeMillis = pendingInitMinTimeMillis;
}
public int getRunningInitTimeOutMillis() {
return runningInitTimeOutMillis;
}
public void setRunningInitTimeOutMillis(int runningInitTimeOutMillis) {
this.runningInitTimeOutMillis = runningInitTimeOutMillis;
}
}

View file

@ -1,91 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.smartinit;
import java.util.concurrent.Executor;
/**
* Smart Init Server config.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 24, 2010 #7277 rjpeter Initial creation
* Apr 23, 2013 #1949 rjpeter Removed initial delay
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class SmartInitSrvConfig {
protected int threads;
protected Executor executor;
protected int pendingInitMinTimeMillis;
protected int runningInitTimeOutMillis;
protected int threadSleepInterval;
public int getThreads() {
return threads;
}
public void setThreads(int threads) {
this.threads = threads;
}
public Executor getExecutor() {
return executor;
}
public void setExecutor(Executor executor) {
this.executor = executor;
}
public int getPendingInitMinTimeMillis() {
return pendingInitMinTimeMillis;
}
public void setPendingInitMinTimeMillis(int pendingInitMinTimeMillis) {
this.pendingInitMinTimeMillis = pendingInitMinTimeMillis;
}
public int getRunningInitTimeOutMillis() {
return runningInitTimeOutMillis;
}
public void setRunningInitTimeOutMillis(int runningInitTimeOutMillis) {
this.runningInitTimeOutMillis = runningInitTimeOutMillis;
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -15,16 +15,9 @@
<constructor-arg value="jms-durable:queue:Ingest.goessounding"/>
</bean>
<bean id="goessoundingCamelRegistered" factory-bean="contextManager"
factory-method="register"
depends-on="persistCamelRegistered">
<constructor-arg ref="goessounding-camel"/>
</bean>
<camelContext id="goessounding-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="goessndgFileEndpoint"
uri="file:${edex.home}/data/sbn/goessndg?noop=true&amp;idempotent=false" />

View file

@ -14,11 +14,6 @@
<bean id="useLatestAggregationStrategy" class="org.apache.camel.processor.aggregate.UseLatestAggregationStrategy" />
<bean id="gribDecodeCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="grib-decode"/>
</bean>
<bean id="gribPostProcessor"
class="com.raytheon.edex.plugin.grib.decoderpostprocessors.GribPostProcessor"
factory-method="getInstance" />
@ -35,8 +30,7 @@
factory-method="getInstance" depends-on="gridcoveragelookup"/>
<camelContext id="grib-decode" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<endpoint id="gribSplitJmsEndpoint" uri="jms-durable:queue:Ingest.GribSplit?concurrentConsumers=${grib-split.count.threads}"/>
<endpoint id="gribDecodeJmsEndpoint" uri="jms-durable:queue:Ingest.GribDecode?concurrentConsumers=${grib-decode.count.threads}"/>
@ -50,9 +44,7 @@
<constant>grid</constant>
</setHeader>
<bean ref="stringToFile" />
<!-- strategyRef is needed because of camel bug https://issues.apache.org/activemq/browse/CAMEL-3333,
without the strategy it uses the original message in the multicast and it loses the largeFileLock header -->
<split strategyRef="useLatestAggregationStrategy" streaming="true">
<split streaming="true">
<method bean="gribSplitter" method="split" />
<to uri="jms-durable:queue:Ingest.GribDecode" />
</split>
@ -63,14 +55,15 @@
</doCatch>
</doTry>
</route>
<route id="gribDecodeIngestRoute">
<from ref="gribDecodeJmsEndpoint" />
<doTry>
<pipeline>
<bean ref="gribGridPointLock" method="reserve"/>
<bean ref="gribDecoder" />
<!-- send for processing -->
<!-- send for processing -->
<bean ref="gribPostProcessor" method="process" />
<to uri="direct-vm:persistIndexAlert" />
</pipeline>

View file

@ -1,4 +1,4 @@
<?xml version="2.0" encoding="UTF-8" standalone="yes"?>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.

View file

@ -17,16 +17,10 @@
</bean>
<bean id="ldadhydroPointData" class="com.raytheon.edex.plugin.ldadhydro.dao.LdadhydroPointDataTransform"/>
<bean id="ldadhydroCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ldadhydro-camel"/>
</bean>
<camelContext id="ldadhydro-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<route id="ldadhydroIngestRoute">
<from uri="jms-durable:queue:Ingest.ldadhydro"/>
<doTry>

View file

@ -15,15 +15,9 @@
<constructor-arg value="jms-durable:queue:Ingest.ldadmanual"/>
</bean>
<bean id="ldadmanualCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ldadmanual-camel"/>
</bean>
<camelContext id="ldadmanual-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<route id="ldadmanualIngestRoute">
<from uri="jms-durable:queue:Ingest.ldadmanual"/>

View file

@ -19,15 +19,9 @@
<constructor-arg value="jms-durable:queue:Ingest.ldadprofiler"/>
</bean>
<bean id="ldadprofilerCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ldadprofiler-camel"/>
</bean>
<camelContext id="ldadprofiler-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="ldadprofilerFileEndpoint" uri="file:${edex.home}/data/sbn/ldadprofiler?noop=true" />

View file

@ -3,16 +3,8 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="obsCamelRegistered" factory-bean="contextManager" factory-method="register"
depends-on="persistCamelRegistered,
shefCamelRegistered,
metarToHMDBCamelRegistered">
<constructor-arg ref="obs-camel" />
</bean>
<camelContext id="obs-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<!-- Begin METAR routes -->
<route id="metarIngestRoute">

View file

@ -5,15 +5,8 @@
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<!-- This spring configuration is currently only used by the ingestHydro EDEX instance. -->
<bean id="obsCamelRegistered" factory-bean="contextManager" factory-method="register"
depends-on="shefCamelRegistered,
metarToHMDBCamelRegistered">
<constructor-arg ref="obs-camel" />
</bean>
<camelContext id="obs-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<!-- Begin METAR routes -->
<route id="metarIngestRoute">

View file

@ -1,8 +1,7 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="obsDecoder" class="com.raytheon.edex.plugin.obs.ObsDecoder" />

View file

@ -12,15 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.poessounding"/>
</bean>
<bean id="poessoundingCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="poessounding-camel"/>
</bean>
<camelContext id="poessounding-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="poessndgFileEndpoint" uri="file:${edex.home}/data/sbn/poessndg?noop=true&amp;idempotent=false"/>

View file

@ -12,15 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.profiler"/>
</bean>
<bean id="profilerCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="profiler-camel"/>
</bean>
<camelContext id="profiler-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="profilerFileEndpoint" uri="file:${edex.home}/data/sbn/profiler?noop=true&amp;idempotent=false"/>

View file

@ -18,15 +18,9 @@
<constructor-arg value="jms-durable:queue:Ingest.RadarRadarServer" />
</bean>
<bean id="radarCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="radar-camel"/>
</bean>
<camelContext id="radar-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="radarFileEndpoint" uri="file:${edex.home}/data/sbn/radar?noop=true&amp;idempotent=false" />

View file

@ -15,15 +15,9 @@
<constructor-arg value="jms-durable:queue:Ingest.recco" />
</bean>
<bean id="reccoCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="recco-camel"/>
</bean>
<camelContext id="recco-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="reccoFileEndpoint" uri="file:${edex.home}/data/sbn/recco?noop=true&amp;idempotent=false" />

View file

@ -45,22 +45,13 @@
<constructor-arg ref="spcMenuListener" />
</bean>
<!--
<bean id="redbookCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="clusteredRedbook-camel"/>
</bean>
-->
<bean id="redbookCamelRegistered" factory-bean="clusteredCamelContextMgr"
factory-method="register">
<constructor-arg ref="clusteredRedbook-camel" />
</bean>
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredRedbook-camel" />
</bean>
<camelContext id="clusteredRedbook-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="redbookFileEndpoint" uri="file:${edex.home}/data/sbn/redbook?noop=true&amp;idempotent=false" />

View file

@ -7,7 +7,7 @@
<property name="dao" ref="satelliteDao" />
</bean>
<bean id="satelliteDao" class="com.raytheon.edex.plugin.satellite.dao.SatelliteDao">
<bean id="satelliteDao" class="com.raytheon.edex.plugin.satellite.dao.SatelliteDao" depends-on="satelliteProperties">
<constructor-arg ref="satellitePluginName" />
</bean>
@ -17,15 +17,9 @@
<constructor-arg value="jms-durable:queue:Ingest.Satellite" />
</bean>
<bean id="satCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="sat-camel"/>
</bean>
<camelContext id="sat-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="satFileEndpoint" uri="file:${edex.home}/data/sbn/sat?noop=true&amp;idempotent=false" />

View file

@ -16,12 +16,6 @@
<constructor-arg value="jms-durable:queue:Ingest.sfcobs" />
</bean>
<bean id="sfcobsCamelRegistered" factory-bean="contextManager" factory-method="register"
depends-on="persistCamelRegistered,
shefCamelRegistered">
<constructor-arg ref="sfcobs-camel" />
</bean>
<bean id="buoyListener" class="com.raytheon.edex.plugin.sfcobs.ingest.BuoySubscriber" />
<bean id="marineInfoListener" class="com.raytheon.edex.plugin.sfcobs.ingest.MarineInfoSubscriber">
@ -52,7 +46,7 @@
</bean>
<camelContext id="sfcobs-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<!-- Begin sfcobs routes -->
<route id="sfcobsIngestRoute">

View file

@ -44,22 +44,17 @@
<constructor-arg value="jms-durable:queue:Ingest.Shef"/>
</bean>
<bean id="shefCamelRegistered" factory-bean="contextManager"
factory-method="register">
<constructor-arg ref="shef-camel" />
</bean>
<!-- Start add for manual input -->
<bean id="shefFileChangedStrategy"
class="com.raytheon.uf.edex.esb.camel.FileChangedExclusiveReadLockStrategy" />
<bean factory-bean="clusteredCamelContextMgr" factory-method="register">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredShefManualProc" />
</bean>
<camelContext id="clusteredShefManualProc" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<endpoint id="shefManualFileEndpoint"
uri="file:${edex.home}/data/share/hydroapps/shefdecode/input?delete=true&amp;maxMessagesPerPoll=1000&amp;delay=15000&amp;exclusiveReadLockStrategy=#shefFileChangedStrategy" />
@ -75,7 +70,7 @@
<!-- End add for manual input -->
<camelContext id="shef-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<!-- Begin shef routes -->
<route id="shefIngestRoute">

View file

@ -18,15 +18,9 @@
<constructor-arg value="jms-durable:queue:Ingest.taf"/>
</bean>
<bean id="tafCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="taf-camel"/>
</bean>
<camelContext id="taf-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="tafFileEndpoint" uri="file:${edex.home}/data/sbn/taf?noop=true&amp;idempotent=false" />

View file

@ -207,8 +207,7 @@
<camelContext id="clustered-text-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!-- TextPurge route -->
<route id="textPurgeRequestRoute">
<from uri="jms-generic:queue:textPurgeRequest" />
@ -232,8 +231,7 @@
</route>
</camelContext>
<bean factory-bean="clusteredCamelContextMgr"
factory-method="register">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clustered-text-camel" />
</bean>
</beans>

View file

@ -12,15 +12,9 @@
<constructor-arg value="jms-durable:queue:Ingest.textlightning"/>
</bean>
<bean id="textlightningCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="textlightning-camel"/>
</bean>
<camelContext id="textlightning-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="textlightningFileEndpoint"
uri="file:${edex.home}/data/sbn/textlightning?noop=true&amp;idempotent=false" />

View file

@ -17,15 +17,9 @@
<constructor-arg value="jms-durable:queue:Ingest.Warning"/>
</bean>
<bean id="warningCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="warning-camel"/>
</bean>
<camelContext id="warning-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<!--
<endpoint id="warningEndpoint"
uri="file:${edex.home}/data/sbn/warning?noop=true&amp;idempotent=false" />

View file

@ -1,36 +1,38 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="geospatialDataGenerator" class="com.raytheon.edex.plugin.warning.gis.GeospatialDataGenerator">
<constructor-arg value="geospatialUpdateNotify"/>
</bean>
<bean id="generateGeospatialDataRequestHandler" class="com.raytheon.edex.plugin.warning.gis.GenerateGeospatialDataRequestHandler">
<constructor-arg ref="geospatialDataGenerator"/>
</bean>
<bean id="generateGeospatialDataRequestHandler" class="com.raytheon.edex.plugin.warning.gis.GenerateGeospatialDataRequestHandler" />
<bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataplugin.warning.gis.GenerateGeospatialDataRequest"/>
<constructor-arg ref="generateGeospatialDataRequestHandler"/>
</bean>
<!-- Instantiating class causes a thread to be run that will generate the warngen geometries -->
<bean class="com.raytheon.edex.plugin.warning.gis.GeospatialDataGeneratorThread" depends-on="spatialQueryRegistered" />
<!--Instantiating class will update the warngen geometries-->
<bean id="geospatialDataUpdater" class="com.raytheon.edex.plugin.warning.gis.GeospatialDataUpdater" />
<camelContext id="geospatialDataUpdater-context"
xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<camelContext id="geospatialDataGenerator-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<endpoint id="geospatialDataUpdaterCron"
uri="clusteredquartz://warning/geospatialDataUpdaterScheduled/?cron=${geospatial.updater.cron}" />
uri="clusteredquartz://warning/checkGeospatialData/?cron=${geospatial.updater.cron}" />
<route id="geospatialDataUpdaterScheduled">
<from uri="geospatialDataUpdaterCron" />
<to uri="jms-generic:queue:geospatialDataUpdaterScheduledWork" />
<!-- Generate once on context start -->
<route id="geospatialDataGeneratorRoute">
<from uri="timer://generateWarngenGeometries?repeatCount=1"/>
<bean ref="geospatialDataGenerator" method="generateUniqueGeospatialMetadataGeometries"/>
</route>
<route id="geospatialDataUpdaterScheduledWork">
<from uri="jms-generic:queue:geospatialDataUpdaterScheduledWork" />
<!-- check generate periodically -->
<route id="geospatialDataUpdaterRoute">
<from ref="geospatialDataUpdaterCron"/>
<doTry>
<bean ref="geospatialDataUpdater" method="runCheckUpdate" />
<bean ref="geospatialDataGenerator" method="generateUniqueGeospatialMetadataGeometries"/>
<doCatch>
<exception>java.lang.Throwable</exception>
<to
@ -38,6 +40,12 @@
</doCatch>
</doTry>
</route>
</camelContext>
</beans>
<!-- Route to send geospatial data update notification -->
<route id="geospatialUpdateNotify">
<from uri="vm:edex.geospatialUpdateNotification" />
<bean ref="serializationUtil" method="transformToThrift" />
<to uri="jms-generic:topic:edex.geospatialUpdate.msg" />
</route>
</camelContext>
</beans>

View file

@ -23,7 +23,7 @@ import com.raytheon.uf.common.dataplugin.warning.gis.GenerateGeospatialDataReque
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
/**
* TODO Add Description
* Generates geospatial data on demand.
*
* <pre>
*
@ -31,8 +31,8 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 22, 2011 rjpeter Initial creation
*
* Jul 22, 2011 rjpeter Initial creation.
* May 19, 2014 2726 rjpeter Updated call to GeospatialDataGenerator.
* </pre>
*
* @author rjpeter
@ -41,6 +41,13 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
public class GenerateGeospatialDataRequestHandler implements
IRequestHandler<GenerateGeospatialDataRequest> {
final GeospatialDataGenerator dataGenerator;
public GenerateGeospatialDataRequestHandler(
GeospatialDataGenerator dataGenerator) {
this.dataGenerator = dataGenerator;
}
/*
* (non-Javadoc)
*
@ -51,8 +58,8 @@ public class GenerateGeospatialDataRequestHandler implements
@Override
public Object handleRequest(GenerateGeospatialDataRequest request)
throws Exception {
return GeospatialDataGenerator.generateGeoSpatialList(
request.getSite(), request.getMetaData());
return dataGenerator.generateGeoSpatialList(request.getSite(),
request.getMetaData());
}
}

View file

@ -20,13 +20,16 @@
package com.raytheon.edex.plugin.warning.gis;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.xml.bind.JAXBException;
@ -62,6 +65,8 @@ import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
@ -97,6 +102,7 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
* May 7, 2013 15690 Qinglu Lin Added convertToMultiPolygon() and updated queryGeospatialData().
* Oct 22, 2013 2361 njensen Use JAXBManager for XML
* Feb 07, 2014 16090 mgamazaychikov Changed visibility of some methods
* Mar 19, 2014 2726 rjpeter Made singleton instance.
* </pre>
*
* @author rjpeter
@ -104,14 +110,19 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
*/
public class GeospatialDataGenerator {
private static final transient IUFStatusHandler statusHandler = UFStatus
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(GeospatialDataGenerator.class);
private static final SingleTypeJAXBManager<GeospatialTimeSet> jaxb = SingleTypeJAXBManager
private final SingleTypeJAXBManager<GeospatialTimeSet> jaxb = SingleTypeJAXBManager
.createWithoutException(GeospatialTimeSet.class);
public static void generateUniqueGeospatialMetadataGeometries() {
private final String updaterEndpoint;
public GeospatialDataGenerator(String updaterEndpoint) {
this.updaterEndpoint = updaterEndpoint;
}
public void generateUniqueGeospatialMetadataGeometries() {
String mySite = SiteUtil.getSite();
DialogConfiguration dialogConfig = null;
@ -129,7 +140,7 @@ public class GeospatialDataGenerator {
for (String site : sites) {
statusHandler.handle(Priority.INFO,
"Generating warngen geometries for site: " + site);
"Checking warngen geometries for site: " + site);
for (GeospatialMetadata md : metaDataSet) {
try {
generateGeoSpatialList(site, md);
@ -143,7 +154,7 @@ public class GeospatialDataGenerator {
}
}
public static Set<GeospatialMetadata> getMetaDataSet(List<String> sites,
public Set<GeospatialMetadata> getMetaDataSet(List<String> sites,
List<String> templates) {
Set<GeospatialMetadata> metaDataSet = new HashSet<GeospatialMetadata>();
@ -178,7 +189,8 @@ public class GeospatialDataGenerator {
}
return metaDataSet;
}
static List<String> getBackupSites(DialogConfiguration dialogConfig) {
public static List<String> getBackupSites(DialogConfiguration dialogConfig) {
String[] CWAs = dialogConfig.getBackupCWAs().split(",");
List<String> rval = new ArrayList<String>(CWAs.length + 1);
for (String s : CWAs) {
@ -189,7 +201,7 @@ public class GeospatialDataGenerator {
return rval;
}
static List<String> getTemplates(DialogConfiguration dialogConfig) {
public static List<String> getTemplates(DialogConfiguration dialogConfig) {
String[] mainProducts = dialogConfig.getMainWarngenProducts()
.split(",");
String[] otherProducts = dialogConfig.getOtherWarngenProducts().split(
@ -209,7 +221,7 @@ public class GeospatialDataGenerator {
return rval;
}
public static GeospatialDataSet generateGeoSpatialList(String site,
public GeospatialDataSet generateGeoSpatialList(String site,
GeospatialMetadata metaData) throws SpatialException {
GeospatialDataSet dataSet = null;
String file = generateGeoDataFilename(metaData);
@ -307,6 +319,19 @@ public class GeospatialDataGenerator {
// save to disk
try {
persistGeoData(site, lastRunTimeMap, curTime, dataSet);
if (updaterEndpoint != null) {
String updatedTimeStamp = getTimeStamp(curTime,
lastRunTime);
try {
EDEXUtil.getMessageProducer().sendAsync(
updaterEndpoint, updatedTimeStamp);
} catch (EdexException e) {
statusHandler.error("Could not send message to "
+ updaterEndpoint, e);
}
}
} catch (Exception e) {
statusHandler.handle(Priority.WARN,
"Error occurred persisting area geometry data", e);
@ -320,7 +345,7 @@ public class GeospatialDataGenerator {
return dataSet;
}
public static GeospatialMetadata getMetaData(WarngenConfiguration template) {
public GeospatialMetadata getMetaData(WarngenConfiguration template) {
GeospatialMetadata rval = new GeospatialMetadata();
GeospatialConfiguration geoConfig = template.getGeospatialConfig();
AreaSourceConfiguration areaConfig = template.getHatchedAreaSource();
@ -346,7 +371,7 @@ public class GeospatialDataGenerator {
return rval;
}
static GeospatialTime queryForCurrentTimes(
public static GeospatialTime queryForCurrentTimes(
GeospatialMetadata metaData) throws Exception {
GeospatialTime rval = new GeospatialTime();
String areaSource = metaData.getAreaSource().toLowerCase();
@ -355,12 +380,12 @@ public class GeospatialDataGenerator {
StringBuilder sql = new StringBuilder(200);
sql.append("SELECT table_name, import_time FROM mapdata.map_version WHERE table_name in ('");
sql.append(areaSource.toLowerCase());
if (tzSource != null && tzSource.length() > 0) {
if ((tzSource != null) && (tzSource.length() > 0)) {
tzSource = tzSource.toLowerCase();
sql.append("', '");
sql.append(tzSource);
}
if (pAreaSource != null && pAreaSource.length() > 0) {
if ((pAreaSource != null) && (pAreaSource.length() > 0)) {
pAreaSource = pAreaSource.toLowerCase();
sql.append("', '");
sql.append(pAreaSource);
@ -390,7 +415,7 @@ public class GeospatialDataGenerator {
return rval;
}
private static GeospatialData[] queryGeospatialData(String site,
private GeospatialData[] queryGeospatialData(String site,
GeospatialMetadata metaData) throws SpatialException {
String areaSource = metaData.getAreaSource();
@ -423,22 +448,24 @@ public class GeospatialDataGenerator {
Geometry clippedGeom = null;
for (int i = 0; i < features.length; i++) {
multiPolygon = null;
for (int j = 0; j < cwaFeatures.length; j++) {
for (SpatialQueryResult cwaFeature : cwaFeatures) {
clippedGeom = features[i].geometry
.intersection(cwaFeatures[j].geometry);
.intersection(cwaFeature.geometry);
if (clippedGeom instanceof GeometryCollection) {
GeometryCollection gc = (GeometryCollection) clippedGeom;
if (multiPolygon != null)
if (multiPolygon != null) {
multiPolygon = multiPolygon
.union(convertToMultiPolygon(gc));
else
} else {
multiPolygon = convertToMultiPolygon(gc);
}
}
}
if (multiPolygon != null)
if (multiPolygon != null) {
features[i].geometry = multiPolygon;
else if (clippedGeom != null)
} else if (clippedGeom != null) {
features[i].geometry = clippedGeom;
}
}
}
@ -463,7 +490,7 @@ public class GeospatialDataGenerator {
*
* @param gc
*/
private static MultiPolygon convertToMultiPolygon(GeometryCollection gc) {
private MultiPolygon convertToMultiPolygon(GeometryCollection gc) {
GeometryCollectionIterator iter = new GeometryCollectionIterator(gc);
Set<Polygon> polygons = new HashSet<Polygon>();
MultiPolygon mp = null;
@ -471,52 +498,59 @@ public class GeospatialDataGenerator {
while (iter.hasNext()) {
Object o = iter.next();
if (o instanceof MultiPolygon) {
if (mp == null)
if (mp == null) {
mp = (MultiPolygon) o;
else
} else {
mp = (MultiPolygon) mp.union((MultiPolygon) o);
}
} else if (o instanceof Polygon) {
polygons.add((Polygon) o);
} else if (o instanceof LineString || o instanceof Point) {
} else if ((o instanceof LineString) || (o instanceof Point)) {
LinearRing lr = null;
Coordinate[] coords = null;
if (o instanceof LineString) {
Coordinate[] cs = ((LineString) o).getCoordinates();
if (cs.length < 4) {
coords = new Coordinate[4];
for (int j = 0; j < cs.length; j++)
for (int j = 0; j < cs.length; j++) {
coords[j] = new Coordinate(cs[j]);
for (int j = cs.length; j < 4; j++)
}
for (int j = cs.length; j < 4; j++) {
coords[j] = new Coordinate(cs[3 - j]);
}
} else {
coords = new Coordinate[cs.length + 1];
for (int j = 0; j < cs.length; j++)
for (int j = 0; j < cs.length; j++) {
coords[j] = new Coordinate(cs[j]);
}
coords[cs.length] = new Coordinate(cs[0]);
}
} else {
coords = new Coordinate[4];
for (int i = 0; i < 4; i++)
for (int i = 0; i < 4; i++) {
coords[i] = ((Point) o).getCoordinate();
}
}
lr = (((Geometry) o).getFactory()).createLinearRing(coords);
Polygon poly = (new GeometryFactory()).createPolygon(lr, null);
polygons.add((Polygon) poly);
polygons.add(poly);
} else {
statusHandler.handle(Priority.WARN,
"Unprocessed Geometry object: "
+ o.getClass().getName());
}
}
if (mp == null && polygons.size() == 0)
if ((mp == null) && (polygons.size() == 0)) {
return null;
}
if (polygons.size() > 0) {
Polygon[] p = polygons.toArray(new Polygon[0]);
if (mp != null)
if (mp != null) {
mp = (MultiPolygon) mp.union(new MultiPolygon(p, gc
.getFactory()));
else
} else {
mp = new MultiPolygon(p, gc.getFactory());
}
}
return mp;
}
@ -527,8 +561,7 @@ public class GeospatialDataGenerator {
*
* @param results
*/
private static void topologySimplifyQueryResults(
SpatialQueryResult[] results) {
private void topologySimplifyQueryResults(SpatialQueryResult[] results) {
GeometryFactory gf = new GeometryFactory();
Geometry[] geoms = new Geometry[results.length];
for (int i = 0; i < results.length; i++) {
@ -571,7 +604,7 @@ public class GeospatialDataGenerator {
* @param hull
* @param geoData
*/
private static GeospatialData[] queryTimeZones(GeospatialMetadata metaData,
private GeospatialData[] queryTimeZones(GeospatialMetadata metaData,
Geometry hull, GeospatialData[] geoData) throws SpatialException {
GeospatialData[] rval = null;
String timezonePathcastTable = metaData.getTimeZoneSource();
@ -627,8 +660,8 @@ public class GeospatialDataGenerator {
* @return
* @throws SpatialException
*/
private static GeospatialData[] queryParentAreas(
GeospatialMetadata metaData, Geometry hull) throws SpatialException {
private GeospatialData[] queryParentAreas(GeospatialMetadata metaData,
Geometry hull) throws SpatialException {
GeospatialData[] rval = null;
String parentAreaSource = metaData.getParentAreaSource();
if (parentAreaSource != null) {
@ -653,7 +686,7 @@ public class GeospatialDataGenerator {
return rval;
}
private static void persistGeoData(String site,
private void persistGeoData(String site,
Map<GeospatialMetadata, GeospatialTime> times,
GeospatialTime curTime, GeospatialDataSet geoData)
throws SerializationException, LocalizationException, JAXBException {
@ -681,7 +714,7 @@ public class GeospatialDataGenerator {
lf.write(xml.getBytes());
}
private static void deleteGeomFiles(String site, GeospatialTime time) {
private void deleteGeomFiles(String site, GeospatialTime time) {
String fileName = time.getFileName();
IPathManager pathMgr = PathManagerFactory.getPathManager();
@ -701,8 +734,28 @@ public class GeospatialDataGenerator {
}
}
private static final String generateGeoDataFilename(
GeospatialMetadata metaData) {
private String generateGeoDataFilename(GeospatialMetadata metaData) {
return metaData.getAreaSource() + "_" + metaData.hashCode() + ".bin";
}
private String getTimeStamp(GeospatialTime curTime,
GeospatialTime lastRunTime) {
long tmStampMs = 0;
if (curTime.getAreaSourceTime() != lastRunTime.getAreaSourceTime()) {
tmStampMs = curTime.getAreaSourceTime();
} else if (curTime.getParentSourceTime() != lastRunTime
.getParentSourceTime()) {
tmStampMs = curTime.getParentSourceTime();
} else if (curTime.getTimeZoneSourceTime() != lastRunTime
.getTimeZoneSourceTime()) {
tmStampMs = curTime.getTimeZoneSourceTime();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(tmStampMs);
return sdf.format(calendar.getTime());
}
}

View file

@ -1,140 +0,0 @@
package com.raytheon.edex.plugin.warning.gis;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.site.SiteUtil;
import com.raytheon.edex.util.Util;
import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialFactory;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialMetadata;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialTime;
import com.raytheon.uf.common.geospatial.SpatialException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.EdexException;
/**
* Compares current time in the database against the time of last run
* generated geometry and if they differ regenerates the files.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 07, 2014 16090 mgamazaychikov Initial creation
* </pre>
*
* @author mgamazaychikov
* @version 1.0
*/
public class GeospatialDataUpdater {
private final static IUFStatusHandler statusHandler = UFStatus
.getHandler(GeospatialDataUpdater.class);
private static final String UPDATER_ENDPOINT = "geospatialUpdateNotify";
private static Log logger = LogFactory.getLog(Util.class);
private static Set<GeospatialMetadata> metaDataSet = null;
private static Map<GeospatialMetadata, GeospatialTime> map = null;
public static void runCheckUpdate() throws SpatialException {
StringBuilder sb = new StringBuilder();
if (metaDataSet == null){
runInit();
}
GeospatialTime curTime = null;
GeospatialTime lastRunTime = null;
boolean generate = false;
sb.append("GeospatialDataUpdater: ");
for (GeospatialMetadata md : metaDataSet) {
lastRunTime = map.get(md);
try {
curTime = GeospatialDataGenerator.queryForCurrentTimes(md);
} catch (Exception e) {
throw new SpatialException(
"Unable to look up database version times.",
e);
}
if (!curTime.equals(lastRunTime)) {
generate = true;
break;
}
else {
generate = false;
}
}
if (generate){
sb.append("Geometry database time differs from current geometry metadata time: regenerating geometries");
}
else {
return;
}
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.info(sb.toString());
}
GeospatialDataGenerator.generateUniqueGeospatialMetadataGeometries();
String updatedTimeStamp = getTimeStamp(curTime, lastRunTime);
try {
EDEXUtil.getMessageProducer().sendAsync(UPDATER_ENDPOINT, updatedTimeStamp);
} catch (EdexException e) {
logger.error("Could not send message to alarm/alert", e);
}
metaDataSet = null;
}
private static String getTimeStamp(GeospatialTime curTime,
GeospatialTime lastRunTime) {
long tmStampMs = 0;
if (curTime.getAreaSourceTime() != lastRunTime.getAreaSourceTime()) {
tmStampMs = curTime.getAreaSourceTime();
} else if (curTime.getParentSourceTime() != lastRunTime.getParentSourceTime()) {
tmStampMs = curTime.getParentSourceTime();
} else if (curTime.getTimeZoneSourceTime() != lastRunTime.getTimeZoneSourceTime()) {
tmStampMs = curTime.getTimeZoneSourceTime();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(tmStampMs);
return sdf.format(calendar.getTime());
}
private static void runInit() {
String mySite = SiteUtil.getSite();
DialogConfiguration dialogConfig = null;
try {
dialogConfig = DialogConfiguration.loadDialogConfig(mySite);
} catch (Exception e) {
statusHandler.handle(Priority.ERROR,
"Error loading warngen config.xml", e);
return;
}
List<String> sites = GeospatialDataGenerator.getBackupSites(dialogConfig);
sites.add(0, mySite);
List<String> templates = GeospatialDataGenerator.getTemplates(dialogConfig);
metaDataSet = GeospatialDataGenerator.getMetaDataSet(sites, templates);
map = GeospatialFactory.loadLastRunGeoTimeSet(mySite);
StringBuilder sb = new StringBuilder();
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
sb.append("GeospatialDataUpdater has been re-inited");
statusHandler.info(sb.toString());
}
}
}

View file

@ -33,7 +33,7 @@
<constructor-arg ref="radarServerNdmListener" />
</bean>
<camelContext id="rpgenvdata-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<camelContext id="rpgenvdata-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<endpoint id="rpgEnvDataCron" uri="clusteredquartz://rpgEnvData/rpgEnvDataRoute/?cron=${rpggenvdata.envdata.cron}"/>
<endpoint id="rpgBiasTableCron" uri="clusteredquartz://rpgBiasTable/rpgBiasTableRoute/?cron=${rpggenvdata.biastable.cron}"/>

View file

@ -5,7 +5,6 @@
<bean id="textDBStaticDataListener" class="com.raytheon.edex.textdb.ingest.TextDBStaticDataSubscriber">
<constructor-arg value="jms-generic:topic:textDBFilesChanged"/>
</bean>
<bean id="siteMapListener" class="com.raytheon.edex.textdb.ingest.SiteMapNationalDatasetSubscriber" />
<bean factory-bean="ndmProc" factory-method="registerListener">

View file

@ -37,7 +37,7 @@
<constructor-arg ref="streamSrv"/>
</bean>
<camelContext id="utility-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<camelContext id="utility-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<route id="utilityNotify">
<from uri="vm://utilityNotify" />

View file

@ -8,7 +8,6 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Export-Package: com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.dataplugin.annotations,
com.raytheon.uf.common.dataplugin.defaults,
com.raytheon.uf.common.dataplugin.exception,
com.raytheon.uf.common.dataplugin.message,
com.raytheon.uf.common.dataplugin.persist,

View file

@ -21,7 +21,6 @@ package com.raytheon.uf.common.dataplugin;
import java.util.List;
import com.raytheon.uf.common.dataplugin.defaults.PluginPropertyDefaults;
import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
/**
@ -32,8 +31,8 @@ import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 20, 2009 njensen Initial creation
*
* Mar 20, 2009 njensen Initial creation.
* Mar 13, 2014 2726 rjpeter Moved default values to set on plugin registration.
* </pre>
*
* @author njensen
@ -54,7 +53,7 @@ public class PluginProperties {
protected Class<PluginDataObject> record;
protected int initialRetentionTime;
protected Integer initialRetentionTime;
protected String pluginFQN;
@ -62,22 +61,40 @@ public class PluginProperties {
protected IHDFFilePathProvider pathProvider;
/**
* Set the defaults for any fields that haven't already been set to a not
* null value.
*
* @param defaults
*/
public void setDefaults(PluginProperties defaults) {
/*
* pluginName, pluginFQN, dependencyFQNs, and record have no defaults to
* inherit
*/
if (database == null) {
database = defaults.getDatabase();
}
if (initializer == null) {
initializer = defaults.getInitializer();
}
if (dao == null) {
dao = defaults.getDao();
}
if (initialRetentionTime == null) {
initialRetentionTime = defaults.getInitialRetentionTime();
}
if (pathProvider == null) {
pathProvider = defaults.getPathProvider();
}
}
/**
* Compression to use on storage, if null, no compression
*/
protected String compression;
/**
* Constructor that initializes values to default values
*/
public PluginProperties() {
database = PluginPropertyDefaults.getDatabase();
initializer = PluginPropertyDefaults.getInitializer();
dao = PluginPropertyDefaults.getDao();
initialRetentionTime = PluginPropertyDefaults.getInitialRetentionTime();
pathProvider = PluginPropertyDefaults.getPathProvider();
}
/**
* @return the database
*/
@ -112,7 +129,11 @@ public class PluginProperties {
* @return the initialRetentionTime
*/
public int getInitialRetentionTime() {
return initialRetentionTime;
if (initialRetentionTime != null) {
return initialRetentionTime;
}
return 0;
}
/**
@ -199,5 +220,4 @@ public class PluginProperties {
public void setCompression(String compression) {
this.compression = compression;
}
}

View file

@ -1,120 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.defaults;
import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
/**
* Defaults for the data plugins. Setters should only be called once through
* Spring XML configuration.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 20, 2009 njensen Initial creation
*
* </pre>
*
* @author njensen
* @version 1.0
*/
public class PluginPropertyDefaults {
protected static String database;
protected static Class<?> initializer;
protected static Class<?> dao;
protected static int initialRetentionTime;
protected static IHDFFilePathProvider pathProvider;
/**
* @return the database
*/
public static String getDatabase() {
return database;
}
/**
* @param database
* the database to set
*/
public void setDatabase(String database) {
PluginPropertyDefaults.database = database;
}
/**
* @return the initialRetentionTime
*/
public static int getInitialRetentionTime() {
return initialRetentionTime;
}
/**
* @param initialRetentionTime
* the initialRetentionTime to set
*/
public void setInitialRetentionTime(int initialRetentionTime) {
PluginPropertyDefaults.initialRetentionTime = initialRetentionTime;
}
/**
* @return the initializer
*/
public static Class<?> getInitializer() {
return initializer;
}
/**
* @param initializer
* the initializer to set
*/
public void setInitializer(Class<?> initializer) {
PluginPropertyDefaults.initializer = initializer;
}
/**
* @return the dao
*/
public static Class<?> getDao() {
return dao;
}
/**
* @param dao
* the dao to set
*/
public void setDao(Class<?> dao) {
PluginPropertyDefaults.dao = dao;
}
public static IHDFFilePathProvider getPathProvider() {
return pathProvider;
}
public void setPathProvider(IHDFFilePathProvider pathProvider) {
PluginPropertyDefaults.pathProvider = pathProvider;
}
}

View file

@ -13,4 +13,5 @@ Import-Package: com.raytheon.uf.common.serialization,
com.raytheon.uf.common.serialization.annotations,
org.apache.commons.lang
Require-Bundle: net.sf.cglib;bundle-version="2.1.3",
com.raytheon.uf.common.status;bundle-version="1.11.11"
com.raytheon.uf.common.status;bundle-version="1.11.11",
com.raytheon.uf.common.util

View file

@ -20,18 +20,13 @@
package com.raytheon.uf.common.message;
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.raytheon.uf.common.message.adapter.WsIdAdapter;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdapter;
import com.raytheon.uf.common.util.SystemUtil;
/**
* The WsId contains the work station identification for the user. *
@ -41,12 +36,12 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdap
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 10, 2009 randerso Initial creation
* Apr 25, 2012 545 randerso Repurposed the lockKey field as threadId
* Sep 19, 2012 #1190 dgilling Cache host names so toPrettyString() doesn't
* get delayed behind DNS requests.
* Sep 20, 2012 #1190 dgilling Create method getHostName().
*
* Jun 10, 2009 randerso Initial creation
* Apr 25, 2012 545 randerso Repurposed the lockKey field as threadId
* Sep 19, 2012 #1190 dgilling Cache host names so toPrettyString() doesn't
* get delayed behind DNS requests.
* Sep 20, 2012 #1190 dgilling Create method getHostName().
* Mar 20, 2014 2726 rjpeter Moved hostNameCache to SystemUtil.
* </pre>
*
* @author randerso
@ -57,32 +52,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdap
@DynamicSerializeTypeAdapter(factory = WsIdAdapter.class)
public class WsId implements Serializable, ISerializableObject {
private static class BoundedMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
private final int maxSize;
public BoundedMap(int maxSize) {
super(16, 0.75f, true);
this.maxSize = maxSize;
}
/*
* (non-Javadoc)
*
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
@Override
protected boolean removeEldestEntry(Entry<K, V> eldest) {
return size() > maxSize;
}
}
private static final long serialVersionUID = 1L;
private static final Map<InetAddress, String> hostNameCache = Collections
.synchronizedMap(new BoundedMap<InetAddress, String>(100));
private final InetAddress networkId;
private final String userName;
@ -169,25 +140,14 @@ public class WsId implements Serializable, ISerializableObject {
this.progName = "unknown";
}
this.pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean()
.getName().split("@")[0]);
this.pid = SystemUtil.getPid();
this.threadId = Thread.currentThread().getId();
if (networkId != null) {
this.networkId = networkId;
} else {
InetAddress addr = null;
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
try {
addr = InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 });
} catch (UnknownHostException e1) {
// won't happen
}
}
this.networkId = addr;
this.networkId = SystemUtil.getLocalAddress();
}
}
@ -203,7 +163,7 @@ public class WsId implements Serializable, ISerializableObject {
long addr = 0;
byte[] bytes = networkId.getAddress();
for (int i = bytes.length - 1; i >= 0; i--) {
addr = addr << 8 | (0xff & bytes[i]);
addr = (addr << 8) | (0xff & bytes[i]);
}
o.append(addr).append(':').append(userName).append(':')
@ -219,7 +179,7 @@ public class WsId implements Serializable, ISerializableObject {
* @return WsId as pretty string
*/
public String toPrettyString() {
String hostname = retrieveFromHostCache(networkId);
String hostname = SystemUtil.getHostName(networkId);
StringBuilder o = new StringBuilder();
o.append(userName).append('@').append(hostname).append(':')
@ -229,16 +189,6 @@ public class WsId implements Serializable, ISerializableObject {
return o.toString();
}
private String retrieveFromHostCache(InetAddress address) {
String hostName = hostNameCache.get(address);
if (hostName == null) {
hostName = address.getHostName();
hostNameCache.put(address, hostName);
}
return hostName;
}
/**
* @return the _networkId
*/
@ -247,7 +197,7 @@ public class WsId implements Serializable, ISerializableObject {
}
public String getHostName() {
return retrieveFromHostCache(networkId);
return SystemUtil.getHostName(networkId);
}
/**
@ -287,13 +237,13 @@ public class WsId implements Serializable, ISerializableObject {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (threadId ^ (threadId >>> 32));
result = prime * result
result = (prime * result) + (int) (threadId ^ (threadId >>> 32));
result = (prime * result)
+ ((networkId == null) ? 0 : networkId.hashCode());
result = prime * result + pid;
result = prime * result
result = (prime * result) + pid;
result = (prime * result)
+ ((progName == null) ? 0 : progName.hashCode());
result = prime * result
result = (prime * result)
+ ((userName == null) ? 0 : userName.hashCode());
return result;
}

View file

@ -21,9 +21,11 @@ package com.raytheon.uf.common.util;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* System utilities such as hostname and pid lookup.
@ -35,18 +37,57 @@ import java.util.Enumeration;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 26, 2011 rjpeter Initial creation
*
* Apr 10, 2014 2726 rjpeter Moved hostName caching logic from WsId to here.
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class SystemUtil {
/**
* Map that can be limited to a given number of entries.
*/
private static class BoundedMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
private final int maxSize;
public BoundedMap(int maxSize) {
super(16, 0.75f, true);
this.maxSize = maxSize;
}
/*
* (non-Javadoc)
*
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
@Override
protected boolean removeEldestEntry(Entry<K, V> eldest) {
return size() > maxSize;
}
}
private static final Map<InetAddress, String> hostNameCache = Collections
.synchronizedMap(new BoundedMap<InetAddress, String>(100));
protected static String hostName;
protected static Integer pid;
protected static InetAddress addr;
static {
/* attempt to initialize fields */
getPid();
getHostName();
}
/**
* Returns the pid of the current process.
*
* @return
*/
public static int getPid() {
if (pid == null) {
pid = new Integer(ManagementFactory.getRuntimeMXBean().getName()
@ -56,43 +97,65 @@ public class SystemUtil {
return pid.intValue();
}
/**
* Returns the local INetAddress.
*
* @return
*/
public static InetAddress getLocalAddress() {
if (addr == null) {
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
try {
return InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 });
} catch (UnknownHostException e1) {
// won't happen
}
}
}
return addr;
}
/**
* Returns the hostName for the given inet address. The address is cached
* for the lifetime of the jvm after first look up. If a machine changes IPs
* it will get mapped to the wrong hostName until a reboot.
*
* @param address
* @return
*/
public static String getHostName(InetAddress address) {
String hostName = hostNameCache.get(address);
if (hostName == null) {
hostName = address.getHostName();
hostNameCache.put(address, hostName);
}
return hostName;
}
/**
* Returns local host name.
*
* @return
*/
public static String getHostName() {
if (hostName == null) {
InetAddress addrToUse = null;
boolean found = false;
try {
Enumeration<NetworkInterface> nis = NetworkInterface
.getNetworkInterfaces();
while (nis.hasMoreElements() && !found) {
NetworkInterface ni = nis.nextElement();
ni.isVirtual();
ni.isUp();
Enumeration<InetAddress> addrs = ni.getInetAddresses();
while (addrs.hasMoreElements() && !found) {
InetAddress addr = addrs.nextElement();
if (addr.isLinkLocalAddress() == false
&& addr.isSiteLocalAddress() == false
&& addr.isLoopbackAddress() == false) {
addrToUse = addr;
found = true;
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
InetAddress addr = getLocalAddress();
hostName = getHostName(addr);
if (addrToUse == null) {
if (hostName == null) {
String hostNameProp = System.getenv("HOSTNAME");
if (hostNameProp != null && hostNameProp.trim().length() == 0) {
if ((hostNameProp != null)
&& (hostNameProp.trim().length() == 0)) {
hostName = hostNameProp;
} else {
hostName = "localhost";
}
} else {
hostName = addrToUse.getHostName();
}
}
return hostName;
}
}

View file

@ -1,14 +1,11 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="clusteredActiveTableContext"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<route id="activeTablePendingRoute">
<from uri="jms-durable:queue:activeTablePending"/>
@ -37,8 +34,7 @@
</camelContext>
<bean factory-bean="clusteredCamelContextMgr"
factory-method="register">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredActiveTableContext" />
</bean>
</beans>

View file

@ -89,7 +89,7 @@
<bean id="fetchATSrv" class="com.raytheon.uf.edex.activetable.vtecsharing.FetchActiveTableSrv"/>
<camelContext id="activeTableSharingRoutes"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<route id="activeSiteForFetchATSrv">
<from uri="jms-generic:queue:gfeSiteActivated" />
@ -102,8 +102,7 @@
</doTry>
</route>
</camelContext>
<bean factory-bean="clusteredCamelContextMgr"
factory-method="register">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="activeTableSharingRoutes" />
</bean>
</beans>

View file

@ -22,9 +22,7 @@ package com.raytheon.uf.edex.core;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
@ -52,12 +50,13 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 04/23/08 1088 chammack Split from Util
* 04/23/2008 1088 chammack Split from Util
* 11/22/2010 2235 cjeanbap Added audio file to StatusMessage.
* 02/02/2011 6500 cjeanbap Added paramter to method signature and
* properly assign source value.
* 06/12/2012 0609 djohnson Use EDEXUtil for EDEX_HOME.
* 3/18/2013 1802 bphillip Added getList utility function
* 03/18/2013 1802 bphillip Added getList utility function
* 04/10/2014 2726 rjpeter Added methods for waiting for edex to be running.
* </pre>
*
* @author chammack
@ -81,20 +80,7 @@ public class EDEXUtil implements ApplicationContextAware {
// TODO
private static final String alertEndpoint = "alertVizNotify";
private static int serverId;
static {
try {
String hostname = InetAddress.getLocalHost().getCanonicalHostName();
serverId = hostname.hashCode();
} catch (UnknownHostException e) {
serverId = 0;
// assume localhost, no network connection
}
}
public static int getServerId() {
return serverId;
}
private static final Object waiter = new Object();
@Override
public void setApplicationContext(ApplicationContext context)
@ -146,6 +132,30 @@ public class EDEXUtil implements ApplicationContextAware {
return "Operational".equals(System.getProperty("System.status"));
}
/**
* Blocks until EDEX is in the running state.
*/
public static void waitForRunning() {
synchronized (waiter) {
try {
while (!isRunning()) {
waiter.wait(15000);
}
} catch (InterruptedException e) {
// ignore
}
}
}
/**
* Called once EDEX is in a running state to notify all waiting clients.
*/
public static void notifyIsRunning() {
synchronized (waiter) {
waiter.notifyAll();
}
}
public static boolean containsESBComponent(String name) {
return CONTEXT.containsBean(name);
}
@ -176,9 +186,10 @@ public class EDEXUtil implements ApplicationContextAware {
persistDir = envProperties.getEnvValue("PERSISTDIR");
persistDir = FileUtil.convertFilePath(persistDir);
if (persistDir == null)
if (persistDir == null) {
throw new PluginException(
"Unable to retrieve value for the PERSISTDIR");
}
dbDirectory = new File(persistDir);
dbDirectory.mkdirs();

View file

@ -0,0 +1,172 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.core;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
/**
* Base class for Timer based threading. Allows previous thread based paradigms
* to hook in to a camel context with minimal work.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 19, 2014 2826 rjpeter Initial creation.
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public abstract class EdexTimerBasedThread implements IContextStateProcessor {
/**
* Number of threads that have been started.
*/
protected final AtomicInteger threadCount = new AtomicInteger(0);
/**
* Current active threads.
*/
protected final List<Thread> threads = new LinkedList<Thread>();
/**
* Whether the container is running or not.
*/
protected volatile boolean running = true;
/**
* Interval thread should sleep between calls.
*/
protected int threadSleepInterval = 30000;
/**
* The name to use for the threads.
*
* @return
*/
public abstract String getThreadGroupName();
/**
* Method to do the work. Should return when done. Run method handles start
* up/shutdown mechanism.
*
* @throws Exception
*/
public abstract void process() throws Exception;
/**
* Can be overridden to do any work to cleanup the thread on shutdown.
*/
public void dispose() {
}
/**
* Called by camel to do the processing. Will run until the context is
* shutdown.
*/
public void run() {
synchronized (threads) {
threads.add(Thread.currentThread());
}
try {
Thread.currentThread().setName(
getThreadGroupName() + "-" + threadCount.incrementAndGet());
while (running) {
try {
process();
} catch (Exception e) {
UFStatus.getHandler().error(
"Error occurred during processing", e);
}
try {
/*
* use waiter to allow shutdown to wake thread for immediate
* shutdown
*/
synchronized (threads) {
threads.wait(threadSleepInterval);
}
} catch (InterruptedException e) {
// ignore
}
}
} finally {
synchronized (threads) {
threads.remove(Thread.currentThread());
threads.notify();
}
dispose();
}
}
@Override
public void preStart() {
}
@Override
public void postStart() {
}
@Override
public void preStop() {
running = false;
synchronized (threads) {
threads.notifyAll();
}
}
@Override
public void postStop() {
IUFStatusHandler statusHandler = UFStatus.getHandler();
String msg = "Waiting for " + getThreadGroupName()
+ " threads to finish";
synchronized (threads) {
while (!threads.isEmpty()) {
statusHandler.info(msg);
try {
threads.wait(10000);
} catch (Exception e) {
// ignore
}
}
}
}
public int getThreadSleepInterval() {
return threadSleepInterval;
}
public void setThreadSleepInterval(int threadSleepInterval) {
this.threadSleepInterval = threadSleepInterval;
}
}

View file

@ -17,10 +17,11 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.warning.gis;
package com.raytheon.uf.edex.core;
/**
* TODO Add Description
* Methods to be called as part of the context life cycle for starting and
* stopping the context.
*
* <pre>
*
@ -28,31 +29,36 @@ package com.raytheon.edex.plugin.warning.gis;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 24, 2011 rjpeter Initial creation
* Feb 26, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public interface IContextStateProcessor {
public class GeospatialDataGeneratorThread {
public GeospatialDataGeneratorThread() {
Thread t = new Thread("WarngenGeometryGenerator") {
public void run() {
// TODO: Move to camel timer, when camel upgraded to at least
// 2.8 and take advantage of single run timer
try {
// delay to allow server to start
Thread.sleep(120000);
} catch (InterruptedException e) {
// ignore
}
GeospatialDataGenerator
.generateUniqueGeospatialMetadataGeometries();
// scan and clean old geometries
}
};
t.start();
}
/**
* Perform any work that needs to be done before the context is started,
* such as initialization.
*/
public void preStart();
/**
* Perform any work that needs to be done after the context is started, such
* as sending notifications to clients.
*/
public void postStart();
/**
* Perform any work that needs to be done before context is stopped, such as
* notifying async threads to stop.
*/
public void preStop();
/**
* Perform any work that needs to be done after the context is stopped, such
* as sending in memory data.
*/
public void postStop();
}

View file

@ -35,8 +35,8 @@ import com.raytheon.uf.common.util.registry.RegistryException;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 6, 2009 mschenke Initial creation
*
* Aug 6, 2009 mschenke Initial creation.
* Mar 19, 2014 2726 rjpeter Updated for graceful shutdown and easier spring dependency management.
* </pre>
*
* @author mschenke
@ -47,7 +47,15 @@ public class PluginRegistry extends GenericRegistry<String, PluginProperties> {
private static PluginRegistry instance = new PluginRegistry();
private List<IPluginRegistryChanged> listeners = new ArrayList<IPluginRegistryChanged>();
/**
* Plugin registry listeners.
*/
private final List<IPluginRegistryChanged> listeners = new ArrayList<IPluginRegistryChanged>();
/**
* Default values for plugins registered with the registry.
*/
private PluginProperties defaultPluginProperties;
private PluginRegistry() {
super();
@ -61,6 +69,8 @@ public class PluginRegistry extends GenericRegistry<String, PluginProperties> {
public Object register(String pluginName, PluginProperties pluginProperties)
throws RegistryException {
if (!registry.containsKey(pluginName)) {
pluginProperties.setDefaults(defaultPluginProperties);
super.register(pluginName, pluginProperties);
for (IPluginRegistryChanged iprc : listeners) {
iprc.pluginAdded(pluginName);
@ -77,4 +87,22 @@ public class PluginRegistry extends GenericRegistry<String, PluginProperties> {
return this;
}
public PluginProperties getDefaultPluginProperties() {
return defaultPluginProperties;
}
public void setDefaultPluginProperties(
PluginProperties defaultPluginProperties) {
this.defaultPluginProperties = defaultPluginProperties;
}
/**
* The initial listeners to the plugin registry to ensure minimum
* requirements are meant via spring launching.
*
* @param listeners
*/
public void setInitialListeners(List<IPluginRegistryChanged> listeners) {
this.listeners.addAll(listeners);
}
}

View file

@ -4,16 +4,10 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="cpgSrvDispatcher" class="com.raytheon.uf.edex.cpgsrv.CPGDispatcher" depends-on="commonTimeRegistered"/>
<bean id="cpgsrvCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="cpgsrv-camel"/>
</bean>
<camelContext id="cpgsrv-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<route id="cpgProcessAlerts">
<from uri="direct-vm:processCPGAlerts"/>
<to uri="direct-vm:stageNotification"/>
@ -21,8 +15,7 @@
</camelContext>
<camelContext id="clusteredCpgSrvRoutes"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<route id="cpgsrvListenerRoute">
<!-- Data from plugin notification -->
<from uri="jms-durable:queue:cpgsrvFiltering?concurrentConsumers=5"/>
@ -38,8 +31,7 @@
</doTry>
</route>
</camelContext>
<bean factory-bean="clusteredCamelContextMgr"
factory-method="register">
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
<constructor-arg ref="clusteredCpgSrvRoutes" />
</bean>
</beans>

View file

@ -49,7 +49,9 @@
<constructor-arg ref="saveOrUpdateHandler"/>
</bean>
<bean id="pluginFactory" class="com.raytheon.uf.edex.database.plugin.PluginFactory" factory-method="getInstance"/>
<bean id="pluginFactory" class="com.raytheon.uf.edex.database.plugin.PluginFactory" factory-method="getInstance">
<property name="defaultPathProvider" ref="defaultPathProvider"/>
</bean>
<bean id="pluginFactoryRegisteredToDataURIUtil"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

View file

@ -40,8 +40,8 @@ import com.raytheon.uf.edex.core.dataplugin.PluginRegistry;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 28, 2010 #5050 rjpeter Initial creation
*
* Apr 28, 2010 #5050 rjpeter Initial creation
* May 29, 2014 2726 rjpeter Added initial listeners and properties for easier spring dependency management.
* </pre>
*
* @author rjpeter
@ -56,7 +56,9 @@ public class DatabasePluginRegistry extends
private static DatabasePluginRegistry instance = new DatabasePluginRegistry();
private List<IDatabasePluginRegistryChanged> listeners = new ArrayList<IDatabasePluginRegistryChanged>();
private final List<IDatabasePluginRegistryChanged> listeners = new ArrayList<IDatabasePluginRegistryChanged>();
private List<DatabasePluginProperties> initialProperties;
private DatabasePluginRegistry() {
super();
@ -66,6 +68,18 @@ public class DatabasePluginRegistry extends
return instance;
}
/**
* Called by spring to initialize the registry. Mainly used to ensure the
* base database plugin is always loaded.
*/
public void init() throws RegistryException {
if ((initialProperties != null) && !initialProperties.isEmpty()) {
for (DatabasePluginProperties dbProp : initialProperties) {
register(dbProp.getPluginFQN(), dbProp);
}
}
}
@Override
public Object register(String pluginFQN,
DatabasePluginProperties pluginProperties) throws RegistryException {
@ -95,7 +109,8 @@ public class DatabasePluginRegistry extends
public void pluginAdded(String pluginName) {
PluginProperties props = PluginRegistry.getInstance()
.getRegisteredObject(pluginName);
if (props.getPluginFQN() != null && props.getPluginFQN().length() > 0) {
if ((props.getPluginFQN() != null)
&& (props.getPluginFQN().length() > 0)) {
// multiple plugins may use the same jar file.
if (!registry.containsKey(props.getPluginFQN())) {
try {
@ -109,4 +124,14 @@ public class DatabasePluginRegistry extends
}
}
}
public void setInitialListeners(
List<IDatabasePluginRegistryChanged> listeners) {
this.listeners.addAll(listeners);
}
public void setInitialProperties(
List<DatabasePluginProperties> initialProperties) {
this.initialProperties = initialProperties;
}
}

View file

@ -31,7 +31,6 @@ import com.raytheon.uf.common.dataplugin.IPluginClassMapper;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.PluginProperties;
import com.raytheon.uf.common.dataplugin.defaults.PluginPropertyDefaults;
import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider;
import com.raytheon.uf.edex.core.dataplugin.PluginRegistry;
@ -50,7 +49,7 @@ import com.raytheon.uf.edex.core.dataplugin.PluginRegistry;
* Feb 06, 2009 1990 bphillip Refactored to use spring container
* Mar 20, 2009 njensen Refactored to use PluginProperties
* May 16, 2013 1869 bsteffen Rewrite dataURI property mappings.
*
* Mar 19, 2014 2726 rjpeter Added defaultPathProvider field.
* </pre>
*
* @author garmendariz
@ -75,7 +74,9 @@ public class PluginFactory implements IPluginClassMapper {
private Map<String, PluginDao> pluginDaoMap = new HashMap<String, PluginDao>();
private Object daoMapLock = new Object();
private final Object daoMapLock = new Object();
private IHDFFilePathProvider defaultPathProvider = null;
/**
* Private constructor
@ -173,6 +174,7 @@ public class PluginFactory implements IPluginClassMapper {
* @throws PluginException
* If the class cannot be determined
*/
@Override
public Class<PluginDataObject> getPluginRecordClass(String pluginName)
throws PluginException {
PluginProperties props = PluginRegistry.getInstance()
@ -233,7 +235,7 @@ public class PluginFactory implements IPluginClassMapper {
if (props != null) {
rval = props.getPathProvider();
} else {
rval = PluginPropertyDefaults.getPathProvider();
rval = defaultPathProvider;
}
return rval;
}
@ -280,4 +282,13 @@ public class PluginFactory implements IPluginClassMapper {
+ " is not registered with the PluginRegistry");
}
}
/**
* Set the default path provider. Used by spring to configure the factory.
*
* @param defaultPathProvider
*/
public void setDefaultPathProvider(IHDFFilePathProvider defaultPathProvider) {
this.defaultPathProvider = defaultPathProvider;
}
}

View file

@ -20,13 +20,8 @@
class="com.raytheon.uf.edex.datadelivery.event.notification.NotificationPurge"
depends-on="ddEventRegister" />
<bean id="noitfyCamelRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="ddNotify-camel" />
</bean>
<camelContext id="ddNotify-camel" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler" autoStartup="false">
errorHandlerRef="errorHandler">
<route id="notificationPurgeRoute">
<from uri="timer://notifiyPurge?period=60s" />

View file

@ -10,12 +10,17 @@
<constructor-arg ref="ProviderHandler" />
</bean>
<bean id="DataSetMetaDataPurgeLauncher" class="com.raytheon.uf.edex.datadelivery.harvester.purge.DataSetMetaDataPurgeLauncher"
factory-method="getInstance" depends-on="DbInit">
</bean>
<camelContext id="MetaData-context"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<endpoint id="metaDataCron" uri="quartz://datadelivery/harvester/?cron=${metadata-process.cron}"/>
<endpoint id="harvesterProcessWorkEndpoint" uri="jms-generic:queue:metaDataProcessWork?concurrentConsumers=${metadata-process.threads}&amp;threadName=harvester"/>
<endpoint id="datasetMetaDataPurgeCron" uri="quartz://datadelivery/metaDataPurge/?cron=${metadata-purge.cron}"/>
<route id="metaDataProcess">
<from uri="metaDataCron" />
@ -35,19 +40,6 @@
</doTry>
</route>
</camelContext>
<!-- Start of DataSetMetaData purge configuration -->
<bean id="DataSetMetaDataPurgeLauncher" class="com.raytheon.uf.edex.datadelivery.harvester.purge.DataSetMetaDataPurgeLauncher"
factory-method="getInstance" depends-on="DbInit">
</bean>
<camelContext id="DataSetMetaDataPurge-context"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<endpoint id="datasetMetaDataPurgeCron" uri="quartz://datadelivery/metaDataPurge/?cron=${metadata-purge.cron}"/>
<route id="metaDataPurge">
<from uri="datasetMetaDataPurgeCron" />
<to uri="jms-generic:queue:metaDataPurgeWork" />
@ -67,6 +59,4 @@
</route>
</camelContext>
<!-- End of DataSetMetaData purge configuration -->
</beans>

View file

@ -1,7 +1,6 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="dataDeliveryRestClient" class="com.raytheon.uf.edex.datadelivery.registry.web.DataDeliveryRESTServices"/>

View file

@ -1,7 +1,6 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="FederatedRegistryMonitor" class="com.raytheon.uf.edex.datadelivery.registry.availability.FederatedRegistryMonitor">
<constructor-arg ref="registryObjectDao"/>

View file

@ -1,7 +1,6 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- This should be moved to a grid OGC plugin when one exists -->
<bean factory-bean="metadataAdapterRegistry" factory-method="register">

View file

@ -20,20 +20,6 @@
</bean>
<camelContext id="handleoupAckMgrContext" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<route id="oupAckMGrRoute">
<from uri="jms-generic:topic:mhs.ackmgr" />
<doTry>
<bean ref="oupAckMgr" method="processAck" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:oup?level=INFO"/>
</doCatch>
</doTry>
</route>
</camelContext>
<camelContext id="handleoupFilePushContext" xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler">
<!-- Non clustered, specifically used by handleOUP.py to push published
files directly into stream -->
@ -50,11 +36,21 @@
<doCatch>
<exception>java.lang.Throwable</exception>
<to
uri="log:manual?level=ERROR&amp;showBody=true" />
uri="log:oup?level=ERROR&amp;showBody=true" />
</doCatch>
</doTry>
</route>
<route id="oupAckMGrRoute">
<from uri="jms-generic:topic:mhs.ackmgr" />
<doTry>
<bean ref="oupAckMgr" method="processAck" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:oup?level=INFO"/>
</doCatch>
</doTry>
</route>
</camelContext>
</beans>

View file

@ -10,8 +10,7 @@
<camelContext id="distro"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
errorHandlerRef="errorHandler">
<endpoint id="refreshDistributionCron" uri="quartz://refreshDist/refreshDistRoute/?cron=${distribution.cron}"/>
@ -59,8 +58,4 @@
</doTry>
</route>
</camelContext>
<bean factory-bean="contextManager"
factory-method="register">
<constructor-arg ref="distro"/>
</bean>
</beans>

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Camel Plug-in
Bundle-SymbolicName: com.raytheon.uf.edex.esb.camel
Bundle-Version: 1.12.1174.qualifier
Bundle-Version: 1.14.0
Bundle-Vendor: Raytheon
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: org.apache.camel;bundle-version="1.0.0",
@ -19,7 +19,7 @@ Require-Bundle: org.apache.camel;bundle-version="1.0.0",
com.raytheon.uf.common.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.json;bundle-version="1.0.0"
Export-Package: com.raytheon.uf.edex.esb.camel,
com.raytheon.uf.edex.esb.camel.directvm,
com.raytheon.uf.edex.esb.camel.context,
com.raytheon.uf.edex.esb.camel.jms
Import-Package: com.raytheon.uf.common.event,
com.raytheon.uf.common.message,

View file

@ -31,7 +31,9 @@ import java.util.concurrent.CountDownLatch;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.PropertiesUtil;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.modes.EDEXModesUtil;
import com.raytheon.uf.edex.esb.camel.context.ContextManager;
@ -54,7 +56,7 @@ import com.raytheon.uf.edex.esb.camel.context.ContextManager;
* Feb 14, 2013 1638 mschenke Removing activemq reference in stop
* Apr 22, 2013 #1932 djohnson Use countdown latch for a shutdown hook.
* Dec 04, 2013 2566 bgonzale refactored mode methods to a utility in edex.core.
*
* Mar 19, 2014 2726 rjpeter Added graceful shutdown.
* </pre>
*
* @author chammack
@ -66,15 +68,36 @@ public class Executor {
private static final CountDownLatch shutdownLatch = new CountDownLatch(1);
public static void start() throws Exception {
final long t0 = System.currentTimeMillis();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
ContextManager ctxMgr = ContextManager.getInstance();
long t1 = System.currentTimeMillis();
System.out
.println("**************************************************");
System.out
.println("* EDEX ESB is shutting down *");
System.out
.println("**************************************************");
ctxMgr.stopContexts();
long t2 = System.currentTimeMillis();
System.out
.println("**************************************************");
System.out
.println("* EDEX ESB is shut down *");
System.out.println("* Total time to shutdown: "
+ TimeUtil.prettyDuration(t2 - t1));
System.out.println("* EDEX ESB uptime: "
+ TimeUtil.prettyDuration(t2 - t0));
System.out
.println("**************************************************");
shutdownLatch.countDown();
}
});
long t0 = System.currentTimeMillis();
Thread.currentThread().setName("EDEXMain");
System.setProperty("System.status", "Starting");
@ -113,7 +136,7 @@ public class Executor {
String modeName = System.getProperty("edex.run.mode");
if (modeName != null && modeName.length() > 0) {
if ((modeName != null) && (modeName.length() > 0)) {
System.out.println("EDEX run configuration: " + modeName);
} else {
System.out
@ -123,8 +146,7 @@ public class Executor {
+ System.getProperty("aw.site.identifier"));
List<String> discoveredPlugins = EDEXModesUtil.extractSpringXmlFiles(
xmlFiles,
modeName);
xmlFiles, modeName);
System.out.println();
System.out.println(" ");
@ -141,8 +163,10 @@ public class Executor {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
xmlFiles.toArray(new String[xmlFiles.size()]));
ContextManager ctxMgr = (ContextManager) context
.getBean("contextManager");
// start final routes
ctxMgr.startContexts();
@ -151,11 +175,12 @@ public class Executor {
.println("**************************************************");
System.out
.println("* EDEX ESB is now operational *");
System.out.println("* Total startup time: " + ((t1 - t0) / 1000)
+ " seconds");
System.out.println("* Total startup time: "
+ TimeUtil.prettyDuration(t1 - t0));
System.out
.println("**************************************************");
System.setProperty("System.status", "Operational");
EDEXUtil.notifyIsRunning();
shutdownLatch.await();
}

View file

@ -19,51 +19,106 @@
**/
package com.raytheon.uf.edex.esb.camel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.ConfigurationException;
import org.apache.camel.AsyncCallback;
import org.apache.camel.AsyncProcessor;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelExecutionException;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Processor;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.Route;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.spi.InterceptStrategy;
import com.raytheon.uf.common.message.IMessage;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.core.IMessageProducer;
import com.raytheon.uf.edex.esb.camel.context.ContextData;
import com.raytheon.uf.edex.esb.camel.context.ContextManager;
/**
* Sends message to endpoints programmatically.
* Sends message to endpoints programmatically. Implements the camel
* {@link InterceptStrategy} to allow for tracking of camel dependencies where
* possible so that the ProducerTemplate is created from the correct context.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 14, 2008 njensen Initial creation
* Nov 14, 2008 njensen Initial creation.
* Mar 27, 2014 2726 rjpeter Modified for graceful shutdown changes.
* </pre>
*
* @author njensen
* @version 1.0
*/
public class MessageProducer implements ApplicationContextAware,
IMessageProducer {
public class MessageProducer implements IMessageProducer, InterceptStrategy {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(MessageProducer.class);
private static ApplicationContext springContext;
/*
* setup via an interceptor used for tracking what context the current
* thread is participating in for dependency management of runtime
* IMessageProducer message sends.
*/
private final ThreadLocal<CamelContext> currentThreadContext = new ThreadLocal<CamelContext>();
private static List<CamelContext> camelContextList;
private final ConcurrentMap<CamelContext, ProducerTemplate> contextProducerMap = new ConcurrentHashMap<CamelContext, ProducerTemplate>();
private static Map<String, String> endpointIdUriMap = new HashMap<String, String>();
/**
* List of messages waiting to be sent.
*/
private final List<WaitingMessage> waitingMessages = new LinkedList<WaitingMessage>();
private static Map<String, CamelContext> endpointContextMap = new HashMap<String, CamelContext>();
/**
* Internal variable for tracking if messages should be queued or not.
*/
private volatile boolean started = false;
private static Map<CamelContext, ProducerTemplate> contextProducerMap = new HashMap<CamelContext, ProducerTemplate>();
/**
* Constructor that launches an internal thread that will send all async
* messages that queue up while camel starts up.
*/
public MessageProducer() {
Thread t = new Thread() {
@Override
public void run() {
EDEXUtil.waitForRunning();
started = true;
sendPendingAsyncMessages();
}
};
t.setName("MessageProducer-pendingMessageSender");
t.start();
}
/**
* Returns the ContextData
*
* @return
* @throws EdexException
*/
protected ContextData getContextData() throws EdexException {
try {
return ContextManager.getInstance().getContextData();
} catch (ConfigurationException e) {
throw new EdexException("Unable to look up camel context data", e);
}
}
/*
* (non-Javadoc)
@ -72,21 +127,42 @@ public class MessageProducer implements ApplicationContextAware,
* com.raytheon.uf.edex.esb.camel.IMessageProducer#sendAsync(java.lang.String
* , java.lang.Object)
*/
@Override
public void sendAsync(String endpoint, Object message) throws EdexException {
CamelContext camelContext = getCamelContext(endpoint);
ProducerTemplate template = getProducerTemplate(camelContext);
String uri = endpointIdUriMap.get(endpoint);
Map<String, Object> headers = getHeaders(message);
if (!started && queueWaitingMessage(WaitingType.ID, endpoint, message)) {
return;
}
String uri = getContextData().getEndpointUriForRouteId(endpoint);
sendAsyncUri(uri, message);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.core.IMessageProducer#sendAsyncUri(java.lang.String,
* java.lang.Object)
*/
@Override
public void sendAsyncUri(String uri, Object message) throws EdexException {
if (!started && queueWaitingMessage(WaitingType.URI, uri, message)) {
return;
}
try {
ProducerTemplate template = getProducerTemplateForUri(uri);
Map<String, Object> headers = getHeaders(message);
if (headers != null) {
template.sendBodyAndHeaders(uri, ExchangePattern.InOnly,
message, headers);
} else {
template.sendBody(uri, ExchangePattern.InOnly, message);
}
} catch (CamelExecutionException e) {
} catch (Exception e) {
throw new EdexException("Error sending asynchronous message: "
+ message + " to endpoint: " + uri, e);
+ message + " to uri: " + uri, e);
}
}
@ -97,114 +173,112 @@ public class MessageProducer implements ApplicationContextAware,
* com.raytheon.uf.edex.esb.camel.IMessageProducer#sendSync(java.lang.String
* , java.lang.Object)
*/
@Override
public Object sendSync(String endpoint, Object message)
throws EdexException {
CamelContext camelContext = getCamelContext(endpoint);
ProducerTemplate template = getProducerTemplate(camelContext);
String uri = endpointIdUriMap.get(endpoint);
Map<String, Object> headers = getHeaders(message);
if (!started) {
throw new EdexException("Cannot send synchronous message to "
+ endpoint + " before EDEX has started");
}
String uri = getContextData().getEndpointUriForRouteId(endpoint);
try {
ProducerTemplate template = getProducerTemplateForUri(uri);
Map<String, Object> headers = getHeaders(message);
if (headers != null) {
return template.sendBodyAndHeaders(uri, ExchangePattern.OutIn,
message, headers);
} else {
return template.sendBody(uri, ExchangePattern.OutIn, message);
}
} catch (CamelExecutionException e) {
} catch (Exception e) {
throw new EdexException("Error sending synchronous message: "
+ message + " to uri: " + uri, e);
}
}
private synchronized CamelContext getCamelContext(String endpointId)
throws EdexException {
CamelContext ctx = endpointContextMap.get(endpointId);
/**
* Queues up an async message for sending to an endpoint.
*
* @param type
* @param endpoint
* @param message
* @return
*/
private boolean queueWaitingMessage(WaitingType type, String endpoint,
Object message) {
synchronized (waitingMessages) {
// make sure container hasn't started while waiting
if (!started) {
WaitingMessage wm = new WaitingMessage();
wm.type = type;
wm.dest = endpoint;
wm.msg = message;
waitingMessages.add(wm);
return true;
}
return false;
}
}
/**
* Returns the a producer template for the CamelContext this thread is
* currently a part of. If thread is not part of a context, will use context
* of the uri. If the uri is not registered in this jvm, will use the first
* context available.
*
* @return
*/
protected ProducerTemplate getProducerTemplateForUri(String uri)
throws ConfigurationException, EdexException {
CamelContext ctx = currentThreadContext.get();
if (ctx == null) {
List<CamelContext> list = getCamelContextList();
boolean found = false;
for (CamelContext c : list) {
List<Route> routes = c.getRoutes();
for (Route r : routes) {
if (r.getProperties() != null
&& endpointId.equals(r.getProperties().get(
Route.ID_PROPERTY))) {
ctx = c;
endpointContextMap.put(endpointId, ctx);
endpointIdUriMap.put(endpointId, r.getEndpoint()
.getEndpointUri());
found = true;
break;
}
}
if (found) {
break;
ContextData contextData = getContextData();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
if (typeAndName != null) {
Route route = contextData.getRouteForEndpointName(typeAndName
.getSecond());
if (route != null) {
ctx = route.getRouteContext().getCamelContext();
}
}
if (ctx == null) {
throw new EdexException("Route id " + endpointId
+ " not found. Check loaded spring configurations.");
// this jvm does not consume from this route, use first context
List<CamelContext> contexts = contextData.getContexts();
if (contexts.size() > 0) {
// should always be a context defined
ctx = contexts.iterator().next();
}
}
}
return ctx;
}
if (ctx != null) {
ProducerTemplate tmp = contextProducerMap.get(ctx);
if (tmp == null) {
tmp = ctx.createProducerTemplate();
ProducerTemplate prev = contextProducerMap
.putIfAbsent(ctx, tmp);
if ((prev != null) && (prev != tmp)) {
try {
tmp.stop();
} catch (Exception e) {
private ProducerTemplate getProducerTemplate(CamelContext ctx) {
ProducerTemplate tmp = contextProducerMap.get(ctx);
if (tmp == null) {
tmp = ctx.createProducerTemplate();
contextProducerMap.put(ctx, tmp);
}
return tmp;
}
private synchronized List<CamelContext> getCamelContextList() {
if (springContext == null) {
springContext = EDEXUtil.getSpringContext();
}
if (springContext == null) {
throw new IllegalStateException(
"Spring context has not been initialized on "
+ MessageProducer.class.getName());
}
if (camelContextList == null) {
camelContextList = new ArrayList<CamelContext>();
String[] camelContexts = springContext
.getBeanNamesForType(CamelContext.class);
for (String name : camelContexts) {
CamelContext c = (CamelContext) springContext.getBean(name);
camelContextList.add(c);
}
tmp = prev;
}
}
return tmp;
}
return camelContextList;
}
@Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
springContext = context;
}
@Override
public void sendAsyncUri(String uri, Object message) throws EdexException {
CamelContext ctx = getCamelContextList().get(0);
ProducerTemplate template = getProducerTemplate(ctx);
Map<String, Object> headers = getHeaders(message);
try {
if (headers != null) {
template.sendBodyAndHeaders(uri, ExchangePattern.InOnly,
message, headers);
} else {
template.sendBody(uri, ExchangePattern.InOnly, message);
}
} catch (CamelExecutionException e) {
throw new EdexException("Error sending asynchronous message: " + message
+ " to uri: " + uri, e);
}
throw new ConfigurationException(
"Could not find a CamelContext for routing to uri [" + uri
+ "]. Check loaded spring configurations.");
}
private Map<String, Object> getHeaders(Object message) {
@ -224,4 +298,90 @@ public class MessageProducer implements ApplicationContextAware,
return headers;
}
/**
* Sends any messages that were queued up while Camel started.
*/
protected void sendPendingAsyncMessages() {
synchronized (waitingMessages) {
for (WaitingMessage wm : waitingMessages) {
try {
switch (wm.type) {
case ID:
sendAsync(wm.dest, wm.msg);
break;
case URI:
sendAsyncUri(wm.dest, wm.msg);
break;
}
} catch (Exception e) {
statusHandler
.error("Error occurred sending startup delayed async message",
e);
}
}
}
}
/**
* Setup for use with MessageProducer to track what context the current
* operating thread is using.
*/
@Override
public Processor wrapProcessorInInterceptors(final CamelContext context,
final ProcessorDefinition<?> definition, final Processor target,
final Processor nextTarget) throws Exception {
return new AsyncProcessor() {
@Override
public void process(Exchange exchange) throws Exception {
/*
* track the thread this context is using for proper dependency
* management.
*/
MessageProducer.this.currentThreadContext.set(context);
target.process(exchange);
}
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
/*
* track the thread this context is using for proper dependency
* management.
*/
MessageProducer.this.currentThreadContext.set(context);
try {
target.process(exchange);
} catch (Throwable e) {
exchange.setException(e);
}
callback.done(true);
return true;
}
@Override
public String toString() {
return "MessageProducer - ContainerWideInterceptor[" + target
+ "]";
}
};
}
/**
* Enum for handling whether the waiting type was uri or msg.
*/
private enum WaitingType {
ID, URI
};
/**
* Inner class for handling messages sent before edex is up.
*/
private class WaitingMessage {
private WaitingType type;
private String dest;
private Object msg;
}
}

View file

@ -20,12 +20,13 @@
package com.raytheon.uf.edex.esb.camel;
import java.io.File;
import java.io.FileNotFoundException;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Performs a transform from Strings to Files
@ -38,9 +39,9 @@ import org.apache.commons.logging.LogFactory;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 1, 2008 chammack Initial creation
* 15Jul2010 6624 garmendariz Log error and interrupt if file missing
*
* Dec 1, 2008 chammack Initial creation.
* 15Jul2010 6624 garmendariz Log error and interrupt if file missing.
* Mar 19, 2014 2726 rjpeter Added debug logging of file being processed.
* </pre>
*
* @author chammack
@ -49,7 +50,8 @@ import org.apache.commons.logging.LogFactory;
public class StringToFile implements Processor {
protected transient Log logger = LogFactory.getLog(getClass());
protected final IUFStatusHandler statusHandler = UFStatus
.getHandler(StringToFile.class);
/*
* (non-Javadoc)
@ -69,12 +71,15 @@ public class StringToFile implements Processor {
// if file does not exist, set fault to interrupt processing
if (!file.exists()) {
logger.error("File does not exist : " + bodyString);
statusHandler.error("File does not exist : " + bodyString);
arg0.getOut().setFault(true);
} else {
arg0.getIn().setBody(file);
arg0.getIn().setHeader("ingestFileName", file.toString());
arg0.getIn().setHeader("dequeueTime", System.currentTimeMillis());
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.debug("Processing file: " + file.toString());
}
}
}
}

View file

@ -1,190 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import org.apache.camel.ServiceStatus;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
/**
* Dynamically starts/stops a context and its associated routes so that only one
* context in the cluster is running. This should mainly be used for reading
* from topics so that only box is processing the topic data in the cluster for
* singleton type events.
*
* <pre>
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 10, 2010 5050 rjpeter Initial creation
* Jul 16, 2012 DR 15073 D. Friedman Stop consumers instead of whole context
* May 14, 2013 1989 njensen Camel 2.11 compatibility
* Aug 26, 2013 DR 2272 bkowal Append an optional suffix to the cluster task details
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ClusteredContextManager {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ClusteredContextManager.class);
private static final String taskName = "ClusteredContext";
private String myName;
private List<CamelContext> clusteredContextList = new ArrayList<CamelContext>();
private int timeOutMillis;
private static ClusteredContextManager instance = new ClusteredContextManager();
public static ClusteredContextManager getInstance() {
return instance;
}
private ClusteredContextManager() {
myName = getHostName() + ":" + System.getProperty("edex.run.mode");
}
private static String getHostName() {
String hostname = System.getenv("HOSTNAME");
if (hostname == null) {
hostname = System.getenv("COMPUTERNAME");
}
if (hostname == null) {
hostname = System.getenv("HOST");
}
if (hostname == null) {
try {
Enumeration<NetworkInterface> nis = NetworkInterface
.getNetworkInterfaces();
while (nis.hasMoreElements()) {
NetworkInterface ni = nis.nextElement();
ni.isVirtual();
ni.isUp();
Enumeration<InetAddress> addrs = ni.getInetAddresses();
while (addrs.hasMoreElements()) {
InetAddress addr = addrs.nextElement();
if (addr.isLinkLocalAddress() == false
&& addr.isSiteLocalAddress() == false
&& addr.isLoopbackAddress() == false) {
hostname = addr.getHostName();
}
}
}
} catch (SocketException e) {
statusHandler.handle(Priority.ERROR,
"Failed to determine hostname", e);
}
}
return hostname;
}
public void checkClusteredContexts() {
String suffix = ClusterLockUtils.CLUSTER_SUFFIX;
for (CamelContext camelContext : clusteredContextList) {
String contextName = camelContext.getName() + suffix;
ClusterTask lock = ClusterLockUtils.lock(taskName, contextName,
myName, timeOutMillis, false);
boolean activateRoute = false;
switch (lock.getLockState()) {
case ALREADY_RUNNING:
// check if we already have lock
activateRoute = lock.getExtraInfo().equals(myName);
break;
case SUCCESSFUL:
activateRoute = true;
break;
default:
}
try {
if (activateRoute) {
ClusterLockUtils.updateLockTime(taskName, contextName,
System.currentTimeMillis());
for (Route route : camelContext.getRoutes()) {
String routeId = route.getId();
ServiceStatus status = camelContext
.getRouteStatus(routeId);
if (status == ServiceStatus.Stopped
|| status == ServiceStatus.Stopping) {
camelContext.startRoute(routeId);
} else if (status == ServiceStatus.Suspended
|| status == ServiceStatus.Suspending) {
camelContext.resumeRoute(routeId);
}
}
} else {
for (Route route : camelContext.getRoutes()) {
String routeId = route.getId();
ServiceStatus status = camelContext
.getRouteStatus(routeId);
if (status == ServiceStatus.Started
|| status == ServiceStatus.Starting) {
// CamelContext API says to use suspend, not stop
camelContext.suspendRoute(routeId);
}
}
}
} catch (Exception e) {
StringBuilder msg = new StringBuilder();
msg.append("Failed to ");
if (activateRoute) {
msg.append("start ");
} else {
msg.append("suspend ");
}
msg.append("context ");
msg.append(camelContext.getName());
statusHandler.handle(Priority.ERROR, msg.toString(), e);
}
}
}
public ClusteredContextManager register(CamelContext context) {
clusteredContextList.add(context);
return this;
}
public int getTimeOutMillis() {
return timeOutMillis;
}
public void setTimeOutMillis(int timeOutMillis) {
this.timeOutMillis = timeOutMillis;
}
}

View file

@ -0,0 +1,144 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.concurrent.ExecutorService;
import org.apache.camel.CamelContext;
import com.raytheon.uf.common.util.SystemUtil;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
/**
* Implementation of {@link IContextStateManager} that handles clustered
* contexts. Extends {@code DependencyContextStateManager} to allow for
* clustered contexts to work with dependencies also.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ClusteredContextStateManager extends DependencyContextStateManager {
/**
* Name field for cluster task.
*/
private static final String taskName = "ClusteredContext";
/**
* Field for extra-info to designate this host.
*/
private final String myName;
/**
* Constructor that takes an {@code ExecutorService}. The
* {@code ExecutorService} is used for starting/stopping dependent contexts.
*
* @param service
*/
public ClusteredContextStateManager(ExecutorService service) {
super(service);
myName = SystemUtil.getHostName() + ":"
+ System.getProperty("edex.run.mode");
}
/**
* Get the {@code ClusterLock} details field.
*
* @param context
* @return
*/
protected static String getLockDetails(CamelContext context) {
return context.getName() + ClusterLockUtils.CLUSTER_SUFFIX;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.DependencyContextStateManager#
* isContextStartable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStartable(CamelContext context) throws Exception {
boolean canStartContext = super.isContextStartable(context);
/*
* Check cluster lock if we can start the context or if context is
* already started in case we need to update the cluster lock.
*/
if (canStartContext || context.getStatus().isStarted()) {
ClusterTask lock = ClusterLockUtils.lock(taskName,
getLockDetails(context), myName, ContextManager
.getInstance().getTimeOutMillis(), false);
switch (lock.getLockState()) {
case ALREADY_RUNNING:
// check if we already have lock
canStartContext = lock.getExtraInfo().equals(myName);
if (canStartContext) {
// update the lock time
ClusterLockUtils
.updateLockTime(taskName, getLockDetails(context),
System.currentTimeMillis());
}
break;
case SUCCESSFUL:
canStartContext = true;
break;
default:
canStartContext = false;
}
}
return canStartContext;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.DependencyContextStateManager#
* stopContext(org.apache.camel.CamelContext)
*/
@Override
public boolean stopContext(CamelContext context) throws Exception {
// on stop, unlock the cluster lock if we own it
String contextName = context.getName()
+ ClusterLockUtils.CLUSTER_SUFFIX;
ClusterTask lock = ClusterLockUtils.lookupLock(taskName, contextName);
if (lock.getExtraInfo().equals(myName) && lock.isRunning()) {
ClusterLockUtils.unlock(taskName, contextName);
}
return super.stopContext(context);
}
}

View file

@ -0,0 +1,222 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.ConfigurationException;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.core.EdexException;
/**
* Contains all known contexts and parsed data about the contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ContextData {
private final List<CamelContext> contexts;
private final Map<String, Route> consumerRouteMapping;
private final Map<String, String> routeIdUriMapping;
/**
* Pulls the direct-vm:name, vm:name, queue:name, topic:name section from
* the endpoint URI.
*/
private static final Pattern endpointUriParsePattern = Pattern
.compile("([^:]+)://([^?]+)");
/**
* Parses passed contexts for route and endpoint data about all contexts.
*
* @param contexts
* @throws ConfigurationException
*/
public ContextData(List<CamelContext> contexts)
throws ConfigurationException {
this.contexts = Collections.unmodifiableList(contexts);
this.consumerRouteMapping = Collections
.unmodifiableMap(generateRouteMappings(this.contexts));
Map<String, String> idUriMapping = new HashMap<String, String>(
consumerRouteMapping.size(), 1);
for (Route route : consumerRouteMapping.values()) {
idUriMapping.put(route.getId(), route.getEndpoint()
.getEndpointUri());
}
this.routeIdUriMapping = Collections.unmodifiableMap(idUriMapping);
}
/**
* Populates an endpointName to {@code Route} mapping for the passed
* {@code CamelContext}s.
*
* @return
* @throws ConfigurationException
*/
protected static Map<String, Route> generateRouteMappings(
List<CamelContext> contexts) throws ConfigurationException {
Map<String, Route> routeMapping = new HashMap<String, Route>(
contexts.size() * 2, 1);
// populate the consumer definitions
for (CamelContext context : contexts) {
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = getEndpointTypeAndName(uri);
if (typeAndName != null) {
String endpointName = typeAndName.getSecond();
Route prev = routeMapping.put(endpointName, route);
if (prev != null) {
throw new ConfigurationException(
"Two contexts listen to the same endpoint name ["
+ endpointName
+ "]. ContextManager cannot handle this situation. Double check configuration. Conflicting contexts ["
+ prev.getRouteContext()
.getCamelContext()
.getName() + "] and ["
+ context.getName() + "]");
}
}
}
}
}
return routeMapping;
}
/**
* Returns the known contexts.
*
* @return
*/
public List<CamelContext> getContexts() {
return contexts;
}
/**
* Parses URI for component type and endpoint name.
*
* @param uri
* @return
*/
public static Pair<String, String> getEndpointTypeAndName(String uri) {
Pair<String, String> rval = null;
Matcher m = endpointUriParsePattern.matcher(uri);
if (m.find()) {
String endpointType = m.group(1);
String endpointName = m.group(2);
rval = new Pair<String, String>(endpointType, endpointName);
}
return rval;
}
/**
* Scans the camel context and associated routes. Groups the routes by
* consumer type.
*
* @return
*/
public Map<String, List<Route>> getContextRoutesByEndpointType()
throws ConfigurationException {
Map<String, List<Route>> routesByType = new HashMap<String, List<Route>>();
for (CamelContext context : contexts) {
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = getEndpointTypeAndName(uri);
String type = typeAndName.getFirst();
List<Route> routesForType = routesByType.get(type);
if (routesForType == null) {
routesForType = new LinkedList<Route>();
routesByType.put(type, routesForType);
}
routesForType.add(route);
}
}
}
return routesByType;
}
/**
* Returns the uri for the consumer endpoint of the route with the specified
* routeId.
*
* @param routeId
* @return
* @throws EdexException
*/
public String getEndpointUriForRouteId(String routeId) throws EdexException {
String uri = routeIdUriMapping.get(routeId);
if (uri == null) {
throw new EdexException("Route id " + routeId
+ " not found. Check loaded spring configurations.");
}
return uri;
}
/**
* Returns the route for the endpoint with the passed name as returned from
* getEndpointTypeAndName().
*
* @param endpointName
* @return
* @throws EdexException
*/
public Route getRouteForEndpointName(String endpointName)
throws EdexException {
Route route = consumerRouteMapping.get(endpointName);
if (route == null) {
throw new EdexException("Endpoint " + endpointName
+ " not found. Check loaded spring configurations.");
}
return route;
}
}

View file

@ -0,0 +1,268 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.ConfigurationException;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Route;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.Pair;
/**
* Contains context dependency mappings.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 26, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ContextDependencyMapping {
/**
* Endpoint types that should be tracked for dependency mapping
*/
protected static final Set<String> DEPENDENCY_ENDPOINT_TYPES;
static {
/*
* Endpoint types that are used for inner context routing. If we add
* other inner jvm routing types, they should be added here.
*/
Set<String> types = new HashSet<String>(8);
types.add("vm");
types.add("direct-vm");
types.add("seda");
types.add("jmx");
types.add("guava-eventbus");
DEPENDENCY_ENDPOINT_TYPES = Collections.unmodifiableSet(types);
}
/**
* The dependency mappings.
*/
protected final Map<CamelContext, DependencyNode> dependencyMapping;
/**
* Populates the dependency mappings for all camel contexts.
* {@code suppressExceptions} can be used to differentiate between
* startup/shutdown conditions to allow the map to be populated regardless
* of detected issues.
*
* @param contextData
* @param suppressExceptions
* @throws ConfigurationException
*/
public ContextDependencyMapping(ContextData contextData,
boolean suppressExceptions) throws ConfigurationException {
dependencyMapping = Collections
.unmodifiableMap(populateDependencyMapping(contextData,
suppressExceptions));
}
/**
* Returns a {@code IUFStatusHandler}. Not cached as rarely used.
*
* @return
*/
private static IUFStatusHandler getHandler() {
return UFStatus.getHandler(ContextDependencyMapping.class);
}
/**
* Dependency mappings per context. The dependency mapping is only for
* internal vm types that have a direct dependency. Indirect dependency via
* a JMS queue for example is not returned/enforced.
*
* @param contextData
* @param suppressExceptions
* Done in a shutdown scenario to get the dependencyMapping as
* close as possible.
*/
protected static Map<CamelContext, DependencyNode> populateDependencyMapping(
ContextData contextData, boolean suppressExceptions)
throws ConfigurationException {
List<CamelContext> contexts = contextData.getContexts();
Map<CamelContext, DependencyNode> dependencyMapping = new LinkedHashMap<CamelContext, DependencyNode>(
contexts.size());
// set up dependency nodes for internal types
Map<String, CamelContext> consumesFrom = new HashMap<String, CamelContext>();
Map<String, List<CamelContext>> producesTo = new HashMap<String, List<CamelContext>>();
Set<String> consumers = new HashSet<String>();
// scan for consuming and producing internal endpoints
for (CamelContext context : contexts) {
dependencyMapping.put(context, new DependencyNode(context));
consumers.clear();
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
if ((typeAndName != null)
&& DEPENDENCY_ENDPOINT_TYPES.contains(typeAndName
.getFirst())) {
String endpointName = typeAndName.getSecond();
consumers.add(endpointName);
/*
* Internal types don't support a fanout type policy
* where multiple routes can listen to the same
* endpoint.
*/
CamelContext prev = consumesFrom.put(endpointName,
context);
if (prev != null) {
String msg = "Two contexts listen to the same internal endpoint ["
+ endpointName
+ "]. ContextManager cannot handle this situation. Double check configuration. Conflicting contexts ["
+ prev.getName()
+ "] and ["
+ context.getName() + "]";
if (suppressExceptions) {
getHandler().error(msg);
} else {
throw new ConfigurationException(msg);
}
}
}
}
}
Collection<Endpoint> endpoints = context.getEndpoints();
if ((endpoints != null) && (endpoints.size() > 0)) {
for (Endpoint ep : endpoints) {
String uri = ep.getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
if ((typeAndName != null)
&& DEPENDENCY_ENDPOINT_TYPES.contains(typeAndName
.getFirst())) {
String endpointName = typeAndName.getSecond();
if (!consumers.contains(endpointName)) {
List<CamelContext> producerCtxs = producesTo
.get(endpointName);
if (producerCtxs == null) {
producerCtxs = new LinkedList<CamelContext>();
producesTo.put(endpointName, producerCtxs);
}
producerCtxs.add(context);
}
}
}
}
}
// setup dependencies for internal routes
for (Map.Entry<String, List<CamelContext>> producersEntry : producesTo
.entrySet()) {
String endpoint = producersEntry.getKey();
CamelContext consumer = consumesFrom.get(endpoint);
List<CamelContext> producers = producersEntry.getValue();
if (consumer == null) {
StringBuilder msg = new StringBuilder(200);
msg.append("Internal Routing Endpoint [")
.append(endpoint)
.append("] has no defined consumers. This is endpoint is used in contexts [");
Iterator<CamelContext> producerIter = producers.iterator();
while (producerIter.hasNext()) {
CamelContext producer = producerIter.next();
msg.append(producer.getName());
if (producerIter.hasNext()) {
msg.append(", ");
}
}
msg.append("]");
if (suppressExceptions) {
getHandler().error(msg.toString());
} else {
throw new ConfigurationException(msg.toString());
}
} else {
DependencyNode consumerNode = dependencyMapping.get(consumer);
for (CamelContext producer : producers) {
DependencyNode producerNode = dependencyMapping
.get(producer);
consumerNode.addDependentNode(producerNode);
}
}
}
return dependencyMapping;
}
/**
* Get the contexts that depend upon the passed context to work. If the
* passed context is unknown null will be returned.
*
* @param context
* @return
*/
public Set<CamelContext> getDependentContexts(CamelContext context) {
DependencyNode dNode = dependencyMapping.get(context);
if (dNode == null) {
return null;
}
return dNode.getDependentContexts();
}
/**
* Get the contexts that the passed context requires to be running to work.
* If the passed context is unknown null will be returned.
*
* @param context
* @return
*/
public Set<CamelContext> getRequiredContexts(CamelContext context) {
DependencyNode dNode = dependencyMapping.get(context);
if (dNode == null) {
return null;
}
return dNode.getRequiredContexts();
}
}

View file

@ -1,96 +1,587 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.naming.ConfigurationException;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import org.apache.camel.impl.DefaultCamelContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.core.IContextStateProcessor;
/**
* Dynamically starts/stops a context and its associated routes so that only one
* context in the cluster is running. This should mainly be used for reading
* from topics so that only box is processing the topic data in the cluster for
* singleton type events.
* Tracks all contexts and is used to auto determine context dependencies and
* start/stop them in the right order. Dynamically starts/stops a clustered
* context and its associated routes so that only one context in the cluster is
* running. This should mainly be used for reading from topics so that only box
* is processing the topic data in the cluster for singleton type events.
*
* <pre>
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 10, 2010 5050 rjpeter Initial creation
* May 13, 2013 1989 njensen Camel 2.11 compatibility
* Nov 10, 2010 5050 rjpeter Initial creation.
* May 13, 2013 1989 njensen Camel 2.11 compatibility.
* Mar 11, 2014 2726 rjpeter Implemented graceful shutdown.
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class ContextManager {
public class ContextManager implements ApplicationContextAware,
BeanFactoryPostProcessor {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ContextManager.class);
private List<CamelContext> contextList = new ArrayList<CamelContext>();
private static ContextManager instance = new ContextManager();
/**
* Service used for start up and shut down threading.
*/
private final ExecutorService service = Executors.newCachedThreadPool();
private final Set<CamelContext> clusteredContexts = new HashSet<CamelContext>();
/**
* State Manager for all contexts that are not clustered.
*/
private final IContextStateManager defaultStateManager = new DependencyContextStateManager(
service);
/**
* State Manager used for all clustered contexts.
*/
private final IContextStateManager clusteredStateManager = new ClusteredContextStateManager(
service);
/**
* Spring context. Set by the spring container after bean construction.
*/
private ApplicationContext springCtx = null;
/**
* Endpoint types that are internal only. Mainly used at shutdown time to
* designate routes that shouldn't be shutdown immediately.
*/
private final Set<String> internalEndpointTypes = new HashSet<String>();
/**
* Map of context processors that have been registered for a given context.
* Used to allow contexts to do custom worn on startup/shutdown.
*/
private final Map<CamelContext, IContextStateProcessor> contextProcessors = new HashMap<CamelContext, IContextStateProcessor>();
/**
* Cluster lock timeout for clustered contexts.
*/
private int timeOutMillis;
/**
* Parsed context data for all contexts known in the spring container.
*/
private volatile ContextData contextData;
/**
* Flag to control shutting down the jvm. This handles shutdown being called
* during startup to short circuit startup.
*/
private final AtomicBoolean shuttingDown = new AtomicBoolean(false);
/**
* Dependency mappings for all camel contexts in the spring container. This
* should only be changed in a sync block. Otherwise mark as volatile.
*/
private ContextDependencyMapping dependencyMapping = null;
/**
* Last time dependency mapping was generated. Used to periodically
* regenerate the dependency mappings.
*/
private final long lastDependencyTime = 0;
public static ContextManager getInstance() {
return instance;
}
/**
* Private constructor. Sets up internal types for prioritized stopping of
* routes on shutdown.
*/
private ContextManager() {
internalEndpointTypes
.addAll(ContextDependencyMapping.DEPENDENCY_ENDPOINT_TYPES);
internalEndpointTypes.add("timer");
internalEndpointTypes.add("quartz");
internalEndpointTypes.add("clusteredquartz");
}
/**
* Gets the context data.
*
* @return
* @throws ConfigurationException
*/
public ContextData getContextData() throws ConfigurationException {
if (contextData == null) {
synchronized (this) {
if (contextData == null) {
contextData = new ContextData(new ArrayList<CamelContext>(
springCtx.getBeansOfType(CamelContext.class)
.values()));
}
}
}
return contextData;
}
/**
* Get the {@link IContextStateManager} for the passed {@code CamelContext}.
*
* @param context
* @return
*/
protected IContextStateManager getStateManager(CamelContext context) {
if (clusteredContexts.contains(context)) {
return clusteredStateManager;
}
return defaultStateManager;
}
/**
* Get the {@link IContextStateProcessor} for the passed
* {@code CamelContext}.
*
* @param context
* @return
*/
public IContextStateProcessor getStateProcessor(CamelContext context) {
return contextProcessors.get(context);
}
/**
* Get the {@link ContextDependencyMapping} for all contexts.
*
* @param suppressExceptions
* @return
* @throws ConfigurationException
*/
public ContextDependencyMapping getDependencyMapping(
boolean suppressExceptions) throws ConfigurationException {
/*
* This is not permanently cashed and regenerated periodically since
* routing via code can change at runtime.
*/
synchronized (this) {
long millis = System.currentTimeMillis();
if ((dependencyMapping == null)
|| (millis > (lastDependencyTime + TimeUtil.MILLIS_PER_MINUTE))) {
dependencyMapping = new ContextDependencyMapping(
getContextData(), suppressExceptions);
}
}
return dependencyMapping;
}
/**
* Starts all routes for all contexts. If a route fails to start the entire
* jvm will be shutdown.
*/
public void startContexts() {
statusHandler.info("Context Manager starting routes");
for (CamelContext camelContext : contextList) {
statusHandler.info("Context Manager starting contexts");
try {
ContextData cxtData = getContextData();
List<Future<Pair<CamelContext, Boolean>>> callbacks = new LinkedList<Future<Pair<CamelContext, Boolean>>>();
for (final CamelContext context : cxtData.getContexts()) {
final IContextStateManager stateManager = getStateManager(context);
if (stateManager.isContextStartable(context)) {
/*
* Have the ExecutorService start the context to allow for
* quicker startup.
*/
callbacks
.add(service
.submit(new Callable<Pair<CamelContext, Boolean>>() {
@Override
public Pair<CamelContext, Boolean> call()
throws Exception {
boolean rval = false;
try {
rval = stateManager
.startContext(context);
if (!rval) {
statusHandler.error("Context ["
+ context.getName()
+ "] failed to start, shutting down");
System.exit(1);
}
} catch (Throwable e) {
statusHandler.fatal(
"Error occurred starting context: "
+ context
.getName(),
e);
System.exit(1);
}
return new Pair<CamelContext, Boolean>(
context, rval);
}
}));
}
}
/*
* Double check call backs that everything started successfully. If
* some did not start successfully, force shutdown.
*/
for (Future<Pair<CamelContext, Boolean>> callback : callbacks) {
Pair<CamelContext, Boolean> val = callback.get();
if (!val.getSecond().booleanValue()) {
statusHandler.error("Context [" + val.getFirst().getName()
+ "] failed to start, shutting down");
System.exit(1);
}
}
} catch (Throwable e) {
statusHandler.fatal(
"Error occurred starting contexts, shutting down", e);
System.exit(1);
}
}
/**
* Register a clustered context that is meant to run as a singleton in the
* cluster.
*
* @param context
* @return
*/
public ContextManager registerClusteredContext(final CamelContext context) {
clusteredContexts.add(context);
return this;
}
/**
* Register a context state processor to be called on start/stop of the
* context.
*
* @param context
* @param processor
* @return
*/
public ContextManager registerContextStateProcessor(
final CamelContext context, final IContextStateProcessor processor) {
contextProcessors.put(context, processor);
return this;
}
/**
* Stops all contexts. Note this method can only be called once for the life
* of the jvm and will gracefully shut down all of camel.
*/
public void stopContexts() {
/*
* flag to ensure no one else runs shutdown also stops
* checkClusteredContext from starting contexts once shutdown has been
* initiated
*/
if (shuttingDown.compareAndSet(false, true)) {
if (springCtx == null) {
statusHandler
.info("Spring Context not set. Start up never completed, cannot orderly shutdown");
}
statusHandler.info("Context Manager stopping routes");
try {
/*
* In camel 2.11, all contexts are "started" automatically but
* the isAutoStartup() flag determines if the routes are
* automatically started. The code in DefaultCamelContext is
* safe to call start() on a second time to get the routes
* started.
*
* For more information, see:
* http://camel.465427.n5.nabble.com/Camel
* -context-autostartup-td5721638.html
*
* https://issues.apache.org/jira/browse/CAMEL-5759
* begin immediate shutdown of routes that are not an internal
* type
*/
if (!camelContext.isAutoStartup()) {
camelContext.start();
LinkedList<Route> routesToStop = new LinkedList<Route>();
ContextData ctxData = getContextData();
List<CamelContext> contexts = ctxData.getContexts();
List<Future<Pair<CamelContext, Boolean>>> callbacks = new LinkedList<Future<Pair<CamelContext, Boolean>>>();
for (final CamelContext context : contexts) {
/*
* group routes by context due to sync lock at context level
* for stopping a route
*/
List<Route> routes = context.getRoutes();
if ((routes != null) && (routes.size() > 0)) {
for (Route route : routes) {
String uri = route.getEndpoint().getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
String type = typeAndName.getFirst();
if (!internalEndpointTypes.contains(type)) {
routesToStop.add(route);
}
}
}
if (routesToStop.size() > 0) {
final IContextStateManager stateMgr = getStateManager(context);
final List<Route> tmp = routesToStop;
callbacks
.add(service
.submit(new Callable<Pair<CamelContext, Boolean>>() {
@Override
public Pair<CamelContext, Boolean> call()
throws Exception {
boolean rval = true;
for (Route route : tmp) {
try {
statusHandler.info("Stopping route ["
+ route.getId()
+ "]");
rval &= stateMgr
.stopRoute(route);
} catch (Exception e) {
statusHandler.error(
"Error occurred closing route: "
+ route.getId(),
e);
}
}
return new Pair<CamelContext, Boolean>(
context, rval);
}
}));
routesToStop = new LinkedList<Route>();
}
}
} catch (Exception e) {
statusHandler.handle(Priority.ERROR,
"Failed to start routes for " + camelContext.getName(),
e);
List<CamelContext> failures = waitForCallbacks(callbacks,
"Waiting for external routes to shutdown: ", 1000);
for (CamelContext failure : failures) {
statusHandler.error("Context [" + failure.getName()
+ "] has routes that failed to stop");
}
statusHandler.info("Shutting down contexts");
for (final CamelContext context : contexts) {
final IContextStateManager stateManager = getStateManager(context);
if (stateManager.isContextStoppable(context)) {
callbacks
.add(service
.submit(new Callable<Pair<CamelContext, Boolean>>() {
@Override
public Pair<CamelContext, Boolean> call()
throws Exception {
boolean rval = false;
try {
statusHandler.info("Stopping context ["
+ context.getName()
+ "]");
rval = stateManager
.stopContext(context);
if (!rval) {
statusHandler.error("Context ["
+ context
.getName()
+ "] failed to stop");
}
} catch (Throwable e) {
statusHandler.fatal(
"Error occurred stopping context: "
+ context
.getName(),
e);
}
return new Pair<CamelContext, Boolean>(
context, rval);
}
}));
}
}
failures = waitForCallbacks(callbacks,
"Waiting for contexts to shutdown: ", 1000);
for (CamelContext failure : failures) {
statusHandler.error("Context [" + failure.getName()
+ "] had a failure trying to stop");
}
} catch (Throwable e) {
statusHandler.fatal("Error occurred during shutdown", e);
}
}
}
public ContextManager register(CamelContext context) {
contextList.add(context);
return this;
/**
* Waits for all callbacks to finish printing a periodic message with number
* of remaining callbacks. Returns a list of contexts that had a failure
* status.
*
* @param callbacks
* @param message
* @param sleepInterval
* @return
*/
private static List<CamelContext> waitForCallbacks(
List<Future<Pair<CamelContext, Boolean>>> callbacks,
String message, long sleepInterval) {
statusHandler.info(message + callbacks.size() + " remaining");
List<CamelContext> failures = new LinkedList<CamelContext>();
while (!callbacks.isEmpty()) {
boolean foundOne = false;
Iterator<Future<Pair<CamelContext, Boolean>>> callbackIter = callbacks
.iterator();
while (callbackIter.hasNext()) {
Future<Pair<CamelContext, Boolean>> callback = callbackIter
.next();
if (callback.isDone()) {
foundOne = true;
callbackIter.remove();
try {
Pair<CamelContext, Boolean> val = callback.get();
if (!val.getSecond().booleanValue()) {
failures.add(val.getFirst());
}
} catch (Exception e) {
statusHandler.error("Failure in callback task", e);
}
}
}
if (!foundOne) {
statusHandler.info(message + callbacks.size() + " remaining");
try {
Thread.sleep(sleepInterval);
} catch (Exception e) {
// ignore
}
}
}
return failures;
}
/**
* Checks the clustered contexts. If context is not running in the cluster
* the context will be started.
*/
public void checkClusteredContexts() {
if (!shuttingDown.get()) {
for (CamelContext camelContext : clusteredContexts) {
boolean activateRoute = true;
try {
IContextStateManager stateManager = getStateManager(camelContext);
if (stateManager.isContextStartable(camelContext)) {
stateManager.startContext(camelContext);
} else if (stateManager.isContextStoppable(camelContext)) {
activateRoute = false;
stateManager.stopContext(camelContext);
}
} catch (Exception e) {
StringBuilder msg = new StringBuilder();
msg.append("Failed to ");
if (activateRoute) {
msg.append("start ");
} else {
msg.append("stop ");
}
msg.append("context ");
msg.append(camelContext.getName());
statusHandler.handle(Priority.ERROR, msg.toString(), e);
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
springCtx = context;
}
public int getTimeOutMillis() {
return timeOutMillis;
}
public void setTimeOutMillis(int timeOutMillis) {
this.timeOutMillis = timeOutMillis;
}
public boolean isShuttingDown() {
return shuttingDown.get();
}
/**
* Update all camel beans to have autoStartup to false and handles quart
* workaround when JMX is disabled.
*/
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (CamelContext ctx : beanFactory.getBeansOfType(CamelContext.class)
.values()) {
ctx.setAutoStartup(false);
if ((ctx instanceof DefaultCamelContext)
&& (ctx.getManagementName() == null)) {
((DefaultCamelContext) ctx).setManagementName(ctx.getName());
}
}
}
}

View file

@ -0,0 +1,215 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.EnumSet;
import java.util.Set;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
import org.apache.camel.ServiceStatus;
import com.raytheon.uf.edex.core.IContextStateProcessor;
/**
* Implementation of IContextStateManager that does basic validation of context
* status as well as handling IContextStateProcessor for startup/shutdown of
* contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class DefaultContextStateManager implements IContextStateManager {
private static final Set<ServiceStatus> STARTABLE_STATES = EnumSet.of(
ServiceStatus.Stopped, ServiceStatus.Suspended,
ServiceStatus.Suspending);
private static final Set<ServiceStatus> SUSPENDABLE_STATES = EnumSet.of(
ServiceStatus.Starting, ServiceStatus.Started);
private static final Set<ServiceStatus> STOPPABLE_STATES = EnumSet.of(
ServiceStatus.Starting, ServiceStatus.Started,
ServiceStatus.Suspending, ServiceStatus.Suspended);
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.IContextStateManager#
* isContextStartable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStartable(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
return STARTABLE_STATES.contains(status)
|| (status.isStarted() && !context.isAutoStartup());
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#startContext
* (org.apache.camel.CamelContext)
*/
@Override
public boolean startContext(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
boolean rval = status.isStarted();
if (rval && !context.isAutoStartup()) {
for (Route route : context.getRoutes()) {
rval &= context.getRouteStatus(route.getId()).isStarted();
}
}
if (!rval) {
IContextStateProcessor processor = ContextManager.getInstance()
.getStateProcessor(context);
if (processor != null) {
processor.preStart();
}
context.start();
rval = context.getStatus().isStarted();
/*
* if a context has autoStartup = false, all of its routes are
* started on the second time context.start is called, adding route
* check for future proofing just in case.
*/
if (!context.isAutoStartup()) {
for (Route route : context.getRoutes()) {
rval &= startRoute(route);
}
/*
* clear the auto start up flag since its an initial condition
* only
*/
context.setAutoStartup(true);
}
if (processor != null) {
processor.postStart();
}
}
return rval;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#startRoute
* (org.apache.camel.Route)
*/
@Override
public boolean startRoute(Route route) throws Exception {
String routeId = route.getId();
CamelContext ctx = route.getRouteContext().getCamelContext();
ServiceStatus status = ctx.getRouteStatus(routeId);
if (STARTABLE_STATES.contains(status)) {
ctx.startRoute(routeId);
status = ctx.getRouteStatus(routeId);
}
return status.isStarted();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.IContextStateManager#
* isContextStoppable (org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStoppable(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
boolean shuttingDown = ContextManager.getInstance().isShuttingDown();
return (shuttingDown && STOPPABLE_STATES.contains(status))
|| (!shuttingDown && SUSPENDABLE_STATES.contains(status));
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#stopContext
* (org.apache.camel.CamelContext)
*/
@Override
public boolean stopContext(CamelContext context) throws Exception {
ServiceStatus status = context.getStatus();
if (isContextStoppable(context)) {
IContextStateProcessor processor = ContextManager.getInstance()
.getStateProcessor(context);
if (processor != null) {
processor.preStop();
}
// a context will automatically stop all its routes
if (ContextManager.getInstance().isShuttingDown()) {
context.stop();
} else {
context.suspend();
}
if (processor != null) {
processor.postStop();
}
status = context.getStatus();
}
return status.isStopped();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.IContextStateManager#stopRoute
* (org.apache.camel.Route)
*/
@Override
public boolean stopRoute(Route route) throws Exception {
String routeId = route.getId();
CamelContext ctx = route.getRouteContext().getCamelContext();
ServiceStatus status = ctx.getRouteStatus(routeId);
if (STOPPABLE_STATES.contains(status)) {
ctx.stopRoute(routeId);
status = ctx.getRouteStatus(routeId);
}
return status.isStopped();
}
}

View file

@ -0,0 +1,229 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
/**
* Implementation of IContextStateManager that handles dependencies between
* contexts so that contexts start/stop in the correct order. Can be given an
* ExecutorService to use to start/stop dependent contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class DependencyContextStateManager extends DefaultContextStateManager {
/**
* Service to use to start/stop dependent contexts. If null, context
* processing will happen on current thread.
*/
protected final ExecutorService service;
public DependencyContextStateManager() {
this(null);
}
public DependencyContextStateManager(ExecutorService service) {
this.service = service;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#
* isContextStartable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStartable(CamelContext context) throws Exception {
if (!super.isContextStartable(context)) {
return false;
}
Set<CamelContext> requiredContexts = ContextManager.getInstance()
.getDependencyMapping(false).getRequiredContexts(context);
if (requiredContexts != null) {
for (CamelContext rContext : requiredContexts) {
if (!rContext.getStatus().isStarted()) {
return false;
} else {
for (Route rRoute : rContext.getRoutes()) {
if (!rContext.getRouteStatus(rRoute.getId())
.isStarted()) {
return false;
}
}
}
}
}
return true;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#
* startContext(org.apache.camel.CamelContext)
*/
@Override
public boolean startContext(CamelContext context) throws Exception {
boolean rval = super.startContext(context);
ContextManager ctxMgr = ContextManager.getInstance();
if (rval) {
Set<CamelContext> dContexts = ctxMgr.getDependencyMapping(false)
.getDependentContexts(context);
if (dContexts != null) {
List<Future<Boolean>> callbacks = null;
for (final CamelContext dCtx : dContexts) {
final IContextStateManager stateMgr = ctxMgr
.getStateManager(dCtx);
if (stateMgr.isContextStartable(dCtx)) {
if (service != null) {
if (callbacks == null) {
callbacks = new LinkedList<Future<Boolean>>();
}
callbacks.add(service
.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return stateMgr.startContext(dCtx);
}
}));
} else {
stateMgr.startContext(dCtx);
}
}
}
if (callbacks != null) {
for (Future<Boolean> callback : callbacks) {
rval &= callback.get().booleanValue();
}
}
}
}
return rval;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#
* isContextStoppable(org.apache.camel.CamelContext)
*/
@Override
public boolean isContextStoppable(CamelContext context) throws Exception {
if (!super.isContextStoppable(context)) {
return false;
}
Set<CamelContext> dContexts = ContextManager.getInstance()
.getDependencyMapping(true).getDependentContexts(context);
if (dContexts != null) {
for (CamelContext dContext : dContexts) {
/*
* only need to check if the context has stopped, can't have a
* stopped context with started routes.
*/
if (!dContext.getStatus().isStopped()) {
return false;
}
}
}
return true;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.esb.camel.context.DefaultContextStateManager#stopContext
* (org.apache.camel.CamelContext)
*/
@Override
public boolean stopContext(CamelContext context) throws Exception {
boolean rval = super.stopContext(context);
ContextManager ctxMgr = ContextManager.getInstance();
if (rval) {
Set<CamelContext> rContexts = ctxMgr.getDependencyMapping(true)
.getRequiredContexts(context);
if (rContexts != null) {
List<Future<Boolean>> callbacks = null;
for (final CamelContext rCtx : rContexts) {
final IContextStateManager stateMgr = ctxMgr
.getStateManager(rCtx);
if (stateMgr.isContextStoppable(rCtx)) {
if (service != null) {
if (callbacks == null) {
callbacks = new LinkedList<Future<Boolean>>();
}
callbacks.add(service
.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return stateMgr.stopContext(rCtx);
}
}));
} else {
stateMgr.stopContext(rCtx);
}
}
}
if (callbacks != null) {
for (Future<Boolean> callback : callbacks) {
rval &= callback.get().booleanValue();
}
}
}
}
return rval;
}
}

View file

@ -0,0 +1,145 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import java.util.HashSet;
import java.util.Set;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Route;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.Pair;
/**
* Class to map a context to its required and dependent contexts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public class DependencyNode {
private final CamelContext context;
/**
* Contexts required by this context.
*/
private final Set<CamelContext> requiredContexs = new HashSet<CamelContext>();
/**
* Contexts that depend on this context.
*/
private final Set<CamelContext> dependentContexts = new HashSet<CamelContext>();
public DependencyNode(CamelContext context) {
this.context = context;
}
/**
* Add a node who is dependent on this node. Applies linking in both
* directions.
*
* @param dNode
*/
public void addDependentNode(DependencyNode dNode) {
if (!requiredContexs.contains(dNode.context)) {
dependentContexts.add(dNode.context);
dNode.requiredContexs.add(context);
} else {
StringBuilder msg = new StringBuilder(300);
msg.append("Circular CamelContext dependency detected between ")
.append(context.getName())
.append(" and ")
.append(dNode.context.getName())
.append(". Removing dependency, startup/shutdown may be incorrect, verify configuration. ");
addRouteData(context, msg);
addRouteData(dNode.context, msg);
UFStatus.getHandler(DependencyNode.class).warn(msg.toString());
}
}
public CamelContext getContext() {
return context;
}
/**
* Get all contexts that this context requires to be running.
*
* @return
*/
public Set<CamelContext> getRequiredContexts() {
return requiredContexs;
}
/**
* Get all contexts that depend on this context to be running.
*
* @return
*/
public Set<CamelContext> getDependentContexts() {
return dependentContexts;
}
/**
* Utility method for printing information about a context.
*
* @param ctx
* @param builder
*/
private static void addRouteData(CamelContext ctx, StringBuilder builder) {
builder.append("Context [").append(ctx.getName())
.append("] consumes from [");
Set<String> consumerEndpoints = new HashSet<String>();
for (Route route : ctx.getRoutes()) {
Endpoint endpoint = route.getEndpoint();
String uri = endpoint.getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
String name = typeAndName.getFirst() + ":"
+ typeAndName.getSecond();
builder.append(name).append(", ");
consumerEndpoints.add(name);
}
builder.delete(builder.length() - 2, builder.length());
builder.append("] and produces to [");
for (Endpoint endpoint : ctx.getEndpoints()) {
String uri = endpoint.getEndpointUri();
Pair<String, String> typeAndName = ContextData
.getEndpointTypeAndName(uri);
String name = typeAndName.getFirst() + ":"
+ typeAndName.getSecond();
if (!consumerEndpoints.contains(name)) {
builder.append(name).append(", ");
}
}
builder.delete(builder.length() - 2, builder.length());
builder.append("]. ");
}
}

View file

@ -0,0 +1,96 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.context;
import org.apache.camel.CamelContext;
import org.apache.camel.Route;
/**
* Represents a way for managing a context for starting and stopping. Allows for
* Context with different purposes to be handled independently of each other.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 10, 2014 2726 rjpeter Initial creation.
*
* </pre>
*
* @author rjpeter
* @version 1.0
*/
public interface IContextStateManager {
/**
* Is the {@code CamelContext} startable?
*
* @param context
* @return
* @throws Exception
*/
public boolean isContextStartable(CamelContext context) throws Exception;
/**
* Start the {@code CamelContext}.
*
* @param context
* @return
* @throws Exception
*/
public boolean startContext(CamelContext context) throws Exception;
/**
* Start the {@code Route}.
*
* @param context
* @return
* @throws Exception
*/
public boolean startRoute(Route route) throws Exception;
/**
* Is the {@code CamelContext} stoppable?
*
* @param context
* @return
* @throws Exception
*/
public boolean isContextStoppable(CamelContext context) throws Exception;
/**
* Stop the {@code CamelContext}.
*
* @param context
* @return
* @throws Exception
*/
public boolean stopContext(CamelContext context) throws Exception;
/**
* Stop the {@code Route}.
*
* @param context
* @return
* @throws Exception
*/
public boolean stopRoute(Route route) throws Exception;
}

View file

@ -1,100 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.directvm;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.camel.Endpoint;
import org.apache.camel.component.direct.DirectComponent;
import org.apache.camel.impl.DefaultConsumer;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.util.ServiceHelper;
/**
* Provides a cross-context synchronous component.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 18, 2008 chammack Initial creation
* Jul 16, 2012 DR 15073 D. Friedman Don't stop all consumer in doStop.
* May 23, 2013 1989 njensen Deprecated
*
* </pre>
*
* @author chammack
* @version 1.0
* @deprecated Use camel's built-in direct-vm component instead. This component
* can be deleted after that has been tested thoroughly.
*/
@SuppressWarnings("unchecked")
@Deprecated
public class DirectVMComponent extends DirectComponent {
private static Map<String, CopyOnWriteArrayList<DefaultConsumer>> CONSUMERS = new HashMap<String, CopyOnWriteArrayList<DefaultConsumer>>();
@Override
protected Endpoint createEndpoint(String uri, String remaining,
Map parameters) throws Exception {
synchronized (CONSUMERS) {
CopyOnWriteArrayList<DefaultConsumer> consumers = CONSUMERS
.get(uri);
if (consumers == null) {
consumers = new CopyOnWriteArrayList<DefaultConsumer>();
CONSUMERS.put(uri, consumers);
}
Endpoint endpoint = new DirectVMEndpoint(uri, this, consumers);
setProperties(endpoint, parameters);
return endpoint;
}
}
@Override
protected void doStop() throws Exception {
Collection<CopyOnWriteArrayList<DefaultConsumer>> set = CONSUMERS
.values();
/*
* Stop only the consumers created through this instance of the
* component.
*/
for (CopyOnWriteArrayList<DefaultConsumer> consumerList : set)
for (DefaultConsumer consumer : consumerList) {
Endpoint endpoint = consumer.getEndpoint();
if (endpoint instanceof DefaultEndpoint)
if (((DefaultEndpoint) endpoint).getComponent() == this)
ServiceHelper.stopService(consumer);
}
super.doStop();
}
}

View file

@ -1,102 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.directvm;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.camel.Consumer;
import org.apache.camel.Producer;
import org.apache.camel.component.direct.DirectEndpoint;
import org.apache.camel.impl.DefaultConsumer;
/**
*
* Provides a cross-context synchronous component.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 18, 2008 chammack Initial creation
* Jul 16, 2012 DR 15073 D. Friedman Override correct methods
* May 09, 2013 1989 njensen Camel 2.11 compatibility
* May 23, 2013 1989 njensen Deprecated
*
* </pre>
*
* @author chammack
* @version 1.0
* @deprecated Use camel's built-in direct-vm component instead. This component
* can be deleted after that has been tested thoroughly.
*/
@Deprecated
public class DirectVMEndpoint extends DirectEndpoint {
private boolean allowMultipleConsumers = true;
private CopyOnWriteArrayList<DefaultConsumer> consumers = new CopyOnWriteArrayList<DefaultConsumer>();
public DirectVMEndpoint(String uri, DirectVMComponent component) {
super(uri, component);
}
public DirectVMEndpoint(String uri, DirectVMComponent component,
CopyOnWriteArrayList<DefaultConsumer> consumers) {
super(uri, component);
this.consumers = consumers;
}
@Override
public Producer createProducer() throws Exception {
return new DirectVMProducer(this);
}
@Override
public Consumer createConsumer(org.apache.camel.Processor processor)
throws Exception {
return new DefaultConsumer(this, processor) {
@Override
protected void doStart() throws Exception {
if (!allowMultipleConsumers && !consumers.isEmpty()) {
throw new IllegalStateException(
"Endpoint "
+ getEndpointUri()
+ " only allows 1 active consumer but you attempted to start a 2nd consumer.");
}
consumers.add(this);
super.doStart();
}
@Override
protected void doStop() throws Exception {
super.doStop();
consumers.remove(this);
}
};
}
public List<DefaultConsumer> getConsumers() {
return consumers;
}
}

View file

@ -1,111 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.esb.camel.directvm;
import java.util.List;
import org.apache.camel.AsyncCallback;
import org.apache.camel.AsyncProcessor;
import org.apache.camel.CamelExchangeException;
import org.apache.camel.Exchange;
import org.apache.camel.component.direct.DirectProducer;
import org.apache.camel.impl.DefaultConsumer;
import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
import org.apache.camel.util.AsyncProcessorHelper;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Direct VM Producer used with DirectVMConsumer.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 27, 2010 mschenke Initial creation
* May 23, 2013 1989 njensen Deprecated
*
* </pre>
*
* @author mschenke
* @version 1.0
* @deprecated Use camel's built-in direct-vm component instead. This component
* can be deleted after that has been tested thoroughly.
*/
@Deprecated
public class DirectVMProducer extends DirectProducer {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(DirectVMProducer.class);
private DirectVMEndpoint endpoint;
/**
* @param endpoint
*/
public DirectVMProducer(DirectVMEndpoint endpoint) {
super(endpoint);
this.endpoint = endpoint;
}
public void process(Exchange exchange) throws Exception {
List<DefaultConsumer> consumers = endpoint.getConsumers();
if (consumers == null || consumers.size() == 0) {
statusHandler.handle(Priority.PROBLEM,
"No consumers available on endpoint: " + endpoint
+ " to process: " + exchange);
throw new CamelExchangeException(
"No consumers available on endpoint: " + endpoint, exchange);
} else {
for (DefaultConsumer consumer : consumers) {
consumer.getProcessor().process(exchange);
}
}
}
public boolean process(Exchange exchange, AsyncCallback callback) {
List<DefaultConsumer> consumers = endpoint.getConsumers();
if (consumers == null || consumers.size() == 0) {
statusHandler.handle(Priority.PROBLEM,
"No consumers available on endpoint: " + endpoint
+ " to process: " + exchange);
// indicate its done synchronously
exchange.setException(new CamelExchangeException(
"No consumers available on endpoint: " + endpoint, exchange));
callback.done(true);
return true;
} else {
boolean sync = true;
for (DefaultConsumer consumer : consumers) {
AsyncProcessor processor = AsyncProcessorTypeConverter
.convert(consumer.getProcessor());
sync &= AsyncProcessorHelper.process(processor, exchange,
callback);
}
return sync;
}
}
}

View file

@ -86,7 +86,6 @@ public class DedicatedThreadJmsComponent extends JmsComponent {
executor.setMaxPoolSize(Math.max(jmsE.getConcurrentConsumers(),
jmsE.getMaxConcurrentConsumers()));
executor.setQueueCapacity(0);
executor.afterPropertiesSet();
jmsE.setTaskExecutor(executor);
jmsE.setMessageListenerContainerFactory(MonitoredDefaultMessageListenerContainerFactory

View file

@ -19,6 +19,8 @@
**/
package com.raytheon.uf.edex.esb.camel.spring;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
@ -32,7 +34,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 15, 2010 rjpeter Initial creation
*
* Apr 10, 2014 2726 rjpeter Updated to create/initialize the ThreadPoolExecutor on demand.
* </pre>
*
* @author rjpeter
@ -40,6 +42,25 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
*/
public class JmsThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
private static final long serialVersionUID = 1L;
private volatile boolean needToInitialize = true;
@Override
public ThreadPoolExecutor getThreadPoolExecutor()
throws IllegalStateException {
// don't initialize until first needed
if (needToInitialize) {
synchronized (this) {
if (needToInitialize) {
afterPropertiesSet();
needToInitialize = false;
}
}
}
return super.getThreadPoolExecutor();
}
@Override
public boolean prefersShortLivedTasks() {
return false;

Some files were not shown because too many files have changed in this diff Show more