Issue #2868 plot delegate python now uses PythonCoordinatorJob API,
Refactored plot data request, image creation, and sample threading Change-Id: I3e1a3dc70b2346aa826ec4509ee7a3e59c61a918 Former-commit-id:85b411bca3
[formerly2418c9bdfe
] [formerlyfe33896e7e
] [formerly85b411bca3
[formerly2418c9bdfe
] [formerlyfe33896e7e
] [formerlyc4beb293b9
[formerlyfe33896e7e
[formerly e421731415d798487c96dd1e56b6f02347d9aa26]]]] Former-commit-id:c4beb293b9
Former-commit-id:df01318647
[formerly0acb4621f9
] [formerly 3d803664963a310bbf45fe46e8f20c9255a3b529 [formerly774091461c
]] Former-commit-id: c0e78be8fc6eca4dfac050feb6b22af3fded1f5c [formerly96339798b5
] Former-commit-id:5b6683bd56
This commit is contained in:
parent
531dafbe7d
commit
6897e58b4e
16 changed files with 1055 additions and 597 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Pointdata Plug-in
|
||||
Bundle-SymbolicName: com.raytheon.viz.pointdata;singleton:=true
|
||||
Bundle-Version: 1.12.1174.qualifier
|
||||
Bundle-Version: 1.14.0.qualifier
|
||||
Bundle-Activator: com.raytheon.viz.pointdata.Activator
|
||||
Bundle-Vendor: Raytheon
|
||||
Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core
|
||||
|
@ -20,7 +20,8 @@ Require-Bundle: org.apache.batik,
|
|||
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.dataplugin.level;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.wxmath
|
||||
com.raytheon.uf.common.wxmath,
|
||||
com.raytheon.uf.common.python.concurrent
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.raytheon.viz.pointdata,
|
||||
com.raytheon.viz.pointdata.drawables,
|
||||
|
|
|
@ -1,196 +0,0 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.pointdata;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.map.MapDescriptor;
|
||||
import com.raytheon.viz.pointdata.thread.GetDataTask;
|
||||
|
||||
/**
|
||||
* Thread pool for requesting data for plots. Each data request job is tied to a
|
||||
* plot generator job.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 30, 2011 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PlotDataThreadPool {
|
||||
|
||||
private static final int THREADS = 2;
|
||||
|
||||
protected ConcurrentLinkedQueue<GetDataTask> stationQueue = new ConcurrentLinkedQueue<GetDataTask>();
|
||||
|
||||
protected List<PlotModelDataRequestJob> jobList = new ArrayList<PlotModelDataRequestJob>();
|
||||
|
||||
public PlotDataThreadPool(IGraphicsTarget aTarget,
|
||||
MapDescriptor mapDescriptor, String plotModelFile, String levelKey,
|
||||
String plugin, HashMap<String, RequestConstraint> constraintMap,
|
||||
IPlotModelGeneratorCaller caller) throws VizException {
|
||||
for (int i = 0; i < THREADS; i++) {
|
||||
jobList.add(new PlotModelDataRequestJob(aTarget, mapDescriptor,
|
||||
plotModelFile, levelKey, plugin, constraintMap, caller,
|
||||
this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a batch of stations to the queue
|
||||
*
|
||||
* @param station
|
||||
*
|
||||
*/
|
||||
public void queueStation(GetDataTask task) {
|
||||
List<PlotInfo[]> station = task.getStations();
|
||||
|
||||
Iterator<PlotInfo[]> itr = station.iterator();
|
||||
while (itr.hasNext()) {
|
||||
PlotInfo[] infos = itr.next();
|
||||
boolean allQueued = true;
|
||||
for (PlotInfo info : infos) {
|
||||
switch (task.getRequestType()) {
|
||||
case PLOT_ONLY:
|
||||
if (!info.plotQueued) {
|
||||
allQueued = false;
|
||||
info.plotQueued = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case SAMPLE_ONLY:
|
||||
if (!info.sampleQueued) {
|
||||
allQueued = false;
|
||||
info.sampleQueued = true;
|
||||
}
|
||||
break;
|
||||
case PLOT_AND_SAMPLE:
|
||||
if (!info.sampleQueued) {
|
||||
allQueued = false;
|
||||
info.sampleQueued = true;
|
||||
}
|
||||
if (!info.plotQueued) {
|
||||
allQueued = false;
|
||||
info.plotQueued = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allQueued) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (station.size() > 0) {
|
||||
task.setStations(station);
|
||||
stationQueue.add(task);
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
if (job.getState() != Job.RUNNING) {
|
||||
job.schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setPlotModelColor(RGB color) {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
job.setPlotModelColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlotModelLineStyle(LineStyle lineStyle) {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
job.setPlotModelLineStyle(lineStyle);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlotModelLineWidth(int outlineWidth) {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
job.setPlotModelLineWidth(outlineWidth);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlotMissingData(boolean plotMissingData) {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
job.setPlotMissingData(plotMissingData);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLowerLimit(double lowerLimit) {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
job.setLowerLimit(lowerLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUpperLimit(double upperLimit) {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
job.setUpperLimit(upperLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public double getPlotModelWidth() {
|
||||
return jobList.get(0).getPlotModelWidth();
|
||||
}
|
||||
|
||||
public void setPlotModelSize(long round) {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
job.setPlotModelSize(round);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
for (PlotModelDataRequestJob job : jobList) {
|
||||
if (!job.isDone()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
List<PlotModelDataRequestJob> jobListCopy = new ArrayList<PlotModelDataRequestJob>(
|
||||
jobList);
|
||||
jobList.clear();
|
||||
stationQueue.clear();
|
||||
for (PlotModelDataRequestJob job : jobListCopy) {
|
||||
job.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -29,6 +29,7 @@ import java.text.ParsePosition;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Formatter;
|
||||
import java.util.HashMap;
|
||||
|
@ -40,8 +41,6 @@ import javax.measure.converter.UnitConverter;
|
|||
import javax.measure.unit.Unit;
|
||||
import javax.measure.unit.UnitFormat;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import org.apache.batik.bridge.BridgeContext;
|
||||
import org.apache.batik.bridge.GVTBuilder;
|
||||
import org.apache.batik.bridge.UserAgentAdapter;
|
||||
|
@ -57,10 +56,8 @@ import org.w3c.dom.NodeList;
|
|||
import org.w3c.dom.Text;
|
||||
|
||||
import com.raytheon.uf.common.localization.IPathManager;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||
import com.raytheon.uf.common.python.PythonScript;
|
||||
import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
@ -69,12 +66,16 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
import com.raytheon.uf.viz.core.map.IMapDescriptor;
|
||||
import com.raytheon.viz.pointdata.lookup.IAbstractLookupTable;
|
||||
import com.raytheon.viz.pointdata.lookup.LookupUtils;
|
||||
import com.raytheon.viz.pointdata.python.CheckPlotValidityExecutor;
|
||||
import com.raytheon.viz.pointdata.python.PlotPythonScript;
|
||||
import com.raytheon.viz.pointdata.python.PlotPythonScriptFactory;
|
||||
import com.raytheon.viz.pointdata.python.SampleTextExecutor;
|
||||
import com.raytheon.viz.pointdata.rsc.PlotResource2;
|
||||
import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
||||
|
||||
/**
|
||||
* A singleton that will create a plot model texture based on a passed in
|
||||
* MetarRecord object.
|
||||
* A factory for generating plot images and sample messages by parsing the
|
||||
* associated plotModel SVG file.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -89,6 +90,7 @@ import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
|||
* Sep 05, 2013 2316 bsteffen Unify pirep and ncpirep.
|
||||
* Sep 05, 2013 2307 dgilling Use better PythonScript constructor.
|
||||
* Nov 20, 2013 2033 njensen Fix detecting plotModels dirs from multiple plugins
|
||||
* Mar 21, 2014 2868 njensen Refactored python usage to PythonJobCoordinator
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -99,7 +101,7 @@ public class PlotModelFactory2 {
|
|||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(PlotModelFactory2.class);
|
||||
|
||||
private static final String PLOT_MODEL_DIR = "plotModels";
|
||||
public static final String PLOT_MODEL_DIR = "plotModels";
|
||||
|
||||
private static final String DM_ATTRIBUTE = "plotMode";
|
||||
|
||||
|
@ -121,8 +123,6 @@ public class PlotModelFactory2 {
|
|||
|
||||
private static final String REQUIRED = "required";
|
||||
|
||||
private static String cachedIncludePath;
|
||||
|
||||
private final SimpleDateFormat SAMPLE_DATE = new SimpleDateFormat("HHmm");
|
||||
|
||||
// Need to include attribute and code to allow for String2String lookups and
|
||||
|
@ -137,8 +137,6 @@ public class PlotModelFactory2 {
|
|||
|
||||
private Document document;
|
||||
|
||||
private GraphicsNode theGraphicsNode;
|
||||
|
||||
private final GVTBuilder builder;
|
||||
|
||||
private final BridgeContext bridgeContext;
|
||||
|
@ -171,9 +169,9 @@ public class PlotModelFactory2 {
|
|||
|
||||
private Map<String, BufferedImage> imageCache = null;
|
||||
|
||||
private ScriptInfo scriptInfo;
|
||||
protected final String plotModelFile;
|
||||
|
||||
private ScriptInfo sampleScriptInfo;
|
||||
protected PythonJobCoordinator<PlotPythonScript> python;
|
||||
|
||||
public static enum DisplayMode {
|
||||
TEXT, BARB, TABLE, AVAIL, RANGE, NULL, SAMPLE, ARROW
|
||||
|
@ -211,6 +209,10 @@ public class PlotModelFactory2 {
|
|||
public Node getPlotNode() {
|
||||
return plotNode;
|
||||
}
|
||||
|
||||
public String getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlotWindElement {
|
||||
|
@ -238,6 +240,7 @@ public class PlotModelFactory2 {
|
|||
byte[] blue = { 0, full };
|
||||
byte[] green = { 0, zero };
|
||||
regenerateStyle();
|
||||
this.plotModelFile = plotModelFile;
|
||||
this.plotFields = new ArrayList<PlotModelElement>();
|
||||
this.sampleFields = new ArrayList<PlotModelElement>();
|
||||
|
||||
|
@ -452,12 +455,16 @@ public class PlotModelFactory2 {
|
|||
imageCache = new HashMap<String, BufferedImage>();
|
||||
}
|
||||
NodeList scriptNodes = document.getElementsByTagName("script");
|
||||
|
||||
// Only one script node supported
|
||||
if (scriptNodes.getLength() > 0) {
|
||||
int nScriptNodes = scriptNodes.getLength();
|
||||
if (nScriptNodes > 1) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Only one script node allowed in plotModel SVG file. Please check and fix "
|
||||
+ plotModelFile);
|
||||
} else if (nScriptNodes == 1) {
|
||||
Element scriptNode = (Element) scriptNodes.item(0);
|
||||
scriptInfo = new ScriptInfo();
|
||||
scriptInfo.plotDelegateName = scriptNode
|
||||
.getAttribute("plotDelegate");
|
||||
String plotDelegateName = scriptNode.getAttribute("plotDelegate");
|
||||
NodeList childNodes = scriptNode.getChildNodes();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
|
@ -466,14 +473,13 @@ public class PlotModelFactory2 {
|
|||
sb.append(((Text) child).getData());
|
||||
}
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
scriptInfo.scriptText = sb.toString();
|
||||
String scriptText = sb.toString().trim();
|
||||
if (scriptText.length() > 0) {
|
||||
PlotPythonScriptFactory pythonFactory = new PlotPythonScriptFactory(
|
||||
plotModelFile, scriptText, plotDelegateName);
|
||||
python = PythonJobCoordinator.newInstance(pythonFactory);
|
||||
}
|
||||
|
||||
sampleScriptInfo = new ScriptInfo();
|
||||
sampleScriptInfo.plotDelegateName = scriptInfo.plotDelegateName;
|
||||
sampleScriptInfo.scriptText = scriptInfo.scriptText;
|
||||
|
||||
// remove the scriptNode in memory so time isn't wasted
|
||||
// later attempting to render it
|
||||
scriptNode.getParentNode().removeChild(scriptNode);
|
||||
|
@ -491,8 +497,8 @@ public class PlotModelFactory2 {
|
|||
byte fullr = (byte) color.red;
|
||||
byte fullg = (byte) color.green;
|
||||
byte fullb = (byte) color.blue;
|
||||
String style = "stroke: rgb(" + color.red + "," + color.green + ","
|
||||
+ color.blue + ");";
|
||||
// String style = "stroke: rgb(" + color.red + "," + color.green + ","
|
||||
// + color.blue + ");";
|
||||
// this.svgRoot.setAttribute("style", style);
|
||||
// System.out.println(style);
|
||||
byte[] red = { 0, fullr };
|
||||
|
@ -567,8 +573,7 @@ public class PlotModelFactory2 {
|
|||
}
|
||||
|
||||
/**
|
||||
* Takes the station name and its MetarRecord object and produces a buffered
|
||||
* image.
|
||||
* Takes the station data object and produces a buffered image.
|
||||
*
|
||||
* @param station
|
||||
* The station name
|
||||
|
@ -591,27 +596,28 @@ public class PlotModelFactory2 {
|
|||
this.gc.setDestinationGeographicPoint(newWorldLocation[0],
|
||||
newWorldLocation[1]);
|
||||
}
|
||||
StringBuffer imageId = new StringBuffer();
|
||||
PlotPythonScript script = null;
|
||||
|
||||
try {
|
||||
boolean discard = false;
|
||||
|
||||
if (scriptInfo != null) {
|
||||
script = scriptInfo.getScript();
|
||||
|
||||
if (python != null) {
|
||||
Boolean result = false;
|
||||
CheckPlotValidityExecutor task = new CheckPlotValidityExecutor(
|
||||
stationData);
|
||||
try {
|
||||
Object result = script.executePlotDelegateMethod("isValid",
|
||||
"rec", stationData);
|
||||
if (result instanceof Boolean
|
||||
&& !((Boolean) result).booleanValue()) {
|
||||
result = python.submitSyncJob(task);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error checking if plot is valid for plot model "
|
||||
+ getPlotModelFilename(), e);
|
||||
} finally {
|
||||
if (result.booleanValue() == false) {
|
||||
return null;
|
||||
}
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder imageId = new StringBuilder();
|
||||
|
||||
for (PlotModelElement element : this.plotFields) {
|
||||
boolean valid = true;
|
||||
boolean required = element.required;
|
||||
|
@ -680,13 +686,13 @@ public class PlotModelFactory2 {
|
|||
this.plotModelWidth, this.plotModelHeight,
|
||||
BufferedImage.TYPE_BYTE_INDEXED, tm);
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
this.theGraphicsNode = builder.build(this.bridgeContext,
|
||||
// long t0 = System.currentTimeMillis();
|
||||
GraphicsNode graphicsNode = builder.build(this.bridgeContext,
|
||||
this.document);
|
||||
Graphics2D g2d = null;
|
||||
try {
|
||||
g2d = bufferedImage.createGraphics();
|
||||
this.theGraphicsNode.primitivePaint(g2d);
|
||||
graphicsNode.primitivePaint(g2d);
|
||||
} finally {
|
||||
if (g2d != null) {
|
||||
g2d.dispose();
|
||||
|
@ -702,9 +708,6 @@ public class PlotModelFactory2 {
|
|||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error:" + e.getLocalizedMessage(), e);
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error:" + e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -712,20 +715,20 @@ public class PlotModelFactory2 {
|
|||
|
||||
public synchronized String getStationMessage(PlotData stationData,
|
||||
String dataURI) {
|
||||
PlotPythonScript script = null;
|
||||
StringBuilder sampleMessage = new StringBuilder();
|
||||
try {
|
||||
if (sampleScriptInfo != null) {
|
||||
script = sampleScriptInfo.getScript();
|
||||
|
||||
Object result = script.executePlotDelegateMethod("isValid",
|
||||
"rec", stationData);
|
||||
if (result instanceof Boolean
|
||||
&& ((Boolean) result).booleanValue()) {
|
||||
result = script.executePlotDelegateMethod("getSampleText",
|
||||
"rec", stationData);
|
||||
if (result instanceof String) {
|
||||
sampleMessage.append((String) result);
|
||||
if (python != null) {
|
||||
String result = null;
|
||||
SampleTextExecutor task = new SampleTextExecutor(stationData);
|
||||
try {
|
||||
result = python.submitSyncJob(task);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error getting sample text for plot model "
|
||||
+ getPlotModelFilename(), e);
|
||||
} finally {
|
||||
if (result != null) {
|
||||
sampleMessage.append(result);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -736,11 +739,8 @@ public class PlotModelFactory2 {
|
|||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
} catch (JepException e) {
|
||||
// TODO Auto-generated catch block. Please revise as appropriate.
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error generating sample text with " + plotModelFile, e);
|
||||
}
|
||||
|
||||
String message = sampleMessage.toString();
|
||||
|
@ -752,7 +752,7 @@ public class PlotModelFactory2 {
|
|||
}
|
||||
|
||||
private void addToImageId(PlotData stationData, String parameters,
|
||||
StringBuffer imageId) {
|
||||
StringBuilder imageId) {
|
||||
for (String parameter : parameters.split(",")) {
|
||||
switch (stationData.getType(parameter)) {
|
||||
case STRING:
|
||||
|
@ -809,6 +809,7 @@ public class PlotModelFactory2 {
|
|||
Formatter testing = new Formatter(sb);
|
||||
testing.format(element.format, displayValue);
|
||||
sValue = sb.toString();
|
||||
testing.close();
|
||||
} else {
|
||||
sValue = Double.toString(displayValue);
|
||||
}
|
||||
|
@ -1073,6 +1074,7 @@ public class PlotModelFactory2 {
|
|||
Formatter testing = new Formatter(sb);
|
||||
testing.format(element.format, displayValue);
|
||||
sValue = sb.toString();
|
||||
testing.close();
|
||||
}
|
||||
} else {
|
||||
sValue = Double.toString(displayValue);
|
||||
|
@ -1138,6 +1140,7 @@ public class PlotModelFactory2 {
|
|||
Formatter testing = new Formatter(sb);
|
||||
testing.format(element.format, displayValue);
|
||||
sValue = sb.toString();
|
||||
testing.close();
|
||||
} else {
|
||||
sValue = Double.toString(displayValue);
|
||||
}
|
||||
|
@ -1197,8 +1200,8 @@ public class PlotModelFactory2 {
|
|||
return major * 5;
|
||||
}
|
||||
|
||||
public synchronized List<PlotModelElement> getPlotFields() {
|
||||
return this.plotFields;
|
||||
public List<PlotModelElement> getPlotFields() {
|
||||
return Collections.unmodifiableList(this.plotFields);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1244,140 +1247,6 @@ public class PlotModelFactory2 {
|
|||
this.plotMissingData = b;
|
||||
}
|
||||
|
||||
public void disposeScript() {
|
||||
if (scriptInfo != null) {
|
||||
try {
|
||||
scriptInfo.disposeScript();
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
"Error disposing plot model script", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void disposeSampleScript() {
|
||||
if (sampleScriptInfo != null) {
|
||||
try {
|
||||
sampleScriptInfo.disposeScript();
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
"Error disposing plot model sample script", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ScriptInfo {
|
||||
public String plotDelegateName;
|
||||
|
||||
public String scriptText;
|
||||
|
||||
private PlotPythonScript script;
|
||||
|
||||
private Thread scriptThread;
|
||||
|
||||
public PlotPythonScript getScript() throws JepException {
|
||||
if (script != null) {
|
||||
if (Thread.currentThread() == scriptThread) {
|
||||
return script;
|
||||
} else {
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
"Plot model scripting was not properly disposed.");
|
||||
script = null;
|
||||
scriptThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
script = createScript();
|
||||
scriptThread = Thread.currentThread();
|
||||
return script;
|
||||
}
|
||||
|
||||
public void disposeScript() throws JepException {
|
||||
if (script != null) {
|
||||
try {
|
||||
if (Thread.currentThread() == scriptThread) {
|
||||
script.dispose();
|
||||
}
|
||||
} finally {
|
||||
script = null;
|
||||
scriptThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PlotPythonScript createScript() throws JepException {
|
||||
synchronized (PlotModelFactory2.class) {
|
||||
if (cachedIncludePath == null) {
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
LocalizationFile[] files = pm
|
||||
.listFiles(
|
||||
pm.getLocalSearchHierarchy(LocalizationType.CAVE_STATIC),
|
||||
PLOT_MODEL_DIR, null, false, false);
|
||||
StringBuilder includePath = new StringBuilder();
|
||||
for (LocalizationFile lf : files) {
|
||||
if (lf.exists() && lf.isDirectory()) {
|
||||
if (includePath.length() > 0) {
|
||||
includePath.append(File.pathSeparator);
|
||||
}
|
||||
includePath.append(lf.getFile().getAbsolutePath());
|
||||
}
|
||||
}
|
||||
cachedIncludePath = includePath.toString();
|
||||
}
|
||||
}
|
||||
|
||||
File baseFile = PathManagerFactory.getPathManager().getStaticFile(
|
||||
PLOT_MODEL_DIR + IPathManager.SEPARATOR
|
||||
+ "PlotModelInterface.py");
|
||||
PlotPythonScript localScript = new PlotPythonScript(
|
||||
baseFile.getAbsolutePath(), cachedIncludePath,
|
||||
plotDelegateName);
|
||||
|
||||
if (scriptText != null) {
|
||||
localScript.evaluate(scriptText);
|
||||
}
|
||||
localScript.executePlotDelegateMethod("init", "plotModelFactory",
|
||||
PlotModelFactory2.this);
|
||||
return localScript;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PlotPythonScript extends PythonScript {
|
||||
|
||||
private static String CHEAT_RUN = "_cheat_run";
|
||||
|
||||
private String plotDelegateName;
|
||||
|
||||
public PlotPythonScript(String filePath, String anIncludePath,
|
||||
String plotDelegateName) throws JepException {
|
||||
super(filePath, anIncludePath, PlotPythonScript.class
|
||||
.getClassLoader());
|
||||
jep.eval("def "
|
||||
+ CHEAT_RUN
|
||||
+ "(text):\n return eval(compile(text,'string','exec'),globals(),globals())");
|
||||
this.plotDelegateName = plotDelegateName;
|
||||
}
|
||||
|
||||
public Object evaluate(String script) throws JepException {
|
||||
Object result = jep.invoke(CHEAT_RUN, script);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Object executePlotDelegateMethod(String methodName,
|
||||
String argName, Object argValue) throws JepException {
|
||||
if (plotDelegateName != null) {
|
||||
HashMap<String, Object> map = null;
|
||||
if (argName != null) {
|
||||
map = new HashMap<String, Object>();
|
||||
map.put(argName, argValue);
|
||||
}
|
||||
return execute(methodName, plotDelegateName, map);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private File getTableFile(String fileName) {
|
||||
File rval = PathManagerFactory.getPathManager().getStaticFile(
|
||||
PLOT_MODEL_DIR + IPathManager.SEPARATOR + fileName);
|
||||
|
@ -1385,10 +1254,24 @@ public class PlotModelFactory2 {
|
|||
}
|
||||
|
||||
public List<PlotModelElement> getSampleFields() {
|
||||
return this.sampleFields;
|
||||
return Collections.unmodifiableList(this.sampleFields);
|
||||
}
|
||||
|
||||
public boolean isCachingImages() {
|
||||
return imageCache != null;
|
||||
}
|
||||
|
||||
public String getPlotModelFilename() {
|
||||
return this.plotModelFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes of the plot model
|
||||
*/
|
||||
public void dispose() {
|
||||
if (python != null) {
|
||||
python.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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.pointdata.python;
|
||||
|
||||
import com.raytheon.viz.pointdata.PlotData;
|
||||
|
||||
/**
|
||||
* Abstract class for python plot delegates where the subclasses will implement
|
||||
* IPythonExecutor<PlotPythonScript, R>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 18, 2014 2868 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public abstract class AbstractPlotDelegateExecutor {
|
||||
|
||||
protected PlotData plotData;
|
||||
|
||||
public AbstractPlotDelegateExecutor(PlotData data) {
|
||||
this.plotData = data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* 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.pointdata.python;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
|
||||
import com.raytheon.viz.pointdata.PlotData;
|
||||
|
||||
/**
|
||||
* Task to check if the plot data is valid based on the python method isValid()
|
||||
* extracted from the SVG file.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 18, 2014 2868 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class CheckPlotValidityExecutor extends AbstractPlotDelegateExecutor
|
||||
implements IPythonExecutor<PlotPythonScript, Boolean> {
|
||||
|
||||
public CheckPlotValidityExecutor(PlotData data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean execute(PlotPythonScript script) throws JepException {
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
args.put("rec", plotData);
|
||||
return (Boolean) script.execute("isValid", args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* 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.pointdata.python;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.python.PythonScript;
|
||||
|
||||
/**
|
||||
* A python interpreter that is expecting to receive and retain a multi-line
|
||||
* script of plot delegate python extracted from a plot model SVG file.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 14, 2014 2868 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PlotPythonScript extends PythonScript {
|
||||
|
||||
protected String plotDelegateName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param filePath
|
||||
* the path to the plot model interface python
|
||||
* @param anIncludePath
|
||||
* the include path for relevant python modules
|
||||
* @param scriptText
|
||||
* the text of the python code extracted from the plot model svg
|
||||
* @param plotDelegateName
|
||||
* the instance name of the plot delegate
|
||||
* @param svgFilename
|
||||
* the name of the SVG file the python code came from, this is
|
||||
* used in exception stacktraces
|
||||
*
|
||||
* @throws JepException
|
||||
*/
|
||||
public PlotPythonScript(String filePath, String anIncludePath,
|
||||
String scriptText, String plotDelegateName, String svgFilename)
|
||||
throws JepException {
|
||||
super(filePath, anIncludePath, PlotPythonScript.class.getClassLoader());
|
||||
/*
|
||||
* jep.eval() won't evaluate more than a single line of python code,
|
||||
* unless that first line is a python class or method definition, so we
|
||||
* work around that by compiling it, then eval-ing it
|
||||
*
|
||||
* TODO contemplate building the workaround into PythonInterpreter,
|
||||
* PythonScript, or PythonEval
|
||||
*/
|
||||
jep.set("scriptToRun", scriptText);
|
||||
jep.eval("eval(compile(scriptToRun, '" + svgFilename + "', 'exec'))");
|
||||
this.plotDelegateName = plotDelegateName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(String methodName, Map<String, Object> args)
|
||||
throws JepException {
|
||||
return execute(methodName, plotDelegateName, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -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.viz.pointdata.python;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.localization.IPathManager;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||
import com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory;
|
||||
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||
|
||||
/**
|
||||
* Builds a plot delegate python script based on the script text extracted from
|
||||
* a plot model SVG file. The name should be the name of the plot model SVG file
|
||||
* to optimize reusing the interpreters across different resources that display
|
||||
* the same plot model.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 14, 2014 2868 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PlotPythonScriptFactory extends
|
||||
AbstractPythonScriptFactory<PlotPythonScript> {
|
||||
|
||||
private static String includePath;
|
||||
|
||||
private static String baseFilePath;
|
||||
|
||||
protected String scriptText;
|
||||
|
||||
protected String plotDelegateName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param plotSvgName
|
||||
* the name of the svg file that the python code was extracted
|
||||
* from
|
||||
* @param scriptText
|
||||
* the python code that was extracted from the svg file
|
||||
* @param plotDelegateName
|
||||
* the name of the instance of the plot delegate inside the
|
||||
* python code
|
||||
*/
|
||||
public PlotPythonScriptFactory(String plotSvgName, String scriptText,
|
||||
String plotDelegateName) {
|
||||
super(plotSvgName, 1);
|
||||
this.scriptText = scriptText;
|
||||
this.plotDelegateName = plotDelegateName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotPythonScript createPythonScript() throws JepException {
|
||||
synchronized (PlotPythonScriptFactory.class) {
|
||||
if (includePath == null) {
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
LocalizationFile[] files = pm.listFiles(pm
|
||||
.getLocalSearchHierarchy(LocalizationType.CAVE_STATIC),
|
||||
PlotModelFactory2.PLOT_MODEL_DIR, null, false, false);
|
||||
StringBuilder includeBuilder = new StringBuilder();
|
||||
for (LocalizationFile lf : files) {
|
||||
if (lf.exists() && lf.isDirectory()) {
|
||||
if (includeBuilder.length() > 0) {
|
||||
includeBuilder.append(File.pathSeparator);
|
||||
}
|
||||
includeBuilder.append(lf.getFile().getAbsolutePath());
|
||||
}
|
||||
}
|
||||
includePath = includeBuilder.toString();
|
||||
}
|
||||
|
||||
if (baseFilePath == null) {
|
||||
File baseFile = PathManagerFactory.getPathManager()
|
||||
.getStaticFile(
|
||||
PlotModelFactory2.PLOT_MODEL_DIR
|
||||
+ IPathManager.SEPARATOR
|
||||
+ "PlotModelInterface.py");
|
||||
baseFilePath = baseFile.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
return new PlotPythonScript(baseFilePath, includePath, scriptText,
|
||||
plotDelegateName, this.getName());
|
||||
}
|
||||
}
|
|
@ -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.viz.pointdata.python;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
|
||||
import com.raytheon.viz.pointdata.PlotData;
|
||||
|
||||
/**
|
||||
* Task to get the sample data text if the plot data is valid. Uses the python
|
||||
* code of the plot delegate's isValid() and getSampleText() methods to get the
|
||||
* sample text.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 18, 2014 2868 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class SampleTextExecutor extends AbstractPlotDelegateExecutor implements
|
||||
IPythonExecutor<PlotPythonScript, String> {
|
||||
|
||||
public SampleTextExecutor(PlotData data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(PlotPythonScript script) throws JepException {
|
||||
String result = null;
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
args.put("rec", plotData);
|
||||
Boolean isValid = (Boolean) script.execute("isValid", args);
|
||||
if (isValid.booleanValue()) {
|
||||
result = (String) script.execute("getSampleText", args);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -60,7 +60,6 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
|||
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
|
||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||
import com.raytheon.viz.pointdata.PlotAlertParser;
|
||||
import com.raytheon.viz.pointdata.PlotDataThreadPool;
|
||||
import com.raytheon.viz.pointdata.PlotInfo;
|
||||
import com.raytheon.viz.pointdata.drawables.IPointImageExtension;
|
||||
import com.raytheon.viz.pointdata.drawables.IPointImageExtension.PointImage;
|
||||
|
@ -70,6 +69,7 @@ import com.raytheon.viz.pointdata.rsc.progdisc.DynamicProgDisclosure;
|
|||
import com.raytheon.viz.pointdata.rsc.progdisc.SpiProgDisclosure;
|
||||
import com.raytheon.viz.pointdata.thread.GetDataTask;
|
||||
import com.raytheon.viz.pointdata.thread.GetDataTask.Params;
|
||||
import com.raytheon.viz.pointdata.thread.PlotThreadOverseer;
|
||||
import com.raytheon.viz.pointdata.units.PlotUnits;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
|
@ -98,6 +98,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
* Jun 25, 2013 1869 bsteffen Fix plot sampling.
|
||||
* Sep 04, 2013 16519 kshresth Fix Metar Display Problem
|
||||
* Dec 02, 2013 2473 njensen Prog Disclose paint frames at high priority
|
||||
* Mar 21, 2014 2868 njensen Use PlotThreadOverseer for increased efficiency
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -116,7 +117,7 @@ public class PlotResource2 extends
|
|||
|
||||
private AbstractProgDisclosure progressiveDisclosure;
|
||||
|
||||
private PlotDataThreadPool generator;
|
||||
private PlotThreadOverseer generator;
|
||||
|
||||
private double plotWidth;
|
||||
|
||||
|
@ -265,7 +266,7 @@ public class PlotResource2 extends
|
|||
Map<String, RequestConstraint> request = resourceData.getMetadataMap();
|
||||
RequestConstraint plugin = request.get("pluginName");
|
||||
PlotUnits.register();
|
||||
generator = new PlotDataThreadPool(aTarget, descriptor,
|
||||
generator = new PlotThreadOverseer(aTarget, descriptor,
|
||||
this.resourceData.getPlotModelFile(),
|
||||
this.resourceData.getLevelKey(), plugin.getConstraintValue(),
|
||||
this.resourceData.getMetadataMap(), this);
|
||||
|
@ -279,7 +280,7 @@ public class PlotResource2 extends
|
|||
this.generator.setPlotMissingData(resourceData.isPlotMissingData());
|
||||
this.generator.setLowerLimit(resourceData.getLowerLimit());
|
||||
this.generator.setUpperLimit(resourceData.getUpperLimit());
|
||||
this.plotWidth = generator.getPlotModelWidth();
|
||||
this.plotWidth = generator.getOriginalPlotModelWidth();
|
||||
this.plotWidth *= getCapability(MagnificationCapability.class)
|
||||
.getMagnification();
|
||||
generator.setPlotModelSize(Math.round(plotWidth));
|
||||
|
@ -431,7 +432,7 @@ public class PlotResource2 extends
|
|||
list.add(samplePlot);
|
||||
Params params = Params.PLOT_AND_SAMPLE;
|
||||
GetDataTask task = new GetDataTask(list, params);
|
||||
generator.queueStation(task);
|
||||
generator.enqueueDataRetrieval(task);
|
||||
// End DR14996
|
||||
}
|
||||
boolean dup = false;
|
||||
|
@ -575,7 +576,7 @@ public class PlotResource2 extends
|
|||
params = Params.SAMPLE_ONLY;
|
||||
}
|
||||
GetDataTask task = new GetDataTask(list, params);
|
||||
generator.queueStation(task);
|
||||
generator.enqueueDataRetrieval(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -616,7 +617,7 @@ public class PlotResource2 extends
|
|||
}
|
||||
} else if (object instanceof MagnificationCapability) {
|
||||
if (generator != null) {
|
||||
this.plotWidth = generator.getPlotModelWidth();
|
||||
this.plotWidth = generator.getOriginalPlotModelWidth();
|
||||
this.plotWidth *= getCapability(
|
||||
MagnificationCapability.class).getMagnification();
|
||||
generator.setPlotModelSize(Math.round(plotWidth));
|
||||
|
@ -758,7 +759,7 @@ public class PlotResource2 extends
|
|||
}
|
||||
if (toQueue.size() > 0) {
|
||||
GetDataTask task = new GetDataTask(toQueue, Params.PLOT_ONLY);
|
||||
generator.queueStation(task);
|
||||
generator.enqueueDataRetrieval(task);
|
||||
}
|
||||
} else {
|
||||
issueRefresh();
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* 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.pointdata.thread;
|
||||
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||
|
||||
/**
|
||||
* Abstract job associated with one of the many details of plot creation.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 21, 2014 2868 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public abstract class AbstractPlotCreationJob extends Job {
|
||||
|
||||
protected static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(PlotModelDataRequestJob.class);
|
||||
|
||||
protected PlotThreadOverseer overseer;
|
||||
|
||||
protected IPlotModelGeneratorCaller listener;
|
||||
|
||||
public AbstractPlotCreationJob(String name, PlotThreadOverseer parent,
|
||||
IPlotModelGeneratorCaller caller) {
|
||||
super(name);
|
||||
this.overseer = parent;
|
||||
this.listener = caller;
|
||||
this.setSystem(false);
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return getState() != Job.RUNNING && getState() != Job.WAITING;
|
||||
}
|
||||
|
||||
public boolean shutdown() {
|
||||
return super.cancel();
|
||||
}
|
||||
|
||||
}
|
|
@ -24,7 +24,8 @@ import java.util.List;
|
|||
import com.raytheon.viz.pointdata.PlotInfo;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* A task to retrieve plot data for a set of stations, possibly requesting the
|
||||
* parameters necessary for the plot image or the sample text or both.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -33,6 +34,7 @@ import com.raytheon.viz.pointdata.PlotInfo;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 18, 2011 njensen Initial creation
|
||||
* Mar 21, 2014 2868 njensen Improved javadoc
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.pointdata;
|
||||
package com.raytheon.viz.pointdata.thread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -27,30 +27,25 @@ import java.util.Map;
|
|||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
|
||||
import com.raytheon.uf.common.pointdata.PointDataContainer;
|
||||
import com.raytheon.uf.common.pointdata.PointDataView;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
||||
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.map.IMapDescriptor;
|
||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||
import com.raytheon.viz.pointdata.PlotData;
|
||||
import com.raytheon.viz.pointdata.PlotInfo;
|
||||
import com.raytheon.viz.pointdata.PlotModelFactory2.PlotModelElement;
|
||||
import com.raytheon.viz.pointdata.PointDataRequest;
|
||||
import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
||||
import com.raytheon.viz.pointdata.thread.GetDataTask;
|
||||
import com.raytheon.viz.pointdata.thread.PlotSampleGeneratorJob;
|
||||
|
||||
/**
|
||||
* Job separated from PlotModelGenerator2 that requests plot data and passes it
|
||||
* on to the PlotModelGeneratorJob.
|
||||
* Job that requests plot data based on a constraintMap and the parameters
|
||||
* specified inside the plot model SVG file.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -60,6 +55,7 @@ import com.raytheon.viz.pointdata.thread.PlotSampleGeneratorJob;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 22, 2011 njensen Initial creation
|
||||
* May 14, 2013 1869 bsteffen Get plots working without dataURI
|
||||
* Mar 21, 2014 2868 njensen Major refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -67,53 +63,42 @@ import com.raytheon.viz.pointdata.thread.PlotSampleGeneratorJob;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PlotModelDataRequestJob extends Job {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(PlotModelDataRequestJob.class);
|
||||
|
||||
private PlotModelFactory2 plotCreator;
|
||||
public class PlotModelDataRequestJob extends AbstractPlotCreationJob {
|
||||
|
||||
private Map<String, RequestConstraint> constraintMap;
|
||||
|
||||
private String plugin;
|
||||
private final String plugin;
|
||||
|
||||
private String levelKey;
|
||||
private final String levelKey;
|
||||
|
||||
private PlotModelGeneratorJob generatorJob;
|
||||
private final List<PlotModelElement> plotFields;
|
||||
|
||||
private PlotSampleGeneratorJob sampleJob;
|
||||
private final List<PlotModelElement> sampleFields;
|
||||
|
||||
private PlotDataThreadPool parent;
|
||||
|
||||
public PlotModelDataRequestJob(IGraphicsTarget aTarget,
|
||||
IMapDescriptor mapDescriptor, String plotModelFile,
|
||||
String levelKey, String plugin,
|
||||
Map<String, RequestConstraint> constraintMap,
|
||||
IPlotModelGeneratorCaller caller, PlotDataThreadPool parent)
|
||||
public PlotModelDataRequestJob(PlotThreadOverseer parent,
|
||||
IPlotModelGeneratorCaller caller,
|
||||
List<PlotModelElement> plotFields,
|
||||
List<PlotModelElement> sampleFields, String levelKey,
|
||||
String plugin, Map<String, RequestConstraint> constraintMap)
|
||||
throws VizException {
|
||||
super("Requesting Plot Data...");
|
||||
plotCreator = new PlotModelFactory2(mapDescriptor, plotModelFile);
|
||||
super("Requesting Plot Data...", parent, caller);
|
||||
this.plotFields = plotFields;
|
||||
this.sampleFields = sampleFields;
|
||||
this.plugin = plugin;
|
||||
this.levelKey = levelKey;
|
||||
this.constraintMap = constraintMap;
|
||||
this.generatorJob = new PlotModelGeneratorJob(plotCreator, caller,
|
||||
aTarget);
|
||||
this.generatorJob.setSystem(false);
|
||||
this.sampleJob = new PlotSampleGeneratorJob(plotCreator, caller);
|
||||
this.sampleJob.setSystem(false);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
while (parent.stationQueue.size() > 0) {
|
||||
while (overseer.dataRetrievalQueue.size() > 0) {
|
||||
List<PlotInfo[]> stationQuery = new ArrayList<PlotInfo[]>();
|
||||
|
||||
GetDataTask task = null;
|
||||
synchronized (this) {
|
||||
task = parent.stationQueue.poll();
|
||||
task = overseer.dataRetrievalQueue.poll();
|
||||
if (task == null) {
|
||||
// possibility another thread got it first
|
||||
continue;
|
||||
}
|
||||
List<PlotInfo[]> batch = task.getStations();
|
||||
|
@ -125,15 +110,15 @@ public class PlotModelDataRequestJob extends Job {
|
|||
List<PlotModelElement> pme = null;
|
||||
switch (task.getRequestType()) {
|
||||
case PLOT_ONLY:
|
||||
pme = this.plotCreator.getPlotFields();
|
||||
pme = plotFields;
|
||||
break;
|
||||
case SAMPLE_ONLY:
|
||||
pme = this.plotCreator.getSampleFields();
|
||||
pme = sampleFields;
|
||||
break;
|
||||
case PLOT_AND_SAMPLE:
|
||||
pme = new ArrayList<PlotModelElement>();
|
||||
pme.addAll(this.plotCreator.getPlotFields());
|
||||
pme.addAll(this.plotCreator.getSampleFields());
|
||||
pme.addAll(plotFields);
|
||||
pme.addAll(sampleFields);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -161,14 +146,14 @@ public class PlotModelDataRequestJob extends Job {
|
|||
if (infos[0].pdv != null) {
|
||||
switch (task.getRequestType()) {
|
||||
case PLOT_ONLY:
|
||||
this.generatorJob.enqueue(infos);
|
||||
overseer.enqueueImageGeneration(infos);
|
||||
break;
|
||||
case SAMPLE_ONLY:
|
||||
this.sampleJob.enqueue(infos);
|
||||
overseer.enqueueSamplePlot(infos);
|
||||
break;
|
||||
case PLOT_AND_SAMPLE:
|
||||
this.generatorJob.enqueue(infos);
|
||||
this.sampleJob.enqueue(infos);
|
||||
overseer.enqueueImageGeneration(infos);
|
||||
overseer.enqueueSamplePlot(infos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -186,12 +171,13 @@ public class PlotModelDataRequestJob extends Job {
|
|||
List<String> params = new ArrayList<String>();
|
||||
|
||||
for (PlotModelElement p : pme) {
|
||||
if (!p.parameter.equals("") && !p.parameter.contains(",")) {
|
||||
params.add(p.parameter);
|
||||
} else if (p.parameter.contains(",")) {
|
||||
String[] individualParams = p.parameter.split(",");
|
||||
for (String param : individualParams) {
|
||||
params.add(param);
|
||||
String param = p.getParameter();
|
||||
if (!param.equals("") && !param.contains(",")) {
|
||||
params.add(param);
|
||||
} else if (param.contains(",")) {
|
||||
String[] individualParams = param.split(",");
|
||||
for (String paramToRequest : individualParams) {
|
||||
params.add(paramToRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +186,7 @@ public class PlotModelDataRequestJob extends Job {
|
|||
.getPluginProperties(plugin).hasDistinctStationId;
|
||||
String uniquePointDataKey = "stationId";
|
||||
String uniqueQueryKey = "location.stationId";
|
||||
if(!hasDistinctStationId){
|
||||
if (!hasDistinctStationId) {
|
||||
uniquePointDataKey = "dataURI";
|
||||
uniqueQueryKey = uniquePointDataKey;
|
||||
|
||||
|
@ -208,7 +194,7 @@ public class PlotModelDataRequestJob extends Job {
|
|||
if (!params.contains(uniquePointDataKey)) {
|
||||
params.add(uniquePointDataKey);
|
||||
}
|
||||
|
||||
|
||||
Map<String, RequestConstraint> map = new HashMap<String, RequestConstraint>();
|
||||
map.putAll(this.constraintMap);
|
||||
RequestConstraint rc = new RequestConstraint();
|
||||
|
@ -221,7 +207,7 @@ public class PlotModelDataRequestJob extends Job {
|
|||
String key = null;
|
||||
if (hasDistinctStationId) {
|
||||
key = info.stationId;
|
||||
}else{
|
||||
} else {
|
||||
key = info.dataURI;
|
||||
}
|
||||
str.add(key);
|
||||
|
@ -347,50 +333,4 @@ public class PlotModelDataRequestJob extends Job {
|
|||
}
|
||||
}
|
||||
|
||||
public void setUpperLimit(double upperLimit) {
|
||||
this.plotCreator.setUpperLimit(upperLimit);
|
||||
}
|
||||
|
||||
public void setLowerLimit(double lowerLimit) {
|
||||
this.plotCreator.setLowerLimit(lowerLimit);
|
||||
}
|
||||
|
||||
public int getPlotModelWidth() {
|
||||
return this.plotCreator.getDefinedPlotModelWidth();
|
||||
}
|
||||
|
||||
public void setPlotModelSize(long width) {
|
||||
this.plotCreator.setPlotDimensions(width, width);
|
||||
this.generatorJob.clearImageCache();
|
||||
}
|
||||
|
||||
public void setPlotModelColor(RGB color) {
|
||||
this.plotCreator.setColor(color);
|
||||
// this.generatorJob.cleanImages();
|
||||
}
|
||||
|
||||
public void setPlotModelLineWidth(int width) {
|
||||
this.plotCreator.setLineWidth(width);
|
||||
this.generatorJob.clearImageCache();
|
||||
}
|
||||
|
||||
public void setPlotModelLineStyle(LineStyle style) {
|
||||
this.plotCreator.setLineStyle(style);
|
||||
this.generatorJob.clearImageCache();
|
||||
}
|
||||
|
||||
public void setPlotMissingData(boolean b) {
|
||||
this.plotCreator.setPlotMissingData(b);
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return getState() != Job.RUNNING && getState() != Job.WAITING
|
||||
&& generatorJob.isDone();
|
||||
}
|
||||
|
||||
public synchronized void shutdown() {
|
||||
this.cancel();
|
||||
this.generatorJob.shutdown();
|
||||
}
|
||||
|
||||
}
|
|
@ -17,29 +17,28 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.pointdata;
|
||||
package com.raytheon.viz.pointdata.thread;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.apache.commons.collections.map.LRUMap;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||
import com.raytheon.viz.pointdata.PlotInfo;
|
||||
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||
|
||||
/**
|
||||
* Job separated from PlotModelGenerator2 that creates the plot images.
|
||||
* Job that generates plot images using a PlotModelFactory2.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -48,6 +47,7 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 22, 2011 njensen Initial creation
|
||||
* Mar 21, 2014 2868 njensen Major refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -55,27 +55,20 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PlotModelGeneratorJob extends Job {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(PlotModelDataRequestJob.class);
|
||||
|
||||
private ConcurrentLinkedQueue<PlotInfo[]> taskQueue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
||||
public class PlotModelGeneratorJob extends AbstractPlotCreationJob {
|
||||
|
||||
private PlotModelFactory2 plotCreator;
|
||||
|
||||
private IPlotModelGeneratorCaller caller;
|
||||
|
||||
private IGraphicsTarget target;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<BufferedImage, IImage> imageCache = new LRUMap(1000);
|
||||
|
||||
protected PlotModelGeneratorJob(PlotModelFactory2 plotCreator,
|
||||
IPlotModelGeneratorCaller caller, IGraphicsTarget target) {
|
||||
super("Creating plots");
|
||||
protected PlotModelGeneratorJob(PlotThreadOverseer parent,
|
||||
IPlotModelGeneratorCaller caller, PlotModelFactory2 plotCreator,
|
||||
IGraphicsTarget target) {
|
||||
super("Creating plots", parent, caller);
|
||||
this.plotCreator = plotCreator;
|
||||
this.caller = caller;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
|
@ -88,9 +81,14 @@ public class PlotModelGeneratorJob extends Job {
|
|||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
long t0 = System.currentTimeMillis();
|
||||
while (!taskQueue.isEmpty()) {
|
||||
long count = 0;
|
||||
while (!overseer.imageCreationQueue.isEmpty()) {
|
||||
try {
|
||||
PlotInfo[] infos = taskQueue.poll();
|
||||
PlotInfo[] infos = overseer.imageCreationQueue.poll();
|
||||
if (infos == null) {
|
||||
// possibility another thread got it first
|
||||
continue;
|
||||
}
|
||||
final BufferedImage bImage = plotCreator.getStationPlot(
|
||||
infos[0].pdv, infos[0].latitude, infos[0].longitude);
|
||||
IImage image = null;
|
||||
|
@ -120,46 +118,40 @@ public class PlotModelGeneratorJob extends Job {
|
|||
}
|
||||
synchronized (this) {
|
||||
if (monitor.isCanceled()) {
|
||||
if(image != null){
|
||||
if (image != null) {
|
||||
image.dispose();
|
||||
}
|
||||
break;
|
||||
}
|
||||
caller.modelGenerated(infos, image);
|
||||
count++;
|
||||
listener.modelGenerated(infos, image);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
statusHandler.error("Error creating plot", e);
|
||||
statusHandler.error("Error creating plot with plotModel "
|
||||
+ plotCreator.getPlotModelFilename(), e);
|
||||
}
|
||||
}
|
||||
|
||||
plotCreator.disposeScript();
|
||||
System.out.println("Time spent creating plots: "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
protected void enqueue(PlotInfo[] task) {
|
||||
this.taskQueue.add(task);
|
||||
if (this.getState() != Job.RUNNING) {
|
||||
this.schedule();
|
||||
if (count > 0) {
|
||||
/*
|
||||
* if count is zero it means by the time this job was scheduled and
|
||||
* run, a different job took care of everything on the queue
|
||||
*/
|
||||
System.out.println("Time spent creating " + count + " plots: "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
}
|
||||
}
|
||||
|
||||
protected int getQueueSize() {
|
||||
return taskQueue.size();
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
protected void clearImageCache() {
|
||||
imageCache.clear();
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return getState() != Job.RUNNING && getState() != Job.WAITING;
|
||||
}
|
||||
|
||||
protected synchronized void shutdown() {
|
||||
cancel();
|
||||
taskQueue.clear();
|
||||
@Override
|
||||
public boolean shutdown() {
|
||||
boolean result = super.shutdown();
|
||||
clearImageCache();
|
||||
plotCreator.dispose();
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -19,22 +19,17 @@
|
|||
**/
|
||||
package com.raytheon.viz.pointdata.thread;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||
import com.raytheon.viz.pointdata.PlotInfo;
|
||||
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||
|
||||
/**
|
||||
* Job that uses the provided factory to generate a sampling message for a
|
||||
* particular plot.
|
||||
* Job that uses the provided plot model factory to generate a sampling message
|
||||
* for a particular plot.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -44,6 +39,7 @@ import com.raytheon.viz.pointdata.PlotModelFactory2;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 13, 2011 njensen Initial creation
|
||||
* Jun 25, 2013 1869 bsteffen Fix plot sampling.
|
||||
* Mar 21, 2014 2868 njensen Major refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -51,22 +47,14 @@ import com.raytheon.viz.pointdata.PlotModelFactory2;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PlotSampleGeneratorJob extends Job {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(PlotSampleGeneratorJob.class);
|
||||
public class PlotSampleGeneratorJob extends AbstractPlotCreationJob {
|
||||
|
||||
private PlotModelFactory2 plotFactory;
|
||||
|
||||
private ConcurrentLinkedQueue<PlotInfo[]> queue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
||||
|
||||
private IPlotModelGeneratorCaller caller;
|
||||
|
||||
public PlotSampleGeneratorJob(PlotModelFactory2 factory,
|
||||
IPlotModelGeneratorCaller caller) {
|
||||
super("Generating samples");
|
||||
public PlotSampleGeneratorJob(PlotThreadOverseer parent,
|
||||
IPlotModelGeneratorCaller caller, PlotModelFactory2 factory) {
|
||||
super("Generating samples", parent, caller);
|
||||
this.plotFactory = factory;
|
||||
this.caller = caller;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -77,27 +65,29 @@ public class PlotSampleGeneratorJob extends Job {
|
|||
*/
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
while (!queue.isEmpty()) {
|
||||
while (!overseer.sampleTextQueue.isEmpty()) {
|
||||
try {
|
||||
PlotInfo[] infos = queue.poll();
|
||||
PlotInfo[] infos = overseer.sampleTextQueue.poll();
|
||||
if (infos == null) {
|
||||
// possibility another thread got it first
|
||||
continue;
|
||||
}
|
||||
String message = plotFactory.getStationMessage(infos[0].pdv,
|
||||
infos[0].dataURI);
|
||||
|
||||
caller.messageGenerated(infos, message);
|
||||
listener.messageGenerated(infos, message);
|
||||
} catch (Exception e) {
|
||||
statusHandler.error("Error creating plot", e);
|
||||
statusHandler.error("Error creating sample with plotModel "
|
||||
+ plotFactory.getPlotModelFilename(), e);
|
||||
}
|
||||
}
|
||||
|
||||
plotFactory.disposeSampleScript();
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
public void enqueue(PlotInfo[] task) {
|
||||
this.queue.add(task);
|
||||
if (this.getState() != Job.RUNNING) {
|
||||
this.schedule();
|
||||
}
|
||||
@Override
|
||||
public boolean shutdown() {
|
||||
boolean result = super.shutdown();
|
||||
plotFactory.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
/**
|
||||
* 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.pointdata.thread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.map.MapDescriptor;
|
||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||
import com.raytheon.viz.pointdata.PlotInfo;
|
||||
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||
import com.raytheon.viz.pointdata.PlotModelFactory2.PlotModelElement;
|
||||
|
||||
/**
|
||||
* Oversees a variety of threads used to concurrently and quickly get plots on
|
||||
* screen. There should be only one PlotThreadOverseer for each PlotResource2.
|
||||
*
|
||||
* This class oversees the pipeline of threads necessary for requesting plot
|
||||
* data, generating plot images, and generating plot samples. Note that it does
|
||||
* not involve itself with progressive disclosure, paint, or python threads.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 21, 2014 2868 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PlotThreadOverseer {
|
||||
|
||||
private static final int DATA_THREADS = 2;
|
||||
|
||||
private static final int IMAGE_THREADS = DATA_THREADS;
|
||||
|
||||
private static final int SAMPLE_THREADS = 1;
|
||||
|
||||
protected ConcurrentLinkedQueue<GetDataTask> dataRetrievalQueue = new ConcurrentLinkedQueue<GetDataTask>();
|
||||
|
||||
protected List<PlotModelDataRequestJob> dataRetrievalJobList = new ArrayList<PlotModelDataRequestJob>(
|
||||
DATA_THREADS);
|
||||
|
||||
protected ConcurrentLinkedQueue<PlotInfo[]> imageCreationQueue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
||||
|
||||
protected List<PlotModelGeneratorJob> imageCreationJobList = new ArrayList<PlotModelGeneratorJob>(
|
||||
IMAGE_THREADS);
|
||||
|
||||
protected List<PlotModelFactory2> plotCreatorList = new ArrayList<PlotModelFactory2>(
|
||||
IMAGE_THREADS);
|
||||
|
||||
protected ConcurrentLinkedQueue<PlotInfo[]> sampleTextQueue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
||||
|
||||
protected List<PlotSampleGeneratorJob> sampleTextJobList = new ArrayList<PlotSampleGeneratorJob>(
|
||||
SAMPLE_THREADS);
|
||||
|
||||
private int plotModelWidth;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param target
|
||||
* @param mapDescriptor
|
||||
* @param plotModelFile
|
||||
* @param levelKey
|
||||
* @param plugin
|
||||
* @param constraintMap
|
||||
* @param caller
|
||||
* @throws VizException
|
||||
*/
|
||||
public PlotThreadOverseer(IGraphicsTarget target,
|
||||
MapDescriptor mapDescriptor, String plotModelFile, String levelKey,
|
||||
String plugin, HashMap<String, RequestConstraint> constraintMap,
|
||||
IPlotModelGeneratorCaller caller) throws VizException {
|
||||
|
||||
/*
|
||||
* Set up image generation jobs first because the PlotModelFactory2
|
||||
* initialization will parse the SVG to determine the parameters to
|
||||
* request
|
||||
*/
|
||||
List<PlotModelElement> plotFields = null;
|
||||
List<PlotModelElement> sampleFields = null;
|
||||
for (int i = 0; i < IMAGE_THREADS; i++) {
|
||||
PlotModelFactory2 plotModelFactory = new PlotModelFactory2(
|
||||
mapDescriptor, plotModelFile);
|
||||
plotCreatorList.add(plotModelFactory);
|
||||
imageCreationJobList.add(new PlotModelGeneratorJob(this, caller,
|
||||
plotModelFactory, target));
|
||||
if (plotFields == null) {
|
||||
/*
|
||||
* data retrieval jobs need to know the plot and sample fields
|
||||
* to request, which have now been parsed out of the SVG
|
||||
*/
|
||||
plotFields = plotModelFactory.getPlotFields();
|
||||
sampleFields = plotModelFactory.getSampleFields();
|
||||
plotModelWidth = plotModelFactory.getDefinedPlotModelWidth();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the data retrieval jobs
|
||||
*/
|
||||
for (int i = 0; i < DATA_THREADS; i++) {
|
||||
dataRetrievalJobList.add(new PlotModelDataRequestJob(this, caller,
|
||||
plotFields, sampleFields, levelKey, plugin, constraintMap));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the sample jobs. We could probably reuse the plot model
|
||||
* factories of the image jobs, regardless, if it's a sample that uses
|
||||
* python it will reuse the python job coordinator underneath, and if
|
||||
* it's not...it's not clear if
|
||||
* PlotModelFactory2.processSampleDirective() is thread safe
|
||||
*
|
||||
* TODO do we care?
|
||||
*/
|
||||
for (int i = 0; i < SAMPLE_THREADS; i++) {
|
||||
PlotModelFactory2 plotModelFactory = new PlotModelFactory2(
|
||||
mapDescriptor, plotModelFile);
|
||||
sampleTextJobList.add(new PlotSampleGeneratorJob(this, caller,
|
||||
plotModelFactory));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues a task of a batch of stations to retrieve data for
|
||||
*
|
||||
* @param task
|
||||
*
|
||||
*/
|
||||
public void enqueueDataRetrieval(GetDataTask task) {
|
||||
List<PlotInfo[]> station = task.getStations();
|
||||
|
||||
Iterator<PlotInfo[]> itr = station.iterator();
|
||||
while (itr.hasNext()) {
|
||||
PlotInfo[] infos = itr.next();
|
||||
boolean allQueued = true;
|
||||
for (PlotInfo info : infos) {
|
||||
switch (task.getRequestType()) {
|
||||
case PLOT_ONLY:
|
||||
if (!info.plotQueued) {
|
||||
allQueued = false;
|
||||
info.plotQueued = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case SAMPLE_ONLY:
|
||||
if (!info.sampleQueued) {
|
||||
allQueued = false;
|
||||
info.sampleQueued = true;
|
||||
}
|
||||
break;
|
||||
case PLOT_AND_SAMPLE:
|
||||
if (!info.sampleQueued) {
|
||||
allQueued = false;
|
||||
info.sampleQueued = true;
|
||||
}
|
||||
if (!info.plotQueued) {
|
||||
allQueued = false;
|
||||
info.plotQueued = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allQueued) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (station.size() > 0) {
|
||||
task.setStations(station);
|
||||
dataRetrievalQueue.add(task);
|
||||
for (PlotModelDataRequestJob job : dataRetrievalJobList) {
|
||||
if (job.getState() != Job.RUNNING) {
|
||||
job.schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a batch of PlotInfos to generate images for
|
||||
*
|
||||
* @param plotInfo
|
||||
*/
|
||||
public void enqueueImageGeneration(PlotInfo[] plotInfo) {
|
||||
if (plotInfo.length > 0) {
|
||||
imageCreationQueue.add(plotInfo);
|
||||
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||
if (job.getState() != Job.RUNNING) {
|
||||
job.schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a batch of PlotInfos to generate sample messages for
|
||||
*
|
||||
* @param plotInfo
|
||||
*/
|
||||
public void enqueueSamplePlot(PlotInfo[] plotInfo) {
|
||||
if (plotInfo.length > 0) {
|
||||
sampleTextQueue.add(plotInfo);
|
||||
for (PlotSampleGeneratorJob job : sampleTextJobList) {
|
||||
if (job.getState() != Job.RUNNING) {
|
||||
job.schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlotModelColor(RGB color) {
|
||||
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||
pmf.setColor(color);
|
||||
}
|
||||
// don't clear the image cache, it's magic
|
||||
}
|
||||
|
||||
public void setPlotModelLineStyle(LineStyle lineStyle) {
|
||||
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||
pmf.setLineStyle(lineStyle);
|
||||
}
|
||||
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||
job.clearImageCache();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlotModelLineWidth(int outlineWidth) {
|
||||
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||
pmf.setLineWidth(outlineWidth);
|
||||
}
|
||||
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||
job.clearImageCache();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlotMissingData(boolean plotMissingData) {
|
||||
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||
pmf.setPlotMissingData(plotMissingData);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLowerLimit(double lowerLimit) {
|
||||
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||
pmf.setLowerLimit(lowerLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUpperLimit(double upperLimit) {
|
||||
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||
pmf.setUpperLimit(upperLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public double getOriginalPlotModelWidth() {
|
||||
return plotModelWidth;
|
||||
}
|
||||
|
||||
public void setPlotModelSize(long round) {
|
||||
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||
pmf.setPlotDimensions(round, round);
|
||||
}
|
||||
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||
job.clearImageCache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all the jobs related to requesting data, creating plot images,
|
||||
* and creating samples are done
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isDone() {
|
||||
for (AbstractPlotCreationJob job : dataRetrievalJobList) {
|
||||
if (!job.isDone()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (AbstractPlotCreationJob job : imageCreationJobList) {
|
||||
if (!job.isDone()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (AbstractPlotCreationJob job : sampleTextJobList) {
|
||||
if (!job.isDone()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down all the threads and clears their queues in a safe manner
|
||||
*/
|
||||
public void shutdown() {
|
||||
/*
|
||||
* by clearing the job lists first, nothing else can get queued, but we
|
||||
* still need a copy of them to ensure they are shut down correctly
|
||||
*/
|
||||
List<AbstractPlotCreationJob> jobListCopy = null;
|
||||
|
||||
// shut down data requests first
|
||||
jobListCopy = new ArrayList<AbstractPlotCreationJob>(
|
||||
dataRetrievalJobList);
|
||||
dataRetrievalJobList.clear();
|
||||
for (AbstractPlotCreationJob job : jobListCopy) {
|
||||
job.shutdown();
|
||||
}
|
||||
dataRetrievalQueue.clear();
|
||||
|
||||
// then shut down images
|
||||
jobListCopy = new ArrayList<AbstractPlotCreationJob>(
|
||||
imageCreationJobList);
|
||||
imageCreationJobList.clear();
|
||||
for (AbstractPlotCreationJob job : jobListCopy) {
|
||||
job.shutdown();
|
||||
}
|
||||
imageCreationQueue.clear();
|
||||
|
||||
// and finally sampling
|
||||
jobListCopy = new ArrayList<AbstractPlotCreationJob>(sampleTextJobList);
|
||||
sampleTextJobList.clear();
|
||||
for (AbstractPlotCreationJob job : jobListCopy) {
|
||||
job.shutdown();
|
||||
}
|
||||
sampleTextQueue.clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ import java.util.concurrent.ExecutionException;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
|
@ -59,6 +60,9 @@ import com.raytheon.uf.common.python.PythonInterpreter;
|
|||
* Jan 31, 2013 mnash Initial creation
|
||||
* Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent
|
||||
* python.
|
||||
* Mar 21, 2014 2868 njensen Changed getInstance() from throwing
|
||||
* RuntimeException to IllegalArgumentException
|
||||
* Added refCount
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -71,10 +75,17 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
|||
|
||||
private ThreadLocal<P> threadLocal = null;
|
||||
|
||||
/**
|
||||
* Tracks the number of times newInstance() vs shutdown() is called for an
|
||||
* instance of a PythonJobCoordinator
|
||||
*/
|
||||
private AtomicInteger refCount;
|
||||
|
||||
private static Map<String, PythonJobCoordinator<? extends PythonInterpreter>> pools = new ConcurrentHashMap<String, PythonJobCoordinator<? extends PythonInterpreter>>();
|
||||
|
||||
private PythonJobCoordinator(final AbstractPythonScriptFactory<P> factory) {
|
||||
threadLocal = new ThreadLocal<P>() {
|
||||
@Override
|
||||
protected P initialValue() {
|
||||
try {
|
||||
return factory.createPythonScript();
|
||||
|
@ -85,10 +96,11 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
|||
};
|
||||
execService = Executors.newFixedThreadPool(factory.getMaxThreads(),
|
||||
new PythonThreadFactory(threadLocal, factory.getName()));
|
||||
refCount = new AtomicInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance by name, or throw a {@link RuntimeException}.
|
||||
* Gets the instance by name, or throw a {@link IllegalArgumentException}.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
|
@ -99,7 +111,7 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
|||
if (pools.containsKey(name)) {
|
||||
return (PythonJobCoordinator<S>) pools.get(name);
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to find instance of PythonJobCoordinator named "
|
||||
+ name
|
||||
+ ", please call newInstance(AbstractPythonScriptFactory)");
|
||||
|
@ -110,7 +122,10 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
|||
/**
|
||||
* Creates a new instance of this class for a new application. If the same
|
||||
* name already exists, it assumes that it is the same application and
|
||||
* returns the existing instance.
|
||||
* returns the existing instance. Also increments the reference count of
|
||||
* applications using this PythonJobCoordinator. For each time that
|
||||
* newInstance() is called, a corresponding call to shutdown() will be
|
||||
* needed if you truly want to shut the job coordinator down.
|
||||
*
|
||||
* @param name
|
||||
* @param numThreads
|
||||
|
@ -119,14 +134,15 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
|||
public static <S extends PythonInterpreter> PythonJobCoordinator<S> newInstance(
|
||||
AbstractPythonScriptFactory<S> factory) {
|
||||
synchronized (pools) {
|
||||
PythonJobCoordinator<S> pool = null;
|
||||
if (pools.containsKey(factory.getName())) {
|
||||
return (PythonJobCoordinator<S>) pools.get(factory.getName());
|
||||
pool = (PythonJobCoordinator<S>) pools.get(factory.getName());
|
||||
} else {
|
||||
PythonJobCoordinator<S> pool = new PythonJobCoordinator<S>(
|
||||
factory);
|
||||
pool = new PythonJobCoordinator<S>(factory);
|
||||
pools.put(factory.getName(), pool);
|
||||
return pool;
|
||||
}
|
||||
pool.refCount.getAndIncrement();
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,15 +187,20 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
|||
/**
|
||||
* This function should take the {@link PythonInterpreter} on each thread in
|
||||
* the thread pool and dispose of it and then shutdown the
|
||||
* {@link ExecutorService}
|
||||
* {@link ExecutorService}. This will reduce the reference count by 1, and
|
||||
* will only shut down the underlying executor service and python
|
||||
* interpreters if the refCount is less than 1.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public void shutdown() {
|
||||
synchronized (pools) {
|
||||
pools.values().remove(this);
|
||||
int count = refCount.decrementAndGet();
|
||||
if (count < 1) {
|
||||
pools.values().remove(this);
|
||||
execService.shutdown();
|
||||
}
|
||||
}
|
||||
execService.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,7 +212,9 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
|||
*/
|
||||
public void shutdownTask(String name) {
|
||||
/*
|
||||
* TODO need to add for future functionality
|
||||
* TODO need to add for future functionality, arg should probably be an
|
||||
* IPythonExecutor, not a String
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue