HBASE-2308 Fix the bin/rename_table.rb script, make it work again

git-svn-id: https://svn.apache.org/repos/asf/hadoop/hbase/trunk@921624 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2010-03-10 23:27:30 +00:00
parent 82e0f680ff
commit 6d0d1cc9a9
2 changed files with 60 additions and 71 deletions

View File

@ -231,6 +231,7 @@ Release 0.21.0 - Unreleased
HBASE-2299 [EC2] mapreduce fixups for PE HBASE-2299 [EC2] mapreduce fixups for PE
HBASE-2295 Row locks may deadlock with themselves HBASE-2295 Row locks may deadlock with themselves
(dhruba borthakur via Stack) (dhruba borthakur via Stack)
HBASE-2308 Fix the bin/rename_table.rb script, make it work again
IMPROVEMENTS IMPROVEMENTS
HBASE-1760 Cleanup TODOs in HTable HBASE-1760 Cleanup TODOs in HTable

View File

@ -1,9 +1,14 @@
# Script that renames table in hbase. As written, will not work for rare # Script that renames table in hbase. As written, will not work for rare
# case where there is more than one region in .META. table. Does the # case where there is more than one region in .META. table (You'd have to
# update of the hbase .META. and moves the directories in filesystem. # have a really massive hbase install). Does the update of the hbase
# HBase MUST be shutdown when you run this script. On successful rename, # .META. and moves the directories in the filesystem. Use at your own
# DOES NOT remove old directory from filesystem because was afraid this # risk. Before running you must DISABLE YOUR TABLE:
# script could remove the original table on error. #
# hbase> disable "YOUR_TABLE_NAME"
#
# Enable the new table after the script completes.
#
# hbase> enable "NEW_TABLE_NAME"
# #
# To see usage for this script, run: # To see usage for this script, run:
# #
@ -15,12 +20,14 @@ import org.apache.hadoop.hbase.util.FSUtils
import org.apache.hadoop.hbase.util.Bytes import org.apache.hadoop.hbase.util.Bytes
import org.apache.hadoop.hbase.util.Writables import org.apache.hadoop.hbase.util.Writables
import org.apache.hadoop.hbase.HConstants import org.apache.hadoop.hbase.HConstants
import org.apache.hadoop.hbase.client.Scan
import org.apache.hadoop.hbase.client.Delete
import org.apache.hadoop.hbase.client.Put
import org.apache.hadoop.hbase.client.HTable
import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.HBaseConfiguration
import org.apache.hadoop.hbase.HStoreKey
import org.apache.hadoop.hbase.HRegionInfo import org.apache.hadoop.hbase.HRegionInfo
import org.apache.hadoop.hbase.HTableDescriptor import org.apache.hadoop.hbase.HTableDescriptor
import org.apache.hadoop.hbase.io.ImmutableBytesWritable import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.regionserver.HLogEdit
import org.apache.hadoop.hbase.regionserver.HRegion import org.apache.hadoop.hbase.regionserver.HRegion
import org.apache.hadoop.fs.Path import org.apache.hadoop.fs.Path
import org.apache.hadoop.fs.FileSystem import org.apache.hadoop.fs.FileSystem
@ -65,8 +72,8 @@ if ARGV.size != 2
end end
# Check good table names were passed. # Check good table names were passed.
oldTableName = HTableDescriptor.isLegalTableName(ARGV[0].to_java_bytes) oldTableName = ARGV[0]
newTableName = HTableDescriptor.isLegalTableName(ARGV[1].to_java_bytes) newTableName = ARGV[1]
# Get configuration to use. # Get configuration to use.
c = HBaseConfiguration.new() c = HBaseConfiguration.new()
@ -79,46 +86,31 @@ fs = FileSystem.get(c)
# If new table directory does not exit, create it. Keep going if already # If new table directory does not exit, create it. Keep going if already
# exists because maybe we are rerunning script because it failed first # exists because maybe we are rerunning script because it failed first
# time. # time. Otherwise we are overwriting a pre-existing table.
rootdir = FSUtils.getRootDir(c) rootdir = FSUtils.getRootDir(c)
oldTableDir = Path.new(rootdir, Path.new(Bytes.toString(oldTableName))) oldTableDir = fs.makeQualified(Path.new(rootdir, Path.new(oldTableName)))
isDirExists(fs, oldTableDir) isDirExists(fs, oldTableDir)
newTableDir = Path.new(rootdir, Bytes.toString(newTableName)) newTableDir = fs.makeQualified(Path.new(rootdir, newTableName))
if !fs.exists(newTableDir) if !fs.exists(newTableDir)
fs.mkdirs(newTableDir) fs.mkdirs(newTableDir)
end end
# Get a logger and a metautils instance. # Get a logger and a metautils instance.
LOG = LogFactory.getLog(NAME) LOG = LogFactory.getLog(NAME)
utils = MetaUtils.new(c)
# Start. Get all meta rows. # Run through the meta table moving region mentions from old to new table name.
begin metaTable = HTable.new(c, HConstants::META_TABLE_NAME)
# Get list of all .META. regions that contain old table name # TODO: Start the scan at the old table offset in .META.
metas = utils.getMETARows(oldTableName) scan = Scan.new()
index = 0 scanner = metaTable.getScanner(scan)
for meta in metas while (result = scanner.next())
# For each row we find, move its region from old to new table. rowid = Bytes.toString(result.getRow())
# Need to update the encoded name in the hri as we move. oldHRI = Writables.getHRegionInfo(result.getValue(HConstants::CATALOG_FAMILY, HConstants::REGIONINFO_QUALIFIER))
# After move, delete old entry and create a new.
LOG.info("Scanning " + meta.getRegionNameAsString())
metaRegion = utils.getMetaRegion(meta)
scanner = metaRegion.getScanner(HConstants::COL_REGIONINFO_ARRAY, oldTableName,
HConstants::LATEST_TIMESTAMP, nil)
begin
key = HStoreKey.new()
value = TreeMap.new(Bytes.BYTES_COMPARATOR)
while scanner.next(key, value)
index = index + 1
keyStr = key.toString()
oldHRI = Writables.getHRegionInfo(value.get(HConstants::COL_REGIONINFO))
if !oldHRI if !oldHRI
raise IOError.new(index.to_s + " HRegionInfo is null for " + keyStr) raise IOError.new("HRegionInfo is null for " + rowid)
end
unless isTableRegion(oldTableName, oldHRI)
# If here, we passed out the table. Break.
break
end end
next unless isTableRegion(oldTableName.to_java_bytes, oldHRI)
puts oldHRI.toString()
oldRDir = Path.new(oldTableDir, Path.new(oldHRI.getEncodedName().to_s)) oldRDir = Path.new(oldTableDir, Path.new(oldHRI.getEncodedName().to_s))
if !fs.exists(oldRDir) if !fs.exists(oldRDir)
LOG.warn(oldRDir.toString() + " does not exist -- region " + LOG.warn(oldRDir.toString() + " does not exist -- region " +
@ -126,29 +118,25 @@ begin
else else
# Now make a new HRegionInfo to add to .META. for the new region. # Now make a new HRegionInfo to add to .META. for the new region.
newHRI = createHRI(newTableName, oldHRI) newHRI = createHRI(newTableName, oldHRI)
puts newHRI.toString()
newRDir = Path.new(newTableDir, Path.new(newHRI.getEncodedName().to_s)) newRDir = Path.new(newTableDir, Path.new(newHRI.getEncodedName().to_s))
# Move the region in filesystem # Move the region in filesystem
LOG.info("Renaming " + oldRDir.toString() + " as " + newRDir.toString()) LOG.info("Renaming " + oldRDir.toString() + " as " + newRDir.toString())
fs.rename(oldRDir, newRDir) fs.rename(oldRDir, newRDir)
# Removing old region from meta # Removing old region from meta
LOG.info("Removing " + Bytes.toString(key.getRow()) + " from .META.") LOG.info("Removing " + rowid + " from .META.")
metaRegion.deleteAll(key.getRow(), HConstants::LATEST_TIMESTAMP) d = Delete.new(result.getRow())
metaTable.delete(d)
# Create 'new' region # Create 'new' region
newR = HRegion.new(rootdir, utils.getLog(), fs, c, newHRI, nil) newR = HRegion.new(rootdir, nil, fs, c, newHRI, nil)
# Add new row. NOTE: Presumption is that only one .META. region. If not, # Add new row. NOTE: Presumption is that only one .META. region. If not,
# need to do the work to figure proper region to add this new region to. # need to do the work to figure proper region to add this new region to.
LOG.info("Adding to meta: " + newR.toString()) LOG.info("Adding to meta: " + newR.toString())
HRegion.addRegionToMETA(metaRegion, newR) p = Put.new(newR.getRegionName())
LOG.info("Done moving: " + Bytes.toString(key.getRow())) p.add(HConstants::CATALOG_FAMILY, HConstants::REGIONINFO_QUALIFIER, Writables.getBytes(newR.getRegionInfo()))
metaTable.put(p)
end end
# Need to clear value else we keep appending values.
value.clear()
end
ensure
scanner.close()
end
end
LOG.info("Renamed table -- manually delete " + oldTableDir.toString());
ensure
utils.shutdown()
end end
scanner.close()
fs.delete(oldTableDir)
LOG.info("DONE");