You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by gu...@apache.org on 2013/08/06 01:33:45 UTC

svn commit: r1510812 - in /hive/branches/tez/ql/src: java/org/apache/hadoop/hive/ql/plan/TezWork.java test/org/apache/hadoop/hive/ql/plan/TestTezWork.java

Author: gunther
Date: Mon Aug  5 23:33:45 2013
New Revision: 1510812

URL: http://svn.apache.org/r1510812
Log:
HIVE-4916: Add TezWork (Gunther Hagleitner)

Added:
    hive/branches/tez/ql/src/java/org/apache/hadoop/hive/ql/plan/TezWork.java
    hive/branches/tez/ql/src/test/org/apache/hadoop/hive/ql/plan/TestTezWork.java

Added: hive/branches/tez/ql/src/java/org/apache/hadoop/hive/ql/plan/TezWork.java
URL: http://svn.apache.org/viewvc/hive/branches/tez/ql/src/java/org/apache/hadoop/hive/ql/plan/TezWork.java?rev=1510812&view=auto
==============================================================================
--- hive/branches/tez/ql/src/java/org/apache/hadoop/hive/ql/plan/TezWork.java (added)
+++ hive/branches/tez/ql/src/java/org/apache/hadoop/hive/ql/plan/TezWork.java Mon Aug  5 23:33:45 2013
@@ -0,0 +1,189 @@
+/**
+ * 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.
+ */
+
+package org.apache.hadoop.hive.ql.plan;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * TezWork. This class encapsulates all the work objects that can be executed 
+ * in a single tez job. Currently it's basically a tree with MapWork at the 
+ * leaves and and ReduceWork in all other nodes.
+ *
+ */
+@SuppressWarnings("serial")
+@Explain(displayName = "Tez")
+public class TezWork extends AbstractOperatorDesc {
+
+  private static transient final Log LOG = LogFactory.getLog(TezWork.class);
+
+  private final Set<BaseWork> roots = new HashSet<BaseWork>();
+  private final Set<BaseWork> leaves = new HashSet<BaseWork>();
+  private final Map<BaseWork, List<BaseWork>> workGraph = new HashMap<BaseWork, List<BaseWork>>();
+  private final Map<BaseWork, List<BaseWork>> invertedWorkGraph = new HashMap<BaseWork, List<BaseWork>>();
+
+  /**
+   * getAllWork returns a topologically sorted list of BaseWork
+   */
+  @Explain(skipHeader = true, displayName = "Tez Work")
+  public List<BaseWork> getAllWork() {
+
+    List<BaseWork> result = new LinkedList<BaseWork>();
+    Set<BaseWork> seen = new HashSet<BaseWork>();
+    
+    for (BaseWork leaf: leaves) {
+      // make sure all leaves are visited at least once
+      visit(leaf, seen, result);
+    }
+    
+    return result;
+  }
+
+  private void visit(BaseWork child, Set<BaseWork> seen, List<BaseWork> result) {
+
+    if (seen.contains(child)) {
+      // don't visit multiple times
+      return;
+    }
+
+    seen.add(child);
+
+    for (BaseWork parent: getParents(child)) {
+      if (!seen.contains(parent)) {
+        visit(parent, seen, result);
+      }
+    }
+    
+    result.add(child);
+  }
+
+  /**
+   * add creates a new node in the graph without any connections
+   */
+  public void add(BaseWork w) {
+    if (workGraph.containsKey(w)) {
+      return;
+    }
+    workGraph.put(w, new LinkedList<BaseWork>());
+    invertedWorkGraph.put(w, new LinkedList<BaseWork>());
+    roots.add(w);
+    leaves.add(w);
+  }
+
+  /**
+   * connect adds an edge between a and b. Both nodes have 
+   * to be added prior to calling connect.
+   */
+  public void connect(BaseWork a, BaseWork b) {
+    workGraph.get(a).add(b);
+    invertedWorkGraph.get(b).add(a);
+    roots.remove(b);
+    leaves.remove(a);
+  }
+
+  /**
+   * disconnect removes an edge between a and b. Both a and 
+   * b have to be in the graph. If there is no matching edge
+   * no change happens.
+   */
+  public void disconnect(BaseWork a, BaseWork b) {
+    workGraph.get(a).remove(b);
+    invertedWorkGraph.get(b).remove(a);
+    if (getParents(b).isEmpty()) {
+      roots.add(b);
+    }
+    if (getChildren(a).isEmpty()) {
+      leaves.add(a);
+    }
+  }
+
+  /**
+   * getRoots returns all nodes that do not have a parent.
+   */
+  public Set<BaseWork> getRoots() {
+    return new HashSet<BaseWork>(roots);
+  }
+
+  /**
+   * getLeaves returns all nodes that do not have a child
+   */
+  public Set<BaseWork> getLeaves() {
+    return new HashSet<BaseWork>(leaves);
+  }
+
+  /**
+   * getParents returns all the nodes with edges leading into work
+   */
+  public List<BaseWork> getParents(BaseWork work) {
+    assert invertedWorkGraph.containsKey(work) 
+      && invertedWorkGraph.get(work) != null;
+    return new LinkedList<BaseWork>(invertedWorkGraph.get(work));
+  }
+
+  /**
+   * getChildren returns all the nodes with edges leading out of work
+   */
+  public List<BaseWork> getChildren(BaseWork work) {
+    assert workGraph.containsKey(work) 
+      && workGraph.get(work) != null;
+    return new LinkedList<BaseWork>(workGraph.get(work));
+  }
+
+  /**
+   * remove removes a node from the graph and removes all edges with
+   * work as start or end point. No change to the graph if the node
+   * doesn't exist.
+   */
+  public void remove(BaseWork work) {
+
+    if (!workGraph.containsKey(work)) {
+      return;
+    }
+    
+    List<BaseWork> children = getChildren(work);
+    List<BaseWork> parents = getParents(work);
+
+    for (BaseWork w: children) {
+      invertedWorkGraph.get(w).remove(work);
+      if (invertedWorkGraph.get(w).size() == 0) {
+        roots.add(w);
+      }
+    }
+
+    for (BaseWork w: parents) {
+      workGraph.get(w).remove(work);
+      if (workGraph.get(w).size() == 0) {
+        leaves.add(w);
+      }
+    }
+
+    roots.remove(work);
+    leaves.remove(work);
+
+    workGraph.remove(work);
+    invertedWorkGraph.remove(work);
+  }
+}

