/* * Copyright 2012 NGDATA nv * * Licensed 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.lilyproject.client.integration; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import org.junit.Test; import org.lilyproject.client.LilyClient; import org.lilyproject.util.io.Closer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; /** * This test verifies that we have the expected number of ZooKeeper connections at any time. * * <p>We test the presence of ZK connections by looking if there are any threads with the * typical ZooKeeper name.</p> * * <p>This is implemented as an integration test, since if the Hadoop/Lily stack would be * started embedded, there would be extra ZK connections which would be hard to * distinguish from those set up by LilyClient.</p> * */ public class ZkConnectionTest { // For each ZK client, there are two threads, one with "-EventThread" in the name, // and one with "-SendThread" in the name. We arbitrarily use one of these. private static final String ZK_THREAD_MARKER = "-SendThread"; @Test public void testZkConnectionsGoneAfterLilyClientStop() throws Exception { // At this point, there should be no running ZK threads checkNoZkThread(); LilyClient lilyClient = new LilyClient(System.getProperty("zkConn", "localhost:2181"), 20000); // Lily client is started, there should be (at least one) ZK thread checkZkThread(); //System.out.println("Before close:"); //printAllZkThreads(); Closer.close(lilyClient); // We can't rely on threads being closed immediately int patience = 10; while (countZkThreads() > 0 && patience > 0) { Thread.sleep(1000); patience--; } //System.out.println("After close:"); //printAllZkThreads(); // Lily client is stopped, ZK threads should have been closed checkNoZkThread(); } @Test public void testZkConnectionCount() throws Exception { // At this point, there should be no running ZK threads checkNoZkThread(); LilyClient lilyClient = new LilyClient(System.getProperty("zkConn", "localhost:2181"), 20000); // What number of ZK connections we expect? // 1 for Lily // 1 for HBase (connection used for direct ops such as scanning, blobs) // [not applicable anymore since CDH3u4] 1 for HBaseAdmin int threadCnt = countZkThreads(); assertEquals(2, threadCnt); Closer.close(lilyClient); } private void checkNoZkThread() { String name = findZkThread(); if (name != null) { fail("Found running ZooKeeper thread: " + name); } } private void checkZkThread() { String name = findZkThread(); if (name == null) { fail("Found NO running ZooKeeper thread."); } } private String findZkThread() { ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); long[] threadIds = threadBean.getAllThreadIds(); for (long tid: threadIds) { ThreadInfo info = threadBean.getThreadInfo(tid); String name = info.getThreadName(); if (name.contains(ZK_THREAD_MARKER)) { return name; } } return null; } private int countZkThreads() { ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); long[] threadIds = threadBean.getAllThreadIds(); int count = 0; for (long tid: threadIds) { ThreadInfo info = threadBean.getThreadInfo(tid); if (info == null) { continue; } String name = info.getThreadName(); if (name.contains(ZK_THREAD_MARKER)) { count++; } } return count; } private void printAllZkThreads() { ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); long[] threadIds = threadBean.getAllThreadIds(); for (long tid: threadIds) { ThreadInfo info = threadBean.getThreadInfo(tid); String name = info.getThreadName(); if (name.contains(ZK_THREAD_MARKER)) { System.out.println(name); } } } }