hbase-jruby 0.3.3-java → 0.3.4-java

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/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