Index: src/test/java/org/apache/hadoop/hbase/ServerManager.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/ServerManager.java (revision 0) +++ src/test/java/org/apache/hadoop/hbase/ServerManager.java (revision 0) @@ -0,0 +1,371 @@ +/** + * 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.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.StringTokenizer; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.util.Shell; + + +/** + * Utility to start/kill servers in a distributed environment. Assumes Unix-like + * commands are available like 'ps', 'kill', etc. Also assumes the user running + * the test has enough "power" to start & stop servers on the remote machines + * (for example, the test user could be the same user as the user the daemon is + * running as) + */ +public abstract class ServerManager { + private static final Log LOG = LogFactory.getLog(ServerManager.class); + + enum Operation {STOP, RESUME, START, KILL}; + public enum ServerTypeName {REGIONSERVER, MASTER}; //hardcoded for now + + final static String REGIONSERVER = "regionserver"; + final String MASTER = "master"; + final String scratchSpaceDir; + private final String slavesFile; + private Random rand = new Random(System.currentTimeMillis()); + private static String TEST_CONF_FILE = "test-conf.xml"; + + public ServerManager(String scratchSpaceDir) { + this.scratchSpaceDir = scratchSpaceDir; + this.slavesFile = scratchSpaceDir + Path.SEPARATOR + + "slave-" + rand.nextInt(); + } + + public static ServerManager getInstanceOfManager(ServerTypeName type, + String scratchSpaceDir) { + if (type == ServerTypeName.REGIONSERVER) { //this could be replaced by config key/val mappings + return new RegionServerManager(scratchSpaceDir); + } + return null; + } + + public static RandomKiller getRandomKillerInstance( + Collection types, String scratchSpaceDir) { + return new RandomKiller(types, scratchSpaceDir); + } + + /** + * The following public methods are for controlling servers using an instance + * of this class. Currently these are not thread-safe. + */ + public void stopServer(Collection servers) throws IOException { + runOperationOnServers(Operation.STOP, servers); + } + public void resumeServer(Collection servers) throws IOException { + runOperationOnServers(Operation.RESUME, servers); + } + public void startServer(Collection servers) throws IOException { + runOperationOnServers(Operation.START, servers); + } + public void killServer(Collection servers) throws IOException { + runOperationOnServers(Operation.KILL, servers); + } + public void stopServer(String server) throws IOException { + ArrayList arr = new ArrayList(); + arr.add(server); + runOperationOnServers(Operation.STOP, arr); + } + public void resumeServer(String server) throws IOException { + ArrayList servers = new ArrayList(); + servers.add(server); + runOperationOnServers(Operation.RESUME, servers); + } + public void startServer(String server) throws IOException { + ArrayList servers = new ArrayList(); + servers.add(server); + runOperationOnServers(Operation.START, servers); + } + public void killServer(String server) throws IOException { + ArrayList servers = new ArrayList(); + servers.add(server); + runOperationOnServers(Operation.KILL, servers); + } + + private void runOperationOnServers(Operation operation, + Collection servers) throws IOException { + try { + writeServersToAffectFile(servers); + runOperation(operation); + } finally { + cleanupScratchSpace(); + } + } + + private void writeServersToAffectFile(Collection servers) + throws IOException { + //not threadsafe + FileOutputStream fos = new FileOutputStream(new File(slavesFile)); + for (String server : servers) { + LOG.info(new Date() + " Marking server on host: " + server); + fos.write((server + "\n").getBytes()); + } + fos.close(); + } + + private void cleanupScratchSpace() { + new File(slavesFile).delete(); + } + + /** + * The following protected methods are expected to be implemented by the + * respective server extensions/implementations of ServerManager + */ + /** + * Get the env name that the server scripts use to point to the slaves file + * (like HBASE_REGIONSERVERS file in the case of hbase). + * IMPORTANT NOTE: MAKE SURE that the scripts on the machine where this test + * is run from doesn't set the env internally (that would interfere with the + * tests) + * @return + */ + protected abstract String getSlavesFileEnvName(); + /** + * Get the env name that the server scripts use to point to the HOME of + * the installation (like HBASE_HOME in the case of hbase) + * @return + */ + protected abstract String getHomeEnvName(); + /** + * The Ssh command path that ssh'es out to the remote nodes and runs commands + * (like bin/regionservers.sh in the case of hbase). If the path doesn't + * begin with a slash, the assumption is that the path is relative to + * the return value of {@link #getHomeEnvName()}, and the path is normalized + * by this class before using it + * @return + */ + protected abstract String getSshCommandPath(); + /** + * The command for 'stopping' the server + * @return + */ + protected abstract String getStopCommand(); + /** + * The command for 'resuming' a 'stopped' server + * @return + */ + protected abstract String getResumeCommand(); + /** + * The command for 'starting' the server + * @return + */ + protected abstract String getStartCommand(); + /** + * The command for 'killing' the server + * @return + */ + protected abstract String getKillCommand(); + + private void runOperation(Operation operation) throws IOException { + Map hMap = new HashMap(); + hMap.put(getSlavesFileEnvName(), slavesFile); + + StringTokenizer strToken; + if (operation == Operation.STOP) { + strToken = new StringTokenizer(getStopCommand(), " "); + } else if(operation == Operation.RESUME) { + strToken = new StringTokenizer(getResumeCommand(), " "); + } else if(operation == Operation.START) { + strToken = new StringTokenizer(getStartCommand(), " "); + } else if(operation == Operation.KILL) { + strToken = new StringTokenizer(getKillCommand(), " "); + } else { + throw new RuntimeException(operation + " currently not supported"); + } + + String commandArgs[] = new String[strToken.countTokens() + 1]; + int i = 0; + commandArgs[i++] = normalizeSshCommandPath(getSshCommandPath()); + while (strToken.hasMoreTokens()) { + commandArgs[i++] = strToken.nextToken(); + } + String output = Shell.execCommand(hMap, commandArgs); + if (output != null && !output.equals("")) { + LOG.info(output); + } + } + private String normalizeSshCommandPath(String command) { + if (command.startsWith("/")) { + return command; + } + final String home; + if ((home = System.getenv(getHomeEnvName())) != null) { + command = home + Path.SEPARATOR + command; + } + return command; + } + + static class RandomKiller extends Thread { + Map> runningServersMap + = new TreeMap>(); + Map> nonRunningServersMap + = new TreeMap>(); + List managers; + String hostFile; + boolean pause = false; + final long SLEEP_BETWEEN_OPS = 5000; + Object pauseMonitor = new Object(); + + public RandomKiller(Collection types, + String scratchSpaceDir) { + Configuration conf = new Configuration(false); + conf.addResource(TEST_CONF_FILE); + for (ServerTypeName t : types) { + ServerManager s = getInstanceOfManager(t, scratchSpaceDir); + String[] servers = conf.getStrings(t.toString()); + ArrayList serverList = new ArrayList(); + for (String str : servers) { + serverList.add(str); + } + runningServersMap.put(s, serverList); + managers.add(s); + } + this.setDaemon(true); + this.setName("RandomStartStopServers"); + } + + public void pauseInjector() { + this.pause = true; + } + + public void resumeInjector() { + this.pause = false; + pauseMonitor.notifyAll(); + } + + private void mightpause() throws InterruptedException { + synchronized (pauseMonitor) { + while (pause) { + pauseMonitor.wait(); + } + } + } + + @Override + public void run() { + Random rand = new Random(); + int size = runningServersMap.size(); + while (true) { + //stop/start in a loop (very simple for now) + try { + int idx = rand.nextInt(size); + ServerManager manager = managers.get(idx); + //there should be at least one server running (refine this later) + List running = runningServersMap.get(manager); + //try to kill some server + if (running.size() > 1) { + int idx1 = rand.nextInt(running.size()); + String serverToStop = running.remove(idx1); + manager.killServer(serverToStop); + List nonRunning = nonRunningServersMap.get(manager); + if (nonRunning == null) { + nonRunning = new ArrayList(); + nonRunningServersMap.put(manager, nonRunning); + } + nonRunning.add(serverToStop); + Thread.sleep(SLEEP_BETWEEN_OPS); + mightpause(); + } else { + Thread.sleep(1000); //don't want this to be a tight loop + } + + idx = rand.nextInt(size); + manager = managers.get(idx); + List nonRunning = nonRunningServersMap.get(manager); + //try to start some server + if (nonRunning.size() >= 1) { + int idx1 = rand.nextInt(nonRunning.size()); + String serverToStart = nonRunning.remove(idx1); + manager.startServer(serverToStart); + running = runningServersMap.get(manager); + running.add(serverToStart); + Thread.sleep(SLEEP_BETWEEN_OPS); + mightpause(); + } else { + Thread.sleep(1000); //don't want this to be a tight loop + } + } catch (Exception ex) {//ignore + } + } + } + } +} + +class RegionServerManager extends ServerManager { + final private String STOP_COMMAND = "ps uwwx | grep java | grep " + + "proc_regionserver"+ " |" + + " grep -v grep | tr -s ' ' | cut -d ' ' -f2 | xargs kill -s STOP"; + final private String RESUME_COMMAND = "ps uwwx | grep java | grep " + + "proc_regionserver"+ " |" + + " grep -v grep | tr -s ' ' | cut -d ' ' -f2 | xargs kill -s CONT"; + final private String START_COMMAND = System.getenv("HBASE_HOME") + + "/bin/hbase-daemon.sh start regionserver"; + final private String KILL_COMMAND = "ps uwwx | grep java | grep " + + "proc_regionserver"+ " |" + + " grep -v grep | tr -s ' ' | cut -d ' ' -f2 | xargs kill -9"; + RegionServerManager(String scratchSpaceDir) { + super(scratchSpaceDir); + } + + @Override + protected String getSlavesFileEnvName() { + return "HBASE_REGIONSERVERS"; + } + @Override + protected String getStopCommand() { + return STOP_COMMAND; + } + @Override + protected String getResumeCommand() { + return RESUME_COMMAND; + } + @Override + protected String getStartCommand() { + return START_COMMAND; + } + @Override + protected String getKillCommand() { + return KILL_COMMAND; + } + @Override + protected String getHomeEnvName() { + return "HBASE_HOME"; + } + @Override + protected String getSshCommandPath() { + return "bin/regionservers.sh"; + } +} + Index: src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java (revision 1339959) +++ src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java (working copy) @@ -963,6 +963,18 @@ Bytes.toBytes("uuu"), Bytes.toBytes("vvv"), Bytes.toBytes("www"), Bytes.toBytes("xxx"), Bytes.toBytes("yyy") }; + + public static final byte[][] NON_EMPTY_KEYS = { + Bytes.toBytes("bbb"), + Bytes.toBytes("ccc"), Bytes.toBytes("ddd"), Bytes.toBytes("eee"), + Bytes.toBytes("fff"), Bytes.toBytes("ggg"), Bytes.toBytes("hhh"), + Bytes.toBytes("iii"), Bytes.toBytes("jjj"), Bytes.toBytes("kkk"), + Bytes.toBytes("lll"), Bytes.toBytes("mmm"), Bytes.toBytes("nnn"), + Bytes.toBytes("ooo"), Bytes.toBytes("ppp"), Bytes.toBytes("qqq"), + Bytes.toBytes("rrr"), Bytes.toBytes("sss"), Bytes.toBytes("ttt"), + Bytes.toBytes("uuu"), Bytes.toBytes("vvv"), Bytes.toBytes("www"), + Bytes.toBytes("xxx"), Bytes.toBytes("yyy") + }; /** * Creates many regions names "aaa" to "zzz". Index: src/test/java/org/apache/hadoop/hbase/TestRegionRebalancing.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/TestRegionRebalancing.java (revision 1339959) +++ src/test/java/org/apache/hadoop/hbase/TestRegionRebalancing.java (working copy) @@ -22,19 +22,26 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import java.io.BufferedReader; +import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Random; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.catalog.CatalogTracker; import org.apache.hadoop.hbase.catalog.MetaReader; import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.apache.hadoop.hbase.client.HConnection; import org.apache.hadoop.hbase.client.HTable; -import org.apache.hadoop.hbase.regionserver.HRegionServer; +import org.apache.hadoop.hbase.ipc.HRegionInterface; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.JVMClusterUtil; +import org.apache.hadoop.util.Tool; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -43,12 +50,16 @@ /** * Test whether region rebalancing works. (HBASE-71) */ -public class TestRegionRebalancing { - final Log LOG = LogFactory.getLog(this.getClass().getName()); +public class TestRegionRebalancing implements Tool { + final static Log LOG = LogFactory.getLog(TestRegionRebalancing.class); private static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); + boolean realCluster = false; + List realHosts; + ServerManager serverManager; HTable table; HTableDescriptor desc; private static final byte [] FAMILY_NAME = Bytes.toBytes("col"); + Configuration conf; @BeforeClass public static void beforeClass() throws Exception { @@ -62,10 +73,20 @@ @Before public void before() { - this.desc = new HTableDescriptor("test"); + createTableDesc("test"); + } + + private void createTableDesc(String name) { + this.desc = new HTableDescriptor(name); this.desc.addFamily(new HColumnDescriptor(FAMILY_NAME)); } + private void deleteTable(String name) throws IOException { + HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); + admin.disableTable(name); + admin.deleteTable(name); + } + /** * For HBASE-71. Try a few different configurations of starting and stopping * region servers to see if the assignment or regions is pretty balanced. @@ -76,7 +97,14 @@ public void testRebalanceOnRegionServerNumberChange() throws IOException, InterruptedException { HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); - admin.createTable(this.desc, HBaseTestingUtility.KEYS); + int keyLength; + if (realCluster) { + admin.createTable(this.desc, HBaseTestingUtility.NON_EMPTY_KEYS); + keyLength = HBaseTestingUtility.NON_EMPTY_KEYS.length; + } else { + admin.createTable(this.desc, HBaseTestingUtility.KEYS); + keyLength = HBaseTestingUtility.KEYS.length; + } this.table = new HTable(UTIL.getConfiguration(), this.desc.getName()); CatalogTracker ct = new CatalogTracker(UTIL.getConfiguration()); ct.start(); @@ -86,52 +114,111 @@ ct.stop(); } assertEquals("Test table should have right number of regions", - HBaseTestingUtility.KEYS.length + 1/*One extra to account for start/end keys*/, + keyLength + 1/*One extra to account for start/end keys*/, this.table.getStartKeys().length); // verify that the region assignments are balanced to start out assertRegionsAreBalanced(); // add a region server - total of 2 - LOG.info("Started second server=" + - UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); - UTIL.getHBaseCluster().getMaster().balance(); + if (realCluster) { + tryAddingServerInCluster(2,"Started second server=", admin); + admin.getMaster().balance(); + } else { + LOG.info("Started second server=" + + UTIL.getHBaseCluster().startRegionServer().getRegionServer() + .getServerName()); + UTIL.getHBaseCluster().getMaster().balance(); + } assertRegionsAreBalanced(); // add a region server - total of 3 - LOG.info("Started third server=" + - UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); - UTIL.getHBaseCluster().getMaster().balance(); + if (realCluster) { + tryAddingServerInCluster(3,"Started third server=", admin); + admin.getMaster().balance(); + } else { + LOG.info("Started third server=" + + UTIL.getHBaseCluster().startRegionServer().getRegionServer() + .getServerName()); + UTIL.getHBaseCluster().getMaster().balance(); + } + assertRegionsAreBalanced(); // kill a region server - total of 2 - LOG.info("Stopped third server=" + UTIL.getHBaseCluster().stopRegionServer(2, false)); - UTIL.getHBaseCluster().waitOnRegionServer(2); - UTIL.getHBaseCluster().getMaster().balance(); + if (realCluster) { + if (realHosts.size() > 2) { + LOG.info("Stopped third server=" + realHosts.get(2)); + serverManager.stopServer(realHosts.get(2)); + admin.getMaster().balance(); + } + } else { + LOG.info("Stopped third server=" + UTIL.getHBaseCluster().stopRegionServer(2, false)); + UTIL.getHBaseCluster().waitOnRegionServer(2); + UTIL.getHBaseCluster().getMaster().balance(); + } + assertRegionsAreBalanced(); // start two more region servers - total of 4 - LOG.info("Readding third server=" + - UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); - LOG.info("Added fourth server=" + - UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); - UTIL.getHBaseCluster().getMaster().balance(); + if (realCluster) { + tryAddingServerInCluster(3,"Readding third server=",admin); + tryAddingServerInCluster(4,"Added fourth server=",admin); + admin.getMaster().balance(); + } else { + LOG.info("Readding third server=" + + UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); + LOG.info("Added fourth server=" + + UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); + UTIL.getHBaseCluster().getMaster().balance(); + } + assertRegionsAreBalanced(); for (int i = 0; i < 6; i++){ - LOG.info("Adding " + (i + 5) + "th region server"); - UTIL.getHBaseCluster().startRegionServer(); + if (realCluster) { + tryAddingServerInCluster(i + 5, + "Adding " + (i + 5) + "th region server", admin); + } else { + LOG.info("Adding " + (i + 5) + "th region server"); + UTIL.getHBaseCluster().startRegionServer(); + } } - UTIL.getHBaseCluster().getMaster().balance(); + if (realCluster) { + admin.getMaster().balance(); + } else { + UTIL.getHBaseCluster().getMaster().balance(); + } + assertRegionsAreBalanced(); } + private void tryAddingServerInCluster(int serverNumber, String log, + HBaseAdmin admin) throws IOException { + //if we have have enough real machines to play with then start + if (realHosts.size() >= serverNumber) { + int prevClusterSize = admin.getClusterStatus().getServersSize(); + serverManager.startServer(realHosts.get(serverNumber-1)); + try { + Thread.sleep(5000); //give it a few + } catch(Exception e){} + if (admin.getClusterStatus().getServersSize() > prevClusterSize) { + LOG.info(log +" "+realHosts.get(serverNumber-1)); + } else { + LOG.error("Couldn't start up " + realHosts.get(serverNumber-1)); + } + } + } + /** figure out how many regions are currently being served. */ private int getRegionCount() throws IOException { int total = 0; - for (HRegionServer server : getOnlineRegionServers()) { - total += server.getOnlineRegions().size(); + for (HRegionInterfaceWithServerName server : getOnlineRegionServers()) { + total += server.hRegion.getOnlineRegions().size(); } + if (realCluster) { + + } return total; } @@ -153,20 +240,28 @@ waitForAllRegionsAssigned(); int regionCount = getRegionCount(); - List servers = getOnlineRegionServers(); - double avg = UTIL.getHBaseCluster().getMaster().getAverageLoad(); + List servers = getOnlineRegionServers(); + double avg; + if (realCluster) { + HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); + ClusterStatus clusterStatus = admin.getClusterStatus(); + avg = clusterStatus.getAverageLoad(); + + } else { + avg = UTIL.getHBaseCluster().getMaster().getAverageLoad(); + } int avgLoadPlusSlop = (int)Math.ceil(avg * (1 + slop)); int avgLoadMinusSlop = (int)Math.floor(avg * (1 - slop)) - 1; LOG.debug("There are " + servers.size() + " servers and " + regionCount + " regions. Load Average: " + avg + " low border: " + avgLoadMinusSlop + ", up border: " + avgLoadPlusSlop + "; attempt: " + i); - for (HRegionServer server : servers) { - int serverLoad = server.getOnlineRegions().size(); - LOG.debug(server.getServerName() + " Avg: " + avg + " actual: " + serverLoad); + for (HRegionInterfaceWithServerName server : servers) { + int serverLoad = server.hRegion.getOnlineRegions().size(); + LOG.debug(server.serverName + " Avg: " + avg + " actual: " + serverLoad); if (!(avg > 2.0 && serverLoad <= avgLoadPlusSlop && serverLoad >= avgLoadMinusSlop)) { - LOG.debug(server.getServerName() + " Isn't balanced!!! Avg: " + avg + + LOG.debug(server.serverName + " Isn't balanced!!! Avg: " + avg + " actual: " + serverLoad + " slop: " + slop); success = false; } @@ -179,7 +274,12 @@ Thread.sleep(10000); } catch (InterruptedException e) {} - UTIL.getHBaseCluster().getMaster().balance(); + if (realCluster) { + HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); + admin.getMaster().balance(); + } else { + UTIL.getHBaseCluster().getMaster().balance(); + } continue; } @@ -191,13 +291,32 @@ fail("After 5 attempts, region assignments were not balanced."); } - private List getOnlineRegionServers() { - List list = new ArrayList(); - for (JVMClusterUtil.RegionServerThread rst : - UTIL.getHBaseCluster().getRegionServerThreads()) { - if (rst.getRegionServer().isOnline()) { - list.add(rst.getRegionServer()); + private List getOnlineRegionServers() { + List list = + new ArrayList(); + if (realCluster) { + try { + HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); + ClusterStatus clusterStatus = admin.getClusterStatus(); + Collectionservers = clusterStatus.getServers(); + HConnection connection = admin.getConnection(); + for (ServerName hsi : servers) { + HRegionInterface server = + connection.getHRegionConnection(hsi.getHostname(), hsi.getPort()); + list.add(new HRegionInterfaceWithServerName(hsi, + server)); + } + } catch (Exception e) { + throw new RuntimeException(e); } + } else { + for (JVMClusterUtil.RegionServerThread rst : + UTIL.getHBaseCluster().getRegionServerThreads()) { + if (rst.getRegionServer().isOnline()) { + list.add(new HRegionInterfaceWithServerName( + rst.getRegionServer().getServerName(),rst.getRegionServer())); + } + } } return list; } @@ -206,12 +325,96 @@ * Wait until all the regions are assigned. */ private void waitForAllRegionsAssigned() throws IOException { - while (getRegionCount() < 22) { - // while (!cluster.getMaster().allRegionsAssigned()) { - LOG.debug("Waiting for there to be 22 regions, but there are " + getRegionCount() + " right now."); + if (realCluster) { + //check that there are no regions in transition + HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); + int count; + while ((count = admin.getClusterStatus().getRegionsInTransition().size()) + != 0) { + LOG.debug("Waiting for "+ count + " regions to settle down"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) {} + } + } else { + while (getRegionCount() < 22) { + // while (!cluster.getMaster().allRegionsAssigned()) { + LOG.debug("Waiting for there to be 22 regions, but there are " + getRegionCount() + " right now."); + try { + Thread.sleep(1000); + } catch (InterruptedException e) {} + } + } + } + private static class HRegionInterfaceWithServerName { + ServerName serverName; + HRegionInterface hRegion; + HRegionInterfaceWithServerName(ServerName serverName, + HRegionInterface hRegion) { + this.serverName = serverName; + this.hRegion = hRegion; + } + } + + @Override + public Configuration getConf() { + return conf; + } + + @Override + public void setConf(Configuration c) { + this.conf = c; + } + + @Override + public int run(String[] args) throws Exception { + if (args.length != 1) { + System.err.println("Usage: java "); + return -1; + } + List hosts = new ArrayList(); + String filename = args[0]; + BufferedReader b = new BufferedReader(new FileReader(filename)); + String str; + while ((str=b.readLine()) != null) { + hosts.add(str); + } + if (hosts.size() == 0) { + System.err.println("The hostlist file is empty!"); + return -1; + } + this.realCluster = true; + this.realHosts = hosts; + this.serverManager = ServerManager.getInstanceOfManager( + ServerManager.ServerTypeName.REGIONSERVER, "/tmp"); + //try for a name that is random enough so that probability + //that it already exists is really low + String tablename = "test" + + new Random(System.currentTimeMillis()).nextInt(Integer.MAX_VALUE); + this.createTableDesc(tablename); + try { + //Killall servers + serverManager.killServer(realHosts); + //start the first server + serverManager.startServer(realHosts.get(0)); + this.testRebalanceOnRegionServerNumberChange(); + } finally { try { - Thread.sleep(1000); - } catch (InterruptedException e) {} + this.deleteTable(tablename); + } catch (Exception ex){ex.printStackTrace();}//ignore } + return 0; } + + public static void main(String args[]) throws Exception { + int status = -1; + try { + TestRegionRebalancing testClass = new TestRegionRebalancing(); + status = testClass.run(args); + } catch (Exception ex) { + ex.printStackTrace(); + LOG.error("Exiting due to " + ex); + } + System.exit(status); + } } Index: bin/hbase =================================================================== --- bin/hbase (revision 1339959) +++ bin/hbase (working copy) @@ -305,7 +305,7 @@ # Exec unless HBASE_NOEXEC is set. if [ "${HBASE_NOEXEC}" != "" ]; then - "$JAVA" -XX:OnOutOfMemoryError="kill -9 %p" $JAVA_HEAP_MAX $HBASE_OPTS -classpath "$CLASSPATH" $CLASS "$@" + "$JAVA" -Dproc_$COMMAND {-XX:OnOutOfMemoryError="kill -9 %p" $JAVA_HEAP_MAX $HBASE_OPTS -classpath "$CLASSPATH" $CLASS "$@" else - exec "$JAVA" -XX:OnOutOfMemoryError="kill -9 %p" $JAVA_HEAP_MAX $HBASE_OPTS -classpath "$CLASSPATH" $CLASS "$@" + exec "$JAVA" -Dproc_$COMMAND -XX:OnOutOfMemoryError="kill -9 %p" $JAVA_HEAP_MAX $HBASE_OPTS -classpath "$CLASSPATH" $CLASS "$@" fi