Changed DBBean from timestamp to WeakReference GBC

This commit is contained in:
Ziver Koc 2016-02-14 17:06:31 +01:00
parent 3da5abab98
commit 08b9da1d69
2 changed files with 35 additions and 44 deletions

View file

@ -447,14 +447,6 @@ public abstract class DBBean {
return id; return id;
} }
/**
* This function cancels the internal cache garbage collector in DBBean
*/
public static void enableBeanGBC(boolean enable){
DBBeanSQLResultHandler.enableBeanGBC(enable);
}
////////////////// EXTENDABLE METHODS ///////////////////////// ////////////////// EXTENDABLE METHODS /////////////////////////

View file

@ -29,6 +29,7 @@ import zutil.db.SQLResultHandler;
import zutil.db.bean.DBBean.DBLinkTable; import zutil.db.bean.DBBean.DBLinkTable;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -41,7 +42,7 @@ import java.util.logging.Logger;
public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
private static final Logger logger = LogUtil.getLogger(); private static final Logger logger = LogUtil.getLogger();
/** This is the time to live for the cached items **/ /** This is the time to live for the cached items **/
public static final long CACHE_TTL = 1000*60*5; // 5 min in ms public static final long CACHE_DATA_TTL = 1000*60*5; // 5 min in ms
/** A cache for detecting recursion **/ /** A cache for detecting recursion **/
protected static Map<Class<?>, Map<Long,DBBeanCache>> cache = protected static Map<Class<?>, Map<Long,DBBeanCache>> cache =
new ConcurrentHashMap<Class<?>, Map<Long,DBBeanCache>>(); new ConcurrentHashMap<Class<?>, Map<Long,DBBeanCache>>();
@ -54,9 +55,9 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
/** /**
* A cache container that contains a object and last read time * A cache container that contains a object and last read time
*/ */
protected static class DBBeanCache{ private static class DBBeanCache{
public long timestamp; public long updateTimestamp;
public DBBean bean; public WeakReference<DBBean> bean;
} }
private Class<? extends DBBean> bean_class; private Class<? extends DBBean> bean_class;
@ -124,11 +125,11 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
* This function cancels the internal cache garbage collector in DBBean. * This function cancels the internal cache garbage collector in DBBean.
* GBC is enabled by default * GBC is enabled by default
*/ */
public static void enableBeanGBC(boolean enable){ private static void enableBeanGBC(boolean enable){
if(enable){ if(enable){
if( timer == null ){ if( timer == null ){
timer = new Timer( true ); // Run as daemon timer = new Timer( true ); // Run as daemon
timer.schedule( new DBBeanGarbageCollector(), 10000, CACHE_TTL*2 ); timer.schedule( new DBBeanGarbageCollector(), CACHE_DATA_TTL, CACHE_DATA_TTL *2 );
logger.info("Bean garbage collection daemon enabled"); logger.info("Bean garbage collection daemon enabled");
} }
} }
@ -165,11 +166,9 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
DBBeanCache beanCache = class_cache.get(objKey); DBBeanCache beanCache = class_cache.get(objKey);
// Check if session is still valid // Check if session is still valid
if( beanCache.timestamp + CACHE_TTL < time ){ if( beanCache.bean.get() == null ){
class_cache.remove(objKey); class_cache.remove(objKey);
removed++; removed++;
logger.finer("Removing old Bean("+beanCache.bean.getClass().getName()+")" +
" from cache with id: "+beanCache.bean.getId());
} }
} }
} }
@ -218,10 +217,8 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
return obj; return obj;
logger.fine("Creating new Bean("+bean_class.getName()+") with id: "+id); logger.fine("Creating new Bean("+bean_class.getName()+") with id: "+id);
obj = bean_class.newInstance(); obj = bean_class.newInstance();
cacheDBBean(obj, id); obj.id = id; // Set id field
cacheDBBean(obj);
// Set id field
obj.id = id;
// Update fields // Update fields
updateBean( result, obj ); updateBean( result, obj );
@ -229,7 +226,7 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
} catch (SQLException e) { } catch (SQLException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
throw new SQLException(e); throw new RuntimeException(e);
} }
} }
@ -315,21 +312,24 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
*/ */
protected DBBean getCachedDBBean(Class<?> c, Long id, ResultSet result) throws SQLException{ protected DBBean getCachedDBBean(Class<?> c, Long id, ResultSet result) throws SQLException{
if( cache.containsKey(c) ){ if( cache.containsKey(c) ){
DBBeanCache item = cache.get(c).get(id); DBBeanCache cacheItem = cache.get(c).get(id);
// Check if the cache is valid // Check if the cache is valid
if( item != null ){ if( cacheItem != null){
DBBean bean = cacheItem.bean.get();
if( bean != null) {
// The cache is old, update and return it // The cache is old, update and return it
if( item.timestamp+CACHE_TTL < System.currentTimeMillis() ){ if (cacheItem.updateTimestamp + CACHE_DATA_TTL < System.currentTimeMillis()) {
// There is no ResultSet to update from // There is no ResultSet to update from
if( result == null ) if (result == null)
return null; return null;
// Only update object if there is no update running now // Only update object if there is no update running now
if( !item.bean.processing_update ){ if (!bean.processing_update) {
logger.finer("Bean("+c.getName()+") cache to old for id: "+id); logger.finer("Bean(" + c.getName() + ") cache to old for id: " + id);
updateBean( result, item.bean ); updateBean(result, bean);
} }
} }
return item.bean; return bean;
}
} }
// The cache is null // The cache is null
cache.get(c).remove(id); cache.get(c).remove(id);
@ -342,17 +342,16 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
* Adds the given object to the cache * Adds the given object to the cache
* *
* @param obj is the object to cache * @param obj is the object to cache
* @param id is the id object of the bean
*/ */
protected static synchronized void cacheDBBean(DBBean obj, Long id) { protected static synchronized void cacheDBBean(DBBean obj) {
DBBeanCache item = new DBBeanCache(); DBBeanCache cacheItem = new DBBeanCache();
item.timestamp = System.currentTimeMillis(); cacheItem.updateTimestamp = System.currentTimeMillis();
item.bean = obj; cacheItem.bean = new WeakReference<DBBean>(obj);
if( cache.containsKey(obj.getClass()) ) if( cache.containsKey(obj.getClass()) )
cache.get(obj.getClass()).put(id, item); cache.get(obj.getClass()).put(obj.getId(), cacheItem);
else{ else{
Map<Long, DBBeanCache> map = new ConcurrentHashMap<Long, DBBeanCache>(); Map<Long, DBBeanCache> map = new ConcurrentHashMap<Long, DBBeanCache>();
map.put(id, item); map.put(obj.getId(), cacheItem);
cache.put(obj.getClass(), map); cache.put(obj.getClass(), map);
} }
} }