详解Hive-CliDriver——细读Hive源码(二)
来源:互联网 发布:汉诺塔问题c语言代码 编辑:程序博客网 时间:2024/06/09 05:16
读程序就要从main函数读起,从而了解程序的流程。所以我首先从CliDriver这个类开始。
一 ,主函数
public static void main(String[] args) throws Exception { int ret = new CliDriver().run(args); System.exit(ret); }
- String[] args 是运行的时候由外部命令穿进来的参数;
- System.exit(ret)明显是退出函数
/** * 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); }
这个是System.exit()的源码,翻译它第一段的注释-“终止当前正在运行的java虚拟机。这个参数作为状态码;按惯例,非零状态代码表示异常终止。与return不同,return只是退回到上一层,exit将会退出到最外层。
3. 最重要的一句就是建立新的CliDriver对象,并调用他的run()函数,下来我们进入类的构造函数。
二,构造函数
public CliDriver() { SessionState ss = SessionState.get(); conf = (ss != null) ? ss.getConf() : new Configuration(); Log LOG = LogFactory.getLog("CliDriver"); if (LOG.isDebugEnabled()) { LOG.debug("CliDriver inited with classpath " + System.getProperty("java.class.path")); } console = new LogHelper(LOG); }
首先创建了一个SessionState类,并调用get()函数; SessionState封装了一个会话的关联的数据,包括配置信息HiveConf,输入输出流,指令类型,用户名称、IP地址等等。SessionState 是一个与线程关联的静态本地变量ThreadLocal,任何一个线程都对应一个SessionState,能够在Hive代码的任何地方获取到(大量被使用到),以返回用户相关或者配置信息等。来看源码:
/** get the current session. */ public static SessionState get() { return tss.get().state; } /** * Singleton Session object per thread. * **/ private static ThreadLocal<SessionStates> tss = new ThreadLocal<SessionStates>() { @Override protected SessionStates initialValue() { return new SessionStates(); } };
注释中说get()是在获取当前会话,返回了一个对象tss的调用,有关tss建立代码我也贴出来了。有关Threadlocal详见:http://blog.csdn.net/lufeng20/article/details/24314381/ 也就是说,Threadlocal 是为了解决多线程当中变量访问冲突的问题,它为每一个线程均拷贝了一份副本,线程可以对此副本进行随意的修改而不会与其他线程发生冲突。其中get()方法返回当前线程所对应的线程局部变量,其初始值为null;
在定义好conf和log之后;System.getProperty 可以获得可执行.class文件的路径以及引入的jar包路径。LogHelper 目前看来就是一个管理日志的类;
在此提出一个问题,为什么在工程中要使用log呢?有什么帮助呢?
三,run()函数
OptionsProcessor oproc = new OptionsProcessor(); if (!oproc.process_stage1(args)) { return 1; }
建立OptionsProcessor类的对象oproc,并且对命令进行初步的解析,提取-e -h hiveconf hivevar等参数信息,设置用户提供的系统和Hive环境变量。具体的细节可以在OptionsProcessor这个类中查看到。
boolean logInitFailed = false; String logInitDetailMessage; try { logInitDetailMessage = LogUtils.initHiveLog4j(); } catch (LogInitializationException e) { logInitFailed = true; logInitDetailMessage = e.getMessage(); }
初始化Log4j日志组件;使用的日志的好处是什么呢?
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; }
使用HiveConf实例化CliSessionState,CliSessionState 继承了SessionState类,,创建了输入输出流,也创建了一些记录用户输入的字符串,比如:fileName,cmdProperties,在实例化的过程中,主要是用来记录HiveConf。
if (!oproc.process_stage2(ss)) { return 2; } 以下是它在OptionsProcessor类中的详细定义: public boolean process_stage2(CliSessionState ss) { ss.getConf(); if (commandLine.hasOption('H')) { printUsage(); return false; } ss.setIsSilent(commandLine.hasOption('S')); ss.database = commandLine.getOptionValue("database"); ss.execString = commandLine.getOptionValue('e'); ss.fileName = commandLine.getOptionValue('f'); ss.setIsVerbose(commandLine.hasOption('v')); String[] initFiles = commandLine.getOptionValues('i'); if (null != initFiles) { ss.initFiles = Arrays.asList(initFiles); } if (ss.execString != null && ss.fileName != null) { System.err.println("The '-e' and '-f' options cannot be specified simultaneously"); printUsage(); return false; } if (commandLine.hasOption("hiveconf")) { Properties confProps = commandLine.getOptionProperties("hiveconf"); for (String propKey : confProps.stringPropertyNames()) { ss.cmdProperties.setProperty(propKey, confProps.getProperty(propKey)); } } return true; }
从这里可以看出,process_stage1只是对命令行进行了一个初步的解析,在process_stage2中对CliSessionState的成员进行了赋值,但这和process-stage1有什么联系吗?不应该执行完process_stage1这个函数就return了吗?程序是不断循环执行的吗?
if (!ss.getIsSilent()) { if (logInitFailed) { System.err.println(logInitDetailMessage); } else { SessionState.getConsole().printInfo(logInitDetailMessage); } }
在允许打印的模式下,如果初始化日志失败就打印错误信息。
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()); }
将用户命令行输入的配置信息和变量等覆盖HiveConf的默认值
prompt = conf.getVar(HiveConf.ConfVars.CLIPROMPT); prompt = new VariableSubstitution().substitute(conf, prompt); prompt2 = spacesForString(prompt);
注释中说:read prompt configuration and substitute variables.也就是读取配置提示和替换变量。这一步有什么作用呢?
SessionState.start(ss); try { return executeDriver(ss, conf, oproc); } finally { ss.close(); } }
设置会话状态,然后执行CLI程序,即excuteDriver().
- 详解Hive-CliDriver——细读Hive源码(二)
- 详解Hive-CliDriver续——细读Hive源码(三)
- 详解Hive-Driver——细读Hive源码(四)
- Hive源码导入eclipse——细读Hive源码(一)
- Hive CliDriver hack
- Hive用户接口(二)—使用Hive JDBC驱动连接Hive操作实例
- Hive on Spark源码分析(二)—— SparkSession与HiveSparkClient
- 大数据(二十三)Hive【Hive三种启动方式 、 HIVE Server2详解 、 jdbc链接HIVE】
- Hive源码解析—之—Hive的入口
- Hive 源码解析—之—Hive的入口
- Hive源码解析—之—Hive的入口:
- hive partition 分区详解二
- hive 操作(二)——使用 mysql 作为 hive 的metastore
- Hive基本操作(二)——Hive实战案例-级联求和
- Hive(二)
- hive学习(二)
- hive系列(二)
- hive基础知识(二)
- Android Studio 引入第三方库(二)
- java 根据表名和关键字全文检索
- Java_>>_and_>>>
- MMI-Android
- 几种内表类型
- 详解Hive-CliDriver——细读Hive源码(二)
- 【JavaScript】实现三个小球围着椭圆旋转的加载动画
- jsp页面加载css文件不生效
- 指数分布族的两个性质
- 粒子群算法求函数极值
- 解决AndroidStudio导入项目在 Building gradle project info 一直卡住
- Rally安装问题记录
- Camera安卓源码剖析-源码中的设计模式实例
- Core ML and Vision