# HG changeset patch # User akahori # Date 1550584496 -32400 # Node ID 38f2c997bb93b311337e116e94ab15f0c38b8b52 # Parent 117794d50054718d1bbc0700db404cf93aab9f45 update chap4 diff -r 117794d50054 -r 38f2c997bb93 final_main/chapter4/chapter4.tex --- a/final_main/chapter4/chapter4.tex Tue Feb 19 21:49:55 2019 +0900 +++ b/final_main/chapter4/chapter4.tex Tue Feb 19 22:54:56 2019 +0900 @@ -65,7 +65,7 @@ \item ノード間で繋がる前にput操作を行うとデータが送られない. \end{itemize} -Take, Peek操作でSuperClassの型を持ったデータを取り出す際にNullPointerExceptionが表示される問題に対しては, DataGearでdataを代入する際にSuperClass, interfacesまで比較するように書き換えた. また, 型の不一致が起こった際は例外を投げるようにした. その修正後のコードをソースコード\ref{code:datagear}に示す. +Take, Peek操作でSuperClassの型を持ったデータを取り出す際にNullPointerExceptionが表示される問題に対しては, DataGearでdataを代入する際にSuperClass, interfacesまで比較するように書き換えた. また, 型の不一致が起こった際は例外を投げるようにした. その修正後のコードをソースコード\ref{code:datagear}に示す. \begin{lstlisting}[caption=修正後のDataGearのソースコード,label=code:datagear] public class DataGear{ @@ -101,101 +101,14 @@ } \end{lstlisting} -TopologyNodeにおいて, 実行するCodeGearをputしておき, 参加するノードがすべて揃ったら, そのCodeGearを実行する. しかし, 実際には実行するCodeGearはCodeGearを継承したものである. Christieは, putされたdataのクラスとTakeされるデータのクラスが一致したならば, dataを代入するという処理を行っている. つまり, SuperClass, interfacesの型までは比較をしない. そのため, 型の不一致が起こり, dataの代入をしないため, NullPointerExceptionが表示されていた. - - +setDataメソッドの中身を変更した. TopologyNodeにおいて, 実行するCodeGearをputしておき, 参加するノードがすべて揃ったら, そのCodeGearを実行する. しかし, 実際には実行するCodeGearはCodeGearを継承したものである. Christieは, putされたdataのクラスとTakeされるデータのクラスが一致したならばdataを代入し, それ以外なら無視するという処理を行っていた. SuperClass, interfacesの型までは比較をしていなかっため, 型の不一致が起こり, dataの代入をしないため, NullPointerExceptionが表示されていた. -ノード間で繋がる前にput操作を行うとデータが送られない問題に対しては, waitを付け加えた. そのコードをソースコード\ref{code:rdg}に示す. この問題は, ノードが繋がる前にputを行うため, 相手のDataGearに書き込みが行われないために起きた. そのため, 相手とDataGearがつながるまでputメソッドをwaitしておき, つながってからput操作を行うように書き換えた. - -\begin{lstlisting}[caption=修正後のDataGearのソースコード,label=code:datagear] -public class RemoteDataGearManager extends DataGearManager{ - boolean connect = false; - Object lock = new Object(); - - public RemoteDataGearManager(final String dgmName, final String address, final int port, CodeGearManager cgm) { - this.cgm = cgm; - RemoteDataGearManager manager = this; - new Thread("Connect-" + dgmName) { - public void run() { - do { - try { - SocketChannel sc = SocketChannel.open(new InetSocketAddress(address, port)); - connection = new Connection(sc.socket(), cgm); - connection.name = dgmName; - connection.socket.setTcpNoDelay(true); - - // add lock - synchronized (lock){ - connect = true; - lock.notify(); - } - } catch (IOException e) { - try { - Thread.sleep(50); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - } - } while (!connect); - IncomingTcpConnection in = new IncomingTcpConnection(connection); - in.setManager(manager); - in.setName(dgmName+"-IncomingTcp"); - in.setPriority(MAX_PRIORITY); - in.start(); - OutboundTcpConnection out = new OutboundTcpConnection(connection); - out.setName(dgmName + "-OutboundTcp"); - out.setPriority(MAX_PRIORITY); - out.start(); - } - }.start(); +ノード間で繋がる前にput操作を行うとデータが送られない問題に対しては, waitを付け加えた. そのコードをソースコード\ref{code:rdgm}に示す. - } - - ... - - @Override - public void put(String key, Object data) { - - Command cm = new PutCommand(0, null, key, new DataGear(data)); - - if(!connect) connectWait(); // add wait +\lstinputlisting[caption=修正後のRemoteDataGearManagerのソースコード,label=code:rdgm]{./src/RemoteDataGearManager.java} - connection.write(cm); - } - - // add method - public void connectWait(){ - synchronized (lock){ - while(!connect){ - try { - lock.wait(); - } catch (InterruptedException e) { - } - } - } - } -} -\end{lstlisting} - -\section{Aliceと比較したChristieの良い点, 悪い点} -Christieの元となった分散フレームワークAliceと比較し, Christieの良い点, 悪い点をそれぞれ述べる. - -良い点としては次のようなことが挙げられる. - -\begin{itemize} -\item ソースコードの可読性が上がった. Aliceでは動的にDataGearのKeyを変更できるため, 実際に使われているクラスと別のところでKeyが変更されている場合も多かった. しかし, Christieでは変数の名前がKeyとなる. そのため, put操作した変数がどこで使われているかがわかりやすくなった. -\item データの取り出しが簡単. アノテーションを用いることで, データを簡単に取り出すことができる. また, Aliceでは型をコード内で再定義しなければならなかったが, その操作がなくなった. - -\item DGMの操作がわかりやすくなった. -\end{itemize} - - -悪い点としては次のようなことが挙げられる -\begin{itemize} -\item TakeFrom, PeekFromの使い方が難しい. TakeFrom, PeekFromは引数でDGM nameを指定する. しかし, DGMの名前を静的に与えるよりも, 動的に与えたい場合が多かった. -\item デバッグが難しい. cgm.setupでCodeGearが実行されるが, keyの待ち合わせで止まり, どこで止まっているかわからないことが多かった. 例えば, putするkeyのスペルミスなどでコードの待ち合わせが起こり, CodeGearが実行されず, エラーなども表示されずにwaitすることがあり, どこで止まっているかわからない事があった. -\end{itemize} +具体的にはソースコード\ref{code:rdgm}の17行目から21行目にlockを付け加え, putメソッドの48行目にwaitするメソッドを置き, 54行目から63行目にwaitするメソッドを付け加えた. この問題は, ノードが繋がる前にconnection.writeを行うため, 相手のDataGearに書き込みが行われないために起きた. そのため, 相手とDataGearがつながるまでputメソッドをwaitしておき, つながってからconnection.write操作を行うように書き換えた. \section{Christieにおけるブロックチェーンの実装の利点と欠点} @@ -203,7 +116,7 @@ その際, Christieで実装した場合の便利な点を述べる. \begin{itemize} -\item ブロック, トランザクションを送るのが簡単. ChristieはDataGearという単位でデータを保持する. そのため, ブロックやトランザクションはDataGearに包めばいい. +\item データの取り出しが簡単. ChristieはDataGearという単位でデータを保持する. そのため, ブロックやトランザクションはDataGearに包めばいいため, どう送るかという問題を考えなくてすむ. \item TopologyManagerでのテストが便利. dotファイルが有れば, TopologyManagerが任意の形でTopologyを作れる. そのため, ノードの配置については理想の環境を作れるため, 理想のテスト環境を作ることができる. \item 機能ごとにファイルが実装できるため, 見通しが良い. ChristieはCbCのgotoと同じように関数が終わるとsetupによって別の関数に移動する. そのため自然に機能ごとにファイルを作るため, 見通しが良くなる. \end{itemize} @@ -211,7 +124,8 @@ 不便な点を以下に述べる. \begin{itemize} -\item デバッグが難しい. 4.4の「Christieの良い点, 悪い点」で述べたが, keyのスペルミスなどが起こると, CodeGearが実行されず, waitされる問題が出る. +\item デバッグが難しい. cgm.setupでCodeGearが実行されるが, keyの待ち合わせで止まり, どこのCGで止まっているかわからないことが多かった. 例えば, putするkeyのスペルミスでコードの待ち合わせが起こり, CGが実行されず, エラーなども表示されずにwaitすることがある. その時に, どこで止まっているか特定するのが難しい. +\item TakeFrom, PeekFromの使い方が難しい. TakeFrom, PeekFromは引数でDGM nameを指定する. しかし, DGMの名前を静的に与えるよりも, 動的に与えたい場合が多かった. \item Takeの待ち合わせでCGが実行されない. 2つのCGで同じ変数をTakeしようとすると, setupされた時点で変数がロックされる. このとき, 片方のCGはDGがすべて揃っているのに, すべての変数が揃っていないもう片方のCGに同名の変数がロックされ, 実行されない場合がある. \end{itemize} diff -r 117794d50054 -r 38f2c997bb93 final_main/main.pdf Binary file final_main/main.pdf has changed diff -r 117794d50054 -r 38f2c997bb93 final_main/src/RemoteDataGearManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/final_main/src/RemoteDataGearManager.java Tue Feb 19 22:54:56 2019 +0900 @@ -0,0 +1,64 @@ +public class RemoteDataGearManager extends DataGearManager{ + boolean connect = false; + Object lock = new Object(); + + public RemoteDataGearManager(final String dgmName, final String address, final int port, CodeGearManager cgm) { + this.cgm = cgm; + RemoteDataGearManager manager = this; + new Thread("Connect-" + dgmName) { + public void run() { + do { + try { + SocketChannel sc = SocketChannel.open(new InetSocketAddress(address, port)); + connection = new Connection(sc.socket(), cgm); + connection.name = dgmName; + connection.socket.setTcpNoDelay(true); + + // add lock + synchronized (lock){ + connect = true; + lock.notify(); + } + } catch (IOException e) { + try { + Thread.sleep(50); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + } while (!connect); + IncomingTcpConnection in = new IncomingTcpConnection(connection); + in.setManager(manager); + in.setName(dgmName+"-IncomingTcp"); + in.setPriority(MAX_PRIORITY); + in.start(); + OutboundTcpConnection out = new OutboundTcpConnection(connection); + out.setName(dgmName + "-OutboundTcp"); + out.setPriority(MAX_PRIORITY); + out.start(); + } + }.start(); + + } + + public void put(String key, Object data) { + + Command cm = new PutCommand(0, null, key, new DataGear(data)); + + if(!connect) connectWait(); // add wait + + connection.write(cm); + } + + // add method + public void connectWait(){ + synchronized (lock){ + while(!connect){ + try { + lock.wait(); + } catch (InterruptedException e) { + } + } + } + } +} \ No newline at end of file