Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(827)

Side by Side Diff: pkg/analysis_server/lib/src/index/b_plus_tree.dart

Issue 324623002: Create/read/write/delete nodes using NodeManager. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analysis_server/test/index/b_plus_tree_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library index.b_plus_tree; 5 library index.b_plus_tree;
6 6
7 import 'dart:collection';
8
7 9
8 /** 10 /**
9 * A simple B+ tree (http://en.wikipedia.org/wiki/B+_tree) implementation. 11 * A simple B+ tree (http://en.wikipedia.org/wiki/B+_tree) implementation.
12 *
13 * [K] is the keys type.
14 * [V] is the values type.
15 * [N] is the type of node identifiers using by the [NodeManager].
10 */ 16 */
11 class BPlusTree<K, V> { 17 class BPlusTree<K, V, N> {
12 /** 18 /**
13 * The [Comparator] to compare keys. 19 * The [Comparator] to compare keys.
14 */ 20 */
15 final Comparator<K> _comparator; 21 final Comparator<K> _comparator;
16 22
17 /** 23 /**
24 * The [NodeManager] to manage nodes.
25 */
26 final NodeManager<K, V, N> _manager;
27
28 /**
18 * The maximum number of keys in an index node. 29 * The maximum number of keys in an index node.
19 */ 30 */
20 final int _maxIndexKeys; 31 final int _maxIndexKeys;
21 32
22 /** 33 /**
23 * The maximum number of keys in a leaf node. 34 * The maximum number of keys in a leaf node.
24 */ 35 */
25 final int _maxLeafKeys; 36 final int _maxLeafKeys;
26 37
27 /** 38 /**
28 * The root node. 39 * The root node.
29 */ 40 */
30 _Node<K, V> _root; 41 _Node<K, V, N> _root;
31 42
32 BPlusTree(this._maxIndexKeys, this._maxLeafKeys, this._comparator) { 43 /**
33 _root = new _LeafNode(_maxLeafKeys, _comparator); 44 * Creates a new [BPlusTree] instance.
45 */
46 BPlusTree(this._maxIndexKeys, this._maxLeafKeys, this._comparator,
47 this._manager) {
48 _root = _newLeafNode();
49 _writeLeafNode(_root);
34 } 50 }
35 51
36 /** 52 /**
37 * Returns the value for [key] or `null` if [key] is not in the tree. 53 * Returns the value for [key] or `null` if [key] is not in the tree.
38 */ 54 */
39 V find(K key) { 55 V find(K key) {
40 return _root.find(key); 56 return _root.find(key);
41 } 57 }
42 58
43 /** 59 /**
44 * Associates the [key] with the given [value]. 60 * Associates the [key] with the given [value].
45 * 61 *
46 * If the key was already in the tree, its associated value is changed. 62 * If the key was already in the tree, its associated value is changed.
47 * Otherwise the key-value pair is added to the tree. 63 * Otherwise the key-value pair is added to the tree.
48 */ 64 */
49 void insert(K key, V value) { 65 void insert(K key, V value) {
50 _Split<K, V> result = _root.insert(key, value); 66 _Split<K, N> result = _root.insert(key, value);
51 if (result != null) { 67 if (result != null) {
52 _IndexNode<K, V> newRoot = new _IndexNode<K, V>(_maxIndexKeys, 68 _IndexNode<K, V, N> newRoot = _newIndexNode();
53 _comparator);
54 newRoot.keys.add(result.key); 69 newRoot.keys.add(result.key);
55 newRoot.children.add(result.left); 70 newRoot.children.add(result.left);
56 newRoot.children.add(result.right); 71 newRoot.children.add(result.right);
57 _root = newRoot; 72 _root = newRoot;
73 _writeIndexNode(_root);
58 } 74 }
59 } 75 }
60 76
61 /** 77 /**
62 * Removes the association for the given [key]. 78 * Removes the association for the given [key].
63 * 79 *
64 * Returns the value associated with [key] in the tree or `null` if [key] is 80 * Returns the value associated with [key] in the tree or `null` if [key] is
65 * not in the tree. 81 * not in the tree.
66 */ 82 */
67 V remove(K key) { 83 V remove(K key) {
68 _Remove<K, V> result = _root.remove(key, null, null, null); 84 _Remove<K, V> result = _root.remove(key, null, null, null);
69 if (_root is _IndexNode<K, V>) { 85 if (_root is _IndexNode<K, V, N>) {
70 List<_Node<K, V>> children = (_root as _IndexNode<K, V>).children; 86 List<N> children = (_root as _IndexNode<K, V, N>).children;
71 if (children.length == 1) { 87 if (children.length == 1) {
72 _root = children[0]; 88 _manager.delete(_root.id);
89 _root = _readNode(children[0]);
73 } 90 }
74 } 91 }
75 return result.value; 92 return result.value;
76 } 93 }
77 94
78 /** 95 /**
79 * Writes a textual presentation of the tree into [buffer]. 96 * Writes a textual presentation of the tree into [buffer].
80 */ 97 */
81 void writeOn(StringBuffer buffer) { 98 void writeOn(StringBuffer buffer) {
82 _root.writeOn(buffer, ''); 99 _root.writeOn(buffer, '');
83 } 100 }
101
102 /**
103 * Creates a new [_IndexNode] instance.
104 */
105 _IndexNode<K, V, N> _newIndexNode() {
106 N id = _manager.createIndex();
107 return new _IndexNode<K, V, N>(this, id, _maxIndexKeys);
108 }
109
110 /**
111 * Creates a new [_LeafNode] instance.
112 */
113 _LeafNode<K, V, N> _newLeafNode() {
114 N id = _manager.createLeaf();
115 return new _LeafNode<K, V, N>(this, id, _maxLeafKeys);
116 }
117
118 /**
119 * Reads the [_IndexNode] with [id] from the manager.
120 */
121 _IndexNode<K, V, N> _readIndexNode(N id) {
122 IndexNodeData<K, N> data = _manager.readIndex(id);
123 _IndexNode<K, V, N> node = new _IndexNode<K, V, N>(this, id, _maxIndexKeys);
124 node.keys.addAll(data.keys);
125 node.children.addAll(data.children);
126 return node;
127 }
128
129 /**
130 * Reads the [_LeafNode] with [id] from the manager.
131 */
132 _LeafNode<K, V, N> _readLeafNode(N id) {
133 _LeafNode<K, V, N> node = new _LeafNode<K, V, N>(this, id, _maxLeafKeys);
134 LeafNodeData<K, V> data = _manager.readLeaf(id);
135 node.keys.addAll(data.keys);
136 node.values.addAll(data.values);
137 return node;
138 }
139
140 /**
141 * Reads the [_IndexNode] or [_LeafNode] with [id] from the manager.
142 */
143 _Node<K, V, N> _readNode(N id) {
144 if (_manager.isIndex(id)) {
145 return _readIndexNode(id);
146 } else {
147 return _readLeafNode(id);
148 }
149 }
150
151 /**
152 * Writes [node] into the manager.
153 */
154 void _writeIndexNode(_IndexNode<K, V, N> node) {
155 _manager.writeIndex(node.id, new IndexNodeData(node.keys, node.children));
156 }
157
158 /**
159 * Writes [node] into the manager.
160 */
161 void _writeLeafNode(_LeafNode<K, V, N> node) {
162 _manager.writeLeaf(node.id, new LeafNodeData(node.keys, node.values));
163 }
164 }
165
166
167 /**
168 * A container with information about an index node.
169 */
170 class IndexNodeData<K, N> {
171 final List<N> children;
172 final List<K> keys;
173 IndexNodeData(this.keys, this.children);
174 }
175
176
177 /**
178 * A container with information about a leaf node.
179 */
180 class LeafNodeData<K, V> {
181 final List<K> keys;
182 final List<V> values;
183 LeafNodeData(this.keys, this.values);
184 }
185
186
187 /**
188 * An implementation of [NodeManager] that keeps node information in memory.
189 */
190 class MemoryNodeManager<K, V> implements NodeManager<K, V, int> {
191 Map<int, IndexNodeData> _indexDataMap = new HashMap<int, IndexNodeData>();
192 Map<int, LeafNodeData> _leafDataMap = new HashMap<int, LeafNodeData>();
193 int _nextPageIndexId = 0;
194 int _nextPageLeafId = 1;
195
196 @override
197 int createIndex() {
198 int id = _nextPageIndexId;
199 _nextPageIndexId += 2;
200 return id;
201 }
202
203 @override
204 int createLeaf() {
205 int id = _nextPageLeafId;
206 _nextPageLeafId += 2;
207 return id;
208 }
209
210 @override
211 void delete(int id) {
212 if (isIndex(id)) {
213 _indexDataMap.remove(id);
214 } else {
215 _leafDataMap.remove(id);
216 }
217 }
218
219 @override
220 bool isIndex(int id) {
221 return id.isEven;
222 }
223
224 @override
225 IndexNodeData<K, int> readIndex(int id) {
226 return _indexDataMap[id];
227 }
228
229 @override
230 LeafNodeData<K, V> readLeaf(int id) {
231 return _leafDataMap[id];
232 }
233
234 @override
235 void writeIndex(int id, IndexNodeData<K, V> data) {
236 _indexDataMap[id] = data;
237 }
238
239 @override
240 void writeLeaf(int id, LeafNodeData<K, V> data) {
241 _leafDataMap[id] = data;
242 }
243 }
244
245
246 /**
247 * A manager that manages nodes.
248 */
249 abstract class NodeManager<K, V, N> {
250 /**
251 * Generates an identifier for a new index node.
252 */
253 N createIndex();
254
255 /**
256 * Generates an identifier for a new leaf node.
257 */
258 N createLeaf();
259
260 /**
261 * Deletes the node with the given identifier.
262 */
263 void delete(N id);
264
265 /**
266 * Checks if the node with the given identifier is an index or a leaf node.
267 */
268 bool isIndex(N id);
269
270 /**
271 * Reads information about the index node with the given identifier.
272 */
273 IndexNodeData<K, N> readIndex(N id);
274
275 /**
276 * Reads information about the leaf node with the given identifier.
277 */
278 LeafNodeData<K, V> readLeaf(N id);
279
280 /**
281 * Writes information about the index node with the given identifier.
282 */
283 void writeIndex(N id, IndexNodeData<K, V> data);
284
285 /**
286 * Writes information about the leaf node with the given identifier.
287 */
288 void writeLeaf(N id, LeafNodeData<K, V> data);
84 } 289 }
85 290
86 291
87 /** 292 /**
88 * An index node with keys and children references. 293 * An index node with keys and children references.
89 */ 294 */
90 class _IndexNode<K, V> extends _Node<K, V> { 295 class _IndexNode<K, V, N> extends _Node<K, V, N> {
Brian Wilkerson 2014/06/08 16:50:06 Should "_IndexNode" be renamed (in a separate CL)
91 final List<_Node<K, V>> children = new List<_Node<K, V>>(); 296 final List<N> children = new List<N>();
92 final int maxKeys; 297 final int maxKeys;
93 final int minKeys; 298 final int minKeys;
94 299
95 _IndexNode(int maxKeys, Comparator<K> comparator) 300 _IndexNode(BPlusTree<K, V, N> tree, N id, int maxKeys)
96 : super(comparator), 301 : super(tree, id),
97 maxKeys = maxKeys, 302 maxKeys = maxKeys,
98 minKeys = maxKeys ~/ 2; 303 minKeys = maxKeys ~/ 2;
99 304
100 @override 305 @override
101 V find(K key) { 306 V find(K key) {
102 int index = findChildIndex(key); 307 int index = _findChildIndex(key);
103 return children[index].find(key); 308 _Node<K, V, N> child = tree._readNode(children[index]);
104 } 309 return child.find(key);
105 310 }
106 /** 311
107 * Returns the index of the child into which [key] should be inserted. 312 _Split<K, N> insert(K key, V value) {
108 */
109 int findChildIndex(K key) {
110 for (int i = 0; i < keys.length; i++) {
111 if (comparator(keys[i], key) > 0) {
112 return i;
113 }
114 }
115 return keys.length;
116 }
117
118 _Split<K, V> insert(K key, V value) {
119 // Early split. 313 // Early split.
120 if (keys.length == maxKeys) { 314 if (keys.length == maxKeys) {
121 int middle = (maxKeys + 1) ~/ 2; 315 int middle = (maxKeys + 1) ~/ 2;
122 K splitKey = keys[middle]; 316 K splitKey = keys[middle];
123 _IndexNode<K, V> sibling = new _IndexNode<K, V>(maxKeys, comparator); 317 // Overflow into a new sibling.
318 _IndexNode<K, V, N> sibling = tree._newIndexNode();
124 sibling.keys.addAll(keys.getRange(middle + 1, keys.length)); 319 sibling.keys.addAll(keys.getRange(middle + 1, keys.length));
125 sibling.children.addAll(children.getRange(middle + 1, children.length)); 320 sibling.children.addAll(children.getRange(middle + 1, children.length));
126 keys.length = middle; 321 keys.length = middle;
127 children.length = middle + 1; 322 children.length = middle + 1;
323 // Insert into this node or sibling.
324 if (comparator(key, splitKey) < 0) {
325 _insertNotFull(key, value);
326 } else {
327 sibling._insertNotFull(key, value);
328 }
128 // Prepare split. 329 // Prepare split.
129 _Split<K, V> result = new _Split<K, V>(splitKey, this, sibling); 330 tree._writeIndexNode(this);
130 if (comparator(key, result.key) < 0) { 331 tree._writeIndexNode(sibling);
131 insertNotFull(key, value); 332 return new _Split<K, N>(splitKey, id, sibling.id);
132 } else {
133 sibling.insertNotFull(key, value);
134 }
135 return result;
136 } 333 }
137 // No split. 334 // No split.
138 insertNotFull(key, value); 335 _insertNotFull(key, value);
139 return null; 336 return null;
140 } 337 }
141 338
142 void insertNotFull(K key, V value) { 339 @override
143 int index = findChildIndex(key); 340 _Remove<K, V> remove(K key, _Node<K, V, N> left, K anchor, _Node<K, V,
144 _Split<K, V> result = children[index].insert(key, value); 341 N> right) {
145 if (result != null) { 342 int index = _findChildIndex(key);
146 keys.insert(index, result.key);
147 children[index] = result.left;
148 children.insert(index + 1, result.right);
149 }
150 }
151
152 @override
153 _Remove<K, V> remove(K key, _Node<K, V> left, K anchor, _Node<K, V> right) {
154 int index = findChildIndex(key);
155 K thisAnchor = index == 0 ? keys[0] : keys[index - 1]; 343 K thisAnchor = index == 0 ? keys[0] : keys[index - 1];
156 _Node<K, V> child = children[index]; 344 // Prepare children.
157 bool hasLeft = index != 0; 345 _Node<K, V, N> child = tree._readNode(children[index]);
158 bool hasRight = index < children.length - 1; 346 _Node<K, V, N> leftChild;
159 _Node<K, V> leftChild = hasLeft ? children[index - 1] : null; 347 _Node<K, V, N> rightChild;
160 _Node<K, V> rightChild = hasRight ? children[index + 1] : null; 348 if (index != 0) {
349 leftChild = tree._readNode(children[index - 1]);
350 } else {
351 leftChild = null;
352 }
353 if (index < children.length - 1) {
354 rightChild = tree._readNode(children[index + 1]);
355 } else {
356 rightChild = null;
357 }
161 // Ask child to remove. 358 // Ask child to remove.
162 _Remove<K, V> result = child.remove(key, leftChild, thisAnchor, rightChild); 359 _Remove<K, V> result = child.remove(key, leftChild, thisAnchor, rightChild);
163 V value = result.value; 360 V value = result.value;
164 if (value == null) { 361 if (value == null) {
165 return new _Remove<K, V>(value); 362 return new _Remove<K, V>(value);
166 } 363 }
167 // Update anchor if borrowed. 364 // Do keys / children updates
168 if (result.leftAnchor != null) { 365 bool hasUpdates = false;
169 keys[index - 1] = result.leftAnchor; 366 {
170 } 367 // Update anchor if borrowed.
171 if (result.rightAnchor != null) { 368 if (result.leftAnchor != null) {
172 keys[index] = result.rightAnchor; 369 keys[index - 1] = result.leftAnchor;
173 } 370 hasUpdates = true;
174 // Update keys / children if merged. 371 }
175 if (result.mergedLeft) { 372 if (result.rightAnchor != null) {
176 keys.removeAt(index - 1); 373 keys[index] = result.rightAnchor;
177 children.removeAt(index); 374 hasUpdates = true;
178 } 375 }
179 if (result.mergedRight) { 376 // Update keys / children if merged.
180 keys.removeAt(index); 377 if (result.mergedLeft) {
181 children.removeAt(index); 378 keys.removeAt(index - 1);
182 } 379 N child = children.removeAt(index);
380 manager.delete(child);
381 hasUpdates = true;
382 }
383 if (result.mergedRight) {
384 keys.removeAt(index);
385 N child = children.removeAt(index);
386 manager.delete(child);
387 hasUpdates = true;
388 }
389 }
390 // Write if updated.
391 if (!hasUpdates) {
392 return new _Remove<K, V>(value);
393 }
394 tree._writeIndexNode(this);
183 // Perform balancing. 395 // Perform balancing.
184 if (keys.length < minKeys) { 396 if (keys.length < minKeys) {
185 // Try left sibling. 397 // Try left sibling.
186 if (left is _IndexNode<K, V>) { 398 if (left is _IndexNode<K, V, N>) {
187 // Try to redistribute. 399 // Try to redistribute.
188 int leftLength = left.keys.length; 400 int leftLength = left.keys.length;
189 if (leftLength > minKeys) { 401 if (leftLength > minKeys) {
190 int halfExcess = (leftLength - minKeys + 1) ~/ 2; 402 int halfExcess = (leftLength - minKeys + 1) ~/ 2;
191 int newLeftLength = leftLength - halfExcess; 403 int newLeftLength = leftLength - halfExcess;
192 keys.insert(0, anchor); 404 keys.insert(0, anchor);
193 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); 405 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength));
194 children.insertAll(0, left.children.getRange(newLeftLength, leftLength 406 children.insertAll(0, left.children.getRange(newLeftLength, leftLength
195 + 1)); 407 + 1));
196 K newAnchor = left.keys[newLeftLength - 1]; 408 K newAnchor = left.keys[newLeftLength - 1];
197 left.keys.length = newLeftLength - 1; 409 left.keys.length = newLeftLength - 1;
198 left.children.length = newLeftLength; 410 left.children.length = newLeftLength;
411 tree._writeIndexNode(this);
412 tree._writeIndexNode(left);
199 return new _Remove<K, V>.borrowLeft(value, newAnchor); 413 return new _Remove<K, V>.borrowLeft(value, newAnchor);
200 } 414 }
201 // Do merge. 415 // Do merge.
202 left.keys.add(anchor); 416 left.keys.add(anchor);
203 left.keys.addAll(keys); 417 left.keys.addAll(keys);
204 left.children.addAll(children); 418 left.children.addAll(children);
419 tree._writeIndexNode(this);
420 tree._writeIndexNode(left);
205 return new _Remove<K, V>.mergeLeft(value); 421 return new _Remove<K, V>.mergeLeft(value);
206 } 422 }
207 // Try right sibling. 423 // Try right sibling.
208 if (right is _IndexNode<K, V>) { 424 if (right is _IndexNode<K, V, N>) {
209 // Try to redistribute. 425 // Try to redistribute.
210 var rightLength = right.keys.length; 426 var rightLength = right.keys.length;
211 if (rightLength > minKeys) { 427 if (rightLength > minKeys) {
212 int halfExcess = (rightLength - minKeys + 1) ~/ 2; 428 int halfExcess = (rightLength - minKeys + 1) ~/ 2;
213 keys.add(anchor); 429 keys.add(anchor);
214 keys.addAll(right.keys.getRange(0, halfExcess - 1)); 430 keys.addAll(right.keys.getRange(0, halfExcess - 1));
215 children.addAll(right.children.getRange(0, halfExcess)); 431 children.addAll(right.children.getRange(0, halfExcess));
216 K newAnchor = right.keys[halfExcess - 1]; 432 K newAnchor = right.keys[halfExcess - 1];
217 right.keys.removeRange(0, halfExcess); 433 right.keys.removeRange(0, halfExcess);
218 right.children.removeRange(0, halfExcess); 434 right.children.removeRange(0, halfExcess);
435 tree._writeIndexNode(this);
436 tree._writeIndexNode(right);
219 return new _Remove<K, V>.borrowRight(value, newAnchor); 437 return new _Remove<K, V>.borrowRight(value, newAnchor);
220 } 438 }
221 // Do merge. 439 // Do merge.
222 right.keys.insert(0, anchor); 440 right.keys.insert(0, anchor);
223 right.keys.insertAll(0, keys); 441 right.keys.insertAll(0, keys);
224 right.children.insertAll(0, children); 442 right.children.insertAll(0, children);
443 tree._writeIndexNode(this);
444 tree._writeIndexNode(right);
225 return new _Remove<K, V>.mergeRight(value); 445 return new _Remove<K, V>.mergeRight(value);
226 } 446 }
227 } 447 }
228 // No balancing required. 448 // No balancing required.
229 return new _Remove<K, V>(value); 449 return new _Remove<K, V>(value);
230 } 450 }
231 451
232 @override 452 @override
233 void writeOn(StringBuffer buffer, String indent) { 453 void writeOn(StringBuffer buffer, String indent) {
234 buffer.write(indent); 454 buffer.write(indent);
235 buffer.write('INode {\n'); 455 buffer.write('INode {\n');
236 for (int i = 0; i < keys.length; i++) { 456 for (int i = 0; i < keys.length; i++) {
237 children[i].writeOn(buffer, indent + ' '); 457 _Node<K, V, N> child = tree._readNode(children[i]);
458 child.writeOn(buffer, indent + ' ');
238 buffer.write(indent); 459 buffer.write(indent);
239 buffer.write(' '); 460 buffer.write(' ');
240 buffer.write(keys[i]); 461 buffer.write(keys[i]);
241 buffer.write('\n'); 462 buffer.write('\n');
242 } 463 }
243 children[keys.length].writeOn(buffer, indent + ' '); 464 _Node<K, V, N> child = tree._readNode(children[keys.length]);
465 child.writeOn(buffer, indent + ' ');
244 buffer.write(indent); 466 buffer.write(indent);
245 buffer.write('}\n'); 467 buffer.write('}\n');
246 } 468 }
469
470 /**
471 * Returns the index of the child into which [key] should be inserted.
472 */
473 int _findChildIndex(K key) {
474 for (int i = 0; i < keys.length; i++) {
475 if (comparator(keys[i], key) > 0) {
476 return i;
477 }
478 }
479 return keys.length;
480 }
481
482 void _insertNotFull(K key, V value) {
483 int index = _findChildIndex(key);
484 _Node<K, V, N> child = tree._readNode(children[index]);
485 _Split<K, N> result = child.insert(key, value);
486 if (result != null) {
487 keys.insert(index, result.key);
488 children[index] = result.left;
489 children.insert(index + 1, result.right);
490 tree._writeIndexNode(this);
491 }
492 }
247 } 493 }
248 494
249 495
250 /** 496 /**
251 * A leaf node with keys and values. 497 * A leaf node with keys and values.
252 */ 498 */
253 class _LeafNode<K, V> extends _Node<K, V> { 499 class _LeafNode<K, V, N> extends _Node<K, V, N> {
254 final int maxKeys; 500 final int maxKeys;
255 final int minKeys; 501 final int minKeys;
256
257 /**
258 * The list of values.
259 */
260 final List<V> values = new List<V>(); 502 final List<V> values = new List<V>();
261 503
262 _LeafNode(int maxKeys, Comparator<K> comparator) 504 _LeafNode(BPlusTree<K, V, N> tree, N id, int maxKeys)
263 : super(comparator), 505 : super(tree, id),
264 maxKeys = maxKeys, 506 maxKeys = maxKeys,
265 minKeys = maxKeys ~/ 2; 507 minKeys = maxKeys ~/ 2;
266 508
267 @override 509 @override
268 V find(K key) { 510 V find(K key) {
269 int index = findKeyIndex(key); 511 int index = _findKeyIndex(key);
270 if (index < 0) { 512 if (index < 0) {
271 return null; 513 return null;
272 } 514 }
273 if (index >= keys.length) { 515 if (index >= keys.length) {
274 return null; 516 return null;
275 } 517 }
276 if (keys[index] != key) { 518 if (keys[index] != key) {
277 return null; 519 return null;
278 } 520 }
279 return values[index]; 521 return values[index];
280 } 522 }
281 523
282 /** 524 _Split<K, N> insert(K key, V value) {
283 * Returns the index where [key] should be inserted. 525 int index = _findKeyIndex(key);
284 */
285 int findKeyIndex(K key) {
286 for (int i = 0; i < keys.length; i++) {
287 if (comparator(keys[i], key) >= 0) {
288 return i;
289 }
290 }
291 return keys.length;
292 }
293
294 _Split<K, V> insert(K key, V value) {
295 int index = findKeyIndex(key);
296 // The node is full. 526 // The node is full.
297 if (keys.length == maxKeys) { 527 if (keys.length == maxKeys) {
298 int middle = (maxKeys + 1) ~/ 2; 528 int middle = (maxKeys + 1) ~/ 2;
299 _LeafNode<K, V> sibling = new _LeafNode<K, V>(maxKeys, comparator); 529 _LeafNode<K, V, N> sibling = tree._newLeafNode();
300 sibling.keys.addAll(keys.getRange(middle, keys.length)); 530 sibling.keys.addAll(keys.getRange(middle, keys.length));
301 sibling.values.addAll(values.getRange(middle, values.length)); 531 sibling.values.addAll(values.getRange(middle, values.length));
302 keys.length = middle; 532 keys.length = middle;
303 values.length = middle; 533 values.length = middle;
304 // Insert into the left / right sibling. 534 // Insert into the left / right sibling.
305 if (index < middle) { 535 if (index < middle) {
306 insertNotFull(key, value, index); 536 _insertNotFull(key, value, index);
307 } else { 537 } else {
308 sibling.insertNotFull(key, value, index - middle); 538 sibling._insertNotFull(key, value, index - middle);
309 } 539 }
310 // Notify the parent about the split. 540 // Notify the parent about the split.
311 return new _Split<K, V>(sibling.keys[0], this, sibling); 541 tree._writeLeafNode(this);
542 tree._writeLeafNode(sibling);
543 return new _Split<K, N>(sibling.keys[0], id, sibling.id);
312 } 544 }
313 // The node was not full. 545 // The node was not full.
314 insertNotFull(key, value, index); 546 _insertNotFull(key, value, index);
315 return null; 547 return null;
316 } 548 }
317 549
318 void insertNotFull(K key, V value, int index) {
319 if (index < keys.length && keys[index] == key) {
320 values[index] = value;
321 } else {
322 keys.insert(index, key);
323 values.insert(index, value);
324 }
325 }
326
327 @override 550 @override
328 _Remove<K, V> remove(K key, _Node<K, V> left, K anchor, _Node<K, V> right) { 551 _Remove<K, V> remove(K key, _Node<K, V, N> left, K anchor, _Node<K, V,
552 N> right) {
329 // Find the key. 553 // Find the key.
330 int index = keys.indexOf(key); 554 int index = keys.indexOf(key);
331 if (index == -1) { 555 if (index == -1) {
332 return new _Remove<K, V>(null); 556 return new _Remove<K, V>(null);
333 } 557 }
334 // Key key / value. 558 // Remove key / value.
335 keys.removeAt(index); 559 keys.removeAt(index);
336 V value = values.removeAt(index); 560 V value = values.removeAt(index);
561 tree._writeLeafNode(this);
337 // Perform balancing. 562 // Perform balancing.
338 if (keys.length < minKeys) { 563 if (keys.length < minKeys) {
339 // Try left sibling. 564 // Try left sibling.
340 if (left is _LeafNode<K, V>) { 565 if (left is _LeafNode<K, V, N>) {
341 // Try to redistribute. 566 // Try to redistribute.
342 int leftLength = left.keys.length; 567 int leftLength = left.keys.length;
343 if (leftLength > minKeys) { 568 if (leftLength > minKeys) {
344 int halfExcess = (leftLength - minKeys + 1) ~/ 2; 569 int halfExcess = (leftLength - minKeys + 1) ~/ 2;
345 int newLeftLength = leftLength - halfExcess; 570 int newLeftLength = leftLength - halfExcess;
346 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength)); 571 keys.insertAll(0, left.keys.getRange(newLeftLength, leftLength));
347 values.insertAll(0, left.values.getRange(newLeftLength, leftLength)); 572 values.insertAll(0, left.values.getRange(newLeftLength,
573 leftLength));
348 left.keys.length = newLeftLength; 574 left.keys.length = newLeftLength;
349 left.values.length = newLeftLength; 575 left.values.length = newLeftLength;
576 tree._writeLeafNode(this);
577 tree._writeLeafNode(left);
350 return new _Remove<K, V>.borrowLeft(value, keys.first); 578 return new _Remove<K, V>.borrowLeft(value, keys.first);
351 } 579 }
352 // Do merge. 580 // Do merge.
353 left.keys.addAll(keys); 581 left.keys.addAll(keys);
354 left.values.addAll(values); 582 left.values.addAll(values);
583 tree._writeLeafNode(this);
584 tree._writeLeafNode(left);
355 return new _Remove<K, V>.mergeLeft(value); 585 return new _Remove<K, V>.mergeLeft(value);
356 } 586 }
357 // Try right sibling. 587 // Try right sibling.
358 if (right is _LeafNode<K, V>) { 588 if (right is _LeafNode<K, V, N>) {
359 // Try to redistribute. 589 // Try to redistribute.
360 var rightLength = right.keys.length; 590 var rightLength = right.keys.length;
361 if (rightLength > minKeys) { 591 if (rightLength > minKeys) {
362 int halfExcess = (rightLength - minKeys + 1) ~/ 2; 592 int halfExcess = (rightLength - minKeys + 1) ~/ 2;
363 keys.addAll(right.keys.getRange(0, halfExcess)); 593 keys.addAll(right.keys.getRange(0, halfExcess));
364 values.addAll(right.values.getRange(0, halfExcess)); 594 values.addAll(right.values.getRange(0, halfExcess));
365 right.keys.removeRange(0, halfExcess); 595 right.keys.removeRange(0, halfExcess);
366 right.values.removeRange(0, halfExcess); 596 right.values.removeRange(0, halfExcess);
597 tree._writeLeafNode(this);
598 tree._writeLeafNode(right);
367 return new _Remove<K, V>.borrowRight(value, right.keys.first); 599 return new _Remove<K, V>.borrowRight(value, right.keys.first);
368 } 600 }
369 // Do merge. 601 // Do merge.
370 right.keys.insertAll(0, keys); 602 right.keys.insertAll(0, keys);
371 right.values.insertAll(0, values); 603 right.values.insertAll(0, values);
604 tree._writeLeafNode(this);
605 tree._writeLeafNode(right);
372 return new _Remove<K, V>.mergeRight(value); 606 return new _Remove<K, V>.mergeRight(value);
373 } 607 }
374 } 608 }
375 // No balancing required. 609 // No balancing required.
376 return new _Remove<K, V>(value); 610 return new _Remove<K, V>(value);
377 } 611 }
378 612
379 @override 613 @override
380 void writeOn(StringBuffer buffer, String indent) { 614 void writeOn(StringBuffer buffer, String indent) {
381 buffer.write(indent); 615 buffer.write(indent);
382 buffer.write('LNode {'); 616 buffer.write('LNode {');
383 for (int i = 0; i < keys.length; i++) { 617 for (int i = 0; i < keys.length; i++) {
384 if (i != 0) { 618 if (i != 0) {
385 buffer.write(', '); 619 buffer.write(', ');
386 } 620 }
387 buffer.write(keys[i]); 621 buffer.write(keys[i]);
388 buffer.write(': '); 622 buffer.write(': ');
389 buffer.write(values[i]); 623 buffer.write(values[i]);
390 } 624 }
391 buffer.write('}\n'); 625 buffer.write('}\n');
392 } 626 }
627
628 /**
629 * Returns the index where [key] should be inserted.
630 */
631 int _findKeyIndex(K key) {
632 for (int i = 0; i < keys.length; i++) {
633 if (comparator(keys[i], key) >= 0) {
634 return i;
635 }
636 }
637 return keys.length;
638 }
639
640 void _insertNotFull(K key, V value, int index) {
641 if (index < keys.length && keys[index] == key) {
642 values[index] = value;
643 } else {
644 keys.insert(index, key);
645 values.insert(index, value);
646 }
647 tree._writeLeafNode(this);
648 }
393 } 649 }
394 650
395 651
396 /** 652 /**
397 * An internal or leaf node. 653 * An internal or leaf node.
398 */ 654 */
399 abstract class _Node<K, V> { 655 abstract class _Node<K, V, N> {
400 /** 656 /**
401 * The [Comparator] to compare keys. 657 * The [Comparator] to compare keys.
402 */ 658 */
403 Comparator<K> comparator; 659 final Comparator<K> comparator;
660
661 /**
662 * The identifier of this node.
663 */
664 final N id;
404 665
405 /** 666 /**
406 * The list of keys. 667 * The list of keys.
407 */ 668 */
408 List<K> keys = new List<K>(); 669 final List<K> keys = new List<K>();
409 670
410 _Node(this.comparator); 671 /**
672 * The [NodeManager] for this tree.
673 */
674 final NodeManager<K, V, N> manager;
675
676 /**
677 * The [BPlusTree] this node belongs to.
678 */
679 final BPlusTree<K, V, N> tree;
680
681 _Node(BPlusTree<K, V, N> tree, this.id)
682 : tree = tree,
683 comparator = tree._comparator,
684 manager = tree._manager;
411 685
412 /** 686 /**
413 * Looks for [key]. 687 * Looks for [key].
414 * 688 *
415 * Returns the associated value if found. 689 * Returns the associated value if found.
416 * Returns `null` if not found. 690 * Returns `null` if not found.
417 */ 691 */
418 V find(K key); 692 V find(K key);
419 693
420 /** 694 /**
421 * Inserts the [key] / [value] pair into this [_Node]. 695 * Inserts the [key] / [value] pair into this [_Node].
422 * 696 *
423 * Returns a [_Split] object if split happens, or `null` otherwise. 697 * Returns a [_Split] object if split happens, or `null` otherwise.
424 */ 698 */
425 _Split<K, V> insert(K key, V value); 699 _Split<K, N> insert(K key, V value);
426 700
427 /** 701 /**
428 * Removes the association for the given [key]. 702 * Removes the association for the given [key].
429 * 703 *
430 * Returns the [_Remove] information about an operation performed. 704 * Returns the [_Remove] information about an operation performed.
431 * It may be restructuring or merging, with [left] or [left] siblings. 705 * It may be restructuring or merging, with [left] or [left] siblings.
432 */ 706 */
433 _Remove<K, V> remove(K key, _Node<K, V> left, K anchor, _Node<K, V> right); 707 _Remove<K, V> remove(K key, _Node<K, V, N> left, K anchor, _Node<K, V,
708 N> right);
434 709
435 /** 710 /**
436 * Writes a textual presentation of the tree into [buffer]. 711 * Writes a textual presentation of the tree into [buffer].
437 */ 712 */
438 void writeOn(StringBuffer buffer, String indent); 713 void writeOn(StringBuffer buffer, String indent);
439 } 714 }
440 715
441 716
442 /** 717 /**
443 * A container with information about redistribute / merge. 718 * A container with information about redistribute / merge.
444 */ 719 */
445 class _Remove<K, V> { 720 class _Remove<K, V> {
446 K leftAnchor; 721 K leftAnchor;
447 bool mergedLeft = false; 722 bool mergedLeft = false;
448 bool mergedRight = false; 723 bool mergedRight = false;
449 K rightAnchor; 724 K rightAnchor;
450 final V value; 725 final V value;
451 _Remove(this.value); 726 _Remove(this.value);
452 _Remove.borrowLeft(this.value, this.leftAnchor); 727 _Remove.borrowLeft(this.value, this.leftAnchor);
453 _Remove.borrowRight(this.value, this.rightAnchor); 728 _Remove.borrowRight(this.value, this.rightAnchor);
454 _Remove.mergeLeft(this.value) : mergedLeft = true; 729 _Remove.mergeLeft(this.value) : mergedLeft = true;
455 _Remove.mergeRight(this.value) : mergedRight = true; 730 _Remove.mergeRight(this.value) : mergedRight = true;
456 } 731 }
457 732
458 733
459 /** 734 /**
460 * A container with information about split during insert. 735 * A container with information about split during insert.
461 */ 736 */
462 class _Split<K, V> { 737 class _Split<K, N> {
463 final K key; 738 final K key;
464 final _Node<K, V> left; 739 final N left;
465 final _Node<K, V> right; 740 final N right;
466 _Split(this.key, this.left, this.right); 741 _Split(this.key, this.left, this.right);
467 } 742 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/index/b_plus_tree_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698