1. 根据前言可以看出,第一步是cli向Driver提交作业,因此我们需要找到代码中的CliDriver类,并搜索出里面的main方法,一切从main开始,如图所示
  2. 可以看到main方法中创建了一个CliDriver对象,然后调用了他的run方法
public static void main(String[] args) throws Exception {
    int ret = new CliDriver().run(args);
    System.exit(ret);
  }
  1. 我们先查看一下CliDriver对象里面包含哪些内容
public CliDriver() {
    // 创建一个SessionState,SessionState内部保存大量配置信息
    // SessionState在hive中大量使用,是很重要的
    SessionState ss = SessionState.get();
    conf = (ss != null) ? ss.getConf() : new Configuration();
    // 获取CliDriver的log
    Logger LOG = LoggerFactory.getLogger("CliDriver");
    // 是否启动debug,如果启动的话会实时打印一些信息
    if (LOG.isDebugEnabled()) {
      LOG.debug("CliDriver inited with classpath {}", System.getProperty("java.class.path"));
    }
    // 一个管理日志的类
    console = new LogHelper(LOG);
  }
  1. 在SessionState对象中封装了一个会话的关联的数据,包括配置信息HiveConf,输入输出流,指令类型,用户名称、IP地址等等。
  2. 回到main方法中,点击进入run方法
    5.1 首先在process_stage1中解析用户命令行中的一些基本信息(hiveconf、hive.root.logger、define、hivevar)
    5.2 定义标准化输入输出和错误输出流
    5.3 在process_stage2中解析命令行中包含的执行方式(-s、-e、-f、-v)
    5.4 在executeDriver中执行cli驱动程序工作
public  int run(String[] args) throws Exception {
    // 1.对命令进行初步的解析,提取-e -h hiveconf hivevar等参数信息,设置用户提供的系统和Hive环境变量。
    OptionsProcessor oproc = new OptionsProcessor();
    //process_stage1解析系统参数(hiveconf、hive.root.logger、define、hivevar)
    if (!oproc.process_stage1(args)) {
      return 1;
    }

    // NOTE: It is critical to do this here so that log4j is reinitialized
    // before any of the other core hive classes are loaded
    // 2.初始化Log4j日志组件
    boolean logInitFailed = false;
    String logInitDetailMessage;
    try {
      logInitDetailMessage = LogUtils.initHiveLog4j();
    } catch (LogInitializationException e) {
      logInitFailed = true;
      logInitDetailMessage = e.getMessage();
    }
    // 3.使用HiveConf实例化CliSessionState,CliSessionState继承了SessionState类
    //   比如:fileName,cmdProperties,在实例化的过程中,主要是用来记录HiveConf。
    CliSessionState ss = new CliSessionState(new HiveConf(SessionState.class));
    ss.in = System.in;
    try {//定义标准输入输出和错误输出流信息,后续需要输入HQL以及打印控制台信息
      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;
    }
    // 4.根据stage1解析的参数内容,填充CliSessionState的字符串
    //   比如用户输入了-e 则这个stage就把-e 对应的字符串赋值给CliSessionState的 execString成员。
    //   -S 表示 沉默状态
    //   -e 获取执行sql
    //   -f 获取要执行的sql文件
    //   -v 是否详细显示
    //   其他, 处理hiveconf 和 i 等参数
    if (!oproc.process_stage2(ss)) {
      return 2;
    }
    // 5.在允许打印的模式下,初始化日志失败时打印对应的错误信息
    if (!ss.getIsSilent()) {
      if (logInitFailed) {
        System.err.println(logInitDetailMessage);
      } else {
        SessionState.getConsole().printInfo(logInitDetailMessage);
      }
    }

    // 6.将用户命令行输入的配置信息和变量等覆盖HiveConf的默认值
    HiveConf conf = ss.getConf();
    for (Map.Entry<Object, Object> item : ss.cmdProperties.entrySet()) {
      conf.set((String) item.getKey(), (String) item.getValue());
      ss.getOverriddenConfigurations().put((String) item.getKey(), (String) item.getValue());
    }

    // 7.读取配置提示和替换变量
    prompt = conf.getVar(HiveConf.ConfVars.CLIPROMPT);//命令行提示符配置值
    prompt = new VariableSubstitution(new HiveVariableSource() {
      @Override
      public Map<String, String> getHiveVariable() {
        return SessionState.get().getHiveVariables();
      }
    }).substitute(conf, prompt);
    prompt2 = spacesForString(prompt);

    if (HiveConf.getBoolVar(conf, ConfVars.HIVE_CLI_TEZ_SESSION_ASYNC)) {
      // Start the session in a fire-and-forget manner. When the asynchronously initialized parts of
      // the session are needed, the corresponding getters and other methods will wait as needed.
      // 8.设置会话状态,然后执行CLI程序,即excuteDriver().
      SessionState.beginStart(ss, console);
    } else {
      SessionState.start(ss);
    }

    ss.updateThreadName();

    // Create views registry
    HiveMaterializedViewsRegistry.get().init();

    //执行cli驱动程序工作
    try {
      return executeDriver(ss, conf, oproc);
    } finally {
      ss.resetThreadName();
      ss.close();
    }
  }