14.1.1-18 baseline

Former-commit-id: 1f27652aa3 [formerly f05a2220cd] [formerly 575e328123] [formerly 1f27652aa3 [formerly f05a2220cd] [formerly 575e328123] [formerly 1d6a9456b7 [formerly 575e328123 [formerly a8009c4ee3effc8586b830244db8db716ec0f37c]]]]
Former-commit-id: 1d6a9456b7
Former-commit-id: 1c7bf39f73 [formerly d61ae6c5f4] [formerly 57fbd21c8831f46d66fe301b77916657b0ab9f05 [formerly c5857c30f2]]
Former-commit-id: 48b7eeaa6cb834b10db17643ac629aaa112f6878 [formerly d1db845406]
Former-commit-id: f47dd3ef59
This commit is contained in:
Brian.Dyke 2014-02-11 15:52:50 -05:00
parent e0236cc20a
commit fc21d2dee4
19 changed files with 546 additions and 145 deletions

View file

@ -107,6 +107,40 @@
</max-perm> </max-perm>
</ini-substitutions> </ini-substitutions>
</memory-setting> </memory-setting>
<memory-setting>
<command-line-args>
<first-arg>-component</first-arg>
<second-arg>servicebackup</second-arg>
</command-line-args>
<ini-substitutions>
<max-memory>
<value>256M</value>
</max-memory>
<max-perm>
<value>128m</value>
</max-perm>
</ini-substitutions>
</memory-setting>
<memory-setting>
<command-line-args>
<first-arg>-perspective</first-arg>
<second-arg>National Centers</second-arg>
</command-line-args>
<ini-substitutions>
<max-memory>
<value>1536M</value>
</max-memory>
<max-perm>
<value>DEFAULT</value>
</max-perm>
</ini-substitutions>
</memory-setting>
</arch.x86> </arch.x86>
<arch.x86_64> <arch.x86_64>
@ -182,6 +216,40 @@
</max-perm> </max-perm>
</ini-substitutions> </ini-substitutions>
</memory-setting> </memory-setting>
<memory-setting>
<command-line-args>
<first-arg>-component</first-arg>
<second-arg>servicebackup</second-arg>
</command-line-args>
<ini-substitutions>
<max-memory>
<value>256M</value>
</max-memory>
<max-perm>
<value>128m</value>
</max-perm>
</ini-substitutions>
</memory-setting>
<memory-setting>
<command-line-args>
<first-arg>-perspective</first-arg>
<second-arg>National Centers</second-arg>
</command-line-args>
<ini-substitutions>
<max-memory>
<value>2048M</value>
</max-memory>
<max-perm>
<value>DEFAULT</value>
</max-perm>
</ini-substitutions>
</memory-setting>
</arch.x86_64> </arch.x86_64>
</cave-memory-settings> </cave-memory-settings>

View file

@ -29,11 +29,15 @@
# ??/??/?? ???????? Initial Creation. # ??/??/?? ???????? Initial Creation.
# 05/14/13 1842 dgilling Use GFEVtecUtil to handle NEW # 05/14/13 1842 dgilling Use GFEVtecUtil to handle NEW
# ETN assignment. # ETN assignment.
# 02/05/14 2774 dgilling Fix error logging statements in
# __warnETNduplication() and
# __highestETNActiveTable.
# #
# #
import time, getopt, sys, copy, string, logging import time, getopt, sys, copy, string, logging
import os
import VTECTableUtil, VTECTable import VTECTableUtil, VTECTable
import TimeRange, AbsTime, ActiveTableVtec import TimeRange, AbsTime, ActiveTableVtec
import JUtil import JUtil
@ -722,7 +726,7 @@ class HazardsTable(VTECTableUtil.VTECTableUtil):
if phensig == activephensig and presentyear == activeyear: if phensig == activephensig and presentyear == activeyear:
# causes failure if tropical hazards are less than 1001 # causes failure if tropical hazards are less than 1001
if active['etn'] < int(self.__tpcBaseETN): if active['etn'] < int(self.__tpcBaseETN):
LogStream.logProblem("Incorrect ETN for tropical hazard.") self.log.error("Incorrect ETN for tropical hazard.")
return etn_base return etn_base
#determine the new etn to use, using the etn cache #determine the new etn to use, using the etn cache
@ -2234,8 +2238,8 @@ class HazardsTable(VTECTableUtil.VTECTableUtil):
if len(dups) > 0: if len(dups) > 0:
errorLine = '\n******************************************************\n' errorLine = '\n******************************************************\n'
LogStream.logProblem("Illegal ETN duplication is found for:\n", \ self.log.error("Illegal ETN duplication is found for:\n" + \
dups, errorLine) str(dups) + errorLine)
# send message to GFE # send message to GFE
msg = "The formatted %s product contains a duplicate ETN.\n"\ msg = "The formatted %s product contains a duplicate ETN.\n"\

View file

@ -29,7 +29,7 @@
# ------------ ---------- ----------- -------------------------- # ------------ ---------- ----------- --------------------------
# 07/25/08 njensen Initial Creation. # 07/25/08 njensen Initial Creation.
# 09/05/13 #2329 randerso Added error handling # 09/05/13 #2329 randerso Added error handling
# # 02/06/2014 #2591 randerso Changed log level to debug
# #
import sys, traceback, os, time, LogStream import sys, traceback, os, time, LogStream
@ -55,7 +55,7 @@ def getCombinations(comboName):
with open(filename,'r') as fd: with open(filename,'r') as fd:
filecontents = fd.read() filecontents = fd.read()
LogStream.logProblem("\nERROR loading combinations file: "+ comboName + LogStream.logDebug("ERROR loading combinations file: "+ comboName +
"\nmd.__file__: " + md.__file__ + "\nmd.__file__: " + md.__file__ +
"\ndir(md): " + str(dir(md)) + "\ndir(md): " + str(dir(md)) +
"\n" + md.__file__ + " last modified: " + time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime(os.path.getmtime(md.__file__))) + "\n" + md.__file__ + " last modified: " + time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime(os.path.getmtime(md.__file__))) +

View file

