Issue #1843: Return status back to client when contacting one of the
configured ETN partners fails. Change-Id: I5bd49f6930c317ba21725ff53f6ab65d548f037c Former-commit-id: 18a09da6aba3caf83f4c4df71f2fcffb63043fb1
This commit is contained in:
parent
62a5739feb
commit
b7b29a1fdb
16 changed files with 1090 additions and 157 deletions
|
@ -31,7 +31,8 @@ Require-Bundle: org.eclipse.ui,
|
|||
com.raytheon.uf.common.python;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
|
||||
com.google.guava;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.style;bundle-version="1.0.0"
|
||||
com.raytheon.uf.common.style;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.activetable
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.raytheon.viz.gfe,
|
||||
com.raytheon.viz.gfe.constants,
|
||||
|
@ -52,8 +53,7 @@ Export-Package: com.raytheon.viz.gfe,
|
|||
com.raytheon.viz.gfe.ui,
|
||||
com.raytheon.viz.gfe.ui.runtimeui,
|
||||
com.raytheon.viz.gfe.ui.zoneselector
|
||||
Import-Package: com.raytheon.uf.common.activetable,
|
||||
com.raytheon.uf.common.dissemination,
|
||||
Import-Package: com.raytheon.uf.common.dissemination,
|
||||
com.raytheon.uf.common.message,
|
||||
com.raytheon.uf.common.python.concurrent,
|
||||
com.raytheon.uf.common.serialization.comm,
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
# ??/??/?? ???????? Initial Creation.
|
||||
# 05/14/13 1842 dgilling Use GFEVtecUtil to handle NEW
|
||||
# ETN assignment.
|
||||
# 09/24/13 1843 dgilling Handle GetNextEtnResponse.
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -713,7 +714,7 @@ class HazardsTable(VTECTableUtil.VTECTableUtil):
|
|||
# Local WFOs do not assign these numbers, so they should have
|
||||
# numbers < 1000
|
||||
if phensig not in self.__tpcKeys or self.__siteID4 in self.__sitesIgnoreNatlEtn:
|
||||
etn_base = GFEVtecUtil.getNextEtn(self.__siteID4, '.'.join(phensig), False) - 1
|
||||
etn_base = GFEVtecUtil.getNextEtn(self.__siteID4, '.'.join(phensig), False).getNextEtn() - 1
|
||||
else:
|
||||
presentyear = time.gmtime(self.__time)[0]
|
||||
for active in activeTable:
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/**
|
||||
* 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.viz.gfe.dialogs.formatterlauncher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Spinner;
|
||||
|
||||
import com.raytheon.uf.common.activetable.response.GetNextEtnResponse;
|
||||
import com.raytheon.viz.ui.dialogs.CaveJFACEDialog;
|
||||
import com.raytheon.viz.ui.dialogs.TextDisplayDlg;
|
||||
import com.raytheon.viz.ui.dialogs.TextDisplayDlg.Location;
|
||||
|
||||
/**
|
||||
* Dialog displayed to manually confirm ETN assignment when backup partners can
|
||||
* not be reached
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Oct 23, 2013 #1843 randerso Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author randerso
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class ETNConfirmationDialog extends CaveJFACEDialog {
|
||||
|
||||
// TODO make this configurable
|
||||
private static final int MAX_ETN_DELTA = 10;
|
||||
|
||||
private String phenSig;
|
||||
|
||||
private int proposedEtn;
|
||||
|
||||
private Map<String, Integer> resultsByHost;
|
||||
|
||||
private List<String> errorMessages;
|
||||
|
||||
private Spinner proposedEtnSpinner;
|
||||
|
||||
/**
|
||||
* Dialog constructor
|
||||
*
|
||||
* @param parentShell
|
||||
* @param etnResponse
|
||||
*/
|
||||
public ETNConfirmationDialog(Shell parentShell,
|
||||
GetNextEtnResponse etnResponse) {
|
||||
super(parentShell);
|
||||
|
||||
this.phenSig = etnResponse.getPhensig();
|
||||
this.proposedEtn = etnResponse.getNextEtn();
|
||||
this.resultsByHost = etnResponse.getResultsByHost();
|
||||
this.errorMessages = etnResponse.getErrorMessages();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets
|
||||
* .Shell)
|
||||
*/
|
||||
@Override
|
||||
protected void configureShell(Shell newShell) {
|
||||
newShell.setText("Confirm ETN for " + this.phenSig);
|
||||
super.configureShell(newShell);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.ui.dialogs.CaveJFACEDialog#createDialogArea(org.eclipse
|
||||
* .swt.widgets.Composite)
|
||||
*/
|
||||
@Override
|
||||
protected Control createDialogArea(Composite parent) {
|
||||
Composite top = (Composite) super.createDialogArea(parent);
|
||||
GridLayout layout = (GridLayout) top.getLayout();
|
||||
layout.numColumns = 2;
|
||||
|
||||
Label label = new Label(top, SWT.LEFT);
|
||||
GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
|
||||
label.setLayoutData(layoutData);
|
||||
label.setText("Proposed ETN for " + this.phenSig + ":");
|
||||
|
||||
proposedEtnSpinner = new Spinner(top, SWT.BORDER);
|
||||
layoutData = new GridData(SWT.FILL, SWT.CENTER, false, false);
|
||||
proposedEtnSpinner.setLayoutData(layoutData);
|
||||
proposedEtnSpinner.setValues(this.proposedEtn, this.proposedEtn,
|
||||
this.proposedEtn + MAX_ETN_DELTA, 0, 1, 1);
|
||||
|
||||
Group group = new Group(top, SWT.NONE);
|
||||
layout = new GridLayout(2, false);
|
||||
group.setLayout(layout);
|
||||
layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
|
||||
layoutData.horizontalSpan = 2;
|
||||
group.setLayoutData(layoutData);
|
||||
group.setText("Partner ETNs");
|
||||
|
||||
for (Entry<String, Integer> entry : this.resultsByHost.entrySet()) {
|
||||
Label host = new Label(group, SWT.LEFT);
|
||||
layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
|
||||
host.setLayoutData(layoutData);
|
||||
host.setText(entry.getKey());
|
||||
|
||||
Label etn = new Label(group, SWT.RIGHT);
|
||||
layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
|
||||
etn.setLayoutData(layoutData);
|
||||
String text = entry.getValue() == null ? "ERR" : entry.getValue()
|
||||
.toString();
|
||||
etn.setText(text);
|
||||
}
|
||||
|
||||
final Button showErrors = new Button(top, SWT.PUSH);
|
||||
layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
|
||||
layoutData.horizontalSpan = 2;
|
||||
showErrors.setLayoutData(layoutData);
|
||||
showErrors.setText("Show Errors");
|
||||
showErrors.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
|
||||
* .swt.events.SelectionEvent)
|
||||
*/
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
showErrors.setEnabled(false);
|
||||
StringBuilder errorText = new StringBuilder();
|
||||
for (String s : errorMessages) {
|
||||
errorText.append(s).append('\n');
|
||||
}
|
||||
TextDisplayDlg errorDlg = new TextDisplayDlg(
|
||||
ETNConfirmationDialog.this.getShell(), "Errors",
|
||||
errorText.toString(), Location.BELOW);
|
||||
|
||||
errorDlg.open();
|
||||
showErrors.setEnabled(true);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse
|
||||
* .swt.widgets.Composite)
|
||||
*/
|
||||
@Override
|
||||
protected void createButtonsForButtonBar(Composite parent) {
|
||||
super.createButtonsForButtonBar(parent);
|
||||
getButton(IDialogConstants.OK_ID).setText("Transmit");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.jface.dialogs.Dialog#okPressed()
|
||||
*/
|
||||
@Override
|
||||
protected void okPressed() {
|
||||
this.proposedEtn = this.proposedEtnSpinner.getSelection();
|
||||
super.okPressed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the proposedEtn
|
||||
*/
|
||||
public int getProposedEtn() {
|
||||
return proposedEtn;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,9 @@
|
|||
package com.raytheon.viz.gfe.dialogs.formatterlauncher;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
|
@ -37,6 +40,7 @@ import org.eclipse.swt.widgets.Text;
|
|||
|
||||
import com.raytheon.uf.common.activetable.PracticeProductOfftimeRequest;
|
||||
import com.raytheon.uf.common.activetable.SendPracticeProductRequest;
|
||||
import com.raytheon.uf.common.activetable.response.GetNextEtnResponse;
|
||||
import com.raytheon.uf.common.dissemination.OUPRequest;
|
||||
import com.raytheon.uf.common.dissemination.OUPResponse;
|
||||
import com.raytheon.uf.common.dissemination.OfficialUserProduct;
|
||||
|
@ -52,6 +56,7 @@ import com.raytheon.uf.viz.core.requests.ThriftClient;
|
|||
import com.raytheon.viz.core.mode.CAVEMode;
|
||||
import com.raytheon.viz.gfe.product.TextDBUtil;
|
||||
import com.raytheon.viz.gfe.vtec.GFEVtecUtil;
|
||||
import com.raytheon.viz.texteditor.util.VtecObject;
|
||||
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
||||
|
||||
/**
|
||||
|
@ -70,6 +75,9 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
|||
* 08 MAY 2013 1842 dgilling Use VtecUtil to set product ETNs, fix
|
||||
* warnings.
|
||||
* 07 Jun 2013 1981 mpduff Set user's id in OUPRequest as it is now a protected operation.
|
||||
* 23 Oct 2013 1843 dgilling Ensure that dialog is always closed,
|
||||
* even on failure, changes for error handling
|
||||
* of intersite ETN assignment.
|
||||
* </pre>
|
||||
*
|
||||
* @author lvenable
|
||||
|
@ -334,46 +342,116 @@ public class StoreTransmitDlg extends CaveSWTDialog implements
|
|||
// Store/Transmit the product...
|
||||
|
||||
if (!countdownThread.threadCancelled()) {
|
||||
boolean retrieveEtnFailed = false;
|
||||
|
||||
try {
|
||||
productText = GFEVtecUtil.finalizeETNs(productText);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.CRITICAL,
|
||||
"Error setting ETNs for product", e);
|
||||
sendTransmissionStatus(ConfigData.productStateEnum.Failed);
|
||||
VizApp.runAsync(new Runnable() {
|
||||
Set<VtecObject> vtecsToAssignEtn = GFEVtecUtil
|
||||
.getVtecLinesThatNeedEtn(productText);
|
||||
Map<String, Integer> etnCache = new HashMap<String, Integer>();
|
||||
|
||||
for (VtecObject vtec : vtecsToAssignEtn) {
|
||||
try {
|
||||
GetNextEtnResponse serverResponse = GFEVtecUtil.getNextEtn(
|
||||
vtec.getOffice(), vtec.getPhensig(), true, true);
|
||||
if (!serverResponse.isOkay()) {
|
||||
final VtecObject vtecToFix = vtec;
|
||||
final boolean[] exitLoopContainer = { false };
|
||||
final Exception[] exceptionContainer = { null };
|
||||
final GetNextEtnResponse[] responseContainer = { serverResponse };
|
||||
|
||||
do {
|
||||
getDisplay().syncExec(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GetNextEtnResponse serverResponse = responseContainer[0];
|
||||
ETNConfirmationDialog dlg = new ETNConfirmationDialog(
|
||||
getShell(), serverResponse);
|
||||
if (dlg.open() == ETNConfirmationDialog.OK) {
|
||||
int etn = dlg.getProposedEtn();
|
||||
statusHandler.info(String
|
||||
.format("User confirmed ETN for %s: %04d",
|
||||
serverResponse
|
||||
.getPhensig(),
|
||||
etn));
|
||||
try {
|
||||
GetNextEtnResponse followupResp = GFEVtecUtil.getNextEtn(
|
||||
vtecToFix.getOffice(),
|
||||
vtecToFix.getPhensig(),
|
||||
true, true, true, etn);
|
||||
responseContainer[0] = followupResp;
|
||||
} catch (VizException e) {
|
||||
exceptionContainer[0] = e;
|
||||
exitLoopContainer[0] = true;
|
||||
}
|
||||
} else {
|
||||
statusHandler
|
||||
.info("User declined to fix ETN for %s",
|
||||
serverResponse
|
||||
.getPhensig());
|
||||
exitLoopContainer[0] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
} while (!responseContainer[0].isOkay()
|
||||
&& !exitLoopContainer[0]);
|
||||
|
||||
if (!responseContainer[0].isOkay()) {
|
||||
String msg = "Unable to set ETN for phensig "
|
||||
+ responseContainer[0].getPhensig()
|
||||
+ "\nStatus: "
|
||||
+ responseContainer[0].toString();
|
||||
Exception e = exceptionContainer[0];
|
||||
if (e == null) {
|
||||
throw new VizException(msg);
|
||||
} else {
|
||||
throw new VizException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
etnCache.put(vtec.getPhensig(), serverResponse.getNextEtn());
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.CRITICAL,
|
||||
"Error setting ETNs for product", e);
|
||||
retrieveEtnFailed = true;
|
||||
VizApp.runAsync(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
sendTransmissionStatus(ConfigData.productStateEnum.Failed);
|
||||
StoreTransmitDlg.this.parentEditor.revive();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!retrieveEtnFailed) {
|
||||
productText = GFEVtecUtil.finalizeETNs(productText, etnCache);
|
||||
|
||||
VizApp.runSync(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
StoreTransmitDlg.this.parentEditor.revive();
|
||||
String pid = productIdTF.getText();
|
||||
if (parentEditor.isTestVTEC()) {
|
||||
if (isStoreDialog) {
|
||||
parentEditor.devStore(pid.substring(3));
|
||||
} else {
|
||||
parentEditor.devStore(pid.substring(4));
|
||||
transmitProduct(true);
|
||||
}
|
||||
} else {
|
||||
if (isStoreDialog) {
|
||||
TextDBUtil.storeProduct(pid, productText,
|
||||
parentEditor.isTestVTEC());
|
||||
} else {
|
||||
transmitProduct(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
VizApp.runSync(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
String pid = productIdTF.getText();
|
||||
if (parentEditor.isTestVTEC()) {
|
||||
if (isStoreDialog) {
|
||||
parentEditor.devStore(pid.substring(3));
|
||||
} else {
|
||||
parentEditor.devStore(pid.substring(4));
|
||||
transmitProduct(true);
|
||||
}
|
||||
} else {
|
||||
if (isStoreDialog) {
|
||||
TextDBUtil.storeProduct(pid, productText,
|
||||
parentEditor.isTestVTEC());
|
||||
} else {
|
||||
transmitProduct(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// The asyncExec call is used to dispose of the shell since it is
|
||||
|
|
|
@ -20,12 +20,15 @@
|
|||
package com.raytheon.viz.gfe.vtec;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.raytheon.uf.common.activetable.response.GetNextEtnResponse;
|
||||
import com.raytheon.uf.common.util.StringUtil;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.viz.texteditor.util.VtecObject;
|
||||
import com.raytheon.viz.texteditor.util.VtecUtil;
|
||||
|
@ -50,6 +53,7 @@ import com.raytheon.viz.texteditor.util.VtecUtil;
|
|||
* multiple NEW segments with the same
|
||||
* phensig.
|
||||
* Aug 29, 2013 #1843 dgilling Add hooks for inter-site ETN assignment.
|
||||
* Oct 21, 2013 #1843 dgilling Use new GetNextEtnResponse.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -78,29 +82,152 @@ public class GFEVtecUtil {
|
|||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static int getNextEtn(String office, String phensig, boolean lockEtn)
|
||||
throws VizException {
|
||||
return getNextEtn(office, phensig, lockEtn, false);
|
||||
/**
|
||||
* Gets the next available ETN for a specific product and office.
|
||||
*
|
||||
* @param office
|
||||
* The 4-character site ID of the office.
|
||||
* @param phensig
|
||||
* The phenomenon and significance of the hazard concatenated
|
||||
* with a '.' (e.g., TO.W or DU.Y)
|
||||
* @param lockEtn
|
||||
* Whether or not to request an exclusive ETN--if true, this will
|
||||
* cause the server to increment its running ETN sequence to the
|
||||
* next number after determining the next ETN for this request.
|
||||
* If false, the next ETN will be returned, but it will not
|
||||
* increment the server's running sequence, so the ETN return
|
||||
* could be used by another client that makes a
|
||||
* GetNextEtnRequest.
|
||||
* @return The next ETN in sequence, given the office and phensig.
|
||||
* @throws VizException
|
||||
* If an error occurred sending the request to the server.
|
||||
*/
|
||||
public static GetNextEtnResponse getNextEtn(String office, String phensig,
|
||||
boolean lockEtn) throws VizException {
|
||||
return getNextEtn(office, phensig, lockEtn, false, false, null);
|
||||
}
|
||||
|
||||
public static int getNextEtn(String office, String phensig,
|
||||
/**
|
||||
* Gets the next available ETN for a specific product and office.
|
||||
*
|
||||
* @param office
|
||||
* The 4-character site ID of the office.
|
||||
* @param phensig
|
||||
* The phenomenon and significance of the hazard concatenated
|
||||
* with a '.' (e.g., TO.W or DU.Y)
|
||||
* @param lockEtn
|
||||
* Whether or not to request an exclusive ETN--if true, this will
|
||||
* cause the server to increment its running ETN sequence to the
|
||||
* next number after determining the next ETN for this request.
|
||||
* If false, the next ETN will be returned, but it will not
|
||||
* increment the server's running sequence, so the ETN return
|
||||
* could be used by another client that makes a
|
||||
* GetNextEtnRequest.
|
||||
* @param performISC
|
||||
* Whether or not to collaborate with neighboring sites to
|
||||
* determine the next ETN. See {@link
|
||||
* GetNextEtnUtil#getNextEtnFromPartners(String, ActiveTableMode,
|
||||
* String, Calendar, List<IRequestRouter>)} for more information.
|
||||
* @return The next ETN in sequence, given the office and phensig.
|
||||
* @throws VizException
|
||||
* If an error occurred sending the request to the server.
|
||||
*/
|
||||
public static GetNextEtnResponse getNextEtn(String office, String phensig,
|
||||
boolean lockEtn, boolean performISC) throws VizException {
|
||||
return VtecUtil.getNextEtn(office, phensig, lockEtn, performISC);
|
||||
return getNextEtn(office, phensig, lockEtn, performISC, false, null);
|
||||
}
|
||||
|
||||
public static String finalizeETNs(String message) throws VizException {
|
||||
if (Strings.isNullOrEmpty(message)) {
|
||||
return message;
|
||||
/**
|
||||
* Gets the next available ETN for a specific product and office.
|
||||
*
|
||||
* @param office
|
||||
* The 4-character site ID of the office.
|
||||
* @param phensig
|
||||
* The phenomenon and significance of the hazard concatenated
|
||||
* with a '.' (e.g., TO.W or DU.Y)
|
||||
* @param lockEtn
|
||||
* Whether or not to request an exclusive ETN--if true, this will
|
||||
* cause the server to increment its running ETN sequence to the
|
||||
* next number after determining the next ETN for this request.
|
||||
* If false, the next ETN will be returned, but it will not
|
||||
* increment the server's running sequence, so the ETN return
|
||||
* could be used by another client that makes a
|
||||
* GetNextEtnRequest.
|
||||
* @param performISC
|
||||
* Whether or not to collaborate with neighboring sites to
|
||||
* determine the next ETN. See {@link
|
||||
* GetNextEtnUtil#getNextEtnFromPartners(String, ActiveTableMode,
|
||||
* String, Calendar, List<IRequestRouter>)} for more information.
|
||||
* @param reportOnlyConflict
|
||||
* Affects which kinds of errors get reported back to the
|
||||
* requestor. If true, only cases where the value of
|
||||
* <code>etnOverride</code> is less than or equal to the last ETN
|
||||
* used by this site or any of its partners will be reported.
|
||||
* Else, all significant errors will be reported back.
|
||||
* @param etnOverride
|
||||
* Allows the user to influence the next ETN assigned by using
|
||||
* this value unless it is less than or equal to the last ETN
|
||||
* used by this site or one of its partners.
|
||||
* @return The next ETN in sequence, given the office and phensig.
|
||||
* @throws VizException
|
||||
* If an error occurred sending the request to the server.
|
||||
*/
|
||||
public static GetNextEtnResponse getNextEtn(String office, String phensig,
|
||||
boolean lockEtn, boolean performISC, boolean reportOnlyConflict,
|
||||
Integer etnOverride) throws VizException {
|
||||
return VtecUtil.getNextEtn(office, phensig, lockEtn, performISC,
|
||||
reportOnlyConflict, etnOverride);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads through a GFE VTEC product and returns VTEC lines with NEW action
|
||||
* codes that need to be assigned an ETN.
|
||||
*
|
||||
* @param product
|
||||
* The product's text.
|
||||
* @return A <code>Set</code> of <code>VtecObject</code>s that need to have
|
||||
* a new ETN assigned to them.
|
||||
*/
|
||||
public static Set<VtecObject> getVtecLinesThatNeedEtn(String product) {
|
||||
if (StringUtil.isEmptyString(product)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
// With GFE VTEC products, it's possible to have multiple segments with
|
||||
// NEW vtec action codes and the same phensig. For this reason,
|
||||
// HazardsTable.py implemented a "cache" that would ensure all NEWs for
|
||||
// the same phensig would be assigned the same ETN. This Map replicates
|
||||
// that legacy behavior.
|
||||
Map<String, Integer> etnCache = new HashMap<String, Integer>();
|
||||
Set<VtecObject> phensigs = new HashSet<VtecObject>();
|
||||
|
||||
Matcher vtecMatcher = VtecUtil.VTEC_REGEX.matcher(message);
|
||||
Matcher vtecMatcher = VtecUtil.VTEC_REGEX.matcher(product);
|
||||
while (vtecMatcher.find()) {
|
||||
VtecObject vtec = new VtecObject(vtecMatcher.group());
|
||||
if (("NEW".equals(vtec.getAction()))
|
||||
&& ((!NATIONAL_PHENSIGS.contains(vtec.getPhensig())) || (IGNORE_NATIONAL_ETN
|
||||
.contains(vtec.getOffice()) && TROPICAL_PHENSIGS
|
||||
.contains(vtec.getPhensig())))) {
|
||||
phensigs.add(vtec);
|
||||
}
|
||||
}
|
||||
|
||||
return phensigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* For any NEW VTEC lines contained within the specified product texts,
|
||||
* generates a <code>GetNextEtnRequest</code> to retrieve the next canonical
|
||||
* ETN in sequence for the given phensig.
|
||||
*
|
||||
* @param product
|
||||
* The product's text.
|
||||
* @return The product's text with any NEW VTEC lines having their ETN
|
||||
* values replaced with the next ETN in sequence.
|
||||
* @throws VizException
|
||||
* If an error occurred sending the request to the server.
|
||||
*/
|
||||
public static String finalizeETNs(String product,
|
||||
Map<String, Integer> etnCache) {
|
||||
if (StringUtil.isEmptyString(product)) {
|
||||
return product;
|
||||
}
|
||||
|
||||
Matcher vtecMatcher = VtecUtil.VTEC_REGEX.matcher(product);
|
||||
StringBuffer finalOutput = new StringBuffer();
|
||||
while (vtecMatcher.find()) {
|
||||
VtecObject vtec = new VtecObject(vtecMatcher.group());
|
||||
|
@ -111,13 +238,13 @@ public class GFEVtecUtil {
|
|||
&& ((!NATIONAL_PHENSIGS.contains(vtec.getPhensig())) || (IGNORE_NATIONAL_ETN
|
||||
.contains(vtec.getOffice()) && TROPICAL_PHENSIGS
|
||||
.contains(vtec.getPhensig())))) {
|
||||
// With GFE VTEC products, it's possible to have multiple
|
||||
// segments with NEW vtec action codes and the same phensig. For
|
||||
// this reason, HazardsTable.py implemented a "cache" that would
|
||||
// ensure all NEWs for the same phensig would be assigned the
|
||||
// same ETN. The etnCache Map replicaes this behavior.
|
||||
String cacheKey = vtec.getPhensig();
|
||||
Integer newEtn = etnCache.get(cacheKey);
|
||||
if (newEtn == null) {
|
||||
newEtn = getNextEtn(vtec.getOffice(), vtec.getPhensig(),
|
||||
true, true);
|
||||
etnCache.put(cacheKey, newEtn);
|
||||
}
|
||||
vtec.setSequence(newEtn);
|
||||
}
|
||||
vtecMatcher
|
||||
|
|
|
@ -25,7 +25,8 @@ Require-Bundle: org.eclipse.ui,
|
|||
com.raytheon.uf.common.dataplugin.radar;bundle-version="1.0.0",
|
||||
com.raytheon.uf.viz.localization,
|
||||
com.raytheon.uf.common.auth;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.dataplugin.warning;bundle-version="1.12.1174"
|
||||
com.raytheon.uf.common.dataplugin.warning;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.activetable
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.raytheon.viz.texteditor,
|
||||
com.raytheon.viz.texteditor.alarmalert.dialogs,
|
||||
|
@ -38,8 +39,7 @@ Export-Package: com.raytheon.viz.texteditor,
|
|||
com.raytheon.viz.texteditor.scripting.runner,
|
||||
com.raytheon.viz.texteditor.util
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Import-Package: com.raytheon.uf.common.activetable,
|
||||
com.raytheon.uf.common.comm,
|
||||
Import-Package: com.raytheon.uf.common.comm,
|
||||
com.raytheon.uf.common.dataplugin.warning.util,
|
||||
com.raytheon.uf.common.dissemination,
|
||||
com.raytheon.uf.common.message,
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
import com.raytheon.uf.common.activetable.ActiveTableMode;
|
||||
import com.raytheon.uf.common.activetable.GetNextEtnRequest;
|
||||
import com.raytheon.uf.common.activetable.response.GetNextEtnResponse;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
||||
|
@ -44,6 +45,7 @@ import com.raytheon.viz.core.mode.CAVEMode;
|
|||
* Feb 09, 2009 bwoodle Initial creation
|
||||
* May 08, 2013 #1842 dgilling Code cleanup.
|
||||
* Aug 29, 2013 #1843 dgilling Use new GetNextEtnRequest constructor.
|
||||
* Oct 21, 2013 #1843 dgilling Use new GetNextEtnResponse.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -106,8 +108,10 @@ public class VtecUtil {
|
|||
}
|
||||
|
||||
if (vtec.getAction().equals("NEW")) {
|
||||
vtec.setSequence(getNextEtn(vtec.getOffice(), vtec.getPhenomena()
|
||||
+ "." + vtec.getSignificance(), lockEtn));
|
||||
int nextEtn = getNextEtn(vtec.getOffice(),
|
||||
vtec.getPhenomena() + "." + vtec.getSignificance(), lockEtn)
|
||||
.getNextEtn();
|
||||
vtec.setSequence(nextEtn);
|
||||
}
|
||||
return replaceFirstVtecString(message, vtec);
|
||||
}
|
||||
|
@ -133,9 +137,9 @@ public class VtecUtil {
|
|||
* If an error occurs while submitting or processing the remote
|
||||
* request.
|
||||
*/
|
||||
public static int getNextEtn(String office, String phensig, boolean lockEtn)
|
||||
throws VizException {
|
||||
return getNextEtn(office, phensig, lockEtn, false);
|
||||
public static GetNextEtnResponse getNextEtn(String office, String phensig,
|
||||
boolean lockEtn) throws VizException {
|
||||
return getNextEtn(office, phensig, lockEtn, false, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,26 +163,37 @@ public class VtecUtil {
|
|||
* determine the next ETN. See {@link
|
||||
* GetNextEtnUtil#getNextEtnFromPartners(String, ActiveTableMode,
|
||||
* String, Calendar, List<IRequestRouter>)} for more information.
|
||||
* @param reportOnlyConflict
|
||||
* Affects which kinds of errors get reported back to the
|
||||
* requestor. If true, only cases where the value of
|
||||
* <code>etnOverride</code> is less than or equal to the last ETN
|
||||
* used by this site or any of its partners will be reported.
|
||||
* Else, all significant errors will be reported back.
|
||||
* @param etnOverride
|
||||
* Allows the user to influence the next ETN assigned by using
|
||||
* this value unless it is less than or equal to the last ETN
|
||||
* used by this site or one of its partners.
|
||||
* @return The next ETN in sequence, given the office and phensig.
|
||||
* @throws VizException
|
||||
* If an error occurs while submitting or processing the remote
|
||||
* request.
|
||||
*/
|
||||
public static int getNextEtn(String office, String phensig,
|
||||
boolean lockEtn, boolean performISC) throws VizException {
|
||||
public static GetNextEtnResponse getNextEtn(String office, String phensig,
|
||||
boolean lockEtn, boolean performISC, boolean reportOnlyConflict,
|
||||
Integer etnOverride) throws VizException {
|
||||
Calendar currentTime = Calendar.getInstance();
|
||||
currentTime.setTime(SimulatedTime.getSystemTime().getTime());
|
||||
ActiveTableMode activeTable = (CAVEMode.getMode()
|
||||
.equals(CAVEMode.PRACTICE)) ? ActiveTableMode.PRACTICE
|
||||
: ActiveTableMode.OPERATIONAL;
|
||||
GetNextEtnRequest req = new GetNextEtnRequest(office, activeTable,
|
||||
phensig, currentTime, lockEtn, performISC);
|
||||
phensig, currentTime, lockEtn, performISC, reportOnlyConflict,
|
||||
etnOverride);
|
||||
|
||||
int rval = 1;
|
||||
Integer resp = (Integer) ThriftClient.sendRequest(req);
|
||||
if (resp != null) {
|
||||
rval = resp;
|
||||
}
|
||||
GetNextEtnResponse resp = (GetNextEtnResponse) ThriftClient
|
||||
.sendRequest(req);
|
||||
GetNextEtnResponse rval = (resp != null) ? resp
|
||||
: new GetNextEtnResponse(1, phensig);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* 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.viz.ui.dialogs;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
/**
|
||||
* Generic <code>Dialog</code> to display a multi-line block of text in a
|
||||
* re-sizable and scrollable window.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Oct 23, 2013 #1843 randerso Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author randerso
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TextDisplayDlg extends CaveJFACEDialog {
|
||||
|
||||
/**
|
||||
* Location of this dialog relative to it's parent.
|
||||
*/
|
||||
public static enum Location {
|
||||
ABOVE, BELOW, LEFT, RIGHT, CENTERED
|
||||
}
|
||||
|
||||
private String title;
|
||||
|
||||
private String contents;
|
||||
|
||||
private Location location;
|
||||
|
||||
/**
|
||||
* @param parentShell
|
||||
* @param title
|
||||
* @param contents
|
||||
*/
|
||||
public TextDisplayDlg(Shell parentShell, String title, String contents,
|
||||
Location location) {
|
||||
super(parentShell);
|
||||
this.title = title;
|
||||
this.contents = contents;
|
||||
this.location = location;
|
||||
|
||||
this.setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets
|
||||
* .Shell)
|
||||
*/
|
||||
@Override
|
||||
protected void configureShell(Shell newShell) {
|
||||
newShell.setText(this.title);
|
||||
super.configureShell(newShell);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.ui.dialogs.CaveJFACEDialog#createDialogArea(org.eclipse
|
||||
* .swt.widgets.Composite)
|
||||
*/
|
||||
@Override
|
||||
protected Control createDialogArea(Composite parent) {
|
||||
Composite top = (Composite) super.createDialogArea(parent);
|
||||
|
||||
Text contents = new Text(top, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY
|
||||
| SWT.V_SCROLL | SWT.H_SCROLL);
|
||||
|
||||
Rectangle screenBounds = this.getShell().getMonitor().getBounds();
|
||||
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
layoutData.widthHint = screenBounds.width / 2;
|
||||
layoutData.heightHint = screenBounds.height / 4;
|
||||
|
||||
contents.setLayoutData(layoutData);
|
||||
contents.setText(this.contents);
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.jface.dialogs.Dialog#getInitialLocation(org.eclipse.swt.graphics
|
||||
* .Point)
|
||||
*/
|
||||
@Override
|
||||
protected Point getInitialLocation(Point initialSize) {
|
||||
Rectangle parentBounds = getParentShell().getBounds();
|
||||
Rectangle myBounds = getShell().getBounds();
|
||||
|
||||
int x = parentBounds.x + ((parentBounds.width - myBounds.width) / 2);
|
||||
int y = parentBounds.y + ((parentBounds.height - myBounds.height) / 2);
|
||||
;
|
||||
switch (this.location) {
|
||||
case ABOVE:
|
||||
y = parentBounds.y - myBounds.height;
|
||||
break;
|
||||
case BELOW:
|
||||
y = parentBounds.y + parentBounds.height;
|
||||
break;
|
||||
case LEFT:
|
||||
x = parentBounds.x - myBounds.width;
|
||||
break;
|
||||
case RIGHT:
|
||||
x = parentBounds.x + parentBounds.width;
|
||||
break;
|
||||
case CENTERED:
|
||||
break;
|
||||
}
|
||||
|
||||
Point location = new Point(x, y);
|
||||
return location;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.ui.dialogs.CaveJFACEDialog#createButtonBar(org.eclipse
|
||||
* .swt.widgets.Composite)
|
||||
*/
|
||||
@Override
|
||||
protected Control createButtonBar(Composite parent) {
|
||||
// no buttons
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,4 +21,5 @@ Require-Bundle: com.raytheon.uf.common.serialization,
|
|||
com.raytheon.uf.common.message;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.python;bundle-version="1.12.1174",
|
||||
org.jep;bundle-version="1.0.0"
|
||||
org.jep;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.util;bundle-version="1.12.1174"
|
||||
|
|
|
@ -34,7 +34,8 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 14, 2011 rjpeter Initial creation
|
||||
* Aug 26, 2013 #1843 dgilling Add performISC field, proper constructors.
|
||||
* Oct 21, 2013 #1843 dgilling Add performISC and reportConflictOnly
|
||||
* fields, proper constructors.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -62,39 +63,89 @@ public class GetNextEtnRequest implements IServerRequest {
|
|||
@DynamicSerializeElement
|
||||
private boolean performISC;
|
||||
|
||||
@DynamicSerializeElement
|
||||
private boolean reportConflictOnly;
|
||||
|
||||
@DynamicSerializeElement
|
||||
private Integer etnOverride;
|
||||
|
||||
public GetNextEtnRequest() {
|
||||
// no-op, for dynamic serialize support
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GetNextEtnRequest.
|
||||
*
|
||||
* @param siteID
|
||||
* The 4-character site ID of the office.
|
||||
* @param mode
|
||||
* Active table mode.
|
||||
* @param phensig
|
||||
* The phenomenon and significance of the hazard concatenated
|
||||
* with a '.' (e.g., TO.W or DU.Y)
|
||||
* @param currentTime
|
||||
* <code>Calendar</code> representing time (needed for DRT mode).
|
||||
* @param lockEtn
|
||||
* Whether or not to request an exclusive ETN--if true, this will
|
||||
* cause the server to increment its running ETN sequence to the
|
||||
* next number after determining the next ETN for this request.
|
||||
* If false, the next ETN will be returned, but it will not
|
||||
* increment the server's running sequence, so the ETN return
|
||||
* could be used by another client that makes a
|
||||
* GetNextEtnRequest.
|
||||
*/
|
||||
public GetNextEtnRequest(String siteID, ActiveTableMode mode,
|
||||
String phensig, Calendar currentTime, boolean lockEtn) {
|
||||
this(siteID, mode, phensig, currentTime, lockEtn, false);
|
||||
this(siteID, mode, phensig, currentTime, lockEtn, false, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GetNextEtnRequest.
|
||||
*
|
||||
* @param siteID
|
||||
* The 4-character site ID of the office.
|
||||
* @param mode
|
||||
* Active table mode.
|
||||
* @param phensig
|
||||
* The phenomenon and significance of the hazard concatenated
|
||||
* with a '.' (e.g., TO.W or DU.Y)
|
||||
* @param currentTime
|
||||
* <code>Calendar</code> representing time (needed for DRT mode).
|
||||
* @param lockEtn
|
||||
* Whether or not to request an exclusive ETN--if true, this will
|
||||
* cause the server to increment its running ETN sequence to the
|
||||
* next number after determining the next ETN for this request.
|
||||
* If false, the next ETN will be returned, but it will not
|
||||
* increment the server's running sequence, so the ETN return
|
||||
* could be used by another client that makes a
|
||||
* GetNextEtnRequest.
|
||||
* @param performISC
|
||||
* Whether or not to collaborate with neighboring sites to
|
||||
* determine the next ETN. See {@link
|
||||
* GetNextEtnUtil#getNextEtnFromPartners(String, ActiveTableMode,
|
||||
* String, Calendar, List<IRequestRouter>)} for more information.
|
||||
* @param reportConflictOnly
|
||||
* Affects which kinds of errors get reported back to the
|
||||
* requestor. If true, only cases where the value of
|
||||
* <code>etnOverride</code> is less than or equal to the last ETN
|
||||
* used by this site or any of its partners will be reported.
|
||||
* Else, all significant errors will be reported back.
|
||||
* @param etnOverride
|
||||
* Allows the user to influence the next ETN assigned by using
|
||||
* this value unless it is less than or equal to the last ETN
|
||||
* used by this site or one of its partners.
|
||||
*/
|
||||
public GetNextEtnRequest(String siteID, ActiveTableMode mode,
|
||||
String phensig, Calendar currentTime, boolean lockEtn,
|
||||
boolean performISC) {
|
||||
boolean performISC, boolean reportConflictOnly, Integer etnOverride) {
|
||||
this.siteID = siteID;
|
||||
this.mode = mode;
|
||||
this.phensig = phensig;
|
||||
this.currentTime = currentTime;
|
||||
this.lockEtn = lockEtn;
|
||||
this.performISC = performISC;
|
||||
this.reportConflictOnly = reportConflictOnly;
|
||||
this.etnOverride = etnOverride;
|
||||
}
|
||||
|
||||
public String getSiteID() {
|
||||
|
@ -144,4 +195,20 @@ public class GetNextEtnRequest implements IServerRequest {
|
|||
public void setPerformISC(boolean performISC) {
|
||||
this.performISC = performISC;
|
||||
}
|
||||
|
||||
public boolean isReportConflictOnly() {
|
||||
return reportConflictOnly;
|
||||
}
|
||||
|
||||
public void setReportConflictOnly(boolean reportConflictOnly) {
|
||||
this.reportConflictOnly = reportConflictOnly;
|
||||
}
|
||||
|
||||
public Integer getEtnOverride() {
|
||||
return etnOverride;
|
||||
}
|
||||
|
||||
public void setEtnOverride(Integer etnOverride) {
|
||||
this.etnOverride = etnOverride;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 19, 2013 #1843 dgilling Initial creation
|
||||
* Oct 21, 2013 #1843 dgilling Add ETN override field.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -61,17 +62,27 @@ public class LockAndGetNextEtnRequest implements IServerRequest {
|
|||
@DynamicSerializeElement
|
||||
private Calendar currentTime;
|
||||
|
||||
@DynamicSerializeElement
|
||||
private Integer etnOverride;
|
||||
|
||||
public LockAndGetNextEtnRequest() {
|
||||
// default constructor for thrift/dynamicserialize
|
||||
}
|
||||
|
||||
public LockAndGetNextEtnRequest(String siteID, String requestorSiteID,
|
||||
ActiveTableMode mode, String phensig, Calendar currentTime) {
|
||||
this(siteID, requestorSiteID, mode, phensig, currentTime, null);
|
||||
}
|
||||
|
||||
public LockAndGetNextEtnRequest(String siteID, String requestorSiteID,
|
||||
ActiveTableMode mode, String phensig, Calendar currentTime,
|
||||
Integer etnOverride) {
|
||||
this.siteID = siteID;
|
||||
this.requestorSiteID = requestorSiteID;
|
||||
this.mode = mode;
|
||||
this.phensig = phensig;
|
||||
this.currentTime = currentTime;
|
||||
this.etnOverride = etnOverride;
|
||||
}
|
||||
|
||||
public String getSiteID() {
|
||||
|
@ -113,4 +124,12 @@ public class LockAndGetNextEtnRequest implements IServerRequest {
|
|||
public void setCurrentTime(Calendar currentTime) {
|
||||
this.currentTime = currentTime;
|
||||
}
|
||||
|
||||
public Integer getEtnOverride() {
|
||||
return etnOverride;
|
||||
}
|
||||
|
||||
public void setEtnOverride(Integer etnOverride) {
|
||||
this.etnOverride = etnOverride;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.common.activetable.response;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
|
||||
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
|
||||
import com.raytheon.uf.common.util.CollectionUtil;
|
||||
import com.raytheon.uf.common.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Response type for <code>GetNextEtnRequest</code>. Contains the next ETN to
|
||||
* use and a list of hosts that could not be contacted during the process to
|
||||
* determine the next ETN.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Oct 24, 2013 #1843 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
@DynamicSerialize
|
||||
public final class GetNextEtnResponse {
|
||||
|
||||
@DynamicSerializeElement
|
||||
private int nextEtn;
|
||||
|
||||
@DynamicSerializeElement
|
||||
private String phensig;
|
||||
|
||||
@DynamicSerializeElement
|
||||
private Map<String, Integer> resultsByHost;
|
||||
|
||||
@DynamicSerializeElement
|
||||
private List<String> errorMessages;
|
||||
|
||||
public GetNextEtnResponse() {
|
||||
// for Dynamic Serialize use only.
|
||||
}
|
||||
|
||||
public GetNextEtnResponse(int nextEtn, String phensig) {
|
||||
this(nextEtn, phensig, new HashMap<String, Integer>(),
|
||||
new ArrayList<String>());
|
||||
this.resultsByHost.put("localhost", this.nextEtn);
|
||||
}
|
||||
|
||||
public GetNextEtnResponse(int nextEtn, String phensig,
|
||||
Map<String, Integer> resultsByHost, List<String> errorMessages) {
|
||||
this.nextEtn = nextEtn;
|
||||
this.phensig = phensig;
|
||||
this.resultsByHost = resultsByHost;
|
||||
this.errorMessages = errorMessages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("GetNextEtnResponse [nextEtn=");
|
||||
builder.append(nextEtn);
|
||||
builder.append(", phensig=");
|
||||
builder.append(phensig);
|
||||
builder.append(", resultsByHost=");
|
||||
builder.append(resultsByHost);
|
||||
builder.append(", errorMessages=");
|
||||
builder.append(errorMessages);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public boolean isOkay() {
|
||||
return errorMessages.isEmpty();
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return !isOkay() ? StringUtil.join(errorMessages, '\n') : "";
|
||||
}
|
||||
|
||||
public void addErrorMessage(String message) {
|
||||
if (CollectionUtil.isNullOrEmpty(errorMessages)) {
|
||||
errorMessages = new ArrayList<String>();
|
||||
}
|
||||
errorMessages.add(message);
|
||||
}
|
||||
|
||||
public int getNextEtn() {
|
||||
return nextEtn;
|
||||
}
|
||||
|
||||
public void setNextEtn(int nextEtn) {
|
||||
this.nextEtn = nextEtn;
|
||||
}
|
||||
|
||||
public String getPhensig() {
|
||||
return phensig;
|
||||
}
|
||||
|
||||
public void setPhensig(String phensig) {
|
||||
this.phensig = phensig;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getResultsByHost() {
|
||||
return resultsByHost;
|
||||
}
|
||||
|
||||
public void setResultsByHost(Map<String, Integer> resultsByHost) {
|
||||
this.resultsByHost = resultsByHost;
|
||||
}
|
||||
|
||||
public List<String> getErrorMessages() {
|
||||
return errorMessages;
|
||||
}
|
||||
|
||||
public void setErrorMessages(List<String> errorMessages) {
|
||||
this.errorMessages = errorMessages;
|
||||
}
|
||||
}
|
|
@ -20,10 +20,13 @@
|
|||
package com.raytheon.uf.edex.activetable;
|
||||
|
||||
import com.raytheon.uf.common.activetable.GetNextEtnRequest;
|
||||
import com.raytheon.uf.common.activetable.response.GetNextEtnResponse;
|
||||
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* Request handler for <code>GetNextEtnRequest</code>. Returns the next ETN to
|
||||
* use for the given office id, phensig, and active table (PRACTICE or
|
||||
* OPERATIONAL).
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -31,6 +34,7 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 15, 2011 rjpeter Initial creation
|
||||
* Oct 21, 2013 #1843 dgilling Change return type.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -41,12 +45,14 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
|
|||
public class GetNextEtnHandler implements IRequestHandler<GetNextEtnRequest> {
|
||||
|
||||
@Override
|
||||
public Integer handleRequest(GetNextEtnRequest request) throws Exception {
|
||||
Integer nextEtn = GetNextEtnUtil.getNextEtn(request.getSiteID(),
|
||||
request.getMode(), request.getPhensig(),
|
||||
public GetNextEtnResponse handleRequest(GetNextEtnRequest request)
|
||||
throws Exception {
|
||||
GetNextEtnResponse response = GetNextEtnUtil.getNextEtn(
|
||||
request.getSiteID(), request.getMode(), request.getPhensig(),
|
||||
request.getCurrentTime(), request.isLockEtn(),
|
||||
request.isPerformISC());
|
||||
return nextEtn;
|
||||
request.isPerformISC(), request.isReportConflictOnly(),
|
||||
request.getEtnOverride());
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,9 +28,13 @@ import java.net.UnknownHostException;
|
|||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Queue;
|
||||
import java.util.SortedMap;
|
||||
|
@ -40,6 +44,7 @@ import com.raytheon.edex.site.SiteUtil;
|
|||
import com.raytheon.uf.common.activetable.ActiveTableMode;
|
||||
import com.raytheon.uf.common.activetable.request.LockAndGetNextEtnRequest;
|
||||
import com.raytheon.uf.common.activetable.request.UnlockAndSetNextEtnRequest;
|
||||
import com.raytheon.uf.common.activetable.response.GetNextEtnResponse;
|
||||
import com.raytheon.uf.common.localization.IPathManager;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
|
@ -79,7 +84,7 @@ public final class GetNextEtnUtil {
|
|||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(GetNextEtnUtil.class);
|
||||
|
||||
private static final String CONFIG_FILE_NAME = "remote-etn-partners.properties";
|
||||
public static final String CONFIG_FILE_NAME = "remote-etn-partners.properties";
|
||||
|
||||
private static final String NEXT_ETN_LOCK = "ActiveTableNextEtn";
|
||||
|
||||
|
@ -121,29 +126,59 @@ public final class GetNextEtnUtil {
|
|||
* <code>isLock</code> is false, this flag is effectively false
|
||||
* and your configured remote partners will not be contacted to
|
||||
* determine the next ETN.
|
||||
* @return The next ETN to be used in sequence.
|
||||
* @param reportConflictOnly
|
||||
* Affects which kinds of errors get reported back to the
|
||||
* requestor. If true, only cases where the value of
|
||||
* <code>etnOverride</code> is less than or equal to the last ETN
|
||||
* used by this site or any of its partners will be reported.
|
||||
* Else, all significant errors will be reported back.
|
||||
* @param etnOverride
|
||||
* Allows the user to influence the next ETN assigned by using
|
||||
* this value unless it is less than or equal to the last ETN
|
||||
* used by this site or one of its partners.
|
||||
* @return A <code>GetNextEtnResponse</code> containing the next ETN to use
|
||||
* and any hosts that couldn't be contacted during this process.
|
||||
*/
|
||||
public static Integer getNextEtn(String siteId, ActiveTableMode mode,
|
||||
String phensig, Calendar currentTime, boolean isLock,
|
||||
boolean performISC) {
|
||||
List<IRequestRouter> hostsToQuery = Collections.emptyList();
|
||||
public static GetNextEtnResponse getNextEtn(String siteId,
|
||||
ActiveTableMode mode, String phensig, Calendar currentTime,
|
||||
boolean isLock, boolean performISC, boolean reportConflictOnly,
|
||||
Integer etnOverride) {
|
||||
SortedMap<String, IRequestRouter> hostsToQuery = new TreeMap<String, IRequestRouter>();
|
||||
List<String> readEtnSourcesErrors = Collections.emptyList();
|
||||
if (performISC) {
|
||||
hostsToQuery = GetNextEtnUtil.getRemoteEtnSources(siteId);
|
||||
try {
|
||||
hostsToQuery = GetNextEtnUtil.getRemoteEtnSources(siteId);
|
||||
} catch (UnknownHostException e) {
|
||||
readEtnSourcesErrors = Arrays.asList(
|
||||
"Falling back to local ETN calculation: ",
|
||||
"Could not perform reverse lookup for localhost: "
|
||||
+ e.getLocalizedMessage());
|
||||
} catch (IOException e) {
|
||||
readEtnSourcesErrors = Arrays.asList(
|
||||
"Falling back to local ETN calculation: ",
|
||||
"Could not read configuration file " + CONFIG_FILE_NAME
|
||||
+ ": " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
int nextEtn;
|
||||
if (performISC && isLock && (!hostsToQuery.isEmpty())) {
|
||||
nextEtn = GetNextEtnUtil.getNextEtnFromPartners(siteId, mode,
|
||||
phensig, currentTime, hostsToQuery);
|
||||
GetNextEtnResponse response;
|
||||
if (performISC && isLock && (!hostsToQuery.isEmpty())
|
||||
&& (readEtnSourcesErrors.isEmpty())) {
|
||||
response = GetNextEtnUtil.getNextEtnFromPartners(siteId, mode,
|
||||
phensig, currentTime, hostsToQuery, reportConflictOnly,
|
||||
etnOverride);
|
||||
} else {
|
||||
nextEtn = GetNextEtnUtil.getNextEtnFromLocal(siteId, mode, phensig,
|
||||
currentTime, isLock);
|
||||
int nextEtn = GetNextEtnUtil.getNextEtnFromLocal(siteId, mode,
|
||||
phensig, currentTime, isLock);
|
||||
response = new GetNextEtnResponse(nextEtn, phensig);
|
||||
response.setErrorMessages(readEtnSourcesErrors);
|
||||
}
|
||||
|
||||
return nextEtn;
|
||||
return response;
|
||||
}
|
||||
|
||||
private static List<IRequestRouter> getRemoteEtnSources(String siteId) {
|
||||
private static SortedMap<String, IRequestRouter> getRemoteEtnSources(
|
||||
String siteId) throws IOException, UnknownHostException {
|
||||
Properties etnBackupProps = new Properties();
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
|
@ -156,11 +191,11 @@ public final class GetNextEtnUtil {
|
|||
etnBackupProps.load(fis);
|
||||
} catch (FileNotFoundException e) {
|
||||
statusHandler.error(CONFIG_FILE_NAME + " file does not exist!", e);
|
||||
return Collections.emptyList();
|
||||
return new TreeMap<String, IRequestRouter>();
|
||||
} catch (IOException e) {
|
||||
statusHandler.error("Error reading " + CONFIG_FILE_NAME + " file!",
|
||||
e);
|
||||
return Collections.emptyList();
|
||||
throw e;
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
try {
|
||||
|
@ -172,6 +207,8 @@ public final class GetNextEtnUtil {
|
|||
}
|
||||
}
|
||||
|
||||
String localhostFQDN = getLocalhostFQDN();
|
||||
|
||||
String[] tokens = etnBackupProps.getProperty("BACKUP.HOSTS." + siteId,
|
||||
"").split(",");
|
||||
|
||||
|
@ -182,17 +219,7 @@ public final class GetNextEtnUtil {
|
|||
for (String token : tokens) {
|
||||
String host = token.trim().toLowerCase();
|
||||
if ("localhost".equals(host)) {
|
||||
try {
|
||||
host = InetAddress.getLocalHost().getCanonicalHostName();
|
||||
} catch (UnknownHostException e) {
|
||||
statusHandler.error(
|
||||
"Unable to retrieve host name for localhost.", e);
|
||||
statusHandler
|
||||
.handle(Priority.CRITICAL,
|
||||
"ETN assignment will not be able to query local server for used ETNs. Please check your network configuration and "
|
||||
+ CONFIG_FILE_NAME + ".");
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
IRequestRouter reqHandler = new RemoteServerRequestRouter("http://"
|
||||
|
@ -200,7 +227,11 @@ public final class GetNextEtnUtil {
|
|||
sources.put(host, reqHandler);
|
||||
}
|
||||
|
||||
return new ArrayList<IRequestRouter>(sources.values());
|
||||
IRequestRouter reqHandler = new RemoteServerRequestRouter("http://"
|
||||
+ localhostFQDN + ":9581/services");
|
||||
sources.put(localhostFQDN, reqHandler);
|
||||
|
||||
return sources;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,10 +275,13 @@ public final class GetNextEtnUtil {
|
|||
* needed if only determining a preliminary ETN. Required to be
|
||||
* set to <code>true</code> if you want to actually move the
|
||||
* sequence forward.
|
||||
* @param etnOverride
|
||||
* TODO
|
||||
* @return The next ETN to be used in sequence.
|
||||
*/
|
||||
public static int lockAndGetNextEtn(String siteId, ActiveTableMode mode,
|
||||
String phensig, Calendar currentTime, boolean isLock) {
|
||||
String phensig, Calendar currentTime, boolean isLock,
|
||||
Integer etnOverride) {
|
||||
String lockName = getEtnClusterLockName(siteId, mode);
|
||||
ClusterTask ct = null;
|
||||
if (isLock) {
|
||||
|
@ -264,19 +298,25 @@ public final class GetNextEtnUtil {
|
|||
currentTime);
|
||||
int nextEtn = (lastEtn != null) ? lastEtn + 1 : 1;
|
||||
|
||||
String year = Integer.toString(currentTime.get(Calendar.YEAR));
|
||||
String eInfo = ct.getExtraInfo();
|
||||
if ((!StringUtil.isEmptyString(eInfo)) && (eInfo.startsWith(year))) {
|
||||
// parse year info
|
||||
try {
|
||||
int ctNextEtn = Integer
|
||||
.parseInt(eInfo.substring(year.length() + 1)) + 1;
|
||||
nextEtn = Math.max(nextEtn, ctNextEtn);
|
||||
} catch (NumberFormatException e) {
|
||||
statusHandler.error(
|
||||
"Caught excetion parsing etn from cluster_task", e);
|
||||
int sysNextEtn = -1;
|
||||
if (etnOverride == null) {
|
||||
String year = Integer.toString(currentTime.get(Calendar.YEAR));
|
||||
String eInfo = ct.getExtraInfo();
|
||||
if ((!StringUtil.isEmptyString(eInfo)) && (eInfo.startsWith(year))) {
|
||||
// parse year info
|
||||
try {
|
||||
sysNextEtn = Integer
|
||||
.parseInt(eInfo.substring(year.length() + 1)) + 1;
|
||||
} catch (NumberFormatException e) {
|
||||
statusHandler
|
||||
.error("Caught exception parsing etn from cluster_task",
|
||||
e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sysNextEtn = etnOverride.intValue();
|
||||
}
|
||||
nextEtn = Math.max(nextEtn, sysNextEtn);
|
||||
|
||||
return nextEtn;
|
||||
}
|
||||
|
@ -330,7 +370,7 @@ public final class GetNextEtnUtil {
|
|||
ActiveTableMode mode, String phensig, Calendar currentTime,
|
||||
boolean isLock) {
|
||||
int nextEtn = lockAndGetNextEtn(siteId, mode, phensig, currentTime,
|
||||
isLock);
|
||||
isLock, null);
|
||||
if (isLock) {
|
||||
setNextEtnAndUnlock(siteId, mode, phensig,
|
||||
currentTime.get(Calendar.YEAR), nextEtn);
|
||||
|
@ -360,50 +400,88 @@ public final class GetNextEtnUtil {
|
|||
* @param hostsToQuery
|
||||
* The remote hosts to query. This should also include the local
|
||||
* EDEX instance initiating this operation.
|
||||
* @return The next ETN to be used in sequence.
|
||||
* @param reportConflictOnly
|
||||
* Affects which kinds of errors get reported back to the
|
||||
* requestor. If true, only cases where the value of
|
||||
* <code>etnOverride</code> is less than or equal to the last ETN
|
||||
* used by this site or any of its partners will be reported.
|
||||
* Else, all significant errors will be reported back.
|
||||
* @param etnOverride
|
||||
* Allows the user to influence the next ETN assigned by using
|
||||
* this value unless it is less than or equal to the last ETN
|
||||
* used by this site or one of its partners.
|
||||
* @return A <code>GetNextEtnResponse</code> containing the next ETN to use
|
||||
* and any hosts that couldn't be contacted during this process.
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static Integer getNextEtnFromPartners(String siteId,
|
||||
public static GetNextEtnResponse getNextEtnFromPartners(String siteId,
|
||||
ActiveTableMode mode, String phensig, Calendar currentTime,
|
||||
List<IRequestRouter> hostsToQuery) {
|
||||
Queue<IRequestRouter> lockQueue = new ArrayDeque<IRequestRouter>(
|
||||
hostsToQuery);
|
||||
Queue<IRequestRouter> unlockQueue = Collections
|
||||
.asLifoQueue(new ArrayDeque<IRequestRouter>(hostsToQuery.size()));
|
||||
SortedMap<String, IRequestRouter> hostsToQuery,
|
||||
boolean reportConflictOnly, Integer etnOverride) {
|
||||
Queue<Entry<String, IRequestRouter>> unlockQueue = Collections
|
||||
.asLifoQueue(new ArrayDeque<Entry<String, IRequestRouter>>(
|
||||
hostsToQuery.size()));
|
||||
|
||||
Map<String, Integer> resultsByHost = new HashMap<String, Integer>(
|
||||
hostsToQuery.size(), 1f);
|
||||
List<String> errors = new ArrayList<String>();
|
||||
|
||||
String mySiteId = SiteUtil.getSite();
|
||||
|
||||
IServerRequest getAndLockReq = new LockAndGetNextEtnRequest(siteId,
|
||||
mySiteId, mode, phensig, currentTime);
|
||||
int nextEtn = 1;
|
||||
for (IRequestRouter router : lockQueue) {
|
||||
mySiteId, mode, phensig, currentTime, etnOverride);
|
||||
for (Entry<String, IRequestRouter> host : hostsToQuery.entrySet()) {
|
||||
IRequestRouter router = host.getValue();
|
||||
String hostName = host.getKey();
|
||||
Integer partnersNextEtn = null;
|
||||
try {
|
||||
Integer partersNextEtn = (Integer) GetNextEtnUtil
|
||||
.sendThriftRequest(router, getAndLockReq);
|
||||
nextEtn = Math.max(nextEtn, partersNextEtn);
|
||||
unlockQueue.add(router);
|
||||
partnersNextEtn = (Integer) GetNextEtnUtil.sendThriftRequest(
|
||||
router, getAndLockReq);
|
||||
unlockQueue.add(host);
|
||||
} catch (RemoteException e) {
|
||||
statusHandler
|
||||
.handle(Priority.WARN,
|
||||
"Error occurred contacting one of the remote ETN partners.",
|
||||
e);
|
||||
String message = "Error occurred contacting remote ETN partner ["
|
||||
+ hostName + "]: " + e.getLocalizedMessage();
|
||||
if (!reportConflictOnly) {
|
||||
errors.add(message);
|
||||
}
|
||||
statusHandler.handle(Priority.WARN, message, e);
|
||||
}
|
||||
resultsByHost.put(hostName, partnersNextEtn);
|
||||
}
|
||||
|
||||
int nextEtn = 1;
|
||||
for (Entry<String, Integer> entry : resultsByHost.entrySet()) {
|
||||
int partnerEtn = (entry.getValue() != null) ? entry.getValue() : -1;
|
||||
nextEtn = Math.max(nextEtn, partnerEtn);
|
||||
|
||||
if ((etnOverride != null) && (etnOverride < partnerEtn)) {
|
||||
String message = "User-provided ETN value of "
|
||||
+ etnOverride.toString()
|
||||
+ " conflicts with calculated ETN value " + partnerEtn
|
||||
+ " from host " + entry.getKey();
|
||||
errors.add(message);
|
||||
statusHandler.warn(message);
|
||||
}
|
||||
}
|
||||
|
||||
IServerRequest unlockReq = new UnlockAndSetNextEtnRequest(siteId,
|
||||
mySiteId, mode, currentTime.get(Calendar.YEAR), phensig,
|
||||
nextEtn);
|
||||
for (IRequestRouter router : unlockQueue) {
|
||||
for (Entry<String, IRequestRouter> host : unlockQueue) {
|
||||
IRequestRouter router = host.getValue();
|
||||
try {
|
||||
GetNextEtnUtil.sendThriftRequest(router, unlockReq);
|
||||
} catch (RemoteException e) {
|
||||
statusHandler
|
||||
.handle(Priority.WARN,
|
||||
"Error occurred unlocking one of the remote ETN partners.",
|
||||
e);
|
||||
String message = "Error occurred unlocking remote ETN partner ["
|
||||
+ host.getKey() + "]: " + e.getLocalizedMessage();
|
||||
if (!reportConflictOnly) {
|
||||
errors.add(message);
|
||||
}
|
||||
statusHandler.handle(Priority.WARN, message, e);
|
||||
}
|
||||
}
|
||||
|
||||
return nextEtn;
|
||||
return new GetNextEtnResponse(nextEtn, phensig, resultsByHost, errors);
|
||||
}
|
||||
|
||||
private static Object sendThriftRequest(final IRequestRouter router,
|
||||
|
@ -429,4 +507,17 @@ public final class GetNextEtnUtil {
|
|||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static String getLocalhostFQDN() throws UnknownHostException {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getCanonicalHostName();
|
||||
} catch (UnknownHostException e) {
|
||||
statusHandler.error("Unable to retrieve host name for localhost.",
|
||||
e);
|
||||
statusHandler
|
||||
.handle(Priority.CRITICAL,
|
||||
"ETN assignment will not be able to query local server for used ETNs. Please check your network configuration.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import com.raytheon.uf.edex.activetable.GetNextEtnUtil;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 19, 2013 #1843 dgilling Initial creation
|
||||
* Oct 23, 2013 #1843 dgilling Update with ETN override.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -64,6 +65,6 @@ public class LockAndGetNextEtnHandler implements
|
|||
+ request.getSiteID() + "]: phensig= " + request.getPhensig());
|
||||
return GetNextEtnUtil.lockAndGetNextEtn(request.getSiteID(),
|
||||
request.getMode(), request.getPhensig(),
|
||||
request.getCurrentTime(), true);
|
||||
request.getCurrentTime(), true, request.getEtnOverride());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
#
|
||||
# To configure remote ETN querying for a specific site id: you must add an
|
||||
# entry to the site version of this file that looks like the following:
|
||||
# BACKUP.HOSTS.KXYZ=ec-xyz,ec-yyy,ec-zzz
|
||||
# BACKUP.HOSTS.KXYZ=ec-yyy,ec-zzz
|
||||
#
|
||||
# Now, when generating VTEC products for site KXYZ, EDEX will query hosts
|
||||
# ec-xyz,ec-yyy, and ec-zzz for the last ETN used for KXYZ. Note that you must
|
||||
# include the host name for this EDEX server in the list of hosts if you want
|
||||
# "localhost" to be in the hosts queried for the next ETN.
|
||||
# ec-yyy and ec-zzz for the last ETN used for KXYZ. Note that "localhost"
|
||||
# will automatically be queried for the next ETN so there is no
|
||||
# requirement to add it to the list of entries.
|
||||
#
|
||||
# There should only ever be one localized copy of this file on the EDEX server,
|
||||
# and it should be located at
|
||||
|
@ -26,4 +26,4 @@
|
|||
# querying (say, in case of service backup), you just add a new BACKUP.HOSTS
|
||||
# entry to this file.
|
||||
#
|
||||
# CONFIGURATION ENTRIES GO BELOW
|
||||
# CONFIGURATION ENTRIES GO BELOW
|
||||
|
|
Loading…
Add table
Reference in a new issue