package de.axone.cache.ng;
import java.io.File;
import java.util.Set;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.Status;
import net.sf.ehcache.config.CacheConfiguration;
import de.axone.cache.Watcher;
import de.axone.cache.ng.CacheNG.Cache;
import de.axone.cache.ng.CacheNG.Realm;
public class CacheEHCache<K,O>
extends AbstractCache<K,O>
implements CacheNG.Cache<K,O> {
private final Realm<K,O> realm;
private final net.sf.ehcache.Cache backend;
public CacheEHCache( Realm<K,O> realm, net.sf.ehcache.Cache ehCache ){
this.realm = realm;
this.backend = ehCache;
}
private Watcher watcher = new Watcher();
public static <I,J> CacheEHCache<I,J> instance( File tmpDir, Realm<I,J> realm, long size ) {
CacheConfiguration config = new CacheConfiguration();
config.setName( realm.name() );
config.setDiskPersistent( true );
config.setDiskStorePath( tmpDir.getAbsolutePath() );
config.setMaxEntriesLocalHeap( size );
CacheManager manager = CacheManager.getInstance();
net.sf.ehcache.Cache newCache = new net.sf.ehcache.Cache( config );
manager.addCacheIfAbsent( newCache );
Status status = newCache.getStatus();
if( status != Status.STATUS_ALIVE ){
throw new IllegalStateException( realm.name() + " is not alive (" + status + ")" );
}
return new CacheEHCache<I,J>( realm, newCache );
}
public static void shutdown(){
CacheManager.getInstance().shutdown();
}
@Override
public void put( K key, O value ) {
backend.put( new Element( key, value ) );
}
@Override
public Cache.Entry<O> fetchEntry( K key ) {
Element element = backend.get( key );
if( element == null ){
watcher.miss();
return null;
}
watcher.hit();
@SuppressWarnings( "unchecked" )
O result = (O)element.getValue();
return new DefaultEntry<O>( result, element.getCreationTime() );
}
@Override
public boolean isCached( K key ) {
boolean result = backend.isKeyInCache( key );
if( result ) watcher.hit();
else watcher.miss();
return result;
}
@Override
public void invalidateEvent( K key ) {
O result = fetch( key );
if( result != null ){
backend.remove( key );
}
}
@Override
public void invalidateAllEvent( boolean force ) {
backend.removeAll();
}
@Override
public int size() {
return backend.getSize();
}
@Override
public int capacity() {
return -1;
}
@Override
public String info() {
return realm.name() + ": " + backend.toString();
}
@Override
public double ratio() {
return watcher.ratio();
}
@Override
public Set<K> keySet() {
throw new UnsupportedOperationException( "Doesn't has direct access" );
}
@Override
public Iterable<O> values() {
throw new UnsupportedOperationException( "Doesn't has direct access" );
}
}