#2318 - Refactor internals - final classes in cache package

This commit is contained in:
rbygrave committed 2021-08-17 21:24:56 +12:00
1 parent d096706685
commit 190a2c47e9
21 files changed
+35 -105

No files matched your search

@@ -8,10 +8,9 @@ import java.util.Collection;
/**
* Change to remove bean from L2 cache.
*/
class CacheChangeBeanRemove implements CacheChange {
final class CacheChangeBeanRemove implements CacheChange {
private final BeanDescriptor<?> descriptor;
private final Collection<Object> ids;
CacheChangeBeanRemove(Object id, BeanDescriptor<?> descriptor) {
@@ -7,7 +7,7 @@ import java.util.Map;
/**
* Put a new bean entry into the cache.
*/
class CacheChangeBeanUpdate implements CacheChange {
final class CacheChangeBeanUpdate implements CacheChange {
private final BeanDescriptor<?> desc;
private final String key;
@@ -5,7 +5,7 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Change the natural key mapping for a bean.
*/
class CacheChangeNaturalKeyPut implements CacheChange {
final class CacheChangeNaturalKeyPut implements CacheChange {
private final BeanDescriptor<?> descriptor;
private final String key;
@@ -14,18 +14,13 @@ import java.util.Set;
/**
* List of changes to be applied to L2 cache.
*/
public class CacheChangeSet {
public final class CacheChangeSet {
private final List<CacheChange> entries = new ArrayList<>();
private final Set<String> touchedTables = new HashSet<>();
private final Set<BeanDescriptor<?>> queryCaches = new HashSet<>();
private final Set<BeanDescriptor<?>> beanCaches = new HashSet<>();
private final Map<BeanDescriptor<?>, CacheChangeBeanRemove> beanRemoveMap = new HashMap<>();
private final Map<ManyKey, ManyChange> manyChangeMap = new HashMap<>();
/**
@@ -173,14 +168,11 @@ public class CacheChangeSet {
/**
* Changes for a specific many property.
*/
private static class ManyChange implements CacheChange {
private static final class ManyChange implements CacheChange {
final ManyKey key;
final Set<Object> removes = new HashSet<>();
final Map<Object, CachedManyIds> puts = new LinkedHashMap<>();
boolean clear;
ManyChange(ManyKey key) {
@@ -229,10 +221,9 @@ public class CacheChangeSet {
/**
* Key for changes on a many property.
*/
private static class ManyKey {
private static final class ManyKey {
private final BeanDescriptor<?> desc;
private final String manyProperty;
ManyKey(BeanDescriptor<?> desc, String manyProperty) {
@@ -10,18 +10,13 @@ import io.ebeaninternal.server.cluster.ClusterManager;
/**
* Configuration options when creating the default cache manager.
*/
public class CacheManagerOptions {
public final class CacheManagerOptions {
private final ClusterManager clusterManager;
private final DatabaseConfig databaseConfig;
private final boolean localL2Caching;
private CurrentTenantProvider currentTenantProvider;
private QueryCacheEntryValidate queryCacheEntryValidate;
private ServerCacheFactory cacheFactory = new DefaultServerCacheFactory();
private ServerCacheOptions beanDefault = new ServerCacheOptions();
private ServerCacheOptions queryDefault = new ServerCacheOptions();
@@ -11,13 +11,12 @@ import java.util.Map;
/**
* Data held in the bean cache for cached beans.
*/
public class CachedBeanData implements Externalizable {
public final class CachedBeanData implements Externalizable {
private long whenCreated;
private long version;
private String discValue;
private Map<String, Object> data;
/**
* The sharable bean is effectively transient (near cache only).
*/
@@ -9,10 +9,9 @@ import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import java.util.LinkedHashMap;
import java.util.Map;
public class CachedBeanDataFromBean {
public final class CachedBeanDataFromBean {
public static CachedBeanData extract(BeanDescriptor<?> desc, EntityBean bean) {
EntityBeanIntercept ebi = bean._ebean_getIntercept();
Map<String, Object> data = new LinkedHashMap<>();
@@ -46,7 +45,6 @@ public class CachedBeanDataFromBean {
}
private static EntityBean createSharableBean(BeanDescriptor<?> desc, EntityBean bean, EntityBeanIntercept beanEbi) {
if (!desc.isCacheSharableBeans() || !beanEbi.isFullyLoadedBean()) {
return null;
}
@@ -7,30 +7,24 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
public class CachedBeanDataToBean {
public final class CachedBeanDataToBean {
public static void load(BeanDescriptor<?> desc, EntityBean bean, CachedBeanData cacheBeanData, PersistenceContext context) {
EntityBeanIntercept ebi = bean._ebean_getIntercept();
// any future lazy loading skips L2 bean cache
ebi.setLoadedFromCache(true);
BeanProperty idProperty = desc.getIdProperty();
if (desc.getInheritInfo() != null) {
desc = desc.getInheritInfo().readType(bean.getClass()).desc();
}
if (idProperty != null) {
// load the id property
loadProperty(bean, cacheBeanData, ebi, idProperty, context);
}
// load the non-many properties
for (BeanProperty prop : desc.propertiesNonMany()) {
loadProperty(bean, cacheBeanData, ebi, prop, context);
}
for (BeanPropertyAssocMany<?> prop : desc.propertiesMany()) {
if (prop.isElementCollection()) {
loadProperty(bean, cacheBeanData, ebi, prop, context);
@@ -38,12 +32,10 @@ public class CachedBeanDataToBean {
prop.createReferenceIfNull(bean);
}
}
ebi.setLoadedLazy();
}
private static void loadProperty(EntityBean bean, CachedBeanData cacheBeanData, EntityBeanIntercept ebi, BeanProperty prop, PersistenceContext context) {
if (cacheBeanData.isLoaded(prop.getName())) {
if (!ebi.isLoadedProperty(prop.getPropertyIndex())) {
Object value = cacheBeanData.getData(prop.getName());
@@ -10,7 +10,7 @@ import java.io.ObjectOutput;
* <p>
* Put into L2 cache such that we know the type of a bean with inheritance.
*/
public class CachedBeanId implements Externalizable {
public final class CachedBeanId implements Externalizable {
private String discValue;
private Object id;
@@ -13,7 +13,7 @@ import java.util.List;
* This is effectively just the Id values for each of the beans in the collection.
* </p>
*/
public class CachedManyIds implements Externalizable {
public final class CachedManyIds implements Externalizable {
private List<Object> idList;
@@ -13,7 +13,7 @@ import java.util.List;
* Used to hide the Supplier part of the SpiCacheManager API from public use.
* </p>
*/
public class DefaultCacheAdapter implements ServerCacheManager {
public final class DefaultCacheAdapter implements ServerCacheManager {
private final SpiCacheManager cacheManager;
@@ -23,14 +23,13 @@ import java.util.concurrent.locks.ReentrantLock;
/**
* Manages the construction of caches.
*/
class DefaultCacheHolder {
final class DefaultCacheHolder {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.ALL");
private final ReentrantLock lock = new ReentrantLock();
private final ConcurrentHashMap<String, ServerCache> allCaches = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Set<String>> collectIdCaches = new ConcurrentHashMap<>();
private final ServerCacheFactory cacheFactory;
private final ServerCacheOptions beanDefault;
private final ServerCacheOptions queryDefault;
@@ -76,7 +75,6 @@ class DefaultCacheHolder {
* Return the cache for a given bean type.
*/
private ServerCache getCacheInternal(Class<?> beanType, ServerCacheType type, String collectionProperty) {
String shortName = key(beanType.getSimpleName(), collectionProperty, type);
String fullKey = key(beanType.getName(), collectionProperty, type);
return allCaches.computeIfAbsent(fullKey, s -> createCache(beanType, type, fullKey, shortName));
@@ -143,10 +141,8 @@ class DefaultCacheHolder {
}
private ServerCacheOptions getBeanOptions(Class<?> cls) {
Cache cache = cls.getAnnotation(Cache.class);
boolean nearCache = (cache != null && cache.nearCache());
CacheBeanTuning tuning = cls.getAnnotation(CacheBeanTuning.class);
if (tuning != null) {
return new ServerCacheOptions(nearCache, tuning).applyDefaults(beanDefault);
@@ -39,7 +39,6 @@ public class DefaultServerCache implements ServerCache {
* The underlying map (ConcurrentHashMap or similar)
*/
protected final Map<Object, SoftReference<CacheEntry>> map;
protected final CountMetric hitCount;
protected final CountMetric missCount;
protected final CountMetric putCount;
@@ -49,16 +48,11 @@ public class DefaultServerCache implements ServerCache {
protected final String name;
protected final String shortName;
private int maxSize;
private final int maxSize;
private final int trimFrequency;
private int maxIdleSecs;
private int maxSecsToLive;
private TenantAwareKey tenantAwareKey;
private final int maxIdleSecs;
private final int maxSecsToLive;
private final TenantAwareKey tenantAwareKey;
public DefaultServerCache(DefaultServerCacheConfig config) {
this.name = config.getName();
@@ -71,7 +65,6 @@ public class DefaultServerCache implements ServerCache {
this.trimFrequency = config.determineTrimFrequency();
MetricFactory factory = MetricFactory.get();
String prefix = "l2n.";
this.hitCount = factory.createCountMetric(prefix + shortName + ".hit");
this.missCount = factory.createCountMetric(prefix + shortName + ".miss");
@@ -82,9 +75,7 @@ public class DefaultServerCache implements ServerCache {
}
public void periodicTrim(BackgroundExecutor executor) {
EvictionRunnable trim = new EvictionRunnable();
// default to trimming the cache every 60 seconds
long trimFreqSecs = (trimFrequency == 0) ? 60 : trimFrequency;
executor.scheduleWithFixedDelay(trim, trimFreqSecs, trimFreqSecs, TimeUnit.SECONDS);
@@ -102,11 +93,9 @@ public class DefaultServerCache implements ServerCache {
@Override
public ServerCacheStatistics getStatistics(boolean reset) {
ServerCacheStatistics cacheStats = new ServerCacheStatistics();
cacheStats.setCacheName(name);
cacheStats.setMaxSize(maxSize);
cacheStats.setSize(size());
cacheStats.setHitCount(hitCount.get(reset));
cacheStats.setMissCount(missCount.get(reset));
@@ -114,7 +103,6 @@ public class DefaultServerCache implements ServerCache {
cacheStats.setRemoveCount(removeCount.get(reset));
cacheStats.setClearCount(clearCount.get(reset));
cacheStats.setEvictCount(evictCount.get(reset));
return cacheStats;
}
@@ -134,10 +122,8 @@ public class DefaultServerCache implements ServerCache {
@Override
public int getHitRatio() {
long mc = missCount.get(false);
long hc = hitCount.get(false);
long totalCount = hc + mc;
if (totalCount == 0) {
return 0;
@@ -178,7 +164,6 @@ public class DefaultServerCache implements ServerCache {
*/
@Override
public Object get(Object id) {
CacheEntry entry = getCacheEntry(id);
if (entry == null) {
missCount.increment();
@@ -252,31 +237,25 @@ public class DefaultServerCache implements ServerCache {
* Run the eviction based on Idle time, Time to live and LRU last access.
*/
public void runEviction() {
long trimForMaxSize;
if (maxSize == 0) {
trimForMaxSize = 0;
} else {
trimForMaxSize = size() - maxSize;
}
if (maxIdleSecs == 0 && maxSecsToLive == 0 && trimForMaxSize < 0) {
// nothing to trim on this cache
return;
}
long startNanos = System.nanoTime();
long trimmedByIdle = 0;
long trimmedByGC = 0;
long trimmedByTTL = 0;
long trimmedByLRU = 0;
List<CacheEntry> activeList = new ArrayList<>(map.size());
long idleExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxIdleSecs);
long ttlExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxSecsToLive);
Iterator<SoftReference<CacheEntry>> it = map.values().iterator();
while (it.hasNext()) {
SoftReference<CacheEntry> ref = it.next();
@@ -287,16 +266,13 @@ public class DefaultServerCache implements ServerCache {
} else if (maxIdleSecs > 0 && idleExpireNano > cacheEntry.getLastAccessTime()) {
it.remove();
trimmedByIdle++;
} else if (maxSecsToLive > 0 && ttlExpireNano > cacheEntry.getCreateTime()) {
it.remove();
trimmedByTTL++;
} else if (trimForMaxSize > 0) {
activeList.add(cacheEntry);
}
}
if (trimForMaxSize > 0 && activeList.size() > maxSize) {
// sort into last access time ascending
activeList.sort(BY_LAST_ACCESS);
@@ -313,7 +289,6 @@ public class DefaultServerCache implements ServerCache {
evictCount.add(trimmedByGC);
evictCount.add(trimmedByTTL);
evictCount.add(trimmedByLRU);
if (logger.isTraceEnabled()) {
long exeMicros = TimeUnit.MICROSECONDS.convert(System.nanoTime() - startNanos, TimeUnit.NANOSECONDS);
logger.trace("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}] gc[{}]",
@@ -324,7 +299,7 @@ public class DefaultServerCache implements ServerCache {
/**
* Runnable that calls the eviction routine.
*/
public class EvictionRunnable implements Runnable {
public final class EvictionRunnable implements Runnable {
@Override
public void run() {
@@ -335,7 +310,7 @@ public class DefaultServerCache implements ServerCache {
/**
* Comparator for sorting by last access time.
*/
public static class CompareByLastAccess implements Comparator<CacheEntry>, Serializable {
public static final class CompareByLastAccess implements Comparator<CacheEntry>, Serializable {
private static final long serialVersionUID = 1L;
@@ -348,7 +323,7 @@ public class DefaultServerCache implements ServerCache {
/**
* Wraps the value to additionally hold createTime and lastAccessTime and hit counter.
*/
public static class CacheEntry {
public static final class CacheEntry {
private final Object key;
private final Object value;
@@ -10,16 +10,14 @@ import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DefaultServerCacheConfig {
public final class DefaultServerCacheConfig {
private final ServerCacheConfig config;
private int maxSize;
private int maxIdleSecs;
private int maxSecsToLive;
private int trimFrequency;
private Map<Object, SoftReference<CacheEntry>> map;
private final int maxSize;
private final int maxIdleSecs;
private final int maxSecsToLive;
private final int trimFrequency;
private final Map<Object, SoftReference<CacheEntry>> map;
public DefaultServerCacheConfig(ServerCacheConfig config) {
this(config, new ConcurrentHashMap<>());
@@ -11,7 +11,7 @@ import io.ebean.cache.ServerCacheNotify;
/**
* Default implementation of ServerCacheFactory.
*/
class DefaultServerCacheFactory implements ServerCacheFactory {
final class DefaultServerCacheFactory implements ServerCacheFactory {
private final BackgroundExecutor executor;
@@ -31,7 +31,6 @@ class DefaultServerCacheFactory implements ServerCacheFactory {
@Override
public ServerCache createCache(ServerCacheConfig config) {
DefaultServerCache cache;
if (config.isQueryCache()) {
// use a server cache aware of extra validation and QueryCacheEntry
@@ -19,18 +19,14 @@ import java.util.Map;
/**
* Manages the bean and query caches.
*/
public class DefaultServerCacheManager implements SpiCacheManager {
public final class DefaultServerCacheManager implements SpiCacheManager {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.REGION");
private final Map<String, SpiCacheRegion> regionMap = new HashMap<>();
private final ClusterManager clusterManager;
private final DefaultCacheHolder cacheHolder;
private final boolean localL2Caching;
private final String serverName;
/**
@@ -8,7 +8,7 @@ import io.ebean.config.DatabaseConfig;
/**
* Default implementation of ServerCachePlugin.
*/
public class DefaultServerCachePlugin implements ServerCachePlugin {
public final class DefaultServerCachePlugin implements ServerCachePlugin {
/**
* Creates the default ServerCacheFactory.
@@ -12,11 +12,10 @@ import java.util.List;
/**
* Cache events broadcast across the cluster.
*/
public class RemoteCacheEvent implements BinaryWritable {
public final class RemoteCacheEvent implements BinaryWritable {
private boolean clearAll;
private List<String> clearCaches;
private final boolean clearAll;
private final List<String> clearCaches;
/**
* Clear all the caches.
@@ -57,10 +56,8 @@ public class RemoteCacheEvent implements BinaryWritable {
}
public static RemoteCacheEvent readBinaryMessage(BinaryReadContext dataInput) throws IOException {
boolean clearAll = dataInput.readBoolean();
int size = dataInput.readInt();
List<String> clearCache = null;
if (size > 0) {
clearCache = new ArrayList<>(size);
@@ -68,7 +65,6 @@ public class RemoteCacheEvent implements BinaryWritable {
clearCache.add(dataInput.readUTF());
}
}
return new RemoteCacheEvent(clearAll, clearCache);
}
@@ -20,7 +20,7 @@ public final class DefaultChangeLogListener implements ChangeLogListener, Plugin
/**
* The usual application specific logger.
*/
protected static final Logger logger = LoggerFactory.getLogger(DefaultChangeLogListener.class);
private static final Logger logger = LoggerFactory.getLogger(DefaultChangeLogListener.class);
/**
* The named logger we send the change set payload to. Can be externally configured as desired.
@@ -30,20 +30,16 @@ public final class DefaultChangeLogRegister implements ChangeLogRegister {
@Override
public ChangeLogFilter getChangeFilter(Class<?> beanType) {
ChangeLog changeLog = getChangeLog(beanType);
if (changeLog == null) {
return null;
}
String[] updatesThatInclude = changeLog.updatesThatInclude();
if (updatesThatInclude.length == 0) {
return insertModeInclude(changeLog.inserts()) ? INCLUDE_INSERTS : EXCLUDE_INSERTS;
}
Set<String> updateProps = new HashSet<>();
Collections.addAll(updateProps, updatesThatInclude);
return new UpdateFilter(insertModeInclude(changeLog.inserts()), updateProps);
}
@@ -10,7 +10,7 @@ import io.ebean.event.readaudit.ReadEvent;
* the user context information on the readEvent bean (like user id).
* </p>
*/
public class DefaultReadAuditPrepare implements ReadAuditPrepare {
public final class DefaultReadAuditPrepare implements ReadAuditPrepare {
@Override
public void prepare(ReadEvent readEvent) {