Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/derby/impl/store/raw/data/ContainerOperation.java


1   /*
2   
3      Derby - Class org.apache.derby.impl.store.raw.data.ContainerOperation
4   
5      Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6   
7      Licensed under the Apache License, Version 2.0 (the "License");
8      you may not use this file except in compliance with the License.
9      You may obtain a copy of the License at
10  
11        http://www.apache.org/licenses/LICENSE-2.0
12  
13     Unless required by applicable law or agreed to in writing, software
14     distributed under the License is distributed on an "AS IS" BASIS,
15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16     See the License for the specific language governing permissions and
17     limitations under the License.
18  
19   */
20  
21  package org.apache.derby.impl.store.raw.data;
22  
23  import org.apache.derby.iapi.services.io.FormatIdUtil;
24  import org.apache.derby.iapi.services.io.StoredFormatIds;
25  import org.apache.derby.iapi.services.sanity.SanityManager;
26  
27  import org.apache.derby.iapi.store.raw.Compensation;
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.Transaction;
31  import org.apache.derby.iapi.store.raw.Undoable;
32  
33  import org.apache.derby.iapi.store.raw.xact.RawTransaction;
34  import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
35  import org.apache.derby.iapi.store.raw.log.LogInstant;
36  
37  import org.apache.derby.iapi.error.StandardException;
38  
39  import org.apache.derby.iapi.util.ByteArray;
40  
41  import java.io.ObjectOutput;
42  import java.io.InputStream;
43  import java.io.ObjectInput;
44  import java.io.IOException;
45  import org.apache.derby.iapi.services.io.LimitObjectInput;
46  
47  /**
48    Log operation to create, drop or remove a container.
49  
50    Both the doMe or the undoMe of a create actually caused the container
51    header to be modified and flushed before the log record is flushed.  This
52    is necessary for 2 reasons, one is that of ensuring enough disk space, and
53    the other is because unlike any other operation, the log record create
54    container is in the log stream before the container is in the container
55    cache.  What this mean is that if a checkpoint started after the container
56    operation but before the container is kept or is dirtied in the container
57    cache, then checkpoint will not know to wait for the container to be kept
58    or cleaned.  The checkpoint will erroneous assume that the operation does
59    not need to be redone since its log instant is before the checkpoint but in
60    fact the change has not been flushed to disk.
61  
62    A drop or remove container does not have this problem.  The container exist
63    and is in kept state when the operation is logged so the checkpoint will
64    not overlook it and it doesn't need to flush the container header.  In the
65    case of remove, the stub is flushed for a different reason - that of
66    ensuring disk space.
67  
68  */
69  public class ContainerOperation extends ContainerBasicOperation implements Undoable
70  {
71    protected byte operation;    // create, drop, or remove
72  
73    // in previous version of contianerOperation, there may not
74    // be a createByteArray
75    transient protected boolean hasCreateByteArray = true;
76  
77    protected ByteArray createByteArray;  // information necessary to
78                                // recreate the container 
79  
80    protected static final byte CREATE = (byte)1;
81    protected static final byte DROP = (byte)2;
82    protected static final byte REMOVE = (byte)4;
83  
84    protected ContainerOperation(RawContainerHandle hdl, byte operation) 
85       throws StandardException
86    {
87      super(hdl);
88      this.operation = operation;
89    }
90  
91    /*
92     * Formatable methods
93     */
94  
95    // no-arg constructor, required by Formatable 
96    public ContainerOperation() { super(); }
97  
98    public void writeExternal(ObjectOutput out) throws IOException  
99    {
100     super.writeExternal(out);
101     out.writeByte(operation);
102 
103     if (operation == CREATE)
104     {
105       try
106       {
107         createByteArray = containerHdl.logCreateContainerInfo();
108       }
109       catch (StandardException se)
110       {
111         throw new IOException(se.toString());
112       }
113           
114       createByteArray.writeExternal(out);
115     }
116   }
117 
118   /**
119     @exception IOException cannot read log record from log stream
120     @exception ClassNotFoundException cannot read ByteArray object
121    */
122   public void readExternal(ObjectInput in)
123      throws IOException, ClassNotFoundException 
124   {
125     super.readExternal(in);
126     operation = in.readByte();
127 
128     if (operation == CREATE && hasCreateByteArray)
129     {
130       createByteArray = new ByteArray();
131       createByteArray.readExternal(in);
132     }
133   }
134 
135   /**
136     Return my format identifier.
137   */
138   public int getTypeFormatId() {
139     return StoredFormatIds.LOGOP_CONTAINER;
140   }
141 
142 
143   /*
144    * override ContainerBasicOperation's findContainerForLoadTran
145    */
146   /**
147         Find container for load tran.
148         <p>
149     If we are in load tran, and the operation is a create, the container
150     may not (should not?) exist yet.  We need to recreate it.
151 
152     @exception StandardException Standard Cloudscape policy.
153    */
154   protected RawContainerHandle findContainerForLoadTran(RawTransaction xact)
155      throws StandardException
156   {
157     if (SanityManager.DEBUG)
158       SanityManager.ASSERT(createByteArray != null,
159       "cannot reCreate container in load tran, createByteArray is null");
160 
161     long sid = containerId.getSegmentId();
162     long cid = containerId.getContainerId();
163 
164     xact.reCreateContainerForLoadTran(sid, cid, createByteArray);
165 
166     // now we should be able to open this container
167     return xact.openDroppedContainer(containerId, (LockingPolicy)null);
168   }
169 
170   /** 
171     @exception StandardException Standard Cloudscape error policy
172   */
173   public final void doMe(Transaction tran, LogInstant instant, 
174                LimitObjectInput in)
175      throws StandardException
176   {
177 
178     switch (operation)
179     {
180     case DROP:
181       containerHdl.dropContainer(instant, true);
182       //
183       // RESOLVE: if it hasn't been stubbified, even at redo time, we will
184       // want to earmark this as a post commit work because we know it will
185       // not be wasted effort.
186       //
187       break;
188 
189     case REMOVE:
190       containerHdl.removeContainer(instant);
191       break;
192 
193     case CREATE:
194       break;
195       // nothing to do with create container, it has already been synced to
196       // disk.  If the container is subsequently dropped or even removed,
197       // that's fine too.  Don't bother to find it.
198     }
199 
200     releaseResource(tran);
201   }
202 
203 
204   /**
205     Undo of create, drop or remove
206 
207     @param tran the transaction that is undoing this operation
208     @param hdl the container handle.  This is found here during runtime
209     undo - in which case we made the CLR and passed in the containerHdl
210     found in generateUndo and it is passed back to this; or it is found in
211     the CLR's needsRedo and is passed in and this operation never found the
212     container.  Either case, release resource at the end is safe
213     @param CLRInstant the log instant of the CLR
214     @param in optional data
215 
216     @exception StandardException Standard Cloudscape error policy
217   */
218   public void undoMe(Transaction tran, RawContainerHandle hdl,
219              LogInstant CLRInstant, LimitObjectInput in)
220      throws StandardException
221   {
222     switch(operation)
223     {
224     case DROP:
225       if (SanityManager.DEBUG) {
226         SanityManager.ASSERT(hdl != null, "container handle is null");
227         SanityManager.ASSERT(hdl.getContainerStatus() != RawContainerHandle.COMMITTED_DROP,
228                    "Undoing a drop but the container status is not dropped");
229       }
230       hdl.dropContainer(CLRInstant, false); // not dropped
231       break;
232 
233     case CREATE: 
234       // remove the container
235       hdl.removeContainer(CLRInstant);
236       break;
237 
238     case REMOVE:
239       if (SanityManager.DEBUG) {
240         SanityManager.THROWASSERT("cannot undo REMOVE, should not have generated a CLR in the first place");
241       }
242       break;
243     }
244     releaseResource(tran);
245 
246   }
247 
248   /**
249     @see org.apache.derby.iapi.store.raw.Undoable
250     @exception StandardException Standard Cloudscape error policy
251   */
252   public Compensation generateUndo(Transaction tran, LimitObjectInput in)
253      throws StandardException
254   {
255     if (operation == REMOVE)
256       return null;    // cannot undo REMOVE
257     else
258     {
259       RawContainerHandle undoContainerHandle = findContainer(tran);
260       
261       // mark the container as pre-dirtied so that if a checkpoint
262       // happens after the log record is sent to the log stream, the
263       // cache cleaning will wait for this change.
264       //
265       // RESOLVE: don't do this now because if undo failed, this
266       // container will be "stuck" in the preDirty state and checkpoint
267       // will be stuck
268       // undoContainerHandle.preDirty(true);
269       //
270 
271       return new ContainerUndoOperation(undoContainerHandle, this);
272     }
273   }
274 
275   /** debug */
276   public String toString()
277   {
278     if (SanityManager.DEBUG)
279     {
280       String str = super.toString();
281       switch(operation)
282       {
283       case CREATE: str += " CREATE container " + containerId;
284         break;
285       case DROP: str += " DROP container " + containerId;
286         break;
287       case REMOVE: str += " REMOVE container " + containerId;
288         break;
289       }
290       return str;
291     }
292     else
293       return null;
294   }
295 
296 
297 }