diff --git a/cave/com.raytheon.uf.viz.common.core.feature/feature.xml b/cave/com.raytheon.uf.viz.common.core.feature/feature.xml
index 1686cc4f82..f0666aee66 100644
--- a/cave/com.raytheon.uf.viz.common.core.feature/feature.xml
+++ b/cave/com.raytheon.uf.viz.common.core.feature/feature.xml
@@ -326,4 +326,11 @@
version="0.0.0"
unpack="false"/>
+
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 5, 2013 mnash Initial creation + * + *+ * + * @author mnash + * @version 1.0 + */ + +public abstract class AbstractPythonScriptFactory
{ + + private final int maxThreads; + + private final String name; + + /** + * This method will be called on the Python thread and will instantiate the + * PythonInterpreter that is going to be used. + * + * @return + */ + public abstract P createPythonScript(); + + public AbstractPythonScriptFactory(String name, int maxThreads) { + this.name = name; + this.maxThreads = maxThreads; + } + + /** + * @return the maxThreads + */ + public final int getMaxThreads() { + return maxThreads; + } + + /** + * @return the name + */ + public final String getName() { + return name; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonExecutor.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonExecutor.java new file mode 100644 index 0000000000..91941f5575 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonExecutor.java @@ -0,0 +1,51 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.python.concurrent; + +import com.raytheon.uf.common.python.PythonInterpreter; + +/** + * Any class that implements this will be able to execute methods on the + * PythonInterpreter that is passed in + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 5, 2013 mnash Initial creation + * + *+ * + * @author mnash + * @version 1.0 + */ + +public interface IPythonExecutor
{ + /** + * Method takes a {@link PythonInterpreter} and executes the necessary parts + * of it + * + * @param script + * @return + */ + public abstract R execute(P script); +} diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonJobListener.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonJobListener.java new file mode 100644 index 0000000000..b50765daac --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonJobListener.java @@ -0,0 +1,56 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.python.concurrent; + +import java.util.EventListener; + +/** + * Subclasses can create their own instance of this class to specify what to do + * when the {@link PythonJob} is finished + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 30, 2013 mnash Initial creation + * + *+ * + * @author mnash + * @version 1.0 + */ + +public interface IPythonJobListener
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 31, 2013 mnash Initial creation + * + *+ * + * @author mnash + * @version 1.0 + */ +public class PythonJob
+ implements Callable threadPython = null;
+
+ private IPythonJobListener executor;
+
+ public PythonJob(IPythonExecutor executor,
+ IPythonJobListener threadLocal,
+ Object... args) {
+ this.listener = listener;
+ this.threadPython = threadLocal;
+ this.executor = executor;
+ }
+
+ @Override
+ public R call() {
+ P script = threadPython.get();
+ R result = null;
+ try {
+ result = executor.execute(script);
+ } catch (Throwable t) {
+ listener.jobFailed(t);
+ return null;
+ }
+
+ // fire listener to alert the original caller that we are done
+ listener.jobFinished(result);
+ return result;
+ }
+}
diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobCoordinator.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobCoordinator.java
new file mode 100644
index 0000000000..9d0ce2cd16
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobCoordinator.java
@@ -0,0 +1,163 @@
+/**
+ * This software was developed and / or modified by Raytheon Company,
+ * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
+ *
+ * U.S. EXPORT CONTROLLED TECHNICAL DATA
+ * This software product contains export-restricted data whose
+ * export/transfer/disclosure is restricted by U.S. law. Dissemination
+ * to non-U.S. persons whether in the United States or abroad requires
+ * an export license or other authorization.
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address: 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
+ * further licensing information.
+ **/
+package com.raytheon.uf.common.python.concurrent;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.raytheon.uf.common.python.PythonInterpreter;
+
+/**
+ * Interface to get to the {@link ExecutorService}. Allows multiple thread pools
+ * to be created in a single JVM, by passing in a different application name.
+ *
+ * This class will be used in this way:
+ *
+ *
+ * {
+
+ private ExecutorService execService = null;
+
+ private ThreadLocal threadLocal = null;
+
+ private static Map factory) {
+ execService = Executors.newFixedThreadPool(factory.getMaxThreads(),
+ new PythonThreadFactory(factory.getName()));
+ threadLocal = new ThreadLocal () {
+ protected P initialValue() {
+ return factory.createPythonScript();
+ };
+ };
+ }
+
+ /**
+ * Gets the instance by name, or throw a {@link RuntimeException}.
+ *
+ * @param name
+ * @return
+ */
+ public static PythonJobCoordinator extends PythonInterpreter> getInstance(
+ String name) {
+ synchronized (pools) {
+ if (pools.containsKey(name)) {
+ return pools.get(name);
+ } else {
+ throw new RuntimeException(
+ "Unable to find instance of PythonJobCoordinator named "
+ + name
+ + ", please call newInstance(AbstractPythonScriptFactory)");
+ }
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @param name
+ * @param numThreads
+ * @return
+ */
+ public static executor,
+ IPythonJobListener job = new PythonJob (executor, listener,
+ threadLocal, args);
+ execService.submit(job);
+ }
+
+ /**
+ * This function should take the {@link PythonInterpreter} on each thread in
+ * the thread pool and dispose of it and then shutdown the
+ * {@link ExecutorService}
+ *
+ * @param name
+ */
+ public void shutdownCoordinator(String name) {
+ /*
+ * TODO need to add for future functionality
+ */
+ }
+
+ /**
+ * This function should cancel any listeners for a certain task and then
+ * remove those corresponding tasks off of the queue to be ran. It should
+ * NOT try to cancel any running python interpreters.
+ *
+ * @param name
+ */
+ public void shutdownTask(String name) {
+ /*
+ * TODO need to add for future functionality
+ */
+ }
+}
diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonThreadFactory.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonThreadFactory.java
new file mode 100644
index 0000000000..943c7aa577
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonThreadFactory.java
@@ -0,0 +1,71 @@
+/**
+ * This software was developed and / or modified by Raytheon Company,
+ * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
+ *
+ * U.S. EXPORT CONTROLLED TECHNICAL DATA
+ * This software product contains export-restricted data whose
+ * export/transfer/disclosure is restricted by U.S. law. Dissemination
+ * to non-U.S. persons whether in the United States or abroad requires
+ * an export license or other authorization.
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address: 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
+ * further licensing information.
+ **/
+package com.raytheon.uf.common.python.concurrent;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Creates new threads named according to what python task they were created
+ * for. Based nearly identically off of {@link ThreadFactory}
+ *
+ *
+ *
+ * AbstractPythonScriptFactory
+ *
+ * @author mnash
+ * @version 1.0
+ */
+public class PythonJobCoordinator PythonJobCoordinator newInstance(
+ AbstractPythonScriptFactory factory) {
+ synchronized (pools) {
+ if (pools.containsKey(factory.getName())) {
+ return (PythonJobCoordinator) pools.get(factory.getName());
+ } else {
+ PythonJobCoordinator pool = new PythonJobCoordinator(
+ factory);
+ pools.put(factory.getName(), pool);
+ return pool;
+ }
+ }
+ }
+
+ /**
+ * Submits a job to the {@link ExecutorService}.
+ *
+ * @param callable
+ * @return
+ * @throws Exception
+ */
+ public
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 31, 2013 mnash Initial creation
+ *
+ *
+ *
+ * @author mnash
+ * @version 1.0
+ */
+
+public class PythonThreadFactory implements ThreadFactory {
+ private static final AtomicInteger poolNumber = new AtomicInteger(1);
+
+ private final ThreadGroup group;
+
+ private final AtomicInteger threadNumber = new AtomicInteger(1);
+
+ private final String namePrefix;
+
+ public PythonThreadFactory(String name) {
+ SecurityManager s = System.getSecurityManager();
+ group = (s != null) ? s.getThreadGroup() : Thread.currentThread()
+ .getThreadGroup();
+ namePrefix = name.toLowerCase() + "-pool-"
+ + poolNumber.getAndIncrement() + "-thread-";
+ }
+
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(group, r, namePrefix
+ + threadNumber.getAndIncrement(), 0);
+ if (t.isDaemon()) {
+ t.setDaemon(false);
+ }
+ if (t.getPriority() != Thread.NORM_PRIORITY) {
+ t.setPriority(Thread.NORM_PRIORITY);
+ }
+ return t;
+ }
+}