shark.execution.ExplainTaskHelper Maven / Gradle / Ivy
The newest version!
/**
* 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 shark.execution;
import java.io.PrintStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.apache.hadoop.hive.ql.exec.ExplainTask.MethodComparator;
import org.apache.hadoop.hive.ql.plan.Explain;
/**
* A helper method for explaining Shark query plan. Based on
* org.apache.hadoop.hive.ql.exec.ExplainTask. The main difference is we
* recursively output parent operators rather than child operators.
*
* @author rxin
*/
public class ExplainTaskHelper {
@SuppressWarnings("unchecked")
public static void outputPlan(Serializable work, PrintStream out, boolean extended,
int indent) throws Exception {
// Check if work has an explain annotation
Annotation note = work.getClass().getAnnotation(Explain.class);
if (note instanceof Explain) {
Explain xpl_note = (Explain) note;
if (extended || xpl_note.normalExplain()) {
out.print(indentString(indent));
out.println(xpl_note.displayName());
}
}
// If this is an operator then we need to call the plan generation on the
// conf and then
// the children
if (work instanceof shark.execution.Operator) {
shark.execution.Operator operator =
(shark.execution.Operator) work;
out.println(indentString(indent) + "**" + operator.getClass().getName());
if (operator.desc() != null) {
outputPlan(operator.desc(), out, extended, indent);
}
if (operator.parentOperators() != null) {
for (shark.execution.Operator op : operator.parentOperatorsAsJavaList()) {
outputPlan(op, out, extended, indent + 2);
}
}
return;
}
if (work instanceof org.apache.hadoop.hive.ql.exec.Operator) {
org.apache.hadoop.hive.ql.exec.Operator operator =
(org.apache.hadoop.hive.ql.exec.Operator) work;
if (operator.getConf() != null) {
outputPlan(operator.getConf(), out, extended, indent);
}
if (operator.getChildOperators() != null) {
for (org.apache.hadoop.hive.ql.exec.Operator op
: operator.getChildOperators()) {
outputPlan(op, out, extended, indent + 2);
}
}
return;
}
outputWork(work, out, extended, indent);
}
public static void outputWork(Serializable work, PrintStream out, boolean extended,
int indent) throws Exception {
// Check if work has an explain annotation
Annotation note = work.getClass().getAnnotation(Explain.class);
// We look at all methods that generate values for explain
Method[] methods = work.getClass().getMethods();
Arrays.sort(methods, new MethodComparator());
for (Method m : methods) {
int prop_indents = indent + 2;
note = m.getAnnotation(Explain.class);
if (note instanceof Explain) {
Explain xpl_note = (Explain) note;
if (extended || xpl_note.normalExplain()) {
Object val = m.invoke(work);
if (val == null) {
continue;
}
String header = null;
if (!xpl_note.displayName().equals("")) {
header = indentString(prop_indents) + xpl_note.displayName() + ":";
} else {
prop_indents = indent;
header = indentString(prop_indents);
}
if (isPrintable(val)) {
out.printf("%s ", header);
out.println(val);
continue;
}
// Try this as a map
try {
// Go through the map and print out the stuff
Map mp = (Map) val;
outputMap(mp, header, out, extended, prop_indents + 2);
continue;
} catch (ClassCastException ce) {
// Ignore - all this means is that this is not a map
}
// Try this as a list
try {
List l = (List) val;
outputList(l, header, out, extended, prop_indents + 2);
continue;
} catch (ClassCastException ce) {
// Ignore
}
// Finally check if it is serializable
try {
Serializable s = (Serializable) val;
out.println(header);
outputPlan(s, out, extended, prop_indents + 2);
continue;
} catch (ClassCastException ce) {
// Ignore
}
}
}
}
}
private static boolean isPrintable(Object val) {
if (val instanceof Boolean || val instanceof String
|| val instanceof Integer || val instanceof Byte
|| val instanceof Float || val instanceof Double) {
return true;
}
if (val != null && val.getClass().isPrimitive()) {
return true;
}
return false;
}
private static void outputMap(Map mp, String header, PrintStream out,
boolean extended, int indent) throws Exception {
boolean first_el = true;
TreeMap