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