hive源码(一)入口类CliDriver

源码下载地址:https://mirrors.tuna.tsinghua.edu.cn/apache/hive/hive-3.1.3/apache-hive-3.1.3-src.tar.gz

一:org.apache.hadoop.hive.cli.CliDriver 类流程

CliDriver 是hive命令行接受输入参数的入口类,我们可以从这深入理解hive

部分方法实体较长、可以直接搜素《《很重要》》 关键字,直接看重要代码

main方法
    //new 一个本类的实例,调用run方法
    //返回一个返回码  这个返回码后面代码中出现多次的
    int ret = new CliDriver().run(args);
    System.exit(ret);
run方法
    //不重要  解析设置的hive参数、hive变量(hivevar、define、hiveconf )
    OptionsProcessor oproc = new OptionsProcessor();
    if (!oproc.process_stage1(args)) {
      return 1;
    }

    //不重要   初始化日志    标准输入输出流
    boolean logInitFailed = false;
    String logInitDetailMessage;
    try {
      logInitDetailMessage = LogUtils.initHiveLog4j();
    } catch (LogInitializationException e) {
      logInitFailed = true;
      logInitDetailMessage = e.getMessage();
    }
    CliSessionState ss = new CliSessionState(new HiveConf(SessionState.class));
    ss.in = System.in;
    try {
      ss.out = new PrintStream(System.out, true"UTF-8");
      ss.info = new PrintStream(System.err, true"UTF-8");
      ss.err = new CachingPrintStream(System.err, true"UTF-8");
    } catch (UnsupportedEncodingException e) {
      return 3;
    }
    //不重要   hive特殊参数处理(-S静默模式 -database -e -f -i等参数 )
    if (!oproc.process_stage2(ss)) {
      return 2;
    }
    //不重要  是否设置静默模式
    if (!ss.getIsSilent()) {
      if (logInitFailed) {
        System.err.println(logInitDetailMessage);
      } else {
        SessionState.getConsole().printInfo(logInitDetailMessage);
      }
    }
    //不重要  设置变量
    HiveConf conf = ss.getConf();
    for (Map.Entry<ObjectObject> item : ss.cmdProperties.entrySet()) {
      conf.set((String) item.getKey(), (String) item.getValue());
      ss.getOverriddenConfigurations().put((String) item.getKey(), (String) item.getValue());
    }
    //不重要  启动客户端交互模式前面打印的那个字符串
    prompt = conf.getVar(HiveConf.ConfVars.CLIPROMPT);
    prompt = new VariableSubstitution(new HiveVariableSource() {
      @Override
      public Map<StringString> getHiveVariable() {
        return SessionState.get().getHiveVariables();
      }
    }).substitute(conf, prompt);
    prompt2 = spacesForString(prompt);
    // tez模式  这次会按照mapreduce模式取读源码  这个先掠过
    if (HiveConf.getBoolVar(conf, ConfVars.HIVE_CLI_TEZ_SESSION_ASYNC)) {
      SessionState.beginStart(ss, console);
    } else {
      SessionState.start(ss);
    }
    ss.updateThreadName();

    // 不重要  注册视图
    HiveMaterializedViewsRegistry.get().init();

    try {
    // 很重要  真正执行逻辑,开启交互窗口,接受输入返回结果
      return executeDriver(ss, conf, oproc);
    } finally {
      ss.resetThreadName();
      ss.close();
    }
