diff options
Diffstat (limited to 'node-repository')
18 files changed, 40 insertions, 36 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java index ff156751f5e..6fa02d4c1c3 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java @@ -118,7 +118,8 @@ public class NodeRepository extends AbstractComponent { this.db = new CuratorDatabaseClient(flavors, curator, clock, useCuratorClientCache, nodeCacheSize); this.zone = zone; this.clock = clock; - this.nodes = new Nodes(db, zone, clock, orchestrator); + this.applications = new Applications(db); + this.nodes = new Nodes(db, zone, clock, orchestrator, applications); this.flavors = flavors; this.resourcesCalculator = provisionServiceProvider.getHostResourcesCalculator(); this.nameResolver = nameResolver; @@ -128,7 +129,6 @@ public class NodeRepository extends AbstractComponent { this.containerImages = new ContainerImages(containerImage, tenantContainerImage); this.archiveUris = new ArchiveUris(db); this.jobControl = new JobControl(new JobControlFlags(db, flagSource)); - this.applications = new Applications(db); this.loadBalancers = new LoadBalancers(db); this.metricsDb = metricsDb; this.orchestrator = orchestrator; diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java index 2770a382383..2cf6d290dc8 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java @@ -8,6 +8,7 @@ import com.yahoo.transaction.Mutex; import com.yahoo.transaction.NestedTransaction; import com.yahoo.vespa.hosted.provision.persistence.CuratorDatabaseClient; +import java.time.Duration; import java.util.List; import java.util.Optional; @@ -62,4 +63,14 @@ public class Applications { db.deleteApplication(transaction); } + /** Create a lock which provides exclusive rights to making changes to the given application */ + public Mutex lock(ApplicationId application) { + return db.lock(application); + } + + /** Create a lock with a timeout which provides exclusive rights to making changes to the given application */ + public Mutex lock(ApplicationId application, Duration timeout) { + return db.lock(application, timeout); + } + } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java index 466582b88e6..97691c84be8 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java @@ -73,7 +73,7 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer { // Lock and write if there are state updates and/or we should autoscale now if (advice.isPresent() && !cluster.get().targetResources().equals(advice.target()) || (updatedCluster != cluster.get() || !advice.reason().equals(cluster.get().autoscalingStatus()))) { - try (var lock = nodeRepository().nodes().lock(applicationId)) { + try (var lock = nodeRepository().applications().lock(applicationId)) { application = nodeRepository().applications().get(applicationId); if (application.isEmpty()) return; cluster = application.get().cluster(clusterId); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java index b2c3859e33a..a94adc5aaae 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java @@ -107,7 +107,7 @@ class MaintenanceDeployment implements Closeable { Duration timeout = Duration.ofSeconds(3); try { // Use a short lock to avoid interfering with change deployments - return Optional.of(nodeRepository.nodes().lock(application, timeout)); + return Optional.of(nodeRepository.applications().lock(application, timeout)); } catch (ApplicationLockException e) { log.log(Level.INFO, () -> "Could not lock " + application + " for maintenance deployment within " + timeout); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java index 624492a14f3..b602d2ac7cd 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeHealthTracker.java @@ -63,7 +63,7 @@ public class NodeHealthTracker extends NodeRepositoryMaintainer { // Lock and update status ApplicationId owner = node.get().allocation().get().owner(); - try (var lock = nodeRepository().nodes().lock(owner)) { + try (var lock = nodeRepository().applications().lock(owner)) { node = getNode(hostname.toString(), owner, lock); // Re-get inside lock if (node.isEmpty()) return; // Node disappeared or changed allocation attempts.add(1); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java index 9cb5f887e48..531201f9484 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainer.java @@ -64,7 +64,7 @@ public class ScalingSuggestionsMaintainer extends NodeRepositoryMaintainer { var suggestion = autoscaler.suggest(application, cluster.get(), clusterNodes); if (suggestion.isEmpty()) return true; // Wait only a short time for the lock to avoid interfering with change deployments - try (Mutex lock = nodeRepository().nodes().lock(applicationId, Duration.ofSeconds(1))) { + try (Mutex lock = nodeRepository().applications().lock(applicationId, Duration.ofSeconds(1))) { // empty suggested resources == keep the current allocation, so we record that var suggestedResources = suggestion.target().orElse(clusterNodes.not().retired().toResources()); applications().get(applicationId).ifPresent(a -> updateSuggestion(suggestedResources, clusterId, a, lock)); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java index 28cf15f7845..50933951a5f 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java @@ -17,6 +17,7 @@ import com.yahoo.vespa.hosted.provision.NoSuchNodeException; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.NodeMutex; +import com.yahoo.vespa.hosted.provision.applications.Applications; import com.yahoo.vespa.hosted.provision.maintenance.NodeFailer; import com.yahoo.vespa.hosted.provision.node.filter.NodeFilter; import com.yahoo.vespa.hosted.provision.persistence.CuratorDatabaseClient; @@ -61,12 +62,14 @@ public class Nodes { private final Zone zone; private final Clock clock; private final Orchestrator orchestrator; + private final Applications applications; - public Nodes(CuratorDatabaseClient db, Zone zone, Clock clock, Orchestrator orchestrator) { + public Nodes(CuratorDatabaseClient db, Zone zone, Clock clock, Orchestrator orchestrator, Applications applications) { this.zone = zone; this.clock = clock; this.db = db; this.orchestrator = orchestrator; + this.applications = applications; } /** Read and write all nodes to make sure they are stored in the latest version of the serialized format */ @@ -229,7 +232,7 @@ public class Nodes { * @param reusable move the node directly to {@link Node.State#dirty} after removal */ public void setRemovable(ApplicationId application, List<Node> nodes, boolean reusable) { - try (Mutex lock = lock(application)) { + try (Mutex lock = applications.lock(application)) { List<Node> removableNodes = nodes.stream() .map(node -> node.with(node.allocation().get().removable(true, reusable))) .toList(); @@ -723,7 +726,7 @@ public class Nodes { } } for (Map.Entry<ApplicationId, List<Node>> applicationNodes : allocatedNodes.entrySet()) { - try (Mutex lock = lock(applicationNodes.getKey())) { + try (Mutex lock = applications.lock(applicationNodes.getKey())) { for (Node node : applicationNodes.getValue()) { Optional<Node> currentNode = db.readNode(node.hostname()); // Re-read while holding lock if (currentNode.isEmpty()) continue; @@ -759,17 +762,6 @@ public class Nodes { } } - /** Create a lock which provides exclusive rights to making changes to the given application */ - // TODO: Move to Applications - public Mutex lock(ApplicationId application) { - return db.lock(application); - } - - /** Create a lock with a timeout which provides exclusive rights to making changes to the given application */ - public Mutex lock(ApplicationId application, Duration timeout) { - return db.lock(application, timeout); - } - /** Create a lock which provides exclusive rights to modifying unallocated nodes */ public Mutex lockUnallocated() { return db.lockInactive(); } @@ -852,7 +844,8 @@ public class Nodes { case proxyhost -> Optional.of(InfrastructureApplication.PROXY_HOST.id()); }; if (application.isPresent()) - return timeout.map(t -> lock(application.get(), t)).orElseGet(() -> lock(application.get())); + return timeout.map(t -> applications.lock(application.get(), t)) + .orElseGet(() -> applications.lock(application.get())); else return timeout.map(db::lockInactive).orElseGet(db::lockInactive); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java index a8fb0a5e4c2..fbe61c24bf9 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java @@ -98,7 +98,7 @@ public class GroupPreparer { /// Note that this will write to the node repo. private List<Node> prepareWithLocks(ApplicationId application, ClusterSpec cluster, NodeSpec requestedNodes, List<Node> surplusActiveNodes, NodeIndices indices, int wantedGroups) { - try (Mutex lock = nodeRepository.nodes().lock(application); + try (Mutex lock = nodeRepository.applications().lock(application); Mutex allocationLock = nodeRepository.nodes().lockUnallocated()) { NodesAndHosts<LockedNodeList> allNodesAndHosts = NodesAndHosts.create(nodeRepository.nodes().list(allocationLock)); NodeAllocation allocation = prepareAllocation(application, cluster, requestedNodes, surplusActiveNodes, diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImpl.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImpl.java index 53defef6fc7..605ef280c2e 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImpl.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/InfraDeployerImpl.java @@ -89,7 +89,7 @@ public class InfraDeployerImpl implements InfraDeployer { public void prepare() { if (prepared) return; - try (Mutex lock = nodeRepository.nodes().lock(application.getApplicationId())) { + try (Mutex lock = nodeRepository.applications().lock(application.getApplicationId())) { NodeType nodeType = application.getCapacity().type(); Version targetVersion = infrastructureVersions.getTargetVersionFor(nodeType); hostSpecs = provisioner.prepare(application.getApplicationId(), diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index 59063f1ce85..ca483fe27b4 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -139,7 +139,7 @@ public class NodeRepositoryProvisioner implements Provisioner { @Override public ProvisionLock lock(ApplicationId application) { - return new ProvisionLock(application, nodeRepository.nodes().lock(application)); + return new ProvisionLock(application, nodeRepository.applications().lock(application)); } /** @@ -147,7 +147,7 @@ public class NodeRepositoryProvisioner implements Provisioner { * and updates the application store with the received min and max. */ private ClusterResources decideTargetResources(ApplicationId applicationId, ClusterSpec clusterSpec, Capacity requested) { - try (Mutex lock = nodeRepository.nodes().lock(applicationId)) { + try (Mutex lock = nodeRepository.applications().lock(applicationId)) { var application = nodeRepository.applications().get(applicationId).orElse(Application.empty(applicationId)) .withCluster(clusterSpec.id(), clusterSpec.isExclusive(), requested); nodeRepository.applications().put(application, lock); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcher.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcher.java index 7b5146955fb..eee1d364c03 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcher.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcher.java @@ -35,7 +35,7 @@ public class ApplicationPatcher implements AutoCloseable { throw new UncheckedIOException("Error reading request body", e); } // Use same timeout for acquiring lock as client timeout for patch request - this.lock = nodeRepository.nodes().lock(applicationId, Duration.ofSeconds(30)); + this.lock = nodeRepository.applications().lock(applicationId, Duration.ofSeconds(30)); try { this.application = nodeRepository.applications().require(applicationId); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java index 8ba00760905..26e1cd71a3d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java @@ -179,7 +179,7 @@ public class MockNodeRepository extends NodeRepository { clock().instant()))); cluster1 = cluster1.withTarget(Optional.of(new ClusterResources(4, 1, new NodeResources(3, 16, 100, 1)))); - try (Mutex lock = nodes().lock(app1Id)) { + try (Mutex lock = applications().lock(app1Id)) { applications().put(app1.with(cluster1), lock); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java index 3d363e8a96b..e75ef10e689 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java @@ -111,7 +111,7 @@ class AutoscalingTester { } public void deactivateRetired(ApplicationId application, ClusterSpec cluster, Capacity capacity) { - try (Mutex lock = nodeRepository().nodes().lock(application)) { + try (Mutex lock = nodeRepository().applications().lock(application)) { for (Node node : nodeRepository().nodes().list(Node.State.active).owner(application)) { if (node.allocation().get().membership().retired()) nodeRepository().nodes().write(node.with(node.allocation().get().removable(true, true)), lock); @@ -137,14 +137,14 @@ class AutoscalingTester { 0, clock().instant().minus(Duration.ofDays(1).minus(duration))).withCompletion(clock().instant().minus(Duration.ofDays(1)))); application = application.with(cluster); - nodeRepository().applications().put(application, nodeRepository().nodes().lock(applicationId)); + nodeRepository().applications().put(application, nodeRepository().applications().lock(applicationId)); } public Autoscaler.Advice autoscale(ApplicationId applicationId, ClusterSpec cluster, Capacity capacity) { capacity = capacityPolicies.applyOn(capacity, applicationId, capacityPolicies.decideExclusivity(capacity, cluster.isExclusive())); Application application = nodeRepository().applications().get(applicationId).orElse(Application.empty(applicationId)) .withCluster(cluster.id(), false, capacity); - try (Mutex lock = nodeRepository().nodes().lock(applicationId)) { + try (Mutex lock = nodeRepository().applications().lock(applicationId)) { nodeRepository().applications().put(application, lock); } return autoscaler.autoscale(application, application.clusters().get(cluster.id()), @@ -155,7 +155,7 @@ class AutoscalingTester { ClusterResources min, ClusterResources max) { Application application = nodeRepository().applications().get(applicationId).orElse(Application.empty(applicationId)) .withCluster(clusterId, false, Capacity.from(min, max)); - try (Mutex lock = nodeRepository().nodes().lock(applicationId)) { + try (Mutex lock = nodeRepository().applications().lock(applicationId)) { nodeRepository().applications().put(application, lock); } return autoscaler.suggest(application, application.clusters().get(clusterId), diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java index 4c7f26f9396..35881c59c5e 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Fixture.java @@ -113,7 +113,7 @@ public class Fixture { var application = application(); application = application.with(application.status().withCurrentReadShare(currentReadShare) .withMaxReadShare(maxReadShare)); - tester.nodeRepository().applications().put(application, tester.nodeRepository().nodes().lock(applicationId)); + tester.nodeRepository().applications().put(application, tester.nodeRepository().applications().lock(applicationId)); } public static class Builder { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/MetricsV2MetricsFetcherTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/MetricsV2MetricsFetcherTest.java index 41851f6888e..e83880404f4 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/MetricsV2MetricsFetcherTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/MetricsV2MetricsFetcherTest.java @@ -81,7 +81,7 @@ public class MetricsV2MetricsFetcherTest { { httpClient.cannedResponse = cannedResponseForApplication2; - try (Mutex lock = tester.nodeRepository().nodes().lock(application1)) { + try (Mutex lock = tester.nodeRepository().applications().lock(application1)) { tester.nodeRepository().nodes().write(tester.nodeRepository().nodes().list(Node.State.active).owner(application2) .first().get().retire(tester.clock().instant()), lock); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java index faf3f60e8af..a7c4e8ecd7a 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java @@ -250,7 +250,7 @@ public class ProvisioningTester { } public void deactivate(ApplicationId applicationId) { - try (var lock = nodeRepository.nodes().lock(applicationId)) { + try (var lock = nodeRepository.applications().lock(applicationId)) { NestedTransaction deactivateTransaction = new NestedTransaction(); nodeRepository.remove(new ApplicationTransaction(new ProvisionLock(applicationId, lock), deactivateTransaction)); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java index 7728e0ac9c8..aaef785704d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java @@ -599,7 +599,7 @@ public class VirtualNodeProvisioningTest { tester.activate(app1, cluster1, Capacity.from(new ClusterResources(5, 1, r))); tester.activate(app1, cluster1, Capacity.from(new ClusterResources(2, 1, r))); - var tx = new ApplicationTransaction(new ProvisionLock(app1, tester.nodeRepository().nodes().lock(app1)), new NestedTransaction()); + var tx = new ApplicationTransaction(new ProvisionLock(app1, tester.nodeRepository().applications().lock(app1)), new NestedTransaction()); tester.nodeRepository().nodes().deactivate(tester.nodeRepository().nodes().list(Node.State.active).owner(app1).retired().asList(), tx); tx.nested().commit(); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcherTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcherTest.java index 244bb40b2bf..79722a747e2 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcherTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/ApplicationPatcherTest.java @@ -20,7 +20,7 @@ public class ApplicationPatcherTest { public void testPatching() { NodeRepositoryTester tester = new NodeRepositoryTester(); Application application = Application.empty(ApplicationId.from("t1", "a1", "i1")); - tester.nodeRepository().applications().put(application, tester.nodeRepository().nodes().lock(application.id())); + tester.nodeRepository().applications().put(application, tester.nodeRepository().applications().lock(application.id())); String patch = "{ \"currentReadShare\" :0.4, \"maxReadShare\": 1.0 }"; ApplicationPatcher patcher = new ApplicationPatcher(new ByteArrayInputStream(patch.getBytes()), application.id(), |