couchbase 1.2.3-x86-mingw32 → 1.3.0-x86-mingw32

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.
@@ -16,10 +16,9 @@
16
16
  #
17
17
 
18
18
  require 'couchbase/version'
19
- require 'multi_json'
20
- require 'ext/multi_json_fix'
21
19
  require 'yaji'
22
20
  require 'uri'
21
+ require 'couchbase/transcoder'
23
22
  require 'couchbase_ext'
24
23
  require 'couchbase/constants'
25
24
  require 'couchbase/utils'
@@ -29,9 +28,12 @@ require 'couchbase/view'
29
28
  require 'couchbase/result'
30
29
  require 'couchbase/cluster'
31
30
 
31
+
32
32
  # Couchbase ruby client
33
33
  module Couchbase
34
34
 
35
+ autoload(:ConnectionPool, 'couchbase/connection_pool')
36
+
35
37
  class << self
36
38
  # The method +connect+ initializes new Bucket instance with all arguments passed.
37
39
  #
@@ -0,0 +1,55 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'connection_pool'
19
+
20
+ module Couchbase
21
+ class ConnectionPool
22
+
23
+ def initialize(pool_size = 5, *args)
24
+ @pool = ::ConnectionPool.new(:size => pool_size) { ::Couchbase::Bucket.new(*args) }
25
+ end
26
+
27
+ def with
28
+ yield @pool.checkout
29
+ ensure
30
+ @pool.checkin
31
+ end
32
+
33
+ def respond_to?(id, *args)
34
+ super || @pool.with { |c| c.respond_to?(id, *args) }
35
+ end
36
+
37
+ def method_missing(name, *args, &block)
38
+ define_proxy_method(name)
39
+ send(name, *args, &block)
40
+ end
41
+
42
+ protected
43
+
44
+ def define_proxy_method(name)
45
+ self.class.class_eval <<-RUBY
46
+ def #{name}(*args, &block)
47
+ @pool.with do |connection|
48
+ connection.send(#{name.inspect}, *args, &block)
49
+ end
50
+ end
51
+ RUBY
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,120 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'multi_json'
19
+ require 'ext/multi_json_fix'
20
+
21
+ module Couchbase
22
+
23
+ module Transcoder
24
+
25
+ module Compat
26
+ def self.enable!
27
+ @disabled = false
28
+ end
29
+
30
+ def self.disable!
31
+ @disabled = true
32
+ end
33
+
34
+ def self.enabled?
35
+ !@disabled
36
+ end
37
+
38
+ def self.guess_and_load(blob, flags, options = {})
39
+ case flags & Bucket::FMT_MASK
40
+ when Bucket::FMT_DOCUMENT
41
+ MultiJson.load(blob)
42
+ when Bucket::FMT_MARSHAL
43
+ ::Marshal.load(blob)
44
+ when Bucket::FMT_PLAIN
45
+ blob
46
+ else
47
+ raise ArgumentError, "unexpected flags (0x%02x)" % flags
48
+ end
49
+ end
50
+ end
51
+
52
+ module Document
53
+ def self.dump(obj, flags, options = {})
54
+ [
55
+ MultiJson.dump(obj),
56
+ (flags & ~Bucket::FMT_MASK) | Bucket::FMT_DOCUMENT
57
+ ]
58
+ end
59
+
60
+ def self.load(blob, flags, options = {})
61
+ if (flags & Bucket::FMT_MASK) == Bucket::FMT_DOCUMENT || options[:forced]
62
+ MultiJson.load(blob)
63
+ else
64
+ if Compat.enabled?
65
+ return Compat.guess_and_load(blob, flags, options)
66
+ else
67
+ raise ArgumentError,
68
+ "unexpected flags (0x%02x instead of 0x%02x)" % [flags, Bucket::FMT_DOCUMENT]
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ module Marshal
75
+ def self.dump(obj, flags, options = {})
76
+ [
77
+ ::Marshal.dump(obj),
78
+ (flags & ~Bucket::FMT_MASK) | Bucket::FMT_MARSHAL
79
+ ]
80
+ end
81
+
82
+ def self.load(blob, flags, options = {})
83
+ if (flags & Bucket::FMT_MASK) == Bucket::FMT_MARSHAL || options[:forced]
84
+ ::Marshal.load(blob)
85
+ else
86
+ if Compat.enabled?
87
+ return Compat.guess_and_load(blob, flags, options)
88
+ else
89
+ raise ArgumentError,
90
+ "unexpected flags (0x%02x instead of 0x%02x)" % [flags, Bucket::FMT_MARSHAL]
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ module Plain
97
+ def self.dump(obj, flags, options = {})
98
+ [
99
+ obj,
100
+ (flags & ~Bucket::FMT_MASK) | Bucket::FMT_PLAIN
101
+ ]
102
+ end
103
+
104
+ def self.load(blob, flags, options = {})
105
+ if (flags & Bucket::FMT_MASK) == Bucket::FMT_PLAIN || options[:forced]
106
+ blob
107
+ else
108
+ if Compat.enabled?
109
+ return Compat.guess_and_load(blob, flags, options)
110
+ else
111
+ raise ArgumentError,
112
+ "unexpected flags (0x%02x instead of 0x%02x)" % [flags, Bucket::FMT_PLAIN]
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ end
119
+
120
+ end
@@ -17,5 +17,5 @@
17
17
 
18
18
  # Couchbase ruby client
19
19
  module Couchbase
20
- VERSION = "1.2.3"
20
+ VERSION = "1.3.0"
21
21
  end
@@ -84,7 +84,7 @@ namespace :ports do
84
84
  directory "ports"
85
85
 
86
86
  task :libcouchbase => ["ports"] do
87
- recipe = MiniPortile.new "libcouchbase", "2.0.3"
87
+ recipe = MiniPortile.new "libcouchbase", "2.0.6"
88
88
  recipe.files << "http://packages.couchbase.com/clients/c/libcouchbase-#{recipe.version}.tar.gz"
89
89
  recipe.configure_options.push("--disable-debug",
90
90
  "--disable-dependency-tracking",
@@ -128,7 +128,7 @@ class TestBucket < MiniTest::Unit::TestCase
128
128
  end
129
129
  end
130
130
 
131
- def test_it_unable_to_connect_to_protected_buckets_with_wrond_credentials
131
+ def test_it_unable_to_connect_to_protected_buckets_with_wrong_credentials
132
132
  with_mock(:buckets_spec => 'protected:secret') do |mock|
133
133
  assert_raises Couchbase::Error::Auth do
134
134
  Couchbase.new(:hostname => mock.host,
@@ -0,0 +1,73 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require File.join(File.dirname(__FILE__), 'setup')
19
+ require 'couchbase/connection_pool'
20
+
21
+ class TestCouchbaseConnectionPool < MiniTest::Unit::TestCase
22
+
23
+ def setup
24
+ @mock = start_mock
25
+ @pool = ::Couchbase::ConnectionPool.new(5, :hostname => @mock.host, :port => @mock.port)
26
+ end
27
+
28
+ def teardown
29
+ stop_mock(@mock)
30
+ end
31
+
32
+ def test_basic_multithreaded_usage
33
+ @pool.set('foo', 'bar')
34
+
35
+ threads = []
36
+ 15.times do
37
+ threads << Thread.new do
38
+ @pool.get('foo')
39
+ end
40
+ end
41
+
42
+ result = threads.map(&:value)
43
+ result.each do |val|
44
+ assert_equal 'bar', val
45
+ end
46
+ end
47
+
48
+ def test_set_and_get
49
+ @pool.set('fiz', 'buzz')
50
+ assert_equal 'buzz', @pool.get('fiz')
51
+ end
52
+
53
+ def test_set_and_delete
54
+ @pool.set('baz', 'bar')
55
+ @pool.delete('baz')
56
+ assert_raises Couchbase::Error::NotFound do
57
+ @pool.get('baz')
58
+ end
59
+ end
60
+
61
+ def test_incr
62
+ @pool.set('counter', 0)
63
+ @pool.incr('counter', 1)
64
+ assert_equal 1, @pool.get('counter')
65
+ end
66
+
67
+ def test_decr
68
+ @pool.set('counter', 1)
69
+ @pool.decr('counter', 1)
70
+ assert_equal 0, @pool.get('counter')
71
+ end
72
+
73
+ end
@@ -37,6 +37,12 @@ class TestCouchbaseRailsCacheStore < MiniTest::Unit::TestCase
37
37
  :port => @mock.port)
38
38
  end
39
39
 
40
+ def pool_store
41
+ @pool_store ||= ActiveSupport::Cache::CouchbaseStore.new(:hostname => @mock.host,
42
+ :port => @mock.port,
43
+ :connection_pool => 5)
44
+ end
45
+
40
46
  def test_it_supported_methods
41
47
  supported_methods = store.public_methods(false).map(&:to_sym)
42
48
  assert supported_methods.include?(:fetch)
@@ -78,18 +84,17 @@ class TestCouchbaseRailsCacheStore < MiniTest::Unit::TestCase
78
84
  end
79
85
  end
80
86
 
81
- if RUBY_VERSION.match /1\.9/
82
- def test_it_reads_raw_data
83
- store.write uniq_id, @foo
84
- assert_equal "\x04\bU:\x0FOpenStruct{\x06:\fpayloadI\"\bfoo\x06:\x06EF",
85
- store.read(uniq_id, :raw => true)
86
- end
87
- else
88
- def test_it_reads_raw_data
89
- store.write uniq_id, @foo
90
- assert_equal "\004\bU:\017OpenStruct{\006:\fpayload\"\bfoo",
91
- store.read(uniq_id, :raw => true)
92
- end
87
+ def test_it_reads_raw_data
88
+ store.write uniq_id, @foo
89
+ expected = case RUBY_VERSION
90
+ when /^2\.0/
91
+ "\x04\bU:\x0FOpenStruct{\x06:\fpayloadI\"\bfoo\x06:\x06ET"
92
+ when /^1\.9/
93
+ "\x04\bU:\x0FOpenStruct{\x06:\fpayloadI\"\bfoo\x06:\x06EF"
94
+ else
95
+ "\004\bU:\017OpenStruct{\006:\fpayload\"\bfoo"
96
+ end
97
+ assert_equal expected, store.read(uniq_id, :raw => true)
93
98
  end
94
99
 
95
100
  def test_it_writes_raw_data
@@ -303,6 +308,25 @@ class TestCouchbaseRailsCacheStore < MiniTest::Unit::TestCase
303
308
  workers.each { |w| w.join }
304
309
  end
305
310
 
311
+ def test_it_can_use_connection_pool_for_thread_safety
312
+ workers = []
313
+
314
+ 10.times do
315
+ workers << Thread.new do
316
+ 100.times do
317
+ pool_store.write('a', 9)
318
+ pool_store.write('b', 11)
319
+ assert_equal 9, pool_store.read('a')
320
+ assert_equal({ 'a' => 9, 'b' => 11 }, pool_store.read_multi('a', 'b'))
321
+ assert_equal 11, pool_store.read('b')
322
+ assert_equal %w(a b), pool_store.read_multi('a', 'b', 'c').keys.sort
323
+ end
324
+ end
325
+ end
326
+
327
+ workers.each { |w| w.join }
328
+ end
329
+
306
330
  private
307
331
 
308
332
  def collect_notifications
@@ -78,7 +78,7 @@ class TestFormat < MiniTest::Unit::TestCase
78
78
  connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
79
79
  connection.set(uniq_id, orig_doc, :format => :marshal)
80
80
  doc, flags, cas = connection.get(uniq_id, :extended => true)
81
- assert_equal 0x01, flags & 0x11
81
+ assert_equal Couchbase::Bucket::FMT_MARSHAL, flags & Couchbase::Bucket::FMT_MASK
82
82
  assert doc.is_a?(ArbitraryClass)
83
83
  assert_equal 'Twoflower', doc.name
84
84
  assert_equal 'The tourist', doc.role
@@ -106,4 +106,54 @@ class TestFormat < MiniTest::Unit::TestCase
106
106
  end
107
107
  end
108
108
 
109
+ def test_it_allows_to_turn_off_transcoder
110
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :transcoder => nil)
111
+ connection.set(uniq_id, "value", :flags => 0xffff_ffff)
112
+ doc, flags, _ = connection.get(uniq_id, :extended => true)
113
+ assert_equal "value", doc
114
+ assert_equal 0xffff_ffff, flags
115
+ end
116
+
117
+ require 'zlib'
118
+ # This class wraps any other transcoder and performs compression
119
+ # using zlib
120
+ class ZlibTranscoder
121
+ FMT_ZLIB = 0x04
122
+
123
+ def initialize(base)
124
+ @base = base
125
+ end
126
+
127
+ def dump(obj, flags, options = {})
128
+ obj, flags = @base.dump(obj, flags, options)
129
+ z = Zlib::Deflate.new(Zlib::BEST_SPEED)
130
+ buffer = z.deflate(obj, Zlib::FINISH)
131
+ z.close
132
+ [buffer, flags|FMT_ZLIB]
133
+ end
134
+
135
+ def load(blob, flags, options = {})
136
+ # decompress value only if Zlib flag set
137
+ if (flags & FMT_ZLIB) == FMT_ZLIB
138
+ z = Zlib::Inflate.new
139
+ blob = z.inflate(blob)
140
+ z.finish
141
+ z.close
142
+ end
143
+ @base.load(blob, flags, options)
144
+ end
145
+ end
146
+
147
+ def test_it_can_use_custom_transcoder
148
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
149
+ connection.transcoder = ZlibTranscoder.new(Couchbase::Transcoder::Document)
150
+ connection.set(uniq_id, {"foo" => "bar"})
151
+ doc, flags, _ = connection.get(uniq_id, :extended => true)
152
+ assert_equal({"foo" => "bar"}, doc)
153
+ assert_equal(ZlibTranscoder::FMT_ZLIB|Couchbase::Bucket::FMT_DOCUMENT, flags)
154
+ connection.transcoder = nil
155
+ doc = connection.get(uniq_id)
156
+ assert_equal "x\x01\xABVJ\xCB\xCFW\xB2RJJ,R\xAA\x05\0\x1Dz\x044", doc
157
+ end
158
+
109
159
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 1.3.0
5
5
  prerelease:
6
6
  platform: x86-mingw32
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-02 00:00:00.000000000 Z
12
+ date: 2013-05-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yaji
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: '1.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: connection_pool
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.2
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: rake
48
64
  requirement: !ruby/object:Gem::Requirement
@@ -175,6 +191,16 @@ files:
175
191
  - examples/chat-em/Gemfile
176
192
  - examples/chat-em/README.markdown
177
193
  - examples/chat-em/server.rb
194
+ - examples/chat-goliath-grape/Gemfile
195
+ - examples/chat-goliath-grape/README.markdown
196
+ - examples/chat-goliath-grape/app.rb
197
+ - examples/chat-goliath-grape/config/app.rb
198
+ - examples/transcoders/Gemfile
199
+ - examples/transcoders/README.markdown
200
+ - examples/transcoders/cb-zcat
201
+ - examples/transcoders/cb-zcp
202
+ - examples/transcoders/gzip_transcoder.rb
203
+ - examples/transcoders/options.rb
178
204
  - ext/couchbase_ext/.gitignore
179
205
  - ext/couchbase_ext/arguments.c
180
206
  - ext/couchbase_ext/arithmetic.c
@@ -204,8 +230,10 @@ files:
204
230
  - lib/couchbase.rb
205
231
  - lib/couchbase/bucket.rb
206
232
  - lib/couchbase/cluster.rb
233
+ - lib/couchbase/connection_pool.rb
207
234
  - lib/couchbase/constants.rb
208
235
  - lib/couchbase/result.rb
236
+ - lib/couchbase/transcoder.rb
209
237
  - lib/couchbase/utils.rb
210
238
  - lib/couchbase/version.rb
211
239
  - lib/couchbase/view.rb
@@ -225,6 +253,7 @@ files:
225
253
  - test/test_bucket.rb
226
254
  - test/test_cas.rb
227
255
  - test/test_couchbase.rb
256
+ - test/test_couchbase_connection_pool.rb
228
257
  - test/test_couchbase_rails_cache_store.rb
229
258
  - test/test_delete.rb
230
259
  - test/test_errors.rb
@@ -256,7 +285,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
256
285
  version: '0'
257
286
  segments:
258
287
  - 0
259
- hash: -322659644960790893
288
+ hash: 3514560369886917635
260
289
  required_rubygems_version: !ruby/object:Gem::Requirement
261
290
  none: false
262
291
  requirements:
@@ -265,7 +294,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
294
  version: '0'
266
295
  segments:
267
296
  - 0
268
- hash: -322659644960790893
297
+ hash: 3514560369886917635
269
298
  requirements: []
270
299
  rubyforge_project:
271
300
  rubygems_version: 1.8.23