asmuts 2004/07/07 17:48:20
Added: src/java/org/apache/jcs/engine/memory/lru
LHMLRUMemoryCache.java
Log:
move to main directory from experimental
Revision Changes Path
1.1
jakarta-turbine-jcs/src/java/org/apache/jcs/engine/memory/lru/LHMLRUMemoryCache.java
Index: LHMLRUMemoryCache.java
===================================================================
package org.apache.jcs.engine.memory.lru;
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jcs.engine.CacheConstants;
import org.apache.jcs.engine.CacheElement;
import org.apache.jcs.engine.behavior.ICacheElement;
import org.apache.jcs.engine.control.CompositeCache;
import org.apache.jcs.engine.memory.AbstractMemoryCache;
import org.apache.jcs.engine.control.group.GroupId;
import org.apache.jcs.engine.control.group.GroupAttrName;
/**
* This is a test memory manager using the jdk1.4 LinkedHashMap.
* There may be some thread safety issues.
* So far i cannot notice any performance difference between this and the
* standard LRU implementation. It needs more testing.
*
[EMAIL PROTECTED] $Id: LHMLRUMemoryCache.java,v 1.1 2004/07/08 00:48:20 asmuts
Exp $
*/
public class LHMLRUMemoryCache
extends AbstractMemoryCache
{
private final static Log log = LogFactory.getLog( LRUMemoryCache.class );
// the extended LinkedHashMap
private Map map;
/**
* For post reflection creation initialization
*
[EMAIL PROTECTED] hub
*/
public synchronized void initialize( CompositeCache hub )
{
super.initialize( hub );
map = new LHMSpooler();
log.info( "initialized LHMLRUMemoryCache for " + cacheName );
}
/**
* Puts an item to the cache.
*
[EMAIL PROTECTED] ce Description of the Parameter
[EMAIL PROTECTED] IOException
*/
public void update( ICacheElement ce ) throws IOException
{
// Asynchronisly create a MemoryElement
ce.getElementAttributes().setLastAccessTimeNow();
map.put( ce.getKey(), ce );
}
/**
* Remove all of the elements from both the Map and the linked
* list implementation. Overrides base class.
*/
public synchronized void removeAll() throws IOException
{
map.clear();
}
/**
* Get an item from the cache without affecting its last access time or
* position. There is no way to do this with the LinkedHashMap!
*
[EMAIL PROTECTED] key Identifies item to find
[EMAIL PROTECTED] Element mathinh key if found, or null
[EMAIL PROTECTED] IOException
*/
public ICacheElement getQuiet( Serializable key ) throws IOException
{
ICacheElement ce = null;
ce = ( ICacheElement ) map.get( key );
if ( ce != null )
{
if ( log.isDebugEnabled() )
{
log.debug( cacheName + ": LRUMemoryCache quiet hit for " + key );
}
}
else if ( log.isDebugEnabled() )
{
log.debug( cacheName + ": LRUMemoryCache quiet miss for " + key );
}
return ce;
}
/**
* Get an item from the cache
*
[EMAIL PROTECTED] key Identifies item to find
[EMAIL PROTECTED] ICacheElement if found, else null
[EMAIL PROTECTED] IOException
*/
public synchronized ICacheElement get( Serializable key ) throws IOException
{
ICacheElement ce = null;
if ( log.isDebugEnabled() )
{
log.debug( "getting item from cache " + cacheName + " for key " +
key );
}
ce = ( ICacheElement ) map.get( key );
if ( ce != null )
{
if ( log.isDebugEnabled() )
{
log.debug( cacheName + ": LRUMemoryCache hit for " + key );
}
}
else
{
log.debug( cacheName + ": LRUMemoryCache miss for " + key );
}
return ce;
}
/**
* Removes an item from the cache. This method handles hierarchical
* removal. If the key is a String and ends with the
* CacheConstants.NAME_COMPONENT_DELIMITER, then all items with keys
* starting with the argument String will be removed.
*
[EMAIL PROTECTED] key
[EMAIL PROTECTED]
[EMAIL PROTECTED] IOException
*/
public synchronized boolean remove( Serializable key ) throws IOException
{
if ( log.isDebugEnabled() )
{
log.debug( "removing item for key: " + key );
}
boolean removed = false;
// handle partial removal
if ( key instanceof String && ( ( String ) key )
.endsWith( CacheConstants.NAME_COMPONENT_DELIMITER ) )
{
// remove all keys of the same name hierarchy.
synchronized ( map )
{
for ( Iterator itr = map.entrySet().iterator(); itr.hasNext(); )
{
Map.Entry entry = ( Map.Entry ) itr.next();
Object k = entry.getKey();
if ( k instanceof String
&& ( ( String ) k ).startsWith( key.toString() ) )
{
itr.remove();
removed = true;
}
}
}
}
else if ( key instanceof GroupId )
{
// remove all keys of the same name hierarchy.
synchronized ( map )
{
for ( Iterator itr = map.entrySet().iterator(); itr.hasNext(); )
{
Map.Entry entry = ( Map.Entry ) itr.next();
Object k = entry.getKey();
if ( k instanceof GroupAttrName
&& ( ( GroupAttrName ) k ).groupId.equals( key ) )
{
itr.remove();
removed = true;
}
}
}
}
else
{
// remove single item.
ICacheElement ce = ( ICacheElement ) map.remove( key );
removed = true;
}
return removed;
}
/**
* Get an Array of the keys for all elements in the memory cache
*
[EMAIL PROTECTED] An Object[]
*/
public Object[] getKeyArray()
{
// need a better locking strategy here.
synchronized ( this )
{
// may need to lock to map here?
return map.keySet().toArray();
}
}
// ---------------------------------------------------------- debug methods
/**
* Dump the cache map for debugging.
*/
public void dumpMap()
{
log.debug( "dumpingMap" );
for ( Iterator itr = map.entrySet().iterator(); itr.hasNext(); )
{
Map.Entry e = ( Map.Entry ) itr.next();
MemoryElementDescriptor me = ( MemoryElementDescriptor ) e.getValue();
log.debug( "dumpMap> key=" + e.getKey() + ", val=" + me.ce.getVal() );
}
}
/**
* Dump the cache entries from first to list for debugging.
*/
public void dumpCacheEntries()
{
log.debug( "dumpingCacheEntries" );
//Map.Entry e = map.
//for ( )
//{
// log.debug( "dumpCacheEntries> key="
// + me.ce.getKey() + ", val=" + me.ce.getVal() );
//}
}
private int dumpCacheSize()
{
int size = 0;
size = map.size();
return size;
}
// ---------------------------------------------------------- extended map
/**
* Implementation of removeEldestEntry in LinkedHashMap
*/
public class LHMSpooler
extends java.util.LinkedHashMap
{
/**
* Initialize to a small size--for now, 1/2 of max
* 3rd variable "true" indicates that it should be access
* and not time goverened. This could be configurable.
*/
public LHMSpooler()
{
super( ( int ) ( cache.getCacheAttributes().getMaxObjects() * .5 ), .75F, true
);
}
/**
* Remove eldest. Automatically called by LinkedHashMap.
*/
protected boolean removeEldestEntry( Map.Entry eldest )
{
CacheElement element = ( CacheElement ) eldest.getValue();
if ( size() <= cache.getCacheAttributes().getMaxObjects() )
{
return false;
}
else
{
if ( log.isDebugEnabled() )
{
log.debug( "LHMLRU max size: " +
cache.getCacheAttributes().getMaxObjects()
+ ". Spooling element, key: " + element.getKey() );
}
spoolToDisk( element );
if ( log.isDebugEnabled() )
{
log.debug( "LHMLRU size: " + map.size() );
}
}
return true;
}
/**
* Puts the element in the DiskStore
* @param element The CacheElement
*/
private void spoolToDisk( CacheElement element )
{
cache.spoolToDisk( element );
if ( log.isDebugEnabled() )
{
log.debug( cache.getCacheName() + "Spoolled element to disk: " +
element.getKey() );
}
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]