268 lines
8.3 KiB
Ruby
268 lines
8.3 KiB
Ruby
# File passed to org.jruby.Main by bin/hbase. Pollutes jirb with hbase imports
|
|
# and hbase commands and then loads jirb. Outputs a banner that tells user
|
|
# where to find help, shell version, and loads up a custom hirb.
|
|
|
|
# TODO: Add 'debug' support (client-side logs show in shell). Add it as
|
|
# command-line option and as command.
|
|
# TODO: Interrupt a table creation or a connection to a bad master. Currently
|
|
# has to time out.
|
|
# TODO: Add support for listing and manipulating catalog tables, etc.
|
|
# TODO: Fix 'irb: warn: can't alias help from irb_help.' in banner message
|
|
|
|
# Run the java magic include and import basic HBase types that will help ease
|
|
# hbase hacking.
|
|
include Java
|
|
import org.apache.hadoop.hbase.HBaseConfiguration
|
|
import org.apache.hadoop.hbase.client.HTable
|
|
import org.apache.hadoop.hbase.client.HBaseAdmin
|
|
import org.apache.hadoop.hbase.HColumnDescriptor
|
|
import org.apache.hadoop.hbase.HConstants
|
|
import org.apache.hadoop.hbase.HTableDescriptor
|
|
import org.apache.hadoop.hbase.io.BatchUpdate
|
|
|
|
# Some goodies for hirb. Should these be left up to the user's discretion?
|
|
require 'irb/completion'
|
|
|
|
# Add the $HBASE_HOME/bin directory, the location of this script, to the ruby
|
|
# load path so I can load up my HBase ruby modules
|
|
$LOAD_PATH.unshift File.dirname($PROGRAM_NAME)
|
|
# Require formatter and hbase
|
|
require 'Formatter'
|
|
require 'HBase'
|
|
|
|
# See if there are args for this shell. If any, read and then strip from ARGV
|
|
# so they don't go through to irb. Output shell 'usage' if user types '--help'
|
|
cmdline_help = <<HERE # HERE document output as shell usage
|
|
HBase Shell command-line options:
|
|
format Formatter for outputting results: console | html. Default: console
|
|
master HBase master shell should connect to: e.g --master=example:60000
|
|
HERE
|
|
master = nil
|
|
@formatter = Formatter::Console.new(STDOUT)
|
|
found = []
|
|
for arg in ARGV
|
|
if arg =~ /^--master=(.+)/i
|
|
master = $1
|
|
found.push(arg)
|
|
elsif arg =~ /^--format=(.+)/i
|
|
format = $1
|
|
if format =~ /^html$/i
|
|
@formatter = Formatter::XHTML.new(STDOUT)
|
|
elsif format =~ /^console$/i
|
|
# This is default
|
|
else
|
|
raise ArgumentError.new("Unsupported format " + arg)
|
|
end
|
|
elsif arg == '-h' || arg == '--help'
|
|
puts cmdline_help
|
|
exit
|
|
end
|
|
end
|
|
for arg in found
|
|
ARGV.delete(arg)
|
|
end
|
|
|
|
# Setup the HBase module. Create a configuration. If a master, set it.
|
|
@configuration = HBaseConfiguration.new()
|
|
@configuration.set("hbase.master", master) if master
|
|
# Do lazy create of admin because if we are pointed at bad master, it will hang
|
|
# shell on startup trying to connect.
|
|
@admin = nil
|
|
|
|
# Promote hbase constants to be constants of this module so can
|
|
# be used bare as keys in 'create', 'alter', etc. To see constants
|
|
# in IRB, type 'Object.constants'. Don't promote defaults because
|
|
# flattens all types to String. Can be confusing.
|
|
def promoteConstants(constants)
|
|
# The constants to import are all in uppercase
|
|
for c in constants
|
|
if c == c.upcase
|
|
eval("%s = \"%s\"" % [c, c]) unless c =~ /DEFAULT_.*/
|
|
end
|
|
end
|
|
end
|
|
promoteConstants(HColumnDescriptor.constants)
|
|
promoteConstants(HTableDescriptor.constants)
|
|
|
|
# Start of the hbase shell commands.
|
|
|
|
# General shell methods
|
|
|
|
def help
|
|
# Output help. Help used to be a dictionary of name to short and long
|
|
# descriptions emitted using Formatters but awkward getting it to show
|
|
# nicely on console; instead use a HERE document. Means we can't
|
|
# output help other than on console but not an issue at the moment.
|
|
# TODO: Add help to the commands themselves rather than keep it distinct
|
|
h = <<HERE
|
|
HBASE SHELL COMMANDS:
|
|
alter Alter column family schema in a table. Pass table name and a
|
|
dictionary specifying the new column family schema. Dictionaries
|
|
are described below in the GENERAL NOTES section. Dictionary must
|
|
include name of column family to alter. For example, to change
|
|
the 'f1' column family in table 't1' to have a MAX_VERSIONS of 5,
|
|
do:
|
|
|
|
hbase> alter 't1', {NAME => 'f1', MAX_VERSIONS => 5}
|
|
|
|
create Create table; pass a table name, a dictionary of specifications per
|
|
column family, and optionally, named parameters of table options.
|
|
Dictionaries are described below in the GENERAL NOTES section. Named
|
|
parameters are like dictionary elements with uppercase names
|
|
(constants) as keys and a '=>' key/value delimiter. Parameters are
|
|
comma-delimited. For example, to create a table named 't1' with an
|
|
alternate maximum region size and a single family named 'f1' with an
|
|
alternate maximum number of cells and 'record' compression, type:
|
|
|
|
hbase> create 't1' {NAME => 'f1', MAX_VERSIONS => 5, \
|
|
COMPRESSION => 'RECORD'}, REGION_SIZE => 1024
|
|
|
|
For compression types, pass one of 'NONE', 'RECORD', or 'BLOCK'
|
|
|
|
describe Describe the named table. Outputs the table and family descriptors
|
|
drop Drop the named table. Table must first be disabled
|
|
disable Disable the named table: e.g. "disable 't1'<RETURN>"
|
|
enable Enable the named table
|
|
exists Does the named table exist? e.g. "exists 't1'<RETURN>"
|
|
exit Exit the shell
|
|
list List all tables
|
|
version Output this HBase version
|
|
|
|
GENERAL NOTES:
|
|
Quote all names in the hbase shell such as table and column names. Don't
|
|
forget commas delimiting command parameters. Dictionaries of configuration used
|
|
in the creation and alteration of tables are ruby-style Hashes. They look like
|
|
this: { 'key1' => 'value1', 'key2' => 'value2', ...}. They are opened and
|
|
closed with curley-braces. Key/values are delimited by the '=>' character
|
|
combination. Usually keys are predefined constants such as NAME, MAX_VERSIONS,
|
|
COMPRESSION, MAX_LENGTH, TTL, etc. Constants do not need to be quoted. Type
|
|
'Object.constants' to see a (messy) list of all constants in the environment.
|
|
See http://wiki.apache.org/hadoop/Hbase/Shell for more on the HBase Shell.
|
|
HERE
|
|
puts h
|
|
end
|
|
|
|
def version
|
|
# Output version.
|
|
puts "Version: #{org.apache.hadoop.hbase.util.VersionInfo.getVersion()},\
|
|
r#{org.apache.hadoop.hbase.util.VersionInfo.getRevision()},\
|
|
#{org.apache.hadoop.hbase.util.VersionInfo.getDate()}"
|
|
end
|
|
|
|
# DDL
|
|
|
|
def admin()
|
|
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
|
|
@admin
|
|
end
|
|
|
|
def create(table_name, *args)
|
|
admin().create(table_name, args)
|
|
end
|
|
|
|
def drop(table_name)
|
|
admin().drop(table_name)
|
|
end
|
|
|
|
def alter(table_name, args)
|
|
admin().alter(table_name, args)
|
|
end
|
|
|
|
# Administration
|
|
|
|
def list
|
|
admin().list()
|
|
end
|
|
|
|
def describe(table_name)
|
|
admin().describe(table_name)
|
|
end
|
|
|
|
def enable(table_name)
|
|
admin().enable(table_name)
|
|
end
|
|
|
|
def disable(table_name)
|
|
admin().disable(table_name)
|
|
end
|
|
|
|
def exists(table_name)
|
|
admin().exists(table_name)
|
|
end
|
|
|
|
# CRUD
|
|
|
|
def get(table_name, row_key, *args)
|
|
puts "Not implemented yet"
|
|
end
|
|
|
|
def put(table_name, row_key, *args)
|
|
puts "Not implemented yet"
|
|
end
|
|
|
|
def scan(table_name, start_key, end_key, *args)
|
|
puts "Not implemented yet"
|
|
end
|
|
|
|
def delete(table_name, row_key, *args)
|
|
puts "Not implemented yet"
|
|
end
|
|
|
|
# Output a banner message that tells users where to go for help
|
|
puts <<HERE
|
|
HBase Shell; enter 'help<RETURN>' for list of supported commands.
|
|
HERE
|
|
version
|
|
|
|
require "irb"
|
|
|
|
# IRB::ExtendCommandBundle.instance_variable_get("@EXTEND_COMMANDS").delete_if{|x| x.first == :irb_help}
|
|
|
|
module IRB
|
|
module ExtendCommandBundle
|
|
# These are attempts at blocking the complaint about :irb_help on startup.
|
|
# @EXTEND_COMMANDS.delete_if{|x| x[0] == :irb_help}
|
|
# @EXTEND_COMMANDS.each{|x| x[3][1] = OVERRIDE_ALL if x[0] == :irb_help}
|
|
# @EXTEND_COMMANDS.each{|x| puts x if x[0] == :irb_help}
|
|
end
|
|
|
|
class HIRB < Irb
|
|
# Subclass irb so can intercept methods
|
|
|
|
def output_value
|
|
# Suppress output if last_value is 'nil'
|
|
# Otherwise, when user types help, get ugly 'nil'
|
|
# after all output.
|
|
if @context.last_value
|
|
super
|
|
end
|
|
end
|
|
end
|
|
|
|
def IRB.start(ap_path = nil)
|
|
$0 = File::basename(ap_path, ".rb") if ap_path
|
|
|
|
IRB.setup(ap_path)
|
|
@CONF[:IRB_NAME]="hbase"
|
|
|
|
if @CONF[:SCRIPT]
|
|
hirb = HIRB.new(nil, @CONF[:SCRIPT])
|
|
else
|
|
hirb = HIRB.new
|
|
end
|
|
|
|
@CONF[:IRB_RC].call(hirb.context) if @CONF[:IRB_RC]
|
|
@CONF[:MAIN_CONTEXT] = hirb.context
|
|
|
|
trap("SIGINT") do
|
|
hirb.signal_handle
|
|
end
|
|
|
|
catch(:IRB_EXIT) do
|
|
hirb.eval_input
|
|
end
|
|
end
|
|
end
|
|
|
|
IRB.start
|