@ -29,6 +29,7 @@
# Dec 05, 2013 #2590 dgilling Modified so gfeclient.sh can be wrapped # Dec 05, 2013 #2590 dgilling Modified so gfeclient.sh can be wrapped
# around this script. # around this script.
# Jan 24, 2014 #2739 bsteffen Log exit status # Jan 24, 2014 #2739 bsteffen Log exit status
# Jan 30, 2014 #2593 bclement warns based on memory usage, fixed for INI files with spaces
# #
# #
@ -46,6 +47,8 @@ JAVA_INSTALL="/awips2/java"
PYTHON_INSTALL="/awips2/python" PYTHON_INSTALL="/awips2/python"
export AWIPS_INSTALL_DIR="${CAVE_INSTALL}" export AWIPS_INSTALL_DIR="${CAVE_INSTALL}"
MAX_MEM_PROPORTION="0.9"
source ${CAVE_INSTALL}/caveUtil.sh source ${CAVE_INSTALL}/caveUtil.sh
RC=$? RC=$?
if [ ${RC} -ne 0 ]; then if [ ${RC} -ne 0 ]; then
@ -113,20 +116,39 @@ export TEXTWS=`hostname | sed -e 's/lx/xt/g'`
hostName=`hostname -s` hostName=`hostname -s`
if [[ $hostName =~ xt.* ]]; then
export IGNORE_NUM_CAVES=1
fi
# check number of running caves # check number of running caves
if [[ -z $IGNORE_NUM_CAVES ]]; then if [[ -z $IGNORE_NUM_CAVES ]]; then
# free usually reports below on G threshold (11 instead of 12G), giving the 3 cave recommended in field # get total memory on system in bytes
mem=( `free -g | grep "Mem:"` ) mem=( `free -b | grep "Mem:"` )
mem=${mem[1]} mem=${mem[1]}
let _maxCaves=mem/3 # get max amount of system memory used before we warn
memThreshold=$(echo "$mem * $MAX_MEM_PROPORTION" | bc)
getPidsOfMyRunningCaves # remove decimal
if [[ "$_numPids" -ge "$_maxCaves" ]]; then printf -v memThreshold "%.0f" "$memThreshold"
zenity --question --title "Max CAVE sessions already running" --text "$_numPids CAVE sessions already running. Starting more may impact system performance and stability.\n\nProceed?" # get launcher.ini argument determined by user arguments
lookupINI "$@"
launcherRegex='--launcher.ini\s(.+\.ini)'
# default to cave.ini
targetIni="/awips2/cave/cave.ini"
if [[ $CAVE_INI_ARG =~ $launcherRegex ]]
then
targetIni="${BASH_REMATCH[1]}"
fi
# read max memory that could be used by this instance
memOfLaunchingCave=$(readMemFromIni "$targetIni")
# read total max memory of caves already running
getTotalMemOfRunningCaves
# add them together
_totalAfterStart=$(($memOfLaunchingCave + $_totalRunningMem))
if [[ "$_totalAfterStart" -ge "$memThreshold" ]]; then
# convert to megs for display
memOfLaunchingCave=$(($memOfLaunchingCave / $BYTES_IN_MB))
_totalRunningMem=$(($_totalRunningMem / $BYTES_IN_MB))
getPidsOfMyRunningCaves
memMsg="$_numPids CAVE applications already running with a combined max memory of ${_totalRunningMem}MB. "
memMsg+="The requested application has a max memory requirement of ${memOfLaunchingCave}MB. "
memMsg+="Starting may impact system performance and stability.\n\nProceed?"
zenity --question --title "Low Available Memory for Application" --text "$memMsg"
cancel="$?" cancel="$?"
if [[ "$cancel" == "1" ]]; then if [[ "$cancel" == "1" ]]; then
@ -181,7 +203,7 @@ curTime=`date +%Y%m%d_%H%M%S`
# At this point fork so that log files can be set up with the process pid and # At this point fork so that log files can be set up with the process pid and
# this process can log the exit status of cave. # this process can log the exit status of cave.
( (
export pid=`$SHELL -c 'echo $PPID'` export pid=`/bin/bash -c 'echo $PPID'`
LOGFILE="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_${pid}_console.log" LOGFILE="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_${pid}_console.log"
export LOGFILE_CAVE="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_${pid}_alertviz.log" export LOGFILE_CAVE="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_${pid}_alertviz.log"
@ -221,9 +243,9 @@ curTime=`date +%Y%m%d_%H%M%S`
fi fi
if [[ "${redirect}" == "true" ]] ; then if [[ "${redirect}" == "true" ]] ; then
exec ${CAVE_INSTALL}/cave ${ARCH_ARGS} ${SWITCHES} ${CAVE_INI_ARG} "${USER_ARGS[@]}" > ${LOGFILE} 2>&1 exec ${CAVE_INSTALL}/cave ${ARCH_ARGS} ${SWITCHES} "${CAVE_INI_ARG}" "${USER_ARGS[@]}" > ${LOGFILE} 2>&1
else else
exec ${CAVE_INSTALL}/cave ${ARCH_ARGS} ${SWITCHES} ${CAVE_INI_ARG} "${USER_ARGS[@]}" 2>&1 | tee ${LOGFILE} exec ${CAVE_INSTALL}/cave ${ARCH_ARGS} ${SWITCHES} "${CAVE_INI_ARG}" "${USER_ARGS[@]}" 2>&1 | tee ${LOGFILE}
fi fi
) & ) &

View file

