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:
parent
076030550f
commit
373c98b0df
|
@ -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
|
||||
|
|
|
@ -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 = "[^,]+";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue