diff --git a/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF b/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF index d3282cf0cc..92125c0101 100644 --- a/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF @@ -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, diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotDataThreadPool.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotDataThreadPool.java deleted file mode 100644 index 42404ff691..0000000000 --- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotDataThreadPool.java +++ /dev/null @@ -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. - * - *
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jun 30, 2011 njensen Initial creation - * - *- * - * @author njensen - * @version 1.0 - */ - -public class PlotDataThreadPool { - - private static final int THREADS = 2; - - protected ConcurrentLinkedQueue
* @@ -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 * ** @@ -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
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 18, 2014 2868 njensen Initial creation + * + *+ * + * @author njensen + * @version 1.0 + */ + +public abstract class AbstractPlotDelegateExecutor { + + protected PlotData plotData; + + public AbstractPlotDelegateExecutor(PlotData data) { + this.plotData = data; + } + +} diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/python/CheckPlotValidityExecutor.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/python/CheckPlotValidityExecutor.java new file mode 100644 index 0000000000..69f1ac1c7d --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/python/CheckPlotValidityExecutor.java @@ -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. + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 18, 2014 2868 njensen Initial creation + * + *+ * + * @author njensen + * @version 1.0 + */ + +public class CheckPlotValidityExecutor extends AbstractPlotDelegateExecutor + implements IPythonExecutor
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 14, 2014 2868 njensen Initial creation + * + *+ * + * @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
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 14, 2014 2868 njensen Initial creation + * + *+ * + * @author njensen + * @version 1.0 + */ + +public class PlotPythonScriptFactory extends + AbstractPythonScriptFactory
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 18, 2014 2868 njensen Initial creation + * + *+ * + * @author njensen + * @version 1.0 + */ + +public class SampleTextExecutor extends AbstractPlotDelegateExecutor implements + IPythonExecutor
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 21, 2014 2868 njensen Initial creation + * + *+ * + * @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(); + } + +} diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/thread/GetDataTask.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/thread/GetDataTask.java index cedfe482e9..2558ecf17f 100644 --- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/thread/GetDataTask.java +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/thread/GetDataTask.java @@ -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. * *
* @@ -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 * ** diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelDataRequestJob.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/thread/PlotModelDataRequestJob.java similarity index 72% rename from cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelDataRequestJob.java rename to cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/thread/PlotModelDataRequestJob.java index 1ea761a078..6209fbabd0 100644 --- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelDataRequestJob.java +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/thread/PlotModelDataRequestJob.java @@ -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. * *
* @@ -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 * ** @@ -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
* @@ -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 * ** @@ -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
* @@ -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 * ** @@ -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
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 21, 2014 2868 njensen Initial creation + * + *+ * + * @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
{ private ThreadLocal
threadLocal = null;
+ /**
+ * Tracks the number of times newInstance() vs shutdown() is called for an
+ * instance of a PythonJobCoordinator
+ */
+ private AtomicInteger refCount;
+
private static Map factory) {
threadLocal = new ThreadLocal () {
+ @Override
protected P initialValue() {
try {
return factory.createPythonScript();
@@ -85,10 +96,11 @@ public class PythonJobCoordinator {
};
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 {
if (pools.containsKey(name)) {
return (PythonJobCoordinator {
/**
* 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 {
public static {
/**
* 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 {
*/
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
*/
}
+
}
) 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 PythonJobCoordinator newInstance(
AbstractPythonScriptFactory factory) {
synchronized (pools) {
+ PythonJobCoordinator pool = null;
if (pools.containsKey(factory.getName())) {
- return (PythonJobCoordinator) pools.get(factory.getName());
+ pool = (PythonJobCoordinator) pools.get(factory.getName());
} else {
- PythonJobCoordinator pool = new PythonJobCoordinator(
- factory);
+ pool = new PythonJobCoordinator(factory);
pools.put(factory.getName(), pool);
- return pool;
}
+ pool.refCount.getAndIncrement();
+ return pool;
}
}
@@ -171,15 +187,20 @@ public class PythonJobCoordinator