Issue #1843: Implement ETN remote partners functionality.
Change-Id: I827e312941b4dbd15e3c6c90e04e38ffbf457294 Former-commit-id:f72a420d53
[formerly b0c40550c1448894915583a0426e78602cbe05c6] Former-commit-id:0359324523
This commit is contained in:
parent
3bdf7eed9d
commit
b8c247b469
13 changed files with 1010 additions and 92 deletions
|
@ -49,6 +49,7 @@ import com.raytheon.viz.texteditor.util.VtecUtil;
|
||||||
* Aug 07, 2013 #1842 dgilling Fix ETN assignment for products with
|
* Aug 07, 2013 #1842 dgilling Fix ETN assignment for products with
|
||||||
* multiple NEW segments with the same
|
* multiple NEW segments with the same
|
||||||
* phensig.
|
* phensig.
|
||||||
|
* Aug 29, 2013 #1843 dgilling Add hooks for inter-site ETN assignment.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -79,7 +80,12 @@ public class GFEVtecUtil {
|
||||||
|
|
||||||
public static int getNextEtn(String office, String phensig, boolean lockEtn)
|
public static int getNextEtn(String office, String phensig, boolean lockEtn)
|
||||||
throws VizException {
|
throws VizException {
|
||||||
return VtecUtil.getNextEtn(office, phensig, lockEtn);
|
return getNextEtn(office, phensig, lockEtn, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getNextEtn(String office, String phensig,
|
||||||
|
boolean lockEtn, boolean performISC) throws VizException {
|
||||||
|
return VtecUtil.getNextEtn(office, phensig, lockEtn, performISC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String finalizeETNs(String message) throws VizException {
|
public static String finalizeETNs(String message) throws VizException {
|
||||||
|
@ -108,8 +114,8 @@ public class GFEVtecUtil {
|
||||||
String cacheKey = vtec.getPhensig();
|
String cacheKey = vtec.getPhensig();
|
||||||
Integer newEtn = etnCache.get(cacheKey);
|
Integer newEtn = etnCache.get(cacheKey);
|
||||||
if (newEtn == null) {
|
if (newEtn == null) {
|
||||||
newEtn = VtecUtil.getNextEtn(vtec.getOffice(),
|
newEtn = getNextEtn(vtec.getOffice(), vtec.getPhensig(),
|
||||||
vtec.getPhensig(), true);
|
true, true);
|
||||||
etnCache.put(cacheKey, newEtn);
|
etnCache.put(cacheKey, newEtn);
|
||||||
}
|
}
|
||||||
vtec.setSequence(newEtn);
|
vtec.setSequence(newEtn);
|
||||||
|
|
|
@ -43,6 +43,7 @@ import com.raytheon.viz.core.mode.CAVEMode;
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Feb 09, 2009 bwoodle Initial creation
|
* Feb 09, 2009 bwoodle Initial creation
|
||||||
* May 08, 2013 #1842 dgilling Code cleanup.
|
* May 08, 2013 #1842 dgilling Code cleanup.
|
||||||
|
* Aug 29, 2013 #1843 dgilling Use new GetNextEtnRequest constructor.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -111,23 +112,69 @@ public class VtecUtil {
|
||||||
return replaceFirstVtecString(message, vtec);
|
return replaceFirstVtecString(message, vtec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 occurs while submitting or processing the remote
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
public static int getNextEtn(String office, String phensig, boolean lockEtn)
|
public static int getNextEtn(String office, String phensig, boolean lockEtn)
|
||||||
throws VizException {
|
throws VizException {
|
||||||
int rval = 1;
|
return getNextEtn(office, phensig, lockEtn, false);
|
||||||
GetNextEtnRequest req = new GetNextEtnRequest();
|
}
|
||||||
req.setSiteID(office);
|
|
||||||
req.setPhensig(phensig);
|
/**
|
||||||
req.setLockEtn(lockEtn);
|
* 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 occurs while submitting or processing the remote
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
public static int getNextEtn(String office, String phensig,
|
||||||
|
boolean lockEtn, boolean performISC) throws VizException {
|
||||||
Calendar currentTime = Calendar.getInstance();
|
Calendar currentTime = Calendar.getInstance();
|
||||||
currentTime.setTime(SimulatedTime.getSystemTime().getTime());
|
currentTime.setTime(SimulatedTime.getSystemTime().getTime());
|
||||||
req.setCurrentTime(currentTime);
|
ActiveTableMode activeTable = (CAVEMode.getMode()
|
||||||
CAVEMode mode = CAVEMode.getMode();
|
.equals(CAVEMode.PRACTICE)) ? ActiveTableMode.PRACTICE
|
||||||
if (mode.equals(CAVEMode.PRACTICE)) {
|
: ActiveTableMode.OPERATIONAL;
|
||||||
req.setMode(ActiveTableMode.PRACTICE);
|
GetNextEtnRequest req = new GetNextEtnRequest(office, activeTable,
|
||||||
} else {
|
phensig, currentTime, lockEtn, performISC);
|
||||||
req.setMode(ActiveTableMode.OPERATIONAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int rval = 1;
|
||||||
Integer resp = (Integer) ThriftClient.sendRequest(req);
|
Integer resp = (Integer) ThriftClient.sendRequest(req);
|
||||||
if (resp != null) {
|
if (resp != null) {
|
||||||
rval = resp;
|
rval = resp;
|
||||||
|
|
|
@ -34,6 +34,7 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Feb 14, 2011 rjpeter Initial creation
|
* Feb 14, 2011 rjpeter Initial creation
|
||||||
|
* Aug 26, 2013 #1843 dgilling Add performISC field, proper constructors.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -58,6 +59,44 @@ public class GetNextEtnRequest implements IServerRequest {
|
||||||
@DynamicSerializeElement
|
@DynamicSerializeElement
|
||||||
private boolean lockEtn;
|
private boolean lockEtn;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private boolean performISC;
|
||||||
|
|
||||||
|
public GetNextEtnRequest() {
|
||||||
|
// no-op, for dynamic serialize support
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param siteID
|
||||||
|
* @param mode
|
||||||
|
* @param phensig
|
||||||
|
* @param currentTime
|
||||||
|
* @param lockEtn
|
||||||
|
*/
|
||||||
|
public GetNextEtnRequest(String siteID, ActiveTableMode mode,
|
||||||
|
String phensig, Calendar currentTime, boolean lockEtn) {
|
||||||
|
this(siteID, mode, phensig, currentTime, lockEtn, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param siteID
|
||||||
|
* @param mode
|
||||||
|
* @param phensig
|
||||||
|
* @param currentTime
|
||||||
|
* @param lockEtn
|
||||||
|
* @param performISC
|
||||||
|
*/
|
||||||
|
public GetNextEtnRequest(String siteID, ActiveTableMode mode,
|
||||||
|
String phensig, Calendar currentTime, boolean lockEtn,
|
||||||
|
boolean performISC) {
|
||||||
|
this.siteID = siteID;
|
||||||
|
this.mode = mode;
|
||||||
|
this.phensig = phensig;
|
||||||
|
this.currentTime = currentTime;
|
||||||
|
this.lockEtn = lockEtn;
|
||||||
|
this.performISC = performISC;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSiteID() {
|
public String getSiteID() {
|
||||||
return siteID;
|
return siteID;
|
||||||
}
|
}
|
||||||
|
@ -98,4 +137,11 @@ public class GetNextEtnRequest implements IServerRequest {
|
||||||
this.currentTime = currentTime;
|
this.currentTime = currentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPerformISC() {
|
||||||
|
return performISC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPerformISC(boolean performISC) {
|
||||||
|
this.performISC = performISC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.activetable.ActiveTableMode;
|
||||||
|
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
|
||||||
|
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
|
||||||
|
import com.raytheon.uf.common.serialization.comm.IServerRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to lock active table and get next ETN to be used.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 19, 2013 #1843 dgilling Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author dgilling
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
@DynamicSerialize
|
||||||
|
public class LockAndGetNextEtnRequest implements IServerRequest {
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private String siteID;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private String requestorSiteID;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private ActiveTableMode mode;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private String phensig;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private Calendar currentTime;
|
||||||
|
|
||||||
|
public LockAndGetNextEtnRequest() {
|
||||||
|
// default constructor for thrift/dynamicserialize
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockAndGetNextEtnRequest(String siteID, String requestorSiteID,
|
||||||
|
ActiveTableMode mode, String phensig, Calendar currentTime) {
|
||||||
|
this.siteID = siteID;
|
||||||
|
this.requestorSiteID = requestorSiteID;
|
||||||
|
this.mode = mode;
|
||||||
|
this.phensig = phensig;
|
||||||
|
this.currentTime = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteID() {
|
||||||
|
return siteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteID(String siteID) {
|
||||||
|
this.siteID = siteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequestorSiteID() {
|
||||||
|
return requestorSiteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestorSiteID(String requestorSiteID) {
|
||||||
|
this.requestorSiteID = requestorSiteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveTableMode getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(ActiveTableMode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhensig() {
|
||||||
|
return phensig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhensig(String phensig) {
|
||||||
|
this.phensig = phensig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Calendar getCurrentTime() {
|
||||||
|
return currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentTime(Calendar currentTime) {
|
||||||
|
this.currentTime = currentTime;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
/**
|
||||||
|
* 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.request;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.activetable.ActiveTableMode;
|
||||||
|
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
|
||||||
|
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
|
||||||
|
import com.raytheon.uf.common.serialization.comm.IServerRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to unlock active table and set next ETN to be used.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 19, 2013 #1843 dgilling Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author dgilling
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
@DynamicSerialize
|
||||||
|
public class UnlockAndSetNextEtnRequest implements IServerRequest {
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private String siteID;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private String requestorSiteID;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private ActiveTableMode mode;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private int year;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private String phensig;
|
||||||
|
|
||||||
|
@DynamicSerializeElement
|
||||||
|
private int newEtn;
|
||||||
|
|
||||||
|
public UnlockAndSetNextEtnRequest() {
|
||||||
|
// default constructor for thrift/dynamicserialize
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnlockAndSetNextEtnRequest(String siteID, String requestorSiteID,
|
||||||
|
ActiveTableMode mode, int year, String phensig, int newEtn) {
|
||||||
|
this.siteID = siteID;
|
||||||
|
this.requestorSiteID = requestorSiteID;
|
||||||
|
this.mode = mode;
|
||||||
|
this.year = year;
|
||||||
|
this.phensig = phensig;
|
||||||
|
this.newEtn = newEtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSiteID() {
|
||||||
|
return siteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSiteID(String siteID) {
|
||||||
|
this.siteID = siteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequestorSiteID() {
|
||||||
|
return requestorSiteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestorSiteID(String requestorSiteID) {
|
||||||
|
this.requestorSiteID = requestorSiteID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveTableMode getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(ActiveTableMode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYear() {
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYear(int year) {
|
||||||
|
this.year = year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhensig() {
|
||||||
|
return phensig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhensig(String phensig) {
|
||||||
|
this.phensig = phensig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNewEtn() {
|
||||||
|
return newEtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewEtn(int newEtn) {
|
||||||
|
this.newEtn = newEtn;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,8 @@ Require-Bundle: com.raytheon.uf.common.localization;bundle-version="1.11.1",
|
||||||
com.raytheon.uf.common.message;bundle-version="1.12.1174",
|
com.raytheon.uf.common.message;bundle-version="1.12.1174",
|
||||||
com.raytheon.uf.common.activetable;bundle-version="1.12.1174",
|
com.raytheon.uf.common.activetable;bundle-version="1.12.1174",
|
||||||
com.raytheon.uf.edex.site;bundle-version="1.0.0",
|
com.raytheon.uf.edex.site;bundle-version="1.0.0",
|
||||||
com.google.guava;bundle-version="1.0.0"
|
com.google.guava;bundle-version="1.0.0",
|
||||||
|
com.raytheon.uf.edex.auth;bundle-version="1.12.1174",
|
||||||
|
com.raytheon.uf.common.serialization.comm
|
||||||
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
|
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
|
||||||
Export-Package: com.raytheon.uf.edex.activetable
|
Export-Package: com.raytheon.uf.edex.activetable
|
||||||
|
|
|
@ -69,6 +69,18 @@
|
||||||
<constructor-arg ref="ingestATHandler"/>
|
<constructor-arg ref="ingestATHandler"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="lockAndGetEtnHandler" class="com.raytheon.uf.edex.activetable.handler.LockAndGetNextEtnHandler"/>
|
||||||
|
<bean factory-bean="handlerRegistry" factory-method="register">
|
||||||
|
<constructor-arg value="com.raytheon.uf.common.activetable.request.LockAndGetNextEtnRequest"/>
|
||||||
|
<constructor-arg ref="lockAndGetEtnHandler"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="setAndUnlockEtnHandler" class="com.raytheon.uf.edex.activetable.handler.UnlockActiveTablePhenSigHandler"/>
|
||||||
|
<bean factory-bean="handlerRegistry" factory-method="register">
|
||||||
|
<constructor-arg value="com.raytheon.uf.common.activetable.request.UnlockAndSetNextEtnRequest"/>
|
||||||
|
<constructor-arg ref="setAndUnlockEtnHandler"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="fetchATSrv" class="com.raytheon.uf.edex.activetable.vtecsharing.FetchActiveTableSrv"/>
|
<bean id="fetchATSrv" class="com.raytheon.uf.edex.activetable.vtecsharing.FetchActiveTableSrv"/>
|
||||||
<camelContext id="activeTableSharingRoutes"
|
<camelContext id="activeTableSharingRoutes"
|
||||||
xmlns="http://camel.apache.org/schema/spring"
|
xmlns="http://camel.apache.org/schema/spring"
|
||||||
|
|
|
@ -52,13 +52,10 @@ import com.raytheon.uf.common.site.SiteMap;
|
||||||
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.status.UFStatus.Priority;
|
||||||
|
import com.raytheon.uf.common.util.CollectionUtil;
|
||||||
import com.raytheon.uf.common.util.FileUtil;
|
import com.raytheon.uf.common.util.FileUtil;
|
||||||
import com.raytheon.uf.edex.core.EDEXUtil;
|
import com.raytheon.uf.edex.core.EDEXUtil;
|
||||||
import com.raytheon.uf.edex.database.DataAccessLayerException;
|
import com.raytheon.uf.edex.database.DataAccessLayerException;
|
||||||
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
|
|
||||||
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState;
|
|
||||||
import com.raytheon.uf.edex.database.cluster.ClusterTask;
|
|
||||||
import com.raytheon.uf.edex.database.cluster.handler.CurrentTimeClusterLockHandler;
|
|
||||||
import com.raytheon.uf.edex.database.dao.CoreDao;
|
import com.raytheon.uf.edex.database.dao.CoreDao;
|
||||||
import com.raytheon.uf.edex.database.dao.DaoConfig;
|
import com.raytheon.uf.edex.database.dao.DaoConfig;
|
||||||
import com.raytheon.uf.edex.database.query.DatabaseQuery;
|
import com.raytheon.uf.edex.database.query.DatabaseQuery;
|
||||||
|
@ -81,6 +78,8 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery;
|
||||||
* May 14, 2013 1842 dgilling Also delete cluster locks when purging
|
* May 14, 2013 1842 dgilling Also delete cluster locks when purging
|
||||||
* PRACTICE active table.
|
* PRACTICE active table.
|
||||||
* Jun 11, 2013 2083 randerso Log active table changes
|
* Jun 11, 2013 2083 randerso Log active table changes
|
||||||
|
* Aug 29, 2013 1843 dgilling Move ETN related methods to
|
||||||
|
* GetNextEtnUtil.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -95,8 +94,6 @@ public class ActiveTable {
|
||||||
private static final Logger changeLog = Logger
|
private static final Logger changeLog = Logger
|
||||||
.getLogger("ActiveTableChange");
|
.getLogger("ActiveTableChange");
|
||||||
|
|
||||||
private static final String NEXT_ETN_LOCK = "ActiveTableNextEtn";
|
|
||||||
|
|
||||||
private static String filePath;
|
private static String filePath;
|
||||||
|
|
||||||
private static String includePath;
|
private static String includePath;
|
||||||
|
@ -228,73 +225,6 @@ public class ActiveTable {
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer getNextEtn(String siteId, ActiveTableMode mode,
|
|
||||||
String phensig, Calendar currentTime, boolean isLock) {
|
|
||||||
String lockName = getEtnClusterLockName(siteId, mode);
|
|
||||||
ClusterTask ct = null;
|
|
||||||
CurrentTimeClusterLockHandler lockHandler = null;
|
|
||||||
if (isLock) {
|
|
||||||
lockHandler = new CurrentTimeClusterLockHandler(15000, false);
|
|
||||||
do {
|
|
||||||
ct = ClusterLockUtils
|
|
||||||
.lock(lockName, phensig, lockHandler, true);
|
|
||||||
} while (!ct.getLockState().equals(LockState.SUCCESSFUL));
|
|
||||||
statusHandler.info("Locking::[lockName = " + lockName
|
|
||||||
+ ", phensig = " + phensig + "]");
|
|
||||||
} else {
|
|
||||||
ct = ClusterLockUtils.lookupLock(lockName, phensig);
|
|
||||||
}
|
|
||||||
|
|
||||||
int nextEtn = 1;
|
|
||||||
List<ActiveTableRecord> records = queryTable(siteId, mode, phensig,
|
|
||||||
null, null, currentTime, false, true);
|
|
||||||
|
|
||||||
if (records != null && records.size() > 0) {
|
|
||||||
// should only be 1
|
|
||||||
nextEtn = Integer.parseInt(records.get(0).getEtn()) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
String year = "" + currentTime.get(Calendar.YEAR);
|
|
||||||
String eInfo = ct.getExtraInfo();
|
|
||||||
if (eInfo != null && eInfo.startsWith(year)) {
|
|
||||||
// parse year info
|
|
||||||
try {
|
|
||||||
int ctNextEtn = Integer
|
|
||||||
.parseInt(eInfo.substring(year.length() + 1)) + 1;
|
|
||||||
if (ctNextEtn > nextEtn) {
|
|
||||||
nextEtn = ctNextEtn;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
statusHandler.error(
|
|
||||||
"Caught excetion parsing etn from cluster_task", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLock) {
|
|
||||||
lockHandler.setExtraInfo(year + ":" + nextEtn);
|
|
||||||
ClusterLockUtils.unlock(ct, false);
|
|
||||||
statusHandler.info("Unlocking::[nextEtn = " + nextEtn + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Integer(nextEtn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the EDEX cluster lock name for the given site and active table
|
|
||||||
* mode.
|
|
||||||
*
|
|
||||||
* @param siteId
|
|
||||||
* 4-char site identifier
|
|
||||||
* @param mode
|
|
||||||
* The active table mode
|
|
||||||
* @return The cluster lock name for the given site and active table.
|
|
||||||
*/
|
|
||||||
private static String getEtnClusterLockName(String siteId,
|
|
||||||
ActiveTableMode mode) {
|
|
||||||
String lockName = NEXT_ETN_LOCK + "_" + siteId + "_" + mode.name();
|
|
||||||
return lockName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the active table with the new warnings
|
* Updates the active table with the new warnings
|
||||||
*
|
*
|
||||||
|
@ -602,7 +532,7 @@ public class ActiveTable {
|
||||||
dao.executeNativeSql(sql);
|
dao.executeNativeSql(sql);
|
||||||
|
|
||||||
sql = "delete from cluster_task where name ='"
|
sql = "delete from cluster_task where name ='"
|
||||||
+ getEtnClusterLockName(requestedSiteId,
|
+ GetNextEtnUtil.getEtnClusterLockName(requestedSiteId,
|
||||||
ActiveTableMode.PRACTICE) + "';";
|
ActiveTableMode.PRACTICE) + "';";
|
||||||
dao.executeNativeSql(sql);
|
dao.executeNativeSql(sql);
|
||||||
}
|
}
|
||||||
|
@ -613,4 +543,34 @@ public class ActiveTable {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last assigned ETN for the specified site and phensig combination.
|
||||||
|
*
|
||||||
|
* @param siteId
|
||||||
|
* The 4-character site identifier.
|
||||||
|
* @param mode
|
||||||
|
* The active table to search.
|
||||||
|
* @param phensig
|
||||||
|
* The phenomenon and significance combination to search for.
|
||||||
|
* @param currentTime
|
||||||
|
* <code>Calendar</code> representing time to perform search from
|
||||||
|
* (needed for DRT mode).
|
||||||
|
* @return The last ETN assigned to the particular site and phensig
|
||||||
|
* combination, or <code>null</code> if no ETNs have been assigned
|
||||||
|
* to this combination.
|
||||||
|
*/
|
||||||
|
public static Integer getLastUsedEtn(String siteId, ActiveTableMode mode,
|
||||||
|
String phensig, Calendar currentTime) {
|
||||||
|
Integer lastEtn = null;
|
||||||
|
List<ActiveTableRecord> records = ActiveTable.queryTable(siteId, mode,
|
||||||
|
phensig, null, null, currentTime, false, true);
|
||||||
|
if (!CollectionUtil.isNullOrEmpty(records)) {
|
||||||
|
// queryTable will return ActiveTableRecords sorted by ETN in
|
||||||
|
// descending order, so the first record's ETN will always be the
|
||||||
|
// last used ETN.
|
||||||
|
lastEtn = Integer.parseInt(records.get(0).getEtn());
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastEtn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,10 @@ public class GetNextEtnHandler implements IRequestHandler<GetNextEtnRequest> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer handleRequest(GetNextEtnRequest request) throws Exception {
|
public Integer handleRequest(GetNextEtnRequest request) throws Exception {
|
||||||
Integer nextEtn = ActiveTable.getNextEtn(request.getSiteID(),
|
Integer nextEtn = GetNextEtnUtil.getNextEtn(request.getSiteID(),
|
||||||
request.getMode(), request.getPhensig(),
|
request.getMode(), request.getPhensig(),
|
||||||
request.getCurrentTime(), request.isLockEtn());
|
request.getCurrentTime(), request.isLockEtn(),
|
||||||
|
request.isPerformISC());
|
||||||
return nextEtn;
|
return nextEtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,432 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.uf.edex.activetable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
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.localization.IPathManager;
|
||||||
|
import com.raytheon.uf.common.localization.LocalizationContext;
|
||||||
|
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||||
|
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||||
|
import com.raytheon.uf.common.serialization.ExceptionWrapper;
|
||||||
|
import com.raytheon.uf.common.serialization.comm.IRequestRouter;
|
||||||
|
import com.raytheon.uf.common.serialization.comm.IServerRequest;
|
||||||
|
import com.raytheon.uf.common.serialization.comm.response.ServerErrorResponse;
|
||||||
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
|
import com.raytheon.uf.common.util.StringUtil;
|
||||||
|
import com.raytheon.uf.edex.auth.RemoteServerRequestRouter;
|
||||||
|
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
|
||||||
|
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState;
|
||||||
|
import com.raytheon.uf.edex.database.cluster.ClusterTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Library module of functions to support retrieval of next ETN in sequence for
|
||||||
|
* a given phensig and 4-character site identifier.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 29, 2013 #1843 dgilling Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author dgilling
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
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";
|
||||||
|
|
||||||
|
private static final String NEXT_ETN_LOCK = "ActiveTableNextEtn";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy private constructor so this class can't be directly instantiated.
|
||||||
|
* Every method is static.
|
||||||
|
*/
|
||||||
|
private GetNextEtnUtil() {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the next ETN in sequence given an office, phensig, and active
|
||||||
|
* table. The next ETN will be determined by using the maximum of the last
|
||||||
|
* ETN found for the given office and phensig in the appropriate active
|
||||||
|
* table and in the cluster task for the same office, phensig, and active
|
||||||
|
* table combination.
|
||||||
|
* <p>
|
||||||
|
* If the <code>performISC</code> flag is set then we will also query a list
|
||||||
|
* of configured remote ETN partners. This configuration is stored in the
|
||||||
|
* file edex_static/site/${AW_SITE_IDENTIFIER}/vtec/remote-etn-partners.
|
||||||
|
* properties.
|
||||||
|
*
|
||||||
|
* @param siteId
|
||||||
|
* The 4-character site identifier.
|
||||||
|
* @param mode
|
||||||
|
* The active table to use.
|
||||||
|
* @param phensig
|
||||||
|
* The phenomenon and significance combination (e.g., TO.W or
|
||||||
|
* DU.Y).
|
||||||
|
* @param currentTime
|
||||||
|
* <code>Calendar</code> representing time (needed for DRT mode).
|
||||||
|
* @param isLock
|
||||||
|
* Whether or not to return a unique ETN--one that has not and
|
||||||
|
* cannot be used by any other requestor.
|
||||||
|
* @param performISC
|
||||||
|
* Whether or not to collaborate with neighboring sites to
|
||||||
|
* determine the next ETN. If this is true, but
|
||||||
|
* <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.
|
||||||
|
*/
|
||||||
|
public static Integer getNextEtn(String siteId, ActiveTableMode mode,
|
||||||
|
String phensig, Calendar currentTime, boolean isLock,
|
||||||
|
boolean performISC) {
|
||||||
|
List<IRequestRouter> hostsToQuery = Collections.emptyList();
|
||||||
|
if (performISC) {
|
||||||
|
hostsToQuery = GetNextEtnUtil.getRemoteEtnSources(siteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextEtn;
|
||||||
|
if (performISC && isLock && (!hostsToQuery.isEmpty())) {
|
||||||
|
nextEtn = GetNextEtnUtil.getNextEtnFromPartners(siteId, mode,
|
||||||
|
phensig, currentTime, hostsToQuery);
|
||||||
|
} else {
|
||||||
|
nextEtn = GetNextEtnUtil.getNextEtnFromLocal(siteId, mode, phensig,
|
||||||
|
currentTime, isLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextEtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<IRequestRouter> getRemoteEtnSources(String siteId) {
|
||||||
|
Properties etnBackupProps = new Properties();
|
||||||
|
FileInputStream fis = null;
|
||||||
|
try {
|
||||||
|
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||||
|
LocalizationContext edexSiteCtx = pathMgr.getContextForSite(
|
||||||
|
LocalizationType.EDEX_STATIC, SiteUtil.getSite());
|
||||||
|
File configFile = pathMgr.getFile(edexSiteCtx, "vtec"
|
||||||
|
+ IPathManager.SEPARATOR + CONFIG_FILE_NAME);
|
||||||
|
fis = new FileInputStream(configFile);
|
||||||
|
etnBackupProps.load(fis);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
statusHandler.error(CONFIG_FILE_NAME + " file does not exist!", e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
} catch (IOException e) {
|
||||||
|
statusHandler.error("Error reading " + CONFIG_FILE_NAME + " file!",
|
||||||
|
e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
} finally {
|
||||||
|
if (fis != null) {
|
||||||
|
try {
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
statusHandler.handle(Priority.WARN, "Error closing "
|
||||||
|
+ CONFIG_FILE_NAME + " file!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] tokens = etnBackupProps.getProperty("BACKUP.HOSTS." + siteId,
|
||||||
|
"").split(",");
|
||||||
|
|
||||||
|
// To prevent deadlock, we ensure every system uses the same ordering by
|
||||||
|
// use of this SortedMap. Configuration entries will be ordered
|
||||||
|
// alphabetically by host name.
|
||||||
|
SortedMap<String, IRequestRouter> sources = new TreeMap<String, IRequestRouter>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IRequestRouter reqHandler = new RemoteServerRequestRouter("http://"
|
||||||
|
+ host + ":9581/services");
|
||||||
|
sources.put(host, reqHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<IRequestRouter>(sources.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the EDEX cluster lock name for the given site and active table
|
||||||
|
* mode.
|
||||||
|
*
|
||||||
|
* @param siteId
|
||||||
|
* 4-char site identifier
|
||||||
|
* @param mode
|
||||||
|
* The active table mode
|
||||||
|
* @return The cluster lock name for the given site and active table.
|
||||||
|
*/
|
||||||
|
protected static String getEtnClusterLockName(String siteId,
|
||||||
|
ActiveTableMode mode) {
|
||||||
|
String lockName = GetNextEtnUtil.NEXT_ETN_LOCK + "_" + siteId + "_"
|
||||||
|
+ mode.name();
|
||||||
|
return lockName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will obtain a cluster task lock for the given active table, office id,
|
||||||
|
* and phensig combination and use the current information in the active
|
||||||
|
* table and that cluster task's metadata to determine the next ETN in
|
||||||
|
* sequence.
|
||||||
|
* <p>
|
||||||
|
* It is the responsibility of the caller of this method to later call
|
||||||
|
* <code>setNextEtnAndUnlock</code> to release the cluster task lock this
|
||||||
|
* method creates.
|
||||||
|
*
|
||||||
|
* @param siteId
|
||||||
|
* The 4-character site identifier.
|
||||||
|
* @param mode
|
||||||
|
* The active table to use.
|
||||||
|
* @param phensig
|
||||||
|
* The phenomenon and significance combination (e.g., TO.W or
|
||||||
|
* DU.Y).
|
||||||
|
* @param currentTime
|
||||||
|
* <code>Calendar</code> representing time (needed for DRT mode).
|
||||||
|
* @param isLock
|
||||||
|
* Whether or not to actually obtain the cluster task lock. Not
|
||||||
|
* needed if only determining a preliminary ETN. Required to be
|
||||||
|
* set to <code>true</code> if you want to actually move the
|
||||||
|
* sequence forward.
|
||||||
|
* @return The next ETN to be used in sequence.
|
||||||
|
*/
|
||||||
|
public static int lockAndGetNextEtn(String siteId, ActiveTableMode mode,
|
||||||
|
String phensig, Calendar currentTime, boolean isLock) {
|
||||||
|
String lockName = getEtnClusterLockName(siteId, mode);
|
||||||
|
ClusterTask ct = null;
|
||||||
|
if (isLock) {
|
||||||
|
do {
|
||||||
|
ct = ClusterLockUtils.lock(lockName, phensig, 15000, true);
|
||||||
|
} while (!ct.getLockState().equals(LockState.SUCCESSFUL));
|
||||||
|
statusHandler.info("Locking::[lockName = " + lockName
|
||||||
|
+ ", phensig = " + phensig + "]");
|
||||||
|
} else {
|
||||||
|
ct = ClusterLockUtils.lookupLock(lockName, phensig);
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer lastEtn = ActiveTable.getLastUsedEtn(siteId, mode, phensig,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextEtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will release the cluster lock for the given office, phensig, and active
|
||||||
|
* table combination and also save the last used ETN for that given
|
||||||
|
* combination.
|
||||||
|
*
|
||||||
|
* @param siteId
|
||||||
|
* The 4-character site identifier.
|
||||||
|
* @param mode
|
||||||
|
* The active table to use.
|
||||||
|
* @param phensig
|
||||||
|
* The phenomenon and significance combination (e.g., TO.W or
|
||||||
|
* DU.Y).
|
||||||
|
* @param year
|
||||||
|
* Year the next ETN is effective for.
|
||||||
|
* @param nextEtn
|
||||||
|
* The ETN to persist.
|
||||||
|
*/
|
||||||
|
public static void setNextEtnAndUnlock(String siteId, ActiveTableMode mode,
|
||||||
|
String phensig, int year, int nextEtn) {
|
||||||
|
String lockName = getEtnClusterLockName(siteId, mode);
|
||||||
|
ClusterLockUtils.updateExtraInfo(lockName, phensig,
|
||||||
|
Integer.toString(year) + ":" + nextEtn);
|
||||||
|
ClusterLockUtils.unlock(lockName, phensig);
|
||||||
|
statusHandler.info("Unlocking::[nextEtn = " + nextEtn + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will retrieve the ETN in sequence for the given site, phensig, and active
|
||||||
|
* table combination by only checking the internal active table and cluster
|
||||||
|
* lock metadata. No remote partners will be contacted.
|
||||||
|
*
|
||||||
|
* @param siteId
|
||||||
|
* The 4-character site identifier.
|
||||||
|
* @param mode
|
||||||
|
* The active table to use.
|
||||||
|
* @param phensig
|
||||||
|
* The phenomenon and significance combination (e.g., TO.W or
|
||||||
|
* DU.Y).
|
||||||
|
* @param currentTime
|
||||||
|
* <code>Calendar</code> representing time (needed for DRT mode).
|
||||||
|
* @param isLock
|
||||||
|
* Whether or not to return a unique ETN--one that has not and
|
||||||
|
* cannot be used by any other requestor.
|
||||||
|
* @return The next ETN to be used in sequence.
|
||||||
|
*/
|
||||||
|
public static Integer getNextEtnFromLocal(String siteId,
|
||||||
|
ActiveTableMode mode, String phensig, Calendar currentTime,
|
||||||
|
boolean isLock) {
|
||||||
|
int nextEtn = lockAndGetNextEtn(siteId, mode, phensig, currentTime,
|
||||||
|
isLock);
|
||||||
|
if (isLock) {
|
||||||
|
setNextEtnAndUnlock(siteId, mode, phensig,
|
||||||
|
currentTime.get(Calendar.YEAR), nextEtn);
|
||||||
|
}
|
||||||
|
return nextEtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will retrieve the ETN in sequence for the given site, phensig, and active
|
||||||
|
* table combination by contacting the EDEX hosts defined in the file
|
||||||
|
* edex_static
|
||||||
|
* /site/${AW_SITE_IDENTIFIER}/vtec/remote-etn-partners.properties.
|
||||||
|
* <p>
|
||||||
|
* It is expected that configuration file will list a number of remote
|
||||||
|
* servers to check, but the host name of the primary EDEX server hosting
|
||||||
|
* the site being queried for should also be listed.
|
||||||
|
*
|
||||||
|
* @param siteId
|
||||||
|
* The 4-character site identifier.
|
||||||
|
* @param mode
|
||||||
|
* The active table to use.
|
||||||
|
* @param phensig
|
||||||
|
* The phenomenon and significance combination (e.g., TO.W or
|
||||||
|
* DU.Y).
|
||||||
|
* @param currentTime
|
||||||
|
* <code>Calendar</code> representing time (needed for DRT mode).
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
public static Integer 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()));
|
||||||
|
|
||||||
|
String mySiteId = SiteUtil.getSite();
|
||||||
|
|
||||||
|
IServerRequest getAndLockReq = new LockAndGetNextEtnRequest(siteId,
|
||||||
|
mySiteId, mode, phensig, currentTime);
|
||||||
|
int nextEtn = 1;
|
||||||
|
for (IRequestRouter router : lockQueue) {
|
||||||
|
try {
|
||||||
|
Integer partersNextEtn = (Integer) GetNextEtnUtil
|
||||||
|
.sendThriftRequest(router, getAndLockReq);
|
||||||
|
nextEtn = Math.max(nextEtn, partersNextEtn);
|
||||||
|
unlockQueue.add(router);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
statusHandler
|
||||||
|
.handle(Priority.WARN,
|
||||||
|
"Error occurred contacting one of the remote ETN partners.",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IServerRequest unlockReq = new UnlockAndSetNextEtnRequest(siteId,
|
||||||
|
mySiteId, mode, currentTime.get(Calendar.YEAR), phensig,
|
||||||
|
nextEtn);
|
||||||
|
for (IRequestRouter router : unlockQueue) {
|
||||||
|
try {
|
||||||
|
GetNextEtnUtil.sendThriftRequest(router, unlockReq);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
statusHandler
|
||||||
|
.handle(Priority.WARN,
|
||||||
|
"Error occurred unlocking one of the remote ETN partners.",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextEtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object sendThriftRequest(final IRequestRouter router,
|
||||||
|
final IServerRequest request) throws RemoteException {
|
||||||
|
Object retVal = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
retVal = router.route(request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RemoteException(
|
||||||
|
"Unhandled exception occurred routing request type "
|
||||||
|
+ request.getClass().toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retVal instanceof ServerErrorResponse) {
|
||||||
|
Throwable cause = ExceptionWrapper
|
||||||
|
.unwrapThrowable(((ServerErrorResponse) retVal)
|
||||||
|
.getException());
|
||||||
|
throw new RemoteException(
|
||||||
|
"Unhandled exception occurred on remote server processing request type "
|
||||||
|
+ request.getClass().toString(), cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.uf.edex.activetable.handler;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.activetable.request.LockAndGetNextEtnRequest;
|
||||||
|
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
|
||||||
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
import com.raytheon.uf.edex.activetable.GetNextEtnUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request handler that locks the active table for a specific phensig and office
|
||||||
|
* ID combination. Should only be activated by another EDEX server.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 19, 2013 #1843 dgilling Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author dgilling
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LockAndGetNextEtnHandler implements
|
||||||
|
IRequestHandler<LockAndGetNextEtnRequest> {
|
||||||
|
|
||||||
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
|
.getHandler(LockAndGetNextEtnHandler.class);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
|
||||||
|
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Integer handleRequest(LockAndGetNextEtnRequest request)
|
||||||
|
throws Exception {
|
||||||
|
statusHandler.info("Received LockAndGetNextEtnRequest from ["
|
||||||
|
+ request.getRequestorSiteID() + "] for site ["
|
||||||
|
+ request.getSiteID() + "]: phensig= " + request.getPhensig());
|
||||||
|
return GetNextEtnUtil.lockAndGetNextEtn(request.getSiteID(),
|
||||||
|
request.getMode(), request.getPhensig(),
|
||||||
|
request.getCurrentTime(), true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.uf.edex.activetable.handler;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.activetable.request.UnlockAndSetNextEtnRequest;
|
||||||
|
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
|
||||||
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
import com.raytheon.uf.edex.activetable.GetNextEtnUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request handler that unlocks the active table for a specific phensig and
|
||||||
|
* office ID combination and sets the next ETN to be used. Should only be
|
||||||
|
* activated by another EDEX server.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 19, 2013 #1843 dgilling Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author dgilling
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class UnlockActiveTablePhenSigHandler implements
|
||||||
|
IRequestHandler<UnlockAndSetNextEtnRequest> {
|
||||||
|
|
||||||
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
|
.getHandler(UnlockActiveTablePhenSigHandler.class);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
|
||||||
|
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean handleRequest(UnlockAndSetNextEtnRequest request)
|
||||||
|
throws Exception {
|
||||||
|
statusHandler.info("Received UnlockAndSetNextEtnRequest from ["
|
||||||
|
+ request.getRequestorSiteID() + "] for site ["
|
||||||
|
+ request.getSiteID() + "]: phensig= " + request.getPhensig()
|
||||||
|
+ ", nextETN= " + request.getNewEtn());
|
||||||
|
GetNextEtnUtil.setNextEtnAndUnlock(request.getSiteID(),
|
||||||
|
request.getMode(), request.getPhensig(), request.getYear(),
|
||||||
|
request.getNewEtn());
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
# This file defines lists of partner sites to check when assigning or
|
||||||
|
# generating the next ETN for a VTEC product in GFE. This functionality is
|
||||||
|
# completely optional--there's no requirement to configure it. If not
|
||||||
|
# configured the system will solely look at local active table entries and
|
||||||
|
# the cluster_task db entry named
|
||||||
|
# "ActiveTableNextEtn_<siteId>_<activeTableName>" for the specific phensig to
|
||||||
|
# determine the next ETN in sequence.
|
||||||
|
#
|
||||||
|
# If configured, when generating GFE VTEC products for the specified 4-char
|
||||||
|
# site ID, it will query each of entries in the list of specified hosts for
|
||||||
|
# the last ETN used for the site, phensig, and active table combination.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# There should only ever be one localized copy of this file on the EDEX server,
|
||||||
|
# and it should be located at
|
||||||
|
# /awips2/edex/data/utility/site/${AW_SITE_IDENTIFIER}/vtec/remote-etn-partners.properties.
|
||||||
|
# If new sites are activated on this server that need to use remote ETN
|
||||||
|
# querying (say, in case of service backup), you just add a new BACKUP.HOSTS
|
||||||
|
# entry to this file.
|
||||||
|
#
|
||||||
|
# CONFIGURATION ENTRIES GO BELOW
|
Loading…
Add table
Reference in a new issue