comparison paper/chapter4.tex @ 115:eac8620cf9cd

Fixed spell miss
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Wed, 05 Mar 2014 19:54:34 +0900
parents d116e59fc8a2
children d45899154815
comparison
equal deleted inserted replaced
114:d116e59fc8a2 115:eac8620cf9cd
52 誰に接続を行えばよいかを訪ねる. 52 誰に接続を行えばよいかを訪ねる.
53 トポロジーマネージャーは訪ねてきたサーバノードに対してノード番号を割り振り, dot ファイル 53 トポロジーマネージャーは訪ねてきたサーバノードに対してノード番号を割り振り, dot ファイル
54 に記述している通りにサーバノード同士が接続を行うよう指示をだす. 54 に記述している通りにサーバノード同士が接続を行うよう指示をだす.
55 55
56 トポロジーマネージャーは接続要求先を聞いてくるサーバノードに対して名前を割り振り, 接続相手を伝える. 56 トポロジーマネージャーは接続要求先を聞いてくるサーバノードに対して名前を割り振り, 接続相手を伝える.
57 dot ファイル\ref{src:alice_dot}により形成されるトポロジーを図\ref{fig:tree_topology}に示す. 57 ソースコード\ref{src:alice_dot}のdotファイルにより形成されるトポロジーを図\ref{fig:tree_topology}に示す.
58 58
59 59
60 \begin{figure}[htpb] 60 \begin{figure}[htpb]
61 \begin{center} 61 \begin{center}
62 \includegraphics[scale=0.70]{figures/tree_topology_noarrow.pdf} 62 \includegraphics[scale=0.70]{figures/tree_topology_noarrow.pdf}
94 \end{lstlisting} 94 \end{lstlisting}
95 95
96 \section{Alice を用いての分散実装} 96 \section{Alice を用いての分散実装}
97 Aliceのポロジー形成と他のサーバのデータへのアクセスする機構を用いるためには, Aliceが 97 Aliceのポロジー形成と他のサーバのデータへのアクセスする機構を用いるためには, Aliceが
98 提供するプログラミングスタイルに沿わなければならない. 98 提供するプログラミングスタイルに沿わなければならない.
99 それはDataSegment(データ)とCodeSegment(タスク)によるプログラムである. 99 それはDataSegmentとCodeSegmentによるプログラムである.
100 ここではまず, DataSegmentとCodeSegmentによるプログラムの方法について説明し, 他サーバとの 100 ここではまず, DataSegmentとCodeSegmentによるプログラムの方法について説明し, 他サーバとの
101 通信部分の実装について述べる. 101 通信部分の実装について述べる.
102 102
103 \subsection{Alice によるプログラミング} 103 \subsection{Alice によるプログラミング}
104 AliceはDataSegment(データ)とCodeSegment(タスク)単位でプログラミングを行うことを述べた. 104 AliceはDataSegment(データ)とCodeSegment(タスク)単位でプログラミングを行う.
105 CodeSegmentには計算に必要なDataSegmentが登録される. 105 CodeSegmentには計算に必要なDataSegmentが登録される.
106 そしてDataSegmentが準備され次第CodeSegmentによる計算が実行される. 106 そしてDataSegmentが準備され次第CodeSegmentによる計算が実行される.
107 DataSegmentの取得は文字列のキーを使うことで行える. 107 DataSegmentの取得は文字列のキーを使うことで行える.
108 ソースコード\ref{src:cs_sample}にCodeSegmentの例を示す. 108 ソースコード\ref{src:cs_sample}にCodeSegmentの例を示す.
109 \newpage 109 \newpage
110 \begin{lstlisting}[frame=lrbt,label=src:cs_sample,caption=CodeSegmentの実行,numbers=left] 110 \begin{lstlisting}[frame=lrbt,label=src:cs_sample,caption=CodeSegmentの実行,numbers=left]
111 public class TestCodeSegment extends CodeSegment { 111 public class TestCodeSegment extends CodeSegment {
112 public Receiver arg1 = ids.create(CommandType.TAKE); 112 public Receiver arg1 = ids.create(CommandType.TAKE);
113 113
114 public TestCodeSegment() { } 114 public TestCodeSegment() { }
115 115
116 public void run() { 116 public void run() {
117 int count = ds.asInteger(); 117 int count = arg1.asInteger();
118 count++; 118 count++;
119 System.out.println("count = "+count); 119 System.out.println("count = "+count);
120 if(c > 10) { exit(0); } 120 if(c > 10) { exit(0); }
121 CodeSegment cs = new TestCodeSegment(); 121 CodeSegment cs = new TestCodeSegment();
122 cs.setKey("count"); 122 cs.setKey("count");
128 cs.arg1.setKey("local", "count"); // setKey API 128 cs.arg1.setKey("local", "count"); // setKey API
129 cs.ods.put("local", "count", 0); 129 cs.ods.put("local", "count", 0);
130 } 130 }
131 } 131 }
132 \end{lstlisting} 132 \end{lstlisting}
133 コードの説明を行う. 133  ソースコード\ref{src:cs_sample}の説明を行う.
134 このプログラムは, 数字を1から10まで出力を行い終了するプログラムである. 134 このプログラムは, 数字を1から10まで出力を行い終了するプログラムである.
135 17行目から19行目の処理が最初に行われる. 135 17行目から19行目の処理が最初に行われる.
136 まずTestCodeSegmentというCodeSegmentのインスタンスcsを生成する. 136 まずTestCodeSegmentというCodeSegmentのインスタンスcsを生成する.
137 csはarg1というReceiverクラスのフィールドを保持しており, Receiverクラスは 137 csはarg1というReceiverクラスのフィールドを保持しており, Receiverクラスは
138 DataSegmentを受けとるためのクラスである. 138 DataSegmentを受けとるためのクラスである.
143 143
144 データの登録は\verb|ods.put|により行える. 144 データの登録は\verb|ods.put|により行える.
145 上記のコード19行目ではputにより"count"をキーとして数値の0を登録している. 145 上記のコード19行目ではputにより"count"をキーとして数値の0を登録している.
146 putがされるとcsの計算が始まり別スレッドにより8行目からの処理が行われる. 146 putがされるとcsの計算が始まり別スレッドにより8行目からの処理が行われる.
147 147
148 putによりキー"count"に登録された数値0はReceiverであるdsを使って取ることができる. 148 putによりキー"count"に登録された数値0はReceiverであるarg1を使って取ることができる.
149 7行目から13行目では\verb|ds.asInteger()|により, "count"に登録したデータの中身を受け取りインクリメントし出力する. 149 7行目から13行目では\verb|arg1.asInteger()|により, "count"に登録したデータの中身を受け取りインクリメントし出力する.
150 そして, 最後には\verb|ods.put|を行っている. 150 そして, 最後には\verb|ods.put|を行っている.
151 新たなTestCodeSegmentも生成しており, これはインクリメントされた"count"がputされることで実行される. 151 新たなTestCodeSegmentも生成しており, これはインクリメントされた"count"がputされることで実行される.
152 この一連の処理を"count"の数値が10以上になるまで行う. 152 この一連の処理を"count"の数値が10以上になるまで行う.
153 153
154 DataSegmentへデータの追加とCodeSegmentの実行について表した図\ref{fig:testcodesegment}になる. 154 DataSegmentへデータの追加とCodeSegmentの実行について表した図\ref{fig:testcodesegment}になる.
213 String name; 213 String name;
214 int age; 214 int age;
215 } 215 }
216 \end{lstlisting} 216 \end{lstlisting}
217  上記のStudentクラスはプリミティブ型しか保持していない. 217  上記のStudentクラスはプリミティブ型しか保持していない.
218 そのためシリアライズが可能である 218 そのためシリアライズが可能である.
219 また, 次のようなクラスもシリアライズ可能な型となる(ソースコード\ref{src:msgpack2}). 219 また, 次のようなクラスもシリアライズ可能な型となる(ソースコード\ref{src:msgpack2}).
220 \begin{lstlisting}[frame=lrbt,label=src:msgpack2,caption=MessagePackによりシリアライズ可能なクラス2,numbers=left] 220 \begin{lstlisting}[frame=lrbt,label=src:msgpack2,caption=MessagePackによりシリアライズ可能なクラス2,numbers=left]
221 import org.msgpack.annotation.Message 221 import org.msgpack.annotation.Message
222 222
223 @Message 223 @Message
225 List<Student> studentList; 225 List<Student> studentList;
226 } 226 }
227 \end{lstlisting} 227 \end{lstlisting}
228  この場合, フィールドはプリミティブな型でないStudentクラスのフィールドを保持している. 228  この場合, フィールドはプリミティブな型でないStudentクラスのフィールドを保持している.
229 しかし, Studentクラスはシリアライズ可能な形で作成しているため, クラスのフィールドとして 229 しかし, Studentクラスはシリアライズ可能な形で作成しているため, クラスのフィールドとして
230 保持しても問題はない. 230 保持しても問題ない.
231 231
232 これらの制約にそった形で作成しDataSegmentにネットワークを介してクラスのインスタンス 232 これらの制約にそった形で作成しDataSegmentにネットワークを介してクラスのインスタンス
233 をputすることができる. 233 をputすることができる.
234 DataSegmentから受け取ったデータはそのままではシリアライズされたものため, 一度手元で 234 DataSegmentから受け取ったデータはそのままではシリアライズされたものなため, 一度手元で
235 元のクラスにコンバートすることで扱う. 235 元のクラスにコンバートすることで扱う.
236 例として, AliceにおけるStudenクラスのコンバートを次に示す(ソースコード\ref{src:msgpack1}). 236 例として, AliceにおけるStudenクラスのコンバートを次に示す(ソースコード\ref{src:msgpack1}).
237 \begin{lstlisting}[frame=lrbt,label=src:msgpack3,caption=DataSegment,numbers=left] 237 \begin{lstlisting}[frame=lrbt,label=src:msgpack3,caption=DataSegment,numbers=left]
238 // public Receiver arg1 = ids.create(CommandType.PEEK); 238 // public Receiver arg1 = ids.create(CommandType.PEEK);
239 Student s = arg1.asClass(Student.class); 239 Student s = arg1.asClass(Student.class);
269 % TreeOperationLog に木の名前の情報がない 269 % TreeOperationLog に木の名前の情報がない
270 % そのため木の名前を追加して持たせた 270 % そのため木の名前を追加して持たせた
271 % 木がなければそのばでつくるようにした 271 % 木がなければそのばでつくるようにした
272 272
273 \subsection{NetworkTreeOperationLogの実装} 273 \subsection{NetworkTreeOperationLogの実装}
274 NetworkTreeOperationLogの実装の一部を以下(図\ref{src:netlog})に示す. 274 NetworkTreeOperationLogの実装の一部を以下(ソースコード\ref{src:netlog})に示す.
275 \begin{lstlisting}[frame=lrbt,label=src:netlog,caption=NetworkTreeOperationが持つフィールド,numbers=left] 275 \begin{lstlisting}[frame=lrbt,label=src:netlog,caption=NetworkTreeOperationが持つフィールド,numbers=left]
276 @Message 276 @Message
277 public class NetworkTreeOperationLog implements TreeOperationLog 277 public class NetworkTreeOperationLog implements TreeOperationLog
278 { 278 {
279 public LinkedList<NetworkTreeOperation> list; 279 public LinkedList<NetworkTreeOperation> list;
302 CodeSegment cs = new LogPutCodeSegment(netLog); 302 CodeSegment cs = new LogPutCodeSegment(netLog);
303 cs.execute(); 303 cs.execute();
304 \end{lstlisting} 304 \end{lstlisting}
305 305
306 LogPutCodeSegmentの実装は次のようになっている(ソースコード\ref{src:logputcs}). 306 LogPutCodeSegmentの実装は次のようになっている(ソースコード\ref{src:logputcs}).
307 \begin{lstlisting}[frame=lrbt,label=src:logputcs,caption=putを行うためだけのCodeSegmentの用意,numbers=left] 307 \begin{lstlisting}[frame=lrbt,label=src:logputcs,caption=putを行うためのCodeSegmentの用意,numbers=left]
308 public class LogPutCodeSegment extends CodeSegment{ 308 public class LogPutCodeSegment extends CodeSegment{
309 NetworkTreeOperationLog log; 309 NetworkTreeOperationLog log;
310 public LogPutCodeSegment(NetworkTreeOperationLog _log) { 310 public LogPutCodeSegment(NetworkTreeOperationLog _log) {
311 log = _log; 311 log = _log;
312 } 312 }
314 public void run() { 314 public void run() {
315 ods.put("log", log); 315 ods.put("log", log);
316 } 316 }
317 } 317 }
318 \end{lstlisting} 318 \end{lstlisting}
319  上で述べた問題は, ベンチマークテストなど, 大量の負荷をかけたさいに発生する. 319  上で述べた問題は, ベンチマークテストなど, 大量の負荷をかけた際に発生する.
320 負荷とはJungleのデータに変更が加わることである. 320 負荷とはJungleのデータに変更が加わることである.
321 多数のデータの変更により大量のログが生成される. 321 多数のデータの変更により大量のログが生成される.
322 そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが 322 そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが
323 悪くなっていた. 323 悪くなっていた.
324 \verb|ods.put|を行うタイミングには気をつけなければず, 上記のコードにしても改良の余地はある. 324 \verb|ods.put|を行うタイミングには気をつけなければず, 上記のコードにしても改良の余地はある.
347 for (String node : list) { 347 for (String node : list) {
348 ods.put(node, log.key, log.getVal()); // Send datasegment to other node 348 ods.put(node, log.key, log.getVal()); // Send datasegment to other node
349 } 349 }
350 : 350 :
351 \end{lstlisting} 351 \end{lstlisting}
352 12行目の\verb|ods.put(node, log.key, log.getVal())|が他サーバノードへデータを送る部分になる. 352  12行目の\verb|ods.put(node, log.key, log.getVal())|が他サーバノードへデータを送る部分になる.
353 変数logにはNetworTreeOperationLogが入っている. 353 変数logにはNetworTreeOperationLogが入っている.
354 変数listには"\_CLIST"により得られたデータが入っている. 354 変数listには"\_CLIST"により得られたデータが入っている.
355 それは文字列のListとなっている. 355 それは文字列のListとなっている.
356 listの中身を1つずつ受け取り, \verb|ods.put|する際に引数として渡してやることで, 他サーバノードの 356 listの中身を1つずつ受け取り, \verb|ods.put|する際に引数として渡してやることで, 他サーバノードの
357 DataSegmentにアクセスが行える. 357 DataSegmentにアクセスが行える.
360 の文字列のListとなっている. 360 の文字列のListとなっている.
361 もし子どもとなるサーバノードがないときは"parent"だけがListには入れられる. 361 もし子どもとなるサーバノードがないときは"parent"だけがListには入れられる.
362 362
363 \subsection{ログの受信とデータ反映} 363 \subsection{ログの受信とデータ反映}
364 次は受け取ったログからデータの編集を行う部分の実装を行う. 364 次は受け取ったログからデータの編集を行う部分の実装を行う.
365 Jungleはのデータを変更する手段として木構造データ毎にTreeEditorクラスが提供される. 365 Jungleはデータを変更する手段として木構造データ毎にTreeEditorクラスを提供している.
366 このTreeEditorを使用し, ログに入っているTreeOperationを1つ1つ取り出し同じ編集を行わせる. 366 このTreeEditorを使用し, ログに入っているTreeOperationを1つ1つ取り出し同じ編集を行わせる.
367 例えば次のようになる(ソースコード\ref{src:data_edit}). 367 例えば次のようになる(ソースコード\ref{src:data_edit}).
368 \begin{lstlisting}[frame=lrbt,label=src:data_edit,caption=ログを受け取ってのデータの反映,numbers=left] 368 \begin{lstlisting}[frame=lrbt,label=src:data_edit,caption=ログを受け取ってのデータの反映,numbers=left]
369 // Receiver log <- "log"キーから取得できるデータが入っている 369 // Receiver log <- "log"キーから取得できるデータが入っている
370 // Jungle jugnle 370 // Jungle jugnle
371 // Either<Error,JungleTreeEditor> either
371 NetworkTreeOperationLog netLog = log.asClass(NetworkTreeOperationLog.class); 372 NetworkTreeOperationLog netLog = log.asClass(NetworkTreeOperationLog.class);
372 String treeName = netLog.getTreeName(); 373 String treeName = netLog.getTreeName();
373 JungleTree tree = jungle.getTreeByName(treeName); 374 JungleTree tree = jungle.getTreeByName(treeName);
374 TreeEditor editor = tree.getLocalTreeEditor(); // Editor の取得 375 TreeEditor editor = tree.getLocalTreeEditor(); // Editor の取得
375 for (TreeOperation op : netlog) { 376 for (TreeOperation op : netlog) {
380 // エラー処理.編集失敗 381 // エラー処理.編集失敗
381 } 382 }
382 editor = either.b(); 383 editor = either.b();
383 } 384 }
384 \end{lstlisting} 385 \end{lstlisting}
385  7行目で取り出されたTreeOperationからさらにNodePathとNodeOperationを取り出しているのが8行目と9行目になる. 386  8行目で取り出されたTreeOperationからさらにNodePathとNodeOperationを取り出しているのが9行目と10行目になる.
386 最後にedit関数にTreeEditorとNodePath, それとNodeOpeartionを引き渡している. 387 最後にedit関数にTreeEditorとNodePath, それとNodeOpeartionを引き渡している.
387 edit関数は次のようになる(ソースコード\ref{src:data_edit2}). 388 edit関数は次のようになる(ソースコード\ref{src:data_edit2}).
388 \begin{lstlisting}[frame=lrbt,label=src:data_edit2,caption=edit関数の実装,numbers=left] 389 \begin{lstlisting}[frame=lrbt,label=src:data_edit2,caption=edit関数の実装,numbers=left]
389 Either<Error, JungleTreeEditor> edit(JungleTreeEditor editor, NodePath path, 390 Either<Error, JungleTreeEditor> edit(JungleTreeEditor editor, NodePath path,
390 NodeOperation nodeOp, int pos) { 391 NodeOperation nodeOp, int pos) {
452 またUUIDや木の名前も取得することができる. 453 またUUIDや木の名前も取得することができる.
453 そのため, NetworkTreeOperationLogへと変換が行える. 454 そのため, NetworkTreeOperationLogへと変換が行える.
454 455
455 ログの書き出しを行いたいときはこのPersistentChangeListWriterを設定することで行えるようになった. 456 ログの書き出しを行いたいときはこのPersistentChangeListWriterを設定することで行えるようになった.
456 これにより木の編集が行われるたびにNetworkTreeOperationLogが書き込まれていく. 457 これにより木の編集が行われるたびにNetworkTreeOperationLogが書き込まれていく.
457 読み込みたいときはMessagePackを使ってディスクから読み込み, データ分散実装と同じの方法で木の編集を行っていく 458 読み込みたいときはMessagePackを使ってディスクから読み込み, データ分散実装と同じ方法で木の編集を行っていく
458 ことができる(ソースコード\ref{src:data_edit}, \ref{src:data_edit2}). 459 ことができる.
459 460
460 461
461 \newpage 462 \newpage
462 \section{Mergeの実装} 463 \section{Mergeの実装}
463 Jungle に分散実装を行った後の問題としてデータ衝突がある. 464 Jungle に分散実装を行った後の問題としてデータ衝突がある.
504 \newpage 505 \newpage
505 506
506 \subsection{掲示板プログラムにおけるMerge} 507 \subsection{掲示板プログラムにおけるMerge}
507 508
508 図\ref{fig:merge_imp2}の server node0 の木の状態にするのが理想である. 509 図\ref{fig:merge_imp2}の server node0 の木の状態にするのが理想である.
509 掲示板のへの書き込みの表示は, 書き込みされた時間が早い順に表示されるようにしたい. 510 掲示板への書き込みの表示は, 書き込みされた時間が早い順に表示されるようにしたい.
510 これを timestamp を利用することで行う. 511 これを timestamp を利用することで行う.
511 他サーバノードから来たデータに関しては, timestamp を参照し, 次に自分の保持している 512 他サーバノードから来たデータに関しては, timestamp を参照し, 次に自分の保持している
512 木の子ノードの timestamp と比べていくことでデータの追加する場所を決める. 513 木の子ノードの timestamp と比べていくことでデータの追加する場所を決める.
513 これが今回実装を行った掲示板システムにおけるMergeになる. 514 これが今回実装を行った掲示板システムにおけるMergeになる.
514 515