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;
21
22
23 import java.io.IOException;
24 import java.lang.reflect.Array;
25 import java.util.LinkedList;
26 import java.util.List;
27
28 import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
29 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
30
31
32
33
34
35
36
37
38
39
40
41
42 {
43
44 protected ElementHolder<Page<K, V>, K, V>[] children;
45
46
47
48
49
50
51
52
53
54
55
56 @SuppressWarnings("unchecked")
57
58 {
59 super( btree, revision, nbElems );
60
61
62 children = ( ElementHolder<Page<K, V>, K, V>[] ) Array.newInstance( ElementHolder.class, nbElems + 1 );
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76
77 @SuppressWarnings("unchecked")
78
79 {
80 super( btree, revision, 1 );
81
82
83 if ( btree.isManaged() )
84 {
85 children = ( ReferenceHolder<Page<K, V>, K, V>[] ) Array.newInstance( ReferenceHolder.class,
86 btree.getPageSize() + 1 );
87 }
88 else
89 {
90 children = ( MemoryHolder[] ) Array.newInstance( MemoryHolder.class,
91 btree.getPageSize() + 1 );
92 }
93
94 children[0] = btree.createHolder( leftPage );
95 children[1] = btree.createHolder( rightPage );
96
97
98
99
100 Class<?> keyType = btree.getKeyType();
101 keys = ( K[] ) Array.newInstance( keyType, btree.getPageSize() );
102
103 keys[0] = key;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118 @SuppressWarnings("unchecked")
119
120 ElementHolder<Page<K, V>, K, V> rightPage )
121 {
122 super( btree, revision, 1 );
123
124
125 children = ( ReferenceHolder<Page<K, V>, K, V>[] ) Array.newInstance( ReferenceHolder.class,
126 btree.getPageSize() + 1 );
127
128 children[0] = leftPage;
129 children[1] = rightPage;
130
131
132
133
134 Class<?> keyType = btree.getKeyType();
135 keys = ( K[] ) Array.newInstance( keyType, btree.getPageSize() );
136
137 keys[0] = key;
138 }
139
140
141
142
143
144 public InsertResult<K, V> insert( long revision, K key, V value ) throws IOException
145 {
146
147 int pos = findPos( key );
148
149 if ( pos < 0 )
150 {
151
152
153 pos = -( pos++ );
154 }
155
156
157 Page<K, V> child = children[pos].getValue( btree );
158
159
160 InsertResult<K, V> result = child.insert( revision, key, value );
161
162
163
164 if ( result instanceof ModifyResult )
165 {
166
167 return replaceChild( revision, ( ModifyResult<K, V> ) result, pos );
168 }
169 else
170 {
171
172
173 SplitResult<K, V> splitResult = ( SplitResult<K, V> ) result;
174 K pivot = splitResult.getPivot();
175 Page<K, V> leftPage = splitResult.getLeftPage();
176 Page<K, V> rightPage = splitResult.getRightPage();
177
178
179
180
181 if ( nbElems == btree.getPageSize() )
182 {
183
184 result = addAndSplit( splitResult.getCopiedPages(), revision, pivot, leftPage, rightPage, pos );
185 }
186 else
187 {
188
189 result = insertChild( splitResult.getCopiedPages(), revision, pivot, leftPage, rightPage, pos );
190 }
191
192 return result;
193 }
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207
208 private RemoveResult<K, V> handleRemoveResult( RemoveResult<K, V> removeResult, int index, int pos, boolean found )
209 throws IOException
210 {
211
212
213
214 Node<K, V> newPage = copy( revision );
215
216 Page<K, V> modifiedPage = removeResult.getModifiedPage();
217
218 if ( found )
219 {
220 newPage.children[index + 1] = createHolder( modifiedPage );
221 }
222 else
223 {
224 newPage.children[index] = createHolder( modifiedPage );
225 }
226
227 if ( pos < 0 )
228 {
229 newPage.keys[index] = removeResult.getModifiedPage().getLeftMostKey();
230 }
231
232
233 removeResult.setModifiedPage( newPage );
234 removeResult.addCopiedPage( this );
235
236 return removeResult;
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250 private RemoveResult<K, V> handleRootRemove( MergedWithSiblingResult<K, V> mergedResult, int pos, boolean found )
251 throws IOException
252 {
253 RemoveResult<K, V> removeResult = null;
254
255
256
257 if ( nbElems == 1 )
258 {
259 removeResult = new RemoveResult<K, V>( mergedResult.getCopiedPages(), mergedResult.getModifiedPage(),
260 mergedResult.getRemovedElement() );
261
262 removeResult.addCopiedPage( this );
263 }
264 else
265 {
266
267 removeResult = removeKey( mergedResult, revision, pos );
268 }
269
270 return removeResult;
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284
285 private DeleteResult<K, V> borrowFromRight( long revision, MergedWithSiblingResult<K, V> mergedResult,
286 Node<K, V> sibling, int pos ) throws IOException
287 {
288
289 Node<K, V> newSibling = new Node<K, V>( btree, revision, sibling.getNbElems() - 1 );
290
291 K siblingKey = sibling.children[0].getValue( btree ).getLeftMostKey();
292
293
294 System.arraycopy( sibling.keys, 1, newSibling.keys, 0, newSibling.getNbElems() );
295 System.arraycopy( sibling.children, 1, newSibling.children, 0, newSibling.getNbElems() + 1 );
296
297
298
299 Node<K, V> newNode = new Node<K, V>( btree, revision, nbElems );
300
301
302 int index = Math.abs( pos );
303
304
305 newNode.keys[nbElems - 1] = siblingKey;
306 newNode.children[nbElems] = sibling.children[0];
307
308 if ( index < 2 )
309 {
310
311 System.arraycopy( keys, 1, newNode.keys, 0, nbElems - 1 );
312
313
314 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
315 newNode.children[0] = createHolder( modifiedPage );
316
317
318 System.arraycopy( children, 2, newNode.children, 1, nbElems - 1 );
319 }
320 else
321 {
322 if ( index > 2 )
323 {
324
325 System.arraycopy( keys, 0, newNode.keys, 0, index - 2 );
326 }
327
328
329 newNode.keys[index - 2] = mergedResult.getModifiedPage().getLeftMostKey();
330
331 if ( index < nbElems )
332 {
333
334 System.arraycopy( keys, index, newNode.keys, index - 1, nbElems - index );
335
336
337 System.arraycopy( children, index + 1, newNode.children, index, nbElems - index );
338 }
339
340
341 System.arraycopy( children, 0, newNode.children, 0, index - 1 );
342
343
344 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
345 newNode.children[index - 1] = createHolder( modifiedPage );
346 }
347
348
349 DeleteResult<K, V> result = new BorrowedFromRightResult<K, V>( mergedResult.getCopiedPages(), newNode,
350 newSibling, mergedResult.getRemovedElement() );
351
352 result.addCopiedPage( this );
353 result.addCopiedPage( sibling );
354
355 return result;
356 }
357
358
359
360
361
362
363
364
365
366
367
368
369
370 private DeleteResult<K, V> borrowFromLeft( long revision, MergedWithSiblingResult<K, V> mergedResult,
371 Node<K, V> sibling, int pos ) throws IOException
372 {
373
374 Page<K, V> siblingChild = sibling.children[sibling.nbElems].getValue( btree );
375
376
377 Node<K, V> newSibling = new Node<K, V>( btree, revision, sibling.getNbElems() - 1 );
378
379
380 System.arraycopy( sibling.keys, 0, newSibling.keys, 0, newSibling.getNbElems() );
381 System.arraycopy( sibling.children, 0, newSibling.children, 0, newSibling.getNbElems() + 1 );
382
383
384
385 Node<K, V> newNode = new Node<K, V>( btree, revision, nbElems );
386
387
388 newNode.children[0] = createHolder( siblingChild );
389
390 int index = Math.abs( pos );
391
392 if ( index < 2 )
393 {
394 newNode.keys[0] = mergedResult.getModifiedPage().getLeftMostKey();
395 System.arraycopy( keys, 1, newNode.keys, 1, nbElems - 1 );
396
397 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
398 newNode.children[1] = createHolder( modifiedPage );
399 System.arraycopy( children, 2, newNode.children, 2, nbElems - 1 );
400 }
401 else
402 {
403
404 newNode.keys[0] = children[0].getValue( btree ).getLeftMostKey();
405
406 if ( index > 2 )
407 {
408
409 System.arraycopy( keys, 0, newNode.keys, 1, index - 2 );
410 }
411
412
413 newNode.keys[index - 1] = mergedResult.getModifiedPage().getLeftMostKey();
414
415 if ( index < nbElems )
416 {
417
418 System.arraycopy( keys, index, newNode.keys, index, nbElems - index );
419
420
421 System.arraycopy( children, index + 1, newNode.children, index + 1, nbElems - index );
422 }
423
424
425 System.arraycopy( children, 0, newNode.children, 1, index - 1 );
426
427
428 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
429 newNode.children[index] = createHolder( modifiedPage );
430 }
431
432
433 DeleteResult<K, V> result = new BorrowedFromLeftResult<K, V>( mergedResult.getCopiedPages(), newNode,
434 newSibling,
435 mergedResult.getRemovedElement() );
436
437 result.addCopiedPage( this );
438 result.addCopiedPage( sibling );
439
440 return result;
441 }
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456 private DeleteResult<K, V> mergeWithSibling( long revision, MergedWithSiblingResult<K, V> mergedResult,
457 Node<K, V> sibling, boolean isLeft, int pos ) throws IOException
458 {
459
460
461 Node<K, V> newNode = new Node<K, V>( btree, revision, btree.getPageSize() );
462 Tuple<K, V> removedElement = mergedResult.getRemovedElement();
463 int half = btree.getPageSize() / 2;
464 int index = Math.abs( pos );
465
466 if ( isLeft )
467 {
468
469 System.arraycopy( sibling.keys, 0, newNode.keys, 0, half );
470 System.arraycopy( sibling.children, 0, newNode.children, 0, half + 1 );
471
472
473 if ( index < 2 )
474 {
475 newNode.keys[half] = mergedResult.getModifiedPage().getLeftMostKey();
476 System.arraycopy( keys, 1, newNode.keys, half + 1, half - 1 );
477
478 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
479 newNode.children[half + 1] = createHolder( modifiedPage );
480 System.arraycopy( children, 2, newNode.children, half + 2, half - 1 );
481 }
482 else
483 {
484
485
486 newNode.keys[half] = children[0].getValue( btree ).getLeftMostKey();
487
488 if ( index > 2 )
489 {
490 System.arraycopy( keys, 0, newNode.keys, half + 1, index - 2 );
491 }
492
493
494 newNode.keys[half + index - 1] = mergedResult.getModifiedPage().getLeftMostKey();
495
496 if ( index < half )
497 {
498 System.arraycopy( keys, index, newNode.keys, half + index, half - index );
499 System.arraycopy( children, index + 1, newNode.children, half + index + 1, half - index );
500 }
501
502
503 System.arraycopy( children, 0, newNode.children, half + 1, index - 1 );
504
505
506 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
507 newNode.children[half + index] = createHolder( modifiedPage );
508 }
509 }
510 else
511 {
512
513 if ( index < 2 )
514 {
515
516 System.arraycopy( keys, 1, newNode.keys, 0, half - 1 );
517
518
519 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
520 newNode.children[0] = createHolder( modifiedPage );
521
522
523 System.arraycopy( children, 2, newNode.children, 1, half - 1 );
524 }
525 else
526 {
527
528 if ( index > 2 )
529 {
530
531 System.arraycopy( keys, 0, newNode.keys, 0, index - 2 );
532 }
533
534
535 System.arraycopy( children, 0, newNode.children, 0, index - 1 );
536
537
538 newNode.keys[index - 2] = mergedResult.getModifiedPage().getLeftMostKey();
539
540
541 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
542 newNode.children[index - 1] = createHolder( modifiedPage );
543
544
545 if ( index < half )
546 {
547 System.arraycopy( keys, index, newNode.keys, index - 1, half - index );
548
549
550 System.arraycopy( children, index + 1, newNode.children, index, half - index );
551 }
552 }
553
554
555 newNode.keys[half - 1] = sibling.findLeftMost().getKey();
556
557
558 System.arraycopy( sibling.keys, 0, newNode.keys, half, half );
559
560
561 System.arraycopy( sibling.children, 0, newNode.children, half, half + 1 );
562 }
563
564
565 DeleteResult<K, V> result = new MergedWithSiblingResult<K, V>( mergedResult.getCopiedPages(), newNode,
566 removedElement );
567
568 result.addCopiedPage( this );
569 result.addCopiedPage( sibling );
570
571 return result;
572 }
573
574
575
576
577
578 public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
579 throws IOException
580 {
581
582
583 int pos = findPos( key );
584 boolean found = pos < 0;
585 int index = pos;
586 Page<K, V> child = null;
587 DeleteResult<K, V> deleteResult = null;
588
589 if ( found )
590 {
591 index = -( pos + 1 );
592 child = children[-pos].getValue( btree );
593 deleteResult = child.delete( revision, key, value, this, -pos );
594 }
595 else
596 {
597 child = children[pos].getValue( btree );
598 deleteResult = child.delete( revision, key, value, this, pos );
599 }
600
601
602 if ( deleteResult instanceof NotPresentResult )
603 {
604
605 return deleteResult;
606 }
607
608
609 if ( deleteResult instanceof RemoveResult )
610 {
611 RemoveResult<K, V> removeResult = handleRemoveResult( ( RemoveResult<K, V> ) deleteResult, index, pos,
612 found );
613
614 return removeResult;
615 }
616
617
618
619 if ( deleteResult instanceof BorrowedFromSiblingResult )
620 {
621 RemoveResult<K, V> removeResult = handleBorrowedResult( ( BorrowedFromSiblingResult<K, V> ) deleteResult,
622 pos );
623
624 return removeResult;
625 }
626
627
628
629 if ( deleteResult instanceof MergedWithSiblingResult )
630 {
631 MergedWithSiblingResult<K, V> mergedResult = ( MergedWithSiblingResult<K, V> ) deleteResult;
632
633
634 if ( parent == null )
635 {
636 RemoveResult<K, V> result = handleRootRemove( mergedResult, pos, found );
637
638 return result;
639 }
640
641
642 int halfSize = btree.getPageSize() / 2;
643
644 if ( nbElems > halfSize )
645 {
646
647
648
649
650 RemoveResult<K, V> result = removeKey( mergedResult, revision, pos );
651
652 return result;
653 }
654 else
655 {
656
657
658
659 int siblingPos = selectSibling( ( Node<K, V> ) parent, parentPos );
660
661 Node<K, V> sibling = ( Node<K, V> ) ( ( ( Node<K, V> ) parent ).children[siblingPos].getValue( btree ) );
662
663 if ( sibling.getNbElems() > halfSize )
664 {
665
666
667 if ( siblingPos < parentPos )
668 {
669 DeleteResult<K, V> result = borrowFromLeft( revision, mergedResult, sibling, pos );
670
671 return result;
672 }
673 else
674 {
675
676 DeleteResult<K, V> result = borrowFromRight( revision, mergedResult, sibling, pos );
677
678 return result;
679 }
680 }
681 else
682 {
683
684 DeleteResult<K, V> result = mergeWithSibling( revision, mergedResult, sibling,
685 ( siblingPos < parentPos ), pos );
686
687 return result;
688 }
689 }
690 }
691
692
693 return null;
694 }
695
696
697
698
699
700
701
702
703
704
705 private RemoveResult<K, V> handleBorrowedResult( BorrowedFromSiblingResult<K, V> borrowedResult, int pos )
706 throws IOException
707 {
708 Page<K, V> modifiedPage = borrowedResult.getModifiedPage();
709 Page<K, V> modifiedSibling = borrowedResult.getModifiedSibling();
710
711 Node<K, V> newPage = copy( revision );
712
713 if ( pos < 0 )
714 {
715 pos = -( pos + 1 );
716
717 if ( borrowedResult.isFromRight() )
718 {
719
720 newPage.keys[pos] = modifiedPage.findLeftMost().getKey();
721 newPage.keys[pos + 1] = modifiedSibling.findLeftMost().getKey();
722
723
724 newPage.children[pos + 1] = createHolder( modifiedPage );
725 newPage.children[pos + 2] = createHolder( modifiedSibling );
726 }
727 else
728 {
729
730 newPage.keys[pos] = modifiedPage.findLeftMost().getKey();
731
732
733 newPage.children[pos] = createHolder( modifiedSibling );
734 newPage.children[pos + 1] = createHolder( modifiedPage );
735 }
736 }
737 else
738 {
739 if ( borrowedResult.isFromRight() )
740 {
741
742 newPage.keys[pos] = modifiedSibling.findLeftMost().getKey();
743
744
745 newPage.children[pos] = createHolder( modifiedPage );
746 newPage.children[pos + 1] = createHolder( modifiedSibling );
747 }
748 else
749 {
750
751 newPage.keys[pos - 1] = modifiedPage.findLeftMost().getKey();
752
753
754 newPage.children[pos - 1] = createHolder( modifiedSibling );
755 newPage.children[pos] = createHolder( modifiedPage );
756 }
757 }
758
759
760 RemoveResult<K, V> removeResult = new RemoveResult<K, V>( borrowedResult.getCopiedPages(), newPage,
761 borrowedResult.getRemovedElement() );
762
763 removeResult.addCopiedPage( this );
764
765 return removeResult;
766 }
767
768
769
770
771
772
773
774
775
776
777
778 private RemoveResult<K, V> removeKey( MergedWithSiblingResult<K, V> mergedResult, long revision, int pos )
779 throws IOException
780 {
781
782 Node<K, V> newNode = new Node<K, V>( btree, revision, nbElems - 1 );
783
784 int index = Math.abs( pos ) - 2;
785
786
787 if ( index < 0 )
788 {
789
790 System.arraycopy( keys, 1, newNode.keys, 0, newNode.nbElems );
791 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
792 newNode.children[0] = createHolder( modifiedPage );
793 System.arraycopy( children, 2, newNode.children, 1, nbElems - 1 );
794 }
795 else
796 {
797
798 if ( index > 0 )
799 {
800 System.arraycopy( keys, 0, newNode.keys, 0, index );
801 }
802
803 newNode.keys[index] = mergedResult.getModifiedPage().findLeftMost().getKey();
804
805 if ( index < nbElems - 2 )
806 {
807 System.arraycopy( keys, index + 2, newNode.keys, index + 1, nbElems - index - 2 );
808 }
809
810
811 System.arraycopy( children, 0, newNode.children, 0, index + 1 );
812
813 Page<K, V> modifiedPage = mergedResult.getModifiedPage();
814 newNode.children[index + 1] = createHolder( modifiedPage );
815
816 if ( index < nbElems - 2 )
817 {
818 System.arraycopy( children, index + 3, newNode.children, index + 2, nbElems - index - 2 );
819 }
820 }
821
822
823 RemoveResult<K, V> result = new RemoveResult<K, V>( mergedResult.getCopiedPages(), newNode,
824 mergedResult.getRemovedElement() );
825
826 result.addCopiedPage( this );
827
828 return result;
829 }
830
831
832
833
834
835 public V get( K key ) throws IOException, KeyNotFoundException
836 {
837 int pos = findPos( key );
838
839 if ( pos < 0 )
840 {
841
842
843 return children[-pos].getValue( btree ).get( key );
844 }
845 else
846 {
847 return children[pos].getValue( btree ).get( key );
848 }
849 }
850
851
852
853
854
855 @Override
856 public BTree<V, V> getValues( K key ) throws KeyNotFoundException, IOException, IllegalArgumentException
857 {
858 int pos = findPos( key );
859
860 if ( pos < 0 )
861 {
862
863
864 return children[-pos].getValue( btree ).getValues( key );
865 }
866 else
867 {
868 return children[pos].getValue( btree ).getValues( key );
869 }
870 }
871
872
873
874
875
876 @Override
877 public boolean hasKey( K key ) throws IOException
878 {
879 int pos = findPos( key );
880
881 if ( pos < 0 )
882 {
883
884
885 return children[-pos].getValue( btree ).hasKey( key );
886 }
887 else
888 {
889 return children[pos].getValue( btree ).hasKey( key );
890 }
891 }
892
893
894
895
896
897 @Override
898 public boolean contains( K key, V value ) throws IOException
899 {
900 int pos = findPos( key );
901
902 if ( pos < 0 )
903 {
904
905
906 return children[-pos].getValue( btree ).contains( key, value );
907 }
908 else
909 {
910 return children[pos].getValue( btree ).contains( key, value );
911 }
912 }
913
914
915
916
917
918
919
920
921 public void setValue( int pos, ElementHolder<Page<K, V>, K, V> value )
922 {
923 children[pos] = value;
924 }
925
926
927
928
929
930 public Page<K, V> getReference( int pos ) throws IOException
931 {
932 if ( pos < nbElems + 1 )
933 {
934 return children[pos].getValue( btree );
935 }
936 else
937 {
938 return null;
939 }
940 }
941
942
943
944
945
946 public Cursor<K, V> browse( K key, Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
947 throws IOException
948 {
949 int pos = findPos( key );
950
951 if ( pos < 0 )
952 {
953 pos = -pos;
954 }
955
956
957 stack.push( new ParentPos<K, V>( this, pos ) );
958
959 return children[pos].getValue( btree ).browse( key, transaction, stack );
960 }
961
962
963
964
965
966 public Cursor<K, V> browse( Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
967 throws IOException
968 {
969 stack.push( new ParentPos<K, V>( this, 0 ) );
970
971 return children[0].getValue( btree ).browse( transaction, stack );
972 }
973
974
975
976
977
978
979
980
981
982
983
984
985
986 private InsertResult<K, V> replaceChild( long revision, ModifyResult<K, V> result, int pos ) throws IOException
987 {
988
989 Page<K, V> newPage = copy( revision );
990
991
992
993 Page<K, V> modifiedPage = result.getModifiedPage();
994
995 ( ( Node<K, V> ) newPage ).children[pos] = createHolder( modifiedPage );
996
997
998
999 result.modifiedPage = newPage;
1000
1001 result.addCopiedPage( this );
1002
1003 return result;
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014 private ElementHolder<Page<K, V>, K, V> createHolder( Page<K, V> page ) throws IOException
1015 {
1016 if ( btree.isManaged() )
1017 {
1018 ElementHolder<Page<K, V>, K, V> holder = btree.getRecordManager().writePage( btree,
1019 page,
1020 revision );
1021
1022
1023 ( ( AbstractPage<K, V> ) page ).setOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
1024 .getOffset() );
1025 ( ( AbstractPage<K, V> ) page ).setLastOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
1026 .getLastOffset() );
1027
1028 return holder;
1029 }
1030 else
1031 {
1032 return btree.createHolder( page );
1033 }
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050 private InsertResult<K, V> insertChild( List<Page<K, V>> copiedPages, long revision, K key, Page<K, V> leftPage,
1051 Page<K, V> rightPage, int pos )
1052 throws IOException
1053 {
1054
1055 Node<K, V> newNode = new Node<K, V>( btree, revision, nbElems + 1 );
1056
1057
1058 if ( nbElems > 0 )
1059 {
1060 System.arraycopy( keys, 0, newNode.keys, 0, pos );
1061 System.arraycopy( children, 0, newNode.children, 0, pos );
1062 }
1063
1064
1065 newNode.keys[pos] = key;
1066
1067
1068
1069 newNode.children[pos] = createHolder( leftPage );
1070 newNode.children[pos + 1] = createHolder( rightPage );
1071
1072
1073 if ( nbElems > 0 )
1074 {
1075 System.arraycopy( keys, pos, newNode.keys, pos + 1, keys.length - pos );
1076 System.arraycopy( children, pos + 1, newNode.children, pos + 2, children.length - pos - 1 );
1077 }
1078
1079
1080 InsertResult<K, V> result = new ModifyResult<K, V>( copiedPages, newNode, null );
1081 result.addCopiedPage( this );
1082
1083 return result;
1084 }
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 private InsertResult<K, V> addAndSplit( List<Page<K, V>> copiedPages, long revision, K pivot, Page<K, V> leftPage,
1106 Page<K, V> rightPage, int pos ) throws IOException
1107 {
1108 int middle = btree.getPageSize() >> 1;
1109
1110
1111 Node<K, V> newLeftPage = new Node<K, V>( btree, revision, middle );
1112 Node<K, V> newRightPage = new Node<K, V>( btree, revision, middle );
1113
1114
1115
1116
1117 if ( pos < middle )
1118 {
1119
1120 System.arraycopy( keys, 0, newLeftPage.keys, 0, pos );
1121 System.arraycopy( children, 0, newLeftPage.children, 0, pos );
1122
1123
1124 newLeftPage.keys[pos] = pivot;
1125 newLeftPage.children[pos] = createHolder( leftPage );
1126 newLeftPage.children[pos + 1] = createHolder( rightPage );
1127
1128
1129 System.arraycopy( keys, pos, newLeftPage.keys, pos + 1, middle - pos - 1 );
1130 System.arraycopy( children, pos + 1, newLeftPage.children, pos + 2, middle - pos - 1 );
1131
1132
1133 System.arraycopy( keys, middle, newRightPage.keys, 0, middle );
1134 System.arraycopy( children, middle, newRightPage.children, 0, middle + 1 );
1135
1136
1137 InsertResult<K, V> result = new SplitResult<K, V>( copiedPages, keys[middle - 1], newLeftPage, newRightPage );
1138 result.addCopiedPage( this );
1139
1140 return result;
1141 }
1142 else if ( pos == middle )
1143 {
1144
1145
1146
1147 System.arraycopy( keys, 0, newLeftPage.keys, 0, middle );
1148 System.arraycopy( children, 0, newLeftPage.children, 0, middle );
1149 newLeftPage.children[middle] = createHolder( leftPage );
1150
1151
1152 System.arraycopy( keys, middle, newRightPage.keys, 0, middle );
1153 System.arraycopy( children, middle + 1, newRightPage.children, 1, middle );
1154 newRightPage.children[0] = createHolder( rightPage );
1155
1156
1157 InsertResult<K, V> result = new SplitResult<K, V>( copiedPages, pivot, newLeftPage, newRightPage );
1158 result.addCopiedPage( this );
1159
1160 return result;
1161 }
1162 else
1163 {
1164
1165 System.arraycopy( keys, 0, newLeftPage.keys, 0, middle );
1166 System.arraycopy( children, 0, newLeftPage.children, 0, middle + 1 );
1167
1168
1169 System.arraycopy( keys, middle + 1, newRightPage.keys, 0, pos - middle - 1 );
1170 System.arraycopy( children, middle + 1, newRightPage.children, 0, pos - middle - 1 );
1171
1172
1173 newRightPage.keys[pos - middle - 1] = pivot;
1174 newRightPage.children[pos - middle - 1] = createHolder( leftPage );
1175 newRightPage.children[pos - middle] = createHolder( rightPage );
1176
1177
1178 System.arraycopy( keys, pos, newRightPage.keys, pos - middle, nbElems - pos );
1179 System.arraycopy( children, pos + 1, newRightPage.children, pos + 1 - middle, nbElems - pos );
1180
1181
1182 InsertResult<K, V> result = new SplitResult<K, V>( copiedPages, keys[middle], newLeftPage, newRightPage );
1183 result.addCopiedPage( this );
1184
1185 return result;
1186 }
1187 }
1188
1189
1190
1191
1192
1193
1194
1195
1196 protected Node<K, V> copy( long revision )
1197 {
1198 Node<K, V> newPage = new Node<K, V>( btree, revision, nbElems );
1199
1200
1201 System.arraycopy( keys, 0, newPage.keys, 0, nbElems );
1202
1203
1204 System.arraycopy( children, 0, newPage.children, 0, nbElems + 1 );
1205
1206 return newPage;
1207 }
1208
1209
1210
1211
1212
1213 public K getLeftMostKey() throws EndOfFileExceededException, IOException
1214 {
1215 return children[0].getValue( btree ).getLeftMostKey();
1216 }
1217
1218
1219
1220
1221
1222 public K getRightMostKey() throws EndOfFileExceededException, IOException
1223 {
1224 int index = ( nbElems + 1 ) - 1;
1225
1226 if ( children[index] != null )
1227 {
1228 return children[index].getValue( btree ).getRightMostKey();
1229 }
1230
1231 return children[nbElems - 1].getValue( btree ).getRightMostKey();
1232 }
1233
1234
1235
1236
1237
1238 public Tuple<K, V> findLeftMost() throws EndOfFileExceededException, IOException
1239 {
1240 return children[0].getValue( btree ).findLeftMost();
1241 }
1242
1243
1244
1245
1246
1247 public Tuple<K, V> findRightMost() throws EndOfFileExceededException, IOException
1248 {
1249 return children[nbElems].getValue( btree ).findRightMost();
1250 }
1251
1252
1253
1254
1255
1256 public String toString()
1257 {
1258 StringBuilder sb = new StringBuilder();
1259
1260 sb.append( "Node[" );
1261 sb.append( super.toString() );
1262 sb.append( "] -> {" );
1263
1264 try
1265 {
1266 if ( nbElems > 0 )
1267 {
1268
1269 if ( children[0] == null )
1270 {
1271 sb.append( "null" );
1272 }
1273 else
1274 {
1275 sb.append( 'r' ).append( children[0].getValue( btree ).getRevision() );
1276 }
1277
1278 for ( int i = 0; i < nbElems; i++ )
1279 {
1280 sb.append( "|<" ).append( keys[i] ).append( ">|" );
1281
1282 if ( children[i + 1] == null )
1283 {
1284 sb.append( "null" );
1285 }
1286 else
1287 {
1288 sb.append( 'r' ).append( children[i + 1].getValue( btree ).getRevision() );
1289 }
1290 }
1291 }
1292 }
1293 catch ( IOException ioe )
1294 {
1295
1296 }
1297
1298 sb.append( "}" );
1299
1300 return sb.toString();
1301 }
1302
1303
1304
1305
1306
1307 public String dumpPage( String tabs )
1308 {
1309 StringBuilder sb = new StringBuilder();
1310
1311 if ( nbElems > 0 )
1312 {
1313 try
1314 {
1315
1316 sb.append( children[0].getValue( btree ).dumpPage( tabs + " " ) );
1317
1318 for ( int i = 0; i < nbElems; i++ )
1319 {
1320 sb.append( tabs );
1321 sb.append( "<" );
1322 sb.append( keys[i] ).append( ">\n" );
1323 sb.append( children[i + 1].getValue( btree ).dumpPage( tabs + " " ) );
1324 }
1325 }
1326 catch ( IOException ioe )
1327 {
1328
1329 }
1330 }
1331
1332 return sb.toString();
1333 }
1334 }