1 21 22 package org.apache.derby.impl.store.raw.data; 23 24 import org.apache.derby.iapi.services.sanity.SanityManager; 25 import org.apache.derby.iapi.error.StandardException; 26 import org.apache.derby.iapi.store.raw.ContainerHandle; 27 import org.apache.derby.iapi.store.raw.xact.RawTransaction; 28 29 import org.apache.derby.iapi.services.io.FormatableBitSet; 30 31 import java.io.Externalizable ; 32 import java.io.IOException ; 33 34 import java.io.ObjectOutput ; 35 import java.io.ObjectInput ; 36 37 114 115 116 public class AllocExtent implements Externalizable 117 { 118 private long extentOffset; private long extentStart; private long extentEnd; 128 private int extentLength; 130 int extentStatus; 131 132 private int preAllocLength; 133 134 private int reserved1; 135 private long reserved2; 136 private long reserved3; 137 138 private static final int HAS_DEALLOCATED = 0x1; 140 private static final int HAS_FREE = 0x2; 141 private static final int ALL_FREE = 0x4; 142 private static final int HAS_UNFILLED_PAGES = 0x10; 143 private static final int KEEP_UNFILLED_PAGES = 0x10000000; 144 private static final int NO_DEALLOC_PAGE_MAP = 0x20000000; 145 private static final int RETIRED = 0x8; 146 147 150 protected static final int ALLOCATED_PAGE = 0; 151 protected static final int DEALLOCATED_PAGE = 1; 152 protected static final int FREE_PAGE = 2; 153 154 155 FormatableBitSet freePages; 158 FormatableBitSet unFilledPages; 159 160 166 protected static int MAX_RANGE(int availspace) 167 { 168 169 int bookkeeping = 8 + 170 8 + 171 8 + 172 4 + 173 4 + 174 4 + 175 4 + 176 8 + 177 8 ; 178 availspace -= bookkeeping; 179 180 availspace /= 3; 182 183 if (availspace <= 0) 184 return 0; 185 186 return FormatableBitSet.maxBitsForSpace(availspace); 188 } 189 190 193 194 197 protected AllocExtent(long offset, long start, int length, int pagesize, int maxlength) { 203 if (SanityManager.DEBUG) 204 { 205 if (length > maxlength) 206 SanityManager.THROWASSERT( 207 "length " + length + " > maxlength " + maxlength); 208 } 209 210 211 this.extentOffset = offset; 212 this.extentStart = start; 213 this.extentEnd = start+maxlength-1; 214 215 this.extentLength = length; 216 preAllocLength = extentLength; 217 218 if (length > 0) 219 extentStatus = HAS_FREE | ALL_FREE ; 220 else 221 extentStatus = 0; 222 223 extentStatus |= KEEP_UNFILLED_PAGES; extentStatus |= NO_DEALLOC_PAGE_MAP; 226 int numbits = (1+(length/8))*8; 227 if (numbits > maxlength) 228 numbits = maxlength; 229 230 freePages = new FormatableBitSet(numbits); 231 unFilledPages = new FormatableBitSet(numbits); 232 233 for (int i = 0; i < length; i++) 236 freePages.set(i); 237 } 238 239 242 protected AllocExtent(AllocExtent original) 243 { 244 extentOffset = original.extentOffset; 245 extentStart = original.extentStart; 246 extentEnd = original.extentEnd; 247 extentLength = original.extentLength; 248 extentStatus = original.extentStatus; 249 preAllocLength = original.preAllocLength; 250 251 freePages = new FormatableBitSet(original.freePages); 252 unFilledPages = new FormatableBitSet(original.unFilledPages); 253 } 254 255 256 259 public AllocExtent() 260 { 261 } 262 263 264 public void writeExternal(ObjectOutput out) throws IOException 265 { 266 267 out.writeLong(extentOffset); 269 out.writeLong(extentStart); 270 out.writeLong(extentEnd); 271 out.writeInt(extentLength); 272 out.writeInt(extentStatus); 273 out.writeInt(preAllocLength); 274 out.writeInt(0); out.writeLong(0); out.writeLong(0); 278 freePages.writeExternal(out); 279 unFilledPages.writeExternal(out); 280 } 281 282 public void readExternal(ObjectInput in) 283 throws IOException , ClassNotFoundException 284 { 285 extentOffset = in.readLong(); 287 extentStart = in.readLong(); 288 extentEnd = in.readLong(); 289 extentLength = in.readInt(); 290 extentStatus = in.readInt(); 291 preAllocLength = in.readInt(); 292 reserved1 = in.readInt(); 293 reserved2 = in.readLong(); 294 reserved3 = in.readLong(); 295 296 freePages = new FormatableBitSet(); freePages.readExternal(in); 298 299 if ((extentStatus & NO_DEALLOC_PAGE_MAP) == 0) 301 { 302 FormatableBitSet deAllocPages = new FormatableBitSet(); 303 deAllocPages.readExternal(in); 304 freePages.or(deAllocPages); 306 extentStatus |= NO_DEALLOC_PAGE_MAP; } 308 309 if ((extentStatus & KEEP_UNFILLED_PAGES) == KEEP_UNFILLED_PAGES) 310 { 311 unFilledPages = new FormatableBitSet(); 312 unFilledPages.readExternal(in); 313 } 314 else { 316 unFilledPages = new FormatableBitSet(freePages.getLength()); 318 extentStatus |= KEEP_UNFILLED_PAGES; } 320 321 } 322 323 324 327 328 329 336 337 342 protected void allocPage(long pagenum) throws StandardException 343 { 344 if (SanityManager.DEBUG) 345 { 346 if (pagenum > getLastPagenum()) 347 { 348 if (pagenum > extentEnd) 350 SanityManager.THROWASSERT("pagenum " + pagenum + 351 " is out of beyond my range (" + 352 extentStart + "," + extentEnd + ")"); 353 if (pagenum != getLastPagenum() + 1) 354 SanityManager.THROWASSERT( 355 "skipping pages, lastPageNumber = " + getLastPagenum() + 356 " pageNumber = " + pagenum + "\n"); 357 } 358 else 359 { 360 checkInRange(pagenum); 362 363 int bitnum = (int)(pagenum-extentStart); 364 365 if (!freePages.isSet(bitnum)) 367 { 368 SanityManager.THROWASSERT( 369 "trying to re-allocate a page ( " + 370 pagenum + " ) that is already allocated "); 371 } 372 } 373 } 374 375 int bitnum = (int)(pagenum-extentStart); 378 379 if (bitnum >= freePages.getLength()) { 381 int numbits = (1+(bitnum/8))*8; 382 if (numbits > (int)(extentEnd - extentStart + 1)) 383 numbits = (int)(extentEnd - extentStart + 1); 384 385 freePages.grow(numbits); 386 unFilledPages.grow(numbits); 387 } 388 389 int numPageAlloced = (int)(pagenum-extentStart+1); 391 392 if (numPageAlloced > extentLength) 393 { 394 extentLength = numPageAlloced; 395 } 396 397 freePages.clear(bitnum); 398 399 } 403 404 410 protected void deallocPage(long pagenum) throws StandardException 411 { 412 int bitnum = (int)(pagenum-extentStart); 413 414 if (SanityManager.DEBUG) 416 { 417 if (freePages.isSet(bitnum)) 418 SanityManager.THROWASSERT( 419 "trying to deallocate a deallocated page " + pagenum); 420 } 421 422 freePages.set(bitnum); 423 unFilledPages.clear(bitnum); 425 setExtentFreePageStatus(true); 426 } 427 428 439 protected int compress( 440 BaseContainerHandle owner, 441 RawTransaction ntt, 442 AllocPage alloc_page) 443 throws StandardException 444 { 445 int compress_bitnum = -1; 446 int num_pages_compressed = 0; 447 448 for (int i = (extentLength - 1); i >= 0; i--) 449 { 450 if (freePages.isSet(i)) 451 { 452 compress_bitnum = i; 453 num_pages_compressed++; 454 } 455 else 456 { 457 break; 458 } 459 } 460 461 int new_highest_page = compress_bitnum - 1; 465 466 if (num_pages_compressed > 0) 467 { 468 if (SanityManager.DEBUG) 469 { 470 for (int i = new_highest_page + 1; i < extentLength; i++) 471 { 472 if (!freePages.isSet(i)) 473 { 474 475 SanityManager.THROWASSERT( 476 "compressPages with nonfree pg to truncate," + 477 "new_highest_page = " + new_highest_page + 478 "num_pages_truncated = " + num_pages_compressed + 479 ";extentLength = " + extentLength + 480 ";extentStart = " + extentStart + 481 ";freePages.isSet(" + i + ") = " + 482 freePages.isSet(i) + 483 "\nextent:\n" + toDebugString()); 484 } 485 } 486 487 SanityManager.ASSERT( 488 (new_highest_page + num_pages_compressed + 1) == 489 extentLength, 490 "truncate page count did not match: " + 491 ";new_highest_page = " + new_highest_page + 492 ";num_pages_truncated = " + num_pages_compressed + 493 ";extentLength = " + extentLength); 494 495 if (extentStart == 1) 500 { 501 SanityManager.ASSERT(new_highest_page >= 0); 502 503 if (num_pages_compressed >= extentLength) 504 { 505 SanityManager.THROWASSERT( 506 "new_highest_page = " + new_highest_page + 507 "num_pages_compressed = " + num_pages_compressed + 508 "; extentLength = " + extentLength + 509 "extent:\n" + toDebugString()); 510 } 511 } 512 } 513 514 522 523 524 owner.getAllocationActionSet().actionCompressSpaceOperation( 525 ntt, alloc_page, new_highest_page, num_pages_compressed); 526 return(compress_bitnum); 527 } 528 else 529 { 530 return(-1); 531 } 532 533 } 534 535 protected void compressPages( 536 int new_highest_page, 537 int num_pages_truncated) 538 { 539 if (SanityManager.DEBUG) 540 { 541 if (new_highest_page >= 0) 542 { 543 for (int i = new_highest_page + 1; i < extentLength; i++) 544 { 545 if (!freePages.isSet(i)) 546 { 547 SanityManager.THROWASSERT( 548 "compressPages with non free page to truncate," + 549 "new_highest_page = " + new_highest_page + 550 "num_pages_truncated = " + num_pages_truncated + 551 ";extentLength = " + extentLength + 552 ";extentStart = " + extentStart + 553 ";freePages.isSet(" + i + ") = " + 554 freePages.isSet(i) + 555 "\nextent:\n" + toDebugString()); 556 } 557 } 558 } 559 560 SanityManager.ASSERT( 561 (new_highest_page + num_pages_truncated + 1) == extentLength, 562 "truncate page count did not match: " + 563 ";new_highest_page = " + new_highest_page + 564 ";num_pages_truncated = " + num_pages_truncated + 565 ";extentLength = " + extentLength); 566 567 if (extentStart == 1) 572 { 573 SanityManager.ASSERT(new_highest_page >= 0); 574 SanityManager.ASSERT(num_pages_truncated < extentLength); 575 } 576 } 577 578 if (new_highest_page >= 0) 579 { 580 freePages.shrink(new_highest_page + 1); 581 unFilledPages.shrink(new_highest_page + 1); 582 583 preAllocLength = extentLength = (new_highest_page + 1); 586 } 587 588 return; 589 } 590 591 609 protected void undoCompressPages( 610 int new_highest_page, 611 int num_pages_truncated) 612 { 613 if (new_highest_page >= 0) 614 { 615 freePages.shrink(new_highest_page + 1); 616 unFilledPages.shrink(new_highest_page + 1); 617 preAllocLength = extentLength = (new_highest_page + 1); 618 } 619 620 return; 621 } 622 623 protected long getExtentEnd() 624 { 625 return extentEnd; 626 } 627 628 629 632 633 636 protected long getFreePageNumber(long pnum) 637 { 638 if (mayHaveFreePage()) 640 { 641 int i = (pnum < extentStart) ? freePages.anySetBit() : 646 freePages.anySetBit((int)(pnum-extentStart)); 647 648 if (i != -1) 649 { 650 if (SanityManager.DEBUG) 651 { 652 if (i >= extentLength) 653 SanityManager.THROWASSERT("returned bit = " + i + 654 " extent length = " + extentLength); 655 } 656 657 return i+extentStart; 658 } 659 660 if (pnum < extentStart) 663 setExtentFreePageStatus(false); 664 } 665 666 if (SanityManager.DEBUG) 668 SanityManager.ASSERT(extentStart+extentLength <= extentEnd); 669 670 return extentStart+extentLength; 673 } 674 675 676 686 protected long getPageOffset(long pagenum, int pagesize, boolean deallocOK) throws StandardException 687 { 688 return pagenum * pagesize; 689 } 690 691 694 protected boolean isRetired() 695 { 696 return ((extentStatus & RETIRED) != 0); 697 } 698 699 private boolean mayHaveFreePage() 700 { 701 return ((extentStatus & HAS_FREE) != 0); 702 } 703 704 private void setExtentFreePageStatus(boolean hasFree) 705 { 706 if (hasFree) 707 extentStatus |= HAS_FREE; 708 else 709 extentStatus &= ~HAS_FREE; 710 } 711 712 protected boolean canAddFreePage(long lastAllocatedPage) 713 { 714 if (extentStart + extentLength <= extentEnd) 716 return true; 717 718 if (!mayHaveFreePage()) 720 return false; 721 722 if (lastAllocatedPage < extentStart) 724 return (freePages.anySetBit() != -1); 725 else 726 return ((freePages.anySetBit((int)(lastAllocatedPage-extentStart))) != -1); 727 } 728 729 732 protected int getPageStatus(long pagenum) 733 { 734 if (SanityManager.DEBUG) 735 checkInRange(pagenum); 736 737 int status = 0; 738 int bitnum = (int)(pagenum-extentStart); 739 740 if (freePages.isSet(bitnum)) 741 status = FREE_PAGE; 742 else 743 status = ALLOCATED_PAGE; 744 745 return status; 746 } 747 748 749 752 protected long getFirstPagenum() 753 { 754 return extentStart; 755 } 756 757 760 protected long getLastPagenum() 761 { 762 return extentStart+extentLength-1; 763 } 764 765 773 protected long getPagenum(int bit_pos) 774 { 775 return(extentStart + bit_pos); 776 } 777 778 779 780 783 784 787 protected long getLastPreallocPagenum() 788 { 789 if (extentLength > preAllocLength) 790 preAllocLength = extentLength; 791 792 return extentStart + preAllocLength - 1 ; 793 } 794 795 798 protected void setLastPreallocPagenum(long preAllocPagenum) 799 { 800 if (SanityManager.DEBUG) 801 SanityManager.ASSERT(preAllocPagenum >= getLastPreallocPagenum(), 802 "setLastPreallocPagenum set to small prealloc length than before"); 803 804 if (preAllocPagenum > extentEnd) 806 preAllocPagenum = extentEnd; 807 808 preAllocLength = (int)(preAllocPagenum - extentStart + 1); 809 } 810 811 812 817 protected long getNextValidPageNumber(long prevPageNumber) 818 { 819 long pageNum; 820 long lastpage = getLastPagenum(); 821 822 if (prevPageNumber < extentStart) 823 pageNum = extentStart; 824 else 825 pageNum = prevPageNumber +1; 826 827 while(pageNum <= lastpage) 828 { 829 int status = getPageStatus(pageNum); 830 if (status == ALLOCATED_PAGE) 831 break; 832 pageNum++; 833 } 834 835 if (pageNum > lastpage) 836 pageNum = ContainerHandle.INVALID_PAGE_NUMBER; 837 return pageNum; 838 } 839 840 841 protected long getLastValidPageNumber() 842 { 843 long pageNum = getLastPagenum(); 844 while(pageNum >= extentStart) 845 { 846 int status = getPageStatus(pageNum); 847 if (status == ALLOCATED_PAGE) 848 break; 849 pageNum--; 850 } 851 if (pageNum < extentStart) 852 pageNum = ContainerHandle.INVALID_PAGE_NUMBER; 853 return pageNum; 854 } 855 856 private void checkInRange(long pagenum) 857 { 858 if (SanityManager.DEBUG) 859 if (pagenum < extentStart || pagenum >= extentStart+extentLength) 860 SanityManager.THROWASSERT( 861 "pagenum " + pagenum + " out of range"); 862 } 863 864 protected void updateUnfilledPageInfo(AllocExtent inputExtent) 865 { 866 if (SanityManager.DEBUG) 867 { 868 if (inputExtent.unFilledPages.getLength() != 869 unFilledPages.getLength()) 870 { 871 SanityManager.THROWASSERT( 872 "inputExtent's unfilled page length " + 873 inputExtent.unFilledPages.getLength() + 874 " != extent's unfilled page length " + 875 unFilledPages.getLength()); 876 } 877 } 878 879 884 unFilledPages = inputExtent.unFilledPages; 889 890 if (unFilledPages.anySetBit() >= 0) 891 extentStatus |= HAS_UNFILLED_PAGES; 892 else 893 extentStatus &= ~HAS_UNFILLED_PAGES; 894 } 895 896 899 protected boolean trackUnfilledPage(long pagenumber, boolean unfilled) 900 { 901 checkInRange(pagenumber); 902 903 int bitnum = (int)(pagenumber-extentStart); 904 905 boolean bitSet = unFilledPages.isSet(bitnum); 906 if (unfilled != bitSet) 907 { 908 if (unfilled) 909 { 910 unFilledPages.set(bitnum); 911 extentStatus |= HAS_UNFILLED_PAGES; 912 } 913 else 914 unFilledPages.clear(bitnum); 915 return true; 916 } 917 918 return false; 919 } 920 921 925 protected long getUnfilledPageNumber(long pagenum) 926 { 927 if ((extentStatus & HAS_UNFILLED_PAGES) == 0) 928 return ContainerHandle.INVALID_PAGE_NUMBER; 929 930 int i = unFilledPages.anySetBit(); 931 932 if (i != -1) 933 { 934 if (i+extentStart != pagenum) 935 return i+extentStart; 936 else 937 { 938 i = unFilledPages.anySetBit(i); 946 if (i != -1) 947 return i+extentStart; 948 } 949 } 950 951 return ContainerHandle.INVALID_PAGE_NUMBER; 952 953 } 954 955 958 protected int getAllocatedPageCount() 959 { 960 int allocatedPageCount = extentLength; 962 963 if (!mayHaveFreePage()) 964 return allocatedPageCount; 965 966 967 byte[] free = freePages.getByteArray(); 968 int numBytes = free.length; 969 970 for (int i = 0; i < numBytes; i++) 971 { 972 if (free[i] != 0) 973 { 974 for (int j = 0; j < 8; j++) 975 { 976 if (((1 << j) & free[i]) != 0) 977 { 978 allocatedPageCount--; 979 } 980 } 981 } 982 } 983 984 if (SanityManager.DEBUG) 985 { 986 if (allocatedPageCount < 0) 987 { 988 SanityManager.THROWASSERT( 989 "number of allocated page < 0, val =" + allocatedPageCount + 990 "\nextent = " + toDebugString()); 991 } 992 } 993 994 return allocatedPageCount; 995 } 996 997 998 1001 protected int getUnfilledPageCount() 1002 { 1003 int unfilledPageCount = 0; 1004 int freePagesSize = freePages.size(); 1005 1006 for (int i = 0; i < unFilledPages.size(); i++) 1007 { 1008 if (unFilledPages.isSet(i) && 1009 (i >= freePagesSize || !freePages.isSet(i))) 1010 unfilledPageCount++; 1011 } 1012 1013 if (SanityManager.DEBUG) 1014 SanityManager.ASSERT(unfilledPageCount >= 0, 1015 "number of unfilled pages < 0"); 1016 1017 return unfilledPageCount; 1018 } 1019 1020 1021 1024 protected int getTotalPageCount() 1025 { 1026 return extentLength; 1027 } 1028 1029 protected String toDebugString() 1030 { 1031 if (SanityManager.DEBUG) 1032 { 1033 String str = 1034 "------------------------------------------------------------------------------\n" + 1035 "Extent map of from page " + extentStart + " to page " + extentEnd + "\n"; 1036 1037 for (long i = extentStart; i < extentStart+extentLength; i++) 1038 { 1039 str += "\tpage " + i + ": "; 1040 switch(getPageStatus(i)) 1041 { 1042 case FREE_PAGE: str += "free page\n"; break; 1043 case ALLOCATED_PAGE: str += "valid, in use page\n"; break; 1044 } 1045 1046 } 1050 1051 if (getLastPagenum() < extentEnd) 1052 str += "\tFrom " + getLastPagenum() + " to " + extentEnd + 1053 " are un-allocated pages\n"; 1054 1055 str += "------------------------------------------------------------------------------\n"; 1056 1057 return str; 1058 } 1059 else 1060 return null; 1061 } 1062 1063} 1064 | Popular Tags |