Added: hive/branches/tez/ql/src/test/org/apache/hadoop/hive/ql/plan/TestTezWork.java
URL: http://svn.apache.org/viewvc/hive/branches/tez/ql/src/test/org/apache/hadoop/hive/ql/plan/TestTezWork.java?rev=1510812&view=auto
==============================================================================
--- hive/branches/tez/ql/src/test/org/apache/hadoop/hive/ql/plan/TestTezWork.java (added)
+++ hive/branches/tez/ql/src/test/org/apache/hadoop/hive/ql/plan/TestTezWork.java Mon Aug  5 23:33:45 2013
@@ -0,0 +1,125 @@
+/**
+ * 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.
+ */
+package org.apache.hadoop.hive.ql.plan;
+
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import java.util.List;
+import java.util.LinkedList;
+
+public class TestTezWork {
+
+  private List<BaseWork> nodes;
+  private TezWork work;
+
+  @Before
+  public void setup() throws Exception {
+    nodes = new LinkedList<BaseWork>();
+    work = new TezWork();
+    addWork(5);
+  }
+
+  private void addWork(int n) {
+    for (int i = 0; i < n; ++i) {
+      BaseWork w = new MapWork();
+      nodes.add(w);
+      work.add(w);
+    }
+  }
+
+  @Test
+  public void testAdd() throws Exception {
+    Assert.assertEquals(work.getAllWork().size(), nodes.size());
+    Assert.assertEquals(work.getRoots().size(), nodes.size());
+    Assert.assertEquals(work.getLeaves().size(), nodes.size());
+    for (BaseWork w: nodes) {
+      Assert.assertEquals(work.getParents(w).size(), 0);
+      Assert.assertEquals(work.getChildren(w).size(), 0);
+    }
+  }
+
+  @Test
+  public void testConnect() throws Exception {
+    BaseWork parent = nodes.get(0);
+    BaseWork child = nodes.get(1);
+    
+    work.connect(parent, child);
+    
+    Assert.assertEquals(work.getParents(child).size(), 1);
+    Assert.assertEquals(work.getChildren(parent).size(), 1);
+    Assert.assertEquals(work.getChildren(parent).get(0), child);
+    Assert.assertEquals(work.getParents(child).get(0), parent);
+    Assert.assertTrue(work.getRoots().contains(parent) && !work.getRoots().contains(child));
+    Assert.assertTrue(!work.getLeaves().contains(parent) && work.getLeaves().contains(child));
+    for (BaseWork w: nodes) {
+      if (w == parent || w == child) {
+        continue;
+      }
+      Assert.assertEquals(work.getParents(w).size(), 0);
+      Assert.assertEquals(work.getChildren(w).size(), 0);
+    }
+  }
+
+  @Test 
+  public void testDisconnect() throws Exception {
+    BaseWork parent = nodes.get(0);
+    BaseWork children[] = {nodes.get(1), nodes.get(2)};
+    
+    work.connect(parent, children[0]);
+    work.connect(parent, children[1]);
+
+    work.disconnect(parent, children[0]);
+
+    Assert.assertTrue(work.getChildren(parent).contains(children[1]));
+    Assert.assertTrue(!work.getChildren(parent).contains(children[0]));
+    Assert.assertTrue(work.getRoots().contains(parent) && work.getRoots().contains(children[0])
+                      && !work.getRoots().contains(children[1]));
+    Assert.assertTrue(!work.getLeaves().contains(parent) && work.getLeaves().contains(children[0])
+                      && work.getLeaves().contains(children[1]));
+  }
+
+  @Test 
+  public void testRemove() throws Exception {
+    BaseWork parent = nodes.get(0);
+    BaseWork children[] = {nodes.get(1), nodes.get(2)};
+    
+    work.connect(parent, children[0]);
+    work.connect(parent, children[1]);
+    
+    work.remove(parent);
+
+    Assert.assertEquals(work.getParents(children[0]).size(), 0);
+    Assert.assertEquals(work.getParents(children[1]).size(), 0);
+    Assert.assertEquals(work.getAllWork().size(), nodes.size()-1);
+    Assert.assertEquals(work.getRoots().size(), nodes.size()-1);
+    Assert.assertEquals(work.getLeaves().size(), nodes.size()-1);
+  }
+
+  @Test
+  public void testGetAllWork() throws Exception {
+    for (int i = 4; i > 0; --i) {
+      work.connect(nodes.get(i), nodes.get(i-1));
+    }
+
+    List<BaseWork> sorted = work.getAllWork();
+    for (int i = 0; i < 5; ++i) {
+      Assert.assertEquals(sorted.get(i), nodes.get(4-i));
+    }
+  }
+}