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