UIMA-6130 Add button to restart an experiment launched as an AP - must have the output dir same as the log dir
git-svn-id: https://svn.apache.org/repos/asf/uima/uima-ducc/trunk@1868799 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java b/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java
index 548b8d7..aaa3fc7 100644
--- a/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java
+++ b/uima-ducc-database/src/main/java/org/apache/uima/ducc/database/HistoryManagerDb.java
@@ -527,7 +527,7 @@
summarizeJob(h, w, "J");
break;
case Service:
- case Pop:
+ case Pop:
break;
case Reservation:
break;
@@ -544,7 +544,7 @@
* 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 @@
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 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 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 @@
/**
- * 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.
*/
diff --git a/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java b/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java
index 9f66cb6..1902e48 100644
--- a/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java
+++ b/uima-ducc-orchestrator/src/main/java/org/apache/uima/ducc/orchestrator/factory/JobFactory.java
@@ -458,27 +458,24 @@
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 @@
}
standardInfo.setNotifications(notificationsArray);
}
+
// scheduling info
DuccSchedulingInfo schedulingInfo = new DuccSchedulingInfo();
job.setSchedulingInfo(schedulingInfo);
@@ -526,6 +524,13 @@
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 @@
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);
diff --git a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java
index 23fff9c..bed0235 100644
--- a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java
+++ b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/DuccStandardInfo.java
@@ -41,7 +41,8 @@
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 @@
return true;
}
+ @Override
+ public String getExperimentDirectory() {
+ return experimentDirectory;
+ }
+
+ @Override
+ public void setExperimentDirectory(String experimentDirectory) {
+ this.experimentDirectory = experimentDirectory;
+ }
+
// **********
//
diff --git a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java
index 197f2a5..c2a913b 100644
--- a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java
+++ b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/IDuccStandardInfo.java
@@ -63,6 +63,9 @@
public String getWorkingDirectory();
public void setWorkingDirectory(String workingDirectory);
+
+ public String getExperimentDirectory();
+ public void setExperimentDirectory(String experimentDirectory);
public String[] getNotifications();
public void setNotifications(String[] notifications);
diff --git a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java
index 4714d2e..7bec865 100644
--- a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java
+++ b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/HistoryPersistenceManager.java
@@ -625,6 +625,12 @@
System.out.println("reservations: "+reservations);
}
+ @Override
+ public IDuccWorkService restoreArbitraryProcess(long friendlyId) throws Exception {
+ // TODO untested!!
+ return restoreService(friendlyId);
+ }
+
///// </tool>
}
diff --git a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java
index f747331..f673a66 100644
--- a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java
+++ b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/IHistoryPersistenceManager.java
@@ -44,6 +44,7 @@
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;
diff --git a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java
index a871866..c3af61f 100644
--- a/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java
+++ b/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/event/common/history/NullHistoryManager.java
@@ -101,6 +101,12 @@
return new ArrayList<IDuccWorkService>();
}
+ public IDuccWorkService restoreArbitraryProcess(long duccId)
+ throws Exception
+ {
+ return null;
+ }
+
public List<IDuccWorkService> restoreArbitraryProcesses(long max)
throws Exception
{
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java
index 372e9aa..a453b74 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccBoot.java
@@ -305,7 +305,7 @@
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;
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
index 3db02a6..fc02114 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/DuccPlugins.java
@@ -22,6 +22,11 @@
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 @@
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 @@
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);
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java
index 66cf35b..98cf8a9 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/authentication/DuccAsUser.java
@@ -23,6 +23,7 @@
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 @@
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();
+ }
+
}
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
index 45a472e..19960c6 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/handlers/experiments/HandlerExperimentsServlets.java
@@ -21,6 +21,7 @@
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.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 @@
private static ExperimentsRegistryManager experimentsRegistryManager = ExperimentsRegistryManager
.getInstance();
- protected boolean terminateEnabled = true;
-
public HandlerExperimentsServlets(DuccWebServer duccWebServer) {
super.init(duccWebServer);
}
@@ -186,6 +187,7 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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(" ");
+ 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 @@
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";
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
index aa5ae72..3054a39 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Experiment.java
@@ -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 @@
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 @@
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 @@
boolean retVal = false;
switch (getStatus()) {
case Running:
+ case Restarting:
retVal = true;
break;
default:
@@ -149,6 +168,7 @@
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 @@
case Running:
running = true;
break;
+ case Restarting:
+ restarting = true;
+ break;
case Failed:
case DependencyFailed:
failed = true;
@@ -177,6 +200,8 @@
// 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 @@
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 @@
}
return retVal;
}
+
}
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
index a3ec179..8fbfd8d 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryManager.java
@@ -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 @@
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 void initialize(String user, String directory) {
- String mName = "initialize";
- if (!enabled)
- 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);
- }
+ // 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);
+ }
+ }
}
-
- private void update(String user, String directory) {
+
+ // 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;
+ }
+
try {
String fileName = ExperimentsRegistryUtilities.getStateFilePath(directory);
long date = ExperimentsRegistryUtilities.getFileDate(user, fileName);
@@ -187,13 +214,16 @@
}.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 @@
}
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 @@
} catch (Exception e) {
WsLog.error(cName, mName, e);
}
- // WsLog.exit(cName, mName);
}
private void check() {
@@ -290,6 +322,7 @@
// 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 @@
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);
+ }
}
}
}
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
index 3a4d82d..cc7f29c 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/ExperimentsRegistryUtilities.java
@@ -23,9 +23,19 @@
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 @@
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;
+ }
+
}
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
index a2822cc..badd76e 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/IExperiment.java
@@ -20,6 +20,8 @@
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 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();
}
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
index a4bbd44..f8d009c 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Jed.java
@@ -82,7 +82,7 @@
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 @@
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)) {
diff --git a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
index eb24c18..8a4a5d6 100644
--- a/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
+++ b/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/xd/Task.java
@@ -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
}
diff --git a/uima-ducc-web/src/main/webapp/root/experiments.jsp b/uima-ducc-web/src/main/webapp/root/experiments.jsp
index 46a969d..4ea2de0 100644
--- a/uima-ducc-web/src/main/webapp/root/experiments.jsp
+++ b/uima-ducc-web/src/main/webapp/root/experiments.jsp
@@ -23,7 +23,6 @@
<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")) {
%>
diff --git a/uima-ducc-web/src/main/webapp/root/js/ducc.experiments.js b/uima-ducc-web/src/main/webapp/root/js/ducc.experiments.js
deleted file mode 100644
index c9d8c8c..0000000
--- a/uima-ducc-web/src/main/webapp/root/js/ducc.experiments.js
+++ /dev/null
@@ -1,35 +0,0 @@
-
-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);
- }
-}
diff --git a/uima-ducc-web/src/main/webapp/root/js/ducc.local.js b/uima-ducc-web/src/main/webapp/root/js/ducc.local.js
index ebcff9b..eca41b9 100644
--- a/uima-ducc-web/src/main/webapp/root/js/ducc.local.js
+++ b/uima-ducc-web/src/main/webapp/root/js/ducc.local.js
@@ -188,10 +188,13 @@
}
}
-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 @@
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);
+ }
+}