executeDriver方法
    // 不重要  变量之间倒腾
    CliDriver cli = new CliDriver();
    cli.setHiveVariables(oproc.getHiveVariables());

    //  不重要  如果启动hive设置了数据库,首先在前面执行一条:use databases;
    cli.processSelectDatabase(ss);

    // 不重要  如果启动hive设置了-i,初始化文件,先执行文件内容
    cli.processInitFiles(ss);
    // 不重要 hive -e "" 模式运行代码
    if (ss.execString != null) {
      int cmdProcessStatus = cli.processLine(ss.execString);
      return cmdProcessStatus;//main函数中的返回值
    }

    try {
      if (ss.fileName != null) {
        // 不重要 hive -f "" 模式运行代码
        return cli.processFile(ss.fileName);
      }
    } catch (FileNotFoundException e) {
      System.err.println("Could not open input file for reading. (" + e.getMessage() + ")");
      return 3;
    }
    // 不重要 如果启动是mr模式,打印告警信息
    if ("mr".equals(HiveConf.getVar(conf, ConfVars.HIVE_EXECUTION_ENGINE))) {
      console.printInfo(HiveConf.generateMrDeprecationWarning());
    }
    // 直接hive 回车等待输入sql模式
    setupConsoleReader();

    String line;
    int ret = 0;
    String prefix = "";
    String curDB = getFormattedDb(conf, ss);
    String curPrompt = prompt + curDB;
    String dbSpaces = spacesForString(curDB);
    // 回车一下再前面打印一个">"
    while ((line = reader.readLine(curPrompt + "> ")) != null) {
      if (!prefix.equals("")) {
        prefix += '\n';
      }
      // 注释SQL就跳过当前行
      if (line.trim().startsWith("--")) {
        continue;
      }
      // 读取到结尾是";" 就处理当前行SQL
      if (line.trim().endsWith(";") && !line.trim().endsWith("\\;")) {
        line = prefix + line;
        // 很重要  开始处理输入SQL
        ret = cli.processLine(line, true);
        prefix = "";
        curDB = getFormattedDb(conf, ss);
        curPrompt = prompt + curDB;
        dbSpaces = dbSpaces.length() == curDB.length() ? dbSpaces : spacesForString(curDB);
      } else {
        prefix = prefix + line;
        curPrompt = prompt2 + dbSpaces;
        continue;
      }
    }
processLine方法
    SignalHandler oldSignal = null;
    Signal interruptSignal = null;
    // 不重要  Ctrl+C 杀掉当前交互窗口
    if (allowInterrupting) {
      interruptSignal = new Signal("INT");
      oldSignal = Signal.handle(interruptSignal, new SignalHandler() {
        private boolean interruptRequested;
        @Override
        public void handle(Signal signal) {
          boolean initialRequest = !interruptRequested;
          interruptRequested = true;
          if (!initialRequest) {
            console.printInfo("Exiting the JVM");
            System.exit(127);
          }//连续 Ctrl+C 的时候,后台还在跑sql 会打印的语句。可以试试
          console.printInfo("Interrupting... Be patient, this might take some time.");
          console.printInfo("Press Ctrl+C again to kill JVM");
          HadoopJobExecHelper.killRunningJobs();
          TezJobExecHelper.killRunningJobs();
          HiveInterruptUtils.interrupt();
        }
      });
    }

    try {
      int lastRet = 0, ret = 0;
      //不重要 split(";")  输入多个sql在一行的处理
      List<String> commands = splitSemiColon(line);

      String command = "";
      for (String oneCmd : commands) {
        if (StringUtils.endsWith(oneCmd, "\\")) {
          command += StringUtils.chop(oneCmd) + ";";
          continue;
        } else {
          command += oneCmd;
        }
        if (StringUtils.isBlank(command)) {
          continue;
        }
        //很重要 处理每一条sql
        ret = processCmd(command);
        command = "";
        lastRet = ret;
        //不重要 异常返回值处理
        boolean ignoreErrors = HiveConf.getBoolVar(conf, HiveConf.ConfVars.CLIIGNOREERRORS);
        if (ret != 0 && !ignoreErrors) {
          return ret;
        }
      }
      return lastRet;
    } finally {
      if (oldSignal != null && interruptSignal != null) {
        Signal.handle(interruptSignal, oldSignal);
      }
    }
