HBASE-4554 Allow set/unset coprocessor table attributes from shell (Mingjie Lai)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1200436 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andrew Kyle Purtell 2011-11-10 17:15:20 +00:00
parent 076030550f
commit 373c98b0df
5 changed files with 113 additions and 2 deletions

View File

@ -739,6 +739,8 @@ Release 0.92.0 - Unreleased
HBASE-3939 Some crossports of Hadoop IPC fixes
HBASE-4756 Enable tab-completion in HBase shell (Ryan Thiessen)
HBASE-4759 Migrate from JUnit 4.8.2 to JUnit 4.10 (nkeywal)
HBASE-4554 Allow set/unset coprocessor table attributes from shell
(Mingjie Lai)
TASKS
HBASE-3559 Move report of split to master OFF the heartbeat channel

View File

@ -537,9 +537,9 @@ public final class HConstants {
Bytes.toString(ROOT_TABLE_NAME), SPLIT_LOGDIR_NAME }));
public static final Pattern CP_HTD_ATTR_KEY_PATTERN = Pattern.compile
("coprocessor\\$([0-9]+)", Pattern.CASE_INSENSITIVE);
("^coprocessor\\$([0-9]+)$", Pattern.CASE_INSENSITIVE);
public static final Pattern CP_HTD_ATTR_VALUE_PATTERN =
Pattern.compile("([^\\|]*)\\|([^\\|]+)\\|[\\s]*([\\d]*)[\\s]*(\\|.*)?");
Pattern.compile("(^[^\\|]*)\\|([^\\|]+)\\|[\\s]*([\\d]*)[\\s]*(\\|.*)?$");
public static final String CP_HTD_ATTR_VALUE_PARAM_KEY_PATTERN = "[^=,]+";
public static final String CP_HTD_ATTR_VALUE_PARAM_VALUE_PATTERN = "[^,]+";

View File

@ -364,6 +364,37 @@ module Hbase
htd.setReadOnly(JBoolean.valueOf(arg[READONLY])) if arg[READONLY]
htd.setMemStoreFlushSize(JLong.valueOf(arg[MEMSTORE_FLUSHSIZE])) if arg[MEMSTORE_FLUSHSIZE]
htd.setDeferredLogFlush(JBoolean.valueOf(arg[DEFERRED_LOG_FLUSH])) if arg[DEFERRED_LOG_FLUSH]
# set a coprocessor attribute
if arg.kind_of?(Hash)
arg.each do |key, value|
k = String.new(key) # prepare to strip
k.strip!
if (k =~ /coprocessor/i)
# validate coprocessor specs
v = String.new(value)
v.strip!
if !(v =~ /^([^\|]*)\|([^\|]+)\|[\s]*([\d]*)[\s]*(\|.*)?$/)
raise ArgumentError, "Coprocessor value doesn't match spec: #{v}"
end
# generate a coprocessor ordinal by checking max id of existing cps
maxId = 0
htd.getValues().each do |k1, v1|
attrName = org.apache.hadoop.hbase.util.Bytes.toString(k1.get())
# a cp key is coprocessor$(\d)
if (attrName =~ /coprocessor\$(\d+)/i)
ids = attrName.scan(/coprocessor\$(\d+)/i)
maxId = ids[0][0].to_i if ids[0][0].to_i > maxId
end
end
maxId += 1
htd.setValue(k + "\$" + maxId.to_s, value)
end
end
end
@admin.modifyTable(table_name.to_java_bytes, htd)
if wait == true
puts "Updating all regions with the new schema..."
@ -372,6 +403,25 @@ module Hbase
next
end
# Unset table attributes
if method == "table_att_unset"
if arg.kind_of?(Hash)
if (!arg[NAME])
next
end
if (htd.getValue(arg[NAME]) == nil)
raise ArgumentError, "Can not find attribute: #{arg[NAME]}"
end
htd.remove(arg[NAME].to_java_bytes)
@admin.modifyTable(table_name.to_java_bytes, htd)
if wait == true
puts "Updating all regions with the new schema..."
alter_status(table_name)
end
end
next
end
# Unknown method
raise ArgumentError, "Unknown method: #{method}"
end

View File

@ -48,6 +48,26 @@ For example, to change the max size of a family to 128MB, do:
hbase> alter 't1', METHOD => 'table_att', MAX_FILESIZE => '134217728'
You can add a table coprocessor by setting a table coprocessor attribute:
hbase> alter 't1', METHOD => 'table_att',
'coprocessor'=>'hdfs:///foo.jar|com.foo.FooRegionObserver|1001|arg1=1,arg2=2'
Since you can have multiple coprocessors configured for a table, a
sequence number will be automatically appended to the attribute name
to uniquely identify it.
The coprocessor attribute must match the pattern below in order for
the framework to understand how to load the coprocessor classes:
[coprocessor jar file location] | class name | [priority] | [arguments]
You can also remove a table-scope attribute:
hbase> alter 't1', METHOD => 'table_att_unset', NAME => 'MAX_FILESIZE'
hbase> alter 't1', METHOD => 'table_att_unset', NAME => 'coprocessor$1'
There could be more than one alteration in one command:
hbase> alter 't1', {NAME => 'f1'}, {NAME => 'f2', METHOD => 'delete'}

View File

@ -271,5 +271,44 @@ module Hbase
admin.alter(@test_name, true, METHOD => 'table_att', 'MAX_FILESIZE' => 12345678)
assert_match(/12345678/, admin.describe(@test_name))
end
define_test "alter should be able to change coprocessor attributes" do
drop_test_table(@test_name)
create_test_table(@test_name)
cp_key = "coprocessor"
class_name = "SimpleRegionObserver"
cp_value = "hdfs:///foo.jar|" + class_name + "|12|arg1=1,arg2=2"
# eval() is used to convert a string to regex
assert_no_match(eval("/" + class_name + "/"), admin.describe(@test_name))
assert_no_match(eval("/" + cp_key + "/"), admin.describe(@test_name))
admin.alter(@test_name, true, 'METHOD' => 'table_att', cp_key => cp_value)
assert_match(eval("/" + class_name + "/"), admin.describe(@test_name))
assert_match(eval("/" + cp_key + "\\$(\\d+)/"), admin.describe(@test_name))
end
define_test "alter should be able to remove a table attribute" do
drop_test_table(@test_name)
create_test_table(@test_name)
key1 = "coprocessor"
key2 = "MAX_FILESIZE"
admin.alter(@test_name, true, 'METHOD' => 'table_att', key1 => "|TestCP||")
admin.alter(@test_name, true, 'METHOD' => 'table_att', key2 => 12345678)
# eval() is used to convert a string to regex
assert_match(eval("/" + key1 + "\\$(\\d+)/"), admin.describe(@test_name))
assert_match(eval("/" + key2 + "/"), admin.describe(@test_name))
# get the cp key
cp_keys = admin.describe(@test_name).scan(/(coprocessor\$\d+)/i)
admin.alter(@test_name, true, 'METHOD' => 'table_att_unset', 'NAME' => cp_keys[0][0])
admin.alter(@test_name, true, 'METHOD' => 'table_att_unset', 'NAME' => key2)
assert_no_match(eval("/" + key1 + "\\$(\\d+)/"), admin.describe(@test_name))
assert_no_match(eval("/" + key2 + "/"), admin.describe(@test_name))
end
end
end