KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.store.raw.data.UpdateOperation
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.error.StandardException;
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
39 import org.apache.derby.iapi.store.raw.log.LogInstant;
40 import org.apache.derby.iapi.store.raw.xact.RawTransaction;
41
42 import org.apache.derby.iapi.types.DataValueDescriptor;
43
44 import org.apache.derby.iapi.services.io.FormatableBitSet;
45 import org.apache.derby.iapi.util.ByteArray;
46 import org.apache.derby.iapi.services.io.CompressedNumber;
47 import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
48 import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
49
50 import java.io.OutputStream JavaDoc;
51 import java.io.ObjectOutput JavaDoc;
52 import java.io.ObjectInput JavaDoc;
53 import java.io.IOException JavaDoc;
54 import org.apache.derby.iapi.services.io.LimitObjectInput;
55
56
57 /**
58     Represents the update of a particular row on a page.
59
60     <PRE>
61     @format_id LOGOP_UPDATE
62         the formatId is written by FormatIdOutputStream when this object is
63         written out by writeObject
64     @purpose update a record on the page
65     @upgrade
66     @disk_layout
67         PhysicalPageOperation the super class
68         doMeSlot(CompressedInt) the slot the updated record is in
69         recordId(CompressedInt) the recordId of the updated record
70
71         OptionalData The new image of the record (length included),
72                         follow by the old image of the record (length included)
73     @end_format
74     </PRE>
75 */

