comparison jungle.tex @ 14:e4da23b04260

commit
author tatsuki
date Wed, 08 Feb 2017 17:26:22 +0900
parents f75a57018792
children 33d8077a5d45
comparison
equal deleted inserted replaced
13:7acd7d5afeb6 14:e4da23b04260
1 \chapter{非破壊的木構造データベースJungle} 1 \chapter{非破壊的木構造データベースJungle}
2 本章では、当研究室で開発を行っているデータベース Jungle について記述する。
3
4 \section{概要}
2 Jungleは、当研究室で開発を行っているデータベースで、Javaを用いて実装されている。 5 Jungleは、当研究室で開発を行っているデータベースで、Javaを用いて実装されている。
3 Jungleは名前付きの複数の木の集合からなり、木は複数のノードの集合で出来ている。 6 Jungleは名前付きの複数の木の集合からなり、木は複数のノードの集合で出来ている。
4 ノードは自身の子のリストと属性名と属性値の組でデータを持ち、データベースのレコードに相当する。 7 ノードは自身の子のリストと属性名と属性値の組でデータを持ち、データベースのレコードに相当する。
5 通常のレコードと異なるのは、ノードに子供となる複数のノードが付くところである。 8 通常のレコードと異なるのは、ノードに子供となる複数のノードが付くところである。
6 Jungleでは、親から子への片方向の参照しか持たない。 9 Jungleでは、親から子への片方向の参照しか持たない。
15 Jungleは分散データベースを構成するように設計されており、分散ノード間の通信は木の変更のログを交換することによって行われる。 18 Jungleは分散データベースを構成するように設計されており、分散ノード間の通信は木の変更のログを交換することによって行われる。
16 持続性のある分散ノードを用いることでJungleの持続性を保証することができる。本論文では基本的に分散実装部分ではなく on memory DBの 19 持続性のある分散ノードを用いることでJungleの持続性を保証することができる。本論文では基本的に分散実装部分ではなく on memory DBの
17 部分について考察する。 20 部分について考察する。
18 本章ではまず破壊的木構造と、非破壊的木構造の説明をし、その後Jungleの提供しているAPIについて述べる。 21 本章ではまず破壊的木構造と、非破壊的木構造の説明をし、その後Jungleの提供しているAPIについて述べる。
19 22
20 \section{破壊的木構造} 23 \newpage
24
25 \section{非破壊的木構造}
26 Jungle は、非破壊的木構造という特殊な木構造を持つ。
27 本節では、初めに破壊的木構造と非破壊的木構造の編集・メリットデメリットについて記述する。
28
29 \vspace{0.3in}
30 {\Large 破壊的木構造の編集}
31
32 \vspace{0.1in}
21 破壊的木構造の編集は, 木構造で保持しているデータを直接書き換えることで行う。 33 破壊的木構造の編集は, 木構造で保持しているデータを直接書き換えることで行う。
22 図\ref{fig:destractive}は破壊的木構造におけるデータ編集を表している。 34 図\ref{fig:destractive}は破壊的木構造におけるデータ編集を表している。
23 35
24 \begin{figure}[htpb] 36 \begin{figure}[htpb]
25 \begin{center} 37 \begin{center}
31 43
32 破壊的木構造は、編集を行う際に木のロックを掛ける必要がある。 44 破壊的木構造は、編集を行う際に木のロックを掛ける必要がある。
33 この時、データを受け取ろうと木を走査するスレッドは書き換えの終了を待つ必要があり、 45 この時、データを受け取ろうと木を走査するスレッドは書き換えの終了を待つ必要があり、
34 閲覧者がいる場合は木の走査が終わるまで書き換えを待たなければならない。 46 閲覧者がいる場合は木の走査が終わるまで書き換えを待たなければならない。
35 47
36 \section{非破壊的木構造} 48
49 \vspace{0.3in}
50 {\Large 非破壊的木構造の編集}
51
52 \vspace{0.1in}
37 データの編集を一度生成した木を上書きせず、ルートから編集を行うノードまでコピーを行い新しく木構造を構築し、そのルートをアトミックに入れ替えることで行う(図\ref{fig:nondestractive})。 53 データの編集を一度生成した木を上書きせず、ルートから編集を行うノードまでコピーを行い新しく木構造を構築し、そのルートをアトミックに入れ替えることで行う(図\ref{fig:nondestractive})。
38 その際、編集に関係ないノードは参照を行い、複製元の木と共有する(図\ref{fig:nondestractive}の例ではノード1・3・4は編集に関係ないため新しいルートノードから参照を行い、過去の木と共有を行っている)。 54 その際、編集に関係ないノードは参照を行い、複製元の木と共有する(図\ref{fig:nondestractive}の例ではノード1・3・4は編集に関係ないため新しいルートノードから参照を行い、過去の木と共有を行っている)。
39 55
40 \begin{figure}[htpb] 56 \begin{figure}[htpb]
41 \begin{center} 57 \begin{center}
43 \caption{非破壊的木構造の編集} 59 \caption{非破壊的木構造の編集}
44 \label{fig:nondestractive} 60 \label{fig:nondestractive}
45 \end{center} 61 \end{center}
46 \end{figure} 62 \end{figure}
47 63
64 \newpage
48 非破壊的木構造においてデータのロックが必要となる部分は、木のコピーを作り終えた後に 65 非破壊的木構造においてデータのロックが必要となる部分は、木のコピーを作り終えた後に
49 ルートノードを更新するときだけである。 66 ルートノードを更新するときだけである。
50 データ編集を行っている間ロックが必要な破壊的木構造に比べ、編集中においてもデータの読み込みが可能であるが、 67 データ編集を行っている間ロックが必要な破壊的木構造に比べ、編集中においてもデータの読み込みが可能であるが、
51 書き込み時の手間は大きくなる。 68 書き込み時の手間は大きくなる。
52 69
70
71
53 \begin{figure}[htpb] 72 \begin{figure}[htpb]
54 \begin{center} 73 \begin{center}
55 \includegraphics[scale=0.7]{figures/non_destructive_merit.pdf} 74 \includegraphics[scale=0.7]{figures/non_destructive_merit.pdf}
56 \caption{非破壊的木構造による利点} 75 \caption{非破壊的木構造による利点}
57 \label{fig:nondestractive_merit} 76 \label{fig:nondestractive_merit}
58 \end{center} 77 \end{center}
59 \end{figure} 78 \end{figure}
79
80 また、過去の木を保持する場合、非破壊的木構造は、木の複製後編集を行う必要がある。
81 一方、非破壊的木構造は過去の木を上書きしないため、過去の木のルートノードを保持するだけで良い。
60 82
61 \section{NodePath} 83 \section{NodePath}
62 Jungleでは、木のノードの位置を{\tt NodePath}クラスを使って表す。 84 Jungleでは、木のノードの位置を{\tt NodePath}クラスを使って表す。
63 {\tt NodePath}クラスはルートノードからスタートし、対象のノードまでの経路を数字を用いて指し示す。また、ルートノードは例外として-1と表記される。 85 {\tt NodePath}クラスはルートノードからスタートし、対象のノードまでの経路を数字を用いて指し示す。また、ルートノードは例外として-1と表記される。
64 {\tt NodePath}クラスを用いて{\tt< -1,1,2,3>}を表している際の例を図\ref{NodePath}に記す。 86 {\tt NodePath}クラスを用いて{\tt< -1,1,2,3>}を表している際の例を図\ref{NodePath}に記す。
174 \label{Attribute} 196 \label{Attribute}
175 \end{center} 197 \end{center}
176 \end{table} 198 \end{table}
177 199
178 \newpage 200 \newpage
179 以下にルートノードの2番目の子供から、属性名 {\tt name}とペアになっている属性値を取得するサンプルコードを記述する。 201 以下にルートノードの2番目の子供から、属性名 {\tt name}とペアになっている属性値を取得するサンプルコード\ref{getAttributeCode}を記述する。
180 \begin{lstlisting}[frame=lrbt,numbers=left,label=getAttributeCode] 202 \begin{lstlisting}[frame=lrbt,numbers=left,label=getAttributeCode]
181 JungleTree tree = jungle.getTreeByName("TreeName"); 203 JungleTree tree = jungle.getTreeByName("TreeName");
182 TreeNode root = tree.getRootNode(); 204 TreeNode root = tree.getRootNode();
183 Children children = root.getChildren(); 205 Children children = root.getChildren();
184 Either<Error,TreeNode> either = children.at(1); 206 Either<Error,TreeNode> either = children.at(1);
187 TreeNode child = either.b(); 209 TreeNode child = either.b();
188 Attribute attribute = child.getAttribute(); 210 Attribute attribute = child.getAttribute();
189 String value = attribute.getString("name"); 211 String value = attribute.getString("name");
190 \end{lstlisting} 212 \end{lstlisting}
191 213
192 \begin{enumerate} 214 ソースコード\ref{getAttributeCode}の説明を行う。
193 \item Jungleから名前が{\tt "TreeName"}の木を取得する。 215 1行目から2行目で
194 \item 取得した木のルートノードを取得する。
195 \item 木のルートノードから{\tt Children}を取得する。
196 \item 3で取得した{\tt Children}から2番目の子供を取得する。
197 \item 関数{\tt Either.isA()}を用いて、2番目の子供が取得できたかを調べる。
198 \item 取得できていなかった場合{\tt Either.a()}でErrorを返す。
199 \item 取得に成功していた場合、{\tt Either.b()}で子ノードを取得する。
200 \item 取得した子ノードから{\tt Attribute}クラスを取得する。
201 \item 取得した{\tt attribute}から属性名 {\tt name}とペアの属性値を取得する。
202 \end{enumerate}
203 216
204 \section{木の編集API} 217 \section{木の編集API}
205 Jungleの木の編集は{\tt Default Jungle Tree Editor}クラスを用いて行われる。 218 Jungleの木の編集は{\tt Default Jungle Tree Editor}クラスを用いて行われる。
206 {\tt Default Jungle Tree Editor}クラスは、木に対する編集を行うAPIが定義されているJungle Tree Editorインターフェースを実装している。 219 {\tt Default Jungle Tree Editor}クラスは、木に対する編集を行うAPIが定義されているJungle Tree Editorインターフェースを実装している。
207 Default Jungle Tree Editorは、Jungle Tree から、{\tt getTreeEditor()}を用いて取得する。 220 Default Jungle Tree Editorは、Jungle Tree から、{\tt getTreeEditor()}を用いて取得する。
208 表\ref{editor}にJungle Tree Editorインターフェースに定義されているAPIを記述する。 221 表\ref{editor}にJungle Tree Editorインターフェースに定義されているAPIを記述する。
209 222 また、表\ref{editor}に記述しているAPIは全て、{\tt Either<Error,JungleTreeEditor>} を返す。
210 \newpage 223 \newpage
211 224
212 \begin{table}[htb] 225 \begin{table}[htb]
213 \begin{center} 226 \begin{center}
214 \caption{Editorに実装されているAPI} 227 \caption{Editorに実装されているAPI}
215 \begin{tabular}{|p{15em}|p{24em}|} \hline 228 \begin{tabular*}{\textwidth}{|p{15em}|p{22em}|} \hline
216 {\tt Either<Error, JungleTreeEditor> addNewChildAt( NodePath path, int pos)} & 229 {\small\tt addNewChildAt( NodePath path, int pos)} &
217 変数{\tt path}で指定した場所にあるノードの、変数{\tt pos}で指定した位置に子ノードを追加する。\\ \hline 230 {\tt path}で指定したノードの{\tt pos}番目の子の後にノードを追加する。\\ \hline
218 {\tt Either<Error, JungleTreeEditor> deleteChildAt( NodePath path,int pos)} & 231 {\small\tt deleteChildAt( NodePath path,int pos)} &
219 変数{\tt path}で指定した場所にあるノードの、変数{\tt pos}で指定した位置の子ノードを削除する。 \\ \hline 232 {\tt path}で指定したノードの{\tt pos}番目の子ノードを削除する。 \\ \hline
220 {\tt Either<Error, JungleTreeEditor> putAttribute( NodePath path,String key,ByteBuffer value)} & 233 {\small\tt putAttribute( NodePath path,String key,ByteBuffer value)} &
221 変数{\tt path}で指定した場所にあるノードに、属性名 変数{\tt key} 属性値 変数{\tt value} のペアで値を挿入する。 \\ \hline 234 {\tt path}で指定したノードに属性名 {\tt key} 属性値 {\tt value} のペアで値を挿入する。 \\ \hline
222 {\tt Either< Error, JungleTreeEditor> deleteAttribute( NodePath path,String key)}& 235 {\small\tt deleteAttribute( NodePath path,String key)}&
223 変数{\tt path}で指定した場所にあるノードが持つ、属性名 変数{\tt key}とペアで保存されている属性値を削除する。\\ \hline 236 {\tt path}で指定したノードが持つ、属性名 {\tt key}とペアで保存されている属性値を削除する。\\ \hline
224 {\tt Either<Error, JungleTreeEditor> moveChild( NodePath path,int num,String move)} & 237 {\small\tt moveChild( NodePath path,int num,String move)} &
225 変数{\tt path}で指定した場所にあるノードの、変数{\tt num}で指定された位置の子供を変数{\tt move}の方向に移動させる。 \\ \hline 238 {\tt path}で指定したノードの{\tt num}番目の子供を{\tt move}の方向に移動させる。 \\ \hline %あとで直す
226 {\tt Either<Error, JungleTreeEditor> pushPop()} & 239 {\small\tt pushPop()} &
227 ルートノードの上に新しいルートノードを追加する。線形の木を作る際に使用することで木の変更の手間をO(n)からO(1)にできる。\\ \hline 240 ルートノードの上に新しいルートノードを追加する。線形の木を作る際に使用することで木の変更の手間をO(n)からO(1)にできる。\\ \hline
228 {\tt Either<Error, JungleTreeEditor> success()} & 241 {\small\tt success()} &
229 木へ行った変更をコミットする。自分が編集を行っていた間に、他のJungleTreeEditorクラスによって木が更新されていた場合、コミットは失敗する。 \\ \hline 242 木へ行った変更をコミットする。自分が編集を行っていた間に、他のJungleTreeEditorクラスによって木が更新されていた場合、コミットは失敗する。 \\ \hline
230 \end{tabular} 243 \end{tabular*}
231 \label{editor} 244 \label{editor}
232 \end{center} 245 \end{center}
233 \end{table} 246 \end{table}
234 247
235 248
286 分散版Jungleでは、Logを他ノードに送ることで、データの分散を行う。 299 分散版Jungleでは、Logを他ノードに送ることで、データの分散を行う。
287 300
288 301
289 302
290 303
291 \section{検索APIの実装} 304 \section{検索API}
292 これまでに紹介したAPIにより、Jungleは木構造を構築できるようになった。 305 これまでに紹介したAPIにより、Jungleは木構造を構築できるようになった。
293 しかし、木に問い合わせを行う検索APIが実装されていなかったため、木の走査を行う{\tt Traverser}クラス内に、lambda式を用いて実装した。 306 しかし、木に問い合わせを行う検索APIが実装されていなかったため、木の走査を行う{\tt Traverser}クラス内に、lambda式を用いて実装した。
294 以下に検索を行う関数{\tt find}の定義を記述する。 307 以下に検索を行う関数{\tt find}の定義を記述する。
295 \begin{lstlisting}[frame=lrbt,label=query,numbers=left] 308 \begin{lstlisting}[frame=lrbt,label=query,numbers=left]
296 public Iterator<TreeNode> find(Query query, String key, String searchValue); 309 public Iterator<TreeNode> find(Query query, String key, String searchValue);
326 339
327 結果として、{\tt ryukyu}に所属する、名前が{\tt kanagawa}のデータを持つノードが取得できる。 340 結果として、{\tt ryukyu}に所属する、名前が{\tt kanagawa}のデータを持つノードが取得できる。
328 341
329 検索の際に使用する Index の実装については次節に記述する。 342 検索の際に使用する Index の実装については次節に記述する。
330 343
331 \section{Indexの実装} 344 \section{Index}
332 Jungleは、非破壊的木構造というデータ構造上、過去の版の木構造を全て保持している。 345 Jungleは、非破壊的木構造というデータ構造上、過去の版の木構造を全て保持している。
333 よって、全ての版に独立したIndexが必要となるため、前の版のIndexを破壊すること無く、Indexを更新する必要がある。 346 よって、全ての版に独立したIndexが必要となるため、前の版のIndexを破壊すること無く、Indexを更新する必要がある。
334 既存のTreeMapでは、一度Indexの複製を行ない、その後更新する必要があったため、Indexの更新オーダーがO(n)となっていた。 347 既存のTreeMapでは、一度Indexの複製を行ない、その後更新する必要があったため、Indexの更新オーダーがO(n)となっていた。
335 その問題を解決するため、非破壊TreeMapを自作し、それを用いてIndexの実装を行った。 348 その問題を解決するため、非破壊TreeMapを自作し、それを用いてIndexの実装を行った。
336 このTreeMapは、Jungleと同じようにルートから変更を加えたノードまでの経路の複製を行い、データの更新を行った際、前の版と最大限データを共有した新しいTreeMapを作成する。 349 このTreeMapは、Jungleと同じようにルートから変更を加えたノードまでの経路の複製を行い、データの更新を行った際、前の版と最大限データを共有した新しいTreeMapを作成する。
358 return nodeListOp.get().iterator(); 371 return nodeListOp.get().iterator();
359 \end{lstlisting} 372 \end{lstlisting}
360 373
361 374
362 \begin{enumerate} 375 \begin{enumerate}
363 \item {\tt indexMap}に、今回検索で使用する属性名 {\tt name}を使用して{\tt get("name")}を行う。すると属性名 {\tt name}に対応したIndexが、{\tt Optional}クラスで包まれて返ってくる。 376 \item {\tt indexMap}に、今回検索で使用する属性名 {\tt name}を使用して{\tt get("name")}を行う。すると属性名 {\tt "name"}に対応したIndexが、{\tt Optional}クラスで包まれて返ってくる。
364 377
365 \item {\tt Optional}オブジェクトに対して、中身を保持しているか(属性名 {\tt name}に対応したIndexを木が持っているか)を調べる。 378 \item {\tt Optional}オブジェクトに対して、中身を保持しているか(属性名 {\tt name}に対応したIndexを木が持っているか)を調べる。
366 379
367 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。 380 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。
368 381
369 \item 持っていた場合、{\tt Optional}オブジェクトからIndexを取得する。 382 \item 持っていた場合、{\tt Optional}オブジェクトからIndexを取得する。
370 383
371 \item 取得したIndexに、検索で使用する属性値{\tt kanagawa}で{\tt get()}を行う。すると、属性名 {\tt name} 属性値{\tt kanagawa}の値を持つノードのリストが、{\tt Optional}クラスに包まれて返ってくる。 384 \item 取得したIndexに、検索で使用する属性値{\tt "kanagawa"}で{\tt get()}を行う。すると、属性名 {\tt "name"} 属性値{\tt "kanagawa"}の値を持つノードのリストが、{\tt Optional}クラスに包まれて返ってくる。
372 385
373 \item {\tt Optional}オブジェクトに対して中身を保持しているか(属性名 {\tt name} 属性値 {\tt kanagawa}を持つノードを木が持っているか)を調べる。 386 \item {\tt Optional}オブジェクトに対して中身を保持しているか(属性名 {\tt "name"} 属性値 {\tt "kanagawa"}を持つノードを木が持っているか)を調べる。
374 387
375 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。 388 \item 持っていなかった場合、空の{\tt Iterator}オブジェクトを返す。
376 389
377 \item 持っていた場合{\tt Optional}オブジェクトからノードリストの{\tt Iterator}を返す。 390 \item 持っていた場合{\tt Optional}オブジェクトからノードリストの{\tt Iterator}を返す。
378 391