couchbase 1.3.3-x86-mingw32 → 1.3.4-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +97 -29
- data/RELEASE_NOTES.markdown +26 -0
- data/Rakefile +0 -2
- data/couchbase.gemspec +6 -6
- data/ext/couchbase_ext/arithmetic.c +1 -0
- data/ext/couchbase_ext/extconf.rb +10 -2
- data/ext/couchbase_ext/multithread_plugin.c +19 -10
- data/lib/active_support/cache/couchbase_store.rb +18 -2
- data/lib/couchbase/bucket.rb +31 -4
- data/lib/couchbase/cluster.rb +16 -2
- data/lib/couchbase/version.rb +1 -1
- data/tasks/compile.rake +63 -25
- data/test/test_arithmetic.rb +9 -0
- data/test/test_cas.rb +158 -0
- data/test/test_couchbase_rails_cache_store.rb +20 -0
- data/test/test_format.rb +6 -1
- metadata +78 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 221f1d443a518cad70e8ead8d41d7c608dbb908e
|
4
|
+
data.tar.gz: 86524a93db4d704a9a63b7ef242dbb5f904901b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04ba277b1f42d6f2fade8012c4d855ba8c4846d33087849e93748066d4adf10dd7403a6983f253cc848069c86b51ffba8a598004d8be6916cd4e31687b53472f
|
7
|
+
data.tar.gz: 019154be57677cf09f9ff39a30a1eba41a59757005c1850ec6e1fad91bb347cdd199e7b8a5368b47d13745d41775a62d58f0bef4a61004f9b6ff152603a604da
|
data/README.markdown
CHANGED
@@ -8,10 +8,11 @@ are related libraries available:
|
|
8
8
|
|
9
9
|
## SUPPORT
|
10
10
|
|
11
|
-
If you
|
12
|
-
always welcome on `#libcouchbase` channel at [freenode.net IRC servers][2].
|
11
|
+
If you find an issue, please file it in our [JIRA][1]. Also you are
|
12
|
+
always welcome on the `#libcouchbase` channel at [freenode.net IRC servers][2].
|
13
13
|
|
14
|
-
Documentation: [http://
|
14
|
+
Documentation: [http://docs.couchbase.com/couchbase-sdk-ruby-1.3/](http://docs.couchbase.com/couchbase-sdk-ruby-1.3/)
|
15
|
+
API Documentation: [http://www.couchbase.com/autodocs/](http://www.couchbase.com/autodocs/)
|
15
16
|
|
16
17
|
## INSTALL
|
17
18
|
|
@@ -39,7 +40,7 @@ your OS release:
|
|
39
40
|
# Ubuntu 10.04 Lucid Lynx (Debian stable or testing)
|
40
41
|
deb http://packages.couchbase.com/ubuntu lucid lucid/main
|
41
42
|
|
42
|
-
Import Couchbase PGP key:
|
43
|
+
Import the Couchbase PGP key:
|
43
44
|
|
44
45
|
wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
|
45
46
|
|
@@ -47,7 +48,7 @@ Then install them
|
|
47
48
|
|
48
49
|
$ sudo apt-get update && sudo apt-get install libcouchbase-dev
|
49
50
|
|
50
|
-
Again, if you need preview
|
51
|
+
Again, if you need a preview of a future version, just use another repository in
|
51
52
|
your `couchbase.list`
|
52
53
|
|
53
54
|
# Ubuntu 11.10 Oneiric Ocelot (Debian unstable)
|
@@ -72,8 +73,8 @@ Then to install libcouchbase itself, run:
|
|
72
73
|
|
73
74
|
$ sudo yum update && sudo yum install libcouchbase-devel
|
74
75
|
|
75
|
-
We have preview repositories for RPMs too, use them if you
|
76
|
-
|
76
|
+
We have preview repositories for RPMs too, use them if you want to try
|
77
|
+
the latest version of libcouchbase:
|
77
78
|
|
78
79
|
[couchbase]
|
79
80
|
name = Couchbase package repository
|
@@ -85,8 +86,8 @@ fresh version of couchbase gem:
|
|
85
86
|
|
86
87
|
### Windows
|
87
88
|
|
88
|
-
There no additional dependencies for Windows systems. The gem
|
89
|
-
prebuilt binary for it.
|
89
|
+
There are no additional dependencies for Windows systems. The gem carries
|
90
|
+
a prebuilt binary for it.
|
90
91
|
|
91
92
|
### Couchbase gem
|
92
93
|
|
@@ -96,12 +97,12 @@ Now install the couchbase gem itself
|
|
96
97
|
|
97
98
|
## USAGE
|
98
99
|
|
99
|
-
First
|
100
|
+
First, you need to load the library:
|
100
101
|
|
101
102
|
require 'couchbase'
|
102
103
|
|
103
|
-
There are several ways to establish new connection to Couchbase Server.
|
104
|
-
By default it uses
|
104
|
+
There are several ways to establish a new connection to Couchbase Server.
|
105
|
+
By default it uses `http://localhost:8091/pools/default/buckets/default`
|
105
106
|
as the endpoint. The client will automatically adjust configuration when
|
106
107
|
the cluster will rebalance its nodes when nodes are added or deleted
|
107
108
|
therefore this client is "smart".
|
@@ -122,13 +123,13 @@ The hash parameters take precedence on string URL.
|
|
122
123
|
If you worry about state of your nodes or not sure what node is alive,
|
123
124
|
you can pass the list of nodes and the library will iterate over it
|
124
125
|
until finds the working one. From that moment it won't use **your**
|
125
|
-
list, because node list from cluster config
|
126
|
+
list, because node list from cluster config carries more detail.
|
126
127
|
|
127
128
|
c = Couchbase.connect(:bucket => "mybucket",
|
128
129
|
:node_list => ['example.com:8091', example.net'])
|
129
130
|
|
130
|
-
There is also handy method `Couchbase.bucket` which uses thread local
|
131
|
-
storage to keep
|
131
|
+
There is also a handy method `Couchbase.bucket` which uses thread local
|
132
|
+
storage to keep a reference to a connection. You can set the
|
132
133
|
connection options via `Couchbase.connection_options`:
|
133
134
|
|
134
135
|
Couchbase.connection_options = {:bucket => 'blog'}
|
@@ -137,9 +138,9 @@ connection options via `Couchbase.connection_options`:
|
|
137
138
|
|
138
139
|
The library supports both synchronous and asynchronous mode. In
|
139
140
|
asynchronous mode all operations will return control to caller
|
140
|
-
without blocking current thread. You can pass
|
141
|
+
without blocking current thread. You can pass a block to the method and it
|
141
142
|
will be called with result when the operation will be completed. You
|
142
|
-
need to run event loop
|
143
|
+
need to run the event loop once you've scheduled your operations:
|
143
144
|
|
144
145
|
c = Couchbase.connect
|
145
146
|
c.run do |conn|
|
@@ -155,7 +156,7 @@ The handlers could be nested
|
|
155
156
|
end
|
156
157
|
end
|
157
158
|
|
158
|
-
The asynchronous callback receives instance of `Couchbase::Result` which
|
159
|
+
The asynchronous callback receives an instance of `Couchbase::Result` which
|
159
160
|
responds to several methods to figure out what was happened:
|
160
161
|
|
161
162
|
* `success?`. Returns `true` if operation succed.
|
@@ -171,7 +172,7 @@ responds to several methods to figure out what was happened:
|
|
171
172
|
|
172
173
|
* `cas`. The CAS version tag.
|
173
174
|
|
174
|
-
* `node`. Node address.
|
175
|
+
* `node`. Node address. This is used in the flush and stats commands.
|
175
176
|
|
176
177
|
* `operation`. The symbol, representing an operation.
|
177
178
|
|
@@ -186,14 +187,14 @@ used. It can be set in following fashions:
|
|
186
187
|
handler = lambda {|opcode, key, exc| }
|
187
188
|
c.on_error = handler
|
188
189
|
|
189
|
-
By default
|
190
|
-
exceptions when the given key
|
190
|
+
By default connections use `:quiet` mode. This mean it won't raise
|
191
|
+
exceptions when the given key does not exist:
|
191
192
|
|
192
193
|
c.get("missing-key") #=> nil
|
193
194
|
|
194
195
|
It could be useful when you are trying to make you code a bit efficient
|
195
196
|
by avoiding exception handling. (See `#add` and `#replace` operations).
|
196
|
-
You can turn on these
|
197
|
+
You can turn on these exceptions by passing `:quiet => false` when you
|
197
198
|
are instantiating the connection or change corresponding attribute:
|
198
199
|
|
199
200
|
c.quiet = false
|
@@ -278,7 +279,7 @@ Hash-like syntax
|
|
278
279
|
|
279
280
|
### Add
|
280
281
|
|
281
|
-
|
282
|
+
The add command will fail if the key already exists. It accepts the same
|
282
283
|
options as set command above.
|
283
284
|
|
284
285
|
c.add("foo", "bar")
|
@@ -338,8 +339,10 @@ Couchbase::Error::DeltaBadval if the delta or value is not a number.
|
|
338
339
|
c.incr("missing2", :create => true) #=> 0
|
339
340
|
c.incr("missing2", :create => true) #=> 1
|
340
341
|
|
341
|
-
Note that it isn't the same as increment/decrement in ruby
|
342
|
-
|
342
|
+
Note that it isn't the same as increment/decrement in ruby. A
|
343
|
+
Couchbase increment is atomic on a distributed system. The
|
344
|
+
Ruby incement could ovewrite intermediate values with multiple
|
345
|
+
clients, as shown with following `set` operation:
|
343
346
|
|
344
347
|
c["foo"] = 10
|
345
348
|
c["foo"] -= 20 #=> -10
|
@@ -469,9 +472,9 @@ To execute view you need to fetch it from design document `_design/blog`:
|
|
469
472
|
blog.views #=> ["recent_posts"]
|
470
473
|
blog.recent_posts #=> [#<Couchbase::ViewRow:9855800 @id="hello-world" @key="2009/01/15 15:52:20" @value="Hello World" @doc=nil @meta={} @views=[]>, ...]
|
471
474
|
|
472
|
-
|
473
|
-
easily
|
474
|
-
them as soon as it
|
475
|
+
The gem uses a streaming parser to access view results so you can iterate them
|
476
|
+
easily. If your code doesn't keep links to the documents the GC might free
|
477
|
+
them as soon as it decides they are unreachable, because the parser doesn't
|
475
478
|
store global JSON tree.
|
476
479
|
|
477
480
|
blog.recent_posts.each do |doc|
|
@@ -499,7 +502,7 @@ You can also use Enumerator to iterate view results
|
|
499
502
|
acc
|
500
503
|
end
|
501
504
|
|
502
|
-
|
505
|
+
Couchbase Server could generate errors during view execution with
|
503
506
|
`200 OK` and partial results. By default the library raises exception as
|
504
507
|
soon as errors detected in the result stream, but you can define the
|
505
508
|
callback `on_error` to intercept these errors and do something more
|
@@ -569,6 +572,69 @@ choose from several asynchronous IO options:
|
|
569
572
|
end
|
570
573
|
end
|
571
574
|
|
575
|
+
## HACKING
|
576
|
+
|
577
|
+
Clone the repository. For starters, you can use github mirror, but
|
578
|
+
make sure you have read and understand [CONTRIBUTING.markdown][10] if
|
579
|
+
you are going to send us patches.
|
580
|
+
|
581
|
+
$ git clone git://github.com/couchbase/couchbase-ruby-client.git
|
582
|
+
$ cd couchbase-ruby-client
|
583
|
+
|
584
|
+
Install all development dependencies. You can use any ruby version
|
585
|
+
since 1.8.7, but make sure your changes work at least on major
|
586
|
+
releases (1.8.7, 1.9.3, 2.0.0 and 2.1.0 at the moment):
|
587
|
+
|
588
|
+
$ gem install bundler
|
589
|
+
$ bundle install
|
590
|
+
|
591
|
+
Don't forget to write the tests. You can find examples in the `tests/`
|
592
|
+
directory. To run tests with a mock just compile extension and run the
|
593
|
+
`test` task, it will download a test mock of couchbase cluster as a
|
594
|
+
part of the process (the mock is generally slower, but easier to
|
595
|
+
setup):
|
596
|
+
|
597
|
+
$ rake compile test
|
598
|
+
|
599
|
+
If you have real Couchbase server installed somewhere, you can pass
|
600
|
+
its address using environment variable `COUCHBASE_SERVER` like this:
|
601
|
+
|
602
|
+
$ COUCHBASE_SERVER=localhost:8091 rake compile test
|
603
|
+
|
604
|
+
And finally, you can package the gem with your awesome changes. For
|
605
|
+
UNIX-like systems a regular source-based package will be enough, so the
|
606
|
+
command below will produce `pkg/couchbase-VERSION.gem`, where
|
607
|
+
`VERSION` is the current version from file `lib/couchbase/version.rb`:
|
608
|
+
|
609
|
+
$ rake package
|
610
|
+
|
611
|
+
The Windows operating system usually doesn't have a build environment
|
612
|
+
installed. This is why we are cross-compiling blobs for Windows from
|
613
|
+
UNIX-like boxes. To do it you need to install mingw and the
|
614
|
+
[rake-compiler][11] and then build a variety of ruby versions currently
|
615
|
+
supported on Windows. An example config looks like this:
|
616
|
+
|
617
|
+
$ rake-compiler update-config
|
618
|
+
Updating /home/avsej/.rake-compiler/config.yml
|
619
|
+
Found Ruby version 1.8.7 for platform i386-mingw32 (/home/avsej/.rake-compiler/ruby/i686-w64-mingw32/ruby-1.8.7-p374/lib/ruby/1.8/i386-mingw32/rbconfig.rb)
|
620
|
+
Found Ruby version 1.9.3 for platform i386-mingw32 (/home/avsej/.rake-compiler/ruby/i686-w64-mingw32/ruby-1.9.3-p448/lib/ruby/1.9.1/i386-mingw32/rbconfig.rb)
|
621
|
+
Found Ruby version 2.0.0 for platform i386-mingw32 (/home/avsej/.rake-compiler/ruby/i686-w64-mingw32/ruby-2.0.0-p247/lib/ruby/2.0.0/i386-mingw32/rbconfig.rb)
|
622
|
+
Found Ruby version 2.1.0 for platform i386-mingw32 (/home/avsej/.rake-compiler/ruby/i686-w64-mingw32/ruby-2.1.0/lib/ruby/2.1.0/i386-mingw32/rbconfig.rb)
|
623
|
+
Found Ruby version 1.9.3 for platform x64-mingw32 (/home/avsej/.rake-compiler/ruby/x86_64-w64-mingw32/ruby-1.9.3-p448/lib/ruby/1.9.1/x64-mingw32/rbconfig.rb)
|
624
|
+
Found Ruby version 2.0.0 for platform x64-mingw32 (/home/avsej/.rake-compiler/ruby/x86_64-w64-mingw32/ruby-2.0.0-p247/lib/ruby/2.0.0/x64-mingw32/rbconfig.rb)
|
625
|
+
Found Ruby version 2.1.0 for platform x64-mingw32 (/home/avsej/.rake-compiler/ruby/x86_64-w64-mingw32/ruby-2.1.0/lib/ruby/2.1.0/x64-mingw32/rbconfig.rb)
|
626
|
+
|
627
|
+
Before you build, check relevant ruby and libcouchbase versions in
|
628
|
+
`tasks/compile.rake`. After that you can run the `package:windows`
|
629
|
+
task and you will find all artifacts in `pkg/` directory:
|
630
|
+
|
631
|
+
$ rake package:windows
|
632
|
+
$ ls -1 pkg/*.gem
|
633
|
+
pkg/couchbase-1.3.4.gem
|
634
|
+
pkg/couchbase-1.3.4-x64-mingw32.gem
|
635
|
+
pkg/couchbase-1.3.4-x86-mingw32.gem
|
636
|
+
|
637
|
+
|
572
638
|
[1]: http://couchbase.com/issues/browse/RCBC
|
573
639
|
[2]: http://freenode.net/irc_servers.shtml
|
574
640
|
[3]: http://www.couchbase.com/develop/c/current
|
@@ -578,4 +644,6 @@ choose from several asynchronous IO options:
|
|
578
644
|
[7]: https://github.com/couchbase/couchbase-ruby-model
|
579
645
|
[8]: http://www.couchbase.com/develop/c/current
|
580
646
|
[9]: http://rubygems.org/gems/eventmachine
|
647
|
+
[10]: https://github.com/couchbase/couchbase-ruby-client/blob/master/CONTRIBUTING.markdown
|
648
|
+
[11]: https://github.com/luislavena/rake-compiler
|
581
649
|
|
data/RELEASE_NOTES.markdown
CHANGED
@@ -3,6 +3,32 @@
|
|
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.3.4 (2014-01-08)
|
7
|
+
|
8
|
+
* [major] Build 64-bit versions of the extensions for Windows
|
9
|
+
platform. Also support ruby 2.0 and 2.1.
|
10
|
+
|
11
|
+
* [minor] Update hacking section in README
|
12
|
+
|
13
|
+
* [minor] Fix gemspec warnings regarding versions of the dependencies.
|
14
|
+
Now it honours semantic versioning and doesn't use strict versions.
|
15
|
+
|
16
|
+
* [major] RCBC-151 Return CAS in extended mode for incr/decr
|
17
|
+
|
18
|
+
* [minor] RCBC-150 Update list of options on `Cluster.create_bucket`.
|
19
|
+
Added new options: `:replica_index`, `:flush_enabled`,
|
20
|
+
`:parallel_db_and_view_compaction`.
|
21
|
+
|
22
|
+
* [major] Allow retries on Couchbase::Bucket#cas collisions. Now it
|
23
|
+
takes a `:retry` Fixnum option that specifies the maximum number of
|
24
|
+
times the method should retry the entire get/update/set operation
|
25
|
+
when a `Couchbase::Error::KeyExists` error is encountered due to a
|
26
|
+
concurrent update from another writer between its `#get` and `#set`
|
27
|
+
calls.
|
28
|
+
|
29
|
+
* [major] MD5 and truncate ActiveSupport::Cache keys that are longer
|
30
|
+
than 250 characters.
|
31
|
+
|
6
32
|
## 1.3.3 (2013-09-12)
|
7
33
|
|
8
34
|
* [major] RCBC-134 Allow application to use several connections with
|
data/Rakefile
CHANGED
data/couchbase.gemspec
CHANGED
@@ -35,15 +35,15 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.extensions = `git ls-files -- ext/**/extconf.rb`.split("\n")
|
36
36
|
s.require_paths = ['lib']
|
37
37
|
|
38
|
-
s.add_runtime_dependency 'yaji', '~> 0.3.2'
|
38
|
+
s.add_runtime_dependency 'yaji', '~> 0.3', '>= 0.3.2'
|
39
39
|
s.add_runtime_dependency 'multi_json', '~> 1.0'
|
40
|
-
s.add_runtime_dependency 'connection_pool', '~> 1.0.0'
|
40
|
+
s.add_runtime_dependency 'connection_pool', '~> 1.0', '>= 1.0.0'
|
41
41
|
|
42
42
|
s.add_development_dependency 'rake'
|
43
|
-
s.add_development_dependency 'minitest', '~> 5.0.4'
|
44
|
-
s.add_development_dependency 'rake-compiler', '>= 0.7.5'
|
45
|
-
s.add_development_dependency 'mini_portile'
|
46
|
-
s.add_development_dependency 'yajl-ruby', '~> 1.1.0'
|
43
|
+
s.add_development_dependency 'minitest', '~> 5.0', '>= 5.0.4'
|
44
|
+
s.add_development_dependency 'rake-compiler', '~> 0.7', '>= 0.7.5'
|
45
|
+
s.add_development_dependency 'mini_portile', '~> 0.5', '>= 0.5.2'
|
46
|
+
s.add_development_dependency 'yajl-ruby', '~> 1.1', '>= 1.1.0'
|
47
47
|
s.add_development_dependency 'active_support'
|
48
48
|
s.add_development_dependency 'eventmachine'
|
49
49
|
end
|
@@ -89,6 +89,7 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
|
|
89
89
|
params.cmd.arith.sign = sign;
|
90
90
|
cb_params_build(¶ms);
|
91
91
|
ctx = cb_context_alloc_common(bucket, proc, params.cmd.arith.num);
|
92
|
+
ctx->extended = params.cmd.arith.extended;
|
92
93
|
err = lcb_arithmetic(bucket->handle, (const void *)ctx,
|
93
94
|
params.cmd.arith.num, params.cmd.arith.ptr);
|
94
95
|
cb_params_destroy(¶ms);
|
@@ -46,8 +46,12 @@ end
|
|
46
46
|
$CFLAGS << ' -std=c99 -Wall -Wextra '
|
47
47
|
if ENV['DEBUG']
|
48
48
|
$CFLAGS << ' -O0 -ggdb3 -pedantic '
|
49
|
+
else
|
50
|
+
$CFLAGS << ' -O2'
|
51
|
+
$LDFLAGS << ' -Wl,--strip-debug' if RbConfig::CONFIG['target_os'] =~ /mingw32/
|
49
52
|
end
|
50
53
|
|
54
|
+
|
51
55
|
if RbConfig::CONFIG['target_os'] =~ /mingw32/
|
52
56
|
dir_config("libcouchbase")
|
53
57
|
else
|
@@ -97,6 +101,7 @@ else
|
|
97
101
|
dir_config("libcouchbase", HEADER_DIRS, LIB_DIRS)
|
98
102
|
end
|
99
103
|
|
104
|
+
|
100
105
|
if COMMON_HEADERS !~ /"ruby\.h"/
|
101
106
|
(COMMON_HEADERS ||= "") << %(\n#include "ruby.h"\n)
|
102
107
|
end
|
@@ -126,6 +131,8 @@ def die(message)
|
|
126
131
|
abort
|
127
132
|
end
|
128
133
|
|
134
|
+
install_notice = "You must install libcouchbase >= 2.1.3\nSee http://www.couchbase.com/communities/c/ for more details"
|
135
|
+
|
129
136
|
unless try_compile(<<-SRC)
|
130
137
|
#include <libcouchbase/couchbase.h>
|
131
138
|
#include <stdio.h>
|
@@ -135,10 +142,11 @@ unless try_compile(<<-SRC)
|
|
135
142
|
return 0;
|
136
143
|
}
|
137
144
|
SRC
|
138
|
-
die(
|
145
|
+
die(install_notice)
|
139
146
|
end
|
140
147
|
|
141
|
-
|
148
|
+
# just to add -lcouchbase properly
|
149
|
+
have_library("couchbase", "lcb_verify_compiler_setup", "libcouchbase/couchbase.h") or die(install_notice)
|
142
150
|
have_header("mach/mach_time.h")
|
143
151
|
have_header("stdint.h") or die("Failed to locate stdint.h")
|
144
152
|
have_header("sys/time.h")
|
@@ -550,7 +550,7 @@ typedef fd_set rb_fdset_t;
|
|
550
550
|
|
551
551
|
typedef struct loop_select_arg {
|
552
552
|
rb_mt_loop *loop;
|
553
|
-
rb_fdset_t in, out;
|
553
|
+
rb_fdset_t in, out, exc;
|
554
554
|
} ls_arg;
|
555
555
|
|
556
556
|
static void
|
@@ -574,7 +574,7 @@ loop_run_select(VALUE argp)
|
|
574
574
|
{
|
575
575
|
ls_arg *args = (ls_arg*) argp;
|
576
576
|
rb_mt_loop *loop = args->loop;
|
577
|
-
rb_fdset_t *in = NULL, *out = NULL;
|
577
|
+
rb_fdset_t *in = NULL, *out = NULL, *exc = NULL;
|
578
578
|
struct timeval timeout;
|
579
579
|
struct timeval *timeoutp = NULL;
|
580
580
|
int result, max = 0;
|
@@ -598,21 +598,26 @@ loop_run_select(VALUE argp)
|
|
598
598
|
uint32_t i;
|
599
599
|
rb_fd_init(&args->in);
|
600
600
|
rb_fd_init(&args->out);
|
601
|
+
rb_fd_init(&args->exc);
|
601
602
|
for(i = 0; i < loop->events.count; i++) {
|
602
603
|
rb_mt_socket_list *list = &loop->events.sockets[i];
|
603
|
-
if (list->flags
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
604
|
+
if (list->flags != 0) {
|
605
|
+
if (list->flags & LCB_READ_EVENT) {
|
606
|
+
in = &args->in;
|
607
|
+
rb_fd_set(list->socket, in);
|
608
|
+
}
|
609
|
+
if (list->flags & LCB_WRITE_EVENT) {
|
610
|
+
out = &args->out;
|
611
|
+
rb_fd_set(list->socket, out);
|
612
|
+
}
|
613
|
+
exc = &args->exc;
|
614
|
+
rb_fd_set(list->socket, exc);
|
610
615
|
}
|
611
616
|
}
|
612
617
|
max = events_max_fd(&loop->events) + 1;
|
613
618
|
}
|
614
619
|
|
615
|
-
result = rb_thread_fd_select(max, in, out,
|
620
|
+
result = rb_thread_fd_select(max, in, out, exc, timeoutp);
|
616
621
|
|
617
622
|
if (result < 0) {
|
618
623
|
rb_sys_fail("rb_thread_fd_select");
|
@@ -636,6 +641,10 @@ loop_run_select(VALUE argp)
|
|
636
641
|
flags |= LCB_WRITE_EVENT;
|
637
642
|
result--;
|
638
643
|
}
|
644
|
+
if (exc && rb_fd_isset(list->socket, exc)) {
|
645
|
+
flags = LCB_ERROR_EVENT | LCB_WRITE_EVENT;
|
646
|
+
result--;
|
647
|
+
}
|
639
648
|
if (flags) {
|
640
649
|
loop_enque_events(&loop->callbacks, sock, flags);
|
641
650
|
}
|
@@ -55,6 +55,7 @@ module ActiveSupport
|
|
55
55
|
options[:default_ttl] ||= options.delete(:expires_in)
|
56
56
|
options[:default_format] ||= :marshal
|
57
57
|
options[:key_prefix] ||= options.delete(:namespace)
|
58
|
+
@key_prefix = options[:key_prefix]
|
58
59
|
options[:connection_pool] ||= options.delete(:connection_pool)
|
59
60
|
args.push(options)
|
60
61
|
|
@@ -348,7 +349,7 @@ module ActiveSupport
|
|
348
349
|
# object responds to +cache_key+. Otherwise, to_param method will be
|
349
350
|
# called. If the key is a Hash, then keys will be sorted alphabetically.
|
350
351
|
def expanded_key(key) # :nodoc:
|
351
|
-
return key.cache_key.to_s if key.respond_to?(:cache_key)
|
352
|
+
return validate_key(key.cache_key.to_s) if key.respond_to?(:cache_key)
|
352
353
|
|
353
354
|
case key
|
354
355
|
when Array
|
@@ -361,7 +362,22 @@ module ActiveSupport
|
|
361
362
|
key = key.sort_by { |k,_| k.to_s }.collect{|k,v| "#{k}=#{v}"}
|
362
363
|
end
|
363
364
|
|
364
|
-
key.respond_to?(:to_param) ? key.to_param : key
|
365
|
+
validate_key(key.respond_to?(:to_param) ? key.to_param : key)
|
366
|
+
end
|
367
|
+
|
368
|
+
def validate_key(key)
|
369
|
+
if key_with_prefix(key).length > 250
|
370
|
+
key = "#{key[0, max_length_before_prefix]}:md5:#{Digest::MD5.hexdigest(key)}"
|
371
|
+
end
|
372
|
+
return key
|
373
|
+
end
|
374
|
+
|
375
|
+
def key_with_prefix(key)
|
376
|
+
(ns = @key_prefix) ? "#{ns}#{key}" : key
|
377
|
+
end
|
378
|
+
|
379
|
+
def max_length_before_prefix
|
380
|
+
@max_length_before_prefix ||= 212 - (@key_prefix || '').size
|
365
381
|
end
|
366
382
|
|
367
383
|
module Threadsafe
|
data/lib/couchbase/bucket.rb
CHANGED
@@ -35,12 +35,23 @@ module Couchbase
|
|
35
35
|
#
|
36
36
|
# @see http://couchbase.com/docs/memcached-api/memcached-api-protocol-text_cas.html
|
37
37
|
#
|
38
|
+
# Setting the +:retry+ option to a positive number will cause this method
|
39
|
+
# to rescue the {Couchbase::Error::KeyExists} error that happens when
|
40
|
+
# an update collision is detected, and automatically get a fresh copy
|
41
|
+
# of the value and retry the block. This will repeat as long as there
|
42
|
+
# continues to be conflicts, up to the maximum number of retries specified.
|
43
|
+
# For asynchronous mode, this means the block will be yielded once for
|
44
|
+
# the initial {Bucket#get}, once for the final {Bucket#set} (successful
|
45
|
+
# or last failure), and zero or more additional {Bucket#get} retries
|
46
|
+
# in between, up to the maximum allowed by the +:retry+ option.
|
47
|
+
#
|
38
48
|
# @param [String, Symbol] key
|
39
49
|
#
|
40
50
|
# @param [Hash] options the options for "swap" part
|
41
51
|
# @option options [Fixnum] :ttl (self.default_ttl) the time to live of this key
|
42
52
|
# @option options [Symbol] :format (self.default_format) format of the value
|
43
53
|
# @option options [Fixnum] :flags (self.default_flags) flags for this key
|
54
|
+
# @option options [Fixnum] :retry (0) maximum number of times to autmatically retry upon update collision
|
44
55
|
#
|
45
56
|
# @yieldparam [Object, Result] value old value in synchronous mode and
|
46
57
|
# +Result+ object in asynchronous mode.
|
@@ -80,16 +91,32 @@ module Couchbase
|
|
80
91
|
#
|
81
92
|
# @return [Fixnum] the CAS of new value
|
82
93
|
def cas(key, options = {})
|
94
|
+
retries_remaining = options.delete(:retry) || 0
|
83
95
|
if async?
|
84
96
|
block = Proc.new
|
85
97
|
get(key) do |ret|
|
86
98
|
val = block.call(ret) # get new value from caller
|
87
|
-
set(ret.key, val, options.merge(:cas => ret.cas, :flags => ret.flags)
|
99
|
+
set(ret.key, val, options.merge(:cas => ret.cas, :flags => ret.flags)) do |set_ret|
|
100
|
+
if set_ret.error.is_a?(Couchbase::Error::KeyExists) && (retries_remaining > 0)
|
101
|
+
cas(key, options.merge(:retry => retries_remaining - 1), &block)
|
102
|
+
else
|
103
|
+
block.call(set_ret)
|
104
|
+
end
|
105
|
+
end
|
88
106
|
end
|
89
107
|
else
|
90
|
-
|
91
|
-
|
92
|
-
|
108
|
+
begin
|
109
|
+
val, flags, ver = get(key, :extended => true)
|
110
|
+
val = yield(val) # get new value from caller
|
111
|
+
set(key, val, options.merge(:cas => ver, :flags => flags))
|
112
|
+
rescue Couchbase::Error::KeyExists
|
113
|
+
if retries_remaining > 0
|
114
|
+
retries_remaining -= 1
|
115
|
+
retry
|
116
|
+
else
|
117
|
+
raise
|
118
|
+
end
|
119
|
+
end
|
93
120
|
end
|
94
121
|
end
|
95
122
|
alias :compare_and_swap :cas
|
data/lib/couchbase/cluster.rb
CHANGED
@@ -42,11 +42,19 @@ module Couchbase
|
|
42
42
|
# bucket. Possible values are "memcached" and "couchbase".
|
43
43
|
# @option options [Fixnum] :ram_quota (100) The RAM quota in megabytes.
|
44
44
|
# @option options [Fixnum] :replica_number (1) The number of replicas of
|
45
|
-
# each document
|
45
|
+
# each document. Minimum 0, maximum 3.
|
46
46
|
# @option options [String] :auth_type ("sasl") The authentication type.
|
47
47
|
# Possible values are "sasl" and "none". Note you should specify free
|
48
48
|
# port for "none"
|
49
49
|
# @option options [Fixnum] :proxy_port The port for moxi
|
50
|
+
# @option options [true, false] :replica_index (true) Disable or
|
51
|
+
# enable indexes for bucket replicas
|
52
|
+
# @option options [true, false] :flush_enabled (false) Enables the
|
53
|
+
# 'flush all' functionality on the specified bucket.
|
54
|
+
# @option options [true, false] :parallel_db_and_view_compaction (false)
|
55
|
+
# Indicates whether database and view files on disk can be
|
56
|
+
# compacted simultaneously
|
57
|
+
#
|
50
58
|
def create_bucket(name, options = {})
|
51
59
|
defaults = {
|
52
60
|
:type => "couchbase",
|
@@ -54,7 +62,10 @@ module Couchbase
|
|
54
62
|
:replica_number => 1,
|
55
63
|
:auth_type => "sasl",
|
56
64
|
:sasl_password => "",
|
57
|
-
:proxy_port => nil
|
65
|
+
:proxy_port => nil,
|
66
|
+
:flush_enabled => false,
|
67
|
+
:replica_index => true,
|
68
|
+
:parallel_db_and_view_compaction => false
|
58
69
|
}
|
59
70
|
options = defaults.merge(options)
|
60
71
|
params = {"name" => name}
|
@@ -64,6 +75,9 @@ module Couchbase
|
|
64
75
|
params["authType"] = options[:auth_type]
|
65
76
|
params["saslPassword"] = options[:sasl_password]
|
66
77
|
params["proxyPort"] = options[:proxy_port]
|
78
|
+
params["flushEnabled"] = !!options[:flush_enabled]
|
79
|
+
params["replicaIndex"] = !!options[:replica_index]
|
80
|
+
params["parallelDBAndViewCompaction"] = !!options[:parallel_db_and_view_compaction]
|
67
81
|
payload = Utils.encode_params(params.reject!{|k, v| v.nil?})
|
68
82
|
request = @connection.make_http_request("/pools/default/buckets",
|
69
83
|
:content_type => "application/x-www-form-urlencoded",
|
data/lib/couchbase/version.rb
CHANGED
data/tasks/compile.rake
CHANGED
@@ -30,6 +30,36 @@ version_router = lambda do |t|
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
class Platform
|
34
|
+
attr_reader :name, :host, :versions
|
35
|
+
|
36
|
+
def initialize(params)
|
37
|
+
@name = params[:name]
|
38
|
+
@host = params[:host]
|
39
|
+
@versions = params[:versions]
|
40
|
+
end
|
41
|
+
|
42
|
+
def each_version
|
43
|
+
@versions.each do |v|
|
44
|
+
yield(v, v[/\d\.\d\.\d/])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def short_versions
|
49
|
+
res = []
|
50
|
+
each_version do |long, short|
|
51
|
+
res << short
|
52
|
+
end
|
53
|
+
res
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
recent = "2.0.0-p353"
|
58
|
+
CROSS_PLATFORMS = [
|
59
|
+
Platform.new(:name => 'x64-mingw32', :host => 'x86_64-w64-mingw32', :versions => %w(1.9.3-p484 2.0.0-p353 2.1.0)),
|
60
|
+
Platform.new(:name => 'x86-mingw32', :host => 'i686-w64-mingw32', :versions => %w(1.8.7-p374 1.9.3-p484 2.0.0-p353 2.1.0)),
|
61
|
+
]
|
62
|
+
|
33
63
|
# Setup compile tasks. Configuration can be passed via ENV.
|
34
64
|
# Example:
|
35
65
|
# rake compile with_libcouchbase_include=/opt/couchbase/include
|
@@ -41,13 +71,14 @@ end
|
|
41
71
|
#
|
42
72
|
Rake::ExtensionTask.new("couchbase_ext", gemspec) do |ext|
|
43
73
|
ext.cross_compile = true
|
44
|
-
ext.cross_platform = ENV['
|
74
|
+
ext.cross_platform = ENV['TARGET']
|
45
75
|
if ENV['RUBY_CC_VERSION']
|
46
76
|
ext.lib_dir = "lib/couchbase"
|
47
77
|
end
|
48
78
|
ext.cross_compiling do |spec|
|
49
79
|
spec.files.delete("lib/couchbase/couchbase_ext.so")
|
50
|
-
spec.files.push("lib/couchbase_ext.rb", Dir["lib/couchbase
|
80
|
+
spec.files.push("lib/couchbase_ext.rb", Dir["lib/couchbase/*/couchbase_ext.so"])
|
81
|
+
spec.files.push(Dir["lib/couchbase/*/couchbase_ext.so"])
|
51
82
|
file "#{ext.tmp_dir}/#{ext.cross_platform}/stage/lib/couchbase_ext.rb", &version_router
|
52
83
|
end
|
53
84
|
|
@@ -66,19 +97,13 @@ end
|
|
66
97
|
|
67
98
|
require 'rubygems/package_task'
|
68
99
|
Gem::PackageTask.new(gemspec) do |pkg|
|
69
|
-
pkg.need_tar =
|
100
|
+
pkg.need_tar = pkg.need_zip = false
|
70
101
|
end
|
71
102
|
|
72
103
|
require 'mini_portile'
|
73
104
|
require 'rake/extensioncompiler'
|
74
105
|
|
75
106
|
class MiniPortile
|
76
|
-
alias :initialize_with_default_host :initialize
|
77
|
-
def initialize(name, version)
|
78
|
-
initialize_with_default_host(name, version)
|
79
|
-
@host = ENV['HOST'] || Rake::ExtensionCompiler.mingw_host
|
80
|
-
end
|
81
|
-
|
82
107
|
alias :cook_without_checkpoint :cook
|
83
108
|
def cook
|
84
109
|
checkpoint = "ports/.#{name}-#{version}-#{host}.installed"
|
@@ -89,13 +114,30 @@ class MiniPortile
|
|
89
114
|
end
|
90
115
|
end
|
91
116
|
|
92
|
-
|
93
|
-
directory "ports"
|
117
|
+
file "lib/couchbase_ext.rb", &version_router
|
94
118
|
|
95
|
-
|
96
|
-
|
119
|
+
desc "Package gem for windows"
|
120
|
+
task "package:windows" => ["package", "lib/couchbase_ext.rb"] do
|
121
|
+
vars = [
|
122
|
+
'CC',
|
123
|
+
'CFLAGS',
|
124
|
+
'CPATH',
|
125
|
+
'CPP',
|
126
|
+
'CPPFLAGS',
|
127
|
+
'LDFLAGS',
|
128
|
+
'LIBRARY_PATH',
|
129
|
+
'PATH'
|
130
|
+
].reduce({}) do |h, v|
|
131
|
+
h[v] = ENV[v]
|
132
|
+
h
|
133
|
+
end
|
134
|
+
CROSS_PLATFORMS.each do |platform|
|
135
|
+
ENV['TARGET'] = platform.name
|
136
|
+
rm_rf("tmp/ ports/")
|
137
|
+
mkdir_p("ports")
|
138
|
+
recipe = MiniPortile.new("libcouchbase", "2.2.0_30_gc87bec4")
|
139
|
+
recipe.host = platform.host
|
97
140
|
recipe.files << "http://packages.couchbase.com/clients/c/libcouchbase-#{recipe.version}.tar.gz"
|
98
|
-
|
99
141
|
recipe.configure_options.push("--disable-debug",
|
100
142
|
"--disable-dependency-tracking",
|
101
143
|
"--disable-couchbasemock",
|
@@ -105,16 +147,12 @@ namespace :ports do
|
|
105
147
|
"--disable-tools")
|
106
148
|
recipe.cook
|
107
149
|
recipe.activate
|
150
|
+
platform.each_version do |long, short|
|
151
|
+
sh("env RUBY_CC_VERSION=#{short} RBENV_VERSION=#{long} rbenv exec rake cross compile")
|
152
|
+
end
|
153
|
+
vars.each do |k, v|
|
154
|
+
ENV[k] = v
|
155
|
+
end
|
156
|
+
sh("env RUBY_CC_VERSION=#{platform.short_versions.join(":")} RBENV_VERSION=#{recent} rbenv exec rake cross native gem")
|
108
157
|
end
|
109
158
|
end
|
110
|
-
|
111
|
-
file "lib/couchbase_ext.rb", &version_router
|
112
|
-
task :cross => ["lib/couchbase_ext.rb", "ports:libcouchbase"]
|
113
|
-
|
114
|
-
desc "Package gem for windows"
|
115
|
-
task "package:windows" => :package do
|
116
|
-
sh("env RUBY_CC_VERSION=1.8.7 RBENV_VERSION=1.8.7-p370 rbenv exec bundle exec rake cross compile")
|
117
|
-
sh("env RUBY_CC_VERSION=1.9.2 RBENV_VERSION=1.9.2-p320 rbenv exec bundle exec rake cross compile")
|
118
|
-
sh("env RUBY_CC_VERSION=2.0.0 RBENV_VERSION=2.0.0-p247 rbenv exec bundle exec rake cross compile")
|
119
|
-
sh("env RUBY_CC_VERSION=1.8.7:1.9.2:2.0.0 RBENV_VERSION=1.9.2-p320 rbenv exec bundle exec rake cross native gem")
|
120
|
-
end
|
data/test/test_arithmetic.rb
CHANGED
@@ -173,4 +173,13 @@ class TestArithmetic < MiniTest::Test
|
|
173
173
|
assert_equal [2, 2], connection.decr(uniq_id(:foo), uniq_id(:bar), :delta => 10).values.sort
|
174
174
|
assert_equal [1, 1], connection.decr(uniq_id(:foo), uniq_id(:bar)).values.sort
|
175
175
|
end
|
176
|
+
|
177
|
+
def test_it_returns_cas_value_in_extended_mode
|
178
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
179
|
+
orig_cas = connection.set(uniq_id(:foo), 1)
|
180
|
+
val, cas = connection.incr(uniq_id(:foo), :extended => true)
|
181
|
+
assert_equal 2, val
|
182
|
+
assert cas.is_a?(Numeric), "CAS should be numeric value: #{cas.inspect}"
|
183
|
+
refute_equal orig_cas, cas
|
184
|
+
end
|
176
185
|
end
|
data/test/test_cas.rb
CHANGED
@@ -40,6 +40,69 @@ class TestCas < MiniTest::Test
|
|
40
40
|
assert_equal expected, val
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_compare_and_swap_collision
|
44
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
45
|
+
:default_format => :document)
|
46
|
+
connection.set(uniq_id, {"bar" => 1})
|
47
|
+
assert_raises(Couchbase::Error::KeyExists) do
|
48
|
+
connection.cas(uniq_id) do |val|
|
49
|
+
# Simulate collision with a separate writer. This will
|
50
|
+
# change the CAS value to be different than what #cas just loaded.
|
51
|
+
connection.set(uniq_id, {"bar" => 2})
|
52
|
+
|
53
|
+
# Complete the modification we desire, which should fail when set.
|
54
|
+
val["baz"] = 3
|
55
|
+
val
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_compare_and_swap_retry
|
61
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
62
|
+
:default_format => :document)
|
63
|
+
connection.set(uniq_id, {"bar" => 1})
|
64
|
+
calls = 0
|
65
|
+
connection.cas(uniq_id, :retry => 1) do |val|
|
66
|
+
calls += 1
|
67
|
+
if calls == 1
|
68
|
+
# Simulate collision with a separate writer. This will
|
69
|
+
# change the CAS value to be different than what #cas just loaded.
|
70
|
+
# Only do this the first time this block is executed.
|
71
|
+
connection.set(uniq_id, {"bar" => 2})
|
72
|
+
end
|
73
|
+
|
74
|
+
# Complete the modification we desire, which should fail when set.
|
75
|
+
val["baz"] = 3
|
76
|
+
val
|
77
|
+
end
|
78
|
+
assert_equal 2, calls
|
79
|
+
val = connection.get(uniq_id)
|
80
|
+
expected = {"bar" => 2, "baz" => 3}
|
81
|
+
assert_equal expected, val
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_compare_and_swap_too_many_retries
|
85
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
86
|
+
:default_format => :document)
|
87
|
+
connection.set(uniq_id, {"bar" => 0})
|
88
|
+
calls = 0
|
89
|
+
assert_raises(Couchbase::Error::KeyExists) do
|
90
|
+
connection.cas(uniq_id, :retry => 10) do |val|
|
91
|
+
calls += 1
|
92
|
+
|
93
|
+
# Simulate collision with a separate writer. This will
|
94
|
+
# change the CAS value to be different than what #cas just loaded.
|
95
|
+
# Do it every time so we just keep retrying and failing.
|
96
|
+
connection.set(uniq_id, {"bar" => calls})
|
97
|
+
|
98
|
+
# Complete the modification we desire, which should fail when set.
|
99
|
+
val["baz"] = 3
|
100
|
+
val
|
101
|
+
end
|
102
|
+
end
|
103
|
+
assert_equal 11, calls
|
104
|
+
end
|
105
|
+
|
43
106
|
def test_compare_and_swap_async
|
44
107
|
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
45
108
|
:default_format => :document)
|
@@ -66,6 +129,101 @@ class TestCas < MiniTest::Test
|
|
66
129
|
assert_equal expected, val
|
67
130
|
end
|
68
131
|
|
132
|
+
def test_compare_and_swap_async_collision
|
133
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
134
|
+
:default_format => :document)
|
135
|
+
connection.set(uniq_id, {"bar" => 1})
|
136
|
+
calls = 0
|
137
|
+
connection.run do |conn|
|
138
|
+
conn.cas(uniq_id) do |ret|
|
139
|
+
calls += 1
|
140
|
+
case ret.operation
|
141
|
+
when :get
|
142
|
+
new_val = ret.value
|
143
|
+
|
144
|
+
# Simulate collision with a separate writer. This will
|
145
|
+
# change the CAS value to be different than what #cas just loaded.
|
146
|
+
connection.set(uniq_id, {"bar" => 2})
|
147
|
+
|
148
|
+
|
149
|
+
# Complete the modification we desire, which should fail when set.
|
150
|
+
new_val["baz"] = 3
|
151
|
+
new_val
|
152
|
+
when :set
|
153
|
+
assert ret.error.is_a? Couchbase::Error::KeyExists
|
154
|
+
else
|
155
|
+
flunk "Unexpected operation: #{ret.operation.inspect}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
assert_equal 2, calls
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_compare_and_swap_async_retry
|
163
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
164
|
+
:default_format => :document)
|
165
|
+
connection.set(uniq_id, {"bar" => 1})
|
166
|
+
calls = 0
|
167
|
+
connection.run do |conn|
|
168
|
+
conn.cas(uniq_id, :retry => 1) do |ret|
|
169
|
+
calls += 1
|
170
|
+
case ret.operation
|
171
|
+
when :get
|
172
|
+
new_val = ret.value
|
173
|
+
|
174
|
+
if calls == 1
|
175
|
+
# Simulate collision with a separate writer. This will
|
176
|
+
# change the CAS value to be different than what #cas just loaded.
|
177
|
+
# Only do this the first time this block is executed.
|
178
|
+
connection.set(uniq_id, {"bar" => 2})
|
179
|
+
end
|
180
|
+
|
181
|
+
# Complete the modification we desire, which should fail when set.
|
182
|
+
new_val["baz"] = 3
|
183
|
+
new_val
|
184
|
+
when :set
|
185
|
+
assert ret.success?
|
186
|
+
else
|
187
|
+
flunk "Unexpected operation: #{ret.operation.inspect}"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
assert_equal 3, calls
|
192
|
+
val = connection.get(uniq_id)
|
193
|
+
expected = {"bar" => 2, "baz" => 3}
|
194
|
+
assert_equal expected, val
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_compare_and_swap_async_too_many_retries
|
198
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
199
|
+
:default_format => :document)
|
200
|
+
connection.set(uniq_id, {"bar" => 0})
|
201
|
+
calls = 0
|
202
|
+
connection.run do |conn|
|
203
|
+
conn.cas(uniq_id, :retry => 10) do |ret|
|
204
|
+
calls += 1
|
205
|
+
case ret.operation
|
206
|
+
when :get
|
207
|
+
new_val = ret.value
|
208
|
+
|
209
|
+
# Simulate collision with a separate writer. This will
|
210
|
+
# change the CAS value to be different than what #cas just loaded.
|
211
|
+
# Do it every time so we just keep retrying and failing.
|
212
|
+
connection.set(uniq_id, {"bar" => calls})
|
213
|
+
|
214
|
+
# Complete the modification we desire, which should fail when set.
|
215
|
+
new_val["baz"] = 3
|
216
|
+
new_val
|
217
|
+
when :set
|
218
|
+
assert ret.error.is_a? Couchbase::Error::KeyExists
|
219
|
+
else
|
220
|
+
flunk "Unexpected operation: #{ret.operation.inspect}"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
assert_equal 12, calls
|
225
|
+
end
|
226
|
+
|
69
227
|
def test_flags_replication
|
70
228
|
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
|
71
229
|
:default_format => :document)
|
@@ -43,6 +43,12 @@ class TestCouchbaseRailsCacheStore < MiniTest::Test
|
|
43
43
|
:connection_pool => 5)
|
44
44
|
end
|
45
45
|
|
46
|
+
def prefixed_store
|
47
|
+
@prefixed_store ||= ActiveSupport::Cache::CouchbaseStore.new(:hostname => @mock.host,
|
48
|
+
:port => @mock.port,
|
49
|
+
:namespace => 'v1')
|
50
|
+
end
|
51
|
+
|
46
52
|
def test_it_supported_methods
|
47
53
|
supported_methods = store.public_methods(false).map(&:to_sym)
|
48
54
|
assert supported_methods.include?(:fetch)
|
@@ -327,6 +333,20 @@ class TestCouchbaseRailsCacheStore < MiniTest::Test
|
|
327
333
|
workers.each { |w| w.join }
|
328
334
|
end
|
329
335
|
|
336
|
+
# These tests are only relevant against a real server,
|
337
|
+
# CouchbaseMock seems to accept long keys.
|
338
|
+
def test_it_can_handle_keys_longer_than_250_characters
|
339
|
+
long_key = 'a' * 260
|
340
|
+
assert store.write(long_key, 123)
|
341
|
+
assert_equal 123, store.read(long_key)
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_it_can_handle_keys_longer_than_250_characters_with_a_prefix
|
345
|
+
long_key = 'a' * 249
|
346
|
+
assert prefixed_store.write(long_key, 123)
|
347
|
+
assert_equal 123, prefixed_store.read(long_key)
|
348
|
+
end
|
349
|
+
|
330
350
|
private
|
331
351
|
|
332
352
|
def collect_notifications
|
data/test/test_format.rb
CHANGED
@@ -153,7 +153,12 @@ class TestFormat < MiniTest::Test
|
|
153
153
|
assert_equal(ZlibTranscoder::FMT_ZLIB|Couchbase::Bucket::FMT_DOCUMENT, flags)
|
154
154
|
connection.transcoder = nil
|
155
155
|
doc = connection.get(uniq_id)
|
156
|
-
|
156
|
+
case RUBY_VERSION
|
157
|
+
when /^1\.8/
|
158
|
+
assert_equal "x\x01\xABVJ\xCB\xCFW\xB2RJJ,R\xAA\x05\0\x1Dz\x044", doc
|
159
|
+
else
|
160
|
+
assert_equal "x\u0001\xABVJ\xCB\xCFW\xB2RJJ,R\xAA\u0005\u0000\u001Dz\u00044", doc
|
161
|
+
end
|
157
162
|
end
|
158
163
|
|
159
164
|
end
|
metadata
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couchbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.4
|
5
5
|
platform: x86-mingw32
|
6
6
|
authors:
|
7
7
|
- Couchbase
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yaji
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
- - '>='
|
18
21
|
- !ruby/object:Gem::Version
|
19
22
|
version: 0.3.2
|
20
23
|
type: :runtime
|
@@ -22,6 +25,9 @@ dependencies:
|
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.3'
|
30
|
+
- - '>='
|
25
31
|
- !ruby/object:Gem::Version
|
26
32
|
version: 0.3.2
|
27
33
|
- !ruby/object:Gem::Dependency
|
@@ -43,6 +49,9 @@ dependencies:
|
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.0'
|
54
|
+
- - '>='
|
46
55
|
- !ruby/object:Gem::Version
|
47
56
|
version: 1.0.0
|
48
57
|
type: :runtime
|
@@ -50,20 +59,23 @@ dependencies:
|
|
50
59
|
version_requirements: !ruby/object:Gem::Requirement
|
51
60
|
requirements:
|
52
61
|
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.0'
|
64
|
+
- - '>='
|
53
65
|
- !ruby/object:Gem::Version
|
54
66
|
version: 1.0.0
|
55
67
|
- !ruby/object:Gem::Dependency
|
56
68
|
name: rake
|
57
69
|
requirement: !ruby/object:Gem::Requirement
|
58
70
|
requirements:
|
59
|
-
- -
|
71
|
+
- - '>='
|
60
72
|
- !ruby/object:Gem::Version
|
61
73
|
version: '0'
|
62
74
|
type: :development
|
63
75
|
prerelease: false
|
64
76
|
version_requirements: !ruby/object:Gem::Requirement
|
65
77
|
requirements:
|
66
|
-
- -
|
78
|
+
- - '>='
|
67
79
|
- !ruby/object:Gem::Version
|
68
80
|
version: '0'
|
69
81
|
- !ruby/object:Gem::Dependency
|
@@ -71,6 +83,9 @@ dependencies:
|
|
71
83
|
requirement: !ruby/object:Gem::Requirement
|
72
84
|
requirements:
|
73
85
|
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '5.0'
|
88
|
+
- - '>='
|
74
89
|
- !ruby/object:Gem::Version
|
75
90
|
version: 5.0.4
|
76
91
|
type: :development
|
@@ -78,41 +93,59 @@ dependencies:
|
|
78
93
|
version_requirements: !ruby/object:Gem::Requirement
|
79
94
|
requirements:
|
80
95
|
- - ~>
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '5.0'
|
98
|
+
- - '>='
|
81
99
|
- !ruby/object:Gem::Version
|
82
100
|
version: 5.0.4
|
83
101
|
- !ruby/object:Gem::Dependency
|
84
102
|
name: rake-compiler
|
85
103
|
requirement: !ruby/object:Gem::Requirement
|
86
104
|
requirements:
|
87
|
-
- -
|
105
|
+
- - ~>
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0.7'
|
108
|
+
- - '>='
|
88
109
|
- !ruby/object:Gem::Version
|
89
110
|
version: 0.7.5
|
90
111
|
type: :development
|
91
112
|
prerelease: false
|
92
113
|
version_requirements: !ruby/object:Gem::Requirement
|
93
114
|
requirements:
|
94
|
-
- -
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.7'
|
118
|
+
- - '>='
|
95
119
|
- !ruby/object:Gem::Version
|
96
120
|
version: 0.7.5
|
97
121
|
- !ruby/object:Gem::Dependency
|
98
122
|
name: mini_portile
|
99
123
|
requirement: !ruby/object:Gem::Requirement
|
100
124
|
requirements:
|
101
|
-
- -
|
125
|
+
- - ~>
|
102
126
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
127
|
+
version: '0.5'
|
128
|
+
- - '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 0.5.2
|
104
131
|
type: :development
|
105
132
|
prerelease: false
|
106
133
|
version_requirements: !ruby/object:Gem::Requirement
|
107
134
|
requirements:
|
108
|
-
- -
|
135
|
+
- - ~>
|
109
136
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
137
|
+
version: '0.5'
|
138
|
+
- - '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: 0.5.2
|
111
141
|
- !ruby/object:Gem::Dependency
|
112
142
|
name: yajl-ruby
|
113
143
|
requirement: !ruby/object:Gem::Requirement
|
114
144
|
requirements:
|
115
145
|
- - ~>
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '1.1'
|
148
|
+
- - '>='
|
116
149
|
- !ruby/object:Gem::Version
|
117
150
|
version: 1.1.0
|
118
151
|
type: :development
|
@@ -120,34 +153,37 @@ dependencies:
|
|
120
153
|
version_requirements: !ruby/object:Gem::Requirement
|
121
154
|
requirements:
|
122
155
|
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '1.1'
|
158
|
+
- - '>='
|
123
159
|
- !ruby/object:Gem::Version
|
124
160
|
version: 1.1.0
|
125
161
|
- !ruby/object:Gem::Dependency
|
126
162
|
name: active_support
|
127
163
|
requirement: !ruby/object:Gem::Requirement
|
128
164
|
requirements:
|
129
|
-
- -
|
165
|
+
- - '>='
|
130
166
|
- !ruby/object:Gem::Version
|
131
167
|
version: '0'
|
132
168
|
type: :development
|
133
169
|
prerelease: false
|
134
170
|
version_requirements: !ruby/object:Gem::Requirement
|
135
171
|
requirements:
|
136
|
-
- -
|
172
|
+
- - '>='
|
137
173
|
- !ruby/object:Gem::Version
|
138
174
|
version: '0'
|
139
175
|
- !ruby/object:Gem::Dependency
|
140
176
|
name: eventmachine
|
141
177
|
requirement: !ruby/object:Gem::Requirement
|
142
178
|
requirements:
|
143
|
-
- -
|
179
|
+
- - '>='
|
144
180
|
- !ruby/object:Gem::Version
|
145
181
|
version: '0'
|
146
182
|
type: :development
|
147
183
|
prerelease: false
|
148
184
|
version_requirements: !ruby/object:Gem::Requirement
|
149
185
|
requirements:
|
150
|
-
- -
|
186
|
+
- - '>='
|
151
187
|
- !ruby/object:Gem::Version
|
152
188
|
version: '0'
|
153
189
|
description: The official client library for use with Couchbase Server.
|
@@ -249,6 +285,7 @@ files:
|
|
249
285
|
- lib/couchbase/1.8/couchbase_ext.so
|
250
286
|
- lib/couchbase/1.9/couchbase_ext.so
|
251
287
|
- lib/couchbase/2.0/couchbase_ext.so
|
288
|
+
- lib/couchbase/2.1/couchbase_ext.so
|
252
289
|
- lib/couchbase_ext.rb
|
253
290
|
homepage: http://couchbase.org
|
254
291
|
licenses:
|
@@ -260,18 +297,41 @@ require_paths:
|
|
260
297
|
- lib
|
261
298
|
required_ruby_version: !ruby/object:Gem::Requirement
|
262
299
|
requirements:
|
263
|
-
- -
|
300
|
+
- - '>='
|
264
301
|
- !ruby/object:Gem::Version
|
265
302
|
version: '0'
|
266
303
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
304
|
requirements:
|
268
|
-
- -
|
305
|
+
- - '>='
|
269
306
|
- !ruby/object:Gem::Version
|
270
307
|
version: '0'
|
271
308
|
requirements: []
|
272
309
|
rubyforge_project:
|
273
|
-
rubygems_version: 2.0.
|
310
|
+
rubygems_version: 2.0.14
|
274
311
|
signing_key:
|
275
312
|
specification_version: 4
|
276
313
|
summary: Couchbase ruby driver
|
277
|
-
test_files:
|
314
|
+
test_files:
|
315
|
+
- test/profile/.gitignore
|
316
|
+
- test/profile/Gemfile
|
317
|
+
- test/profile/benchmark.rb
|
318
|
+
- test/setup.rb
|
319
|
+
- test/test_arithmetic.rb
|
320
|
+
- test/test_async.rb
|
321
|
+
- test/test_bucket.rb
|
322
|
+
- test/test_cas.rb
|
323
|
+
- test/test_couchbase.rb
|
324
|
+
- test/test_couchbase_connection_pool.rb
|
325
|
+
- test/test_couchbase_rails_cache_store.rb
|
326
|
+
- test/test_delete.rb
|
327
|
+
- test/test_errors.rb
|
328
|
+
- test/test_eventmachine.rb
|
329
|
+
- test/test_format.rb
|
330
|
+
- test/test_get.rb
|
331
|
+
- test/test_stats.rb
|
332
|
+
- test/test_store.rb
|
333
|
+
- test/test_timer.rb
|
334
|
+
- test/test_touch.rb
|
335
|
+
- test/test_unlock.rb
|
336
|
+
- test/test_utils.rb
|
337
|
+
- test/test_version.rb
|