|
@@ -15,22 +15,64 @@ function impalaDagre(id) {
|
|
|
var _impalaDagree = {
|
|
var _impalaDagree = {
|
|
|
update: function(plan) {
|
|
update: function(plan) {
|
|
|
renderGraph(plan);
|
|
renderGraph(plan);
|
|
|
|
|
+ _impalaDagree._width = $(svg[0]).width();
|
|
|
},
|
|
},
|
|
|
height: function(value) {
|
|
height: function(value) {
|
|
|
var scale = _impalaDagree.scale || 1;
|
|
var scale = _impalaDagree.scale || 1;
|
|
|
var height = value || 600;
|
|
var height = value || 600;
|
|
|
|
|
+ _impalaDagree._height = height;
|
|
|
svg.attr('height', Math.min(g.graph().height * scale + 40, height) || height);
|
|
svg.attr('height', Math.min(g.graph().height * scale + 40, height) || height);
|
|
|
},
|
|
},
|
|
|
|
|
+ action: function(type) {
|
|
|
|
|
+ if (type == 'plus') {
|
|
|
|
|
+ zoom.scale(zoom.scale() + 0.25);
|
|
|
|
|
+ inner.attr("transform", "translate(" + zoom.translate() + ")" +
|
|
|
|
|
+ "scale(" + zoom.scale() + ")");
|
|
|
|
|
+ } else if (type == 'minus') {
|
|
|
|
|
+ zoom.scale(zoom.scale() - 0.25);
|
|
|
|
|
+ inner.attr("transform", "translate(" + zoom.translate() + ")" +
|
|
|
|
|
+ "scale(" + zoom.scale() + ")");
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
moveTo: function(id) {
|
|
moveTo: function(id) {
|
|
|
zoomToNode(id);
|
|
zoomToNode(id);
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ select: function(id) {
|
|
|
|
|
+ select(id);
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
|
|
+ createActions();
|
|
|
|
|
+
|
|
|
|
|
+ function createActions () {
|
|
|
|
|
+ d3.select("#"+id)
|
|
|
|
|
+ .style('position', 'relative')
|
|
|
|
|
+ .append('div')
|
|
|
|
|
+ .style('position', 'absolute')
|
|
|
|
|
+ .style('right', '5px')
|
|
|
|
|
+ .style('bottom', '5px')
|
|
|
|
|
+ .classed('button', true)
|
|
|
|
|
+ .selectAll('button').data([{ type: 'plus', icon: 'fa-plus' }, { type: 'minus', icon: 'fa-minus' }])
|
|
|
|
|
+ .enter()
|
|
|
|
|
+ .append(function (data) {
|
|
|
|
|
+ var button = $("<div class='fa fa-fw valign-middle " + data.icon + "'></div>")[0];
|
|
|
|
|
+ $(button).on('click', function () {
|
|
|
|
|
+ _impalaDagree.action(data.type);
|
|
|
|
|
+ });
|
|
|
|
|
+ return button;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Set up zoom support
|
|
// Set up zoom support
|
|
|
var zoom = d3.behavior.zoom().on("zoom", function() {
|
|
var zoom = d3.behavior.zoom().on("zoom", function() {
|
|
|
- _impalaDagree.scale = d3.event.scale;
|
|
|
|
|
- inner.attr("transform", "translate(" + d3.event.translate + ")" +
|
|
|
|
|
- "scale(" + d3.event.scale + ")");
|
|
|
|
|
|
|
+ var e = d3.event,
|
|
|
|
|
+ scale = Math.min(Math.max(e.scale, Math.min(_impalaDagree._width / g.graph().width, _impalaDagree._height / g.graph().height)), 2),
|
|
|
|
|
+ tx = Math.min(40, Math.max(e.translate[0], _impalaDagree._width - 40 - g.graph().width * scale)),
|
|
|
|
|
+ ty = Math.min(40, Math.max(e.translate[1], _impalaDagree._height - 40 - g.graph().height * scale));
|
|
|
|
|
+ _impalaDagree.scale = scale;
|
|
|
|
|
+ zoom.translate([tx, ty]);
|
|
|
|
|
+ zoom.scale(scale);
|
|
|
|
|
+ inner.attr("transform", "translate(" + [tx, ty] + ")" +
|
|
|
|
|
+ "scale(" + scale + ")");
|
|
|
});
|
|
});
|
|
|
svg.call(zoom);
|
|
svg.call(zoom);
|
|
|
|
|
|
|
@@ -47,14 +89,16 @@ function impalaDagre(id) {
|
|
|
function build(node, parent, edges, states, colour_idx, max_node_time) {
|
|
function build(node, parent, edges, states, colour_idx, max_node_time) {
|
|
|
if (!node["output_card"]) return;
|
|
if (!node["output_card"]) return;
|
|
|
states.push({ "name": node["label"],
|
|
states.push({ "name": node["label"],
|
|
|
|
|
+ "type": node["type"],
|
|
|
|
|
+ "label": node["name"],
|
|
|
"detail": node["label_detail"],
|
|
"detail": node["label_detail"],
|
|
|
"num_instances": node["num_instances"],
|
|
"num_instances": node["num_instances"],
|
|
|
"num_active": node["num_active"],
|
|
"num_active": node["num_active"],
|
|
|
"max_time": node["max_time"],
|
|
"max_time": node["max_time"],
|
|
|
"avg_time": node["avg_time"],
|
|
"avg_time": node["avg_time"],
|
|
|
|
|
+ "icon": node["icon"],
|
|
|
"is_broadcast": node["is_broadcast"],
|
|
"is_broadcast": node["is_broadcast"],
|
|
|
- "max_time_val": node["max_time_val"],
|
|
|
|
|
- "style": "fill: " + colours[colour_idx]});
|
|
|
|
|
|
|
+ "max_time_val": node["max_time_val"]});
|
|
|
if (parent) {
|
|
if (parent) {
|
|
|
var label_val = "" + node["output_card"].toLocaleString();
|
|
var label_val = "" + node["output_card"].toLocaleString();
|
|
|
edges.push({ start: node["label"], end: parent,
|
|
edges.push({ start: node["label"], end: parent,
|
|
@@ -66,7 +110,7 @@ function impalaDagre(id) {
|
|
|
edges.push({ "start": node["label"],
|
|
edges.push({ "start": node["label"],
|
|
|
"end": node["data_stream_target"],
|
|
"end": node["data_stream_target"],
|
|
|
"style": { label: "" + node["output_card"].toLocaleString(),
|
|
"style": { label: "" + node["output_card"].toLocaleString(),
|
|
|
- style: "stroke: #f66; stroke-dasharray: 5, 5;"}});
|
|
|
|
|
|
|
+ style: "stroke-dasharray: 5, 5;"}});
|
|
|
}
|
|
}
|
|
|
max_node_time = Math.max(node["max_time_val"], max_node_time)
|
|
max_node_time = Math.max(node["max_time_val"], max_node_time)
|
|
|
for (var i = 0; i < node["children"].length; ++i) {
|
|
for (var i = 0; i < node["children"].length; ++i) {
|
|
@@ -78,7 +122,16 @@ function impalaDagre(id) {
|
|
|
|
|
|
|
|
var is_first = true;
|
|
var is_first = true;
|
|
|
|
|
|
|
|
- function zoomToNode(node) {
|
|
|
|
|
|
|
+ function select(node) {
|
|
|
|
|
+ var key = getKey(node);
|
|
|
|
|
+ if (!key) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ $("g.node").attr('class', 'node') // addClass doesn't work in svg on our version of jQuery
|
|
|
|
|
+ $("g.node:contains('" + key + "')").attr('class', 'node active');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function getKey(node) {
|
|
|
var nodes = g.nodes();
|
|
var nodes = g.nodes();
|
|
|
var key;
|
|
var key;
|
|
|
var nNode = parseInt(node, 10);
|
|
var nNode = parseInt(node, 10);
|
|
@@ -89,6 +142,11 @@ function impalaDagre(id) {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ return key;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function zoomToNode(node) {
|
|
|
|
|
+ var key = getKey(node);
|
|
|
if (!key) {
|
|
if (!key) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -122,14 +180,18 @@ function impalaDagre(id) {
|
|
|
var states_by_name = { };
|
|
var states_by_name = { };
|
|
|
states.forEach(function(state) {
|
|
states.forEach(function(state) {
|
|
|
// Build the label for the node from the name and the detail
|
|
// Build the label for the node from the name and the detail
|
|
|
- var html = "<span>" + state.name + "</span><br/>";
|
|
|
|
|
- html += "<span>" + state.detail + "</span><br/>";
|
|
|
|
|
- html += "<span>" + state.num_instances + " instance";
|
|
|
|
|
- if (state.num_instances > 1) {
|
|
|
|
|
- html += "s";
|
|
|
|
|
|
|
+ var html = "";
|
|
|
|
|
+ if (state.icon && state.icon.svg) {
|
|
|
|
|
+ html += '<svg class="hi"><use xlink:href="#'+ state.icon.svg +'"></use></svg>'
|
|
|
|
|
+ //html += "<img src=\"" + icon.svg + "\"></img>";
|
|
|
|
|
+ } else if (state.icon && state.icon.font){
|
|
|
|
|
+ html += "<span class='fa fa-fw valign-middle " + state.icon.font + "'></span>";
|
|
|
}
|
|
}
|
|
|
- html += "</span><br/>";
|
|
|
|
|
- html += "<span>Max: " + state.max_time + ", avg: " + state.avg_time + "</span>";
|
|
|
|
|
|
|
+ html += "<span class='name'>" + state.label + "</span><br/>";
|
|
|
|
|
+ html += "<span class='metric'>" + state.max_time + "</span>";
|
|
|
|
|
+ html += "<span class='detail'>" + state.detail + "</span><br/>";
|
|
|
|
|
+ html += "<span class='metric'>" + state.max_time + "</span>"
|
|
|
|
|
+ html += "<span class='id'>" + state.name + "</span>";;
|
|
|
|
|
|
|
|
var style = state.style;
|
|
var style = state.style;
|
|
|
|
|
|
|
@@ -150,7 +212,7 @@ function impalaDagre(id) {
|
|
|
// Impala marks 'broadcast' as a property of the receiver, not the sender. We use
|
|
// Impala marks 'broadcast' as a property of the receiver, not the sender. We use
|
|
|
// '(BCAST)' to denote that a node is duplicating its output to all receivers.
|
|
// '(BCAST)' to denote that a node is duplicating its output to all receivers.
|
|
|
if (states_by_name[edge.end].is_broadcast) {
|
|
if (states_by_name[edge.end].is_broadcast) {
|
|
|
- edge.style.label += " \n(BCAST * " + states_by_name[edge.end].num_instances + ")";
|
|
|
|
|
|
|
+ edge.style.label += " * " + states_by_name[edge.end].num_instances;
|
|
|
}
|
|
}
|
|
|
g.setEdge(edge.start, edge.end, edge.style);
|
|
g.setEdge(edge.start, edge.end, edge.style);
|
|
|
});
|
|
});
|