hbase-jruby 0.1.6-java → 0.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,109 @@
1
+ class HBase
2
+ class Table
3
+ # Returns a read-only org.apache.hadoop.hbase.HTableDescriptor object
4
+ # @return [org.apache.hadoop.hbase.client.UnmodifyableHTableDescriptor]
5
+ def descriptor
6
+ htable.get_table_descriptor
7
+ end
8
+
9
+ # Returns table properties
10
+ # @return [Hash]
11
+ def properties
12
+ desc = descriptor
13
+ {}.tap { |props|
14
+ TABLE_PROPERTIES.each do |prop, gs|
15
+ get = gs[:get]
16
+ if get && desc.respond_to?(get)
17
+ props[prop] = parse_property desc.send get
18
+ end
19
+ end
20
+ }
21
+ end
22
+
23
+ # Returns raw String-to-String map of table properties
24
+ # @return [Hash]
25
+ def raw_properties
26
+ parse_raw_map descriptor.values
27
+ end
28
+
29
+ # Returns properties of column families indexed by family name
30
+ # @return [Hash]
31
+ def families
32
+ {}.tap { |ret|
33
+ descriptor.families.each do |family|
34
+ name = family.name_as_string
35
+ ret[name] =
36
+ {}.tap { |props|
37
+ COLUMN_PROPERTIES.each do |prop, gs|
38
+ get = gs[:get]
39
+ if get && family.respond_to?(get)
40
+ props[prop] = parse_property family.send get
41
+ end
42
+ end
43
+ }
44
+ end
45
+ }
46
+ end
47
+
48
+ # Returns raw String-to-String map of column family properties indexed by name
49
+ # @return [Hash]
50
+ def raw_families
51
+ {}.tap { |ret|
52
+ descriptor.families.each do |family|
53
+ name = family.name_as_string
54
+ ret[name] = parse_raw_map family.values
55
+ end
56
+ }
57
+ end
58
+
59
+ # Returns region information
60
+ # @return [Hash]
61
+ def regions
62
+ with_admin do |admin|
63
+ _regions admin
64
+ end
65
+ end
66
+
67
+ # Returns a printable version of the table description
68
+ # @return [String] Table description
69
+ def inspect
70
+ if exists?
71
+ descriptor.toStringCustomizedValues
72
+ else
73
+ # FIXME
74
+ "{NAME => '#{@name}'}"
75
+ end
76
+ end
77
+
78
+ private
79
+ def _regions admin
80
+ admin.getTableRegions(@name.to_java_bytes).map { |ri|
81
+ {}.tap { |r|
82
+ r[:name] = ri.region_name
83
+ r[:id] = ri.region_id
84
+ r[:start_key] = nil_if_empty ri.start_key
85
+ r[:end_key] = nil_if_empty ri.end_key
86
+ r[:root] = ri.is_root_region
87
+ r[:meta] = ri.is_meta_region
88
+ r[:online] = !ri.is_offline
89
+ }
90
+ }
91
+ end
92
+
93
+ def nil_if_empty v
94
+ v.empty? ? nil : v
95
+ end
96
+
97
+ def parse_property v
98
+ if v.is_a?(java.lang.Enum)
99
+ v.to_s
100
+ else
101
+ v
102
+ end
103
+ end
104
+
105
+ def parse_raw_map m
106
+ Hash[ m.keys.map { |e| e.get.to_s }.zip m.values.map { |e| e.get.to_s } ]
107
+ end
108
+ end#Table
109
+ end#HBase
@@ -13,234 +13,27 @@ class Table
13
13
  include Enumerable
14
14
  include Admin
15
15
  include Scoped::Aggregation::Admin
16
+ include HBase::Util
16
17
 
17
- # Returns a read-only org.apache.hadoop.hbase.HTableDescriptor object
18
- # @return [org.apache.hadoop.hbase.client.UnmodifyableHTableDescriptor]
19
- def descriptor
20
- htable.get_table_descriptor
18
+ # (INTERNAL) Returns the underlying org.apache.hadoop.hbase.client.HTable object (local to current thread)
19
+ # @return [org.apache.hadoop.hbase.client.HTable]
20
+ def htable
21
+ check_closed
22
+
23
+ local_htables = Thread.current[:htable] ||= {}
24
+ local_htables[@name] ||= @pool.get_table(@name)
21
25
  end
22
26
 
23
- # Closes the table and returns HTable object back to the HTablePool.
27
+ # @deprecated
24
28
  # @return [nil]
25
29
  def close
26
- Thread.current[:htable] ||= {}
27
- ht = Thread.current[:htable].delete(@name)
28
- ht.close if ht
29
30
  nil
30
31
  end
31
32
 
32
- # Checks if the table of the name exists
33
- # @return [true, false] Whether table exists
34
- def exists?
35
- with_admin { |admin| admin.tableExists @name }
36
- end
37
-
38
- # Checks if the table is enabled
39
- # @return [true, false] Whether table is enabled
40
- def enabled?
41
- with_admin { |admin| admin.isTableEnabled(@name) }
42
- end
43
-
44
- # Checks if the table is disabled
45
- # @return [true, false] Whether table is disabled
46
- def disabled?
47
- !enabled?
48
- end
49
-
50
- # Creates the table
51
- # @overload create!(column_family_name, props = {})
52
- # Create the table with one column family of the given name
53
- # @param [#to_s] The name of the column family
54
- # @param [Hash] props Table properties
55
- # @return [nil]
56
- # @overload create!(column_family_hash, props = {})
57
- # Create the table with the specified column families
58
- # @param [Hash] Column family properties
59
- # @param [Hash] props Table properties
60
- # @return [nil]
61
- # @example
62
- # table.create!(
63
- # # Column family with default options
64
- # :cf1 => {},
65
- # # Another column family with custom properties
66
- # :cf2 => {
67
- # :blockcache => true,
68
- # :blocksize => 128 * 1024,
69
- # :bloomfilter => :row,
70
- # :compression => :snappy,
71
- # :in_memory => true,
72
- # :keep_deleted_cells => true,
73
- # :min_versions => 2,
74
- # :replication_scope => 0,
75
- # :ttl => 100,
76
- # :versions => 5
77
- # }
78
- # )
79
- # @overload create!(table_descriptor)
80
- # Create the table with the given HTableDescriptor
81
- # @param [org.apache.hadoop.hbase.HTableDescriptor] Table descriptor
82
- # @return [nil]
83
- def create! desc, props = {}
84
- todo = nil
85
- with_admin do |admin|
86
- raise RuntimeError, 'Table already exists' if admin.tableExists(@name)
87
-
88
- case desc
89
- when HTableDescriptor
90
- patch_table_descriptor! desc, props
91
- admin.createTable desc
92
- when Symbol, String
93
- todo = lambda { create!({desc => {}}, props) }
94
- when Hash
95
- htd = HTableDescriptor.new(@name.to_java_bytes)
96
- patch_table_descriptor! htd, props
97
- desc.each do |name, opts|
98
- htd.addFamily hcd(name, opts)
99
- end
100
-
101
- admin.createTable htd
102
- else
103
- raise ArgumentError, 'Invalid table description'
104
- end
105
- end
106
- todo.call if todo # Avoids mutex relocking
107
- end
108
-
109
- # Alters the table (synchronous)
110
- # @param [Hash] props Table properties
111
- # @return [nil]
112
- # @example
113
- # table.alter!(
114
- # :max_filesize => 512 * 1024 ** 2,
115
- # :memstore_flushsize => 64 * 1024 ** 2,
116
- # :readonly => false,
117
- # :deferred_log_flush => true
118
- # )
119
- def alter! props, &block
120
- _alter props, true, &block
121
- end
122
-
123
- # Alters the table (asynchronous)
124
- # @see HBase::Table#alter!
125
- def alter props
126
- _alter props, false
127
- end
128
-
129
- # Adds the column family (synchronous)
130
- # @param [#to_s] name The name of the column family
131
- # @param [Hash] opts Column family properties
132
- # @return [nil]
133
- def add_family! name, opts, &block
134
- _add_family name, opts, true, &block
135
- end
136
-
137
- # Adds the column family (asynchronous)
138
- # @see HBase::Table#add_family!
139
- def add_family name, opts
140
- _add_family name, opts, false
141
- end
142
-
143
- # Alters the column family
144
- # @param [#to_s] name The name of the column family
145
- # @param [Hash] opts Column family properties
146
- # @return [nil]
147
- def alter_family! name, opts, &block
148
- _alter_family name, opts, true, &block
149
- end
150
-
151
- # Alters the column family (asynchronous)
152
- # @see HBase::Table#alter_family!
153
- def alter_family name, opts
154
- _alter_family name, opts, false
155
- end
156
-
157
- # Removes the column family
158
- # @param [#to_s] name The name of the column family
159
- # @return [nil]
160
- def delete_family! name, &block
161
- _delete_family name, true, &block
162
- end
163
-
164
- # Removes the column family (asynchronous)
165
- # @see HBase::Table#delete_family!
166
- def delete_family name
167
- _delete_family name, false
168
- end
169
-
170
- # Adds the table coprocessor to the table
171
- # @param [String] class_name Full class name of the coprocessor
172
- # @param [Hash] props Coprocessor properties
173
- # @option props [String] path The path of the JAR file
174
- # @option props [Fixnum] priority Coprocessor priority
175
- # @option props [Hash<#to_s, #to_s>] params Arbitrary key-value parameter pairs passed into the coprocessor
176
- def add_coprocessor! class_name, props = {}, &block
177
- _add_coprocessor class_name, props, true, &block
178
- end
179
-
180
- # Adds the table coprocessor to the table (asynchronous)
181
- def add_coprocessor class_name, props = {}
182
- _add_coprocessor class_name, props, false
183
- end
184
-
185
- # Removes the coprocessor from the table.
186
- # @param [String] class_name Full class name of the coprocessor
187
- # @return [nil]
188
- def remove_coprocessor! class_name, &block
189
- _remove_coprocessor class_name, true, &block
190
- end
191
-
192
- # Removes the coprocessor from the table (asynchronous)
193
- # @see HBase::Table#remove_coprocessor!
194
- def remove_coprocessor class_name
195
- _remove_coprocessor class_name, false
196
- end
197
-
198
- # Return if the table has the coprocessor of the given class name
199
- # @param [String] class_name Full class name of the coprocessor
200
- # @return [true, false]
201
- def has_coprocessor? class_name
202
- descriptor.hasCoprocessor(class_name)
203
- end
204
-
205
- # Enables the table
206
- # @return [nil]
207
- def enable!
208
- with_admin do |admin|
209
- admin.enableTable @name unless admin.isTableEnabled(@name)
210
- end
211
- end
212
-
213
- # Disables the table
214
- # @return [nil]
215
- def disable!
216
- with_admin do |admin|
217
- admin.disableTable @name if admin.isTableEnabled(@name)
218
- end
219
- end
220
-
221
- # Truncates the table by dropping it and recreating it.
222
- # @return [nil]
223
- def truncate!
224
- htd = htable.get_table_descriptor
225
- drop!
226
- create! htd
227
- end
228
-
229
- # Drops the table
230
- # @return [nil]
231
- def drop!
232
- with_admin do |admin|
233
- raise RuntimeError, 'Table does not exist' unless admin.tableExists @name
234
-
235
- admin.disableTable @name if admin.isTableEnabled(@name)
236
- admin.deleteTable @name
237
- close
238
- end
239
- end
240
-
241
33
  [:get, :count, :aggregate,
242
34
  :range, :project, :filter, :while,
243
- :limit, :versions, :caching, :batch
35
+ :limit, :versions, :caching, :batch,
36
+ :time_range, :at
244
37
  ].each do |method|
