diff 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
line wrap: on
line diff
--- a/paper/chapter4.tex	Sat Feb 01 11:44:34 2014 +0900
+++ b/paper/chapter4.tex	Sat Feb 01 15:59:14 2014 +0900
@@ -60,17 +60,15 @@
 
 \begin{figure}[htpb]
   \begin{center}
-    \includegraphics[scale=0.70]{figures/tree_topology.pdf}
+    \includegraphics[scale=0.70]{figures/tree_topology_noarrow.pdf}
     \caption{Alice によるネットワークトポロジー形成}
     \label{fig:tree_topology}
   \end{center}
 \end{figure}
 
-矢印に書かれている文字列は, 相手のデータにアクセスするキーを示す.
-"child1", "child2", "parent" というキーを使うことで別のサーバノードにあるデータを取得することができる.
-%子共となるノードは "parent" キーにより親の DSM (Remote DSM) にアクセスすることができる.
-%また, 親も子供となるノードの DSM に対して "child1" や "child2" キーによりアクセスすることが可能となる.
-これでトポロジーマネージャーが起動される.
+%矢印に書かれている文字列は, 相手のデータにアクセスするキーを示す.
+%"child1", "child2", "parent" というキーを使うことで別のサーバノードにあるデータを取得することができる.
+%これでトポロジーマネージャーが起動される.
 
 \subsection{アプリケーション側の記述}
 次は Jungle 側のプログラムが最初に Alice のトポロジーノードと通信を行うようにする.
@@ -170,7 +168,7 @@
 次はネットワークを介して他サーバノードのDataSegmentにアクセスするプログラムについて述べる.
 
 まず, Aliceにより2分木3ノードのトポロジーが形成された場合を想定する.
-その時に実際に作られるトポロジーを図\ref{fig:remote_cs}に示す.
+その時に実際に作られるトポロジーは図\ref{fig:remote_cs}となる.
 \begin{figure}[htpb]
   \begin{center}
     \includegraphics[scale=0.70]{figures/remote_codesegment.pdf}
@@ -288,7 +286,7 @@
 他サーバノードへ伝える必要のある情報が増えた場合, このようにNetworkTreeOperationLogに情報を付与することで
 対応することができる.
 
-\subsection{ログの送信}
+\subsection{ログの送信部分}
 ログを送信するタイミングはいつ行うか.
 それは, 木の編集が成功した時である.
 木の編集が成功した結果得られるTreeOperationLogをNetworkTreeOperationLogに変換し, \verb|ods.put|を使って
@@ -319,29 +317,144 @@
   ods.put("log", log);
 }
 \end{lstlisting}
-上で述べた問題は, 通常のアプリケーションとして使用する分には発生しない.
-だが, ベンチマークテストなど, 大量の負荷をかけた際に発生する.
-ベンチマークテストでは大量のログが生成される.
+上で述べた問題は, ベンチマークテストなど, 大量の負荷をかけたさいに発生する.
+負荷とはJungleのデータに変更を加わることである.
+データの変更により大量のログが生成される.
 そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが
 悪くなっていた.
 \verb|ods.put|を行うタイミングには気をつけなければず, 上記のコードにしても改良の余地はある.
 
+\subsection{他サーバノードへのログの送信}
+上記の実装によりDataSegmentの"log"キーにアクセスすることでTreeOperationLogを取得できるようになった.
+次はこのデータを他サーバノードへ送る部分の実装を行う.
 
+他サーバノードに対してデータを送るときに必要なことは, そのサーバノードのDataSegmentにアクセスする
+キーである.
+Aliceでは接続を行っている相手のDataSegmentのキーのリストは"\_CLIST"キーを使うことで取得することができる.
+"\_CLIST"キーで得られるリストを使って他サーバノードへとデータをputするコードを次に示す.
 
