KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > store > raw > data > UpdateFieldOperation


1 /*
2
3    Derby - Class org.apache.derby.impl.store.raw.data.UpdateFieldOperation
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.store.raw.data;
23
24 import org.apache.derby.iapi.reference.SQLState;
25
26 import org.apache.derby.impl.store.raw.data.BasePage;
27
28 import org.apache.derby.iapi.services.sanity.SanityManager;
29
30 import org.apache.derby.iapi.services.io.FormatIdUtil;
31 import org.apache.derby.iapi.services.io.StoredFormatIds;
32
33 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
34
35 import org.apache.derby.iapi.store.raw.Page;
36 import org.apache.derby.iapi.store.raw.RecordHandle;
37 import org.apache.derby.iapi.store.raw.Transaction;
38 import org.apache.derby.iapi.store.raw.xact.RawTransaction;
39
40 import org.apache.derby.iapi.store.raw.log.LogInstant;
41
42 import org.apache.derby.iapi.error.StandardException;
43
44 import org.apache.derby.iapi.types.DataValueDescriptor;
45
46 import org.apache.derby.iapi.services.io.FormatableBitSet;
47 import org.apache.derby.iapi.services.io.CompressedNumber;
48 import org.apache.derby.iapi.util.ByteArray;
49 import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
50
51 import java.io.OutputStream JavaDoc;
52 import java.io.ObjectOutput JavaDoc;
53 import java.io.ObjectInput JavaDoc;
54 import java.io.IOException JavaDoc;
55 import org.apache.derby.iapi.services.io.LimitObjectInput;
56
57
58 /**
59     Represents the update of a particular field of a row on a page.
60
61     <PRE>
62     @format_id LOGOP_UPDATE_FIELD
63         the formatId is written by FormatIdOutputStream when this object is
64         written out by writeObject
65     @purpose update a field of a record on the page
66     @upgrade
67     @disk_layout
68         LogicalPageOperation the super class
69         doMeSlot(CompressedInt) the slot of the record being updated
70         fieldId(CompressedInt) the recordId of the record being updated
71
72         OptionalData The after image of the column (length included),
73                         follow by the old image of the record (length
74                         included). If this is logically undoable, then the
75                         before image of the entire row is logged
76     @end_format
77     </PRE>
78 */

