couchbase 1.3.3-x86-mingw32 → 1.3.4-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.
- 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
|