summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java57
-rw-r--r--zkfacade/src/main/java/com/yahoo/vespa/curator/Lock.java3
-rw-r--r--zkfacade/src/main/java/com/yahoo/vespa/curator/MultiplePathsLock.java41
3 files changed, 88 insertions, 13 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
index 6eaad63251c..94d60432337 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
@@ -14,6 +14,7 @@ import com.yahoo.slime.Slime;
import com.yahoo.slime.SlimeUtils;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.Lock;
+import com.yahoo.vespa.curator.MultiplePathsLock;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveBucket;
@@ -143,20 +144,21 @@ public class CuratorDb {
return curator.lock(lockPath(name), defaultLockTimeout.multipliedBy(2));
}
+ // TODO: Remove MultiplePathsLock and use of legacyLockPath() methods after 7.752 has been rolled out
public Lock lock(TenantAndApplicationId id) {
- return curator.lock(lockPath(id), defaultLockTimeout.multipliedBy(2));
+ return new MultiplePathsLock(lockPath(id), legacyLockPath(id), defaultLockTimeout.multipliedBy(2),curator);
}
public Lock lockForDeployment(ApplicationId id, ZoneId zone) {
- return curator.lock(lockPath(id, zone), deployLockTimeout);
+ return new MultiplePathsLock(lockPath(id, zone), legacyLockPath(id, zone), deployLockTimeout, curator);
}
public Lock lock(ApplicationId id, JobType type) {
- return curator.lock(lockPath(id, type), defaultLockTimeout);
+ return new MultiplePathsLock(lockPath(id, type), legacyLockPath(id, type), defaultLockTimeout, curator);
}
public Lock lock(ApplicationId id, JobType type, Step step) throws TimeoutException {
- return tryLock(lockPath(id, type, step));
+ return tryLock(lockPath(id, type, step), legacyLockPath(id, type, step));
}
public Lock lockRotations() {
@@ -239,6 +241,19 @@ public class CuratorDb {
}
}
+ /** Try locking with a low timeout, meaning it is OK to fail lock acquisition.
+ *
+ * Useful for maintenance jobs, where there is no point in running the jobs back to back.
+ */
+ private Lock tryLock(Path path, Path path2) throws TimeoutException {
+ try {
+ return new MultiplePathsLock(path, path2, tryLockTimeout, curator);
+ }
+ catch (UncheckedTimeoutException e) {
+ throw new TimeoutException(e.getMessage());
+ }
+ }
+
private <T> Optional<T> read(Path path, Function<byte[], T> mapper) {
return curator.getData(path).filter(data -> data.length > 0).map(mapper);
}
@@ -667,32 +682,48 @@ public class CuratorDb {
.append(tenant.value());
}
- private Path lockPath(TenantAndApplicationId application) {
+ private Path legacyLockPath(TenantAndApplicationId application) {
return lockPath(application.tenant())
.append(application.application().value());
}
- private Path lockPath(ApplicationId instance) {
- return lockPath(TenantAndApplicationId.from(instance))
+ private Path legacyLockPath(ApplicationId instance) {
+ return legacyLockPath(TenantAndApplicationId.from(instance))
.append(instance.instance().value());
}
- private Path lockPath(ApplicationId instance, ZoneId zone) {
- return lockPath(instance)
+ private Path legacyLockPath(ApplicationId instance, ZoneId zone) {
+ return legacyLockPath(instance)
.append(zone.environment().value())
.append(zone.region().value());
}
- private Path lockPath(ApplicationId instance, JobType type) {
- return lockPath(instance)
+ private Path legacyLockPath(ApplicationId instance, JobType type) {
+ return legacyLockPath(instance)
.append(type.jobName());
}
- private Path lockPath(ApplicationId instance, JobType type, Step step) {
- return lockPath(instance, type)
+ private Path legacyLockPath(ApplicationId instance, JobType type, Step step) {
+ return legacyLockPath(instance, type)
.append(step.name());
}
+ private Path lockPath(TenantAndApplicationId application) {
+ return lockRoot.append(application.tenant().value() + ":" + application.application().value());
+ }
+
+ private Path lockPath(ApplicationId instance, ZoneId zone) {
+ return lockRoot.append(instance.serializedForm() + ":" + zone.region().value());
+ }
+
+ private Path lockPath(ApplicationId instance, JobType type) {
+ return lockRoot.append(instance.serializedForm() + ":" + type.jobName());
+ }
+
+ private Path lockPath(ApplicationId instance, JobType type, Step step) {
+ return lockRoot.append(instance.serializedForm() + ":" + type.jobName() + ":" + step.name());
+ }
+
private Path lockPath(String provisionId) {
return lockRoot
.append(provisionStatePath())
diff --git a/zkfacade/src/main/java/com/yahoo/vespa/curator/Lock.java b/zkfacade/src/main/java/com/yahoo/vespa/curator/Lock.java
index 56ae65bb317..3f9c52594a3 100644
--- a/zkfacade/src/main/java/com/yahoo/vespa/curator/Lock.java
+++ b/zkfacade/src/main/java/com/yahoo/vespa/curator/Lock.java
@@ -69,6 +69,9 @@ public class Lock implements Mutex {
throw new RuntimeException("Exception releasing lock '" + lockPath + "'");
}
}
+
+ protected String lockPath() { return lockPath; }
+
}
diff --git a/zkfacade/src/main/java/com/yahoo/vespa/curator/MultiplePathsLock.java b/zkfacade/src/main/java/com/yahoo/vespa/curator/MultiplePathsLock.java
new file mode 100644
index 00000000000..65ae77c8ffa
--- /dev/null
+++ b/zkfacade/src/main/java/com/yahoo/vespa/curator/MultiplePathsLock.java
@@ -0,0 +1,41 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.curator;
+
+import com.yahoo.concurrent.UncheckedTimeoutException;
+import com.yahoo.path.Path;
+
+import java.time.Duration;
+
+/**
+ * Class that holds two locks, originally used for transitioning from one lock to
+ * another, where you need to hold both the old lock and the new lock in the
+ * transition period.
+ *
+ * @author hmusum
+ */
+public class MultiplePathsLock extends Lock {
+
+ private final Lock oldLock;
+ private final Lock newLock;
+
+ public MultiplePathsLock(Path newLockPath, Path oldLockPath, Duration timeout, Curator curator) {
+ super(newLockPath.getAbsolute(), curator);
+ this.newLock = curator.lock(newLockPath, timeout);
+ this.oldLock = curator.lock(oldLockPath, timeout);;
+ }
+
+ @Override
+ public void acquire(Duration timeout) throws UncheckedTimeoutException {
+ oldLock.acquire(timeout);
+ newLock.acquire(timeout);
+ }
+
+ @Override
+ public void close() {
+ oldLock.close();
+ newLock.close();
+ }
+
+}
+
+