Hiveのパッチ投稿のやりかた

こんにちは、ポテトサラダを極めようと心に決めたタムタムです。
(昨日作って食べたら満足しました(・w・))

今日はHiveのパッチの書き方をまとめます。
Hadoop本体とはちょっと作法が違います。Hadoop本体はパッチを投げると自動でJenkinsがテストしてくれたりするらしいのですが、Hiveはそんなことやってくれません。またパッチもJIRAに添付するだけではダメで、Phabricator(Reviewボードみたいなもの)というツールを使ってDiffをアップしてReviewしてもらう必要があります。

今回は実際にHIVE-2703のパッチを投げるまでの手順を書いていきます。
http://mt.orz.at/archives/2012/02/hivejira.html こちらの内容と被っていますが、こっちでは説明しきれなかったところも書いていきます。
なお、手順はsubversionの手順になっています。ぶっちゃけgitの方をオススメします。subversionだと複数のパッチを書くときにローカルでブランチを切れないのでとってもとってもつらいです・・。(私がsubversionを使っているのは、gitだとphabricatorのarcコマンドがうまく動作せずにarc diff --jira HIVE-xxxでパッチをあげることができなかったからです)

なお私はFedora16をVirtualBoxの上で動かして開発しています。(MacbookとかオシャレなPC持っていません・・)
あと、Hadoopの環境は普通に作っておいてください。ローカルモードで良いです。これも省略。

今やいろんな本が出ていますが、Hadoop徹底入門がオススメです。

まずざっくりとした手順は以下のようになります。

  • ソースを落とす
  • ソースをいじる
  • テストする
  • (JIRAで適宜コメント書いたり、やりとりしたり)
  • Phabricatorでreviewして貰う
  • 最終版のDIFFをJIRAに添付する(ASFライセンス付ける)

細かい手順を説明していきます。

まず、ソースを落としてEclipseのプロジェクトを作ります。(Eclipse使わなくてもパッチは投稿できます。ただJavaのソースをIDE無しで書くのは結構つらいと思います。)
なお、ソースを落としてきたら、HIVE-2902, HIVE-2904のパッチを当てましょう。今のバージョンだと正しいEclipseのテンプレートを作ってくれません。

# ソースを落としてくる
svn checkout http://svn.apache.org/repos/asf/hive/trunk hive-trunk
cd hive-trunk
# パッチを当てる(※1)
wget https://issues.apache.org/jira/secure/attachment/12523301/HIVE-2902.2.patch.txt
wget https://issues.apache.org/jira/secure/attachment/12522738/HIVE-2904.D2487.3.patch
patch -p0 < HIVE-2902.2.patch.txt
patch -p0 < HIVE-2904.D2487.3.patch
# ビルドする
ant clean package
# Eclipse用のプロジェクトを生成する
ant eclipse-files
# テストドライバとか生成する
cd metastore
ant model-jar
cd ../ql
ant gen-test

※1 追記(2012/04/19 13:30) パッチのバージョンを変更しました。最新のソースだとDDLTaskがjson形式で出力できるようになっていて、JsonMetaDataFormatterがjacksonに依存するようになっていました。

これでhive-trunkにeclipseのprojectファイルが出来ています。あとはEclipseからインポートするだけです。なお、Eclipseの使い方は今更説明するようなものではないので省略します。注意点としては、ワークスペースの文字コードをUTF-8に、JDKは6を使いましょう。

また、プロジェクトの設定で「Javaエディタ → 保管アクション」の設定でインポートの編成が行われるようになっています。なのでパッチを書いた時にdiffを取ったらいじっていないところも変更されている事があります。これは気にしたら負けです。
もう1つ、プロジェクトの設定の「ビルダー」で「Hive_Ant_Builder」のチェックは外した方が良いです。保存する度にAntが走って重めのビルドが走ることになってちょっとイラッとします。

ここまでで、開発環境は整いました。
というわけで、普通に開発をしましょう。なお、パッチを出す時は基本的にテストケースも一緒に追加します。(パッチの内容にもよりますけど)。

次にテストの方法です。単体テストはJUnitで書かれています。Eclipse用のプロジェクトを生成した時に、実行構成も既に設定されています。例えばJdbcDriverTestという単体テストの実行構成を見ると、以下のように既に必要な設定(VM引数、環境変数、作業ディレクトリなど)が入っています。


