KickJava   Java API By Example, From Geeks To Geeks.

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


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
24 import org.netbeans.mdr.persistence.*;
25
26 /** A map page, used by the log file to keep track of before-image pages
27 */

28 class MapPage {
29
30     /* page size */
31     private int pageSize;
32
33     /* offset in the file of this page */
34     private int myOffset;
35
36     /* number of files being logged */
37     private short numFiles;
38
39     /* maximum page entries that fit */
40     private short maxPages;
41
42     /* file header data for these files */
43     private long fileId;
44     private long timeStamp;
45     private long newTimeStamp;
46
47     /* number of before-image pages mapped by this page */
48     private short pageCount;
49
50     /* checksum for this page */
51     private short checksum;
52
53     private static final int FIXED_SIZE = 40; /* size of above */
54
55     /** end-of-file marks for each loggged file */
56     private int oldEOF[];
57
58     /** offsets for each page described by this map */
59     private int offsets[];
60
61     /** Create a new map mage
62     * @param pgSz the page size
63     * @param noFiles the number of files being logged
64     * @param offset the offset into the file of this map page
65     */

66     MapPage(int pgSz, int noFiles, int offset) {
67         myOffset = offset;
68         pageSize = pgSz;
69         numFiles = (short)noFiles;
70         oldEOF = new int[numFiles];
71         maxPages = (short)((pageSize - FIXED_SIZE - (4 * numFiles)) / 4);
72         offsets = new int[maxPages];
73     }
74
75
76     /** Set EOF array
77     * @param files array of files
78     * @exception StorageException I/O error determining EOF
79     */

80     void setEOFs(RandomAccessFile files[] ) throws StorageException {
81         try {
82             for (int i = 0; i < numFiles; i++) {
83                 oldEOF[i] = (int)files[i].length();
84             }
85         }
86         catch (IOException ex) {
87             throw new StorageIOException(ex);
88         }
89     }
90
91     /** Get EOF for a file
92     */

93     int getEOF(int index) {
94         return oldEOF[index];
95     }
96
97     /** create the next map page in a log filfilee
98     * @param previous the previous map page for this file
99     */

100     MapPage(MapPage previous) {
101         this(previous.pageSize, previous.numFiles,
102             previous.myOffset + ((previous.pageCount + 1) * previous.pageSize));
103         setTimeStamps(previous.timeStamp, previous.newTimeStamp);
104         oldEOF = new int[previous.oldEOF.length];
105         System.arraycopy(previous.oldEOF, 0, oldEOF, 0, oldEOF.length);
106     }
107
108     /** Set the file ID for this map page
109     * @param fileId new file id
110     */

111     void setFileID(long id) {
112         fileId = id;
113     }
114
115     /** set the time stamps for this map page
116     * @param stamp the timestamp for the last comitted transaction
117     * @param newStamp the timestamp for the currently outstanding transaction
118     */

119     void setTimeStamps(long stamp, long newStamp) {
120         timeStamp = stamp;
121         newTimeStamp = newStamp;
122     }
123
124     /** write the map page to a file
125     * @param file the file to write it to
126     * @exception StorageException I/O error writing the page
127     */

128     void write(RandomAccessFile file) throws StorageException {
129
130         byte buffer[] = new byte[pageSize];
131         IntHolder offset = new IntHolder(0);
132         checksum = computeChecksum();
133         Converter.writeInt(buffer, offset, pageSize);
134         Converter.writeInt(buffer, offset, myOffset);
135         Converter.writeShort(buffer, offset, numFiles);
136         Converter.writeShort(buffer, offset, maxPages);
137         Converter.writeShort(buffer, offset, pageCount);
138         Converter.writeShort(buffer, offset, checksum);
139         Converter.writeLong(buffer, offset, fileId);
140         Converter.writeLong(buffer, offset, timeStamp);
141         Converter.writeLong(buffer, offset, newTimeStamp);
142
143         for (int i = 0; i < numFiles; i++)
144             Converter.writeInt(buffer, offset, oldEOF[i]);
145
146         for (int i = 0; i < pageCount; i++)
147             Converter.writeInt(buffer, offset, offsets[i]);
148
149         try {
150             file.seek(myOffset);
151             file.write(buffer);
152         }
153         catch (IOException ex) {
154             throw new StorageIOException(ex);
155         }
156     }
157
158
159     /** create a map page by reading from a file
160     * @param file the file to read from
161     * @param offset the offset in the file where the map page lives
162     * @exception StorageException I/O error reading the file
163     * @exception BadParameterException inconsistent page size
164     */

165     MapPage(RandomAccessFile file, int offset, int pgSz)
166         throws StorageException {
167
168         byte buffer[] = new byte[pgSz];
169
170         try {
171             file.seek(offset);
172             file.readFully(buffer);
173         }
174         catch (IOException ex) {
175             throw new StorageIOException(ex);
176         }
177
178         IntHolder index = new IntHolder(0);
179         pageSize = Converter.readInt(buffer, index);
180         if (pageSize == 0) {
181             return;
182         }
183         else if (pageSize != pgSz) {
184             throw new StoragePersistentDataException(
185                 MessageFormat.format(
186                     "Invalid page size {0}: {1} expected",
187                     new Object JavaDoc[] {
188                         new Integer JavaDoc(pgSz),
189                         new Integer JavaDoc(pageSize)}));
190         }
191         myOffset = Converter.readInt(buffer, index);
192         numFiles = Converter.readShort(buffer, index);
193         maxPages = Converter.readShort(buffer, index);
194         pageCount = Converter.readShort(buffer, index);
195         checksum = Converter.readShort(buffer, index);
196         fileId = Converter.readLong(buffer, index);
197         timeStamp = Converter.readLong(buffer, index);
198         newTimeStamp = Converter.readLong(buffer, index);
199
200         oldEOF = new int[numFiles];
201         offsets = new int[pageCount];
202
203         for (int i = 0; i < numFiles; i++)
204             oldEOF[i] = Converter.readInt(buffer, index);
205         for (int i = 0; i < pageCount; i++)
206             offsets[i] = Converter.readInt(buffer, index);
207
208         if (checksum != computeChecksum())
209             throw new StoragePersistentDataException(
210                 "Invalid checksum in MapPage");
211     }
212
213     /** see if this was a page of zeros */
214     boolean isEmpty() {
215         return pageSize == 0;
216     }
217
218     /** get next map page from log file
219     * @exception StorageException I/O error reading the file
220     * @exception BadParameterException inconsistent page size
221     */

222     MapPage getNext(RandomAccessFile file, int numPages)
223                             throws StorageException {
224         if (!isFull())
225             return null;
226
227         int offset = myOffset + (pageSize * (pageCount + 1));
228         if (offset >= (numPages * pageSize))
229             return null;
230
231         return new MapPage(file, offset, pageSize);
232     }
233
234     /** check that recovery parameters are consistent
235     * @exception BadParameterException parameters inconsistent with
236     * map page
237     */

238     void checkParameters(int thePageSize, int theNumberOfFiles)
239             throws StorageException {
240         if (thePageSize != pageSize) {
241             throw new StoragePersistentDataException(
242                 "Map page contains wrong page size.");
243         }
244
245         if (theNumberOfFiles != numFiles) {
246             throw new StoragePersistentDataException(
247                     "Map page contains wrong number of files.");
248         }
249     }
250
251     /**
252     * check timestamps in logged file
253     * @param file file which contains header
254     * @exception StorageException I/O error opening or reading the file or
255     * file header is corrupt
256     */

257     void checkFileHeader(RandomAccessFile file)
258             throws StorageException {
259         FileHeader header = new FileHeader(file);
260
261         if (header.timeStamp != timeStamp &&
262             header.timeStamp != newTimeStamp) {
263
264                 throw new StoragePersistentDataException(
265                             "Map page contains invalid timestamp" +
266                 + header.timeStamp + " valid would be " +
267                 timeStamp + " or " + newTimeStamp);
268         }
269
270         if (header.fileId != fileId) {
271              throw new StoragePersistentDataException(
272                     "Map page contains invalid file id");
273         }
274     }
275
276     /**
277     * where the next before-image page should be written to
278     */

279     int nextPageOffset() {
280         return myOffset + (pageCount + 1) * pageSize;
281     }
282
283     /** add a page to the map
284     * @param page page to add
285     */

286     void add(CachedPage page) {
287         offsets[pageCount++] = encode(page.key);
288     }
289
290     /** is this page full
291     */

292     boolean isFull() {
293         return pageCount == maxPages;
294     }
295
296     /* encode file index and offset into an int */
297     private int encode(PageID page) {
298         return (page.fileIndex << 20) | (page.offset / pageSize);
299     }
300
301     /* decode file index and offset from an int */
302     private PageID decode(int pageID) {
303         return new PageID(pageID >>> 20, (pageID & 0XFFFFF) * pageSize);
304     }
305
306     /** cacluate the checksum for this map page */
307     short computeChecksum() {
308         int sum = 0;
309
310         sum += fileId;
311         sum += timeStamp;
312         sum += newTimeStamp;
313         sum += pageCount;
314         for (int i = 0; i < numFiles; i++)
315             sum += (oldEOF[i]);
316         for (int i = 0; i < pageCount; i++)
317             sum += offsets[i];
318
319         return (short) ((sum & 0xFFFF) + (sum >>> 16));
320     }
321
322     /** set files to their pre-transaction size
323     * @exception StorageException I/O error truncating the files
324     */

325     void truncateFiles(RandomAccessFile files[]) throws StorageException{
326         try {
327             for (int i = 0; i < files.length; i++) {
328                 files[i].setLength(oldEOF[i]);
329             }
330         }
331         catch (IOException ex) {
332             throw new StorageIOException(ex);
333         }
334     }
335
336     /** restore all of the before pages listed in this map page
337     * @exception StorageException I/O error restoring the pages
338     */

339     void recover(RandomAccessFile files[], RandomAccessFile logFile,
340                  int numPages, byte buffer[]) throws StorageException {
341         try {
342             for (int i = 0; i < pageCount; i++) {
343                 int logOffset = myOffset + (pageSize * (i + 1));
344                 if (logOffset >= (numPages * pageSize))
345                     break;
346
347                 PageID entry = decode(offsets[i]);
348                 files[entry.fileIndex].seek(entry.offset);
349                 logFile.seek(logOffset);
350                 logFile.readFully(buffer);
351                 files[entry.fileIndex].write(buffer);
352             }
353         }
354         catch (IOException ex) {
355             throw new StorageIOException(ex);
356         }
357     }
358 }
359
Popular Tags