annotate jungle.tex @ 15:33d8077a5d45

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