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