MayCoder

Valarmorghulis

Hive Compile and Apply Patch

2012-09-20

回归来的第一篇,另外还有好几篇躺在 published:false 中,还没搞好 :-(

这个礼拜最大的收获是编译啥啥啥还是蛮简单的,又没叫你去改代码。有些东西动手尝试一下,往往会发现没有多难,不能停留在口上上说说而已。看到 一段相关但不是很切题的话 :

不可忽视的一点是:在技术性团体里,做永远比说要来的有效。在想法成熟之前就贸然游说,往往会招致相反的效果。大家都是工程师,不会贸然接纳陌生事物。如果自己都还没有想清楚就开始大肆游说,往往会被大家提出的实际的工程问题驳斥地体无完肤。当你哑口无言之时,大家也已经对你的方案产生了难以磨灭的 “不靠谱”的第一印象,这时要再想咸鱼翻身,可就没那么容易了。

相对的,首先自行查阅文档资料并进行试验,制作demo,通过试验发现和解决实际出现的问题。在想法基本成型时,和个别观念开放的同仁进行探讨,这时往往可以发现大量之前自己没有考虑到的问题,再转而细化方案。这个过程反复迭代几次之后,方案和demo逐渐成熟,同时也潜移默化地达到了传教的目的。等到方案完全成熟之后,再拿出实际可工作的demo开始游说,这时自然就成竹在胸了。

进入正题,这里主要是参考几篇文章,说说编译hive和打补丁, 或者说贴贴链接= =

hive 代码编译

install hive on linux
使用ant编译hive
hive打补丁编译hive

这里我在ubuntu上操作的, 编译hive需要依赖 JAVA, ANT (这里不依赖hadoop原因是ant会自动去下载hadoop)。
安装好后export JAVA_HOME , ANT_HOME 变量 (我直接加入.bashrc当中了)。
接下来去官网下载hive源码包。这里我使用的是 hive.0.9.0 。 解压之后进入src目录,需要修改一些配置:

build.properties
1
2
3
4
5
6
7
8
9
hadoop.version=1.0.1

主要是facebook被墙了,镜像地址可参考 http://www.apache.org/dyn/closer.cgi/hadoop/core/
hadoop.mirror1=http://mirror.bjtu.edu.cn/apache  
hadoop.mirror2=http://mirror.bjtu.edu.cn/apache

以下的修改主要是看到镜像中的hadoop版本已经没有默认的版本号了,估计是不支持了?故改成包含的版本号。
hadoop-0.20.version=0.20.2
hadoop-0.20S.version=1.0.1 (S的版本不知有没有啥区别)

接下来执行 ant package 即开始编译了, 结果默认会放在 build/dist 目录中,使用 -Dtarget.dir=xxx 可以更新目标位置。

如果BUILD FAIL的话,一般参考提示可以看出是哪里出了问题(遇到比较多还是被墙的问题= =)。

hive 单元测试

hive中的单元测试
hive中的test case
QtestUtil.java
hive unit test

hive 中的 单元测试 还是蛮有趣的,既有传统的单元测试代码,又可以批量执行查询脚本判断结果是否一致:

在hive中会有大量的.q的文件即执行测试的query文件,.q.out是测试的结果文件。 进行新测试后产生的结果和标准的q.out一致则表示测试成功。
具体来说,src/ql/src/test/queries下面是测试用例,clientpositive是运行成功的用例,clientnegative是运行失败,返回非0的用例。 src/ql/src/test/results 下面是测试用例对应的输出结果。 如src/ql/src/test/queries/case_sensitivity.q对应的输出结果是src/ql/src/test/results/case_sensitivity.q.out 。

使用 ant test 运行单元测试,不过此命令要跑好多测试, 光TestCliDriver一项就要跑好几个小时 , 我们可以

ant test
1
2
3
4
5
运行所有的正面的测试
ant test -Dtestcase=TestCliDriver
 
运行特定的测试,以groupby为例子
ant test -Dtestcase=TestCliDriver -Dqfile=groupby1.q

使用 -Doverwrite=true 可以覆盖结果文件,后面有新的更新想测试表现是否一致的时候就可以使用了, 通常在我们增加新的udf的时候可以这么来生成测试数据。

hive代码打补丁

下载了 hive 0.9.0 稳定版,不过发布之后还是有若干bug,这时搜索一下 hive jira 一般能看到相应ticket,比如 这个substr遇到UTF8的问题 。一般打的补丁会走一个 publish-review-apply过程 ,准确解决问题的补丁会被加入版本库中,而临时补丁一般不会采用。作为用户,有时难免得打一些这样的补丁。打补丁也很方便,下载社区提供的补丁之后,使用 patch 命令即可以应用到源码中, 后续在进行编译测试即可。

另外我们有时会有需求将 自己使用的 udf 编译到hive当中以方便使用 ,这其实也可以看成打补丁的行为。

打补丁多了,管理是后面会遇到的问题。 就个人而言,可以自己载个官方的git仓库,然后开分支来维护自己的变更。如果要多人协作的话,可以创建一个新的git仓库,然后添加两个远端, 其中一个是官方的git仓库,另外一个可以是大家从某个分支开始维护的版本。纯属yy,实际操作起来也未必省心。 这里看起来使用 github organization 是蛮适合的。

当然,可以预见的是,大部分时间我们都不会打补丁,可能只会在新增一些UDF= =, 于是似乎完全没有必要这么干, 大概 类似这样就可以了 , 看起来一般将用到的udf打包,然后要用的时候加一句声明即可。

不过我还是蛋疼去搞了一个 organization , fork一下官方代码。 我在本地git加入 apache/hive 作为另一个远端, 称为 mirror 。由于我们目前使用的是 0.9, 故我考虑的是在 origin/branch-0.9 下做开发,并将 mirror/branch-0.9 定期 merge 回 branch-0.9 。至于 trunk 则不动。

这样一来我就开始捣鼓了,首先还是改 build.properties , 我将这些也一并提交到分支里面了。 然后我开始将 udf 编译进去,这次遇到一个比较坑爹的问题就是 编译一直成功,但是执行单元测试一直找不到新的UDF 。 捣鼓了很久无果后找小美支援,小美在分析一阵之指出测试的时候没有引用到编译的 FunctionRegistry.class , 估计使用到别的旧的文件了。又过了一段时间之后我确实发现有个地方 ~/.ivy2/ 下面有一些cache, 简单google之后又发现 hive jira 上已经有一个 tck , 看了大概是由 HIVE-2646 引入的, 导致测试的时候会从ivy cache来加载hive相关的类而不是 build/dist/lib 。这个改动恰恰不在 0.9.0发布版但是 commit到 branch-0.9 中了, 所以我从 branch-0.9 的代码开始编译就中招了。这个patch有加入trunk中,故 cherry-pick 一下即可(本来我打算直接打patch的)。当然这里我不清楚为啥这个补丁不加入 0.9 分支,估计不算大问题? 没有运行bug?从版本库编译就是比较坑爹= =

Comments