KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.store.raw.data.LogicalPageOperation
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.impl.store.raw.data.RecordId;
25 import org.apache.derby.impl.store.raw.data.BasePage;
26
27 import org.apache.derby.iapi.services.sanity.SanityManager;
28
29 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
30
31 import org.apache.derby.iapi.store.raw.ContainerHandle;
32 import org.apache.derby.iapi.store.raw.Compensation;
33 import org.apache.derby.iapi.store.raw.LogicalUndoable;
34 import org.apache.derby.iapi.store.raw.LockingPolicy;
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.Undoable;
39
40 import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
41 import org.apache.derby.iapi.store.raw.xact.RawTransaction;
42 import org.apache.derby.iapi.store.raw.log.LogInstant;
43
44 import org.apache.derby.iapi.error.StandardException;
45
46 import org.apache.derby.iapi.types.DataValueDescriptor;
47
48 import org.apache.derby.iapi.services.io.CompressedNumber;
49
50 import java.io.ObjectOutput JavaDoc;
51 import java.io.ObjectInput JavaDoc;
52 import java.io.IOException JavaDoc;
53 import org.apache.derby.iapi.services.io.LimitObjectInput;
54
55 /**
56     An abstract class that is used for logical log operation. A logical log
57     operation is one where the undo of the operation may be applied to a
58     different page than the original operation.
59
60     <PRE>
61     @format_id no format id, an abstract class.
62     @purpose provide methods for logical undo
63     @upgrade
64     @disk_layout
65         PageBasicOperation the super class
66         recordId(CompressedInt) the recordId this operation affects
67         undo(LogicalUndo) the piece of code that can figure out which page
68                                 the row has moved into
69         OptionalData none
70     @end_format
71     </PRE>
72
73 */

74 public abstract class LogicalPageOperation
75     extends PageBasicOperation implements LogicalUndoable
76 {
77
78     protected LogicalUndo undo; // Callback to access for logical undo.
79
// If non-null, then logical undo is necessary
80
// for this operation. If null, then the
81
// operation really only needs physical undo
82

83     protected int recordId; // record id - this is what the
84
// recordId is during the doMe time, it
85
// may have been changed now since the
86
// record may move to another page.
87

88     // no-arg constructor, required by Formatable
89
public LogicalPageOperation() { super(); }
90
91     protected LogicalPageOperation(BasePage page, LogicalUndo undo, int recordId)
92     {
93         super(page);
94         this.undo = undo;
95         this.recordId = recordId;
96     }
97
98     /*
99      * Formatable methods
100      */

101
102
103     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
104     {
105         super.writeExternal(out);
106         CompressedNumber.writeInt(out, recordId);
107         out.writeObject(undo);
108     }
109
110     /**
111         Read this in
112         @exception IOException error reading from log stream
113         @exception ClassNotFoundException log stream corrupted
114     */

115     public void readExternal(ObjectInput JavaDoc in)
116          throws IOException JavaDoc, ClassNotFoundException JavaDoc
117     {
118         super.readExternal(in);
119         recordId = CompressedNumber.readInt(in);
120         undo = (LogicalUndo)in.readObject();
121     }
122
123
124     /**
125         Undoable method
126     */

127
128     /**
129         Generate a Compensation (PageUndoOperation) that will rollback the
130         changes of this page operation. If this Page operation cannot or need not
131         be rolled back (redo only), overwrite this function to return null.
132
133         @see LogicalUndo
134         @exception StandardException Standard Cloudscape policy.
135         @exception IOException Method may read from ObjectInput
136     */

137
138     public Compensation generateUndo(Transaction xact, LimitObjectInput in)
139          throws StandardException, IOException JavaDoc
140     {
141         // if logical undo is not necessary, use normal physical undo
142
if (undo == null)
143         {
144             BasePage undoPage = findpage(xact);
145
146             // Needs to pre-dirty this page so that if a checkpoint is taken
147
// any time after the CLR is sent to the log stream, it will wait
148
// for the actual undo to happen on the page. We need this to
149
// preserve the integrity of the redoLWM.
150
undoPage.preDirty();
151
152             return new LogicalUndoOperation(undoPage, recordId, this);
153         }
154         else
155         {
156             if (SanityManager.DEBUG)
157             {
158                 // Sanity check to make sure logical undo is not called inside
159
// internal transaction
160
RawTransaction rtran = (RawTransaction)xact;
161                 rtran.checkLogicalOperationOk();
162             }
163
164             BasePage logicalUndoPage = findLogicalPage(xact, undo, in);
165
166             // Needs to pre-dirty this page so that if a checkpoint is taken
167
// any time after the CLR is sent to the log stream, it will wait
168
// for the actual undo to happen on the page. We need this to
169
// preserve the integrity of the redoLWM.
170
logicalUndoPage.preDirty();
171
172             // find logical page is going to call undo.findUndo to find the
173
// right page to apply the CLR to. If the record has changed,
174
// logicalUndo should have resetRecordHandle to reset the page
175
// number and the recordId to the new record location. We need to
176
// store both of these in the clr since during recovery redo,
177
// undo.findUndo is not called.
178
return new LogicalUndoOperation(logicalUndoPage, recordId, this);
179
180         }
181     }
182
183
184     /*
185      * LogicalUndoable methods
186      * These methods are called by undo.findUndo to extract information out of
187      * the log record for the purpose of logical undo.
188      */

189
190     /**
191         Return the container handle where the log operated on
192     */

193     public ContainerHandle getContainer()
194     {
195         if (SanityManager.DEBUG) {
196             SanityManager.ASSERT(containerHdl != null, "accessing null container handle");
197         }
198
199         return containerHdl;
200     }
201
202     /**
203         After the logical undo logic figures out where the real record that
204         needs roll back is, reset this log operation to refer to that record
205     */

206     public void resetRecordHandle(RecordHandle rh)
207     {
208         resetPageNumber(rh.getPageNumber());
209         recordId = rh.getId();
210     }
211
212
213     /**
214         Return the record handle that correspond to the record that was changed
215         during roll forward. This is used as a hint by logical undo as a good
216         place to look for the record to apply the roll back.
217     */

218     public RecordHandle getRecordHandle()
219     {
220         return new RecordId(getPageId(), recordId);
221     }
222
223     /**************************************************************************
224      * Public Methods of RePreparable Interface:
225      **************************************************************************
226      */

227
228     /**
229      * reclaim locks associated with the changes in this log record.
230      * <p>
231      * @param locking_policy The locking policy to use to claim the locks.
232      *
233      *
234      * @exception StandardException Standard exception policy.
235      **/

236     public void reclaimPrepareLocks(
237     Transaction t,
238     LockingPolicy locking_policy)
239         throws StandardException
240     {
241         if (SanityManager.DEBUG)
242         {
243             SanityManager.DEBUG_PRINT("", "reclaimPrepareLocks().");
244             SanityManager.ASSERT(getRecordHandle() != null);
245         }
246
247         ContainerHandle ch = t.openContainer(
248             getPageId().getContainerId(), locking_policy,
249             (ContainerHandle.MODE_FORUPDATE |
250              ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY |
251              ContainerHandle.MODE_LOCK_NOWAIT));
252
253         if (SanityManager.DEBUG)
254         {
255             SanityManager.ASSERT(ch != null);
256         }
257
258         if (ch != null)
259             ch.close();
260
261         /*
262         // get the intent lock on the container.
263         boolean lock_granted =
264             locking_policy.lockContainer(
265                 t,
266                 getContainer(),
267                 false, // don't wait for the lock, it is bug if a
268                                 // lock has to wait while reclaiming locks
269                                 // during recovery.
270                 true); // lock for update.
271
272         if (SanityManager.DEBUG)
273         {
274             SanityManager.ASSERT(lock_granted);
275         }
276         
277         */

278         // get the row lock on the c.
279
boolean lock_granted =
280             locking_policy.lockRecordForWrite(
281                 t,
282                 getRecordHandle(),
283                 false, // default is not for insert.
284
false); // don't wait for the lock, it is bug if a
285
// lock has to wait while reclaiming locks
286
// during recovery.
287

288         releaseResource(t);
289
290         if (SanityManager.DEBUG)
291         {
292             SanityManager.ASSERT(lock_granted);
293         }
294     }
295
296     /*
297      * method specific to this class
298      */

299
300     /**
301       Find the page that the rollback operation should be applied to.
302
303       <P>The actual logical log operation is expected to implement
304       Undoable.generateUndo. This utility function findLogicalPage is provided
305       for the common case scenario of using a LogicalUndo interface to find the
306       undo page. The subclass that implements Undoable.generateUndo can use
307       this function to find the logical page with its LogicalUndo callback function.
308       This method can be used with the default releaseResource().
309
310       <P>During recovery redo, the logging system is page oriented and will use
311       the pageID stored in the PageUndoOperation to find the page. The
312       page will be latched and released using the default findpage and
313       releaseResource - this.releaseResource() will still be called so it has
314       to know not to release any resource it did not acquire.
315
316       @param xact the transaction doing the compensating
317       @param in optional input
318
319       @return the compensation operation that will rollback this change
320
321         @exception StandardException Standard Cloudscape error policy
322         @exception IOException Method may read from ObjectInput
323
324       @see PageBasicOperation
325       @see Undoable#generateUndo
326       @see org.apache.derby.iapi.store.raw.Loggable#releaseResource
327     
328
329     */

330     private BasePage findLogicalPage(Transaction xact, LogicalUndo undo,
331                                        LimitObjectInput in)
332          throws StandardException, IOException JavaDoc
333     {
334         releaseResource(xact);
335
336         if (SanityManager.DEBUG) {
337             // the try,finally code makes these assumptions.
338
SanityManager.ASSERT(containerHdl == null);
339             SanityManager.ASSERT(page == null);
340         }
341
342         boolean okExit = false;
343
344         try {
345
346             // open the container
347
RawTransaction rtran = (RawTransaction)xact;
348
349             containerHdl = rtran.openDroppedContainer
350                 (getPageId().getContainerId(), (LockingPolicy) null);
351
352             if (SanityManager.DEBUG) {
353                 SanityManager.ASSERT(containerHdl != null, "cannot open container");
354                 SanityManager.ASSERT(containerHdl.getContainerStatus() != RawContainerHandle.COMMITTED_DROP,
355                                  "finding a page for undo in a committed dropped container");
356             }
357
358             page = (BasePage)(undo.findUndo(xact, this, in));
359
360             if (SanityManager.DEBUG) {
361                 SanityManager.ASSERT(page != null, "findUndo returns null page");
362                 SanityManager.ASSERT(page.getPageNumber() == getPageId().getPageNumber(),
363                                 "undo.findUndo did not reset the log op's recordHandle");
364             }
365
366             // if you add code here then ensure that you handle page unlatching in the
367
// backout code.
368

369             okExit = true;
370         } finally {
371
372             if (!okExit) {
373
374                 if (containerHdl != null) {
375                     containerHdl.close();
376                     containerHdl = null;
377                 }
378             }
379
380             // no need to unlatch page here because is page is valid no
381
// exceptions can be thrown, until some adds code after the findUndo.
382
}
383
384         foundHere = true;
385         return page;
386     }
387
388
389     /**
390         Undo the change indicated by this log operation and optional data.
391         The undoPage and undoRecordId is the page, record the undo should apply to.
392         The undoRecorId differs from the roll forward recordId if the undoPage
393         differs from the page the roll forward operation was applied to, in
394         other words, the record moved to another page and the recordId changed.
395
396         <BR>A logical operation can at most deal with 1 record.
397
398         <P> The available() method of in indicates how much data can be read, i.e.
399         how much was originally written.
400
401         <BR><B>In this RawStore implementation, should only only be called via
402         CompOp.doMe</B>.
403
404
405         @param xact the Transaction doing the rollback
406         @param undoPage the page to rollback changes on
407         @param undoRecordId the recordId to rollback changes on
408         @param CLRinstant the log instant of this (PageUndo) operation
409         @param in optional data for the rollback operation
410
411         @exception IOException Can be thrown by any of the methods of ObjectInput.
412         @exception StandardException Standard Cloudscape policy.
413     */

414     abstract public void undoMe(Transaction xact, BasePage undoPage, int undoRecordId,
415                                 LogInstant CLRinstant, LimitObjectInput in)
416          throws StandardException, IOException JavaDoc;
417
418
419 }
420
Popular Tags