79 public final class UpdateFieldOperation extends LogicalPageOperation
80 {
81
82     protected int doMeSlot; // insert slot - only valid during a doMe() operation
83
protected int fieldId;
84
85     transient protected ByteArray preparedLog;
86
87     public UpdateFieldOperation(
88     RawTransaction t,
89     BasePage page,
90     int slot,
91     int recordId,
92     int fieldId,
93     Object JavaDoc column,
94     LogicalUndo undo)
95         throws StandardException
96     {
97         super(page, undo, recordId);
98
99         this.doMeSlot = slot;
100         this.fieldId = fieldId;
101
102         try {
103             writeOptionalDataToBuffer(t, column);
104         } catch (IOException JavaDoc ioe) {
105             throw StandardException.newException(
106                     SQLState.DATA_UNEXPECTED_EXCEPTION, ioe);
107         }
108     }
109
110     /*
111      * Formatable methods
112      */

113
114     // no-arg constructor, required by Formatable
115
public UpdateFieldOperation() { super(); }
116
117     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
118     {
119         super.writeExternal(out);
120         CompressedNumber.writeInt(out, doMeSlot);
121         CompressedNumber.writeInt(out, fieldId);
122     }
123
124     /**
125         Read this in
126         @exception IOException error reading from log stream
127         @exception ClassNotFoundException log stream corrupted
128     */

129     public void readExternal(ObjectInput JavaDoc in)
130          throws IOException JavaDoc, ClassNotFoundException JavaDoc
131     {
132         super.readExternal(in);
133         doMeSlot = CompressedNumber.readInt(in);
134         fieldId = CompressedNumber.readInt(in);
135     }
136
137     /**
138         Return my format identifier.
139     */

140     public int getTypeFormatId() {
141         return StoredFormatIds.LOGOP_UPDATE_FIELD;
142     }
143
144     /*
145      * Loggable methods
146      */

147     /**
148         Change the value of a field.
149
150         @exception IOException Can be thrown by any of the methods of ObjectInput.
151         @exception StandardException Standard Cloudscape policy.
152
153         @see org.apache.derby.iapi.store.raw.Loggable#doMe
154     */

155     public void doMe(Transaction xact, LogInstant instant, LimitObjectInput in)
156          throws StandardException, IOException JavaDoc
157     {
158         this.page.storeField(instant, doMeSlot, fieldId, in);
159     }
160     
161     /*
162      * Undoable methods
163      */

164
165     /**
166         Restore field to its old value.
167
168         @exception IOException Can be thrown by any of the methods of ObjectInput.
169         @exception StandardException Standard Cloudscape policy.
170
171         @see LogicalPageOperation#undoMe
172     */

173     public void undoMe(Transaction xact, BasePage undoPage, int undoRecordId,
174                        LogInstant CLRInstant, LimitObjectInput in)
175          throws StandardException, IOException JavaDoc
176     {
177         int slot =
178             undoPage.findRecordById(undoRecordId, Page.FIRST_SLOT_NUMBER);
179         
180         if (SanityManager.DEBUG)
181         {
182             // if the record Id has changed, the page had better changed
183
// this can only happen during recovery since in run time undo,
184
// this resetRecordHandle gets called and this object have the new
185
// page number and recordId
186
if (undoRecordId != this.recordId)
187                 if (undoPage.getPageNumber() == getPageId().getPageNumber())
188                     SanityManager.THROWASSERT(
189                                      "recordId changed from " + this.recordId +
190                                      " to " + undoRecordId +
191                                      " but page number did not change " +
192                                      undoPage.getPageNumber());
193
194             if (slot == -1)
195                 SanityManager.THROWASSERT(
196                     "recordId " +
197                     undoRecordId +
198                     " not found on page " +
199                     undoPage.getPageNumber());
200         }
201
202         undoPage.skipField((java.io.ObjectInput JavaDoc) in); // skip the after image of the column
203
undoPage.storeField(CLRInstant, slot, fieldId, in);
204         undoPage.setAuxObject(null);
205     }
206
207     /*
208      * LogicalUndoable methods
209      */

210
211
212     /**
213         Restore the row stored in the optional data of the log record.
214
215         @exception IOException error reading from log stream
216         @exception StandardException Standard Cloudscape error policy
217     */

218     public void restoreLoggedRow(Object JavaDoc[] row, LimitObjectInput in)
219         throws StandardException, IOException JavaDoc
220     {
221         BasePage p = null;
222
223         try {
224             // the optional data is written by the page in the same format it
225
// stores record on the page,
226
// only a page knows how to restore a logged row back to a storable row
227
// first get the page where the insert went even though the row may no
228
// longer be there
229
p = (BasePage)(getContainer().getPage(getPageId().getPageNumber()));
230
231             // skip over the before and after image of the column, position the
232
// input stream at the entire row
233
p.skipField(in); // AI of the column
234
p.skipField(in); // BI of the column
235

236             p.restoreRecordFromStream(in, row);
237
238             // RESOLVE: this returns the BI of the row, what we need is the AI
239
// of the row. We need to someone splice in the AI of the column
240
// into the storable row.
241

242         } finally {
243
244             if (p != null) {
245                 p.unlatch();
246                 p = null;
247             }
248         }
249     }
250
251     /*
252      * method to support BeforeImageLogging
253      */

254
255     /**
256      * restore the before image of the page
257      *
258      * @exception StandardException Standard Cloudscape Error Policy
259      * @exception IOException problem reading the complete log record from the
260      * input stream
261      */

262     public void restoreMe(Transaction xact, BasePage undoPage, LogInstant CLRInstant, LimitObjectInput in)
263          throws StandardException, IOException JavaDoc
264     {
265         int slot = undoPage.findRecordById(recordId, Page.FIRST_SLOT_NUMBER);
266         if (SanityManager.DEBUG)
267         {
268             if ( ! getPageId().equals(undoPage.getPageId()))
269                 SanityManager.THROWASSERT(
270                                 "restoreMe cannot restore to a different page. "
271                                  + "doMe page:" + getPageId() + " undoPage:" +
272                                  undoPage.getPageId());
273             if (slot != doMeSlot)
274                 SanityManager.THROWASSERT(
275                                 "restoreMe cannot restore to a different slot. "
276                                  + "doMe slot:" + doMeSlot + " undoMe slot: " +
277                                  slot + " recordId:" + recordId);
278         }
279
280         undoPage.skipField(in); // skip the after image of the column
281
undoPage.storeField(CLRInstant, slot, fieldId, in);
282         undoPage.setAuxObject(null);
283     }
284
285     /*
286         methods to support prepared log
287         
288         the following two methods should not be called during recover
289     */

290
291     public ByteArray getPreparedLog()
292     {
293         return (this.preparedLog);
294     }
295
296     /**
297       Write the old column value and and new column value as optional data.
298       If logical undo, writes out the entire row's before image.
299
300         @exception IOException Can be thrown by any of the methods of ObjectOutput.
301         @exception StandardException Standard Cloudscape policy.
302     */

303     private void writeOptionalDataToBuffer(
304     RawTransaction t,
305     Object JavaDoc column)
306         throws StandardException, IOException JavaDoc
307     {
308
309         if (SanityManager.DEBUG) {
310             SanityManager.ASSERT(this.page != null);
311         }
312
313         DynamicByteArrayOutputStream logBuffer = t.getLogBuffer();
314         int optionalDataStart = logBuffer.getPosition();
315
316         if (SanityManager.DEBUG) {
317             SanityManager.ASSERT(optionalDataStart == 0,
318                 "Buffer for writing optional data should start at position 0");
319         }
320                 
321         this.page.logColumn(doMeSlot, fieldId, column, logBuffer, 100); // the after image of the column
322
this.page.logField(doMeSlot, fieldId, logBuffer); // the BI of the column
323
if (undo != null)
324         {
325             // RESOLVE: we want the AFTER image of the row, not the BEFORE
326
// image. This works for now because only btree needs a logical
327
// undoable updateField and it always update only the pointer field
328
// to point to something else.
329
//
330
// But in the future, it needs to be changed.
331

332             this.page.logRecord(doMeSlot, BasePage.LOG_RECORD_DEFAULT,
333                                 recordId, (FormatableBitSet) null, logBuffer,
334                                 (RecordHandle)null);
335             // log the BI of the entire row
336

337         }
338
339         int optionalDataLength = logBuffer.getPosition() - optionalDataStart;
340
341         if (SanityManager.DEBUG) {
342             if (optionalDataLength != logBuffer.getUsed())
343                 SanityManager.THROWASSERT("wrong optional data length, optionalDataLength = "
344                     + optionalDataLength + ", logBuffer.getUsed() = " + logBuffer.getUsed());
345         }
346
347         // set the position to the beginning of the buffer
348
logBuffer.setPosition(optionalDataStart);
349
350         this.preparedLog = new ByteArray(logBuffer.getByteArray(), optionalDataStart,
351             optionalDataLength);
352     }
353
354     /**
355       DEBUG: Print self.
356     */

357     public String JavaDoc toString()
358     {
359         if (SanityManager.DEBUG)
360         {
361             return super.toString() +
362                 "UpdateField : " +
363                 " Slot=" + doMeSlot +
364                 " recordId=" + recordId +
365                 " fieldId=" + fieldId;
366         }
367         else
368             return null;
369     }
370
371 }
372
Popular Tags