どのクラスがどの単体テストが担当しているのかは、クラスの参照を調べればなんとなく推測できます。まずは関連する単体テストがピンポイントで通るようにするのが良いです、なお、UDF関数やクエリのテストはまたちょっと違います。後者のテストの方法は以下のようにします。 このテストは、「ql/src/test/queries/clientpositive/timestamp_udf.q」を実行した時に「ql/src/test/results/clientpositive/timestamp_udf.q.out」の結果になるかというテストです。前回の記事にも書いてあります。 -Dqfileを省略すると全部のテストを実行します。

# ポジティブテスト
ant -Dtestcase=TestCliDriver -Dqfile=timestamp_udf.q -Dtest.silent=false test
# ネガティブテスト
ant -Dtestcase=TestNegativeCliDriver -Dqfile=timestamp_udf.q -Dtest.silent=false test

このあたりをピンポイントで実行してから、最後に全体のテストを実行します。非情に時間がかかります。4,5時間は覚悟してください。寝る前に実行しましょう。

ant package test
ant testreport

これで build/test/junit-noframes.html というファイルが生成されます。このファイルにテストの結果が書いてあります。

パッチを投げる前にsvn diffを取って差分を確認してください。(※最初に環境構築をするためにパッチを当てたやつは除外する必要があります。)

# LANGが日本語になっていると「リビジョン」という日本語が入るので
export LANG=C
svn diff > HIVE-xxxx.1.patch.txt

gitの場合は、以下のような感じです。

git diff --no-prefix > HIVE-xxxx.1.patch.txt

これでパッチを投げる準備ができました。(後述するPhabricatorを使わない場合は、このDIFFをJIRAにファイル添付すれば良いです。)

チケットの開き方は前回の記事を参考にしてください。
※こんな事を書くと怒られるかもしれませんが、ぶっちゃけ英語なんて適当で通じます(たぶん)。英語が出来なくてウジウジするくらいならコードを書いてパッチを投げましょう。(もしくは知り合いに英訳して貰いましょう)。自分たちが外国人のニンジャ語を理解できるように向こうの人もきっと理解してくれます。たぶん(・3・)。

パッチの投稿の仕方です。Phabricatorをインストールする必要があります。以下のURLを参考にします。
http://www.phabricator.com/docs/phabricator/article/Arcanist_User_Guide.html
https://cwiki.apache.org/confluence/display/Hive/PhabricatorCodeReview

# どこかのディレクトリで以下を実行
git clone git://github.com/facebook/libphutil.git
git clone git://github.com/facebook/arcanist.git
# BashのTab Completion(arc[TAB]で引数を表示してくれる)を有効にする
source arcanist/resources/shell/bash-completion

その後、以下のコマンドを叩いて準備をします。
arcanist/bin を環境変数PATHに通しておくと良いです。

ant arc-setup
arc install-certificate

Phabricatorにパッチを投げる手順は以下になります。これは実際にsvnかgitでdiffを取ってPhabricatorに投稿します。これでJIRAにパッチが添付されます。

# svnの場合
arc diff --jira HIVE-xxxx
# gitの場合(gitの場合はarc diffで--previewオプションが使えます)
git checkout HIVE-xxxx-dev-branch
ソース編集
git commit -a --amend --reset-author -C HEAD
arc diff

以上でJIRAにパッチが投稿されるので、「Submit Patch」を押します。するとステータスがPatch Availableになります。 パッチがNGな場合は、レビューの内容やコメントの内容を見て修正しましょう。

レビューが終わったら最終バージョンのパッチをJIRAに添付します。添付する時はASFライセンスを付与しましょう。この時に新機能の追加や互換性が無くなる変更の場合はReleaseNoteを各必要があります。 

私はHiveにはそんなに詳しくない初級者ですが、何か困ったことがあれば協力できるかも。

なお、Hadoop Hackathonというものがあります。
http://www.zusaar.com/event/250002

私が参加した時は、JIRAの使い方とパッチの書き方を最初に教えていただきました。基本は黙々とハッカソンするわけですが、
お菓子を食べながらプロジェクターにソースを映してアレやコレやと楽しかったです。
開発環境とJavaさえ書ければ、英語は出来なくてもみんな英語が出来るので誰かが助けてくれます。

Hadoopのここが気にくわないわー。Hiveのここが気にくわないわー。あのBug放置されてるわー、直したいわー。という人は参加を考えてみると良いかも。

新しいサイトもよろしくお願いします!