Repository: ambari Updated Branches: refs/heads/trunk 1d3dce261 -> da9086dca
AMBARI-20168. Hive 2: Compact Visual Explain Plan is not loading in firefox (pallavkul) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/da9086dc Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/da9086dc Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/da9086dc Branch: refs/heads/trunk Commit: da9086dcaaf161a15e58bfc5fe44c338da18078d Parents: 1d3dce2 Author: pallavkul <[email protected]> Authored: Fri Feb 24 19:34:17 2017 +0530 Committer: pallavkul <[email protected]> Committed: Fri Feb 24 19:34:17 2017 +0530 ---------------------------------------------------------------------- .../ui/app/templates/queries/query/log.hbs | 2 +- .../ui/app/templates/queries/query/results.hbs | 2 +- .../templates/queries/query/visual-explain.hbs | 2 +- .../ui/app/utils/hive-explainer/processor.js | 32 +++++- .../ui/app/utils/hive-explainer/renderer.js | 55 ++++++++- .../ui/app/utils/hive-explainer/transformer.js | 115 +++++++++++++------ 6 files changed, 160 insertions(+), 48 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/da9086dc/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/log.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/log.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/log.hbs index db1cea2..c7e30f2 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/log.hbs +++ b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/log.hbs @@ -17,7 +17,7 @@ }} {{#unless hasJobAssociated}} - <div>No Log avaiable.</div> + <div>No Log available.</div> {{/unless}} {{#if hasJobAssociated}} http://git-wip-us.apache.org/repos/asf/ambari/blob/da9086dc/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/results.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/results.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/results.hbs index 370e3ef..d859b04 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/results.hbs +++ b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/results.hbs @@ -19,7 +19,7 @@ {{outlet}} {{#unless hasJobAssociated}} - <div>No Results avaiable.</div> + <div>No Results available.</div> {{/unless}} {{#if hasJobAssociated}} http://git-wip-us.apache.org/repos/asf/ambari/blob/da9086dc/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/visual-explain.hbs ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/visual-explain.hbs b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/visual-explain.hbs index ef441b5..5b7e566 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/visual-explain.hbs +++ b/contrib/views/hive20/src/main/resources/ui/app/templates/queries/query/visual-explain.hbs @@ -19,7 +19,7 @@ {{outlet}} {{#unless hasJobAssociated}} - <div>No Visual Explain avaiable.</div> + <div>No Visual Explain available.</div> {{/unless}} {{#if hasJobAssociated}} http://git-wip-us.apache.org/repos/asf/ambari/blob/da9086dc/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/processor.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/processor.js b/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/processor.js index 5dbeb2b..a252498 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/processor.js +++ b/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/processor.js @@ -25,11 +25,12 @@ function processEdges(vertices, edges) { return vertices .map(cVertex => { - const isVertexPartOfSimpleEdge = edges.some(cEdge => cEdge.type === 'SIMPLE_EDGE' && cEdge.parent === cVertex._vertex); - const isVertexPartOfBroadcastEdge = edges.some(cEdge => cEdge.type === 'BROADCAST_EDGE' && cEdge.parent === cVertex._vertex); - const isVertexPartOfCustomSimpleEdge = edges.some(cEdge => cEdge.type === 'CUSTOM_SIMPLE_EDGE' && cEdge.parent === cVertex._vertex); - const isVertexPartOfCustomEdge = edges.some(cEdge => cEdge.type === 'CUSTOM_EDGE' && cEdge.parent === cVertex._vertex); - const isVertexPartOfXProdEdge = edges.some(cEdge => cEdge.type === 'XPROD_EDGE' && cEdge.parent === cVertex._vertex); + const isVertexPartOfSimpleEdge = edges.some(cEdge => cEdge.type === 'SIMPLE_EDGE' && cEdge._source === cVertex._vertex); + const isVertexPartOfBroadcastEdge = edges.some(cEdge => cEdge.type === 'BROADCAST_EDGE' && cEdge._source === cVertex._vertex); + const isVertexPartOfCustomSimpleEdge = edges.some(cEdge => cEdge.type === 'CUSTOM_SIMPLE_EDGE' && cEdge._source === cVertex._vertex); + const isVertexPartOfCustomEdge = edges.some(cEdge => cEdge.type === 'CUSTOM_EDGE' && cEdge._source === cVertex._vertex); + const isVertexPartOfXProdEdge = edges.some(cEdge => cEdge.type === 'XPROD_EDGE' && cEdge._source === cVertex._vertex); + const isVertexPartOfUnionEdge = edges.some(cEdge => cEdge.type === 'CONTAINS' && cEdge._source === cVertex._vertex); let tVertex = cVertex; @@ -58,6 +59,11 @@ function processEdges(vertices, edges) { _operator: 'Cross-product Distribute Pseudo-Edge' }); } + if(isVertexPartOfUnionEdge) { + tVertex = appendIfTerminusOfOperator(tVertex, { + _operator: 'Partition/Sort Pseudo-Edge' + }); + } return tVertex; }); @@ -238,3 +244,19 @@ function doCloneAndOmit(obj, keys) { [cObjKey]: obj[cObjKey] }), {}); } + +export function getEdgesWithCorrectedUnion(edges) { + + return edges + .map(cEdge => { + if(cEdge.type === 'CONTAINS') { + return Object.assign({}, cEdge, { + _source: cEdge._target, + _target: cEdge._source, + }); + } else { + return cEdge; + } + }); + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/da9086dc/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/renderer.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/renderer.js b/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/renderer.js index 5fa5d2e..196a514 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/renderer.js +++ b/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/renderer.js @@ -18,7 +18,7 @@ export default function doRender(data, selector, onRequestDetail) { - const width = '100vw', height = '100vh'; + const width = '1200', height = '960'; d3.select(selector).select('*').remove(); const svg = @@ -30,7 +30,8 @@ export default function doRender(data, selector, onRequestDetail) { const container = svg.append('g'); const zoom = d3.behavior.zoom() - .scaleExtent([1 / 10, 4]) + .scale(1/10) + .scaleExtent([1 / 10, 1]) .on('zoom', () => { container.attr('transform', `translate(${d3.event.translate}) scale(${d3.event.scale})`); }); @@ -58,7 +59,7 @@ export default function doRender(data, selector, onRequestDetail) { .enter() .insert('path', ':first-child') .attr('class', 'edge') - .attr('d', d => getConnectionPath(d, svg, container)); + .attr('d', d => (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) ? getConnectionPathFF(d, svg, container) : getConnectionPath(d, svg, container)); reset(zoom, svg, container); @@ -273,7 +274,51 @@ function reset(zoom, svg, container) { .call( zoom.event ); } -function getConnectionPath(connector, svg, container) { +function getConnectionPathFF(connector, svg, container) { + const source = container.select(`#${connector._source._uuid}`).node(); + const target = container.select(`#${connector._target._uuid}`).node(); + const rSource = d3.select(source).data()[0]; + const rTarget = d3.select(target).data()[0]; + const rSourceVertex = d3.select($(source).closest('.vertex').get(0)).data()[0]; + const rTargetVertex = d3.select($(target).closest('.vertex').get(0)).data()[0]; + + const offsetBox = $(container.node()).children('.vertex').get(0).getBoundingClientRect(); + + + const pSource = { + x: offsetBox.left - 200 + (rSourceVertex._X + (rSourceVertex._widthOfSelf - (rSource._indexX + 1))) * 200 + 140 / 2, + y: offsetBox.top + (rSourceVertex._Y + rSource._indexY) * 100 + 55 / 2, + }; + const pTarget = { + x: offsetBox.left - 200 + (rTargetVertex._X + (rTargetVertex._widthOfSelf - (rTarget._indexX + 1))) * 200 + 140 / 2, + y: offsetBox.top + (rTargetVertex._Y + rTarget._indexY) * 100 + 55 / 2, + }; + const path = [ + pTarget + ]; + const junctionXMultiplier = (pTarget.x - pSource.x < 0) ? +1 : -1; + if(pSource.y !== pTarget.y) { + path.push({ + x: pTarget.x + junctionXMultiplier * 90, + y: pTarget.y + }, { + x: pTarget.x + junctionXMultiplier * 90, + y: pSource.y + }); + } + path.push(pSource); + const offsetY = svg.node().getBoundingClientRect().top; + return path.reduce((accumulator, cPoint, index) => { + if(index === 0) { + return accumulator + `M ${cPoint.x}, ${cPoint.y - offsetY}\n` + } else { + return accumulator + `L ${cPoint.x}, ${cPoint.y - offsetY}\n` + } + }, ''); +} + + +function getConnectionPath(connector, svg, container){ const operators = container.selectAll('.operator'); const source = container.select(`#${connector._source._uuid}`); const target = container.select(`#${connector._target._uuid}`); @@ -317,7 +362,7 @@ function doClean(node) { } else { return ( Object.keys(node) - .filter(cNodeKey => cNodeKey !== '_children' && cNodeKey !== '_uuid') + .filter(cNodeKey => cNodeKey === '_operator' || !cNodeKey.startsWith('_')) .reduce((accumulator, cNodeKey) => { accumulator[cNodeKey] = node[cNodeKey]; return accumulator; http://git-wip-us.apache.org/repos/asf/ambari/blob/da9086dc/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/transformer.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/transformer.js b/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/transformer.js index 70647a8..01d6000 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/transformer.js +++ b/contrib/views/hive20/src/main/resources/ui/app/utils/hive-explainer/transformer.js @@ -17,7 +17,7 @@ */ import doEnhance from './enhancer'; -import {getProcessedVertices} from './processor'; +import {getProcessedVertices, getEdgesWithCorrectedUnion} from './processor'; export default function doTransform(data) { const plan = getTezPlan(data); @@ -29,22 +29,23 @@ export default function doTransform(data) { ]; const tezEdges = getEdges(plan, vertices); - const edges = getEdgesWithFetch(tezEdges, vertices); + const edgesWithCorrectedUnion = getEdgesWithCorrectedUnion(tezEdges); + const edges = getEdgesWithFetch(edgesWithCorrectedUnion, vertices); const enhancedVertices = doEnhance(vertices); const processedVertices = getProcessedVertices(enhancedVertices, edges); + const verticesWithIndexOfChildren = getVerticesWithIndexOfChildren(processedVertices); const tree = getVertexTree(edges); - const connections = getConnections(processedVertices, edges); - const treeWithOffsetY = getTreeWithOffsetAndHeight(tree, processedVertices, connections); + const connections = getConnections(verticesWithIndexOfChildren, edges); + const treeWithOffsetY = getTreeWithOffsetAndHeight(tree, verticesWithIndexOfChildren, connections); - - const nodes = getNodes(processedVertices); + const nodes = getNodes(verticesWithIndexOfChildren); return ({ - vertices: processedVertices, + vertices: verticesWithIndexOfChildren, edges, tree: treeWithOffsetY, nodes, @@ -52,6 +53,32 @@ export default function doTransform(data) { }); } +function getVerticesWithIndexOfChildren(vertices) { + const verticesWithIndexX = vertices.map(cVertex => Object.assign({}, cVertex, { + _children: doGetChildrenWithIndexX(cVertex._children, 0) + })); + + const verticesWithIndexY = verticesWithIndexX.map(cVertex => Object.assign({}, cVertex, { + _children: doGetChildrenWithIndexY(cVertex._children, 0) + })); + + return verticesWithIndexY; +} + +function doGetChildrenWithIndexX(children, cIndex) { + return children.map(cChild => Object.assign({}, cChild, { + _indexX: cIndex, + _children: doGetChildrenWithIndexX(cChild._children, cIndex + 1) + })) +} + +function doGetChildrenWithIndexY(children, cIndex) { + return children.map((cChild, index) => Object.assign({}, cChild, { + _indexY: cIndex + index, + _children: doGetChildrenWithIndexY(cChild._children, cIndex + index) + })) +} + function getTezPlan(data) { const stages = data['STAGE PLANS']; const tezStageKey = Object.keys(stages).find(cStageKey => stages[cStageKey].hasOwnProperty('Tez')); @@ -179,21 +206,17 @@ function doHarmonize(nodes) { }); } -function doGetHeightOfNodes(children) { - if(children.length > 0) { - return children.reduce((height, cChild) => height + doGetHeightOfNodes(cChild._children), 0); - } - return 1; -} - function getTreeWithOffsetAndHeight(node, vertices, connections) { - const treeWithCumulativeHeight = getTreeWithCumulativeHeight(node, vertices); - const treeWithCumulativeWidth = getTreeWithIndividualWidth(treeWithCumulativeHeight, vertices); - const treeWithOffsetY = Object.assign({}, getTreeWithOffsetYInHiererchy(treeWithCumulativeWidth, connections), { + const treeWithCumulativeHeight = getTreeWithCumulativeHeight(node, vertices, connections); + const treeWithIndividualWidth = getTreeWithIndividualWidth(treeWithCumulativeHeight, vertices); + //const treeWithCumulativeWidth = getTreeWithCumulativeWidth(treeWithIndividualWidth); + const treeWithOffsetY = Object.assign({}, getTreeWithOffsetYInHiererchy(treeWithIndividualWidth, connections), { _offsetY: 0 }); + const treeWithEffectiveOffsetX = getTreeWithEffectiveOffsetX(treeWithOffsetY, 0); + const treeWithEffectiveOffsetY = getTreeWithEffectiveOffsetY(treeWithEffectiveOffsetX, 0); - return treeWithOffsetY; + return treeWithEffectiveOffsetY; } function doGetWidthOfNodes(children = []) { @@ -203,15 +226,50 @@ function doGetWidthOfNodes(children = []) { return 1 + Math.max(0, ...children.map(cChild => doGetWidthOfNodes(cChild._children))); } -function getTreeWithCumulativeHeight(node, vertices) { +function getTreeWithEffectiveOffsetX(node, positionX) { + const _vertices = node._vertices.map(cVertex => getTreeWithEffectiveOffsetX(cVertex, positionX + node._widthOfSelf)); + + return Object.assign({}, node, { + _X: positionX, + _vertices, + }); +} + +function getTreeWithEffectiveOffsetY(node, positionY) { + const _vertices = node._vertices.map(cVertex => getTreeWithEffectiveOffsetY(cVertex, positionY + cVertex._offsetY)); + + return Object.assign({}, node, { + _Y: positionY, + _vertices, + }); +} + +function doGetHeightOfNodes(children) { + if(children.length > 0) { + return children.reduce((height, cChild) => height + doGetHeightOfNodes(cChild._children), 0); + } + return 1; +} + +function getTreeWithCumulativeHeight(node, vertices, connections) { const vertexKey = node._vertex; const vertex = vertices.find(cVertex => cVertex._vertex === vertexKey); + // if does not overlap > add 1 + const vertexNext = node._vertices[0] && vertices.find(cVertex => cVertex._vertex === node._vertices[0]._vertex); + const source = vertexNext && getLastOperatorOf(vertexNext); + const target = getFirstOperatorOf(vertex); + const isFirstConnectedToLast = connections.some(cConnection => source && target && cConnection._source._uuid === source._uuid && cConnection._target._uuid === target._uuid); + + let _height = doGetHeightOfNodes(vertex._children); let _vertices = []; if(Array.isArray(node._vertices)){ - _vertices = node._vertices.map(cVertex => getTreeWithCumulativeHeight(cVertex, vertices)); - _height = Math.max(_height, _vertices.reduce((height, cVertex) => height + cVertex._height, 1)); + _vertices = node._vertices.map(cVertex => getTreeWithCumulativeHeight(cVertex, vertices, connections)); + _height = Math.max(_height, _vertices.reduce((height, cVertex) => height + cVertex._height, 0)); + } + if(source && !isFirstConnectedToLast) { + _height = _height + 1; } return Object.assign({}, node, vertex, { _height, @@ -288,20 +346,7 @@ function getEdges(plan, vertices) { } }, []); - const edgesWithFixedUnions = - edges - .map(cEdge => { - if(cEdge.type === 'CONTAINS') { - return Object.assign({}, cEdge, { - _source: cEdge._target, - _target: cEdge._source, - }); - } else { - return cEdge; - } - }); - - return edgesWithFixedUnions; + return edges; } function doCloneAndOmit(obj, keys) {
