couchbase-jruby-client 0.1.0-java → 0.1.5-java
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/.jrubyrc +722 -0
- data/.ruby-version +1 -1
- data/README.md +12 -90
- data/couchbase-jruby-client.gemspec +6 -6
- data/lib/couchbase/async.rb +18 -0
- data/lib/couchbase/bucket.rb +90 -180
- data/lib/couchbase/constants.rb +17 -0
- data/lib/couchbase/design_doc.rb +83 -0
- data/lib/couchbase/error.rb +31 -0
- data/lib/couchbase/operations/arithmetic.rb +17 -0
- data/lib/couchbase/operations/delete.rb +17 -0
- data/lib/couchbase/operations/design_docs.rb +99 -0
- data/lib/couchbase/operations/get.rb +73 -67
- data/lib/couchbase/operations/stats.rb +28 -1
- data/lib/couchbase/operations/store.rb +114 -97
- data/lib/couchbase/operations/touch.rb +49 -19
- data/lib/couchbase/operations/unlock.rb +209 -0
- data/lib/couchbase/operations/utils.rb +22 -10
- data/lib/couchbase/operations.rb +21 -0
- data/lib/couchbase/query.rb +92 -0
- data/lib/couchbase/result.rb +18 -1
- data/lib/couchbase/transcoder.rb +36 -42
- data/lib/couchbase/version.rb +18 -1
- data/lib/couchbase/view.rb +30 -172
- data/lib/couchbase/view_row.rb +38 -98
- data/lib/couchbase.rb +74 -72
- data/test/profile/.jrubyrc +722 -0
- data/test/profile/Gemfile +5 -5
- data/test/profile/benchmark.rb +106 -124
- data/test/profile/profile.rb +59 -0
- data/test/setup.rb +10 -145
- data/test/test_arithmetic.rb +54 -77
- data/test/test_async.rb +74 -102
- data/test/test_bucket.rb +74 -60
- data/test/test_cas.rb +10 -23
- data/test/test_couchbase.rb +11 -3
- data/test/test_delete.rb +41 -43
- data/test/test_design_docs.rb +62 -0
- data/test/test_errors.rb +9 -18
- data/test/test_format.rb +21 -31
- data/test/test_get.rb +107 -151
- data/test/test_query.rb +23 -0
- data/test/test_stats.rb +9 -24
- data/test/test_store.rb +52 -65
- data/test/test_timer.rb +4 -12
- data/test/test_touch.rb +26 -33
- data/test/test_unlock.rb +47 -78
- data/test/test_utils.rb +2 -11
- data/test/test_version.rb +5 -14
- data/test/test_view.rb +87 -0
- metadata +27 -14
- data/lib/couchbase/jruby/couchbase_client.rb +0 -22
- data/lib/couchbase/jruby/future.rb +0 -8
data/test/profile/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem
|
4
|
-
gem
|
5
|
-
gem
|
6
|
-
gem
|
3
|
+
gem 'benchmark-ips'
|
4
|
+
gem 'jrjackson', '~> 0.2.3'
|
5
|
+
gem 'multi_json', '~> 1.0'
|
6
|
+
gem 'atomic', '~> 1.1.14'
|
data/test/profile/benchmark.rb
CHANGED
@@ -24,15 +24,12 @@
|
|
24
24
|
# show exceptions
|
25
25
|
#
|
26
26
|
|
27
|
-
require
|
28
|
-
require
|
29
|
-
|
30
|
-
require 'benchmark'
|
27
|
+
require 'rubygems'
|
28
|
+
require 'bundler/setup'
|
31
29
|
|
32
30
|
$LOAD_PATH << File.join(File.dirname(__FILE__), "..", "..", "lib")
|
33
31
|
require 'couchbase'
|
34
|
-
require '
|
35
|
-
require 'dalli'
|
32
|
+
require 'benchmark/ips'
|
36
33
|
|
37
34
|
puts `uname -a`
|
38
35
|
puts File.readlines('/proc/cpuinfo').sort.uniq.grep(/model name|cpu cores/) rescue nil
|
@@ -40,21 +37,13 @@ puts RUBY_DESCRIPTION
|
|
40
37
|
|
41
38
|
class Bench
|
42
39
|
|
43
|
-
def initialize
|
44
|
-
@loops = (loops || 50000).to_i
|
45
|
-
@stack_depth = (stack_depth || 0).to_i
|
40
|
+
def initialize
|
46
41
|
|
47
42
|
puts "PID is #{Process.pid}"
|
48
|
-
puts "Loops is #{@loops}"
|
49
|
-
puts "Stack depth is #{@stack_depth}"
|
50
43
|
|
51
|
-
@
|
52
|
-
@small_value = ["testing"])
|
53
|
-
@m_large_value = Marshal.dump(
|
54
|
-
@large_value = [{"test" => "1", "test2" => "2", Object.new => "3", 4 => 4, "test5" => 2**65}] * 2048)
|
44
|
+
@value = { 'im' => [ 'testing', 'stuff' ] }
|
55
45
|
|
56
|
-
puts "
|
57
|
-
puts "Large value size is: #{@m_large_value.size} bytes"
|
46
|
+
puts "Raw value size is: #{@value.size} bytes"
|
58
47
|
|
59
48
|
@keys = [
|
60
49
|
@k1 = "Short",
|
@@ -64,132 +53,125 @@ class Bench
|
|
64
53
|
@k5 = "Medium2" * 8,
|
65
54
|
@k6 = "Long3" * 40]
|
66
55
|
|
67
|
-
|
56
|
+
@cb = Couchbase.new
|
57
|
+
@cl = @cb.client
|
68
58
|
|
69
|
-
|
70
|
-
|
59
|
+
# Ensure it is JITed
|
60
|
+
2_000.times do
|
61
|
+
@cb.set(@k1, 'a')
|
62
|
+
@cb.get(@k1)
|
71
63
|
end
|
72
64
|
end
|
73
65
|
|
74
|
-
def run
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
def reset_clients
|
81
|
-
host = ENV['HOST'] || '127.0.0.1'
|
82
|
-
@clients = {
|
83
|
-
"dalli" => lambda { Dalli::Client.new("#{host}:11211", :marshal => true, :threadsafe => false) },
|
84
|
-
"memcached" => lambda { Memcached::Rails.new("#{host}:11211", :no_block => false, :buffer_requests => false, :binary_protocol => true) },
|
85
|
-
"memcached:buffer" => lambda { Memcached::Rails.new("#{host}:11211", :no_block => true, :buffer_requests => true, :binary_protocol => true) },
|
86
|
-
"couchbase" => lambda { Couchbase.new("http://#{host}:8091/pools/default/buckets/default", :default_format => :marshal) }
|
87
|
-
}
|
88
|
-
end
|
89
|
-
|
90
|
-
def benchmark_clients(test_name, populate_keys = true)
|
91
|
-
return if ENV["TEST"] and !test_name.include?(ENV["TEST"])
|
92
|
-
|
93
|
-
@clients.keys.each do |client_name|
|
94
|
-
next if ENV["CLIENT"] and !client_name.include?(ENV["CLIENT"])
|
95
|
-
|
96
|
-
kid = fork do
|
97
|
-
client = @clients[client_name].call
|
98
|
-
begin
|
99
|
-
if populate_keys
|
100
|
-
client.set @k1, @m_value
|
101
|
-
client.set @k2, @m_value
|
102
|
-
client.set @k3, @m_value
|
103
|
-
else
|
104
|
-
client.delete @k1
|
105
|
-
client.delete @k2
|
106
|
-
client.delete @k3
|
107
|
-
end
|
108
|
-
|
109
|
-
GC.disable
|
110
|
-
@benchmark.report("#{test_name}: #{client_name}") { @loops.times { yield client } }
|
111
|
-
STDOUT.flush
|
112
|
-
rescue Exception => e
|
113
|
-
puts "#{test_name}: #{client_name} => #{e.inspect}" if ENV["DEBUG"]
|
114
|
-
end
|
115
|
-
exit
|
66
|
+
def run
|
67
|
+
Benchmark.ips do |x|
|
68
|
+
x.report('jruby set') do
|
69
|
+
@cb.set @k1, @value
|
70
|
+
@cb.set @k2, @value
|
71
|
+
@cb.set @k3, @value
|
116
72
|
end
|
117
|
-
Signal.trap("INT") { Process.kill("KILL", kid); exit }
|
118
|
-
Process.wait(kid)
|
119
|
-
end
|
120
|
-
puts
|
121
|
-
end
|
122
73
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
74
|
+
x.report('java set') do
|
75
|
+
@cl.set(@k1, MultiJson.dump(@value)).get
|
76
|
+
@cl.set(@k2, MultiJson.dump(@value)).get
|
77
|
+
@cl.set(@k3, MultiJson.dump(@value)).get
|
78
|
+
end
|
129
79
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
80
|
+
x.report('jruby get') do
|
81
|
+
@cb.get @k1
|
82
|
+
@cb.get @k2
|
83
|
+
@cb.get @k3
|
84
|
+
end
|
135
85
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
c.get @keys
|
86
|
+
x.report('java get') do
|
87
|
+
MultiJson.load @cl.get(@k1)
|
88
|
+
MultiJson.load @cl.get(@k2)
|
89
|
+
MultiJson.load @cl.get(@k3)
|
141
90
|
end
|
142
|
-
end
|
143
91
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
c.append @k3, @m_value
|
148
|
-
end
|
92
|
+
x.report('jruby get multi') do
|
93
|
+
@cb.get([@k1, @k2, @k3])
|
94
|
+
end
|
149
95
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
c.prepend @k3, @m_value
|
154
|
-
end
|
96
|
+
x.report('java get multi') do
|
97
|
+
@cl.getBulk([@k1, @k2, @k3])
|
98
|
+
end
|
155
99
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
100
|
+
x.report('jruby delete') do
|
101
|
+
@cb.set @k1, ''
|
102
|
+
@cb.set @k2, ''
|
103
|
+
@cb.set @k3, ''
|
104
|
+
@cb.delete(@k1)
|
105
|
+
@cb.delete(@k2)
|
106
|
+
@cb.delete(@k3)
|
107
|
+
end
|
161
108
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
109
|
+
x.report('java delete') do
|
110
|
+
@cl.set @k1, ''
|
111
|
+
@cl.set @k2, ''
|
112
|
+
@cl.set @k3, ''
|
113
|
+
@cl.delete @k1
|
114
|
+
@cl.delete @k2
|
115
|
+
@cl.delete @k3
|
116
|
+
end
|
167
117
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
118
|
+
x.report('jruby get missing') do
|
119
|
+
@cb.get(@k1, quiet: true)
|
120
|
+
@cb.get(@k2, quiet: true)
|
121
|
+
@cb.get(@k3, quiet: true)
|
122
|
+
end
|
173
123
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
124
|
+
x.report('java get missing') do
|
125
|
+
@cl.get @k1
|
126
|
+
@cl.get @k2
|
127
|
+
@cl.get @k3
|
128
|
+
end
|
179
129
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
130
|
+
# x.report('jruby async set') do
|
131
|
+
# @cb.run do
|
132
|
+
# 100.times do
|
133
|
+
# @cb.set @k1, @value
|
134
|
+
# @cb.set @k2, @value
|
135
|
+
# @cb.set @k3, @value
|
136
|
+
# end
|
137
|
+
# end
|
138
|
+
# end
|
139
|
+
|
140
|
+
# x.report('java async set') do
|
141
|
+
# futures = []
|
142
|
+
# 100.times do
|
143
|
+
# futures << @cb.client.set(@k1, MultiJson.dump(@value))
|
144
|
+
# futures << @cb.client.set(@k2, MultiJson.dump(@value))
|
145
|
+
# futures << @cb.client.set(@k3, MultiJson.dump(@value))
|
146
|
+
# end
|
147
|
+
# futures.each(&:get)
|
148
|
+
# end
|
149
|
+
|
150
|
+
# x.report('jruby async get') do
|
151
|
+
# @cb.run do
|
152
|
+
# 100.times do
|
153
|
+
# @cb.get @k1
|
154
|
+
# @cb.get @k2
|
155
|
+
# @cb.get @k3
|
156
|
+
# end
|
157
|
+
# end
|
158
|
+
# end
|
159
|
+
|
160
|
+
# x.report('java async get') do
|
161
|
+
# futures = []
|
162
|
+
# 100.times do
|
163
|
+
# futures << @cb.client.asyncGet(@k1)
|
164
|
+
# futures << @cb.client.asyncGet(@k2)
|
165
|
+
# futures << @cb.client.asyncGet(@k3)
|
166
|
+
# end
|
167
|
+
# futures.each(&:get)
|
168
|
+
# end
|
185
169
|
|
186
|
-
benchmark_clients("get_large") do |c|
|
187
|
-
c.get @k1
|
188
|
-
c.get @k2
|
189
|
-
c.get @k3
|
190
170
|
end
|
191
171
|
|
172
|
+
@cb.disconnect
|
192
173
|
end
|
174
|
+
|
193
175
|
end
|
194
176
|
|
195
|
-
Bench.new
|
177
|
+
Bench.new.run
|
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "..", "..", "lib")
|
6
|
+
require 'couchbase'
|
7
|
+
require 'jruby/profiler'
|
8
|
+
|
9
|
+
puts `uname -a`
|
10
|
+
puts File.readlines('/proc/cpuinfo').sort.uniq.grep(/model name|cpu cores/) rescue nil
|
11
|
+
puts RUBY_DESCRIPTION
|
12
|
+
|
13
|
+
class Profile
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
|
17
|
+
puts "PID is #{Process.pid}"
|
18
|
+
|
19
|
+
@value = { 'im' => [ 'testing', 'stuff' ] }
|
20
|
+
|
21
|
+
puts "Raw value size is: #{@value.size} bytes"
|
22
|
+
|
23
|
+
@keys = [
|
24
|
+
@k1 = "Short",
|
25
|
+
@k2 = "Sym1-2-3::45" * 8,
|
26
|
+
@k3 = "Long" * 40,
|
27
|
+
@k4 = "Medium" * 8,
|
28
|
+
@k5 = "Medium2" * 8,
|
29
|
+
@k6 = "Long3" * 40]
|
30
|
+
|
31
|
+
@cb = Couchbase.new
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
profile_data = JRuby::Profiler.profile do
|
38
|
+
2_000.times do
|
39
|
+
@cb.set(@k1, @value)
|
40
|
+
@cb.set(@k2, @value)
|
41
|
+
@cb.set(@k3, @value)
|
42
|
+
end
|
43
|
+
|
44
|
+
2_000.times do
|
45
|
+
@cb.get(@k1)
|
46
|
+
@cb.get(@k2)
|
47
|
+
@cb.get(@k3)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
profile_printer = JRuby::Profiler::GraphProfilePrinter.new(profile_data)
|
52
|
+
profile_printer.printProfile(STDOUT)
|
53
|
+
|
54
|
+
@cb.disconnect
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
Profile.new.run
|
data/test/setup.rb
CHANGED
@@ -21,6 +21,9 @@ require 'couchbase'
|
|
21
21
|
|
22
22
|
require 'socket'
|
23
23
|
require 'open-uri'
|
24
|
+
require 'ostruct'
|
25
|
+
|
26
|
+
require 'pry'
|
24
27
|
|
25
28
|
# Surpress connection logging
|
26
29
|
# java_import java.lang.System
|
@@ -39,153 +42,18 @@ require 'open-uri'
|
|
39
42
|
|
40
43
|
Minitest.after_run { Couchbase.disconnect }
|
41
44
|
|
42
|
-
class CouchbaseServer
|
43
|
-
attr_accessor :host, :port, :num_nodes, :buckets_spec
|
44
|
-
|
45
|
-
def real?
|
46
|
-
true
|
47
|
-
end
|
48
|
-
|
49
|
-
def initialize(params = {})
|
50
|
-
@host, @port = ['localhost', 8091] #ENV['COUCHBASE_SERVER'].split(':')
|
51
|
-
@port = @port.to_i
|
52
|
-
|
53
|
-
if @host.nil? || @host.empty? || @port == 0
|
54
|
-
raise ArgumentError, "Check COUCHBASE_SERVER variable. It should be hostname:port"
|
55
|
-
end
|
56
|
-
|
57
|
-
@config = MultiJson.load(open("http://#{@host}:#{@port}/pools/default"))
|
58
|
-
@num_nodes = @config["nodes"].size
|
59
|
-
@buckets_spec = params[:buckets_spec] || "default:" # "default:,protected:secret,cache::memcache"
|
60
|
-
end
|
61
|
-
|
62
|
-
def start
|
63
|
-
# flush all buckets
|
64
|
-
@buckets_spec.split(',') do |bucket|
|
65
|
-
name, password, _ = bucket.split(':')
|
66
|
-
connection = Couchbase.new(:hostname => @host,
|
67
|
-
:port => @port,
|
68
|
-
:username => name,
|
69
|
-
:bucket => name,
|
70
|
-
:password => password)
|
71
|
-
begin
|
72
|
-
connection.flush
|
73
|
-
rescue Couchbase::Error::NotSupported
|
74
|
-
# on recent server flush is disabled
|
75
|
-
ensure
|
76
|
-
connection.disconnect
|
77
|
-
end
|
78
|
-
end if ENV['COUCHBASE_FLUSH_BUCKETS']
|
79
|
-
end
|
80
|
-
|
81
|
-
def stop
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
class CouchbaseMock
|
86
|
-
Monitor = Struct.new(:pid, :client, :socket, :port)
|
87
|
-
|
88
|
-
attr_accessor :host, :port, :buckets_spec, :num_nodes, :num_vbuckets
|
89
|
-
|
90
|
-
def real?
|
91
|
-
false
|
92
|
-
end
|
93
|
-
|
94
|
-
def initialize(params = {})
|
95
|
-
@host = "127.0.0.1"
|
96
|
-
@port = 0
|
97
|
-
@num_nodes = 10
|
98
|
-
@num_vbuckets = 4096
|
99
|
-
@buckets_spec = "default:" # "default:,protected:secret,cache::memcache"
|
100
|
-
params.each do |key, value|
|
101
|
-
send("#{key}=", value)
|
102
|
-
end
|
103
|
-
yield self if block_given?
|
104
|
-
if @num_vbuckets < 1 || (@num_vbuckets & (@num_vbuckets - 1) != 0)
|
105
|
-
raise ArgumentError, "Number of vbuckets should be a power of two and greater than zero"
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def start
|
110
|
-
@monitor = Monitor.new
|
111
|
-
@monitor.socket = TCPServer.new(nil, 0)
|
112
|
-
@monitor.socket.listen(10)
|
113
|
-
_, @monitor.port, _, _ = @monitor.socket.addr
|
114
|
-
trap("CLD") do
|
115
|
-
puts "CouchbaseMock.jar died unexpectedly during startup"
|
116
|
-
exit(1)
|
117
|
-
end
|
118
|
-
@monitor.pid = fork
|
119
|
-
if @monitor.pid.nil?
|
120
|
-
rc = exec(command_line("--harakiri-monitor=:#{@monitor.port}"))
|
121
|
-
else
|
122
|
-
trap("CLD", "SIG_DFL")
|
123
|
-
@monitor.client, _ = @monitor.socket.accept
|
124
|
-
@port = @monitor.client.recv(100).to_i
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def stop
|
129
|
-
@monitor.client.close
|
130
|
-
@monitor.socket.close
|
131
|
-
Process.kill("TERM", @monitor.pid)
|
132
|
-
Process.wait(@monitor.pid)
|
133
|
-
end
|
134
|
-
|
135
|
-
def failover_node(index, bucket = "default")
|
136
|
-
@monitor.client.send("failover,#{index},#{bucket}", 0)
|
137
|
-
end
|
138
|
-
|
139
|
-
def respawn_node(index, bucket = "default")
|
140
|
-
@monitor.client.send("respawn,#{index},#{bucket}", 0)
|
141
|
-
end
|
142
|
-
|
143
|
-
protected
|
144
|
-
|
145
|
-
def command_line(extra = nil)
|
146
|
-
cmd = "java -jar #{File.dirname(__FILE__)}/CouchbaseMock.jar"
|
147
|
-
cmd << " --host #{@host}" if @host
|
148
|
-
cmd << " --port #{@port}" if @port
|
149
|
-
cmd << " --nodes #{@num_nodes}" if @num_nodes
|
150
|
-
cmd << " --vbuckets #{@num_vbuckets}" if @num_vbuckets
|
151
|
-
cmd << " --buckets #{@buckets_spec}" if @buckets_spec
|
152
|
-
cmd << " #{extra}"
|
153
|
-
cmd
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
45
|
class MiniTest::Test
|
158
46
|
|
159
|
-
def
|
160
|
-
|
161
|
-
if true # ENV['COUCHBASE_SERVER']
|
162
|
-
mock = CouchbaseServer.new(params)
|
163
|
-
if (params[:port] && mock.port != params[:port]) ||
|
164
|
-
(params[:host] && mock.host != params[:host]) ||
|
165
|
-
mock.buckets_spec != "default:"
|
166
|
-
skip("Unable to configure real cluster. Requested config is: #{params.inspect}")
|
167
|
-
end
|
168
|
-
else
|
169
|
-
mock = CouchbaseMock.new(params)
|
170
|
-
end
|
171
|
-
mock.start
|
172
|
-
mock
|
47
|
+
def cb
|
48
|
+
Couchbase.bucket
|
173
49
|
end
|
174
50
|
|
175
|
-
def
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
def with_mock(params = {})
|
181
|
-
return
|
182
|
-
mock = nil
|
183
|
-
if block_given?
|
184
|
-
mock = start_mock(params)
|
185
|
-
yield mock
|
51
|
+
def with_configs(configs = {})
|
52
|
+
configs = Couchbase::Bucket::DEFAULT_OPTIONS.merge(configs)
|
53
|
+
if configs[:host].nil?
|
54
|
+
configs[:host] = configs[:hostname]
|
186
55
|
end
|
187
|
-
|
188
|
-
stop_mock(mock) if mock
|
56
|
+
yield OpenStruct.new(configs)
|
189
57
|
end
|
190
58
|
|
191
59
|
def uniq_id(*suffixes)
|
@@ -195,7 +63,4 @@ class MiniTest::Test
|
|
195
63
|
[test_id, @ids[test_id]].join("_")
|
196
64
|
end
|
197
65
|
|
198
|
-
def after_teardown
|
199
|
-
GC.start
|
200
|
-
end
|
201
66
|
end
|