memcached 0.14 → 0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,13 @@
1
1
 
2
- HERE = File.dirname(__FILE__)
3
- $LOAD_PATH << "#{HERE}/../../lib/"
2
+ require "#{File.dirname(__FILE__)}/../setup"
4
3
 
4
+ $LOAD_PATH << "#{File.dirname(__FILE__)}/../../lib/"
5
5
  require 'rubygems'
6
6
  require 'memcached'
7
7
  require 'ruby-prof'
8
8
 
9
- @cache = Memcached.new(
10
- '127.0.0.1:43042', '127.0.0.1:43043'],
11
- :namespace => "namespace"
12
- )
13
-
14
9
  result = RubyProf.profile do
15
- load "#{HERE}/valgrind.rb"
10
+ load "#{HERE}/profile/valgrind.rb"
16
11
  end
17
12
 
18
13
  printer = RubyProf::GraphPrinter.new(result)
@@ -1,14 +1,14 @@
1
1
 
2
- HERE = File.dirname(__FILE__)
3
- $LOAD_PATH << "#{HERE}/../../lib/"
2
+ require "#{File.dirname(__FILE__)}/../setup"
4
3
 
4
+ $LOAD_PATH << "#{File.dirname(__FILE__)}/../../lib/"
5
5
  require 'memcached'
6
6
  require 'rubygems'
7
7
 
8
8
  class Worker
9
9
  def initialize(method_name, iterations)
10
10
  @method = method_name || 'mixed'
11
- @i = (iterations || 1000).to_i
11
+ @i = (iterations || 10000).to_i
12
12
 
13
13
  @key1 = "key1-"*8
14
14
  @key2 = "key2-"*8
@@ -17,15 +17,13 @@ class Worker
17
17
  @marshalled = Marshal.dump(@value)
18
18
 
19
19
  @opts = [
20
- ['127.0.0.1:43042', '127.0.0.1:43043'],
20
+ ["#{UNIX_SOCKET_NAME}0", "#{UNIX_SOCKET_NAME}1"],
21
21
  {
22
22
  :buffer_requests => false,
23
23
  :no_block => false,
24
24
  :namespace => "namespace"
25
25
  }
26
26
  ]
27
- system("ruby #{HERE}/../setup.rb")
28
- sleep(1)
29
27
  @cache = Memcached.new(*@opts)
30
28
 
31
29
  @cache.set @key1, @value
@@ -103,11 +101,6 @@ class Worker
103
101
  when "clone"
104
102
  @i.times do
105
103
  cache = @cache.clone
106
- cache.destroy(false)
107
- end
108
- when "clone-nodestroy"
109
- @i.times do
110
- @cache.clone
111
104
  end
112
105
  when "servers"
113
106
  @i.times do
@@ -117,7 +110,7 @@ class Worker
117
110
  raise "No such method"
118
111
  end
119
112
 
120
- @cache.destroy
113
+ GC.start
121
114
  end
122
115
 
123
116
  end
@@ -1,17 +1,22 @@
1
-
2
- # Start memcached
3
-
4
- HERE = File.dirname(__FILE__)
5
-
6
- `ps awx`.split("\n").grep(/4304[2-6]/).map do |process|
7
- system("kill -9 #{process.to_i}")
1
+
2
+ unless defined? UNIX_SOCKET_NAME
3
+ HERE = File.dirname(__FILE__)
4
+ UNIX_SOCKET_NAME = File.join(ENV['TMPDIR']||'/tmp','memcached')
5
+
6
+ # Kill memcached
7
+ system("killall -9 memcached")
8
+
9
+ # Start memcached
10
+ verbosity = (ENV['DEBUG'] ? "-vv" : "")
11
+ log = "/tmp/memcached.log"
12
+ system ">#{log}"
13
+
14
+ # Network memcached
15
+ (43042..43046).each do |port|
16
+ system "memcached #{verbosity} -U #{port} -p #{port} >> #{log} 2>&1 &"
17
+ end
18
+ # Domain socket memcached
19
+ (0..1).each do |i|
20
+ system "memcached -M -s #{UNIX_SOCKET_NAME}#{i} #{verbosity} >> #{log} 2>&1 &"
21
+ end
8
22
  end
9
-
10
- log = "/tmp/memcached.log"
11
- system ">#{log}"
12
-
13
- verbosity = (ENV['DEBUG'] ? "-vv" : "")
14
-
15
- (43042..43046).each do |port|
16
- system "memcached #{verbosity} -p #{port} >> #{log} 2>&1 &"
17
- end
@@ -1,8 +1,10 @@
1
1
 
2
2
  $LOAD_PATH << "#{File.dirname(__FILE__)}/../lib"
3
3
 
4
+ require 'rubygems'
5
+ require 'mocha'
6
+
4
7
  if ENV['DEBUG']
5
- require 'rubygems'
6
8
  require 'ruby-debug'
7
9
  end
8
10
 
@@ -10,5 +12,7 @@ require 'memcached'
10
12
  require 'test/unit'
11
13
  require 'ostruct'
12
14
 
15
+ UNIX_SOCKET_NAME = File.join(ENV['TMPDIR']||'/tmp','memcached') unless defined? UNIX_SOCKET_NAME
16
+
13
17
  class GenericClass
14
18
  end
@@ -1,12 +1,13 @@
1
-
1
+
2
2
  require "#{File.dirname(__FILE__)}/../test_helper"
3
3
  require 'socket'
4
+ require 'mocha'
4
5
  require 'benchmark'
5
6
 
6
7
  class MemcachedTest < Test::Unit::TestCase
7
8
 
8
9
  def setup
9
- @servers = ['localhost:43042', 'localhost:43043']
10
+ @servers = ['localhost:43042', 'localhost:43043', "#{UNIX_SOCKET_NAME}0"]
10
11
 
11
12
  # Maximum allowed prefix key size for :hash_with_prefix_key_key => false
12
13
  @prefix_key = 'prefix_key_'
@@ -18,6 +19,14 @@ class MemcachedTest < Test::Unit::TestCase
18
19
  }
19
20
  @cache = Memcached.new(@servers, @options)
20
21
 
22
+ @udp_options = {
23
+ :prefix_key => @prefix_key,
24
+ :hash => :default,
25
+ :udp => true,
26
+ :distribution => :modula
27
+ }
28
+ @udp_cache = Memcached.new(@servers, @udp_options)
29
+
21
30
  @nb_options = {
22
31
  :prefix_key => @prefix_key,
23
32
  :no_block => true,
@@ -35,10 +44,9 @@ class MemcachedTest < Test::Unit::TestCase
35
44
  def test_initialize
36
45
  cache = Memcached.new @servers, :prefix_key => 'test'
37
46
  assert_equal 'test', cache.options[:prefix_key]
38
- assert_equal 2, cache.send(:server_structs).size
47
+ assert_equal 3, cache.send(:server_structs).size
39
48
  assert_equal 'localhost', cache.send(:server_structs).first.hostname
40
- assert_equal 'localhost', cache.send(:server_structs).last.hostname
41
- assert_equal 43043, cache.send(:server_structs).last.port
49
+ assert_equal 43042, cache.send(:server_structs).first.port
42
50
  end
43
51
 
44
52
  def test_initialize_with_ip_addresses
@@ -69,6 +77,12 @@ class MemcachedTest < Test::Unit::TestCase
69
77
  end
70
78
  end
71
79
 
80
+ def test_initialize_with_ip_address_and_options
81
+ cache = Memcached.new '127.0.0.1:43042', :ketama_weighted => false
82
+ assert_equal '127.0.0.1', cache.send(:server_structs).first.hostname
83
+ assert_equal false, cache.options[:ketama_weighted]
84
+ end
85
+
72
86
  def test_options_are_set
73
87
  Memcached::DEFAULTS.merge(@nb_options).each do |key, expected|
74
88
  value = @nb_cache.options[key]
@@ -120,7 +134,7 @@ class MemcachedTest < Test::Unit::TestCase
120
134
  def test_initialize_without_prefix_key
121
135
  cache = Memcached.new @servers
122
136
  assert_equal nil, cache.options[:prefix_key]
123
- assert_equal 2, cache.send(:server_structs).size
137
+ assert_equal 3, cache.send(:server_structs).size
124
138
  end
125
139
 
126
140
  def test_initialize_negative_behavior
@@ -204,6 +218,12 @@ class MemcachedTest < Test::Unit::TestCase
204
218
  result = @cache.get key
205
219
  assert_equal @value, result
206
220
  end
221
+
222
+ def test_udp_get
223
+ @udp_cache.set key, @value
224
+ result = @udp_cache.get key
225
+ assert_equal @value, result
226
+ end
207
227
 
208
228
  def test_get_nil
209
229
  @cache.set key, nil, 0
@@ -222,21 +242,21 @@ class MemcachedTest < Test::Unit::TestCase
222
242
  socket = stub_server 43047
223
243
  cache = Memcached.new("localhost:43047:1", :timeout => 0.5)
224
244
  assert 0.49 < (Benchmark.measure do
225
- assert_raise(Memcached::UnknownReadFailure) do
245
+ assert_raise(Memcached::ATimeoutOccurred) do
226
246
  result = cache.get key
227
247
  end
228
248
  end).real
229
249
 
230
250
  cache = Memcached.new("localhost:43047:1", :poll_timeout => 0.001, :rcv_timeout => 0.5)
231
251
  assert 0.49 < (Benchmark.measure do
232
- assert_raise(Memcached::UnknownReadFailure) do
252
+ assert_raise(Memcached::ATimeoutOccurred) do
233
253
  result = cache.get key
234
254
  end
235
255
  end).real
236
256
 
237
257
  cache = Memcached.new("localhost:43047:1", :poll_timeout => 0.25, :rcv_timeout => 0.25)
238
- assert 0.4 > (Benchmark.measure do
239
- assert_raise(Memcached::UnknownReadFailure) do
258
+ assert 0.51 > (Benchmark.measure do
259
+ assert_raise(Memcached::ATimeoutOccurred) do
240
260
  result = cache.get key
241
261
  end
242
262
  end).real
@@ -246,14 +266,14 @@ class MemcachedTest < Test::Unit::TestCase
246
266
  socket = stub_server 43048
247
267
  cache = Memcached.new("localhost:43048:1", :no_block => true, :timeout => 0.25)
248
268
  assert 0.24 < (Benchmark.measure do
249
- assert_raise(Memcached::UnknownReadFailure) do
269
+ assert_raise(Memcached::ATimeoutOccurred) do
250
270
  result = cache.get key
251
271
  end
252
272
  end).real
253
273
 
254
274
  cache = Memcached.new("localhost:43048:1", :no_block => true, :poll_timeout => 0.25, :rcv_timeout => 0.001)
255
275
  assert 0.24 < (Benchmark.measure do
256
- assert_raise(Memcached::UnknownReadFailure) do
276
+ assert_raise(Memcached::ATimeoutOccurred) do
257
277
  result = cache.get key
258
278
  end
259
279
  end).real
@@ -263,7 +283,7 @@ class MemcachedTest < Test::Unit::TestCase
263
283
  :rcv_timeout => 0.25 # No affect in no-block mode
264
284
  )
265
285
  assert 0.24 > (Benchmark.measure do
266
- assert_raise(Memcached::UnknownReadFailure) do
286
+ assert_raise(Memcached::ATimeoutOccurred) do
267
287
  result = cache.get key
268
288
  end
269
289
  end).real
@@ -379,6 +399,12 @@ class MemcachedTest < Test::Unit::TestCase
379
399
  end
380
400
  end
381
401
 
402
+ def test_udp_set
403
+ assert_nothing_raised do
404
+ @udp_cache.set(key, @value)
405
+ end
406
+ end
407
+
382
408
  def test_set_expiry
383
409
  @cache.set key, @value, 1
384
410
  assert_nothing_raised do
@@ -655,17 +681,25 @@ class MemcachedTest < Test::Unit::TestCase
655
681
  end
656
682
  end
657
683
 
658
- def test_set_object_too_large
659
- assert_raise(Memcached::ServerError) do
660
- @cache.set key, "I'm big" * 1000000
661
- end
684
+ def test_server_error_message
685
+ @cache.set key, "I'm big" * 1000000
686
+ assert false # Never reached
687
+ rescue Memcached::ServerError => e
688
+ assert_match /^"object too large for cache". Key/, e.message
689
+ end
690
+
691
+ def test_errno_message
692
+ Rlibmemcached::MemcachedServerSt.any_instance.expects("cached_errno").returns(1)
693
+ @cache.send(:check_return_code, Rlibmemcached::MEMCACHED_ERRNO, key)
694
+ rescue Memcached::SystemError => e
695
+ assert_match /^Errno 1: "Operation not permitted". Key/, e.message
662
696
  end
663
697
 
664
698
  # Stats
665
699
 
666
700
  def test_stats
667
701
  stats = @cache.stats
668
- assert_equal 2, stats[:pid].size
702
+ assert_equal 3, stats[:pid].size
669
703
  assert_instance_of Fixnum, stats[:pid].first
670
704
  assert_instance_of String, stats[:version].first
671
705
  end
@@ -753,30 +787,64 @@ class MemcachedTest < Test::Unit::TestCase
753
787
 
754
788
  # Server removal and consistent hashing
755
789
 
756
- def test_missing_server
790
+ def test_unresponsive_server
757
791
  socket = stub_server 43041
758
792
  cache = Memcached.new(
759
793
  [@servers.last, 'localhost:43041'],
760
794
  :prefix_key => @prefix_key,
761
795
  :auto_eject_hosts => true,
762
- :server_failure_limit => 1,
796
+ :server_failure_limit => 2,
763
797
  :retry_timeout => 1,
764
798
  :hash_with_prefix_key => false,
765
799
  :hash => :md5
766
800
  )
767
801
 
768
- # Hit first server
769
- key1 = 'test_missing_server6'
770
- cache.set(key1, @value)
771
- cache.get(key1) == @value
802
+ # Hit second server up to the server_failure_limit
803
+ key2 = 'test_missing_server'
804
+ assert_raise(Memcached::ATimeoutOccurred) { cache.set(key2, @value) }
805
+ assert_raise(Memcached::ATimeoutOccurred) { cache.get(key2, @value) }
772
806
 
773
- # Hit second server
807
+ # Hit second server and pass the limit
774
808
  key2 = 'test_missing_server'
775
- assert_raise(Memcached::UnknownReadFailure) do
809
+ begin
810
+ cache.get(key2)
811
+ rescue => e
812
+ assert_equal Memcached::ServerIsMarkedDead, e.class
813
+ assert_match /localhost:43041/, e.message
814
+ end
815
+
816
+ # Hit first server on retry
817
+ assert_nothing_raised do
776
818
  cache.set(key2, @value)
819
+ assert_equal cache.get(key2), @value
777
820
  end
821
+
822
+ sleep(2)
823
+
824
+ # Hit second server again after restore, expect same failure
825
+ key2 = 'test_missing_server'
826
+ assert_raise(Memcached::ATimeoutOccurred) do
827
+ cache.set(key2, @value)
828
+ end
829
+ end
778
830
 
779
- # Hit second server again
831
+ def test_missing_server
832
+ cache = Memcached.new(
833
+ [@servers.last, 'localhost:43041'],
834
+ :prefix_key => @prefix_key,
835
+ :auto_eject_hosts => true,
836
+ :server_failure_limit => 2,
837
+ :retry_timeout => 1,
838
+ :hash_with_prefix_key => false,
839
+ :hash => :md5
840
+ )
841
+
842
+ # Hit second server up to the server_failure_limit
843
+ key2 = 'test_missing_server'
844
+ assert_raise(Memcached::SystemError) { cache.set(key2, @value) }
845
+ assert_raise(Memcached::SystemError) { cache.get(key2, @value) }
846
+
847
+ # Hit second server and pass the limit
780
848
  key2 = 'test_missing_server'
781
849
  begin
782
850
  cache.get(key2)
@@ -788,14 +856,14 @@ class MemcachedTest < Test::Unit::TestCase
788
856
  # Hit first server on retry
789
857
  assert_nothing_raised do
790
858
  cache.set(key2, @value)
791
- cache.get(key2)
859
+ assert_equal cache.get(key2), @value
792
860
  end
793
861
 
794
862
  sleep(2)
795
863
 
796
864
  # Hit second server again after restore, expect same failure
797
865
  key2 = 'test_missing_server'
798
- assert_raise(Memcached::UnknownReadFailure) do
866
+ assert_raise(Memcached::SystemError) do
799
867
  cache.set(key2, @value)
800
868
  end
801
869
  end
@@ -849,7 +917,7 @@ class MemcachedTest < Test::Unit::TestCase
849
917
  threads.each {|thread| thread.join}
850
918
  end
851
919
 
852
- # Hash
920
+ # Hash
853
921
 
854
922
  def test_hash
855
923
  assert_equal 3157003241,
@@ -4,7 +4,7 @@ require "#{File.dirname(__FILE__)}/../test_helper"
4
4
  class RailsTest < Test::Unit::TestCase
5
5
 
6
6
  def setup
7
- @servers = ['127.0.0.1:43042', '127.0.0.1:43043']
7
+ @servers = ['127.0.0.1:43042', '127.0.0.1:43043', "#{UNIX_SOCKET_NAME}0"]
8
8
  @namespace = 'rails_test'
9
9
  @cache = Memcached::Rails.new(:servers => @servers, :namespace => @namespace)
10
10
  @value = OpenStruct.new(:a => 1, :b => 2, :c => GenericClass)
@@ -19,7 +19,7 @@ class RailsTest < Test::Unit::TestCase
19
19
 
20
20
  def test_get_multi
21
21
  @cache.set key, @value
22
- result = @cache.get_multi key
22
+ result = @cache.get_multi([key])
23
23
  assert_equal(
24
24
  {key => @value},
25
25
  result
@@ -47,6 +47,36 @@ class RailsTest < Test::Unit::TestCase
47
47
  assert_equal @value, result
48
48
  end
49
49
 
50
+ def test_cas
51
+ cache = Memcached::Rails.new(:servers => @servers, :namespace => @namespace, :support_cas => true)
52
+ value2 = OpenStruct.new(:d => 3, :e => 4, :f => GenericClass)
53
+
54
+ # Existing set
55
+ cache.set key, @value
56
+ cache.cas(key) do |current|
57
+ assert_equal @value, current
58
+ value2
59
+ end
60
+ assert_equal value2, cache.get(key)
61
+
62
+ # Missing set
63
+ cache.delete key
64
+ assert_nothing_raised do
65
+ cache.cas(key) { @called = true }
66
+ end
67
+ assert_nil cache.get(key)
68
+ assert_nil @called
69
+
70
+ # Conflicting set
71
+ cache.set key, @value
72
+ assert_raises(Memcached::ConnectionDataExists) do
73
+ cache.cas(key) do |current|
74
+ cache.set key, value2
75
+ current
76
+ end
77
+ end
78
+ end
79
+
50
80
  def test_get_missing
51
81
  @cache.delete key rescue nil
52
82
  result = @cache.get key