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 java.util.LinkedList;
24  
25  import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
26  
27  
28  /**
29   * This class construct a B-tree from a serialized version of a B-tree. We need it
30   * to avoid exposing all the methods of the B-tree class.<br>
31   *
32   * All its methods are static.
33   *
34   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
35   *
36   * @param <K> The B-tree key type
37   * @param <V> The B-tree value type
38   */
39  public class BTreeFactory<K, V>
40  {
41      //--------------------------------------------------------------------------------------------
42      // Create persisted btrees
43      //--------------------------------------------------------------------------------------------
44      /**
45       * Creates a new persisted B-tree, with no initialization.
46       *
47       * @return a new B-tree instance
48       */
49      public static <K, V> BTree<K, V> createPersistedBTree()
50      {
51          BTree<K, V> btree = new PersistedBTree<K, V>();
52  
53          return btree;
54      }
55  
56  
57      /**
58       * Creates a new persisted B-tree, with no initialization.
59       *
60       * @return a new B-tree instance
61       */
62      public static <K, V> BTree<K, V> createPersistedBTree( BTreeTypeEnum type )
63      {
64          BTree<K, V> btree = new PersistedBTree<K, V>();
65          ((AbstractBTree<K, V>)btree).setType( type );
66  
67          return btree;
68      }
69  
70  
71      /**
72       * Sets the btreeHeader offset for a Persisted BTree
73       *
74       * @param btree The btree to update
75       * @param btreeHeaderOffset The offset
76       */
77      public static <K, V> void setBtreeHeaderOffset( PersistedBTree<K, V> btree, long btreeHeaderOffset )
78      {
79          btree.setBtreeHeaderOffset( btreeHeaderOffset );
80      }
81  
82      /**
83       * Creates a new persisted B-tree using the BTreeConfiguration to initialize the
84       * B-tree
85       *
86       * @param configuration The configuration to use
87       * @return a new B-tree instance
88       */
89      public static <K, V> BTree<K, V> createPersistedBTree( PersistedBTreeConfiguration<K, V> configuration )
90      {
91          BTree<K, V> btree = new PersistedBTree<K, V>( configuration );
92  
93          return btree;
94      }
95  
96  
97      /**
98       * Creates a new persisted B-tree using the parameters to initialize the
99       * B-tree
100      *
101      * @param name The B-tree's name
102      * @param keySerializer Key serializer
103      * @param valueSerializer Value serializer
104      * @return a new B-tree instance
105      */
106     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
107         ElementSerializer<V> valueSerializer )
108     {
109         PersistedBTreeConfiguration<K, V> configuration = new PersistedBTreeConfiguration<K, V>();
110 
111         configuration.setName( name );
112         configuration.setKeySerializer( keySerializer );
113         configuration.setValueSerializer( valueSerializer );
114         configuration.setPageSize( BTree.DEFAULT_PAGE_SIZE );
115         configuration.setAllowDuplicates( BTree.FORBID_DUPLICATES );
116         configuration.setCacheSize( PersistedBTree.DEFAULT_CACHE_SIZE );
117         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
118 
119         BTree<K, V> btree = new PersistedBTree<K, V>( configuration );
120 
121         return btree;
122     }
123 
124 
125     /**
126      * Creates a new persisted B-tree using the parameters to initialize the
127      * B-tree
128      *
129      * @param name The B-tree's name
130      * @param keySerializer Key serializer
131      * @param valueSerializer Value serializer
132      * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
133      * @return a new B-tree instance
134      */
135     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
136         ElementSerializer<V> valueSerializer, boolean allowDuplicates )
137     {
138         PersistedBTreeConfiguration<K, V> configuration = new PersistedBTreeConfiguration<K, V>();
139 
140         configuration.setName( name );
141         configuration.setKeySerializer( keySerializer );
142         configuration.setValueSerializer( valueSerializer );
143         configuration.setPageSize( BTree.DEFAULT_PAGE_SIZE );
144         configuration.setAllowDuplicates( allowDuplicates );
145         configuration.setCacheSize( PersistedBTree.DEFAULT_CACHE_SIZE );
146         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
147 
148         BTree<K, V> btree = new PersistedBTree<K, V>( configuration );
149 
150         return btree;
151     }
152 
153 
154     /**
155      * Creates a new persisted B-tree using the parameters to initialize the
156      * B-tree
157      *
158      * @param name The B-tree's name
159      * @param keySerializer Key serializer
160      * @param valueSerializer Value serializer
161      * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
162      * @param cacheSize The size to be used for this B-tree cache
163      * @return a new B-tree instance
164      */
165     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
166         ElementSerializer<V> valueSerializer, boolean allowDuplicates, int cacheSize )
167     {
168         PersistedBTreeConfiguration<K, V> configuration = new PersistedBTreeConfiguration<K, V>();
169 
170         configuration.setName( name );
171         configuration.setKeySerializer( keySerializer );
172         configuration.setValueSerializer( valueSerializer );
173         configuration.setPageSize( BTree.DEFAULT_PAGE_SIZE );
174         configuration.setAllowDuplicates( allowDuplicates );
175         configuration.setCacheSize( cacheSize );
176         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
177 
178         BTree<K, V> btree = new PersistedBTree<K, V>( configuration );
179 
180         return btree;
181     }
182 
183 
184     /**
185      * Creates a new persisted B-tree using the parameters to initialize the
186      * B-tree
187      *
188      * @param name The B-tree's name
189      * @param keySerializer Key serializer
190      * @param valueSerializer Value serializer
191      * @param pageSize Size of the page
192      * @return a new B-tree instance
193      */
194     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
195         ElementSerializer<V> valueSerializer, int pageSize )
196     {
197         PersistedBTreeConfiguration<K, V> configuration = new PersistedBTreeConfiguration<K, V>();
198 
199         configuration.setName( name );
200         configuration.setKeySerializer( keySerializer );
201         configuration.setValueSerializer( valueSerializer );
202         configuration.setPageSize( pageSize );
203         configuration.setAllowDuplicates( BTree.FORBID_DUPLICATES );
204         configuration.setCacheSize( PersistedBTree.DEFAULT_CACHE_SIZE );
205         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
206 
207         BTree<K, V> btree = new PersistedBTree<K, V>( configuration );
208 
209         return btree;
210     }
211 
212 
213     /**
214      * Creates a new persisted B-tree using the parameters to initialize the
215      * B-tree
216      *
217      * @param name The B-tree's name
218      * @param keySerializer Key serializer
219      * @param valueSerializer Value serializer
220      * @param pageSize Size of the page
221      * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
222      * @return a new B-tree instance
223      */
224     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
225         ElementSerializer<V> valueSerializer, int pageSize, boolean allowDuplicates )
226     {
227         PersistedBTreeConfiguration<K, V> configuration = new PersistedBTreeConfiguration<K, V>();
228 
229         configuration.setName( name );
230         configuration.setKeySerializer( keySerializer );
231         configuration.setValueSerializer( valueSerializer );
232         configuration.setPageSize( pageSize );
233         configuration.setAllowDuplicates( allowDuplicates );
234         configuration.setCacheSize( PersistedBTree.DEFAULT_CACHE_SIZE );
235         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
236 
237         BTree<K, V> btree = new PersistedBTree<K, V>( configuration );
238 
239         return btree;
240     }
241 
242 
243     /**
244      * Creates a new persisted B-tree using the parameters to initialize the
245      * B-tree
246      *
247      * @param name The B-tree's name
248      * @param keySerializer Key serializer
249      * @param valueSerializer Value serializer
250      * @param pageSize Size of the page
251      * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
252      * @param cacheSize The size to be used for this B-tree cache
253      * @return a new B-tree instance
254      */
255     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
256         ElementSerializer<V> valueSerializer, int pageSize, boolean allowDuplicates, int cacheSize )
257     {
258         PersistedBTreeConfiguration<K, V> configuration = new PersistedBTreeConfiguration<K, V>();
259 
260         configuration.setName( name );
261         configuration.setKeySerializer( keySerializer );
262         configuration.setValueSerializer( valueSerializer );
263         configuration.setPageSize( pageSize );
264         configuration.setAllowDuplicates( allowDuplicates );
265         configuration.setCacheSize( cacheSize );
266         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
267 
268         BTree<K, V> btree = new PersistedBTree<K, V>( configuration );
269 
270         return btree;
271     }
272 
273 
274     //--------------------------------------------------------------------------------------------
275     // Create in-memory B-trees
276     //--------------------------------------------------------------------------------------------
277     /**
278      * Creates a new in-memory B-tree, with no initialization.
279      *
280      * @return a new B-tree instance
281      */
282     public static <K, V> BTree<K, V> createInMemoryBTree()
283     {
284         BTree<K, V> btree = new InMemoryBTree<K, V>();
285 
286         return btree;
287     }
288 
289 
290     /**
291      * Creates a new in-memory B-tree using the BTreeConfiguration to initialize the
292      * B-tree
293      *
294      * @param configuration The configuration to use
295      * @return a new B-tree instance
296      */
297     public static <K, V> BTree<K, V> createInMemoryBTree( InMemoryBTreeConfiguration<K, V> configuration )
298     {
299         BTree<K, V> btree = new InMemoryBTree<K, V>( configuration );
300 
301         return btree;
302     }
303 
304 
305     /**
306      * Creates a new in-memory B-tree using the parameters to initialize the
307      * B-tree
308      *
309      * @param name The B-tree's name
310      * @param keySerializer Key serializer
311      * @param valueSerializer Value serializer
312      * @return a new B-tree instance
313      */
314     public static <K, V> BTree<K, V> createInMemoryBTree( String name, ElementSerializer<K> keySerializer,
315         ElementSerializer<V> valueSerializer )
316     {
317         InMemoryBTreeConfiguration<K, V> configuration = new InMemoryBTreeConfiguration<K, V>();
318 
319         configuration.setName( name );
320         configuration.setKeySerializer( keySerializer );
321         configuration.setValueSerializer( valueSerializer );
322         configuration.setPageSize( BTree.DEFAULT_PAGE_SIZE );
323         configuration.setAllowDuplicates( BTree.FORBID_DUPLICATES );
324         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
325 
326         BTree<K, V> btree = new InMemoryBTree<K, V>( configuration );
327 
328         return btree;
329     }
330 
331 
332     /**
333      * Creates a new in-memory B-tree using the parameters to initialize the
334      * B-tree
335      *
336      * @param name The B-tree's name
337      * @param keySerializer Key serializer
338      * @param valueSerializer Value serializer
339      * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
340      * @return a new B-tree instance
341      */
342     public static <K, V> BTree<K, V> createInMemoryBTree( String name, ElementSerializer<K> keySerializer,
343         ElementSerializer<V> valueSerializer, boolean allowDuplicates )
344     {
345         InMemoryBTreeConfiguration<K, V> configuration = new InMemoryBTreeConfiguration<K, V>();
346 
347         configuration.setName( name );
348         configuration.setKeySerializer( keySerializer );
349         configuration.setValueSerializer( valueSerializer );
350         configuration.setPageSize( BTree.DEFAULT_PAGE_SIZE );
351         configuration.setAllowDuplicates( allowDuplicates );
352         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
353 
354         BTree<K, V> btree = new InMemoryBTree<K, V>( configuration );
355 
356         return btree;
357     }
358 
359 
360     /**
361      * Creates a new in-memory B-tree using the parameters to initialize the
362      * B-tree
363      *
364      * @param name The B-tree's name
365      * @param keySerializer Key serializer
366      * @param valueSerializer Value serializer
367      * @param pageSize Size of the page
368      * @return a new B-tree instance
369      */
370     public static <K, V> BTree<K, V> createInMemoryBTree( String name, ElementSerializer<K> keySerializer,
371         ElementSerializer<V> valueSerializer, int pageSize )
372     {
373         InMemoryBTreeConfiguration<K, V> configuration = new InMemoryBTreeConfiguration<K, V>();
374 
375         configuration.setName( name );
376         configuration.setKeySerializer( keySerializer );
377         configuration.setValueSerializer( valueSerializer );
378         configuration.setPageSize( pageSize );
379         configuration.setAllowDuplicates( BTree.FORBID_DUPLICATES );
380         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
381 
382         BTree<K, V> btree = new InMemoryBTree<K, V>( configuration );
383 
384         return btree;
385     }
386 
387 
388     /**
389      * Creates a new in-memory B-tree using the parameters to initialize the
390      * B-tree
391      *
392      * @param name The B-tree's name
393      * @param filePath The name of the data directory with absolute path
394      * @param keySerializer Key serializer
395      * @param valueSerializer Value serializer
396      * @return a new B-tree instance
397      */
398     public static <K, V> BTree<K, V> createInMemoryBTree( String name, String filePath,
399         ElementSerializer<K> keySerializer,
400         ElementSerializer<V> valueSerializer )
401     {
402         InMemoryBTreeConfiguration<K, V> configuration = new InMemoryBTreeConfiguration<K, V>();
403 
404         configuration.setName( name );
405         configuration.setFilePath( filePath );
406         configuration.setKeySerializer( keySerializer );
407         configuration.setValueSerializer( valueSerializer );
408         configuration.setPageSize( BTree.DEFAULT_PAGE_SIZE );
409         configuration.setAllowDuplicates( BTree.FORBID_DUPLICATES );
410         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
411 
412         BTree<K, V> btree = new InMemoryBTree<K, V>( configuration );
413 
414         return btree;
415     }
416 
417 
418     /**
419      * Creates a new in-memory B-tree using the parameters to initialize the
420      * B-tree
421      *
422      * @param name The B-tree's name
423      * @param filePath The name of the data directory with absolute path
424      * @param keySerializer Key serializer
425      * @param valueSerializer Value serializer
426      * @param pageSize Size of the page
427      * @return a new B-tree instance
428      */
429     public static <K, V> BTree<K, V> createInMemoryBTree( String name, String filePath,
430         ElementSerializer<K> keySerializer, ElementSerializer<V> valueSerializer, int pageSize )
431     {
432         InMemoryBTreeConfiguration<K, V> configuration = new InMemoryBTreeConfiguration<K, V>();
433 
434         configuration.setName( name );
435         configuration.setFilePath( filePath );
436         configuration.setKeySerializer( keySerializer );
437         configuration.setValueSerializer( valueSerializer );
438         configuration.setPageSize( pageSize );
439         configuration.setAllowDuplicates( BTree.FORBID_DUPLICATES );
440         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
441 
442         BTree<K, V> btree = new InMemoryBTree<K, V>( configuration );
443 
444         return btree;
445     }
446 
447 
448     /**
449      * Creates a new in-memory B-tree using the parameters to initialize the
450      * B-tree
451      *
452      * @param name The B-tree's name
453      * @param filePath The name of the data directory with absolute path
454      * @param keySerializer Key serializer
455      * @param valueSerializer Value serializer
456      * @param pageSize Size of the page
457      * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
458      * @return a new B-tree instance
459      */
460     public static <K, V> BTree<K, V> createInMemoryBTree( String name, String filePath,
461         ElementSerializer<K> keySerializer,
462         ElementSerializer<V> valueSerializer, int pageSize, boolean allowDuplicates )
463     {
464         InMemoryBTreeConfiguration<K, V> configuration = new InMemoryBTreeConfiguration<K, V>();
465 
466         configuration.setName( name );
467         configuration.setFilePath( filePath );
468         configuration.setKeySerializer( keySerializer );
469         configuration.setValueSerializer( valueSerializer );
470         configuration.setPageSize( pageSize );
471         configuration.setAllowDuplicates( allowDuplicates );
472         configuration.setWriteBufferSize( BTree.DEFAULT_WRITE_BUFFER_SIZE );
473 
474         BTree<K, V> btree = new InMemoryBTree<K, V>( configuration );
475 
476         return btree;
477     }
478 
479 
480     //--------------------------------------------------------------------------------------------
481     // Create Pages
482     //--------------------------------------------------------------------------------------------
483     /**
484      * Create a new Leaf for the given B-tree.
485      *
486      * @param btree The B-tree which will contain this leaf
487      * @param revision The Leaf's revision
488      * @param nbElems The number or elements in this leaf
489      *
490      * @return A Leaf instance
491      */
492     /* no qualifier*/static <K, V> Page<K, V> createLeaf( BTree<K, V> btree, long revision, int nbElems )
493     {
494         if ( btree.getType() != BTreeTypeEnum.IN_MEMORY )
495         {
496             return new PersistedLeaf<K, V>( btree, revision, nbElems );
497         }
498         else
499         {
500             return new InMemoryLeaf<K, V>( btree, revision, nbElems );
501         }
502     }
503 
504 
505     /**
506      * Create a new Node for the given B-tree.
507      *
508      * @param btree The B-tree which will contain this node
509      * @param revision The Node's revision
510      * @param nbElems The number or elements in this node
511      * @return A Node instance
512      */
513     /* no qualifier*/static <K, V> Page<K, V> createNode( BTree<K, V> btree, long revision, int nbElems )
514     {
515         if ( btree.getType() != BTreeTypeEnum.IN_MEMORY )
516         {
517             return new PersistedNode<K, V>( btree, revision, nbElems );
518         }
519         else
520         {
521             return new InMemoryNode<K, V>( btree, revision, nbElems );
522         }
523     }
524 
525 
526     //--------------------------------------------------------------------------------------------
527     // Update pages
528     //--------------------------------------------------------------------------------------------
529     /**
530      * Set the key at a give position
531      *
532      * @param btree The B-tree to update
533      * @param page The page to update
534      * @param pos The position in the keys array
535      * @param key The key to inject
536      */
537     /* no qualifier*/static <K, V> void setKey( BTree<K, V> btree, Page<K, V> page, int pos, K key )
538     {
539         KeyHolder<K> keyHolder;
540 
541         if ( btree.getType() != BTreeTypeEnum.IN_MEMORY )
542         {
543             keyHolder = new PersistedKeyHolder<K>( btree.getKeySerializer(), key );
544         }
545         else
546         {
547             keyHolder = new KeyHolder<K>( key );
548         }
549 
550         ( ( AbstractPage<K, V> ) page ).setKey( pos, keyHolder );
551     }
552 
553 
554     /**
555      * Set the value at a give position
556      *
557      * @param btree The B-tree to update
558      * @param page The page to update
559      * @param pos The position in the values array
560      * @param value the value to inject
561      */
562     /* no qualifier*/static <K, V> void setValue( BTree<K, V> btree, Page<K, V> page, int pos, ValueHolder<V> value )
563     {
564         if ( btree.getType() != BTreeTypeEnum.IN_MEMORY )
565         {
566             ( ( PersistedLeaf<K, V> ) page ).setValue( pos, value );
567         }
568         else
569         {
570             ( ( InMemoryLeaf<K, V> ) page ).setValue( pos, value );
571         }
572     }
573 
574 
575     /**
576      * Set the page at a give position
577      *
578      * @param btree The B-tree to update
579      * @param page The page to update
580      * @param pos The position in the values array
581      * @param child the child page to inject
582      */
583     /* no qualifier*/static <K, V> void setPage( BTree<K, V> btree, Page<K, V> page, int pos, Page<K, V> child )
584     {
585         if ( btree.getType() != BTreeTypeEnum.IN_MEMORY )
586         {
587             ( ( PersistedNode<K, V> ) page ).setValue( pos, new PersistedPageHolder<K, V>( btree, child ) );
588         }
589         else
590         {
591             ( ( InMemoryNode<K, V> ) page ).setPageHolder( pos, new PageHolder<K, V>( btree, child ) );
592         }
593     }
594 
595 
596     //--------------------------------------------------------------------------------------------
597     // Update B-tree
598     //--------------------------------------------------------------------------------------------
599     /**
600      * Sets the KeySerializer into the B-tree
601      *
602      * @param btree The B-tree to update
603      * @param keySerializerFqcn the Key serializer FQCN to set
604      * @throws ClassNotFoundException If the key serializer class cannot be found
605      * @throws InstantiationException If the key serializer class cannot be instanciated
606      * @throws IllegalAccessException If the key serializer class cannot be accessed
607      * @throws NoSuchFieldException
608      * @throws SecurityException
609      * @throws IllegalArgumentException
610      */
611     /* no qualifier*/static <K, V> void setKeySerializer( BTree<K, V> btree, String keySerializerFqcn )
612         throws ClassNotFoundException, IllegalAccessException, InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException
613     {
614         Class<?> keySerializer = Class.forName( keySerializerFqcn );
615         @SuppressWarnings("unchecked")
616         ElementSerializer<K> instance = null;
617         try
618         {
619             instance = ( ElementSerializer<K> ) keySerializer.getDeclaredField( "INSTANCE" ).get( null );
620         }
621         catch( NoSuchFieldException e )
622         {
623             // ignore
624         }
625 
626         if ( instance == null )
627         {
628             instance = ( ElementSerializer<K> ) keySerializer.newInstance();
629         }
630 
631         btree.setKeySerializer( instance );
632     }
633 
634 
635     /**
636      * Sets the ValueSerializer into the B-tree
637      *
638      * @param btree The B-tree to update
639      * @param valueSerializerFqcn the Value serializer FQCN to set
640      * @throws ClassNotFoundException If the value serializer class cannot be found
641      * @throws InstantiationException If the value serializer class cannot be instanciated
642      * @throws IllegalAccessException If the value serializer class cannot be accessed
643      * @throws NoSuchFieldException
644      * @throws SecurityException
645      * @throws IllegalArgumentException
646      */
647     /* no qualifier*/static <K, V> void setValueSerializer( BTree<K, V> btree, String valueSerializerFqcn )
648         throws ClassNotFoundException, IllegalAccessException, InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException
649     {
650         Class<?> valueSerializer = Class.forName( valueSerializerFqcn );
651         @SuppressWarnings("unchecked")
652         ElementSerializer<V> instance = null;
653         try
654         {
655             instance = ( ElementSerializer<V> ) valueSerializer.getDeclaredField( "INSTANCE" ).get( null );
656         }
657         catch( NoSuchFieldException e )
658         {
659             // ignore
660         }
661         
662         if ( instance == null )
663         {
664             instance = ( ElementSerializer<V> ) valueSerializer.newInstance();
665         }
666         
667         btree.setValueSerializer( instance );
668     }
669 
670 
671     /**
672      * Set the new root page for this tree. Used for debug purpose only. The revision
673      * will always be 0;
674      *
675      * @param btree The B-tree to update
676      * @param root the new root page.
677      */
678     /* no qualifier*/static <K, V> void setRootPage( BTree<K, V> btree, Page<K, V> root )
679     {
680         ( ( AbstractBTree<K, V> ) btree ).setRootPage( root );
681     }
682 
683 
684     /**
685      * Return the B-tree root page
686      *
687      * @param btree The B-tree we want to root page from
688      * @return The root page
689      */
690     /* no qualifier */static <K, V> Page<K, V> getRootPage( BTree<K, V> btree )
691     {
692         return btree.getRootPage();
693     }
694 
695 
696     /**
697      * Update the B-tree number of elements
698      *
699      * @param btree The B-tree to update
700      * @param nbElems the nbElems to set
701      */
702     /* no qualifier */static <K, V> void setNbElems( BTree<K, V> btree, long nbElems )
703     {
704         ( ( AbstractBTree<K, V> ) btree ).setNbElems( nbElems );
705     }
706 
707 
708     /**
709      * Update the B-tree revision
710      *
711      * @param btree The B-tree to update
712      * @param revision the revision to set
713      */
714     /* no qualifier*/static <K, V> void setRevision( BTree<K, V> btree, long revision )
715     {
716         ( ( AbstractBTree<K, V> ) btree ).setRevision( revision );
717     }
718 
719 
720     /**
721      * Set the B-tree name
722      *
723      * @param btree The B-tree to update
724      * @param name the name to set
725      */
726     /* no qualifier */static <K, V> void setName( BTree<K, V> btree, String name )
727     {
728         btree.setName( name );
729     }
730 
731 
732     /**
733      * Set the maximum number of elements we can store in a page.
734      *
735      * @param btree The B-tree to update
736      * @param pageSize The requested page size
737      */
738     /* no qualifier */static <K, V> void setPageSize( BTree<K, V> btree, int pageSize )
739     {
740         btree.setPageSize( pageSize );
741     }
742 
743 
744     //--------------------------------------------------------------------------------------------
745     // Utility method
746     //--------------------------------------------------------------------------------------------
747     /**
748      * Includes the intermediate nodes in the path up to and including the right most leaf of the tree
749      *
750      * @param btree the B-tree
751      * @return a LinkedList of all the nodes and the final leaf
752      */
753     /* no qualifier*/static <K, V> LinkedList<ParentPos<K, V>> getPathToRightMostLeaf( BTree<K, V> btree )
754     {
755         LinkedList<ParentPos<K, V>> stack = new LinkedList<ParentPos<K, V>>();
756 
757         ParentPos<K, V> last = new ParentPos<K, V>( btree.getRootPage(), btree.getRootPage().getNbElems() );
758         stack.push( last );
759 
760         if ( btree.getRootPage().isLeaf() )
761         {
762             Page<K, V> leaf = btree.getRootPage();
763             ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) leaf ).getValue( last.pos );
764             last.valueCursor = valueHolder.getCursor();
765         }
766         else
767         {
768             Page<K, V> node = btree.getRootPage();
769 
770             while ( true )
771             {
772                 Page<K, V> p = ( ( AbstractPage<K, V> ) node ).getPage( node.getNbElems() );
773 
774                 last = new ParentPos<K, V>( p, p.getNbElems() );
775                 stack.push( last );
776 
777                 if ( p.isLeaf() )
778                 {
779                     Page<K, V> leaf = last.page;
780                     ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) leaf ).getValue( last.pos );
781                     last.valueCursor = valueHolder.getCursor();
782                     break;
783                 }
784             }
785         }
786 
787         return stack;
788     }
789 
790 
791     //--------------------------------------------------------------------------------------------
792     // Persisted B-tree methods
793     //--------------------------------------------------------------------------------------------
794     /**
795      * Set the rootPage offset of the B-tree
796      *
797      * @param btree The B-tree to update
798      * @param rootPageOffset The rootPageOffset to set
799      */
800     /* no qualifier*/static <K, V> void setRootPageOffset( BTree<K, V> btree, long rootPageOffset )
801     {
802         if ( btree instanceof PersistedBTree )
803         {
804             ( ( PersistedBTree<K, V> ) btree ).getBtreeHeader().setRootPageOffset( rootPageOffset );
805         }
806         else
807         {
808             throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
809         }
810     }
811 
812 
813     /**
814      * Set the RecordManager
815      *
816      * @param btree The B-tree to update
817      * @param recordManager The injected RecordManager
818      */
819     /* no qualifier*/static <K, V> void setRecordManager( BTree<K, V> btree, RecordManager recordManager )
820     {
821         if ( btree instanceof PersistedBTree )
822         {
823             ( ( PersistedBTree<K, V> ) btree ).setRecordManager( recordManager );
824         }
825         else
826         {
827             throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
828         }
829     }
830 
831 
832     /**
833      * Set the key at a give position
834      *
835      * @param btree The B-tree to update
836      * @param page The page to update
837      * @param pos The position of this key in the page
838      * @param buffer The byte[] containing the serialized key
839      */
840     /* no qualifier*/static <K, V> void setKey( BTree<K, V> btree, Page<K, V> page, int pos, byte[] buffer )
841     {
842         if ( btree instanceof PersistedBTree )
843         {
844             KeyHolder<K> keyHolder = new PersistedKeyHolder<K>( btree.getKeySerializer(), buffer );
845             ( ( AbstractPage<K, V> ) page ).setKey( pos, keyHolder );
846         }
847         else
848         {
849             throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
850         }
851     }
852 
853 
854     /**
855      * Includes the intermediate nodes in the path up to and including the left most leaf of the tree
856      *
857      * @param btree The B-tree to process
858      * @return a LinkedList of all the nodes and the final leaf
859      */
860     /* no qualifier*/static <K, V> LinkedList<ParentPos<K, V>> getPathToLeftMostLeaf( BTree<K, V> btree )
861     {
862         if ( btree instanceof PersistedBTree )
863         {
864             LinkedList<ParentPos<K, V>> stack = new LinkedList<ParentPos<K, V>>();
865 
866             ParentPos<K, V> first = new ParentPos<K, V>( btree.getRootPage(), 0 );
867             stack.push( first );
868 
869             if ( btree.getRootPage().isLeaf() )
870             {
871                 Page<K, V> leaf = btree.getRootPage();
872                 ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) leaf ).getValue( first.pos );
873                 first.valueCursor = valueHolder.getCursor();
874             }
875             else
876             {
877                 Page<K, V> node = btree.getRootPage();
878 
879                 while ( true )
880                 {
881                     Page<K, V> page = ( ( AbstractPage<K, V> ) node ).getPage( 0 );
882 
883                     first = new ParentPos<K, V>( page, 0 );
884                     stack.push( first );
885 
886                     if ( page.isLeaf() )
887                     {
888                         ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) page ).getValue( first.pos );
889                         first.valueCursor = valueHolder.getCursor();
890                         break;
891                     }
892                 }
893             }
894 
895             return stack;
896         }
897         else
898         {
899             throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
900         }
901     }
902 }