Solaris で擬似ファイルシステムをつくろう/其の3(HDFSファイルシステム)
if ($preview) { ?>
print($vars["preview"]); ?>
} ?>
WYSIWYGԽǤΤϡInternet ExplorerMozillaϥ֥饦(Firefoxʤ)ΤߤǤ
̾Խ
#wysiwyg<br/><br/> <h2 id="">Solaris で擬似ファイルシステムをつくろう/其の3(HDFSファイルシステム)</h2> #norelated<br/><br/> <h2 id="">目次 [#v4fc9936]</h2> #contents<br/><br/> <h2 id="">ご注意 [#s352c217]</h2> ここで紹介しているプログラムは、カーネルモジュールを含んでいます。そのため、プログラム上に問題があった場合(可能性大)にはシステムが PANIC し、場合によってはファイルシステムに重大な障害を引き起こす可能性があります。以下のプログラムはテストプログラムで、十分な検証を行ってはいません。したがってあくまで個人の検証ためにお使いいただき、重要なシステム上では動作させないでください。本プログラムの使用により発生したトラブルなど、いかなる損害についても一切の責任を負いかねます。ご利用は自己責任にてお願いいたします。<br/><br/> <h2 id="">概要 [#f863b7fa]</h2> <a href="" rel="nofollow">http://hadoop.apache.org/</a> の <a href="" rel="nofollow">http://hadoop.apache.org/common/docs/current/hdfs_design.html</a> を Solaris 上でマウント可能にする Solaris 用のファイルシステム・モジュールとユーザモードプログラムです。<br /> NFS の様に HDFS をマウントすることができ、一度マウントしてしまえば HDFS 上のディレクトリを cd コマンドで行き来したり、HDFS 上のファイルをローカルファイルの様にオープンして読み込んだり、実行可能ファイルを実行したりできます。また新規ファイルの作成と、追加書き込みもサポートしています。<br/><br/> <blockquote>※ 同様のことが行える FUSE (Filesystem in userland) というものがあります。本気で HDFS をマウントして活用したい!と思っている方はこちらを試したほうが良いかもしれません。(安全と言う意味で)・・・しかしながら、自分の環境ではビルドできなかったので私自身は試せてません(泣)うまくいった方がいたら教えてください。速度比較してみたいです。 <ul class="list1 list-indent1"><li><a href="" rel="nofollow">http://hub.opensolaris.org/bin/view/Project+fuse/</a></li> <li><a href="" rel="nofollow">http://www.google.co.jp/url?sa=t&source=web&ct=res&cd=1&ved=0CBcQFjAA&url=http%3A%2F%2Fwiki.apache.org%2Fhadoop%2FMountableHDFS&ei=zzf2S5GMLJLm7APS_dDyBQ&usg=AFQjCNEQbxmrMGKAETj3FPEw3Lr1PBHz-w&sig2=8J9zNdheaCXlw2UQInMr6g</a></li></ul></blockquote> <h2 id="">ソースファイルとダウンロード [#p0da4166]</h2> 管理の利便性からソースコードは<a href="" rel="nofollow">http://github.com</a> に移動いたしました。<br /> 今後はこちらにアップデートしていきます。ソースコードもこちらからご参照いただけます。(最終更新日 2011/06/08)<br/><br/> <dl class="list1 list-indent1"><dt>ファイルシステムモジュールのソースファイルのダウンロード</dt> <dd><a href="" rel="nofollow">https://github.com/kaizawa/iumfs/tarball/master</a></dd></dl> <dl class="list1 list-indent1"><dt>ユーザモードデーモンプログラムのソースファイルのダウンロード</dt> <dd><a href="" rel="nofollow">https://github.com/kaizawa/iumfs-hdfs/tarball/master</a></dd> <dt>ソースコードの参照</dt> <dd>http://github.com/kaizawa/iumfs <br /> http://github.com/kaizawa/iumfs-hdfs</dd></dl> COLOR(RED){Github へのコードの配置にともない文字コードを UTF-8 に切り替えました}<br/><br/> <h2 id="">動作確認済み Solaris バージョン及びプラットフォーム [#p23d16d4]</h2> このプログラムの動作確認状況は以下のようになっています。<br/><br/> <div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">プラットフォーム<br />Solarisバージョン</td><td class="style_td">Sparc<br />(32bit)</td><td class="style_td">Sparc<br />(64bit)</td><td class="style_td">x86</td><td class="style_td">x64</td></tr><tr><td class="style_td">Solaris10</td><td class="style_td">-</td><td class="style_td">◯</td><td class="style_td">?</td><td class="style_td">?</td></tr><tr><td class="style_td">OpenSolaris</td><td class="style_td">-</td><td class="style_td">?</td><td class="style_td">◯</td><td class="style_td">◯</td></tr><tr><td class="style_td">OpenIndiana 148</td><td class="style_td">-</td><td class="style_td">?</td><td class="style_td">◯</td><td class="style_td">?</td></tr><tr><td class="style_td">Solaris11 express</td><td class="style_td">-</td><td class="style_td">?</td><td class="style_td">◯</td><td class="style_td">?</td></tr><tr><td class="style_td">Solaris11</td><td class="style_td">-</td><td class="style_td">?</td><td class="style_td">?</td><td class="style_td">◯</td></tr></tbody></table></div> <blockquote>○:動作確認済み ×:動作不可 ?:未確認 -:該当なし<br /></blockquote> <h2 id="">プログラムの解説 [#ta6aa97f]</h2> 基本的な考え方は「Solaris で擬似ファイルシステムをつくろう/其の2」の FTP ファイルシステムと同じで、このプログラムはカーネルモジュールであるファイルシステムモジュール兼仮想デバイスドライバと、Java のユーザモードプログラムで構成されています。<br/><br/> <h3 id="">iumfs ファイルシステムモジュール [#b36c5a3a]</h3> ファイルシステムとしての基本的な枠組みは「Solaris で擬似ファイルシステムをつくろう/其の2」と同じです。<br /> モジュールのファイル名は「iumfs」ですが、カーネルに登録するファイルシステムの名称は「hdfs」です。<br/><br/> <h3 id="">iumfscntl デバイスドライバ [#na7df0d0]</h3> こちらも基本的には「Solaris で擬似ファイルシステムをつくろう/其の2」と同じです。<br /> ただ、今回は Java プログラムからアクセスされることを考えて mmap(2) を使ったデータのやりとりをやめ、read(2)、 write(2) だけでデータのやり取りができるように変更しています。また、Java プログラムとのデータの受け渡しが容易になるように、構造体を簡素化し、各メンバのサイズを8の倍数バイトとしています。<br/><br/> <h3 id="">hdfsd ユーザモードデーモンプログラム [#g8c4e78e]</h3> <a href="" rel="nofollow">http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/fs/FileSystem.html</a> を使って HDFS の各データノードからファイルデータを読み込む java で書かれたプログラムです。<br /> このプログラムは起動時に /dev/iumfscntl デバイスをオープンして、カーネル上のファイルシステムモジュールからのリクエストを待ちます。デバイスドライバを通じてファイルデータや属性情報の読み込み要求がくると、hadoop の API を使って HDFS 上のファイルデータや属性情報を取ってきます。取得したデータは再度 /dev/iumfscntl デバイスを通じてファイルシステムモジュールに渡します。この Java プログラムは nio の <a href="" rel="nofollow">http://java.sun.com/javase/ja/6/docs/ja/api/java/nio/ByteBuffer.html</a> を使って /dev/iumfscntl デバイスのからのデータの読み書きを実現しています。JNI は使ってません。(ちょっとこだわり)<br/><br/> <h3 id="">iumfs ファイルシステム用 mount コマンド [#s65b30a4]</h3> iumfs ファイルシステム専用の mount コマンドです。<br /> 其の2とほぼ同じでものです。mount(1M) コマンドが自動的にこのコマンドを見つけて呼び出してくれるため、ユーザはこの iumfs 専用の mount コマンドの存在を意識する必要はありません。ただ -F オプションに「iumfs」を渡し、ファイルシステムを指定すればよいだけです。<br/><br/> <h2 id="">実行環境の要件 [#f19b4629]</h2> このプログラムのコンパイル、及び実行時には以下の要件が満たされている必要があります。<br/><br/> <ol class="list1 list-indent1"><li>Solaris/OpenSolaris([[動作確認済み Solaris バージョン>#p23d16d4]])</li> <li>JDK6 がインストールされている(JRE5.0以前は動作確認してません)</li> <li>hadoop 0.21.0(以降)がインストールされていて、正常に動作している(※)</li> <li>HADOOP_HOME 環境変数に Hadoop のインストールディレクトリがセットされている</li></ol> (※)ここでは説明しきれないので Hadoop のセットアップ方法や動作確認方法は他のサイトの情報をご活用ください。<br/><br/> <h2 id="">インストール [#q0561d17]</h2> <h3 id="">コンパイル&インストール [#re8fcf25]</h3> <h4 id="">カーネルモジュールと mount コマンド [#m2a36a0e]</h4> ファイルシステムモジュールのダウンロードファイルを解凍し、configure, make を実行すると環境に応じて 64bit/32bit のファイルシステムモジュール兼、擬似デバイスドライバであるiumfs モジュールと、mount コマンドが作成されます。コンパイル終了後、make install にてファイルのコピーと、ファイルシステムモジュールのカーネルへのロードが行われます。<br /> OpenSolaris での実行例:<br/><br/> <pre>$ cd kaizawa-iumfs-4f1da99 $ ./configure checking for gcc... no checking for cc... cc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... no checking whether cc accepts -g... yes checking for cc option to accept ISO C89... none needed checking for a BSD-compatible install... /usr/bin/ginstall -c checking for isainfo... yes configure: creating ./config.status config.status: creating Makefile</pre> <pre>$ make cd module ; make gcc -c -DPACKAGE_NAME="IUMFS" -DPACKAGE_TARNAME="iumfs" -DPACKAGE_VERSION="0.1" -DPACKAGE_STRING="IUMFS 0.1.2" -DPACKAGE_BUGREPORT="admin2@whiteboard.ne.jp" -g -O2 -Wall -DOPENSOLARIS -DSOL10 -m64 -mcmodel=kernel -mno-red-zone -D_KERNEL -I. iumfs_vfsops.c -o iumfs_vfsops.o gcc -c -DPACKAGE_NAME="IUMFS" -DPACKAGE_TARNAME="iumfs" -DPACKAGE_VERSION="0.1" -DPACKAGE_STRING="IUMFS 0.1.2" -DPACKAGE_BUGREPORT="admin2@whiteboard.ne.jp" -g -O2 -Wall -DOPENSOLARIS -DSOL10 -m64 -mcmodel=kernel -mno-red-zone -D_KERNEL -I. iumfs_vnops.c -o iumfs_vnops.o :</pre> <blockquote>※ 表示の都合上、一部改行してるところがあります</blockquote> <pre># make install cd module ; make install /bin/ginstall -c -m 0644 -o root -g sys iumfs /kernel/fs/amd64 /bin/ginstall -c -m 0644 -o root -g sys iumfs.conf /usr/kernel/drv : </pre> <blockquote>※ ここだけ root 権限が必要です!</blockquote> <h4 id="">ユーザモードデーモン [#meda3505]</h4> ユーザモードデーモンプログラムのダウンロードファイルにはユーザモードデーモンである hdfsd.jar ファイルが含まれていますので、そのままでも実行することができます。もし、Java コードに変更等を行って再コンパイルしたい場合には "cmd" ディレクトリで ant を実行すると Java のプログラムがコンパイルされ jar ファイルが作成されます。なお、ant 実行の際には HADOOP_HOME 環境変数が設定されている必要があります。$HADOOP_HOME は hadoop がインストールされているディレクトリです。<br/><br/> <pre>$ export HADOOP_HOME=/usr/local/hadoop $ export JAVA_HOME=/usr/java $ cd cmd $ ant Buildfile: build.xml compile: [javac] Compiling 12 source files to /var/tmp/hdfs/cmd/build dist: [jar] Building jar: /var/tmp/hdfs/cmd/hdfsd.jar BUILD SUCCESSFUL Total time: 2 seconds </pre> <h3 id="">アンインストール [#zd68f39b]</h3> ファイルシステムモジュールおよびコマンドのアンインストールは make uninstall で行います。<br /> もし、インストール時に利用した Makefile がすでに無い場合も、以下のログを参考に各コマンドをマニュアルで実行していただければ同じ結果を得られます。<br/><br/> <pre># make uninstall</pre> <blockquote>※ root 権限が必要です</blockquote> hdfs ファイルシステムが利用中(マウントされている)の場合、ファイルの削除は可能ですが、モジュールのアンロードは失敗します。この場合システムのリブート後に完全に削除されます。<br/><br/> <h2 id="">使い方 [#ja8cf0fb]</h2> hdfs ファイルシステムの利用方法についてご説明します。<br/><br/> <blockquote>COLOR(RED){※ hadoop のネームノード、データノードは予め起動されている必要があります!!}<br /></blockquote> 既存ファイルへの追記(Append)を有効にするためには ${HADOOP_HOME}/conf/hdfs-site.xml ファイルに以下のように COLOR(RED){dfs.support.append} プロパティを追記して HDFS を再起動する必要があります。<br/><br/> <pre><property> <name>dfs.support.append</name> <value>true</value> </property> </pre> &nbsp;このプロパティを設定しないで書き込み操作をすると I/O エラー(EIO)が返されて失敗してしまいます。<br/><br/> <pre>$ echo aaa >> hoge -ksh: echo: write to 1 failed [I/O error</pre> <h3 id="">hdfsd デーモンの起動 [#j5e9cc04]</h3> hadoop 各データノードと通信を行う hdfsd デーモンを起動します。<br /> 実際にはこのデーモンの起動と、後述のファイルシステムのマウントの順番は逆でも大丈夫ですが、デーモンを起動していない状態でファイルシステムのマウントしたとしても HDFS 上のファイルは参照できませんし、cd コマンドや ls コマンドは待たされることになります。(現実装ではタイムアウトを設けてませんので、デーモンが起動されるまでずーと待ち続けます。もちろんコマンドをキャンセルすることはできます)<br /> 起動方法:<br /> ユーザモードデーモンプログラムのダウンロードファイルを展開したディレクトリにある start-hdfsd.sh シェルスクリプトを実行します。<br/><br/> <pre>$ ./start-hdfsd.sh</pre> 若しくは、直接 hadoop コマンドを使って hdfsd を実行することもできます。<br/><br/> <pre>% ${HADOOP_HOME}/bin/hadoop -cp ${CLASSPATH} iumfs.hdfs.Main</pre> $HADOO_HOME は Hadoop がインストールされているディレクトリです。<br /> $CLASSPATH には最低でも以下の4つをパスを指定する必要があります。<br/><br/> <ol class="list1 list-indent1"><li>hdfsd.jar ファイルスのパス(ダウンロードファイルに含まれるデーモンプログラム)</li> <li>iumfs-daemon-core-xx.jar (ダウンロードファイルに含まれるライブラリ)</li> <li>hadoop-core-xxx.jar ファイルのパス ファイル(hadoop のメイン jar ファイル)</li> <li>hadoop の設定ファイルが置いてあるディレクトリ のパス</li></ol> 実行例:<br/><br/> <pre>$ hadoop -cp "./cmd/hdfsd.jar:./cmd/lib/iumfs-daemon-core-0.2.0.jar:/usr/local/hadoop/conf:\ /usr/local/hadoop/hadoop-core-1.0.2.jar" iumfs.hdfs.Main</pre> <blockquote>※ 一般ユーザでも起動できるはずですが、もし権限不足で iumfscntl デバイスのオープンに失敗してしまったら、root ユーザで /devices/pseudo/iumfs@0:iumfscntl に読み込み権を与えてください。</blockquote> また、<a href="" rel="nofollow">http://java.sun.com/javase/ja/6/docs/ja/api/java/util/logging/Logger.html</a> の[[設定ファイル>source:fs_3/log.prop]]を用意して、起動時に java.util.logging.config.file プロパティでファイルパスを指定すればデバッグ出力が得られます。Hadoop API 自体のデバッグ情報に加え、hdfsd のデバッグ情報も得られます。<br/><br/> デバッグ実行例:<br/><br/> <pre>$ hadoop -Djava.util.logging.config.file=cmd/log.prop -cp "./cmd/hdfsd.jar:./cmd/lib/iumfs-daemon-core-0.2.0.jar:\ /usr/local/hadoop/conf:/usr/local/hadoop/hadoop-core-1.0.2.jar" iumfs.hdfs.Main 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Successfully open device. 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Started 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Successfully open device. 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Started 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Successfully open device. 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Started 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Successfully open device. 2012/04/30 12:10:50 iumfs.ControlDevicePollingThread run 詳細レベル (低): Started :</pre> ※ 表示の都合上、途中で改行しています。<br/><br/> <h3 id="">ファイルシステムのマウント [#i7948cdf]</h3> iumfs ファイルシステムのマウントには通常の mount(1M) コマンドを利用します。<br /> マウント時にはファイルシステムタイプとして iumfs を指定し、NameNode 名とマウントを行う HDFS 上の元となるディレクトリ(ベースディレクトリ)と、マウントポイントを指定します。<br/><br/> 使い方:<br/><br/> <pre># /usr/sbin/mount -F iumfs hdfs://name_node/base_path mount_point</pre> <dl class="list1 list-indent1"><dt>name_node</dt> <dd>NameNode のホスト名</dd> <dt>base_path</dt> <dd>マウントをする HDFS 上のディレクトリのパスです。(「/」だけでもかまいません)</dd> <dt>mount_point</dt> <dd>hdfs ファイルシステムをマウントするローカルのマウントポイント</dd></dl> <blockquote>※ root 権限が必要です</blockquote> 以下に /mnt ディレクトリに HDFS (NameNode はnamenode.example.com) 上の /user/myname ディレクトリをマウントする例を示します。<br/><br/> <pre># /usr/sbin/mount -F iumfs hdfs://namenode.example.com/user/myname /mnt ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^ NameNode ベース マウントポイント</pre> マウントの確認:<br/><br/> <pre># /usr/sbin/mount : : /mnt on hdfs://namenode.example.com/user/myname read/write/setuid/devices/dev=91c0004 on Wed Jun 8 00:41:35 2011</pre> <h3 id="">可能なファイル操作 [#g8e2a81e]</h3> <h4 id="">ディレクトリの移動、ディレクトリエントリの参照 [#b7167fdb]</h4> <pre>$ cd /mnt/ $ /bin/ls inputs</pre> <h4 id="">各ファイルの属性情報の参照 [#saeda8b3]</h4> <pre>$ /bin/ls -l total 3 drwxr-xr-x 1 root root 0 May 21 23:03 ./ drwxr-xr-x 1 root root 0 May 21 23:03 ../ drwxr-xr-x 1 root root 0 May 21 23:03 inputs/</pre> ファイル属性のうち、ファイルタイプ、ファイルサイズ、ファイルの最終変更日時、あとパーミッションはオリジナルファイルの情報がそのまま反映されますが、ファイルのオーナー情報だけはリモートホスト側の実際のオーナーに関わらず常に<span style="font-style: italic;">root:root</span>と表示されます。<br/><br/> <h4 id="">ファイルの読み込み [#ud041f82]</h4> <pre>$ cd inputs $ cat file1 this is file1 this is file1 this is file1 this is file1 $</pre> <h4 id="">ファイルのコピー [#s3801688]</h4> HDFS からローカルディスクへ<br/><br/> <pre>$ cp file1 /var/tmp $</pre> ローカルディスクから HDFSへ<br/><br/> <pre>$ cp /etc/hosts /mnt</pre> <h3 id="">不可能な操作 [#uc61e2ee]</h3> open,creat,read,write,mkdir,rmdir,getdent,ulink,stat 以外のファイル操作は<span style="font-style: italic;">できません。</span>hdfs ファイルシステム上のファイルに対してこれら以外の操作を行った場合はエラーが返されるか、全く無視されます。<br/><br/> ファイルのアクセス権の変更<br/><br/> <pre>$ chmod 777 file1 $ <-- エラーにはなりませんがアクセス権は変更されません</pre> ファイルの更新日時を変更<br/><br/> <pre>$ <-- エラーにはなりませんがファイルの更新日は変更になりません</pre> ファイルのオーナーを変更<br/><br/> <pre>$ chown nobody file1 $ <-- エラーにはなりませんがオーナーは root のママです。</pre> <h3 id="">ファイルシステムのアンマウント [#t4473c5e]</h3> hdfs ファイルシステムのアンマウントには通常の umount(1M) コマンドを利用します。<br/><br/> <pre>Usage: umount mount_point mount_point : ファイルシステムがマウントされているマウントポイント</pre> 他のファイルシステムでもおなじですが、だれかがそのファイルシステム上のファイルを利用中の場合には BUSY が返り、umount(1M) は失敗します。<br/><br/> アンマウントの成功例)<br/><br/> <pre># umount /mnt #</pre> ファイルシステムが利用中である為にアンマウントが失敗する例)<br/><br/> <pre># pwd /mnt # umount /mnt umount: /mnt 使用中です。</pre> <h2 id="">今後の課題 [#q8d2f3d7]</h2> <ol class="list1 list-indent1"><li>パフォーマンスの向上<br />最初の読み込み時に dfs の copyToLocal と同程度の転送速度が出せるのが目標。(今回の変更でパフォーマンスが向上)</li></ol>
: