hbase/bin/hirb.rb

258 lines
7.9 KiB
Ruby
Raw Normal View History

# 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'.
def promoteConstants(constants)
# The constants to import are all in uppercase
for c in constants
if c == c.upcase
eval("%s = \"%s\"" % [c, c])
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:
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, type:
create 't1' {NAME => 'f1', MAX_VERSIONS => 5}, REGION_SIZE => 123
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 that
do not need to be quoted such as NAME, MAX_VERSIONS, MAX_LENGTH, TTL, etc.
Type 'Object.constants' to see a (messy) list of all constants in the
environment.
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 create(table_name, *args)
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
@admin.create(table_name, args)
end
def drop(table_name)
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
@admin.drop(table_name)
end
def alter(table_name, *args)
puts "Not implemented yet"
end
# Administration
def list
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
@admin.list()
end
def describe(table_name)
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
@admin.describe(table_name)
end
def enable(table_name)
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
@admin.enable(table_name)
end
def disable(table_name)
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
@admin.disable(table_name)
end
def exists(table_name)
@admin = HBase::Admin.new(@configuration, @formatter) unless @admin
@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 "HBase Shell; type 'help<RETURN>' for the list of supported HBase commands"
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