📄 cacherecordmanager.java
字号:
/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: CacheRecordManager.java,v 1.9 2005/06/25 23:12:32 doomdark Exp $ */package jdbm.recman;import jdbm.RecordManager;import jdbm.helper.CacheEvictionException;import jdbm.helper.CachePolicy;import jdbm.helper.CachePolicyListener;import jdbm.helper.DefaultSerializer;import jdbm.helper.Serializer;import jdbm.helper.WrappedRuntimeException;import java.io.IOException;import java.util.Enumeration;/** * A RecordManager wrapping and caching another RecordManager. * * @author <a href="mailto:boisvert@intalio.com">Alex Boisvert</a> * @author <a href="cg@cdegroot.com">Cees de Groot</a> * @version $Id: CacheRecordManager.java,v 1.9 2005/06/25 23:12:32 doomdark Exp $ */public class CacheRecordManager implements RecordManager{ /** * Wrapped RecordManager */ protected RecordManager _recman; /** * Cache for underlying RecordManager */ protected CachePolicy _cache; /** * Construct a CacheRecordManager wrapping another RecordManager and * using a given cache policy. * * @param recman Wrapped RecordManager * @param cache Cache policy */ public CacheRecordManager( RecordManager recman, CachePolicy cache ) { if ( recman == null ) { throw new IllegalArgumentException( "Argument 'recman' is null" ); } if ( cache == null ) { throw new IllegalArgumentException( "Argument 'cache' is null" ); } _recman = recman; _cache = cache; _cache.addListener( new CacheListener() ); } /** * Get the underlying Record Manager. * * @return underlying RecordManager or null if CacheRecordManager has * been closed. */ public RecordManager getRecordManager() { return _recman; } /** * Get the underlying cache policy * * @return underlying CachePolicy or null if CacheRecordManager has * been closed. */ public CachePolicy getCachePolicy() { return _cache; } /** * Inserts a new record using a custom serializer. * * @param obj the object for the new record. * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public long insert( Object obj ) throws IOException { return insert( obj, DefaultSerializer.INSTANCE ); } /** * Inserts a new record using a custom serializer. * * @param obj the object for the new record. * @param serializer a custom serializer * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized long insert( Object obj, Serializer serializer ) throws IOException { checkIfClosed(); long recid = _recman.insert( obj, serializer ); try { _cache.put( new Long( recid ), new CacheEntry( recid, obj, serializer, false ) ); } catch ( CacheEvictionException except ) { throw new WrappedRuntimeException( except ); } return recid; } /** * Deletes a record. * * @param recid the rowid for the record that should be deleted. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void delete( long recid ) throws IOException { checkIfClosed(); _recman.delete( recid ); _cache.remove( new Long( recid ) ); } /** * Updates a record using standard Java serialization. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @throws IOException when one of the underlying I/O operations fails. */ public void update( long recid, Object obj ) throws IOException { update( recid, obj, DefaultSerializer.INSTANCE ); } /** * Updates a record using a custom serializer. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @param serializer a custom serializer * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void update( long recid, Object obj, Serializer serializer ) throws IOException { CacheEntry entry; Long id; checkIfClosed(); id = new Long( recid ); try { entry = (CacheEntry) _cache.get( id ); if ( entry != null ) { // reuse existing cache entry entry._obj = obj; entry._serializer = serializer; entry._isDirty = true; } else { _cache.put( id, new CacheEntry( recid, obj, serializer, true ) ); } } catch ( CacheEvictionException except ) { throw new IOException( except.getMessage() ); } } /** * Fetches a record using standard Java serialization. * * @param recid the recid for the record that must be fetched. * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public Object fetch( long recid ) throws IOException { return fetch( recid, DefaultSerializer.INSTANCE ); } /** * Fetches a record using a custom serializer. * * @param recid the recid for the record that must be fetched. * @param serializer a custom serializer * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized Object fetch( long recid, Serializer serializer ) throws IOException { checkIfClosed(); Long id = new Long( recid ); CacheEntry entry = (CacheEntry) _cache.get( id ); if ( entry == null ) { entry = new CacheEntry( recid, null, serializer, false ); entry._obj = _recman.fetch( recid, serializer ); try { _cache.put( id, entry ); } catch ( CacheEvictionException except ) { throw new WrappedRuntimeException( except ); } } return entry._obj; } /** * Closes the record manager. * * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void close() throws IOException { checkIfClosed(); updateCacheEntries(); _recman.close(); _recman = null; _cache = null; } /** * Returns the number of slots available for "root" rowids. These slots * can be used to store special rowids, like rowids that point to * other rowids. Root rowids are useful for bootstrapping access to * a set of data. */ public synchronized int getRootCount() { checkIfClosed(); return _recman.getRootCount(); } /** * Returns the indicated root rowid. * * @see #getRootCount */ public synchronized long getRoot( int id ) throws IOException { checkIfClosed(); return _recman.getRoot( id ); } /** * Sets the indicated root rowid. * * @see #getRootCount */ public synchronized void setRoot( int id, long rowid ) throws IOException { checkIfClosed(); _recman.setRoot( id, rowid ); } /** * Commit (make persistent) all changes since beginning of transaction. */ public synchronized void commit() throws IOException { checkIfClosed(); updateCacheEntries(); _recman.commit(); } /** * Rollback (cancel) all changes since beginning of transaction. */ public synchronized void rollback() throws IOException { checkIfClosed(); _recman.rollback(); // discard all cache entries since we don't know which entries // where part of the transaction _cache.removeAll(); } /** * Obtain the record id of a named object. Returns 0 if named object * doesn't exist. */ public synchronized long getNamedObject( String name ) throws IOException { checkIfClosed(); return _recman.getNamedObject( name ); } /** * Set the record id of a named object. */ public synchronized void setNamedObject( String name, long recid ) throws IOException { checkIfClosed(); _recman.setNamedObject( name, recid ); } /** * Check if RecordManager has been closed. If so, throw an * IllegalStateException */ private void checkIfClosed() throws IllegalStateException { if ( _recman == null ) { throw new IllegalStateException( "RecordManager has been closed" ); } } /** * Update all dirty cache objects to the underlying RecordManager. */ protected void updateCacheEntries() throws IOException { Enumeration enume = _cache.elements(); while ( enume.hasMoreElements() ) { CacheEntry entry = (CacheEntry) enume.nextElement(); if ( entry._isDirty ) { _recman.update( entry._recid, entry._obj, entry._serializer ); entry._isDirty = false; } } } private class CacheEntry { long _recid; Object _obj; Serializer _serializer; boolean _isDirty; CacheEntry( long recid, Object obj, Serializer serializer, boolean isDirty ) { _recid = recid; _obj = obj; _serializer = serializer; _isDirty = isDirty; } } // class CacheEntry private class CacheListener implements CachePolicyListener { /** Notification that cache is evicting an object * * @arg obj object evited from cache * */ public void cacheObjectEvicted( Object obj ) throws CacheEvictionException { CacheEntry entry = (CacheEntry) obj; if ( entry._isDirty ) { try { _recman.update( entry._recid, entry._obj, entry._serializer ); } catch ( IOException except ) { throw new CacheEvictionException( except ); } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -