KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > mdr > persistence > btreeimpl > btreestorage > BtreeExtent


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.mdr.persistence.btreeimpl.btreestorage;
20
21 import java.io.*;
22 import java.text.*;
23 import java.util.*;
24
25 import org.netbeans.mdr.persistence.*;
26
27 /** This is the base class for all extent types in the data file. On disk,
28 * all extents begin with the same three fields:
29 *
30 * <ol>
31 * <li>
32 * bytes 0-1 magic number
33 * <li>
34 * bytes 2-3 number of chunks
35 * <li>
36 * bytes 4-7 next extent in chain (0 if none)
37 * </ol>
38 *
39 * There are three kinds of extent:
40 * <p>
41 * A normal extent is the first extent in a record. if the record does
42 * not fit in one extent, those after the first are continuation extents.
43 * These two kinds comprise the active extents, that is, extents which contain
44 * live data. There are also extents which describe space in the file from
45 * which records have been deleted. There are called deleted extents.
46 * <p>
47 * Active extents are chained together into records, as described above.
48 * Deleted extents of the same size are also chained together, with the
49 * start of each chain in the BtreeDataFile header.
50 * @see BtreeDataFile
51 */

52 abstract class BtreeExtent {
53
54     /** magic number for normal extents */
55     static final int NORMAL_MAGIC = 0x2A2A;
56
57     /** magic number for continuation extents */
58     static final int CONTINUATION_MAGIC = 0x6B6B;
59
60     /** magic number for deleted extents */
61     static final int DELETED_MAGIC = 0x5F5F;
62
63     /** number of chunks in extent */
64     final short chunks;
65
66     /** The biggest extent possible */
67     public static final int MAX_EXTENT_SIZE =
68             BtreeDataFile.BTREE_CHUNK_SIZE * BtreeDataFile.MAX_CHUNKS_IN_EXTENT;
69
70     /** pointer to next extent in chain */
71     int nextInChain;
72
73     /** offset in file */
74     final int myChunkNum;
75
76     /** header has changed from disk copy */
77     boolean headerIsDirty;
78
79     /** The file we are an extent of */
80     final BtreeDataFile owner;
81
82     /* returns from getType() */
83     static final byte IS_NORMAL = 1;
84     static final byte IS_CONTINUATION = 2;
85     static final byte IS_DELETED = 3;
86
87     /* returns from getTypeName() */
88     static final String JavaDoc NORMAL_NAME = "normal";
89     static final String JavaDoc CONTINUATION_NAME = "continuation";
90     static final String JavaDoc DELETED_NAME = "deleted";
91
92     /** create a BtreeExtent from another. This is used when changing types
93     * of extents, for instance when deleting a record, and thus converting
94     * all of its extents to deleted extents.
95     * @param src the extent we are being created from
96     */

97     BtreeExtent(BtreeExtent src) {
98         chunks = src.chunks;
99         myChunkNum = src.myChunkNum;
100         owner = src.owner;
101         headerIsDirty = true;
102     }
103
104     /** called by subclasses to intialize a BtreeExtent
105     * @param file the BtreeDataFile this extent will belong to
106     * @param chunkNum where this extent begins
107     * @param numChunks the size of the extent
108     */

109     BtreeExtent(BtreeDataFile file, int chunkNum, short numChunks) {
110         owner = file;
111         chunks = numChunks;
112         myChunkNum = chunkNum;
113         headerIsDirty = true;
114     }
115
116     /** Read an extent from the datafile, and use the magic number to determine
117     * which subclass of BtreeExtent to create.
118     * @param dataFile the file to read from
119     * @param chunkNum the chunk where the extent begins
120     * @return the extent
121     * @exception StorageException if btree detects an inconsistency
122     * or if an I/O error occurs
123     */

124     final static BtreeExtent readExtent(BtreeDataFile dataFile, int chunkNum)
125         throws StorageException {
126
127         BtreeExtent extent = null;
128         IntHolder offset = new IntHolder();
129         CachedPage page = dataFile.getChunk(chunkNum, offset);
130         try {
131             short magic = Converter.readShort(page.contents, offset);
132             short chunks = Converter.readShort(page.contents, offset);
133
134             switch (magic) {
135                 case NORMAL_MAGIC:
136                     extent = new NormalBtreeExtent(dataFile, chunkNum, chunks);
137                     break;
138
139                 case CONTINUATION_MAGIC:
140                     extent = new ContinuationBtreeExtent(
141                                                     dataFile, chunkNum, chunks);
142                     break;
143
144                 case DELETED_MAGIC:
145                     extent = new DeletedBtreeExtent(dataFile, chunkNum, chunks);
146                     break;
147
148                 default:
149                     throw new StoragePersistentDataException(
150                         MessageFormat.format(
151                             "Bad Magic Number {0} in header at offset {1}",
152                                 new Object JavaDoc[] {
153                                     new Integer JavaDoc(magic),
154                                     new Integer JavaDoc(chunkNum)}));
155             }
156
157             extent.nextInChain = Converter.readInt(page.contents, offset);
158             extent.headerIsDirty = false;
159             extent.readHeaderFromPage(page.contents, offset);
160         }
161         finally {
162             page.unpin();
163         }
164
165         return extent;
166     }
167
168     /** read the type-specific parts of the extent header from the
169     * buffer.
170     * @param buffer the buffer to read from
171     * @param offset the offset to being reading at
172     */

173     abstract void readHeaderFromPage(byte buffer[], IntHolder offset);
174
175     /** Write the header to the file cache if it is dirty.
176     * @exception StorageException if btree detects an inconsistency
177     * or if an I/O error occurs
178     */

179     final void writeHeader() throws StorageException {
180         if (!headerIsDirty)
181             return;
182
183         IntHolder offst = new IntHolder();
184         CachedPage page = owner.getChunk(myChunkNum, offst);
185         try {
186             page.setWritable();
187             Converter.writeShort(page.contents, offst, getMagic());
188             Converter.writeShort(page.contents, offst, chunks);
189             Converter.writeInt(page.contents, offst, nextInChain);
190             writeHeaderToPage(page, offst.getValue());
191         }
192         finally {
193             page.unpin();
194         }
195         headerIsDirty = false;
196     }
197
198     /** write the type-specific part of the header to the file cache
199     * @param page the page to write to
200     * @param offset the offset to begin an
201     */

202     protected abstract void writeHeaderToPage(CachedPage page, int offset);
203
204     /** Get the magic number for this type of extent
205     * @return the magic number
206     */

207     abstract short getMagic();
208
209     /** get the size of the extent in chunks
210     * @return the size
211     */

212     int getSize() {
213         return chunks;
214     }
215
216     /** set this exent to point to another.
217     * @param next the starting chunk of the next extent, or 0, if this
218     * is to be the last in its chain
219     */

220     void setNext(int next) {
221         if (nextInChain != next) {
222             nextInChain = next;
223             headerIsDirty = true;
224         }
225     }
226
227     /** set this exent to point to another.
228     * @param next the next extent in the chain (not null)
229     */

230     void setNext(BtreeExtent next) {
231         setNext(next.myChunkNum);
232     }
233
234     /** get the starting chunk for the next extent in the chain.
235     * @return the next extent in the chain, or 0 if this is the last
236     * in its chain
237     */

238     int getNext() {
239         return nextInChain;
240     }
241
242     /** get the starting chunk number of the extent
243     * @return starting chunk number
244     */

245     int getOffset() {
246         return myChunkNum;
247     }
248
249     /** return type of extent
250     * @return IS_NORMAL, IS_CONTINUTATION, or IS_DELETED
251     */

252     abstract byte getType();
253
254     /** return name of type of extent
255     * @return NORMAL_NAME, CONTINUTATION_NAME, or DELETED_NAME
256     */

257     abstract String JavaDoc getTypeName();
258
259     /** return name of type of extent given type
260     * @param extentType IS_NORMAL, IS_CONTINUTATION, or IS_DELETED
261     * @return NORMAL_NAME, CONTINUTATION_NAME, or DELETED_NAME
262     */

263     static String JavaDoc getTypeName(int extentType) {
264         switch(extentType) {
265             case IS_NORMAL:
266                 return NORMAL_NAME;
267
268             case IS_CONTINUATION:
269                 return CONTINUATION_NAME;
270
271             case IS_DELETED:
272                 return DELETED_NAME;
273         }
274
275         return "unknown";
276     }
277
278     /** dump baisc header info */
279     public static final int DUMP_BASIC = 1;
280
281     /** dump key as hex */
282     public static final int DUMP_KEY = 2;
283
284     /** dump data as text */
285     public static final int DUMP_DATA = 4;
286
287     /** dump data checksum */
288     public static final int DUMP_DATA_CHECKSUM = 8;
289
290     /** dump extent as text (for debugging)
291     * "level" is a bitmask.
292     * <ol>
293     * <li>
294     * DUMP_BASIC -- basic header info
295     * <li>
296     * DUMP_KEY -- dump key as hex
297     * <li>
298     * DUMP_DATA -- dump data as text
299     * <li>
300     * DUMP_DATA_CHECKSUM -- dump data checksum
301     * </ol>
302     * @param level bitmask of what to dump.
303     * @param strm where to dump it to
304     */

305     void dump(int level, PrintWriter strm)
306                             throws StorageException{
307     if ((level & DUMP_BASIC) != 0) {
308         strm.println("Extent: " + myChunkNum);
309         strm.println("Type: " + this.getClass().getName());
310         strm.println("Size: " + chunks);
311         if (nextInChain > 0)
312         strm.println("Next: " + nextInChain);
313     }
314     }
315
316     /** utility to dump bytes as hex, 16 to a line
317     * @param in source of bytes
318     * @param out output stream
319     * @param indent indentation for each new line
320     */

321     static void dumpBytesAsHex(InputStream in, PrintWriter out, String JavaDoc indent) {
322
323         try {
324             int position = 0;
325             int data;
326             while ((data = in.read()) >= 0) {
327                 if (position >= 16) {
328                     out.println();
329                     position = 0;
330                 }
331                 if (position == 0)
332                     out.print(indent);
333                 else
334                     out.print(" ");
335             
336                 String JavaDoc hex = Integer.toHexString(data);
337                 if (hex.length() == 1)
338                     hex = "0" + hex;
339                 out.print(hex);
340                 position++;
341             }
342             if (position > 0)
343                 out.println();
344         }
345         catch (IOException exc) {
346             out.print("\n\nIO EXCEPTION!\n\n");
347         }
348     }
349 }
350
Popular Tags