KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.store.raw.data.PageBasicOperation
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.store.raw.ContainerHandle;
29 import org.apache.derby.iapi.store.raw.LockingPolicy;
30 import org.apache.derby.iapi.store.raw.Loggable;
31 import org.apache.derby.iapi.store.raw.Page;
32 import org.apache.derby.iapi.store.raw.RePreparable;
33 import org.apache.derby.iapi.store.raw.Transaction;
34 import org.apache.derby.iapi.store.raw.PageKey;
35
36 import org.apache.derby.iapi.store.raw.xact.RawTransaction;
37 import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
38 import org.apache.derby.iapi.store.raw.log.LogInstant;
39 import org.apache.derby.iapi.store.raw.RawStoreFactory;
40
41 import org.apache.derby.iapi.error.StandardException;
42 import org.apache.derby.iapi.services.sanity.SanityManager;
43
44 import org.apache.derby.iapi.types.DataValueDescriptor;
45
46 import org.apache.derby.iapi.services.io.CompressedNumber;
47 import org.apache.derby.iapi.util.ByteArray;
48 import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
49 import org.apache.derby.iapi.services.property.PropertyUtil;
50
51 import java.io.InputStream 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     A PageBasicOperation changed the content of a page, this is the root class of all
59     page oriented operation. Each PageBasicOperation record change(s)
60     that apply to <B>one and only one page</B>. The pageID that is changed
61     must be recorded in the log operation - in other words, redo
62     must be physical (or more correctly, in Gray's term, physiological, since
63     changes are logical <B>within</B> a page).
64     <BR>Undo can be logical, but the undo logic must be hidden in
65     generateUndo. By the time a compensation operation is logged as a
66     LogOperation, the page that needs roll back must be determined.
67
68     <PRE>
69     @format_id no format id, an abstract class.
70     @purpose provide methods for logical undo
71     @upgrade
72     @disk_layout
73         pageId(PageKey) the page this operation applies to
74         pageVersion(CompressedLong) the page version this operation applied to
75         OptionalData none
76     @end_format
77     </PRE>
78
79     @see Loggable
80 */

81
82 public abstract class PageBasicOperation implements Loggable, RePreparable
83 {
84
85
86     /* page info this operation changed */
87     private PageKey pageId;
88     private long pageVersion;
89
90
91     /* runtime page and data necessary to maintain it */
92     transient protected BasePage page;
93     transient protected RawContainerHandle containerHdl;
94     transient protected boolean foundHere;
95
96     protected PageBasicOperation(BasePage page)
97     {
98         if (SanityManager.DEBUG)
99         {
100             SanityManager.ASSERT(
101                 page != null,
102                 "cannot create page operation on a null page pointer");
103         }
104
105         // runtime info
106
this.page = page;
107
108         // info which will be logged.
109
pageId = page.getPageId();
110         pageVersion = page.getPageVersion();
111     }
112
113     // no-arg constructor, required by Formatable
114
public PageBasicOperation()
115     {
116     }
117
118     public String JavaDoc toString()
119     {
120         if (SanityManager.DEBUG)
121         {
122             return "Page Operation: " + pageId.toString() +
123                 " pageVersion " + pageVersion + " : ";
124         }
125         else
126             return null;
127     }
128
129     /*
130      * Formatable methods
131      */

132
133
134     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
135     {
136         pageId.writeExternal(out);
137         CompressedNumber.writeLong(out, pageVersion);
138     }
139
140     public void readExternal(ObjectInput JavaDoc in)
141         throws IOException JavaDoc, ClassNotFoundException JavaDoc
142     {
143         pageId = PageKey.read(in);
144
145         pageVersion = CompressedNumber.readLong(in);
146     }
147
148     /*
149      * Loggable methods
150      */

151
152     /** Returns true if this op should be redone during recovery redo,
153         if so, get and latched the page.
154
155         @exception StandardException Standard Cloudscape policy.
156      */

157     public final boolean needsRedo(Transaction xact)
158          throws StandardException
159     {
160         if (findpage(xact) == null) // committed dropped container
161
return false;
162
163         long pversion = page.getPageVersion();
164         if (pversion == pageVersion)
165             return true;
166
167         releaseResource(xact);
168
169         if (pversion > pageVersion)
170             return false;
171         else
172             throw StandardException.newException(
173                     SQLState.DATA_MISSING_LOG, pageId,
174                     new Long JavaDoc(pversion),
175                     new Long JavaDoc(pageVersion));
176     }
177
178     /** Release latched page and any other resources acquired during a previous
179         findpage, safe to call multiple times.
180
181         In this RawStore implementataion, resource is acquired by a log
182         operation in one of two places
183         <nl>
184         <li> during runtime or recovery undo in PageOperation.generateUndo()
185         <li> during recovery redo in PageBasicOperation.needsRedo()
186         </nl>
187      */

188     public void releaseResource(Transaction xact)
189     {
190         if (!foundHere) // don't release anything not found by this
191
return;
192
193         if (page != null)
194         {
195             page.unlatch();
196             page = null;
197         }
198
199         if (containerHdl != null)
200         {
201             containerHdl.close();
202             containerHdl = null;
203         }
204
205         foundHere = false;
206     }
207
208     /**
209         A page operation is a RAWSTORE log record
210     */

211     public int group()
212     {
213         return(Loggable.RAWSTORE | Loggable.XA_NEEDLOCK);
214     }
215
216     /**
217         the default for optional data is set to null. If an operation has optional data,
218         the operation need to prepare the optional data for this method.
219
220         WARNING: If a log operation extends this class, and the operation has optional data,
221         it MUST overwrite this method to return a ByteArray that contains the optional data.
222
223         @exception StandardException Standard Cloudscape policy.
224     */

225     public ByteArray getPreparedLog() throws StandardException
226     {
227         return (ByteArray) null;
228     }
229
230     /**************************************************************************
231      * Public Methods of RePreparable Interface:
232      **************************************************************************
233      */

234
235     /**
236      * reclaim locks associated with the changes in this log record.
237      * <p>
238      *
239      * @exception StandardException Standard exception policy.
240      **/

241     public void reclaimPrepareLocks(
242     Transaction t,
243     LockingPolicy locking_policy)
244         throws StandardException
245     {
246         if (SanityManager.DEBUG)
247             SanityManager.DEBUG_PRINT("", "PageBasicOperation.reclaimPrepareLocks().");
248     }
249
250     /*
251      * Methods specific to this class
252      */

253          
254     /**
255         Reset the pageNumber
256     */

257     protected final void resetPageNumber(long pageNumber)
258     {
259         pageId = new PageKey(pageId.getContainerId(), pageNumber);
260     }
261
262     protected final PageKey getPageId() {
263         return pageId;
264     }
265
266     /** Find the page the operation applies to and latch it, this only
267         uses the segmentId, containerId, and pageId stored in this log
268         record to find the page.
269
270         @return null if container is dropped and committed (possibly
271         stubbified), else return the latched page
272
273         @exception StandardException Standard Cloudscape policy.
274      */

275     public final BasePage findpage(Transaction xact) throws StandardException
276     {
277         releaseResource(xact);
278
279         RawTransaction rtran = (RawTransaction)xact;
280         containerHdl = rtran.openDroppedContainer(pageId.getContainerId(),
281             (LockingPolicy) null);
282
283         if (containerHdl == null)
284         {
285             throw StandardException.newException(
286                     SQLState.DATA_CONTAINER_VANISHED, pageId.getContainerId());
287         }
288
289         foundHere = true;
290
291         // if container is dropped and committed, cannot look at any page,
292
// it may be a container stub
293
if (containerHdl.getContainerStatus() == RawContainerHandle.COMMITTED_DROP)
294         {
295             releaseResource(xact);
296             return null;
297         }
298
299         StandardException getPageException = null;
300         try
301         {
302             // get and latch page - we don't know the status of the page or what
303
// kind of page we are looking for, get any type of page
304
page = (BasePage)(containerHdl.getAnyPage(pageId.getPageNumber()));
305         }
306         catch (StandardException se)
307         {
308             getPageException = se;
309         }
310             
311         //Try to initialize the page if page not found exception occurs during
312
//recovery and the page version is zero(Init Page).
313
//We do this if derby.storage.patchInitPageRecoverError is set.
314
if (page == null && getPageException != null && pageVersion == 0)
315             if (PropertyUtil.getSystemBoolean(RawStoreFactory.PATCH_INITPAGE_RECOVER_ERROR))
316                 page = getPageForRedoRecovery(xact);
317         
318         // maybe we are in rollforward recovery and this is an init page operation,
319
// give subclass a chance to create the page
320
if (page == null && getPageException != null)
321         {
322             //if are rolloforward recovery reload the page using load tran methods
323
//that initialize the page. because in rollforward recovery, we
324
//might be actually recreating the page container did not exist
325
//in the backup when we started the rollforward recovery.
326

327             if (rtran.inRollForwardRecovery())
328             {
329                 if (SanityManager.DEBUG)
330                     if(SanityManager.DEBUG_ON("LoadTran"))
331                         SanityManager.DEBUG_PRINT(
332                             "Trace", "got null page " + pageId +
333                             " and getPageException, attempt last ditch effort");
334
335                 page = getPageForRedoRecovery(xact);
336                 
337                 if (SanityManager.DEBUG)
338                     if(SanityManager.DEBUG_ON("LoadTran"))
339                         SanityManager.DEBUG_PRINT(
340                             "Trace"," getPageForRedoRecovery, got page=" +
341                             (page != null));
342             }
343         }
344
345         if (page == null)
346         {
347             if (getPageException != null)
348             {
349                 throw getPageException; // that is the original error
350
}
351             else
352             {
353                 throw StandardException.newException(
354                         SQLState.DATA_MISSING_PAGE, pageId);
355             }
356         }
357
358         return page;
359     }
360
361     /**
362         Subclass (e.g., init page) that wishes to do something about missing
363         pages in load tran should override this method to return the page
364
365         @exception StandardException Cloudscape Standard error policy
366      */

367     protected BasePage getPageForRedoRecovery(Transaction xact)
368          throws StandardException
369     {
370         return null;
371     }
372
373     public final Page getPage() {
374         return page;
375     }
376
377     public final long getPageVersion() {
378         return pageVersion;
379     }
380
381
382     /**
383         Undo the change indicated by this log operation and optional data.
384         The page the undo should apply to is the latched undoPage.
385         The undoPage must be the same page as the doMe page and the undo
386         operation must restore the before image of the row that changed.
387
388         <BR> this can only be used under special circumstances: namely
389         table level locking, and no internal or nested transaction, and all
390         operations are rollec back with restoreMe instead of undoMe.
391
392         <BR><B>This method is here to support BeforeImageLogging</B>
393
394         @param xact the Transaction doing the rollback
395         @param undoPage the page to rollback changes on
396         @param CLRinstant the log instant of this (PageUndo) operation
397         @param in optional data for the rollback operation
398
399         @exception IOException Can be thrown by any of the methods of ObjectInput.
400         @exception StandardException Standard Cloudscape policy.
401     */

402     abstract public void restoreMe(Transaction xact, BasePage undoPage,
403                                 LogInstant CLRinstant, LimitObjectInput in)
404          throws StandardException, IOException JavaDoc;
405
406
407 }
408
Popular Tags