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:
Michael Stack 2012-04-30 21:48:54 +00:00
parent 06c67c6b80
commit aee5d1d286
18 changed files with 468 additions and 41 deletions

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -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
] ]
) )

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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")

View File

@ -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")

View File

@ -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')

View File

@ -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')

View File

@ -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

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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