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.managed;
22
23
24 import static org.apache.directory.mavibot.btree.managed.BTreeFactory.createLeaf;
25 import static org.apache.directory.mavibot.btree.managed.BTreeFactory.createNode;
26 import static org.apache.directory.mavibot.btree.managed.BTreeFactory.setKey;
27 import static org.apache.directory.mavibot.btree.managed.BTreeFactory.setValue;
28
29 import java.io.IOException;
30 import java.lang.reflect.Array;
31 import java.util.ArrayList;
32 import java.util.Iterator;
33 import java.util.List;
34
35 import org.apache.directory.mavibot.btree.Tuple;
36 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
37
38
39
40
41
42
43
44 public class BTreeBuilder<K, V>
45 {
46 private String name;
47
48 private int numKeysInNode;
49
50 private ElementSerializer<K> keySerializer;
51
52 private ElementSerializer<V> valueSerializer;
53
54
55 public BTreeBuilder( String name, int numKeysInNode, ElementSerializer<K> keySerializer,
56 ElementSerializer<V> valueSerializer )
57 {
58 this.name = name;
59 this.numKeysInNode = numKeysInNode;
60 this.keySerializer = keySerializer;
61 this.valueSerializer = valueSerializer;
62 }
63
64
65 @SuppressWarnings("unchecked")
66 public BTree<K, V> build( Iterator<Tuple<K, V>> sortedTupleItr ) throws IOException
67 {
68 BTree<K, V> btree = new BTree<K, V>( name, keySerializer, valueSerializer );
69 btree.init();
70
71 List<Page<K, V>> lstLeaves = new ArrayList<Page<K, V>>();
72
73 int totalTupleCount = 0;
74
75 Leaf<K, V> leaf1 = createLeaf( btree, 0, numKeysInNode );
76 lstLeaves.add( leaf1 );
77
78 int leafIndex = 0;
79
80 while ( sortedTupleItr.hasNext() )
81 {
82 Tuple<K, V> tuple = sortedTupleItr.next();
83
84 setKey( leaf1, leafIndex, tuple.getKey() );
85
86 ValueHolder<V> eh = new ValueHolder<V>( btree.getRecordManager(), btree.getValueSerializer(),
87 tuple.getValue() );
88
89 setValue( leaf1, leafIndex, eh );
90
91 leafIndex++;
92 totalTupleCount++;
93 if ( ( totalTupleCount % numKeysInNode ) == 0 )
94 {
95 leafIndex = 0;
96 leaf1 = createLeaf( btree, 0, numKeysInNode );
97 lstLeaves.add( leaf1 );
98 }
99 }
100
101 if ( lstLeaves.isEmpty() )
102 {
103 return btree;
104 }
105
106
107 Leaf<K, V> lastLeaf = ( Leaf<K, V> ) lstLeaves.get( lstLeaves.size() - 1 );
108 for ( int i = 0; i < lastLeaf.nbElems; i++ )
109 {
110 if ( lastLeaf.keys[i] == null )
111 {
112 int n = i;
113 lastLeaf.nbElems = n;
114 KeyHolder<K>[] keys = lastLeaf.keys;
115
116 lastLeaf.keys = ( KeyHolder[] ) Array.newInstance( KeyHolder.class, n );
117 System.arraycopy( keys, 0, lastLeaf.keys, 0, n );
118
119 ValueHolder<V>[] values = lastLeaf.values;
120 lastLeaf.values = ( ValueHolder<V>[] ) Array.newInstance( ValueHolder.class, n );
121 System.arraycopy( values, 0, lastLeaf.values, 0, n );
122
123 break;
124 }
125 }
126
127 Page<K, V> rootPage = attachNodes( lstLeaves, btree );
128
129 btree.rootPage = rootPage;
130
131 return btree;
132 }
133
134
135 @SuppressWarnings("unchecked")
136 private Page<K, V> attachNodes( List<Page<K, V>> children, BTree<K, V> btree ) throws IOException
137 {
138 if ( children.size() == 1 )
139 {
140 return children.get( 0 );
141 }
142
143 List<Page<K, V>> lstNodes = new ArrayList<Page<K, V>>();
144
145 int numChildren = numKeysInNode + 1;
146
147 Node<K, V> node = createNode( btree, 0, numKeysInNode );
148 lstNodes.add( node );
149 int i = 0;
150 int totalNodes = 0;
151
152 for ( Page<K, V> p : children )
153 {
154 if ( i != 0 )
155 {
156 setKey( node, i - 1, p.getLeftMostKey() );
157 }
158
159 node.children[i] = btree.createPageHolder( p );
160
161 i++;
162 totalNodes++;
163
164 if ( ( totalNodes % numChildren ) == 0 )
165 {
166 i = 0;
167 node = createNode( btree, 0, numKeysInNode );
168 lstNodes.add( node );
169 }
170 }
171
172
173 AbstractPage<K, V> lastNode = ( AbstractPage<K, V> ) lstNodes.get( lstNodes.size() - 1 );
174
175 for ( int j = 0; j < lastNode.nbElems; j++ )
176 {
177 if ( lastNode.keys[j] == null )
178 {
179 int n = j;
180 lastNode.nbElems = n;
181 KeyHolder<K>[] keys = lastNode.keys;
182
183 lastNode.keys = ( KeyHolder[] ) Array.newInstance( KeyHolder.class, n );
184 System.arraycopy( keys, 0, lastNode.keys, 0, n );
185
186 break;
187 }
188 }
189
190 return attachNodes( lstNodes, btree );
191 }
192 }