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