1 21 22 package org.apache.derby.impl.store.access.btree; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 import org.apache.derby.iapi.services.sanity.SanityManager; 26 import org.apache.derby.iapi.services.io.FormatIdUtil; 27 import org.apache.derby.iapi.services.io.StoredFormatIds; 28 import org.apache.derby.iapi.services.io.TypedFormat; 29 import org.apache.derby.iapi.error.StandardException; 30 31 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo; 32 33 import org.apache.derby.iapi.store.access.AccessFactoryGlobals; 34 import org.apache.derby.iapi.store.access.ConglomerateController; 35 import org.apache.derby.iapi.store.access.Qualifier; 36 import org.apache.derby.iapi.store.access.RowUtil; 37 import org.apache.derby.iapi.store.access.ScanController; 38 39 import org.apache.derby.iapi.store.raw.ContainerHandle; 40 import org.apache.derby.iapi.store.raw.FetchDescriptor; 41 import org.apache.derby.iapi.store.raw.Page; 42 import org.apache.derby.iapi.store.raw.RecordHandle; 43 import org.apache.derby.iapi.store.raw.Transaction; 44 45 import org.apache.derby.iapi.types.DataValueDescriptor; 46 47 import java.io.PrintStream ; 48 import org.apache.derby.iapi.services.io.FormatableBitSet; 49 50 74 75 public class LeafControlRow extends ControlRow 76 { 77 80 81 87 public LeafControlRow() 88 { 89 } 90 91 103 LeafControlRow( 104 OpenBTree btree, 105 Page page, 106 ControlRow parent, 107 boolean isRoot) 108 throws StandardException 109 { 110 super(btree, page, 0, parent, isRoot); 112 } 113 114 115 116 125 private static LeafControlRow Allocate( 126 OpenBTree btree, 127 ControlRow parent) 128 throws StandardException 129 { 130 Page page = btree.container.addPage(); 131 132 LeafControlRow control_row = 134 new LeafControlRow(btree, page, parent, false); 135 136 byte insertFlag = Page.INSERT_INITIAL; 141 insertFlag |= Page.INSERT_DEFAULT; 142 RecordHandle rh = 143 page.insertAtSlot(Page.FIRST_SLOT_NUMBER, 144 control_row.getRow(), 145 (FormatableBitSet) null, 146 (LogicalUndo) null, insertFlag, 147 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD); 148 149 if (SanityManager.DEBUG) 150 { 151 RecordHandle rh2 = null; 152 153 rh2 = page.fetchFromSlot( 154 (RecordHandle) null, page.FIRST_SLOT_NUMBER, 155 new DataValueDescriptor[0], (FetchDescriptor) null, true); 156 157 SanityManager.ASSERT(rh.getId() == rh2.getId() && 158 rh.getPageNumber() == rh2.getPageNumber()); 159 } 160 161 return(control_row); 163 } 164 165 181 private float get_left_nondeleted_rowcnt( 182 int startslot) 183 throws StandardException 184 { 185 int non_deleted_row_count = 0; 186 187 for (int slot = 1; slot <= startslot; slot++) 188 { 189 if (!this.page.isDeletedAtSlot(slot)) 190 { 191 non_deleted_row_count++; 192 } 193 } 194 return(non_deleted_row_count); 195 } 196 197 198 199 200 204 protected final void ControlRowInit() 205 { 206 } 207 208 219 public static void initEmptyBtree( 220 OpenBTree open_btree) 221 throws StandardException 222 { 223 Page page = 224 open_btree.container.getPage(ContainerHandle.FIRST_PAGE_NUMBER); 225 226 LeafControlRow control_row = 228 new LeafControlRow(open_btree, page, null, true); 229 230 byte insertFlag = Page.INSERT_INITIAL; 231 insertFlag |= Page.INSERT_DEFAULT; 232 RecordHandle rh = 233 page.insertAtSlot( 234 Page.FIRST_SLOT_NUMBER, 235 control_row.getRow(), 236 (FormatableBitSet) null, 237 (LogicalUndo) null, insertFlag, 238 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD); 239 240 if (SanityManager.DEBUG) 241 { 242 RecordHandle rh2 = null; 243 244 rh2 = page.fetchFromSlot( 245 (RecordHandle) null, 246 Page.FIRST_SLOT_NUMBER, 247 new DataValueDescriptor[0], (FetchDescriptor) null, true); 248 249 SanityManager.ASSERT(rh.getId() == rh2.getId() && 250 rh.getPageNumber() == rh2.getPageNumber()); 251 } 252 253 if (SanityManager.DEBUG) 254 { 255 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 256 { 257 control_row.checkConsistency( 258 open_btree, (ControlRow) null, true); 259 } 260 } 261 262 page.unlatch(); 263 264 return; 265 } 266 267 270 271 272 282 protected final int getNumberOfControlRowColumns() 283 { 284 return(this.CR_NCOLUMNS); 285 } 286 287 296 public boolean isLeftmostLeaf() 297 throws StandardException 298 { 299 return(getleftSiblingPageNumber() == 300 ContainerHandle.INVALID_PAGE_NUMBER); 301 } 302 303 312 public boolean isRightmostLeaf() 313 throws StandardException 314 { 315 return(getrightSiblingPageNumber() == 316 ContainerHandle.INVALID_PAGE_NUMBER); 317 } 318 319 320 331 public ControlRow search( 332 SearchParameters sp) 333 throws StandardException 334 { 335 searchForEntry(sp); 336 337 if (sp.searchForOptimizer) 338 { 339 342 348 int startslot = sp.resultSlot; 349 350 if (sp.resultExact) 351 { 352 354 if (SanityManager.DEBUG) 355 SanityManager.ASSERT(sp.resultSlot > 0); 356 357 360 if (sp.partial_key_match_op == 361 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH) 362 { 363 startslot--; 365 } 366 } 367 368 float non_deleted_left_rows = get_left_nondeleted_rowcnt(startslot); 372 373 int non_deleted_row_count = this.page.nonDeletedRecordCount(); 374 375 380 if (this.getIsRoot()) 381 { 382 sp.current_fraction = 1; 383 sp.left_fraction = 0; 384 } 385 386 391 if (non_deleted_row_count > 1) 392 sp.left_fraction += 393 (sp.current_fraction) * 394 (non_deleted_left_rows / (non_deleted_row_count - 1)); 395 396 if (non_deleted_row_count > 1) 399 sp.current_fraction = 400 (sp.current_fraction) * 401 (((float) 1) / (non_deleted_row_count - 1)); 402 } 403 404 return(this); 405 } 406 407 421 protected ControlRow searchLeft(OpenBTree btree) 422 throws StandardException 423 { 424 return(this); 425 } 426 427 441 protected ControlRow searchRight(OpenBTree btree) 442 throws StandardException 443 { 444 return(this); 445 } 446 447 448 462 protected boolean shrinkFor( 463 OpenBTree btree, 464 DataValueDescriptor[] key) 465 throws StandardException 466 { 467 boolean shrink_me = false; 468 469 try 470 { 471 475 478 if ((this.page.recordCount() == 1) && !getIsRoot()) 479 { 480 shrink_me = unlink(btree); 484 } 485 } 486 finally 487 { 488 if (!shrink_me) 489 this.release(); 490 } 491 492 return(shrink_me); 493 } 494 495 496 522 protected long splitFor( 523 OpenBTree open_btree, 524 DataValueDescriptor[] template, 525 BranchControlRow parent_page, 526 DataValueDescriptor[] splitrow, 527 int flag) 528 throws StandardException 529 { 530 long current_leaf_pageno = this.page.getPageNumber(); 531 532 if (SanityManager.DEBUG) 533 { 534 if (parent_page == null && ( ! this.getIsRoot())) 535 SanityManager.THROWASSERT( 536 this + " splitFor null parent and non-root"); 537 } 538 539 if ((this.page.recordCount() - 1 < 541 open_btree.getConglomerate().maxRowsPerPage) && 542 (this.page.spaceForInsert(splitrow, (FormatableBitSet) null, 543 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD))) 544 { 545 open_btree.getXactMgr().commit(); 548 549 if (parent_page != null) 550 parent_page.release(); 551 552 this.release(); 553 554 return(current_leaf_pageno); 555 } 556 557 if (SanityManager.DEBUG) 560 SanityManager.ASSERT(this.page.recordCount() > 1); 561 562 564 if (this.getIsRoot()) 565 { 566 568 growRoot(open_btree, template, this); 569 570 571 574 ControlRow new_root = ControlRow.Get(open_btree, BTree.ROOTPAGEID); 575 576 return( 577 new_root.splitFor(open_btree, template, null, splitrow, flag)); 578 } 579 580 583 int splitpoint = (this.page.recordCount() - 1) / 2 + 1; 584 585 if ((flag & ControlRow.SPLIT_FLAG_FIRST_ON_PAGE) != 0) 586 { 587 splitpoint = 1; 589 } 590 else if ((flag & ControlRow.SPLIT_FLAG_LAST_ON_PAGE) != 0) 591 { 592 splitpoint = this.page.recordCount() - 1; 595 } 596 597 if (SanityManager.DEBUG) 598 { 599 if (splitpoint <= 0) 600 SanityManager.THROWASSERT(this + " yikes! splitpoint of 0!"); 601 } 602 603 DataValueDescriptor[] split_leaf_row = 606 open_btree.getConglomerate().createTemplate(); 607 608 this.page.fetchFromSlot( 609 (RecordHandle) null, splitpoint, split_leaf_row, 610 (FetchDescriptor) null, true); 611 612 BranchRow branchrow = BranchRow.createBranchRowFromOldLeafRow( 617 split_leaf_row, BranchRow.DUMMY_PAGE_NUMBER); 618 619 620 if (!parent_page.page.spaceForInsert( 624 branchrow.getRow(), (FormatableBitSet) null, 625 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD)) 626 { 627 return( 633 ((BranchControlRow) parent_page).restartSplitFor( 634 open_btree, template, parent_page, this, 635 branchrow.getRow(), splitrow, flag)); 636 637 } 638 if (SanityManager.DEBUG) 646 SanityManager.ASSERT(open_btree.init_open_user_scans != null); 647 648 open_btree.init_open_user_scans.saveScanPositions( 649 open_btree.getConglomerate(), this.page); 650 651 655 if (!open_btree.getLockingPolicy().lockScan( 656 this, parent_page, true , 657 ConglomerateController.LOCK_UPD)) 658 { 659 666 return(current_leaf_pageno); 669 } 670 671 LeafControlRow newleaf = 673 LeafControlRow.Allocate(open_btree, parent_page); 674 675 branchrow.setPageNumber(newleaf.page.getPageNumber()); 678 679 if (SanityManager.DEBUG) 681 { 682 if (SanityManager.DEBUG_ON("leaf_split_abort1")) 683 { 684 throw StandardException.newException( 685 SQLState.BTREE_ABORT_THROUGH_TRACE); 686 } 687 } 688 689 newleaf.linkRight(open_btree, this); 691 692 693 int num_rows_to_move = this.page.recordCount() - splitpoint; 698 699 if (SanityManager.DEBUG) 700 SanityManager.ASSERT(num_rows_to_move >= 0); 701 702 if (num_rows_to_move != 0) 703 { 704 this.page.copyAndPurge( 705 newleaf.page, splitpoint, num_rows_to_move, 1); 706 } 707 708 if (SanityManager.DEBUG) 710 { 711 if (SanityManager.DEBUG_ON("leaf_split_abort2")) 712 { 713 throw StandardException.newException( 714 SQLState.BTREE_ABORT_THROUGH_TRACE); 715 } 716 } 717 718 if (SanityManager.DEBUG) 720 { 721 if (SanityManager.DEBUG_ON("leaf_split_abort3")) 722 { 723 throw StandardException.newException( 724 SQLState.BTREE_ABORT_THROUGH_TRACE); 725 } 726 } 727 728 730 731 BranchRow branch_template = 732 BranchRow.createEmptyTemplate(open_btree.getConglomerate()); 733 SearchParameters sp = 734 new SearchParameters( 735 branchrow.getRow(), 736 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH, 737 branch_template.getRow(), 738 open_btree, false); 739 740 parent_page.searchForEntry(sp); 741 742 if (SanityManager.DEBUG) 744 { 745 SanityManager.ASSERT( 746 parent_page.page.spaceForInsert( 747 branchrow.getRow(), (FormatableBitSet) null, 748 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD)); 749 } 750 751 byte insertFlag = Page.INSERT_INITIAL; 752 insertFlag |= Page.INSERT_DEFAULT; 753 insertFlag |= Page.INSERT_UNDO_WITH_PURGE; 754 if (parent_page.page.insertAtSlot( 755 sp.resultSlot + 1, 756 branchrow.getRow(), 757 (FormatableBitSet) null, 758 (LogicalUndo)null, 759 insertFlag, 760 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD) == null) { 761 762 throw StandardException.newException( 763 SQLState.BTREE_NO_SPACE_FOR_KEY); 764 } 765 766 branchrow = null; 768 769 if (SanityManager.DEBUG) 774 { 775 if (SanityManager.DEBUG_ON("leaf_split_abort4")) 776 { 777 throw StandardException.newException( 778 SQLState.BTREE_ABORT_THROUGH_TRACE); 779 } 780 } 781 782 if (SanityManager.DEBUG) 783 { 784 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 785 { 786 this.checkConsistency(open_btree, parent_page, false); 787 newleaf.checkConsistency(open_btree, parent_page, false); 788 parent_page.checkConsistency(open_btree, null, false); 789 } 790 } 791 792 open_btree.getXactMgr().commit(); 796 797 parent_page.release(); 798 this.release(); 800 long new_leaf_pageno = newleaf.page.getPageNumber(); 801 newleaf.release(); 802 803 return(new_leaf_pageno); 810 } 811 812 824 private static void growRoot( 825 OpenBTree open_btree, 826 DataValueDescriptor[] template, 827 LeafControlRow leafroot) 828 throws StandardException 829 { 830 BranchControlRow branchroot = null; 831 LeafControlRow newleaf = null; 832 833 834 open_btree.init_open_user_scans.saveScanPositions( 839 open_btree.getConglomerate(), leafroot.page); 840 841 847 if (!open_btree.getLockingPolicy().lockScan( 848 leafroot, (ControlRow) null, 849 true , 850 ConglomerateController.LOCK_UPD)) 851 { 852 860 return; 861 } 862 863 865 newleaf = LeafControlRow.Allocate(open_btree, leafroot); 866 867 if (SanityManager.DEBUG) 869 { 870 if (SanityManager.DEBUG_ON("leaf_split_growRoot1")) 871 { 872 throw StandardException.newException( 873 SQLState.BTREE_ABORT_THROUGH_TRACE); 874 } 875 } 876 877 881 if (SanityManager.DEBUG) 882 SanityManager.ASSERT((leafroot.page.recordCount() - 1) > 0); 883 leafroot.page.copyAndPurge( 884 newleaf.page, 1, leafroot.page.recordCount() - 1, 1); 885 886 if (SanityManager.DEBUG) 888 { 889 if (SanityManager.DEBUG_ON("leaf_split_growRoot2")) 890 { 891 throw StandardException.newException( 892 SQLState.BTREE_ABORT_THROUGH_TRACE); 893 } 894 } 895 896 if (SanityManager.DEBUG) 898 { 899 if (SanityManager.DEBUG_ON("leaf_split_growRoot3")) 900 { 901 leafroot.setLevel(42); 904 leafroot.setParent(42); 905 throw StandardException.newException( 906 SQLState.BTREE_ABORT_THROUGH_TRACE); 907 } 908 } 909 910 914 919 branchroot = new BranchControlRow( 920 open_btree, leafroot.page, 1, null, true, 921 newleaf.page.getPageNumber()); 922 leafroot = null; 923 924 branchroot.page.updateAtSlot( 927 0, branchroot.getRow(), (FormatableBitSet) null); 928 929 if (SanityManager.DEBUG) 931 { 932 if (SanityManager.DEBUG_ON("leaf_split_growRoot4")) 933 { 934 throw StandardException.newException( 935 SQLState.BTREE_ABORT_THROUGH_TRACE); 936 } 937 } 938 939 if (SanityManager.DEBUG) 940 { 941 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 942 { 943 newleaf.checkConsistency(open_btree, branchroot, false); 944 branchroot.checkConsistency(open_btree, null, false); 945 } 946 } 947 948 open_btree.getXactMgr().commit(); 952 953 if (SanityManager.DEBUG) 955 { 956 if (SanityManager.DEBUG_ON("leaf_split_growRoot5")) 957 { 958 throw StandardException.newException( 959 SQLState.BTREE_ABORT_THROUGH_TRACE); 960 } 961 } 962 963 if (branchroot != null) 969 branchroot.release(); 970 if (leafroot != null) 971 leafroot.release(); 972 if (newleaf != null) 973 newleaf.release(); 974 } 975 976 987 protected ControlRow getLeftChild(OpenBTree btree) 988 throws StandardException 989 { 990 return(null); 991 } 992 993 1004 protected ControlRow getRightChild(OpenBTree btree) 1005 throws StandardException 1006 { 1007 return(null); 1008 } 1009 1010 1013 1014 1032 public int checkConsistency( 1033 OpenBTree btree, 1034 ControlRow parent, 1035 boolean check_other_pages 1036 ) 1037 throws StandardException 1038 { 1039 checkGeneric(btree, parent, check_other_pages); 1042 1043 if (SanityManager.DEBUG) 1045 { 1046 SanityManager.ASSERT(this.getLevel() == 0, "leaf not at level 0"); 1047 1048 1056 SanityManager.ASSERT( 1057 this.page.fetchNumFieldsAtSlot(CR_SLOT) == 1058 ControlRow.CR_NCOLUMNS); 1059 1060 1062 int numslots = this.page.recordCount(); 1065 for (int slot = 1; slot < numslots; slot++) 1066 { 1067 if (this.page.fetchNumFieldsAtSlot(slot) < 1068 btree.getConglomerate().nKeyFields) 1069 SanityManager.THROWASSERT( 1070 "row[" + slot + "]" 1071 + " has " + this.page.fetchNumFieldsAtSlot(slot) 1072 + " columns, should have at least" + 1073 btree.getConglomerate().nKeyFields); 1074 1075 } 1081 1082 } 1083 1084 return 1; 1086 } 1087 1088 1094 public void printTree( 1095 OpenBTree btree) 1096 throws StandardException 1097 { 1098 if (SanityManager.DEBUG) 1099 { 1100 SanityManager.DEBUG_PRINT("p_tree", this.debugPage(btree)); 1101 1102 return; 1103 } 1104 } 1105 1106 1107 1110 1111 1112 1117 public int getTypeFormatId() 1118 { 1119 return StoredFormatIds.ACCESS_BTREE_LEAFCONTROLROW_V1_ID; 1120 } 1121} 1122 | Popular Tags |