245
38
  define_method(method) do |*args|
246
39
  self.each.send(method, *args)
@@ -286,11 +79,11 @@ class Table
286
79
  # @return [nil]
287
80
  # @example
288
81
  # table.delete('a000', 'cf1:col1')
289
- # @overload delete(rowkey, column, timestamp)
290
- # Deletes a version of a column
82
+ # @overload delete(rowkey, column, *timestamps)
83
+ # Deletes specified versions of a column
291
84
  # @param [Object] rowkey
292
85
  # @param [String, Array] column Column expression in String "FAMILY:QUALIFIER", or in Array [FAMILY, QUALIFIER]
293
- # @param [Fixnum] timestamp Timestamp.
86
+ # @param [*Fixnum] timestamps Timestamps.
294
87
  # @return [nil]
295
88
  # @example
296
89
  # table.delete('a000', 'cf1:col1', 1352978648642)
@@ -314,7 +107,7 @@ class Table
314
107
  Delete.new(Util.to_bytes rowkey).tap { |del|
315
108
  if !ts.empty?
316
109
  ts.each do |t|
317
- del.deleteColumn cf, cq, t
110
+ del.deleteColumn cf, cq, time_to_long(t)
318
111
  end
319
112
  elsif cq
320
113
  # Delete all versions
@@ -358,9 +151,12 @@ class Table
358
151
  end
359
152
 
360
153
  # Scan through the table
361
- # @yield [HBase::Result] Yields each row in the scope
154
+ # @yield [row] Yields each row in the scope
155
+ # @yieldparam [HBase::Result] row
362
156
  # @return [HBase::Scoped]
363
157
  def each
158
+ check_closed
159
+
364
160
  if block_given?
365
161
  Scoped.send(:new, self).each { |r| yield r }
366
162
  else
@@ -368,40 +164,16 @@ class Table
368
164
  end
369
165
  end
370
166
 
371
- # Returns the underlying org.apache.hadoop.hbase.client.HTable object (local to current thread)
372
- # @return [org.apache.hadoop.hbase.client.HTable]
373
- def htable
374
- # @htable ||= @pool.get_table(@name)
375
- (local_htables = Thread.current[:htable] ||= {})[@name] ||
376
- (local_htables[@name] = @pool.get_table(@name))
377
- end
378
-
379
- # Returns a printable version of the table description
380
- # @return [String] Table description
381
- def inspect
382
- if exists?
383
- htable.get_table_descriptor.to_s
384
- else
385
- # FIXME
386
- "{NAME => '#{@name}'}"
387
- end
388
- end
389
-
390
167
  private
391
- def initialize config, htable_pool, name
392
- @config = config
393
- @pool = htable_pool
394
- @name = name.to_s
395
- @htable = nil
168
+ def initialize hbase, config, htable_pool, name
169
+ @hbase = hbase
170
+ @config = config
171
+ @pool = htable_pool
172
+ @name = name.to_s
396
173
  end
397
174
 
398
- def while_disabled admin
399
- begin
400
- admin.disableTable @name if admin.isTableEnabled(@name)
401
- yield
402
- ensure
403
- admin.enableTable @name
404
- end
175
+ def check_closed
176
+ raise RuntimeError, "HBase connection is already closed" if @hbase.closed?
405
177
  end
406
178
 
407
179
  def putify rowkey, props
@@ -412,9 +184,9 @@ private
412
184
  when Hash
413
185
  val.each do |t, v|
414
186
  case t
415
- # Timestamp
416
- when Fixnum
417
- put.add cf, cq, t, Util.to_bytes(v)
187
+ # Timestamp / Ruby Time
188
+ when Time, Fixnum
189
+ put.add cf, cq, time_to_long(t), Util.to_bytes(v)
418
190
  # Types: :byte, :short, :int, ...
419
191
  else
420
192
  put.add cf, cq, Util.to_bytes(t => v)
@@ -426,137 +198,6 @@ private
426
198
  end
427
199
  }
428
200
  end
429
-
430
- def hcd name, opts
431
- method_map = {
432
- :blockcache => :setBlockCacheEnabled,
433
- :blocksize => :setBlocksize,
434
- :bloomfilter => :setBloomFilterType,
435
- :compression => :setCompressionType,
436
- :data_block_encoding => :setDataBlockEncoding,
437
- :encode_on_disk => :setEncodeOnDisk,
438
- :in_memory => :setInMemory,
439
- :keep_deleted_cells => :setKeepDeletedCells,
440
- :min_versions => :setMinVersions,
441
- :replication_scope => :setScope,
442
- :ttl => :setTimeToLive,
443
- :versions => :setMaxVersions,
444
- }
445
- HColumnDescriptor.new(name.to_s).tap do |hcd|
446
- opts.each do |key, val|
447
- if method_map[key]
448
- hcd.send method_map[key],
449
- ({
450
- :bloomfilter => proc { |v|
451
- const_shortcut StoreFile::BloomType, v, "Invalid bloom filter type"
452
- },
453
- :compression => proc { |v|
454
- const_shortcut Compression::Algorithm, v, "Invalid compression algorithm"
455
- }
456
- }[key] || proc { |a| a }).call(val)
457
- else
458
- raise ArgumentError, "Invalid option: #{key}"
459
- end
460
- end#opts
461
- end
462
- end
463
-
464
- def const_shortcut base, v, message
465
- vs = v.to_s.upcase
466
- # const_get doesn't work with symbols in 1.8 compatibility mode
467
- if base.constants.map { |c| base.const_get c }.any? { |cv| v == cv }
468
- v
469
- elsif base.constants.map(&:to_s).include?(vs)
470
- base.const_get vs
471
- else
472
- raise ArgumentError, [message, v.to_s].join(': ')
473
- end
474
- end
475
-
476
- def patch_table_descriptor! htd, props
477
- props.each do |key, value|
478
- method = {
479
- :max_filesize => :setMaxFileSize,
480
- :readonly => :setReadOnly,
481
- :memstore_flushsize => :setMemStoreFlushSize,
482
- :deferred_log_flush => :setDeferredLogFlush
483
- }[key]
484
- raise ArgumentError, "Invalid table property: #{key}" unless method
485
-
486
- htd.send method, value
487
- end
488
- htd
489
- end
490
-
491
- def _alter props, bang, &block
492
- with_admin do |admin|
493
- htd = admin.get_table_descriptor(@name.to_java_bytes)
494
- patch_table_descriptor! htd, props
495
- while_disabled(admin) do
496
- admin.modifyTable @name.to_java_bytes, htd
497
- wait_async_admin(admin, &block) if bang
498
- end
499
- end
500
- end
501
-
502
- def _add_family name, opts, bang, &block
503
- with_admin do |admin|
504
- while_disabled(admin) do
505
- admin.addColumn @name, hcd(name.to_s, opts)
506
- wait_async_admin(admin, &block) if bang
507
- end
508
- end
509
- end
510
-
511
- def _alter_family name, opts, bang, &block
512
- with_admin do |admin|
513
- while_disabled(admin) do
514
- admin.modifyColumn @name, hcd(name.to_s, opts)
515
- wait_async_admin(admin, &block) if bang
516
- end
517
- end
518
- end
519
-
520
- def _delete_family name, bang, &block
521
- with_admin do |admin|
522
- while_disabled(admin) do
523
- admin.deleteColumn @name, name.to_s
524
- wait_async_admin(admin, &block) if bang
525
- end
526
- end
527
- end
528
-
529
- def _add_coprocessor class_name, props = {}, bang, &block
530
- with_admin do |admin|
531
- while_disabled(admin) do
532
-
533
- htd = admin.get_table_descriptor(@name.to_java_bytes)
534
- if props.empty?
535
- htd.addCoprocessor class_name
536
- else
537
- path, priority, params = props.values_at :path, :priority, :params
538
- params = Hash[ params.map { |k, v| [k.to_s, v.to_s] } ]
539
- htd.addCoprocessor class_name, path, priority || Coprocessor::PRIORITY_USER, params
540
- end
541
- admin.modifyTable @name.to_java_bytes, htd
542
- wait_async_admin(admin, &block) if bang
543
- end
544
- end
545
- end
546
-
547
- def _remove_coprocessor name, bang, &block
548
- unless org.apache.hadoop.hbase.HTableDescriptor.respond_to?(:removeCoprocessor)
549
- raise NotImplementedError, "org.apache.hadoop.hbase.HTableDescriptor.removeCoprocessor not implemented"
550
- end
551
- with_admin do |admin|
552
- while_disabled(admin) do
553
- htd = admin.get_table_descriptor(@name.to_java_bytes)
554
- htd.removeCoprocessor name
555
- admin.modifyTable @name.to_java_bytes, htd
556
- wait_async_admin(admin, &block) if bang
557
- end
558
- end
559
- end
560
201
  end#Table
