All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy