You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by bu...@apache.org on 2019/10/23 12:34:56 UTC

svn commit: r1868799 - in /uima/uima-ducc/trunk: uima-ducc-database/src/main/java/org/apache/uima/ducc/database/ uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/ uima-ducc-transport/src/main/java/org/apache/uima/ducc/tran...

Author: burn
Date: Wed Oct 23 12:34:55 2019
New Revision: 1868799

URL: http://svn.apache.org/viewvc?rev=1868799&view=rev
Log:
UIMA-6130 Add button to restart an experiment launched as an AP - must have the output dir same as the log dir

Removed:
    uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/js/ducc.experiments.js
Modified:
    uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java
    uima/uima-ducc/trunk/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java
    uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java
    uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java
    uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java
    uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java
    uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
    uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/experiments.jsp
    uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/js/ducc.local.js

Modified: uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java Wed Oct 23 12:34:55 2019
@@ -527,7 +527,7 @@ public class HistoryManagerDb
                 summarizeJob(h, w, "J");
                 break;
             case Service:
-            case Pop:       
+            case Pop:   
                 break;
             case Reservation:
                 break;
@@ -544,7 +544,7 @@ public class HistoryManagerDb
      * Part of history management, recover the indicated job from history.
      */
     @SuppressWarnings("unchecked")
-	<T> T restoreWork(Class<T> cl, String tablename, long friendly_id)
+	<T> T restoreWork(Class<T> cl, String tablename, String type, long friendly_id)
         throws Exception
     {
     	String methodName = "restoreWork";
@@ -552,7 +552,7 @@ public class HistoryManagerDb
         DbHandle h = null;
 
         h = dbManager.open();
-        String cql = "SELECT WORK FROM " + tablename + " WHERE DUCC_ID=" + Long.toString(friendly_id);
+        String cql = "SELECT WORK FROM " + tablename + " WHERE TYPE='" + type +"' AND DUCC_ID=" + Long.toString(friendly_id);
         ResultSet rs = h.execute(cql);
         for ( Row r : rs ) {
             logger.info(methodName, null, "----- Restoring", friendly_id); 
@@ -636,7 +636,7 @@ public class HistoryManagerDb
     public IDuccWorkJob restoreJob(long friendly_id)
         throws Exception
     {
-        return (IDuccWorkJob) restoreWork(IDuccWorkJob.class, JOB_HISTORY_TABLE, friendly_id);
+        return (IDuccWorkJob) restoreWork(IDuccWorkJob.class, JOB_HISTORY_TABLE, "job", friendly_id);
     }
     
     /**
@@ -667,7 +667,7 @@ public class HistoryManagerDb
 	public IDuccWorkReservation restoreReservation(long duccid)
         throws Exception
     {
-        return (IDuccWorkReservation) restoreWork(IDuccWorkReservation.class, RES_HISTORY_TABLE, duccid);
+        return (IDuccWorkReservation) restoreWork(IDuccWorkReservation.class, RES_HISTORY_TABLE, "reservation", duccid);
     }
 	
     /**
@@ -694,14 +694,21 @@ public class HistoryManagerDb
 
 	
     /**
-     * Part of history management, recover ths indicated service instance from history.
+     * Part of history management, recover the indicated service instance from history.
      */
 	public IDuccWorkService restoreService(long duccid)
 		throws Exception
     {
-        return (IDuccWorkService) restoreWork(IDuccWorkService.class, SVC_HISTORY_TABLE, duccid);
+        return (IDuccWorkService) restoreWork(IDuccWorkService.class, SVC_HISTORY_TABLE, "service", duccid);
 	}
 	
+  /**
+   * Restore an AP instance from history.
+   */
+  public IDuccWorkService restoreArbitraryProcess(long duccid) throws Exception {
+    return (IDuccWorkService) restoreWork(IDuccWorkService.class, SVC_HISTORY_TABLE, "AP", duccid);
+  }
+	 
     /**
      * Part of history management, recover ths indicated service instances from history.
      */

Modified: uima/uima-ducc/trunk/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java Wed Oct 23 12:34:55 2019
@@ -458,27 +458,24 @@ public class JobFactory implements IJobF
 		jobRequestProperties.normalize();
 		DuccId jobid = job.getDuccId();
 		DuccType duccType = job.getDuccType();
-        // Service Deployment Type
-        if(jobRequestProperties.containsKey(ServiceRequestProperties.key_service_type_custom)) {
-			job.setServiceDeploymentType(ServiceDeploymentType.custom);
-		}
-        else if(jobRequestProperties.containsKey(ServiceRequestProperties.key_service_type_other)) {
-			job.setServiceDeploymentType(ServiceDeploymentType.other);
-		}
-        else if(jobRequestProperties.containsKey(ServiceRequestProperties.key_service_type_uima)) {
-			job.setServiceDeploymentType(ServiceDeploymentType.uima);
-		}
-        else {
-        	job.setServiceDeploymentType(ServiceDeploymentType.unspecified);
-        }
-        // Service Id
-        String serviceId = null;
-        if(jobRequestProperties.containsKey(ServiceRequestProperties.key_service_id)) {
-        	serviceId = jobRequestProperties.getProperty(ServiceRequestProperties.key_service_id);
-        }
-        job.setServiceId(serviceId);
-
-		// sweep out leftover logging trash
+    // Service Deployment Type
+    if (jobRequestProperties.containsKey(ServiceRequestProperties.key_service_type_custom)) {
+      job.setServiceDeploymentType(ServiceDeploymentType.custom);
+    } else if (jobRequestProperties.containsKey(ServiceRequestProperties.key_service_type_other)) {
+      job.setServiceDeploymentType(ServiceDeploymentType.other);
+    } else if (jobRequestProperties.containsKey(ServiceRequestProperties.key_service_type_uima)) {
+      job.setServiceDeploymentType(ServiceDeploymentType.uima);
+    } else {
+      job.setServiceDeploymentType(ServiceDeploymentType.unspecified);
+    }
+    // Service Id
+    String serviceId = null;
+    if (jobRequestProperties.containsKey(ServiceRequestProperties.key_service_id)) {
+      serviceId = jobRequestProperties.getProperty(ServiceRequestProperties.key_service_id);
+    }
+    job.setServiceId(serviceId);
+    
+    // sweep out leftover logging trash
 		logSweeper(jobRequestProperties.getProperty(JobRequestProperties.key_log_directory), job.getDuccId());
 		// log
 		jobRequestProperties.specification(logger, job.getDuccId());
@@ -508,6 +505,7 @@ public class JobFactory implements IJobF
 			}
 			standardInfo.setNotifications(notificationsArray);
 		}
+
 		// scheduling info
 		DuccSchedulingInfo schedulingInfo = new DuccSchedulingInfo();
 		job.setSchedulingInfo(schedulingInfo);
@@ -526,6 +524,13 @@ public class JobFactory implements IJobF
 
 		if (job.getDuccType() == DuccType.Job){
 		    checkSchedulingLimits(job, schedulingInfo);
+		} else {
+		  // HACK - Check if a JED AP ... duccType is "service" !!!
+		  // HACK - experiment directory MUST = log directoery
+	    String args = jobRequestProperties.getProperty(JobSpecificationProperties.key_process_executable_args);
+	    if (args != null && args.contains(" com.ibm.watsonx.framework.jed.Driver ")) {
+	      standardInfo.setExperimentDirectory(standardInfo.getLogDirectory());
+	    }
 		}
 
 		// process_initialization_time_max (in minutes)
@@ -678,6 +683,7 @@ public class JobFactory implements IJobF
 			executableProcessCommandLine.getArguments().addAll(process_executable_arguments);
 		}
 		// process_initialization_failures_cap
+		// ?? These are not set for APs or SPs ??
 		String failures_cap = jobRequestProperties.getProperty(JobSpecificationProperties.key_process_initialization_failures_cap);
 		try {
 			long process_failures_cap = Long.parseLong(failures_cap);

Modified: uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java Wed Oct 23 12:34:55 2019
@@ -41,7 +41,8 @@ public class DuccStandardInfo implements
 	private String workingDirectory = null;
 	private String[] notifications = null;
 	private long processInitializationTimeMax = 0;
-    private String umask = null;;
+  private String umask = null;
+  private String experimentDirectory;;
 
 	public String getUser() {
 		return user;
@@ -298,6 +299,16 @@ public class DuccStandardInfo implements
 		return true;
 	}
 
+  @Override
+  public String getExperimentDirectory() {
+    return experimentDirectory;
+  }
+
+  @Override
+  public void setExperimentDirectory(String experimentDirectory) {
+    this.experimentDirectory = experimentDirectory;
+  }
+
 	// **********
 
 //

Modified: uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java Wed Oct 23 12:34:55 2019
@@ -63,6 +63,9 @@ public interface IDuccStandardInfo exten
 
 	public String getWorkingDirectory();
 	public void setWorkingDirectory(String workingDirectory);
+	
+  public String getExperimentDirectory();
+  public void setExperimentDirectory(String experimentDirectory);
 
 	public String[] getNotifications();
 	public void setNotifications(String[] notifications);

Modified: uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java Wed Oct 23 12:34:55 2019
@@ -625,6 +625,12 @@ public class HistoryPersistenceManager i
         System.out.println("reservations: "+reservations);
     }
 
+    @Override
+    public IDuccWorkService restoreArbitraryProcess(long friendlyId) throws Exception {
+      // TODO untested!!
+      return restoreService(friendlyId);
+    }
+
     ///// </tool>
 
 }

Modified: uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java Wed Oct 23 12:34:55 2019
@@ -44,6 +44,7 @@ public interface IHistoryPersistenceMana
 	public void                       saveService(IDuccWorkService duccWorkService) throws Exception;
 	public IDuccWorkService           restoreService(long friendly_id)              throws Exception;
 	public List<IDuccWorkService>     restoreServices(long max)                     throws Exception;
+	public IDuccWorkService           restoreArbitraryProcess(long friendlyId)      throws Exception;
 	public List<IDuccWorkService>     restoreArbitraryProcesses(long max)           throws Exception;
 	
     public boolean checkpoint(DuccWorkMap work, Map<DuccId, DuccId> processToJob)   throws Exception;

Modified: uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java Wed Oct 23 12:34:55 2019
@@ -101,6 +101,12 @@ public class NullHistoryManager
 		return  new ArrayList<IDuccWorkService>();
 	}
     
