# HG changeset patch # User Nobuyasu Oshiro # Date 1392411654 -32400 # Node ID 6f73e05d5024ec4a9a87c12cc5d5de1d8c322b0d # Parent 1d5736ae832f1bd9e6299c1d0d6a837627b560fb Fixed chapter4.tex diff -r 1d5736ae832f -r 6f73e05d5024 paper/chapter4.tex --- a/paper/chapter4.tex Sat Feb 15 04:47:28 2014 +0900 +++ b/paper/chapter4.tex Sat Feb 15 06:00:54 2014 +0900 @@ -1,5 +1,5 @@ \chapter{木構造データベースJungleの分散実装} -前章では Jungle のアーキテクチャと分散設計について説明した. + 前章では Jungle のアーキテクチャと分散設計について説明した. トポロジーの形成と他サーバノードのデータのアクセス方法には Alice を使用する. また, Jungle ではデータ編集のログとして TreeOperationLog がある. この TreeOperationLog を Alice により他サーバノードへ送ることでデータの分散を行う. @@ -17,7 +17,7 @@ \subsection{トポロジーマネージャーの起動} Alice を用いてサーバノードでトポロジーの形成を行う方法を述べる. -Alice のトポロジーマネージャーの起動は\ref{src:alice_ntm_run}の様に行う. +Alice のトポロジーマネージャーの起動はソースコード\ref{src:alice_ntm_run}の様に行う. \begin{lstlisting}[frame=lrbt,label=src:alice_ntm_run,caption=Alice によるネットワークトポロジーマネージャーの起動,numbers=left] % java -cp Alice.jar alice.topology.manager.TopologyManager -p 10000 -conf ./topology/tree5.dot \end{lstlisting} @@ -25,7 +25,7 @@ ポート番号は Alice により記述された並列分散プログラムの起動時に渡す必要がある. dot ファイルには, トポロジーをどのように形成するかが書かれている. -以下に, サーバノード数5で, 2分木ツリー構造を形成する dot ファイルの例を示す(\ref{src:alice_dot}). +以下に, サーバノード数5で, 2分木ツリー構造を形成する dot ファイルの例を示す(ソースコード\ref{src:alice_dot}). \newpage \begin{lstlisting}[frame=lrbt,label=src:alice_dot,caption=ネットワークトポロジー設定用 dot ファイル,numbers=left] % cat tree5.dot @@ -71,7 +71,7 @@ \subsection{アプリケーション側の記述} 次は Jungle 側のプログラムが最初に Alice のトポロジーノードと通信を行うようにする. -そのためには Alice の TopologyNode クラスに必要な情報を渡してインスタンスを生成する(\ref{src:app_start}). +そのためには Alice の TopologyNode クラスに必要な情報を渡してインスタンスを生成する(ソースコード\ref{src:app_start}). \begin{lstlisting}[frame=lrbt,label=src:app_start,caption=アプリケーションの起動,numbers=left] public static void main( String[] args ) throws Exception { @@ -88,7 +88,7 @@ アプリケーションの起動時にはコンフィグの情報として, トポロジーマネージャーが動いているサーバのドメインとポート番号を 渡す必要がある. 例えば, mass00.cs.ie.u-ryukyu.ac.jp というサーバ上でポート番号10000を指定してトポロジーマネージャーを -起動した場合は次のようになる(\ref{src:run_program}). +起動した場合は次のようになる(ソースコード\ref{src:run_program}). \begin{lstlisting}[frame=lrbt,label=src:run_program,caption=トポロジーマネージャーの利用,numbers=left] % java Program -host mass00.cs.ie.u-ryukyu.ac.jp -port 10000 \end{lstlisting} @@ -97,7 +97,7 @@ Aliceのポロジー形成と他のサーバのデータへのアクセスする機構を用いるためには, Aliceが 提供するプログラミングスタイルに沿わなければならない. それはDataSegment(データ)とCodeSegment(タスク)によるプログラムである. -ここではまずDataSegmentとCodeSegmentによるプログラムの方法について説明し, 他サーバとの +ここではまず, DataSegmentとCodeSegmentによるプログラムの方法について説明し, 他サーバとの 通信部分の実装について述べる. \subsection{Alice によるプログラミング} @@ -105,7 +105,7 @@ CodeSegmentには計算に必要なDataSegmentが登録される. そしてDataSegmentが準備され次第CodeSegmentによる計算が実行される. DataSegmentの取得は文字列のキーを使うことで行える. -コード\ref{src:cs_sample}にCodeSegmentの例を示す. +ソースコード\ref{src:cs_sample}にCodeSegmentの例を示す. \newpage \begin{lstlisting}[frame=lrbt,label=src:cs_sample,caption=CodeSegmentの実行,numbers=left] public class TestCodeSegment extends CodeSegment { @@ -147,7 +147,7 @@ putによりキー"count"に登録された数値0はReceiverであるdsを使って取ることができる. 7行目から13行目では\verb|ds.asInteger()|により, "count"に登録したデータの中身を受け取りインクリメントし出力する. -そして最後には\verb|ods.put|を行っている. +そして, 最後には\verb|ods.put|を行っている. 新たなTestCodeSegmentも生成しており, これはインクリメントされた"count"がputされることで実行される. この一連の処理を"count"の数値が10以上になるまで行う. @@ -182,15 +182,14 @@ 他サーバノードを示す文字列のキーとは図\ref{fig:remote_cs}に矢印の隣に書かれている文字列 "parent", "child1", "child2" のことを指す. 例えば, server node0 が server node1のDataSegmentに入っている"count"というデータを -を使用したい場合は, 次のようにsetKeyを行えばよい(\ref{src:remote_cs1}). +を使用したい場合は, 次のようにsetKeyを行えばよい(ソースコード\ref{src:remote_cs1}). \begin{lstlisting}[frame=lrbt,label=src:remote_cs1,caption=CodeSegmentで他サーバノードのDataSegmentを使用する,numbers=left] CodeSegment cs = new RemoteCodeSegment(); cs.arg1.setKey("child1", "count"); \end{lstlisting} -また, 他サーバノードのDataSegmentにデータを送りたい場合は, putを行うときにサーバノードへのキーを + また, 他サーバノードのDataSegmentにデータを送りたい場合は, putを行うときにサーバノードへのキーを 追加すればよい. -例として, server node1やserver node2がserver node0のDataSegmentに"message"というキーでデータを追加したい場合 -次のようになる(\ref{src:remote_cs2}). +例として, server node1やserver node2がserver node0のDataSegmentに"message"というキーでデータを追加したい場合は, 次のようになる(ソースコード\ref{src:remote_cs2}). \begin{lstlisting}[frame=lrbt,label=src:remote_cs2,caption=他サーバーノードのDatasSegmentにデータを追加する,numbers=left] ods.put("parent", "message", "Hello parent"); \end{lstlisting} @@ -205,7 +204,7 @@ MessagePackによりシリアライズとなるクラスはいくつか制限がある. それはそのクラスに@Messageアノテーションを付けることと, そのクラスが保持するフィールドが MessagePackによりシリアライズ可能であることである. -例えば次のようなクラスである. +例えば次のようなクラスである(ソースコード\ref{src:msgpack1}). \begin{lstlisting}[frame=lrbt,label=src:msgpack1,caption=MessagePackによりシリアライズ可能なクラス1,numbers=left] import org.msgpack.annotation.Message @@ -215,9 +214,9 @@ int age; } \end{lstlisting} -上記のStudentクラスはプリミティブ型しか保持していない. + 上記のStudentクラスはプリミティブ型しか保持していない. そのためシリアライズが可能である -また, 次のようなクラスもシリアライズ可能な型となる. +また, 次のようなクラスもシリアライズ可能な型となる(ソースコード\ref{src:msgpack2}). \begin{lstlisting}[frame=lrbt,label=src:msgpack2,caption=MessagePackによりシリアライズ可能なクラス2,numbers=left] import org.msgpack.annotation.Message @@ -226,7 +225,7 @@ List studentList; } \end{lstlisting} -この場合, フィールドはプリミティブな型でないStudentクラスのフィールドを保持している. + この場合, フィールドはプリミティブな型でないStudentクラスのフィールドを保持している. しかし, Studentクラスはシリアライズ可能な形で作成しているため, クラスのフィールドとして 保持しても問題はない. @@ -234,12 +233,12 @@ をputすることができる. DataSegmentから受け取ったデータはそのままではシリアライズされたものため, 一度手元で 元のクラスにコンバートすることで扱う. -例として, AliceにおけるStudenクラス(Listing\ref{src:msgpack1})のコンバートを次に示す. +例として, AliceにおけるStudenクラスのコンバートを次に示す(ソースコード\ref{src:msgpack1}). \begin{lstlisting}[frame=lrbt,label=src:msgpack3,caption=DataSegment,numbers=left] // public Receiver arg1 = ids.create(CommandType.PEEK); Student s = arg1.asClass(Student.class); \end{lstlisting} -MessagePackでシリアライズ可能な形としているためDataSegmentはネットワークを介して + MessagePackでシリアライズ可能な形としているためDataSegmentはネットワークを介して 送受信が可能である. @@ -272,7 +271,7 @@ % 木がなければそのばでつくるようにした \subsection{NetworkTreeOperationLogの実装} -NetworkTreeOperationLogの実装の一部を以下(\ref{src:netlog})に示す. +NetworkTreeOperationLogの実装の一部を以下(図\ref{src:netlog})に示す. \begin{lstlisting}[frame=lrbt,label=src:netlog,caption=NetworkTreeOperationが持つフィールド,numbers=left] @Message public class NetworkTreeOperationLog implements TreeOperationLog @@ -297,15 +296,15 @@ あることだ. そのため, \verb|ods.put|を行うのは別のThreadにしたほうがよい. 以下のコードはcommitに成功した後に, NetworkTreeOperationへと変換したログを別スレッドに渡し -て処理させるコードである. +て処理させるコードである(ソースコード\ref{src:logconvert_and_execute}). \begin{lstlisting}[frame=lrbt,label=src:logconvert_and_execute,caption=NetworkTreeOperationをputするために別スレッドを立ち上げる,numbers=left] NetworkTreeOperationLog netLog = new NetworkTreeOperationLog(_uuid, _treeName,newLog); CodeSegment cs = new LogPutCodeSegment(netLog); cs.execute(); \end{lstlisting} -LogPutCodeSegmentの実装は次のようになっている. -\begin{lstlisting}[frame=lrbt,label=src:,caption=putを行うためだけのCodeSegmentの用意,numbers=left] +LogPutCodeSegmentの実装は次のようになっている(ソースコード\ref{src:logputcs}). +\begin{lstlisting}[frame=lrbt,label=src:logputcs,caption=putを行うためだけのCodeSegmentの用意,numbers=left] public class LogPutCodeSegment extends CodeSegment{ NetworkTreeOperationLog log; public LogPutCodeSegment(NetworkTreeOperationLog _log) { @@ -317,7 +316,7 @@ } } \end{lstlisting} -上で述べた問題は, ベンチマークテストなど, 大量の負荷をかけたさいに発生する. + 上で述べた問題は, ベンチマークテストなど, 大量の負荷をかけたさいに発生する. 負荷とはJungleのデータに変更が加わることである. 多数のデータの変更により大量のログが生成される. そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが @@ -331,7 +330,7 @@ 他サーバノードに対してデータを送るときに必要なことは, そのサーバノードのDataSegmentにアクセスする キーである. Aliceでは接続を行っている相手のDataSegmentのキーのリストは"\_CLIST"キーを使うことで取得することができる. -"\_CLIST"キーで得られるリストを使って他サーバノードへとデータをputするコードを次に示す. +"\_CLIST"キーで得られるリストを使って他サーバノードへとデータをputするコードを次に示す(ソースコード\ref{src:log_put}). \newpage \begin{lstlisting}[frame=lrbt,label=src:log_put,caption=他サーバノードへのログの送信部分,numbers=left] @@ -350,7 +349,7 @@ } : \end{lstlisting} -12行目の\verb|ods.put(node, log.key, log.getVal())|が他サーバノードへデータを送る部分になる. + 12行目の\verb|ods.put(node, log.key, log.getVal())|が他サーバノードへデータを送る部分になる. 変数logにはNetworTreeOperationLogが入っている. 変数listには"\_CLIST"により得られたデータが入っている. それは文字列のListとなっている. @@ -361,12 +360,11 @@ の文字列のListとなっている. もし子どもとなるサーバノードがないときは"parent"だけがListには入れられる. - \subsection{ログの受信とデータ反映} 次は受け取ったログからデータの編集を行う部分の実装を行う. Jungleはのデータを変更する手段として木構造データ毎にTreeEditorクラスが提供される. このTreeEditorを使用し, ログに入っているTreeOperationを1つ1つ取り出し同じ編集を行わせる. -例えば次のようになる. +例えば次のようになる(ソースコード\ref{src:data_edit}). \begin{lstlisting}[frame=lrbt,label=src:data_edit,caption=ログを受け取ってのデータの反映,numbers=left] // Receiver log <- "log"キーから取得できるデータが入っている // Jungle jugnle @@ -384,9 +382,9 @@ editor = either.b(); } \end{lstlisting} -7行目で取り出されたTreeOperationからさらにNodePathとNodeOperationを取り出しているのが8行目と9行目になる. + 7行目で取り出されたTreeOperationからさらにNodePathとNodeOperationを取り出しているのが8行目と9行目になる. 最後にedit関数にTreeEditorとNodePath, それとNodeOpeartionを引き渡している. -edit関数は次のようになる. +edit関数は次のようになる(ソースコード\ref{src:data_edit2}). \begin{lstlisting}[frame=lrbt,label=src:data_edit2,caption=edit関数の実装,numbers=left] Either edit(JungleTreeEditor editor, NodePath path, NodeOperation nodeOp, int pos) { @@ -406,7 +404,7 @@ return editor.deleteChildAt(path, 0); } \end{lstlisting} -NodeOperationのAPIの種類(Command)毎に使用するTreeEditorのAPIを変えている. + NodeOperationのAPIの種類(Command)毎に使用するTreeEditorのAPIを変えている. もしNodeOperationのAPIの種類を増えるようなことが合っても, 上記のコードのように 対応するTreeEditorのAPIを書くことで対応できる. @@ -423,7 +421,7 @@ NetworkTreeOperationLogの実装を行った. つまり, WriterでNetworkTreeOperationLogを書き出すようにすればよい. -以下にログをディスクへ書き出すためのクラスPersistentChangeListWriterの実装を示す. +以下にログをディスクへ書き出すためのクラスPersistentChangeListWriterの実装を示す(ソースコード\ref{src:writer}). \begin{lstlisting}[frame=lrbt,label=src:writer,caption=NetworkTreeOperationをディスクへ書き出す,numbers=left] public class PersistentChangeListWriter implements ChangeListWriter { @@ -449,7 +447,7 @@ return Result.FAILED; } \end{lstlisting} -write関数はJungleのデータ編集が完了すると呼び出される関数である. + write関数はJungleのデータ編集が完了すると呼び出される関数である. 引数として渡されているChangeListはTreeOperationLogと同じく\verb|Iterable|を継承している. またUUIDや木の名前も取得することができる. そのため, NetworkTreeOperationLogへと変換が行える. @@ -457,7 +455,7 @@ ログの書き出しを行いたいときはこのPersistentChangeListWriterを設定することで行えるようになった. これにより木の編集が行われるたびにNetworkTreeOperationLogが書き込まれていく. 読み込みたいときはMessagePackを使ってディスクから読み込み, データ分散実装と同じの方法で木の編集を行っていく -ことができる(Listing\ref{src:data_edit}, \ref{src:data_edit2}). +ことができる(ソースコード\ref{src:data_edit}, \ref{src:data_edit2}). \newpage diff -r 1d5736ae832f -r 6f73e05d5024 paper/master_paper.pdf Binary file paper/master_paper.pdf has changed