Package org.apache.hadoop.hive.ql.exec

Source Code of org.apache.hadoop.hive.ql.exec.ExplainTask$MethodComparator

/**
* 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.exec;

import java.io.OutputStream;
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.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.ql.Context;
import org.apache.hadoop.hive.ql.DriverContext;
import org.apache.hadoop.hive.ql.plan.Explain;
import org.apache.hadoop.hive.ql.plan.ExplainWork;
import org.apache.hadoop.hive.ql.plan.api.StageType;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;

/**
* ExplainTask implementation.
*
**/
public class ExplainTask extends Task<ExplainWork> implements Serializable {
  private static final long serialVersionUID = 1L;

  public ExplainTask() {
    super();
  }

  static public JSONObject getJSONPlan(PrintStream out, ExplainWork work)
      throws Exception {
    // If the user asked for a formatted output, dump the json output
    // in the output stream
    JSONObject outJSONObject = new JSONObject();
    boolean jsonOutput = work.isFormatted();
    if (jsonOutput) {
      out = null;
    }

    // Print out the parse AST
    if (work.getAstStringTree() != null) {
      String jsonAST = outputAST(work.getAstStringTree(), out, jsonOutput, 0);
      if (out != null) {
        out.println();
      }

      if (jsonOutput) {
        outJSONObject.put("ABSTRACT SYNTAX TREE", jsonAST);
      }
    }

    JSONObject jsonDependencies = outputDependencies(out, jsonOutput,
        work.getRootTasks(), 0);

    if (out != null) {
      out.println();
    }

    if (jsonOutput) {
      outJSONObject.put("STAGE DEPENDENCIES", jsonDependencies);
    }

    // Go over all the tasks and dump out the plans
    JSONObject jsonPlan = outputStagePlans(out, work, work.getRootTasks(), 0);

    if (jsonOutput) {
      outJSONObject.put("STAGE PLANS", jsonPlan);
    }

    return jsonOutput ? outJSONObject : null;
  }

  @Override
  public int execute(DriverContext driverContext) {

    PrintStream out = null;
    try {
      Path resFile = new Path(work.getResFile());
      OutputStream outS = resFile.getFileSystem(conf).create(resFile);
      out = new PrintStream(outS);

      JSONObject jsonPlan = getJSONPlan(out, work);

      if (work.isFormatted()) {
        out.print(jsonPlan);
      }

      out.close();
      out = null;
      return (0);
    }
    catch (Exception e) {
      console.printError("Failed with exception " + e.getMessage(),
          "\n" + StringUtils.stringifyException(e));
      return (1);
    }
    finally {
      IOUtils.closeStream(out);
    }
  }

  private static String indentString(int indent) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < indent; ++i) {
      sb.append(" ");
    }

    return sb.toString();
  }

  private static JSONObject outputMap(Map<?, ?> mp, String header, PrintStream out,
      boolean extended, boolean jsonOutput, int indent) throws Exception {

    boolean first_el = true;
    TreeMap<Object, Object> tree = new TreeMap<Object, Object>();
    tree.putAll(mp);
    JSONObject json = jsonOutput ? new JSONObject() : null;
    for (Entry<?, ?> ent : tree.entrySet()) {
      if (first_el && (out != null)) {
        out.println(header);
      }
      first_el = false;

      // Print the key
      if (out != null) {
        out.print(indentString(indent));
        out.printf("%s ", ent.getKey().toString());
      }

      // Print the value
      if (isPrintable(ent.getValue())) {
        if (out != null) {
          out.print(ent.getValue());
          out.println();
        }
        if (jsonOutput) {
          json.put(ent.getKey().toString(), ent.getValue().toString());
        }
      }
      else if (ent.getValue() instanceof List || ent.getValue() instanceof Map) {
        if (out != null) {
          out.print(ent.getValue().toString());
          out.println();
        }
        if (jsonOutput) {
          json.put(ent.getKey().toString(), ent.getValue().toString());
        }
      }
      else if (ent.getValue() instanceof Serializable) {
        if (out != null) {
          out.println();
        }
        JSONObject jsonOut = outputPlan((Serializable) ent.getValue(), out,
            extended, jsonOutput, jsonOutput ? 0 : indent + 2);
        if (jsonOutput) {
          json.put(ent.getKey().toString(), jsonOut);
        }
      }
      else {
        if (out != null) {
          out.println();
        }
      }
    }

    return jsonOutput ? json : null;
  }

  private static String outputList(List<?> l, String header, PrintStream out,
      boolean extended, boolean jsonOutput, int indent) throws Exception {

    boolean first_el = true;
    boolean nl = false;
    StringBuffer s = new StringBuffer();
    for (Object o : l) {
      if (first_el && (out != null)) {
        out.print(header);
      }

      if (isPrintable(o)) {
        String delim = first_el ? " " : ", ";
        if (out != null) {
          out.print(delim);
          out.print(o);
        }

        if (jsonOutput) {
          s.append(delim);
          s.append(o);
        }
        nl = true;
      }
      else if (o instanceof Serializable) {
        if (first_el && (out != null)) {
          out.println();
        }
        JSONObject jsonOut = outputPlan((Serializable) o, out, extended,
            jsonOutput, jsonOutput ? 0 : indent + 2);
        if (jsonOutput) {
          if (!first_el) {
            s.append(", ");
          }
          s.append(jsonOut);
        }
      }

      first_el = false;
    }

    if (nl && (out != null)) {
      out.println();
    }
    return jsonOutput ? s.toString() : null;
  }

  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 JSONObject outputPlan(Serializable work, PrintStream out,
      boolean extended, boolean jsonOutput, int indent) throws Exception {
    // Check if work has an explain annotation
    Annotation note = work.getClass().getAnnotation(Explain.class);

    String keyJSONObject = null;

    if (note instanceof Explain) {
      Explain xpl_note = (Explain) note;
      if (extended || xpl_note.normalExplain()) {
        keyJSONObject = xpl_note.displayName();
        if (out != null) {
          out.print(indentString(indent));
          out.println(xpl_note.displayName());
        }
      }
    }

    JSONObject json = jsonOutput ? new JSONObject() : null;
    // If this is an operator then we need to call the plan generation on the
    // conf and then the children
    if (work instanceof Operator) {
      Operator<? extends Serializable> operator = (Operator<? extends Serializable>) work;
      if (operator.getConf() != null) {
        JSONObject jsonOut = outputPlan(operator.getConf(), out, extended,
            jsonOutput, jsonOutput ? 0 : indent);
        if (jsonOutput) {
          json.put(operator.getOperatorId(), jsonOut);
        }
      }

      if (operator.getChildOperators() != null) {
        for (Operator<? extends Serializable> op : operator.getChildOperators()) {
          JSONObject jsonOut = outputPlan(op, out, extended, jsonOutput, jsonOutput ? 0 : indent + 2);
          if (jsonOutput) {
            json.put(operator.getOperatorId(), jsonOut);
          }
        }
      }

      if (jsonOutput) {
        if (keyJSONObject != null) {
          JSONObject ret = new JSONObject();
          ret.put(keyJSONObject, json);
          return ret;
        }

        return json;
      }
      return null;
    }

    // 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 = jsonOutput ? 0 : 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)) {
            if (out != null) {
              out.printf("%s ", header);
              out.println(val);
            }
            if (jsonOutput) {
              json.put(header, val.toString());
            }
            continue;
          }
          // Try this as a map
          try {
            // Go through the map and print out the stuff
            Map<?, ?> mp = (Map<?, ?>) val;
            JSONObject jsonOut = outputMap(mp, header, out, extended, jsonOutput,
                jsonOutput ? 0 : prop_indents + 2);
            if (jsonOutput) {
              json.put(header, jsonOut);
            }
            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;
            String jsonOut = outputList(l, header, out, extended, jsonOutput,
                jsonOutput ? 0 : prop_indents + 2);
            if (jsonOutput) {
              json.put(header, jsonOut);
            }
            continue;
          }
          catch (ClassCastException ce) {
            // Ignore
          }

          // Finally check if it is serializable
          try {
            Serializable s = (Serializable) val;
            if (out != null) {
              out.println(header);
            }
            JSONObject jsonOut = outputPlan(s, out, extended, jsonOutput,
                jsonOutput ? 0 : prop_indents + 2);
            if (jsonOutput) {
              json.put(header, jsonOut);
            }
            continue;
          }
          catch (ClassCastException ce) {
            // Ignore
          }
        }
      }
    }

    if (jsonOutput) {
      if (keyJSONObject != null) {
        JSONObject ret = new JSONObject();
        ret.put(keyJSONObject, json);
        return ret;
      }

      return json;
    }

    return null;
  }

  private static JSONObject outputPlan(Task<? extends Serializable> task,
      PrintStream out, JSONObject parentJSON, boolean extended,
      boolean jsonOutput, HashSet<Task<? extends Serializable>> displayedSet,
      int indent) throws Exception {

    if (displayedSet.contains(task)) {
      return null;
    }
    displayedSet.add(task);

    if (out != null) {
      out.print(indentString(indent));
      out.printf("Stage: %s\n", task.getId());
    }

    // Start by getting the work part of the task and call the output plan for
    // the work
    JSONObject jsonOutputPlan = outputPlan(task.getWork(), out, extended,
        jsonOutput, jsonOutput ? 0 : indent + 2);

    if (out != null) {
      out.println();
    }

    if (jsonOutput) {
      parentJSON.put(task.getId(), jsonOutputPlan);
    }

    if (task instanceof ConditionalTask
        && ((ConditionalTask) task).getListTasks() != null) {
      for (Task<? extends Serializable> con : ((ConditionalTask) task).getListTasks()) {
        outputPlan(con, out, parentJSON, extended, jsonOutput, displayedSet,
            jsonOutput ? 0 : indent);
      }
    }
    if (task.getChildTasks() != null) {
      for (Task<? extends Serializable> child : task.getChildTasks()) {
        outputPlan(child, out, parentJSON, extended, jsonOutput, displayedSet,
            jsonOutput ? 0 : indent);
      }
    }
    return null;
  }

  private static JSONObject outputDependencies(Task<? extends Serializable> task,
      Set<Task<? extends Serializable>> dependeciesTaskSet, PrintStream out,
      JSONObject parentJson, boolean jsonOutput, int indent,
      boolean rootTskCandidate) throws Exception {

    if (dependeciesTaskSet.contains(task)) {
      return null;
    }
    dependeciesTaskSet.add(task);
    boolean first = true;
    JSONObject json = jsonOutput ? new JSONObject() : null;
    if (out != null) {
      out.print(indentString(indent));
      out.printf("%s", task.getId());
    }

    if ((task.getParentTasks() == null || task.getParentTasks().isEmpty())) {
      if (rootTskCandidate) {
        if (out != null) {
          out.print(" is a root stage");
        }

        if (jsonOutput) {
          json.put("ROOT STAGE", "TRUE");
        }
      }
    }
    else {
      StringBuffer s = new StringBuffer();
      first = true;
      for (Task<? extends Serializable> parent : task.getParentTasks()) {
        if (!first) {
          s.append(", ");
        }
        first = false;
        s.append(parent.getId());
      }

      if (out != null) {
        out.print(" depends on stages: ");
        out.print(s.toString());
      }
      if (jsonOutput) {
        json.put("DEPENDENT STAGES", s.toString());
      }
    }

    Task<? extends Serializable> currBackupTask = task.getBackupTask();
    if (currBackupTask != null) {
      if (out != null) {
        out.print(" has a backup stage: ");
        out.print(currBackupTask.getId());
      }
      if (jsonOutput) {
        json.put("BACKUP STAGE", currBackupTask.getId());
      }
    }

    if (task instanceof ConditionalTask
        && ((ConditionalTask) task).getListTasks() != null) {
      StringBuffer s = new StringBuffer();
      first = true;
      for (Task<? extends Serializable> con : ((ConditionalTask) task).getListTasks()) {
        if (!first) {
          s.append(", ");
        }
        first = false;
        s.append(con.getId());
      }

      if (out != null) {
        out.print(" , consists of ");
        out.print(s.toString());
      }
      if (jsonOutput) {
        json.put("CONDITIONAL CHILD TASKS", s.toString());
      }
    }

    if (out != null) {
      out.println();
    }

    if (task instanceof ConditionalTask
        && ((ConditionalTask) task).getListTasks() != null) {
      for (Task<? extends Serializable> con : ((ConditionalTask) task).getListTasks()) {
        JSONObject jsonOut = outputDependencies(con, dependeciesTaskSet, out,
            parentJson, jsonOutput, jsonOutput ? 0 : indent, false);
        if (jsonOutput && (jsonOut != null)) {
          parentJson.put(con.getId(), jsonOut);
        }
      }
    }

    if (task.getChildTasks() != null) {
      for (Task<? extends Serializable> child : task.getChildTasks()) {
        JSONObject jsonOut = outputDependencies(child, dependeciesTaskSet, out,
            parentJson, jsonOutput, jsonOutput ? 0 : indent, true);
        if (jsonOutput && (jsonOut != null)) {
          parentJson.put(child.getId(), jsonOut);
        }
      }
    }
    return jsonOutput ? json : null;
  }

  public static String outputAST(String treeString, PrintStream out,
      boolean jsonOutput, int indent) throws JSONException {
    if (out != null) {
      out.print(indentString(indent));
      out.println("ABSTRACT SYNTAX TREE:");
      out.print(indentString(indent + 2));
      out.println(treeString);
    }

    return jsonOutput ? treeString : null;
  }

  public static JSONObject outputDependencies(PrintStream out, boolean jsonOutput,
      List<Task<? extends Serializable>> rootTasks, int indent)
      throws Exception {
    if (out != null) {
      out.print(indentString(indent));
      out.println("STAGE DEPENDENCIES:");
    }

    JSONObject json = jsonOutput ? new JSONObject() : null;
    Set<Task<? extends Serializable>> dependenciesTaskSet =
      new HashSet<Task<? extends Serializable>>();

    for (Task<? extends Serializable> rootTask : rootTasks) {
      JSONObject jsonOut = outputDependencies(rootTask,
          dependenciesTaskSet, out, json, jsonOutput,
          jsonOutput ? 0 : indent + 2, true);
      if (jsonOutput && (jsonOut != null)) {
        json.put(rootTask.getId(), jsonOut);
      }
    }

    return jsonOutput ? json : null;
  }

  public static JSONObject outputStagePlans(PrintStream out, ExplainWork work,
      List<Task<? extends Serializable>> rootTasks, int indent)
      throws Exception {
    boolean jsonOutput = work.isFormatted();
    if (out != null) {
      out.print(indentString(indent));
      out.println("STAGE PLANS:");
    }

    JSONObject json = jsonOutput ? new JSONObject() : null;
    HashSet<Task<? extends Serializable>> displayedSet = new HashSet<Task<? extends Serializable>>();
    for (Task<? extends Serializable> rootTask : rootTasks) {
      outputPlan(rootTask, out, json, work.getExtended(), jsonOutput,
          displayedSet, jsonOutput ? 0 : indent + 2);
    }
    return jsonOutput ? json : null;
  }

  /**
   * MethodComparator.
   *
   */
  public static class MethodComparator implements Comparator {
    public int compare(Object o1, Object o2) {
      Method m1 = (Method) o1;
      Method m2 = (Method) o2;
      return m1.getName().compareTo(m2.getName());
    }
  }

  @Override
  public StageType getType() {
    return StageType.EXPLAIN;
  }

  @Override
  public String getName() {
    return "EXPLAIN";
  }

  @Override
  protected void localizeMRTmpFilesImpl(Context ctx) {
    // explain task has nothing to localize
    // we don't expect to enter this code path at all
    throw new RuntimeException("Unexpected call");
  }

}
TOP

Related Classes of org.apache.hadoop.hive.ql.exec.ExplainTask$MethodComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.