详解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);  }
  1. String[] args 是运行的时候由外部命令穿进来的参数;
  2. 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();    }  };
  1. 注释中说get()是在获取当前会话,返回了一个对象tss的调用,有关tss建立代码我也贴出来了。有关Threadlocal详见:http://blog.csdn.net/lufeng20/article/details/24314381/ 也就是说,Threadlocal 是为了解决多线程当中变量访问冲突的问题,它为每一个线程均拷贝了一份副本,线程可以对此副本进行随意的修改而不会与其他线程发生冲突。其中get()方法返回当前线程所对应的线程局部变量,其初始值为null;

  2. 在定义好conf和log之后;System.getProperty 可以获得可执行.class文件的路径以及引入的jar包路径。LogHelper 目前看来就是一个管理日志的类;

  3. 在此提出一个问题,为什么在工程中要使用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().

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机号码注销了微信密码忘了怎么办 摄像师把婚礼资料弄丢了怎么办 青岛拍的婚纱照修的不好怎么办 鞋店剩的鞋都是小码的怎么办 淘宝想买的衣服下架了怎么办 买家要求到付仲裁发生运费怎么办 淘宝退货退款页面刷新不出来怎么办 淘宝退货退款快递单号写错了怎么办 淘宝上已经退款的店家还发货怎么办 千牛买家下单付款了卖家怎么办 京东货到付款支付宝支付退款怎么办 美萍餐饮管理系统下单错误怎么办 淘宝店上传宝贝显示空间不足怎么办 淘宝店品牌被投诉未授权怎么办 淘宝天猫退货单号填错了怎么办 淘宝退货我把快递单号弄丢了怎么办 唯品会退货快递单号填错了怎么办 天猫换货写错运单号怎么办 训练衣舍的店铺名连接怎么办 兼职模特被骗去微整还贷了款怎么办 卖家已经发货了我要退款怎么办 卖家显示发货单号信息查不到怎么办 淘宝申请退款卖家发货了怎么办 咸鱼卖家不发货好会自动退款怎么办 淘宝卖家涨价后不发货怎么办 淘宝卖家发货选错在线下单怎么办 申请退款后卖家又虚假发货了怎么办 公司用淘宝没发票做账怎么办 淘宝网买了假货确认了怎么办? 吃了安眠药睡了一天还没有醒怎么办 淘宝买的东西退货快递弄丢了怎么办 在淘宝上已付钱店家说没货了怎么办 从淘宝物流寄东西到国外被扣怎么办 不是天猫的淘宝卖家不发货怎么办 微店违规说卖假冒商品怎么办 云集微店的商品没货了怎么办 淘宝买家被检测有虚拟交易怎么办 媒体声音突然没有声音了该怎么办 华为微信运动步数为零怎么办 淘宝店铺没货了客户拍了怎么办 房子涨价了卖家反悔不卖了怎么办