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