View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.mavibot.btree;
21  
22  
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertFalse;
25  import static org.junit.Assert.assertTrue;
26  
27  import java.io.File;
28  import java.io.IOException;
29  import java.util.Random;
30  import java.util.Set;
31  
32  import org.apache.directory.mavibot.btree.BTree;
33  import org.apache.directory.mavibot.btree.InMemoryBTree;
34  import org.apache.directory.mavibot.btree.Tuple;
35  import org.apache.directory.mavibot.btree.TupleCursor;
36  import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
37  import org.apache.directory.mavibot.btree.serializer.IntSerializer;
38  import org.apache.directory.mavibot.btree.serializer.LongSerializer;
39  import org.apache.directory.mavibot.btree.serializer.StringSerializer;
40  import org.junit.Rule;
41  import org.junit.Test;
42  import org.junit.rules.TemporaryFolder;
43  
44  
45  /**
46   * A unit test class for BTree flush() operation
47   * 
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   */
50  public class InMemoryBTreeFlushTest
51  {
52      @Rule
53      public TemporaryFolder tempFolder = new TemporaryFolder();
54  
55      // Some values to inject in a btree
56      private static int[] sortedValues = new int[]
57          {
58              0, 1, 2, 4, 5, 6, 8, 9, 11, 12,
59              13, 14, 16, 19, 21, 22, 23, 25, 26, 28,
60              30, 31, 32, 34, 36, 37, 38, 39, 41, 42,
61              44, 45, 47, 50, 52, 53, 54, 55, 56, 58,
62              59, 60, 63, 64, 67, 68, 70, 72, 73, 74,
63              76, 77, 79, 80, 81, 82, 85, 88, 89, 90,
64              92, 93, 95, 97, 98, 100, 101, 102, 103, 104,
65              105, 106, 107, 109, 110, 111, 112, 117, 118, 120,
66              121, 128, 129, 130, 131, 132, 135, 136, 137, 138,
67              139, 140, 141, 142, 143, 146, 147, 148, 149, 150,
68              152, 154, 156, 160, 161, 162, 163, 165, 167, 168,
69              169, 171, 173, 174, 175, 176, 177, 178, 179, 180,
70              181, 182, 183, 189, 190, 193, 194, 195, 199, 200,
71              202, 203, 205, 206, 207, 208, 209, 210, 212, 215,
72              216, 217, 219, 220, 222, 223, 224, 225, 226, 227,
73              228, 230, 231, 235, 236, 238, 239, 241, 242, 243,
74              245, 246, 247, 249, 250, 251, 252, 254, 256, 257,
75              258, 259, 261, 262, 263, 264, 266, 268, 272, 273,
76              274, 276, 277, 278, 279, 282, 283, 286, 289, 290,
77              292, 293, 294, 296, 298, 299, 300, 301, 303, 305,
78              308, 310, 316, 317, 318, 319, 322, 323, 324, 326,
79              327, 329, 331, 333, 334, 335, 336, 337, 338, 339,
80              340, 341, 346, 347, 348, 349, 350, 351, 352, 353,
81              355, 356, 357, 358, 359, 361, 365, 366, 373, 374,
82              375, 379, 380, 381, 382, 384, 385, 387, 388, 389,
83              390, 392, 393, 395, 396, 397, 398, 399, 400, 401,
84              404, 405, 406, 407, 410, 411, 412, 416, 417, 418,
85              420, 421, 422, 424, 426, 427, 428, 430, 431, 432,
86              433, 436, 439, 441, 443, 444, 445, 446, 447, 448,
87              449, 450, 451, 452, 453, 454, 455, 456, 458, 459,
88              464, 466, 469, 470, 471, 472, 475, 477, 478, 482,
89              483, 484, 485, 486, 488, 490, 491, 492, 493, 495,
90              496, 497, 500, 502, 503, 504, 505, 506, 507, 509,
91              510, 514, 516, 518, 520, 521, 523, 524, 526, 527,
92              528, 529, 530, 532, 533, 535, 538, 539, 540, 542,
93              543, 544, 546, 547, 549, 550, 551, 553, 554, 558,
94              559, 561, 563, 564, 566, 567, 568, 569, 570, 571,
95              572, 576, 577, 578, 580, 582, 583, 586, 588, 589,
96              590, 592, 593, 596, 597, 598, 599, 600, 601, 604,
97              605, 606, 607, 609, 610, 613, 615, 617, 618, 619,
98              620, 621, 626, 627, 628, 631, 632, 633, 635, 636,
99              637, 638, 639, 640, 641, 643, 645, 647, 648, 649,
100             650, 651, 652, 653, 655, 656, 658, 659, 660, 662,
101             666, 669, 673, 674, 675, 676, 677, 678, 680, 681,
102             682, 683, 685, 686, 687, 688, 689, 690, 691, 692,
103             693, 694, 696, 698, 699, 700, 701, 705, 708, 709,
104             711, 713, 714, 715, 719, 720, 723, 725, 726, 727,
105             728, 731, 732, 733, 734, 735, 736, 739, 740, 743,
106             744, 745, 746, 747, 749, 750, 752, 753, 762, 763,
107             765, 766, 768, 770, 772, 773, 774, 776, 777, 779,
108             782, 784, 785, 788, 790, 791, 793, 794, 795, 798,
109             799, 800, 801, 803, 804, 805, 808, 810, 812, 813,
110             814, 816, 818, 821, 822, 823, 824, 827, 828, 829,
111             831, 832, 833, 834, 835, 837, 838, 839, 840, 843,
112             846, 847, 849, 852, 853, 854, 856, 857, 859, 860,
113             863, 864, 865, 866, 867, 868, 869, 872, 873, 877,
114             880, 881, 882, 883, 887, 888, 889, 890, 891, 894,
115             895, 897, 898, 899, 902, 904, 905, 907, 908, 910,
116             911, 912, 915, 916, 917, 918, 919, 923, 925, 926,
117             927, 928, 929, 930, 932, 935, 936, 937, 938, 939,
118             944, 945, 947, 952, 953, 954, 955, 956, 957, 958,
119             960, 967, 970, 971, 972, 974, 975, 976, 978, 979,
120             980, 981, 983, 984, 985, 987, 988, 989, 991, 995
121     };
122 
123 
124     private String create100KElementsFile() throws IOException
125     {
126         Random random = new Random( System.nanoTime() );
127 
128         int nbError = 0;
129 
130         long l1 = System.currentTimeMillis();
131         int n = 0;
132         long delta = l1;
133         int nbElems = 100000;
134 
135         BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", new LongSerializer(),
136             new StringSerializer() );
137         btree.setPageSize( 32 );
138 
139         for ( int i = 0; i < nbElems; i++ )
140         {
141             Long key = ( long ) random.nextLong();
142             String value = Long.toString( key );
143 
144             try
145             {
146                 btree.insert( key, value );
147             }
148             catch ( Exception e )
149             {
150                 e.printStackTrace();
151                 System.out.println( btree );
152                 System.out.println( "Error while adding " + value );
153                 nbError++;
154                 btree.close();
155 
156                 return null;
157             }
158 
159             if ( i % 10000 == 0 )
160             {
161                 if ( n > 0 )
162                 {
163                     long t0 = System.currentTimeMillis();
164                     System.out.println( "Written " + i + " elements in : " + ( t0 - delta ) + "ms" );
165                     delta = t0;
166                 }
167 
168                 n++;
169             }
170         }
171 
172         long l2 = System.currentTimeMillis();
173 
174         System.out.println( "Delta : " + ( l2 - l1 ) + ", nbError = " + nbError
175             + ", Nb insertion per second : " + ( ( nbElems ) / ( l2 - l1 ) ) * 1000 );
176 
177         // Now, flush the btree
178 
179         File tempFile = tempFolder.newFile( "mavibot.tmp" );
180 
181         long t0 = System.currentTimeMillis();
182 
183         ( ( InMemoryBTree<Long, String> ) btree ).flush( tempFile );
184 
185         long t1 = System.currentTimeMillis();
186 
187         System.out.println( "Time to flush 100 000 elements : " + ( t1 - t0 ) + "ms" );
188         btree.close();
189 
190         return tempFile.getCanonicalPath();
191     }
192 
193 
194     /**
195      * Checks the created BTree contains the expected values
196      */
197     private boolean checkTreeLong( Set<Long> expected, BTree<Long, String> btree ) throws IOException
198     {
199         // We loop on all the expected value to see if they have correctly been inserted
200         // into the btree
201         for ( Long key : expected )
202         {
203             try
204             {
205                 btree.get( key );
206             }
207             catch ( KeyNotFoundException knfe )
208             {
209                 return false;
210             }
211         }
212 
213         return true;
214     }
215 
216 
217     /**
218      * Test the browse method going backward
219      * @throws Exception
220      */
221     @Test
222     public void testFlushBTree() throws Exception
223     {
224         // Create a BTree with pages containing 8 elements
225         String path = tempFolder.getRoot().getCanonicalPath();
226 
227         BTree<Integer, String> btree = BTreeFactory.createInMemoryBTree( "test", path, new IntSerializer(),
228             new StringSerializer() );
229         btree.setPageSize( 8 );
230 
231         File journal = ( ( InMemoryBTree<Integer, String> ) btree ).getJournal();
232         File data = ( ( InMemoryBTree<Integer, String> ) btree ).getFile();
233 
234         try
235         {
236             // Inject the values
237             for ( int value : sortedValues )
238             {
239                 String strValue = "V" + value;
240 
241                 btree.insert( value, strValue );
242             }
243 
244             // The journal must be full
245             assertTrue( journal.length() > 0 );
246 
247             // Now, flush the btree
248             btree.flush();
249 
250             // The journal must be empty
251             assertEquals( 0, journal.length() );
252 
253             // Load the data into a new tree
254             BTree<Integer, String> btreeLoaded = BTreeFactory.createInMemoryBTree( "test", path, new IntSerializer(),
255                 new StringSerializer() );
256             btree.setPageSize( 8 );
257 
258             TupleCursor<Integer, String> cursor1 = btree.browse();
259             TupleCursor<Integer, String> cursor2 = btree.browse();
260 
261             while ( cursor1.hasNext() )
262             {
263                 assertTrue( cursor2.hasNext() );
264 
265                 Tuple<Integer, String> tuple1 = cursor1.next();
266                 Tuple<Integer, String> tuple2 = cursor2.next();
267 
268                 assertEquals( tuple1.getKey(), tuple2.getKey() );
269                 assertEquals( tuple1.getValue(), tuple2.getValue() );
270             }
271 
272             assertFalse( cursor2.hasNext() );
273 
274             btree.close();
275             btreeLoaded.close();
276         }
277         finally
278         {
279             data.delete();
280             journal.delete();
281         }
282     }
283 
284 
285     /**
286      * Test the insertion of 5 million elements in a BTree
287      * @throws Exception
288      */
289     @Test
290     public void testLoadBTreeFromFile() throws Exception
291     {
292         String data100K = create100KElementsFile();
293         File dataFile = new File( data100K );
294         BTree<Long, String> btree = BTreeFactory.createInMemoryBTree(
295             "test",
296             dataFile.getParent(),
297             new LongSerializer(),
298             new StringSerializer() );
299         btree.setPageSize( 32 );
300         btree.close();
301     }
302 }