@ -26,6 +26,9 @@
# Dec 05, 2013 #2590 dgilling Modified extendLibraryPath() to export a # Dec 05, 2013 #2590 dgilling Modified extendLibraryPath() to export a
# var if it's already been run. # var if it's already been run.
# Jan 24, 2014 #2739 bsteffen Add method to log exit status of process. # Jan 24, 2014 #2739 bsteffen Add method to log exit status of process.
# Jan 30, 2014 #2593 bclement extracted generic part of getPidsOfMyRunningCaves into forEachRunningCave
# added methods for reading max memory from .ini files
# fixes for INI files with spaces
# #
# #
@ -40,6 +43,10 @@ fi
# This script will be sourced by cave.sh. # This script will be sourced by cave.sh.
export CAVE_INI_ARG= export CAVE_INI_ARG=
BYTES_IN_KB=1024
BYTES_IN_MB=1048576
BYTES_IN_GB=1073741824
function lookupINI() function lookupINI()
{ {
# Arguments: # Arguments:
@ -56,7 +63,7 @@ function lookupINI()
position=$(( $position + 1 )) position=$(( $position + 1 ))
nextArg=${!position} nextArg=${!position}
retrieveAssociatedINI ${arg} ${nextArg} retrieveAssociatedINI ${arg} "${nextArg}"
RC=$? RC=$?
if [ ${RC} -eq 0 ]; then if [ ${RC} -eq 0 ]; then
export CAVE_INI_ARG="--launcher.ini /awips2/cave/${ASSOCIATED_INI}" export CAVE_INI_ARG="--launcher.ini /awips2/cave/${ASSOCIATED_INI}"
@ -117,8 +124,8 @@ function copyVizShutdownUtilIfNecessary()
chmod a+x ${HOME}/.kde/shutdown/${VIZ_UTILITY_SCRIPT} chmod a+x ${HOME}/.kde/shutdown/${VIZ_UTILITY_SCRIPT}
} }
# returns _numPids and array _pids containing the pids of the currently running cave sessions. # takes a function as an argument and calls the function passing in the ps string of the process
function getPidsOfMyRunningCaves() function forEachRunningCave()
{ {
local user=`whoami` local user=`whoami`
local caveProcs=`ps -ef | grep -E "(/awips2/cave|/usr/local/viz)/cave " | grep -v "grep" | grep $user` local caveProcs=`ps -ef | grep -E "(/awips2/cave|/usr/local/viz)/cave " | grep -v "grep" | grep $user`
@ -126,17 +133,89 @@ function getPidsOfMyRunningCaves()
# preserve IFS and set it to line feed only # preserve IFS and set it to line feed only
local PREV_IFS=$IFS local PREV_IFS=$IFS
IFS=$'\n' IFS=$'\n'
_numPids=0
# grab the pids for future use
for caveProc in $caveProcs for caveProc in $caveProcs
do do
_pids[$_numPids]=`echo $caveProc | awk '{print $2}'` "$@" $caveProc
let "_numPids+=1"
done done
IFS=$PREV_IFS IFS=$PREV_IFS
} }
# takes in ps string of cave process, stores pid in _pids and increments _numPids
function processPidOfCave()
{
_pids[$_numPids]=`echo $1 | awk '{print $2}'`
let "_numPids+=1"
}
# returns _numPids and array _pids containing the pids of the currently running cave sessions.
function getPidsOfMyRunningCaves()
{
_numPids=0
forEachRunningCave processPidOfCave
}
# takes a name of an ini file as an argument, echos the memory (in bytes) from file (or default)
function readMemFromIni()
{
local inifile="$1"
local mem
local unit
local regex='^[^#]*-Xmx([0-9]+)([bBkKmMgG])?'
# read ini file line by line looking for Xmx arg
while read -r line
do
if [[ $line =~ $regex ]]
then
mem=${BASH_REMATCH[1]}
unit=${BASH_REMATCH[2]}
break
fi
done < "$inifile"
# convert to bytes
case "$unit" in
[kK])
mem=$(($mem * $BYTES_IN_KB))
;;
[mM])
mem=$(($mem * $BYTES_IN_MB))
;;
[gG])
mem=$(($mem * $BYTES_IN_GB))
;;
esac
regex='^[0-9]+$'
if [[ ! $mem =~ $regex ]]
then
# we couldn't find a valid Xmx value
# java default is usually 1G
mem=1073741824
fi
echo $mem
}
# takes in ps string of cave process, reads Xmx from ini and adds bytes to _totalRunninMem
function addMemOfCave()
{
local inifile
# get ini file from process string
local regex='--launcher.ini\s(.+\.ini)'
if [[ $1 =~ $regex ]]
then
inifile="${BASH_REMATCH[1]}"
else
inifile="/awips2/cave/cave.ini"
fi
let "_totalRunningMem+=$(readMemFromIni "$inifile")"
}
# finds total max memory of running caves in bytes and places it in _totalRunningMem
function getTotalMemOfRunningCaves()
{
_totalRunningMem=0
forEachRunningCave addMemOfCave
}
function deleteOldCaveDiskCaches() function deleteOldCaveDiskCaches()
{ {
local curDir=`pwd` local curDir=`pwd`
@ -201,6 +280,7 @@ function logExitStatus()
pid=$1 pid=$1
logFile=$2 logFile=$2
trap 'kill $pid' SIGHUP SIGINT SIGQUIT SIGTERM
wait $pid wait $pid
exitCode=$? exitCode=$?
curTime=`date --rfc-3339=seconds` curTime=`date --rfc-3339=seconds`

View file

@ -81,6 +81,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* archive and category directory and * archive and category directory and
* implementation of compression. * implementation of compression.
* Oct 08, 2013 2442 rferrel Remove category directory. * Oct 08, 2013 2442 rferrel Remove category directory.
* Feb 04, 2013 2270 rferrel Move HDF files to parent's directory.
* *
* </pre> * </pre>
* *
@ -89,6 +90,10 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
*/ */
public class GenerateCaseDlg extends CaveSWTDialog { public class GenerateCaseDlg extends CaveSWTDialog {
/** Extension for HDF files. */
private static final String hdfExt = ".h5";
private final IUFStatusHandler statusHandler = UFStatus private final IUFStatusHandler statusHandler = UFStatus
.getHandler(GenerateCaseDlg.class); .getHandler(GenerateCaseDlg.class);
@ -539,6 +544,11 @@ public class GenerateCaseDlg extends CaveSWTDialog {
new File(destination, file)); new File(destination, file));
} }
} else { } else {
// DR 2270 bump HDF files up a directory.
if (destination.getName().endsWith(hdfExt)) {
destination = new File(destination.getParentFile()
.getParentFile(), destination.getName());
}
FileUtil.copyFile(source, destination); FileUtil.copyFile(source, destination);
destination.setLastModified(source.lastModified()); destination.setLastModified(source.lastModified());
} }
@ -652,6 +662,13 @@ public class GenerateCaseDlg extends CaveSWTDialog {
addTarFiles(file.listFiles()); addTarFiles(file.listFiles());
} }
} else { } else {
// DR 2270 bump HDF files up a directory.
if (name.endsWith(hdfExt)) {
File destination = new File(file.getParentFile()
.getParentFile(), file.getName());
name = destination.getAbsolutePath().substring(
startRelativePath);
}
TarArchiveEntry entry = new TarArchiveEntry(file, name); TarArchiveEntry entry = new TarArchiveEntry(file, name);
entry.setSize(file.length()); entry.setSize(file.length());
FileInputStream fileStream = null; FileInputStream fileStream = null;

View file

@ -63,6 +63,7 @@ import com.raytheon.viz.gfe.textformatter.TextProductManager;
* DataManager instance. * DataManager instance.
* 05 SEP 2013 2329 randerso Added call to ZoneCombinerComp.applyZoneCombo when * 05 SEP 2013 2329 randerso Added call to ZoneCombinerComp.applyZoneCombo when
* when run formatter button is clicked. * when run formatter button is clicked.
* 05 FEB 2014 2591 randerso Added dataManager to ZoneCombinerComp constructor
* *
* </pre> * </pre>
* *
@ -592,7 +593,7 @@ public class ProductAreaComp extends Composite implements
*/ */
private void createZoneCombinerComp() { private void createZoneCombinerComp() {
zoneCombiner = new ZoneCombinerComp(stackGridComp, productTabCB, zoneCombiner = new ZoneCombinerComp(stackGridComp, productTabCB,
productName, getTextProductManager()); productName, getTextProductManager(), this.dataMgr);
} }
/** /**

View file

@ -155,6 +155,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
* 01/06/2014 2649 dgilling Pass flag to StoreTransmitDlg to only * 01/06/2014 2649 dgilling Pass flag to StoreTransmitDlg to only
* update VTEC lines on products that * update VTEC lines on products that
* aren't being corrected. * aren't being corrected.
* 02/05/2014 17022 ryu Modified loadDraft() to fix merging of WMO heading and AWIPS ID.
* *
* </pre> * </pre>
* *
@ -2389,10 +2390,13 @@ public class ProductEditorComp extends Composite implements
} }
DraftProduct draft = DraftProduct.load(lf); DraftProduct draft = DraftProduct.load(lf);
setTabColorFunc(productStateEnum.Finished);
productDefinition = draft.getProductDefinition(); productDefinition = draft.getProductDefinition();
clearProductText();
setProductText(draft.getProductText()); setProductText(draft.getProductText());
setTabColorFunc(productStateEnum.Finished);
setStatusText('R', productId + " draft loaded."); setStatusText('R', productId + " draft loaded.");
if (productDefinition.get("brain") != null) { if (productDefinition.get("brain") != null) {
brain(); brain();
String msg = "Your saved draft was loaded, but the draft is invalid " String msg = "Your saved draft was loaded, but the draft is invalid "

View file

@ -58,8 +58,7 @@ import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation;
import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException; import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException;
import com.raytheon.uf.common.localization.FileUpdatedMessage; import com.raytheon.uf.common.dataplugin.gfe.server.notify.CombinationsFileChangedNotification;
import com.raytheon.uf.common.localization.ILocalizationFileObserver;
import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
@ -74,7 +73,9 @@ import com.raytheon.uf.viz.core.RGBColors;
import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.gfe.Activator; import com.raytheon.viz.gfe.Activator;
import com.raytheon.viz.gfe.core.DataManager;
import com.raytheon.viz.gfe.core.DataManagerUIFactory; import com.raytheon.viz.gfe.core.DataManagerUIFactory;
import com.raytheon.viz.gfe.core.internal.NotificationRouter.AbstractGFENotificationObserver;
import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil; import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil;
import com.raytheon.viz.gfe.textformatter.TextProductManager; import com.raytheon.viz.gfe.textformatter.TextProductManager;
import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector; import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector;
@ -100,6 +101,11 @@ import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector;
* Dec 03, 2013 #2591 dgilling Ensure all change states to the combo * Dec 03, 2013 #2591 dgilling Ensure all change states to the combo
* file are handled. * file are handled.
* Jan 07, 2014 #2662 randerso Disabled zone combiner if no maps are selected * Jan 07, 2014 #2662 randerso Disabled zone combiner if no maps are selected
* Feb 04, 2014 #2591 randerso Forced reload of combinations file after save to ensure
* file is updated prior to running formatter
* Changed to use CombinationsFileChangedNotification instead of
* FileUpdatedMessage so we can ignore our own changes
* Moved retrieval of combinations file to CombinationsFileUtil.init
* *
* </pre> * </pre>
* *
@ -107,8 +113,7 @@ import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector;
* @version 1.0 * @version 1.0
* *
*/ */
public class ZoneCombinerComp extends Composite implements public class ZoneCombinerComp extends Composite implements IZoneCombiner {
ILocalizationFileObserver, IZoneCombiner {
private final transient IUFStatusHandler statusHandler = UFStatus private final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ZoneCombinerComp.class); .getHandler(ZoneCombinerComp.class);
@ -191,6 +196,8 @@ public class ZoneCombinerComp extends Composite implements
protected TextProductManager textProductMgr; protected TextProductManager textProductMgr;
protected DataManager dataManager;
protected String product; protected String product;
protected boolean mapRequired; protected boolean mapRequired;
@ -224,6 +231,8 @@ public class ZoneCombinerComp extends Composite implements
private List<String> mapNames; private List<String> mapNames;
private AbstractGFENotificationObserver<CombinationsFileChangedNotification> comboChangeListener;
private void initPreferences() { private void initPreferences() {
IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); IPreferenceStore prefs = Activator.getDefault().getPreferenceStore();
@ -247,7 +256,8 @@ public class ZoneCombinerComp extends Composite implements
* Product name. * Product name.
*/ */
public ZoneCombinerComp(Composite parent, IProductTab callBack, public ZoneCombinerComp(Composite parent, IProductTab callBack,
String productName, TextProductManager textProductMgr) { String productName, TextProductManager textProductMgr,
DataManager dataManager) {
super(parent, SWT.NONE); super(parent, SWT.NONE);
this.parent = parent; this.parent = parent;
@ -258,6 +268,8 @@ public class ZoneCombinerComp extends Composite implements
this.textProductMgr = textProductMgr; this.textProductMgr = textProductMgr;
this.dataManager = dataManager;
mapRequired = this.textProductMgr.mapRequired(productName); mapRequired = this.textProductMgr.mapRequired(productName);
this.mapNames = getMapNames(productName); this.mapNames = getMapNames(productName);
if (mapNames.isEmpty()) { if (mapNames.isEmpty()) {
@ -272,15 +284,30 @@ public class ZoneCombinerComp extends Composite implements
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE); LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
comboDir = pathMgr.getLocalizationFile(baseCtx, comboDir = pathMgr.getLocalizationFile(baseCtx,
CombinationsFileUtil.COMBO_DIR_PATH); CombinationsFileUtil.COMBO_DIR_PATH);
comboDir.addFileUpdatedObserver(this);
this.comboChangeListener = new AbstractGFENotificationObserver<CombinationsFileChangedNotification>(
CombinationsFileChangedNotification.class) {
@Override
public void notify(
CombinationsFileChangedNotification notificationMessage) {
comboFileChanged(notificationMessage);
}
};
this.addDisposeListener(new DisposeListener() { this.addDisposeListener(new DisposeListener() {
@Override @Override
public void widgetDisposed(DisposeEvent e) { public void widgetDisposed(DisposeEvent e) {
comboDir.removeFileUpdatedObserver(ZoneCombinerComp.this); ZoneCombinerComp.this.dataManager.getNotificationRouter()
.removeObserver(
ZoneCombinerComp.this.comboChangeListener);
} }
}); });
dataManager.getNotificationRouter().addObserver(
this.comboChangeListener);
} }
private List<String> getMapNames(String productName) { private List<String> getMapNames(String productName) {
@ -779,9 +806,14 @@ public class ZoneCombinerComp extends Composite implements
} }
try { try {
String comboName = getCombinationsFileName();
CombinationsFileUtil.generateAutoCombinationsFile( CombinationsFileUtil.generateAutoCombinationsFile(
zoneSelector.getZoneGroupings(), getCombinationsFileName() zoneSelector.getZoneGroupings(), comboName);
+ ".py");
// reload here forces file to be retrieved from server before
// allowing formatter to run
loadCombinationsFile(comboName);
applyButtonState(false); applyButtonState(false);
} catch (Exception e) { } catch (Exception e) {
statusHandler.handle(Priority.PROBLEM, "Unable to save " statusHandler.handle(Priority.PROBLEM, "Unable to save "
@ -925,17 +957,7 @@ public class ZoneCombinerComp extends Composite implements
public Map<String, Integer> loadCombinationsFile(String comboName) { public Map<String, Integer> loadCombinationsFile(String comboName) {
Map<String, Integer> dict = new HashMap<String, Integer>(); Map<String, Integer> dict = new HashMap<String, Integer>();
try { try {
File localFile = PathManagerFactory.getPathManager().getStaticFile( List<List<String>> combolist = CombinationsFileUtil.init(comboName);
FileUtil.join(CombinationsFileUtil.COMBO_DIR_PATH,
comboName + ".py"));
List<List<String>> combolist = new ArrayList<List<String>>();
if ((localFile != null) && localFile.exists()) {
combolist = CombinationsFileUtil.init(comboName);
} else {
// statusHandler
// .error("Combinations file not found: " + comboName);
}
// reformat combinations into combo dictionary // reformat combinations into combo dictionary
int group = 1; int group = 1;
@ -951,8 +973,7 @@ public class ZoneCombinerComp extends Composite implements
return new HashMap<String, Integer>(); return new HashMap<String, Integer>();
} }
currentComboFile = FileUtil.join(CombinationsFileUtil.COMBO_DIR_PATH, currentComboFile = comboName;
comboName + ".py");
return dict; return dict;
} }
@ -987,20 +1008,14 @@ public class ZoneCombinerComp extends Composite implements
return colors; return colors;
} }
/* private void comboFileChanged(CombinationsFileChangedNotification notif) {
* (non-Javadoc) String comboName = notif.getCombinationsFileName();
*
* @see // if it's the same file and not changed by me update the combos
* com.raytheon.uf.common.localization.ILocalizationFileObserver#fileUpdated if (comboName.equalsIgnoreCase(currentComboFile)
* (com.raytheon.uf.common.localization.FileUpdatedMessage) && !VizApp.getWsId().equals(notif.getWhoChanged())) {
*/
@Override
public void fileUpdated(FileUpdatedMessage message) {
if (message.getFileName().equalsIgnoreCase(currentComboFile)) {
File file = new File(message.getFileName());
String comboName = file.getName().replace(".py", "");
statusHandler statusHandler
.info("Received FileUpdatedMessage for combinations file: " .info("Received CombinationsFileChangedNotification for combinations file: "
+ comboName); + comboName);
Map<String, Integer> comboDict = loadCombinationsFile(comboName); Map<String, Integer> comboDict = loadCombinationsFile(comboName);
this.zoneSelector.updateCombos(comboDict); this.zoneSelector.updateCombos(comboDict);

View file

@ -52,6 +52,7 @@ import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.serialization.SerializationUtil;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.viz.gfe.core.DataManagerUIFactory; import com.raytheon.viz.gfe.core.DataManagerUIFactory;
import com.raytheon.viz.gfe.core.internal.IFPClient; import com.raytheon.viz.gfe.core.internal.IFPClient;
@ -67,6 +68,8 @@ import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil.ComboData.Entry;
* Jul 25, 2008 mnash Initial creation * Jul 25, 2008 mnash Initial creation
* Sep 05, 2013 #2329 randerso Moved genereateAutoCombinationsFile here * Sep 05, 2013 #2329 randerso Moved genereateAutoCombinationsFile here
* Cleaned up error handling * Cleaned up error handling
* Feb 05, 2014 #2591 randerso Forced retrieval of combinations file
* Implemented retry on error
* *
* </pre> * </pre>
* *
@ -78,6 +81,8 @@ public class CombinationsFileUtil {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(CombinationsFileUtil.class); .getHandler(CombinationsFileUtil.class);
private static final int MAX_TRIES = 2;
public static String COMBO_DIR_PATH = FileUtil.join("gfe", "combinations"); public static String COMBO_DIR_PATH = FileUtil.join("gfe", "combinations");
public static String SAVED_COMBO_DIR = FileUtil.join("gfe", "comboData"); public static String SAVED_COMBO_DIR = FileUtil.join("gfe", "comboData");
@ -194,8 +199,8 @@ public class CombinationsFileUtil {
throws SerializationException { throws SerializationException {
LocalizationFile lf = idToFile(id); LocalizationFile lf = idToFile(id);
File file = lf.getFile(); File file = lf.getFile();
ComboData comboData = (ComboData) SerializationUtil ComboData comboData = SerializationUtil.jaxbUnmarshalFromXmlFile(
.jaxbUnmarshalFromXmlFile(file); ComboData.class, file);
Map<String, Integer> comboDict = new HashMap<String, Integer>( Map<String, Integer> comboDict = new HashMap<String, Integer>(
comboData.combos.size()); comboData.combos.size());
@ -211,13 +216,20 @@ public class CombinationsFileUtil {
IPathManager pm = PathManagerFactory.getPathManager(); IPathManager pm = PathManagerFactory.getPathManager();
// retrieve combinations file if it's changed
LocalizationFile lf = pm.getStaticLocalizationFile(FileUtil.join(
COMBO_DIR_PATH, comboName + ".py"));
File pyFile;
try {
pyFile = lf.getFile(true);
} catch (LocalizationException e) {
throw new GfeException("Error retrieving combinations file: "
+ comboName, e);
}
LocalizationContext baseContext = pm.getContext( LocalizationContext baseContext = pm.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE); LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
// Strip any path components from comboName
File comboFile = new File(comboName);
comboName = comboFile.getName();
String scriptPath = FileUtil.join( String scriptPath = FileUtil.join(
GfePyIncludeUtil.getUtilitiesLF(baseContext).getFile() GfePyIncludeUtil.getUtilitiesLF(baseContext).getFile()
.getPath(), "CombinationsInterface.py"); .getPath(), "CombinationsInterface.py");
@ -226,19 +238,39 @@ public class CombinationsFileUtil {
HashMap<String, Object> map = new HashMap<String, Object>(); HashMap<String, Object> map = new HashMap<String, Object>();
map.put("comboName", comboName); map.put("comboName", comboName);
PythonScript python = null; PythonScript python = null;
try { for (int retryCount = 0; retryCount < MAX_TRIES; retryCount++) {
python = new PythonScript(scriptPath, PyUtil.buildJepIncludePath( try {
GfePyIncludeUtil.getCombinationsIncludePath(), python = new PythonScript(scriptPath,
GfePyIncludeUtil.getCommonPythonIncludePath()), PyUtil.buildJepIncludePath(
CombinationsFileUtil.class.getClassLoader()); GfePyIncludeUtil.getCombinationsIncludePath(),
Object com = python.execute("getCombinations", map); GfePyIncludeUtil.getCommonPythonIncludePath()),
combos = (List<List<String>>) com; CombinationsFileUtil.class.getClassLoader());
} catch (JepException e) {
throw new GfeException("Error loading combinations file: " Object com = python.execute("getCombinations", map);
+ comboName, e); combos = (List<List<String>>) com;
} finally {
if (python != null) { // if successfully retrieved break out of the loop
python.dispose(); break;
} catch (JepException e) {
// remove the .pyo file
new File(pyFile.getAbsolutePath() + "o").delete();
// if not last try, log and try again
if (retryCount < MAX_TRIES - 1) {
// log but don't pop up
statusHandler.handle(Priority.EVENTB,
"Error loading combinations file: " + comboName
+ ", retrying ", e);
}
// else throw exception
else {
throw new GfeException("Error loading combinations file: "
+ comboName, e);
}
} finally {
if (python != null) {
python.dispose();
}
} }
} }
return combos; return combos;

View file

@ -19,8 +19,12 @@
**/ **/
package com.raytheon.viz.gfe.vtec; package com.raytheon.viz.gfe.vtec;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -53,6 +57,7 @@ import com.raytheon.viz.texteditor.util.VtecUtil;
* Nov 22, 2013 #2578 dgilling Fix ETN assignment for products with * Nov 22, 2013 #2578 dgilling Fix ETN assignment for products with
* multiple NEW VTEC lines for the same * multiple NEW VTEC lines for the same
* phensig but disjoint TimeRanges. * phensig but disjoint TimeRanges.
* Feb 05, 2014 #2774 dgilling Additional correction to previous fix.
* *
* </pre> * </pre>
* *
@ -71,6 +76,19 @@ public class GFEVtecUtil {
public static final Collection<String> IGNORE_NATIONAL_ETN = ImmutableSet public static final Collection<String> IGNORE_NATIONAL_ETN = ImmutableSet
.copyOf(GFEVtecConfig.getInstance().getSitesIgnoreNationalEtn()); .copyOf(GFEVtecConfig.getInstance().getSitesIgnoreNationalEtn());
private static final Comparator<TimeRange> TIME_COMPARATOR = new Comparator<TimeRange>() {
@Override
public int compare(TimeRange tr1, TimeRange tr2) {
int retVal = tr1.getStart().compareTo(tr2.getStart());
if (retVal == 0) {
retVal = tr1.getEnd().compareTo(tr2.getEnd());
}
return retVal;
}
};
/** /**
* A private constructor so that Java does not attempt to create one for us. * A private constructor so that Java does not attempt to create one for us.
* As this class should not be instantiated, do not attempt to ever call * As this class should not be instantiated, do not attempt to ever call
@ -101,7 +119,7 @@ public class GFEVtecUtil {
// 1. The first level is keyed by the hazard's phensig. // 1. The first level is keyed by the hazard's phensig.
// 2. The second level is keyed by the valid period of the hazard. // 2. The second level is keyed by the valid period of the hazard.
// Effectively, making this a Map<Phensig, Map<ValidPeriod, ETN>>. // Effectively, making this a Map<Phensig, Map<ValidPeriod, ETN>>.
Map<String, Map<TimeRange, Integer>> etnCache = new HashMap<String, Map<TimeRange, Integer>>(); Map<String, Map<TimeRange, Integer>> etnCache = buildETNCache(message);
Matcher vtecMatcher = VtecUtil.VTEC_REGEX.matcher(message); Matcher vtecMatcher = VtecUtil.VTEC_REGEX.matcher(message);
StringBuffer finalOutput = new StringBuffer(); StringBuffer finalOutput = new StringBuffer();
@ -114,38 +132,10 @@ public class GFEVtecUtil {
&& ((!NATIONAL_PHENSIGS.contains(vtec.getPhensig())) || (IGNORE_NATIONAL_ETN && ((!NATIONAL_PHENSIGS.contains(vtec.getPhensig())) || (IGNORE_NATIONAL_ETN
.contains(vtec.getOffice()) && TROPICAL_PHENSIGS .contains(vtec.getOffice()) && TROPICAL_PHENSIGS
.contains(vtec.getPhensig())))) { .contains(vtec.getPhensig())))) {
// Some more clarification on the ETN assignment behavior: all
// NEW VTEC lines with the same phensig should be assigned the
// same ETN if the hazards' valid periods are adjacent or
// overlapping.
// If there's a discontinuity in TimeRanges we increment to the
// next ETN.
Integer newEtn = null;
String phensig = vtec.getPhensig(); String phensig = vtec.getPhensig();
TimeRange validPeriod = new TimeRange(vtec.getStartTime() TimeRange validPeriod = new TimeRange(vtec.getStartTime()
.getTime(), vtec.getEndTime().getTime()); .getTime(), vtec.getEndTime().getTime());
Integer newEtn = etnCache.get(phensig).get(validPeriod);
Map<TimeRange, Integer> etnsByTR = etnCache.get(phensig);
if (etnsByTR != null) {
for (TimeRange tr : etnsByTR.keySet()) {
if ((validPeriod.isAdjacentTo(tr))
|| (validPeriod.overlaps(tr))) {
newEtn = etnsByTR.get(tr);
break;
}
}
}
if (newEtn == null) {
newEtn = VtecUtil.getNextEtn(vtec.getOffice(),
vtec.getPhensig(), true);
}
Map<TimeRange, Integer> cacheLevel2 = (etnsByTR != null) ? etnsByTR
: new HashMap<TimeRange, Integer>();
cacheLevel2.put(validPeriod, newEtn);
etnCache.put(phensig, cacheLevel2);
vtec.setSequence(newEtn); vtec.setSequence(newEtn);
} }
vtecMatcher vtecMatcher
@ -157,4 +147,72 @@ public class GFEVtecUtil {
vtecMatcher.appendTail(finalOutput); vtecMatcher.appendTail(finalOutput);
return finalOutput.toString(); return finalOutput.toString();
} }
private static Map<String, Map<TimeRange, Integer>> buildETNCache(
final String message) throws VizException {
Map<String, Map<TimeRange, Integer>> etnCache = new HashMap<String, Map<TimeRange, Integer>>();
String officeId = null;
Matcher vtecMatcher = VtecUtil.VTEC_REGEX.matcher(message);
while (vtecMatcher.find()) {
VtecObject vtec = new VtecObject(vtecMatcher.group());
officeId = vtec.getOffice();
if (("NEW".equals(vtec.getAction()))
&& ((!NATIONAL_PHENSIGS.contains(vtec.getPhensig())) || (IGNORE_NATIONAL_ETN
.contains(vtec.getOffice()) && TROPICAL_PHENSIGS
.contains(vtec.getPhensig())))) {
String phensig = vtec.getPhensig();
TimeRange validPeriod = new TimeRange(vtec.getStartTime()
.getTime(), vtec.getEndTime().getTime());
Map<TimeRange, Integer> etnsByTR = etnCache.get(phensig);
if (etnsByTR == null) {
etnsByTR = new HashMap<TimeRange, Integer>();
etnCache.put(phensig, etnsByTR);
}
etnsByTR.put(validPeriod, 0);
}
}
// With our first pass over the product text we have a list of all the
// NEW VTEC lines that need to have an ETN assigned to them. Depending
// on whether or not the time ranges of these lines overlap and the
// phensigs match, we might reuse ETNs for multiple VTEC lines.
for (String phensig : etnCache.keySet()) {
List<TimeRange> trList = new ArrayList<TimeRange>(etnCache.get(
phensig).keySet());
Collections.sort(trList, TIME_COMPARATOR);
for (int i = 0; i < trList.size(); i++) {
TimeRange validPeriod = trList.get(i);
Integer currentEtn = etnCache.get(phensig).get(validPeriod);
// the first time we select a new, unique ETN, any other VTEC
// lines in the product that have the same phensig and an
// adjacent TimeRange can also re-use this ETN
if (currentEtn == 0) {
currentEtn = VtecUtil.getNextEtn(officeId, phensig, true);
etnCache.get(phensig).put(validPeriod, currentEtn);
} else {
// BUT...once we've made our one pass through the product
// and re-used the ETN where appropriate, we should not
// check again
continue;
}
for (int j = i + 1; j < trList.size(); j++) {
TimeRange validPeriod2 = trList.get(j);
Integer currentEtn2 = etnCache.get(phensig).get(
validPeriod2);
if ((currentEtn2 == 0)
&& (validPeriod2.isAdjacentTo(validPeriod) || validPeriod2
.overlaps(validPeriod))) {
etnCache.get(phensig).put(validPeriod2, currentEtn);
}
}
}
}
return etnCache;
}
} }

View file

@ -34,6 +34,7 @@ import com.raytheon.viz.hydrocommon.data.GageData.ThreatIndex;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Nov 21, 2008 mpduff Initial creation * Nov 21, 2008 mpduff Initial creation
* Feb 03, 2014 16843 lbousaidi add a check for index OutOfBoundsException
* *
* </pre> * </pre>
* *
@ -101,8 +102,9 @@ public class PDCFindBasis {
} else { } else {
currentLid = fcstReportList.get(fcstIndex).getLid(); currentLid = fcstReportList.get(fcstIndex).getLid();
} }
} else if (obsReportList.get(obsIndex) != null) { } else if ((obsIndex< obsReportList.size()) && (obsReportList
currentLid = obsReportList.get(obsIndex).getLid(); .get(obsIndex) != null)) {
currentLid = obsReportList.get(obsIndex).getLid();
} else { } else {
currentLid = fcstReportList.get(fcstIndex).getLid(); currentLid = fcstReportList.get(fcstIndex).getLid();
} }

View file

@ -20,21 +20,23 @@
package com.raytheon.edex.plugin.gfe.server.handler; package com.raytheon.edex.plugin.gfe.server.handler;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.OutputStreamWriter;
import java.io.FileWriter;
import java.io.Writer; import java.io.Writer;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.dataplugin.gfe.request.SaveCombinationsFileRequest; import com.raytheon.uf.common.dataplugin.gfe.request.SaveCombinationsFileRequest;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse; import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.CombinationsFileChangedNotification;
import com.raytheon.uf.common.localization.FileUpdatedMessage; import com.raytheon.uf.common.localization.FileUpdatedMessage;
import com.raytheon.uf.common.localization.FileUpdatedMessage.FileChangeType; import com.raytheon.uf.common.localization.FileUpdatedMessage.FileChangeType;
import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.serialization.comm.IRequestHandler; import com.raytheon.uf.common.serialization.comm.IRequestHandler;
import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.common.util.FileUtil;
@ -55,6 +57,7 @@ import com.raytheon.uf.edex.core.EDEXUtil;
* May 16, 2011 dgilling Initial creation * May 16, 2011 dgilling Initial creation
* Dec 02, 2013 #2591 dgilling Only send notification after Writer is * Dec 02, 2013 #2591 dgilling Only send notification after Writer is
* flushed/closed. * flushed/closed.
* Feb 05, 2014 #2591 Added CombinationFileChangedNotification
* *
* </pre> * </pre>
* *
@ -78,19 +81,22 @@ public class SaveCombinationsFileHandler implements
@Override @Override
public ServerResponse<Object> handleRequest( public ServerResponse<Object> handleRequest(
SaveCombinationsFileRequest request) throws Exception { SaveCombinationsFileRequest request) throws Exception {
String siteID = request.getSiteID();
IPathManager pm = PathManagerFactory.getPathManager(); IPathManager pm = PathManagerFactory.getPathManager();
LocalizationContext localization = pm.getContextForSite( LocalizationContext localization = pm.getContextForSite(
LocalizationType.CAVE_STATIC, request.getSiteID()); LocalizationType.CAVE_STATIC, siteID);
File localFile = pm.getFile(localization, String comboName = request.getFileName();
FileUtil.join(COMBO_FILE_DIR, request.getFileName())); String fileName = FileUtil.join(COMBO_FILE_DIR, comboName) + ".py";
boolean isAdded = (!localFile.exists()); LocalizationFile lf = pm.getLocalizationFile(localization, fileName);
boolean isAdded = (!lf.exists());
Writer outWriter = null; Writer outWriter = null;
try { try {
outWriter = new BufferedWriter(new FileWriter(localFile)); outWriter = new BufferedWriter(new OutputStreamWriter(
lf.openOutputStream()));
String zoneComments = "\n# Automatically generated combinations file\n# " String zoneComments = "\n# Automatically generated combinations file\n# "
+ request.getFileName() + "\n\nCombinations = [\n"; + comboName + "\n\nCombinations = [\n";
outWriter.write(zoneComments); outWriter.write(zoneComments);
NumberFormat df = new DecimalFormat("00"); NumberFormat df = new DecimalFormat("00");
@ -115,20 +121,25 @@ public class SaveCombinationsFileHandler implements
outWriter.close(); outWriter.close();
} }
} }
lf.save();
// placing the notification code here ensures we only send the // placing the notification code here ensures we only send the
// notification on a successful file write operation. Otherwise we would // notification on a successful file write operation. Otherwise we would
// have thrown an IOException and never gotten to this portion of the // have thrown an IOException and never gotten to this portion of the
// request handler. // request handler.
// TODO: remove sending of FileUpdateMessage after DR #2768 is fixed
FileChangeType changeType = isAdded ? FileChangeType.ADDED FileChangeType changeType = isAdded ? FileChangeType.ADDED
: FileChangeType.UPDATED; : FileChangeType.UPDATED;
EDEXUtil.getMessageProducer().sendAsync( EDEXUtil.getMessageProducer().sendAsync(
"utilityNotify", "utilityNotify",
new FileUpdatedMessage(localization, FileUtil.join( new FileUpdatedMessage(localization, fileName, changeType, lf
COMBO_FILE_DIR, request.getFileName()), changeType, .getTimeStamp().getTime()));
localFile.lastModified()));
CombinationsFileChangedNotification notif = new CombinationsFileChangedNotification(
comboName, request.getWorkstationID(), siteID);
SendNotifications.send(notif);
return new ServerResponse<Object>(); return new ServerResponse<Object>();
} }
} }

View file

@ -84,7 +84,7 @@ from com.raytheon.uf.edex.database.cluster import ClusterTask
# 11/05/13 2517 randerso Restructured logging so it coulde be used by WECache # 11/05/13 2517 randerso Restructured logging so it coulde be used by WECache
# Changed WECache to limit the number of cached grids kept in memory # Changed WECache to limit the number of cached grids kept in memory
# 01/09/14 16952 randerso Fix regression made in #2517 which caused errors with overlapping grids # 01/09/14 16952 randerso Fix regression made in #2517 which caused errors with overlapping grids
# # 02/04/14 17042 ryu Check in changes for randerso.
# #
BATCH_DELAY = 0.0 BATCH_DELAY = 0.0
@ -1531,7 +1531,7 @@ class IscMosaic:
smsg, oldEntry, keyentry, ",".join(changedReasons)) smsg, oldEntry, keyentry, ",".join(changedReasons))
msg = "%s %s %s [%s] -> [%s] (%s)" % \ msg = "%s %s %s [%s] -> [%s] (%s)" % \
self.__siteID, parmName, printShortTR(tr), oldEntry, keyentry, ",".join(changedReasons) (self.__siteID, parmName, printShortTR(tr), oldEntry, keyentry, ",".join(changedReasons))
self.__adjDataMsg.append(msg) self.__adjDataMsg.append(msg)
key[idx] = keyentry #store back into list key[idx] = keyentry #store back into list
@ -1631,7 +1631,7 @@ class IscMosaic:
smsg, oldEntry, keyentry, ",".join(changedReasons)) smsg, oldEntry, keyentry, ",".join(changedReasons))
msg = "%s %s %s [%s] -> [%s] (%s)" % \ msg = "%s %s %s [%s] -> [%s] (%s)" % \
self.__siteID, parmName, printShortTR(tr), oldEntry, keyentry, ",".join(changedReasons) (self.__siteID, parmName, printShortTR(tr), oldEntry, keyentry, ",".join(changedReasons))
self.__adjDataMsg.append(msg) self.__adjDataMsg.append(msg)

View file

@ -0,0 +1,83 @@
/**
* 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.gfe.server.notify;
import com.raytheon.uf.common.message.WsId;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* Combinations File Changed Notification
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 5, 2014 #2591 randerso Initial creation
*
* </pre>
*
* @author randerso
* @version 1.0
*/
@DynamicSerialize
public class CombinationsFileChangedNotification extends GfeNotification {
@DynamicSerializeElement
private String combinationsFileName;
@DynamicSerializeElement
private WsId whoChanged;
/**
* default constructor for serialization
*/
public CombinationsFileChangedNotification() {
super();
}
public CombinationsFileChangedNotification(String combinationsFileName,
WsId whoChanged, String siteID) {
super();
this.siteID = siteID;
this.combinationsFileName = combinationsFileName;
this.whoChanged = whoChanged;
}
public String getCombinationsFileName() {
return combinationsFileName;
}
public void setCombinationsFileName(String combinationsFileName) {
this.combinationsFileName = combinationsFileName;
}
public WsId getWhoChanged() {
return whoChanged;
}
public void setWhoChanged(WsId whoChanged) {
this.whoChanged = whoChanged;
}
}

View file

@ -76,6 +76,7 @@ import com.raytheon.uf.edex.database.processor.IDatabaseProcessor;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Dec 10, 2013 2555 rjpeter Initial creation. * Dec 10, 2013 2555 rjpeter Initial creation.
* Jan 23, 2014 2555 rjpeter Updated to be a row at a time using ScrollableResults. * Jan 23, 2014 2555 rjpeter Updated to be a row at a time using ScrollableResults.
* Feb 04, 2014 2770 rferrel The dumpPdos now dumps all PluginDataObjects.
* </pre> * </pre>
* *
* @author rjpeter * @author rjpeter
@ -665,8 +666,11 @@ public class DatabaseArchiveProcessor<T extends PersistableDataObject<?>>
Iterator<PersistableDataObject<?>> pdoIter = pdos.iterator(); Iterator<PersistableDataObject<?>> pdoIter = pdos.iterator();
writer = new BufferedWriter(new FileWriter(dumpFile)); writer = new BufferedWriter(new FileWriter(dumpFile));
statusHandler.info(String.format("%s: Dumping records to: %s",
pluginName, dumpFile.getAbsolutePath())); if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.info(String.format("%s: Dumping records to: %s",
pluginName, dumpFile.getAbsolutePath()));
}
while (pdoIter.hasNext()) { while (pdoIter.hasNext()) {
PersistableDataObject<?> pdo = pdoIter.next(); PersistableDataObject<?> pdo = pdoIter.next();
@ -676,9 +680,11 @@ public class DatabaseArchiveProcessor<T extends PersistableDataObject<?>>
// otherwise was read from file and will be recorded in // otherwise was read from file and will be recorded in
// a previous entry // a previous entry
writer.write("" + pluginDataObject.getId() + ":"); writer.write("" + pluginDataObject.getId() + ":");
writer.write(pluginDataObject.getDataURI()); } else {
writer.write("\n"); writer.write("-:");
} }
writer.write(pluginDataObject.getDataURI());
writer.write("\n");
} else { } else {
writer.write(pdo.getIdentifier().toString()); writer.write(pdo.getIdentifier().toString());
writer.write("\n"); writer.write("\n");

View file

@ -5,7 +5,7 @@
Name: awips2-ant Name: awips2-ant
Summary: AWIPS II Ant Distribution Summary: AWIPS II Ant Distribution
Version: 1.7.1 Version: 1.7.1
Release: 2 Release: 3
Group: AWIPSII Group: AWIPSII
BuildRoot: %{_build_root} BuildRoot: %{_build_root}
BuildArch: noarch BuildArch: noarch

View file

@ -8,10 +8,7 @@ if [ ${RC} -ne 0 ]; then
fi fi
# Determine Where Ant Has Been Installed. # Determine Where Ant Has Been Installed.
ANT_INSTALL=`rpm -q --queryformat '%{INSTALLPREFIX}' awips2-ant` ANT_INSTALL=/awips2/ant
if [ "${ANT_INSTALL}" = "" ]; then
return
fi
# Update The Environment. # Update The Environment.
export ANT_HOME="${ANT_INSTALL}" export ANT_HOME="${ANT_INSTALL}"

View file

@ -410,7 +410,8 @@ fi
if [ "${1}" = "-viz" ]; then if [ "${1}" = "-viz" ]; then
buildRPM "awips2" buildRPM "awips2"
buildRPM "awips2-common-base" buildRPM "awips2-common-base"
buildRPM "awips2-python-numpy" #buildRPM "awips2-python-numpy"
buildRPM "awips2-ant"
#buildRPM "awips2-python-dynamicserialize" #buildRPM "awips2-python-dynamicserialize"
#buildRPM "awips2-python" #buildRPM "awips2-python"
#buildRPM "awips2-adapt-native" #buildRPM "awips2-adapt-native"
@ -421,9 +422,9 @@ if [ "${1}" = "-viz" ]; then
#buildRPM "awips2-httpd-pypies" #buildRPM "awips2-httpd-pypies"
#buildRPM "awips2-hydroapps-shared" #buildRPM "awips2-hydroapps-shared"
#buildRPM "awips2-rcm" #buildRPM "awips2-rcm"
buildRPM "awips2-gfesuite-client" #buildRPM "awips2-gfesuite-client"
buildRPM "awips2-gfesuite-server" #buildRPM "awips2-gfesuite-server"
buildRPM "awips2-tools" #buildRPM "awips2-tools"
#buildRPM "awips2-cli" #buildRPM "awips2-cli"
buildCAVE buildCAVE
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then