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(
|
||||
"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) {
|
||||
status.setStatus("Running coprocessor pre-open hook");
|
||||
coprocessorHost.preOpen();
|
||||
|
|
|
@ -45,8 +45,8 @@ module Hbase
|
|||
end
|
||||
|
||||
# Create new one each time
|
||||
def table(table, formatter)
|
||||
::Hbase::Table.new(configuration, table, formatter)
|
||||
def table(table, shell)
|
||||
::Hbase::Table.new(configuration, table, shell)
|
||||
end
|
||||
|
||||
def replication_admin(formatter)
|
||||
|
|
|
@ -25,15 +25,102 @@ include Java
|
|||
module Hbase
|
||||
class Table
|
||||
include HBaseConstants
|
||||
attr_reader :table
|
||||
|
||||
def initialize(configuration, table_name, formatter)
|
||||
@table = org.apache.hadoop.hbase.client.HTable.new(configuration, table_name)
|
||||
# Add the command 'name' to table s.t. the shell command also called via '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
|
||||
|
||||
# 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
|
||||
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)
|
||||
family, qualifier = parse_column_name(column)
|
||||
if timestamp
|
||||
|
@ -46,13 +133,13 @@ module Hbase
|
|||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# Delete a cell
|
||||
def delete(row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||
deleteall(row, column, timestamp)
|
||||
def _delete_internal(row, column, timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP)
|
||||
deleteall_internal(row, column, timestamp)
|
||||
end
|
||||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# 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)
|
||||
if column
|
||||
family, qualifier = parse_column_name(column)
|
||||
|
@ -63,7 +150,7 @@ module Hbase
|
|||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# Increment a counter atomically
|
||||
def incr(row, column, value = nil)
|
||||
def _incr_internal(row, column, value = nil)
|
||||
value ||= 1
|
||||
family, qualifier = parse_column_name(column)
|
||||
@table.incrementColumnValue(row.to_s.to_java_bytes, family, qualifier, value)
|
||||
|
@ -71,7 +158,7 @@ module Hbase
|
|||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# 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
|
||||
scan = org.apache.hadoop.hbase.client.Scan.new
|
||||
scan.cache_blocks = false
|
||||
|
@ -98,7 +185,7 @@ module Hbase
|
|||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# 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)
|
||||
maxlength = -1
|
||||
|
||||
|
@ -188,7 +275,7 @@ module 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)
|
||||
# Format get request
|
||||
get = org.apache.hadoop.hbase.client.Get.new(row.to_s.to_java_bytes)
|
||||
|
@ -205,8 +292,8 @@ module Hbase
|
|||
end
|
||||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
# Scans whole table or a range of keys and returns rows matching specific criterias
|
||||
def scan(args = {})
|
||||
# Scans whole table or a range of keys and returns rows matching specific criteria
|
||||
def _scan_internal(args = {})
|
||||
unless args.kind_of?(Hash)
|
||||
raise ArgumentError, "Arguments should be a hash. Failed to parse #{args.inspect}, #{args.class}"
|
||||
end
|
||||
|
@ -298,8 +385,55 @@ module Hbase
|
|||
return ((block_given?) ? count : res)
|
||||
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
|
||||
#everthing below here is 'private' - can only be called from within the class context
|
||||
private
|
||||
|
||||
# Returns a list of column names in the table
|
||||
def get_all_columns
|
||||
|
@ -345,6 +479,5 @@ module Hbase
|
|||
end
|
||||
(maxlength != -1) ? val[0, maxlength] : val
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,7 +80,7 @@ module Shell
|
|||
end
|
||||
|
||||
def hbase_table(name)
|
||||
hbase.table(name, formatter)
|
||||
hbase.table(name, self)
|
||||
end
|
||||
|
||||
def hbase_replication_admin
|
||||
|
@ -93,10 +93,15 @@ module Shell
|
|||
|
||||
def export_commands(where)
|
||||
::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
|
||||
def #{cmd}(*args)
|
||||
@shell.command('#{cmd}', *args)
|
||||
ret = @shell.command('#{cmd}', *args)
|
||||
puts
|
||||
return ret
|
||||
end
|
||||
EOF
|
||||
end
|
||||
|
@ -106,8 +111,17 @@ module Shell
|
|||
::Shell.commands[command.to_s].new(self)
|
||||
end
|
||||
|
||||
#call the method 'command' on the specified command
|
||||
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
|
||||
|
||||
def print_banner
|
||||
|
@ -211,6 +225,7 @@ Shell.load_command_group(
|
|||
:commands => %w[
|
||||
status
|
||||
version
|
||||
table_help
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -234,6 +249,7 @@ Shell.load_command_group(
|
|||
show_filters
|
||||
alter_status
|
||||
alter_async
|
||||
get_table
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -21,14 +21,18 @@
|
|||
module Shell
|
||||
module Commands
|
||||
class Command
|
||||
attr_accessor :shell
|
||||
|
||||
def initialize(shell)
|
||||
self.shell = shell
|
||||
@shell = shell
|
||||
end
|
||||
|
||||
def command_safe(debug, *args)
|
||||
translate_hbase_exceptions(*args) { command(*args) }
|
||||
#wrap an execution of cmd to catch hbase exceptions
|
||||
# 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
|
||||
puts
|
||||
puts "ERROR: #{e}"
|
||||
|
@ -37,30 +41,28 @@ module Shell
|
|||
puts "Here is some help for this command:"
|
||||
puts help
|
||||
puts
|
||||
ensure
|
||||
return nil
|
||||
end
|
||||
|
||||
def admin
|
||||
shell.hbase_admin
|
||||
@shell.hbase_admin
|
||||
end
|
||||
|
||||
def table(name)
|
||||
shell.hbase_table(name)
|
||||
@shell.hbase_table(name)
|
||||
end
|
||||
|
||||
def replication_admin
|
||||
shell.hbase_replication_admin
|
||||
@shell.hbase_replication_admin
|
||||
end
|
||||
|
||||
def security_admin
|
||||
shell.hbase_security_admin
|
||||
@shell.hbase_security_admin
|
||||
end
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
def formatter
|
||||
shell.formatter
|
||||
@shell.formatter
|
||||
end
|
||||
|
||||
def format_simple_command
|
||||
|
@ -70,6 +72,14 @@ module Shell
|
|||
formatter.footer(now)
|
||||
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)
|
||||
yield
|
||||
rescue org.apache.hadoop.hbase.TableNotFoundException
|
||||
|
|
|
@ -35,10 +35,22 @@ parameter. Examples:
|
|||
hbase> count 't1', INTERVAL => 100000
|
||||
hbase> count 't1', 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
|
||||
end
|
||||
|
||||
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
|
||||
params = { 'INTERVAL' => params } if params.kind_of?(Fixnum)
|
||||
|
||||
|
@ -51,7 +63,7 @@ EOF
|
|||
# Call the counter method
|
||||
now = Time.now
|
||||
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}" ])
|
||||
end
|
||||
formatter.footer(now, count)
|
||||
|
@ -59,3 +71,6 @@ EOF
|
|||
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> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname)
|
||||
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
|
||||
end
|
||||
|
||||
def command(table, *args)
|
||||
format_simple_command do
|
||||
admin.create(table, *args)
|
||||
ret = admin.create(table, *args)
|
||||
end
|
||||
#and then return the table you just created
|
||||
table(table)
|
||||
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:
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
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
|
||||
table(table).delete(row, column, timestamp)
|
||||
table._delete_internal(row, column, timestamp)
|
||||
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', 'c1'
|
||||
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
|
||||
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
|
||||
table(table).deleteall(row, column, timestamp)
|
||||
table.deleteall_internal(row, column, timestamp)
|
||||
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', '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
|
||||
end
|
||||
|
||||
def command(table, row, *args)
|
||||
get(table(table), row, *args)
|
||||
end
|
||||
|
||||
def get(table, row, *args)
|
||||
now = Time.now
|
||||
formatter.header(["COLUMN", "CELL"])
|
||||
|
||||
table(table).get(row, *args) do |column, value|
|
||||
table._get_internal(row, *args) do |column, value|
|
||||
formatter.row([ column, value ])
|
||||
end
|
||||
|
||||
|
@ -52,3 +70,6 @@ EOF
|
|||
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:
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
def command(table, row, column, value)
|
||||
get_counter(table(table), row, column, value)
|
||||
end
|
||||
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}"
|
||||
else
|
||||
puts "No counter found at specified coordinates"
|
||||
|
@ -41,3 +49,5 @@ EOF
|
|||
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', 1
|
||||
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
|
||||
end
|
||||
|
||||
def command(table, row, column, value = nil)
|
||||
cnt = table(table).incr(row, column, value)
|
||||
def command(table, 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}"
|
||||
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:
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
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
|
||||
table(table).put(row, column, value, timestamp)
|
||||
table._put_internal(row, column, value, timestamp)
|
||||
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:
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
def command(table, args = {})
|
||||
scan(table(table), args)
|
||||
end
|
||||
|
||||
#internal command that actually does the scanning
|
||||
def scan(table, args = {})
|
||||
now = Time.now
|
||||
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 ])
|
||||
end
|
||||
|
||||
|
@ -74,3 +88,6 @@ EOF
|
|||
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.SingleColumnValueFilter;
|
||||
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.TaskMonitor;
|
||||
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.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
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,
|
||||
byte [] ...families)
|
||||
|
|
|
@ -310,5 +310,13 @@ module Hbase
|
|||
assert_no_match(eval("/" + key1 + "\\$(\\d+)/"), admin.describe(@test_name))
|
||||
assert_no_match(eval("/" + key2 + "/"), admin.describe(@test_name))
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue