comparison jungle.tex @ 15:33d8077a5d45

commit
author tatsuki
date Thu, 09 Feb 2017 17:25:56 +0900
parents e4da23b04260
children d5306971efbf
comparison
equal deleted inserted replaced
14:e4da23b04260 15:33d8077a5d45
1 \chapter{非破壊的木構造データベースJungle} 1 \chapter{非破壊的木構造データベースJungle}
2 本章では、当研究室で開発を行っているデータベース Jungle について記述する。 2 本章では、Jungleの基本的な解説を行う。
3 3 初めに Jungle の特徴である非破壊的木構造の説明をし、その後提供しているAPIについて述べる。
4 \section{概要} 4
5 Jungleは、当研究室で開発を行っているデータベースで、Javaを用いて実装されている。
6 Jungleは名前付きの複数の木の集合からなり、木は複数のノードの集合で出来ている。
7 ノードは自身の子のリストと属性名と属性値の組でデータを持ち、データベースのレコードに相当する。
8 通常のレコードと異なるのは、ノードに子供となる複数のノードが付くところである。
9 Jungleでは、親から子への片方向の参照しか持たない。
10
11 通常のRDBと異なり、Jungleは木構造をそのまま読み込むことができる。例えば、XMLやJsonで記述された構造を、データベースを設計することなく読み込むことが可能である。
12 また、この木を、そのままデータベースとして使用することも可能である。しかし、木の変更の手間は木の構造に依存する。
13 %特に非破壊木構造を採用しているJungleでは木構造の変更にo(1)からo(n)の様々な選択肢がある。つまり、アプリケーションに合わせて木を設計しない限り、
14 特に非破壊木構造を採用しているJungleでは、木構造の変更の手間はO(1)からO(n)となりえる。つまり、アプリケーションに合わせて木を設計しない限り、
15 十分な性能を出すことはできない。逆に、正しい木の設計を行えば高速な処理が可能である。
16
17 Jungleは基本的にon memoryで使用することを考えており、一度、木のルートを取得すれば、その上で木構造として自由にアクセスして良い。
18 Jungleは分散データベースを構成するように設計されており、分散ノード間の通信は木の変更のログを交換することによって行われる。
19 持続性のある分散ノードを用いることでJungleの持続性を保証することができる。本論文では基本的に分散実装部分ではなく on memory DBの
20 部分について考察する。
21 本章ではまず破壊的木構造と、非破壊的木構造の説明をし、その後Jungleの提供しているAPIについて述べる。
22
23 \newpage
24 5
25 \section{非破壊的木構造} 6 \section{非破壊的木構造}
26 Jungle は、非破壊的木構造という特殊な木構造を持つ。 7 Jungle は、非破壊的木構造という特殊な木構造を持つ。
27 本節では、初めに破壊的木構造と非破壊的木構造の編集・メリットデメリットについて記述する。 8 本節では、破壊的木構造と非破壊的木構造の編集・メリットデメリットについて記述する。
28 9
29 \vspace{0.3in} 10 \vspace{0.3in}
30 {\Large 破壊的木構造の編集} 11 {\Large 破壊的木構造の編集}
31 12
32 \vspace{0.1in} 13 \vspace{0.1in}
59 \caption{非破壊的木構造の編集} 40 \caption{非破壊的木構造の編集}
60 \label{fig:nondestractive} 41 \label{fig:nondestractive}
61 \end{center} 42 \end{center}
62 \end{figure} 43 \end{figure}
63 44
64 \newpage
65 非破壊的木構造においてデータのロックが必要となる部分は、木のコピーを作り終えた後に 45 非破壊的木構造においてデータのロックが必要となる部分は、木のコピーを作り終えた後に
66 ルートノードを更新するときだけである。 46 ルートノードを更新するときだけである。
67 データ編集を行っている間ロックが必要な破壊的木構造に比べ、編集中においてもデータの読み込みが可能であるが、 47 データ編集を行っている間ロックが必要な破壊的木構造に比べ、編集中においてもデータの読み込みが可能であるが、
68 書き込み時の手間は大きくなる。 48 書き込み時の手間は大きくなる。
69 49
101 以下にEitherクラスが提供しているAPI(表\ref{EitherAPI})を記す。 81 以下にEitherクラスが提供しているAPI(表\ref{EitherAPI})を記す。
102 \begin{table}[htb] 82 \begin{table}[htb]
103 \begin{center} 83 \begin{center}
104 \caption{Eitherに実装されているAPI} 84 \caption{Eitherに実装されているAPI}
105 \begin{tabular}{|p{15em}|p{24em}|} \hline 85 \begin{tabular}{|p{15em}|p{24em}|} \hline
106 {\tt boolean isA()} & EitherがAを持っているかどうかを調べる。持っている場合trueを返す。\\ \hline 86 {\small{\tt boolean isA()}} & {\small EitherがAを持っているかどうかを調べる。持っている場合trueを返す。}\\ \hline
107 {\tt boolean isB()} & EitherがBを持っているかどうかを調べる。持っている場合trueを返す。\\ \hline 87 {\small{\tt boolean isB()}} & {\small EitherがBを持っているかどうかを調べる。持っている場合trueを返す。}\\ \hline
108 {\tt A a()} & Aの値を取得する。\\ \hline 88 {\small{\tt A a()}} &{\small Aの値を取得する。}\\ \hline
109 {\tt B b()} & Bの値を取得する。\\ \hline 89 {\small{\tt B b()}} &{\small Bの値を取得する。}\\ \hline
110 \end{tabular} 90 \end{tabular}
111 \label{EitherAPI} 91 \label{EitherAPI}
112 \end{center} 92 \end{center}
113 \end{table} 93 \end{table}
114 94
123 103
124 \begin{table}[htb] 104 \begin{table}[htb]
125 \begin{center} 105 \begin{center}
126 \caption{Jungleに実装されているAPI} 106 \caption{Jungleに実装されているAPI}
127 \begin{tabular}{|p{15em}|p{24em}|} \hline 107 \begin{tabular}{|p{15em}|p{24em}|} \hline
128 {\tt JungleTree createNewTree(String treeName) } & Jungleに新しく木を生成する。木の名前が重複した場合、生成に失敗しnullを返す。 \\ \hline 108 {\small {\tt JungleTree createNewTree(String treeName)}} &{\small Jungleに新しく木を生成する。木の名前が重複した場合、生成に失敗しnullを返す。} \\ \hline
129 {\tt JungleTree getTreeByName(String treeName)} & JungleからtreeNameと名前が一致するtreeを取得する。名前が一致するTreeがない場合取得は失敗しnullを返す \\ \hline 109 {\small {\tt JungleTree getTreeByName(String treeName)}} &{\small JungleからtreeNameと名前が一致するtreeを取得する。名前が一致するTreeがない場合取得は失敗しnullを返す。} \\ \hline
130 \end{tabular} 110 \end{tabular}
131 \label{jungleAPI} 111 \label{jungleAPI}
132 \end{center} 112 \end{center}
133 \end{table} 113 \end{table}
134 114
135 115
136 \section{JungleTree} 116 \section{JungleTree}
137 Jungleは複数の木の集合で出来ている。 117 Jungleは複数の木の集合で出来ている。
138 Jungleの木は、変更を加えるためのEditor・検索を行うTraversreなどを保持しており、ユーザーはそれらを用いてデータにアクセスする。 118 Jungleの木は、自身の情報をTreeContext というオブジェクトに保持している。
139 過去のバージョンの木に対するアクセスや、特定のノードのPathを検索する機能も持っている。 119 TreeContextとは、木構造のデータ(表\ref{TreeContext1})を持つクラスである。
120
121 \newpage
122 \begin{table}[htb]
123 \begin{center}
124 \caption{TreeContextが保持している値}
125 \begin{tabular}{|l|} \hline
126 {\tt } 自身のルートノード\\ \hline
127 {\tt } 1つ前のバージョンのTreeContext\\ \hline
128 {\tt } 編集のログ\\ \hline
129 {\tt } 木のuuid \\ \hline
130 {\tt } 木の名前 \\ \hline
131 {\tt } 木のversion \\ \hline
132 {\tt } 木の検索に使うTraverser \\ \hline
133 \end{tabular}
134 \label{TreeContext1}
135 \end{center}
136 \end{table}
137
138 Jungle の木は、自身の木構造に編集を行う Editor や 検索に使用する Traverser を提供しており、ユーザーはそれを用いて木構造にアクセスする。
139 また、過去のバージョンの木に対するアクセスや、特定のノードのPathを検索する機能も持っている。
140 以下にJungleTreeクラスが提供しているAPI(表\ref{JungleTreeAPI})を記す 140 以下にJungleTreeクラスが提供しているAPI(表\ref{JungleTreeAPI})を記す
141 \begin{table}[htb] 141 \begin{table}[htb]
142 \begin{center} 142 \begin{center}
143 \caption{JungleTreeに実装されているAPI} 143 \caption{JungleTreeに実装されているAPI}
144 \begin{tabular}{|p{15em}|p{24em}|} \hline 144 \begin{tabular}{|p{15em}|p{24em}|} \hline
145 {\tt TreeNode getRootNode()} &木のルートノードを取得する。 \\ \hline 145 {\small {\tt TreeNode getRootNode()}} &{\small 木のルートノードを取得する。} \\ \hline
146 {\tt long revision()} & 木のバーションを取得する。初めは0から始まり、木への変更がCommitされる度に1上昇する。 \\ \hline 146 {\small {\tt long revision()}} & {\small 木のバーションを取得する。初めは0から始まり、木への変更がCommitされる度に1上昇する。} \\ \hline
147 {\tt JungleTreeEditor getJungleTreeEditor()} & 木へ変更を加えるEditorを取得する。\\ \hline 147 {\small {\tt JungleTreeEditor getJungleTreeEditor()}} &{\small 木へ変更を加えるEditorを取得する。}\\ \hline
148 {\tt Either<Error, JungleTree> getOldTree(long revision)} & 引数で指定したint revisionに等しいバージョンの木を取得する。 \\ \hline 148 {\small {\tt Either<Error, JungleTree> getOldTree(long revision)}} & {\small 引数で指定したint revisionに等しいバージョンの木を取得する。} \\ \hline
149 {\tt InterfaceTraverser getTraverser()} & 木の検索を行うTraverserを取得する。 \\ \hline 149 {\small {\tt InterfaceTraverser getTraverser()}} & {\small 木の検索を行うTraverserを取得する。} \\ \hline
150 {\tt Either<Error, TreeNode> getNodeOfPath(NodePath path)} & {\tt NodePathで指定した位置と値なるノードを取得する。} \\ \hline 150 {\small {\tt Either<Error, TreeNode> getNodeOfPath(NodePath path)}} &{\small {\tt NodePathで指定した位置と値なるノードを取得する。}} \\ \hline
151 {\tt NodePath getNodePath(TreeNode node)} & 引数で渡したノードの位置を表す{\tt NodePath}を返す。\\ \hline 151 {\small {\tt NodePath getNodePath(TreeNode node)}} & {\small 引数で渡したノードの位置を表す{\tt NodePath}を返す。}\\ \hline
152 \end{tabular} 152 \end{tabular}
153 \label{JungleTreeAPI} 153 \label{JungleTreeAPI}
154 \end{center} 154 \end{center}
155 \end{table} 155 \end{table}
156 156
162 162
163 \begin{table}[htb] 163 \begin{table}[htb]
164 \begin{center} 164 \begin{center}
165 \caption{TreeNodeに実装されているAPI} 165 \caption{TreeNodeに実装されているAPI}
166 \begin{tabular}{|p{15em}|p{24em}|} \hline 166 \begin{tabular}{|p{15em}|p{24em}|} \hline
167 {\tt Children getChildren()} & ノードの子供を扱うChildrenオブジェクトを返す。\\ \hline 167 {\small {\tt Children getChildren()}} &{\small ノードの子供を扱うChildrenオブジェクトを返す} \\ \hline
168 {\tt Attribute getAttribute()} &ノードが保持しているデータを扱うAttribteオブジェクトを返す。 \\ \hline 168 {\small {\tt Attribute getAttribute()}} &{\small ノードが保持しているデータを扱うAttribteオブジェクトを返す。} \\ \hline
169 \end{tabular} 169 \end{tabular}
170 \label{TreeNodeAPI} 170 \label{TreeNodeAPI}
171 \end{center} 171 \end{center}
172 \end{table} 172 \end{table}
173 173
175 これらを利用しノードが保持している値や、子供にアクセスする。 175 これらを利用しノードが保持している値や、子供にアクセスする。
176 \begin{table}[htbH] 176 \begin{table}[htbH]
177 \begin{center} 177 \begin{center}
178 \caption{Childrenに実装されているAPI} 178 \caption{Childrenに実装されているAPI}
179 \begin{tabular}{|p{15em}|p{24em}|} \hline 179 \begin{tabular}{|p{15em}|p{24em}|} \hline
180 {\tt int size()} & 子供の数を返す。\\ \hline 180 {\small{\tt int size()}} & {\small 子供の数を返す。}\\ \hline
181 {\tt <Either Error,TreeNode> at(int num)} &ノードが持つ子供の中から、 変数{\tt num}で指定された位置にある子ノードを返す。存在しない位置を指定した場合、{\tt Error} を返す。 \\ \hline 181 {\small{\tt <Either Error,TreeNode> at(int num)}} &{\small ノードが持つ子供の中から、 変数{\tt num}で指定された位置にある子ノードを返す。存在しない位置を指定した場合、{\tt Error} を返す。} \\ \hline
182 \end{tabular} 182 \end{tabular}
183 \label{Children} 183 \label{Children}
184 \end{center} 184 \end{center}
185 \end{table} 185 \end{table}
186 186
188 188
189 \begin{table}[htbH] 189 \begin{table}[htbH]
190 \begin{center} 190 \begin{center}
191 \caption{Attributeに実装されているAPI} 191 \caption{Attributeに実装されているAPI}
192 \begin{tabular}{|p{15em}|p{24em}|} \hline 192 \begin{tabular}{|p{15em}|p{24em}|} \hline
193 {\tt ByteBuffer get(String key)} &ノードが持つ値から、属性名 {\tt key}とペアの属性値を{\tt ByteBuffer}型で返す。ノードが保持していない{\tt key}を渡した場合エラーを返す。 \\ \hline 193 {\small{\tt ByteBuffer get(String key)}} &{\small ノードが持つ値から、属性名 {\tt key}とペアの属性値を{\tt ByteBuffer}型で返す。ノードが保持していない{\tt key}を渡した場合エラーを返す。} \\ \hline
194 {\tt String getString(String key)} &ノードが持つ値から、属性名 {\tt key} とペアの属性値を{\tt String}型で返す。ノードが保持していない{\tt key}を渡した場合エラーを返す。 \\ \hline 194 {\small{\tt String getString(String key)}} &{\small ノードが持つ値から、属性名 {\tt key} とペアの属性値を{\tt String}型で返す。ノードが保持していない{\tt key}を渡した場合エラーを返す。} \\ \hline
195 \end{tabular} 195 \end{tabular}
196 \label{Attribute} 196 \label{Attribute}
197 \end{center} 197 \end{center}
198 \end{table} 198 \end{table}
199 199
210 Attribute attribute = child.getAttribute(); 210 Attribute attribute = child.getAttribute();
211 String value = attribute.getString("name"); 211 String value = attribute.getString("name");
212 \end{lstlisting} 212 \end{lstlisting}
213 213
214 ソースコード\ref{getAttributeCode}の説明を行う。 214 ソースコード\ref{getAttributeCode}の説明を行う。
215 1行目から2行目で 215
216 1行目で Jungle から木を取得し、
217 2行目で、取得した木のルートノードを取得している。
218 3 - 7行目でルートノードの1番目の子ノードを取得し、
219 8 - 9行目で、ルートの1番目の子ノードから、属性名 "name" とペアの属性値を取得している。
216 220
217 \section{木の編集API} 221 \section{木の編集API}
218 Jungleの木の編集は{\tt Default Jungle Tree Editor}クラスを用いて行われる。 222 Jungleの木の編集は{\tt Default Jungle Tree Editor}クラスを用いて行われる。
219 {\tt Default Jungle Tree Editor}クラスは、木に対する編集を行うAPIが定義されているJungle Tree Editorインターフェースを実装している。 223 {\tt Default Jungle Tree Editor}クラスは、木に対する編集を行うAPIが定義されているJungle Tree Editorインターフェースを実装している。
220 Default Jungle Tree Editorは、Jungle Tree から、{\tt getTreeEditor()}を用いて取得する。 224 Default Jungle Tree Editorは、Jungle Tree から、{\tt getTreeEditor()}を用いて取得する。
221 表\ref{editor}にJungle Tree Editorインターフェースに定義されているAPIを記述する。 225 表\ref{editor}にJungle Tree Editorインターフェースに定義されているAPIを記述する。
222 また、表\ref{editor}に記述しているAPIは全て、{\tt Either<Error,JungleTreeEditor>} を返す。 226 また、表\ref{editor}に記述しているAPIは全て、{\tt Either<Error,JungleTreeEditor>} を返す。
223 \newpage
224 227
225 \begin{table}[htb] 228 \begin{table}[htb]
226 \begin{center} 229 \begin{center}
227 \caption{Editorに実装されているAPI} 230 \caption{Editorに実装されているAPI}
228 \begin{tabular*}{\textwidth}{|p{15em}|p{22em}|} \hline 231 \begin{tabular*}{\textwidth}{|p{15em}|p{22em}|} \hline
229 {\small\tt addNewChildAt( NodePath path, int pos)} & 232 {\small\tt addNewChildAt( NodePath path, int pos)} &
230 {\tt path}で指定したノードの{\tt pos}番目の子の後にノードを追加する。\\ \hline 233 {\small\tt path}で指定したノードの{\tt pos}番目の子の後にノードを追加する。\\ \hline
231 {\small\tt deleteChildAt( NodePath path,int pos)} & 234 {\small\tt deleteChildAt( NodePath path,int pos)} &
232 {\tt path}で指定したノードの{\tt pos}番目の子ノードを削除する。 \\ \hline 235 {\small\tt path}で指定したノードの{\tt pos}番目の子ノードを削除する。 \\ \hline
233 {\small\tt putAttribute( NodePath path,String key,ByteBuffer value)} & 236 {\small\tt putAttribute( NodePath path,String key,ByteBuffer value)} &
234 {\tt path}で指定したノードに属性名 {\tt key} 属性値 {\tt value} のペアで値を挿入する。 \\ \hline 237 {\small\tt path}で指定したノードに属性名 {\tt key} 属性値 {\tt value} のペアで値を挿入する。 \\ \hline
235 {\small\tt deleteAttribute( NodePath path,String key)}& 238 {\small\tt deleteAttribute( NodePath path,String key)}&
236 {\tt path}で指定したノードが持つ、属性名 {\tt key}とペアで保存されている属性値を削除する。\\ \hline 239 {\small\tt path}で指定したノードが持つ、属性名 {\tt key}とペアで保存されている属性値を削除する。\\ \hline
237 {\small\tt moveChild( NodePath path,int num,String move)} & 240 {\small\tt moveChild( NodePath path,int num,String move)} &
238 {\tt path}で指定したノードの{\tt num}番目の子供を{\tt move}の方向に移動させる。 \\ \hline %あとで直す 241 {\small\tt path}で指定したノードの{\tt num}番目の子供を{\tt move}の方向に移動させる。 \\ \hline %あとで直す
239 {\small\tt pushPop()} & 242 {\small\tt pushPop()} &
240 ルートノードの上に新しいルートノードを追加する。線形の木を作る際に使用することで木の変更の手間をO(n)からO(1)にできる。\\ \hline 243 ルートノードの上に新しいルートノードを追加する。線形の木を作る際に使用することで木の変更の手間をO(n)からO(1)にできる。\\ \hline
241 {\small\tt success()} & 244 {\small\tt success()} &
242 木へ行った変更をコミットする。自分が編集を行っていた間に、他のJungleTreeEditorクラスによって木が更新されていた場合、コミットは失敗する。 \\ \hline 245 木へ行った変更をコミットする。自分が編集を行っていた間に、他のJungleTreeEditorクラスによって木が更新されていた場合、コミットは失敗する。 \\ \hline
243 \end{tabular*} 246 \end{tabular*}
245 \end{center} 248 \end{center}
246 \end{table} 249 \end{table}
247 250
248 251
249 252
250 編集後に返される{\tt JungleTreeEditor}クラスは、編集後の木構造を保持しているため、編集前の木構造を保持している{\tt JungleTreeEditor}クラスとは別のオブジェクトである。 253 編集後に返される{\tt Default Jungle Tree Editor}クラスは、編集後の木構造を保持しているため、編集前の木構造を保持している{\tt Default Jungle Tree Editor}クラスとは別のオブジェクトである。
251 編集を行った後は、関数{\tt editor.success()}で今までの編集をコミットすることができる。他の{\tt JungleTreeEditor}クラスによって木が更新されていた場合はコミットは失敗し、{\tt success()}は{\tt Error}を返す。 254 編集を行った後は、関数{\tt editor.success()}で今までの編集をコミットすることができる。他の{\tt Default Jungle Tree Editor}クラスによって木が更新されていた場合はコミットは失敗し、{\tt success()}は{\tt Error}を返す。
252 その場合は、木の編集を最初からやり直す必要がある。 255 その場合は、木の編集を最初からやり直す必要がある。
253 256
254 以下に{\tt JungleTreeEditor}クラスを用いて、木の編集を行うサンプルコードを記述する。 257 以下に{\tt JungleTreeEditor}クラスを用いて、木の編集を行うサンプルコードを記述する。
255
256 \newpage
257 258
258 \begin{lstlisting}[frame=lrbt,numbers=left,label=editorCode] 259 \begin{lstlisting}[frame=lrbt,numbers=left,label=editorCode]
259 JungleTreeEditor editor = tree.getTreeEditor(); 260 JungleTreeEditor editor = tree.getTreeEditor();
260 DefaultNodePath editNodePath = new DefaultNodePath(); 261 DefaultNodePath editNodePath = new DefaultNodePath();
261 Either<Error, JungleTreeEditor> either = editor.addNewChildAt(editNodePath, 0); 262 Either<Error, JungleTreeEditor> either = editor.addNewChildAt(editNodePath, 0);
263 return either.a(); 264 return either.a();
264 editor = either.b(); 265 editor = either.b();
265 editor.success(); 266 editor.success();
266 \end{lstlisting} 267 \end{lstlisting}
267 268
269 1行目で、木から Editor を取得している。
270 2行目で、編集を行うノードの Path を作成している。Default Node Path は、生成時はルートノードを指しているため、今回はルートノードに対する変更であることがわかる。
271 3行目で、実際にルートノードに対して、子ノードの追加を行っている。
272 4行目以降で、編集が成功したかどうかを {\tt Either }を使って確かめ、成功していた場合7行目で変更を木に Commit している。
273
274 \begin{comment}
268 \begin{enumerate} 275 \begin{enumerate}
269 \item 関数{\tt tree.getEditor()}で編集を行う木から、{\tt JungleTreeEditor}クラスを取得する。 276 \item 関数{\tt tree.getEditor()}で編集を行う木から、{\tt JungleTreeEditor}クラスを取得する。
270 \item 次に変更するノードの場所を示す、{\tt NodePath}クラスを作成する。 277 \item 次に変更するノードの場所を示す、{\tt NodePath}クラスを作成する。
271 \item 関数{\tt editor.addNewChildAt()}を用いて、変数{\tt path}で指定したノードの子供の0番目に子ノードを追加する。 278 \item 関数{\tt editor.addNewChildAt()}を用いて、変数{\tt path}で指定したノードの子供の0番目に子ノードを追加する。
272 \item 返り値の変数{\tt either}が{\tt Error}クラスを保持していないか(編集に失敗していないか)を確認する。 279 \item 返り値の変数{\tt either}が{\tt Error}クラスを保持していないか(編集に失敗していないか)を確認する。
273 \item {\tt Error}クラスを保持していた場合{\tt Either.a()}でErrorを返す。 280 \item {\tt Error}クラスを保持していた場合{\tt Either.a()}でErrorを返す。
274 \item 編集に成功していた場合、編集後木を持った、{\tt JungleTreeEditor}クラスを取得する。 281 \item 編集に成功していた場合、編集後木を持った、{\tt JungleTreeEditor}クラスを取得する。
275 \item 取得した{\tt JungleTreeEditor}クラスを用いて木の変更をコミットする。 282 \item 取得した{\tt JungleTreeEditor}クラスを用いて木の変更をコミットする。
276 \end{enumerate} 283 \end{enumerate}
284 \end{comment}
277 285
278 また、木に対して行われた変更は、Logとして書き出される。 286 また、木に対して行われた変更は、Logとして書き出される。
287
288 \section{Commit}
289 Jungle Tree Editor を用いて木に変更を加えた後は、Commit を行う必要がある。
290 Commit は、前節で記述した Jungle Tree Editor が持つ関数 {\tt success()} を使用することで行われる。
291
292 Commit を行うと、Jungle Tree Editor が保持している編集後の木構造のデータを持つ TreeContext を作成する。
293 そして、編集前の木が持つ TreeContext と 新しく作った TreeContext を置き換えることで Commit は完了する。
294 TreeContext の置き換えは、編集を行っている他の Thread と競合した際に、木の整合性を保つために以下の手順で行われる。
295
296 \begin{enumerate}
297 \item 新しく作った TreeContext が持つ、1つ前のバージョンの TreeContext と、編集前の木構造の TreeContext を比較する。
298
299 \item 一致しなかった場合、他のが Thread が Commit をすでに行っているため、失敗する(競合に負けた)。
300
301 \item 一致した場合、TreeContext を Atomic に入れ替える(競合に勝った)。
302 \end{enumerate}
303
304 競合に負けた場合は、新しい木に対してもう一度同じ変更を行う必要がある。
279 これらのAPIにより、Jungleは木構造を格納、編集する機能を持っている。 305 これらのAPIにより、Jungleは木構造を格納、編集する機能を持っている。
280 306
281 \section{Log} 307 \section{Log}
282 Jungle は、 Editor を用いて木に編集を加える際、使用した API に応じて対応する NodeOperation を作成する。 308 Jungle は、 Editor を用いて木に編集を加える際、使用した API に応じて対応する NodeOperation を作成する。
283 NodeOperation は NodePath とペアで扱わなければならず、このペアを TreeOperation という。 309 NodeOperation は NodePath とペアで扱わなければならず、このペアを TreeOperation という。
285 この TreeOperation の集まりを TreeOperationLog という。 311 この TreeOperation の集まりを TreeOperationLog という。
286 TreeOperationLogの仕様をソースコード\ref{src:treeoperationlog}に示す. 312 TreeOperationLogの仕様をソースコード\ref{src:treeoperationlog}に示す.
287 \begin{lstlisting}[frame=lrbt,label=src:treeoperationlog,caption=TreeOperationLogの仕様,numbers=left] 313 \begin{lstlisting}[frame=lrbt,label=src:treeoperationlog,caption=TreeOperationLogの仕様,numbers=left]
288 public interface TreeOperationLog extends Iterable<TreeOperation> 314 public interface TreeOperationLog extends Iterable<TreeOperation>
289 { 315 {
290 public TreeOperationLog add(NodePath _p,NodeOperation _op); 316 public TreeOperationLog add(NodePath _p,NodeOperation _op);
291 public TreeOperationLog append(TreeOperationLog _log); 317 public TreeOperationLog append(TreeOperationLog _log);
292 public int length(); 318 public int length();
293 } 319 }
294 \end{lstlisting} 320 \end{lstlisting}
295 321
296 \verb|Iterable<TreeOperation>|を継承しているためIteratorによりTreeOperationを取り出せるようになっている。 322 \verb|Iterable<TreeOperation>|を継承しているためIteratorによりTreeOperationを取り出せるようになっている。
297 addやappendメソッドを使ってTreeOperationを積み上げていくことができる。 323 addやappendメソッドを使ってTreeOperationを積み上げていくことができる。
301 327
302 328
303 329
304 \section{検索API} 330 \section{検索API}
305 これまでに紹介したAPIにより、Jungleは木構造を構築できるようになった。 331 これまでに紹介したAPIにより、Jungleは木構造を構築できるようになった。
306 しかし、木に問い合わせを行う検索APIが実装されていなかったため、木の走査を行う{\tt Traverser}クラス内に、lambda式を用いて実装した。 332 しかし、木に問い合わせを行う検索APIが実装されていなかったため、木の走査を行う{\tt Interface Traverser}クラス内に、lambda式を用いて実装した。
307 以下に検索を行う関数{\tt find}の定義を記述する。 333 以下に検索を行う関数{\tt find}の定義を記述する。
308 \begin{lstlisting}[frame=lrbt,label=query,numbers=left] 334 \begin{lstlisting}[frame=lrbt,label=query,numbers=left]
309 public Iterator<TreeNode> find(Query query, String key, String searchValue); 335 public Iterator<TreeNode> find(Query query, String key, String searchValue);
310 \end{lstlisting} 336 \end{lstlisting}
311 337
312 関数{\tt find}は、第一引数には、探索の条件を記述する関数{\tt boolean comdition(TreeNode)}を定義した{\tt Query}を。 338 関数{\tt find}は、第一引数には、探索の条件を記述する関数{\tt boolean comdition(TreeNode)}を定義した{\tt Query}を、
313 第二、第三引数には、Indexを用いた絞込に使用する{\tt String key、String value}を取り、条件に一致したノードの{\tt Iterator}を返す。 339 第二、第三引数には、Indexを用いた絞込に使用する{\tt String key、String value}を取り、条件に一致したノードの{\tt Iterator}を返す。
314 {\tt 関数find}の使用例を以下に記す。 340 {\tt 関数find}の使用例を以下に記す。
315 341
316 \begin{lstlisting}[frame=lrbt,label=find,numbers=left] 342 \begin{lstlisting}[frame=lrbt,label=find,numbers=left]
317 InterfaceTraverser traverser = tree.getTraverser(true); 343 InterfaceTraverser traverser = tree.getTraverser(true);
318 Iterator<TreeNode> resultNodeIterator = traverser.find((TreeNode node) -> { 344 Iterator<TreeNode> resultNodeIterator = traverser.find((TreeNode node) -> {
319 String personId = node.getAttributes().getString("name"); 345 String name = node.getAttributes().getString("name");
320 if (personId == null) return false; 346 if (name == null) return false;
321 return personId.equals("kanagawa"); 347 return name.equals("kanagawa");
322 }, "belong", "ryukyu"); 348 }, "belong", "ryukyu");
323 \end{lstlisting} 349 \end{lstlisting}
324 350
325 351
326 上記コードについて解説する。 352 上記コードについて解説する。
353
354 1行目で検索対象の木から、検索に使用する {\tt Interface Traverser} を取得する。
355 2行目で、検索を行う関数 {\tt find()} を使用する。
356 今回は、Index を使って、属性名 {\tt "belong"} 属性値 {\tt "ryukyu"} を持つノード取得し、
357 3 - 5行目で定義されたクエリに渡す。
358
359 そして、クエリの中で属性名 {\tt "name"} 属性値 {\tt "kanagawa"} を持つノードかどうかを確かめる。
360
361 結果として、属性名 {\tt "belong"} 属性値{\tt "ryukyu"}と、属性名 {\tt "name"} 属性値{\tt kanagawa}の2つのデータを持つノードの {\tt Iterator} が取得できる。
362
363 検索の際に使用する Index の実装については次節に記述する。
364
365 \begin{comment}
327 \begin{enumerate} 366 \begin{enumerate}
328 \item 木の走査を行う{\tt Traverser}クラスを取得する。 367 \item 木の走査を行う{\tt Traverser}クラスを取得する。
329 368
330 \item Indexから{\tt find}の第2、第3引数である、属性名 {\tt belong}、属性値 {\tt ryukyu}の組のデータを持つノードを取得し、Queryに渡す(ノードの絞込を行う)。 369 \item Indexから{\tt find}の第2、第3引数である、属性名 {\tt belong}、属性値 {\tt ryukyu}の組のデータを持つノードを取得し、Queryに渡す(ノードの絞込を行う)。
331 370
332 \item 引数のノードから関数{\tt getAttributes().getString("name")}で属性名 {\tt name}とペアになっている属性値を取得する。 371 \item 引数のノードから関数{\tt getAttributes().getString("name")}で属性名 {\tt name}とペアになっている属性値を取得する。
333 372
334 \item 属性値が{\tt null}だった場合、このノードには属性名が{\tt name}の組のデータは存在しないので、{\tt false}を返し次のノードの評価を行う。 373 \item 属性値が{\tt null}だった場合、このノードには属性名が{\tt name}の組のデータは存在しないので、{\tt false}を返し次のノードの評価を行う。
335 374
336 \item 属性値が{\tt null}でなかった場合、{\tt kanagawa}と一致するかどうかを調べ結果を返す。 375 \item 属性値が{\tt null}でなかった場合、{\tt kanagawa}と一致するかどうかを調べ結果を返す。
337 376
338 \end{enumerate} 377 \end{enumerate}
339 378 \end{comment}
340 結果として、{\tt ryukyu}に所属する、名前が{\tt kanagawa}のデータを持つノードが取得できる。 379
341
342 検索の際に使用する Index の実装については次節に記述する。
343 380
344 \section{Index} 381 \section{Index}
345 Jungleは、非破壊的木構造というデータ構造上、過去の版の木構造を全て保持している。 382 Jungleは、非破壊的木構造というデータ構造上、過去の版の木構造を全て保持している。
346 よって、全ての版に独立したIndexが必要となるため、前の版のIndexを破壊すること無く、Indexを更新する必要がある。 383 よって、全ての版に独立したIndexが必要となるため、前の版のIndexを破壊すること無く、Indexを更新する必要がある。
347 既存のTreeMapでは、一度Indexの複製を行ない、その後更新する必要があったため、Indexの更新オーダーがO(n)となっていた。 384 既存のTreeMapでは、一度Indexの複製を行ない、その後更新する必要があったため、Indexの更新オーダーがO(n)となっていた。
362 399
363 \begin{lstlisting}[frame=lrbt,label=find,numbers=left] 400 \begin{lstlisting}[frame=lrbt,label=find,numbers=left]
364 Optional<TreeMap<String, List<TreeNode>>> indexOp = indexMap.get("name"); 401 Optional<TreeMap<String, List<TreeNode>>> indexOp = indexMap.get("name");
365 if (!indexOp.isPresent()) 402 if (!indexOp.isPresent())
366 return new NulIterator<TreeNode>(); 403 return new NulIterator<TreeNode>();
367 TreeMap<String, List<TreeNode>> index = indexOp.get(); 404 TreeMap<String, List<TreeNode>> index = indexOp.get();
368 Optional<List<TreeNode>> nodeListOp = index.get("kanagawa"); 405 Optional<List<TreeNode>> nodeListOp = index.get("kanagawa");
369 if (!nodeListOp.isPresent()) 406 if (!nodeListOp.isPresent())
370 return new NulIterator<TreeNode>(); 407 return new NulIterator<TreeNode>();
371 return nodeListOp.get().iterator(); 408 return nodeListOp.get().iterator();
372 \end{lstlisting} 409 \end{lstlisting}
373 410
374 411 1 - 4行目で IndexMap から 属性名 "name" に対する値を持つ Index を取得している。
375 \begin{enumerate} 412 5 - 8行目で 取得した Index から、 属性名 "kanagawa" を持つノードの{ \tt Iterator}を取得している。
376 \item {\tt indexMap}に、今回検索で使用する属性名 {\tt name}を使用して{\tt get("name")}を行う。すると属性名 {\tt "name"}に対応したIndexが、{\tt Optional}クラスで包まれて返ってくる。 413
377 414
378 \item {\tt Optional}オブジェクトに対して、中身を保持しているか(属性名 {\tt name}に対応したIndexを木が持っているか)を調べる。 415 \begin{comment}
379 416 \begin{enumerate}
380 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。 417 \item {\tt indexMap}に、今回検索で使用する属性名 {\tt name}を使用して{\tt get("name")}を行う。すると属性名 {\tt "name"}に対応したIndexが、{\tt Optional}クラスで包まれて返ってくる。
381 418
382 \item 持っていた場合、{\tt Optional}オブジェクトからIndexを取得する。 419 \item {\tt Optional}オブジェクトに対して、中身を保持しているか(属性名 {\tt name}に対応したIndexを木が持っているか)を調べる。
383 420
384 \item 取得したIndexに、検索で使用する属性値{\tt "kanagawa"}で{\tt get()}を行う。すると、属性名 {\tt "name"} 属性値{\tt "kanagawa"}の値を持つノードのリストが、{\tt Optional}クラスに包まれて返ってくる。 421 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。
385 422
386 \item {\tt Optional}オブジェクトに対して中身を保持しているか(属性名 {\tt "name"} 属性値 {\tt "kanagawa"}を持つノードを木が持っているか)を調べる。 423 \item 持っていた場合、{\tt Optional}オブジェクトからIndexを取得する。
387 424
388 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。 425 \item 取得したIndexに、検索で使用する属性値{\tt "kanagawa"}で{\tt get()}を行う。すると、属性名 {\tt "name"} 属性値{\tt "kanagawa"}の値を持つノードのリストが、{\tt Optional}クラスに包まれて返ってくる。
389 426
390 \item 持っていた場合{\tt Optional}オブジェクトからノードリストの{\tt Iterator}を返す。 427 \item {\tt Optional}オブジェクトに対して中身を保持しているか(属性名 {\tt "name"} 属性値 {\tt "kanagawa"}を持つノードを木が持っているか)を調べる。
391 428
392 \end{enumerate} 429 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。
393 430
394 JungleはこれらのAPIにより、木構造を格納、編集、検索する機能を持っている。 431 \item 持っていた場合{\tt Optional}オブジェクトからノードリストの{\tt Iterator}を返す。
395 432
396 \newpage 433 \end{enumerate}
434 \end{comment}
435
436 JungleはこれらのAPIにより、木構造を格納、編集、検索する機能を持っている。
437
438 \newpage