001: /*
002:
003: Derby - Class org.apache.derbyTesting.unitTests.store.T_DaemonService
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.derbyTesting.unitTests.store;
023:
024: import org.apache.derbyTesting.unitTests.harness.T_Fail;
025:
026: import org.apache.derby.iapi.store.raw.*;
027:
028: import org.apache.derby.iapi.services.sanity.SanityManager;
029: import org.apache.derby.iapi.services.io.FormatIdUtil;
030: import org.apache.derby.iapi.services.io.Formatable;
031: import org.apache.derby.iapi.services.io.StoredFormatIds;
032: import org.apache.derby.iapi.error.StandardException;
033: import org.apache.derby.iapi.store.raw.log.LogInstant;
034: import org.apache.derby.iapi.util.ByteArray;
035: import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
036: import java.io.IOException;
037: import java.io.IOException;
038: import java.io.InputStream;
039: import java.io.ObjectInput;
040: import java.io.ObjectOutput;
041: import java.io.StreamCorruptedException;
042: import java.util.Vector;
043: import java.io.OutputStream;
044: import java.io.InputStream;
045: import org.apache.derby.iapi.services.io.LimitObjectInput;
046:
047: //
048: // Tracing can be done like so (commented out)
049: //import org.apache.derbyTesting.unitTests.util.MsgTrace;
050:
051: public class T_Undoable implements Undoable {
052: static final int REMOVE_NONE = 0;
053: static final int REMOVE_ME = 1;
054: static final int REMOVE_TO_ME = 2;
055:
056: protected ByteArray preparedLog;
057: protected DynamicByteArrayOutputStream logBuffer;
058:
059: GlobalTransactionId tid = null;
060: int tranSeq = -1;
061: int recordSeq = -1;
062: int removeWhat = REMOVE_NONE;
063: int LWMTranSeq = 0;
064: boolean rollBack = true;
065: int lastRecord = -1;
066: boolean lastTransaction = false;
067: int optionalDataLen;
068: boolean verbose;
069:
070: // no-arg constructor, required by Formatable
071: public T_Undoable() {
072: super ();
073: }
074:
075: T_Undoable(GlobalTransactionId tid, int tranSeq, int recordSeq,
076: int removeWhat, int LWMTranSeq, boolean rollBack,
077: int lastRecord, boolean lastTransaction,
078: int optionalDataLen, boolean verbose) throws T_Fail {
079: //MsgTrace.traceString("{{{tu.new");
080: T_Fail.T_ASSERT((removeWhat >= REMOVE_NONE)
081: && (removeWhat <= REMOVE_TO_ME));
082: T_Fail.T_ASSERT(rollBack == (recordSeq < 0));
083: T_Fail.T_ASSERT(rollBack == (tranSeq < 0));
084: this .tid = tid;
085: this .tranSeq = tranSeq;
086: this .recordSeq = recordSeq;
087: this .removeWhat = removeWhat;
088: this .LWMTranSeq = LWMTranSeq;
089: this .rollBack = rollBack;
090: this .lastRecord = lastRecord;
091: this .lastTransaction = lastTransaction;
092: this .optionalDataLen = optionalDataLen;
093: this .verbose = verbose;
094:
095: try {
096: writeOptionalDataToBuffer();
097: } catch (IOException ioe) {
098: throw T_Fail.exceptionFail(ioe);
099: } catch (StandardException se) {
100: throw T_Fail.exceptionFail(se);
101: }
102:
103: //MsgTrace.traceString("}}}tu.new");
104:
105: }
106:
107: private void writeOptionalDataToBuffer() throws StandardException,
108: IOException {
109:
110: if (logBuffer == null) {
111: // YYZ: need to revisit this. Do we really want to allocate this much for a buffer every time?
112: logBuffer = new DynamicByteArrayOutputStream(1024); // init size 1K
113: } else {
114: logBuffer.reset();
115: }
116:
117: int optionalDataStart = logBuffer.getPosition();
118:
119: if (SanityManager.DEBUG) {
120: SanityManager
121: .ASSERT(optionalDataStart == 0,
122: "Buffer for writing the optional data should start at position 0");
123: }
124:
125: //MsgTrace.traceString("{{{tu.writeOpetionalData");
126: if (optionalDataLen > 0) {
127: byte[] buf = new byte[optionalDataLen];
128: for (int ix = 0; ix < optionalDataLen; ix++)
129: buf[ix] = (byte) ix;
130: logBuffer.write(buf);
131: }
132: //MsgTrace.traceString("}}}tu.writeOpetionalData");
133:
134: int optionalDataLength = logBuffer.getPosition()
135: - optionalDataStart;
136:
137: if (SanityManager.DEBUG) {
138: if (optionalDataLength != logBuffer.getUsed())
139: SanityManager
140: .THROWASSERT("wrong optional data length, optionalDataLength = "
141: + optionalDataLength
142: + ", logBuffer.getUsed() = "
143: + logBuffer.getUsed());
144: }
145:
146: // set the position to the beginning of the buffer
147: logBuffer.setPosition(optionalDataStart);
148:
149: this .preparedLog = new ByteArray(logBuffer.getByteArray(),
150: optionalDataStart, optionalDataLength);
151: }
152:
153: /*
154: Loggable methods
155: */
156: public void doMe(Transaction xact, LogInstant instant,
157: LimitObjectInput in) {
158: if (verbose)
159: System.out.println("Loggable.doMe(" + toString() + ")");
160: return;
161: }
162:
163: /*
164: methods to support prepared log
165: the following two methods should not be called during recover
166: */
167:
168: public ByteArray getPreparedLog() {
169: return this .preparedLog;
170: }
171:
172: public boolean needsRedo(Transaction xact) {
173: return false;
174: }
175:
176: public void releaseResource(Transaction xact) {
177: return;
178: }
179:
180: public int group() {
181: return Loggable.RAWSTORE;
182: };
183:
184: /*
185: Undoable methods.
186: */
187: public Compensation generateUndo(Transaction xact,
188: LimitObjectInput in) throws StandardException, IOException {
189: //MsgTrace.traceString("+++tu.generateUndo");
190: return new T_Compensation();
191: }
192:
193: /*
194: Formatable methods
195: */
196:
197: /**
198: @exception IOException thrown on error
199: */
200: public void writeExternal(ObjectOutput out) throws IOException {
201: //MsgTrace.traceString("{{{tu.writeExternal");
202: if (SanityManager.DEBUG) {
203: SanityManager.ASSERT((removeWhat >= REMOVE_NONE)
204: && (removeWhat <= REMOVE_TO_ME));
205: SanityManager.ASSERT(rollBack == (recordSeq < 0));
206: SanityManager.ASSERT(rollBack == (tranSeq < 0));
207: }
208: out.writeObject(tid);
209: out.writeInt(tranSeq);
210: out.writeInt(recordSeq);
211: out.writeInt(removeWhat);
212: out.writeInt(LWMTranSeq);
213: out.writeBoolean(rollBack);
214: out.writeInt(lastRecord);
215: out.writeBoolean(lastTransaction);
216: out.writeInt(optionalDataLen);
217: //MsgTrace.traceString("}}}tu.writeExternal");
218: }
219:
220: public void readExternal(ObjectInput in) throws IOException,
221: ClassNotFoundException {
222: //MsgTrace.traceString("{{{tu.readExternal");
223: try {
224: tid = (GlobalTransactionId) in.readObject();
225: tranSeq = in.readInt();
226: recordSeq = in.readInt();
227: removeWhat = in.readInt();
228: LWMTranSeq = in.readInt();
229: rollBack = in.readBoolean();
230: lastRecord = in.readInt();
231: lastTransaction = in.readBoolean();
232: optionalDataLen = in.readInt();
233: }
234:
235: catch (ClassCastException exception) {
236: //MsgTrace.traceString("{{{tu.readExternal---exception");
237: throw new StreamCorruptedException();
238: }
239: //MsgTrace.traceString("}}}tu.readExternal");
240: }
241:
242: public int getTypeFormatId() {
243: return StoredFormatIds.SERIALIZABLE_FORMAT_ID;
244: }
245:
246: /*
247: Object methods.
248: */
249: public String toString() {
250: String traceTid = "tid: null";
251:
252: if (tid != null)
253: traceTid = "tid: " + tid;
254:
255: String traceRemoveWhat;
256: switch (removeWhat) {
257: case REMOVE_NONE:
258: traceRemoveWhat = "REMOVE_NONE";
259: break;
260: case REMOVE_ME:
261: traceRemoveWhat = "REMOVE_ME";
262: break;
263: case REMOVE_TO_ME:
264: traceRemoveWhat = "REMOVE_TO_ME";
265: break;
266: default:
267: traceRemoveWhat = "removeWhat: invalidValue";
268: break;
269: }
270:
271: return traceTid + " " + "tranSeq: " + tranSeq + " "
272: + "recordSeq: " + recordSeq + " " + traceRemoveWhat
273: + " " + "LWMTranSeq: " + LWMTranSeq + " "
274: + "rollback: " + rollBack + " " + "lastRecord: "
275: + lastRecord + " " + "optionalDataLen: "
276: + optionalDataLen + " " + "lastTransaction: "
277: + lastTransaction;
278: }
279:
280: }
|