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.
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