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