📄 filecontainer.java
字号:
/* Derby - Class org.apache.derby.impl.store.raw.data.FileContainer 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.Property;import org.apache.derby.iapi.reference.Limits;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.impl.store.raw.data.BaseContainer;import org.apache.derby.impl.store.raw.data.BaseContainerHandle;import org.apache.derby.impl.store.raw.data.BasePage;import org.apache.derby.impl.store.raw.data.PageVersion;import org.apache.derby.iapi.services.cache.Cacheable;import org.apache.derby.iapi.services.cache.CacheManager;import org.apache.derby.iapi.services.context.ContextService;import org.apache.derby.iapi.services.daemon.DaemonService;import org.apache.derby.iapi.services.daemon.Serviceable;import org.apache.derby.iapi.services.monitor.Monitor;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.io.FormatIdUtil;import org.apache.derby.iapi.services.io.FormatIdOutputStream;import org.apache.derby.iapi.services.io.StoredFormatIds;import org.apache.derby.iapi.services.io.TypedFormat;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.store.raw.ContainerHandle;import org.apache.derby.iapi.store.raw.ContainerKey;import org.apache.derby.iapi.store.raw.LockingPolicy;import org.apache.derby.iapi.store.raw.Loggable;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.RecordHandle;import org.apache.derby.iapi.store.raw.RawStoreFactory;import org.apache.derby.iapi.store.raw.Transaction;import org.apache.derby.iapi.store.raw.log.LogInstant;import org.apache.derby.iapi.store.raw.xact.RawTransaction;import org.apache.derby.iapi.store.access.TransactionController;import org.apache.derby.iapi.store.access.AccessFactory;import org.apache.derby.iapi.store.access.SpaceInfo;import org.apache.derby.iapi.services.io.ArrayInputStream;import org.apache.derby.iapi.services.io.ArrayOutputStream;import org.apache.derby.iapi.services.property.PropertyUtil;import org.apache.derby.iapi.util.ByteArray;import java.io.IOException;import java.io.DataInput;import java.io.DataOutput;import java.util.Properties;import java.util.zip.CRC32;/** FileContainer is an abstract base class for containers which are based on files. This class extends BaseContainer and implements Cacheable and TypedFormat*/abstract class FileContainer extends BaseContainer implements Cacheable, TypedFormat{ /* * typed format */ protected static final int formatIdInteger = StoredFormatIds.RAW_STORE_SINGLE_CONTAINER_FILE; // format Id must fit in 4 bytes /** Return my format identifier. */ public int getTypeFormatId() { return StoredFormatIds.RAW_STORE_SINGLE_CONTAINER_FILE; } /* ** Immutable fields */ protected final CacheManager pageCache; // my page's cache protected final CacheManager containerCache; // cache I am in. protected final BaseDataFileFactory dataFactory; // creating factory /* ** Fields that are mutable only during identity changes */ protected int pageSize; // size of my pages protected int spareSpace; // % space kept free on page in inserts protected int minimumRecordSize; // minimum space a record should // occupy on the page. protected short initialPages; // initial number of pages preallocated // to the container when created protected boolean canUpdate; // can I be written to? private int PreAllocThreshold; // how many pages before preallocation // kicks in, only stored in memory private int PreAllocSize; // how many pages to preallocate at once // only stored in memory private boolean bulkIncreaseContainerSize;// if true, the next addPage will // attempt to preallocate a larger // than normal number of pages. // // preallocation parameters private static final int PRE_ALLOC_THRESHOLD = 8; private static final int MIN_PRE_ALLOC_SIZE = 1; private static final int DEFAULT_PRE_ALLOC_SIZE = 8; private static final int MAX_PRE_ALLOC_SIZE = 1000; /* ** Mutable fields, only valid when the identity is valid. */ // RESOLVE: if we run out of bytes in the container, we can change // containerVersion from a long to an int because this number is only // bumped when the container is dropped (and rolled back), so it is almost // impossible for the containverVersion to get beyond a short, let alone // and int - someone will have to write an application that attempt to drop // the container 2 billion times for that to happen. protected long firstAllocPageNumber; // first alloc page number protected long firstAllocPageOffset; // first alloc page offset protected long containerVersion; // the logged version number protected long estimatedRowCount; // value is changed unlogged protected LogInstant lastLogInstant; // last time this container // object was touched. /** The page that was last inserted into. Use this for getPageForInsert. Remember the last allocated non-overflow page, and remember it in memory only. Use Get/Set method to access this field except when we know it is being single thread access. */ private long lastInsertedPage[]; private int lastInsertedPage_index; /** The last unfilled page found. Use this for getPageForInsert. Remember the last unfilled page found, and remember it in memory only. Use Get/Set method to access this field except when we know it is being single thread access. */ private long lastUnfilledPage; /** The last allocated page. This global var is access *without* synchronization. It is used as a hint for page allocation to find the next reusable page. */ private long lastAllocatedPage; /** An estimated page count. Use this for getEstimatedPagecount. Remember it in memory only. */ private long estimatedPageCount; // The isDirty flag indicates if the container has been modified. The // preDirty flag indicates that the container is about to be modified. The // reason for these 2 flags instead of just one is to accomodate // checkpoint. After a clean container sends a log record to the log // stream but before that conatiner is dirtied by the log operation, a // checkpoint could be taken. If so, then the redoLWM will be after the // log record but, without preDirty, the cache cleaning will not have // waited for the change. So the preDirty bit is to stop the cache // cleaning from skipping over this container even though it has not really // been modified yet. protected boolean preDirty; protected boolean isDirty; /* allocation information cached by the container object. <P>MT - Access to the allocation cache MUST be synchronized on the allocCache object. FileContainer manages all MT issue w/r to AllocationCache. The AllocationCache object itself is not MT-safe. <P> The protocol for accessing both the allocation cache and the alloc page is: get the alloc cache semaphore, then get the alloc page. Once both are held, they can be released in any order. <BR> It is legal to get one or the other, i.e, it is legal to only get the alloc cache semaphore without latching the alloc page, and it is legal to get the alloc page latch without the alloc cache semaphore. <BR> it is illegal to hold alloc page latch and then get the allocation cache semaphore <PRE> Writer to alloc Page (to invalidate alloc cache) 1) synchronized(allocCache) 2) invalidate cache 3) get latch on alloc Page 4) release synchonized(allocCache) Reader: 1) synchronized(allocCache) 2) if valid, read value and release synchronized(allocCache) 3) if cache is invalid, get latch on alloc page 4) validate cache 5) release alloc page latch 6) read value 7) release synchonized(allocCache) </PRE> */ protected AllocationCache allocCache; /* * array to store persistently stored fields */ byte[] containerInfo; private CRC32 checksum; // holder for the checksum /* ** buffer for encryption/decryption */ private byte[] encryptionBuffer; /* * constants */ /** the container format must fit in this many bytes */ private static final int CONTAINER_FORMAT_ID_SIZE = 4; /* the checksum size */ protected static final int CHECKSUM_SIZE = 8; /** The size of the persistently stored container info ContainerHeader contains the following information: 4 bytes int FormatId 4 bytes int status 4 bytes int pageSize 4 bytes int spareSpace 4 bytes int minimumRecordSize 2 bytes short initialPages 2 bytes short spare1 8 bytes long first Allocation page number 8 bytes long first Allocation page offset 8 bytes long container version 8 bytes long estimated number of rows 8 bytes long spare2 8 bytes long spare3 8 bytes long checksum container info size is 80 bytes, with 20 bytes of spare space */ protected static final int CONTAINER_INFO_SIZE = CONTAINER_FORMAT_ID_SIZE+4+4+4+4+2+2+8+8+8+8+CHECKSUM_SIZE+8+8; /** the number of arguments we need to pass to alloc page for create */ protected static final int STORED_PAGE_ARG_NUM = 5; protected static final int ALLOC_PAGE_ARG_NUM = 6; /** * where the first alloc page is located - * the logical page number and the physical page offset * NOTE if it is not 0 this is not going to work for Stream * file which doesn't support seek */ public static final long FIRST_ALLOC_PAGE_NUMBER = 0L; public static final long FIRST_ALLOC_PAGE_OFFSET = 0L; // file status for persistent storage private static final int FILE_DROPPED = 0x1; private static final int FILE_COMMITTED_DROP = 0x2; // recordId in this container can be reused when a page is reused. private static final int FILE_REUSABLE_RECORDID = 0x8; protected static final String SPACE_TRACE = (SanityManager.DEBUG ? "SpaceTrace" : null); FileContainer(BaseDataFileFactory factory) { dataFactory = factory; pageCache = factory.getPageCache(); containerCache = factory.getContainerCache(); initContainerHeader(true); } /** Get information about space used by the container. **/ public SpaceInfo getSpaceInfo(BaseContainerHandle handle) throws StandardException { SpaceInformation spaceInfo; synchronized(allocCache) { spaceInfo = allocCache.getAllPageCounts(handle,firstAllocPageNumber); } spaceInfo.setPageSize(pageSize); return spaceInfo; } /* ** Methods of Cacheable ** ** getIdentity() and clearIdentity() are implemented by BaseContainer */ /** Containers */ /** Open the container. @return a valid object if the container was successfully opened, null if it does not exist. @exception StandardException Some problem in opening a container. @see Cacheable#setIdentity */ public Cacheable setIdentity(Object key) throws StandardException { return setIdent((ContainerKey) key); } /** * Open the container. * <p> * Open the container with key "newIdentity". * <p> * should be same name as setIdentity but seems to cause method resolution * ambiguities * * @exception StandardException Some problem in opening a container. * * @see Cacheable#setIdentity **/ protected Cacheable setIdent(ContainerKey newIdentity) throws StandardException { boolean ok = openContainer(newIdentity); initializeLastInsertedPage(1); lastUnfilledPage = ContainerHandle.INVALID_PAGE_NUMBER; lastAllocatedPage = ContainerHandle.INVALID_PAGE_NUMBER; estimatedPageCount = -1; if (ok) { // set up our identity. // If we raise an exception after this we must clear our identity. fillInIdentity(newIdentity); return this;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -