📄 storedpage.java
字号:
cleanPage(); // clean up the page array setPageVersion(0); // page is being created for the first time nextId = RecordHandle.FIRST_RECORD_ID; // first record Id generation = 0; prevGeneration = 0; // there is no previous generation bipLocation = 0L; createOutStreams(); } /** * Initialize the page from values in the page buffer. * <p> * Initialize in memory structure using the buffer in pageData. This * is how a StoredPage object is intialized to represent page read in * from disk. * <p> * * @param myContainer The container to read the page in from. * @param newIdentity The key representing page being read in (segment, * container, page number) * * @exception StandardException If the page cannot be read correctly, * or is inconsistent. **/ protected void initFromData( FileContainer myContainer, PageKey newIdentity) throws StandardException { if (myContainer != null) { // read in info about page stored once in the container header. spareSpace = myContainer.getSpareSpace(); minimumRecordSize = myContainer.getMinimumRecordSize(); } // if it is null, assume spareSpace and minimumRecordSize is the // same. We would only call initFromData after a restore then. try { readPageHeader(); initSlotTable(); } catch (IOException ioe) { // i/o methods on the byte array have thrown an IOException throw dataFactory.markCorrupt( StandardException.newException( SQLState.DATA_CORRUPT_PAGE, ioe, newIdentity)); } try { validateChecksum(newIdentity); } catch (StandardException se) { if (se.getMessageId().equals(SQLState.FILE_BAD_CHECKSUM)) { // it is remotely possible that the disk transfer got garbled, // i.e., the page is actually fine on disk but the version we // got has some rubbish on it. Double check. int pagesize = getPageSize(); byte[] corruptPage = pageData; pageData = null; // clear this // set up the new page array setPageArray(pagesize); try { myContainer.readPage(newIdentity.getPageNumber(), pageData); } catch (IOException ioe) { throw dataFactory.markCorrupt( StandardException.newException( SQLState.DATA_CORRUPT_PAGE, ioe, newIdentity)); } if (SanityManager.DEBUG) { SanityManager.DEBUG_CLEAR("TEST_BAD_CHECKSUM"); } // see if this read confirms the checksum error try { validateChecksum(newIdentity); } catch (StandardException sse) { // really bad throw dataFactory.markCorrupt(se); } // If we got here, this means the first read is bad but the // second read is good. This could be due to disk I/O error or // a bug in the way the file pointer is mis-managed. String firstImage = pagedataToHexDump(corruptPage); String secondImage = (SanityManager.DEBUG) ? toString() : pagedataToHexDump(corruptPage); throw StandardException.newException( SQLState.FILE_IO_GARBLED, se, newIdentity, firstImage, secondImage); } else { throw se; } } } /** * Validate the check sum on the page. * <p> * Compare the check sum stored in the page on disk with the checksum * calculated from the bytes on the page. * <p> * * @param id The key that describes the page. * * @exception StandardException Standard exception policy. **/ protected void validateChecksum(PageKey id) throws StandardException { long onDiskChecksum; try { // read the checksum stored on the page on disk. It is stored // in the last "CHECKSUM_SIZE" bytes of the page, and is a long. rawDataIn.setPosition(getPageSize() - CHECKSUM_SIZE); onDiskChecksum = rawDataIn.readLong(); } catch (IOException ioe) { // i/o methods on the byte array have thrown an IOException throw dataFactory.markCorrupt( StandardException.newException( SQLState.DATA_CORRUPT_PAGE, ioe, id)); } // Force the checksum to be recalculated based on the current page. checksum.reset(); checksum.update(pageData, 0, getPageSize() - CHECKSUM_SIZE); // force a bad checksum error if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("TEST_BAD_CHECKSUM")) { // set on disk checksum to wrong value onDiskChecksum = 123456789; } } if (onDiskChecksum != checksum.getValue()) { // try again using new checksum object to be doubly sure CRC32 newChecksum = new CRC32(); newChecksum.reset(); newChecksum.update(pageData, 0, getPageSize()-CHECKSUM_SIZE); if (onDiskChecksum != newChecksum.getValue()) { throw StandardException.newException( SQLState.FILE_BAD_CHECKSUM, id, new Long(checksum.getValue()), new Long(onDiskChecksum), pagedataToHexDump(pageData)); } else { // old one is bad, get rid of it if (SanityManager.DEBUG) SanityManager.THROWASSERT("old checksum gets wrong value"); checksum = newChecksum; } } } /** * Recalculate checksum and write it to the page array. * <p> * Recalculate the checksum of the page, and write the result back into * the last bytes of the page. * * @exception IOException if writing to end of array fails. **/ protected void updateChecksum() throws IOException { checksum.reset(); checksum.update(pageData, 0, getPageSize() - CHECKSUM_SIZE); rawDataOut.setPosition(getPageSize() - CHECKSUM_SIZE); logicalDataOut.writeLong(checksum.getValue()); } /** * Write information about page from variables into page byte array. * <p> * This routine insures that all information about the page is reflected * in the page byte buffer. This involves moving information from local * variables into encoded version on the page in page header and checksum. * <p> * * @return void. * * @param identity The key of this page. * * @exception StandardException Standard exception policy. **/ protected void writePage(PageKey identity) throws StandardException { if (SanityManager.DEBUG) { // some consistency checks on fields of the page, good to check // before we write them into the page. if ((freeSpace < 0) || (firstFreeByte + freeSpace) != (getSlotOffset(slotsInUse - 1))) { // make sure free space is not negative and does not overlap // used space. SanityManager.THROWASSERT("slotsInUse = " + slotsInUse + ", firstFreeByte = " + firstFreeByte + ", freeSpace = " + freeSpace + ", slotOffset = " + (getSlotOffset(slotsInUse - 1)) + ", page = " + this); } if ((slotsInUse == 0) && (firstFreeByte != (getPageSize() - totalSpace - CHECKSUM_SIZE))) { SanityManager.THROWASSERT("slotsInUse = " + slotsInUse + ", firstFreeByte = " + firstFreeByte + ", freeSpace = " + freeSpace + ", slotOffset = " + (getSlotOffset(slotsInUse - 1)) + ", page = " + this); } } try { if (headerOutOfDate) { updatePageHeader(); } else { // page version always need to be updated if page is dirty, // either do it in updatePageHeader or by itself updatePageVersion(); } updateChecksum(); } catch (IOException ioe) { // i/o methods on the byte array have thrown an IOException throw dataFactory.markCorrupt( StandardException.newException( SQLState.DATA_CORRUPT_PAGE, ioe, identity)); } } /** * Write out the format id of this page * * @param identity The key of this page. * * @exception StandardException Standard exception policy. **/ protected void writeFormatId(PageKey identity) throws StandardException { try { if (rawDataOut == null) createOutStreams(); rawDataOut.setPosition(0); FormatIdUtil.writeFormatIdInteger( logicalDataOut, getTypeFormatId()); } catch (IOException ioe) { // i/o methods on the byte array have thrown an IOException throw dataFactory.markCorrupt( StandardException.newException( SQLState.DATA_CORRUPT_PAGE, ioe, identity)); } } /************************************************************************** * Protected Methods of Cacheable Interface: ************************************************************************** */ /************************************************************************** * Protected OverRidden Methods of BasePage: ************************************************************************** */ /** * Ensure that the page is released from the cache when it is unlatched. * * @see org.apache.derby.impl.store.raw.data.BasePage#releaseExclusive * **/ protected void releaseExclusive() { super.releaseExclusive(); pageCache.release(this); } /** * Return the total number of bytes used, reserved, or wasted by the * record at this slot. * <p> * The amount of space the record on this slot is currently taking on the * page. * * If there is any reserve space or wasted space, count that in also * Do NOT count the slot entry size * <p> * * @return The number of bytes used by the row at slot "slot". * * @param slot look at row at this slot. * * @exception StandardException Standard exception policy. **/ public int getTotalSpace(int slot) throws StandardException { try { // A slot entry looks like the following: // 1st field: offset of the record on the page // 2nd field: length of the record on the page // 3rd field: amount of space reserved for the record to grow. // position the read at the beginning of the 2nd field. rawDataIn.setPosition(getSlotOffset(slot) + slotFieldSize); // return the size of the record + size of the reserved space. // the size of the fields to read is determined by slotFieldSize. return( ((slotFieldSize == SMALL_SLOT_SIZE) ? (rawDataIn.readUnsignedShort() + rawDataIn.readUnsignedShort()) : (rawDataIn.readInt() + rawDataIn.readInt()))); } catch (IOException ioe) { throw dataFactory.markCorrupt(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -