hbase-ruby 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +3 -0
- data/README.textile +1 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/hbase/client.rb +5 -0
- data/lib/hbase/exception.rb +2 -0
- data/lib/hbase/model/scanner.rb +5 -2
- data/lib/hbase/operation/scanner_operation.rb +23 -15
- data/lib/hbase/response/scanner_response.rb +5 -1
- data/spec/hbase/operation/scanner_operation_spec.rb +26 -4
- metadata +2 -2
data/History.txt
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
v1.1.1 Nov 7, 2009
|
2
|
+
* Improved the scanner functionality. Decided it was worth a version bump and release.
|
3
|
+
|
1
4
|
v1.1.0 Nov 7, 2009
|
2
5
|
* Bumped to version 1.1.0 to avoid confusion with an existing hbase-ruby on gemcutter that was at version 1.0
|
3
6
|
* Reimplemented entirely with HBase Stargate (old REST API was obsoleted by this)
|
data/README.textile
CHANGED
@@ -57,7 +57,7 @@ row = client.show_row('users', 'sishen') # show the data of row
|
|
57
57
|
row2 = client.create_row('users', 'sishen', Time.now.to_i, {:name => 'habbit:football', :value => 'i like football'}) # create the row 'sishen' with the data in the table 'users'
|
58
58
|
client.delete_row('users', 'sishen', nil, 'habbit:football') # delete the row 'sishen' of table 'users' with the optional column 'habbit:football'
|
59
59
|
|
60
|
-
# Scanner Operation
|
60
|
+
# Scanner Operation (see spec/hbase/operation/scanner_operation_spec.rb for more examples)
|
61
61
|
scanner = client.open_scanner('users', {:start_row => "row2", :batch => 5, :columns => ["habbit:"]}) # See more options from HBase::Model::Scanner.AVAILABLE_OPTS
|
62
62
|
rows = client.get_rows(scanner)
|
63
63
|
client.close_scanner(scanner)
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ begin
|
|
5
5
|
|
6
6
|
Jeweler::Tasks.new do |gemspec|
|
7
7
|
gemspec.name = "hbase-ruby"
|
8
|
-
gemspec.authors = ['Ye Dingding', '
|
8
|
+
gemspec.authors = ['Ye Dingding', 'Openplaces']
|
9
9
|
gemspec.email = 'greg.lu@gmail.com'
|
10
10
|
gemspec.homepage = "http://github.com/greglu/hbase-ruby"
|
11
11
|
gemspec.summary = "A pure ruby client for HBase using the Stargate interface."
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.1
|
data/lib/hbase/client.rb
CHANGED
@@ -28,6 +28,11 @@ module HBase
|
|
28
28
|
safe_request { @connection.get(@url.path + path, {"Accept" => "application/json"}) }
|
29
29
|
end
|
30
30
|
|
31
|
+
# Needed for scanner functionality
|
32
|
+
def get_response(path)
|
33
|
+
safe_response { @connection.get(@url.path + path, {"Accept" => "application/json"}) }
|
34
|
+
end
|
35
|
+
|
31
36
|
def post(path, data = nil)
|
32
37
|
safe_request { @connection.post(@url.path + path, data, {'Content-Type' => 'text/xml'}) }
|
33
38
|
end
|
data/lib/hbase/exception.rb
CHANGED
data/lib/hbase/model/scanner.rb
CHANGED
@@ -3,11 +3,14 @@ module HBase
|
|
3
3
|
class Scanner < Record
|
4
4
|
AVAILABLE_OPTS = { :start_row => "startRow", :end_row => "endRow",
|
5
5
|
:start_time => "startTime", :end_time => "endTime",
|
6
|
-
:batch => "batch"
|
6
|
+
:batch => "batch" }
|
7
7
|
|
8
8
|
attr_accessor :table_name
|
9
|
-
attr_accessor :scanner_id
|
10
9
|
attr_accessor :scanner_url
|
10
|
+
attr_accessor :batch_size
|
11
|
+
|
12
|
+
# Deprecation: scanner_url is used instead of just the ID
|
13
|
+
attr_accessor :scanner_id
|
11
14
|
end
|
12
15
|
end
|
13
16
|
end
|
@@ -3,7 +3,7 @@ module HBase
|
|
3
3
|
module ScannerOperation
|
4
4
|
# Trying to maintain some API stability for now
|
5
5
|
def open_scanner(table_name, columns, start_row, stop_row = nil, timestamp = nil)
|
6
|
-
warn "[DEPRECATION] This method is deprecated. Use #open_scanner(table_name, options) instead."
|
6
|
+
warn "[DEPRECATION] This method is deprecated. Use #open_scanner(table_name, options = {}) instead."
|
7
7
|
|
8
8
|
open_scanner(table_name, {:columns => columns, :start_row => start_row, :stop_row => stop_row, :timestamp => timestamp})
|
9
9
|
end
|
@@ -11,16 +11,15 @@ module HBase
|
|
11
11
|
def open_scanner(table_name, options = {})
|
12
12
|
raise ArgumentError, "options should be given as a Hash" unless options.instance_of? Hash
|
13
13
|
columns = options.delete(:columns)
|
14
|
+
batch = options.delete(:batch) || "10"
|
14
15
|
|
15
16
|
begin
|
16
17
|
request = Request::ScannerRequest.new(table_name)
|
17
18
|
|
18
|
-
xml_data = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><Scanner "
|
19
|
+
xml_data = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><Scanner batch='#{batch}' "
|
19
20
|
options.each do |key,value|
|
20
21
|
if Model::Scanner::AVAILABLE_OPTS.include? key
|
21
|
-
xml_data << "#{Model::Scanner::AVAILABLE_OPTS[key]}='"
|
22
|
-
xml_data << ( (key == :batch) ? value.to_s : [value.to_s].flatten.pack('m') )
|
23
|
-
xml_data << "' "
|
22
|
+
xml_data << "#{Model::Scanner::AVAILABLE_OPTS[key]}='#{[value.to_s].flatten.pack('m')}' "
|
24
23
|
else
|
25
24
|
warn "[open_scanner] Received invalid option key :#{key}"
|
26
25
|
end
|
@@ -37,25 +36,34 @@ module HBase
|
|
37
36
|
|
38
37
|
scanner = Response::ScannerResponse.new(post_response(request.open, xml_data), :open_scanner).parse
|
39
38
|
scanner.table_name = table_name
|
39
|
+
scanner.batch_size = batch
|
40
40
|
scanner
|
41
41
|
rescue Net::ProtocolError => e
|
42
|
-
|
43
|
-
raise TableNotFoundError, "Table #{table_name} Not Found!"
|
44
|
-
else
|
45
|
-
raise StandardError, e.to_s
|
46
|
-
end
|
42
|
+
raise StandardError, e.to_s
|
47
43
|
end
|
48
44
|
end
|
49
45
|
|
50
46
|
def get_rows(scanner, limit = nil)
|
51
|
-
warn "[DEPRECATION] Use of 'limit' here is deprecated. Instead, define the batch size when creating the scanner." if limit
|
52
47
|
begin
|
53
48
|
request = Request::ScannerRequest.new(scanner.table_name)
|
54
|
-
|
55
|
-
|
56
|
-
|
49
|
+
request_url = request.get_rows(scanner) # The url to the scanner is the same for each batch
|
50
|
+
|
51
|
+
rows = []
|
52
|
+
begin
|
53
|
+
# Loop until we've reached the limit, or the scanner was exhausted (HTTP 204 returned)
|
54
|
+
until (limit && rows.size >= limit) || (response = get_response(request_url)).code == "204"
|
55
|
+
rows.concat Response::ScannerResponse.new(response.body, :get_rows).parse
|
56
|
+
|
57
|
+
rows.each do |row|
|
58
|
+
row.table_name = scanner.table_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
rescue Exception => e
|
62
|
+
raise HBase::ScannerError, "Scanner failed while getting rows. #{e.message}"
|
57
63
|
end
|
58
|
-
|
64
|
+
|
65
|
+
# Prune the last few rows if the limit was passed.
|
66
|
+
(limit) ? rows.slice(0, limit) : rows
|
59
67
|
rescue StandardError => e
|
60
68
|
if e.to_s.include?("TableNotFoundException")
|
61
69
|
raise TableNotFoundError, "Table #{table_name} Not Found!"
|
@@ -15,7 +15,11 @@ module HBase
|
|
15
15
|
when Net::HTTPCreated
|
16
16
|
HBase::Model::Scanner.new(:scanner_url => raw_data["Location"])
|
17
17
|
else
|
18
|
-
|
18
|
+
if raw_data.message.include?("TableNotFoundException")
|
19
|
+
raise TableNotFoundError, "Table #{table_name} Not Found!"
|
20
|
+
else
|
21
|
+
raise StandardError, "Unable to open scanner. Received the following message: #{raw_data.message}"
|
22
|
+
end
|
19
23
|
end
|
20
24
|
when :get_rows
|
21
25
|
# Dispatch it to RowResponse, since that method is made
|
@@ -12,6 +12,12 @@ describe HBase::Operation::ScannerOperation do
|
|
12
12
|
@client.create_row('test-hbase-ruby', 'row3', nil, {:name => 'col1:', :value => "row3-col1"})
|
13
13
|
end
|
14
14
|
|
15
|
+
it "should throw TableNotFoundError if a scanner is requested for an non-existant table" do
|
16
|
+
lambda {
|
17
|
+
scanner = @client.open_scanner("test-dsg-ruby")
|
18
|
+
}.should raise_error
|
19
|
+
end
|
20
|
+
|
15
21
|
it "should open a scanner and close it successfully" do
|
16
22
|
scanner = @client.open_scanner("test-hbase-ruby")
|
17
23
|
scanner.should.is_a? HBase::Model::Scanner
|
@@ -25,17 +31,33 @@ describe HBase::Operation::ScannerOperation do
|
|
25
31
|
}.should_not raise_error
|
26
32
|
end
|
27
33
|
|
28
|
-
it "should scan the whole table when given no options" do
|
34
|
+
it "should scan the whole table when given no options and no limit" do
|
29
35
|
scanner = @client.open_scanner("test-hbase-ruby")
|
30
36
|
|
31
37
|
rows = @client.get_rows(scanner)
|
32
|
-
rows.size.should ==
|
33
|
-
rows.
|
38
|
+
rows.size.should == 3
|
39
|
+
rows.each do |row|
|
40
|
+
row.should be_an_instance_of HBase::Model::Row
|
41
|
+
["row1", "row2", "row3"].should include(row.name)
|
42
|
+
end
|
43
|
+
|
44
|
+
@client.close_scanner(scanner).should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should scan the whole table but limit the results when given a limit" do
|
48
|
+
scanner = @client.open_scanner("test-hbase-ruby")
|
49
|
+
|
50
|
+
rows = @client.get_rows(scanner, 2)
|
51
|
+
rows.size.should == 2
|
52
|
+
rows.each do |row|
|
53
|
+
row.should be_an_instance_of HBase::Model::Row
|
54
|
+
["row1", "row2"].should include(row.name)
|
55
|
+
end
|
34
56
|
|
35
57
|
@client.close_scanner(scanner).should be_true
|
36
58
|
end
|
37
59
|
|
38
|
-
it "should
|
60
|
+
it "should return all rows when given a batch size larger than the number of rows" do
|
39
61
|
scanner = @client.open_scanner("test-hbase-ruby", {:batch => 5})
|
40
62
|
|
41
63
|
rows = @client.get_rows(scanner)
|
metadata
CHANGED