Parkour(Clojure版Hadoop実行モデルのニューフェイス)をOSX上で試す


## 概要
[2013年12月付けのClouderaブログ](http://blog.cloudera.com/blog/2013/12/write-mapreduce-jobs-in-idiomatic-clojure-with-parkour/)を読んで気になったので試してみた。

[Parkour](https://github.com/damballa/parkour)を[作成した動機](https://github.com/damballa/parkour/blob/master/doc/motivation.md)によると、Crackle(効率的なMapReduceフレームワークのGoogle’s Flumeを参考にしたApache Crunchのラッパー)、Cascalog(Cascadingのラッパー)よりClojureの文法を生かした動作モデルで設計しているらしい。

詳しくは、[各ドキュメント](https://github.com/damballa/parkour#documentation)を参照のこと。

文法は、[ネームスペースガイド](https://github.com/damballa/parkour/blob/master/doc/namespaces.md)、[MapReduce詳細](https://github.com/damballa/parkour/blob/master/doc/mr-detailed.md)あたりが参考になる。

SequenceではなくReducerをなぜ使っているかという点についても記述がある。
（この点に関しては、日本語の考察資料も複数ある）
ここは、効率的なMapReduce実行のポイントになっているかも。

## 対応環境
java 1.6 向けで試した。
（java 1.7 向けに調整したら一応動いたが、調整内容は未記載）

## leiningenプロジェクトをクローン

```bash
$ git clone https://github.com/damballa/parkour.git
$ cd parkour
```

## 単体で試す

### Parkour(Hadoop関連)の環境変数
java 1.6を用意しておく。

java 1.6、realm、heap関連で問題が起きたので対処。
一時的な環境変数として設定した。

```bash
# 環境変数を設定
# java6
$ export JAVA_CMD="$(/usr/libexec/java_home -v 1.6)/bin/java"
# heap, utf8, realm対策
$ export JVM_OPTS="-server -Xmx1024m -Dfile.encoding=UTF-8 -Djava.security.krb5.realm= -Djava.security.krb.kdc="
```

テスト実行

```bash
# project.clj変更時に実行する
$ lein clean

# 依存ファイルのダウンロード
$ lein deps
# テスト
$ lein test
```

問題なければ、サンプルの実行へ

### サンプルをためす
examples以下にある、word-count(word_count.clj)を試す。
ファイル名で「_」を使っている場合の、ネームスペースは「-」になっている場合が多いので気をつける。

```bash
# サンプル実行
$ lein run -m parkour.examples.word-count outputs README.md
# 結果は、標準出力

# フォルダ削除
$ rm -Rf ./outputs
```

```bash
# サンプル、log4j,slf4j,slf4j12,jsr166yをuberjarに追加
$ lein with-profile "examples,provided,java6" uberjar
```

provided追加は、slf4jのバージョン問題のため
providedを外して、「/usr/local/Cellar/hadoop/1.2.1/libexec/lib」以下の
slf4jとslj4j12を1.6.5に上げても良さそう。


## Hadoopスタンドアローン環境設定
[OSXにApache Hadoopをインストール](http://slowquery.hatenablog.com/entry/2013/07/11/014052)を参考に簡潔な設定にした。

```bash
# hadoopをインストール
$ brew install hadoop
```

以下、hadoop 1.2.1の場合。

参照先に追加した変更点

```bash:/usr/local/Cellar/hadoop/1.2.1/libexec/conf/hadoop-env.sh
export JAVA_HOME="$(/usr/libexec/java_home -v 1.6)"

export HADOOP_OPTS="-server -Dfile.encoding=UTF-8 -Djava.security.krb5.realm= -Djava.security.krb.kdc="
```

```bash
# Hadoopサービスの起動
$ start-all.sh
```

```bash
# HDFSにファイル配備
$ hadoop fs -put README.md

# サンプルを実行
# 入出力ともにHDFS上の空間
$ hadoop jar /usr/local/Cellar/hadoop/1.2.1/libexec/hadoop-1.2.1-examples.jar wordcount README.md outputs
# 結果はoutputs/part-r-00000に書き出し

$ hadoop fs -ls .
# 実行結果をHDFSから取得
$ hadoop fs -get outputs/part-r-00000 .

# 確認
$ cat part-r-00000

# フォルダ削除（再実行前に削除が必要）
$ hadoop fs -rmr outputs
```

```bash
# Hadoopサービスの停止（この後使うので必要なし）
$ stop-all.sh
```

## Hadoopスタンドアローン環境でのparkour
[デプロイに関する資料](https://github.com/damballa/parkour/blob/master/doc/deployment.md)など参考にサンプルを動かした。

```bash
# Hadoopサービスの起動
$ start-all.sh
```

gen-class化とaotが未実施のため、clojure.mainから実行する。

```bash
# （上で実施済み）
$ hadoop fs -put README.md

# サンプルを実行
# 入出力ともにHDFS上の空間
$ hadoop jar ./target/parkour-0.5.3-SNAPSHOT-standalone.jar clojure.main -m parkour.examples.word-count outputs-parkour README.md
# 結果は、標準出力

# ls
$ hadoop fs -ls .
# ファイル削除
$ hadoop fs -rmr outputs-parkour
```

```bash
# Hadoopサービスの停止
$ stop-all.sh
```

今回はここまで。

## その他参考資料
[slf4のエラーについて](http://metasearch.sourceforge.jp/wiki/index.php?HCatalog%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%EB#re375f3f)
[Hadoopインストール](http://codezine.jp/article/detail/2485)