com.genexus.db.InProcessCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gxclassR Show documentation
Show all versions of gxclassR Show documentation
Core classes for the runtime used by Java and Android apps generated with GeneXus
package com.genexus.db;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.genexus.Application;
import com.genexus.CommonUtil;
import com.genexus.ICacheService2;
import com.genexus.Preferences;
import com.genexus.management.CacheItemJMX;
import com.genexus.management.CacheJMX;
import com.genexus.util.DoubleLinkedQueue;
public class InProcessCache implements ICacheService2
{
protected long cacheStorageSize;
protected long currentSize;
protected int cacheDrops;
protected boolean cacheEnabled;
protected DoubleLinkedQueue lru = new DoubleLinkedQueue();
private static final boolean DEBUG = com.genexus.DebugFlag.DEBUG;
private ConcurrentHashMap cache = new ConcurrentHashMap();
private Object lockObject = new Object();
public InProcessCache()
{
Preferences prefs = Preferences.getDefaultPreferences();
cacheStorageSize = prefs.getCACHE_STORAGE_SIZE() * 1024;
cacheEnabled = prefs.getCACHING();
//JMX Enabled
if (Application.isJMXEnabled())
CacheJMX.CreateCacheJMX(this);
}
public boolean isEnabled()
{
return cacheEnabled;
}
public void setEnabled(boolean value)
{
cacheEnabled = value;
}
public ConcurrentHashMap getCache()
{
return cache;
}
public void setCacheStorageSize(long cacheStorageSize)
{
this.cacheStorageSize = cacheStorageSize;
}
public long getCacheStorageSize()
{
return cacheStorageSize;
}
public long getCacheCurrentSize()
{
return currentSize;
}
public int getCacheDrops()
{
return cacheDrops;
}
public T get(String cacheid, String key, Class type)
{
return get(getKey(cacheid, key), type);
}
@Override
public List getAll(String cacheid, String[] keys, Class type) {
String[] prefixedKeys = getKey(cacheid, keys);
List values = new ArrayList();
for (String key : prefixedKeys) {
values.add(get(key, type));
}
return values;
}
@SuppressWarnings("unchecked")
private T get(String key, Class type)
{
if(DEBUG)
{
getStatsFor(key).hits++;
}
CacheValue value = cache.get(key);
if(value == null)
{
return null;
}
else
{
if(value.hasExpired())
{ // Si ha expirado el cache, debo eliminar el value del cache
clearKey(key, value);
return null;
}
else
{
// If cache limit
if (cacheStorageSize != 0) {
lru.moveToStart(value); // Muevo el item al comienzo de la LRU
}
value.incHits(); //TODO: this is not thread safe, we can miss hits for a value.
if(DEBUG)
{
getStatsFor(key).hitsAfterFullLoaded++;
}
if ( type.isInstance(value) ) {
return (T)value;
}
else
return type.cast(((CachedIFieldGetter)value.getIterator().nextElement()).getValue(0));
}
}
}
public void clear() {
//JMX Remove
if (Application.isJMXEnabled())
CacheJMX.DestroyCacheJMX();
}
public void clearKey(String key, CacheValue value) {
if (value!=null)
{
if(DEBUG)
{
getStatsFor(value).removeFromStats(value);
}
if (cacheStorageSize != 0) {
synchronized (lockObject) {
lru.remove(value);
currentSize -= value.getSize();
}
}
//JMX Remove
if (Application.isJMXEnabled())
CacheItemJMX.DestroyCacheItemJMX(value);
cache.remove(key);
}
}
public void clearKey(String key){
CacheValue value = cache.get(key);
clearKey(key, value);
}
public void set(String cacheid, String key, T value, int expirationSeconds)
{
set(getKey(cacheid, key), value, expirationSeconds);
}
@Override
public void setAll(String cacheid, String[] keys, T[] values, int expirationSeconds) {
if (keys!=null && values!=null && keys.length == values.length) {
String[] prefixedKeys = getKey(cacheid, keys);
int idx = 0;
for (String key : prefixedKeys) {
set(key, values[idx], expirationSeconds);
idx++;
}
}
}
private void set(String key, T value, int expirationSeconds)
{
if (value instanceof CacheValue)
add(key, (CacheValue)value);
else
{
CacheValue cvalue = new CacheValue(key, null);
cvalue.addItem(value);
cvalue.setExpiryTime(expirationSeconds);
add(key, cvalue);
}
}
public void set(String cacheid, String key, T value) {
set(getKey(cacheid, key), value, Preferences.TTL_NO_EXPIRY);
}
private void set(String key, T value)
{
set(key, value, Preferences.TTL_NO_EXPIRY);
}
private boolean containsKey(String key) {
CacheValue value = cache.get(key);
if(value != null){
if(value.hasExpired()){
clearKey(key, value);
}
}
return cache.containsKey(key);
}
public boolean containtsKey(String cacheid, String key) {
return containsKey(getKey(cacheid, key));
}
public void clear(String cacheid, String key) {
cache.remove(getKey(cacheid, key));
}
public void clearCache(String cacheid) {
set(cacheid,Long.valueOf(CommonUtil.now().getTime()));
}
public void clearAllCaches() {
cache.clear();
}
private Long getKeyPrefix(String cacheid)
{
Long prefix = get(cacheid, Long.class);
if (prefix == null)
{
prefix = CommonUtil.now(false,false).getTime();
set(cacheid, Long.valueOf(prefix));
}
return prefix;
}
private String getKey(String cacheid, String key)
{
return formatKey(cacheid, key, getKeyPrefix(cacheid));
}
private String[] getKey(String cacheid, String[] keys)
{
Long prefix = getKeyPrefix(cacheid);
String[] prefixedKeys = new String[keys.length];
for (int idx =0; idx 0) {
synchronized (lockObject) {
while (currentSize > cacheStorageSize)
{
CacheValue item = (CacheValue)lru.takeFromEnd();
if(item == null)
{
break;
}
currentSize -= item.getSize();
//JMX Remove
if (Application.isJMXEnabled())
CacheItemJMX.DestroyCacheItemJMX(item);
cache.remove(item.getKey().getKey());
cacheDrops++;
if(DEBUG)
{
getStatsFor(item).removeFromStats(item);
}
}
}
}
}
public void removeExpiredEntries()
{
for(Enumeration enum1 = cache.elements(); enum1.hasMoreElements();)
{
CacheValue value = (CacheValue)enum1.nextElement();
if(value.hasExpired())
{
if(DEBUG)
{
String key = value.getKey().getKey();
getStatsFor(value).removeFromStats(value);
}
if (cacheStorageSize != 0) {
lru.remove(value);
}
currentSize -= value.getSize();
//JMX Remove
if (Application.isJMXEnabled())
CacheItemJMX.DestroyCacheItemJMX(value);
cache.remove(value.getKey().getKey());
}
}
}
public void setTimeToLive(int [] value)
{
for(int i = 0; i < Preferences.CANT_CATS; i++)
{
Preferences.TTL[i] = value[i];
}
}
public void setHitsToLive(int [] value)
{
for(int i = 0; i < Preferences.CANT_CATS; i++)
{
Preferences.HTL[i] = value[i];
}
}
//------------------------------------ STATS ---------------
private ConcurrentHashMap cacheStats = new ConcurrentHashMap();
public void addStats(String key)
{
getStatsFor(key);
}
public Stats getStatsFor(String key)
{
Stats newStats = new Stats(key);
Stats stats = cacheStats.putIfAbsent(key, newStats);
return (stats != null) ? stats : newStats;
}
public Stats getStatsFor(CacheValue value)
{
String key = value.getKey().toString();
return getStatsFor(key);
}
public ConcurrentHashMap getStats()
{
return cacheStats;
}
public String getStatsSentence(String key)
{
return getStatsFor(key).sentence;
}
public int getStatsHits(String key)
{
return getStatsFor(key).hits;
}
public int getStatsHitsCached(String key)
{
return getStatsFor(key).hitsAfterFullLoaded;
}
public int getStatsFullLoaded(String key)
{
return getStatsFor(key).fullLoaded;
}
public int getStatsCacheSize(String key)
{
return getStatsFor(key).cacheSize;
}
public long getStatsTTL(String key)
{
return getStatsFor(key).TTL / Preferences.SECONDS_IN_ONE_MINUTE;
}
class Stats
{
public Stats(String sentence)
{
this.sentence = sentence;
TTL = -1;
}
public void removeFromStats(CacheValue value)
{
fullLoaded--;
cacheSize -= value.getSize();
}
public void addToStats(CacheValue value)
{
fullLoaded++;
cacheSize += value.getSize();
}
public String sentence;
public int hits;
public int hitsAfterFullLoaded;
public int fullLoaded;
public int cacheSize;
public long TTL;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy