couchbase 1.2.2-x86-mingw32 → 1.2.3-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.
- data/CONTRIBUTING.markdown +75 -0
- data/RELEASE_NOTES.markdown +8 -0
- data/ext/couchbase_ext/extconf.rb +1 -0
- data/ext/couchbase_ext/gethrtime.c +5 -0
- data/ext/couchbase_ext/store.c +17 -1
- data/lib/active_support/cache/couchbase_store.rb +23 -7
- data/lib/couchbase.rb +14 -1
- data/lib/couchbase/version.rb +1 -1
- data/tasks/util.rake +1 -1
- data/test/test_couchbase.rb +49 -0
- data/test/test_couchbase_rails_cache_store.rb +23 -0
- metadata +5 -4
@@ -0,0 +1,75 @@
|
|
1
|
+
We've decided to use "gerrit" for our code review system, making it
|
2
|
+
easier for all of us to contribute with code and comments.
|
3
|
+
|
4
|
+
1. Visit http://review.couchbase.org and "Register" for an account
|
5
|
+
2. Review http://review.couchbase.org/static/individual_agreement.html
|
6
|
+
3. Agree to agreement by visiting http://review.couchbase.org/#/settings/agreements
|
7
|
+
4. If you do not receive an email, please contact us
|
8
|
+
5. Check out the `couchbase-ruby-client` area http://review.couchbase.org/#/q/status:open+project:couchbase-ruby-client,n,z
|
9
|
+
6. Join us on IRC at #libcouchbase on Freenode :-)
|
10
|
+
|
11
|
+
We normally don't go looking for stuff in gerrit, so you should add at
|
12
|
+
least me `"Sergey Avseyev" <sergey.avseyev@gmail.com>` as a reviewer
|
13
|
+
for your patch (and I'll know who else to add and add them for you).
|
14
|
+
|
15
|
+
## Contributing Using Repo Tool
|
16
|
+
|
17
|
+
Follow ["Uploading Changes" guide][1] on the site if you have some code to contribute.
|
18
|
+
|
19
|
+
All you should need to set up your development environment should be:
|
20
|
+
|
21
|
+
~ % mkdir couchbase-ruby
|
22
|
+
~ % cd couchbase-ruby
|
23
|
+
~/couchbase-ruby % repo init -u git://github.com/trondn/manifests.git -m ruby.xml
|
24
|
+
~/couchbase-ruby % repo sync
|
25
|
+
~/couchbase-ruby % repo start my-branch-name --all
|
26
|
+
~/couchbase-ruby % make
|
27
|
+
|
28
|
+
This will build the latest version of `libcouchbase`,
|
29
|
+
`couchbase-ruby-client` and `couchbase-ruby-client` libraries. You must
|
30
|
+
have a C and C++ compiler installed, automake, autoconf.
|
31
|
+
|
32
|
+
If you have to make any changes just commit them before you upload
|
33
|
+
them to gerrit with the following command:
|
34
|
+
|
35
|
+
~/couchbase-ruby/client % repo upload
|
36
|
+
|
37
|
+
You might experience a problem trying to upload the patches if you've
|
38
|
+
selected a different login name at http://review.couchbase.org than
|
39
|
+
your login name. Don't worry, all you need to do is to add the
|
40
|
+
following to your ~/.gitconfig file:
|
41
|
+
|
42
|
+
[review "review.couchbase.org"]
|
43
|
+
username = YOURNAME
|
44
|
+
|
45
|
+
## Contributing Using Plain Git
|
46
|
+
|
47
|
+
If you not so familiar with repo tool and its workflow there is
|
48
|
+
alternative way to do the same job. Lets assume you have installed
|
49
|
+
couchbase gem and libcouchbase from official packages and would you to
|
50
|
+
contribute to couchbase-client gem only. Then you just need to complete
|
51
|
+
gerrit registration steps above and clone the source repository
|
52
|
+
(remember the repository on github.com is just a mirror):
|
53
|
+
|
54
|
+
~ % git clone ssh://YOURNAME@review.couchbase.org:29418/couchbase-ruby-client.git
|
55
|
+
|
56
|
+
Install [`commit-msg` hook][2]:
|
57
|
+
|
58
|
+
~/couchbase-ruby-client % scp -p -P 29418 YOURNAME@review.couchbase.org:hooks/commit-msg .git/hooks/
|
59
|
+
|
60
|
+
Make your changes and upload them for review:
|
61
|
+
|
62
|
+
~/couchbase-ruby-client % git commit
|
63
|
+
~/couchbase-ruby-client % git push origin HEAD:refs/for/master
|
64
|
+
|
65
|
+
If you need to fix or add something to your patch, do it and re-upload
|
66
|
+
the changes (all you need is to keep `Change-Id:` line the same to
|
67
|
+
allow gerrit to track the patch.
|
68
|
+
|
69
|
+
~/couchbase-ruby-client % git commit --amend
|
70
|
+
~/couchbase-ruby-client % git push origin HEAD:refs/for/master
|
71
|
+
|
72
|
+
Happy hacking!
|
73
|
+
|
74
|
+
[1]: http://review.couchbase.org/Documentation/user-upload.html
|
75
|
+
[2]: http://review.couchbase.org/Documentation/user-changeid.html
|
data/RELEASE_NOTES.markdown
CHANGED
@@ -3,6 +3,14 @@
|
|
3
3
|
This document is a list of user visible feature changes and important
|
4
4
|
bugfixes. Do not forget to update this doc in every important patch.
|
5
5
|
|
6
|
+
## 1.2.3 (2013-04-02)
|
7
|
+
|
8
|
+
* [major] Make ActiveSupport::Cache::CouchbaseStore threadsafe
|
9
|
+
|
10
|
+
* [minor] Check for gethrtime. Needed for solaris/smartos
|
11
|
+
|
12
|
+
* [minor] Update documentation bits regarding SET operations
|
13
|
+
|
6
14
|
## 1.2.2 (2013-02-11)
|
7
15
|
|
8
16
|
* [minor] Bucket#design_docs will return a Hash with DesignDoc
|
@@ -135,6 +135,7 @@ have_type("st_index_t")
|
|
135
135
|
have_func("clock_gettime")
|
136
136
|
have_func("gettimeofday")
|
137
137
|
have_func("QueryPerformanceCounter")
|
138
|
+
have_func("gethrtime")
|
138
139
|
have_func("rb_hash_lookup2")
|
139
140
|
have_func("rb_thread_fd_select")
|
140
141
|
have_func("rb_thread_blocking_region")
|
@@ -16,6 +16,9 @@
|
|
16
16
|
*/
|
17
17
|
|
18
18
|
#include "couchbase_ext.h"
|
19
|
+
|
20
|
+
#ifndef HAVE_GETHRTIME
|
21
|
+
|
19
22
|
#include <stdlib.h>
|
20
23
|
#include <time.h>
|
21
24
|
#include <assert.h>
|
@@ -122,3 +125,5 @@ hrtime_t gethrtime(void)
|
|
122
125
|
#error "I don't know how to build a highres clock..."
|
123
126
|
#endif
|
124
127
|
}
|
128
|
+
|
129
|
+
#endif
|
data/ext/couchbase_ext/store.c
CHANGED
@@ -228,6 +228,22 @@ cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
|
|
228
228
|
* @example Store the key which will be expired in 2 seconds using relative TTL.
|
229
229
|
* c.set("foo", "bar", :ttl => 2)
|
230
230
|
*
|
231
|
+
* @example Perform multi-set operation. It takes a Hash store its keys/values into the bucket
|
232
|
+
* c.set("foo1" => "bar1", "foo2" => "bar2")
|
233
|
+
* #=> {"foo1" => cas1, "foo2" => cas2}
|
234
|
+
*
|
235
|
+
* @example More advanced multi-set using asynchronous mode
|
236
|
+
* c.run do
|
237
|
+
* # fire and forget
|
238
|
+
* c.set("foo1", "bar1", :ttl => 10)
|
239
|
+
* # receive result into the callback
|
240
|
+
* c.set("foo2", "bar2", :ttl => 10) do |ret|
|
241
|
+
* if ret.success?
|
242
|
+
* puts ret.cas
|
243
|
+
* end
|
244
|
+
* end
|
245
|
+
* end
|
246
|
+
*
|
231
247
|
* @example Store the key which will be expired in 2 seconds using absolute TTL.
|
232
248
|
* c.set("foo", "bar", :ttl => Time.now.to_i + 2)
|
233
249
|
*
|
@@ -235,7 +251,7 @@ cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
|
|
235
251
|
* c.set("foo", {"bar" => "baz}, :format => :document)
|
236
252
|
*
|
237
253
|
* @example Use hash-like syntax to store the value
|
238
|
-
* c
|
254
|
+
* c["foo"] = {"bar" => "baz}
|
239
255
|
*
|
240
256
|
* @example Use extended hash-like syntax
|
241
257
|
* c["foo", {:flags => 0x1000, :format => :plain}] = "bar"
|
@@ -19,6 +19,7 @@ require 'couchbase'
|
|
19
19
|
require 'securerandom'
|
20
20
|
require 'active_support/core_ext/array/extract_options'
|
21
21
|
require 'active_support/cache'
|
22
|
+
require 'monitor'
|
22
23
|
|
23
24
|
module ActiveSupport
|
24
25
|
module Cache
|
@@ -56,6 +57,7 @@ module ActiveSupport
|
|
56
57
|
options[:key_prefix] ||= options.delete(:namespace)
|
57
58
|
args.push(options)
|
58
59
|
@data = ::Couchbase::Bucket.new(*args)
|
60
|
+
@lock = Monitor.new
|
59
61
|
end
|
60
62
|
|
61
63
|
# Fetches data from the cache, using the given key.
|
@@ -182,7 +184,9 @@ module ActiveSupport
|
|
182
184
|
options[:format] = :plain
|
183
185
|
end
|
184
186
|
instrument(:read_multi, names, options) do
|
185
|
-
@
|
187
|
+
@lock.synchronize do
|
188
|
+
@data.get(names, options)
|
189
|
+
end
|
186
190
|
end
|
187
191
|
rescue ::Couchbase::Error::Base => e
|
188
192
|
logger.error("#{e.class}: #{e.message}") if logger
|
@@ -243,7 +247,9 @@ module ActiveSupport
|
|
243
247
|
options[:create] = true
|
244
248
|
instrument(:increment, name, options) do |payload|
|
245
249
|
payload[:amount] = amount if payload
|
246
|
-
@
|
250
|
+
@lock.synchronize do
|
251
|
+
@data.incr(name, amount, options)
|
252
|
+
end
|
247
253
|
end
|
248
254
|
rescue ::Couchbase::Error::Base => e
|
249
255
|
logger.error("#{e.class}: #{e.message}") if logger
|
@@ -275,7 +281,9 @@ module ActiveSupport
|
|
275
281
|
options[:create] = true
|
276
282
|
instrument(:decrement, name, options) do |payload|
|
277
283
|
payload[:amount] = amount if payload
|
278
|
-
@
|
284
|
+
@lock.synchronize do
|
285
|
+
@data.decr(name, amount, options)
|
286
|
+
end
|
279
287
|
end
|
280
288
|
rescue ::Couchbase::Error::Base => e
|
281
289
|
logger.error("#{e.class}: #{e.message}") if logger
|
@@ -289,14 +297,18 @@ module ActiveSupport
|
|
289
297
|
#
|
290
298
|
# @return [Hash]
|
291
299
|
def stats(*arg)
|
292
|
-
@
|
300
|
+
@lock.synchronize do
|
301
|
+
@data.stats(*arg)
|
302
|
+
end
|
293
303
|
end
|
294
304
|
|
295
305
|
protected
|
296
306
|
|
297
307
|
# Read an entry from the cache.
|
298
308
|
def read_entry(key, options) # :nodoc:
|
299
|
-
@
|
309
|
+
@lock.synchronize do
|
310
|
+
@data.get(key, options)
|
311
|
+
end
|
300
312
|
rescue ::Couchbase::Error::Base => e
|
301
313
|
logger.error("#{e.class}: #{e.message}") if logger
|
302
314
|
raise if @raise_errors
|
@@ -313,7 +325,9 @@ module ActiveSupport
|
|
313
325
|
if ttl = options.delete(:expires_in)
|
314
326
|
options[:ttl] ||= ttl
|
315
327
|
end
|
316
|
-
@
|
328
|
+
@lock.synchronize do
|
329
|
+
@data.send(method, key, value, options)
|
330
|
+
end
|
317
331
|
rescue ::Couchbase::Error::Base => e
|
318
332
|
logger.error("#{e.class}: #{e.message}") if logger
|
319
333
|
raise if @raise_errors
|
@@ -322,7 +336,9 @@ module ActiveSupport
|
|
322
336
|
|
323
337
|
# Delete an entry from the cache.
|
324
338
|
def delete_entry(key, options) # :nodoc:
|
325
|
-
@
|
339
|
+
@lock.synchronize do
|
340
|
+
@data.delete(key, options)
|
341
|
+
end
|
326
342
|
rescue ::Couchbase::Error::Base => e
|
327
343
|
logger.error("#{e.class}: #{e.message}") if logger
|
328
344
|
raise if @raise_errors
|
data/lib/couchbase.rb
CHANGED
@@ -73,7 +73,18 @@ module Couchbase
|
|
73
73
|
|
74
74
|
# @private the thread local storage
|
75
75
|
def thread_storage
|
76
|
-
Thread.current[:couchbase] ||= {}
|
76
|
+
Thread.current[:couchbase] ||= { :pid => Process.pid }
|
77
|
+
end
|
78
|
+
|
79
|
+
# @private resets thread local storage if process ids don't match
|
80
|
+
# see 13.3.1: http://www.modrails.com/documentation/Users%20guide%20Apache.html
|
81
|
+
def verify_connection!
|
82
|
+
reset_thread_storage! if thread_storage[:pid] != Process.pid
|
83
|
+
end
|
84
|
+
|
85
|
+
# @private resets thread local storage
|
86
|
+
def reset_thread_storage!
|
87
|
+
Thread.current[:couchbase] = nil
|
77
88
|
end
|
78
89
|
|
79
90
|
# The connection instance for current thread
|
@@ -87,6 +98,7 @@ module Couchbase
|
|
87
98
|
#
|
88
99
|
# @return [Bucket]
|
89
100
|
def bucket
|
101
|
+
verify_connection!
|
90
102
|
thread_storage[:bucket] ||= connect(connection_options)
|
91
103
|
end
|
92
104
|
|
@@ -96,6 +108,7 @@ module Couchbase
|
|
96
108
|
#
|
97
109
|
# @return [Bucket]
|
98
110
|
def bucket=(connection)
|
111
|
+
verify_connection!
|
99
112
|
thread_storage[:bucket] = connection
|
100
113
|
end
|
101
114
|
|
data/lib/couchbase/version.rb
CHANGED
data/tasks/util.rake
CHANGED
data/test/test_couchbase.rb
CHANGED
@@ -16,13 +16,62 @@
|
|
16
16
|
#
|
17
17
|
|
18
18
|
require File.join(File.dirname(__FILE__), 'setup')
|
19
|
+
require 'minitest/mock'
|
19
20
|
|
20
21
|
class TestCouchbase < MiniTest::Unit::TestCase
|
21
22
|
|
23
|
+
def teardown
|
24
|
+
Couchbase.reset_thread_storage!
|
25
|
+
end
|
26
|
+
|
22
27
|
def test_that_it_create_instance_of_bucket
|
23
28
|
with_mock do |mock|
|
24
29
|
assert_instance_of Couchbase::Bucket, Couchbase.new("http://#{mock.host}:#{mock.port}/pools/default")
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
33
|
+
def test_verify_connection
|
34
|
+
pid = Process.pid
|
35
|
+
assert_equal pid, Couchbase.thread_storage[:pid]
|
36
|
+
Couchbase.verify_connection!
|
37
|
+
assert_equal pid, Couchbase.thread_storage[:pid]
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_verify_connection_when_process_forks
|
41
|
+
pid = Process.pid
|
42
|
+
assert_equal pid, Couchbase.thread_storage[:pid]
|
43
|
+
|
44
|
+
# stub a simulated Kernel#fork
|
45
|
+
Process.stub(:pid, Process.pid + 1) do
|
46
|
+
Couchbase.verify_connection!
|
47
|
+
refute_equal pid, Couchbase.thread_storage[:pid]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_new_connection_when_process_forks
|
52
|
+
with_mock do |mock|
|
53
|
+
connection_options = "http://#{mock.host}:#{mock.port}/pools/default"
|
54
|
+
Couchbase.connection_options = connection_options
|
55
|
+
old_bucket_id = Couchbase.bucket.object_id
|
56
|
+
|
57
|
+
Process.stub(:pid, Process.pid + 1) do
|
58
|
+
refute_equal old_bucket_id, Couchbase.bucket.object_id
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_new_connection_has_same_configuration_options
|
64
|
+
with_mock do |mock|
|
65
|
+
connection_options = "http://#{mock.host}:#{mock.port}/pools/default"
|
66
|
+
Couchbase.connection_options = connection_options
|
67
|
+
old_bucket = Couchbase.bucket
|
68
|
+
|
69
|
+
Process.stub(:pid, Process.pid + 1) do
|
70
|
+
new_bucket = Couchbase.bucket
|
71
|
+
assert_equal old_bucket.name, new_bucket.name
|
72
|
+
assert_equal old_bucket.hostname, new_bucket.hostname
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
28
77
|
end
|
@@ -280,6 +280,29 @@ class TestCouchbaseRailsCacheStore < MiniTest::Unit::TestCase
|
|
280
280
|
assert_equal({:key => uniq_id, :amount => 1, :create => true}, decrement.payload)
|
281
281
|
end
|
282
282
|
|
283
|
+
# Inspiration: https://github.com/mperham/dalli/blob/master/test/test_dalli.rb#L416
|
284
|
+
def test_it_is_threadsafe
|
285
|
+
workers = []
|
286
|
+
|
287
|
+
# Have a bunch of threads perform a bunch of operations at the same time.
|
288
|
+
# Verify the result of each operation to ensure the request and response
|
289
|
+
# are not intermingled between threads.
|
290
|
+
10.times do
|
291
|
+
workers << Thread.new do
|
292
|
+
100.times do
|
293
|
+
store.write('a', 9)
|
294
|
+
store.write('b', 11)
|
295
|
+
assert_equal 9, store.read('a')
|
296
|
+
assert_equal({ 'a' => 9, 'b' => 11 }, store.read_multi('a', 'b'))
|
297
|
+
assert_equal 11, store.read('b')
|
298
|
+
assert_equal %w(a b), store.read_multi('a', 'b', 'c').keys.sort
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
workers.each { |w| w.join }
|
304
|
+
end
|
305
|
+
|
283
306
|
private
|
284
307
|
|
285
308
|
def collect_notifications
|
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.
|
4
|
+
version: 1.2.3
|
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-02
|
12
|
+
date: 2013-04-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: yaji
|
@@ -164,6 +164,7 @@ files:
|
|
164
164
|
- .gitignore
|
165
165
|
- .travis.yml
|
166
166
|
- .yardopts
|
167
|
+
- CONTRIBUTING.markdown
|
167
168
|
- Gemfile
|
168
169
|
- LICENSE
|
169
170
|
- Makefile
|
@@ -255,7 +256,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
255
256
|
version: '0'
|
256
257
|
segments:
|
257
258
|
- 0
|
258
|
-
hash:
|
259
|
+
hash: -322659644960790893
|
259
260
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
260
261
|
none: false
|
261
262
|
requirements:
|
@@ -264,7 +265,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
264
265
|
version: '0'
|
265
266
|
segments:
|
266
267
|
- 0
|
267
|
-
hash:
|
268
|
+
hash: -322659644960790893
|
268
269
|
requirements: []
|
269
270
|
rubyforge_project:
|
270
271
|
rubygems_version: 1.8.23
|