comparison paper/chapter4.tex @ 63:d770a2b534b3

Writed description of persistent
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Sat, 01 Feb 2014 15:59:14 +0900
parents 2cb5ac9282b0
children 4f31182c8244
comparison
equal deleted inserted replaced
62:2cb5ac9282b0 63:d770a2b534b3
58 dot ファイル\ref{src:alice_dot}により形成されるトポロジーを図\ref{fig:tree_topology}に示す. 58 dot ファイル\ref{src:alice_dot}により形成されるトポロジーを図\ref{fig:tree_topology}に示す.
59 59
60 60
61 \begin{figure}[htpb] 61 \begin{figure}[htpb]
62 \begin{center} 62 \begin{center}
63 \includegraphics[scale=0.70]{figures/tree_topology.pdf} 63 \includegraphics[scale=0.70]{figures/tree_topology_noarrow.pdf}
64 \caption{Alice によるネットワークトポロジー形成} 64 \caption{Alice によるネットワークトポロジー形成}
65 \label{fig:tree_topology} 65 \label{fig:tree_topology}
66 \end{center} 66 \end{center}
67 \end{figure} 67 \end{figure}
68 68
69 矢印に書かれている文字列は, 相手のデータにアクセスするキーを示す. 69 %矢印に書かれている文字列は, 相手のデータにアクセスするキーを示す.
70 "child1", "child2", "parent" というキーを使うことで別のサーバノードにあるデータを取得することができる. 70 %"child1", "child2", "parent" というキーを使うことで別のサーバノードにあるデータを取得することができる.
71 %子共となるノードは "parent" キーにより親の DSM (Remote DSM) にアクセスすることができる. 71 %これでトポロジーマネージャーが起動される.
72 %また, 親も子供となるノードの DSM に対して "child1" や "child2" キーによりアクセスすることが可能となる.
73 これでトポロジーマネージャーが起動される.
74 72
75 \subsection{アプリケーション側の記述} 73 \subsection{アプリケーション側の記述}
76 次は Jungle 側のプログラムが最初に Alice のトポロジーノードと通信を行うようにする. 74 次は Jungle 側のプログラムが最初に Alice のトポロジーノードと通信を行うようにする.
77 そのためには Alice の TopologyNode クラスに必要な情報を渡してインスタンスを生成する(\ref{src:app_start}). 75 そのためには Alice の TopologyNode クラスに必要な情報を渡してインスタンスを生成する(\ref{src:app_start}).
78 \begin{lstlisting}[frame=lrbt,label=src:app_start,caption=アプリケーションの起動,numbers=left] 76 \begin{lstlisting}[frame=lrbt,label=src:app_start,caption=アプリケーションの起動,numbers=left]
168 \subsection{他サーバノードのDataSegmentへアクセス} 166 \subsection{他サーバノードのDataSegmentへアクセス}
169 Aliceにおける基本的なプログラミングは述べた. 167 Aliceにおける基本的なプログラミングは述べた.
170 次はネットワークを介して他サーバノードのDataSegmentにアクセスするプログラムについて述べる. 168 次はネットワークを介して他サーバノードのDataSegmentにアクセスするプログラムについて述べる.
171 169
172 まず, Aliceにより2分木3ノードのトポロジーが形成された場合を想定する. 170 まず, Aliceにより2分木3ノードのトポロジーが形成された場合を想定する.
173 その時に実際に作られるトポロジーを図\ref{fig:remote_cs}に示す. 171 その時に実際に作られるトポロジーは図\ref{fig:remote_cs}となる.
174 \begin{figure}[htpb] 172 \begin{figure}[htpb]
175 \begin{center} 173 \begin{center}
176 \includegraphics[scale=0.70]{figures/remote_codesegment.pdf} 174 \includegraphics[scale=0.70]{figures/remote_codesegment.pdf}
177 \caption{トポロジーの形成} 175 \caption{トポロジーの形成}
178 \label{fig:remote_cs} 176 \label{fig:remote_cs}
286 Listにより保持しているNetworkTreeOperationはTreeOperationをシリアライズ可能な形にしたものである. 284 Listにより保持しているNetworkTreeOperationはTreeOperationをシリアライズ可能な形にしたものである.
287 TreeOperationLogをimplementsし, 木の名前とtimestampをを保持する. 285 TreeOperationLogをimplementsし, 木の名前とtimestampをを保持する.
288 他サーバノードへ伝える必要のある情報が増えた場合, このようにNetworkTreeOperationLogに情報を付与することで 286 他サーバノードへ伝える必要のある情報が増えた場合, このようにNetworkTreeOperationLogに情報を付与することで
289 対応することができる. 287 対応することができる.
290 288
291 \subsection{ログの送信} 289 \subsection{ログの送信部分}
292 ログを送信するタイミングはいつ行うか. 290 ログを送信するタイミングはいつ行うか.
293 それは, 木の編集が成功した時である. 291 それは, 木の編集が成功した時である.
294 木の編集が成功した結果得られるTreeOperationLogをNetworkTreeOperationLogに変換し, \verb|ods.put|を使って 292 木の編集が成功した結果得られるTreeOperationLogをNetworkTreeOperationLogに変換し, \verb|ods.put|を使って
295 CodeSegment側から利用できるようにする. 293 CodeSegment側から利用できるようにする.
296 294
317 @Override 315 @Override
318 public void run() { 316 public void run() {
319 ods.put("log", log); 317 ods.put("log", log);
320 } 318 }
321 \end{lstlisting} 319 \end{lstlisting}
322 上で述べた問題は, 通常のアプリケーションとして使用する分には発生しない. 320 上で述べた問題は, ベンチマークテストなど, 大量の負荷をかけたさいに発生する.
323 だが, ベンチマークテストなど, 大量の負荷をかけた際に発生する. 321 負荷とはJungleのデータに変更を加わることである.
324 ベンチマークテストでは大量のログが生成される. 322 データの変更により大量のログが生成される.
325 そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが 323 そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが
326 悪くなっていた. 324 悪くなっていた.
327 \verb|ods.put|を行うタイミングには気をつけなければず, 上記のコードにしても改良の余地はある. 325 \verb|ods.put|を行うタイミングには気をつけなければず, 上記のコードにしても改良の余地はある.
328 326
329 327 \subsection{他サーバノードへのログの送信}
330 328 上記の実装によりDataSegmentの"log"キーにアクセスすることでTreeOperationLogを取得できるようになった.
331 \begin{lstlisting}[frame=lrbt,label=src:,caption=,numbers=left] 329 次はこのデータを他サーバノードへ送る部分の実装を行う.
332 330
333 \end{lstlisting} 331 他サーバノードに対してデータを送るときに必要なことは, そのサーバノードのDataSegmentにアクセスする
334 332 キーである.
335 333 Aliceでは接続を行っている相手のDataSegmentのキーのリストは"\_CLIST"キーを使うことで取得することができる.
336 \begin{lstlisting}[frame=lrbt,label=src:,caption=,numbers=left] 334 "\_CLIST"キーで得られるリストを使って他サーバノードへとデータをputするコードを次に示す.
337 335
338 \end{lstlisting} 336 \begin{lstlisting}[frame=lrbt,label=src:log_put,caption=他サーバノードへのログの送信部分,numbers=left]
339 337 public class LogUpdateCodeSegment extends CodeSegment {
340 338 Receiver log = ids.create(CommandType.TAKE);
341 339 Receiver clist = ids.create(CommandType.PEEK);
342 \subsection{local専用の編集の用意} 340
343 341 public LogUpdateCodeSegment() {
344 342 log.setKey("log");
343 clist.setKey("_CLIST");;
344 }
345
346 List<String> list = clist.asClass(List.class);
347 for (String node : list) {
348 ods.put(node, log.key, log.getVal());
349 }
350 :
351 \end{lstlisting}
352 変数logはNetworTreeOperationLogが入っている.
353 変数listには"\_CLIST"により得られたデータが入っている.
354 それは文字列のListとなっている.
355 listの中身を1つずつ受け取り, \verb|ods.put|する際に引数として渡してやることで, 他サーバノードの
356 DataSegmentにアクセスが行える.
357
358 listの具体的な内容は, 図\ref{fig:tree_topology}で組まれたトポロジーでいうところの, "parent", "child1", "child2"
359 の文字列となっている.
360 もし子どもとなるサーバノードがないときは"parent"だけがListには入れられる.
361
362
363 \subsection{ログの受信とデータ反映}
364 次は受け取ったログからデータの編集を行う部分の実装を行う.
365 Jungleはのデータを変更する手段として木構造データ毎にTreeEditorクラスが提供される.
366 このTreeEditorを使用し, ログに入っているTreeOperationを1つ1つ取り出し同じ編集を行わせる.
367 例えば次のようになる.
368 \begin{lstlisting}[frame=lrbt,label=src:data_edit,caption=ログを受け取ってのデータの反映,numbers=left]
369 // Receiver log <- "log"キーから取得できるデータが張っている
370 // Jungle jugnle
371 NetworkTreeOperationLog netLog = log.asClass(NetworkTreeOperationLog.class); // NetworkTreeOperationLogへのコンバート
372 String treeName = netLog.getTreeName();
373 JungleTree tree = jungle.getTreeByName(treeName);
374 TreeEditor editor = tree.getLocalTreeEditor(); // Editor の取得
375 for (TreeOperation op : netlog) {
376 NodePath path = op.getNodePath();
377 NodeOperation nodeOp = op.getNodeOperation();
378 either = edit(editor, path, nodeOp, nodeOp.getPosition()); // データの編集を行う.
379 if(either.isA()) {
380 // エラー処理.編集失敗
381 }
382 editor = either.b();
383 }
384 \end{lstlisting}
385 7行目で取り出されたTreeOperationからさらにNodePathとNodeOperationを取り出しているのが8行目と9行目になる.
386 最後にedit関数にTreeEditorとNodePath, それとNodeOpeartionを引き渡している.
387 edit関数は次のようになる.
388 \begin{lstlisting}[frame=lrbt,label=src:data_edito2,caption=edit関数の実装,numbers=left]
389 Either<Error, JungleTreeEditor> edit(JungleTreeEditor editor, NodePath path,
390 NodeOperation nodeOp, int pos) {
391 String key = ";
392 Command c = nodeOp.getCommand();
393 switch (c) {
394 case PUT_ATTRIBUTE:
395 key = nodeOp.getKey();
396 ByteBuffer value = nodeOp.getValue();
397 return editor.putAttribute(path, key, value);
398 case DELETE_ATTRIBUTE:
399 key = nodeOp.getKey();
400 return editor.deleteAttribute(path, key);
401 case APPEND_CHILD:
402 return editor.addNewChildAt(path, pos);
403 case DELETE_CHILD:
404 return editor.deleteChildAt(path, 0);
405 }
406 \end{lstlisting}
407 NodeOperationのAPIの種類(Command)毎に使用するTreeEditorのAPIを変えている.
408 もしNodeOperationのAPIの種類を増えるようなことが合っても, 上記のコードのように
409 対応するTreeEditorのAPIを書くことで対応できる.
410
411 %\subsection{ローカルのデータ編集専用のTreeEditorの用意}
412 %データ編集が行われ,
413
414 \section{永続性の実装}
415 次は, ログの書き出しによる永続性の実装について述べる.
416 第3章でJungleはWriterいう永続性実装のための機能が元々用意されていることを述べた.
417 永続性で考えなければならないことは, どのようなデータをどんなデータ表現で書き込むかということである.
418 今回の実装ではログであるTreeOperationLogを書き出す.
419 また, TreeOperationLogの情報を保持しつつ, MessagePackでシリアライズできるクラスとして
420 NetworkTreeOperationLogの実装を行った.
421
422 つまり, WriterでNetworkTreeOperationLogを書き出すようにすればよい.
423 以下にログをディスクへ書き出すためのクラスPersistentChangeListWriterの実装を示す.
424 \begin{lstlisting}[frame=lrbt,label=src:,caption=NetworkTreeOperationをディスクへ書き出す,numbers=left]
425 public class PersistentChangeListWriter implements ChangeListWriter {
426
427 MessagePack msgpack;
428 OutputStream out;
429
430 public PersistentChangeListWriter(OutputStream _out, MessagePack _msgpack) {
431 out = _out;
432 msgpack = _msgpack;
433 }
434 @Override
435 public Result write(ChangeList cs)
436 {
437 NetworkTreeOperationLog log
438 = new NetworkTreeOperationLog(cs.uuid(), cs.getTreeName(), cs);
439 try {
440 msgpack.write(out, log);
441 out.flush();
442 return Result.SUCCESS;
443 } catch (IOException e) {
444 // エラー処理
445 }
446 return Result.FAILED;
447 }
448 \end{lstlisting}
449 write関数はJungleのデータ編集が完了すると呼び出される関数である.
450 引数として渡されているChangeListはTreeOperationLogと同じく\verb|Iterable<TreeOperation>|を継承している.
451 またUUIDや木の名前も取得することができる.
452 そのため, NetworkTreeOperationLogへと変換が行える.
453
454 ログの書き出しを行いたいときはこのPersistentChangeListWriterを設定することで行えるようになった.
455 これにより木の編集が行われるたびにNetworkTreeOperationLogが書き込まれていく.
456 読み込みたいときはMessagePackを使ってディスクから読み込み, データ分散実装と同じの方法で木の編集を行っていく
457 ことができる(Listing\ref{src:data_edit}, \ref{src:data_edit2}).
345 458
346 459
347 \section{掲示板プログラムにおけるマージの実装} 460 \section{掲示板プログラムにおけるマージの実装}
348 Jungle に分散実装を行った後の問題としてデータ衝突がある. 461 Jungle に分散実装を行った後の問題としてデータ衝突がある.
349 他のサーバノードから送られてくるデータが既に手元で変更を加えた木構造を対象とした 462 他のサーバノードから送られてくるデータが既に手元で変更を加えた木構造を対象とした
395 508
396 %単一サーバで動いている時の Jungle はただ子ノードとして後ろに追加するだけだが, 分散 509 %単一サーバで動いている時の Jungle はただ子ノードとして後ろに追加するだけだが, 分散
397 %環境下においては timestamp に従い子ノードを追加する位置を決めるようにする. 510 %環境下においては timestamp に従い子ノードを追加する位置を決めるようにする.
398 511
399 512
400
401