/** * 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.zookeeper.test; import java.io.IOException; import java.util.Date; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.ZooDefs.Ids; import org.junit.Assert; import org.junit.Test; public class ClientHammerTest extends ClientBase { protected static final Logger LOG = LoggerFactory.getLogger(ClientHammerTest.class); private static final long HAMMERTHREAD_LATENCY = 5; private static abstract class HammerThread extends Thread { protected final int count; protected volatile int current = 0; HammerThread(String name, int count) { super(name); this.count = count; } } private static class BasicHammerThread extends HammerThread { private final ZooKeeper zk; private final String prefix; BasicHammerThread(String name, ZooKeeper zk, String prefix, int count) { super(name, count); this.zk = zk; this.prefix = prefix; } public void run() { byte b[] = new byte[256]; try { for (; current < count; current++) { // Simulate a bit of network latency... Thread.sleep(HAMMERTHREAD_LATENCY); zk.create(prefix + current, b, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (Throwable t) { LOG.error("Client create operation Assert.failed", t); } finally { try { zk.close(); } catch (InterruptedException e) { LOG.warn("Unexpected", e); } } } } private static class SuperHammerThread extends HammerThread { private final ClientHammerTest parent; private final String prefix; SuperHammerThread(String name, ClientHammerTest parent, String prefix, int count) { super(name, count); this.parent = parent; this.prefix = prefix; } public void run() { byte b[] = new byte[256]; try { for (; current < count; current++) { ZooKeeper zk = parent.createClient(); try { zk.create(prefix + current, b, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } finally { try { zk.close(); } catch (InterruptedException e) { LOG.warn("Unexpected", e); } } } } catch (Throwable t) { LOG.error("Client create operation Assert.failed", t); } } } /** * Separate threads each creating a number of nodes. Each thread * is using a non-shared (owned by thread) client for all node creations. * @throws Throwable */ @Test public void testHammerBasic() throws Throwable { runHammer(10, 1000); } public void runHammer(final int threadCount, final int childCount) throws Throwable { try { HammerThread[] threads = new HammerThread[threadCount]; long start = System.currentTimeMillis(); for (int i = 0; i < threads.length; i++) { ZooKeeper zk = createClient(); String prefix = "/test-" + i; zk.create(prefix, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); prefix += "/"; HammerThread thread = new BasicHammerThread("BasicHammerThread-" + i, zk, prefix, childCount); thread.start(); threads[i] = thread; } verifyHammer(start, threads, childCount); } catch (Throwable t) { LOG.error("test Assert.failed", t); throw t; } } /** * Separate threads each creating a number of nodes. Each thread * is creating a new client for each node creation. * @throws Throwable */ @Test public void testHammerSuper() throws Throwable { try { final int threadCount = 5; final int childCount = 10; HammerThread[] threads = new HammerThread[threadCount]; long start = System.currentTimeMillis(); for (int i = 0; i < threads.length; i++) { String prefix = "/test-" + i; { ZooKeeper zk = createClient(); try { zk.create(prefix, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } finally { zk.close(); } } prefix += "/"; HammerThread thread = new SuperHammerThread("SuperHammerThread-" + i, this, prefix, childCount); thread.start(); threads[i] = thread; } verifyHammer(start, threads, childCount); } catch (Throwable t) { LOG.error("test Assert.failed", t); throw t; } } public void verifyHammer(long start, HammerThread[] threads, int childCount) throws IOException, InterruptedException, KeeperException { // look for the clients to finish their create operations LOG.info("Starting check for completed hammers"); int workingCount = threads.length; for (int i = 0; i < 120; i++) { Thread.sleep(10000); for (HammerThread h : threads) { if (!h.isAlive() || h.current == h.count) { workingCount--; } } if (workingCount == 0) { break; } workingCount = threads.length; } if (workingCount > 0) { for (HammerThread h : threads) { LOG.warn(h.getName() + " never finished creation, current:" + h.current); } } else { LOG.info("Hammer threads completed creation operations"); } for (HammerThread h : threads) { final int safetyFactor = 3; verifyThreadTerminated(h, threads.length * childCount * HAMMERTHREAD_LATENCY * safetyFactor); } LOG.info(new Date() + " Total time " + (System.currentTimeMillis() - start)); ZooKeeper zk = createClient(); try { LOG.info("******************* Connected to ZooKeeper" + new Date()); for (int i = 0; i < threads.length; i++) { LOG.info("Doing thread: " + i + " " + new Date()); List<String> children = zk.getChildren("/test-" + i, false); Assert.assertEquals(childCount, children.size()); children = zk.getChildren("/test-" + i, false, null); Assert.assertEquals(childCount, children.size()); } for (int i = 0; i < threads.length; i++) { List<String> children = zk.getChildren("/test-" + i, false); Assert.assertEquals(childCount, children.size()); children = zk.getChildren("/test-" + i, false, null); Assert.assertEquals(childCount, children.size()); } } finally { zk.close(); } } }