-\begin{lstlisting}[frame=lrbt,label=src:,caption=,numbers=left]
+\begin{lstlisting}[frame=lrbt,label=src:log_put,caption=他サーバノードへのログの送信部分,numbers=left]
+public class LogUpdateCodeSegment extends CodeSegment {
+  Receiver log = ids.create(CommandType.TAKE);
+  Receiver clist = ids.create(CommandType.PEEK);
+  
+  public LogUpdateCodeSegment() {
+    log.setKey("log"); 
+    clist.setKey("_CLIST");; 
+  }
+  
+  List<String> list = clist.asClass(List.class);
+  for (String node : list) {
+    ods.put(node, log.key, log.getVal());
+  }
+  :
+\end{lstlisting}
+変数logはNetworTreeOperationLogが入っている.
+変数listには"\_CLIST"により得られたデータが入っている.
+それは文字列のListとなっている.
+listの中身を1つずつ受け取り, \verb|ods.put|する際に引数として渡してやることで, 他サーバノードの
+DataSegmentにアクセスが行える.
 
-\end{lstlisting}
+listの具体的な内容は, 図\ref{fig:tree_topology}で組まれたトポロジーでいうところの, "parent", "child1", "child2"
+の文字列となっている.
+もし子どもとなるサーバノードがないときは"parent"だけがListには入れられる.
 
 
-\begin{lstlisting}[frame=lrbt,label=src:,caption=,numbers=left]
-
+\subsection{ログの受信とデータ反映}
+次は受け取ったログからデータの編集を行う部分の実装を行う.
+Jungleはのデータを変更する手段として木構造データ毎にTreeEditorクラスが提供される.
+このTreeEditorを使用し, ログに入っているTreeOperationを1つ1つ取り出し同じ編集を行わせる.
+例えば次のようになる.
+\begin{lstlisting}[frame=lrbt,label=src:data_edit,caption=ログを受け取ってのデータの反映,numbers=left]
+// Receiver log <- "log"キーから取得できるデータが張っている
+// Jungle jugnle
+NetworkTreeOperationLog netLog = log.asClass(NetworkTreeOperationLog.class); // NetworkTreeOperationLogへのコンバート
+String treeName = netLog.getTreeName();
+JungleTree tree = jungle.getTreeByName(treeName);
+TreeEditor editor = tree.getLocalTreeEditor();  // Editor の取得
+for (TreeOperation op : netlog) { 
+  NodePath path = op.getNodePath();
+  NodeOperation nodeOp = op.getNodeOperation();
+  either = edit(editor, path, nodeOp, nodeOp.getPosition()); // データの編集を行う.
+  if(either.isA()) {
+    // エラー処理.編集失敗
+  }
+  editor = either.b();
+}
 \end{lstlisting}
-
+7行目で取り出されたTreeOperationからさらにNodePathとNodeOperationを取り出しているのが8行目と9行目になる.
+最後にedit関数にTreeEditorとNodePath, それとNodeOpeartionを引き渡している.
+edit関数は次のようになる.
+\begin{lstlisting}[frame=lrbt,label=src:data_edito2,caption=edit関数の実装,numbers=left]
+Either<Error, JungleTreeEditor> edit(JungleTreeEditor editor, NodePath path, 
+  NodeOperation nodeOp, int pos) {
+    String key = ";
+    Command c = nodeOp.getCommand();
+    switch (c) {
+     case PUT_ATTRIBUTE:
+       key = nodeOp.getKey();
+       ByteBuffer value = nodeOp.getValue();
+       return editor.putAttribute(path, key, value);
+     case DELETE_ATTRIBUTE:
+       key = nodeOp.getKey();
+       return editor.deleteAttribute(path, key);
+     case APPEND_CHILD:
+       return editor.addNewChildAt(path, pos);
+     case DELETE_CHILD:
+       return editor.deleteChildAt(path, 0);
+}
+\end{lstlisting}
+NodeOperationのAPIの種類(Command)毎に使用するTreeEditorのAPIを変えている.
+もしNodeOperationのAPIの種類を増えるようなことが合っても, 上記のコードのように
+対応するTreeEditorのAPIを書くことで対応できる.
 
+%\subsection{ローカルのデータ編集専用のTreeEditorの用意}
+%データ編集が行われ, 
 
-\subsection{local専用の編集の用意}
+\section{永続性の実装}
+次は, ログの書き出しによる永続性の実装について述べる.
+第3章でJungleはWriterいう永続性実装のための機能が元々用意されていることを述べた.
+永続性で考えなければならないことは, どのようなデータをどんなデータ表現で書き込むかということである.
+今回の実装ではログであるTreeOperationLogを書き出す.
+また, TreeOperationLogの情報を保持しつつ, MessagePackでシリアライズできるクラスとして
+NetworkTreeOperationLogの実装を行った.
+
+つまり, WriterでNetworkTreeOperationLogを書き出すようにすればよい.
+以下にログをディスクへ書き出すためのクラスPersistentChangeListWriterの実装を示す.
+\begin{lstlisting}[frame=lrbt,label=src:,caption=NetworkTreeOperationをディスクへ書き出す,numbers=left]
+public class PersistentChangeListWriter implements ChangeListWriter {
+  
+  MessagePack msgpack;
+  OutputStream out;
 
+  public PersistentChangeListWriter(OutputStream _out, MessagePack _msgpack) {
+    out = _out;
+    msgpack = _msgpack;
+  }
+  @Override
+  public Result write(ChangeList cs)
+  {
+    NetworkTreeOperationLog log 
+      = new NetworkTreeOperationLog(cs.uuid(), cs.getTreeName(), cs);
+    try {
+      msgpack.write(out, log);
+      out.flush();
+      return Result.SUCCESS;
+    } catch (IOException e) {
+      // エラー処理
+    }
+  return Result.FAILED;
+}
+\end{lstlisting}
+write関数はJungleのデータ編集が完了すると呼び出される関数である.
+引数として渡されているChangeListはTreeOperationLogと同じく\verb|Iterable<TreeOperation>|を継承している.
+またUUIDや木の名前も取得することができる.
+そのため, NetworkTreeOperationLogへと変換が行える.
 
+ログの書き出しを行いたいときはこのPersistentChangeListWriterを設定することで行えるようになった.
+これにより木の編集が行われるたびにNetworkTreeOperationLogが書き込まれていく.
+読み込みたいときはMessagePackを使ってディスクから読み込み, データ分散実装と同じの方法で木の編集を行っていく
+ことができる(Listing\ref{src:data_edit}, \ref{src:data_edit2}).
 
 
 \section{掲示板プログラムにおけるマージの実装}
@@ -397,5 +510,3 @@
 %環境下においては timestamp に従い子ノードを追加する位置を決めるようにする.
 
 
-
-