1 21 22 package org.apache.derby.impl.store.raw.data; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 26 import org.apache.derby.impl.store.raw.data.BasePage; 27 28 import org.apache.derby.iapi.store.raw.log.LogInstant; 29 import org.apache.derby.iapi.store.raw.ContainerHandle; 30 import org.apache.derby.iapi.store.raw.PageKey; 31 32 import org.apache.derby.iapi.services.cache.Cacheable; 33 import org.apache.derby.iapi.services.cache.CacheManager; 34 import org.apache.derby.iapi.services.context.ContextService; 35 36 import org.apache.derby.iapi.services.monitor.Monitor; 37 38 import org.apache.derby.iapi.services.sanity.SanityManager; 39 40 import org.apache.derby.iapi.services.io.FormatIdUtil; 41 import org.apache.derby.iapi.services.io.StoredFormatIds; 42 43 import org.apache.derby.iapi.error.StandardException; 44 import org.apache.derby.iapi.error.ExceptionSeverity; 45 import java.io.IOException ; 46 47 54 55 public abstract class CachedPage extends BasePage implements Cacheable 56 { 57 protected boolean alreadyReadPage; 60 protected byte[] pageData; 63 74 protected boolean isDirty; 78 protected boolean preDirty; 83 84 protected int initialRowCount; 87 private long containerRowCount; 91 94 95 100 protected CacheManager pageCache; 101 102 107 protected CacheManager containerCache; 108 109 114 protected BaseDataFileFactory dataFactory; 116 117 protected static final int PAGE_FORMAT_ID_SIZE = 4; 118 119 122 public static final int WRITE_SYNC = 1; 123 124 127 public static final int WRITE_NO_SYNC = 2; 128 129 public CachedPage() 130 { 131 super(); 132 } 133 134 public final void setFactory(BaseDataFileFactory factory) 135 { 136 dataFactory = factory; 137 pageCache = factory.getPageCache(); 138 containerCache = factory.getContainerCache(); 139 } 140 141 147 protected void initialize() 148 { 149 super.initialize(); 150 isDirty = false; 151 preDirty = false; 152 initialRowCount = 0; 153 containerRowCount = 0; 154 } 155 156 159 160 173 public Cacheable setIdentity(Object key) 174 throws StandardException 175 { 176 if (SanityManager.DEBUG) 177 { 178 SanityManager.ASSERT(key instanceof PageKey); 179 } 180 181 initialize(); 182 183 PageKey newIdentity = (PageKey) key; 184 185 FileContainer myContainer = 186 (FileContainer) containerCache.find(newIdentity.getContainerId()); 187 188 setContainerRowCount(myContainer.getEstimatedRowCount(0)); 189 190 try 191 { 192 if (!alreadyReadPage) 193 { 194 readPage(myContainer, newIdentity); 196 } 197 else 198 { 199 alreadyReadPage = false; 201 } 202 203 int fmtId = getTypeFormatId(); 206 207 int onPageFormatId = FormatIdUtil.readFormatIdInteger(pageData); 208 if (fmtId != onPageFormatId) 209 { 210 return changeInstanceTo( 211 onPageFormatId, newIdentity).setIdentity(key); 212 } 213 214 initFromData(myContainer, newIdentity); 216 } 217 finally 218 { 219 containerCache.release(myContainer); 220 myContainer = null; 221 } 222 223 fillInIdentity(newIdentity); 224 225 initialRowCount = 0; 226 227 return this; 228 } 229 230 249 public Cacheable createIdentity( 250 Object key, 251 Object createParameter) 252 throws StandardException 253 { 254 255 if (SanityManager.DEBUG) 256 { 257 SanityManager.ASSERT(key instanceof PageKey); 258 } 259 260 initialize(); 261 262 PageKey newIdentity = (PageKey) key; 263 264 int[] createArgs = (int[]) createParameter; 265 266 if (createArgs[0] == -1) 267 { 268 throw StandardException.newException( 269 SQLState.DATA_UNKNOWN_PAGE_FORMAT, newIdentity); 270 } 271 272 if (createArgs[0] != getTypeFormatId()) 276 { 277 return( 278 changeInstanceTo(createArgs[0], newIdentity).createIdentity( 279 key, createParameter)); 280 } 281 282 initializeHeaders(5); 284 createPage(newIdentity, createArgs); 285 286 fillInIdentity(newIdentity); 287 288 initialRowCount = 0; 289 290 304 if ((createArgs[1] & WRITE_SYNC) != 0 || 305 (createArgs[1] & WRITE_NO_SYNC) != 0) 306 writePage(newIdentity, (createArgs[1] & WRITE_SYNC) != 0); 307 308 if (SanityManager.DEBUG) 309 { 310 if (SanityManager.DEBUG_ON(FileContainer.SPACE_TRACE)) 311 { 312 String syncFlag = 313 ((createArgs[1] & WRITE_SYNC) != 0) ? "Write_Sync" : 314 (((createArgs[1] & WRITE_NO_SYNC) != 0) ? "Write_NO_Sync" : 315 "No_write"); 316 317 SanityManager.DEBUG( 318 FileContainer.SPACE_TRACE, 319 "creating new page " + newIdentity + " with " + syncFlag); 320 } 321 } 322 323 return this; 324 } 325 326 343 private CachedPage changeInstanceTo(int fid, PageKey newIdentity) 344 throws StandardException 345 { 346 CachedPage realPage; 347 try 348 { 349 realPage = 350 (CachedPage) Monitor.newInstanceFromIdentifier(fid); 351 352 } 353 catch (StandardException se) 354 { 355 if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY) 356 { 357 throw se; 358 } 359 else 360 { 361 throw StandardException.newException( 362 SQLState.DATA_UNKNOWN_PAGE_FORMAT, se, newIdentity); 363 } 364 } 365 366 realPage.setFactory(dataFactory); 367 368 if (this.pageData != null) 372 { 373 realPage.alreadyReadPage = true; 374 realPage.usePageBuffer(this.pageData); 375 } 376 377 380 383 389 return realPage; 390 } 391 392 410 public boolean isDirty() 411 { 412 synchronized (this) 413 { 414 return isDirty || preDirty; 415 } 416 } 417 418 426 public boolean isActuallyDirty() 427 { 428 synchronized (this) 429 { 430 return isDirty; 431 } 432 } 433 434 439 public void preDirty() 440 { 441 synchronized (this) 442 { 443 if (!isDirty) 444 preDirty = true; 445 } 446 } 447 448 454 protected void setDirty() 455 { 456 synchronized (this) 457 { 458 isDirty = true; 459 preDirty = false; 460 } 461 } 462 463 469 protected void releaseExclusive() 470 { 471 if (isDirty && !isOverflowPage() && 481 (containerRowCount / 8) < recordCount()) 482 { 483 int currentRowCount = internalNonDeletedRecordCount(); 484 int delta = currentRowCount-initialRowCount; 485 int posDelta = delta > 0 ? delta : (-delta); 486 487 if ((containerRowCount/8) < posDelta) 488 { 489 FileContainer myContainer = null; 493 494 try 495 { 496 myContainer = (FileContainer) 497 containerCache.find(identity.getContainerId()); 498 499 if (myContainer != null) 500 { 501 myContainer.updateEstimatedRowCount(delta); 502 setContainerRowCount( 503 myContainer.getEstimatedRowCount(0)); 504 505 initialRowCount = currentRowCount; 506 507 myContainer.trackUnfilledPage( 510 identity.getPageNumber(), unfilled()); 511 } 512 } 513 catch (StandardException se) 514 { 515 } 518 finally 519 { 520 if (myContainer != null) 521 containerCache.release(myContainer); 522 } 523 } 524 } 525 526 super.releaseExclusive(); 527 } 528 529 530 546 public void clean(boolean remove) throws StandardException 547 { 548 549 synchronized (this) 551 { 552 if (!isDirty()) 553 return; 554 555 while (inClean) 557 { 558 try 559 { 560 wait(); 561 } 562 catch (InterruptedException ie) 563 { 564 throw StandardException.interrupt(ie); 565 } 566 } 567 568 570 if (!isDirty()) 571 return; 572 573 inClean = true; 574 575 while ((owner != null) && !preLatch) 580 { 581 try 582 { 583 wait(); 584 } 585 catch (InterruptedException ie) 586 { 587 inClean = false; 588 throw StandardException.interrupt(ie); 589 } 590 } 591 592 if (!isActuallyDirty()) 596 { 597 preDirty = false; 600 inClean = false; 601 notifyAll(); 602 return; 603 } 604 } 605 606 try 607 { 608 writePage(getPageId(), false); 609 } 610 catch(StandardException se) 611 { 612 throw dataFactory.markCorrupt(se); 621 } 622 finally 623 { 624 628 synchronized (this) 629 { 630 inClean = false; 631 notifyAll(); 632 } 633 } 634 } 635 636 public void clearIdentity() 637 { 638 alreadyReadPage = false; 639 super.clearIdentity(); 640 } 641 642 654 private void readPage( 655 FileContainer myContainer, 656 PageKey newIdentity) 657 throws StandardException 658 { 659 int pagesize = myContainer.getPageSize(); 660 661 setPageArray(pagesize); 664 665 for (int io_retry_count = 0;;) 666 { 667 try 668 { 669 myContainer.readPage(newIdentity.getPageNumber(), pageData); 670 break; 671 } 672 catch (IOException ioe) 673 { 674 io_retry_count++; 675 676 if (io_retry_count > 4) 690 { 691 693 StandardException se = 694 StandardException.newException( 695 SQLState.FILE_READ_PAGE_EXCEPTION, 696 ioe, newIdentity, new Integer (pagesize)); 697 698 699 if (dataFactory.getLogFactory().inRFR()) 700 { 701 throw se; 708 } 709 else 710 { 711 if (SanityManager.DEBUG) 712 { 713 throw dataFactory.markCorrupt(se); 716 } 717 else 718 { 719 throw se; 724 } 725 } 726 } 727 } 728 } 729 } 730 731 732 741 private void writePage( 742 PageKey identity, 743 boolean syncMe) 744 throws StandardException 745 { 746 747 writeFormatId(identity); 749 750 writePage(identity); 753 754 LogInstant flushLogTo = getLastLogInstant(); 759 dataFactory.flush(flushLogTo); 760 761 if (flushLogTo != null) 762 { 763 clearLastLogInstant(); 764 } 765 766 767 FileContainer myContainer = 769 (FileContainer) containerCache.find(identity.getContainerId()); 770 771 if (myContainer != null) 772 { 773 try 774 { 775 myContainer.writePage( 776 identity.getPageNumber(), pageData, syncMe); 777 778 783 if (!isOverflowPage() && isDirty()) 784 { 785 786 myContainer.trackUnfilledPage( 789 identity.getPageNumber(), unfilled()); 790 791 int currentRowCount = internalNonDeletedRecordCount(); 800 801 if (currentRowCount != initialRowCount) 802 { 803 myContainer.updateEstimatedRowCount( 804 currentRowCount - initialRowCount); 805 806 setContainerRowCount( 807 myContainer.getEstimatedRowCount(0)); 808 809 initialRowCount = currentRowCount; 810 } 811 } 812 813 } 814 catch (IOException ioe) 815 { 816 throw StandardException.newException( 818 SQLState.FILE_WRITE_PAGE_EXCEPTION, 819 ioe, identity, new Integer (myContainer.getPageSize())); 820 } 821 finally 822 { 823 containerCache.release(myContainer); 824 myContainer = null; 825 } 826 } 827 else 828 { 829 StandardException nested = 830 StandardException.newException( 831 SQLState.DATA_CONTAINER_VANISHED, 832 identity.getContainerId()); 833 throw dataFactory.markCorrupt( 834 StandardException.newException( 835 SQLState.FILE_WRITE_PAGE_EXCEPTION, nested, 836 identity, new Integer (myContainer.getPageSize()))); 837 } 838 839 synchronized (this) 840 { 841 isDirty = false; 843 preDirty = false; 844 } 845 } 846 847 public void setContainerRowCount(long rowCount) 848 { 849 containerRowCount = rowCount; 850 } 851 852 856 857 protected void setPageArray(int pageSize) throws StandardException 858 { 859 if ((pageData == null) || (pageData.length != pageSize)) 860 { 861 pageData = new byte[pageSize]; 862 863 if (pageData == null || pageData.length != pageSize) 864 { 865 throw StandardException.newException( 866 SQLState.DATA_OBJECT_ALLOCATION_FAILED, "PAGE"); 867 } 868 869 usePageBuffer(pageData); 870 } 871 } 872 873 874 887 protected byte[] getPageArray() throws StandardException 888 { 889 writeFormatId(identity); 891 892 writePage(identity); 895 896 return pageData; 897 } 898 899 900 901 protected abstract void usePageBuffer(byte[] buffer); 905 906 907 protected abstract void initFromData(FileContainer container, PageKey id) 909 throws StandardException; 910 911 912 protected abstract void createPage(PageKey id, int[] args) 914 throws StandardException; 915 916 protected abstract void writePage(PageKey id) throws StandardException; 918 919 protected abstract void writeFormatId(PageKey identity) 921 throws StandardException; 922 } 923 | Popular Tags |