HBASE-5548 Add ability to get a table in the shell
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1332419 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
06c67c6b80
commit
aee5d1d286
|
@ -491,6 +491,22 @@ public class HRegion implements HeapSize { // , Writable{
|
||||||
MonitoredTask status = TaskMonitor.get().createStatus(
|
MonitoredTask status = TaskMonitor.get().createStatus(
|
||||||
"Initializing region " + this);
|
"Initializing region " + this);
|
||||||
|
|
||||||
|
long nextSeqId = -1;
|
||||||
|
try {
|
||||||
|
nextSeqId = initializeRegionInternals(reporter, status);
|
||||||
|
return nextSeqId;
|
||||||
|
} finally {
|
||||||
|
// nextSeqid will be -1 if the initialization fails.
|
||||||
|
// At least it will be 0 otherwise.
|
||||||
|
if (nextSeqId == -1) {
|
||||||
|
status
|
||||||
|
.abort("Exception during region " + this.getRegionNameAsString() + " initialization.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long initializeRegionInternals(final CancelableProgressable reporter, MonitoredTask status)
|
||||||
|
throws IOException, UnsupportedEncodingException {
|
||||||
if (coprocessorHost != null) {
|
if (coprocessorHost != null) {
|
||||||
status.setStatus("Running coprocessor pre-open hook");
|
status.setStatus("Running coprocessor pre-open hook");
|
||||||
coprocessorHost.preOpen();
|
coprocessorHost.preOpen();
|
||||||
|
|
|
@ -45,8 +45,8 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create new one each time
|
# Create new one each time
|
||||||
def table(table, formatter)
|
def table(table, shell)
|
||||||
::Hbase::Table.new(configuration, table, formatter)
|
::Hbase::Table.new(configuration, table, shell)
|
||||||
end
|
end
|
||||||
|
|
||||||
def replication_admin(formatter)
|
def replication_admin(formatter)
|
||||||
|
|
|
@ -25,15 +25,102 @@ include Java
|
||||||
module Hbase
|
module Hbase
|
||||||
class Table
|
class Table
|
||||||
include HBaseConstants
|
include HBaseConstants
|
||||||
attr_reader :table
|
|
||||||
|
|
||||||
def initialize(configuration, table_name, formatter)
|
# Add the command 'name' to table s.t. the shell command also called via 'name'
|
||||||
@table = org.apache.hadoop.hbase.client.HTable.new(configuration, table_name)
|
# and has an internal method also called 'name'.
|
||||||
|
#
|
||||||
|
# e.g. name = scan, adds table.scan which calls Scan.scan
|
||||||
|
def self.add_shell_command(name)
|
||||||
|
self.add_command(name, name, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# add a named command to the table instance
|
||||||
|
#
|
||||||
|
# name - name of the command that should added to the table
|
||||||
|
# (eg. sending 'scan' here would allow you to do table.scan)
|
||||||
|
# shell_command - name of the command in the shell
|
||||||
|
# internal_method_name - name of the method in the shell command to forward the call
|
||||||
|
def self.add_command(name, shell_command, internal_method_name)
|
||||||
|
method = name.to_sym
|
||||||
|
self.class_eval do
|
||||||
|
define_method method do |*args|
|
||||||
|
@shell.internal_command(shell_command, internal_method_name, self, *args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# General help for the table
|
||||||
|
# class level so we can call it from anywhere
|
||||||
|
def self.help
|
||||||
|
return <<-EOF
|
||||||
|
Help for table-reference commands.
|
||||||
|
|
||||||
|
You can either create a table via 'create' and then manipulate the table via commands like 'put', 'get', etc.
|
||||||
|
See the standard help information for how to use each of these commands.
|
||||||
|
|
||||||
|
However, as of 0.96, you can also get a reference to a table, on which you can invoke commands.
|
||||||
|
For instance, you can get create a table and keep around a reference to it via:
|
||||||
|
|
||||||
|
hbase> t = create 't', 'cf'
|
||||||
|
|
||||||
|
Or, if you have already created the table, you can get a reference to it:
|
||||||
|
|
||||||
|
hbase> t = get_table 't'
|
||||||
|
|
||||||
|
You can do things like call 'put' on the table:
|
||||||
|
|
||||||
|
hbase> t.put 'r', 'cf:q', 'v'
|
||||||
|
|
||||||
|
which puts a row 'r' with column family 'cf', qualifier 'q' and value 'v' into table t.
|
||||||
|
|
||||||
|
To read the data out, you can scan the table:
|
||||||
|
|
||||||
|
hbase> t.scan
|
||||||
|
|
||||||
|
which will read all the rows in table 't'.
|
||||||
|
|
||||||
|
Essentially, any command that takes a table name can also be done via table reference.
|
||||||
|
Other commands include things like: get, delete, deleteall,
|
||||||
|
get_all_columns, get_counter, count, incr. These functions, along with
|
||||||
|
the standard JRuby object methods are also available via tab completion.
|
||||||
|
|
||||||
|
For more information on how to use each of these commands, you can also just type:
|
||||||
|
|
||||||
|
hbase> t.help 'scan'
|
||||||
|
|
||||||
|
which will output more information on how to use that command.
|
||||||
|
|
||||||
|
You can also do general admin actions directly on a table; things like enable, disable,
|
||||||
|
flush and drop just by typing:
|
||||||
|
|
||||||
|
hbase> t.enable
|
||||||
|
hbase> t.flush
|
||||||
|
hbase> t.disable
|
||||||
|
hbase> t.drop
|
||||||
|
|
||||||
|
Note that after dropping a table, your reference to it becomes useless and further usage
|
||||||
|
is undefined (and not recommended).
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# let external objects read the underlying table object
|
||||||
|
attr_reader :table
|
||||||
|
# let external objects read the table name
|
||||||
|
attr_reader :name
|
||||||
|
|
||||||
|
def initialize(configuration, table_name, shell)
|
||||||
|
@table = org.apache.hadoop.hbase.client.HTable.new(configuration, table_name)
|
||||||
|
@name = table_name
|
||||||
|
@shell = shell
|
||||||
|
end
|
||||||
|
|
||||||
|
# Note the below methods are prefixed with '_' to hide them from the average user, as
|
||||||
|
# they will be much less likely to tab complete to the 'dangerous' internal method
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Put a cell 'value' at specified table/row/column
|
# Put a cell 'value' at specified table/row/column
|
||||||
def put(row, column, value, timestamp = nil)
|
def _put_internal(row, column, value, timestamp = nil)
|
||||||
p = org.apache.hadoop.hbase.client.Put.new(row.to_s.to_java_bytes)
|
p = org.apache.hadoop.hbase.client.Put.new(row.to_s.to_java_bytes)
|
||||||
family, qualifier = parse_column_name(column)
|
family, qualifier = parse_column_name(column)
|
||||||
if timestamp
|
if timestamp
|
||||||
|
@ -46,13 +133,13 @@ module Hbase
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Delete a cell
|
# Delete a cell
|
||||||
def delete(row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
def _delete_internal(row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||||
deleteall(row, column, timestamp)
|
deleteall_internal(row, column, timestamp)
|
||||||
end
|
end
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Delete a row
|
# Delete a row
|
||||||
def deleteall(row, column = nil, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
def _deleteall_internal(row, column = nil, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||||
d = org.apache.hadoop.hbase.client.Delete.new(row.to_s.to_java_bytes, timestamp, nil)
|
d = org.apache.hadoop.hbase.client.Delete.new(row.to_s.to_java_bytes, timestamp, nil)
|
||||||
if column
|
if column
|
||||||
family, qualifier = parse_column_name(column)
|
family, qualifier = parse_column_name(column)
|
||||||
|
@ -63,7 +150,7 @@ module Hbase
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Increment a counter atomically
|
# Increment a counter atomically
|
||||||
def incr(row, column, value = nil)
|
def _incr_internal(row, column, value = nil)
|
||||||
value ||= 1
|
value ||= 1
|
||||||
family, qualifier = parse_column_name(column)
|
family, qualifier = parse_column_name(column)
|
||||||
@table.incrementColumnValue(row.to_s.to_java_bytes, family, qualifier, value)
|
@table.incrementColumnValue(row.to_s.to_java_bytes, family, qualifier, value)
|
||||||
|
@ -71,7 +158,7 @@ module Hbase
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Count rows in a table
|
# Count rows in a table
|
||||||
def count(interval = 1000, caching_rows = 10)
|
def _count_internal(interval = 1000, caching_rows = 10)
|
||||||
# We can safely set scanner caching with the first key only filter
|
# We can safely set scanner caching with the first key only filter
|
||||||
scan = org.apache.hadoop.hbase.client.Scan.new
|
scan = org.apache.hadoop.hbase.client.Scan.new
|
||||||
scan.cache_blocks = false
|
scan.cache_blocks = false
|
||||||
|
@ -98,7 +185,7 @@ module Hbase
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Get from table
|
# Get from table
|
||||||
def get(row, *args)
|
def _get_internal(row, *args)
|
||||||
get = org.apache.hadoop.hbase.client.Get.new(row.to_s.to_java_bytes)
|
get = org.apache.hadoop.hbase.client.Get.new(row.to_s.to_java_bytes)
|
||||||
maxlength = -1
|
maxlength = -1
|
||||||
|
|
||||||
|
@ -188,7 +275,7 @@ module Hbase
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Fetches and decodes a counter value from hbase
|
# Fetches and decodes a counter value from hbase
|
||||||
def get_counter(row, column)
|
def _get_counter_internal(row, column)
|
||||||
family, qualifier = parse_column_name(column.to_s)
|
family, qualifier = parse_column_name(column.to_s)
|
||||||
# Format get request
|
# Format get request
|
||||||
get = org.apache.hadoop.hbase.client.Get.new(row.to_s.to_java_bytes)
|
get = org.apache.hadoop.hbase.client.Get.new(row.to_s.to_java_bytes)
|
||||||
|
@ -205,8 +292,8 @@ module Hbase
|
||||||
end
|
end
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
# Scans whole table or a range of keys and returns rows matching specific criterias
|
# Scans whole table or a range of keys and returns rows matching specific criteria
|
||||||
def scan(args = {})
|
def _scan_internal(args = {})
|
||||||
unless args.kind_of?(Hash)
|
unless args.kind_of?(Hash)
|
||||||
raise ArgumentError, "Arguments should be a hash. Failed to parse #{args.inspect}, #{args.class}"
|
raise ArgumentError, "Arguments should be a hash. Failed to parse #{args.inspect}, #{args.class}"
|
||||||
end
|
end
|
||||||
|
@ -298,8 +385,55 @@ module Hbase
|
||||||
return ((block_given?) ? count : res)
|
return ((block_given?) ? count : res)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#----------------------------
|
||||||
|
# Add general administration utilities to the shell
|
||||||
|
# each of the names below adds this method name to the table
|
||||||
|
# by callling the corresponding method in the shell
|
||||||
|
# Add single method utilities to the current class
|
||||||
|
# Generally used for admin functions which just have one name and take the table name
|
||||||
|
def self.add_admin_utils(*args)
|
||||||
|
args.each do |method|
|
||||||
|
define_method method do
|
||||||
|
@shell.command(method, @name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#Add the following admin utilities to the table
|
||||||
|
add_admin_utils :enable, :disable, :flush, :drop, :describe
|
||||||
|
|
||||||
|
#----------------------------
|
||||||
|
#give the general help for the table
|
||||||
|
# or the named command
|
||||||
|
def help (command = nil)
|
||||||
|
#if there is a command, get the per-command help from the shell
|
||||||
|
if command
|
||||||
|
begin
|
||||||
|
return @shell.help_command(command)
|
||||||
|
rescue NoMethodError
|
||||||
|
puts "Command \'#{command}\' does not exist. Please see general table help."
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return @shell.help('table_help')
|
||||||
|
end
|
||||||
|
|
||||||
|
# Table to string
|
||||||
|
def to_s
|
||||||
|
cl = self.class()
|
||||||
|
return "#{cl} - #{@name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Standard ruby call to get the return value for an object
|
||||||
|
# overriden here so we get sane semantics for printing a table on return
|
||||||
|
def inspect
|
||||||
|
to_s
|
||||||
|
end
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------
|
||||||
# Helper methods
|
# Helper methods
|
||||||
|
#everthing below here is 'private' - can only be called from within the class context
|
||||||
|
private
|
||||||
|
|
||||||
# Returns a list of column names in the table
|
# Returns a list of column names in the table
|
||||||
def get_all_columns
|
def get_all_columns
|
||||||
|
@ -345,6 +479,5 @@ module Hbase
|
||||||
end
|
end
|
||||||
(maxlength != -1) ? val[0, maxlength] : val
|
(maxlength != -1) ? val[0, maxlength] : val
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -80,7 +80,7 @@ module Shell
|
||||||
end
|
end
|
||||||
|
|
||||||
def hbase_table(name)
|
def hbase_table(name)
|
||||||
hbase.table(name, formatter)
|
hbase.table(name, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def hbase_replication_admin
|
def hbase_replication_admin
|
||||||
|
@ -93,10 +93,15 @@ module Shell
|
||||||
|
|
||||||
def export_commands(where)
|
def export_commands(where)
|
||||||
::Shell.commands.keys.each do |cmd|
|
::Shell.commands.keys.each do |cmd|
|
||||||
|
# here where is the IRB namespace
|
||||||
|
# this method just adds the call to the specified command
|
||||||
|
# which just references back to 'this' shell object
|
||||||
|
# a decently extensible way to add commands
|
||||||
where.send :instance_eval, <<-EOF
|
where.send :instance_eval, <<-EOF
|
||||||
def #{cmd}(*args)
|
def #{cmd}(*args)
|
||||||
@shell.command('#{cmd}', *args)
|
ret = @shell.command('#{cmd}', *args)
|
||||||
puts
|
puts
|
||||||
|
return ret
|
||||||
end
|
end
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
@ -106,8 +111,17 @@ module Shell
|
||||||
::Shell.commands[command.to_s].new(self)
|
::Shell.commands[command.to_s].new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#call the method 'command' on the specified command
|
||||||
def command(command, *args)
|
def command(command, *args)
|
||||||
command_instance(command).command_safe(self.debug, *args)
|
internal_command(command, :command, *args)
|
||||||
|
end
|
||||||
|
|
||||||
|
#call a specific internal method in the command instance
|
||||||
|
# command - name of the command to call
|
||||||
|
# method_name - name of the method on the command to call. Defaults to just 'command'
|
||||||
|
# args - to be passed to the named method
|
||||||
|
def internal_command(command, method_name= :command, *args)
|
||||||
|
command_instance(command).command_safe(self.debug,method_name, *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_banner
|
def print_banner
|
||||||
|
@ -211,6 +225,7 @@ Shell.load_command_group(
|
||||||
:commands => %w[
|
:commands => %w[
|
||||||
status
|
status
|
||||||
version
|
version
|
||||||
|
table_help
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -234,6 +249,7 @@ Shell.load_command_group(
|
||||||
show_filters
|
show_filters
|
||||||
alter_status
|
alter_status
|
||||||
alter_async
|
alter_async
|
||||||
|
get_table
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,18 @@
|
||||||
module Shell
|
module Shell
|
||||||
module Commands
|
module Commands
|
||||||
class Command
|
class Command
|
||||||
attr_accessor :shell
|
|
||||||
|
|
||||||
def initialize(shell)
|
def initialize(shell)
|
||||||
self.shell = shell
|
@shell = shell
|
||||||
end
|
end
|
||||||
|
|
||||||
def command_safe(debug, *args)
|
#wrap an execution of cmd to catch hbase exceptions
|
||||||
translate_hbase_exceptions(*args) { command(*args) }
|
# cmd - command name to execture
|
||||||
|
# args - arguments to pass to the command
|
||||||
|
def command_safe(debug, cmd = :command, *args)
|
||||||
|
# send is internal ruby method to call 'cmd' with *args
|
||||||
|
#(everything is a message, so this is just the formal semantics to support that idiom)
|
||||||
|
translate_hbase_exceptions(*args) { send(cmd,*args) }
|
||||||
rescue => e
|
rescue => e
|
||||||
puts
|
puts
|
||||||
puts "ERROR: #{e}"
|
puts "ERROR: #{e}"
|
||||||
|
@ -37,30 +41,28 @@ module Shell
|
||||||
puts "Here is some help for this command:"
|
puts "Here is some help for this command:"
|
||||||
puts help
|
puts help
|
||||||
puts
|
puts
|
||||||
ensure
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def admin
|
def admin
|
||||||
shell.hbase_admin
|
@shell.hbase_admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def table(name)
|
def table(name)
|
||||||
shell.hbase_table(name)
|
@shell.hbase_table(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def replication_admin
|
def replication_admin
|
||||||
shell.hbase_replication_admin
|
@shell.hbase_replication_admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def security_admin
|
def security_admin
|
||||||
shell.hbase_security_admin
|
@shell.hbase_security_admin
|
||||||
end
|
end
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
def formatter
|
def formatter
|
||||||
shell.formatter
|
@shell.formatter
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_simple_command
|
def format_simple_command
|
||||||
|
@ -70,6 +72,14 @@ module Shell
|
||||||
formatter.footer(now)
|
formatter.footer(now)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def format_and_return_simple_command
|
||||||
|
now = Time.now
|
||||||
|
ret = yield
|
||||||
|
formatter.header
|
||||||
|
formatter.footer(now)
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
def translate_hbase_exceptions(*args)
|
def translate_hbase_exceptions(*args)
|
||||||
yield
|
yield
|
||||||
rescue org.apache.hadoop.hbase.TableNotFoundException
|
rescue org.apache.hadoop.hbase.TableNotFoundException
|
||||||
|
|
|
@ -35,10 +35,22 @@ parameter. Examples:
|
||||||
hbase> count 't1', INTERVAL => 100000
|
hbase> count 't1', INTERVAL => 100000
|
||||||
hbase> count 't1', CACHE => 1000
|
hbase> count 't1', CACHE => 1000
|
||||||
hbase> count 't1', INTERVAL => 10, CACHE => 1000
|
hbase> count 't1', INTERVAL => 10, CACHE => 1000
|
||||||
|
|
||||||
|
The same commands also can be run on a table reference. Suppose you had a reference
|
||||||
|
t to table 't1', the corresponding commands would be:
|
||||||
|
|
||||||
|
hbase> t.count
|
||||||
|
hbase> t.count INTERVAL => 100000
|
||||||
|
hbase> t.count CACHE => 1000
|
||||||
|
hbase> t.count INTERVAL => 10, CACHE => 1000
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, params = {})
|
def command(table, params = {})
|
||||||
|
count(table(table), params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def count(table, params = {})
|
||||||
# If the second parameter is an integer, then it is the old command syntax
|
# If the second parameter is an integer, then it is the old command syntax
|
||||||
params = { 'INTERVAL' => params } if params.kind_of?(Fixnum)
|
params = { 'INTERVAL' => params } if params.kind_of?(Fixnum)
|
||||||
|
|
||||||
|
@ -51,7 +63,7 @@ EOF
|
||||||
# Call the counter method
|
# Call the counter method
|
||||||
now = Time.now
|
now = Time.now
|
||||||
formatter.header
|
formatter.header
|
||||||
count = table(table).count(params['INTERVAL'].to_i, params['CACHE'].to_i) do |cnt, row|
|
count = table._count_internal(params['INTERVAL'].to_i, params['CACHE'].to_i) do |cnt, row|
|
||||||
formatter.row([ "Current count: #{cnt}, row: #{row}" ])
|
formatter.row([ "Current count: #{cnt}, row: #{row}" ])
|
||||||
end
|
end
|
||||||
formatter.footer(now, count)
|
formatter.footer(now, count)
|
||||||
|
@ -59,3 +71,6 @@ EOF
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#Add the method table.count that calls count.count
|
||||||
|
::Hbase::Table.add_shell_command("count")
|
||||||
|
|
|
@ -38,13 +38,22 @@ Examples:
|
||||||
hbase> # Optionally pre-split the table into NUMREGIONS, using
|
hbase> # Optionally pre-split the table into NUMREGIONS, using
|
||||||
hbase> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname)
|
hbase> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname)
|
||||||
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
|
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
|
||||||
|
|
||||||
|
You can also keep around a reference to the created table:
|
||||||
|
|
||||||
|
hbase> t1 = create 't1', 'f1'
|
||||||
|
|
||||||
|
Which gives you a reference to the table named 't1', on which you can then
|
||||||
|
call methods.
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, *args)
|
def command(table, *args)
|
||||||
format_simple_command do
|
format_simple_command do
|
||||||
admin.create(table, *args)
|
ret = admin.create(table, *args)
|
||||||
end
|
end
|
||||||
|
#and then return the table you just created
|
||||||
|
table(table)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,14 +30,26 @@ versions. To delete a cell from 't1' at row 'r1' under column 'c1'
|
||||||
marked with the time 'ts1', do:
|
marked with the time 'ts1', do:
|
||||||
|
|
||||||
hbase> delete 't1', 'r1', 'c1', ts1
|
hbase> delete 't1', 'r1', 'c1', ts1
|
||||||
|
|
||||||
|
The same command can also be run on a table reference. Suppose you had a reference
|
||||||
|
t to table 't1', the corresponding command would be:
|
||||||
|
|
||||||
|
hbase> t.delete 'r1', 'c1', ts1
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
def command(table, row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||||
|
delete(table(table), row, column, timestamp)
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(table, row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||||
format_simple_command do
|
format_simple_command do
|
||||||
table(table).delete(row, column, timestamp)
|
table._delete_internal(row, column, timestamp)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#Add the method table.delete that calls delete.delete
|
||||||
|
::Hbase::Table.add_shell_command("delete")
|
|
@ -29,14 +29,28 @@ a column and timestamp. Examples:
|
||||||
hbase> deleteall 't1', 'r1'
|
hbase> deleteall 't1', 'r1'
|
||||||
hbase> deleteall 't1', 'r1', 'c1'
|
hbase> deleteall 't1', 'r1', 'c1'
|
||||||
hbase> deleteall 't1', 'r1', 'c1', ts1
|
hbase> deleteall 't1', 'r1', 'c1', ts1
|
||||||
|
|
||||||
|
The same commands also can be run on a table reference. Suppose you had a reference
|
||||||
|
t to table 't1', the corresponding command would be:
|
||||||
|
|
||||||
|
hbase> t.deleteall 'r1'
|
||||||
|
hbase> t.deleteall 'r1', 'c1'
|
||||||
|
hbase> t.deleteall 'r1', 'c1', ts1
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, row, column = nil, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
def command(table, row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||||
|
deleteall(table(table), row, column, timestamp)
|
||||||
|
end
|
||||||
|
|
||||||
|
def deleteall(table, row, column = nil, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||||
format_simple_command do
|
format_simple_command do
|
||||||
table(table).deleteall(row, column, timestamp)
|
table.deleteall_internal(row, column, timestamp)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#Add the method table.deleteall that calls deleteall.deleteall
|
||||||
|
::Hbase::Table.add_shell_command("deleteall")
|
|
@ -36,14 +36,32 @@ a dictionary of column(s), timestamp, timerange and versions. Examples:
|
||||||
hbase> get 't1', 'r1', 'c1'
|
hbase> get 't1', 'r1', 'c1'
|
||||||
hbase> get 't1', 'r1', 'c1', 'c2'
|
hbase> get 't1', 'r1', 'c1', 'c2'
|
||||||
hbase> get 't1', 'r1', ['c1', 'c2']
|
hbase> get 't1', 'r1', ['c1', 'c2']
|
||||||
|
|
||||||
|
The same commands also can be run on a reference to a table (obtained via get_table or
|
||||||
|
create_table). Suppose you had a reference t to table 't1', the corresponding commands would be:
|
||||||
|
|
||||||
|
hbase> t.get 'r1'
|
||||||
|
hbase> t.get 'r1', {TIMERANGE => [ts1, ts2]}
|
||||||
|
hbase> t.get 'r1', {COLUMN => 'c1'}
|
||||||
|
hbase> t.get 'r1', {COLUMN => ['c1', 'c2', 'c3']}
|
||||||
|
hbase> t.get 'r1', {COLUMN => 'c1', TIMESTAMP => ts1}
|
||||||
|
hbase> t.get 'r1', {COLUMN => 'c1', TIMERANGE => [ts1, ts2], VERSIONS => 4}
|
||||||
|
hbase> t.get 'r1', {COLUMN => 'c1', TIMESTAMP => ts1, VERSIONS => 4}
|
||||||
|
hbase> t.get 'r1', 'c1'
|
||||||
|
hbase> t.get 'r1', 'c1', 'c2'
|
||||||
|
hbase> t.get 'r1', ['c1', 'c2']
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, row, *args)
|
def command(table, row, *args)
|
||||||
|
get(table(table), row, *args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(table, row, *args)
|
||||||
now = Time.now
|
now = Time.now
|
||||||
formatter.header(["COLUMN", "CELL"])
|
formatter.header(["COLUMN", "CELL"])
|
||||||
|
|
||||||
table(table).get(row, *args) do |column, value|
|
table._get_internal(row, *args) do |column, value|
|
||||||
formatter.row([ column, value ])
|
formatter.row([ column, value ])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,3 +70,6 @@ EOF
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#add get command to table
|
||||||
|
::Hbase::Table.add_shell_command('get')
|
||||||
|
|
|
@ -28,11 +28,19 @@ A cell cell should be managed with atomic increment function oh HBase
|
||||||
and the data should be binary encoded. Example:
|
and the data should be binary encoded. Example:
|
||||||
|
|
||||||
hbase> get_counter 't1', 'r1', 'c1'
|
hbase> get_counter 't1', 'r1', 'c1'
|
||||||
|
|
||||||
|
The same commands also can be run on a table reference. Suppose you had a reference
|
||||||
|
t to table 't1', the corresponding command would be:
|
||||||
|
|
||||||
|
hbase> t.get_counter 'r1', 'c1'
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def command(table, row, column, value)
|
||||||
|
get_counter(table(table), row, column, value)
|
||||||
|
end
|
||||||
def command(table, row, column, value = nil)
|
def command(table, row, column, value = nil)
|
||||||
if cnt = table(table).get_counter(row, column)
|
if cnt = table._get_counter_internal(row, column)
|
||||||
puts "COUNTER VALUE = #{cnt}"
|
puts "COUNTER VALUE = #{cnt}"
|
||||||
else
|
else
|
||||||
puts "No counter found at specified coordinates"
|
puts "No counter found at specified coordinates"
|
||||||
|
@ -41,3 +49,5 @@ EOF
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
::Hbase::Table.add_shell_command('get_counter')
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#
|
||||||
|
# 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 GetTable < Command
|
||||||
|
def help
|
||||||
|
return <<-EOF
|
||||||
|
Get the given table name and return it as an actual object to
|
||||||
|
be manipulated by the user. See table.help for more information
|
||||||
|
on how to use the table.
|
||||||
|
Eg.
|
||||||
|
|
||||||
|
hbase> t1 = get_table 't1'
|
||||||
|
|
||||||
|
returns the table named 't1' as a table object. You can then do
|
||||||
|
|
||||||
|
hbase> t1.help
|
||||||
|
|
||||||
|
which will then print the help for that table.
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
def command(table, *args)
|
||||||
|
format_and_return_simple_command do
|
||||||
|
table(table)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -30,13 +30,27 @@ To increment a cell value in table 't1' at row 'r1' under column
|
||||||
hbase> incr 't1', 'r1', 'c1'
|
hbase> incr 't1', 'r1', 'c1'
|
||||||
hbase> incr 't1', 'r1', 'c1', 1
|
hbase> incr 't1', 'r1', 'c1', 1
|
||||||
hbase> incr 't1', 'r1', 'c1', 10
|
hbase> incr 't1', 'r1', 'c1', 10
|
||||||
|
|
||||||
|
The same commands also can be run on a table reference. Suppose you had a reference
|
||||||
|
t to table 't1', the corresponding command would be:
|
||||||
|
|
||||||
|
hbase> t.incr 'r1', 'c1'
|
||||||
|
hbase> t.incr 'r1', 'c1', 1
|
||||||
|
hbase> t.incr 'r1', 'c1', 10
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, row, column, value = nil)
|
def command(table, row, column, value)
|
||||||
cnt = table(table).incr(row, column, value)
|
incr(table(table), row, column, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def incr(table, row, column, value = nil)
|
||||||
|
cnt = table._incr_internal(row, column, value)
|
||||||
puts "COUNTER VALUE = #{cnt}"
|
puts "COUNTER VALUE = #{cnt}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#add incr comamnd to Table
|
||||||
|
::Hbase::Table.add_shell_command("incr")
|
|
@ -28,14 +28,26 @@ timestamp coordinates. To put a cell value into table 't1' at
|
||||||
row 'r1' under column 'c1' marked with the time 'ts1', do:
|
row 'r1' under column 'c1' marked with the time 'ts1', do:
|
||||||
|
|
||||||
hbase> put 't1', 'r1', 'c1', 'value', ts1
|
hbase> put 't1', 'r1', 'c1', 'value', ts1
|
||||||
|
|
||||||
|
The same commands also can be run on a table reference. Suppose you had a reference
|
||||||
|
t to table 't1', the corresponding command would be:
|
||||||
|
|
||||||
|
hbase> t.put 'r1', 'c1', 'value', ts1
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, row, column, value, timestamp = nil)
|
def command(table, row, column, value, timestamp = nil)
|
||||||
|
put table(table), row, column, value, timestamp
|
||||||
|
end
|
||||||
|
|
||||||
|
def put(table, row, column, value, timestamp = nil)
|
||||||
format_simple_command do
|
format_simple_command do
|
||||||
table(table).put(row, column, value, timestamp)
|
table._put_internal(row, column, value, timestamp)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#Add the method table.put that calls Put.put
|
||||||
|
::Hbase::Table.add_shell_command("put")
|
|
@ -58,14 +58,28 @@ cells). This option cannot be combined with requesting specific COLUMNS.
|
||||||
Disabled by default. Example:
|
Disabled by default. Example:
|
||||||
|
|
||||||
hbase> scan 't1', {RAW => true, VERSIONS => 10}
|
hbase> scan 't1', {RAW => true, VERSIONS => 10}
|
||||||
|
|
||||||
|
Scan can also be used directly from a table, by first getting a reference to a table, like such:
|
||||||
|
|
||||||
|
hbase> t = get_table 't'
|
||||||
|
hbase> t.scan
|
||||||
|
|
||||||
|
Note in the above situation, you can still provide all the filtering, columns, options, etc as
|
||||||
|
described above.
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def command(table, args = {})
|
def command(table, args = {})
|
||||||
|
scan(table(table), args)
|
||||||
|
end
|
||||||
|
|
||||||
|
#internal command that actually does the scanning
|
||||||
|
def scan(table, args = {})
|
||||||
now = Time.now
|
now = Time.now
|
||||||
formatter.header(["ROW", "COLUMN+CELL"])
|
formatter.header(["ROW", "COLUMN+CELL"])
|
||||||
|
|
||||||
count = table(table).scan(args) do |row, cells|
|
#actually do the scanning
|
||||||
|
count = table._scan_internal(args) do |row, cells|
|
||||||
formatter.row([ row, cells ])
|
formatter.row([ row, cells ])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -74,3 +88,6 @@ EOF
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#Add the method table.scan that calls Scan.scan
|
||||||
|
::Hbase::Table.add_shell_command("scan")
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#
|
||||||
|
# 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 TableHelp < Command
|
||||||
|
def help
|
||||||
|
return Hbase::Table.help
|
||||||
|
end
|
||||||
|
|
||||||
|
#just print the help
|
||||||
|
def command
|
||||||
|
# call the shell to get the nice formatting there
|
||||||
|
@shell.help_command 'table_help'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -69,6 +69,7 @@ import org.apache.hadoop.hbase.filter.NullComparator;
|
||||||
import org.apache.hadoop.hbase.filter.PrefixFilter;
|
import org.apache.hadoop.hbase.filter.PrefixFilter;
|
||||||
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
|
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
|
||||||
import org.apache.hadoop.hbase.master.HMaster;
|
import org.apache.hadoop.hbase.master.HMaster;
|
||||||
|
import org.apache.hadoop.hbase.monitoring.MonitoredRPCHandler;
|
||||||
import org.apache.hadoop.hbase.monitoring.MonitoredTask;
|
import org.apache.hadoop.hbase.monitoring.MonitoredTask;
|
||||||
import org.apache.hadoop.hbase.monitoring.TaskMonitor;
|
import org.apache.hadoop.hbase.monitoring.TaskMonitor;
|
||||||
import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;
|
import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;
|
||||||
|
@ -87,6 +88,7 @@ import org.apache.hadoop.hbase.util.PairOfSameType;
|
||||||
import org.apache.hadoop.hbase.util.Threads;
|
import org.apache.hadoop.hbase.util.Threads;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
@ -3459,6 +3461,45 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testcase to check state of region initialization task set to ABORTED or not if any exceptions
|
||||||
|
* during initialization
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testStatusSettingToAbortIfAnyExceptionDuringRegionInitilization() throws Exception {
|
||||||
|
HRegionInfo info = null;
|
||||||
|
try {
|
||||||
|
FileSystem fs = Mockito.mock(FileSystem.class);
|
||||||
|
Mockito.when(fs.exists((Path) Mockito.anyObject())).thenThrow(new IOException());
|
||||||
|
HTableDescriptor htd = new HTableDescriptor(tableName);
|
||||||
|
htd.addFamily(new HColumnDescriptor("cf"));
|
||||||
|
info = new HRegionInfo(htd.getName(), HConstants.EMPTY_BYTE_ARRAY,
|
||||||
|
HConstants.EMPTY_BYTE_ARRAY, false);
|
||||||
|
Path path = new Path(DIR + "testStatusSettingToAbortIfAnyExceptionDuringRegionInitilization");
|
||||||
|
// no where we are instantiating HStore in this test case so useTableNameGlobally is null. To
|
||||||
|
// avoid NullPointerException we are setting useTableNameGlobally to false.
|
||||||
|
SchemaMetrics.setUseTableNameInTest(false);
|
||||||
|
region = HRegion.newHRegion(path, null, fs, conf, info, htd, null);
|
||||||
|
// region initialization throws IOException and set task state to ABORTED.
|
||||||
|
region.initialize();
|
||||||
|
fail("Region initialization should fail due to IOException");
|
||||||
|
} catch (IOException io) {
|
||||||
|
List<MonitoredTask> tasks = TaskMonitor.get().getTasks();
|
||||||
|
for (MonitoredTask monitoredTask : tasks) {
|
||||||
|
if (!(monitoredTask instanceof MonitoredRPCHandler)
|
||||||
|
&& monitoredTask.getDescription().contains(region.toString())) {
|
||||||
|
assertTrue("Region state should be ABORTED.",
|
||||||
|
monitoredTask.getState().equals(MonitoredTask.State.ABORTED));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
HRegion.closeHRegion(region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void putData(int startRow, int numRows, byte [] qf,
|
private void putData(int startRow, int numRows, byte [] qf,
|
||||||
byte [] ...families)
|
byte [] ...families)
|
||||||
|
|
|
@ -310,5 +310,13 @@ module Hbase
|
||||||
assert_no_match(eval("/" + key1 + "\\$(\\d+)/"), admin.describe(@test_name))
|
assert_no_match(eval("/" + key1 + "\\$(\\d+)/"), admin.describe(@test_name))
|
||||||
assert_no_match(eval("/" + key2 + "/"), admin.describe(@test_name))
|
assert_no_match(eval("/" + key2 + "/"), admin.describe(@test_name))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
define_test "get_table should get a real table" do
|
||||||
|
drop_test_table(@test_name)
|
||||||
|
create_test_table(@test_name)
|
||||||
|
|
||||||
|
table = table(@test_name)
|
||||||
|
assert_not_equal(nil, table)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue