Added Job timeline view
git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_dev_next@897 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/ActivityId.java b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/ActivityId.java
index c6ca51c..32a3afd 100644
--- a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/ActivityId.java
+++ b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/ActivityId.java
@@ -52,6 +52,16 @@
}
public String toString() {
- return "ANID:[" + odId + "]:" + id;
+ return "ANID:" + odId + ":" + id;
+ }
+
+ public static ActivityId parse(String str) {
+ if (str.startsWith("ANID:")) {
+ str = str.substring(5);
+ int idIdx = str.lastIndexOf(':');
+ return new ActivityId(OperatorDescriptorId.parse(str.substring(0, idIdx)), Integer.parseInt(str
+ .substring(idIdx + 1)));
+ }
+ throw new IllegalArgumentException();
}
}
\ No newline at end of file
diff --git a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/OperatorDescriptorId.java b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/OperatorDescriptorId.java
index b858736..330e3a2 100644
--- a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/OperatorDescriptorId.java
+++ b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/OperatorDescriptorId.java
@@ -49,4 +49,12 @@
public String toString() {
return "ODID:" + id;
}
+
+ public static OperatorDescriptorId parse(String str) {
+ if (str.startsWith("ODID:")) {
+ str = str.substring(5);
+ return new OperatorDescriptorId(Integer.parseInt(str));
+ }
+ throw new IllegalArgumentException();
+ }
}
\ No newline at end of file
diff --git a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskAttemptId.java b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskAttemptId.java
index d4e6972..96437bf 100644
--- a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskAttemptId.java
+++ b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskAttemptId.java
@@ -52,6 +52,15 @@
@Override
public String toString() {
- return "TAID:[" + taskId + "]:" + attempt;
+ return "TAID:" + taskId + ":" + attempt;
+ }
+
+ public static TaskAttemptId parse(String str) {
+ if (str.startsWith("TAID:")) {
+ str = str.substring(5);
+ int idIdx = str.lastIndexOf(':');
+ return new TaskAttemptId(TaskId.parse(str.substring(0, idIdx)), Integer.parseInt(str.substring(idIdx + 1)));
+ }
+ throw new IllegalArgumentException();
}
}
\ No newline at end of file
diff --git a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskId.java b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskId.java
index ee63355..78abaa2 100644
--- a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskId.java
+++ b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/dataflow/TaskId.java
@@ -52,6 +52,15 @@
@Override
public String toString() {
- return "TID:[" + activityId + "]:" + partition;
+ return "TID:" + activityId + ":" + partition;
+ }
+
+ public static TaskId parse(String str) {
+ if (str.startsWith("TID:")) {
+ str = str.substring(4);
+ int idIdx = str.lastIndexOf(':');
+ return new TaskId(ActivityId.parse(str.substring(0, idIdx)), Integer.parseInt(str.substring(idIdx + 1)));
+ }
+ throw new IllegalArgumentException();
}
}
\ No newline at end of file
diff --git a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobActivityGraph.java b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobActivityGraph.java
index 930d299..4577f4c 100644
--- a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobActivityGraph.java
+++ b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobActivityGraph.java
@@ -209,13 +209,11 @@
public JSONObject toJSON() throws JSONException {
JSONObject jplan = new JSONObject();
- jplan.put("type", "plan");
jplan.put("flags", jobFlags.toString());
JSONArray jans = new JSONArray();
for (IActivity an : activityNodes.values()) {
JSONObject jan = new JSONObject();
- jan.put("type", "activity");
jan.put("id", an.getActivityId().toString());
jan.put("java-class", an.getClass().getName());
jan.put("operator-id", an.getActivityId().getOperatorDescriptorId().toString());
@@ -225,7 +223,6 @@
JSONArray jInputs = new JSONArray();
for (int i = 0; i < inputs.size(); ++i) {
JSONObject jInput = new JSONObject();
- jInput.put("type", "activity-input");
jInput.put("input-port", i);
jInput.put("connector-id", inputs.get(i).getConnectorId().toString());
jInputs.put(jInput);
@@ -238,7 +235,6 @@
JSONArray jOutputs = new JSONArray();
for (int i = 0; i < outputs.size(); ++i) {
JSONObject jOutput = new JSONObject();
- jOutput.put("type", "activity-output");
jOutput.put("output-port", i);
jOutput.put("connector-id", outputs.get(i).getConnectorId().toString());
jOutputs.put(jOutput);
diff --git a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobSpecification.java b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobSpecification.java
index 23b33f0..cdea942 100644
--- a/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobSpecification.java
+++ b/hyracks-api/src/main/java/edu/uci/ics/hyracks/api/job/JobSpecification.java
@@ -264,8 +264,6 @@
public JSONObject toJSON() throws JSONException {
JSONObject jjob = new JSONObject();
- jjob.put("type", "job");
-
JSONArray jopArray = new JSONArray();
for (Map.Entry<OperatorDescriptorId, IOperatorDescriptor> e : opMap.entrySet()) {
jopArray.put(e.getValue().toJSON());
@@ -277,7 +275,6 @@
JSONObject conn = new JSONObject();
Pair<Pair<IOperatorDescriptor, Integer>, Pair<IOperatorDescriptor, Integer>> connection = connectorOpMap
.get(e.getKey());
- conn.put("type", "connector-info");
if (connection != null) {
conn.put("in-operator-id", connection.first.first.getOperatorId().toString());
conn.put("in-operator-port", connection.first.second.intValue());
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.java
index 6b7e143..3a86c42 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.java
@@ -15,9 +15,12 @@
package edu.uci.ics.hyracks.control.cc.adminconsole.pages;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.EmptyPanel;
@@ -26,6 +29,8 @@
import org.json.JSONArray;
import org.json.JSONObject;
+import edu.uci.ics.hyracks.api.dataflow.ActivityId;
+import edu.uci.ics.hyracks.api.dataflow.TaskId;
import edu.uci.ics.hyracks.api.job.JobId;
import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
import edu.uci.ics.hyracks.control.cc.work.GetJobActivityGraphJSONWork;
@@ -35,7 +40,7 @@
public class JobDetailsPage extends AbstractPage {
private static final long serialVersionUID = 1L;
- private static final int HEIGHT = 9;
+ private static final int HEIGHT = 29;
private static final int WIDTH = 9;
public JobDetailsPage(PageParameters params) throws Exception {
@@ -47,18 +52,164 @@
GetJobSpecificationJSONWork gjsw = new GetJobSpecificationJSONWork(ccs, jobId);
ccs.getWorkQueue().scheduleAndSync(gjsw);
- add(new Label("job-specification", gjsw.getJSON().toString()));
+ Label jobspec = new Label("job-specification", gjsw.getJSON().toString());
+ jobspec.setEscapeModelStrings(false);
+ add(jobspec);
GetJobActivityGraphJSONWork gjagw = new GetJobActivityGraphJSONWork(ccs, jobId);
ccs.getWorkQueue().scheduleAndSync(gjagw);
- add(new Label("job-activity-graph", gjagw.getJSON().toString()));
+ Label jag = new Label("job-activity-graph", gjagw.getJSON().toString());
+ jag.setEscapeModelStrings(false);
+ add(jag);
+
+ JSONObject jagO = gjagw.getJSON();
+
+ Map<ActivityId, String> activityMap = new HashMap<ActivityId, String>();
+ if (jagO.has("activities")) {
+ JSONArray aArray = jagO.getJSONArray("activities");
+ for (int i = 0; i < aArray.length(); ++i) {
+ JSONObject aO = aArray.getJSONObject(i);
+ ActivityId aid = ActivityId.parse(aO.getString("id"));
+ String className = aO.getString("java-class");
+
+ activityMap.put(aid, className);
+ }
+ }
GetJobRunJSONWork gjrw = new GetJobRunJSONWork(ccs, jobId);
ccs.getWorkQueue().scheduleAndSync(gjrw);
- add(new Label("job-run", gjrw.getJSON().toString()));
+ Label jobrun = new Label("job-run", gjrw.getJSON().toString());
+ jobrun.setEscapeModelStrings(false);
+ add(jobrun);
JSONObject jrO = gjrw.getJSON();
+ List<TaskClusterAttempt[]> tcList = new ArrayList<TaskClusterAttempt[]>();
+ long minTime = Long.MAX_VALUE;
+ long maxTime = Long.MIN_VALUE;
+ if (jrO.has("activity-clusters")) {
+ JSONArray acA = jrO.getJSONArray("activity-clusters");
+ for (int i = 0; i < acA.length(); ++i) {
+ JSONObject acO = acA.getJSONObject(i);
+ if (acO.has("plan")) {
+ JSONObject planO = acO.getJSONObject("plan");
+ if (planO.has("task-clusters")) {
+ JSONArray tcA = planO.getJSONArray("task-clusters");
+ for (int j = 0; j < tcA.length(); ++j) {
+ JSONObject tcO = tcA.getJSONObject(j);
+ String tcId = tcO.getString("task-cluster-id");
+ if (tcO.has("attempts")) {
+ JSONArray tcaA = tcO.getJSONArray("attempts");
+ TaskClusterAttempt[] tcAttempts = new TaskClusterAttempt[tcaA.length()];
+ for (int k = 0; k < tcaA.length(); ++k) {
+ JSONObject tcaO = tcaA.getJSONObject(k);
+ int attempt = tcaO.getInt("attempt");
+ long startTime = tcaO.getLong("start-time");
+ long endTime = tcaO.getLong("end-time");
+
+ tcAttempts[k] = new TaskClusterAttempt(tcId, attempt, startTime, endTime);
+ if (startTime < minTime) {
+ minTime = startTime;
+ }
+ if (endTime > maxTime) {
+ maxTime = endTime;
+ }
+ if (tcaO.has("task-attempts")) {
+ JSONArray taArray = tcaO.getJSONArray("task-attempts");
+ tcAttempts[k].tasks = new TaskAttempt[taArray.length()];
+ for (int l = 0; l < taArray.length(); ++l) {
+ JSONObject taO = taArray.getJSONObject(l);
+ TaskAttempt ta = new TaskAttempt(taO.getString("task-id"),
+ taO.getLong("start-time"), taO.getLong("end-time"));
+ tcAttempts[k].tasks[l] = ta;
+ TaskId tid = TaskId.parse(taO.getString("task-id"));
+ ta.name = activityMap.get(tid.getActivityId());
+ ta.partition = tid.getPartition();
+ }
+ Arrays.sort(tcAttempts[k].tasks, new Comparator<TaskAttempt>() {
+ @Override
+ public int compare(TaskAttempt o1, TaskAttempt o2) {
+ return o1.startTime < o2.startTime ? -1
+ : (o1.startTime > o2.startTime ? 1 : 0);
+ }
+ });
+ }
+ }
+ Arrays.sort(tcAttempts, new Comparator<TaskClusterAttempt>() {
+ @Override
+ public int compare(TaskClusterAttempt o1, TaskClusterAttempt o2) {
+ return o1.startTime < o2.startTime ? -1 : (o1.startTime > o2.startTime ? 1 : 0);
+ }
+ });
+ tcList.add(tcAttempts);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!tcList.isEmpty()) {
+ Collections.sort(tcList, new Comparator<TaskClusterAttempt[]>() {
+ @Override
+ public int compare(TaskClusterAttempt[] o1, TaskClusterAttempt[] o2) {
+ if (o1.length == 0) {
+ return o2.length == 0 ? 0 : -1;
+ } else if (o2.length == 0) {
+ return 1;
+ }
+ return o1[0].startTime < o2[0].startTime ? -1 : (o1[0].startTime > o2[0].startTime ? 1 : 0);
+ }
+ });
+ long range = maxTime - minTime;
+
+ double leftOffset = 20;
+
+ int xWidth = 1024;
+ double width = ((double) xWidth) / range;
+ StringBuilder buffer = new StringBuilder();
+ int y = 0;
+ for (TaskClusterAttempt[] tcAttempts : tcList) {
+ for (int i = 0; i < tcAttempts.length; ++i) {
+ TaskClusterAttempt tca = tcAttempts[i];
+ long startTime = tca.startTime - minTime;
+ long endTime = tca.endTime - minTime;
+ buffer.append("<rect x=\"").append(startTime * width + leftOffset).append("\" y=\"")
+ .append(y * (HEIGHT + 1)).append("\" width=\"").append(width * (endTime - startTime))
+ .append("\" height=\"").append(HEIGHT).append("\"/>\n");
+ buffer.append("<text x=\"").append(endTime * width + leftOffset + 20).append("\" y=\"")
+ .append(y * (HEIGHT + 1) + HEIGHT * 3 / 4).append("\">")
+ .append((endTime - startTime) + " ms").append("</text>\n");
+ ++y;
+ for (int j = 0; j < tca.tasks.length; ++j) {
+ TaskAttempt ta = tca.tasks[j];
+ long tStartTime = ta.startTime - minTime;
+ long tEndTime = ta.endTime - minTime;
+ buffer.append("<rect x=\"").append(tStartTime * width + leftOffset).append("\" y=\"")
+ .append(y * (HEIGHT + 1) + HEIGHT / 4).append("\" width=\"")
+ .append(width * (tEndTime - tStartTime)).append("\" height=\"").append(HEIGHT / 2)
+ .append("\"/>\n");
+ buffer.append("<text x=\"").append(tEndTime * width + leftOffset + 20).append("\" y=\"")
+ .append(y * (HEIGHT + 1) + HEIGHT * 3 / 4).append("\">")
+ .append((tEndTime - tStartTime) + " ms (" + ta.name + ":" + ta.partition + ")")
+ .append("</text>\n");
+ ++y;
+ }
+ }
+ }
+ buffer.append("<rect x=\"").append(leftOffset).append("\" y=\"").append(0).append("\" width=\"").append(1)
+ .append("\" height=\"").append((y + 2) * (HEIGHT + 1)).append("\"/>\n");
+ buffer.append("<rect x=\"").append(0).append("\" y=\"").append((y + 1) * (HEIGHT + 1))
+ .append("\" width=\"").append(xWidth + 2 * leftOffset).append("\" height=\"").append(1)
+ .append("\"/>\n");
+ buffer.append("</svg>");
+ Label markup = new Label("job-timeline",
+ "<svg version=\"1.1\"\nxmlns=\"http://www.w3.org/2000/svg\" width=\"" + (xWidth * 1.5)
+ + "\" height=\"" + ((y + 2) * (HEIGHT + 1)) + "\">\n" + buffer.toString());
+ markup.setEscapeModelStrings(false);
+ add(markup);
+ }
+
List<TaskProfile> taskProfiles = new ArrayList<TaskProfile>();
if (jrO.has("profile")) {
JSONObject pO = jrO.getJSONObject("profile");
@@ -104,8 +255,8 @@
long timeRange = taskProfiles.get(taskProfiles.size() - 1).closeTime - startTime;
int n = taskProfiles.size();
StringBuilder buffer = new StringBuilder();
- buffer.append("<svg viewBox=\"0 0 ").append((timeRange + 1) * (WIDTH + 1))
- .append(' ').append((n + 1) * (HEIGHT + 1)).append("\" version=\"1.1\"\n");
+ buffer.append("<svg viewBox=\"0 0 ").append((timeRange + 1) * (WIDTH + 1)).append(' ')
+ .append((n + 1) * (HEIGHT + 1)).append("\" version=\"1.1\"\n");
buffer.append("xmlns=\"http://www.w3.org/2000/svg\">\n");
for (int i = 0; i < n; ++i) {
TaskProfile tp = taskProfiles.get(i);
@@ -116,11 +267,11 @@
close(buffer, i, tp.closeTime - startTime);
}
buffer.append("</svg>");
- Label markup = new Label("job-timeline", buffer.toString());
+ Label markup = new Label("job-timeline-profile", buffer.toString());
markup.setEscapeModelStrings(false);
add(markup);
} else {
- add(new EmptyPanel("job-timeline"));
+ add(new EmptyPanel("job-timeline-profile"));
}
}
@@ -139,6 +290,35 @@
.append("\" width=\"").append(WIDTH).append("\" height=\"").append(HEIGHT).append("\"/>\n");
}
+ private static class TaskAttempt {
+ private String taskId;
+ private long startTime;
+ private long endTime;
+ private String name;
+ private int partition;
+
+ public TaskAttempt(String taskId, long startTime, long endTime) {
+ this.taskId = taskId;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ }
+ }
+
+ private static class TaskClusterAttempt {
+ private String tcId;
+ private int attempt;
+ private long startTime;
+ private long endTime;
+ private TaskAttempt[] tasks;
+
+ public TaskClusterAttempt(String tcId, int attempt, long startTime, long endTime) {
+ this.tcId = tcId;
+ this.attempt = attempt;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ }
+ }
+
private static class TaskProfile {
private String activityId;
private int partition;
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
index df003b2..a72a866 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/JobRun.java
@@ -316,6 +316,8 @@
JSONObject attempt = new JSONObject();
attempt.put("attempt", tca.getAttempt());
attempt.put("status", tca.getStatus());
+ attempt.put("start-time", tca.getStartTime());
+ attempt.put("end-time", tca.getEndTime());
JSONArray taskAttempts = new JSONArray();
for (TaskAttempt ta : tca.getTaskAttempts()) {
@@ -324,6 +326,8 @@
taskAttempt.put("task-attempt-id", ta.getTaskAttemptId());
taskAttempt.put("status", ta.getStatus());
taskAttempt.put("node-id", ta.getNodeId());
+ taskAttempt.put("start-time", ta.getStartTime());
+ taskAttempt.put("end-time", ta.getEndTime());
String failureDetails = ta.getFailureDetails();
if (failureDetails != null) {
taskAttempt.put("failure-details", failureDetails);
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskAttempt.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskAttempt.java
index 43495db..7c0dd57 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskAttempt.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskAttempt.java
@@ -29,7 +29,7 @@
private final TaskAttemptId taskId;
- private final Task taskState;
+ private final Task task;
private String nodeId;
@@ -37,10 +37,16 @@
private String failureDetails;
- public TaskAttempt(TaskClusterAttempt tcAttempt, TaskAttemptId taskId, Task taskState) {
+ private long startTime;
+
+ private long endTime;
+
+ public TaskAttempt(TaskClusterAttempt tcAttempt, TaskAttemptId taskId, Task task) {
this.tcAttempt = tcAttempt;
this.taskId = taskId;
- this.taskState = taskState;
+ this.task = task;
+ startTime = -1;
+ endTime = -1;
}
public TaskClusterAttempt getTaskClusterAttempt() {
@@ -51,8 +57,8 @@
return taskId;
}
- public Task getTaskState() {
- return taskState;
+ public Task getTask() {
+ return task;
}
public String getNodeId() {
@@ -75,4 +81,20 @@
this.status = status;
this.failureDetails = details;
}
+
+ public long getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(long startTime) {
+ this.startTime = startTime;
+ }
+
+ public long getEndTime() {
+ return endTime;
+ }
+
+ public void setEndTime(long endTime) {
+ this.endTime = endTime;
+ }
}
\ No newline at end of file
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskClusterAttempt.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskClusterAttempt.java
index 9d33d12..84848bb 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskClusterAttempt.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/job/TaskClusterAttempt.java
@@ -32,9 +32,15 @@
private int pendingTaskCounter;
+ private long startTime;
+
+ private long endTime;
+
public TaskClusterAttempt(TaskCluster taskCluster, int attempt) {
this.taskCluster = taskCluster;
this.attempt = attempt;
+ startTime = -1;
+ endTime = -1;
}
public TaskCluster getTaskCluster() {
@@ -61,6 +67,22 @@
return status;
}
+ public long getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(long startTime) {
+ this.startTime = startTime;
+ }
+
+ public long getEndTime() {
+ return endTime;
+ }
+
+ public void setEndTime(long endTime) {
+ this.endTime = endTime;
+ }
+
public void initializePendingTaskCounter() {
pendingTaskCounter = taskAttempts.length;
}
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/scheduler/JobScheduler.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/scheduler/JobScheduler.java
index 3feb5a6..6933bf0 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/scheduler/JobScheduler.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/scheduler/JobScheduler.java
@@ -387,6 +387,7 @@
}
taskAttempt.setNodeId(nodeId);
taskAttempt.setStatus(TaskAttempt.TaskStatus.RUNNING, null);
+ taskAttempt.setStartTime(System.currentTimeMillis());
List<TaskAttemptDescriptor> tads = taskAttemptMap.get(nodeId);
if (tads == null) {
tads = new ArrayList<TaskAttemptDescriptor>();
@@ -399,6 +400,7 @@
tcAttempt.initializePendingTaskCounter();
tcAttempts.add(tcAttempt);
tcAttempt.setStatus(TaskClusterAttempt.TaskClusterStatus.RUNNING);
+ tcAttempt.setStartTime(System.currentTimeMillis());
inProgressTaskClusters.add(tc);
}
@@ -477,6 +479,7 @@
LOGGER.info("Checking " + taId + ": " + ta.getStatus());
if (status == TaskAttempt.TaskStatus.RUNNING || status == TaskAttempt.TaskStatus.COMPLETED) {
ta.setStatus(TaskAttempt.TaskStatus.ABORTED, null);
+ ta.setEndTime(System.currentTimeMillis());
List<TaskAttemptId> abortTaskAttempts = abortTaskAttemptMap.get(ta.getNodeId());
if (abortTaskAttempts == null) {
abortTaskAttempts = new ArrayList<TaskAttemptId>();
@@ -524,6 +527,7 @@
TaskClusterAttempt tca = findLastTaskClusterAttempt(tc);
if (tca != null) {
abortTaskCluster(tca);
+ tca.setEndTime(System.currentTimeMillis());
tca.setStatus(TaskClusterAttempt.TaskClusterStatus.ABORTED);
}
}
@@ -571,14 +575,16 @@
public void notifyTaskComplete(TaskAttempt ta) throws HyracksException {
TaskAttemptId taId = ta.getTaskAttemptId();
- TaskCluster tc = ta.getTaskState().getTaskCluster();
+ TaskCluster tc = ta.getTask().getTaskCluster();
TaskClusterAttempt lastAttempt = findLastTaskClusterAttempt(tc);
if (lastAttempt != null && taId.getAttempt() == lastAttempt.getAttempt()) {
TaskAttempt.TaskStatus taStatus = ta.getStatus();
if (taStatus == TaskAttempt.TaskStatus.RUNNING) {
ta.setStatus(TaskAttempt.TaskStatus.COMPLETED, null);
+ ta.setEndTime(System.currentTimeMillis());
if (lastAttempt.decrementPendingTasksCounter() == 0) {
lastAttempt.setStatus(TaskClusterAttempt.TaskClusterStatus.COMPLETED);
+ lastAttempt.setEndTime(System.currentTimeMillis());
inProgressTaskClusters.remove(tc);
startRunnableActivityClusters();
}
@@ -604,13 +610,14 @@
try {
LOGGER.info("Received failure notification for TaskAttempt " + ta.getTaskAttemptId());
TaskAttemptId taId = ta.getTaskAttemptId();
- TaskCluster tc = ta.getTaskState().getTaskCluster();
+ TaskCluster tc = ta.getTask().getTaskCluster();
TaskClusterAttempt lastAttempt = findLastTaskClusterAttempt(tc);
if (lastAttempt != null && taId.getAttempt() == lastAttempt.getAttempt()) {
LOGGER.info("Marking TaskAttempt " + ta.getTaskAttemptId() + " as failed");
ta.setStatus(TaskAttempt.TaskStatus.FAILED, details);
abortTaskCluster(lastAttempt);
lastAttempt.setStatus(TaskClusterAttempt.TaskClusterStatus.FAILED);
+ lastAttempt.setEndTime(System.currentTimeMillis());
abortDoomedTaskClusters();
if (lastAttempt.getAttempt() >= ac.getMaxTaskClusterAttempts()) {
abortJob(new HyracksException(details));
@@ -648,6 +655,7 @@
assert (ta.getStatus() == TaskAttempt.TaskStatus.COMPLETED || ta.getStatus() == TaskAttempt.TaskStatus.RUNNING);
if (deadNodes.contains(ta.getNodeId())) {
ta.setStatus(TaskAttempt.TaskStatus.FAILED, "Node " + ta.getNodeId() + " failed");
+ ta.setEndTime(System.currentTimeMillis());
abort = true;
}
}
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java
index 2838ed4..2694af4 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskCompleteWork.java
@@ -39,7 +39,7 @@
@Override
protected void performEvent(TaskAttempt ta) {
try {
- ActivityCluster ac = ta.getTaskState().getTaskCluster().getActivityCluster();
+ ActivityCluster ac = ta.getTask().getTaskCluster().getActivityCluster();
JobRun run = ac.getJobRun();
if (statistics != null) {
JobProfile jobProfile = run.getJobProfile();
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskFailureWork.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskFailureWork.java
index b80d928..3201bec 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskFailureWork.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/work/TaskFailureWork.java
@@ -31,7 +31,7 @@
@Override
protected void performEvent(TaskAttempt ta) {
- ActivityCluster ac = ta.getTaskState().getTaskCluster().getActivityCluster();
+ ActivityCluster ac = ta.getTask().getTaskCluster().getActivityCluster();
ac.getJobRun().getScheduler().notifyTaskFailure(ta, ac, details);
}
diff --git a/hyracks-control-cc/src/main/resources/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.html b/hyracks-control-cc/src/main/resources/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.html
index f11e480..8c5578d 100644
--- a/hyracks-control-cc/src/main/resources/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.html
+++ b/hyracks-control-cc/src/main/resources/edu/uci/ics/hyracks/control/cc/adminconsole/pages/JobDetailsPage.html
@@ -5,5 +5,6 @@
</div>
<div id="job-run" wicket:id="job-run" style="display: none;">
</div>
- <div wicket:id="job-timeline"></div>
+ <div wicket:id="job-timeline" style="overflow: auto;"></div>
+ <div wicket:id="job-timeline-profile"></div>
</wicket:extend>
\ No newline at end of file
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobProfile.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobProfile.java
index 5457ac5..46a964a 100644
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobProfile.java
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobProfile.java
@@ -3,6 +3,7 @@
import java.util.HashMap;
import java.util.Map;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -32,12 +33,13 @@
public JSONObject toJSON() throws JSONException {
JSONObject json = new JSONObject();
- json.put("type", "job-profile");
json.put("job-id", jobId.toString());
populateCounters(json);
+ JSONArray jobletsArray = new JSONArray();
for (JobletProfile p : jobletProfiles.values()) {
- json.accumulate("joblets", p.toJSON());
+ jobletsArray.put(p.toJSON());
}
+ json.put("joblets", jobletsArray);
return json;
}
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobletProfile.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobletProfile.java
index 78f885d..0c60006 100644
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobletProfile.java
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/JobletProfile.java
@@ -47,7 +47,6 @@
public JSONObject toJSON() throws JSONException {
JSONObject json = new JSONObject();
- json.put("type", "joblet-profile");
json.put("node-id", nodeId.toString());
populateCounters(json);
JSONArray tasks = new JSONArray();
diff --git a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/TaskProfile.java b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/TaskProfile.java
index 3764a01..139a985 100644
--- a/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/TaskProfile.java
+++ b/hyracks-control-common/src/main/java/edu/uci/ics/hyracks/control/common/job/profiling/om/TaskProfile.java
@@ -48,7 +48,6 @@
public JSONObject toJSON() throws JSONException {
JSONObject json = new JSONObject();
- json.put("type", "task-profile");
json.put("activity-id", taskAttemptId.getTaskId().getActivityId().toString());
json.put("partition", taskAttemptId.getTaskId().getPartition());
json.put("attempt", taskAttemptId.getAttempt());
diff --git a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractConnectorDescriptor.java b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractConnectorDescriptor.java
index f3535f8..4ffc060 100644
--- a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractConnectorDescriptor.java
+++ b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractConnectorDescriptor.java
@@ -41,7 +41,6 @@
public JSONObject toJSON() throws JSONException {
JSONObject jconn = new JSONObject();
- jconn.put("type", "connector");
jconn.put("id", getConnectorId().getId());
jconn.put("java-class", getClass().getName());
diff --git a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractOperatorDescriptor.java b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractOperatorDescriptor.java
index 15fc75d..1bb13ca 100644
--- a/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractOperatorDescriptor.java
+++ b/hyracks-dataflow-std/src/main/java/edu/uci/ics/hyracks/dataflow/std/base/AbstractOperatorDescriptor.java
@@ -75,7 +75,6 @@
@Override
public JSONObject toJSON() throws JSONException {
JSONObject jop = new JSONObject();
- jop.put("type", "operator");
jop.put("id", getOperatorId().getId());
jop.put("java-class", getClass().getName());
jop.put("in-arity", getInputArity());