hbase-jruby 0.3.3-java → 0.3.4-java

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 0.3.4
5
+ -----
6
+ - Cleanup all thread-local (fiber-local) HTable references when connection is closed
7
+ - Added `HBase#reset_table_pool` method for recreating HTable pool
8
+
4
9
  0.3.3
5
10
  -----
6
11
 
@@ -1,4 +1,6 @@
1
1
  require 'java'
2
+ require 'set'
3
+ require 'thread'
2
4
 
3
5
  # @author Junegunn Choi <junegunn.c@gmail.com>
4
6
  # @!attribute [r] config
@@ -61,8 +63,10 @@ class HBase
61
63
  end
62
64
  end
63
65
  @htable_pool = HTablePool.new @config, java.lang.Integer::MAX_VALUE
64
- @schema = Schema.new
65
- @closed = false
66
+ @threads = Set.new
67
+ @mutex = Mutex.new
68
+ @schema = Schema.new
69
+ @closed = false
66
70
  end
67
71
 
68
72
  # Returns an HBaseAdmin object for administration
@@ -70,10 +74,10 @@ class HBase
70
74
  # @yieldparam [org.apache.hadoop.hbase.client.HBaseAdmin] admin
71
75
  # @return [org.apache.hadoop.hbase.client.HBaseAdmin]
72
76
  def admin
73
- check_closed
74
77
  if block_given?
75
78
  with_admin { |admin| yield admin }
76
79
  else
80
+ check_closed
77
81
  HBaseAdmin.new @config
78
82
  end
79
83
  end
@@ -81,13 +85,12 @@ class HBase
81
85
  # Closes HTablePool and connection
82
86
  # @return [nil]
83
87
  def close
84
- unless @closed
85
- @htable_pool.close
86
- HConnectionManager.deleteConnection(@config, true)
87
- if Thread.current[:hbase_jruby]
88
- Thread.current[:hbase_jruby].delete(self)
88
+ @mutex.synchronize do
89
+ unless @closed
90
+ @closed = true
91
+ close_table_pool
92
+ HConnectionManager.deleteConnection(@config, true)
89
93
  end
90
- @closed = true
91
94
  end
92
95
  end
93
96
 
@@ -118,7 +121,7 @@ class HBase
118
121
  def table table_name
119
122
  check_closed
120
123
 
121
- ht = HBase::Table.send :new, self, @config, @htable_pool, table_name
124
+ ht = HBase::Table.send :new, self, @config, table_name
122
125
 
123
126
  if block_given?
124
127
  yield ht
@@ -151,9 +154,40 @@ class HBase
151
154
  schema[table] = definition
152
155
  end
153
156
  @schema = schema
157
+ end
158
+
159
+ # Reset underlying HTablePool
160
+ # @return [nil]
161
+ def reset_table_pool
162
+ @mutex.synchronize do
163
+ close_table_pool
164
+ @htable_pool = HTablePool.new @config, java.lang.Integer::MAX_VALUE
165
+ end
166
+ nil
154
167
  end
155
168
 
156
169
  private
170
+ def register_thread t
171
+ @mutex.synchronize do
172
+ check_closed
173
+ @threads << t
174
+ end
175
+ end
176
+
177
+ def close_table_pool
178
+ # Close all the HTable instances in the pool
179
+ @htable_pool.close
180
+
181
+ # Cleanup thread-local references
182
+ @threads.each do |thr|
183
+ thr[:hbase_jruby].delete self
184
+ end
185
+ end
186
+
187
+ def get_htable name
188
+ @htable_pool.get_table name
189
+ end
190
+
157
191
  def check_closed
158
192
  raise RuntimeError, "Connection already closed" if closed?
159
193
  end
@@ -48,8 +48,6 @@ class Scoped
48
48
  # @param [Array<Object>] *rowkeys Rowkeys
49
49
  # @return [Array<HBase::Row>]
50
50
  def get rowkeys
51
- check_closed
52
-
53
51
  case rowkeys
54
52
  when Array
