Removed DBBean garbage collector
it it is not needed with WeakReference anymore
This commit is contained in:
parent
0ba153b118
commit
f8a46f2089
1 changed files with 27 additions and 85 deletions
|
|
@ -17,96 +17,36 @@ import java.util.logging.Logger;
|
||||||
*/
|
*/
|
||||||
class DBBeanCache {
|
class DBBeanCache {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
/** This is the time to live for the cached items **/
|
/**
|
||||||
public static final long CACHE_DATA_TTL = 1000*60*5; // 5 min in ms
|
* This is the time to live for the cached items
|
||||||
/** A cache for detecting recursion **/
|
**/
|
||||||
|
public static final long CACHE_DATA_TTL = 1000 * 60 * 5; // 5 min in ms
|
||||||
|
/**
|
||||||
|
* A cache for detecting recursion
|
||||||
|
**/
|
||||||
private static Map<Class<?>, Map<Long, CacheItem>> cache =
|
private static Map<Class<?>, Map<Long, CacheItem>> cache =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
private static ScheduledExecutorService executor;
|
|
||||||
|
|
||||||
|
|
||||||
static {
|
|
||||||
enableBeanGBC(true); // Initiate DBBeanGarbageCollector
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache container that contains a bean and its last filed update time
|
* A cache container that contains a bean and its last filed update time
|
||||||
*/
|
*/
|
||||||
private static class CacheItem{
|
private static class CacheItem {
|
||||||
public long updateTimestamp;
|
public long updateTimestamp;
|
||||||
public WeakReference<DBBean> bean;
|
public WeakReference<DBBean> bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean contains(DBBean obj) {
|
||||||
|
|
||||||
/**
|
|
||||||
* This function cancels the internal cache garbage collector in DBBean.
|
|
||||||
* GBC is enabled by default
|
|
||||||
*/
|
|
||||||
public static synchronized void enableBeanGBC(boolean enable){
|
|
||||||
if(enable){
|
|
||||||
if( executor == null ){
|
|
||||||
executor = Executors.newSingleThreadScheduledExecutor();
|
|
||||||
executor.scheduleAtFixedRate( new DBBeanGarbageCollector(), CACHE_DATA_TTL, CACHE_DATA_TTL *2, TimeUnit.MILLISECONDS );
|
|
||||||
logger.fine("Bean garbage collection daemon enabled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (executor != null) {
|
|
||||||
executor.shutdown();
|
|
||||||
executor = null;
|
|
||||||
logger.fine("Bean garbage collection daemon disabled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class acts as an garbage collector that removes old DBBeans
|
|
||||||
*/
|
|
||||||
private static class DBBeanGarbageCollector implements Runnable {
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
if (cache == null) {
|
|
||||||
logger.severe("DBBeanSQLResultHandler not initialized, stopping DBBeanGarbageCollector timer.");
|
|
||||||
enableBeanGBC(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int removed = 0;
|
|
||||||
for (Object classKey : cache.keySet()) {
|
|
||||||
if (classKey == null) continue;
|
|
||||||
|
|
||||||
Map<Long, CacheItem> class_cache = cache.get(classKey);
|
|
||||||
for (Iterator<Map.Entry<Long, CacheItem>> it = class_cache.entrySet().iterator(); it.hasNext(); ) {
|
|
||||||
Map.Entry<Long, CacheItem> entry = it.next();
|
|
||||||
if (entry.getKey() == null) continue;
|
|
||||||
// Check if session is still valid
|
|
||||||
if (entry.getValue().bean.get() == null) {
|
|
||||||
it.remove();
|
|
||||||
removed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (removed > 0)
|
|
||||||
logger.info("DBBean GarbageCollector has cleared " + removed + " beans from cache.");
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.log(Level.SEVERE, "DBBeanGarbageCollector thread has crashed", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static boolean contains(DBBean obj){
|
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
return false;
|
return false;
|
||||||
return contains(obj.getClass(), obj.getId());
|
return contains(obj.getClass(), obj.getId());
|
||||||
}
|
}
|
||||||
public static boolean contains(Class<?> c, Long id){
|
|
||||||
if( cache.containsKey(c) ){
|
public static boolean contains(Class<?> c, Long id) {
|
||||||
|
if (cache.containsKey(c)) {
|
||||||
CacheItem cacheItem = cache.get(c).get(id);
|
CacheItem cacheItem = cache.get(c).get(id);
|
||||||
|
|
||||||
// Check if the cache is valid
|
// Check if the cache is valid
|
||||||
if( cacheItem != null && cacheItem.bean.get() != null ) {
|
if (cacheItem != null && cacheItem.bean.get() != null) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// The bean has been deallocated
|
// The bean has been deallocated
|
||||||
|
|
@ -124,19 +64,19 @@ class DBBeanCache {
|
||||||
* @return a cached DBBean object, null if there is a cache miss
|
* @return a cached DBBean object, null if there is a cache miss
|
||||||
*/
|
*/
|
||||||
public static DBBean get(Class<?> c, Long id) {
|
public static DBBean get(Class<?> c, Long id) {
|
||||||
if(contains(c, id)){
|
if (contains(c, id)) {
|
||||||
CacheItem cacheItem = cache.get(c).get(id);
|
CacheItem cacheItem = cache.get(c).get(id);
|
||||||
return cacheItem.bean.get();
|
return cacheItem.bean.get();
|
||||||
}
|
}
|
||||||
logger.finer("Bean("+c.getName()+") cache miss for id: "+id);
|
logger.finer("Bean(" + c.getName() + ") cache miss for id: " + id);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the bean data is outdated, false if the data is current or if the bean was not found in the cache
|
* @return true if the bean data is outdated, false if the data is current or if the bean was not found in the cache
|
||||||
*/
|
*/
|
||||||
public static boolean isOutDated(DBBean obj){
|
public static boolean isOutDated(DBBean obj) {
|
||||||
if(contains(obj)) {
|
if (contains(obj)) {
|
||||||
CacheItem cacheItem = cache.get(obj.getClass()).get(obj.getId());
|
CacheItem cacheItem = cache.get(obj.getClass()).get(obj.getId());
|
||||||
return cacheItem.updateTimestamp + CACHE_DATA_TTL < System.currentTimeMillis();
|
return cacheItem.updateTimestamp + CACHE_DATA_TTL < System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
@ -152,21 +92,23 @@ class DBBeanCache {
|
||||||
cache.get(obj.getClass()).get(obj.getId()).updateTimestamp = System.currentTimeMillis();
|
cache.get(obj.getClass()).get(obj.getId()).updateTimestamp = System.currentTimeMillis();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CacheItem cacheItem = new CacheItem();
|
CacheItem cacheItem = new CacheItem();
|
||||||
cacheItem.updateTimestamp = System.currentTimeMillis();
|
cacheItem.updateTimestamp = System.currentTimeMillis();
|
||||||
cacheItem.bean = new WeakReference<>(obj);
|
cacheItem.bean = new WeakReference<>(obj);
|
||||||
if( cache.containsKey(obj.getClass()) )
|
|
||||||
|
if (cache.containsKey(obj.getClass()))
|
||||||
cache.get(obj.getClass()).put(obj.getId(), cacheItem);
|
cache.get(obj.getClass()).put(obj.getId(), cacheItem);
|
||||||
else{
|
else {
|
||||||
Map<Long, CacheItem> map = new ConcurrentHashMap<>();
|
Map<Long, CacheItem> map = new ConcurrentHashMap<>();
|
||||||
map.put(obj.getId(), cacheItem);
|
map.put(obj.getId(), cacheItem);
|
||||||
cache.put(obj.getClass(), map);
|
cache.put(obj.getClass(), map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void remove(DBBean obj){
|
public static void remove(DBBean obj) {
|
||||||
if (obj != null)
|
if (obj != null)
|
||||||
if( cache.containsKey(obj.getClass()) )
|
if (cache.containsKey(obj.getClass()))
|
||||||
cache.get(obj.getClass()).remove(obj.getId());
|
cache.get(obj.getClass()).remove(obj.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue