summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabase.java42
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java9
2 files changed, 44 insertions, 7 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 */
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java
index 6d92f9c4541..bea7973541a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java
@@ -1,6 +1,8 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.restapi.v2.filter;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId;
@@ -11,6 +13,7 @@ import com.yahoo.vespa.hosted.provision.NodeRepository;
import java.security.cert.X509Certificate;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static com.yahoo.vespa.athenz.tls.SubjectAlternativeName.Type.DNS_NAME;
@@ -31,9 +34,13 @@ class NodeIdentifier {
private final Zone zone;
private final NodeRepository nodeRepository;
+
+ private final Supplier<List<Node>> nodeCache;
+
NodeIdentifier(Zone zone, NodeRepository nodeRepository) {
this.zone = zone;
this.nodeRepository = nodeRepository;
+ nodeCache = Suppliers.memoizeWithExpiration(nodeRepository::getNodes, 1, TimeUnit.MINUTES);
}
NodePrincipal resolveNode(List<X509Certificate> certificateChain) throws NodeIdentifierException {
@@ -73,7 +80,7 @@ class NodeIdentifier {
private String getHostFromCalypsoCertificate(List<SubjectAlternativeName> sans) {
String openstackId = getUniqueInstanceId(sans);
- return nodeRepository.getNodes().stream()
+ return nodeCache.get().stream()
.filter(node -> node.openStackId().equals(openstackId))
.map(Node::hostname)
.findFirst()