CuratorDatabaseClient { public Lock lock(ApplicationId application) { return lock(application, defaultLockTimeout); } CuratorDatabaseClient(NodeFlavors flavors, Curator curator, Clock clock, Zone zone, boolean useCache,
                                 long nodeCacheSize); List<String> cluster(); List<Node> addNodesInState(List<Node> nodes, Node.State expectedState, Agent agent); void removeNodes(List<Node> nodes); List<Node> writeTo(List<Node> nodes, Agent agent, Optional<String> reason); List<Node> writeTo(Node.State toState, List<Node> nodes,
                              Agent agent, Optional<String> reason); Node writeTo(Node.State toState, Node node, Agent agent, Optional<String> reason); List<Node> writeTo(Node.State toState, List<Node> nodes,
                              Agent agent, Optional<String> reason,
                              NestedTransaction transaction); List<Node> readNodes(Node.State ... states); List<Node> readNodes(ApplicationId applicationId, Node.State ... states); Optional<Node> readNode(CuratorDatabase.Session session, String hostname, Node.State ... states); Optional<Node> readNode(String hostname, Node.State ... states); Lock lockInactive(); Lock lock(ApplicationId application); Lock lock(ApplicationId application, Duration timeout); Lock configLock(ApplicationId application); List<ApplicationId> readApplicationIds(); Optional<Application> readApplication(ApplicationId id); void writeApplication(Application application, NestedTransaction transaction); void deleteApplication(ApplicationId application, NestedTransaction transaction); Lock lockMaintenanceJob(String jobName); Map<NodeType, Version> readInfrastructureVersions(); void writeInfrastructureVersions(Map<NodeType, Version> infrastructureVersions); Lock lockInfrastructureVersions(); OsVersionChange readOsVersionChange(); void writeOsVersionChange(OsVersionChange change); Lock lockOsVersionChange(); Map<NodeType, DockerImage> readDockerImages(); void writeDockerImages(Map<NodeType, DockerImage> dockerImages); Lock lockDockerImages(); void writeFirmwareCheck(Optional<Instant> after); Optional<Instant> readFirmwareCheck(); List<LoadBalancerId> readLoadBalancerIds(); Map<LoadBalancerId, LoadBalancer> readLoadBalancers(Predicate<LoadBalancerId> filter); Optional<LoadBalancer> readLoadBalancer(LoadBalancerId id); void writeLoadBalancer(LoadBalancer loadBalancer); void writeLoadBalancers(Collection<LoadBalancer> loadBalancers, NestedTransaction transaction); void removeLoadBalancer(LoadBalancerId loadBalancer); List<Integer> getProvisionIndexes(int numIndexes); CacheStats cacheStats(); CacheStats nodeSerializerCacheStats();  }
@Test public void locks_can_be_acquired_and_released() { ApplicationId app = ApplicationId.from(TenantName.from("testTenant"), ApplicationName.from("testApp"), InstanceName.from("testInstance")); try (var ignored = zkClient.lock(app)) { throw new RuntimeException(); } catch (RuntimeException expected) { } try (var ignored = zkClient.lock(app)) { } try (var ignored = zkClient.lock(app)) { } }