+  public IDuccWorkService restoreArbitraryProcess(long duccId)
+          throws Exception
+    {
+      return null;
+    }
+  
     public List<IDuccWorkService> restoreArbitraryProcesses(long max)
         	throws Exception
     {

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java Wed Oct 23 12:34:55 2019
@@ -305,7 +305,7 @@ public class DuccBoot extends Thread {
             return;                               // Nothing to do if this fails
 		}
 
-        logger.info(location, jobid, messages.fetchLabel("Number of services fetched from history"), duccWorkServices.size());
+        logger.info(location, jobid, messages.fetchLabel("Number of APs fetched from history"), duccWorkServices.size());
 
         int restored = 0;
         int nExperiments = 0;

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java Wed Oct 23 12:34:55 2019
@@ -22,6 +22,11 @@ import java.util.ArrayList;
 
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.id.DuccId;
+import org.apache.uima.ducc.transport.cmdline.ICommandLine;
+import org.apache.uima.ducc.transport.event.common.DuccWorkJob;
+import org.apache.uima.ducc.transport.event.common.IDuccProcess;
+import org.apache.uima.ducc.transport.event.common.IDuccSchedulingInfo;
+import org.apache.uima.ducc.transport.event.common.IDuccStandardInfo;
 import org.apache.uima.ducc.transport.event.common.IDuccWorkJob;
 import org.apache.uima.ducc.transport.event.common.IDuccWorkMap;
 import org.apache.uima.ducc.transport.event.common.IDuccWorkReservation;
@@ -57,10 +62,7 @@ public class DuccPlugins {
     String location = "restore";
     try {
       if (job != null) {
-        String user = job.getStandardInfo().getUser();
-        String directory = job.getStandardInfo().getLogDirectory();
-        logger.info(location, jobid, "user", user, "directory", directory);
-        experimentsRegistryManager.initialize(user, directory);
+        experimentsRegistryManager.initialize(job);
       }
     } catch (Throwable t) {
       logger.error(location, jobid, t);
@@ -80,10 +82,9 @@ public class DuccPlugins {
     String location = "restore";
     try {
       // Also process managed reservations in case the experiment has only these.
+      // Note: APs are saved in DB as services of type "other"
       if (service != null && service.getServiceDeploymentType() == ServiceDeploymentType.other) {
-        String user = service.getStandardInfo().getUser();
-        String directory = service.getStandardInfo().getLogDirectory();
-        experimentsRegistryManager.initialize(user, directory);
+        experimentsRegistryManager.initialize(service);
       }
     } catch (Throwable t) {
       logger.error(location, jobid, t);

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java Wed Oct 23 12:34:55 2019
@@ -23,6 +23,7 @@ import java.io.File;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.uima.ducc.common.IDuccUser;
 import org.apache.uima.ducc.common.utils.DuccLogger;
@@ -180,4 +181,65 @@ public class DuccAsUser {
 		
 		return retVal.toString();
 	}
+	
+	/**
+	 * Similar to duckling method but can set the environment
+	 * 
+	 * @param userid      - userid to run as
+	 * @param environment - Map of environment entries for the process (use System.getenv() to inherit)
+	 * @param command     - command and arguments
+	 * @return            - console output
+	 */
+  public static String execute(String userid, Map<String, String> environment, String... comamnd) {
+
+    String methodName = "execute";
+
+    StringBuffer retVal = new StringBuffer();
+
+    String c_launcher_path = Utils.resolvePlaceholderIfExists(System.getProperty("ducc.agent.launcher.ducc_spawn_path"), System.getProperties());
+
+    ArrayList<String> cmd = new ArrayList<String>();
+    cmd.add(c_launcher_path);
+    cmd.add("-u");
+    cmd.add(userid);
+    cmd.add("--");
+    for (String arg : comamnd) {
+      cmd.add(arg);
+    }
+    ProcessBuilder pb = new ProcessBuilder(cmd);
+    Map<String, String> env = pb.environment();
+    env.clear();
+    if (environment != null) {
+      env.putAll(environment);      // Use provided environment 
+    }
+    
+    if (duccLogger.isDebug()) {
+      duccLogger.debug(methodName, null, "cmd: " + cmd);
+      for (Entry<String, String> envEntry : env.entrySet()) {
+        duccLogger.debug(methodName, null, "ENV:", envEntry.getKey() + "=" + envEntry.getValue());
+      }
+    }
+    
+    try {
+      pb.redirectErrorStream(true);
+      Process proc = pb.start();
+      String line;
+      BufferedReader stdout = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+      while ((line = stdout.readLine()) != null) {
+        if (line.startsWith(magicString)) {   // Ignore all "duccling" lines up thru this one
+          break;
+        }
+      }
+      while ((line = stdout.readLine()) != null) {
+        retVal.append(line+"\n");
+      }
+      stdout.close();
+      proc.waitFor();
+    } catch (Exception e) {
+      duccLogger.info(methodName, null, e);
+    }
+
+    return retVal.toString();
+  }
+
 }

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java Wed Oct 23 12:34:55 2019
@@ -21,6 +21,7 @@ package org.apache.uima.ducc.ws.handlers
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
@@ -47,7 +48,9 @@ import org.apache.uima.ducc.ws.utils.For
 import org.apache.uima.ducc.ws.utils.FormatServletClassic;
 import org.apache.uima.ducc.ws.utils.FormatServletScroll;
 import org.apache.uima.ducc.ws.utils.HandlersHelper;
+import org.apache.uima.ducc.ws.utils.HandlersHelper.AuthorizationStatus;
 import org.apache.uima.ducc.ws.xd.ExperimentsRegistryManager;
+import org.apache.uima.ducc.ws.xd.ExperimentsRegistryUtilities;
 import org.apache.uima.ducc.ws.xd.IExperiment;
 import org.apache.uima.ducc.ws.xd.Jed;
 import org.apache.uima.ducc.ws.xd.Jed.Status;
@@ -76,8 +79,6 @@ public class HandlerExperimentsServlets
   private static ExperimentsRegistryManager experimentsRegistryManager = ExperimentsRegistryManager
           .getInstance();
 
-  protected boolean terminateEnabled = true;
-
   public HandlerExperimentsServlets(DuccWebServer duccWebServer) {
     super.init(duccWebServer);
   }
@@ -186,6 +187,7 @@ public class HandlerExperimentsServlets
       if (HandlersUtilities.isListable(request, users, fullTable, experiment)) {
 
         // Format each row with:  Terminate-Button Start Duration User Tasks State Directory
+        // Display Terminate button if experiment is Running - activated only if owned by the logged-in user.
         // (Column headings defined in expeiments.jsp)
 
         fmt.startRow();
@@ -243,12 +245,19 @@ public class HandlerExperimentsServlets
     return handled;
   }
 
-  private String decorateState(IExperiment experiment, Task task, boolean isRestartable) {
+  // Note - could put the 2 boolean flags in the experiment ??
+  private String decorateState(IExperiment experiment, Task task, boolean isRestartable, boolean isCanceled) {
     String mName = "decorateState";
     String state = "";
     if (task.status != null) {
       state = task.status;
+      // If experiment has been canceled change any "Running" tasks to "Canceled"
       Jed.Status status = Jed.Status.getEnum(state);
+      if (isCanceled && (status == Jed.Status.Running)) {
+        status = Jed.Status.Canceled;
+        state = "Canceled";
+      }
+      String color = "";   // Default button coloring
       switch (status) {
         case Running:
           if (experiment.isStale()) {
@@ -258,21 +267,25 @@ public class HandlerExperimentsServlets
             state = "<span class=\"health_green\">Running";
           }
           break;
+        case Canceled:
+          state = "Canceled";  // TODO - JED spellings should be cleaned up
         case Failed:
         case DependencyFailed:
-        case Canceled:
-          state = "<span class=\"health_red\"" + ">" + state + "</span>";
-          break;
+          // Use red text for error states
+          if (isRestartable) {
+            color = "color:red";
+          } else {
+            state = "<span class=\"health_red\"" + ">" + state + "</span>";
+          }
         case Completed:
         case Done:
-          // If experiment can be restarted display a toggle button
+          // If experiment can be restarted display a button that can toggle to green "Rerun"
           if (isRestartable) {
-            String color = "";
             if (task.rerun) {
               state = "Rerun";
-              color = " style='background-color:palegreen'";
+              color = "background-color:PaleGreen;";
             }
-            state = "<input type=\"button\"" + color
+            state = "<input type='button' style='" + color + "'"
                     + " onclick=\"ducc_toggle_task_state('" + experiment.getId() + "','" + task.taskId + "')\""
                     + " title=\"Click to toggle state\"" 
                     + " value=\"" + state + "\" />";
@@ -361,7 +374,7 @@ public class HandlerExperimentsServlets
   }
 
   private void edTaskDucc(FormatServlet fmt, IExperiment experiment, Task task,
-          HttpServletRequest request, long duccId, long now, boolean isRestartable) {
+          HttpServletRequest request, long duccId, long now, boolean isRestartable, boolean isCanceled) {
     DuccData duccData = DuccData.getInstance();
     
     // Format first 8 columns: 
@@ -370,7 +383,7 @@ public class HandlerExperimentsServlets
     fmt.addElemR(task.taskId);
     fmt.addElemR(task.parentId);
     fmt.addElemL(task.name);
-    fmt.addElemL(decorateState(experiment, task, isRestartable));
+    fmt.addElemL(decorateState(experiment, task, isRestartable, isCanceled));
     fmt.addElemL(task.type);
     fmt.addElemL(decorateStepStart(task, request));
     fmt.addElemR(decorateStepDuration(task), task.runTime);
@@ -432,36 +445,39 @@ public class HandlerExperimentsServlets
     
     if (experiment != null) {
       // Check if the experiment can be restarted, i.e.
-      // launched by DUCC, stopped, and owned by the logged-in user
-      // ?? Could be an experiment attribute?
-      boolean duccLaunched = true;  // TODO ... FIX!
-      boolean isRestartable = duccLaunched 
-              && experiment.getStatus() != Jed.Status.Running 
-              && HandlersHelper.isUserAuthorized(request, experiment.getUser());
+      // launched by DUCC as a JED AP, stopped, and owned by the logged-in user
+      boolean isRestartable = experiment.getJedDuccId() != null  
+              && !experiment.isActive()
+              && HandlersHelper.getAuthorizationStatus(request, experiment.getUser()) == AuthorizationStatus.LoggedInOwner;
+      
+      boolean isCanceled = experiment.getStatus() == Jed.Status.Canceled;
 
       Task[] tasks = experiment.getTasks();
       if (tasks != null) {
         // Check if given a task whose state is to be toggled between Completed & Rerun
         String toggleTask = request.getParameter("taskid");
         if (toggleTask != null) {
-          WsLog.info(cName, mName, "!! id = '"+id+"' taskid = '"+toggleTask+"'");
           int toggle = Integer.parseInt(toggleTask);
           Task task = tasks[toggle-1];
           task.rerun = !task.rerun;
           markSubtasks(tasks, toggle, task.rerun);
         }
+        // Find the latest duccId to display for a task ... omit if not started or has been reset for a rerun
         for (Task task : tasks) {
           long latestDuccId = 0;
-          String type = (task.type != null) ? task.type : "";
-          Jed.Type jedType = Jed.Type.getEnum(type);
-          if (jedType == Jed.Type.Ducc_Job || jedType == Jed.Type.Java) {
+          if (task.type != null) {
+            Jed.Type jedType = Jed.Type.getEnum(task.type);
+            if (jedType == Jed.Type.Ducc_Job || jedType == Jed.Type.Java) {
               long[] duccIds = task.duccId;
-              int nIds = duccIds.length;
-              latestDuccId = nIds == 0 ? 0 : duccIds[--nIds];
-              //String otherIds = reverse(duccIds, nIds);
+              if (duccIds != null) {
+                int nIds = duccIds.length;
+                latestDuccId = nIds == 0 ? 0 : duccIds[--nIds];
+                // String otherIds = reverse(duccIds, nIds);
+              }
+            }
           }
           fmt.startRow();
-          edTaskDucc(fmt, experiment, task, request, latestDuccId, now, isRestartable);
+          edTaskDucc(fmt, experiment, task, request, latestDuccId, now, isRestartable, isCanceled);
           fmt.endRow();
         }
       }
@@ -498,31 +514,57 @@ public class HandlerExperimentsServlets
     String mName = "handleServletExperimentDetailsDirectory";
     WsLog.enter(cName, mName);
 
-    boolean handled = false;
-
     StringBuffer sb = new StringBuffer();
 
     String id = request.getParameter("id");
 
+    boolean restart = false;
+
     IExperiment experiment = experimentsRegistryManager.getById(id);
 
-    if (experiment != null) {
+    if (experiment != null && experiment.getDirectory() != null) {
       String directory = experiment.getDirectory();
-      if (directory != null) {
-        sb.append("<b>");
-        sb.append("Directory:");
-        sb.append(" ");
-        sb.append(directory);
-        sb.append("</b>");
+      
+      // Display Terminate/Restart button if DUCC-launched && the owner logged in
+      String button = null;
+      if (experiment.getJedDuccId() != null &&
+        HandlersHelper.getAuthorizationStatus(request, experiment.getUser()) == AuthorizationStatus.LoggedInOwner) {
+        restart = request.getParameter("restart") != null;
+        Status status = experiment.getStatus();
+        if (restart || status == Jed.Status.Restarting) {
+          button = "<button style='background-color:Beige;font-size:16px' "
+                  + "disabled"
+                  + " title='experiment is restarting'>Restarting...</button>";
+        } else if (status == Jed.Status.Running) {
+          button = "<button style='background-color:LightPink;font-size:16px' "
+                  + "onclick=\"ducc_confirm_terminate_experiment('" + id + "','" + directory + "')\""
+                  + " title='click to terminate experiment'>TERMINATE</button>";
+        } else {
+          button = "<button style='background-color:PaleGreen;font-size:16px' "
+                  + "onclick=\"ducc_restart_experiment()\""
+                  + " title='click to restart experiment'>RESTART</button>";
+        }
+      }
+
+      sb.append("<b>");
+      sb.append("Directory:");
+      sb.append(" ");
+      sb.append(directory);
+      if (button != null) {
+        sb.append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
+        sb.append(button);
       }
+      sb.append("</b>");
     }
 
     response.getWriter().println(sb);
-
-    handled = true;
+    
+    if (restart) {
+      ExperimentsRegistryUtilities.launchJed(experiment);
+    }
 
     WsLog.exit(cName, mName);
-    return handled;
+    return true;
   }
 
   private boolean handleServletExperimentCancelRequest(String target, Request baseRequest,
@@ -552,8 +594,9 @@ public class HandlerExperimentsServlets
 
     if (HandlersHelper.isUserAuthorized(request, resourceOwnerUserId)) {
       String userId = resourceOwnerUserId;
-      String[] arglist = { "-u", userId, "--", command, path };
-      result = DuccAsUser.duckling(userId, arglist);
+      String[] arglist = { command, path };
+      WsLog.info(cName, mName, "cmd: " + Arrays.toString(arglist));
+      result = DuccAsUser.execute(userId, null, arglist);
       response.getWriter().println(result);
     } else {
       result = "user not authorized";

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java Wed Oct 23 12:34:55 2019
@@ -18,12 +18,27 @@
 */
 package org.apache.uima.ducc.ws.xd;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.UUID;
 
+import org.apache.uima.ducc.common.utils.DuccLogger;
+import org.apache.uima.ducc.common.utils.id.DuccId;
+import org.apache.uima.ducc.transport.event.common.IDuccWork;
+import org.apache.uima.ducc.ws.authentication.DuccAsUser;
+import org.apache.uima.ducc.ws.log.WsLog;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
 public class Experiment implements IExperiment {
+  
+  private static DuccLogger logger = DuccLogger.getLogger(Experiment.class);
 
   private String user = null;
 
@@ -36,28 +51,21 @@ public class Experiment implements IExpe
   private String id = UUID.randomUUID().toString();
 
   private int version;
-  
-  public Experiment(String user, String directory, long date, int version, ArrayList<Task> tasks)
-          throws Exception {
-    initialize(user, directory, date, version, tasks);
-  }
 
-  private void initialize(String user, String directory, long fileDate, int version,
-          ArrayList<Task> tasks) throws Exception {
-    if (user == null) {
-      throw new ExperimentException("missing user");
-    }
-    if (directory == null) {
-      throw new ExperimentException("missing directory");
-    }
-    if (tasks == null) {
-      throw new ExperimentException("missing tasks");
-    }
+  private DuccId jedDuccId;
+
+  public String umask;
+  
+  public Experiment(String user, String directory, long fileDate, int version, ArrayList<Task> tasks, IDuccWork work) {
     this.user = user;
     this.directory = directory;
     this.fileDate = fileDate;
     this.version = version;
     this.tasks = tasks;
+    if (work != null) {
+      this.jedDuccId = work.getDuccId();
+      this.umask = work.getStandardInfo().getUmask();
+    }
   }
 
   @Override
@@ -80,6 +88,16 @@ public class Experiment implements IExpe
     return directory;
   }
 
+  @Override
+  public void setJedDuccId(DuccId duccId) {
+    this.jedDuccId = duccId;
+  }
+
+  @Override
+  public DuccId getJedDuccId() {
+    return jedDuccId;
+  }
+  
   // Create an array indexed by taskId-1
   @Override
   public Task[] getTasks() {
@@ -132,6 +150,7 @@ public class Experiment implements IExpe
     boolean retVal = false;
     switch (getStatus()) {
       case Running:
+      case Restarting:
         retVal = true;
         break;
       default:
@@ -149,6 +168,7 @@ public class Experiment implements IExpe
       boolean failed = false;
       boolean running = false;
       boolean done = false;
+      boolean restarting = false;
       for (Task task : tasks) {
         if (task.parentId == 0 && task.status != null) {
           Jed.Status status = Jed.Status.getEnum(task.status);
@@ -159,6 +179,9 @@ public class Experiment implements IExpe
             case Running:
               running = true;
               break;
+            case Restarting:
+              restarting = true;
+              break;
             case Failed:
             case DependencyFailed:
               failed = true;
@@ -177,6 +200,8 @@ public class Experiment implements IExpe
       // But if JED appears to have been killed while running change state to Unknown
       if (running) {
         retVal = isStale() ? Jed.Status.Unknown : Jed.Status.Running;
+      } else if (restarting) {
+        retVal = Jed.Status.Restarting;
       } else if (failed) {
         retVal = Jed.Status.Failed;
       } else if (canceled) {
@@ -190,6 +215,61 @@ public class Experiment implements IExpe
     return retVal;
   }
 
+  /*
+   * Set status of the top-level task(s) to "Restarting",
+   * clear status of all rerun tasks selected to be rerun,
+   + then rewrite the Experiment.state file
+   */
+  @Override
+  public boolean updateStateFile() {
+    Task[] tasks = getTasks();
+    if (tasks == null) {
+      return true;
+    }
+    for (Task task : tasks) {
+      if (task.parentId == 0) {
+        task.status = "Restarting";
+      } else if (task.rerun) {
+        // Indicate that task has not yet started
+        task.status = null;
+        task.startTime = null;
+        task.runTime = 0;
+      }
+    }
+    return writeStateFile();
+  }
+  
+  /*
+   * Write the state as a temporary file, 
+   * as the user copy it to the output directory,
+   * delete the temp file.
+   */
+  private boolean writeStateFile() {
+    File tempFile = null;
+    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
+    try {
+      tempFile = File.createTempFile("experiment", jedDuccId.toString());
+      FileWriter out = new FileWriter(tempFile);
+      String text = gson.toJson(tasks);
+      out.write(text);
+      out.close();
+    } catch (IOException e) {
+      WsLog.error(logger, "writeExperiment", "Failed to write experiment state as " + tempFile + " - " + e);
+      return false;
+    }
+
+    File stateFile = new File(directory, "Experiment.state");
+    HashMap<String, String> environment = new HashMap<String, String>();
+    environment.put("DUCC_UMASK", umask);
+    String sysout = DuccAsUser.execute(user, environment, "/bin/cp", tempFile.getAbsolutePath(), stateFile.getAbsolutePath());
+    if (sysout.length() == 0) {
+      tempFile.delete();
+      return true;
+    }
+    WsLog.error(logger, "writeExperiment", "Failed to copy experiment state file\n" + sysout);
+    return false;
+  }
+  
   private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd-HH:mm:ss");
 
   private static long getMillis(String dateString) {
@@ -347,4 +427,5 @@ public class Experiment implements IExpe
     }
     return retVal;
   }
+
 }

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java Wed Oct 23 12:34:55 2019
@@ -18,6 +18,8 @@
 */
 package org.apache.uima.ducc.ws.xd;
 
+import java.io.File;
+import java.io.IOException;
 import java.io.StringReader;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
@@ -106,8 +108,21 @@ public class ExperimentsRegistryManager
 
   private void replace(String directory, Experiment experiment) {
     String mName = "replace";
+    
+    // Keep the same id
     String id = map.get(directory).getId();
     experiment.setId(id);
+    
+    // Keep latest JED id ... and umask in case this is not the JED AP
+    DuccId oldDuccId = map.get(directory).getJedDuccId();
+    long oldNum = oldDuccId==null? 0 : oldDuccId.getFriendly();
+    DuccId newDuccId = experiment.getJedDuccId();
+    long newNum = newDuccId==null? 0 : newDuccId.getFriendly();
+    if (oldNum > newNum) {
+      experiment.setJedDuccId(oldDuccId);
+      experiment.umask = ((Experiment)map.get(directory)).umask;   // Ugh - should update rather than replace ??
+    }
+    
     map.put(directory, experiment);
     WsLog.debug(cName, mName, directory);
   }
@@ -143,22 +158,34 @@ public class ExperimentsRegistryManager
     }
   }
 
-  public void initialize(String user, String directory) {
-    String mName = "initialize";
-    if (!enabled) 
+  // Called by DuccPlugins when web-server boots
+  public void initialize(IDuccWork dw) {
+    IDuccStandardInfo stdInfo = dw.getStandardInfo();
+    if (stdInfo != null) {
+      String user = stdInfo.getUser();
+      String directory = stdInfo.getLogDirectory();
+      String experimentDirectory = stdInfo.getExperimentDirectory();
+      if (experimentDirectory != null) {
+        update(user, experimentDirectory, false, dw);
+      } else {
+        directory = ExperimentsRegistryUtilities.upOne(directory);
+        update(user, directory, false, null);
+      }
+    }      
+  }
+  
+  // DuccWork provided only for the AP that launches JED
+  private void update(String user, String directory, IDuccWork work) {
+    String mName = "update";
+    
+    // "normalize" directory name
+    try {
+      directory = new File(directory).getCanonicalPath();
+    } catch (IOException e) {
+      WsLog.error(cName, mName, "Failed to create canonical name for " + directory + "\n" + e);
       return;
-    if (user == null) {
-      WsLog.warn(cName, mName, "missing user");
-    } else if (directory == null) {
-      WsLog.warn(cName, mName, "missing directory");
-    } else {
-      String parent = ExperimentsRegistryUtilities.upOne(directory);
-      update(user, parent, false);
     }
-  }
 
-  private void update(String user, String directory) {
-    String mName = "update";
     try {
       String fileName = ExperimentsRegistryUtilities.getStateFilePath(directory);
       long date = ExperimentsRegistryUtilities.getFileDate(user, fileName);
@@ -187,13 +214,16 @@ public class ExperimentsRegistryManager
         }.getType();
         try {
           ArrayList<Task> taskArray = gson.fromJson(sr, tasksType);
-          Experiment experiment = new Experiment(user, directory, date, version, taskArray);
+          Experiment experiment = new Experiment(user, directory, date, version, taskArray, work);
           put(directory, experiment);
         } catch (JsonParseException e) {
           WsLog.warn(cName, mName,
                   "Ignoring " + fileName + " as has Json syntax error " + e.getMessage());
         }
       } else {
+        if (work != null) {
+          WsLog.warn(cName, mName, "State file missing or inaccessible in " + directory + " for JED AP " + work.getDuccId());
+        }
         WsLog.trace(cName, mName, "state file missing or inaccessible in " + directory);
         remove(directory);
       }
@@ -203,14 +233,17 @@ public class ExperimentsRegistryManager
   }
 
   private void update(String user, String directory, boolean overwrite) {
+    update(user, directory, overwrite, null);
+  }
+  
+  private void update(String user, String directory, boolean overwrite, IDuccWork work) {
     String mName = "update";
-    WsLog.enter(cName, mName);
     try {
       if (overwrite) {
-        update(user, directory);
+        update(user, directory, work);
       } else {
         if (!containsKey(directory)) {
-          update(user, directory);
+          update(user, directory, work);
         } else {
           WsLog.trace(cName, mName, "duplicate directory: " + directory);
         }
@@ -219,7 +252,6 @@ public class ExperimentsRegistryManager
     } catch (Exception e) {
       WsLog.error(cName, mName, e);
     }
-    // WsLog.exit(cName, mName);
   }
 
   private void check() {
@@ -290,6 +322,7 @@ public class ExperimentsRegistryManager
     // WsLog.exit(cName, mName);
   }
 
+  // Called by DuccPlugins for each OR publication
   public void update(IDuccWorkMap dwm) {
     String mName = "update";
     if (!enabled) 
@@ -325,8 +358,13 @@ public class ExperimentsRegistryManager
             if (stdInfo != null) {
               String user = stdInfo.getUser();
               String directory = stdInfo.getLogDirectory();
-              String parent = ExperimentsRegistryUtilities.upOne(directory);
-              update(user, parent, true);
+              String experimentDirectory = stdInfo.getExperimentDirectory();
+              if (experimentDirectory != null) {
+                update(user, experimentDirectory, true, job);
+              } else {
+                directory = ExperimentsRegistryUtilities.upOne(directory);
+                update(user, directory, true, null);
+              }
             }
           }
         }

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java Wed Oct 23 12:34:55 2019
@@ -23,9 +23,19 @@ import java.io.Closeable;
 import java.io.File;
 import java.io.FileReader;
 import java.io.StringReader;
+import java.util.Arrays;
+import java.util.Map.Entry;
 
+import org.apache.uima.ducc.common.IDuccUser;
 import org.apache.uima.ducc.common.utils.AlienFile;
 import org.apache.uima.ducc.common.utils.DuccLogger;
+import org.apache.uima.ducc.transport.cmdline.ACommandLine;
+import org.apache.uima.ducc.transport.cmdline.ICommandLine;
+import org.apache.uima.ducc.transport.event.common.IDuccWorkJob;
+import org.apache.uima.ducc.transport.event.common.IDuccWorkService;
+import org.apache.uima.ducc.transport.event.common.history.HistoryFactory;
+import org.apache.uima.ducc.transport.event.common.history.IHistoryPersistenceManager;
+import org.apache.uima.ducc.ws.authentication.DuccAsUser;
 import org.apache.uima.ducc.ws.log.WsLog;
 
 public class ExperimentsRegistryUtilities {
@@ -172,4 +182,85 @@ public class ExperimentsRegistryUtilitie
     return retVal;
   }
 
+  public static boolean launchJed(IExperiment experiment) {
+    String mName = "launchJed";
+    
+    IHistoryPersistenceManager hpm = HistoryFactory.getInstance(ExperimentsRegistryUtilities.class.getName());
+    IDuccWorkService service = null;
+    try {
+      service = hpm.restoreArbitraryProcess(experiment.getJedDuccId().getFriendly());
+      if (service == null) {
+        // If relaunch is too quick DB may not have been updated so wait 10 secs and try again
+        Thread.sleep(10000);
+        service = hpm.restoreArbitraryProcess(experiment.getJedDuccId().getFriendly());
+        if (service == null) {
+          WsLog.error(cName, mName, "No entry found in DB for JED AP "+experiment.getJedDuccId());
+          return false;
+        }
+      }
+    } catch (Exception e) {
+      WsLog.error(cName, mName, "Failed to access DB for JED AP "+experiment.getJedDuccId());
+      WsLog.error(cName, mName, e);
+      return false;
+    }
+       
+    if (! (service instanceof IDuccWorkJob)) {
+      WsLog.error(cName, mName, "Wrong class for JED AP? "+service.getClass().getName());
+      return false;
+    }
+    IDuccWorkJob dwj = (IDuccWorkJob) service;
+    ICommandLine cmd = dwj.getCommandLine();
+    if (cmd == null) {
+      WsLog.info(cName, mName, "No cmdline for JED AP " + experiment.getJedDuccId());
+      return false;
+    }
+
+    // Build the ducc_process_submit command to launch JED.
+    // Create blank-delimited lists of arguments and environment variable assignments
+
+    StringBuilder args = new StringBuilder();
+    if (cmd.getOptions() != null) {
+      for (String opt : cmd.getOptions()) {
+        args.append(opt).append(' ');
+      }
+    }
+    for (String arg : cmd.getArguments()) {
+      args.append(arg).append(' ');
+    }
+    StringBuilder envs = new StringBuilder();
+    if (cmd instanceof ACommandLine) {
+      for (Entry<String, String> ent : ((ACommandLine) cmd).getEnvironment().entrySet()) {
+        envs.append(ent.getKey() + "=" + ent.getValue() + " ");
+      }
+    }
+
+    // Create the java command with the appropriate DUCC options
+    String duccHome = System.getProperty(IDuccUser.EnvironmentVariable.DUCC_HOME.value());
+    String[] submitCmd = { 
+        cmd.getExecutable(), 
+        "-cp", duccHome + "/lib/uima-ducc-cli.jar", "org.apache.uima.ducc.cli.DuccManagedReservationSubmit",
+        "--process_executable",      cmd.getExecutable(), 
+        "--process_executable_args", args.toString(),
+        "--environment",             envs.toString(),
+        "--log_directory",           dwj.getStandardInfo().getLogDirectory(),
+        "--working_directory",       dwj.getStandardInfo().getWorkingDirectory(),
+        "--scheduling_class",        dwj.getSchedulingInfo().getSchedulingClass(),
+        "--process_memory_size",     dwj.getSchedulingInfo().getMemorySizeRequested(),
+        "--description",             "JED---" + dwj.getStandardInfo().getLogDirectory()
+    };
+    
+    // Update state file AFTER successfully restoring the JED AP from the DB
+    if (!experiment.updateStateFile()) {
+      return false;
+    }
+    
+    WsLog.info(cName, mName, "Submitting: " + Arrays.toString(submitCmd));
+    
+    // Submit the AP as the user
+    String sysout = DuccAsUser.execute(experiment.getUser(), null, submitCmd);
+    WsLog.info(cName, mName, sysout);
+    
+    return true;
+  }
+
 }

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java Wed Oct 23 12:34:55 2019
@@ -20,6 +20,8 @@ package org.apache.uima.ducc.ws.xd;
 
 import java.util.ArrayList;
 
+import org.apache.uima.ducc.common.utils.id.DuccId;
+
 public interface IExperiment extends Comparable<Object> {
   public void setId(String value);
 
@@ -48,4 +50,13 @@ public interface IExperiment extends Com
   public int getVersion();
 
   public boolean isStale();
+
+  // Set the DuccId of the AP that launched the experiment
+  public void setJedDuccId(DuccId duccId);
+  
+  // Return the DuccId of the AP that launched the experiment, or null
+  public DuccId getJedDuccId();
+  
+  // Update the Experiment.state file indicating the tasks to be rerun
+  public boolean updateStateFile();
 }

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java Wed Oct 23 12:34:55 2019
@@ -82,7 +82,7 @@ public class Jed {
 
   public enum Status {
 
-    Running, Completed, Done, Canceled, Failed, DependencyFailed, Ignored, Unknown, Other;
+    Running, Restarting, Completed, Done, Canceled, Failed, DependencyFailed, Ignored, Unknown, Other;
 
     private static String Dependency_Failed = "Dependency-Failed";
 
@@ -97,6 +97,8 @@ public class Jed {
         retVal = DependencyFailed;
       } else if (Running.name().equalsIgnoreCase(value)) {
         retVal = Running;
+      } else if (Restarting.name().equalsIgnoreCase(value)) {
+        retVal = Restarting;
       } else if (Completed.name().equalsIgnoreCase(value)) {
         retVal = Completed;
       } else if (Done.name().equalsIgnoreCase(value)) {

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java Wed Oct 23 12:34:55 2019
@@ -18,30 +18,43 @@
 */
 package org.apache.uima.ducc.ws.xd;
 
+import com.google.gson.annotations.Expose;
+
 /*
- * This represents the "Expose"d fields written by JED in the Experiment.state file
- * See com.ibm.bluej.system.driver/src/com/ibm/bluej/system/driver/TaskState.java 
+ * The "exposed" fields are those exposed and saved by JED in the Experiment.state file
+ * See TaskState in the com.ibm.watsonx.framework.jed project 
  */
 public class Task {
+  
+  @Expose
   public String pathId;
   
-  public int taskId = 0;
+  @Expose
+  public int taskId;
 
-  public int parentId = 0;
+  @Expose
+  public int parentId;
   
-  public String name = null;
+  @Expose
+  public String name;
 
-  public String type = null;
+  @Expose
+  public String type;
 
-  public String status = null;
+  @Expose
+  public String status;
 
-  public String startTime = null;
+  @Expose
+  public String startTime;
 
-  public long runTime = 0;
+  @Expose
+  public long runTime;
 
-  public int[] subTasks = new int[0];
+  @Expose
+  public int[] subTasks;
 
-  public long[] duccId = new long[0];
+  @Expose
+  public long[] duccId;
   
   public boolean rerun = false;  // Note - this is NOT in the Experiment.state file
 }

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/experiments.jsp
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/experiments.jsp?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/experiments.jsp (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/experiments.jsp Wed Oct 23 12:34:55 2019
@@ -23,7 +23,6 @@ under the License.
   <title>ducc-mon</title>
   <meta http-equiv="CACHE-CONTROL" content="NO-CACHE">
   <%@ include file="$imports.jsp" %>
-  <script src="js/ducc.experiments.js"></script>
 <%
 if (table_style.equals("scroll")) {
 %>  

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/js/ducc.local.js
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/js/ducc.local.js?rev=1868799&r1=1868798&r2=1868799&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/js/ducc.local.js (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/js/ducc.local.js Wed Oct 23 12:34:55 2019
@@ -188,10 +188,13 @@ function ducc_init_data(type)
         }
 }
 
-function ducc_load_identify_experiment_details()
+function ducc_load_identify_experiment_details(params)
 {
+    if (params == undefined) {
+	params = "";
+    }
         try {
-                server_url= "/ducc-servlet/experiment-details-directory"+location.search;
+                server_url= "/ducc-servlet/experiment-details-directory"+location.search+params;
                 $.ajax(
                 {
                         url : server_url,
@@ -258,3 +261,49 @@ function ducc_toggle_task_state(expid, t
                 ducc_error("ducc_toggle_task_state",err);
         }       
 }
+
+function ducc_restart_experiment()
+{
+        try {
+                ducc_load_identify_experiment_details("&restart=true");
+                ducc_load_data("experiment-details");
+        }
+        catch(err) {
+                ducc_error("ducc_restart_experiment",err);
+        }       
+}
+
+function ducc_terminate_experiment(id)
+{	
+	try {
+		$.jGrowl(" Pending termination...");
+		$.ajax(
+		{
+			type: 'POST',
+			url : "/ducc-servlet/experiment-cancel-request"+"?id="+id,
+			success : function (data) 
+			{
+			$.jGrowl(data, { life: 6000 });
+			setTimeout(function(){window.close();}, 5000);
+			}
+		});
+		setTimeout(function(){window.close();}, 5000);
+	}
+	catch(err) {
+		ducc_error("ducc_terminate_experiment",err);
+	}	
+	return false;
+}
+
+function ducc_confirm_terminate_experiment(id,directory)
+{
+	try {
+		var result=confirm("Terminate experiment "+directory+"?");
+		if (result==true) {
+  			ducc_terminate_experiment(id);
+  		}
+  	}
+	catch(err) {
+		ducc_error("ducc_confirm_terminate_experiment",err);
+	}
+}