--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.store.raw.data.BaseContainer\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.store.raw.data;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.services.locks.CompatibilitySpace;\r
+import org.apache.derby.iapi.services.locks.Lockable;\r
+import org.apache.derby.iapi.services.locks.Latch;\r
+import org.apache.derby.iapi.services.locks.C_LockFactory;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+import org.apache.derby.iapi.store.access.SpaceInfo;\r
+\r
+import org.apache.derby.iapi.store.raw.ContainerHandle;\r
+import org.apache.derby.iapi.store.raw.LockingPolicy;\r
+import org.apache.derby.iapi.store.raw.Page;\r
+import org.apache.derby.iapi.store.raw.PageKey;\r
+import org.apache.derby.iapi.store.raw.PageTimeStamp;\r
+import org.apache.derby.iapi.store.raw.RecordHandle;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+import org.apache.derby.iapi.store.raw.ContainerKey;\r
+import org.apache.derby.iapi.store.raw.data.RawContainerHandle;\r
+import org.apache.derby.iapi.store.raw.log.LogInstant;\r
+import org.apache.derby.iapi.store.raw.xact.RawTransaction;\r
+\r
+import org.apache.derby.iapi.util.ByteArray;\r
+\r
+import java.util.Properties;\r
+import java.util.Hashtable;\r
+\r
+/**\r
+ BaseContainer is an abstract class that provides the locking bahaviour\r
+ for an object representing an active container, that is the actual\r
+ storage container, not the ContainerHandle interface. This class is designed\r
+ so that it can change the container it represents to avoid creating\r
+ a new object for every container.\r
+ <P>\r
+ This object implements lockable to provide an object to lock while a page is being\r
+ allocated.\r
+ <BR> MT - Mutable - mutable identity : \r
+*/\r
+abstract class BaseContainer implements Lockable {\r
+\r
+ /**\r
+ Identity of the container.\r
+\r
+ <BR> MT - Mutable\r
+ */\r
+ protected ContainerKey identity;\r
+\r
+ \r
+ /**\r
+ Dropped state of the container.\r
+\r
+ <BR> MT - mutable : single thread required. Either the container must be exclusive\r
+ locked by this thread, or the container must have no identity (ie. it is being created\r
+ or opened).\r
+ */\r
+ protected boolean isDropped;\r
+\r
+\r
+ /**\r
+ Committed Drop state of the container. If a post comit action\r
+ determined that the drop container operation is committed, the whole\r
+ container may be removed and space reclaimed.\r
+\r
+ <BR> MT - mutable : single thread required. Either the container must be exclusive\r
+ locked by this thread, or the container must have no identity (ie. it is being created\r
+ or opened).\r
+ */\r
+ protected boolean isCommittedDrop;\r
+\r
+\r
+ /**\r
+ Is reusable recordId. By default, record Ids are not reusable when a\r
+ page is reused. However, under special circumstances, clients to raw\r
+ store may decide that record Ids may be reused after the page is\r
+ reused. When this flag is set, pages that are reused will have its\r
+ next recordId set to RecordHandle.FIRST_RECORD_ID\r
+ */\r
+ protected boolean isReusableRecordId = false;\r
+\r
+ BaseContainer() {\r
+ }\r
+\r
+ /*\r
+ ** portions of Cacheable interface, interface is actually implemented by\r
+ ** sub-class. This section also contains methods related to this interface.\r
+ */\r
+\r
+ protected void fillInIdentity(ContainerKey key) {\r
+\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT(identity == null || (identity == key));\r
+ }\r
+\r
+ identity = key;\r
+ }\r
+\r
+ public void clearIdentity() {\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT(identity != null);\r
+ }\r
+\r
+ identity = null;\r
+ }\r
+\r
+ public Object getIdentity() {\r
+ return identity;\r
+ }\r
+\r
+ /*\r
+ ** Methods from Lockable, just require a single exclusive locker\r
+ */\r
+\r
+ public void lockEvent(Latch lockInfo) {\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT(identity != null);\r
+ }\r
+ }\r
+\r
+ public boolean requestCompatible(Object requestedQualifier, Object grantedQualifier) {\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT(identity != null);\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean lockerAlwaysCompatible() {\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT(identity != null);\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public void unlockEvent(Latch lockInfo) {\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT(identity != null);\r
+ }\r
+ }\r
+\r
+ /*\r
+ ** Implementation specific methods\r
+ */\r
+\r
+\r
+ /**\r
+ Release free space to the OS.\r
+ <P>\r
+ As is possible release any free space to the operating system. This\r
+ will usually mean releasing any free pages located at the end of the\r
+ file using the java truncate() interface.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ public void compressContainer(BaseContainerHandle handle)\r
+ throws StandardException\r
+ {\r
+ RawTransaction ntt = handle.getTransaction().startNestedTopTransaction();\r
+\r
+ int mode = handle.getMode(); \r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT((mode & ContainerHandle.MODE_FORUPDATE) ==\r
+ ContainerHandle.MODE_FORUPDATE, \r
+ "addPage handle not for update");\r
+ }\r
+\r
+ // if we are not in the same transaction as the one which created the\r
+ // container and the container may have logged some operation already, \r
+ // then we need to log allocation regardless of whether user changes\r
+ // are logged. Otherwise, the database will be corrupted if it\r
+ // crashed. \r
+ if ((mode & ContainerHandle.MODE_CREATE_UNLOGGED) == 0 &&\r
+ (mode & ContainerHandle.MODE_UNLOGGED) ==\r
+ ContainerHandle.MODE_UNLOGGED) \r
+ mode &= ~ContainerHandle.MODE_UNLOGGED;\r
+\r
+ // make a handle which is tied to the ntt, not to the user transaction \r
+ // this handle is tied to. The container is already locked by the \r
+ // user transaction, open it nolock\r
+ BaseContainerHandle allocHandle = (BaseContainerHandle)\r
+ ntt.openContainer(identity, (LockingPolicy)null, mode);\r
+\r
+ if (allocHandle == null)\r
+ {\r
+ throw StandardException.newException(\r
+ SQLState.DATA_ALLOC_NTT_CANT_OPEN, \r
+ new Long(getSegmentId()), \r
+ new Long(getContainerId()));\r
+ }\r
+\r
+ CompatibilitySpace cs = ntt.getCompatibilitySpace();\r
+ // Latch this container, the commit will release the latch\r
+ ntt.getLockFactory().lockObject(\r
+ cs, ntt, this, null, C_LockFactory.WAIT_FOREVER);\r
+\r
+ try\r
+ {\r
+ incrementReusableRecordIdSequenceNumber(); \r
+ compressContainer(ntt, allocHandle);\r
+ }\r
+ finally\r
+ {\r
+ ntt.commit();\r
+\r
+ ntt.close();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the reusable RecordId sequence number for the\r
+ * container. This sequence number should be incremented every time\r
+ * there is an operation which may cause RecorIds to be reused.\r
+ * This method can be used by clients to check if a RecordId they \r
+ * obtained is still guaranteed to be valid.\r
+ * If the sequence number has changed, the RecordId may have been\r
+ * reused for another row.\r
+ * @return sequence number for reusable RecordId\r
+ */\r
+ public abstract long getReusableRecordIdSequenceNumber();\r
+\r
+ /**\r
+ * Increment the reusable RecordId sequence number.\r
+ */\r
+ protected abstract void incrementReusableRecordIdSequenceNumber();\r
+ \r
+\r
+ /**\r
+ Add a page to this container.\r
+\r
+ <BR> MT - thread aware - \r
+\r
+ The add page operation involves 2 transactions, one is the user\r
+ transaction (the transaction which owns the passed in handle), the\r
+ other one is a NestedTopTransaction created by this BaseContainer.\r
+\r
+ The nestedTopTransaction is used by the underlying container to change\r
+ high contention structures, such as link list anchor or bit map pages.\r
+ The nestedTopTransaction commits or aborts before this routine returns.\r
+\r
+ The user transaction is used to latch the newly created page.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ public Page addPage(BaseContainerHandle handle, boolean isOverflow) throws StandardException {\r
+ \r
+ RawTransaction ntt = handle.getTransaction().startNestedTopTransaction();\r
+\r
+ int mode = handle.getMode(); \r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT((mode & ContainerHandle.MODE_FORUPDATE) ==\r
+ ContainerHandle.MODE_FORUPDATE, \r
+ "addPage handle not for update");\r
+ }\r
+\r
+ // if we are not in the same transaction as the one which created the\r
+ // container and the container may have logged some operation already, \r
+ // then we need to log allocation regardless of whether user changes\r
+ // are logged. Otherwise, the database will be corrupted if it\r
+ // crashed. \r
+ if ((mode & ContainerHandle.MODE_CREATE_UNLOGGED) == 0 &&\r
+ (mode & ContainerHandle.MODE_UNLOGGED) ==\r
+ ContainerHandle.MODE_UNLOGGED) \r
+ mode &= ~ContainerHandle.MODE_UNLOGGED;\r
+\r
+ // make a handle which is tied to the ntt, not to the user transaction this\r
+ // handle is tied to. The container is already locked by the user transaction,\r
+ // open it nolock\r
+ BaseContainerHandle allocHandle = (BaseContainerHandle)ntt.openContainer\r
+ (identity, (LockingPolicy)null, mode);\r
+\r
+ if (allocHandle == null)\r
+ {\r
+ throw StandardException.newException(\r
+ SQLState.DATA_ALLOC_NTT_CANT_OPEN, \r
+ new Long(getSegmentId()), \r
+ new Long(getContainerId()));\r
+ }\r
+\r
+ // Latch this container, the commit will release the latch\r
+ CompatibilitySpace cs = ntt.getCompatibilitySpace();\r
+ ntt.getLockFactory().lockObject(\r
+ cs, ntt, this, null, C_LockFactory.WAIT_FOREVER);\r
+\r
+ BasePage newPage = null;\r
+ try\r
+ {\r
+ newPage = newPage(handle, ntt, allocHandle, isOverflow);\r
+ }\r
+ finally\r
+ {\r
+ if (newPage != null)\r
+ {\r
+ // it is ok to commit without syncing, as it is ok if this\r
+ // transaction never makes it to the db, if no subsequent\r
+ // log record makes it to the log. If any subsequent log\r
+ // record is sync'd then this transaction will be sync'd\r
+ // as well.\r
+ ntt.commitNoSync(Transaction.RELEASE_LOCKS);\r
+ }\r
+ else\r
+ { \r
+ ntt.abort();\r
+ }\r
+ ntt.close();\r
+ }\r
+\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT(newPage.isLatched());\r
+ }\r
+\r
+ if (!this.identity.equals(newPage.getPageId().getContainerId())) {\r
+\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.THROWASSERT("BaseContainer.addPage(), just got a new page from a different container"\r
+ + "\n this.identity = " + this.identity\r
+ + "\n newPage.getPageId().getContainerId() = " + newPage.getPageId().getContainerId()\r
+ + "\n handle is: " + handle\r
+ + "\n allocHandle is: " + allocHandle\r
+ + "\n this container is: " + this);\r
+ }\r
+\r
+ throw StandardException.newException(\r
+ SQLState.DATA_DIFFERENT_CONTAINER,\r
+ this.identity, newPage.getPageId().getContainerId());\r
+ }\r
+\r
+ return newPage;\r
+ }\r
+\r
+ /**\r
+ * Request the system properties associated with a container.\r
+ * <p>\r
+ * Request the value of properties that are associated with a container. \r
+ * The following properties can be requested:\r
+ * derby.storage.pageSize \r
+ * derby.storage.pageReservedSpace\r
+ * derby.storage.minimumRecordSize\r
+ * <p>\r
+ * To get the value of a particular property add it to the property list,\r
+ * and on return the value of the property will be set to it's current \r
+ * value. For example:\r
+ *\r
+ * get_prop(BaseContainer base)\r
+ * {\r
+ * Properties prop = new Properties();\r
+ * prop.put("derby.storage.pageSize", "");\r
+ * base.getContainerProperties(prop);\r
+ *\r
+ * System.out.println(\r
+ * "container's page size = " + \r
+ * prop.getProperty("derby.storage.pageSize");\r
+ * }\r
+ *\r
+ * @param prop Property list to fill in.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ public abstract void getContainerProperties(Properties prop)\r
+ throws StandardException;\r
+\r
+ /**\r
+ Remove a page from this container. The page will be unlatched by this\r
+ routine before it returns.\r
+\r
+ Unlike addPage, this method done as part of the user transaction. \r
+ The removed page is not usable by anyone until the user transaction \r
+ comits.\r
+ If the user transaction rolls back, the removed page is un-removed.\r
+\r
+ <BR> MT - thread aware -\r
+\r
+ @param handle the container handle that has opened the container and latched the page\r
+ @param page the latched page that is to be deallocated\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected void removePage(BaseContainerHandle handle, BasePage page) \r
+ throws StandardException\r
+ {\r
+ try\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(page.isLatched(), "page is not latched");\r
+ }\r
+\r
+ // get dealloc lock nowait on the page to be deallocated\r
+ // this lock is held until this transaction commits.\r
+ // then gc can free this page\r
+ RecordHandle deallocLock = \r
+ page.makeRecordHandle(RecordHandle.DEALLOCATE_PROTECTION_HANDLE);\r
+\r
+ // don't get deallocLock wait because caller have a page latched\r
+ if (!getDeallocLock(handle, deallocLock, \r
+ false /* no wait */,\r
+ false /* not zeroDuration */))\r
+ {\r
+ throw StandardException.newException(\r
+ SQLState.DATA_CANNOT_GET_DEALLOC_LOCK, \r
+ page.getIdentity());\r
+ }\r
+\r
+ deallocatePage(handle, page);\r
+ }\r
+ finally\r
+ {\r
+ if (page != null)\r
+ page.unlatch();\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ Get the special dealloc lock on the page - the lock is gotten by the\r
+ transaction that owns the container handle\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected boolean getDeallocLock(BaseContainerHandle handle, \r
+ RecordHandle deallocLock, \r
+ boolean wait,\r
+ boolean zeroDuration)\r
+ throws StandardException\r
+ {\r
+ // get deallocate lock on page so that the GC won't attempt to \r
+ // free and re-allocate it until the transaction commits\r
+ RawTransaction tran = handle.getTransaction();\r
+\r
+ LockingPolicy lp = \r
+ tran.newLockingPolicy(\r
+ LockingPolicy.MODE_RECORD,\r
+ TransactionController.ISOLATION_REPEATABLE_READ, \r
+ true); // striterOK\r
+ \r
+ PageKey pkey = new PageKey(identity, deallocLock.getPageNumber());\r
+ if (lp != null)\r
+ {\r
+ if (zeroDuration)\r
+ return lp.zeroDurationLockRecordForWrite(\r
+ tran, deallocLock, false, wait); \r
+ else\r
+ return lp.lockRecordForWrite(tran, deallocLock, false, wait);\r
+ }\r
+ else\r
+ {\r
+ throw StandardException.newException(\r
+ SQLState.DATA_CANNOT_GET_DEALLOC_LOCK, pkey);\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ Get an allocation page and latch it.\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected Page getAllocPage(BaseContainerHandle handle, long pageNumber, boolean wait)\r
+ throws StandardException\r
+ {\r
+ return latchPage(handle, getAllocPage(pageNumber), wait);\r
+ }\r
+\r
+ /**\r
+ Get any page and latch it .\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected Page getAnyPage(BaseContainerHandle handle, long pageNumber, boolean wait)\r
+ throws StandardException\r
+ {\r
+ return latchPage(handle, getAnyPage(handle, pageNumber), wait);\r
+ }\r
+\r
+\r
+ /**\r
+ Get the first valid page. Result is latched.\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected Page getFirstPage(BaseContainerHandle handle) throws StandardException\r
+ {\r
+ return getFirstHeadPage(handle, true /* wait */);\r
+ }\r
+\r
+ /**\r
+ Get the next valid page and latch it\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected Page getNextPage(BaseContainerHandle handle, long pageNumber)\r
+ throws StandardException\r
+ {\r
+ return getNextHeadPage(handle, pageNumber, true /* wait */);\r
+ }\r
+\r
+ /*\r
+ utility to latch a page\r
+ */\r
+ protected BasePage latchPage(BaseContainerHandle handle, BasePage foundPage, boolean wait)\r
+ throws StandardException\r
+ {\r
+ if (foundPage != null) {\r
+ if (wait) {\r
+ foundPage.setExclusive(handle);\r
+ } else {\r
+ if (!foundPage.setExclusiveNoWait(handle))\r
+ {\r
+ // sub-class will release page from the cache if required.\r
+ return null;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.ASSERT((foundPage == null) || foundPage.isLatched());\r
+ }\r
+\r
+ return foundPage;\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ Lock the container and mark the container as in-use by this container handle.\r
+\r
+ @param droppedOK if true, use this container even if it is dropped.,\r
+ @return true if the container can be used, false if it has been dropped\r
+ since the lock was requested and droppedOK is not true.\r
+\r
+ @exception StandardException I cannot be opened for update.\r
+ */\r
+ protected boolean use(BaseContainerHandle handle, boolean forUpdate,\r
+ boolean droppedOK) \r
+ throws StandardException {\r
+\r
+ // see if the container can be updated\r
+ if (forUpdate && !canUpdate())\r
+ {\r
+ throw StandardException.newException(\r
+ SQLState.DATA_CONTAINER_READ_ONLY);\r
+ }\r
+\r
+ // if the container is dropped, cannot see if unless droppedOK is set\r
+ if (!droppedOK && (getDroppedState() || getCommittedDropState())) {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ Discontinue use of this container. Note that the unlockContainer\r
+ call made from this method may not release any locks. The container\r
+ lock may be held until the end of the transaction.\r
+\r
+ */\r
+ protected void letGo(BaseContainerHandle handle) {\r
+\r
+ RawTransaction t = handle.getTransaction();\r
+\r
+ handle.getLockingPolicy().unlockContainer(t, handle);\r
+ }\r
+\r
+ protected boolean getDroppedState() {\r
+ return isDropped;\r
+ }\r
+\r
+ protected boolean getCommittedDropState()\r
+ {\r
+ return isCommittedDrop;\r
+ }\r
+\r
+\r
+ protected boolean isReusableRecordId()\r
+ {\r
+ return isReusableRecordId;\r
+ }\r
+\r
+ public int getContainerStatus()\r
+ {\r
+ if (getCommittedDropState())\r
+ return RawContainerHandle.COMMITTED_DROP;\r
+\r
+ if (getDroppedState())\r
+ return RawContainerHandle.DROPPED;\r
+\r
+ return RawContainerHandle.NORMAL;\r
+ }\r
+\r
+ public long getContainerId() {\r
+ return identity.getContainerId();\r
+ }\r
+\r
+ public long getSegmentId() {\r
+ return identity.getSegmentId();\r
+ }\r
+\r
+\r
+ //public int getPageSize() {\r
+ // return pageSize();\r
+ //}\r
+\r
+ /*\r
+ ** Methods that need to be provided by a sub-class.\r
+ */\r
+\r
+ /**\r
+ Get information about space used by the container.\r
+ **/\r
+ protected abstract SpaceInfo getSpaceInfo(BaseContainerHandle handle)\r
+ throws StandardException;\r
+\r
+ /**\r
+ Can the container be updated.\r
+\r
+ @return true if the container can be updated, false otherwise.\r
+ */\r
+ protected abstract boolean canUpdate();\r
+\r
+ /**\r
+ The container is about to be modified.\r
+ Loggable actions use this to make sure the container gets cleaned if a\r
+ checkpoint is taken after any log record is sent to the log stream but\r
+ before the container is actually dirtied.\r
+ */\r
+ protected abstract void preDirty(boolean preDirtyOn);\r
+\r
+\r
+ /**\r
+ Return a BasePage that represents the given page number in this container.\r
+ The resulting page is latched.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract BasePage getPage(BaseContainerHandle handle, long pageNumber,\r
+ boolean wait) throws StandardException;\r
+\r
+ /**\r
+ Return a BasePage that represents the given alloc page number in this container.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract BasePage getAllocPage(long pageNumber) throws StandardException;\r
+\r
+ /**\r
+ Return a BasePage that represents any page - alloc page, valid page, free page,\r
+ dealloced page etc. The only requirement is that the page is initialized...\r
+\r
+ @exception StandardException Derby Standard error policy\r
+ */\r
+ protected abstract BasePage getAnyPage(BaseContainerHandle handle, long pageNumber)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * ReCreate a page for rollforward recovery. \r
+ * <p>\r
+ * During redo recovery it is possible for the system to try to redo\r
+ * the creation of a page (ie. going from non-existence to version 0).\r
+ * It first trys to read the page from disk, but a few different types\r
+ * of errors can occur:\r
+ * o the page does not exist at all on disk, this can happen during\r
+ * rollforward recovery applied to a backup where the file was\r
+ * copied and the page was added to the file during the time frame\r
+ * of the backup but after the physical file was copied.\r
+ * o space in the file exists, but it was never initalized. This\r
+ * can happen if you happen to crash at just the right moment during\r
+ * the allocation process. Also\r
+ * on some OS's it is possible to read from a part of the file that\r
+ * was not ever written - resulting in garbage from the store's \r
+ * point of view (often the result is all 0's). \r
+ *\r
+ * All these errors are easy to recover from as the system can easily \r
+ * create a version 0 from scratch and write it to disk.\r
+ *\r
+ * Because the system does not sync allocation of data pages, it is also\r
+ * possible at this point that whlie writing the version 0 to disk to \r
+ * create it we may encounter an out of disk space error (caught in this\r
+ * routine as a StandardException from the create() call. We can't \r
+ * recovery from this without help from outside, so the caught exception\r
+ * is nested and a new exception thrown which the recovery system will\r
+ * output to the user asking them to check their disk for space/errors.\r
+ *\r
+ * The arguments passed in need to be sufficient for the page cache to \r
+ * materialize a brand new page and write it to disk. \r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ protected abstract BasePage\r
+ reCreatePageForRedoRecovery(\r
+ BaseContainerHandle handle,\r
+ int pageFormat,\r
+ long pageNumber,\r
+ long pageOffset)\r
+ throws StandardException;\r
+\r
+ /**\r
+ Log all information on the container creation necessary to recreate teh\r
+ container during a load tran.\r
+\r
+ @exception StandardException Derby Standard error policy\r
+ */\r
+ protected abstract ByteArray logCreateContainerInfo()\r
+ throws StandardException;\r
+\r
+\r
+ /**\r
+ Get only a valid, non-overflow page. If page number is either invalid\r
+ or overflow, returns null\r
+\r
+ @exception StandardException Derby Standard error policy\r
+ */\r
+ protected abstract BasePage getHeadPage(BaseContainerHandle handle,\r
+ long pagenumber, boolean wait) throws StandardException;\r
+\r
+ /**\r
+ Get the first page in the container.\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract BasePage getFirstHeadPage(BaseContainerHandle handle,\r
+ boolean wait) throws StandardException;\r
+\r
+ /**\r
+ Get the next page in the container.\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract BasePage getNextHeadPage(BaseContainerHandle handle,\r
+ long pageNumber, boolean wait) throws StandardException;\r
+\r
+ /**\r
+ Get a potentially suitable page for insert and latch it.\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract BasePage getPageForInsert(BaseContainerHandle handle,\r
+ int flag)\r
+ throws StandardException;\r
+\r
+ protected abstract BasePage getPageForCompress(\r
+ BaseContainerHandle handle,\r
+ int flag,\r
+ long pageno)\r
+ throws StandardException;\r
+\r
+ protected abstract void truncatePages(long lastValidPagenum)\r
+ throws StandardException;\r
+\r
+\r
+ /**\r
+ Create a new page in the container.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract BasePage newPage(BaseContainerHandle userhandle,\r
+ RawTransaction t,\r
+ BaseContainerHandle allocHandle,\r
+ boolean isOverflow) throws StandardException;\r
+\r
+ protected abstract void compressContainer(\r
+ RawTransaction t,\r
+ BaseContainerHandle allocHandle)\r
+ throws StandardException;\r
+\r
+\r
+ /**\r
+ Deallocate a page from the container.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract void deallocatePage(BaseContainerHandle userhandle,\r
+ BasePage page) throws StandardException;\r
+\r
+\r
+ protected void truncate(BaseContainerHandle handle) throws StandardException {\r
+ if (SanityManager.DEBUG) {\r
+ SanityManager.THROWASSERT("truncate not supported");\r
+ }\r
+ }\r
+\r
+ /**\r
+ Mark the container as drop or not drop depending on the input value.\r
+\r
+ */\r
+ protected abstract void dropContainer(LogInstant instant, boolean drop);\r
+\r
+\r
+ /**\r
+ Remove the container and reclaim its space. Once executed, this\r
+ operation cannot be undone - as opposed to dropContainer which only\r
+ marks the container as dropped and can be rolled back.\r
+ <BR><B> This operation should only be called by post commit clean up </B>\r
+\r
+ @param leaveStub if true, leave a stub. If false, remove everything\r
+ @see org.apache.derby.iapi.store.raw.data.RawContainerHandle#removeContainer\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract void removeContainer(LogInstant instant, boolean leaveStub) throws StandardException;\r
+\r
+ /**\r
+ Get the logged container version.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract long getContainerVersion() throws StandardException;\r
+\r
+ /**\r
+ Flush all outstanding changes in this container to persistent storage.\r
+\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected abstract void flushAll() throws StandardException;\r
+\r
+ /**\r
+ The container will be grown vastly, prepare for it.\r
+ */\r
+ protected abstract void prepareForBulkLoad(BaseContainerHandle handle,\r
+ int numPage);\r
+\r
+ /**\r
+ The container will have no pre-allocate threshold, i.e., if the\r
+ implementation supports it, page preallocation will happen\r
+ the next time a new page is allocated.\r
+ */\r
+ protected abstract void clearPreallocThreshold();\r
+\r
+ /*\r
+ Cost estimates\r
+ */\r
+ /**\r
+ @see ContainerHandle#getEstimatedRowCount\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ public abstract long getEstimatedRowCount(int flag) throws StandardException;\r
+\r
+ /**\r
+ @see ContainerHandle#setEstimatedRowCount\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ public abstract void setEstimatedRowCount(long count, int flag) throws StandardException;\r
+\r
+ /**\r
+ @see ContainerHandle#getEstimatedPageCount\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ public abstract long getEstimatedPageCount(BaseContainerHandle handle, int flag) throws StandardException;\r
+\r
+ /**\r
+ * Backup the container to the specified path.\r
+ * \r
+ * @param handle the container handle.\r
+ * @param backupContainerPath location of the backup container. \r
+ * @exception StandardException Standard Derby error policy \r
+ */\r
+ protected abstract void backupContainer(BaseContainerHandle handle, \r
+ String backupContainerPath) throws StandardException ;\r
+\r
+\r
+ /**\r
+ * Create encrypted version of the container with the \r
+ * user specified encryption properties. \r
+ *\r
+ * @param handle the container handle.\r
+ * @param newFilePath file to store the new encrypted version of the container\r
+ * @exception StandardException Standard Derby error policy \r
+ */\r
+ protected abstract void encryptContainer(BaseContainerHandle handle, \r
+ String newFilePath) \r
+ throws StandardException ;\r
+\r
+\r
+ /*\r
+ ** Methods to be used by sub-classes.\r
+ */\r
+\r
+ /**\r
+ Set the container's dropped state\r
+ */\r
+ protected void setDroppedState(boolean isDropped) {\r
+ this.isDropped = isDropped;\r
+ }\r
+\r
+ protected void setCommittedDropState(boolean isCommittedDrop)\r
+ {\r
+ this.isCommittedDrop = isCommittedDrop;\r
+ }\r
+\r
+\r
+ protected void setReusableRecordIdState(boolean isReusableRecordId)\r
+ {\r
+ this.isReusableRecordId = isReusableRecordId;\r
+ }\r
+\r
+ //protected void setPageSize(int pageSize) {\r
+ // identity.setPageSize(pageSize);\r
+ //}\r
+\r
+ // Not interested in participating in the diagnostic virtual lock table.\r
+ public boolean lockAttributes(int flag, Hashtable attributes)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ \r
+\r
+}\r
+\r