diff options
Diffstat (limited to 'node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java')
-rw-r--r-- | node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java index 8ecdb0cbb1f..6036cc2366f 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java @@ -62,6 +62,7 @@ public class CuratorDatabaseClient { private static final Path root = Path.fromString("/provision/v1"); private static final Path lockRoot = root.append("locks"); + private static final Path configLockRoot = Path.fromString("/config/v2/locks/"); private static final Path loadBalancersRoot = root.append("loadBalancers"); private static final Duration defaultLockTimeout = Duration.ofMinutes(2); @@ -312,7 +313,7 @@ public class CuratorDatabaseClient { return root.append(toDir(nodeState)).append(nodeName); } - /** Creates an returns the path to the lock for this application */ + /** Creates and returns the path to the lock for this application */ private Path lockPath(ApplicationId application) { Path lockPath = lockRoot @@ -323,6 +324,14 @@ public class CuratorDatabaseClient { return lockPath; } + /** Creates and returns the path to the config server lock for this application */ + private Path configLockPath(ApplicationId application) { + // This must match the lock path used by com.yahoo.vespa.config.server.application.TenantApplications + Path lockPath = configLockRoot.append(application.tenant().value()).append(application.serializedForm()); + curatorDatabase.create(lockPath); + return lockPath; + } + private String toDir(Node.State state) { switch (state) { case active: return "allocated"; // legacy name @@ -358,6 +367,28 @@ public class CuratorDatabaseClient { } } + /** + * Acquires the single cluster-global, re-entrant config lock for given application. Note that this is the same lock + * that configserver itself takes when modifying applications. + * + * This lock must be taken when writes to paths owned by this class may happen on both the configserver and + * node-repository side. This behaviour is obviously wrong, but since we pass a NestedTransaction across the + * configserver and node-repository boundary, the ownership semantics of the transaction (and its operations) + * becomes unclear. + * + * Example of when to use: The config server creates a new transaction and passes the transaction to + * {@link com.yahoo.vespa.hosted.provision.provisioning.NodeRepositoryProvisioner}, which appends operations to the + * transaction. The config server then commits (writes) the transaction which may include operations that modify + * data in paths owned by this class. + */ + public Lock lockConfig(ApplicationId application) { + try { + return lock(configLockPath(application), defaultLockTimeout); + } catch (UncheckedTimeoutException e) { + throw new ApplicationLockException(e); + } + } + private Lock lock(Path path, Duration timeout) { return curatorDatabase.lock(path, timeout); } @@ -525,6 +556,7 @@ public class CuratorDatabaseClient { transaction.commit(); } + // TODO(mpolden): Remove this and usages after April 2020 public Lock lockLoadBalancers(ApplicationId application) { return lock(lockRoot.append("loadBalancersLock2").append(application.serializedForm()), defaultLockTimeout); } |