processCmd方法
    CliSessionState ss = (CliSessionState) SessionState.get();
    ss.setLastCommand(cmd);

    ss.updateThreadName();

    ss.err.flush();
    String cmd_trimmed = HiveStringUtils.removeComments(cmd).trim();
    String[] tokens = tokenizeCmd(cmd_trimmed);
    int ret = 0;
    //不重要 如果输入的sql 是exit 、或者quit就退出当前命令行
    if (cmd_trimmed.toLowerCase().equals("quit") || cmd_trimmed.toLowerCase().equals("exit")) {
      ss.close();
      System.exit(0);
    //不重要 如果输入的sql是source  就去执行sql文件或者shell文件
    } else if (tokens[0].equalsIgnoreCase("source")) {
      String cmd_1 = getFirstCmd(cmd_trimmed, tokens[0].length());
      cmd_1 = new VariableSubstitution(new HiveVariableSource() {
        @Override
        public Map<StringString> getHiveVariable() {
          return SessionState.get().getHiveVariables();
        }
      }).substitute(ss.getConf(), cmd_1);

      File sourceFile = new File(cmd_1);
      if (! sourceFile.isFile()){
        console.printError("File: "+ cmd_1 + " is not a file.");
        ret = 1;
      } else {
        try {
          ret = processFile(cmd_1);
        } catch (IOException e) {
          console.printError("Failed processing file "+ cmd_1 +" "+ e.getLocalizedMessage(),
            stringifyException(e));
          ret = 1;
        }
      }
    }//不重要 如果输入的sql是!开头 就去执行shell
    else if (cmd_trimmed.startsWith("!")) {
      String shell_cmd = cmd.trim().substring(1);
      shell_cmd = new VariableSubstitution(new HiveVariableSource() {
        @Override
        public Map<StringString> getHiveVariable() {
          return SessionState.get().getHiveVariables();
        }
      }).substitute(ss.getConf(), shell_cmd);

      try {
        ShellCmdExecutor executor = new ShellCmdExecutor(shell_cmd, ss.out, ss.err);
        ret = executor.execute();
        if (ret != 0) {
          console.printError("Command failed with exit code = " + ret);
        }
      } catch (Exception e) {
        console.printError("Exception raised from Shell command " + e.getLocalizedMessage(),
            stringifyException(e));
        ret = 1;
      }
    }  else //不重要 处理单条sql的代码{
      try {

        try (CommandProcessor proc = CommandProcessorFactory.get(tokens, (HiveConf) conf)) {
          if (proc instanceof IDriver) {
//很重要  代码入口
            ret = processLocalCmd(cmd, proc, ss);
          } else {
            ret = processLocalCmd(cmd_trimmed, proc, ss);
          }
        }
      } catch (SQLException e) {
        console.printError("Failed processing command " + tokens[0] + " " + e.getLocalizedMessage(),
          org.apache.hadoop.util.StringUtils.stringifyException(e));
        ret = 1;
      }
      catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    ss.resetThreadName();
    return ret;
processLocalCmd 方法
    //不重要 回车换行
    boolean escapeCRLF = HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_CLI_PRINT_ESCAPE_CRLF);
    int ret = 0;

    if (proc != null) {
      if (proc instanceof IDriver) {
        //不重要 计算sql运行时长变量
        IDriver qp = (IDriver) proc;
        PrintStream out = ss.out;
        long start = System.currentTimeMillis();
        if (ss.getIsVerbose()) {
          out.println(cmd);
        }
        //很重要 运行sql的逻辑入口
        ret = qp.run(cmd).getResponseCode();
        if (ret != 0) {
          qp.close();
          return ret;
        }

        //不重要 计算sql运行时长  打印出来
        long end = System.currentTimeMillis();
        double timeTaken = (end - start) / 1000.0;

        ArrayList<String> res = new ArrayList<String>();

        printHeader(qp, out);//打印头部信息  返回参数里面可以解析出来返回的列名

        //不重要 打印结果
        int counter = 0;
        try {
          if (out instanceof FetchConverter) {
            ((FetchConverter) out).fetchStarted();
          }
          while (qp.getResults(res)) {
            for (String r : res) {
                  if (escapeCRLF) {
                    r = EscapeCRLFHelper.escapeCRLF(r);//不重要 转移回车换行
                  }
              out.println(r);
            }
            counter += res.size();
            res.clear();
            if (out.checkError()) {
              break;
            }
          }
        } catch (IOException e) {
          //不重要 sql执行错误  打印错误信息
          console.printError("Failed with exception " + e.getClass().getName() + ":" + e.getMessage(),
              "\n" + org.apache.hadoop.util.StringUtils.stringifyException(e));
          ret = 1;
        }

        qp.close();

        if (out instanceof FetchConverter) {
          ((FetchConverter) out).fetchFinished();
        }
        // 不重要 sql运行完成后,打印的本地运行花费的时间
        console.printInfo(
            "Time taken: " + timeTaken + " seconds" + (counter == 0 ? "" : ", Fetched: " + counter + " row(s)"));
      } else {
        String firstToken = tokenizeCmd(cmd.trim())[0];
        String cmd_1 = getFirstCmd(cmd.trim(), firstToken.length());

        if (ss.getIsVerbose()) {
          ss.out.println(firstToken + " " + cmd_1);
        }
        CommandProcessorResponse res = proc.run(cmd_1);
        if (res.getResponseCode() != 0) {
          ss.out
              .println("Query returned non-zero code: " + res.getResponseCode() + ", cause: " + res.getErrorMessage());
        }
        if (res.getConsoleMessages() != null) {
          for (String consoleMsg : res.getConsoleMessages()) {
            console.printInfo(consoleMsg);
          }
        }
        ret = res.getResponseCode();
      }
    }
    return ret;
posted @ 2022-06-30 15:05  Kotlin  阅读(650)  评论(0编辑  收藏  举报
Live2D