📄 storedpage.java
字号:
/* Derby - Class org.apache.derby.impl.store.raw.data.StoredPage Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.*/package org.apache.derby.impl.store.raw.data;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.impl.store.raw.data.BasePage;import org.apache.derby.impl.store.raw.data.LongColumnException;import org.apache.derby.impl.store.raw.data.OverflowInputStream;import org.apache.derby.impl.store.raw.data.PageVersion;import org.apache.derby.impl.store.raw.data.RecordId;import org.apache.derby.impl.store.raw.data.RawField;import org.apache.derby.impl.store.raw.data.ReclaimSpace;import org.apache.derby.impl.store.raw.data.StoredFieldHeader;import org.apache.derby.impl.store.raw.data.StoredRecordHeader;import org.apache.derby.iapi.services.io.FormatIdUtil;import org.apache.derby.iapi.services.io.FormatIdInputStream;import org.apache.derby.iapi.services.io.FormatIdOutputStream;import org.apache.derby.iapi.services.io.StoredFormatIds;import org.apache.derby.iapi.services.io.StreamStorable;import org.apache.derby.iapi.services.io.TypedFormat;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;import org.apache.derby.iapi.store.access.Qualifier;import org.apache.derby.iapi.store.access.RowUtil;import org.apache.derby.iapi.store.raw.ContainerHandle;import org.apache.derby.iapi.store.raw.FetchDescriptor;import org.apache.derby.iapi.store.raw.Page;import org.apache.derby.iapi.store.raw.PageKey;import org.apache.derby.iapi.store.raw.PageTimeStamp;import org.apache.derby.iapi.store.raw.RawStoreFactory;import org.apache.derby.iapi.store.raw.RecordHandle;import org.apache.derby.iapi.store.raw.log.LogInstant;import org.apache.derby.iapi.store.raw.xact.RawTransaction;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.types.Orderable;import org.apache.derby.iapi.services.io.ArrayInputStream;import org.apache.derby.iapi.services.io.ArrayOutputStream;import org.apache.derby.iapi.services.io.FormatableBitSet;import org.apache.derby.iapi.util.ByteArray;import org.apache.derby.iapi.services.io.CompressedNumber;import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;import org.apache.derby.iapi.services.io.LimitObjectInput;import org.apache.derby.iapi.services.io.ErrorObjectInput;import java.util.zip.CRC32;import java.io.IOException;import java.io.EOFException;import java.io.Externalizable;import java.io.InvalidClassException;import java.io.ObjectOutput;import java.io.ObjectInput;import java.io.DataInput;import java.io.DataOutput;import java.io.InputStream;import java.io.OutputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;/** StoredPage is a sub class of CachedPage that stores page data in a fixed size byte array and is designed to be written out to a file through a DataInput/DataOutput interface. A StoredPage can exist in its clean or dirty state without the FileContainer it was created from being in memory. <P><B>Page Format</B><BR> The page is broken into five sections <PRE> +----------+-------------+-------------------+-------------------+----------+ | formatId | page header | records | slot offset table | checksum | +----------+-------------+-------------------+-------------------+----------+ </PRE> <BR><B>FormatId</B><BR> The formatId is a 4 bytes array, it contains the format Id of this page. <BR><B>Page Header</B><BR> The page header is a fixed size, 56 bytes <PRE> 1 byte boolean is page an overflow page 1 byte byte page status (a field maintained in base page) 8 bytes long pageVersion (a field maintained in base page) 2 bytes unsigned short number of slots in slot offset table 4 bytes integer next record identifier 4 bytes integer generation number of this page (Future Use) 4 bytes integer previous generation of this page (Future Use) 8 bytes bipLocation the location of the beforeimage page (Future Use) 2 bytes unsigned short number of deleted rows on page. (new release 2.0) 2 bytes unsigned short % of the page to keep free for updates 2 bytes short spare for future use 4 bytes long spare for future use (encryption uses to write random bytes here). 8 bytes long spare for future use 8 bytes long spare for future use </PRE> Note that spare space has been guaranteed to be writen with "0", so that future use of field should not either not use "0" as a valid data item or pick 0 as a valid default value so that on the fly upgrade can assume that 0 means field was never assigned. <BR><B>Records</B> The records section contains zero or more records, the format of each record follows. minimumRecordSize is the minimum user record size, excluding the space we use for the record header and field headers. When a record is inserted, it is stored in a space at least as large as the sum of the minimumRecordSize and total header size. For example, If minimumRecordSize is 10 bytes, the user record is 7 bytes, we used 5 bytes for record and field headers, this record will take (10 + 5) bytes of space, extra 3 bytes is put into reserve. If minimumRecordSize is 10 bytes, user record is 17 bytes, we used 5 bytes for record and field headers, this record will take (17 + 5) bytes of space, no reserve space here. minimumRecordSize is defined by user on per container basis. The default for minimumRecordSize is set to 1. This implementation always keeps occupied bytes at the low end of the record section. Thus removing (purging) a record moves all other records down, and their slots are also moved down. A page has no empty slot (an empty page has no slot) <BR><B>Record & Field Format</B> Record Header format is defined in the StoredRecordHeader class. <PRE> <BR><B>Fields</B> 1 byte Boolean - is null, if true no more data follows. 4 bytes Integer - length of field that follows (excludes these four bytes). StoredPage will use the static method provided by StoredFieldHeader to read/write field status and field data length. Field Header format is defined in the StoredFieldHeader class. <data> </PRE> <BR><B>Slot Offset Table</B><BR> The slot offset table is a table of 6 or 12 bytes per record, depending on the pageSize being less or greater than 64K: 2 bytes (unsigned short) or 4 bytes (int) page offset for the record that is assigned to the slot, and 2 bytes (unsigned short) or 4 bytes (int) for the length of the record on this page. 2 bytes (unsigned short) or 4 bytes (int) for the length of the reserved number of bytes for this record on this page. First slot is slot 0. The slot table grows backwards. Slots are never left empty. <BR><B>Checksum</B><BR> 8 bytes of a java.util.zip.CRC32 checksum of the entire's page contents without the 8 bytes representing the checksum. <P><B>Page Access</B> The page data is accessed in this class by one of three methods. <OL> <LI>As a byte array using pageData (field in cachedPage). This is the fastest. <LI>As an ArrayInputStream (rawDataIn) and ArrayOutputStream (rawDataOut), this is used to set limits on any one reading the page logically. <LI>Logically through rawDataIn (ArrayInputStream) and logicalDataOut (FormatIdOutputStream), this provides the methods to write logical data (e.g. booleans and integers etc.) and the ObjectInput and ObjectOutput interfaces for DataValueDescriptor's. These logical streams are constructed using the array streams. </OL> @see java.util.zip.CRC32 @see ArrayInputStream @see ArrayOutputStream **/ /************************************************************************** * Public Methods of This class: ************************************************************************** */ /************************************************************************** * Public Methods of XXXX class: ************************************************************************** */public class StoredPage extends CachedPage{ /************************************************************************** * static final Fields of the class ************************************************************************** */ /* * typed format */ public static final int FORMAT_NUMBER = StoredFormatIds.RAW_STORE_STORED_PAGE; /** * Return my format identifier. **/ public int getTypeFormatId() { return StoredFormatIds.RAW_STORE_STORED_PAGE; } /** * Constants used to find different portions of data on the page. * <p> * The page is laid out as follows: * The page is broken into five sections * +----------+-------------+---------+-------------------+----------+ * | formatId | page header | records | slot offset table | checksum | * +----------+-------------+---------+-------------------+----------+ * * offset size section * ------ ------------------- -------------------------- * 0 PAGE_FORMAT_ID_SIZE formatId * PAGE_FORMAT_ID_SIZE: PAGE_HEADER_SIZE (56) page header * RECORD_SPACE_OFFSET: variable records **/ /** * Start of page, formatId must fit in 4 bytes. * <p> * where the page header starts - page format is mandated by cached page **/ protected static final int PAGE_HEADER_OFFSET = PAGE_FORMAT_ID_SIZE; /** * Fixed size of the page header **/ protected static final int PAGE_HEADER_SIZE = 56; /** Start of the record storage area */ /** * Start of the record storage area. * <p> * Note: a subclass may change the start of the record storage area. * Don't always count on this number. **/ protected static final int RECORD_SPACE_OFFSET = PAGE_HEADER_OFFSET + PAGE_HEADER_SIZE; /** * offset of the page version number **/ protected static final int PAGE_VERSION_OFFSET = PAGE_HEADER_OFFSET + 2; /** * SMALL_SLOT_SIZE are for pages smaller than 64K, * LARGE_SLOT_SIZE is for pages bigger than 64K. **/ protected static final int SMALL_SLOT_SIZE = 2; protected static final int LARGE_SLOT_SIZE = 4; /** * Size of the checksum stored on the page. * * The checksum is stored in the last 8 bytes of the page, the slot table * grows backward up the page starting at the end of the page just before * the checksum. **/ protected static final int CHECKSUM_SIZE = 8; /** * OVERFLOW_POINTER_SIZE - Number of bytes to reserve for overflow pointer * * The overflow pointer is the pointer that the takes the place of the * last column of a row if the row can't fit on the page. The pointer * then points to another page where the next column of the row can be * found. The overflow pointer can be bigger than a row, so when * overflowing a row the code must overflow enough columns so that there * is enough free space to write the row. Note this means that the * minimum space a row can take on a page must allow for at least the * size of the overflow pointers so that if the row is updated it can * write the over flow pointer. * **/ protected static final int OVERFLOW_POINTER_SIZE = 12; /** * OVERFLOW_PTR_FIELD_SIZE - Number of bytes of an overflow field * * This is the length to reserve for either an column or row overflow * pointer field. It includes the size of the field header plus the * maxium length of the overflow pointer (it could be shorter due to * compressed storage). * * The calcualtion is: * * OVERFLOW_PTR_FIELD_SIZE = * OVERFLOW_POINTER_SIZE + * sizeof(status byte) + * sizeof(field length field for a field which is just an overflow ptr) * * **/ protected static final int OVERFLOW_PTR_FIELD_SIZE = OVERFLOW_POINTER_SIZE + 1 + 1; /** * In memory buffer used as scratch space for streaming columns. **/ ByteHolder bh = null; /************************************************************************** * Fields of the class ************************************************************************** */ /** * Constants used in call to logColumn. * <p> * Action taken in this routine is determined by the kind of column as * specified in the columnFlag: * COLUMN_NONE - the column is insignificant * COLUMN_FIRST - this is the first column in a logRow() call * COLUMN_LONG - this is a known long column, therefore we will * store part of the column on the current page and * overflow the rest if necessary. **/ protected static final int COLUMN_NONE = 0; protected static final int COLUMN_FIRST = 1; protected static final int COLUMN_LONG = 2; /** * maxFieldSize is a worst case calculation for the size of a record * on an empty page, with a single field, but still allow room for * an overflow pointer if another field is to be added. See initSpace(). * maxFieldSize is a worst case calculation for the size of a record * * This is used as the threshold for a long column. * * maxFieldSize = * totalSpace * (1 - spareSpace/100) -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -