1 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; private static final int SizeOfMetadataArea = 64; private static final int CurrentPageStoreVersion = 1; private static final byte[] ZEROES = new byte[1024]; 22 23 private String 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 40 public static void create(String 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 52 public static void delete(String fileName) { 53 new File(fileName).delete(); 54 } 55 56 59 public static boolean exists(String fileName) { 60 return new File(fileName).exists(); 61 } 62 63 66 public PageStore(AbstractPagePolicy policy) { 67 this.policy = policy; 68 this.storeOffset = NumberOfMetadataAreas * SizeOfMetadataArea; 69 } 70 71 74 80 111 122 public void open(String 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"); } 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 140 modifiedPages = LogReader.getModifiedPages(this); 141 flush(); 142 Log.delete(name); 143 144 acquiredPages = new HashMap(); 145 } 146 147 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 170 private void convertPageStore(int fromVersion) throws PageStoreException { 171 throw new PageStoreException(PageStoreException.ConversionFailure); 172 } 173 174 177 public void close() { 178 close(true); 179 } 180 181 184 public void close(boolean commit) { 185 if (commit) { 186 try { 187 commit(); 188 } catch (PageStoreException e) { 189 } 191 } 192 try { 193 file.close(); 194 } catch (IOException e) { 195 } 197 file = null; 198 } 199 200 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 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 258 261 270 297 public Page acquire(int pageNumber) throws PageStoreException { 298 numberOfReads++; 299 Integer key = new Integer (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 321 public void release(Page page) { 322 Integer key = new Integer (page.getPageNumber()); 323 page.removeReference(); 324 if (page.hasReferences()) 325 return; 326 page.deleteObserver(this); 327 acquiredPages.remove(key); 328 } 329 330 333 public void update(Observable object, Object arg) { 334 Page page = (Page) object; 335 Integer key = new Integer (page.getPageNumber()); 336 modifiedPages.put(key, page); 337 } 338 339 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 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 438 protected int numberOfPagesInFile() { 439 return (int) ((getFileLength() - offsetOfPage(0)) / Page.SIZE); 440 } 441 442 445 public String getName() { 446 return name; 447 } 448 449 public AbstractPagePolicy getPolicy() { 450 return policy; 451 } 452 453 458 public int numberOfPages() { 459 return numberOfPages; 460 } 461 } 462 | Popular Tags |