1 21 22 package org.apache.derby.impl.store.access.btree; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 26 import org.apache.derby.iapi.services.io.FormatIdUtil; 27 import org.apache.derby.iapi.services.io.Storable; 28 import org.apache.derby.iapi.services.io.StoredFormatIds; 29 30 import org.apache.derby.iapi.services.sanity.SanityManager; 31 32 import org.apache.derby.iapi.error.StandardException; 33 34 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo; 35 36 import org.apache.derby.iapi.store.access.AccessFactoryGlobals; 37 import org.apache.derby.iapi.store.access.Qualifier; 38 import org.apache.derby.iapi.store.access.RowUtil; 39 import org.apache.derby.iapi.store.access.ScanController; 40 41 import org.apache.derby.iapi.store.raw.ContainerHandle; 42 import org.apache.derby.iapi.store.raw.FetchDescriptor; 43 import org.apache.derby.iapi.store.raw.Page; 44 import org.apache.derby.iapi.store.raw.RecordHandle; 45 46 import org.apache.derby.iapi.types.DataValueDescriptor; 47 48 import org.apache.derby.iapi.types.SQLLongint; 49 50 import org.apache.derby.iapi.services.io.FormatableBitSet; 51 52 77 78 81 public class BranchControlRow extends ControlRow 82 { 83 protected SQLLongint left_child_page = null; 84 85 86 90 transient SQLLongint child_pageno_buf = null; 91 92 93 private static final int CR_LEFTCHILD = ControlRow.CR_COLID_LAST + 1; 94 private static final int CR_COLID_LAST = CR_LEFTCHILD; 95 private static final int CR_NCOLUMNS = CR_COLID_LAST + 1; 96 97 100 protected static final FormatableBitSet CR_LEFTCHILD_BITMAP = 101 new FormatableBitSet(CR_LEFTCHILD + 1); 102 103 106 107 static 108 { 109 CR_LEFTCHILD_BITMAP.set(CR_LEFTCHILD); 110 } 111 112 118 public BranchControlRow() 119 { 120 } 121 122 public BranchControlRow( 123 OpenBTree open_btree, 124 Page page, 125 int level, 126 ControlRow parent, 127 boolean isRoot, 128 long left_child) 129 throws StandardException 130 { 131 super(open_btree, page, 132 level, parent, isRoot); 133 134 this.left_child_page = new SQLLongint(left_child); 135 136 this.row[CR_LEFTCHILD] = left_child_page; 139 140 child_pageno_buf = new SQLLongint(); 142 } 143 144 147 148 152 protected final void ControlRowInit() 153 { 154 child_pageno_buf = new SQLLongint(); 155 } 156 157 166 public boolean isLeftmostLeaf() 167 throws StandardException 168 { 169 return(false); 170 } 171 172 181 public boolean isRightmostLeaf() 182 throws StandardException 183 { 184 return(false); 185 } 186 187 197 protected final int getNumberOfControlRowColumns() 198 { 199 return(this.CR_NCOLUMNS); 200 } 201 202 public static long restartSplitFor( 203 OpenBTree open_btree, 204 DataValueDescriptor[] template, 205 BranchControlRow parent, 206 ControlRow child, 207 DataValueDescriptor[] newbranchrow, 208 DataValueDescriptor[] splitrow, 209 int flag) 210 throws StandardException 211 { 212 parent.release(); 214 child.release(); 215 parent = null; 216 child = null; 217 218 ControlRow root = ControlRow.Get(open_btree, BTree.ROOTPAGEID); 221 222 if (SanityManager.DEBUG) 223 SanityManager.ASSERT(root.page.isLatched()); 224 225 return(root.splitFor(open_btree, template, null, newbranchrow, flag)); 226 } 227 228 229 240 public ControlRow search(SearchParameters sp) 241 throws StandardException 242 { 243 ControlRow childpage = null; 244 long childpageid; 245 boolean got_error = true; 246 247 try 248 { 249 searchForEntry(sp); 250 251 if (sp.searchForOptimizer) 252 { 253 256 float left_rows = sp.resultSlot; 263 264 int row_count = this.page.recordCount(); 267 268 if (this.getIsRoot()) 269 { 270 sp.current_fraction = 1; 271 sp.left_fraction = 0; 272 } 273 274 sp.left_fraction += 283 (sp.current_fraction) * (left_rows / row_count); 284 285 sp.current_fraction = 286 (sp.current_fraction) * (((float) 1) / row_count); 287 } 288 289 childpage = 290 this.getChildPageAtSlot(sp.btree, sp.resultSlot); 291 292 this.release(); 293 294 got_error = false; 295 296 return childpage.search(sp); 297 } 298 finally 299 { 300 if (got_error) 301 { 302 if (childpage != null) 303 childpage.release(); 304 if (this.page.isLatched()) 305 this.release(); 306 } 307 } 308 } 309 310 324 protected ControlRow searchLeft(OpenBTree btree) 325 throws StandardException 326 { 327 ControlRow childpage = null; 328 boolean got_error = true; 329 330 try 331 { 332 childpage = this.getLeftChild(btree); 333 this.release(); 334 335 got_error = false; 336 return childpage.searchLeft(btree); 337 } 338 finally 339 { 340 if (got_error) 341 { 342 if (childpage != null) 343 childpage.release(); 344 if (this.page.isLatched()) 345 this.release(); 346 } 347 } 348 } 349 350 364 protected ControlRow searchRight(OpenBTree btree) 365 throws StandardException 366 { 367 ControlRow childpage = null; 368 boolean got_error = true; 369 370 try 371 { 372 childpage = this.getRightChild(btree); 373 this.release(); 374 375 got_error = false; 376 return(childpage.searchRight(btree)); 377 } 378 finally 379 { 380 if (got_error) 381 { 382 if (childpage != null) 383 childpage.release(); 384 if (this.page.isLatched()) 385 this.release(); 386 } 387 } 388 } 389 390 391 405 protected boolean shrinkFor( 406 OpenBTree open_btree, 407 DataValueDescriptor[] shrink_key) 408 throws StandardException 409 { 410 ControlRow childpage = null; 411 boolean shrinkme = false; 412 413 try 414 { 415 if (SanityManager.DEBUG) 416 SanityManager.ASSERT(this.page.isLatched()); 417 418 420 BranchRow branch_template = 421 BranchRow.createEmptyTemplate(open_btree.getConglomerate()); 422 SearchParameters sp = new SearchParameters( 423 shrink_key, 424 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH, 425 branch_template.getRow(), open_btree, false); 426 427 this.searchForEntry(sp); 428 childpage = this.getChildPageAtSlot(sp.btree, sp.resultSlot); 429 430 435 if (childpage.shrinkFor(open_btree, shrink_key)) 436 { 437 if (sp.resultSlot != 0) 439 { 440 this.page.purgeAtSlot(sp.resultSlot, 1, true); 444 } 445 else 446 { 447 453 if (this.page.recordCount() > 1) 454 { 455 459 long leftchildpageid = 460 getChildPageIdAtSlot(open_btree, 1); 461 462 this.setLeftChildPageno(leftchildpageid); 463 464 this.page.purgeAtSlot(1, 1, true); 468 } 469 else 470 { 471 480 if (this.getIsRoot()) 481 { 482 487 495 if (SanityManager.DEBUG) 496 { 497 SanityManager.ASSERT( 498 this.page.recordCount() == 1); 499 } 500 501 LeafControlRow newleafroot = new LeafControlRow( 502 open_btree, this.page, null, true); 503 504 newleafroot.page.updateAtSlot( 505 0, newleafroot.getRow(), 506 (FormatableBitSet) null); 507 508 newleafroot.release(); 509 510 shrinkme = true; 511 } 512 else 513 { 514 519 if (this.unlink(open_btree)) 521 { 522 shrinkme = true; 524 } 525 } 526 } 527 } 528 } 529 } 530 finally 531 { 532 if (!shrinkme) 536 this.release(); 537 } 538 539 return(shrinkme); 540 } 541 542 580 protected long splitFor( 581 OpenBTree open_btree, 582 DataValueDescriptor[] template, 583 BranchControlRow parent, 584 DataValueDescriptor[] splitrow, 585 int flag) 586 throws StandardException 587 { 588 int childpageid; 589 ControlRow childpage; 590 591 594 if (SanityManager.DEBUG) 595 { 596 SanityManager.ASSERT(parent != null || this.getIsRoot()); 597 598 SanityManager.ASSERT( 599 parent == null || parent.page.isLatched(), 600 "parent page is not latched"); 601 602 SanityManager.ASSERT(this.page.isLatched(), 603 "page is not latched:"); 604 } 605 606 if ((this.page.recordCount() - 1 >= 607 open_btree.getConglomerate().maxRowsPerPage) || 608 (!this.page.spaceForInsert(splitrow, (FormatableBitSet) null, 609 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD))) 610 { 611 612 if (this.page.recordCount() == 1) 613 { 614 throw StandardException.newException( 618 SQLState.BTREE_NO_SPACE_FOR_KEY); 619 } 620 621 623 if (this.getIsRoot()) 624 { 625 growRoot(open_btree, template, this); 627 628 parent = (BranchControlRow) 629 ControlRow.Get(open_btree, BTree.ROOTPAGEID); 630 631 632 return(parent.splitFor( 633 open_btree, template, null, splitrow, flag)); 634 } 635 636 if (SanityManager.DEBUG) 639 { 640 SanityManager.ASSERT(!this.getIsRoot()); 641 SanityManager.ASSERT(parent != null); 642 } 643 644 int splitpoint = (this.page.recordCount() - 1) / 2 + 1; 645 646 if ((flag & ControlRow.SPLIT_FLAG_FIRST_ON_PAGE) != 0) 647 { 648 splitpoint = 1; 650 } 651 else if ((flag & ControlRow.SPLIT_FLAG_LAST_ON_PAGE) != 0) 652 { 653 splitpoint = this.page.recordCount() - 1; 656 } 657 658 if (SanityManager.DEBUG) 659 { 660 if (splitpoint <= 0) 661 SanityManager.THROWASSERT(this + "yikes! splitpoint of 0!"); 662 } 663 664 665 672 BranchRow split_branch_row = 674 BranchRow.createEmptyTemplate(open_btree.getConglomerate()); 675 676 this.page.fetchFromSlot( 677 (RecordHandle) null, splitpoint, split_branch_row.getRow(), 678 (FetchDescriptor) null, true); 679 680 BranchRow newbranchrow = 685 split_branch_row.createBranchRowFromOldBranchRow( 686 BranchRow.DUMMY_PAGE_NUMBER); 687 688 if (!parent.page.spaceForInsert( 692 newbranchrow.getRow(), (FormatableBitSet) null, 693 AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD)) 694 { 695 return( 701 parent.restartSplitFor( 702 open_btree, template, parent, this, 703 newbranchrow.getRow(), splitrow, flag)); 704 } 705 706 715 childpage = this.getChildPageAtSlot(open_btree, splitpoint); 716 717 BranchControlRow newbranch = 720 BranchControlRow.Allocate(open_btree, childpage, 721 this.getLevel(), parent); 722 newbranch.linkRight(open_btree, this); 723 724 725 if (SanityManager.DEBUG) 727 { 728 if (SanityManager.DEBUG_ON("branch_split_abort1")) 729 { 730 throw StandardException.newException( 731 SQLState.BTREE_ABORT_THROUGH_TRACE); 732 } 733 } 734 735 childpage.release(); 737 738 newbranchrow.setPageNumber(newbranch.page.getPageNumber()); 741 742 BranchRow branch_template = 743 BranchRow.createEmptyTemplate(open_btree.getConglomerate()); 744 SearchParameters sp = new SearchParameters( 745 newbranchrow.getRow(), 746 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH, 747 branch_template.getRow(), 748 open_btree, false); 749 750 parent.searchForEntry(sp); 751 752 byte insertFlag = Page.INSERT_INITIAL; 753 insertFlag |= Page.INSERT_DEFAULT; 754 insertFlag |= Page.INSERT_UNDO_WITH_PURGE; 755 if (parent.page.insertAtSlot( 756 sp.resultSlot + 1, 757 newbranchrow.getRow(), 758 (FormatableBitSet) null, 759 (LogicalUndo)null, 760 insertFlag, AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD) 761 == null) 762 { 763 throw StandardException.newException( 764 SQLState.BTREE_NO_SPACE_FOR_KEY); 765 } 766 767 768 if (SanityManager.DEBUG) 770 { 771 if (SanityManager.DEBUG_ON("branch_split_abort2")) 772 { 773 throw StandardException.newException( 774 SQLState.BTREE_ABORT_THROUGH_TRACE); 775 } 776 } 777 778 newbranchrow = null; 781 782 int num_rows_to_move = this.page.recordCount() - (splitpoint + 1); 787 788 if (num_rows_to_move > 0) 789 { 790 this.page.copyAndPurge( 791 newbranch.page, splitpoint + 1, num_rows_to_move, 1); 792 } 793 794 this.page.purgeAtSlot(splitpoint, 1, true); 797 798 if (SanityManager.DEBUG) 800 { 801 if (SanityManager.DEBUG_ON("branch_split_abort3")) 802 { 803 throw StandardException.newException( 804 SQLState.BTREE_ABORT_THROUGH_TRACE); 805 } 806 } 807 808 if (SanityManager.DEBUG) 810 { 811 if (SanityManager.DEBUG_ON("branch_split_abort4")) 812 { 813 throw StandardException.newException( 814 SQLState.BTREE_ABORT_THROUGH_TRACE); 815 } 816 } 817 818 if (SanityManager.DEBUG) 820 { 821 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 822 { 823 parent.checkConsistency(open_btree, null, false); 824 newbranch.checkConsistency(open_btree, parent, false); 825 this.checkConsistency(open_btree, parent, false); 826 } 827 } 828 829 newbranch.fixChildrensParents(open_btree, null); 832 833 open_btree.getXactMgr().commit(); 839 840 BranchControlRow pagetofollow; 842 843 if (CompareIndexRowToKey( 844 splitrow, 845 split_branch_row.getRow(), 846 split_branch_row.getRow().length - 1, 0, 847 open_btree.getConglomerate().ascDescInfo) >= 0) 848 { 849 pagetofollow = newbranch; 851 this.release(); 852 } 853 else 854 { 855 pagetofollow = this; 857 newbranch.release(); 858 } 859 860 if (SanityManager.DEBUG) 864 { 865 SanityManager.ASSERT(parent != null); 866 SanityManager.ASSERT(parent.page.isLatched()); 867 SanityManager.ASSERT( 868 pagetofollow.page.isLatched()); 869 } 870 871 return( 873 pagetofollow.splitFor( 874 open_btree, template, parent, splitrow, flag)); 875 } 876 877 if (SanityManager.DEBUG) 878 { 879 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 880 { 881 this.checkConsistency(open_btree, parent, false); 882 } 883 } 884 885 if (parent != null) 887 parent.release(); 888 889 BranchRow branch_template = 891 BranchRow.createEmptyTemplate(open_btree.getConglomerate()); 892 SearchParameters sp = new SearchParameters( 893 splitrow, 894 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH, 895 branch_template.getRow(), 896 open_btree, false); 897 898 searchForEntry(sp); 899 900 childpage = this.getChildPageAtSlot(open_btree, sp.resultSlot); 901 902 return(childpage.splitFor(open_btree, template, this, splitrow, flag)); 903 } 904 905 908 909 910 929 public int checkConsistency( 930 OpenBTree btree, 931 ControlRow parent, 932 boolean check_other_pages) 933 throws StandardException 934 { 935 checkGeneric(btree, parent, check_other_pages); 938 939 if (SanityManager.DEBUG) 941 { 942 SanityManager.ASSERT( 943 this.getLevel() > 0, "branch not above level 0"); 944 945 952 SanityManager.ASSERT( 953 this.page.fetchNumFieldsAtSlot(CR_SLOT) == 954 BranchControlRow.CR_NCOLUMNS); 955 SanityManager.ASSERT(getLeftChildPageno() != 956 ContainerHandle.INVALID_PAGE_NUMBER); 957 958 SanityManager.ASSERT(getLeftChildPageno() >= BTree.ROOTPAGEID); 962 } 963 964 if (SanityManager.DEBUG) 966 { 967 968 int numslots = this.page.recordCount(); 973 for (int slot = 1; slot < numslots; slot++) 974 { 975 if ((this.page.fetchNumFieldsAtSlot(slot) != 976 (btree.getConglomerate().nKeyFields + 1))) 977 SanityManager.THROWASSERT( 978 "row[" + slot + "]" 979 + " has " + this.page.fetchNumFieldsAtSlot(slot) 980 + " columns, should have at least " + 981 (btree.getConglomerate().nKeyFields + 1)); 982 983 SanityManager.ASSERT(this.getChildPageIdAtSlot(btree, slot) != 984 ContainerHandle.INVALID_PAGE_NUMBER); 985 986 SanityManager.ASSERT(!this.page.isDeletedAtSlot(slot)); 988 989 SanityManager.ASSERT(getLeftChildPageno() >= BTree.ROOTPAGEID); 994 } 995 } 996 997 if (check_other_pages) 1001 checkChildOrderAgainstRowOrder(btree); 1002 1003 int nchildren = 0; 1005 1006 if (check_other_pages) 1008 nchildren = checkChildren(btree); 1009 1010 return nchildren + 1; 1012 } 1013 1014 private int checkChildren(OpenBTree btree) 1015 throws StandardException 1016 { 1017 int nchildren = 0; 1018 ControlRow childpage = null; 1019 1020 try 1021 { 1022 childpage = this.getLeftChild(btree); 1024 nchildren += childpage.checkConsistency(btree, this, true); 1025 childpage.release(); 1026 childpage = null; 1027 1028 int numslots = this.page.recordCount(); 1030 for (int slot = 1; slot < numslots; slot++) 1031 { 1032 childpage = this.getChildPageAtSlot(btree, slot); 1033 nchildren += childpage.checkConsistency(btree, this, true); 1034 childpage.release(); 1035 childpage = null; 1036 } 1037 1038 return(nchildren); 1039 } 1040 finally 1041 { 1042 if (childpage != null) 1043 childpage.release(); 1044 } 1045 } 1046 1047 private void checkChildOrderAgainstRowOrder(OpenBTree btree) 1048 throws StandardException 1049 { 1050 ControlRow cur = null; 1051 ControlRow prev = null; 1052 1053 try 1054 { 1055 prev = this.getLeftChild(btree); 1056 1057 int numslots = this.page.recordCount(); 1058 for (int slot = 1; slot < numslots; slot++) 1059 { 1060 cur = this.getChildPageAtSlot(btree, slot); 1061 1062 long shouldbecur_pageno = prev.getrightSiblingPageNumber(); 1063 if (SanityManager.DEBUG) 1064 { 1065 if (shouldbecur_pageno != cur.page.getPageNumber()) 1066 SanityManager.THROWASSERT( 1067 "child linkage error going right.\n" + 1068 "cur page control row = " + cur + "\n" + 1069 "prev page control row = " + prev + "\n"); 1070 } 1071 1072 long shouldbeprev_pageno = cur.getleftSiblingPageNumber(); 1073 1074 if (SanityManager.DEBUG) 1075 { 1076 SanityManager.ASSERT( 1077 shouldbeprev_pageno == prev.page.getPageNumber(), 1078 "child linkeage error going left"); 1079 } 1080 1081 prev.release(); 1082 prev = cur; 1083 cur = null; 1084 } 1085 1086 prev.release(); 1087 prev = null; 1088 } 1089 finally 1090 { 1091 if (prev != null) 1092 prev.release(); 1093 if (cur != null) 1094 cur.release(); 1095 } 1096 1097 return; 1098 } 1099 1100 1107 public void printTree( 1108 OpenBTree btree) 1109 throws StandardException 1110 { 1111 if (SanityManager.DEBUG) 1112 { 1113 SanityManager.DEBUG_PRINT("p_tree", this.debugPage(btree)); 1114 1115 ControlRow child = null; 1116 1117 try 1118 { 1119 child = this.getLeftChild(btree); 1120 1121 child.printTree(btree); 1122 child.release(); 1123 child = null; 1124 1125 int numslots = this.page.recordCount(); 1126 for (int slot = 1; slot < numslots; slot++) 1127 { 1128 child = this.getChildPageAtSlot(btree, slot); 1129 child.printTree(btree); 1130 child.release(); 1131 child = null; 1132 } 1133 } 1134 finally 1135 { 1136 if (child != null) 1137 child.release(); 1138 } 1139 1140 return; 1141 } 1142 } 1143 1144 1147 1148 1171 private static void growRoot( 1172 OpenBTree open_btree, 1173 DataValueDescriptor[] template, 1174 BranchControlRow root) 1175 throws StandardException 1176 { 1177 ControlRow leftchild = null; 1178 BranchControlRow branch = null; 1179 1180 try 1181 { 1182 if (SanityManager.DEBUG) 1183 { 1184 SanityManager.ASSERT(root.page.isLatched()); 1185 SanityManager.ASSERT(root.getIsRoot()); 1186 } 1187 1188 1191 leftchild = root.getLeftChild(open_btree); 1195 1196 branch = 1200 BranchControlRow.Allocate( 1201 open_btree, leftchild, root.getLevel(), root); 1202 1203 root.page.copyAndPurge(branch.page, 1, root.page.recordCount() - 1, 1); 1207 1208 root.setLeftChild(branch); 1210 1211 root.setLevel(root.getLevel() + 1); 1213 1214 branch.fixChildrensParents(open_btree, leftchild); 1218 1219 if (SanityManager.DEBUG) 1220 { 1221 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 1222 { 1223 root.checkConsistency(open_btree, null, false); 1224 branch.checkConsistency(open_btree, root, false); 1225 leftchild.checkConsistency(open_btree, branch, false); 1226 } 1227 } 1228 1229 open_btree.getXactMgr().commit(); 1233 1234 } 1235 finally 1236 { 1237 root.release(); 1241 if (branch != null) 1242 branch.release(); 1243 if (leftchild != null) 1244 leftchild.release(); 1245 } 1246 return; 1247 } 1248 1253 private static BranchControlRow Allocate( 1254 OpenBTree open_btree, 1255 ControlRow leftchild, 1256 int level, 1257 ControlRow parent) 1258 throws StandardException 1259 { 1260 Page page = open_btree.container.addPage(); 1261 1262 BranchControlRow control_row = 1264 new BranchControlRow( 1265 open_btree, page, level, 1266 parent, false, leftchild.page.getPageNumber()); 1267 1268 byte insertFlag = Page.INSERT_INITIAL; 1270 insertFlag |= Page.INSERT_DEFAULT; 1271 page.insertAtSlot( 1272 Page.FIRST_SLOT_NUMBER, 1273 control_row.getRow(), 1274 (FormatableBitSet) null, 1275 (LogicalUndo)null, 1276 insertFlag, AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD); 1277 1278 return(control_row); 1280 } 1281 1282 protected void setLeftChildPageno(long leftchild_pageno) 1283 throws StandardException 1284 { 1285 if (left_child_page == null) 1287 left_child_page = new SQLLongint(leftchild_pageno); 1288 else 1289 this.left_child_page.setValue(leftchild_pageno); 1290 1291 this.page.updateFieldAtSlot( 1293 CR_SLOT, CR_LEFTCHILD, this.left_child_page, null); 1294 } 1295 1296 protected void setLeftChild(ControlRow leftchild) 1297 throws StandardException 1298 { 1299 this.setLeftChildPageno(leftchild.page.getPageNumber()); 1300 } 1301 1302 1318 private void fixChildrensParents( 1319 OpenBTree btree, 1320 ControlRow leftchild) 1321 throws StandardException 1322 { 1323 ControlRow child = null; 1324 1325 try 1326 { 1327 if (leftchild == null) 1328 { 1329 child = this.getLeftChild(btree); 1330 child.setParent(this.page.getPageNumber()); 1331 1332 if (SanityManager.DEBUG) 1333 { 1334 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 1335 { 1336 child.checkConsistency(btree, this, false); 1337 } 1338 } 1339 1340 child.release(); 1341 child = null; 1342 } 1343 else 1344 { 1345 leftchild.setParent(this.page.getPageNumber()); 1346 1347 if (SanityManager.DEBUG) 1348 { 1349 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 1350 { 1351 leftchild.checkConsistency(btree, this, false); 1352 } 1353 } 1354 } 1355 1356 int numslots = this.page.recordCount(); 1357 for (int slot = 1; slot < numslots; slot++) 1358 { 1359 child = getChildPageAtSlot(btree, slot); 1360 child.setParent(this.page.getPageNumber()); 1361 if (SanityManager.DEBUG) 1362 { 1363 if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) 1364 { 1365 child.checkConsistency(btree, this, false); 1366 } 1367 } 1368 1369 child.release(); 1370 child = null; 1371 } 1372 } 1373 finally 1374 { 1375 if (child != null) 1376 child.release(); 1377 } 1378 } 1379 1380 private long getChildPageIdAtSlot( 1381 OpenBTree btree, 1382 int slot) 1383 throws StandardException 1384 { 1385 long child_page_id; 1386 1387 if (slot == 0) 1388 { 1389 child_page_id = this.getLeftChildPageno(); 1390 } 1391 else 1392 { 1393 this.page.fetchFieldFromSlot( 1394 slot, btree.getConglomerate().nKeyFields, child_pageno_buf); 1395 child_page_id = child_pageno_buf.getLong(); 1396 } 1397 1398 return(child_page_id); 1399 } 1400 1401 protected ControlRow getChildPageAtSlot( 1402 OpenBTree open_btree, 1403 int slot) 1404 throws StandardException 1405 { 1406 ControlRow child_control_row; 1407 1408 if (slot == 0) 1409 { 1410 child_control_row = this.getLeftChild(open_btree); 1411 } 1412 else 1413 { 1414 this.page.fetchFieldFromSlot( 1415 slot, open_btree.getConglomerate().nKeyFields, 1416 child_pageno_buf); 1417 1418 child_control_row = 1419 ControlRow.Get(open_btree, child_pageno_buf.getLong()); 1420 } 1421 1422 return(child_control_row); 1423 } 1424 1425 1436 public ControlRow getLeftChild(OpenBTree open_btree) 1437 throws StandardException 1438 { 1439 return(ControlRow.Get(open_btree, this.getLeftChildPageno())); 1440 } 1441 1442 1453 protected ControlRow getRightChild(OpenBTree open_btree) 1454 throws StandardException 1455 { 1456 ControlRow right_child; 1457 int num_slots = this.page.recordCount(); 1458 1459 right_child = 1463 (num_slots == 1 ? 1464 ControlRow.Get(open_btree, this.getLeftChildPageno()) : 1465 getChildPageAtSlot(open_btree, (num_slots - 1))); 1466 1467 return(right_child); 1468 } 1469 1470 1475 long getLeftChildPageno() 1476 throws StandardException 1477 { 1478 if (this.left_child_page == null) 1479 { 1480 this.left_child_page = new SQLLongint(); 1481 1482 scratch_row[CR_LEFTCHILD] = this.left_child_page; 1483 1484 fetchDesc.setValidColumns(CR_LEFTCHILD_BITMAP); 1485 this.page.fetchFromSlot( 1486 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 1487 } 1488 return(left_child_page.getLong()); 1489 } 1490 1491 1494 1495 1496 1501 public int getTypeFormatId() 1502 { 1503 return StoredFormatIds.ACCESS_BTREE_BRANCHCONTROLROW_V1_ID; 1504 } 1505 1506 1517 public DataValueDescriptor[] getRowTemplate(OpenBTree open_btree) 1518 throws StandardException 1519 { 1520 return(BranchRow.createEmptyTemplate( 1521 open_btree.getConglomerate()).getRow()); 1522 } 1523 1524 1527 public String toString() 1528 { 1529 if (SanityManager.DEBUG) 1530 { 1531 String string = super.toString(); 1532 1533 try 1534 { 1535 string += "left child page = " + getLeftChildPageno() + ";"; 1536 1537 } 1538 catch (Throwable t) 1539 { 1540 string += "error encountered while doing ControlRow.toString()"; 1541 } 1542 1543 return(string); 1544 } 1545 else 1546 { 1547 return(null); 1548 } 1549 } 1550} 1551 | Popular Tags |