<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

{{> www/common-header.tmpl }}

</div>

<div class="container" style="width:1200px;margin:0 auto;">

<style id="css">
/* Text style for graph nodes */
.node {
  color: white;
  font-size:14px;
  font-weight:700;
  text-align: center;
  white-space: nowrap;
  vertical-align: baseline;
}

.node rect {
  stroke: #333;
  fill: #fff;
}

.edgePath path {
  stroke: #333;
  fill: #333;
  stroke-width: 1.5px;
}
</style>

{{> www/query_detail_tabs.tmpl }}


{{?plan_metadata_unavailable}}
<h3>Plan not yet available. Page will update when query planning completes.</h3>
{{/plan_metadata_unavailable}}

{{^plan_metadata_unavailable}}
<h3>Plan</h3>
<div>
  <label>
  <input type="checkbox" checked="true" id="colour_scheme" onClick="refresh()"/>
  Shade nodes according to time spent (if unchecked, shade according to plan fragment)
  </label>
</div>

<svg style="border: 1px solid darkgray" width=1200 height=600 class="panel"><g/></svg>
{{/plan_metadata_unavailable}}

{{> www/common-footer.tmpl }}

<script src="{{ __common__.host-url }}/www/d3.v3.min.js" charset="utf-8"></script>
<script src="{{ __common__.host-url }}/www/dagre-d3.min.js"></script>

<!-- Builds and then renders a plan graph using Dagre / D3. The JSON for the current query
is retrieved by an HTTP call, and then the graph of nodes and edges is built by walking
over each plan fragment in turn. Plan fragments are connected wherever a node has a
data_stream_target attribute. -->

<script>
$("#plan-tab").addClass("active");

var g = new dagreD3.graphlib.Graph().setGraph({rankDir: "BT"});

var svg = d3.select("svg");
var inner = svg.select("g");

// Set up zoom support
var zoom = d3.behavior.zoom().on("zoom", function() {
  inner.attr("transform", "translate(" + d3.event.translate + ")" +
             "scale(" + d3.event.scale + ")");
});
svg.call(zoom);

// Set of colours to use, with the same colour used for every node in the same plan
// fragment.
var colours = ["#A9A9A9", "#FF8C00", "#8A2BE2", "#A52A2A", "#00008B", "#006400",
               "#228B22", "#4B0082", "#DAA520", "#008B8B", "#000000", "#DC143C"]

// Shades of red in order of intensity, used for colouring nodes by time taken
var cols_by_time = ["#000000", "#1A0500", "#330A00", "#4C0F00", "#661400", "#801A00",
                    "#991F00", "#B22400", "#CC2900", "#E62E00", "#FF3300", "#FF4719"];

// Recursively build a list of edges and states that comprise the plan graph
function build(node, parent, edges, states, colour_idx, max_node_time) {
  states.push({ "name": node["label"],
                "detail": node["label_detail"],
                "num_instances": node["num_instances"],
                "num_active": node["num_active"],
                "max_time": node["max_time"],
                "avg_time": node["avg_time"],
                "is_broadcast": node["is_broadcast"],
                "max_time_val": node["max_time_val"],
                "style": "fill: " + colours[colour_idx]});
  if (parent != null) {
    var label_val = "" + node["output_card"].toLocaleString();
    edges.push({ start: node["label"], end: parent,
                 style: { label: label_val }});
  }
  // Add an inter-fragment edge. We use a red dashed line to show that rows are crossing
  // the fragment boundary.
  if (node["data_stream_target"]) {
    edges.push({ "start": node["label"],
                 "end": node["data_stream_target"],
                 "style": { label: "" + node["output_card"].toLocaleString(),
                            style: "stroke: #f66; stroke-dasharray: 5, 5;"}});
  }
  max_node_time = Math.max(node["max_time_val"], max_node_time)
  for (var i = 0; i < node["children"].length; ++i) {
    max_node_time = build(
      node["children"][i], node["label"], edges, states, colour_idx, max_node_time);
  }
  return max_node_time;
}

var is_first = true;

function renderGraph(ignored_arg) {
  if (req.status != 200) return;
  var json = JSON.parse(req.responseText);
  var plan = json["plan_json"];
  var inflight = json["inflight"];
  if (!inflight) {
    clearInterval(intervalId);
  }

  var states = []
  var edges = []
  var colour_idx = 0;

  var max_node_time = 0;
  plan["plan_nodes"].forEach(function(parent) {
    max_node_time = Math.max(
      build(parent, null, edges, states, colour_idx, max_node_time));
    // Pick a new colour for each plan fragment
    colour_idx = (colour_idx + 1) % colours.length;
  });

  // Keep a map of names to states for use when processing edges.
  var states_by_name = { }
  states.forEach(function(state) {
    // 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";
    }
    html += "</span><br/>";
    html += "<span>Max: " + state.max_time + ", avg: " + state.avg_time + "</span>";

    var style = state.style;

    // If colouring nodes by total time taken, choose a shade in the cols_by_time list
    // with idx proportional to the max time of the node divided by the max time over all
    // nodes.
    if (document.getElementById("colour_scheme").checked) {
      var idx = (cols_by_time.length - 1) * (state.max_time_val / (1.0 * max_node_time));
      style = "fill: " + cols_by_time[Math.floor(idx)];
    }
    g.setNode(state.name, { "label": html,
                            "labelType": "html",
                            "style": style });
    states_by_name[state.name] = state;
  });

  edges.forEach(function(edge) {
    // 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.
    if (states_by_name[edge.end].is_broadcast) {
      edge.style.label += " \n(BCAST * " + states_by_name[edge.end].num_instances + ")";
    }
    g.setEdge(edge.start, edge.end, edge.style);
  });

  g.nodes().forEach(function(v) {
    var node = g.node(v);
    node.rx = node.ry = 5;
  });

  // Create the renderer
  var render = new dagreD3.render();

  // Run the renderer. This is what draws the final graph.
  render(inner, g);

  // Center the graph, but only the first time through (so as to not lose user zooms).
  if (is_first) {
    var initialScale = 0.75;
    zoom.translate([(svg.attr("width") - g.graph().width * initialScale) / 2, 20])
      .scale(initialScale)
      .event(svg);
    svg.attr('height', Math.max(g.graph().height * initialScale + 40, 600));
    is_first = false;
  }

}

// Called periodically, fetches the plan JSON from Impala and passes it to renderGraph()
// for display.
function refresh() {
  req = new XMLHttpRequest();
  req.onload = renderGraph;
  req.open("GET", make_url("/query_plan?query_id={{query_id}}&json"), true);
  req.send();
}

// Force one refresh before starting the timer.
refresh();

var intervalId = setInterval(refresh, 2000);

</script>
