📄 allocextent.java
字号:
/* Derby - Class org.apache.derby.impl.store.raw.data.AllocExtent 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.services.sanity.SanityManager;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.store.raw.ContainerHandle;import org.apache.derby.iapi.store.raw.xact.RawTransaction; import org.apache.derby.iapi.services.io.FormatableBitSet;import java.io.Externalizable;import java.io.IOException;import java.io.ObjectOutput;import java.io.ObjectInput;/** An allocation extent row manages the page status of page in the extent. AllocExtent is externalizable and is written to the AllocPage directly, without being converted to a row first. <P> <PRE> @format_id none, format implied by AllocPage's format @purpose manage page status of page in extent @upgrade @disk_layout extentOffset(long) the begin physical byte offset of the first page of this extent extentStart(long) the first logical page mananged by this extent. extentEnd(long) the last page this extent can ever hope to manage extentLength(int) the number of pages allocated in this extent extentStatus(int) status bits for the whole extent. HAS_DEALLOCATED - most likely, this extent has a deallocated page somewhere If !HAD_DEALLOCATED, the extent has no deallocated page HAS_FREE - most likely, this extent has a free page somewhere If !HAS_FREE, there is no free page in the extent ALL_FREE - most likely, this extent only has free pages, good candidate for shrinking the file. If !ALL_FREE, the extent is not all free HAS_UNFILLED_PAGES - most likely, this extent has unfilled pages. if !HAS_UNFILLED_PAGES, all pages are filled KEEP_UNFILLED_PAGES - this extent keeps track of unfilled pages (post v1.3). If not set, this extent has no notion of unfilled page and has no unFilledPage bitmap. NO_DEALLOC_PAGE_MAP - this extents do not have a dealloc and a free page bit maps. Prior to 2.0, there are 2 bit maps, a deallocate page bit map and a free page bit map. Cloudscape 2.0 and later merged the dealloc page bit map into the free page bit map. RETIRED - this extent contains only 'retired' pages, never use any page from this extent. The pages don't actually exist, i.e., it maps to nothing (physicalOffset is garbage). The purpose of this extent is to blot out a range of logical page numbers that no longer exists for this container. Use this to reuse a physical page when a logical page has exhausted all recordId or for logical pages that has been shrunk out. preAllocLength(int) the number of pages that have been preallocated reserved1(int) reserved2(long) reserved for future use reserved3(long) reserved for future use FreePages(bit) bitmap of free pages Bit[i] is ON iff page i is free for immediate (re)use. [ on disk version before 2.0 deAllocPages(bit) bitmap of deallocated pages Bit[i] is ON iff page i has been deallocated. ] unFilledPages(bit) bitmap of pages that has free space Bit[i] is ON if page i is likely to be < 1/2 full org.apache.derby.iapi.services.io.FormatableBitSet is used to store the bit map. FormatableBitSet is an externalizable class. @end_format <PRE> A page can have the following logical state: <BR>Free - a page that is free to be used <BR>Valid - a page that is currently in use <P> There is another type of transitional pages which pages that have been allocated on disk but has not yet been used. These pages are Free. <P> Bit[K] freePages Bit[i] is ON iff page i maybe free for reuse. User must get the dealloc page lock on the free page to make sure the transaction. <P> K is the size of the bit array, it must be >= length. @see AllocPage*/public class AllocExtent implements Externalizable{ private long extentOffset; // begin physical offset private long extentStart; // first logical page number private long extentEnd; // last logical page number // page[extentStart] to page[extentEnd] are the pages in the range of this // alloc extent. // page[exentStart] to page[extentStart+extentLength-1] are actually // allocated in this extent // when the extent is completely allocated, // extentEnd == extentStart+extentLength -1 private int extentLength; // number of pages allocated in the extent int extentStatus; private int preAllocLength; private int reserved1; private long reserved2; private long reserved3; // extent Status bits private static final int HAS_DEALLOCATED = 0x1; private static final int HAS_FREE = 0x2; private static final int ALL_FREE = 0x4; private static final int HAS_UNFILLED_PAGES = 0x10; private static final int KEEP_UNFILLED_PAGES = 0x10000000; private static final int NO_DEALLOC_PAGE_MAP = 0x20000000; private static final int RETIRED = 0x8; /** public Per Page status */ protected static final int ALLOCATED_PAGE = 0; protected static final int DEALLOCATED_PAGE = 1; protected static final int FREE_PAGE = 2; // a page which is not a freePage is a regular old // allocated page. Only an allocated page can be unFilled. FormatableBitSet freePages; FormatableBitSet unFilledPages; /** Statically calculates how many pages this extent can manage given the availspace number of bytes to store this extent in if read/writeExternal changes, this must change too */ protected static int MAX_RANGE(int availspace) { /* extent Offset, Start, End, Length, Status, preAllocLength, reserved1,2,3 */ int bookkeeping = 8 /* offset */ + 8 /* start */ + 8 /* end */ + 4 /* length */ + 4 /* status */ + 4 /* preAllocLength */ + 4 /* reserved1 */ + 8 /* reserved2 */ + 8 /* reserved3 */; availspace -= bookkeeping; // each bit array is allowed to the 1/3 the remaining space availspace /= 3; if (availspace <= 0) return 0; // ask bit array how many bits it can store in this amount of space return FormatableBitSet.maxBitsForSpace(availspace); } /* * methods */ /* * ctors */ protected AllocExtent(long offset, // physical offset long start, // starting logical page number int length, // how many pages are in this extent int pagesize, // size of all the pages in the extent int maxlength) // initial size of the bit map arrays { if (SanityManager.DEBUG) { if (length > maxlength) SanityManager.THROWASSERT( "length " + length + " > maxlength " + maxlength); } this.extentOffset = offset; this.extentStart = start; this.extentEnd = start+maxlength-1; this.extentLength = length; preAllocLength = extentLength; if (length > 0) extentStatus = HAS_FREE | ALL_FREE ; else extentStatus = 0; extentStatus |= KEEP_UNFILLED_PAGES; // v1.3 or beyond extentStatus |= NO_DEALLOC_PAGE_MAP; // v2.0 or beyond int numbits = (1+(length/8))*8; if (numbits > maxlength) numbits = maxlength; freePages = new FormatableBitSet(numbits); unFilledPages = new FormatableBitSet(numbits); // by definition, all pages are free to begin with, no pages are // deallocated and no page is unfilled for (int i = 0; i < length; i++) freePages.set(i); } /* Copy constructor */ protected AllocExtent(AllocExtent original) { extentOffset = original.extentOffset; extentStart = original.extentStart; extentEnd = original.extentEnd; extentLength = original.extentLength; extentStatus = original.extentStatus; preAllocLength = original.preAllocLength; freePages = new FormatableBitSet(original.freePages); unFilledPages = new FormatableBitSet(original.unFilledPages); } /* * Methods of Externalizable */ public AllocExtent() { } public void writeExternal(ObjectOutput out) throws IOException { // any change to this routine must change maxRange out.writeLong(extentOffset); out.writeLong(extentStart); out.writeLong(extentEnd); out.writeInt(extentLength); out.writeInt(extentStatus); out.writeInt(preAllocLength); out.writeInt(0); // reserved1 out.writeLong(0); // reserved2 out.writeLong(0); // reserved3 freePages.writeExternal(out); unFilledPages.writeExternal(out); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // any change to this routine must change maxRange extentOffset = in.readLong(); extentStart = in.readLong(); extentEnd = in.readLong(); extentLength = in.readInt(); extentStatus = in.readInt(); preAllocLength = in.readInt(); reserved1 = in.readInt(); reserved2 = in.readLong(); reserved3 = in.readLong(); freePages = new FormatableBitSet(); // don't know how to point to it freePages.readExternal(in); // this extent is created before 2.0 if ((extentStatus & NO_DEALLOC_PAGE_MAP) == 0) { FormatableBitSet deAllocPages = new FormatableBitSet(); deAllocPages.readExternal(in); // fold this into free page bit map freePages.or(deAllocPages); extentStatus |= NO_DEALLOC_PAGE_MAP; // dealloc page map has been merged } if ((extentStatus & KEEP_UNFILLED_PAGES) == KEEP_UNFILLED_PAGES) { unFilledPages = new FormatableBitSet(); unFilledPages.readExternal(in); } else // before we keep track of unfilled pages pre 1.3 { // make sure there are enough space unFilledPages = new FormatableBitSet(freePages.getLength()); extentStatus |= KEEP_UNFILLED_PAGES; // now we keep track of them } } /* * methods specific to allocExtent */ /* * write operation that is called underneath the log * * page goes thru the following transition: * ALLOCATED_PAGE <-> deallocated page -> free page <-> ALLOCATED_PAGE * */ /** Allocate this page - this is called underneath the log record @exception StandardException Standard Cloudscape error policy */ protected void allocPage(long pagenum) throws StandardException { if (SanityManager.DEBUG) { if (pagenum > getLastPagenum()) { // adding a brand new page, it should be at most one off from the last page if (pagenum > extentEnd) SanityManager.THROWASSERT("pagenum " + pagenum + " is out of beyond my range (" + extentStart + "," + extentEnd + ")"); if (pagenum != getLastPagenum() + 1) SanityManager.THROWASSERT( "skipping pages, lastPageNumber = " + getLastPagenum() + " pageNumber = " + pagenum + "\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -