001: /*
002:
003: Derby - Class org.apache.derby.impl.store.raw.data.ContainerBasicOperation
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.reference.SQLState;
025:
026: import org.apache.derby.iapi.store.raw.ContainerKey;
027:
028: import org.apache.derby.iapi.store.raw.ContainerHandle;
029: import org.apache.derby.iapi.store.raw.Loggable;
030: import org.apache.derby.iapi.store.raw.LockingPolicy;
031: import org.apache.derby.iapi.store.raw.Transaction;
032:
033: import org.apache.derby.iapi.store.raw.xact.RawTransaction;
034: import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
035:
036: import org.apache.derby.iapi.error.StandardException;
037: import org.apache.derby.iapi.services.sanity.SanityManager;
038:
039: import org.apache.derby.iapi.services.io.CompressedNumber;
040: import org.apache.derby.iapi.util.ByteArray;
041:
042: import java.io.OutputStream;
043: import java.io.ObjectInput;
044: import java.io.ObjectOutput;
045: import java.io.IOException;
046:
047: /**
048: A Container Operation change the state of the container.
049: A ContainerBasicOperation is the base class for all container operations.
050: */
051:
052: public abstract class ContainerBasicOperation implements Loggable {
053: /* page info this operation changed */
054: private long containerVersion;
055: protected ContainerKey containerId;
056:
057: transient protected RawContainerHandle containerHdl = null;
058: transient private boolean foundHere = false;
059:
060: protected ContainerBasicOperation(RawContainerHandle hdl)
061: throws StandardException {
062: containerHdl = hdl;
063: containerId = hdl.getId();
064: containerVersion = hdl.getContainerVersion();
065: }
066:
067: /*
068: * Formatable methods
069: */
070:
071: // no-arg constructor, required by Formatable
072: public ContainerBasicOperation() {
073: super ();
074: }
075:
076: public void writeExternal(ObjectOutput out) throws IOException {
077: containerId.writeExternal(out);
078: CompressedNumber.writeLong(out, containerVersion);
079: }
080:
081: public void readExternal(ObjectInput in) throws IOException,
082: ClassNotFoundException {
083: containerId = ContainerKey.read(in);
084: containerVersion = CompressedNumber.readLong(in);
085: }
086:
087: /**
088: Loggable methods
089: */
090:
091: /**
092: the default for prepared log is always null for all the operations
093: that don't have optionalData. If an operation has optional data,
094: the operation need to prepare the optional data for this method.
095:
096: Space Operation has no optional data to write out
097: */
098: public ByteArray getPreparedLog() {
099: return (ByteArray) null;
100: }
101:
102: public void releaseResource(Transaction tran) {
103: if (!foundHere)
104: return;
105:
106: if (containerHdl != null) {
107: containerHdl.close();
108: containerHdl = null;
109: }
110:
111: foundHere = false;
112: }
113:
114: /**
115: A space operation is a RAWSTORE log record
116: */
117: public int group() {
118: return Loggable.RAWSTORE;
119: }
120:
121: /**
122: Methods specific to this class
123: */
124:
125: /**
126: Open the container with this segmentId and containerId.
127: This method should only be called if the container has already been
128: created.
129:
130: @exception StandardException the container cannot be found or cannot be
131: opened.
132: */
133: protected RawContainerHandle findContainer(Transaction tran)
134: throws StandardException {
135: releaseResource(tran);
136:
137: RawTransaction rtran = (RawTransaction) tran;
138: containerHdl = rtran.openDroppedContainer(containerId,
139: (LockingPolicy) null);
140:
141: //If we are in roll forward recovery, missing container will be
142: //recreated becuase we might have hit a log record which has a
143: //reused the container id that was dropped earlier.
144: if (rtran.inRollForwardRecovery()) {
145: if (containerHdl == null) {
146: if (SanityManager.DEBUG) {
147: if (SanityManager.DEBUG_ON("LoadTran")) {
148: SanityManager
149: .DEBUG_PRINT(
150: "Trace",
151: "cannot find container "
152: + containerId
153: + ", now attempt last ditch effort");
154: }
155: }
156:
157: containerHdl = findContainerForRedoRecovery(rtran);
158:
159: if (SanityManager.DEBUG) {
160: if (SanityManager.DEBUG_ON("LoadTran")) {
161: SanityManager.DEBUG_PRINT("Trace",
162: " findContainerForRedoRecovery, got container="
163: + (containerHdl != null));
164: }
165: }
166:
167: }
168: }
169:
170: if (containerHdl == null) {
171: throw StandardException.newException(
172: SQLState.DATA_CONTAINER_VANISHED, containerId);
173: }
174:
175: foundHere = true;
176: return containerHdl;
177: }
178:
179: /**
180: Subclass (e.g., ContainerOperation) that wishes to do something abou
181: missing container in load tran should override this method to return
182: the recreated container
183:
184: @exception StandardException Cloudscape Standard error policy
185: */
186: protected RawContainerHandle findContainerForRedoRecovery(
187: RawTransaction tran) throws StandardException {
188: return null;
189: }
190:
191: /**
192: @exception StandardException Standard Cloudscape error policy
193: */
194: public boolean needsRedo(Transaction xact) throws StandardException {
195: findContainer(xact);
196:
197: long cVersion = containerHdl.getContainerVersion();
198:
199: if (cVersion == containerVersion)
200: return true;
201:
202: releaseResource(xact);
203:
204: if (cVersion > containerVersion)
205: return false;
206: else {
207: // RESOLVE - correct error handling
208: if (SanityManager.DEBUG) {
209: SanityManager
210: .THROWASSERT("log corrupted, missing log record: "
211: + "log container version = "
212: + containerVersion
213: + " container header version "
214: + cVersion);
215: }
216: return false;
217: }
218: }
219:
220: public String toString() {
221: if (SanityManager.DEBUG) {
222: return "Space Operation: " + containerId;
223: } else
224: return null;
225: }
226:
227: }
|