561
202
  end#HBase
562
203
 
@@ -15,6 +15,8 @@ module Util
15
15
  # @return [byte[]]
16
16
  def to_bytes v
17
17
  case v
18
+ when Array
19
+ v.to_java(Java::byte)
18
20
  when String, ByteArray
19
21
  v.to_java_bytes
20
22
  when Fixnum
@@ -47,7 +49,7 @@ module Util
47
49
  Bytes.java_send :toBytes, [Java::int], val
48
50
  when :short
49
51
  Bytes.java_send :toBytes, [Java::short], val
50
- when :long, :fixnum
52
+ when :long, :fixnum
51
53
  Bytes.java_send :toBytes, [Java::long], val
52
54
  else
53
55
  raise ArgumentError, "Invalid value format"
@@ -123,6 +125,19 @@ module Util
123
125
  end
124
126
  end
125
127
  end
128
+
129
+ private
130
+ # @private
131
+ def time_to_long ts
132
+ case ts
133
+ when Fixnum
134
+ ts
135
+ when Time
136
+ (ts.to_f * 1000).to_i
137
+ else
138
+ raise ArgumentError, "Invalid time format"
139
+ end
140
+ end
126
141
  end#Util
127
142
  end#HBase
128
143
 
@@ -1,5 +1,5 @@
1
1
  class HBase
2
2
  module JRuby
3
- VERSION = "0.1.6"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
data/lib/hbase-jruby.rb CHANGED
@@ -12,6 +12,8 @@ require "hbase-jruby/admin"
12
12
  require "hbase-jruby/scoped/aggregation"
13
13
  require "hbase-jruby/scoped"
14
14
  require "hbase-jruby/table"
15
+ require "hbase-jruby/table/admin"
16
+ require "hbase-jruby/table/inspection"
15
17
  require "hbase-jruby/result"
16
18
  require 'hbase-jruby/hbase'
17
19
 
data/test/helper.rb CHANGED
@@ -8,13 +8,10 @@ SimpleCov.start
8
8
  RECREATE = false
9
9
 
10
10
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
11
- require "hbase-jruby"
12
11
 
13
- # Required
14
- unless HBase.resolve_dependency!(ENV.fetch 'HBASE_JRUBY_TEST_DIST').all? { |f| File.exists? f }
15
- puts "Invalid return value from HBase.resolve_dependency!"
16
- exit 1
17
- end
12
+ require "hbase-jruby"
13
+ HBase.resolve_dependency!(ENV.fetch('HBASE_JRUBY_TEST_DIST'), :verbose => true)
14
+ HBase.log4j = { 'log4j.threshold' => 'ERROR' }
18
15
 
19
16
  class TestHBaseJRubyBase < Test::Unit::TestCase
20
17
  TABLE = 'test_hbase_jruby'
@@ -36,7 +33,7 @@ class TestHBaseJRubyBase < Test::Unit::TestCase
36
33
  @table.create!(
37
34
  :cf1 => { :compression => :none, :bloomfilter => :row },
38
35
  :cf2 => { :bloomfilter => :rowcol },
39
- :cf3 => { :versions => 1, :bloomfilter => org.apache.hadoop.hbase.regionserver.StoreFile::BloomType::ROWCOL }
36
+ :cf3 => { :versions => 1, :bloomfilter => :rowcol }
40
37
  ) unless @table.exists?
41
38
  @table.enable! if @table.disabled?
42
39
 
data/test/test_cell.rb CHANGED
@@ -31,12 +31,12 @@ class TestCell < Test::Unit::TestCase
31
31
  assert_instance_of String, cell.inspect
32
32
  end
33
33
  end
34
-
34
+
35
35
  def test_order
36
36
  ts = Time.now.to_i * 1000
37
37
 
38
38
  val = "val".to_java_bytes
39
- cells =
39
+ cells =
40
40
  [
41
41
  KeyValue.new("rowkey".to_java_bytes, "apple".to_java_bytes, "alpha".to_java_bytes, ts, val),
42
42
  KeyValue.new("rowkey".to_java_bytes, "apple".to_java_bytes, "alpha".to_java_bytes, ts - 1000, val),