/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.flink.runtime.zookeeper; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.test.TestingCluster; import org.apache.curator.test.TestingServer; import org.apache.curator.utils.ZKPaths; import org.apache.flink.configuration.Configuration; import org.apache.flink.configuration.HighAvailabilityOptions; import org.apache.flink.runtime.util.ZooKeeperUtils; import org.apache.zookeeper.KeeperException; import java.util.List; /** * Simple ZooKeeper and CuratorFramework setup for tests. */ public class ZooKeeperTestEnvironment { private final TestingServer zooKeeperServer; private final TestingCluster zooKeeperCluster; private final CuratorFramework client; /** * Starts a ZooKeeper cluster with the number of quorum peers and a client. * * @param numberOfZooKeeperQuorumPeers Starts a {@link TestingServer}, if <code>1</code>. * Starts a {@link TestingCluster}, if <code>=>1</code>. */ public ZooKeeperTestEnvironment(int numberOfZooKeeperQuorumPeers) { if (numberOfZooKeeperQuorumPeers <= 0) { throw new IllegalArgumentException("Number of peers needs to be >= 1."); } final Configuration conf = new Configuration(); try { if (numberOfZooKeeperQuorumPeers == 1) { zooKeeperServer = new TestingServer(true); zooKeeperCluster = null; conf.setString(HighAvailabilityOptions.HA_ZOOKEEPER_QUORUM, zooKeeperServer.getConnectString()); } else { zooKeeperServer = null; zooKeeperCluster = new TestingCluster(numberOfZooKeeperQuorumPeers); zooKeeperCluster.start(); conf.setString(HighAvailabilityOptions.HA_ZOOKEEPER_QUORUM, zooKeeperCluster.getConnectString()); } client = ZooKeeperUtils.startCuratorFramework(conf); client.newNamespaceAwareEnsurePath("/") .ensure(client.getZookeeperClient()); } catch (Exception e) { throw new RuntimeException("Error setting up ZooKeeperTestEnvironment", e); } } /** * Shutdown the client and ZooKeeper server/cluster. */ public void shutdown() throws Exception { if (client != null) { client.close(); } if (zooKeeperServer != null) { zooKeeperServer.close(); } if (zooKeeperCluster != null) { zooKeeperCluster.close(); } } public String getConnectString() { if (zooKeeperServer != null) { return zooKeeperServer.getConnectString(); } else { return zooKeeperCluster.getConnectString(); } } /** * Returns a client for the started ZooKeeper server/cluster. */ public CuratorFramework getClient() { return client; } public String getClientNamespace() { return client.getNamespace(); } public List<String> getChildren(String path) throws Exception { return client.getChildren().forPath(path); } /** * Creates a new client for the started ZooKeeper server/cluster. */ public CuratorFramework createClient() { Configuration config = new Configuration(); config.setString(HighAvailabilityOptions.HA_ZOOKEEPER_QUORUM, getConnectString()); return ZooKeeperUtils.startCuratorFramework(config); } /** * Deletes all ZNodes under the root node. * * @throws Exception If the ZooKeeper operation fails */ public void deleteAll() throws Exception { final String path = "/" + client.getNamespace(); int maxAttempts = 10; for (int i = 0; i < maxAttempts; i++) { try { ZKPaths.deleteChildren(client.getZookeeperClient().getZooKeeper(), path, false); return; } catch (org.apache.zookeeper.KeeperException.NoNodeException e) { // that seems all right. if one of the children we want to delete is // actually already deleted, that's fine. return; } catch (KeeperException.ConnectionLossException e) { // Keep retrying Thread.sleep(100); } } throw new Exception("Could not clear the ZNodes under " + path + ". ZooKeeper is not in " + "a clean state."); } }