55
53
  htable.get(rowkeys.map { |rk| getify rk }).map { |result|
@@ -65,8 +63,6 @@ class Scoped
65
63
  # @yield [row] Yields each row in the scope
66
64
  # @yieldparam [HBase::Row] row
67
65
  def each
68
- check_closed
69
-
70
66
  return enum_for(:each) unless block_given?
71
67
 
72
68
  begin
@@ -22,8 +22,11 @@ class Table
22
22
 
23
23
  # [:hbase_jruby][HBase connection][Table name]
24
24
  local_vars = Thread.current[:hbase_jruby] ||= {}
25
- local_htables = local_vars[@hbase] ||= {}
26
- local_htables[@name] ||= @pool.get_table(@name)
25
+ unless local_htables = local_vars[@hbase]
26
+ @hbase.send :register_thread, Thread.current
27
+ local_htables = local_vars[@hbase] = {}
28
+ end
29
+ local_htables[@name] ||= @hbase.send :get_htable, @name
27
30
  end
28
31
 
29
32
  # @deprecated
@@ -67,8 +70,6 @@ class Table
67
70
  # @param [Hash<Hash>] data Data to put indexed by rowkeys
68
71
  # @return [Fixnum] Number of puts succeeded
69
72
  def put *args
70
- check_closed
71
-
72
73
  case args.length
73
74
  when 1
74
75
  puts = args.first.map { |rowkey, props| make_put rowkey, props }
@@ -122,8 +123,6 @@ class Table
122
123
  # ['a002', 'cf1'],
123
124
  # ['a003'])
124
125
  def delete *args
125
- check_closed
126
-
127
126
  specs = args.first.is_a?(Array) ? args : [args]
128
127
 
129
128
  htable.delete specs.map { |spec| spec.empty? ? nil : make_delete(*spec) }.compact
@@ -133,8 +132,6 @@ class Table
133
132
  # @param [*Object] rowkeys List of rowkeys of rows to delete
134
133
  # @return [nil]
135
134
  def delete_row *rowkeys
136
- check_closed
137
-
138
135
  htable.delete rowkeys.map { |rk| Delete.new(Util.to_bytes rk) }
139
136
  end
140
137
 
@@ -160,8 +157,6 @@ class Table
160
157
  # table.increment 'a000' => { 'cf1:col1' => 1, 'cf1:col2' => 2 },
161
158
  # 'a001' => { 'cf1:col1' => 3, 'cf1:col2' => 4 }
162
159
  def increment rowkey, *args
163
- check_closed
164
-
165
160
  if args.empty? && rowkey.is_a?(Hash)
166
161
  rowkey.each do |key, spec|
167
162
  increment key, spec
@@ -222,10 +217,9 @@ class Table
222
217
  end
223
218
 
224
219
  private
225
- def initialize hbase, config, htable_pool, name
220
+ def initialize hbase, config, name
226
221
  @hbase = hbase
227
222
  @config = config
228
- @pool = htable_pool
229
223
  @name = name.to_s
230
224
  @name_sym = name.to_sym
231
225
  end
@@ -1,5 +1,5 @@
1
1
  class HBase
2
2
  module JRuby
3
- VERSION = '0.3.3'
3
+ VERSION = '0.3.4'
4
4
  end
5
5
  end
data/test/test_hbase.rb CHANGED
@@ -71,5 +71,61 @@ class TestHBase < TestHBaseJRubyBase
71
71
  hbase2 = HBase.new @hbase.config
72
72
  assert_equal @hbase.config, hbase2.config
73
73
  end
74
+
75
+ def test_thread_local_cleanup
76
+ # Open a new connection
77
+ hbase2 = HBase.new @hbase.config
78
+
79
+ # Thread-local htable cache is empty
80
+ assert_nil Thread.current[:hbase_jruby][hbase2]
81
+
82
+ table = hbase2[TABLE]
83
+ assert_nil Thread.current[:hbase_jruby][hbase2]
84
+
85
+ table.htable
86
+ # Thread-local htable cache has now been created
87
+ assert Thread.current[:hbase_jruby][hbase2][TABLE]
88
+
89
+ threads = 4.times.map { |i|
90
+ Thread.new {
91
+ ht = hbase2[TABLE].htable
92
+ }
93
+ }
94
+ threads.each do |t|
95
+ t.join
96
+ assert t[:hbase_jruby][hbase2][TABLE]
97
+ end
98
+
99
+ # Now close the connection
100
+ hbase2.close
101
+
102
+ # Threads-local htable cache deleted
103
+ assert_nil Thread.current[:hbase_jruby][hbase2]
104
+ threads.each do |t|
105
+ assert_nil t[:hbase_jruby][hbase2]
106
+ end
107
+
108
+ # Connection is already closed
109
+ assert_raise(RuntimeError) { hbase2[TABLE] }
110
+ assert_raise(RuntimeError) { table.htable }
111
+ end
112
+
113
+ def test_reset_pool
114
+ hbase2 = HBase.new @hbase.config
115
+ table = hbase2[TABLE]
116
+
117
+ htable = table.htable
118
+ assert_equal htable, table.htable
119
+ assert_equal htable, hbase2[TABLE.to_sym].htable
120
+
121
+ assert_nil hbase2.reset_table_pool
122
+
123
+ assert_not_equal htable, table.htable
124
+ assert_not_equal htable, hbase2[TABLE].htable
125
+
126
+ htable = table.htable
127
+ assert_equal htable, table.htable
128
+ assert_equal htable, hbase2[TABLE.to_sym].htable
129
+ end
74
130
  end
75
131
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hbase-jruby
3
3
  version: !ruby/object:Gem::Version
4
+ version: 0.3.4
4
5
  prerelease:
5
- version: 0.3.3
6
6
  platform: java
7
7
  authors:
8
8
  - Junegunn Choi
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-12 00:00:00.000000000 Z
12
+ date: 2013-07-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit