KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > indexing > PageStore


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.indexing;
12
13 import java.io.*;
14 import java.util.*;
15
16 public class PageStore implements Observer {
17
18     private static final int NumberOfMetadataAreas = 16; // NEVER change this
19
private static final int SizeOfMetadataArea = 64; // NEVER change this
20
private static final int CurrentPageStoreVersion = 1; // version 1
21
private static final byte[] ZEROES = new byte[1024];
22
23     private String JavaDoc name;
24     private RandomAccessFile file;
25     private int numberOfPages;
26     private int numberOfFileReads;
27     private int numberOfFileWrites;
28     private int numberOfReads;
29     private int numberOfCacheHits;
30     private Map modifiedPages;
31     private Map acquiredPages;
32     private int storeOffset;
33     private AbstractPagePolicy policy;
34     private byte[] pageBuffer;
35     private byte[] metadataBuffer;
36
37     /**
38      * Creates the page file on the file system. Creates a file of zero length.
39      */

40     public static void create(String JavaDoc fileName) throws PageStoreException {
41         try {
42             FileOutputStream out = new FileOutputStream(fileName);
43             out.close();
44         } catch (IOException e) {
45             throw new PageStoreException(PageStoreException.CreateFailure, e);
46         }
47     }
48
49     /**
50      * Deletes the page file from the file system.
51      */

52     public static void delete(String JavaDoc fileName) {
53         new File(fileName).delete();
54     }
55
56     /**
57      * Returns true if the file exists in the file system.
58      */

59     public static boolean exists(String JavaDoc fileName) {
60         return new File(fileName).exists();
61     }
62
63     /**
64      * Creates a new PageStore with a given policy.
65      */

66     public PageStore(AbstractPagePolicy policy) {
67         this.policy = policy;
68         this.storeOffset = NumberOfMetadataAreas * SizeOfMetadataArea;
69     }
70
71     /**
72      * Acquires a new empty page.
73      */

74     //public Page acquire(IPageFactory pageFactory) throws PageStoreException {
75
// return acquire(pageFactory, numberOfPages);
76
//}
77
/**
78      * Returns the page that has the given page number from the page file.
79      */

80     //public Page acquire(IPageFactory pageFactory, int pageNumber) throws PageStoreException {
81
// Page p = null;
82
// numberOfReads++;
83
// Integer key = new Integer(pageNumber);
84
// p = (Page)acquiredPages.get(key);
85
// if (p != null) {
86
// numberOfCacheHits++;
87
// addReference(p);
88
// return p;
89
// }
90
// p = (Page)modifiedPages.get(key);
91
// if (p != null) {
92
// numberOfCacheHits++;
93
// addReference(p);
94
// return p;
95
// }
96
// p = readCache.get(pageNumber);
97
// if (p != null) {
98
// numberOfCacheHits++;
99
// addReference(p);
100
// return p;
101
// }
102
// numberOfPages = Math.max(pageNumber + 1, numberOfPages);
103
// p = pageFactory.create(this, pageNumber);
104
// getPageFromFile(pageNumber, p);
105
// addReference(p);
106
// return p;
107
//}
108
/**
109      * Adds a reference to a page.
110      */

111     //private void addReference(Page page) {
112
// Integer key = new Integer(page.getPageNumber());
113
// if (!page.hasReferences()) acquiredPages.put(key, page);
114
// page.addReference();
115
//}
116
/**
117      * Opens the PageStore. The file is created if necessary.
118      * This will raise an exception if the
119      * media on which the file is located is read-only
120      * or not authorized to the user.
121      */

122     public void open(String JavaDoc name) throws PageStoreException {
123         this.name = name;
124         pageBuffer = new byte[Page.SIZE];
125         metadataBuffer = new byte[SizeOfMetadataArea];
126         if (!exists(name))
127             create(name);
128         try {
129             this.file = new RandomAccessFile(name, "rw"); //$NON-NLS-1$
130
} catch (IOException e) {
131             throw new PageStoreException(PageStoreException.OpenFailure, e);
132         }
133         checkMetadata();
134         numberOfPages = numberOfPagesInFile();
135         numberOfFileReads = 0;
136         numberOfFileWrites = 0;
137         numberOfReads = 0;
138         numberOfCacheHits = 0;
139         /* apply any outstanding transaction by reading the log file and applying it */
140         modifiedPages = LogReader.getModifiedPages(this);
141         flush();
142         Log.delete(name);
143         /* prepare for normal operation */
144         acquiredPages = new HashMap();
145     }
146
147     /**
148      * Checks to see if the metadata stored in the page store matches that expected by this
149      * code. If not, a conversion is necessary.
150      */

151     private void checkMetadata() throws PageStoreException {
152         byte[] md = readMetadataArea(0);
153         Buffer metadata = new Buffer(md);
154         Field versionField = metadata.getField(0, 4);
155         int pageStoreVersion = versionField.getInt();
156         if (pageStoreVersion == 0) {
157             versionField.put(CurrentPageStoreVersion);
158             writeMetadataArea(0, md);
159             return;
160         }
161         if (pageStoreVersion == CurrentPageStoreVersion)
162             return;
163         convertPageStore(pageStoreVersion);
164     }
165
166     /**
167      * Converts the page store file from a previous to the current version.
168      * No conversions are yet defined.
169      */

170     private void convertPageStore(int fromVersion) throws PageStoreException {
171         throw new PageStoreException(PageStoreException.ConversionFailure);
172     }
173
174     /**
175      * Commits all changes and closes the page store.
176      */

177     public void close() {
178         close(true);
179     }
180
181     /**
182      * Closes the page store.
183      */

184     public void close(boolean commit) {
185         if (commit) {
186             try {
187                 commit();
188             } catch (PageStoreException e) {
189                 // ignore
190
}
191         }
192         try {
193             file.close();
194         } catch (IOException e) {
195             // ignore
196
}
197         file = null;
198     }
199
200     /**
201      * Commits all modified pages to the file.
202      */

203     public void commit() throws PageStoreException {
204         if (modifiedPages.size() == 0)
205             return;
206         LogWriter.putModifiedPages(this, modifiedPages);
207         flush();
208         Log.delete(name);
209     }
210
211     /**
212      * Writes the modified pages to the page file.
213      */

214     private void flush() throws PageStoreException {
215         if (modifiedPages.size() == 0)
216             return;
217         Iterator pageStream = modifiedPages.values().iterator();
218         while (pageStream.hasNext()) {
219             Page page = (Page) pageStream.next();
220             writePage(page);
221         }
222         modifiedPages.clear();
223     }
224
225     //public void readFrom(RandomAccessFile file, long offset) throws IOException {
226
// long n = file.length() - offset;
227
// if (n <= 0) {
228
// clear(contents, 0, contents.length);
229
// return;
230
// }
231
// file.seek(offset);
232
// int m = (int)Math.min((long)contents.length, n);
233
// file.readFully(contents, 0, m);
234
// if (m < contents.length) {
235
// clear(contents, m, contents.length - m);
236
// }
237
//}
238
//public void writeTo(OutputStream out) throws IOException {
239
// out.write(contents);
240
//}
241
//public void writeTo(OutputStream out, int offset, int length) throws IOException {
242
// out.write(contents, offset, length);
243
//}
244
//public void writeTo(RandomAccessFile file, long offset) throws IOException {
245
// long p = file.length();
246
// long n = offset - p;
247
// while (n > 0) {
248
// int m = (int)Math.min((long)ZEROES.length, n);
249
// file.seek(p);
250
// file.write(ZEROES, 0, m);
251
// p += m;
252
// n -= m;
253
// }
254
// file.seek(offset);
255
// file.write(contents);
256
//}
257

258     /**
259      * Opens the PageStore with a cache size of 40.
260      */

261     //public void open(String name) throws PageStoreException {
262
// open(name, 40);
263
//}
264
/**
265      * Opens the PageStore. The file is created if necessary.
266      * This will raise an exception if the
267      * media on which the file is located is read-only
268      * or not authorized to the user.
269      */

270     //public void open(String name, int cacheSize) throws PageStoreException {
271
// if (!exists(name)) create(name);
272
// try {
273
// this.file = new RandomAccessFile(name, "rw");
274
// } catch (IOException e) {
275
// throw new PageStoreException(PageStoreException.OpenFailure);
276
// }
277
// this.name = name;
278
// checkMetadata();
279
// numberOfPages = numberOfPagesInFile();
280
// numberOfFileReads = 0;
281
// numberOfFileWrites = 0;
282
// numberOfReads = 0;
283
// numberOfWrites = 0;
284
// numberOfCacheHits = 0;
285
// /* apply any outstanding transaction by reading the log file and applying it */
286
// readCache = new PageCache(0);
287
// modifiedPages = LogReader.getModifiedPages(name);
288
// flush();
289
// Log.delete(name);
290
// /* prepare for normal operation */
291
// readCache = new PageCache(cacheSize);
292
// acquiredPages = new HashMap();
293
//}
294
/**
295      * Acquires the page that has the given page number from the page store.
296      */

297     public Page acquire(int pageNumber) throws PageStoreException {
298         numberOfReads++;
299         Integer JavaDoc key = new Integer JavaDoc(pageNumber);
300         Page page = (Page) acquiredPages.get(key);
301         if (page == null) {
302             page = (Page) modifiedPages.get(key);
303             if (page == null) {
304                 numberOfPages = Math.max(pageNumber + 1, numberOfPages);
305                 page = readPage(pageNumber);
306             } else {
307                 numberOfCacheHits++;
308             }
309             acquiredPages.put(key, page);
310             page.addObserver(this);
311         } else {
312             numberOfCacheHits++;
313         }
314         page.addReference();
315         return page;
316     }
317
318     /**
319      * Releases a page and decrements its reference count.
320      */

321     public void release(Page page) {
322         Integer JavaDoc key = new Integer JavaDoc(page.getPageNumber());
323         page.removeReference();
324         if (page.hasReferences())
325             return;
326         page.deleteObserver(this);
327         acquiredPages.remove(key);
328     }
329
330     /**
331      * Processes a page update.
332      */

333     public void update(Observable object, Object JavaDoc arg) {
334         Page page = (Page) object;
335         Integer JavaDoc key = new Integer JavaDoc(page.getPageNumber());
336         modifiedPages.put(key, page);
337     }
338
339     /**
340      * Returns the file seek offset for a given page number.
341      */

342     protected long offsetOfPage(int pageNumber) {
343         return (long) (pageNumber * Page.SIZE) + storeOffset;
344     }
345
346     protected Page readPage(int pageNumber) throws PageStoreException {
347         if (!readBuffer(offsetOfPage(pageNumber), pageBuffer)) {
348             throw new PageStoreException(PageStoreException.ReadFailure);
349         }
350         numberOfFileReads++;
351         Page p = policy.createPage(pageNumber, pageBuffer, this);
352         p.addObserver(this);
353         return p;
354     }
355
356     protected void writePage(Page page) throws PageStoreException {
357         page.toBuffer(pageBuffer);
358         long fileOffset = offsetOfPage(page.getPageNumber());
359         if (!writeBuffer(fileOffset, pageBuffer, 0, pageBuffer.length)) {
360             throw new PageStoreException(PageStoreException.WriteFailure);
361         }
362         numberOfFileWrites++;
363     }
364
365     /**
366      * Returns the file seek offset for a given metadata area
367      */

368     protected long offsetOfMetadataArea(int i) {
369         return (long) i * SizeOfMetadataArea;
370     }
371
372     public byte[] readMetadataArea(int i) throws PageStoreException {
373         if (!readBuffer(offsetOfMetadataArea(i), metadataBuffer)) {
374             throw new PageStoreException(PageStoreException.MetadataRequestFailure);
375         }
376         return new Buffer(metadataBuffer).get(0, metadataBuffer.length);
377     }
378
379     public void writeMetadataArea(int i, byte[] buffer) throws PageStoreException {
380         if (i < 0 || i >= NumberOfMetadataAreas)
381             throw new PageStoreException(PageStoreException.MetadataRequestFailure);
382         if (buffer.length != SizeOfMetadataArea)
383             throw new PageStoreException(PageStoreException.MetadataRequestFailure);
384         if (!writeBuffer(offsetOfMetadataArea(i), buffer, 0, buffer.length)) {
385             throw new PageStoreException(PageStoreException.MetadataRequestFailure);
386         }
387         return;
388     }
389
390     protected boolean readBuffer(long fileOffset, byte[] buffer) {
391         new Buffer(buffer).clear();
392         long fileLength = getFileLength();
393         if (fileOffset >= fileLength)
394             return true;
395         int bytesToRead = (int) Math.min(buffer.length, (fileLength - fileOffset));
396         try {
397             file.seek(fileOffset);
398             file.readFully(buffer, 0, bytesToRead);
399         } catch (IOException e) {
400             return false;
401         }
402         return true;
403     }
404
405     protected boolean writeBuffer(long fileOffset, byte[] buffer, int offset, int length) {
406         clearFileToOffset(fileOffset);
407         try {
408             file.seek(fileOffset);
409             file.write(buffer, offset, length);
410         } catch (IOException e) {
411             return false;
412         }
413         return true;
414     }
415
416     protected long getFileLength() {
417         long n = 0;
418         try {
419             n = file.length();
420         } catch (IOException e) {
421             return 0;
422         }
423         return n;
424     }
425
426     protected void clearFileToOffset(long fileOffset) {
427         long fileLength = getFileLength();
428         while (fileLength < fileOffset) {
429             int m = (int) Math.min(ZEROES.length, (fileOffset - fileLength));
430             writeBuffer(fileLength, ZEROES, 0, m);
431             fileLength += m;
432         }
433     }
434
435     /**
436      * Returns the number of pages actually in the underlying file.
437      */

438     protected int numberOfPagesInFile() {
439         return (int) ((getFileLength() - offsetOfPage(0)) / Page.SIZE);
440     }
441
442     /**
443      * Returns the name of the page store.
444      */

445     public String JavaDoc getName() {
446         return name;
447     }
448
449     public AbstractPagePolicy getPolicy() {
450         return policy;
451     }
452
453     /**
454      * Returns the number of pages known about in the PageFile. This can be greater than
455      * the number of pages actually in the underlying file in the file system if new ones
456      * have been manufactured and not yet written to the underlying file.
457      */

458     public int numberOfPages() {
459         return numberOfPages;
460     }
461 }
462
Popular Tags