Hive源码阅读--作业的入口--CliDriver

hive执行流程

在这里插入图片描述
整个流程的第一步,就是cli提交作业给driver,这一步需要通过org.apache.hadoop.hive.cli.CliDriver类。

CliDriver类

首先看CliDriver类的main方法。

org.apache.hadoop.hive.cli.CliDriver
----------
	/**
	 * 输入参数String[] args不需要分析,是外部命令传进来的参数
	 */
    public static void main(String[] args) throws Exception {
    	// run  运行函数
        int ret = (new CliDriver()).run(args);
        // exit 退出函数
        System.exit(ret);
    }

exit是退出函数,对源码注解直译内容为:

终止当前正在运行的java虚拟机。这个参数作为状态码;按惯例,非零状态代码表示异常终止。与return不同,return只是退回到上一层,exit将会退出到最外层。

java.lang.System
----------

    /**
     * Terminates the currently running Java Virtual Machine. The
     * argument serves as a status code; by convention, a nonzero status
     * code indicates abnormal termination.
     * <p>
     * This method calls the <code>exit</code> method in class
     * <code>Runtime</code>. This method never returns normally.
     * <p>
     * The call <code>System.exit(n)</code> is effectively equivalent to
     * the call:
     * <blockquote><pre>
     * Runtime.getRuntime().exit(n)
     * </pre></blockquote>
     *
     * @param      status   exit status.
     * @throws  SecurityException
     *        if a security manager exists and its <code>checkExit</code>
     *        method doesn't allow exit with the specified status.
     * @see        java.lang.Runtime#exit(int)
     */
    public static void exit(int status) {
        Runtime.getRuntime().exit(status);
    }

run函数表示作业开始正式提交,最主要的是他建立新的CliDriver对象,并调用run函数。
所以我们先看CliDriver的创建过程,再看run函数。

org.apache.hadoop.hive.cli.CliDriver
----------
	/**
	 * CliDriver构造函数
	 */
    public CliDriver() {
    	// 创建一个SessionState,SessionState内部保存大量配置信息
    	// SessionState在hive中大量使用,是很重要的
        SessionState ss = SessionState.get();
        // 三目表达式,就是将ss内部的配置信息给conf 
        this.conf = (Configuration)(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"));
        }
		// 一个管理日志的类
        this.console = new LogHelper(LOG);
    }

在看run方法前先来看看SessionStateget函数。SessionState封装了一个会话的关联的数据,包括配置信息HiveConf,输入输出流,指令类型,用户名称、IP地址等等。
SessionState 是一个与线程关联的静态本地变量ThreadLocal,任何一个线程都对应一个SessionState

org.apache.hadoop.hive.ql.session.SessionState 
----------
  /**
   * 获取当前会话,返回了一个对象tss的调用
   * SessionState中有一个很重要的知识点ThreadLocal,本节不做分析
   */
    public static SessionState get() {
        return ((SessionState.SessionStates)tss.get()).state;
    }

上面创建了一个富含各种信息的CliDriver对象,现在来看他怎么调用run方法。

public int run(String[] args) throws Exception {
		// 1.建立OptionsProcessor类的对象oproc,并且对命令进行初步的解析.
		//   提取-e -h hiveconf hivevar等参数信息,设置用户提供的系统和Hive环境变量。
        OptionsProcessor oproc = new OptionsProcessor();
        if (!oproc.process_stage1(args)) {
            return 1;
        } else {
        // 2.初始化Log4j日志组件
            boolean logInitFailed = false;

            String logInitDetailMessage;
            try {
                logInitDetailMessage = LogUtils.initHiveLog4j();
            } catch (LogInitializationException var15) {
                logInitFailed = true;
                logInitDetailMessage = var15.getMessage();
            }
		// 3.使用HiveConf实例化CliSessionState,CliSessionState继承了SessionState类
		//   创建了输入输出流,也创建了一些记录用户输入的字符串,
		//   比如:fileName,cmdProperties,在实例化的过程中,主要是用来记录HiveConf。
            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 var14) {
                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;
            } else {
        // 5.在允许打印的模式下,如果初始化日志失败就打印错误信息
                if (!ss.getIsSilent()) {
                    if (logInitFailed) {
                        System.err.println(logInitDetailMessage);
                    } else {
                        SessionState.getConsole().printInfo(logInitDetailMessage);
                    }
                }
		// 6.将用户命令行输入的配置信息和变量等覆盖HiveConf的默认值
                HiveConf conf = ss.getConf();
                Iterator var7 = ss.cmdProperties.entrySet().iterator();

                while(var7.hasNext()) {
                    Entry<Object, Object> item = (Entry)var7.next();
                    conf.set((String)item.getKey(), (String)item.getValue());
                    ss.getOverriddenConfigurations().put((String)item.getKey(), (String)item.getValue());
                }
		// 7.读取配置提示和替换变量
                prompt = conf.getVar(ConfVars.CLIPROMPT);
                prompt = (new VariableSubstitution(new HiveVariableSource() {
                    public Map<String, String> getHiveVariable() {
                        return SessionState.get().getHiveVariables();
                    }
                })).substitute(conf, prompt);
                prompt2 = spacesForString(prompt);
        // 8.设置会话状态,然后执行CLI程序,即excuteDriver().
                if (HiveConf.getBoolVar(conf, ConfVars.HIVE_CLI_TEZ_SESSION_ASYNC)) {
                    SessionState.beginStart(ss, this.console);
                } else {
                    SessionState.start(ss);
                }

                ss.updateThreadName();

                int var16;
                try {
                    var16 = this.executeDriver(ss, conf, oproc);
                } finally {
                    ss.resetThreadName();
                    ss.close();
                }

                return var16;
            }
        }
    }

大致的流程可以整理为:

  • 读取命令行输入的参数,保存在OptionsProcessor对象oproc
  • 初始化Log4j日志组件
  • 创建CliSessionState对象ss读取SessionState内配置信息
  • 接着对CliSessionState对象进行初始化,如果报错且允许打印则输出报错信息
  • CliSessionState对象ss读取SessionState内配置信息覆盖默认配置信息
  • 完成替换后做好允许准备,进入下一步骤。

简单来说就是读取相关环境配置,开启日志,读取相关配置覆盖默认配置,准备允许。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寒 暄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值