memcached 0.14 → 0.15

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