大数据框架hadoop之版本显示的实现逻辑

    版本显示在各个项目或系统中都有使用到,实现方式也各式各样,接下来了解一下hadoop是如何实现版本显示的逻辑的。首先从使用场景开始。

使用场景

    bin目录下打印系统版本信息。

执行命令

结果

hadoop version


 

结果显示,当前的hadoop版本为1.0.0

接下来就一步步地跟踪代码,详细了解一下版本显示的实现逻辑。

Hadoop脚本

首先打开hadoop脚本(目录${HADOOP_HOME}/BIN),查看脚本接收到命令version后调用哪个类来处理。相关脚本如下:

... ...

elif [ "$COMMAND" = "version" ] ; then

  CLASS=org.apache.hadoop.util.VersionInfo

  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"

... ...

从上表可知,脚本接收到version命令后,对应的执行类是org.apache.hadoop.util.VersionInfo

VersionInfo

运行时,对应的执行类VersionInfomain中直接打印消息。相关代码如下:

/**

 * This class finds the package info for Hadoop and the HadoopVersionAnnotation

 * information.

 */

public class VersionInfo {

  private static Package myPackage;

  private static HadoopVersionAnnotation version;

  static {

    myPackage = HadoopVersionAnnotation.class.getPackage();

    version = myPackage.getAnnotation(HadoopVersionAnnotation.class);

  }

  ... ...

  /**

   * 获取了HadoopVersionAnnotation实例的version()方法的返回值。

   * @return the Hadoop version string, eg. "0.6.3-dev"

   */

  public static String getVersion() {

    return version != null ? version.version() : "Unknown";

  }

  

  /**

   * Get the subversion revision number for the root directory

   * @return the revision number, eg. "451451"

   */

  public static String getRevision() {

    return version != null ? version.revision() : "Unknown";

  }

  

  /**

   * 获取了HadoopVersionAnnotation实例的date()方法的返回值。

   * @return the compilation date in unix date format

   */

  public static String getDate() {

    return version != null ? version.date() : "Unknown";

  }

  

  /**

   * 获取了HadoopVersionAnnotation实例的user()方法的返回值。

   * @return the username of the user

   */

  public static String getUser() {

    return version != null ? version.user() : "Unknown";

  }

  

  /**

   * Get the subversion URL for the root Hadoop directory.

   */

  public static String getUrl() {

    return version != null ? version.url() : "Unknown";

  }

  ... ...

  public static void main(String[] args) {

    System.out.println("Hadoop " + getVersion());

    System.out.println("Subversion " + getUrl() + " -r " + getRevision());

    System.out.println("Compiled by " + getUser() + " on " + getDate());

  }

}

定义了静态变量:myPackeageversion。其中versionHadoopVersionAnnotation的实例。 HadoopVersionAnnotationAnnotation接口类,在这里,hadoop项目组通过这种方式来获取系统版本信息。并不是直接写在代码中。

这个类是个比较普通的类,但是管理了Hadoop的版本信息,包括用户、编译时间、版本信息等内容。在这个类中,封装了HadoopVersionAnnotation这个注释类。

HadoopVersionAnnotation

相关代码如下:

/**

 * A package attribute that captures the version of Hadoop that was compiled.

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.PACKAGE)//是对包的注释,很多地方都是用

public @interface HadoopVersionAnnotation {

 

  /**

   * Get the Hadoop version

   * @return the version string "0.6.3-dev"

   */

  String version();

  

  /**

   * Get the username that compiled Hadoop.

   */

  String user();

  

  /**

   * Get the date when Hadoop was compiled.

   * @return the date in unix 'date' format

   */

  String date();

  

  /**

   * Get the url for the subversion repository.

   */

  String url();

  

  /**

   * Get the subversion revision.

   * @return the revision number as a string (eg. "451451")

   */

  String revision();

}

    这只是个接口类,但是纵观整个项目工程,并没有找到实现类;查看整个项目的源码,也没有找到初始化的地方。

    根据JDK语法,如果类型设置为PACKAGE,则需要在这个Annotation所在的包中,有一个package-info.java类,并且定义如下:

@HadoopVersionAnnotation(version="1.0.0-SNAPSHOT")

package org.apache.hadoop;

    这样,在调用HadoopVersionAnnotationversion()方法时,可以得到在package-info.java中对该方法的返回值。

    下面,就要介绍这个package-info.java是怎么来的了。

package-info.java

     查看编译后生成的hadoop-core-1.0.0.jar包,是可以看到package-info.class类的,相关信息如下:


 

由此可以推测,package-info类应该是在项目工程编译过程中生成的,接下来看一下build.xml文件,虽然没有package-info字眼,但确看到了version字眼,而且执行该脚本是在init目标下。如下所示:

  <!-- ====================================================== -->

  <!-- Stuff needed by all targets                            -->

  <!-- ====================================================== -->

<target name="init" depends="ivy-retrieve-common">

... ...

<exec executable="sh">

   <arg line="src/saveVersion.sh ${version} ${build.dir}"/>

</exec>

... ...

</target>

    接下来将目光转移到saveVersion.sh脚本。

saveVersion.sh脚本

    打开脚本saveVersion.sh,终于发现生成package-info.java类的源码了。相关脚本如下:

... ...

mkdir -p $build_dir/src/org/apache/hadoop

cat << EOF | \

  sed -e "s/VERSION/$version/" -e "s/USER/$user/" -e "s/DATE/$date/" \

      -e "s|URL|$url|" -e "s/REV/$revision/" \

      > $build_dir/src/org/apache/hadoop/package-info.java

/*

 * Generated by src/saveVersion.sh

 */

@HadoopVersionAnnotation(version="VERSION", revision="REV", 

                         user="USER", date="DATE", url="URL")

package org.apache.hadoop;

EOF

打开hadoop编译时创建的目录,确实找到了package-info.java类,如下所示:


 
 

再打开package-info.java类,文件内容正是我们所期待的。如下所示:

/*

 * Generated by src/saveVersion.sh

 */

@HadoopVersionAnnotation(version="1.0.0", revision="", 

                         user="e40-nb2-pcmyuser", date="Mon Nov 17 14:40:26     2014", url="")

package org.apache.hadoop;

 

猜你喜欢

转载自seandeng888.iteye.com/blog/2164141
今日推荐