couchbase-jruby-client 0.1.0-java → 0.1.5-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.jrubyrc +722 -0
  3. data/.ruby-version +1 -1
  4. data/README.md +12 -90
  5. data/couchbase-jruby-client.gemspec +6 -6
  6. data/lib/couchbase/async.rb +18 -0
  7. data/lib/couchbase/bucket.rb +90 -180
  8. data/lib/couchbase/constants.rb +17 -0
  9. data/lib/couchbase/design_doc.rb +83 -0
  10. data/lib/couchbase/error.rb +31 -0
  11. data/lib/couchbase/operations/arithmetic.rb +17 -0
  12. data/lib/couchbase/operations/delete.rb +17 -0
  13. data/lib/couchbase/operations/design_docs.rb +99 -0
  14. data/lib/couchbase/operations/get.rb +73 -67
  15. data/lib/couchbase/operations/stats.rb +28 -1
  16. data/lib/couchbase/operations/store.rb +114 -97
  17. data/lib/couchbase/operations/touch.rb +49 -19
  18. data/lib/couchbase/operations/unlock.rb +209 -0
  19. data/lib/couchbase/operations/utils.rb +22 -10
  20. data/lib/couchbase/operations.rb +21 -0
  21. data/lib/couchbase/query.rb +92 -0
  22. data/lib/couchbase/result.rb +18 -1
  23. data/lib/couchbase/transcoder.rb +36 -42
  24. data/lib/couchbase/version.rb +18 -1
  25. data/lib/couchbase/view.rb +30 -172
  26. data/lib/couchbase/view_row.rb +38 -98
  27. data/lib/couchbase.rb +74 -72
  28. data/test/profile/.jrubyrc +722 -0
  29. data/test/profile/Gemfile +5 -5
  30. data/test/profile/benchmark.rb +106 -124
  31. data/test/profile/profile.rb +59 -0
  32. data/test/setup.rb +10 -145
  33. data/test/test_arithmetic.rb +54 -77
  34. data/test/test_async.rb +74 -102
  35. data/test/test_bucket.rb +74 -60
  36. data/test/test_cas.rb +10 -23
  37. data/test/test_couchbase.rb +11 -3
  38. data/test/test_delete.rb +41 -43
  39. data/test/test_design_docs.rb +62 -0
  40. data/test/test_errors.rb +9 -18
  41. data/test/test_format.rb +21 -31
  42. data/test/test_get.rb +107 -151
  43. data/test/test_query.rb +23 -0
  44. data/test/test_stats.rb +9 -24
  45. data/test/test_store.rb +52 -65
  46. data/test/test_timer.rb +4 -12
  47. data/test/test_touch.rb +26 -33
  48. data/test/test_unlock.rb +47 -78
  49. data/test/test_utils.rb +2 -11
  50. data/test/test_version.rb +5 -14
  51. data/test/test_view.rb +87 -0
  52. metadata +27 -14
  53. data/lib/couchbase/jruby/couchbase_client.rb +0 -22
  54. data/lib/couchbase/jruby/future.rb +0 -8
data/test/profile/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "memcached", "~> 1.3.6"
4
- gem "kgio", "~> 2.7.2"
5
- gem "dalli", "~> 1.1.4"
6
- gem "yajl-ruby", "~> 1.1.0"
3
+ gem 'benchmark-ips'
4
+ gem 'jrjackson', '~> 0.2.3'
5
+ gem 'multi_json', '~> 1.0'
6
+ gem 'atomic', '~> 1.1.14'
@@ -24,15 +24,12 @@
24
24
  # show exceptions
25
25
  #
26
26
 
27
- require "rubygems"
28
- require "bundler/setup"
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 'memcached'
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(loops = nil, stack_depth = nil)
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
- @m_value = Marshal.dump(
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 "Small value size is: #{@m_value.size} bytes"
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
- reset_clients
56
+ @cb = Couchbase.new
57
+ @cl = @cb.client
68
58
 
69
- Benchmark.bm(36) do |x|
70
- @benchmark = x
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(level = @stack_depth)
75
- level > 0 ? run(level - 1) : run_without_recursion
76
- end
77
-
78
- private
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
- def run_without_recursion
124
- benchmark_clients("set") do |c|
125
- c.set @k1, @m_value
126
- c.set @k2, @m_value
127
- c.set @k3, @m_value
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
- benchmark_clients("get") do |c|
131
- c.get @k1
132
- c.get @k2
133
- c.get @k3
134
- end
80
+ x.report('jruby get') do
81
+ @cb.get @k1
82
+ @cb.get @k2
83
+ @cb.get @k3
84
+ end
135
85
 
136
- benchmark_clients("get_multi") do |c|
137
- if c.respond_to?(:get_multi)
138
- c.get_multi @keys
139
- else
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
- benchmark_clients("append") do |c|
145
- c.append @k1, @m_value
146
- c.append @k2, @m_value
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
- benchmark_clients("prepend") do |c|
151
- c.prepend @k1, @m_value
152
- c.prepend @k2, @m_value
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
- benchmark_clients("delete") do |c|
157
- c.delete @k1
158
- c.delete @k2
159
- c.delete @k3
160
- end
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
- benchmark_clients("get_missing", false) do |c|
163
- c.get @k1 rescue nil
164
- c.get @k2 rescue nil
165
- c.get @k3 rescue nil
166
- end
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
- benchmark_clients("append_missing", false) do |c|
169
- c.append @k1, @m_value rescue nil
170
- c.append @k2, @m_value rescue nil
171
- c.append @k3, @m_value rescue nil
172
- end
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
- benchmark_clients("prepend_missing", false) do |c|
175
- c.prepend @k1, @m_value rescue nil
176
- c.prepend @k2, @m_value rescue nil
177
- c.prepend @k3, @m_value rescue nil
178
- end
124
+ x.report('java get missing') do
125
+ @cl.get @k1
126
+ @cl.get @k2
127
+ @cl.get @k3
128
+ end
179
129
 
180
- benchmark_clients("set_large") do |c|
181
- c.set @k1, @m_large_value
182
- c.set @k2, @m_large_value
183
- c.set @k3, @m_large_value
184
- end
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(ENV["LOOPS"], ENV["STACK_DEPTH"]).run
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 start_mock(params = {})
160
- mock = nil
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 stop_mock(mock)
176
- assert(mock)
177
- mock.stop
178
- end
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
- ensure
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