1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.directory.mavibot.btree;
22
23
24 import java.io.IOException;
25 import java.lang.reflect.Array;
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29
30 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
31
32
33
34
35
36
37
38 public class InMemoryBTreeBuilder<K, V>
39 {
40
41 private InMemoryBTreeConfiguration<K, V> btreeConfiguration;
42
43
44
45
46
47
48
49
50
51
52 public InMemoryBTreeBuilder( String name, int numKeysInNode, ElementSerializer<K> keySerializer,
53 ElementSerializer<V> valueSerializer )
54 {
55 btreeConfiguration = new InMemoryBTreeConfiguration<K, V>();
56 btreeConfiguration.setName( name );
57 btreeConfiguration.setPageSize( numKeysInNode );
58 btreeConfiguration.setKeySerializer( keySerializer );
59 btreeConfiguration.setValueSerializer( valueSerializer );
60 }
61
62
63
64
65
66
67
68 public InMemoryBTreeBuilder( InMemoryBTreeConfiguration<K, V> btreeConfiguration )
69 {
70 this.btreeConfiguration = btreeConfiguration;
71 }
72
73
74 @SuppressWarnings("unchecked")
75 public BTree<K, V> build( Iterator<Tuple<K, V>> sortedTupleItr ) throws IOException
76 {
77 BTree<K, V> btree = BTreeFactory.createInMemoryBTree( btreeConfiguration );
78 int pageSize = btree.getPageSize();
79 int maxElements = ( pageSize + 1 ) * pageSize;
80
81
82
83 List<InMemoryNode<K, V>>[] pageStack = new ArrayList[15];
84
85 for ( int i = 0; i < 15; i++ )
86 {
87 pageStack[i] = new ArrayList<InMemoryNode<K, V>>( maxElements );
88 }
89
90
91 int nbAdded = 0;
92
93
94 int btreeHeight = 0;
95
96
97
98 List<Tuple<K, V>> tuples = new ArrayList<Tuple<K, V>>( maxElements );
99
100
101 List<InMemoryNode<K, V>> nodes = new ArrayList<InMemoryNode<K, V>>();
102
103
104 while ( sortedTupleItr.hasNext() )
105 {
106 nbAdded++;
107
108
109 Tuple<K, V> tuple = sortedTupleItr.next();
110 tuples.add( tuple );
111
112 if ( tuples.size() == maxElements )
113 {
114
115 InMemoryNode<K, V> node = ( InMemoryNode<K, V> ) addLeaves( btree, tuples, maxElements );
116 int level = 0;
117
118 if ( node != null )
119 {
120 while ( true )
121 {
122 pageStack[level].add( node );
123
124
125
126 if ( pageStack[level].size() > btree.getPageSize() )
127 {
128 node = createParentNode( btree, pageStack[level], btree.getPageSize() );
129 pageStack[level].clear();
130 level++;
131 }
132 else
133 {
134 break;
135 }
136 }
137
138 ( ( AbstractBTree<K, V> ) btree ).setRootPage( pageStack[level].get( 0 ) );
139
140
141 if ( btreeHeight < level )
142 {
143 btreeHeight = level;
144 }
145 }
146
147 tuples.clear();
148 }
149 }
150
151 if ( tuples.size() > 0 )
152 {
153
154 Page<K, V> page = addLeaves( btree, tuples, maxElements );
155
156 if ( page instanceof InMemoryNode )
157 {
158 nodes.add( ( InMemoryNode<K, V> ) page );
159
160
161
162 if ( nodes.size() == maxElements )
163 {
164 Page<K, V> rootPage = createParentNode( btree, nodes, maxElements );
165
166 ( ( AbstractBTree<K, V> ) btree ).setRootPage( rootPage );
167 }
168 }
169 else
170 {
171 InMemoryLeaf<K, V> leaf = ( InMemoryLeaf<K, V> ) page;
172
173
174 if ( pageStack[0].size() != 0 )
175 {
176
177
178 if ( leaf.getNbElems() < btree.getPageSize() / 2 )
179 {
180
181
182 }
183 else
184 {
185
186
187
188 }
189 }
190 }
191 }
192
193
194 ( ( AbstractBTree<K, V> ) btree ).getBtreeHeader().setNbElems( nbAdded );
195
196 return btree;
197 }
198
199
200
201
202
203 private InMemoryNode<K, V> createParentNode( BTree<K, V> btree, List<InMemoryNode<K, V>> nodes, int maxElements )
204 {
205
206
207 InMemoryNode<K, V> parentNode = ( InMemoryNode<K, V> ) BTreeFactory.createNode( btree, 0,
208 btreeConfiguration.getPageSize() );
209
210 int nodePos = 0;
211
212
213 for ( InMemoryNode<K, V> node : nodes )
214 {
215 if ( nodePos != 0 )
216 {
217 K key = node.getLeftMostKey();
218 BTreeFactory.setKey( btree, parentNode, nodePos - 1, key );
219 }
220
221 PageHolder<K, V> pageHolder = new PageHolder<K, V>( btree, node );
222 parentNode.setPageHolder( nodePos, pageHolder );
223 nodePos++;
224 }
225
226
227 return parentNode;
228 }
229
230
231
232
233
234 private Page<K, V> addLeaves( BTree<K, V> btree, List<Tuple<K, V>> tuples, int maxElements )
235 {
236 if ( tuples.size() == 0 )
237 {
238
239 return null;
240 }
241
242
243 int leafPos = 0;
244
245
246
247 if ( tuples.size() < btree.getPageSize() )
248 {
249
250
251 InMemoryLeaf<K, V> leaf = ( InMemoryLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0,
252 btreeConfiguration.getPageSize() );
253
254
255 for ( Tuple<K, V> tuple : tuples )
256 {
257 injectTuple( btree, leaf, leafPos, tuple );
258 leafPos++;
259 }
260
261 return leaf;
262 }
263
264
265 if ( tuples.size() < maxElements )
266 {
267
268
269
270 InMemoryNode<K, V> node = ( InMemoryNode<K, V> ) BTreeFactory.createNode( btree, 0,
271 btreeConfiguration.getPageSize() );
272
273
274 InMemoryLeaf<K, V> leaf = ( InMemoryLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0,
275 btreeConfiguration.getPageSize() );
276
277 int nodePos = 0;
278
279
280 for ( Tuple<K, V> tuple : tuples )
281 {
282 if ( leafPos == btree.getPageSize() )
283 {
284
285
286 BTreeFactory.setKey( btree, node, nodePos, tuple.getKey() );
287 PageHolder<K, V> pageHolder = new PageHolder<K, V>( btree, leaf );
288 node.setPageHolder( nodePos, pageHolder );
289 nodePos++;
290
291
292 leaf = ( InMemoryLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0,
293 btree.getPageSize() );
294
295
296 injectTuple( btree, leaf, 0, tuple );
297 leafPos = 1;
298 }
299 else
300 {
301
302 injectTuple( btree, leaf, leafPos, tuple );
303 leafPos++;
304 }
305 }
306
307
308 if ( leafPos > 0 )
309 {
310 PageHolder<K, V> pageHolder = new PageHolder<K, V>( btree, leaf );
311 node.setPageHolder( nodePos, pageHolder );
312 }
313
314 return node;
315 }
316 else
317 {
318
319
320 InMemoryNode<K, V> node = ( InMemoryNode<K, V> ) BTreeFactory.createNode( btree, 0,
321 btreeConfiguration.getPageSize() );
322
323
324 InMemoryLeaf<K, V> leaf = ( InMemoryLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0,
325 btreeConfiguration.getPageSize() );
326
327 int nodePos = 0;
328
329
330 for ( Tuple<K, V> tuple : tuples )
331 {
332 if ( leafPos == btree.getPageSize() )
333 {
334
335
336 BTreeFactory.setKey( btree, node, nodePos, tuple.getKey() );
337 PageHolder<K, V> pageHolder = new PageHolder<K, V>( btree, leaf );
338 node.setPageHolder( nodePos, pageHolder );
339 nodePos++;
340
341
342 leaf = ( InMemoryLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0,
343 btree.getPageSize() );
344
345
346 injectTuple( btree, leaf, 0, tuple );
347 leafPos = 1;
348 }
349 else
350 {
351
352 injectTuple( btree, leaf, leafPos, tuple );
353 leafPos++;
354 }
355 }
356
357
358 if ( leafPos > 0 )
359 {
360 PageHolder<K, V> pageHolder = new PageHolder<K, V>( btree, leaf );
361 node.setPageHolder( nodePos, pageHolder );
362 }
363
364
365 return node;
366 }
367 }
368
369
370 private void injectTuple( BTree<K, V> btree, InMemoryLeaf<K, V> leaf, int leafPos, Tuple<K, V> tuple )
371 {
372 BTreeFactory.setKey( btree, leaf, leafPos, tuple.getKey() );
373 ValueHolder<V> valueHolder = new InMemoryValueHolder<V>( btree, tuple.getValue() );
374 BTreeFactory.setValue( btree, leaf, leafPos, valueHolder );
375 }
376
377
378 private int add( BTree<K, V> btree, Page<K, V>[] pageStack, int level, Page<K, V> page, Tuple<K, V> tuple )
379 {
380 if ( page == null )
381 {
382
383 if ( level == 0 )
384 {
385
386 InMemoryLeaf<K, V> leaf = ( InMemoryLeaf<K, V> ) BTreeFactory.createLeaf( btree, 0,
387 btreeConfiguration.getPageSize() );
388
389
390 pageStack[level] = leaf;
391
392
393 BTreeFactory.setKey( btree, leaf, 0, tuple.getKey() );
394 ValueHolder<V> valueHolder = new InMemoryValueHolder<V>( btree, tuple.getValue() );
395 BTreeFactory.setValue( btree, leaf, 0, valueHolder );
396 }
397 else
398 {
399
400 InMemoryNode<K, V> node = ( InMemoryNode<K, V> ) BTreeFactory.createNode( btree, 0,
401 btreeConfiguration.getPageSize() );
402
403
404 BTreeFactory.setKey( btree, node, 0, tuple.getKey() );
405 PageHolder<K, V> pageHolder = new PageHolder<K, V>( btree, pageStack[level - 1] );
406 node.setPageHolder( 0, pageHolder );
407 }
408 }
409 else
410 {
411
412 if ( page.getNbElems() == btree.getPageSize() )
413 {
414
415
416
417 }
418 else
419 {
420
421
422 if ( page.isLeaf() )
423 {
424
425 BTreeFactory.setKey( btree, page, page.getNbElems(), tuple.getKey() );
426 ValueHolder<V> valueHolder = new InMemoryValueHolder<V>( btree, tuple.getValue() );
427 BTreeFactory.setValue( btree, page, page.getNbElems(), valueHolder );
428 }
429 else
430 {
431
432 BTreeFactory.setKey( btree, page, page.getNbElems(), tuple.getKey() );
433 PageHolder<K, V> pageHolder = new PageHolder<K, V>( btree, pageStack[level - 1] );
434 ( ( InMemoryNode<K, V> ) page ).setPageHolder( page.getNbElems(), pageHolder );
435 }
436 }
437 }
438
439 return level;
440 }
441
442
443 @SuppressWarnings("unchecked")
444 private Page<K, V> attachNodes( List<Page<K, V>> children, BTree<K, V> btree ) throws IOException
445 {
446 if ( children.size() == 1 )
447 {
448 return children.get( 0 );
449 }
450
451 List<Page<K, V>> lstNodes = new ArrayList<Page<K, V>>();
452
453 int numChildren = btreeConfiguration.getPageSize() + 1;
454
455 InMemoryNode<K, V> node = ( InMemoryNode<K, V> ) BTreeFactory.createNode( btree, 0,
456 btreeConfiguration.getPageSize() );
457 lstNodes.add( node );
458 int i = 0;
459 int totalNodes = 0;
460
461 for ( Page<K, V> p : children )
462 {
463 if ( i != 0 )
464 {
465 BTreeFactory.setKey( btree, node, i - 1, p.getLeftMostKey() );
466 }
467
468 node.setPageHolder( i, new PageHolder<K, V>( btree, p ) );
469
470 i++;
471 totalNodes++;
472
473 if ( ( totalNodes % numChildren ) == 0 )
474 {
475 i = 0;
476 node = ( InMemoryNode<K, V> ) BTreeFactory.createNode( btree, 0, btreeConfiguration.getPageSize() );
477 lstNodes.add( node );
478 }
479 }
480
481
482 AbstractPage<K, V> lastNode = ( AbstractPage<K, V> ) lstNodes.get( lstNodes.size() - 1 );
483
484 for ( int j = 0; j < lastNode.getNbElems(); j++ )
485 {
486 if ( lastNode.getKey( j ) == null )
487 {
488 int n = j;
489 lastNode.setNbElems( n );
490 KeyHolder<K>[] keys = lastNode.getKeys();
491
492 lastNode.setKeys( ( KeyHolder[] ) Array.newInstance( KeyHolder.class, n ) );
493 System.arraycopy( keys, 0, lastNode.getKeys(), 0, n );
494
495 break;
496 }
497 }
498
499 return attachNodes( lstNodes, btree );
500 }
501 }