1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.mavibot.btree.memory;
21
22
23 import static org.apache.directory.mavibot.btree.memory.InternalUtil.setDupsContainer;
24
25 import java.io.IOException;
26 import java.lang.reflect.Array;
27 import java.util.LinkedList;
28
29 import org.apache.directory.mavibot.btree.Tuple;
30 import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
31 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
32
33
34
35
36
37
38
39
40
41
42
43 {
44
45 protected ElementHolder<V, K, V>[] values;
46
47
48
49
50
51
52
53
54 {
55 super( btree );
56 }
57
58
59
60
61
62
63
64
65
66 @SuppressWarnings("unchecked")
67
68
69 {
70 super( btree, revision, nbElems );
71
72 if ( btree.isAllowDuplicates() )
73 {
74 this.values = ( MultipleMemoryHolder<K, V>[] ) Array.newInstance( MultipleMemoryHolder.class,
75 nbElems );
76 }
77 else
78 {
79 this.values = ( MemoryHolder<K, V>[] ) Array.newInstance( MemoryHolder.class, nbElems );
80 }
81 }
82
83
84
85
86
87 public InsertResult<K, V> insert( long revision, K key, V value ) throws IOException
88 {
89
90 int pos = findPos( key );
91
92 if ( pos < 0 )
93 {
94
95
96 int index = -( pos + 1 );
97
98
99 InsertResult<K, V> result = replaceElement( revision, key, value, index );
100
101 return result;
102 }
103
104
105 if ( nbElems < btree.getPageSize() )
106 {
107
108
109 Page<K, V> modifiedPage = addElement( revision, key, value, pos );
110
111 InsertResult<K, V> result = new ModifyResult<K, V>( modifiedPage, null );
112 result.addCopiedPage( this );
113
114 return result;
115 }
116 else
117 {
118
119
120 InsertResult<K, V> result = addAndSplit( revision, key, value, pos );
121 result.addCopiedPage( this );
122
123 return result;
124 }
125 }
126
127
128
129
130
131 @SuppressWarnings("unchecked")
132 public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
133 throws IOException
134 {
135
136 if ( nbElems == 0 )
137 {
138
139 return NotPresentResult.NOT_PRESENT;
140 }
141
142
143 int pos = findPos( key );
144
145 if ( pos >= 0 )
146 {
147
148 return NotPresentResult.NOT_PRESENT;
149 }
150
151
152 Tuple<K, V> removedElement = null;
153
154
155 boolean keyRemoved = false;
156
157 int index = -( pos + 1 );
158
159 if ( btree.isAllowDuplicates() )
160 {
161 MultipleMemoryHolder<K, V> mvHolder = ( MultipleMemoryHolder<K, V> ) values[index];
162
163
164
165 V existingVal = mvHolder.getValue( btree );
166
167 if ( value == null )
168 {
169 removedElement = new Tuple<K, V>( keys[index], existingVal );
170 keyRemoved = true;
171 }
172 else
173 {
174 if ( mvHolder.isSingleValue() )
175 {
176 if ( btree.getValueSerializer().compare( value, existingVal ) == 0 )
177 {
178 removedElement = new Tuple<K, V>( keys[index], existingVal );
179 keyRemoved = true;
180 }
181 else
182
183 {
184 return NotPresentResult.NOT_PRESENT;
185 }
186 }
187 else
188 {
189 BTree<V, V> dups = ( BTree<V, V> ) existingVal;
190
191 if ( dups.hasKey( value ) )
192 {
193 dups.delete( value );
194
195 if ( dups.getNbElems() == 0 )
196 {
197 keyRemoved = true;
198 }
199 else
200 {
201 if ( dups.getNbElems() == 1 )
202 {
203
204 mvHolder.switchToSingleValMode();
205 }
206 }
207
208 removedElement = new Tuple<K, V>( keys[index], value );
209 }
210 else
211
212 {
213 return NotPresentResult.NOT_PRESENT;
214 }
215 }
216 }
217 }
218 else
219 {
220 V existing = values[index].getValue( btree );
221
222 if ( ( ( existing == null ) && ( value == null ) ) || ( value == null ) )
223 {
224 removedElement = new Tuple<K, V>( keys[index], existing );
225 keyRemoved = true;
226 }
227 else if ( btree.getValueSerializer().compare( value, existing ) == 0 )
228 {
229 removedElement = new Tuple<K, V>( keys[index], value );
230 keyRemoved = true;
231 }
232 else
233 {
234 return NotPresentResult.NOT_PRESENT;
235 }
236 }
237
238 Leaf<K, V> newLeaf = null;
239
240 if ( keyRemoved )
241 {
242 newLeaf = new Leaf<K, V>( btree, revision, nbElems - 1 );
243 }
244 else
245 {
246 newLeaf = new Leaf<K, V>( btree, revision, nbElems );
247 }
248
249
250 DeleteResult<K, V> defaultResult = new RemoveResult<K, V>( newLeaf, removedElement );
251
252
253 if ( parent == null )
254 {
255
256 copyAfterRemovingElement( keyRemoved, newLeaf, index );
257
258
259 defaultResult.addCopiedPage( this );
260
261 return defaultResult;
262 }
263 else if ( keyRemoved )
264 {
265
266
267 int halfSize = btree.getPageSize() / 2;
268
269 if ( nbElems == halfSize )
270 {
271
272
273
274
275 int siblingPos = selectSibling( ( Node<K, V> ) parent, parentPos );
276 Leaf<K, V> sibling = ( Leaf<K, V> ) ( ( ( Node<K, V> ) parent ).children[siblingPos].getValue( btree ) );
277
278 if ( sibling.getNbElems() == halfSize )
279 {
280
281 DeleteResult<K, V> result = mergeWithSibling( removedElement, revision, sibling,
282 ( siblingPos < parentPos ), index );
283
284 return result;
285 }
286 else
287 {
288
289 if ( siblingPos < parentPos )
290 {
291 DeleteResult<K, V> result = borrowFromLeft( removedElement, revision, sibling, index );
292
293 return result;
294 }
295 else
296 {
297
298 DeleteResult<K, V> result = borrowFromRight( removedElement, revision, sibling, index );
299
300 return result;
301 }
302 }
303 }
304 else
305 {
306
307
308
309
310 copyAfterRemovingElement( keyRemoved, newLeaf, index );
311
312
313 defaultResult.addCopiedPage( this );
314
315 return defaultResult;
316 }
317 }
318 else
319 {
320
321
322 System.arraycopy( keys, 0, newLeaf.keys, 0, nbElems );
323 System.arraycopy( values, 0, newLeaf.values, 0, nbElems );
324
325
326 defaultResult.addCopiedPage( this );
327
328 return defaultResult;
329 }
330 }
331
332
333
334
335
336
337
338
339
340
341
342
343 private DeleteResult<K, V> mergeWithSibling( Tuple<K, V> removedElement, long revision, Leaf<K, V> sibling,
344 boolean isLeft, int pos )
345 throws EndOfFileExceededException, IOException
346 {
347
348
349 Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, btree.getPageSize() - 1 );
350
351 if ( isLeft )
352 {
353
354
355 System.arraycopy( sibling.keys, 0, newLeaf.keys, 0, sibling.nbElems );
356 System.arraycopy( sibling.values, 0, newLeaf.values, 0, sibling.nbElems );
357
358
359 System.arraycopy( keys, 0, newLeaf.keys, sibling.nbElems, pos );
360 System.arraycopy( values, 0, newLeaf.values, sibling.nbElems, pos );
361
362
363 System.arraycopy( keys, pos + 1, newLeaf.keys, sibling.nbElems + pos, nbElems - pos - 1 );
364 System.arraycopy( values, pos + 1, newLeaf.values, sibling.nbElems + pos, nbElems - pos - 1 );
365 }
366 else
367 {
368
369
370 System.arraycopy( keys, 0, newLeaf.keys, 0, pos );
371 System.arraycopy( values, 0, newLeaf.values, 0, pos );
372
373
374 System.arraycopy( keys, pos + 1, newLeaf.keys, pos, nbElems - pos - 1 );
375 System.arraycopy( values, pos + 1, newLeaf.values, pos, nbElems - pos - 1 );
376
377
378 System.arraycopy( sibling.keys, 0, newLeaf.keys, nbElems - 1, sibling.nbElems );
379 System.arraycopy( sibling.values, 0, newLeaf.values, nbElems - 1, sibling.nbElems );
380 }
381
382
383 DeleteResult<K, V> result = new MergedWithSiblingResult<K, V>( newLeaf,
384 removedElement );
385
386 result.addCopiedPage( this );
387 result.addCopiedPage( sibling );
388
389 return result;
390 }
391
392
393
394
395
396
397
398
399
400
401
402
403
404 private DeleteResult<K, V> borrowFromLeft( Tuple<K, V> removedElement, long revision, Leaf<K, V> sibling, int pos )
405 throws IOException
406 {
407
408 K siblingKey = sibling.keys[sibling.getNbElems() - 1];
409 ElementHolder<V, K, V> siblingValue = sibling.values[sibling.getNbElems() - 1];
410
411
412 Leaf<K, V> newSibling = ( Leaf<K, V> ) sibling.copy( revision, sibling.getNbElems() - 1 );
413
414
415
416 Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems );
417
418
419 newLeaf.keys[0] = siblingKey;
420 newLeaf.values[0] = siblingValue;
421
422
423 System.arraycopy( keys, 0, newLeaf.keys, 1, pos );
424 System.arraycopy( values, 0, newLeaf.values, 1, pos );
425
426
427 System.arraycopy( keys, pos + 1, newLeaf.keys, pos + 1, keys.length - pos - 1 );
428 System.arraycopy( values, pos + 1, newLeaf.values, pos + 1, values.length - pos - 1 );
429
430 DeleteResult<K, V> result = new BorrowedFromLeftResult<K, V>( newLeaf, newSibling, removedElement );
431
432
433 result.addCopiedPage( this );
434 result.addCopiedPage( sibling );
435
436 return result;
437 }
438
439
440
441
442
443
444
445
446
447
448
449
450
451 private DeleteResult<K, V> borrowFromRight( Tuple<K, V> removedElement, long revision, Leaf<K, V> sibling, int pos )
452 throws IOException
453 {
454
455 K siblingKey = sibling.keys[0];
456 ElementHolder<V, K, V> siblingHolder = sibling.values[0];
457
458
459 Leaf<K, V> newSibling = new Leaf<K, V>( btree, revision, sibling.getNbElems() - 1 );
460
461
462 System.arraycopy( sibling.keys, 1, newSibling.keys, 0, sibling.nbElems - 1 );
463 System.arraycopy( sibling.values, 1, newSibling.values, 0, sibling.nbElems - 1 );
464
465
466
467 Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems );
468
469
470 newLeaf.keys[nbElems - 1] = siblingKey;
471 newLeaf.values[nbElems - 1] = siblingHolder;
472
473
474 System.arraycopy( keys, 0, newLeaf.keys, 0, pos );
475 System.arraycopy( values, 0, newLeaf.values, 0, pos );
476
477
478 System.arraycopy( keys, pos + 1, newLeaf.keys, pos, keys.length - pos - 1 );
479 System.arraycopy( values, pos + 1, newLeaf.values, pos, values.length - pos - 1 );
480
481 DeleteResult<K, V> result = new BorrowedFromRightResult<K, V>( newLeaf, newSibling, removedElement );
482
483
484 result.addCopiedPage( this );
485 result.addCopiedPage( sibling );
486
487 return result;
488 }
489
490
491
492
493
494
495
496
497
498
499 private void copyAfterRemovingElement( boolean keyRemoved, Leaf<K, V> newLeaf, int pos ) throws IOException
500 {
501 if ( keyRemoved )
502 {
503
504
505 if ( nbElems == 1 )
506 {
507 return;
508 }
509
510
511 System.arraycopy( keys, 0, newLeaf.keys, 0, pos );
512 System.arraycopy( values, 0, newLeaf.values, 0, pos );
513
514
515 System.arraycopy( keys, pos + 1, newLeaf.keys, pos, keys.length - pos - 1 );
516 System.arraycopy( values, pos + 1, newLeaf.values, pos, values.length - pos - 1 );
517 }
518 else
519
520 {
521 System.arraycopy( keys, 0, newLeaf.keys, 0, nbElems );
522 System.arraycopy( values, 0, newLeaf.values, 0, nbElems );
523 }
524 }
525
526
527
528
529
530 public V get( K key ) throws KeyNotFoundException, IOException
531 {
532 int pos = findPos( key );
533
534 if ( pos < 0 )
535 {
536 if ( btree.isAllowDuplicates() )
537 {
538 MultipleMemoryHolder<K, V> mvHolder = ( MultipleMemoryHolder<K, V> ) values[-( pos + 1 )];
539 if ( mvHolder.isSingleValue() )
540 {
541 return mvHolder.getValue( btree );
542 }
543 else
544 {
545
546 BTree<V, V> dupTree = ( BTree<V, V> ) mvHolder.getValue( btree );
547 return dupTree.rootPage.getLeftMostKey();
548 }
549 }
550
551 V v = values[-( pos + 1 )].getValue( btree );
552
553 return v;
554 }
555 else
556 {
557 throw KEY_NOT_FOUND_EXCEPTION;
558 }
559 }
560
561
562
563
564
565 @Override
566 public DuplicateKeyVal<V> getValues( K key ) throws KeyNotFoundException, IOException, IllegalArgumentException
567 {
568 if ( !btree.isAllowDuplicates() )
569 {
570 throw new IllegalArgumentException( "Duplicates are not allowed in this tree" );
571 }
572
573 int pos = findPos( key );
574
575 if ( pos < 0 )
576 {
577 MultipleMemoryHolder<K, V> mvHolder = ( MultipleMemoryHolder<K, V> ) values[-( pos + 1 )];
578
579 if ( mvHolder.isSingleValue() )
580 {
581 return new DuplicateKeyVal<V>( mvHolder.getValue( btree ) );
582 }
583
584 return new DuplicateKeyVal<V>( ( BTree<V, V> ) mvHolder.getValue( btree ) );
585 }
586 else
587 {
588 throw KEY_NOT_FOUND_EXCEPTION;
589 }
590 }
591
592
593
594
595
596 public boolean hasKey( K key )
597 {
598 int pos = findPos( key );
599
600 if ( pos < 0 )
601 {
602 return true;
603 }
604
605 return false;
606 }
607
608
609 @Override
610 public boolean contains( K key, V value ) throws IOException
611 {
612 int pos = findPos( key );
613
614 if ( pos < 0 )
615 {
616 if ( btree.isAllowDuplicates() )
617 {
618 MultipleMemoryHolder<K, V> mvHolder = ( MultipleMemoryHolder<K, V> ) values[-( pos + 1 )];
619 if ( mvHolder.isSingleValue() )
620 {
621 return ( btree.getValueSerializer().compare( value, mvHolder.getValue( btree ) ) == 0 );
622 }
623 else
624 {
625
626 BTree<V, V> dupTree = ( ( BTree<V, V> ) mvHolder.getValue( btree ) );
627 return dupTree.hasKey( value );
628 }
629 }
630 else
631 {
632 V v = values[-( pos + 1 )].getValue( btree );
633 return ( btree.getValueSerializer().compare( value, v ) == 0 );
634 }
635 }
636 else
637 {
638 return false;
639 }
640 }
641
642
643
644
645
646 public ElementHolder<V, K, V> getValue( int pos )
647 {
648 if ( pos < nbElems )
649 {
650 return values[pos];
651 }
652 else
653 {
654 return null;
655 }
656 }
657
658
659
660
661
662
663
664 public void setValue( int pos, ElementHolder<V, K, V> value )
665 {
666 values[pos] = value;
667 }
668
669
670
671
672
673 public CursorImpl<K, V> browse( K key, Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
674 {
675 int pos = findPos( key );
676 CursorImpl<K, V> cursor = null;
677
678 if ( pos < 0 )
679 {
680 int index = -( pos + 1 );
681
682
683 ParentPos<K, V> parentPos = new ParentPos<K, V>( this, index );
684 setDupsContainer( parentPos, btree );
685 stack.push( parentPos );
686
687 cursor = new CursorImpl<K, V>( btree, transaction, stack );
688 }
689 else
690 {
691
692 if ( pos < nbElems )
693 {
694 ParentPos<K, V> parentPos = new ParentPos<K, V>( this, pos );
695 setDupsContainer( parentPos, btree );
696 stack.push( parentPos );
697
698 cursor = new CursorImpl<K, V>( btree, transaction, stack );
699 }
700 else
701 {
702
703 stack.push( new ParentPos<K, V>( null, -1 ) );
704
705 return new CursorImpl<K, V>( btree, transaction, stack );
706 }
707 }
708
709 return cursor;
710 }
711
712
713
714
715
716 public CursorImpl<K, V> browse( Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
717 {
718 int pos = 0;
719 CursorImpl<K, V> cursor = null;
720
721 if ( nbElems == 0 )
722 {
723
724 stack.push( new ParentPos<K, V>( null, -1 ) );
725
726 return new CursorImpl<K, V>( btree, transaction, stack );
727 }
728 else
729 {
730
731 ParentPos<K, V> parentPos = new ParentPos<K, V>( this, pos );
732
733 setDupsContainer( parentPos, btree );
734
735 stack.push( parentPos );
736
737 cursor = new CursorImpl<K, V>( btree, transaction, stack );
738 }
739
740 return cursor;
741 }
742
743
744
745
746
747
748
749
750
751 private Page<K, V> copy( long revision, int nbElems )
752 {
753 Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems );
754
755
756 System.arraycopy( keys, 0, newLeaf.keys, 0, nbElems );
757 System.arraycopy( values, 0, newLeaf.values, 0, nbElems );
758
759 return newLeaf;
760 }
761
762
763
764
765
766
767
768
769
770
771
772
773 private InsertResult<K, V> replaceElement( long revision, K key, V value, int pos )
774 throws IOException
775 {
776 Leaf<K, V> newLeaf = this;
777
778 if ( this.revision != revision )
779 {
780
781 newLeaf = ( Leaf<K, V> ) copy( revision, nbElems );
782 }
783
784 V oldValue = null;
785
786 if ( btree.isAllowDuplicates() )
787 {
788 MultipleMemoryHolder<K, V> mvHolder = ( MultipleMemoryHolder<K, V> ) newLeaf.values[pos];
789
790 if ( mvHolder.isSingleValue() )
791 {
792 V singleVal = mvHolder.getValue( btree );
793
794
795 if ( btree.getValueSerializer().compare( value, singleVal ) == 0 )
796 {
797 oldValue = value;
798 }
799 else
800
801 {
802 mvHolder.createAndSwitchToSubTree();
803 }
804 }
805
806
807
808 if ( oldValue == null )
809 {
810 BTree<V, V> dupValues = ( BTree<V, V> ) mvHolder.getValue( btree );
811
812
813 if ( !dupValues.hasKey( value ) )
814 {
815 dupValues.insert( value, null, 0 );
816 }
817 else
818 {
819 oldValue = value;
820 }
821 }
822 }
823 else
824 {
825
826 oldValue = newLeaf.values[pos].getValue( btree );
827 newLeaf.values[pos] = btree.createValueHolder( value );
828 }
829
830
831 InsertResult<K, V> result = new ModifyResult<K, V>( newLeaf, oldValue );
832 result.addCopiedPage( this );
833
834 return result;
835 }
836
837
838
839
840
841
842
843
844
845
846
847
848 private Page<K, V> addElement( long revision, K key, V value, int pos )
849 {
850
851 Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems + 1 );
852
853
854
855 ElementHolder valueHolder = null;
856
857 if ( btree.isAllowDuplicates() )
858 {
859 valueHolder = new MultipleMemoryHolder<K, V>( btree, value );
860 }
861 else
862 {
863 valueHolder = new MemoryHolder<K, V>( btree, value );
864 }
865
866
867
868
869 if ( nbElems == 0 )
870 {
871 newLeaf.keys[0] = key;
872
873 newLeaf.values[0] = valueHolder;
874 }
875 else
876 {
877
878 System.arraycopy( keys, 0, newLeaf.keys, 0, pos );
879 System.arraycopy( values, 0, newLeaf.values, 0, pos );
880
881
882 newLeaf.keys[pos] = key;
883 newLeaf.values[pos] = valueHolder;
884
885
886 System.arraycopy( keys, pos, newLeaf.keys, pos + 1, keys.length - pos );
887 System.arraycopy( values, pos, newLeaf.values, pos + 1, values.length - pos );
888 }
889
890 return newLeaf;
891 }
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909 private InsertResult<K, V> addAndSplit( long revision, K key, V value, int pos )
910 {
911 int middle = btree.getPageSize() >> 1;
912 Leaf<K, V> leftLeaf = null;
913 Leaf<K, V> rightLeaf = null;
914 ElementHolder<V, K, V> valueHolder = btree.createValueHolder( value );
915
916
917 if ( pos <= middle )
918 {
919
920 leftLeaf = new Leaf<K, V>( btree, revision, middle + 1 );
921
922
923 System.arraycopy( keys, 0, leftLeaf.keys, 0, pos );
924 System.arraycopy( values, 0, leftLeaf.values, 0, pos );
925
926
927 leftLeaf.keys[pos] = key;
928 leftLeaf.values[pos] = valueHolder;
929
930
931 System.arraycopy( keys, pos, leftLeaf.keys, pos + 1, middle - pos );
932 System.arraycopy( values, pos, leftLeaf.values, pos + 1, middle - pos );
933
934
935 rightLeaf = new Leaf<K, V>( btree, revision, middle );
936
937
938 System.arraycopy( keys, middle, rightLeaf.keys, 0, middle );
939 System.arraycopy( values, middle, rightLeaf.values, 0, middle );
940 }
941 else
942 {
943
944 leftLeaf = new Leaf<K, V>( btree, revision, middle );
945
946
947 System.arraycopy( keys, 0, leftLeaf.keys, 0, middle );
948 System.arraycopy( values, 0, leftLeaf.values, 0, middle );
949
950
951 rightLeaf = new Leaf<K, V>( btree, revision, middle + 1 );
952
953 int rightPos = pos - middle;
954
955
956 System.arraycopy( keys, middle, rightLeaf.keys, 0, rightPos );
957 System.arraycopy( values, middle, rightLeaf.values, 0, rightPos );
958
959
960 rightLeaf.keys[rightPos] = key;
961 rightLeaf.values[rightPos] = valueHolder;
962
963
964 System.arraycopy( keys, pos, rightLeaf.keys, rightPos + 1, nbElems - pos );
965 System.arraycopy( values, pos, rightLeaf.values, rightPos + 1, nbElems - pos );
966 }
967
968
969 K pivot = rightLeaf.keys[0];
970
971
972 InsertResult<K, V> result = new SplitResult<K, V>( pivot, leftLeaf, rightLeaf );
973
974 return result;
975 }
976
977
978
979
980
981 public K getLeftMostKey()
982 {
983 return keys[0];
984 }
985
986
987
988
989
990 public K getRightMostKey()
991 {
992 return keys[nbElems - 1];
993 }
994
995
996
997
998
999 public Tuple<K, V> findLeftMost() throws IOException
1000 {
1001 V val = null;
1002
1003 if ( btree.isAllowDuplicates() )
1004 {
1005 BTree<V, V> dupTree = ( BTree<V, V> ) values[0].getValue( btree );
1006 val = dupTree.rootPage.getLeftMostKey();
1007 }
1008 else
1009 {
1010 val = values[0].getValue( btree );
1011 }
1012
1013 return new Tuple<K, V>( keys[0], val );
1014 }
1015
1016
1017
1018
1019
1020 public Tuple<K, V> findRightMost() throws EndOfFileExceededException, IOException
1021 {
1022 V val = null;
1023
1024 if ( btree.isAllowDuplicates() )
1025 {
1026 BTree<V, V> dupTree = ( BTree<V, V> ) values[nbElems - 1].getValue( btree );
1027 val = dupTree.rootPage.getRightMostKey();
1028 }
1029 else
1030 {
1031 val = values[nbElems - 1].getValue( btree );
1032 }
1033
1034 return new Tuple<K, V>( keys[nbElems - 1], val );
1035 }
1036
1037
1038
1039
1040
1041 public String toString()
1042 {
1043 StringBuilder sb = new StringBuilder();
1044
1045 sb.append( "Leaf[" );
1046 sb.append( super.toString() );
1047
1048 sb.append( "] -> {" );
1049
1050 if ( nbElems > 0 )
1051 {
1052 boolean isFirst = true;
1053
1054 for ( int i = 0; i < nbElems; i++ )
1055 {
1056 if ( isFirst )
1057 {
1058 isFirst = false;
1059 }
1060 else
1061 {
1062 sb.append( ", " );
1063 }
1064
1065 sb.append( "<" ).append( keys[i] ).append( "," ).append( values[i] ).append( ">" );
1066 }
1067 }
1068
1069 sb.append( "}" );
1070
1071 return sb.toString();
1072 }
1073
1074
1075
1076
1077
1078 public String dumpPage( String tabs )
1079 {
1080 StringBuilder sb = new StringBuilder();
1081
1082 sb.append( tabs );
1083
1084 if ( nbElems > 0 )
1085 {
1086 boolean isFirst = true;
1087
1088 for ( int i = 0; i < nbElems; i++ )
1089 {
1090 if ( isFirst )
1091 {
1092 isFirst = false;
1093 }
1094 else
1095 {
1096 sb.append( ", " );
1097 }
1098
1099 sb.append( "<" ).append( keys[i] ).append( "," ).append( values[i] ).append( ">" );
1100 }
1101 }
1102
1103 sb.append( "\n" );
1104
1105 return sb.toString();
1106 }
1107 }