76
77 public final class UpdateOperation extends PhysicalPageOperation {
78
79     protected int doMeSlot; // record slot - only valid during a doMe() operation
80
protected int recordId; // record id
81
transient protected int nextColumn; // next column that needs to be updated in a row.
82

83     transient protected ByteArray preparedLog;
84     
85     public UpdateOperation(
86     RawTransaction t,
87     BasePage page,
88     int slot,
89     int recordId,
90     Object JavaDoc[] row,
91     FormatableBitSet validColumns,
92     int realStartColumn,
93     DynamicByteArrayOutputStream logBuffer,
94     int realSpaceOnPage,
95     RecordHandle headRowHandle)
96         throws StandardException
97     {
98         super(page);
99
100         this.doMeSlot = slot;
101         this.recordId = recordId;
102         this.nextColumn = -1;
103         
104         // RESOLVE SRW-DJD/YYZ
105
try {
106             writeOptionalDataToBuffer(t, (DynamicByteArrayOutputStream) logBuffer,
107                 row, validColumns, realStartColumn,
108                 realSpaceOnPage, headRowHandle);
109         } catch (IOException JavaDoc ioe) {
110             throw StandardException.newException(
111                     SQLState.DATA_UNEXPECTED_EXCEPTION, ioe);
112         }
113
114     }
115
116     /*
117      * Formatable methods
118      */

119
120     // no-arg constructor, required by Formatable
121
public UpdateOperation() { super(); }
122
123     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
124     {
125         super.writeExternal(out);
126         CompressedNumber.writeInt(out, doMeSlot);
127         CompressedNumber.writeInt(out, recordId);
128     }
129
130     /**
131         Read this in
132         @exception IOException error reading from log stream
133         @exception ClassNotFoundException log stream corrupted
134     */

135     public void readExternal(ObjectInput JavaDoc in)
136          throws IOException JavaDoc, ClassNotFoundException JavaDoc
137     {
138         super.readExternal(in);
139         doMeSlot = CompressedNumber.readInt(in);
140         recordId = CompressedNumber.readInt(in);
141     }
142
143     /**
144         Return my format identifier.
145     */

146     public int getTypeFormatId() {
147         return StoredFormatIds.LOGOP_UPDATE;
148     }
149
150     /**
151         Return the last column of the row this operation logged
152     */

153     public int getNextStartColumn() {
154         return nextColumn;
155     }
156
157     /*
158      * Loggable methods
159      */

160     /**
161         Store the new record directly over the old record, the implementation
162         of storeRecord is responsible for removing any old data.
163
164         @exception StandardException Thrown by methods I call
165         @exception IOException Thrown by methods I call
166
167         @see BasePage#storeRecord
168         @see org.apache.derby.iapi.store.raw.Loggable#doMe
169     */

170     public void doMe(Transaction xact, LogInstant instant, LimitObjectInput in)
171          throws StandardException, IOException JavaDoc
172     {
173         this.page.storeRecord(instant, doMeSlot, false, in);
174     }
175     
176
177     /*
178      * PhysicalPageOperation methods
179      */

180
181     /**
182         Store the old record directly over the new record, the implementation
183         of storeRecord is responsible for removing any new data.
184
185         @exception StandardException Thrown by methods I call
186         @exception IOException Thrown by methods I call
187
188         @see BasePage#storeRecord
189         @see PhysicalPageOperation#undoMe
190     */

191     public void undoMe(Transaction xact, BasePage undoPage,
192                        LogInstant CLRInstant, LimitObjectInput in)
193          throws StandardException, IOException JavaDoc
194     {
195
196         int slot = undoPage.findRecordById(recordId, Page.FIRST_SLOT_NUMBER);
197
198         // skip the after image of the record
199
undoPage.skipRecord(in);
200
201         undoPage.storeRecord(CLRInstant, slot, false, in);
202         undoPage.setAuxObject(null);
203     }
204
205     /*
206         methods to support prepared log
207         
208         the following two methods should not be called during recover
209     */

210
211     public ByteArray getPreparedLog()
212     {
213         return (this.preparedLog);
214     }
215
216     /**
217         Write out the changed colums of new record (from the row) followed by
218         changed columns of the old record (from the page).
219
220         @exception StandardException Thrown by methods I call
221         @exception IOException Thrown by methods I call
222     */

223     private void writeOptionalDataToBuffer(
224     RawTransaction t,
225     DynamicByteArrayOutputStream logBuffer,
226     Object JavaDoc[] row,
227     FormatableBitSet validColumns,
228     int realStartColumn,
229     int realSpaceOnPage,
230     RecordHandle headRowHandle)
231         throws StandardException, IOException JavaDoc
232     {
233
234         if (SanityManager.DEBUG)
235         {
236             SanityManager.ASSERT(this.page != null);
237         }
238
239         if (realStartColumn == (-1))
240         {
241             logBuffer = t.getLogBuffer();
242         }
243
244         int optionalDataStart = logBuffer.getPosition();
245
246         if (SanityManager.DEBUG)
247         {
248
249             SanityManager.ASSERT(
250                 (realStartColumn != -1 || optionalDataStart == 0),
251                 "Buffer for writing optional data should start at position 0");
252         }
253
254
255         this.nextColumn =
256             this.page.logRow(
257                 doMeSlot, false, recordId, row, validColumns,
258                 logBuffer, 0, Page.INSERT_OVERFLOW, realStartColumn,
259                 realSpaceOnPage, 100);
260
261         FormatableBitSet loggedColumns = validColumns;
262
263         // If this update results in moving columns off the current page to
264
// another page, then we must log the before image values of the columns
265
// being moved (deleted from this page) in addition to logging the
266
// columns actually being changed as part of the update.
267

268         if ((nextColumn != -1) && (validColumns != null))
269         {
270             // if nextColumn is not -1, then this must be an update which moves
271
// columns off of the current page. If validColumns == null then
272
// we are logging all of the before image columns anyway.
273

274             // get total number of fields of the old record.
275
int numberFields = page.getHeaderAtSlot(doMeSlot).getNumberFields();
276
277             // create new bit map, copying all bits that were set in original
278
loggedColumns = new FormatableBitSet(validColumns);
279
280             // make sure there is room in the bit map to add the columns being
281
// deleted from the end of the row.
282
// The important thing is that endField must be at least as big as
283
// the number of columns in the entire record (including previous
284
// pages of a long row) up to the end of this page.
285
int endField = nextColumn + numberFields;
286             loggedColumns.grow(endField);
287             // now include all columns being deleted.
288
// This actually sets too many bits in this bit set but
289
// logRecord will just ignore the extra bits.
290
for (int i = nextColumn; i < endField; i++)
291             {
292                 loggedColumns.set(i);
293             }
294         }
295
296         // log the old version of the changed data
297
this.page.logRecord(
298             doMeSlot, BasePage.LOG_RECORD_FOR_UPDATE,
299             recordId, loggedColumns, logBuffer, headRowHandle);
300
301         // get length of all the optional data.
302
optionalDataStart = logBuffer.getBeginPosition();
303         int optionalDataLength = logBuffer.getPosition() - optionalDataStart;
304
305         // set the position to the beginning of the buffer
306
logBuffer.setPosition(optionalDataStart);
307
308         this.preparedLog = new ByteArray(
309             logBuffer.getByteArray(), optionalDataStart, optionalDataLength);
310     }
311
312     /*
313      * PageBasicOperation
314      */

315
316     /**
317      * restore the before image of the page
318      *
319      * @exception StandardException Standard Cloudscape Error Policy
320      * @exception IOException problem reading the complete log record from the
321      * input stream
322      */

323     public void restoreMe(Transaction xact, BasePage undoPage,
324                        LogInstant CLRInstant, LimitObjectInput in)
325          throws StandardException, IOException JavaDoc
326     {
327         undoMe(xact, undoPage, CLRInstant, in);
328     }
329
330
331     public String JavaDoc toString()
332     {
333         if (SanityManager.DEBUG)
334         {
335             return super.toString() +
336             "Update " +
337             " Slot=" + doMeSlot +
338             " recordId=" + recordId;
339         }
340         else
341             return null;
342     }
343 }
344
Popular Tags