couchbase-jruby-client 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.jrubyrc +722 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +203 -0
- data/README.md +349 -0
- data/Rakefile +10 -0
- data/couchbase-jruby-client.gemspec +31 -0
- data/lib/couchbase/async/callback.rb +19 -0
- data/lib/couchbase/async/queue.rb +26 -0
- data/lib/couchbase/async.rb +140 -0
- data/lib/couchbase/bucket.rb +556 -0
- data/lib/couchbase/cluster.rb +105 -0
- data/lib/couchbase/constants.rb +12 -0
- data/lib/couchbase/design_doc.rb +61 -0
- data/lib/couchbase/error.rb +43 -0
- data/lib/couchbase/jruby/couchbase_client.rb +22 -0
- data/lib/couchbase/jruby/future.rb +8 -0
- data/lib/couchbase/operations/arithmetic.rb +301 -0
- data/lib/couchbase/operations/delete.rb +104 -0
- data/lib/couchbase/operations/design_docs.rb +99 -0
- data/lib/couchbase/operations/get.rb +282 -0
- data/lib/couchbase/operations/stats.rb +26 -0
- data/lib/couchbase/operations/store.rb +461 -0
- data/lib/couchbase/operations/touch.rb +136 -0
- data/lib/couchbase/operations/unlock.rb +192 -0
- data/lib/couchbase/operations/utils.rb +44 -0
- data/lib/couchbase/operations.rb +27 -0
- data/lib/couchbase/query.rb +73 -0
- data/lib/couchbase/result.rb +43 -0
- data/lib/couchbase/transcoder.rb +77 -0
- data/lib/couchbase/utils.rb +62 -0
- data/lib/couchbase/version.rb +3 -0
- data/lib/couchbase/view.rb +367 -0
- data/lib/couchbase/view_row.rb +193 -0
- data/lib/couchbase.rb +157 -0
- data/lib/jars/commons-codec-1.5.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0-javadoc.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0-sources.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0.jar +0 -0
- data/lib/jars/httpcore-4.1.1.jar +0 -0
- data/lib/jars/httpcore-nio-4.1.1.jar +0 -0
- data/lib/jars/jettison-1.1.jar +0 -0
- data/lib/jars/netty-3.5.5.Final.jar +0 -0
- data/lib/jars/spymemcached-2.10.0-javadoc.jar +0 -0
- data/lib/jars/spymemcached-2.10.0-sources.jar +0 -0
- data/lib/jars/spymemcached-2.10.0.jar +0 -0
- data/test/profile/.gitignore +1 -0
- data/test/profile/.jrubyrc +722 -0
- data/test/profile/Gemfile +6 -0
- data/test/profile/benchmark.rb +168 -0
- data/test/profile/profile.rb +59 -0
- data/test/setup.rb +203 -0
- data/test/test_arithmetic.rb +177 -0
- data/test/test_async.rb +324 -0
- data/test/test_bucket.rb +213 -0
- data/test/test_cas.rb +79 -0
- data/test/test_couchbase.rb +29 -0
- data/test/test_couchbase_rails_cache_store.rb +341 -0
- data/test/test_delete.rb +125 -0
- data/test/test_design_docs.rb +72 -0
- data/test/test_errors.rb +82 -0
- data/test/test_format.rb +161 -0
- data/test/test_get.rb +417 -0
- data/test/test_query.rb +23 -0
- data/test/test_stats.rb +57 -0
- data/test/test_store.rb +213 -0
- data/test/test_timer.rb +43 -0
- data/test/test_touch.rb +97 -0
- data/test/test_unlock.rb +121 -0
- data/test/test_utils.rb +58 -0
- data/test/test_version.rb +53 -0
- data/test/test_view.rb +94 -0
- metadata +255 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2011, 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module Couchbase
|
19
|
+
|
20
|
+
class Cluster
|
21
|
+
|
22
|
+
# Establish connection to the cluster for administration
|
23
|
+
#
|
24
|
+
# @param [Hash] options The connection parameter
|
25
|
+
# @option options [String] :username The username
|
26
|
+
# @option options [String] :password The password
|
27
|
+
# @option options [String] :pool ("default") The pool name
|
28
|
+
# @option options [String] :hostname ("localhost") The hostname
|
29
|
+
# @option options [String] :port (8091) The port
|
30
|
+
def initialize(options = {})
|
31
|
+
if options[:username].nil? || options[:password].nil?
|
32
|
+
raise ArgumentError, "username and password mandatory to connect to the cluster"
|
33
|
+
end
|
34
|
+
@connection = Bucket.new(options.merge(:type => :cluster))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create data bucket
|
38
|
+
#
|
39
|
+
# @param [String] name The name of the bucket
|
40
|
+
# @param [Hash] options The bucket parameters
|
41
|
+
# @option options [String] :bucket_type ("couchbase") The type of the
|
42
|
+
# bucket. Possible values are "memcached" and "couchbase".
|
43
|
+
# @option options [Fixnum] :ram_quota (100) The RAM quota in megabytes.
|
44
|
+
# @option options [Fixnum] :replica_number (1) The number of replicas of
|
45
|
+
# each document
|
46
|
+
# @option options [String] :auth_type ("sasl") The authentication type.
|
47
|
+
# Possible values are "sasl" and "none". Note you should specify free
|
48
|
+
# port for "none"
|
49
|
+
# @option options [Fixnum] :proxy_port The port for moxi
|
50
|
+
def create_bucket(name, options = {})
|
51
|
+
defaults = {
|
52
|
+
:type => "couchbase",
|
53
|
+
:ram_quota => 100,
|
54
|
+
:replica_number => 1,
|
55
|
+
:auth_type => "sasl",
|
56
|
+
:sasl_password => "",
|
57
|
+
:proxy_port => nil
|
58
|
+
}
|
59
|
+
options = defaults.merge(options)
|
60
|
+
params = {"name" => name}
|
61
|
+
params["bucketType"] = options[:type]
|
62
|
+
params["ramQuotaMB"] = options[:ram_quota]
|
63
|
+
params["replicaNumber"] = options[:replica_number]
|
64
|
+
params["authType"] = options[:auth_type]
|
65
|
+
params["saslPassword"] = options[:sasl_password]
|
66
|
+
params["proxyPort"] = options[:proxy_port]
|
67
|
+
payload = Utils.encode_params(params.reject!{|k, v| v.nil?})
|
68
|
+
request = @connection.make_http_request("/pools/default/buckets",
|
69
|
+
:content_type => "application/x-www-form-urlencoded",
|
70
|
+
:type => :management,
|
71
|
+
:method => :post,
|
72
|
+
:extended => true,
|
73
|
+
:body => payload)
|
74
|
+
response = nil
|
75
|
+
request.on_body do |r|
|
76
|
+
response = r
|
77
|
+
response.instance_variable_set("@operation", :create_bucket)
|
78
|
+
yield(response) if block_given?
|
79
|
+
end
|
80
|
+
request.continue
|
81
|
+
response
|
82
|
+
end
|
83
|
+
|
84
|
+
# Delete the data bucket
|
85
|
+
#
|
86
|
+
# @param [String] name The name of the bucket
|
87
|
+
# @param [Hash] options
|
88
|
+
def delete_bucket(name, options = {})
|
89
|
+
request = @connection.make_http_request("/pools/default/buckets/#{name}",
|
90
|
+
:type => :management,
|
91
|
+
:method => :delete,
|
92
|
+
:extended => true)
|
93
|
+
response = nil
|
94
|
+
request.on_body do |r|
|
95
|
+
response = r
|
96
|
+
response.instance_variable_set("@operation", :delete_bucket)
|
97
|
+
yield(response) if block_given?
|
98
|
+
end
|
99
|
+
request.continue
|
100
|
+
response
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Couchbase
|
2
|
+
module Constants # :nodoc:
|
3
|
+
S_ID = 'id'.freeze
|
4
|
+
S_DOC = 'doc'.freeze
|
5
|
+
S_VALUE = 'value'.freeze
|
6
|
+
S_META = 'meta'.freeze
|
7
|
+
S_FLAGS = 'flags'.freeze
|
8
|
+
S_CAS = 'cas'.freeze
|
9
|
+
S_KEY = 'key'.freeze
|
10
|
+
S_IS_LAST = Object.new.freeze
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Couchbase
|
2
|
+
class DesignDoc
|
3
|
+
|
4
|
+
def initialize(bucket, doc)
|
5
|
+
@all_views = {}
|
6
|
+
@bucket = bucket
|
7
|
+
@name = doc.name
|
8
|
+
@views = doc.views
|
9
|
+
@spatial = doc.spatial_views
|
10
|
+
@views.each { |view| @all_views[view.name] = "#{@name}/_view/#{view.name}" }
|
11
|
+
@spatial.each { |view| @all_views[view.name] = "#{@name}/_spatial/#{view.name}" }
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(meth, *args)
|
15
|
+
if path = @all_views[meth.to_s]
|
16
|
+
View.new(@bucket, path, *args)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to_missing?(meth, *args)
|
23
|
+
@all_views[meth.to_s] || super
|
24
|
+
end
|
25
|
+
|
26
|
+
# The list of views defined or empty array
|
27
|
+
#
|
28
|
+
# @since 1.2.1
|
29
|
+
#
|
30
|
+
# @return [Array<View>]
|
31
|
+
attr_accessor :views
|
32
|
+
|
33
|
+
# The list of spatial views defined or empty array
|
34
|
+
#
|
35
|
+
# @since 1.2.1
|
36
|
+
#
|
37
|
+
# @return [Array<View>]
|
38
|
+
attr_accessor :spatial
|
39
|
+
|
40
|
+
# Check if the document has views defines
|
41
|
+
#
|
42
|
+
# @since 1.2.1
|
43
|
+
#
|
44
|
+
# @see DesignDoc#views
|
45
|
+
#
|
46
|
+
# @return [true, false] +true+ if the document have views
|
47
|
+
def has_views?
|
48
|
+
!@views.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
desc = "#<#{self.class.name}:#{self.object_id}"
|
53
|
+
[:@id, :@views, :@spatial].each do |iv|
|
54
|
+
desc << " #{iv}=#{instance_variable_get(iv).inspect}"
|
55
|
+
end
|
56
|
+
desc << ">"
|
57
|
+
desc
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
module Couchbase
|
3
|
+
module Error
|
4
|
+
class Base < Exception
|
5
|
+
attr_accessor :cas, :error, :inner_exception, :key, :operation, :status
|
6
|
+
|
7
|
+
def to_s
|
8
|
+
if inner_exception
|
9
|
+
inner_exception.to_s
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Connect < Base
|
17
|
+
end
|
18
|
+
|
19
|
+
class Auth < Base
|
20
|
+
end
|
21
|
+
|
22
|
+
class Connect < Base
|
23
|
+
end
|
24
|
+
|
25
|
+
class NotFound < Base
|
26
|
+
end
|
27
|
+
|
28
|
+
class Invalid < Base
|
29
|
+
end
|
30
|
+
|
31
|
+
class KeyExists < Base
|
32
|
+
end
|
33
|
+
|
34
|
+
class ValueFormat < Base
|
35
|
+
end
|
36
|
+
|
37
|
+
class TemporaryFail < Base
|
38
|
+
end
|
39
|
+
|
40
|
+
class NotStored < Base
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Couchbase
|
2
|
+
module Jruby
|
3
|
+
class CouchbaseClient < Java::ComCouchbaseClient::CouchbaseClient
|
4
|
+
|
5
|
+
# Futures
|
6
|
+
%w(add set append asyncCAS asyncDecr asyncGet asyncGetAndTouch asyncGetBulk
|
7
|
+
asyncGets asyncIncr delete flush prepend replace set touch).each do |op|
|
8
|
+
define_method(op) do |*|
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(*)
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
VALUE_OPS = %w(
|
18
|
+
|
19
|
+
).freeze
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,301 @@
|
|
1
|
+
module Couchbase::Operations
|
2
|
+
module Arithmetic
|
3
|
+
|
4
|
+
# Increment the value of an existing numeric key
|
5
|
+
#
|
6
|
+
# @since 1.0.0
|
7
|
+
#
|
8
|
+
# The increment methods allow you to increase a given stored integer
|
9
|
+
# value. These are the incremental equivalent of the decrement operations
|
10
|
+
# and work on the same basis; updating the value of a key if it can be
|
11
|
+
# parsed to an integer. The update operation occurs on the server and is
|
12
|
+
# provided at the protocol level. This simplifies what would otherwise be a
|
13
|
+
# two-stage get and set operation.
|
14
|
+
#
|
15
|
+
# @note that server values stored and transmitted as unsigned numbers,
|
16
|
+
# therefore if you try to store negative number and then increment or
|
17
|
+
# decrement it will cause overflow. (see "Integer overflow" example
|
18
|
+
# below)
|
19
|
+
#
|
20
|
+
# @overload incr(key, delta = 1, options = {})
|
21
|
+
# @param key [String, Symbol] Key used to reference the value.
|
22
|
+
# @param delta [Fixnum] Integer (up to 64 bits) value to increment
|
23
|
+
# @param options [Hash] Options for operation.
|
24
|
+
# @option options [true, false] :create (false) If set to +true+, it will
|
25
|
+
# initialize the key with zero value and zero flags (use +:initial+
|
26
|
+
# option to set another initial value). Note: it won't increment the
|
27
|
+
# missing value.
|
28
|
+
# @option options [Fixnum] :initial (0) Integer (up to 64 bits) value for
|
29
|
+
# missing key initialization. This option imply +:create+ option is
|
30
|
+
# +true+.
|
31
|
+
# @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
|
32
|
+
# Values larger than 30*24*60*60 seconds (30 days) are interpreted as
|
33
|
+
# absolute times (from the epoch). This option ignored for existent
|
34
|
+
# keys.
|
35
|
+
# @option options [true, false] :extended (false) If set to +true+, the
|
36
|
+
# operation will return tuple +[value, cas]+, otherwise (by default) it
|
37
|
+
# returns just value.
|
38
|
+
#
|
39
|
+
# @yieldparam ret [Result] the result of operation in asynchronous mode
|
40
|
+
# (valid attributes: +error+, +operation+, +key+, +value+, +cas+).
|
41
|
+
#
|
42
|
+
# @return [Fixnum] the actual value of the key.
|
43
|
+
#
|
44
|
+
# @raise [Couchbase::Error::NotFound] if key is missing and +:create+
|
45
|
+
# option isn't +true+.
|
46
|
+
#
|
47
|
+
# @raise [Couchbase::Error::DeltaBadval] if the key contains non-numeric
|
48
|
+
# value
|
49
|
+
#
|
50
|
+
# @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
51
|
+
#
|
52
|
+
# @raise [ArgumentError] when passing the block in synchronous mode
|
53
|
+
#
|
54
|
+
# @example Increment key by one
|
55
|
+
# c.incr("foo")
|
56
|
+
#
|
57
|
+
# @example Increment key by 50
|
58
|
+
# c.incr("foo", 50)
|
59
|
+
#
|
60
|
+
# @example Increment key by one <b>OR</b> initialize with zero
|
61
|
+
# c.incr("foo", :create => true) #=> will return old+1 or 0
|
62
|
+
#
|
63
|
+
# @example Increment key by one <b>OR</b> initialize with three
|
64
|
+
# c.incr("foo", 50, :initial => 3) #=> will return old+50 or 3
|
65
|
+
#
|
66
|
+
# @example Increment key and get its CAS value
|
67
|
+
# val, cas = c.incr("foo", :extended => true)
|
68
|
+
#
|
69
|
+
# @example Integer overflow
|
70
|
+
# c.set("foo", -100)
|
71
|
+
# c.get("foo") #=> -100
|
72
|
+
# c.incr("foo") #=> 18446744073709551517
|
73
|
+
#
|
74
|
+
# @example Asynchronous invocation
|
75
|
+
# c.run do
|
76
|
+
# c.incr("foo") do |ret|
|
77
|
+
# ret.operation #=> :increment
|
78
|
+
# ret.success? #=> true
|
79
|
+
# ret.key #=> "foo"
|
80
|
+
# ret.value
|
81
|
+
# ret.cas
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
def incr(*args)
|
86
|
+
sync_block_error if !async? && block_given?
|
87
|
+
do_arithmetic(:incr, *args)
|
88
|
+
end
|
89
|
+
alias_method :increment, :incr
|
90
|
+
|
91
|
+
# Decrement the value of an existing numeric key
|
92
|
+
#
|
93
|
+
# @since 1.0.0
|
94
|
+
#
|
95
|
+
# The decrement methods reduce the value of a given key if the
|
96
|
+
# corresponding value can be parsed to an integer value. These operations
|
97
|
+
# are provided at a protocol level to eliminate the need to get, update,
|
98
|
+
# and reset a simple integer value in the database. It supports the use of
|
99
|
+
# an explicit offset value that will be used to reduce the stored value in
|
100
|
+
# the database.
|
101
|
+
#
|
102
|
+
# @note that server values stored and transmitted as unsigned numbers,
|
103
|
+
# therefore if you try to decrement negative or zero key, you will always
|
104
|
+
# get zero.
|
105
|
+
#
|
106
|
+
# @overload decr(key, delta = 1, options = {})
|
107
|
+
# @param key [String, Symbol] Key used to reference the value.
|
108
|
+
# @param delta [Fixnum] Integer (up to 64 bits) value to decrement
|
109
|
+
# @param options [Hash] Options for operation.
|
110
|
+
# @option options [true, false] :create (false) If set to +true+, it will
|
111
|
+
# initialize the key with zero value and zero flags (use +:initial+
|
112
|
+
# option to set another initial value). Note: it won't decrement the
|
113
|
+
# missing value.
|
114
|
+
# @option options [Fixnum] :initial (0) Integer (up to 64 bits) value for
|
115
|
+
# missing key initialization. This option imply +:create+ option is
|
116
|
+
# +true+.
|
117
|
+
# @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
|
118
|
+
# Values larger than 30*24*60*60 seconds (30 days) are interpreted as
|
119
|
+
# absolute times (from the epoch). This option ignored for existent
|
120
|
+
# keys.
|
121
|
+
# @option options [true, false] :extended (false) If set to +true+, the
|
122
|
+
# operation will return tuple +[value, cas]+, otherwise (by default) it
|
123
|
+
# returns just value.
|
124
|
+
#
|
125
|
+
# @yieldparam ret [Result] the result of operation in asynchronous mode
|
126
|
+
# (valid attributes: +error+, +operation+, +key+, +value+, +cas+).
|
127
|
+
#
|
128
|
+
# @return [Fixnum] the actual value of the key.
|
129
|
+
#
|
130
|
+
# @raise [Couchbase::Error::NotFound] if key is missing and +:create+
|
131
|
+
# option isn't +true+.
|
132
|
+
#
|
133
|
+
# @raise [Couchbase::Error::DeltaBadval] if the key contains non-numeric
|
134
|
+
# value
|
135
|
+
#
|
136
|
+
# @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
137
|
+
#
|
138
|
+
# @raise [ArgumentError] when passing the block in synchronous mode
|
139
|
+
#
|
140
|
+
# @example Decrement key by one
|
141
|
+
# c.decr("foo")
|
142
|
+
#
|
143
|
+
# @example Decrement key by 50
|
144
|
+
# c.decr("foo", 50)
|
145
|
+
#
|
146
|
+
# @example Decrement key by one <b>OR</b> initialize with zero
|
147
|
+
# c.decr("foo", :create => true) #=> will return old-1 or 0
|
148
|
+
#
|
149
|
+
# @example Decrement key by one <b>OR</b> initialize with three
|
150
|
+
# c.decr("foo", 50, :initial => 3) #=> will return old-50 or 3
|
151
|
+
#
|
152
|
+
# @example Decrement key and get its CAS value
|
153
|
+
# val, cas = c.decr("foo", :extended => true)
|
154
|
+
#
|
155
|
+
# @example Decrementing zero
|
156
|
+
# c.set("foo", 0)
|
157
|
+
# c.decrement("foo", 100500) #=> 0
|
158
|
+
#
|
159
|
+
# @example Decrementing negative value
|
160
|
+
# c.set("foo", -100)
|
161
|
+
# c.decrement("foo", 100500) #=> 0
|
162
|
+
#
|
163
|
+
# @example Asynchronous invocation
|
164
|
+
# c.run do
|
165
|
+
# c.decr("foo") do |ret|
|
166
|
+
# ret.operation #=> :decrement
|
167
|
+
# ret.success? #=> true
|
168
|
+
# ret.key #=> "foo"
|
169
|
+
# ret.value
|
170
|
+
# ret.cas
|
171
|
+
# end
|
172
|
+
# end
|
173
|
+
#
|
174
|
+
def decr(*args)
|
175
|
+
sync_block_error if !async? && block_given?
|
176
|
+
do_arithmetic(:decr, *args)
|
177
|
+
end
|
178
|
+
alias_method :decrement, :decr
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
def do_arithmetic(op, *args)
|
183
|
+
key, delta, options = expand_arithmetic_args(args)
|
184
|
+
|
185
|
+
case key
|
186
|
+
when String, Symbol
|
187
|
+
single_arithmetic(op, key, delta, options)
|
188
|
+
when Array, Hash
|
189
|
+
multi_arithmetic(op, key, delta)
|
190
|
+
else
|
191
|
+
raise # something
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def expand_arithmetic_args(args)
|
196
|
+
options = if args.size > 1 && args.last.respond_to?(:to_h)
|
197
|
+
args.pop
|
198
|
+
else
|
199
|
+
{}
|
200
|
+
end
|
201
|
+
|
202
|
+
delta = if args.size > 1 && args.last.respond_to?(:to_int)
|
203
|
+
args.pop
|
204
|
+
else
|
205
|
+
options[:delta] || 1
|
206
|
+
end
|
207
|
+
|
208
|
+
key = args.size == 1 ? args.first : args
|
209
|
+
|
210
|
+
[key, delta, options]
|
211
|
+
end
|
212
|
+
|
213
|
+
def single_arithmetic(op, key, delta, options = {})
|
214
|
+
if async?
|
215
|
+
java_async_arithmetic(op, key, delta)
|
216
|
+
else
|
217
|
+
result = java_arithmetic(op, key, delta)
|
218
|
+
set_default_arithmetic_or_raise(key, result, options)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def set_default_arithmetic_or_raise(key, result, options)
|
223
|
+
if result < 0
|
224
|
+
if options[:initial] || options[:create] || set_default_arithmetic_init?
|
225
|
+
value = if options[:initial]
|
226
|
+
options[:initial]
|
227
|
+
elsif options[:create]
|
228
|
+
0
|
229
|
+
else
|
230
|
+
default_arithmetic_init_int
|
231
|
+
end
|
232
|
+
|
233
|
+
set(key, value, options) && value
|
234
|
+
else
|
235
|
+
not_found_error(true)
|
236
|
+
end
|
237
|
+
else
|
238
|
+
result
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def set_default_arithmetic_init?
|
243
|
+
default_arithmetic_init == true ||
|
244
|
+
default_arithmetic_init.respond_to?(:to_int) &&
|
245
|
+
default_arithmetic_init > 0
|
246
|
+
end
|
247
|
+
|
248
|
+
def default_arithmetic_init_int
|
249
|
+
default_arithmetic_init == true ? 0 : default_arithmetic_init
|
250
|
+
end
|
251
|
+
|
252
|
+
def multi_arithmetic(op, keys, delta)
|
253
|
+
{}.tap do |results|
|
254
|
+
if keys.respond_to?(:each_pair)
|
255
|
+
keys.each_pair do |k, v|
|
256
|
+
results[k] = single_arithmetic(op, k, v)
|
257
|
+
end
|
258
|
+
else
|
259
|
+
keys.each do |k|
|
260
|
+
results[k] = single_arithmetic(op, k, delta)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def java_arithmetic(op, key, delta)
|
267
|
+
case op
|
268
|
+
when :incr
|
269
|
+
java_incr(key, delta)
|
270
|
+
when :decr
|
271
|
+
java_decr(key, delta)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def java_async_arithmetic(op, key, delta)
|
276
|
+
case op
|
277
|
+
when :incr
|
278
|
+
java_async_incr(key, delta)
|
279
|
+
when :decr
|
280
|
+
java_async_decr(key, delta)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def java_incr(key, delta)
|
285
|
+
client.incr(key, delta)
|
286
|
+
end
|
287
|
+
|
288
|
+
def java_async_incr(key, delta)
|
289
|
+
client.asyncIncr(key, delta)
|
290
|
+
end
|
291
|
+
|
292
|
+
def java_decr(key, delta)
|
293
|
+
client.decr(key, delta)
|
294
|
+
end
|
295
|
+
|
296
|
+
def java_async_decr(key, delta)
|
297
|
+
client.asyncDecr(key, delta)
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
301
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Couchbase::Operations
|
2
|
+
module Delete
|
3
|
+
|
4
|
+
# Delete the specified key
|
5
|
+
#
|
6
|
+
# @since 1.0.0
|
7
|
+
#
|
8
|
+
# @overload delete(key, options = {})
|
9
|
+
# @param key [String, Symbol] Key used to reference the value.
|
10
|
+
# @param options [Hash] Options for operation.
|
11
|
+
# @option options [true, false] :quiet (self.quiet) If set to +true+, the
|
12
|
+
# operation won't raise error for missing key, it will return +nil+.
|
13
|
+
# Otherwise it will raise error in synchronous mode. In asynchronous
|
14
|
+
# mode this option ignored.
|
15
|
+
# @option options [Fixnum] :cas The CAS value for an object. This value
|
16
|
+
# created on the server and is guaranteed to be unique for each value of
|
17
|
+
# a given key. This value is used to provide simple optimistic
|
18
|
+
# concurrency control when multiple clients or threads try to
|
19
|
+
# update/delete an item simultaneously.
|
20
|
+
#
|
21
|
+
# @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
22
|
+
# @raise [ArgumentError] when passing the block in synchronous mode
|
23
|
+
# @raise [Couchbase::Error::KeyExists] on CAS mismatch
|
24
|
+
# @raise [Couchbase::Error::NotFound] if key is missing in verbose mode
|
25
|
+
#
|
26
|
+
# @return [true, false, Hash<String, Boolean>] the result of the
|
27
|
+
# operation
|
28
|
+
#
|
29
|
+
# @example Delete the key in quiet mode (default)
|
30
|
+
# c.set("foo", "bar")
|
31
|
+
# c.delete("foo") #=> true
|
32
|
+
# c.delete("foo") #=> false
|
33
|
+
#
|
34
|
+
# @example Delete the key verbosely
|
35
|
+
# c.set("foo", "bar")
|
36
|
+
# c.delete("foo", :quiet => false) #=> true
|
37
|
+
# c.delete("foo", :quiet => true) #=> nil (default behaviour)
|
38
|
+
# c.delete("foo", :quiet => false) #=> will raise Couchbase::Error::NotFound
|
39
|
+
#
|
40
|
+
# @example Delete the key with version check
|
41
|
+
# ver = c.set("foo", "bar") #=> 5992859822302167040
|
42
|
+
# c.delete("foo", :cas => 123456) #=> will raise Couchbase::Error::KeyExists
|
43
|
+
# c.delete("foo", :cas => ver) #=> true
|
44
|
+
#
|
45
|
+
def delete(*args, &block)
|
46
|
+
sync_block_error if !async? && block_given?
|
47
|
+
key, options = expand_get_args(args)
|
48
|
+
key, cas = delete_args_parser(key)
|
49
|
+
|
50
|
+
if key.respond_to?(:to_ary)
|
51
|
+
delete_multi(key, options)
|
52
|
+
else
|
53
|
+
delete_single(key, cas, options, &block)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def delete_args_parser(args)
|
60
|
+
if args.respond_to?(:to_str)
|
61
|
+
[args, nil]
|
62
|
+
else
|
63
|
+
cas = if args.size > 1 &&
|
64
|
+
args.last.respond_to?(:to_int)
|
65
|
+
args.pop
|
66
|
+
else
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
key = args.size == 1 ? args.first : args
|
71
|
+
|
72
|
+
[key, cas]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete_single(key, cas, options, &block)
|
77
|
+
if async?
|
78
|
+
java_async_delete(key, &block)
|
79
|
+
else
|
80
|
+
cas = java_delete(key)
|
81
|
+
not_found_error(!cas, options)
|
82
|
+
cas
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete_multi(keys, options = {})
|
87
|
+
{}.tap do |results|
|
88
|
+
keys.each do |key|
|
89
|
+
results[key] = delete_single(key, nil, options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def java_delete(key)
|
95
|
+
future = client.delete(key)
|
96
|
+
future_cas(future)
|
97
|
+
end
|
98
|
+
|
99
|
+
def java_async_delete(key, &block)
|
100
|
+
future = client.delete(key)
|
101
|
+
register_future(future, { op: :delete }, &block)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|