Mercurial > hg > Papers > 2014 > nobuyasu-master
comparison paper/chapter4.tex @ 62:2cb5ac9282b0
writed description of ods.put
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 01 Feb 2014 11:44:34 +0900 |
parents | c5c761588168 |
children | d770a2b534b3 |
comparison
equal
deleted
inserted
replaced
61:c5c761588168 | 62:2cb5ac9282b0 |
---|---|
11 上での注意点を述べる. | 11 上での注意点を述べる. |
12 次に, それらをふまえてJungleの分散実装を行っていく. | 12 次に, それらをふまえてJungleの分散実装を行っていく. |
13 データ分散に必要なクラスを用意することで他サーバノードとの通信を行う. | 13 データ分散に必要なクラスを用意することで他サーバノードとの通信を行う. |
14 最後に, データ更新時の衝突において具体的なMergeの例として掲示板プログラムにおけるMergeについて述べる. | 14 最後に, データ更新時の衝突において具体的なMergeの例として掲示板プログラムにおけるMergeについて述べる. |
15 | 15 |
16 | |
17 \section{Alice のトポロジーマネージャーの利用} | 16 \section{Alice のトポロジーマネージャーの利用} |
18 | 17 |
19 \subsection{トポロジーマネージャーの起動} | 18 \subsection{トポロジーマネージャーの起動} |
20 Alice を用いてサーバノードでトポロジーの形成を行う方法を述べる. | 19 Alice を用いてサーバノードでトポロジーの形成を行う方法を述べる. |
21 Alice のトポロジーマネージャーの起動は\ref{src:alice_dot}の様に行う. | 20 Alice のトポロジーマネージャーの起動は\ref{src:alice_dot}の様に行う. |
26 -p オプションはトポロジーマネージャーが開くポートの番号, -conf オプションには dot ファイルのパスを渡す. | 25 -p オプションはトポロジーマネージャーが開くポートの番号, -conf オプションには dot ファイルのパスを渡す. |
27 | 26 |
28 ポート番号は Alice により記述された並列分散プログラムの起動時に渡す必要がある. | 27 ポート番号は Alice により記述された並列分散プログラムの起動時に渡す必要がある. |
29 dot ファイルには, トポロジーをどのように形成するかが書かれている. | 28 dot ファイルには, トポロジーをどのように形成するかが書かれている. |
30 以下に, サーバノード数5で, 2分木ツリー構造を形成する dot ファイルの例を示す(\ref{src:alice_dot}). | 29 以下に, サーバノード数5で, 2分木ツリー構造を形成する dot ファイルの例を示す(\ref{src:alice_dot}). |
30 \newpage | |
31 \begin{lstlisting}[frame=lrbt,label=src:alice_dot,caption=ネットワークトポロジー設定用 dot ファイル,numbers=left] | 31 \begin{lstlisting}[frame=lrbt,label=src:alice_dot,caption=ネットワークトポロジー設定用 dot ファイル,numbers=left] |
32 % cat tree5.dot | 32 % cat tree5.dot |
33 digraph test { | 33 digraph test { |
34 node0 -> node1 [label="child1"] | 34 node0 -> node1 [label="child1"] |
35 node0 -> node2 [label="child2"] | 35 node0 -> node2 [label="child2"] |
120 count++; | 120 count++; |
121 System.out.println("count = "+count); | 121 System.out.println("count = "+count); |
122 if(c > 10) { exit(0); } | 122 if(c > 10) { exit(0); } |
123 CodeSegment cs = new TestCodeSegment(); | 123 CodeSegment cs = new TestCodeSegment(); |
124 cs.setKey("count"); | 124 cs.setKey("count"); |
125 ods.update("local", "count", c); | 125 ods.put("local", "count", c); |
126 } | 126 } |
127 | 127 |
128 public static void main(String[] args) { | 128 public static void main(String[] args) { |
129 CodeSegment cs = new TestCodeSegment(); | 129 CodeSegment cs = new TestCodeSegment(); |
130 cs.arg1.setKey("local", "count"); // setKey API | 130 cs.arg1.setKey("local", "count"); // setKey API |
131 cs.ods.update("local", "count", 0); | 131 cs.ods.put("local", "count", 0); |
132 } | 132 } |
133 } | 133 } |
134 \end{lstlisting} | 134 \end{lstlisting} |
135 これは, 数字を1から10まで出力を行い終了するプログラムである. | 135 これは, 数字を1から10まで出力を行い終了するプログラムである. |
136 コードの説明を行う. | 136 コードの説明を行う. |
141 arg1に対しsetKey APIを使うことで, 使用したいDataSegmentのキー"count"を登録することができる. | 141 arg1に対しsetKey APIを使うことで, 使用したいDataSegmentのキー"count"を登録することができる. |
142 これによりキー"count"に対してデータが登録された場合, そのデータを受け取りcsの計算が自動で始まる. | 142 これによりキー"count"に対してデータが登録された場合, そのデータを受け取りcsの計算が自動で始まる. |
143 setKey APIの第一引数に渡している"local"はどのマシンのDataSegmentにアクセスするのかを指定している. | 143 setKey APIの第一引数に渡している"local"はどのマシンのDataSegmentにアクセスするのかを指定している. |
144 この場合は自分自身を表す"local"になる. | 144 この場合は自分自身を表す"local"になる. |
145 | 145 |
146 データの登録は\verb|ods.update|により行える. | 146 データの登録は\verb|ods.put|により行える. |
147 上記のコード19行目ではupdateにより"count"をキーとして数値の0を登録している. | 147 上記のコード19行目ではputにより"count"をキーとして数値の0を登録している. |
148 updateがされるとcsの計算が始まり別スレッドにより8行目からの処理が行われる. | 148 putがされるとcsの計算が始まり別スレッドにより8行目からの処理が行われる. |
149 | 149 |
150 updateによりキー"count"に登録された数値0はReceiverであるdsを使って取ることができる. | 150 putによりキー"count"に登録された数値0はReceiverであるdsを使って取ることができる. |
151 7行目から13行目では\verb|ds.asInteger()|により, "count"に登録したデータの中身を受け取りインクリメントし出力する. | 151 7行目から13行目では\verb|ds.asInteger()|により, "count"に登録したデータの中身を受け取りインクリメントし出力する. |
152 そして最後には\verb|ods.update|を行っている. | 152 そして最後には\verb|ods.put|を行っている. |
153 新たなTestCodeSegmentも生成しており, これはインクリメントされた"count"がupdateされることで実行される. | 153 新たなTestCodeSegmentも生成しており, これはインクリメントされた"count"がputされることで実行される. |
154 この一連の処理を"count"の数値が10以上になるまで行う. | 154 この一連の処理を"count"の数値が10以上になるまで行う. |
155 | 155 |
156 DataSegmentへデータの追加とCodeSegmentの実行について表した図\ref{fig:testcodesegment}になる. | 156 DataSegmentへデータの追加とCodeSegmentの実行について表した図\ref{fig:testcodesegment}になる. |
157 \begin{figure}[htpb] | 157 \begin{figure}[htpb] |
158 \begin{center} | 158 \begin{center} |
160 \caption{DataSegmentとCodeSegmentによるプログラムの例} | 160 \caption{DataSegmentとCodeSegmentによるプログラムの例} |
161 \label{fig:testcodesegment} | 161 \label{fig:testcodesegment} |
162 \end{center} | 162 \end{center} |
163 \end{figure} | 163 \end{figure} |
164 | 164 |
165 | 165 \newpage |
166 % Alice の他サーバノードへの"log"のputの問題 | 166 % Alice の他サーバノードへの"log"のputの問題 |
167 | 167 |
168 \subsection{他サーバノードのDataSegmentへアクセス} | 168 \subsection{他サーバノードのDataSegmentへアクセス} |
169 Aliceにおける基本的なプログラミングは述べた. | 169 Aliceにおける基本的なプログラミングは述べた. |
170 次はネットワークを介して他サーバノードのDataSegmentにアクセスするプログラムについて述べる. | 170 次はネットワークを介して他サーバノードのDataSegmentにアクセスするプログラムについて述べる. |
198 \end{lstlisting} | 198 \end{lstlisting} |
199 | 199 |
200 \subsection{独自クラスのインスタンスの送受信} | 200 \subsection{独自クラスのインスタンスの送受信} |
201 最後に, 独自クラスのインスタンスのDataSegmentでの扱い方について述べる. | 201 最後に, 独自クラスのインスタンスのDataSegmentでの扱い方について述べる. |
202 AliceではMessagePackを用いてシリアライズを行い他サーバノードへと送信している. | 202 AliceではMessagePackを用いてシリアライズを行い他サーバノードへと送信している. |
203 MessagePackはクラス単位でシリアライズを行うことができる. | 203 MessagePackはインスタンス単位でシリアライズを行うことができる. |
204 そのため, Aliceではプリミティブな型に限らずクラスのインスタンスをDataSegmentとして | 204 そのため, Aliceでもプリミティブな型に限らずクラスのインスタンスをDataSegmentとして |
205 扱うことができる. | 205 扱うことができる. |
206 | 206 |
207 MessagePackによりシリアライズとなるクラスはいくつか制限がある. | 207 MessagePackによりシリアライズとなるクラスはいくつか制限がある. |
208 それはそのクラスに@Messageアノテーションを付けることと, そのクラスが保持するフィールドが | 208 それはそのクラスに@Messageアノテーションを付けることと, そのクラスが保持するフィールドが |
209 MessagePackによりシリアライズ可能であることである. | 209 MessagePackによりシリアライズ可能であることである. |
215 public class Student { | 215 public class Student { |
216 String name; | 216 String name; |
217 int age; | 217 int age; |
218 } | 218 } |
219 \end{lstlisting} | 219 \end{lstlisting} |
220 上記のStudenクラスはプリミティブ型しか保持していない. | 220 上記のStudentクラスはプリミティブ型しか保持していない. |
221 そのためシリアライズが可能である | 221 そのためシリアライズが可能である |
222 また, 次のようなクラスもシリアライズ可能な型となる. | 222 また, 次のようなクラスもシリアライズ可能な型となる. |
223 \begin{lstlisting}[frame=lrbt,label=src:msgpack2,caption=MessagePackによりシリアライズ可能なクラス2,numbers=left] | 223 \begin{lstlisting}[frame=lrbt,label=src:msgpack2,caption=MessagePackによりシリアライズ可能なクラス2,numbers=left] |
224 import org.msgpack.annotation.Message | 224 import org.msgpack.annotation.Message |
225 | 225 |
231 この場合, フィールドはプリミティブな型でないStudentクラスのフィールドを保持している. | 231 この場合, フィールドはプリミティブな型でないStudentクラスのフィールドを保持している. |
232 しかし, Studentクラスはシリアライズ可能な形で作成しているため, クラスのフィールドとして | 232 しかし, Studentクラスはシリアライズ可能な形で作成しているため, クラスのフィールドとして |
233 保持しても問題はない. | 233 保持しても問題はない. |
234 | 234 |
235 これらの制約にそった形で作成しDataSegmentにネットワークを介してクラスのインスタンス | 235 これらの制約にそった形で作成しDataSegmentにネットワークを介してクラスのインスタンス |
236 をupdateすることができる. | 236 をputすることができる. |
237 DataSegmentから受け取ったデータはそのままではシリアライズされたものため, 一度手元で | 237 DataSegmentから受け取ったデータはそのままではシリアライズされたものため, 一度手元で |
238 元のクラスにコンバートすることで扱う. | 238 元のクラスにコンバートすることで扱う. |
239 例として, AliceにおけるStudenクラス(Listing\ref{src:msgpack1})のコンバートを次に示す. | 239 例として, AliceにおけるStudenクラス(Listing\ref{src:msgpack1})のコンバートを次に示す. |
240 \begin{lstlisting}[frame=lrbt,label=src:msgpack3,caption=DataSegment,numbers=left] | 240 \begin{lstlisting}[frame=lrbt,label=src:msgpack3,caption=DataSegment,numbers=left] |
241 // public Receiver arg1 = ids.create(CommandType.PEEK); | 241 // public Receiver arg1 = ids.create(CommandType.PEEK); |
267 そのため, TreeOperationLogだけを受け取っても, そのログがどの木に対して行われるのか | 267 そのため, TreeOperationLogだけを受け取っても, そのログがどの木に対して行われるのか |
268 わからなかった. | 268 わからなかった. |
269 そこで, TreeOperationLogの情報だけでなく, 木の名前とUUID, それとtimestampの情報も付与 | 269 そこで, TreeOperationLogの情報だけでなく, 木の名前とUUID, それとtimestampの情報も付与 |
270 してシリアライズが可能なNetworkTreeOperationLogの実装を行った. | 270 してシリアライズが可能なNetworkTreeOperationLogの実装を行った. |
271 | 271 |
272 \subsection{NetworkTreeOperationLogの実装} | |
273 NetworkTreeOperationLogの実装の一部を以下に示す. | |
274 | |
275 | |
276 | |
277 | |
278 | |
279 % TreeOperationLog に木の名前の情報がない | 272 % TreeOperationLog に木の名前の情報がない |
280 % そのため木の名前を追加して持たせた | 273 % そのため木の名前を追加して持たせた |
281 % 木がなければそのばでつくるようにした | 274 % 木がなければそのばでつくるようにした |
282 | 275 |
276 \subsection{NetworkTreeOperationLogの実装} | |
277 NetworkTreeOperationLogの実装の一部を以下(\ref{fig:netlog})に示す. | |
278 \begin{lstlisting}[frame=lrbt,label=src:netlog,caption=NetworkTreeOperationが持つフィールド,numbers=left] | |
279 @Message | |
280 public class NetworkTreeOperationLog implements TreeOperationLog | |
281 { | |
282 public LinkedList<NetworkTreeOperation> list; | |
283 String treeName; | |
284 long timestamp; | |
285 \end{lstlisting} | |
286 Listにより保持しているNetworkTreeOperationはTreeOperationをシリアライズ可能な形にしたものである. | |
287 TreeOperationLogをimplementsし, 木の名前とtimestampをを保持する. | |
288 他サーバノードへ伝える必要のある情報が増えた場合, このようにNetworkTreeOperationLogに情報を付与することで | |
289 対応することができる. | |
290 | |
291 \subsection{ログの送信} | |
292 ログを送信するタイミングはいつ行うか. | |
293 それは, 木の編集が成功した時である. | |
294 木の編集が成功した結果得られるTreeOperationLogをNetworkTreeOperationLogに変換し, \verb|ods.put|を使って | |
295 CodeSegment側から利用できるようにする. | |
296 | |
297 しかし, この時気をつけなければならないことがある. | |
298 それは, \verb|ods.put|の処理をレスポンスを返すスレッドの中で行うと, レスポンスが悪くなる可能性が | |
299 あることだ. | |
300 そのため, \verb|ods.put|を行うのは別のThreadにしたほうがよい. | |
301 以下のコードはcommitに成功した後に, NetworkTreeOperationへと変換したログを別スレッド渡し | |
302 て処理させるコードである. | |
303 \begin{lstlisting}[frame=lrbt,label=src:logconvert_and_execute,caption=NetworkTreeOperationをputするために別スレッドを立ち上げる,numbers=left] | |
304 NetworkTreeOperationLog netLog = new NetworkTreeOperationLog(_uuid, _treeName,newLog); | |
305 CodeSegment cs = new LogPutCodeSegment(netLog); | |
306 cs.execute(); | |
307 \end{lstlisting} | |
308 | |
309 LogPutCodeSegmentの実装は次のようになっている. | |
310 \begin{lstlisting}[frame=lrbt,label=src:,caption=putを行うためだけのCodeSegmentの用意,numbers=left] | |
311 // LogPutCodeSegment Class | |
312 NetworkTreeOperationLog log; | |
313 public LogPutCodeSegment(NetworkTreeOperationLog _log) { | |
314 log = _log; | |
315 } | |
316 | |
317 @Override | |
318 public void run() { | |
319 ods.put("log", log); | |
320 } | |
321 \end{lstlisting} | |
322 上で述べた問題は, 通常のアプリケーションとして使用する分には発生しない. | |
323 だが, ベンチマークテストなど, 大量の負荷をかけた際に発生する. | |
324 ベンチマークテストでは大量のログが生成される. | |
325 そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが | |
326 悪くなっていた. | |
327 \verb|ods.put|を行うタイミングには気をつけなければず, 上記のコードにしても改良の余地はある. | |
328 | |
329 | |
330 | |
331 \begin{lstlisting}[frame=lrbt,label=src:,caption=,numbers=left] | |
332 | |
333 \end{lstlisting} | |
334 | |
335 | |
336 \begin{lstlisting}[frame=lrbt,label=src:,caption=,numbers=left] | |
337 | |
338 \end{lstlisting} | |
339 | |
340 | |
341 | |
283 \subsection{local専用の編集の用意} | 342 \subsection{local専用の編集の用意} |
284 | 343 |
285 | |
286 \subsection{} | |
287 | 344 |
288 | 345 |
289 | 346 |
290 \section{掲示板プログラムにおけるマージの実装} | 347 \section{掲示板プログラムにおけるマージの実装} |
291 Jungle に分散実装を行った後の問題としてデータ衝突がある. | 348 Jungle に分散実装を行った後の問題としてデータ衝突がある. |