1 21 22 package org.apache.derby.impl.store.access.btree; 23 24 import java.io.PrintStream ; 25 26 import org.apache.derby.iapi.services.monitor.Monitor; 27 import org.apache.derby.iapi.services.sanity.SanityManager; 28 29 import org.apache.derby.iapi.services.io.FormatIdUtil; 30 import org.apache.derby.iapi.services.io.Storable; 31 import org.apache.derby.iapi.services.io.TypedFormat; 32 33 import org.apache.derby.iapi.error.StandardException; 34 35 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo; 36 37 import org.apache.derby.iapi.store.access.Qualifier; 38 import org.apache.derby.iapi.store.access.RowUtil; 39 40 import org.apache.derby.iapi.store.raw.AuxObject; 41 import org.apache.derby.iapi.store.raw.FetchDescriptor; 42 import org.apache.derby.iapi.store.raw.Page; 43 import org.apache.derby.iapi.store.raw.ContainerHandle; 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 import org.apache.derby.impl.store.access.StorableFormatId; 50 51 52 import org.apache.derby.iapi.services.io.FormatableBitSet; 53 54 import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil; 55 56 88 89 public abstract class ControlRow implements AuxObject, TypedFormat 90 { 91 98 private StorableFormatId version = null; 99 100 108 private SQLLongint leftSiblingPageNumber; 109 110 119 private SQLLongint rightSiblingPageNumber; 120 121 133 private SQLLongint parentPageNumber; 135 136 145 private SQLLongint level; 146 147 155 private SQLLongint isRoot = null; 156 157 166 private BTree btree = null; 167 168 171 protected Page page; 172 173 176 protected DataValueDescriptor row[]; 177 178 181 protected DataValueDescriptor[] scratch_row; 182 183 186 protected FetchDescriptor fetchDesc; 187 188 192 transient protected boolean use_last_search_result_hint = false; 193 194 198 transient protected int last_search_result = 0; 199 200 210 protected static final int CR_COLID_FIRST = 0; 211 protected static final int CR_VERSION_COLID = CR_COLID_FIRST + 0; 212 protected static final int CR_LEFTSIB_COLID = CR_COLID_FIRST + 1; 213 protected static final int CR_RIGHTSIB_COLID = CR_COLID_FIRST + 2; 214 protected static final int CR_PARENT_COLID = CR_COLID_FIRST + 3; 215 protected static final int CR_LEVEL_COLID = CR_COLID_FIRST + 4; 216 protected static final int CR_ISROOT_COLID = CR_COLID_FIRST + 5; 217 protected static final int CR_CONGLOM_COLID = CR_COLID_FIRST + 6; 218 protected static final int CR_COLID_LAST = CR_CONGLOM_COLID; 219 protected static final int CR_NCOLUMNS = CR_COLID_LAST + 1; 220 221 224 protected static final FormatableBitSet CR_VERSION_BITSET = 225 new FormatableBitSet(CR_VERSION_COLID + 1); 226 protected static final FormatableBitSet CR_LEFTSIB_BITSET = 227 new FormatableBitSet(CR_LEFTSIB_COLID + 1); 228 protected static final FormatableBitSet CR_RIGHTSIB_BITSET = 229 new FormatableBitSet(CR_RIGHTSIB_COLID + 1); 230 protected static final FormatableBitSet CR_PARENT_BITSET = 231 new FormatableBitSet(CR_PARENT_COLID + 1); 232 protected static final FormatableBitSet CR_LEVEL_BITSET = 233 new FormatableBitSet(CR_LEVEL_COLID + 1); 234 protected static final FormatableBitSet CR_ISROOT_BITSET = 235 new FormatableBitSet(CR_ISROOT_COLID + 1); 236 protected static final FormatableBitSet CR_CONGLOM_BITSET = 237 new FormatableBitSet(CR_CONGLOM_COLID + 1); 238 239 240 243 244 public static final int SPLIT_FLAG_LAST_ON_PAGE = 0x000000001; 245 246 public static final int SPLIT_FLAG_LAST_IN_TABLE = 0x000000002; 247 248 public static final int SPLIT_FLAG_FIRST_ON_PAGE = 0x000000004; 249 250 public static final int SPLIT_FLAG_FIRST_IN_TABLE = 0x000000008; 251 252 255 protected static final int CR_SLOT = 0; 256 257 260 261 static 262 { 263 CR_VERSION_BITSET.set(CR_VERSION_COLID); 264 CR_LEFTSIB_BITSET.set(CR_LEFTSIB_COLID); 265 CR_RIGHTSIB_BITSET.set(CR_RIGHTSIB_COLID); 266 CR_PARENT_BITSET.set(CR_PARENT_COLID); 267 CR_LEVEL_BITSET.set(CR_LEVEL_COLID); 268 CR_ISROOT_BITSET.set(CR_ISROOT_COLID); 269 CR_CONGLOM_BITSET.set(CR_CONGLOM_COLID); 270 } 271 272 278 protected ControlRow() 279 { 280 this.scratch_row = 281 new DataValueDescriptor[getNumberOfControlRowColumns()]; 282 283 this.fetchDesc = 284 new FetchDescriptor( 285 this.scratch_row.length, (FormatableBitSet) null, (Qualifier[][]) null); 286 } 287 288 305 protected ControlRow( 306 OpenBTree btree, 307 Page page, 308 int level, 309 ControlRow parent, 310 boolean isRoot 311 ) 312 throws StandardException 313 { 314 if (SanityManager.DEBUG) 316 { 317 SanityManager.ASSERT(page.isLatched()); 318 SanityManager.ASSERT(parent == null || parent.page.isLatched()); 319 } 320 321 this.page = page; 323 324 leftSiblingPageNumber = 327 new SQLLongint(btree.container.INVALID_PAGE_NUMBER); 328 rightSiblingPageNumber = 329 new SQLLongint(btree.container.INVALID_PAGE_NUMBER); 330 331 parentPageNumber = new SQLLongint( 333 (parent == null ? 334 btree.container.INVALID_PAGE_NUMBER : 335 parent.page.getPageNumber())); 336 337 this.isRoot = new SQLLongint(isRoot ? 1 : 0); 341 342 this.level = new SQLLongint(level); 344 this.version = new StorableFormatId(getTypeFormatId()); 345 346 this.btree = 350 (isRoot ? 351 btree.getConglomerate() : 352 (BTree) Monitor.newInstanceFromIdentifier( 353 btree.getConglomerate().getTypeFormatId())); 354 355 this.row = new DataValueDescriptor[getNumberOfControlRowColumns()]; 358 this.row[CR_VERSION_COLID] = this.version; 359 this.row[CR_LEFTSIB_COLID] = this.leftSiblingPageNumber; 360 this.row[CR_RIGHTSIB_COLID] = this.rightSiblingPageNumber; 361 this.row[CR_PARENT_COLID] = this.parentPageNumber; 362 this.row[CR_LEVEL_COLID] = this.level; 363 this.row[CR_ISROOT_COLID] = this.isRoot; 364 this.row[CR_CONGLOM_COLID] = this.btree; 365 366 367 page.setAuxObject(this); 370 } 371 372 388 protected ControlRow(ContainerHandle container, Page page) 389 throws StandardException 390 { 391 System.out.println("ControlRow construct 2."); 392 393 if (SanityManager.DEBUG) 395 SanityManager.ASSERT(page.isLatched()); 396 397 this.page = page; 399 400 } 403 404 405 406 416 protected int getVersion() 417 throws StandardException 418 { 419 if (this.version == null) 420 { 421 this.version = new StorableFormatId(); 423 424 scratch_row[CR_VERSION_COLID] = this.version; 425 426 fetchDesc.setValidColumns(CR_VERSION_BITSET); 427 428 this.page.fetchFromSlot( 429 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 430 } 431 return this.version.getValue(); 432 } 433 434 442 protected void setVersion(int version) 443 throws StandardException 444 { 445 if (this.version == null) 447 this.version = new StorableFormatId(); 448 this.version.setValue(version); 449 450 this.page.updateFieldAtSlot( 452 CR_SLOT, CR_VERSION_COLID, this.version, null); 453 } 454 455 466 public ControlRow getLeftSibling(OpenBTree btree) 467 throws StandardException, WaitError 468 { 469 ControlRow cr; 470 471 long pageno = this.getleftSiblingPageNumber(); 472 473 if (pageno == ContainerHandle.INVALID_PAGE_NUMBER) 475 return null; 476 477 cr = ControlRow.GetNoWait(btree, pageno); 479 if (cr == null) 480 throw new WaitError(); 481 482 return cr; 483 } 484 485 protected void setLeftSibling(ControlRow leftsib) 486 throws StandardException 487 { 488 long left_sib_pageno = 489 (leftsib == null ? ContainerHandle.INVALID_PAGE_NUMBER : 490 leftsib.page.getPageNumber()); 491 492 if (leftSiblingPageNumber == null) 494 leftSiblingPageNumber = new SQLLongint(left_sib_pageno); 495 else 496 this.leftSiblingPageNumber.setValue(left_sib_pageno); 497 498 try 500 { 501 this.page.updateFieldAtSlot( 502 CR_SLOT, CR_LEFTSIB_COLID, this.leftSiblingPageNumber, null); 503 } 504 catch (StandardException se) 505 { 506 if (SanityManager.DEBUG) 510 { 511 SanityManager.THROWASSERT( 512 "setLeftSibling got an exception: " + se + 513 "control_row = " + this + 514 "trying to update field number " + CR_LEFTSIB_COLID + 515 "to new value " + this.leftSiblingPageNumber); 516 } 517 throw(se); 518 } 519 } 520 521 528 protected ControlRow getRightSibling(OpenBTree open_btree) 529 throws StandardException 530 { 531 long pageno = this.getrightSiblingPageNumber(); 532 533 if (pageno == ContainerHandle.INVALID_PAGE_NUMBER) 535 return null; 536 else 537 return ControlRow.Get(open_btree, pageno); 538 } 539 540 protected void setRightSibling(ControlRow rightsib) 542 throws StandardException 543 { 544 long right_sib_pageno = 545 (rightsib == null ? ContainerHandle.INVALID_PAGE_NUMBER : 546 rightsib.page.getPageNumber()); 547 548 if (rightSiblingPageNumber == null) 550 rightSiblingPageNumber = new SQLLongint(right_sib_pageno); 551 else 552 this.rightSiblingPageNumber.setValue(right_sib_pageno); 553 554 try 556 { 557 this.page.updateFieldAtSlot( 558 CR_SLOT, CR_RIGHTSIB_COLID, this.rightSiblingPageNumber, null); 559 } 560 catch (StandardException se) 561 { 562 566 if (SanityManager.DEBUG) 567 { 568 SanityManager.THROWASSERT( 569 "setRightSibling got an exception: " + se + 570 "control_row = " + this + 571 "trying to update field number " + CR_RIGHTSIB_COLID + 572 "to new value " + this.rightSiblingPageNumber); 573 } 574 throw(se); 575 } 576 } 577 578 584 public long getleftSiblingPageNumber() 585 throws StandardException 586 { 587 if (this.leftSiblingPageNumber == null) 588 { 589 this.leftSiblingPageNumber = new SQLLongint(); 591 592 if (SanityManager.DEBUG) 593 SanityManager.ASSERT(scratch_row != null); 594 595 scratch_row[CR_LEFTSIB_COLID] = this.leftSiblingPageNumber; 596 597 fetchDesc.setValidColumns(CR_LEFTSIB_BITSET); 598 this.page.fetchFromSlot( 599 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 600 601 } 602 603 return(leftSiblingPageNumber.getLong()); 604 } 605 606 612 protected long getrightSiblingPageNumber() 613 throws StandardException 614 { 615 if (this.rightSiblingPageNumber == null) 616 { 617 this.rightSiblingPageNumber = new SQLLongint(); 619 620 scratch_row[CR_RIGHTSIB_COLID] = this.rightSiblingPageNumber; 621 622 fetchDesc.setValidColumns(CR_RIGHTSIB_BITSET); 623 this.page.fetchFromSlot( 624 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 625 } 626 627 return(rightSiblingPageNumber.getLong()); 628 } 629 630 638 protected long getParentPageNumber() 639 throws StandardException 640 { 641 if (this.parentPageNumber == null) 642 { 643 this.parentPageNumber = new SQLLongint(); 645 646 scratch_row[CR_PARENT_COLID] = this.parentPageNumber; 647 648 fetchDesc.setValidColumns(CR_PARENT_BITSET); 649 this.page.fetchFromSlot( 650 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 651 } 652 653 long pageno = parentPageNumber.getLong(); 655 return pageno; 656 } 657 658 void setParent(long parent) 659 throws StandardException 660 { 661 if (parentPageNumber == null) 663 parentPageNumber = new SQLLongint(); 664 this.parentPageNumber.setValue(parent); 665 666 try 668 { 669 this.page.updateFieldAtSlot( 670 CR_SLOT, CR_PARENT_COLID, this.parentPageNumber, null); 671 } 672 catch (StandardException se) 673 { 674 678 if (SanityManager.DEBUG) 679 { 680 SanityManager.THROWASSERT( 681 "setParent got an exception: " + se + 682 "control_row = " + this + 683 "trying to update field number " + CR_PARENT_COLID + 684 "to new value " + this.parentPageNumber); 685 } 686 throw(se); 687 } 688 689 return; 690 } 691 692 protected int getLevel() 693 throws StandardException 694 { 695 if (this.level == null) 696 { 697 this.level = new SQLLongint(); 699 700 scratch_row[CR_LEVEL_COLID] = this.level; 701 702 fetchDesc.setValidColumns(CR_LEVEL_BITSET); 703 this.page.fetchFromSlot( 704 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 705 } 706 707 return((int) this.level.getLong()); 708 } 709 710 protected void setLevel(int newlevel) 711 throws StandardException 712 { 713 if (this.level == null) 715 this.level = new SQLLongint(); 716 this.level.setValue((long) newlevel); 717 718 this.page.updateFieldAtSlot(CR_SLOT, CR_LEVEL_COLID, this.level, null); 720 } 721 722 protected boolean getIsRoot() 723 throws StandardException 724 { 725 727 if (this.isRoot == null) 728 { 729 this.isRoot = new SQLLongint(); 731 732 scratch_row[CR_ISROOT_COLID] = this.isRoot; 733 734 fetchDesc.setValidColumns(CR_ISROOT_BITSET); 735 this.page.fetchFromSlot( 736 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 737 } 738 739 return((this.isRoot.getLong() == 1)); 740 } 741 742 protected void setIsRoot(boolean isRoot) 743 throws StandardException 744 { 745 747 if (this.isRoot == null) 749 this.isRoot = new SQLLongint(); 750 751 this.isRoot.setValue((isRoot) ? 1 : 0); 752 753 this.page.updateFieldAtSlot( 755 CR_SLOT, CR_ISROOT_COLID, this.isRoot, null); 756 } 757 758 768 public BTree getConglom(int format_id) 769 throws StandardException 770 { 771 772 if (SanityManager.DEBUG) 773 { 774 SanityManager.ASSERT( 777 (this.page.getPageNumber() == BTree.ROOTPAGEID) && getIsRoot()); 778 } 779 780 if (this.btree == null) 781 { 782 this.btree = (BTree) Monitor.newInstanceFromIdentifier(format_id); 784 785 scratch_row[CR_CONGLOM_COLID] = this.btree; 786 787 fetchDesc.setValidColumns(CR_CONGLOM_BITSET); 788 this.page.fetchFromSlot( 789 (RecordHandle) null, CR_SLOT, scratch_row, fetchDesc, false); 790 } 791 return this.btree; 792 } 793 794 801 private void setConglom(BTree btree) 802 throws StandardException 803 { 804 807 this.page.updateFieldAtSlot(CR_SLOT, CR_CONGLOM_COLID, btree, null); 809 } 810 811 814 815 823 public static ControlRow Get(OpenBTree open_btree, long pageNumber) 824 throws StandardException 825 { 826 return(ControlRow.Get(open_btree.container, pageNumber)); 827 } 828 829 public static ControlRow Get(ContainerHandle container, long pageNumber) 830 throws StandardException 831 { 832 if (SanityManager.DEBUG) 833 { 834 SanityManager.ASSERT(container != null, 835 "ControlRow.Get() is being called on a closed container."); 836 } 837 838 Page page = container.getPage(pageNumber); 840 841 if (SanityManager.DEBUG) 842 { 843 if (page == null) 844 SanityManager.THROWASSERT( 845 "No page at pagenumber: " + pageNumber + 846 "; ContainerHandle = " + container); 847 } 848 849 return GetControlRowForPage(container, page); 851 } 852 853 859 public static ControlRow GetNoWait( 860 OpenBTree open_btree, 861 long pageNumber) 862 throws StandardException 863 { 864 Page page = open_btree.container.getUserPageNoWait(pageNumber); 867 if (page == null) 868 return null; 869 870 return GetControlRowForPage(open_btree.container, page); 873 } 874 875 protected static ControlRow GetControlRowForPage( 876 ContainerHandle container, 877 Page page) 878 throws StandardException 879 { 880 ControlRow cr = null; 881 882 AuxObject auxobject = page.getAuxObject(); 885 if (auxobject != null) 886 return (ControlRow) auxobject; 887 888 if (SanityManager.DEBUG) 889 SanityManager.ASSERT(page.recordCount() >= 1); 890 891 893 897 StorableFormatId version = new StorableFormatId(); 898 899 DataValueDescriptor[] version_ret = new DataValueDescriptor[1]; 900 901 version_ret[0] = version; 902 903 905 page.fetchFromSlot( 906 (RecordHandle) null, CR_SLOT, version_ret, 907 new FetchDescriptor(1, CR_VERSION_BITSET, (Qualifier[][]) null), 908 false); 909 910 cr = (ControlRow) Monitor.newInstanceFromIdentifier(version.getValue()); 912 cr.page = page; 913 914 cr.ControlRowInit(); 916 917 page.setAuxObject(cr); 919 920 return(cr); 921 } 922 923 926 public void release() 927 { 928 if (SanityManager.DEBUG) 929 SanityManager.ASSERT(page != null); 930 931 if (page != null) 932 page.unlatch(); 933 934 } 941 942 959 protected void searchForEntry(SearchParameters params) 960 throws StandardException 961 { 962 if (SanityManager.DEBUG) 963 { 964 } 968 969 970 int leftrange = 1; 974 int rightrange = page.recordCount() - 1; 975 976 int leftslot = 0; 981 int rightslot = rightrange + 1; 982 983 int midslot; 984 int compare_ret; 985 986 990 991 if (this.use_last_search_result_hint) 992 { 993 midslot = 995 ((this.last_search_result == 0) ? 1 : this.last_search_result); 996 997 if (midslot > rightrange) 998 midslot = rightrange; 999 } 1000 else 1001 { 1002 midslot = (leftrange + rightrange) / 2; 1005 } 1006 1007 if (SanityManager.DEBUG) 1008 { 1009 if ((leftslot != (rightslot - 1)) && 1010 !(midslot >= leftrange && midslot <= rightrange)) 1011 { 1012 SanityManager.THROWASSERT( 1013 "midslot = " + midslot + 1014 ";leftrange = " + leftrange + 1015 ";rightrange = " + rightrange); 1016 } 1017 } 1018 1019 1020 while (leftslot != (rightslot - 1)) 1021 { 1022 compare_ret = 1024 CompareIndexRowFromPageToKey( 1025 this, 1026 midslot, 1027 params.template, params.searchKey, 1028 params.btree.getConglomerate().nUniqueColumns, 1029 params.partial_key_match_op, 1030 params.btree.getConglomerate().ascDescInfo); 1031 1032 if (compare_ret == 0) 1033 { 1034 params.resultSlot = midslot; 1036 params.resultExact = true; 1037 1038 use_last_search_result_hint = 1040 (midslot == this.last_search_result) ? true : false; 1041 this.last_search_result = midslot; 1042 1043 return; 1044 } 1045 else if (compare_ret > 0) 1046 { 1047 rightslot = midslot; 1049 rightrange = midslot - 1; 1050 } 1051 else 1052 { 1053 leftslot = midslot; 1055 leftrange = midslot + 1; 1056 } 1057 1058 midslot = (leftrange + rightrange) / 2; 1059 } 1061 1062 this.use_last_search_result_hint = 1064 (leftslot == this.last_search_result); 1065 this.last_search_result = leftslot; 1066 1067 if (SanityManager.DEBUG) 1072 { 1073 if (leftslot != rightslot - 1) 1074 SanityManager.THROWASSERT( 1075 "leftslot = " + leftslot + "; rightslot = " + rightslot); 1076 } 1077 1078 params.resultSlot = leftslot; 1079 params.resultExact = false; 1080 1081 if (SanityManager.DEBUG) 1082 { 1083 } 1085 1086 return; 1087 } 1088 1089 protected void searchForEntryBackward(SearchParameters params) 1090 throws StandardException 1091 { 1092 if (SanityManager.DEBUG) 1093 { 1094 } 1098 1099 1100 int leftrange = 1; 1104 int rightrange = page.recordCount() - 1; 1105 1106 int leftslot = 0; 1111 int rightslot = rightrange + 1; 1112 1113 int midslot; 1114 int compare_ret; 1115 1116 1120 1121 if (this.use_last_search_result_hint) 1122 { 1123 midslot = 1125 ((this.last_search_result == 0) ? 1 : this.last_search_result); 1126 1127 if (midslot > rightrange) 1128 midslot = rightrange; 1129 } 1130 else 1131 { 1132 midslot = (leftrange + rightrange) / 2; 1135 } 1136 1137 if (SanityManager.DEBUG) 1138 { 1139 if ((leftslot != (rightslot - 1)) && 1140 !(midslot >= leftrange && midslot <= rightrange)) 1141 { 1142 SanityManager.THROWASSERT( 1143 "midslot = " + midslot + 1144 ";leftrange = " + leftrange + 1145 ";rightrange = " + rightrange); 1146 } 1147 } 1148 1149 1150 while (leftslot != (rightslot - 1)) 1151 { 1152 compare_ret = 1154 CompareIndexRowFromPageToKey( 1155 this, 1156 midslot, 1157 params.template, params.searchKey, 1158 params.btree.getConglomerate().nUniqueColumns, 1159 params.partial_key_match_op, 1160 params.btree.getConglomerate().ascDescInfo); 1161 1162 if (compare_ret == 0) 1163 { 1164 params.resultSlot = midslot; 1166 params.resultExact = true; 1167 1168 use_last_search_result_hint = 1170 (midslot == this.last_search_result) ? true : false; 1171 this.last_search_result = midslot; 1172 1173 return; 1174 } 1175 else if (compare_ret > 0) 1176 { 1177 rightslot = midslot; 1179 rightrange = midslot - 1; 1180 } 1181 else 1182 { 1183 leftslot = midslot; 1185 leftrange = midslot + 1; 1186 } 1187 1188 midslot = (leftrange + rightrange) / 2; 1189 } 1191 1192 this.use_last_search_result_hint = 1194 (leftslot == this.last_search_result); 1195 this.last_search_result = leftslot; 1196 1197 if (SanityManager.DEBUG) 1202 { 1203 if (leftslot != rightslot - 1) 1204 SanityManager.THROWASSERT( 1205 "leftslot = " + leftslot + "; rightslot = " + rightslot); 1206 } 1207 1208 params.resultSlot = leftslot; 1209 params.resultExact = false; 1210 1211 if (SanityManager.DEBUG) 1212 { 1213 } 1215 1216 return; 1217 } 1218 1219 1247 public static int CompareIndexRowFromPageToKey( 1248 ControlRow indexpage, 1249 int slot, 1250 DataValueDescriptor[] indexrow, 1251 DataValueDescriptor[] key, 1252 int nCompareCols, 1253 int partialKeyOrder, 1254 boolean[] ascOrDesc) 1255 throws StandardException 1256 { 1257 int compare_result; 1258 1259 int partialKeyCols = key.length; 1262 1263 indexpage.page.fetchFromSlot( 1269 (RecordHandle) null, slot, indexrow, 1270 (FetchDescriptor) null, 1271 true); 1272 1273 for (int i = 0; i < nCompareCols; i++) 1275 { 1276 if (i >= partialKeyCols) 1278 { 1279 return partialKeyOrder; 1291 } 1292 1293 1295 1298 1301 int r = indexrow[i].compare(key[i]); 1302 1303 if (r != 0) 1306 { 1307 1311 if (ascOrDesc[i]) return r; 1313 else 1314 return -r; 1315 } 1316 } 1317 1318 return 0; 1321 } 1322 1323 public static int CompareIndexRowToKey( 1324 DataValueDescriptor[] indexrow, 1325 DataValueDescriptor[] key, 1326 int nCompareCols, 1327 int partialKeyOrder, 1328 boolean[] ascOrDesc) 1329 throws StandardException 1330 { 1331 int partialKeyCols = key.length; 1334 1335 for (int i = 0; i < nCompareCols; i++) 1337 { 1338 if (i >= partialKeyCols) 1340 { 1341 return partialKeyOrder; 1353 } 1354 1355 DataValueDescriptor indexcol = indexrow[i]; 1357 DataValueDescriptor keycol = key[i]; 1358 1359 int r = indexcol.compare(keycol); 1361 1362 if (r != 0) 1365 { 1366 if (ascOrDesc[i]) return r; 1368 else 1369 return -r; 1370 } 1371 } 1372 1373 return 0; 1376 } 1377 1378 1402 protected void checkGeneric( 1403 OpenBTree btree, 1404 ControlRow parent, 1405 boolean check_other_pages) 1406 throws StandardException 1407 { 1408 if (SanityManager.DEBUG) 1409 { 1410 SanityManager.ASSERT(this.page.recordCount() >= 1); 1411 SanityManager.ASSERT(!this.page.isDeletedAtSlot(0)); 1412 1413 if (((parent != null) && 1415 (parent.page.getPageNumber() != this.getParentPageNumber()))) 1416 SanityManager.THROWASSERT(this + " not child of " + parent); 1417 1418 if (((parent != null) && 1420 (parent.getLevel() != this.getLevel() + 1))) 1421 SanityManager.THROWASSERT(this + 1422 " at wrong level when compared to parent:" + parent); 1423 1424 checkRowOrder(btree, parent); 1426 1427 if (check_other_pages) 1429 checkSiblings(btree); 1430 } 1431 } 1432 1433 1439 protected boolean checkRowOrder(OpenBTree btree, ControlRow parent) 1440 throws StandardException 1441 { 1442 if (SanityManager.DEBUG) 1443 { 1444 RecordHandle lesser_handle = null; 1445 RecordHandle greater_handle = null; 1446 DataValueDescriptor[] lesser = getRowTemplate(btree); 1447 DataValueDescriptor[] greater = getRowTemplate(btree); 1448 boolean is_consistent = true; 1449 1450 1451 int numslots = page.recordCount(); 1452 for (int i = ControlRow.CR_SLOT + 1; (i + 1) < numslots; i++) 1453 { 1454 lesser_handle = 1455 page.fetchFromSlot( 1456 (RecordHandle) null, i, lesser, 1457 (FetchDescriptor) null, true); 1458 greater_handle = 1459 page.fetchFromSlot( 1460 (RecordHandle) null, i + 1, greater, 1461 (FetchDescriptor) null, true); 1462 1463 SanityManager.ASSERT(btree.getConglomerate().nUniqueColumns <= 1464 btree.getConglomerate().nKeyFields); 1465 int compare_result = 1466 CompareIndexRowToKey( 1467 lesser, greater, 1468 btree.getConglomerate().nUniqueColumns, 0, 1469 btree.getConglomerate().ascDescInfo); 1470 1471 if (compare_result >= 0) 1473 { 1474 SanityManager.THROWASSERT( 1475 "Bad order of rows found in conglomerate: " + btree + 1476 "\n." + 1477 "compare result = " + compare_result + ". " + 1478 "nKeyFields = " + btree.getConglomerate().nKeyFields + 1479 ".\n" + 1480 this + " rows " + (i) + " and " + (i + 1) + 1481 " out of order.\n" + 1482 "row[" + i + "] + " + RowUtil.toString(lesser) + "\n" + 1483 "row[" + (i + 1) + "] + " + RowUtil.toString(greater) + 1484 "\ndump of page = " + 1485 debugPage(btree) + 1486 "\ndump of parent page = " + 1487 ((parent != null) ? 1488 parent.debugPage(btree) : "null parent") + 1489 "\rawstore dump = " + this.page); 1490 1491 is_consistent = false; 1492 } 1493 } 1494 return(is_consistent); 1495 } 1496 else 1497 { 1498 return(true); 1499 } 1500 } 1501 1502 protected boolean compareRowsOnSiblings( 1503 OpenBTree btree, 1504 ControlRow left_sib, 1505 ControlRow right_sib) 1506 throws StandardException 1507 { 1508 if (SanityManager.DEBUG) 1509 { 1510 boolean is_consistent = true; 1511 1512 if (left_sib.page.recordCount() > 1 && 1514 right_sib.page.recordCount() > 1) 1515 { 1516 DataValueDescriptor[] left_lastrow = getRowTemplate(btree); 1517 DataValueDescriptor[] right_firstrow = getRowTemplate(btree); 1518 1519 RecordHandle left_lastrow_handle = 1520 left_sib.page.fetchFromSlot( 1521 (RecordHandle) null, left_sib.page.recordCount() - 1, 1522 left_lastrow, 1523 (FetchDescriptor) null, true); 1524 1525 RecordHandle right_firstrow_handle = 1526 right_sib.page.fetchFromSlot( 1527 (RecordHandle) null, 1, right_firstrow, 1528 (FetchDescriptor) null, true); 1529 1530 int r = 1531 CompareIndexRowToKey( 1532 left_lastrow, right_firstrow, 1533 btree.getConglomerate().nUniqueColumns, 1534 0, btree.getConglomerate().ascDescInfo); 1535 1536 if (r >= 0) 1537 { 1538 SanityManager.THROWASSERT( 1539 "last row on left page " + 1540 left_sib.page.getPageNumber() + 1541 " > than first row on right page " + 1542 right_sib.page.getPageNumber() + "\n" + 1543 "left last row = " + RowUtil.toString(left_lastrow) + 1544 "right first row = " + RowUtil.toString(right_firstrow)+ 1545 left_sib + " last > first of " + right_sib); 1546 1547 is_consistent = false; 1548 } 1549 } 1550 return(is_consistent); 1551 } 1552 else 1553 { 1554 return(true); 1555 } 1556 } 1557 1558 1566 protected void checkSiblings(OpenBTree btree) 1567 throws StandardException 1568 { 1569 if (SanityManager.DEBUG) 1570 { 1571 ControlRow leftsib = null; 1573 ControlRow rightsib = null; 1574 1575 try 1576 { 1577 try 1578 { 1579 leftsib = this.getLeftSibling(btree); 1580 } 1581 catch (WaitError e) 1582 { 1583 1596 1600 leftsib = null; 1602 } 1603 1604 if (leftsib != null) 1606 { 1607 if (leftsib.getLevel() != this.getLevel()) 1609 SanityManager.THROWASSERT( 1610 (leftsib + "not at same level as " + this)); 1611 1612 long hopefullythis_pageno = 1614 leftsib.getrightSiblingPageNumber(); 1615 1616 if (hopefullythis_pageno != this.page.getPageNumber()) 1617 SanityManager.THROWASSERT( 1618 "right sibling of " + leftsib + " isn't " + this); 1619 1620 compareRowsOnSiblings(btree, leftsib, this); 1622 1623 leftsib.release(); 1625 leftsib = null; 1626 } 1627 1628 rightsib = this.getRightSibling(btree); 1630 1631 if (rightsib != null) 1633 { 1634 if (rightsib.getLevel() != this.getLevel()) 1636 SanityManager.THROWASSERT( 1637 rightsib + "not at same level as " + this); 1638 1639 long hopefullythis_pageno = 1641 rightsib.getleftSiblingPageNumber(); 1642 1643 if (hopefullythis_pageno != this.page.getPageNumber()) 1644 SanityManager.THROWASSERT( 1645 "left sibling of " + rightsib + " isn't " + this); 1646 1647 compareRowsOnSiblings(btree, this, rightsib); 1649 1650 rightsib.release(); 1652 rightsib = null; 1653 } 1654 } 1655 finally 1656 { 1657 if (leftsib != null) 1658 leftsib.release(); 1659 if (rightsib != null) 1660 rightsib.release(); 1661 } 1662 } 1663 } 1664 1665 1677 void linkRight(OpenBTree btree, ControlRow target) 1678 throws StandardException 1679 { 1680 ControlRow rightSibling = null; 1681 1682 try 1683 { 1684 rightSibling = target.getRightSibling(btree); 1685 this.setRightSibling(rightSibling); 1686 this.setLeftSibling(target); 1687 if (rightSibling != null) 1688 rightSibling.setLeftSibling(this); 1689 target.setRightSibling(this); 1690 } 1691 finally 1692 { 1693 if (rightSibling != null) 1694 rightSibling.release(); 1695 } 1696 } 1697 1698 1716 boolean unlink(OpenBTree btree) 1717 throws StandardException 1718 { 1719 ControlRow leftsib = null; 1720 ControlRow rightsib = null; 1721 1722 1723 try 1724 { 1725 1728 try 1729 { 1730 leftsib = this.getLeftSibling(btree); 1731 } 1732 catch (WaitError e) 1733 { 1734 return false; 1735 } 1736 1737 1740 rightsib = this.getRightSibling(btree); 1741 1742 1745 if (leftsib != null) 1746 leftsib.setRightSibling(rightsib); 1747 if (rightsib != null) 1748 rightsib.setLeftSibling(leftsib); 1749 1750 btree.container.removePage(this.page); 1755 1756 if (SanityManager.DEBUG) 1759 { 1760 SanityManager.ASSERT(!this.page.isLatched()); 1761 } 1762 1763 return true; 1764 } 1765 finally 1766 { 1767 if (leftsib != null) 1769 leftsib.release(); 1770 if (rightsib != null) 1771 rightsib.release(); 1772 } 1773 } 1774 1775 public Page getPage() 1776 { 1777 return(page); 1778 } 1779 1780 1789 protected final DataValueDescriptor[] getRow() 1790 { 1791 return(row); 1792 } 1793 1794 1798 1799 1815 abstract protected int checkConsistency( 1816 OpenBTree btree, 1817 ControlRow parent, 1818 boolean check_other_pages) 1819 throws StandardException; 1820 1821 1832 protected abstract ControlRow getLeftChild(OpenBTree btree) 1833 throws StandardException; 1834 1835 1846 protected abstract ControlRow getRightChild(OpenBTree btree) 1847 throws StandardException; 1848 1849 1854 protected abstract void ControlRowInit(); 1855 1856 1865 public abstract boolean isLeftmostLeaf() 1866 throws StandardException; 1867 1868 1877 public abstract boolean isRightmostLeaf() 1878 throws StandardException; 1879 1880 1891 public abstract ControlRow search( 1892 SearchParameters search_params) 1893 throws StandardException; 1894 1904 protected abstract int getNumberOfControlRowColumns(); 1905 1906 1920 protected abstract ControlRow searchLeft(OpenBTree btree) 1921 throws StandardException; 1922 1923 1937 protected abstract ControlRow searchRight(OpenBTree btree) 1938 throws StandardException; 1939 1940 1964 protected abstract boolean shrinkFor( 1965 OpenBTree btree, 1966 DataValueDescriptor[] key) 1967 throws StandardException; 1968 1969 1991 protected abstract long splitFor( 1992 OpenBTree open_btree, 1993 DataValueDescriptor[] template, 1994 BranchControlRow parentpage, 1995 DataValueDescriptor[] row, 1996 int flag) 1997 throws StandardException; 1998 1999 2004 public abstract void printTree( 2005 OpenBTree btree) 2006 throws StandardException; 2007 2008 2009 2010 2013 2014 2021 public void auxObjectInvalidated() 2022 { 2023 version = null; 2024 leftSiblingPageNumber = null; 2025 rightSiblingPageNumber = null; 2026 parentPageNumber = null; 2027 level = null; 2028 isRoot = null; 2029 page = null; 2030 } 2031 2032 2043 public DataValueDescriptor[] getRowTemplate(OpenBTree open_btree) 2044 throws StandardException 2045 { 2046 return(open_btree.getConglomerate().createTemplate()); 2047 } 2048 2049 2050 2053 2054 2062 public String debugPage( 2063 OpenBTree open_btree) 2064 throws StandardException 2065 { 2066 String ret_str; 2067 2068 if (SanityManager.DEBUG) 2069 { 2070 StringBuffer string = new StringBuffer (4096); 2071 string.append(this.toString()); 2072 string.append("\n"); 2073 2074 DataValueDescriptor[] row = getRowTemplate(open_btree); 2075 2076 string.append( 2077 ConglomerateUtil.debugPage( 2078 page, ControlRow.CR_SLOT + 1, false, row)); 2079 2080 ret_str = string.toString(); 2081 } 2082 else 2083 { 2084 ret_str = null; 2085 } 2086 2087 return(ret_str); 2088 } 2089 2090 2098 public String toString() 2099 { 2100 if (SanityManager.DEBUG) 2101 { 2102 StringBuffer string = new StringBuffer (4096); 2103 2104 try { 2105 2106 2107 string.append((getLevel() == 0) ? "\nLEAF" : "\nBRANCH"); 2109 string.append((getIsRoot()) ? "-ROOT" : ""); 2110 2111 string.append("("); 2114 string.append(this.page.getPageNumber()); 2115 string.append(")(lev="); 2116 string.append(level); 2117 string.append("): num recs = "); 2118 string.append(this.page.recordCount()); 2119 string.append("\n"); 2120 2121 string.append("\t"); 2123 2124 string.append("left = "); 2125 string.append(getleftSiblingPageNumber()); 2126 string.append(";"); 2127 2128 string.append("right = "); 2129 string.append(getrightSiblingPageNumber()); 2130 string.append(";"); 2131 2132 string.append("parent = "); 2133 string.append(getParentPageNumber()); 2134 string.append(";"); 2135 2136 string.append("isRoot = "); 2137 string.append(getIsRoot()); 2138 string.append(";"); 2139 2140 } 2141 catch (Throwable t) 2142 { 2143 string.append( 2144 "error encountered while doing ControlRow.toString()"); 2145 } 2146 2147 return(string.toString()); 2148 } 2149 else 2150 { 2151 return(null); 2152 } 2153 } 2154} 2155 | Popular Tags |