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.assertNotNull;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  
29  import java.io.File;
30  import java.io.IOException;
31  import java.util.ArrayList;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Set;
35  import java.util.UUID;
36  
37  import org.apache.commons.io.FileUtils;
38  import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
39  import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
40  import org.apache.directory.mavibot.btree.serializer.LongSerializer;
41  import org.apache.directory.mavibot.btree.serializer.StringSerializer;
42  import org.junit.After;
43  import org.junit.Before;
44  import org.junit.Ignore;
45  import org.junit.Rule;
46  import org.junit.Test;
47  import org.junit.rules.TemporaryFolder;
48  
49  
50  /**
51   * test the RecordManager
52   *
53   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
54   */
55  public class RecordManagerTest
56  {
57      private BTree<Long, String> btree = null;
58  
59      private RecordManager recordManager = null;
60  
61      @Rule
62      public TemporaryFolder tempFolder = new TemporaryFolder();
63  
64      private File dataDir = null;
65  
66  
67      @Before
68      public void createBTree() throws IOException
69      {
70          dataDir = tempFolder.newFolder( UUID.randomUUID().toString() );
71  
72          System.out.println( dataDir + "/mavibot.db" );
73  
74          openRecordManagerAndBtree();
75  
76          try
77          {
78              // Create a new BTree
79              btree = recordManager.addBTree( "test", LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
80          }
81          catch ( Exception e )
82          {
83              throw new RuntimeException( e );
84          }
85      }
86  
87  
88      @After
89      public void cleanup() throws IOException
90      {
91          btree.close();
92  
93          if ( dataDir.exists() )
94          {
95              FileUtils.deleteDirectory( dataDir );
96          }
97      }
98  
99  
100     private void openRecordManagerAndBtree()
101     {
102         try
103         {
104             if ( recordManager != null )
105             {
106                 recordManager.close();
107             }
108 
109             // Now, try to reload the file back
110             recordManager = new RecordManager( dataDir.getAbsolutePath() );
111 
112             // load the last created btree
113             if ( btree != null )
114             {
115                 btree = recordManager.getManagedTree( btree.getName() );
116             }
117         }
118         catch ( Exception e )
119         {
120             throw new RuntimeException( e );
121         }
122     }
123 
124 
125     /**
126      * Test the creation of a RecordManager, and that we can read it back.
127      */
128     @Test
129     @Ignore
130     public void testRecordManager() throws IOException, BTreeAlreadyManagedException
131     {
132         assertEquals( 1, recordManager.getNbManagedTrees() );
133 
134         Set<String> managedBTrees = recordManager.getManagedTrees();
135 
136         assertEquals( 1, managedBTrees.size() );
137         assertTrue( managedBTrees.contains( "test" ) );
138 
139         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
140 
141         assertNotNull( btree1 );
142         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
143         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
144         assertEquals( btree.getName(), btree1.getName() );
145         assertEquals( btree.getNbElems(), btree1.getNbElems() );
146         assertEquals( btree.getPageSize(), btree1.getPageSize() );
147         assertEquals( btree.getRevision(), btree1.getRevision() );
148         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
149     }
150 
151 
152     /**
153      * Test the creation of a RecordManager with a BTree containing data.
154      */
155     @Test
156     public void testRecordManagerWithBTree() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException
157     {
158         // Now, add some elements in the BTree
159         btree.insert( 3L, "V3" );
160         btree.insert( 1L, "V1" );
161         btree.insert( 5L, "V5" );
162 
163         // Now, try to reload the file back
164         openRecordManagerAndBtree();
165 
166         assertEquals( 1, recordManager.getNbManagedTrees() );
167 
168         Set<String> managedBTrees = recordManager.getManagedTrees();
169 
170         assertEquals( 1, managedBTrees.size() );
171         assertTrue( managedBTrees.contains( "test" ) );
172 
173         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
174 
175         assertNotNull( btree1 );
176         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
177         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
178         assertEquals( btree.getName(), btree1.getName() );
179         assertEquals( btree.getNbElems(), btree1.getNbElems() );
180         assertEquals( btree.getPageSize(), btree1.getPageSize() );
181         assertEquals( btree.getRevision(), btree1.getRevision() );
182         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
183 
184         // Check the stored element
185         assertTrue( btree1.hasKey( 1L ) );
186         assertTrue( btree1.hasKey( 3L ) );
187         assertTrue( btree1.hasKey( 5L ) );
188         assertEquals( "V1", btree1.get( 1L ) );
189         assertEquals( "V3", btree1.get( 3L ) );
190         assertEquals( "V5", btree1.get( 5L ) );
191     }
192 
193 
194     /**
195      * Test the creation of a RecordManager with a BTree containing data, enough for some Node to be created.
196      */
197     @Test
198     public void testRecordManagerWithBTreeLeafNode() throws IOException, BTreeAlreadyManagedException,
199         KeyNotFoundException
200     {
201         // Now, add some elements in the BTree
202         for ( long i = 1L; i < 32L; i++ )
203         {
204             btree.insert( i, "V" + i );
205         }
206 
207         for ( long i = 1L; i < 32L; i++ )
208         {
209             if ( !btree.hasKey( i ) )
210             {
211                 System.out.println( "Not found !!! " + i );
212             }
213             assertTrue( btree.hasKey( i ) );
214             assertEquals( "V" + i, btree.get( i ) );
215         }
216 
217         // Now, try to reload the file back
218         openRecordManagerAndBtree();
219 
220         assertEquals( 1, recordManager.getNbManagedTrees() );
221 
222         Set<String> managedBTrees = recordManager.getManagedTrees();
223 
224         assertEquals( 1, managedBTrees.size() );
225         assertTrue( managedBTrees.contains( "test" ) );
226 
227         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
228 
229         assertNotNull( btree1 );
230         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
231         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
232         assertEquals( btree.getName(), btree1.getName() );
233         assertEquals( btree.getNbElems(), btree1.getNbElems() );
234         assertEquals( btree.getPageSize(), btree1.getPageSize() );
235         assertEquals( btree.getRevision(), btree1.getRevision() );
236         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
237 
238         // Check the stored element
239         for ( long i = 1L; i < 32L; i++ )
240         {
241             if ( !btree1.hasKey( i ) )
242             {
243                 System.out.println( "Not found " + i );
244             }
245             assertTrue( btree1.hasKey( i ) );
246             assertEquals( "V" + i, btree1.get( i ) );
247         }
248     }
249 
250 
251     /**
252      * Test the creation of a RecordManager with a BTree containing 100 000 elements
253      */
254     @Test
255     @Ignore("This is a performance test")
256     public void testRecordManagerWithBTreeLeafNode100K() throws IOException, BTreeAlreadyManagedException,
257         KeyNotFoundException
258     {
259         // Don't keep any revision
260         recordManager.setKeepRevisions( false );
261 
262         String fileName = dataDir.getAbsolutePath() + "/mavibot.db";
263         File file = new File( fileName );
264         long fileSize = file.length();
265         long nbElems = 100000L;
266         System.out.println( "----- Size before = " + fileSize );
267 
268         // Now, add some elements in the BTree
269         long t0 = System.currentTimeMillis();
270 
271         for ( Long i = 0L; i < nbElems; i++ )
272         {
273             String value = "V" + i;
274             btree.insert( i, value );
275 
276             /*
277             if ( !recordManager1.check() )
278             {
279                 System.out.println( "Failure while adding element " + i );
280                 fail();
281             }
282             */
283 
284             if ( i % 10000 == 0 )
285             {
286                 fileSize = file.length();
287                 System.out.println( "----- Size after insertion of " + i + " = " + fileSize );
288                 System.out.println( recordManager );
289                 //System.out.println( btree );
290             }
291         }
292         long t1 = System.currentTimeMillis();
293 
294         fileSize = file.length();
295         System.out.println( "Size after insertion of 100 000 elements : " + fileSize );
296         System.out.println( "Time taken to write 100 000 elements : " + ( t1 - t0 ) );
297         System.out.println( "  Nb elem/s : " + ( ( nbElems * 1000 ) / ( t1 - t0 ) ) );
298         System.out.println( "Nb created page " + recordManager.nbCreatedPages.get() );
299         System.out.println( "Nb allocated page " + recordManager.nbReusedPages.get() );
300         System.out.println( "Nb page we have freed " + recordManager.nbFreedPages.get() );
301         System.out.println( recordManager );
302 
303         // Now, try to reload the file back
304         openRecordManagerAndBtree();
305 
306         assertEquals( 1, recordManager.getNbManagedTrees() );
307 
308         Set<String> managedBTrees = recordManager.getManagedTrees();
309 
310         assertEquals( 1, managedBTrees.size() );
311         assertTrue( managedBTrees.contains( "test" ) );
312 
313         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
314 
315         assertNotNull( btree1 );
316         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
317         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
318         assertEquals( btree.getName(), btree1.getName() );
319         assertEquals( btree.getNbElems(), btree1.getNbElems() );
320         assertEquals( btree.getPageSize(), btree1.getPageSize() );
321         assertEquals( btree.getRevision(), btree1.getRevision() );
322         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
323 
324         // Check the stored element
325         long t2 = System.currentTimeMillis();
326         for ( long i = 0L; i < nbElems; i++ )
327         {
328             //assertTrue( btree1.exist( i ) );
329             assertEquals( "V" + i, btree1.get( i ) );
330         }
331         long t3 = System.currentTimeMillis();
332         System.out.println( "Time taken to verify 100 000 elements : " + ( t3 - t2 ) );
333 
334         // Check the stored element a second time
335         long t4 = System.currentTimeMillis();
336         for ( long i = 0L; i < nbElems; i++ )
337         {
338             //assertTrue( btree1.exist( i ) );
339             assertEquals( "V" + i, btree1.get( i ) );
340         }
341         long t5 = System.currentTimeMillis();
342         System.out.println( "Time taken to verify 100 000 elements : " + ( t5 - t4 ) );
343     }
344 
345 
346     private void checkBTreeRevisionBrowse( BTree<Long, String> btree, long revision, long... values )
347         throws IOException,
348         KeyNotFoundException
349     {
350         TupleCursor<Long, String> cursor = btree.browse( revision );
351         List<Long> expected = new ArrayList<Long>( values.length );
352         Set<Long> found = new HashSet<Long>( values.length );
353 
354         for ( long value : values )
355         {
356             expected.add( value );
357         }
358 
359         int nb = 0;
360 
361         while ( cursor.hasNext() )
362         {
363             Tuple<Long, String> res = cursor.next();
364 
365             long key = res.getKey();
366             assertEquals( expected.get( nb ), ( Long ) key );
367             assertFalse( found.contains( key ) );
368             found.add( key );
369             assertEquals( "V" + key, res.getValue() );
370             nb++;
371         }
372 
373         assertEquals( values.length, nb );
374         cursor.close();
375     }
376 
377 
378     private void checkBTreeRevisionBrowseFrom( BTree<Long, String> btree, long revision, long from, long... values )
379         throws IOException,
380         KeyNotFoundException
381     {
382         TupleCursor<Long, String> cursor = btree.browseFrom( revision, from );
383         List<Long> expected = new ArrayList<Long>( values.length );
384         Set<Long> found = new HashSet<Long>( values.length );
385 
386         for ( long value : values )
387         {
388             expected.add( value );
389         }
390 
391         int nb = 0;
392 
393         while ( cursor.hasNext() )
394         {
395             Tuple<Long, String> res = cursor.next();
396 
397             long key = res.getKey();
398             assertEquals( expected.get( nb ), ( Long ) key );
399             assertFalse( found.contains( key ) );
400             found.add( key );
401             assertEquals( "V" + key, res.getValue() );
402             nb++;
403         }
404 
405         assertEquals( values.length, nb );
406         cursor.close();
407 
408     }
409 
410 
411     /**
412      * Test the creation of a RecordManager with a BTree containing data, where we keep the revisions,
413      * and browse the BTree.
414      */
415     @Test
416     public void testRecordManagerBrowseWithKeepRevisions() throws IOException, BTreeAlreadyManagedException,
417         KeyNotFoundException
418     {
419         recordManager.setKeepRevisions( true );
420 
421         // Now, add some elements in the BTree
422         btree.insert( 3L, "V3" );
423         long rev1 = btree.getRevision();
424 
425         btree.insert( 1L, "V1" );
426         long rev2 = btree.getRevision();
427 
428         btree.insert( 5L, "V5" );
429         long rev3 = btree.getRevision();
430 
431         // Check that we can browse each revision
432         // revision 1
433         checkBTreeRevisionBrowse( btree, rev1, 3L );
434 
435         // Revision 2
436         checkBTreeRevisionBrowse( btree, rev2, 1L, 3L );
437 
438         // Revision 3
439         checkBTreeRevisionBrowse( btree, rev3, 1L, 3L, 5L );
440 
441         // Now, try to reload the file back
442         openRecordManagerAndBtree();
443 
444         assertEquals( 1, recordManager.getNbManagedTrees() );
445 
446         Set<String> managedBTrees = recordManager.getManagedTrees();
447 
448         assertEquals( 1, managedBTrees.size() );
449         assertTrue( managedBTrees.contains( "test" ) );
450 
451         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
452 
453         assertNotNull( btree1 );
454         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
455         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
456         assertEquals( btree.getName(), btree1.getName() );
457         assertEquals( btree.getNbElems(), btree1.getNbElems() );
458         assertEquals( btree.getPageSize(), btree1.getPageSize() );
459         assertEquals( btree.getRevision(), btree1.getRevision() );
460         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
461 
462         // Check the stored element
463         assertTrue( btree1.hasKey( 1L ) );
464         assertTrue( btree1.hasKey( 3L ) );
465         assertTrue( btree1.hasKey( 5L ) );
466         assertEquals( "V1", btree1.get( 1L ) );
467         assertEquals( "V3", btree1.get( 3L ) );
468         assertEquals( "V5", btree1.get( 5L ) );
469 
470         // Check that we can read the revision again
471         // revision 1
472         checkBTreeRevisionBrowse( btree, rev1 );
473 
474         // Revision 2
475         checkBTreeRevisionBrowse( btree, rev2 );
476 
477         // Revision 3
478         checkBTreeRevisionBrowse( btree, rev3, 1L, 3L, 5L );
479     }
480 
481 
482     /**
483      * Test the creation of a RecordManager with a BTree containing data, where we keep the revision, and
484      * we browse from a key
485      */
486     @Test
487     public void testRecordManagerBrowseFromWithRevision() throws IOException, BTreeAlreadyManagedException,
488         KeyNotFoundException
489     {
490         recordManager.setKeepRevisions( true );
491 
492         // Now, add some elements in the BTree
493         btree.insert( 3L, "V3" );
494         long rev1 = btree.getRevision();
495 
496         btree.insert( 1L, "V1" );
497         long rev2 = btree.getRevision();
498 
499         btree.insert( 5L, "V5" );
500         long rev3 = btree.getRevision();
501 
502         // Check that we can browse each revision
503         // revision 1
504         checkBTreeRevisionBrowseFrom( btree, rev1, 3L, 3L );
505 
506         // Revision 2
507         checkBTreeRevisionBrowseFrom( btree, rev2, 3L, 3L );
508 
509         // Revision 3
510         checkBTreeRevisionBrowseFrom( btree, rev3, 3L, 3L, 5L );
511 
512         // Now, try to reload the file back
513         openRecordManagerAndBtree();
514 
515         assertEquals( 1, recordManager.getNbManagedTrees() );
516 
517         Set<String> managedBTrees = recordManager.getManagedTrees();
518 
519         assertEquals( 1, managedBTrees.size() );
520         assertTrue( managedBTrees.contains( "test" ) );
521 
522         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
523 
524         assertNotNull( btree1 );
525         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
526         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
527         assertEquals( btree.getName(), btree1.getName() );
528         assertEquals( btree.getNbElems(), btree1.getNbElems() );
529         assertEquals( btree.getPageSize(), btree1.getPageSize() );
530         assertEquals( btree.getRevision(), btree1.getRevision() );
531         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
532 
533         // Check the stored element
534         assertTrue( btree1.hasKey( 1L ) );
535         assertTrue( btree1.hasKey( 3L ) );
536         assertTrue( btree1.hasKey( 5L ) );
537         assertEquals( "V1", btree1.get( 1L ) );
538         assertEquals( "V3", btree1.get( 3L ) );
539         assertEquals( "V5", btree1.get( 5L ) );
540 
541         // Check that we can read the revision again
542         // revision 1
543         checkBTreeRevisionBrowseFrom( btree, rev1, 3L );
544 
545         // Revision 2
546         checkBTreeRevisionBrowseFrom( btree, rev2, 3L );
547 
548         // Revision 3
549         checkBTreeRevisionBrowseFrom( btree, rev3, 3L, 3L, 5L );
550     }
551 
552 
553     /**
554      * Test a get() from a given revision
555      */
556     @Test
557     public void testGetWithRevision() throws IOException, BTreeAlreadyManagedException,
558         KeyNotFoundException
559     {
560         recordManager.setKeepRevisions( true );
561 
562         // Now, add some elements in the BTree
563         btree.insert( 3L, "V3" );
564         long rev1 = btree.getRevision();
565 
566         btree.insert( 1L, "V1" );
567         long rev2 = btree.getRevision();
568 
569         btree.insert( 5L, "V5" );
570         long rev3 = btree.getRevision();
571 
572         // Delete one element
573         btree.delete( 3L );
574         long rev4 = btree.getRevision();
575 
576         // Check that we can get a value from each revision
577         // revision 1
578         assertEquals( "V3", btree.get( rev1, 3L ) );
579 
580         // revision 2
581         assertEquals( "V1", btree.get( rev2, 1L ) );
582         assertEquals( "V3", btree.get( rev2, 3L ) );
583 
584         // revision 3
585         assertEquals( "V1", btree.get( rev3, 1L ) );
586         assertEquals( "V3", btree.get( rev3, 3L ) );
587         assertEquals( "V5", btree.get( rev3, 5L ) );
588 
589         // revision 4
590         assertEquals( "V1", btree.get( rev4, 1L ) );
591         assertEquals( "V5", btree.get( rev4, 5L ) );
592 
593         try
594         {
595             btree.get( rev4, 3L );
596             fail();
597         }
598         catch ( KeyNotFoundException knfe )
599         {
600             // expected
601         }
602 
603         // Now, try to reload the file back
604         openRecordManagerAndBtree();
605 
606         assertEquals( 1, recordManager.getNbManagedTrees() );
607 
608         Set<String> managedBTrees = recordManager.getManagedTrees();
609 
610         assertEquals( 1, managedBTrees.size() );
611         assertTrue( managedBTrees.contains( "test" ) );
612 
613         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
614 
615         assertNotNull( btree1 );
616         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
617         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
618         assertEquals( btree.getName(), btree1.getName() );
619         assertEquals( btree.getNbElems(), btree1.getNbElems() );
620         assertEquals( btree.getPageSize(), btree1.getPageSize() );
621         assertEquals( btree.getRevision(), btree1.getRevision() );
622         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
623 
624         // Check the stored element
625         assertTrue( btree1.hasKey( 1L ) );
626         assertFalse( btree1.hasKey( 3L ) );
627         assertTrue( btree1.hasKey( 5L ) );
628         assertEquals( "V1", btree1.get( 1L ) );
629         assertEquals( "V5", btree1.get( 5L ) );
630 
631         // Check that we can get a value from each revision
632         // revision 1
633         checkBTreeRevisionBrowse( btree, rev1 );
634 
635         // revision 2
636         checkBTreeRevisionBrowse( btree, rev2 );
637 
638         // revision 3
639         checkBTreeRevisionBrowse( btree, rev3 );
640 
641         // revision 4
642         checkBTreeRevisionBrowse( btree, rev4, 1L, 5L );
643 
644         try
645         {
646             btree.get( rev4, 3L );
647             fail();
648         }
649         catch ( KeyNotFoundException knfe )
650         {
651             // expected
652         }
653     }
654 
655 
656     /**
657      * Test a contain() from a given revision
658      */
659     @Test
660     public void testContainWithRevision() throws IOException, BTreeAlreadyManagedException,
661         KeyNotFoundException
662     {
663         recordManager.setKeepRevisions( true );
664 
665         // Now, add some elements in the BTree
666         btree.insert( 3L, "V3" );
667         long rev1 = btree.getRevision();
668 
669         btree.insert( 1L, "V1" );
670         long rev2 = btree.getRevision();
671 
672         btree.insert( 5L, "V5" );
673         long rev3 = btree.getRevision();
674 
675         // Delete one element
676         btree.delete( 3L );
677         long rev4 = btree.getRevision();
678 
679         // Check that we can get a value from each revision
680         // revision 1
681         assertFalse( btree.contains( rev1, 1L, "V1" ) );
682         assertTrue( btree.contains( rev1, 3L, "V3" ) );
683         assertFalse( btree.contains( rev1, 5L, "V5" ) );
684 
685         // revision 2
686         assertTrue( btree.contains( rev2, 1L, "V1" ) );
687         assertTrue( btree.contains( rev2, 3L, "V3" ) );
688         assertFalse( btree.contains( rev2, 5L, "V5" ) );
689 
690         // revision 3
691         assertTrue( btree.contains( rev3, 1L, "V1" ) );
692         assertTrue( btree.contains( rev3, 3L, "V3" ) );
693         assertTrue( btree.contains( rev3, 5L, "V5" ) );
694 
695         // revision 4
696         assertTrue( btree.contains( rev4, 1L, "V1" ) );
697         assertFalse( btree.contains( rev4, 3L, "V3" ) );
698         assertTrue( btree.contains( rev4, 5L, "V5" ) );
699 
700         // Now, try to reload the file back
701         openRecordManagerAndBtree();
702 
703         assertEquals( 1, recordManager.getNbManagedTrees() );
704 
705         Set<String> managedBTrees = recordManager.getManagedTrees();
706 
707         assertEquals( 1, managedBTrees.size() );
708         assertTrue( managedBTrees.contains( "test" ) );
709 
710         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
711 
712         assertNotNull( btree1 );
713         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
714         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
715         assertEquals( btree.getName(), btree1.getName() );
716         assertEquals( btree.getNbElems(), btree1.getNbElems() );
717         assertEquals( btree.getPageSize(), btree1.getPageSize() );
718         assertEquals( btree.getRevision(), btree1.getRevision() );
719         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
720 
721         // Check the stored element
722         assertTrue( btree1.hasKey( 1L ) );
723         assertFalse( btree1.hasKey( 3L ) );
724         assertTrue( btree1.hasKey( 5L ) );
725         assertEquals( "V1", btree1.get( 1L ) );
726         assertEquals( "V5", btree1.get( 5L ) );
727 
728         // Check that we can get a value from each revision
729         // revision 1
730         assertFalse( btree.contains( rev1, 1L, "V1" ) );
731         assertFalse( btree.contains( rev1, 3L, "V3" ) );
732         assertFalse( btree.contains( rev1, 5L, "V5" ) );
733 
734         // revision 2
735         assertFalse( btree.contains( rev2, 1L, "V1" ) );
736         assertFalse( btree.contains( rev2, 3L, "V3" ) );
737         assertFalse( btree.contains( rev2, 5L, "V5" ) );
738 
739         // revision 3
740         assertFalse( btree.contains( rev3, 1L, "V1" ) );
741         assertFalse( btree.contains( rev3, 3L, "V3" ) );
742         assertFalse( btree.contains( rev3, 5L, "V5" ) );
743 
744         // revision 4
745         assertTrue( btree.contains( rev4, 1L, "V1" ) );
746         assertFalse( btree.contains( rev4, 3L, "V3" ) );
747         assertTrue( btree.contains( rev4, 5L, "V5" ) );
748     }
749 
750 
751     /**
752      * Test a hasKey() from a given revision
753      */
754     @Test
755     public void testHasKeyWithRevision() throws IOException, BTreeAlreadyManagedException,
756         KeyNotFoundException
757     {
758         recordManager.setKeepRevisions( true );
759 
760         // Now, add some elements in the BTree
761         btree.insert( 3L, "V3" );
762         long rev1 = btree.getRevision();
763 
764         btree.insert( 1L, "V1" );
765         long rev2 = btree.getRevision();
766 
767         btree.insert( 5L, "V5" );
768         long rev3 = btree.getRevision();
769 
770         // Delete one element
771         btree.delete( 3L );
772         long rev4 = btree.getRevision();
773 
774         // Check that we can get a value from each revision
775         // revision 1
776         assertFalse( btree.hasKey( rev1, 1L ) );
777         assertTrue( btree.hasKey( rev1, 3L ) );
778         assertFalse( btree.hasKey( rev1, 5L ) );
779 
780         // revision 2
781         assertTrue( btree.hasKey( rev2, 1L ) );
782         assertTrue( btree.hasKey( rev2, 3L ) );
783         assertFalse( btree.hasKey( rev2, 5L ) );
784 
785         // revision 3
786         assertTrue( btree.hasKey( rev3, 1L ) );
787         assertTrue( btree.hasKey( rev3, 3L ) );
788         assertTrue( btree.hasKey( rev3, 5L ) );
789 
790         // revision 4
791         assertTrue( btree.hasKey( rev4, 1L ) );
792         assertFalse( btree.hasKey( rev4, 3L ) );
793         assertTrue( btree.hasKey( rev4, 5L ) );
794 
795         // Now, try to reload the file back
796         openRecordManagerAndBtree();
797 
798         assertEquals( 1, recordManager.getNbManagedTrees() );
799 
800         Set<String> managedBTrees = recordManager.getManagedTrees();
801 
802         assertEquals( 1, managedBTrees.size() );
803         assertTrue( managedBTrees.contains( "test" ) );
804 
805         BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );
806 
807         assertNotNull( btree1 );
808         assertEquals( btree.getKeyComparator().getClass().getName(), btree1.getKeyComparator().getClass().getName() );
809         assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
810         assertEquals( btree.getName(), btree1.getName() );
811         assertEquals( btree.getNbElems(), btree1.getNbElems() );
812         assertEquals( btree.getPageSize(), btree1.getPageSize() );
813         assertEquals( btree.getRevision(), btree1.getRevision() );
814         assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
815 
816         // Check the stored element
817         assertTrue( btree1.hasKey( 1L ) );
818         assertFalse( btree1.hasKey( 3L ) );
819         assertTrue( btree1.hasKey( 5L ) );
820         assertEquals( "V1", btree1.get( 1L ) );
821         assertEquals( "V5", btree1.get( 5L ) );
822 
823         // Check that we can get a value from each revision
824         // revision 1
825         assertFalse( btree.hasKey( rev1, 1L ) );
826         assertFalse( btree.hasKey( rev1, 3L ) );
827         assertFalse( btree.hasKey( rev1, 5L ) );
828 
829         // revision 2
830         assertFalse( btree.hasKey( rev2, 1L ) );
831         assertFalse( btree.hasKey( rev2, 3L ) );
832         assertFalse( btree.hasKey( rev2, 5L ) );
833 
834         // revision 3
835         assertFalse( btree.hasKey( rev3, 1L ) );
836         assertFalse( btree.hasKey( rev3, 3L ) );
837         assertFalse( btree.hasKey( rev3, 5L ) );
838 
839         // revision 4
840         assertTrue( btree.hasKey( rev4, 1L ) );
841         assertFalse( btree.hasKey( rev4, 3L ) );
842         assertTrue( btree.hasKey( rev4, 5L ) );
843     }
844 
845 
846     /**
847      * Test with BTrees containing duplicate keys
848      */
849     @Test
850     public void testBTreesDuplicateKeys() throws IOException, BTreeAlreadyManagedException,
851         KeyNotFoundException
852     {
853         int pageSize = 16;
854         int numKeys = 1;
855         String name = "duplicateTree";
856         String[] testValues = new String[]
857             { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10" };
858 
859         BTree<Long, String> dupsTree = BTreeFactory.createPersistedBTree( name, LongSerializer.INSTANCE,
860             StringSerializer.INSTANCE, pageSize, true );
861 
862         recordManager.manage( dupsTree );
863 
864         for ( long i = 0; i < numKeys; i++ )
865         {
866             for ( int k = 0; k < pageSize + 1; k++ )
867             {
868                 dupsTree.insert( i, testValues[k] );
869             }
870         }
871 
872         // Now, try to reload the file back
873         openRecordManagerAndBtree();
874 
875         dupsTree = recordManager.getManagedTree( name );
876 
877         for ( long i = 0; i < numKeys; i++ )
878         {
879             ValueCursor<String> values = dupsTree.getValues( i );
880 
881             for ( int k = 0; k < pageSize + 1; k++ )
882             {
883                 assertTrue( values.next().equals( testValues[k] ) );
884             }
885         }
886     }
887 
888 
889     @Test
890     public void testAdds() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException
891     {
892         btree.insert( 1L, "V1" );
893         btree.insert( 2L, "V2" );
894     }
895 }