src.jptools.cache.strategy.impl.map.LRUFeaturedCacheImpl Maven / Gradle / Ivy
/*
* LRUFeaturedCacheImpl.java
*
* Copyright by jptools, all rights reserved.
*/
package jptools.cache.strategy.impl.map;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jptools.logger.Logger;
/**
* This class implements a least recently used (LRU) cache. The origin of the
* algorithm is from the book modern operating systems from Andrew S. Tannenbaum.
*
* @param the type of keys maintained by this map
* @param the type of mapped values
* @author Patrick Meier
* @version $Revision: 1.6 $
*/
public class LRUFeaturedCacheImpl
extends AbstractMapCacheImpl
implements IMapCacheImpl
{
private static final int MAX_CACHE_SIZE = 2000;
/** The serial version */
private static final long serialVersionUID = 3618980092106388017L;
/** Version-number for version-control */
public static final String VERSION = "$Revision: 1.6 $";
private static Logger log = Logger.getLogger(LRUFeaturedCacheImpl.class);
private int maxSize;
private Map keyRowMap;
private Map rowKeyMap;
private int flagMap[][];
private K lastRemovedKey;
/**
* Constructor
*
* @param maxSize the max size of the cache
*/
public LRUFeaturedCacheImpl( int maxSize )
{
super();
this.maxSize = maxSize;
this.lastRemovedKey = null;
init( this.maxSize );
}
/**
* @see jptools.cache.strategy.impl.map.AbstractMapCacheImpl#containsKey(java.lang.Object)
*/
@Override
public boolean containsKey( K key )
{
if( key==null )
return false;
boolean result = cache.containsKey( key );
if( result )
mark( getRowFromKey( key ) );
return result;
}
/**
* @see jptools.cache.strategy.impl.map.AbstractMapCacheImpl#put(java.lang.Object, java.lang.Object)
*/
@Override
public V put( K key, V value )
{
V result = null;
// check if the key exist
if( !cache.containsKey( key ) )
{
int row = getLRU();
K k = getKeyFromRow( row );
if( verbose && k!=null && log.isDebugEnabled() )
log.debug( getLogInformation(), "The max. of cache entries is reached, remove the least recently used key ["+k+"] from cache." );
result = remove( k );
cache.put( createKey( row, key ), value );
}
else
{
result = cache.put( key, value );
mark( getRowFromKey( key ) );
}
return result;
}
/**
* @see jptools.cache.strategy.impl.map.AbstractMapCacheImpl#remove(java.lang.Object)
*/
@Override
public V remove( K key )
{
if( key==null )
return null;
if( keyRowMap==null )
return null;
V value = cache.remove( key );
int row = getRowFromKey( key );
if( row>=0 )
{
rowKeyMap.remove( row );
markRow( row, 0 );
}
keyRowMap.remove( key );
lastRemovedKey = key;
return value;
}
/**
* Removes all mappings from this map (optional operation).
*/
@Override
public void clear()
{
cache.clear();
rowKeyMap.clear();
keyRowMap.clear();
lastRemovedKey = null;
init( maxSize );
}
/**
* @see jptools.cache.strategy.IReplacementCache#getReplacedElement()
*/
@Override
public K getReplacedElement()
{
return lastRemovedKey;
}
/**
* @see jptools.cache.strategy.IReplacementCache#getNextReplacement()
*/
@Override
public K getNextReplacement()
{
return getLRUKey();
}
/**
* Gets the LRU row
* @return the row
*/
public K getLRUKey()
{
return getKeyFromRow( getLRU() );
}
/**
* @see jptools.cache.strategy.IReplacementCache#getNewest()
*/
@Override
public K getNewest()
{
return getKeyFromRow( getNewestIndex() );
}
/**
* Gets the internal status as string (only for debug purpose).
*
* @return the statuse
*/
public String getCacheStatus()
{
StringBuilder buffer = new StringBuilder();
buffer.append( "replacement data : " + getNextReplacement() + "\n" );
buffer.append( "newest data : " + getNewest() + "\n" );
for( int i=0; isum )
{
maxVal = sum;
row = i;
}
}
return row;
}
/**
* Gets the newest row
* @return the row
*/
protected int getNewestIndex()
{
int maxVal = 0;
int row = 0;
for( int i=0; imaxVal )
{
maxVal = sum;
row = i;
}
}
return row;
}
/**
* Marks an entry
* @param row the row to mark
*/
protected void mark( int row )
{
int r = row;
markRow( r );
markColumn( r );
}
/**
* Initialize the class
* @param cacheSize the max size of the cache
*/
private void init( int cacheSize )
{
int size = cacheSize;
if( size<0 )
size = MAX_CACHE_SIZE;
flagMap = new int[ size ][ size ];
keyRowMap = new ConcurrentHashMap( size );
rowKeyMap = new ConcurrentHashMap( size );
for( int i=0; i=maxSize ) )
return;
for( int i=0; i=maxSize ) )
return;
for( int i=0; i