夢とガラクタの集積場

落ちこぼれ三流エンジニアである管理人の夢想=『夢』と、潰えた夢=『ガラクタ』の集積場です。

StormのMasterSourceをビルドしてみる

こんにちは。

最近外を移動する際に日陰を移動できるルートを確認しながら移動する癖がつきつつある今日この頃です。
別に日光に当たったからと言って黄色い汁になって溶けてしまったりはしないんですが、まぁ一応w


さて、前回Storm0.8.2系のビルド手順を確立したので、次はStormのMasterSourceのビルド方法を確認してみます。
きちんと改造に成功したのならMasterSourceでビルドして動作確認した上でPullRequestを投げる必要がありますからね。

というわけで。

1.必要となる環境

Storm0.8.2系ではLeiningenの1系を使用していましたが、StormのMasterSourceではプロジェクト定義が以下のようになっています。
そのため、Leiningenの2系をインストールする必要がある・・・というわけですね。

  • project.clj
(def VERSION (.trim (slurp "VERSION")))
(def MODULES (-> "MODULES" slurp (.split "\n")))
(def DEPENDENCIES (for [m MODULES] [(symbol (str "storm/" m)) VERSION]))

(eval `(defproject storm/storm ~VERSION
  :url "http://storm-project.net"
  :description "Distributed and fault-tolerant realtime computation"
  :license {:name "Eclipse Public License - Version 1.0" :url "https://github.com/nathanmarz/storm/blob/master/LICENSE.html"}
  :mailing-list {:name "Storm user mailing list"
                 :archive "https://groups.google.com/group/storm-user"
                 :post "storm-user@googlegroups.com"}
  :dependencies [~@DEPENDENCIES]
  :plugins [[~'lein-sub "0.2.1"]]  
  :min-lein-version "2.0.0"
  :sub [~@MODULES]
  ))

そのため、まずはインストールから始めてみます。

2.Leiningen2系のインストール

Leiningen1系と違い、leinコマンドを直接ダウンロードできるため、ダウンロードして実行する方式を取ります。

$ cd /opt
$ mkdir leiningen-2.3.1
$ cd leiningen-2.3.1/
$ mkdir bin
$ cd bin
$ wget https://raw.github.com/technomancy/leiningen/stable/bin/lein
 → /opt/leiningen-2.3.1/bin/lein にleinコマンドがダウンロード
$ chmod +x lein
$ cd /opt
$ rm leiningen
 → Leiningen1系へのシンボリックリンクを削除
$ ln -s leiningen-2.3.1 leiningen
$ lein self-install
 → 「Downloading Leiningen to /root/.lein/self-installs/leiningen-2.3.1-standalone.jar now...」と表示され、ダウンロード

以上です。これでlein helpコマンドを実行するとleinのコマンド一覧が表示されます。

3.とりあえずビルドしてみる

とりあえずはMasterSourceをダウンロードしてビルドをかけてみます。
これも何故か前と同じようにwgetコマンドでGitHubのソースをダウンロードするとブランチの名称になってしまうため、途中でリネームを挟んでいます。

$ cd /opt/build
$ wget https://github.com/nathanmarz/storm/archive/master.zip
$ unzip storm-master.zip
 → /opt/build/storm-master配下にファイルが展開
$ cd storm-master
$ chmod +x bin/build_release.sh

後は、前回と同じくstorm-core/project.cljの-Djava.library.pathに/usr/lib64を追加しておきます。

これで準備はできたため、ビルドコマンドを実行してみます。すると・・・

$ bin/build_release.sh
(省略)
/opt/build/storm-master/storm-core/src/jvm/backtype/storm/nimbus/DefaultTopologyValidator.java:7: エラー: DefaultTopologyValidatorはabstractでなく、ITopologyValidator内のabstractメソッドvalidate(String,Map,StormTopology)をオーバーライドしません
public class DefaultTopologyValidator implements ITopologyValidator {
       ^
/opt/build/storm-master/storm-core/src/jvm/backtype/storm/nimbus/DefaultTopologyValidator.java:11: エラー: メソッドはスーパータイプのメソッドをオーバーライドまたは実装しません
    @Override
    ^
注意:/opt/build/storm-master/storm-core/src/jvm/backtype/storm/coordination/CoordinatedBolt.javaは推奨されないAPIを使用またはオーバーライドしています。
注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
注意:入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。
注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。
エラー2個
Compilation of Java sources(lein javac) failed.
(省略)

となり、ビルドに失敗してしまいます。あうち。
PullRequestが多数飛んでいる状態なので、一部整合性が保てない状態になっているのでしょう。
DefaultTopologyValidatorクラスはTopologyの検証を行うデフォルトバリデーションクラスであり、中身は無いクラスのため、
ソースを以下のように修正して進めます。

public class DefaultTopologyValidator implements ITopologyValidator {
    @Override
    public void prepare(Map StormConf){
    }
    @Override
    public void validate(String topologyName, Map topologyConf, StormTopology topology) throws InvalidTopologyException {        
    }    
}

では、気を取り直して再度ビルドを実行してみると・・・

$ bin/build_release.sh
(省略)
Compiling backtype.storm.testing4j
(省略)
Caused by: java.lang.ClassNotFoundException: backtype.storm.LocalCluster
	at java.net.URLClassLoader$1.run(URLClassLoader.java:366) ~[na:1.7.0_25]
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355) ~[na:1.7.0_25]
	at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_25]
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354) ~[na:1.7.0_25]
	at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:61) ~[clojure-1.4.0.jar:na]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.7.0_25]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.7.0_25]
	at java.lang.Class.forName0(Native Method) ~[na:1.7.0_25]
	at java.lang.Class.forName(Class.java:190) ~[na:1.7.0_25]
	at backtype.storm.testing4j$loading__4784__auto__.invoke(testing4j.clj:1) ~[classes/:na]
	at clojure.lang.AFn.applyToHelper(AFn.java:159) ~[clojure-1.4.0.jar:na]
	at clojure.lang.AFn.applyTo(AFn.java:151) ~[clojure-1.4.0.jar:na]
	at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3382) ~[clojure-1.4.0.jar:na]
	... 27 common frames omitted
Compilation failed: Subprocess failed」

となり、今度はテスト用のClojureコードであるtesting4jをビルドするときにエラーとなります。
しかも、厄介なことに「backtype.storm.LocalCluster」というコード自体は存在しており、単にコンパイルの順番でclassファイルが生成されておらず失敗しているようです。
→ ビルドに失敗したタイミングでビルド用ディレクトリを見ると、「LocalCluster.class」は存在しない。

・・・結局、コンパイルの順番を変更する手段は明確にならず、以下の理由によりtesting4jを削除してビルドするという駄目な回避策を取っちゃいました(汗

  1. 今回はPullRequest用に確認できるようビルドするのが目的
  2. テスト関連クラスは動作確認時には使用しない

コマンドは以下です。

$ rm storm-core/src/clj/backtype/storm/testing4j.clj
$ bin/build_release.sh
(省略)
Created /opt/build/storm-master/storm-console-logging/target/release/storm-console-logging-0.9.0-wip21.jar
(省略)
Created /opt/build/storm-master/storm-core/target/release/storm-core-0.9.0-wip21.jar
 → このタイミングで「LocalCluster.class」も生成されている。つまり純粋にコンパイルの順番?
(省略)
Created /opt/build/storm-master/storm-netty/target/release/storm-netty-0.9.0-wip21.jar
(省略)

とりあえず、これでビルドをすることはできました。
ただ、この問題はどこかで解決する必要があるため、気長に調査を続けることにします。