/** * Copyright 2007 The Apache Software Foundation * * 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.hadoop.hbase; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.client.HConnectionManager; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.util.FSUtils; import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster; import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.util.ReflectionUtils; /** * Abstract base class for HBase cluster junit tests. Spins up an hbase * cluster in setup and tears it down again in tearDown. * @deprecated Use junit4 and {@link HBaseTestingUtility} */ public abstract class HBaseClusterTestCase extends HBaseTestCase { private static final Log LOG = LogFactory.getLog(HBaseClusterTestCase.class); public MiniHBaseCluster cluster; protected MiniDFSCluster dfsCluster; protected MiniZooKeeperCluster zooKeeperCluster; protected int regionServers; protected boolean startDfs; private boolean openMetaTable = true; /** default constructor */ public HBaseClusterTestCase() { this(1); } /** * Start a MiniHBaseCluster with regionServers region servers in-process to * start with. Also, start a MiniDfsCluster before starting the hbase cluster. * The configuration used will be edited so that this works correctly. * @param regionServers number of region servers to start. */ public HBaseClusterTestCase(int regionServers) { this(regionServers, true); } /** in-process to * start with. Optionally, startDfs indicates if a MiniDFSCluster should be * started. If startDfs is false, the assumption is that an external DFS is * configured in hbase-site.xml and is already started, or you have started a * MiniDFSCluster on your own and edited the configuration in memory. (You * can modify the config used by overriding the preHBaseClusterSetup method.) * @param regionServers number of region servers to start. * @param startDfs set to true if MiniDFS should be started */ public HBaseClusterTestCase(int regionServers, boolean startDfs) { super(); this.startDfs = startDfs; this.regionServers = regionServers; } protected void setOpenMetaTable(boolean val) { openMetaTable = val; } /** * Subclass hook. * * Run after dfs is ready but before hbase cluster is started up. */ protected void preHBaseClusterSetup() throws Exception { // continue } /** * Actually start the MiniHBase instance. */ protected void hBaseClusterSetup() throws Exception { File testDir = new File(getUnitTestdir(getName()).toString()); if (testDir.exists()) testDir.delete(); // Note that this is done before we create the MiniHBaseCluster because we // need to edit the config to add the ZooKeeper servers. this.zooKeeperCluster = new MiniZooKeeperCluster(); int clientPort = this.zooKeeperCluster.startup(testDir); conf.set("hbase.zookeeper.property.clientPort", Integer.toString(clientPort)); Configuration c = new Configuration(this.conf); // start the mini cluster this.cluster = new MiniHBaseCluster(c, regionServers); if (openMetaTable) { // opening the META table ensures that cluster is running new HTable(c, HConstants.META_TABLE_NAME); } } /** * Run after hbase cluster is started up. */ protected void postHBaseClusterSetup() throws Exception { // continue } @Override protected void setUp() throws Exception { try { if (this.startDfs) { // This spews a bunch of warnings about missing scheme. TODO: fix. this.dfsCluster = new MiniDFSCluster(0, this.conf, 2, true, true, true, null, null, null, null); // mangle the conf so that the fs parameter points to the minidfs we // just started up FileSystem filesystem = dfsCluster.getFileSystem(); conf.set("fs.defaultFS", filesystem.getUri().toString()); Path parentdir = filesystem.getHomeDirectory(); conf.set(HConstants.HBASE_DIR, parentdir.toString()); filesystem.mkdirs(parentdir); FSUtils.setVersion(filesystem, parentdir); } // do the super setup now. if we had done it first, then we would have // gotten our conf all mangled and a local fs started up. super.setUp(); // run the pre-cluster setup preHBaseClusterSetup(); // start the instance hBaseClusterSetup(); // run post-cluster setup postHBaseClusterSetup(); } catch (Exception e) { LOG.error("Exception in setup!", e); if (cluster != null) { cluster.shutdown(); } if (zooKeeperCluster != null) { zooKeeperCluster.shutdown(); } if (dfsCluster != null) { shutdownDfs(dfsCluster); } throw e; } } @Override protected void tearDown() throws Exception { if (!openMetaTable) { // open the META table now to ensure cluster is running before shutdown. new HTable(conf, HConstants.META_TABLE_NAME); } super.tearDown(); try { HConnectionManager.deleteConnection(conf, true); if (this.cluster != null) { try { this.cluster.shutdown(); } catch (Exception e) { LOG.warn("Closing mini dfs", e); } try { this.zooKeeperCluster.shutdown(); } catch (IOException e) { LOG.warn("Shutting down ZooKeeper cluster", e); } } if (startDfs) { shutdownDfs(dfsCluster); } } catch (Exception e) { LOG.error(e); } // ReflectionUtils.printThreadInfo(new PrintWriter(System.out), // "Temporary end-of-test thread dump debugging HADOOP-2040: " + getName()); } /** * Use this utility method debugging why cluster won't go down. On a * period it throws a thread dump. Method ends when all cluster * regionservers and master threads are no long alive. */ public void threadDumpingJoin() { if (this.cluster.getRegionServerThreads() != null) { for(Thread t: this.cluster.getRegionServerThreads()) { threadDumpingJoin(t); } } threadDumpingJoin(this.cluster.getMaster()); } protected void threadDumpingJoin(final Thread t) { if (t == null) { return; } long startTime = System.currentTimeMillis(); while (t.isAlive()) { try { Thread.sleep(1000); } catch (InterruptedException e) { LOG.info("Continuing...", e); } if (System.currentTimeMillis() - startTime > 60000) { startTime = System.currentTimeMillis(); ReflectionUtils.printThreadInfo(new PrintWriter(System.out), "Automatic Stack Trace every 60 seconds waiting on " + t.getName()); } } } }