diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2018-05-31 22:07:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-31 22:07:40 +0200 |
commit | d1e6b20cc515c9fac69d2349cb0c59fa6d2fff2a (patch) | |
tree | 8cefb569e3875aef62515dd56216f67711f8efaf /node-repository | |
parent | c25b13dc55b3aee0365a792553b2bfe0b782ad60 (diff) | |
parent | ce44a54179768c8e3f0675e8ce3a8d9bd5e9f12e (diff) |
Merge pull request #6031 from vespa-engine/balder/ensure-we-only-create-one-new-cache
Ensure we do not race on cache creation and create many caches that w…
Diffstat (limited to 'node-repository')
-rw-r--r-- | node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabase.java | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabase.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabase.java index 12a0496ed2e..203f52a7b70 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabase.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabase.java @@ -38,6 +38,8 @@ public class CuratorDatabase { /** Whether we should return data from the cache or always read fro ZooKeeper */ private final boolean useCache; + private final Object cacheCreationLock = new Object(); + /** * All keys, to allow reentrancy. * This will grow forever with the number of applications seen, but this should be too slow to be a problem. @@ -94,14 +96,42 @@ public class CuratorDatabase { public Optional<byte[]> getData(Path path) { return getCache().getData(path); } + private static class CacheAndGeneration { + public CacheAndGeneration(CuratorDatabaseCache cache, long generation) + { + this.cache = cache; + this.generation = generation; + } + public boolean expired() { + return generation != cache.generation(); + } + public CuratorDatabaseCache validCache() { + if (expired()) { + throw new IllegalStateException("The cache has generation " + cache.generation() + + " while the root genration counter in zookeeper says " + generation + + ". That is totally unacceptable and must be a sever programming error in my close vicinity."); + } + return cache; + } + + private CuratorDatabaseCache cache; + private long generation; + } + private CacheAndGeneration getCacheSnapshot() { + return new CacheAndGeneration(cache.get(), changeGenerationCounter.get()); + } private CuratorDatabaseCache getCache() { - CuratorDatabaseCache cache = this.cache.get(); - long currentCuratorGeneration = changeGenerationCounter.get(); - if (currentCuratorGeneration != cache.generation()) { // current cache is invalid - start new - cache = newCache(currentCuratorGeneration); - this.cache.set(cache); + CacheAndGeneration cacheAndGeneration = getCacheSnapshot(); + while (cacheAndGeneration.expired()) { + synchronized (cacheCreationLock) { // Prevent a race for creating new caches + cacheAndGeneration = getCacheSnapshot(); + if (cacheAndGeneration.expired()) { + cache.set(newCache(changeGenerationCounter.get())); + cacheAndGeneration = getCacheSnapshot(); + } + } } - return cache; + return cacheAndGeneration.validCache(); } /** Caches must only be instantiated using this method */ |