Hive源码分析:CLI入口类

2013.08.21 | Comments

说明:

本文的源码分析基于hive-0.10.0-cdh4.3.0。

启动脚本

从shell脚本/usr/lib/hive/bin/ext/cli.sh可以看到hive cli的入口类为org.apache.hadoop.hive.cli.CliDriver

	cli () {
	  CLASS=org.apache.hadoop.hive.cli.CliDriver
	  execHiveCmd $CLASS "$@"
	}
	cli_help () {
	  CLASS=org.apache.hadoop.hive.cli.CliDriver
	  execHiveCmd $CLASS "--help"
	}

入口类

java中的类如果有main方法就能运行,故直接查找org.apache.hadoop.hive.cli.CliDriver中的main方法即可。

CliDriver类中的方法有:

main方法代码如下:

	public static void main(String[] args) throws Exception {
	    int ret = run(args);
	    System.exit(ret);
	}

阅读run函数可以看到,主要做了以下几件事情:

  • 读取main方法的参数
  • 重置默认的log4j配置并为hive重新初始化log4j,注意,在这里是读取hive-log4j.properties来初始化log4j。
  • 创建CliSessionState,并初始化in、out、info、error等stream流。CliSessionState是一次命令行操作的session会话,其继承了SessionState。
  • 重命令行参数中读取参数并设置到CliSessionState中。
  • 启动SessionState并连接到hive server
  • 如果cli是本地模式运行,则加载hive.aux.jars.path参数配置的jar包到classpath
  • 创建一个CliDriver对象,并设置当前选择的数据库。可以在命令行参数添加-database database来选择连接那个数据库,默认为default数据库。
  • 加载初始化文件.hiverc,该文件位于当前用户主目录下,读取该文件内容后,然后调用processFile方法处理文件内容。
  • 如果命令行中有-e参数,则运行指定的sql语句;如果有-f参数,则读取该文件内容并运行。注意:不能同时指定这两个参数。
	hive -e 'show tables'
	hive -f /root/hive.sql
  • 如果没有指定上面两个参数,则从当前用户主目录读取.hivehistory文件,如果不存在则创建。该文件保存了当前用户所有运行的hive命令。
  • 在while循环里不断读取控制台的输入内容,每次读取一行,如果行末有分号,则调用CliDriver的processLine方法运行读取到的内容。
  • 每次调用processLine方法时,都会创建SignalHandler用于捕捉用户的输入,当用户输入Ctrl+C时,会kill当前正在运行的任务以及kill掉当前进程。kill当前正在运行的job的代码如下.
	HadoopJobExecHelper.killRunningJobs();
  • 处理hive命令。

处理hive命令过程

如果输入的是quit或者exit,则程序退出。

如果命令开头是source,则会读取source 后面文件内容,然后执行该文件内容。通过这种方式,你可以在hive命令行模式运行一个文件中的hive命令。

如果命令开头是感叹号,执行操作系统命令(如!ls,列出当前目录的文件信息)。通过以下代码来运行:

	Process executor = Runtime.getRuntime().exec(shell_cmd);
	StreamPrinter outPrinter = new StreamPrinter(executor.getInputStream(), null, ss.out);
	StreamPrinter errPrinter = new StreamPrinter(executor.getErrorStream(), null, ss.err);

	outPrinter.start();
	errPrinter.start();

	ret = executor.waitFor();
	if (ret != 0) {
	  console.printError("Command failed with exit code = " + ret);
	}

shell_cmd的内容大概如下:

	shell_cmd = "/bin/bash -c \'" + shell_cmd + "\'"

如果命令开头是list,列出jar/file/archive

如果是远程模式运行命令行,则通过HiveClient来运行命令;否则,调用processLocalCmd方法运行本地命令。

以本地模式运行时,会通过CommandProcessorFactory工厂解析输入的语句来获得一个CommandProcessor,CommandProcessor接口的实现类见下图:

从上图可以看到指定的命令(set/dfs/add/delete/reset)交给指定的CommandProcessor处理,其余的(指hql语句)交给Driver类来处理。

故,org.apache.hadoop.hive.ql.Driver类是hql查询的起点,而run()方法会先后调用compile()和execute()两个函数来完成查询,所以一个command的查询分为compile和execute两个阶段。

总结

作为尝试,第一次使用思维导图分析代码逻辑,简单整理了一下CliDriver类的运行逻辑,如下图。以后还需要加强画图和表达能力。

hive-cli-clidriver

参考文章


原创文章,转载请注明: 转载自JavaChen Blog,作者:JavaChen
本文链接地址:http://blog.javachen.com/2013/08/21/hive-CliDriver.html
本文基于署名2.5中国大陆许可协议发布,欢迎转载、演绎或用于商业目的,但是必须保留本文署名和文章链接。 如您有任何疑问或者授权方面的协商,请邮件联系我。