Added timeline computation to admin console
git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_dev_next@799 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/IndexPage.java b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/IndexPage.java
index 0c24ca4..3b9be36 100644
--- a/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/IndexPage.java
+++ b/hyracks-control-cc/src/main/java/edu/uci/ics/hyracks/control/cc/adminconsole/pages/IndexPage.java
@@ -75,7 +75,7 @@
item.add(new Label("start-time", o.getString("start-time")));
item.add(new Label("end-time", o.getString("end-time")));
PageParameters params = new PageParameters();
- params.add("job-id", o.getString("node-id"));
+ params.add("job-id", o.getString("job-id"));
item.add(new BookmarkablePageLink<Object>("job-details", JobDetailsPage.class, params));
} catch (JSONException e) {
throw new RuntimeException(e);
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 5f05ce0..6b7e143 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
@@ -14,9 +14,17 @@
*/
package edu.uci.ics.hyracks.control.cc.adminconsole.pages;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.string.StringValue;
+import org.json.JSONArray;
+import org.json.JSONObject;
import edu.uci.ics.hyracks.api.job.JobId;
import edu.uci.ics.hyracks.control.cc.ClusterControllerService;
@@ -27,6 +35,9 @@
public class JobDetailsPage extends AbstractPage {
private static final long serialVersionUID = 1L;
+ private static final int HEIGHT = 9;
+ private static final int WIDTH = 9;
+
public JobDetailsPage(PageParameters params) throws Exception {
ClusterControllerService ccs = getAdminConsoleApplication().getClusterControllerService();
@@ -45,5 +56,105 @@
GetJobRunJSONWork gjrw = new GetJobRunJSONWork(ccs, jobId);
ccs.getWorkQueue().scheduleAndSync(gjrw);
add(new Label("job-run", gjrw.getJSON().toString()));
+
+ JSONObject jrO = gjrw.getJSON();
+
+ List<TaskProfile> taskProfiles = new ArrayList<TaskProfile>();
+ if (jrO.has("profile")) {
+ JSONObject pO = jrO.getJSONObject("profile");
+ if (pO.has("joblets")) {
+ JSONArray jobletsA = pO.getJSONArray("joblets");
+ for (int i = 0; i < jobletsA.length(); ++i) {
+ JSONObject jobletO = jobletsA.getJSONObject(i);
+ if (jobletO.has("tasks")) {
+ JSONArray tasksA = jobletO.getJSONArray("tasks");
+ for (int j = 0; j < tasksA.length(); ++j) {
+ JSONObject taskO = tasksA.getJSONObject(j);
+ String activityId = taskO.getString("activity-id");
+ int partition = taskO.getInt("partition");
+ int attempt = taskO.getInt("attempt");
+ if (taskO.has("partition-send-profile")) {
+ JSONArray taskProfilesA = taskO.getJSONArray("partition-send-profile");
+ for (int k = 0; k < taskProfilesA.length(); ++k) {
+ JSONObject ppO = taskProfilesA.getJSONObject(k);
+ long openTime = ppO.getLong("open-time");
+ long closeTime = ppO.getLong("close-time");
+ JSONArray frameTimesA = ppO.getJSONArray("frame-times");
+ long[] frameTimes = new long[frameTimesA.length()];
+ for (int l = 0; l < frameTimes.length; ++l) {
+ frameTimes[l] = frameTimesA.getLong(l);
+ }
+ taskProfiles.add(new TaskProfile(activityId, partition, attempt, openTime,
+ closeTime, frameTimes));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!taskProfiles.isEmpty()) {
+ Collections.sort(taskProfiles, new Comparator<TaskProfile>() {
+ @Override
+ public int compare(TaskProfile o1, TaskProfile o2) {
+ return o1.openTime < o2.openTime ? -1 : (o1.openTime > o2.openTime ? 1 : 0);
+ }
+ });
+ long startTime = taskProfiles.get(0).openTime;
+ 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("xmlns=\"http://www.w3.org/2000/svg\">\n");
+ for (int i = 0; i < n; ++i) {
+ TaskProfile tp = taskProfiles.get(i);
+ open(buffer, i, tp.openTime - startTime);
+ for (long ft : tp.frameTimes) {
+ nextFrame(buffer, i, ft - startTime);
+ }
+ close(buffer, i, tp.closeTime - startTime);
+ }
+ buffer.append("</svg>");
+ Label markup = new Label("job-timeline", buffer.toString());
+ markup.setEscapeModelStrings(false);
+ add(markup);
+ } else {
+ add(new EmptyPanel("job-timeline"));
+ }
+ }
+
+ private void open(StringBuilder buffer, int i, long openTime) {
+ buffer.append("<rect x=\"").append(openTime * (WIDTH + 1)).append("\" y=\"").append(i * (HEIGHT + 1))
+ .append("\" width=\"").append(WIDTH).append("\" height=\"").append(HEIGHT).append("\"/>\n");
+ }
+
+ private void close(StringBuilder buffer, int i, long closeTime) {
+ buffer.append("<rect x=\"").append(closeTime * (WIDTH + 1)).append("\" y=\"").append(i * (HEIGHT + 1))
+ .append("\" width=\"").append(WIDTH).append("\" height=\"").append(HEIGHT).append("\"/>\n");
+ }
+
+ private void nextFrame(StringBuilder buffer, int i, long frameTime) {
+ buffer.append("<rect x=\"").append(frameTime * (WIDTH + 1)).append("\" y=\"").append(i * (HEIGHT + 1))
+ .append("\" width=\"").append(WIDTH).append("\" height=\"").append(HEIGHT).append("\"/>\n");
+ }
+
+ private static class TaskProfile {
+ private String activityId;
+ private int partition;
+ private int attempt;
+ private long openTime;
+ private long closeTime;
+ private long[] frameTimes;
+
+ public TaskProfile(String activityId, int partition, int attempt, long openTime, long closeTime,
+ long[] frameTimes) {
+ this.activityId = activityId;
+ this.partition = partition;
+ this.activityId = activityId;
+ this.openTime = openTime;
+ this.closeTime = closeTime;
+ this.frameTimes = frameTimes;
+ }
}
}
\ No newline at end of file
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 da6d8a6..f11e480 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,4 +5,5 @@
</div>
<div id="job-run" wicket:id="job-run" style="display: none;">
</div>
+ <div wicket:id="job-timeline"></div>
</wicket:extend>
\ No newline at end of file