- 根据前言可以看出,第一步是cli向Driver提交作业,因此我们需要找到代码中的CliDriver类,并搜索出里面的main方法,一切从main开始,如图所示
- 可以看到main方法中创建了一个CliDriver对象,然后调用了他的run方法
public static void main(String[] args) throws Exception {
int ret = new CliDriver().run(args);
System.exit(ret);
}
- 我们先查看一下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);
}
- 在SessionState对象中封装了一个会话的关联的数据,包括配置信息HiveConf,输入输出流,指令类型,用户名称、IP地址等等。
- 回到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();
}
}