001: /*
002:
003: Derby - Class org.apache.derby.impl.store.raw.data.ReclaimSpace
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.store.raw.data;
023:
024: import org.apache.derby.iapi.store.raw.ContainerKey;
025: import org.apache.derby.iapi.store.raw.RecordHandle;
026: import org.apache.derby.iapi.store.raw.PageTimeStamp;
027: import org.apache.derby.iapi.store.raw.PageKey;
028:
029: import org.apache.derby.iapi.services.context.ContextManager;
030: import org.apache.derby.iapi.services.daemon.Serviceable;
031: import org.apache.derby.iapi.services.sanity.SanityManager;
032:
033: import org.apache.derby.iapi.error.StandardException;
034: import org.apache.derby.iapi.store.raw.data.DataFactory;
035: import org.apache.derby.iapi.store.raw.ContainerHandle;
036:
037: /**
038: Post commit work to reclaim some space from the raw store. This is a
039: wrapper class for the real serviceable class who wraps this on top of
040: itself so different things can be identified.
041: */
042: public final class ReclaimSpace implements Serviceable {
043: private boolean serviceASAP;
044:
045: private ContainerKey containerId;
046: private PageKey pageId; // Not used for reclaiming container.
047: private RecordHandle headRowHandle; // Used for reclaiming overflow page
048: // and row reserved space.
049:
050: // The following is used for reclaiming column chain only.
051: private int columnId; // Which column in the row to reclaim.
052: private long columnPageId; // Where the column chain pointer
053: private int columnRecordId; // is pointed at.
054: private PageTimeStamp timeStamp; // Time stamp of columnPageId to make sure
055: // the post commit work doesn't get
056: // exercised more then once.
057:
058: private int attempts;
059:
060: private DataFactory processor; // processor knows how to reclaim file space
061:
062: private int reclaim; // what is it we should be reclaiming
063: public static final int CONTAINER = 1; // reclaim the entire container
064: public static final int PAGE = 2; // reclaim an overflow page
065: public static final int ROW_RESERVE = 3; // reclaim reserved space on a row
066: public static final int COLUMN_CHAIN = 4; // reclaim a column chain
067:
068: private void initContainerInfo(ContainerKey containerId,
069: int reclaim, DataFactory processor, boolean serviceASAP) {
070: this .containerId = containerId;
071: this .reclaim = reclaim;
072: this .attempts = 0;
073:
074: this .processor = processor;
075: this .serviceASAP = serviceASAP;
076: }
077:
078: // reclaim container
079: public ReclaimSpace(int reclaim, ContainerKey containerId,
080: DataFactory processor, boolean serviceASAP) {
081: if (SanityManager.DEBUG)
082: SanityManager.ASSERT(reclaim == CONTAINER);
083: initContainerInfo(containerId, reclaim, processor, serviceASAP);
084: }
085:
086: // reclaim page - undo of insert into overflow page
087: public ReclaimSpace(int reclaim, PageKey pageId,
088: DataFactory processor, boolean serviceASAP) {
089: if (SanityManager.DEBUG)
090: SanityManager.ASSERT(reclaim == PAGE);
091: initContainerInfo(pageId.getContainerId(), reclaim, processor,
092: serviceASAP);
093:
094: this .pageId = pageId;
095: }
096:
097: // reclaim row reserved space
098: public ReclaimSpace(int reclaim, RecordHandle headRowHandle,
099: DataFactory processor, boolean serviceASAP) {
100: if (SanityManager.DEBUG)
101: SanityManager.ASSERT(reclaim == ROW_RESERVE);
102:
103: initContainerInfo(headRowHandle.getContainerId(), reclaim,
104: processor, serviceASAP);
105:
106: this .headRowHandle = headRowHandle;
107: }
108:
109: // reclaim column chain
110: public ReclaimSpace(int reclaim, RecordHandle headRowHandle,
111: int columnId, long ovPageId, int ovRecordId,
112: PageTimeStamp timeStamp, DataFactory processor,
113: boolean serviceASAP) {
114: if (SanityManager.DEBUG)
115: SanityManager.ASSERT(reclaim == COLUMN_CHAIN);
116: initContainerInfo(headRowHandle.getContainerId(), reclaim,
117: processor, serviceASAP);
118:
119: this .headRowHandle = headRowHandle;
120: this .columnId = columnId;
121: this .columnPageId = ovPageId;
122: this .columnRecordId = ovRecordId;
123: this .timeStamp = timeStamp;
124: }
125:
126: /*
127: * Serviceable methods
128: */
129:
130: public boolean serviceASAP() {
131: return serviceASAP;
132: }
133:
134: public int performWork(ContextManager context)
135: throws StandardException {
136: if (SanityManager.DEBUG) {
137: SanityManager.ASSERT(context != null, "context is null");
138: SanityManager
139: .ASSERT(processor != null, "processor is null");
140: }
141:
142: return processor.reclaimSpace(this , context);
143: }
144:
145: // @return true, if this work needs to be done on a user thread immediately
146: public boolean serviceImmediately() {
147:
148: //It's very important that we reclaim container space immediately
149: //as part of post commit cleanup. Because typically could typically
150: //involve large amount of space freed and
151: //we don't want conatiner reclaim requests lost if the server crashes
152: //for some reasom before Container Reclaim requests could be
153: //processed successfully by an asynchronous thread.
154: //if(reclaim == CONTAINER)
155: // return true; else return false;
156: return true;
157: }
158:
159: /*
160: * class specific methods
161: */
162:
163: public final ContainerKey getContainerId() {
164: return containerId;
165: }
166:
167: public final PageKey getPageId() {
168: return pageId;
169: }
170:
171: public final RecordHandle getHeadRowHandle() {
172: return headRowHandle;
173: }
174:
175: public final int getColumnId() {
176: return columnId;
177: }
178:
179: public final long getColumnPageId() {
180: return columnPageId;
181: }
182:
183: public final int getColumnRecordId() {
184: return columnRecordId;
185: }
186:
187: public final PageTimeStamp getPageTimeStamp() {
188: return timeStamp;
189: }
190:
191: public final int reclaimWhat() {
192: return reclaim;
193: }
194:
195: public final int incrAttempts() {
196: return ++attempts;
197: }
198:
199: // debug
200: public String toString() {
201: if (SanityManager.DEBUG) {
202: if (reclaim == CONTAINER)
203: return "Reclaim CONTAINER (" + containerId + ")";
204:
205: if (reclaim == PAGE)
206: return "Reclaim PAGE (" + pageId + ") head row at "
207: + headRowHandle;
208:
209: if (reclaim == ROW_RESERVE)
210: return "Reclaim ROW_RESERVE (" + pageId + ")."
211: + headRowHandle + ")";
212:
213: if (reclaim == COLUMN_CHAIN)
214: return "Reclaim COLUMN_CHAIN (" + pageId + ").("
215: + headRowHandle + "," + columnId + ") at ("
216: + columnPageId + "," + columnRecordId + ")";
217: }
218: return null;
219:
220: }
221:
222: }
|