|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.mdr.persistence.btreeimpl.btreestorage; import org.netbeans.mdr.persistence.btreeimpl.btreeindex.*; import org.netbeans.mdr.persistence.*; import java.io.*; import java.text.*; import java.util.*; /** * BtreePageSource implementation for pages which are stored directly in a file * (the primary index pages) rather than as repository objects. The file * access is all handled by the FileCache class. * * @author Dana Bergen * @version 1.0 */ public class BtreeFileSource extends Object implements BtreePageSource, FileCache.NotifyOnCommit { /* * A page exists in two forms: as an instantiated BtreePage object, and as * a byte array. On disk or in the FileCache, it is in the array form. * Each BtreePage has a reference (pageBuffer) to its array in the * FileCache. * * BtreeFileSource also maintains a cache of instantiated BtreePage's. * These cached BtreePage's may be reused, that is reinitialized * from a different page buffer for a different page. * * All pages in the BtreePage cache are pinned with respect to the * FileCache regardless of whether they are pinned with respect to the * BtreePage cache. A page is unpinned in the BtreePage cache if the BtreePage * is not in use. When a BtreePage is removed from the BtreePage cache, it is * then unpinned with respect to the FileCache. */ static final int MAGIC = 123456789; static final int VERSION = 1; static final int NO_PAGEID = -1; static final int NEXTFREE_OFFSET = FileHeader.HEADER_SIZE + 8; static final int CACHE_SIZE = 5; private FileCache fileCache; // source of pages from file private int fileId; // file where our pages are stored, // for making FileCache requests private int pageSize; private EntryTypeInfo pageIdInfo; private byte[] noPageId; private boolean metaChanged; private int nextFree; // page number of next free page private BtreeStorage storage; private Hashtable btreeCache; // BtreePages hashed on pageId private IntrusiveList lruList; // unpinned BtreePages lru first private MofidGenerator gen; private static class CacheEntry extends IntrusiveList.Member { BtreePage page; CachedPage fcp; // FileCache's cache entry int pinned; // number of current users of this page boolean needsStore; // has the page been modified } /** * Constructor for a BtreeFileSource from a new or existing index file. * * @param fileId file ID to use in FileCache requests * @param fileCache source of index pages * @param pageSize size of index pages * @param isNew true if this index is being newly created * @param mGen Mofid generator */ public BtreeFileSource(int fileId, FileCache fileCache, int pageSize, boolean isNew, MofidGenerator mGen, BtreeStorage storage) throws StorageException { CachedPage metaFCP, rootFCP; CacheEntry rootEntry; byte[] metadata; int offset; this.fileId = fileId; this.fileCache = fileCache; this.pageSize = pageSize; this.storage = storage; gen = mGen; pageIdInfo = EntryTypeInfo.getEntryTypeInfo(Storage.EntryType.INT, null); noPageId = pageIdInfo.toBuffer(new Integer(NO_PAGEID)); btreeCache = new Hashtable(10); lruList = new IntrusiveList(); metaChanged = false; metaFCP = fileCache.getPage(fileId, 0); metadata = metaFCP.contents; offset = FileHeader.HEADER_SIZE; if (isNew) { // Initialize the metadata page offset = Converter.writeInt(metadata, offset, MAGIC); offset = Converter.writeInt(metadata, offset, VERSION); nextFree = 1; offset = Converter.writeInt(metadata, offset, nextFree); fileCache.setWritable(metaFCP); } else { // Read the metadata page and verify int magic, version; magic = Converter.readInt(metadata, offset); offset += 4; version = Converter.readInt(metadata, offset); offset += 4; nextFree = Converter.readInt(metadata, offset); if (magic != MAGIC) { throw new StorageBadRequestException( MessageFormat.format( "Index file has bad magic number ", new Object[] {new Integer(magic) } )); } if (version != VERSION) { throw new StorageBadRequestException( MessageFormat.format( "Index file has incorrect version number. {0} expected, {1} found", new Object[] { new Integer(VERSION), new Integer(version) } )); } } fileCache.unpin(metaFCP); fileCache.addNotifier(this); } public EntryTypeInfo getPageIdInfo() { return new IntInfo(); } /** * Set the passed-in pageId to contain the special value noPageId */ public void setNoPage(byte[] pageId) { System.arraycopy(noPageId, 0, pageId, 0, pageId.length); } /** * Test whether the passed-in pageId contains the special value noPageId */ public boolean isNoPage(byte[] pageId) { for (int i = 0; i < pageId.length; i++) { if (pageId[i] != noPageId[i]) { return false; } } return true; } /** * Prepares all cached modified pages to be written out. */ public synchronized void prepareToCommit() throws StorageException { Enumeration entries; CacheEntry entry; CachedPage metaFCP; entries = btreeCache.elements(); while (entries.hasMoreElements()) { entry = (CacheEntry) entries.nextElement(); if (entry.needsStore) { entry.page.store(); } } /* Update the metadata page if necessary */ if (metaChanged) { metaFCP = fileCache.getPage(fileId, 0); fileCache.setWritable(metaFCP); Converter.writeInt(metaFCP.contents, NEXTFREE_OFFSET, nextFree); fileCache.unpin(metaFCP); } metaChanged = false; } /** * Return the root page if it already exists, otherwise create it. * * @return BtreePage which is the root page */ public BtreePage getRootPage(Btree btree) throws StorageException { if (nextFree > 1) { return getPage(pageIdInfo.toBuffer(new Integer(1)), btree); } else { return newPage(btree); } } /** * Get a BtreePage by its pageId. * * @param pageId Byte array containing pageId * * @return The page identified by pageId. * * @exception StorageException If the page is not valid */ public synchronized BtreePage getPage(byte[] pageId, Btree btree) throws StorageException { Integer pageNum; CacheEntry entry; pageNum = (Integer) pageIdInfo.fromBuffer(pageId); entry = (CacheEntry) btreeCache.get(pageNum); if (entry == null) { entry = addToBtreeCache(pageId, pageNum, false, btree); } else if (entry.pinned == 0) { lruList.remove((IntrusiveList.Member)entry); } entry.pinned++; return entry.page; } private CacheEntry addToBtreeCache(byte[] pageId, Integer pageNum, boolean isNew, Btree btree) throws StorageException { CacheEntry entry; entry = getCacheEntry(); entry.fcp = fileCache.getPage(fileId, pageNum.intValue()); if (entry.page == null) { entry.page = btree.pageFactory(); } else { entry.page.uninit(); } entry.page.init(btree, pageId, entry.fcp.contents, isNew); btreeCache.put(pageNum, entry); return entry; } private CacheEntry getCacheEntry() throws StorageException { CacheEntry entry = null; Integer pageNum; if (btreeCache.size() >= CACHE_SIZE) { /* look for a page to recycle */ entry = (CacheEntry) lruList.removeFirst(); } if (entry != null) { pageNum = (Integer) pageIdInfo.fromBuffer(entry.page.pageId); btreeCache.remove(pageNum); if (entry.needsStore) { entry.page.store(); entry.needsStore = false; } fileCache.unpin(entry.fcp); } else { entry = new CacheEntry(); } return entry; } /** * Returns a newly allocated btree page. * * @return A new BtreePage * * @exception StorageException If the page is not valid */ public synchronized BtreePage newPage(Btree btree) throws StorageException { CacheEntry entry; Integer pageNum; byte[] pageId; pageNum = new Integer(nextFree); nextFree++; metaChanged = true; pageId = pageIdInfo.toBuffer(pageNum); entry = addToBtreeCache(pageId, pageNum, true, btree); entry.pinned++; dirtyPage(entry.page); return entry.page; } /** * Returns a newly allocated BigKeyPage. * BigKeyPages are not recycled. They are only cached while in use. */ public synchronized BigKeyPage newBigKeyPage(Btree btree) throws StorageException { CacheEntry entry; Integer pageNum; byte[] pageId; pageNum = new Integer(nextFree); nextFree++; metaChanged = true; pageId = pageIdInfo.toBuffer(pageNum); entry = new CacheEntry(); entry.fcp = fileCache.getPage(fileId, pageNum.intValue()); entry.page = new BigKeyPage(); entry.page.init(btree, pageId, entry.fcp.contents, true); btreeCache.put(pageNum, entry); entry.pinned++; dirtyPage(entry.page); return (BigKeyPage)entry.page; } /** * Notifies the btree that the caller is done using this page. This * decrements its pinned count in the btree cache. It does not change * its pinned status in the FileCache; that only happens when a page is * removed from the btree cache. * * @param page BtreePage to be unpinned */ public synchronized void unpinPage(BtreePage page) { CacheEntry entry; entry = (CacheEntry) btreeCache.get(pageIdInfo.fromBuffer(page.pageId)); if (--entry.pinned == 0) { lruList.addLast((IntrusiveList.Member)entry); } } public synchronized void unpinPage(BigKeyPage page) throws StorageException { CacheEntry entry; Integer pageNum; entry = (CacheEntry) btreeCache.get(pageIdInfo.fromBuffer(page.pageId)); if (--entry.pinned == 0) { pageNum = (Integer) pageIdInfo.fromBuffer(entry.page.pageId); btreeCache.remove(pageNum); if (entry.needsStore) { entry.page.store(); entry.needsStore = false; } fileCache.unpin(entry.fcp); } } /** * Notifies the btree that the caller is going to modify this page. * This must be called prior to modifying the page contents. * * @param page The page being modified */ public synchronized void dirtyPage(BtreePage page) throws StorageException { CacheEntry entry; entry = (CacheEntry) btreeCache.get(pageIdInfo.fromBuffer(page.pageId)); entry.needsStore = true; fileCache.setWritable(entry.fcp); } public int getPageIdLength() { return pageIdInfo.getLength(); } public int getPageSize() { return pageSize; } public long getNextMofid() { if (gen != null) return gen.getNextMofid(); throw new RuntimeException("Not implemented"); } public String getMofidPrefix() { if (gen != null) return gen.getMofidPrefix(); throw new RuntimeException("Not implemented"); } public BtreeStorage getStorage () { return storage; } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.