From 12016ddff7d52114eaa35a397f41e1dde7e664df Mon Sep 17 00:00:00 2001 From: Shashi Madappa Date: Fri, 10 Mar 2017 19:13:30 -0800 Subject: [PATCH] Synchronizing the creation of in memory cache so we don't endup with duplicates --- .../netflix/evcache/EVCacheInMemoryCache.java | 87 +++++++++++-------- .../pool/EVCacheClientPoolManager.java | 11 ++- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/evcache-client/src/main/java/com/netflix/evcache/EVCacheInMemoryCache.java b/evcache-client/src/main/java/com/netflix/evcache/EVCacheInMemoryCache.java index 8f994e0f..1795277a 100644 --- a/evcache-client/src/main/java/com/netflix/evcache/EVCacheInMemoryCache.java +++ b/evcache-client/src/main/java/com/netflix/evcache/EVCacheInMemoryCache.java @@ -17,6 +17,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; +import com.google.common.cache.CacheStats; import com.google.common.cache.LoadingCache; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFutureTask; @@ -165,18 +166,23 @@ public ListenableFuture reload(final String key, T prev) { ListenableFutureTask task = ListenableFutureTask.create(new Callable() { public T call() { try { - final T t = load(key); - if(t == null) { - EVCacheMetricsFactory.increment(appName, null, null, "EVCacheInMemoryCache" + "-" + appName + "-Reload-NotFound"); - } else { - EVCacheMetricsFactory.increment(appName, null, null, "EVCacheInMemoryCache" + "-" + appName + "-Reload-Success"); - } - return t; - } catch (EVCacheException e) { - log.error("EVCacheException while reloading key -> "+ key, e); - EVCacheMetricsFactory.increment(appName, null, null, "EVCacheInMemoryCache" + "-" + appName + "-Reload-Fail"); - return prev; - } + T t = load(key); + if(t != null && t.equals(prev)) { + EVCacheMetricsFactory.increment(appName, null, null, "EVCacheInMemoryCache" + "-" + appName + "-Reload-UsePrevious"); + t = prev; + } + if(t == null) { + EVCacheMetricsFactory.increment(appName, null, null, "EVCacheInMemoryCache" + "-" + appName + "-Reload-NotFound"); + return prev; + } else { + EVCacheMetricsFactory.increment(appName, null, null, "EVCacheInMemoryCache" + "-" + appName + "-Reload-Success"); + } + return t; + } catch (EVCacheException e) { + log.error("EVCacheException while reloading key -> "+ key, e); + EVCacheMetricsFactory.increment(appName, null, null, "EVCacheInMemoryCache" + "-" + appName + "-Reload-Fail"); + return prev; + } } }); pool.execute(task); @@ -195,12 +201,21 @@ public T call() { } } + private LoadingCache getCache() { + return cache; + } + + private CacheStats getStats() { + return cache.stats(); + } + private void setupMonitoring(final String appName) { final StepCounter sizeCounter = new StepCounter(getMonitorConfig(appName, "size", DataSourceType.GAUGE)) { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Long.valueOf(cache.size()); + if (getCache() == null) return Long.valueOf(0); + log.debug("Current size is : " + getCache().size()); + return Long.valueOf(getCache().size()); } @Override @@ -219,8 +234,8 @@ public Number getValue(int pollerIndex) { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Long.valueOf(cache.stats().requestCount()); + if (getCache() == null) return Long.valueOf(0); + return Long.valueOf(getStats().requestCount()); } @Override @@ -237,8 +252,8 @@ public MonitorConfig getConfig() { final StepCounter hitrateCounter = new StepCounter(getMonitorConfig(appName, "hitrate", DataSourceType.GAUGE)) { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().hitRate()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().hitRate()); } @Override @@ -257,8 +272,8 @@ public Number getValue(int pollerIndex) { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().hitCount()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().hitCount()); } @Override @@ -281,8 +296,8 @@ public MonitorConfig getConfig() { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().missCount()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().missCount()); } @Override @@ -305,8 +320,8 @@ public MonitorConfig getConfig() { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().evictionCount()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().evictionCount()); } @Override @@ -329,8 +344,8 @@ public MonitorConfig getConfig() { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().loadExceptionCount()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().loadExceptionCount()); } @Override @@ -353,8 +368,8 @@ public MonitorConfig getConfig() { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().loadCount()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().loadCount()); } @Override @@ -377,8 +392,8 @@ public MonitorConfig getConfig() { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().loadSuccessCount()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().loadSuccessCount()); } @Override @@ -401,8 +416,8 @@ public MonitorConfig getConfig() { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().totalLoadTime()/1000000); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().totalLoadTime()/1000000); } @Override @@ -419,8 +434,8 @@ public MonitorConfig getConfig() { final StepCounter loadExceptionRate = new StepCounter(getMonitorConfig(appName, "loadExceptionRate", DataSourceType.GAUGE)) { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().loadExceptionRate()); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().loadExceptionRate()); } @Override @@ -433,8 +448,8 @@ public Number getValue(int pollerIndex) { final StepCounter averageLoadTime = new StepCounter(getMonitorConfig(appName, "averageLoadTime-ms", DataSourceType.GAUGE)) { @Override public Number getValue() { - if (cache == null) return Long.valueOf(0); - return Double.valueOf(cache.stats().averageLoadPenalty()/1000000); + if (getCache() == null) return Long.valueOf(0); + return Double.valueOf(getStats().averageLoadPenalty()/1000000); } @Override diff --git a/evcache-client/src/main/java/com/netflix/evcache/pool/EVCacheClientPoolManager.java b/evcache-client/src/main/java/com/netflix/evcache/pool/EVCacheClientPoolManager.java index 076c9a2c..5f536432 100644 --- a/evcache-client/src/main/java/com/netflix/evcache/pool/EVCacheClientPoolManager.java +++ b/evcache-client/src/main/java/com/netflix/evcache/pool/EVCacheClientPoolManager.java @@ -12,6 +12,8 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -263,12 +265,17 @@ private String getAppName(String _app) { return app; } + private WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); private final Map> inMemoryMap = new ConcurrentHashMap>(); public EVCacheInMemoryCache createInMemoryCache(String appName, Transcoder tc, EVCacheImpl impl) { EVCacheInMemoryCache cache = (EVCacheInMemoryCache) inMemoryMap.get(appName); if(cache == null) { - cache = new EVCacheInMemoryCache(appName, tc, impl); - inMemoryMap.put(appName, cache); + writeLock.lock(); + if((cache = getInMemoryCache(appName)) == null) { + cache = new EVCacheInMemoryCache(appName, tc, impl); + inMemoryMap.put(appName, cache); + } + writeLock.unlock(); } return cache; }