HBASE-3267 close_region shell command breaks region

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1040243 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2010-11-29 19:41:02 +00:00
parent a7dc9f982f
commit 2149277bf3
13 changed files with 270 additions and 49 deletions

View File

@ -714,6 +714,7 @@ Release 0.90.0 - Unreleased
HBASE-3275 [rest] No gzip/deflate content encoding support HBASE-3275 [rest] No gzip/deflate content encoding support
HBASE-3261 NPE out of HRS.run at startup when clock is out of sync HBASE-3261 NPE out of HRS.run at startup when clock is out of sync
HBASE-3277 HBase Shell zk_dump command broken HBASE-3277 HBase Shell zk_dump command broken
HBASE-3267 close_region shell command breaks region
IMPROVEMENTS IMPROVEMENTS

View File

@ -751,7 +751,8 @@ public class HBaseAdmin implements Abortable {
} }
/** /**
* Close a region. For expert-admins. * Close a region. For expert-admins. Runs close on the regionserver. The
* master will not be informed of the close.
* @param regionname region name to close * @param regionname region name to close
* @param hostAndPort If supplied, we'll use this location rather than * @param hostAndPort If supplied, we'll use this location rather than
* the one currently in <code>.META.</code> * the one currently in <code>.META.</code>
@ -763,7 +764,8 @@ public class HBaseAdmin implements Abortable {
} }
/** /**
* Close a region. For expert-admins. * Close a region. For expert-admins Runs close on the regionserver. The
* master will not be informed of the close.
* @param regionname region name to close * @param regionname region name to close
* @param hostAndPort If supplied, we'll use this location rather than * @param hostAndPort If supplied, we'll use this location rather than
* the one currently in <code>.META.</code> * the one currently in <code>.META.</code>
@ -801,7 +803,8 @@ public class HBaseAdmin implements Abortable {
private void closeRegion(final HServerAddress hsa, final HRegionInfo hri) private void closeRegion(final HServerAddress hsa, final HRegionInfo hri)
throws IOException { throws IOException {
HRegionInterface rs = this.connection.getHRegionConnection(hsa); HRegionInterface rs = this.connection.getHRegionConnection(hsa);
rs.closeRegion(hri); // Close the region without updating zk state.
rs.closeRegion(hri, false);
} }
/** /**
@ -956,8 +959,14 @@ public class HBaseAdmin implements Abortable {
/** /**
* Move the region <code>r</code> to <code>dest</code>. * Move the region <code>r</code> to <code>dest</code>.
* @param encodedRegionName The encoded region name. * @param encodedRegionName The encoded region name; i.e. the hash that makes
* @param destServerName The servername of the destination regionserver * 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 destServerName The servername of the destination regionserver. If
* passed the empty byte array we'll assign to a random server. A server name
* is made of host, port and startcode. Here is an example:
* <code> host187.example.com,60020,1289493121758</code>.
* @throws UnknownRegionException Thrown if we can't find a region named * @throws UnknownRegionException Thrown if we can't find a region named
* <code>encodedRegionName</code> * <code>encodedRegionName</code>
* @throws ZooKeeperConnectionException * @throws ZooKeeperConnectionException
@ -968,6 +977,36 @@ public class HBaseAdmin implements Abortable {
getMaster().move(encodedRegionName, destServerName); getMaster().move(encodedRegionName, destServerName);
} }
/**
* @param regionName Region name to assign.
* @param force True to force assign.
* @throws MasterNotRunningException
* @throws ZooKeeperConnectionException
* @throws IOException
*/
public void assign(final byte [] regionName, final boolean force)
throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
getMaster().assign(regionName, force);
}
/**
* Unassign a region from current hosting regionserver. Region will then be
* assigned to a regionserver chosen at random. Region could be reassigned
* back to the same server. Use {@link #move(byte[], byte[])} if you want
* to control the region movement.
* @param regionName Region to unassign. Will clear any existing RegionPlan
* if one found.
* @param force If true, force unassign (Will remove region from
* regions-in-transition too if present).
* @throws MasterNotRunningException
* @throws ZooKeeperConnectionException
* @throws IOException
*/
public void unassign(final byte [] regionName, final boolean force)
throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
getMaster().unassign(regionName, force);
}
/** /**
* Turn the load balancer on or off. * Turn the load balancer on or off.
* @param b If true, enable balancer. If false, disable balancer. * @param b If true, enable balancer. If false, disable balancer.

View File

@ -135,14 +135,44 @@ public interface HMasterInterface extends HBaseRPCProtocolVersion {
/** /**
* Move the region <code>r</code> to <code>dest</code>. * Move the region <code>r</code> to <code>dest</code>.
* @param encodedRegionName The encoded region name. * @param encodedRegionName The encoded region name; i.e. the hash that makes
* @param destServerName The servername of the destination regionserver * 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 destServerName The servername of the destination regionserver. If
* passed the empty byte array we'll assign to a random server. A server name
* is made of host, port and startcode. Here is an example:
* <code> host187.example.com,60020,1289493121758</code>.
* @throws UnknownRegionException Thrown if we can't find a region named * @throws UnknownRegionException Thrown if we can't find a region named
* <code>encodedRegionName</code> * <code>encodedRegionName</code>
*/ */
public void move(final byte [] encodedRegionName, final byte [] destServerName) public void move(final byte [] encodedRegionName, final byte [] destServerName)
throws UnknownRegionException; throws UnknownRegionException;
/**
* Assign a region to a server chosen at random.
* @param regionName Region to assign. Will use existing RegionPlan if one
* found.
* @param force If true, will force the assignment.
* @throws IOException
*/
public void assign(final byte [] regionName, final boolean force)
throws IOException;
/**
* Unassign a region from current hosting regionserver. Region will then be
* assigned to a regionserver chosen at random. Region could be reassigned
* back to the same server. Use {@link #move(byte[], byte[])} if you want
* to control the region movement.
* @param regionName Region to unassign. Will clear any existing RegionPlan
* if one found.
* @param force If true, force unassign (Will remove region from
* regions-in-transition too if present).
* @throws IOException
*/
public void unassign(final byte [] regionName, final boolean force)
throws IOException;
/** /**
* Run the balancer. Will run the balancer and if regions to move, it will * Run the balancer. Will run the balancer and if regions to move, it will
* go ahead and do the reassignments. Can NOT run for various reasons. Check * go ahead and do the reassignments. Can NOT run for various reasons. Check

View File

@ -1360,9 +1360,7 @@ public class AssignmentManager extends ZooKeeperListener {
synchronized (this.regions) { synchronized (this.regions) {
this.regions.remove(hri); this.regions.remove(hri);
} }
synchronized (this.regionPlans) { clearRegionPlan(hri.getEncodedName());
this.regionPlans.remove(hri.getEncodedName());
}
synchronized (this.servers) { synchronized (this.servers) {
for (List<HRegionInfo> regions : this.servers.values()) { for (List<HRegionInfo> regions : this.servers.values()) {
for (int i=0;i<regions.size();i++) { for (int i=0;i<regions.size();i++) {
@ -1375,6 +1373,15 @@ public class AssignmentManager extends ZooKeeperListener {
} }
} }
/**
* @param encodedRegionName Region whose plan we are to clear.
*/
void clearRegionPlan(final String encodedRegionName) {
synchronized (this.regionPlans) {
this.regionPlans.remove(encodedRegionName);
}
}
/** /**
* Wait on region to clear regions-in-transition. * Wait on region to clear regions-in-transition.
* @param hri Region to wait on. * @param hri Region to wait on.

View File

@ -703,11 +703,20 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
this.assignmentManager.getAssignment(encodedRegionName); this.assignmentManager.getAssignment(encodedRegionName);
if (p == null) if (p == null)
throw new UnknownRegionException(Bytes.toString(encodedRegionName)); throw new UnknownRegionException(Bytes.toString(encodedRegionName));
HServerInfo dest = HRegionInfo hri = p.getFirst();
this.serverManager.getServerInfo(new String(destServerName)); HServerInfo dest = null;
if (destServerName == null || destServerName.length == 0) {
LOG.info("Passed destination servername is null/empty so " +
"choosing a server at random");
this.assignmentManager.clearRegionPlan(hri.getEncodedName());
// Unassign will reassign it elsewhere choosing random server.
this.assignmentManager.unassign(hri);
} else {
dest = this.serverManager.getServerInfo(new String(destServerName));
RegionPlan rp = new RegionPlan(p.getFirst(), p.getSecond(), dest); RegionPlan rp = new RegionPlan(p.getFirst(), p.getSecond(), dest);
this.assignmentManager.balance(rp); this.assignmentManager.balance(rp);
} }
}
public void createTable(HTableDescriptor desc, byte [][] splitKeys) public void createTable(HTableDescriptor desc, byte [][] splitKeys)
throws IOException { throws IOException {
@ -979,10 +988,30 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
return isInitialized; return isInitialized;
} }
@Override
public void assign(final byte [] regionName, final boolean force)
throws IOException {
Pair<HRegionInfo, HServerAddress> pair =
MetaReader.getRegion(this.catalogTracker, regionName);
if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
assignRegion(pair.getFirst());
}
public void assignRegion(HRegionInfo hri) { public void assignRegion(HRegionInfo hri) {
assignmentManager.assign(hri, true); assignmentManager.assign(hri, true);
} }
@Override
public void unassign(final byte [] regionName, final boolean force)
throws IOException {
Pair<HRegionInfo, HServerAddress> pair =
MetaReader.getRegion(this.catalogTracker, regionName);
if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
HRegionInfo hri = pair.getFirst();
if (force) this.assignmentManager.clearRegionFromTransition(hri);
this.assignmentManager.unassign(hri, force);
}
/** /**
* Utility for constructing an instance of the passed HMaster class. * Utility for constructing an instance of the passed HMaster class.
* @param masterClass * @param masterClass

View File

@ -25,6 +25,7 @@ java_import org.apache.zookeeper.ZooKeeperMain
java_import org.apache.hadoop.hbase.HColumnDescriptor java_import org.apache.hadoop.hbase.HColumnDescriptor
java_import org.apache.hadoop.hbase.HTableDescriptor java_import org.apache.hadoop.hbase.HTableDescriptor
java_import org.apache.hadoop.hbase.HRegionInfo java_import org.apache.hadoop.hbase.HRegionInfo
java_import org.apache.hadoop.hbase.util.Bytes
java_import org.apache.zookeeper.ZooKeeper java_import org.apache.zookeeper.ZooKeeper
# Wrapper for org.apache.hadoop.hbase.client.HBaseAdmin # Wrapper for org.apache.hadoop.hbase.client.HBaseAdmin
@ -72,6 +73,20 @@ module Hbase
@admin.split(table_or_region_name) @admin.split(table_or_region_name)
end end
#----------------------------------------------------------------------------------------------
# Requests a cluster balance
# Returns true if balancer ran
def balancer()
@admin.balancer()
end
#----------------------------------------------------------------------------------------------
# Enable/disable balancer
# Returns previous balancer switch setting.
def balance_switch(enableDisable)
@admin.balanceSwitch(java.lang.Boolean::valueOf(enableDisable))
end
#---------------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------------
# Enables a table # Enables a table
def enable(table_name) def enable(table_name)
@ -150,15 +165,21 @@ module Hbase
end end
#---------------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------------
# Enables a region # Assign a region
def enable_region(region_name) def assign(region_name, force)
online(region_name, false) @admin.assign(Bytes::toBytes(region_name), java.lang.Boolean::valueOf(force))
end end
#---------------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------------
# Disables a region # Unassign a region
def disable_region(region_name) def unassign(region_name, force)
online(region_name, true) @admin.unassign(Bytes::toBytes(region_name), java.lang.Boolean::valueOf(force))
end
#----------------------------------------------------------------------------------------------
# Move a region
def move(encoded_region_name, server = nil)
@admin.move(encoded_region_name, server ? [server].to_java: nil)
end end
#---------------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------------
@ -364,12 +385,5 @@ module Hbase
put.add(HConstants::CATALOG_FAMILY, HConstants::REGIONINFO_QUALIFIER, Writables.getBytes(hri)) put.add(HConstants::CATALOG_FAMILY, HConstants::REGIONINFO_QUALIFIER, Writables.getBytes(hri))
meta.put(put) meta.put(put)
end end
#----------------------------------------------------------------------------------------------
# Invoke a ZooKeeper maintenance command
def zk(args)
line = args.join(' ')
line = 'help' if line.empty?
@zk_main.executeLine(line)
end
end end
end end

View File

@ -248,14 +248,16 @@ Shell.load_command_group(
:full_name => 'HBASE SURGERY TOOLS', :full_name => 'HBASE SURGERY TOOLS',
:comment => "WARNING: Above commands are for 'experts'-only as misuse can damage an install", :comment => "WARNING: Above commands are for 'experts'-only as misuse can damage an install",
:commands => %w[ :commands => %w[
assign
balancer
balance_switch
close_region close_region
compact compact
disable_region
enable_region
flush flush
major_compact major_compact
move
split split
zk unassign
zk_dump zk_dump
] ]
) )

View File

@ -20,16 +20,19 @@
module Shell module Shell
module Commands module Commands
class Zk < Command class Assign < Command
def help def help
return <<-EOF return <<-EOF
Low level ZooKeeper surgery tools. Type "zk 'help'" for more Assign a region. Add 'true' to force assign of a region. Use with caution.
information (Yes, you must quote 'help'). If region already assigned, this command will just go ahead and reassign
the region anyways. For experts only.
EOF EOF
end end
def command(*args) def command(region_name, force = 'false')
admin.zk(args) format_simple_command do
admin.assign(region_name, force)
end
end end
end end
end end

View File

@ -20,18 +20,18 @@
module Shell module Shell
module Commands module Commands
class DisableRegion < Command class BalanceSwitch < Command
def help def help
return <<-EOF return <<-EOF
Disable a single region. For example: Enable/Disable balancer. Returns previous balancer state.
hbase> disable_region 'REGIONNAME'
EOF EOF
end end
def command(region_name) def command(enableDisable)
format_simple_command do format_simple_command do
admin.disable_region(region_name) formatter.row([
admin.balance_switch(enableDisable)? "true" : "false"
])
end end
end end
end end

View File

@ -20,18 +20,19 @@
module Shell module Shell
module Commands module Commands
class EnableRegion < Command class Balancer < Command
def help def help
return <<-EOF return <<-EOF
Enable a single region. For example: Trigger the cluster balancer. Returns true if balancer ran. Otherwise
false (Will not run if regions in transition).
hbase> enable_region 'REGIONNAME'
EOF EOF
end end
def command(region_name) def command()
format_simple_command do format_simple_command do
admin.enable_region(region_name) formatter.row([
admin.balancer()? "true": "false"
])
end end
end end
end end

View File

@ -23,8 +23,12 @@ module Shell
class CloseRegion < Command class CloseRegion < Command
def help def help
return <<-EOF return <<-EOF
Close a single region. Optionally specify regionserver. Close a single region. Optionally specify regionserver. Connects to the
Examples: 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:
hbase> close_region 'REGIONNAME' hbase> close_region 'REGIONNAME'
hbase> close_region 'REGIONNAME', 'REGIONSERVER_IP:PORT' hbase> close_region 'REGIONNAME', 'REGIONSERVER_IP:PORT'

View File

@ -0,0 +1,48 @@
#
# Copyright 2010 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.
#
module Shell
module Commands
class Move < Command
def help
return <<-EOF
Move a region. Optionally specify target regionserver else we choose one
at random. NOTE: You pass the encoded region name, not the region name so
this command is a little different to the others. The encoded region name
is the hash suffix on region names: e.g. if the region name were
TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396. then
the encoded region name portion is 527db22f95c8a9e0116f0cc13c680396
A server name is its host, port plus startcode. For example:
host187.example.com,60020,1289493121758
Examples:
hbase> move 'ENCODED_REGIONNAME'
hbase> move 'ENCODED_REGIONNAME', 'SERVER_NAME'
EOF
end
def command(encoded_region_name, server_name = nil)
format_simple_command do
admin.move(encoded_region_name, server_name)
end
end
end
end
end

View File

@ -0,0 +1,43 @@
#
# Copyright 2010 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.
#
module Shell
module Commands
class Unassign < Command
def help
return <<-EOF
Unassign a region. Unassign will close region in current location and then
reopen it again. Pass 'true' to force the unassignment ('force' will clear
all in-memory state in master before the reassign). Use with caution. For
expert use only. Examples:
hbase> unassign 'REGIONNAME'
hbase> unassign 'REGIONNAME', true
EOF
end
def command(region_name, force = 'false')
format_simple_command do
admin.unassign(region_name, force)
end
end
end
end
end