/*
* Copyright (C) 2006 http://www.chaidb.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
package org.chaidb.db.helper.cache;
import org.chaidb.db.helper.cache.algorithm.MeasurableFIFO;
import org.chaidb.db.helper.cache.algorithm.MeasurableLRU;
import org.chaidb.db.helper.cache.algorithm.MeasurableReplacementAlgorithm;
import org.chaidb.db.helper.cache.measurable.Measurable;
import org.chaidb.db.helper.cache.measurable.SizeTooLargeException;
import org.chaidb.db.helper.cache.persistence.CachePersistenceException;
import org.chaidb.db.helper.cache.persistence.DummyPersistenceListener;
import org.chaidb.db.helper.cache.persistence.NoSuchKeyException;
import org.chaidb.db.helper.cache.persistence.PersistenceListener;
public class MeasurableCache implements Measurable {
public MeasurableCache(long cacheSizeInBytes) {
this(cacheSizeInBytes, null);
}
public MeasurableCache(long cacheSizeInBytes, String name) {
this(cacheSizeInBytes, "LRU", name);
}
public MeasurableCache(long cacheSizeInBytes, String algorithmName, String name) {
this(cacheSizeInBytes, algorithmName, new DummyPersistenceListener(), name);
}
public MeasurableCache(long cacheSizeInBytes, String algorithmName, PersistenceListener listener, String name) {
if (listener == null) {
throw new IllegalArgumentException("listener must NOT be null");
} else {
this.listener = listener;
}
if (cacheSizeInBytes <= 0) {
throw new IllegalArgumentException("cacheSizeInBytes must be larger than 0");
} else {
if (algorithmName == null) {
algorithm = new MeasurableLRU(cacheSizeInBytes);
} else if (algorithmName.equals("LRU")) {
algorithm = new MeasurableLRU(cacheSizeInBytes);
} else if (algorithmName.equals("FIFO")) {
algorithm = new MeasurableFIFO(cacheSizeInBytes);
} else {
throw new IllegalArgumentException("unknown replacement algorithm: " + algorithmName);
}
}
this.name = name;
administrator.register(this);
}
public String getName() {
return this.name;
}
public String setName(String name) {
String oldName = this.name;
this.name = name;
return oldName;
}
public boolean containsKey(Measurable key) throws CacheException {
synchronized (algorithm) {
if (algorithm.containsKey(key)) {
return true;
} else {
try {
listener.retrieve(key);
} catch (CachePersistenceException e) {
throw new CacheException("retrieve value from underlying storage error", e);
} catch (NoSuchKeyException e) {
return false;
}
return true;
}
}
}
public Measurable getFromCache(Measurable key) throws CacheException {
synchronized (algorithm) {
if (!algorithm.containsKey(key)) {
try {
Measurable value = (Measurable) listener.retrieve(key);
return algorithm.put(key, value);
} catch (CachePersistenceException e) {
throw new CacheException("retrieve value from underlying storage error", e);
} catch (SizeTooLargeException e) {
throw new CacheException("in-memory cache is NOT able to hold specified key/value pair.", e);
} catch (NoSuchKeyException e) {
return null;
}
} else {
return algorithm.get(key);
}
}
}
public Measurable putIntoCache(Measurable key, Measurable value) throws CacheException {
synchronized (algorithm) {
try {
return (Measurable) algorithm.put(key, value);
} catch (SizeTooLargeException e) {
throw new CacheException("in-memory cache is NOT able to hold specified key/value pair", e);
}
}
}
public Measurable removeFromCache(Measurable key) throws CacheException {
synchronized (algorithm) {
return (Measurable) algorithm.remove(key);
}
}
public void clearCache() {
synchronized (algorithm) {
algorithm.clear();
}
}
public long getSizeBoundary() {
synchronized (algorithm) {
return algorithm.getSizeBoundary();
}
}
public long getRetainedSize() {
return algorithm.getRetainedSize();
}
public long calculateRetainedSize() {
return algorithm.calculateRetainedSize();
}
protected final MeasurableReplacementAlgorithm algorithm;
protected final PersistenceListener listener;
private String name;
private static CacheAdministrator administrator = CacheAdministrator.getInstance();
}