HBASE-4217 HRS.closeRegion should be able to close regions with only the encoded name
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1161658 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7ede7e9b39
commit
581af1b086
|
@ -478,6 +478,8 @@ Release 0.90.5 - Unreleased
|
|||
Campbell)
|
||||
HBASE-4095 Hlog may not be rolled in a long time if checkLowReplication's
|
||||
request of LogRoll is blocked (Jieshan Bean)
|
||||
HBASE-4217 HRS.closeRegion should be able to close regions with only
|
||||
the encoded name (ramkrishna.s.vasudevan)
|
||||
|
||||
IMPROVEMENT
|
||||
HBASE-4205 Enhance HTable javadoc (Eric Charles)
|
||||
|
|
|
@ -1009,6 +1009,45 @@ public class HBaseAdmin implements Abortable, Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For expert-admins. Runs close on the regionserver. Closes a region based on
|
||||
* the encoded region name. The region server name is mandatory. If the
|
||||
* servername is provided then based on the online regions in the specified
|
||||
* regionserver the specified region will be closed. The master will not be
|
||||
* informed of the close. Note that the regionname is the encoded regionname.
|
||||
*
|
||||
* @param encodedRegionName
|
||||
* The encoded region name; i.e. the hash that makes up the region
|
||||
* name suffix: e.g. if regionname is
|
||||
* <code>TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396.</code>
|
||||
* , then the encoded region name is:
|
||||
* <code>527db22f95c8a9e0116f0cc13c680396</code>.
|
||||
* @param serverName
|
||||
* The servername of the regionserver. A server name is made of host,
|
||||
* port and startcode. This is mandatory. Here is an example:
|
||||
* <code> host187.example.com,60020,1289493121758</code>
|
||||
* @return true if the region was closed, false if not.
|
||||
* @throws IOException
|
||||
* if a remote or network exception occurs
|
||||
*/
|
||||
public boolean closeRegionWithEncodedRegionName(final String encodedRegionName,
|
||||
final String serverName) throws IOException {
|
||||
byte[] encodedRegionNameInBytes = Bytes.toBytes(encodedRegionName);
|
||||
if (null == serverName || ("").equals(serverName.trim())) {
|
||||
throw new IllegalArgumentException(
|
||||
"The servername cannot be null or empty.");
|
||||
}
|
||||
ServerName sn = new ServerName(serverName);
|
||||
HRegionInterface rs = this.connection.getHRegionConnection(
|
||||
sn.getHostname(), sn.getPort());
|
||||
// Close the region without updating zk state.
|
||||
boolean isRegionClosed = rs.closeRegion(encodedRegionNameInBytes, false);
|
||||
if (false == isRegionClosed) {
|
||||
LOG.error("Not able to close the region " + encodedRegionName + ".");
|
||||
}
|
||||
return isRegionClosed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a region. For expert-admins Runs close on the regionserver. The
|
||||
* master will not be informed of the close.
|
||||
|
|
|
@ -366,6 +366,21 @@ public interface HRegionInterface extends VersionedProtocol, Stoppable, Abortabl
|
|||
*/
|
||||
public boolean closeRegion(final HRegionInfo region, final boolean zk)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Closes the region in the RS with the specified encoded regionName and will
|
||||
* use or not use ZK during the close according to the specified flag. Note
|
||||
* that the encoded region name is in byte format.
|
||||
*
|
||||
* @param encodedRegionName
|
||||
* in bytes
|
||||
* @param zk
|
||||
* true if to use zookeeper, false if need not.
|
||||
* @return true if region is closed, false if not.
|
||||
* @throws IOException
|
||||
*/
|
||||
public boolean closeRegion(byte[] encodedRegionName, final boolean zk)
|
||||
throws IOException;
|
||||
|
||||
// Region administrative methods
|
||||
|
||||
|
|
|
@ -2361,6 +2361,12 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
|
|||
}
|
||||
return closeRegion(region, false, zk);
|
||||
}
|
||||
|
||||
@Override
|
||||
@QosPriority(priority=HIGH_QOS)
|
||||
public boolean closeRegion(byte[] encodedRegionName, boolean zk) throws IOException {
|
||||
return closeRegion(encodedRegionName, false, zk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param region Region to close
|
||||
|
@ -2389,6 +2395,29 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
|
|||
this.service.submit(crh);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param encodedRegionName
|
||||
* encodedregionName to close
|
||||
* @param abort
|
||||
* True if we are aborting
|
||||
* @param zk
|
||||
* True if we are to update zk about the region close; if the close
|
||||
* was orchestrated by master, then update zk. If the close is being
|
||||
* run by the regionserver because its going down, don't update zk.
|
||||
* @return True if closed a region.
|
||||
*/
|
||||
protected boolean closeRegion(byte[] encodedRegionName, final boolean abort,
|
||||
final boolean zk) throws IOException {
|
||||
String encodedRegionNameStr = Bytes.toString(encodedRegionName);
|
||||
HRegion region = this.getFromOnlineRegions(encodedRegionNameStr);
|
||||
if (null != region) {
|
||||
return closeRegion(region.getRegionInfo(), abort, zk);
|
||||
}
|
||||
LOG.error("The specified region name" + encodedRegionNameStr
|
||||
+ " does not exist to close the region.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Manual remote region administration RPCs
|
||||
|
||||
|
@ -3031,4 +3060,6 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
|
|||
return c.getBlockCacheColumnFamilySummaries(this.conf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -209,13 +209,18 @@ module Hbase
|
|||
@admin.createTable(htd, splits)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# Closes a region
|
||||
def close_region(region_name, server = nil)
|
||||
@admin.closeRegion(region_name, server)
|
||||
# Closes a region.
|
||||
# If server name is nil, we presume region_name is full region name (HRegionInfo.getRegionName).
|
||||
# If server name is not nil, we presume it is the region's encoded name (HRegionInfo.getEncodedName)
|
||||
def close_region(region_name, server)
|
||||
if (server == nil || !closeEncodedRegion?(region_name, server))
|
||||
@admin.closeRegion(region_name, server)
|
||||
end
|
||||
end
|
||||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# Assign a region
|
||||
def assign(region_name, force)
|
||||
|
@ -389,6 +394,12 @@ module Hbase
|
|||
@admin.isTableEnabled(table_name)
|
||||
end
|
||||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
#Is supplied region name is encoded region name
|
||||
def closeEncodedRegion?(region_name, server)
|
||||
@admin.closeRegionWithEncodedRegionName(region_name, server)
|
||||
end
|
||||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# Return a new HColumnDescriptor made of passed args
|
||||
def hcd(arg, htd)
|
||||
|
|
|
@ -23,14 +23,25 @@ module Shell
|
|||
class CloseRegion < Command
|
||||
def help
|
||||
return <<-EOF
|
||||
Close a single region. Optionally specify regionserver 'servername' where
|
||||
A server name is its host, port plus startcode. For example:
|
||||
host187.example.com,60020,1289493121758 (find servername in master ui or
|
||||
when you do detailed status in shell). Connects to the regionserver and
|
||||
runs close on hosting regionserver. The close is done without the master's
|
||||
involvement (It will not know of the close). Once closed, region will stay
|
||||
closed. Use assign to reopen/reassign. Use unassign or move to assign the
|
||||
region elsewhere on cluster. Use with caution. For experts only. Examples:
|
||||
Close a single region. Ask the master to close a region out on the cluster
|
||||
or if 'SERVER_NAME' is supplied, ask the designated hosting regionserver to
|
||||
close the region directly. Closing a region, the master expects 'REGIONNAME'
|
||||
to be a fully qualified region name. When asking the hosting regionserver to
|
||||
directly close a region, you pass the regions' encoded name only. A region
|
||||
name looks like this:
|
||||
|
||||
TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396.
|
||||
|
||||
The trailing period is part of the regionserver name. A region's encoded name
|
||||
is the hash at the end of a region name; e.g. 527db22f95c8a9e0116f0cc13c680396
|
||||
(without the period). A 'SERVER_NAME' is its host, port plus startcode. For
|
||||
example: host187.example.com,60020,1289493121758 (find servername in master ui
|
||||
or when you do detailed status in shell). This command will end up running
|
||||
close on the region hosting regionserver. The close is done without the
|
||||
master's involvement (It will not know of the close). Once closed, region will
|
||||
stay closed. Use assign to reopen/reassign. Use unassign or move to assign
|
||||
the region elsewhere on cluster. Use with caution. For experts only.
|
||||
Examples:
|
||||
|
||||
hbase> close_region 'REGIONNAME'
|
||||
hbase> close_region 'REGIONNAME', 'SERVER_NAME'
|
||||
|
|
|
@ -23,6 +23,7 @@ package org.apache.hadoop.hbase.client;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -35,6 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||
import org.apache.hadoop.hbase.HConstants;
|
||||
|
@ -49,7 +51,11 @@ import org.apache.hadoop.hbase.executor.EventHandler;
|
|||
import org.apache.hadoop.hbase.executor.EventHandler.EventType;
|
||||
import org.apache.hadoop.hbase.executor.ExecutorService;
|
||||
import org.apache.hadoop.hbase.master.MasterServices;
|
||||
import org.apache.hadoop.hbase.regionserver.HRegionServer;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.zookeeper.ZKAssign;
|
||||
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -904,6 +910,157 @@ public class TestAdmin {
|
|||
new HTable(TEST_UTIL.getConfiguration(),
|
||||
"testTableNotFoundExceptionWithoutAnyTables");
|
||||
}
|
||||
@Test
|
||||
public void testShouldCloseTheRegionBasedOnTheEncodedRegionName()
|
||||
throws Exception {
|
||||
byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion");
|
||||
HBaseAdmin admin = createTable(TABLENAME);
|
||||
|
||||
HRegionInfo info = null;
|
||||
HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
|
||||
List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
|
||||
for (HRegionInfo regionInfo : onlineRegions) {
|
||||
if (!regionInfo.isMetaRegion() && !regionInfo.isRootRegion()) {
|
||||
info = regionInfo;
|
||||
admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(), rs
|
||||
.getServerName().getServerName());
|
||||
}
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
onlineRegions = rs.getOnlineRegions();
|
||||
assertFalse("The region should not be present in online regions list.",
|
||||
onlineRegions.contains(info));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception {
|
||||
byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion1");
|
||||
HBaseAdmin admin = createTable(TABLENAME);
|
||||
|
||||
HRegionInfo info = null;
|
||||
HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
|
||||
List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
|
||||
for (HRegionInfo regionInfo : onlineRegions) {
|
||||
if (!regionInfo.isMetaRegion() && !regionInfo.isRootRegion()) {
|
||||
if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion1")) {
|
||||
info = regionInfo;
|
||||
admin.closeRegionWithEncodedRegionName("sample", rs.getServerName()
|
||||
.getServerName());
|
||||
}
|
||||
}
|
||||
}
|
||||
onlineRegions = rs.getOnlineRegions();
|
||||
assertTrue("The region should be present in online regions list.",
|
||||
onlineRegions.contains(info));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseRegionThatFetchesTheHRIFromMeta() throws Exception {
|
||||
byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion2");
|
||||
HBaseAdmin admin = createTable(TABLENAME);
|
||||
|
||||
HRegionInfo info = null;
|
||||
HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
|
||||
List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
|
||||
for (HRegionInfo regionInfo : onlineRegions) {
|
||||
if (!regionInfo.isMetaRegion() && !regionInfo.isRootRegion()) {
|
||||
|
||||
if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion2")) {
|
||||
info = regionInfo;
|
||||
admin.closeRegion(regionInfo.getRegionNameAsString(), rs
|
||||
.getServerName().getServerName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
onlineRegions = rs.getOnlineRegions();
|
||||
assertFalse("The region should not be present in online regions list.",
|
||||
onlineRegions.contains(info));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseRegionWhenServerNameIsNull() throws Exception {
|
||||
byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion3");
|
||||
HBaseAdmin admin = createTable(TABLENAME);
|
||||
|
||||
HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
|
||||
|
||||
try {
|
||||
List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
|
||||
for (HRegionInfo regionInfo : onlineRegions) {
|
||||
if (!regionInfo.isMetaRegion() && !regionInfo.isRootRegion()) {
|
||||
if (regionInfo.getRegionNameAsString()
|
||||
.contains("TestHBACloseRegion3")) {
|
||||
admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(),
|
||||
null);
|
||||
}
|
||||
}
|
||||
}
|
||||
fail("The test should throw exception if the servername passed is null.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCloseRegionWhenServerNameIsEmpty() throws Exception {
|
||||
byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion3");
|
||||
HBaseAdmin admin = createTable(TABLENAME);
|
||||
|
||||
HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
|
||||
|
||||
try {
|
||||
List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
|
||||
for (HRegionInfo regionInfo : onlineRegions) {
|
||||
if (!regionInfo.isMetaRegion() && !regionInfo.isRootRegion()) {
|
||||
if (regionInfo.getRegionNameAsString()
|
||||
.contains("TestHBACloseRegion3")) {
|
||||
admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(),
|
||||
" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
fail("The test should throw exception if the servername passed is empty.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseRegionWhenEncodedRegionNameIsNotGiven() throws Exception {
|
||||
byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion4");
|
||||
HBaseAdmin admin = createTable(TABLENAME);
|
||||
|
||||
HRegionInfo info = null;
|
||||
HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME);
|
||||
|
||||
List<HRegionInfo> onlineRegions = rs.getOnlineRegions();
|
||||
for (HRegionInfo regionInfo : onlineRegions) {
|
||||
if (!regionInfo.isMetaRegion() && !regionInfo.isRootRegion()) {
|
||||
if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion4")) {
|
||||
info = regionInfo;
|
||||
admin.closeRegionWithEncodedRegionName(regionInfo
|
||||
.getRegionNameAsString(), rs.getServerName().getServerName());
|
||||
}
|
||||
}
|
||||
}
|
||||
onlineRegions = rs.getOnlineRegions();
|
||||
assertTrue("The region should be present in online regions list.",
|
||||
onlineRegions.contains(info));
|
||||
}
|
||||
|
||||
private HBaseAdmin createTable(byte[] TABLENAME) throws IOException {
|
||||
|
||||
Configuration config = TEST_UTIL.getConfiguration();
|
||||
HBaseAdmin admin = new HBaseAdmin(config);
|
||||
|
||||
HTableDescriptor htd = new HTableDescriptor(TABLENAME);
|
||||
HColumnDescriptor hcd = new HColumnDescriptor("value");
|
||||
|
||||
htd.addFamily(hcd);
|
||||
admin.createTable(htd, null);
|
||||
return admin;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHundredsOfTable() throws IOException{
|
||||
|
|
Loading…
Reference in New Issue