memcache-client 1.7.7 → 1.7.8
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.
- data/FAQ.rdoc +1 -1
- data/History.rdoc +17 -11
- data/README.rdoc +1 -1
- data/Rakefile +4 -5
- data/VERSION.yml +2 -2
- data/lib/memcache.rb +18 -10
- data/lib/memcache_util.rb +2 -2
- data/test/test_benchmark.rb +10 -10
- data/test/test_mem_cache.rb +29 -21
- metadata +3 -7
- data/lib/continuum_native.rbc +0 -362
- data/lib/memcache.rbc +0 -18734
- data/test/test_benchmark.rbc +0 -2524
- data/test/test_mem_cache.rbc +0 -26058
data/FAQ.rdoc
CHANGED
@@ -27,5 +27,5 @@ You can increase the timeout or disable them completely with the following confi
|
|
27
27
|
|
28
28
|
The latest version of memcached-client is anywhere from 33% to 100% slower than memcached in various benchmarks. Keep in mind this means that 10,000 get requests take 1.8 sec instead of 1.2 seconds.
|
29
29
|
In practice, memcache-client is unlikely to be a bottleneck in your system but there is always going
|
30
|
-
to be an overhead to pure Ruby. memcache-client does have the advantage of built-in integration into
|
30
|
+
to be an overhead to pure Ruby. memcache-client does have the advantage of built-in integration into
|
31
31
|
Rails and should work on non-MRI platforms: JRuby, MacRuby, etc.
|
data/History.rdoc
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
= 1.7.8 (2010-02-03)
|
2
|
+
|
3
|
+
* Fix issue where autofix_keys logic did not account for namespace length. (menno)
|
4
|
+
* Fix issue when using memcache-client without rubygems. (anvar)
|
5
|
+
* Fix issue when using the cas method with raw=true (Takahiro Kikumoto)
|
6
|
+
|
1
7
|
= 1.7.7 (2009-11-24)
|
2
8
|
|
3
|
-
* Fix invalid delete request in memcached 1.4.x. The expiry parameter to MemCache#delete is
|
9
|
+
* Fix invalid delete request in memcached 1.4.x. The expiry parameter to MemCache#delete is
|
4
10
|
now ignored as memcached 1.4.x has dropped support for this feature.
|
5
11
|
|
6
12
|
= 1.7.6 (2009-11-03)
|
@@ -39,15 +45,15 @@
|
|
39
45
|
|
40
46
|
= 1.7.1 (2009-03-28)
|
41
47
|
|
42
|
-
* Performance optimizations:
|
43
|
-
* Rely on higher performance operating system socket timeouts for low-level socket
|
48
|
+
* Performance optimizations:
|
49
|
+
* Rely on higher performance operating system socket timeouts for low-level socket
|
44
50
|
read/writes where possible, instead of the (slower) SystemTimer or (slowest,
|
45
51
|
unreliable) Timeout libraries.
|
46
|
-
* the native binary search is back! The recent performance tuning made the binary search
|
47
|
-
a bottleneck again so it had to return. It uses RubyInline to compile the native extension and
|
52
|
+
* the native binary search is back! The recent performance tuning made the binary search
|
53
|
+
a bottleneck again so it had to return. It uses RubyInline to compile the native extension and
|
48
54
|
silently falls back to pure Ruby if anything fails. Make sure you run:
|
49
55
|
`gem install RubyInline` if you want ultimate performance.
|
50
|
-
* the changes make memcache-client 100% faster than 1.7.0 in my performance test on Ruby 1.8.6:
|
56
|
+
* the changes make memcache-client 100% faster than 1.7.0 in my performance test on Ruby 1.8.6:
|
51
57
|
15 sec -> 8 sec.
|
52
58
|
* Fix several logging issues.
|
53
59
|
|
@@ -58,7 +64,7 @@
|
|
58
64
|
- append
|
59
65
|
- prepend
|
60
66
|
- replace
|
61
|
-
|
67
|
+
|
62
68
|
Append and prepend only work with raw data since it makes no sense to concatenate two Marshalled
|
63
69
|
values together. The cas functionality should be considered a prototype. Since I don't have an
|
64
70
|
application which uses +cas+, I'm not sure what semantic sugar the API should provide. Should it
|
@@ -119,17 +125,17 @@ and work on JRuby and Ruby 1.8.5 when the native code fails to compile.
|
|
119
125
|
|
120
126
|
= 1.6.1 (2009-01-28)
|
121
127
|
|
122
|
-
* Add option to disable socket timeout support. Socket timeout has a significant performance
|
123
|
-
penalty (approx 3x slower than without in Ruby 1.8.6). You can turn off the timeouts if you
|
128
|
+
* Add option to disable socket timeout support. Socket timeout has a significant performance
|
129
|
+
penalty (approx 3x slower than without in Ruby 1.8.6). You can turn off the timeouts if you
|
124
130
|
need absolute performance, but by default timeouts are enabled. The performance
|
125
131
|
penalty is much lower in Ruby 1.8.7, 1.9 and JRuby. (mperham)
|
126
132
|
|
127
|
-
* Add option to disable server failover. Failover can lead to "split-brain" caches that
|
133
|
+
* Add option to disable server failover. Failover can lead to "split-brain" caches that
|
128
134
|
return stale data. (mperham)
|
129
135
|
|
130
136
|
* Implement continuum binary search in native code for performance reasons. Pure ruby
|
131
137
|
is available for platforms like JRuby or Rubinius which can't use C extensions. (mperham)
|
132
|
-
|
138
|
+
|
133
139
|
* Fix #add with raw=true (iamaleksey)
|
134
140
|
|
135
141
|
= 1.6.0
|
data/README.rdoc
CHANGED
@@ -39,7 +39,7 @@ gem installed.
|
|
39
39
|
|
40
40
|
== Questions?
|
41
41
|
|
42
|
-
memcache-client is maintained by Mike Perham and was originally written by Bob Cottrell,
|
42
|
+
memcache-client is maintained by Mike Perham and was originally written by Bob Cottrell,
|
43
43
|
Eric Hodel and the seattle.rb crew.
|
44
44
|
|
45
45
|
Email:: mailto:mperham@gmail.com
|
data/Rakefile
CHANGED
@@ -14,18 +14,17 @@ begin
|
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.files = FileList["[A-Z]*", "{lib,test}/**/*", 'performance.txt']
|
16
16
|
s.test_files = FileList["test/test_*.rb"]
|
17
|
-
s.rubyforge_project = 'seattlerb'
|
18
17
|
end
|
19
|
-
|
18
|
+
Jeweler::GemcutterTasks.new
|
20
19
|
rescue LoadError
|
21
20
|
puts "Jeweler not available. Install it for jeweler-related tasks with: sudo gem install jeweler"
|
22
21
|
end
|
23
22
|
|
24
23
|
|
25
24
|
Rake::RDocTask.new do |rd|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
rd.main = "README.rdoc"
|
26
|
+
rd.rdoc_files.include("README.rdoc", "FAQ.rdoc", "History.rdoc", "lib/memcache.rb")
|
27
|
+
rd.rdoc_dir = 'doc'
|
29
28
|
end
|
30
29
|
|
31
30
|
Rake::TestTask.new do |t|
|
data/VERSION.yml
CHANGED
data/lib/memcache.rb
CHANGED
@@ -3,6 +3,7 @@ $TESTING = defined?($TESTING) && $TESTING
|
|
3
3
|
require 'socket'
|
4
4
|
require 'thread'
|
5
5
|
require 'zlib'
|
6
|
+
require 'yaml'
|
6
7
|
require 'digest/sha1'
|
7
8
|
require 'net/protocol'
|
8
9
|
|
@@ -82,13 +83,13 @@ class MemCache
|
|
82
83
|
# The hash is only used on keys longer than 250 characters, or containing spaces,
|
83
84
|
# to avoid impacting performance unnecesarily.
|
84
85
|
#
|
85
|
-
# In theory, your code should generate correct keys when calling memcache,
|
86
|
+
# In theory, your code should generate correct keys when calling memcache,
|
86
87
|
# so it's your responsibility and you should try to fix this problem at its source.
|
87
88
|
#
|
88
89
|
# But if that's not possible, enable this option and memcache-client will give you a hand.
|
89
|
-
|
90
|
+
|
90
91
|
attr_reader :autofix_keys
|
91
|
-
|
92
|
+
|
92
93
|
##
|
93
94
|
# The servers this client talks to. Play at your own peril.
|
94
95
|
|
@@ -136,7 +137,7 @@ class MemCache
|
|
136
137
|
# set/add/delete/incr/decr significantly.
|
137
138
|
# [:check_size] Raises a MemCacheError if the value to be set is greater than 1 MB, which
|
138
139
|
# is the maximum key size for the standard memcached server. Defaults to true.
|
139
|
-
# [:autofix_keys] If a key is longer than 250 characters or contains spaces,
|
140
|
+
# [:autofix_keys] If a key is longer than 250 characters or contains spaces,
|
140
141
|
# use an SHA1 hash instead, to prevent collisions on truncated keys.
|
141
142
|
# Other options are ignored.
|
142
143
|
|
@@ -260,7 +261,7 @@ class MemCache
|
|
260
261
|
end
|
261
262
|
|
262
263
|
##
|
263
|
-
# Performs a +get+ with the given +key+. If
|
264
|
+
# Performs a +get+ with the given +key+. If
|
264
265
|
# the value does not exist and a block was given,
|
265
266
|
# the block will be called and the result saved via +add+.
|
266
267
|
#
|
@@ -405,7 +406,7 @@ class MemCache
|
|
405
406
|
(value, token) = gets(key, raw)
|
406
407
|
return nil unless value
|
407
408
|
updated = yield value
|
408
|
-
value = Marshal.dump
|
409
|
+
value = raw ? updated : Marshal.dump(updated)
|
409
410
|
|
410
411
|
with_server(key) do |server, cache_key|
|
411
412
|
logger.debug { "cas #{key} to #{server.inspect}: #{value.to_s.size}" } if logger
|
@@ -451,7 +452,7 @@ class MemCache
|
|
451
452
|
end
|
452
453
|
end
|
453
454
|
end
|
454
|
-
|
455
|
+
|
455
456
|
##
|
456
457
|
# Add +key+ to the cache with value +value+ that expires in +expiry+
|
457
458
|
# seconds, but only if +key+ already exists in the cache.
|
@@ -667,17 +668,24 @@ class MemCache
|
|
667
668
|
# requested.
|
668
669
|
|
669
670
|
def make_cache_key(key)
|
670
|
-
if @autofix_keys
|
671
|
+
if @autofix_keys && (key =~ /\s/ || key_length(key) > 250)
|
671
672
|
key = "#{Digest::SHA1.hexdigest(key)}-autofixed"
|
672
673
|
end
|
673
674
|
|
674
|
-
if namespace.nil?
|
675
|
+
if namespace.nil?
|
675
676
|
key
|
676
677
|
else
|
677
678
|
"#{@namespace}#{@namespace_separator}#{key}"
|
678
679
|
end
|
679
680
|
end
|
680
681
|
|
682
|
+
##
|
683
|
+
# Calculate length of the key, including the namespace and namespace-separator.
|
684
|
+
|
685
|
+
def key_length(key)
|
686
|
+
key.length + (namespace.nil? ? 0 : ( namespace.length + (@namespace_separator.nil? ? 0 : @namespace_separator.length) ) )
|
687
|
+
end
|
688
|
+
|
681
689
|
##
|
682
690
|
# Returns an interoperable hash value for +key+. (I think, docs are
|
683
691
|
# sketchy for down servers).
|
@@ -705,7 +713,7 @@ class MemCache
|
|
705
713
|
break unless failover
|
706
714
|
hkey = hash_for "#{try}#{key}"
|
707
715
|
end
|
708
|
-
|
716
|
+
|
709
717
|
raise MemCacheError, "No servers available"
|
710
718
|
end
|
711
719
|
|
data/lib/memcache_util.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
##
|
2
2
|
# A utility wrapper around the MemCache client to simplify cache access. All
|
3
3
|
# methods silently ignore MemCache errors.
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# This API is deprecated, please use the Rails.cache API or your own wrapper API
|
6
6
|
# around MemCache.
|
7
7
|
|
8
8
|
module Cache
|
9
|
-
|
9
|
+
|
10
10
|
##
|
11
11
|
# Try to return a logger object that does not rely
|
12
12
|
# on ActiveRecord for logging.
|
data/test/test_benchmark.rb
CHANGED
@@ -17,7 +17,7 @@ class TestBenchmark < Test::Unit::TestCase
|
|
17
17
|
# which is a constant penalty that both clients have to pay
|
18
18
|
@value = []
|
19
19
|
@marshalled = Marshal.dump(@value)
|
20
|
-
|
20
|
+
|
21
21
|
@opts = [
|
22
22
|
['127.0.0.1:11211', 'localhost:11211'],
|
23
23
|
{
|
@@ -31,16 +31,16 @@ class TestBenchmark < Test::Unit::TestCase
|
|
31
31
|
@key3 = "Long"*40
|
32
32
|
@key4 = "Medium"*8
|
33
33
|
# 5 and 6 are only used for multiget miss test
|
34
|
-
@key5 = "Medium2"*8
|
35
|
-
@key6 = "Long3"*40
|
34
|
+
@key5 = "Medium2"*8
|
35
|
+
@key6 = "Long3"*40
|
36
36
|
end
|
37
37
|
|
38
38
|
def test_benchmark
|
39
39
|
Benchmark.bm(31) do |x|
|
40
|
-
|
40
|
+
|
41
41
|
n = 2500
|
42
42
|
# n = 1000
|
43
|
-
|
43
|
+
|
44
44
|
@m = MemCache.new(*@opts)
|
45
45
|
x.report("set:plain:memcache-client") do
|
46
46
|
n.times do
|
@@ -52,7 +52,7 @@ class TestBenchmark < Test::Unit::TestCase
|
|
52
52
|
@m.set @key3, @marshalled, 0, true
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
@m = MemCache.new(*@opts)
|
57
57
|
x.report("set:ruby:memcache-client") do
|
58
58
|
n.times do
|
@@ -64,7 +64,7 @@ class TestBenchmark < Test::Unit::TestCase
|
|
64
64
|
@m.set @key3, @value
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
@m = MemCache.new(*@opts)
|
69
69
|
x.report("get:plain:memcache-client") do
|
70
70
|
n.times do
|
@@ -76,7 +76,7 @@ class TestBenchmark < Test::Unit::TestCase
|
|
76
76
|
@m.get @key3, true
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
@m = MemCache.new(*@opts)
|
81
81
|
x.report("get:ruby:memcache-client") do
|
82
82
|
n.times do
|
@@ -96,7 +96,7 @@ class TestBenchmark < Test::Unit::TestCase
|
|
96
96
|
@m.get_multi @key1, @key2, @key3, @key4, @key5, @key6
|
97
97
|
end
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
@m = MemCache.new(*@opts)
|
101
101
|
x.report("missing:ruby:memcache-client") do
|
102
102
|
n.times do
|
@@ -108,7 +108,7 @@ class TestBenchmark < Test::Unit::TestCase
|
|
108
108
|
begin @m.get @key3; rescue; end
|
109
109
|
end
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
@m = MemCache.new(*@opts)
|
113
113
|
x.report("mixed:ruby:memcache-client") do
|
114
114
|
n.times do
|
data/test/test_mem_cache.rb
CHANGED
@@ -19,7 +19,7 @@ class MemCache
|
|
19
19
|
|
20
20
|
attr_writer :namespace
|
21
21
|
attr_writer :autofix_keys
|
22
|
-
|
22
|
+
|
23
23
|
end
|
24
24
|
|
25
25
|
class FakeSocket
|
@@ -54,11 +54,11 @@ class Test::Unit::TestCase
|
|
54
54
|
assert true
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
def memcached_running?
|
59
59
|
TCPSocket.new('localhost', 11211) rescue false
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
def xprofile(name, &block)
|
63
63
|
a = Time.now
|
64
64
|
block.call
|
@@ -76,7 +76,7 @@ class Test::Unit::TestCase
|
|
76
76
|
end
|
77
77
|
time
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
end
|
81
81
|
|
82
82
|
class FakeServer
|
@@ -168,7 +168,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
168
168
|
assert same_count > 700
|
169
169
|
end
|
170
170
|
end
|
171
|
-
|
171
|
+
|
172
172
|
def test_get_multi_with_server_failure
|
173
173
|
@cache = MemCache.new 'localhost:1', :namespace => 'my_namespace', :logger => nil #Logger.new(STDOUT)
|
174
174
|
s1 = FakeServer.new
|
@@ -211,11 +211,11 @@ class TestMemCache < Test::Unit::TestCase
|
|
211
211
|
assert s1.alive?
|
212
212
|
assert !s2.alive?
|
213
213
|
end
|
214
|
-
|
214
|
+
|
215
215
|
def test_cache_get_without_failover
|
216
216
|
s1 = FakeServer.new
|
217
217
|
s2 = FakeServer.new
|
218
|
-
|
218
|
+
|
219
219
|
s1.socket.data.write "VALUE foo 0 14\r\n\004\b\"\0170123456789\r\n"
|
220
220
|
s1.socket.data.rewind
|
221
221
|
s2.socket.data.write "bogus response\r\nbogus response\r\n"
|
@@ -336,7 +336,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
336
336
|
def test_multithread_error
|
337
337
|
server = FakeServer.new
|
338
338
|
server.multithread = false
|
339
|
-
|
339
|
+
|
340
340
|
@cache = MemCache.new(['localhost:1'], :multithread => false)
|
341
341
|
|
342
342
|
server.socket.data.write "bogus response\r\nbogus response\r\n"
|
@@ -489,7 +489,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
489
489
|
value = @cache.fetch('key', 1)
|
490
490
|
assert_equal nil, value
|
491
491
|
end
|
492
|
-
|
492
|
+
|
493
493
|
def test_fetch_miss
|
494
494
|
server = FakeServer.new
|
495
495
|
server.socket.data.write "END\r\n"
|
@@ -725,29 +725,37 @@ class TestMemCache < Test::Unit::TestCase
|
|
725
725
|
hash = Digest::SHA1.hexdigest(key)
|
726
726
|
@cache.namespace = nil
|
727
727
|
assert_equal key, @cache.make_cache_key(key)
|
728
|
+
end
|
728
729
|
|
730
|
+
def test_make_cache_key_with_autofix
|
729
731
|
@cache.autofix_keys = true
|
730
732
|
|
731
733
|
@cache.namespace = "my_namespace"
|
732
734
|
assert_equal 'my_namespace:key', @cache.make_cache_key('key')
|
733
735
|
@cache.namespace = nil
|
734
736
|
assert_equal 'key', @cache.make_cache_key('key')
|
735
|
-
|
737
|
+
|
736
738
|
key = "keys with more than two hundred and fifty characters can cause problems, because they get truncated and start colliding with each other. It's not a common occurrence, but when it happens is very hard to debug. the autofix option takes care of that for you"
|
737
739
|
hash = Digest::SHA1.hexdigest(key)
|
738
740
|
@cache.namespace = "my_namespace"
|
739
741
|
assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
|
740
742
|
@cache.namespace = nil
|
741
743
|
assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
|
742
|
-
|
744
|
+
|
743
745
|
key = "a short key with spaces"
|
744
746
|
hash = Digest::SHA1.hexdigest(key)
|
745
747
|
@cache.namespace = "my_namespace"
|
746
748
|
assert_equal "my_namespace:#{hash}-autofixed", @cache.make_cache_key(key)
|
747
749
|
@cache.namespace = nil
|
748
750
|
assert_equal "#{hash}-autofixed", @cache.make_cache_key(key)
|
751
|
+
|
752
|
+
# namespace + separator + key > 250
|
753
|
+
key = 'k' * 240
|
754
|
+
hash = Digest::SHA1.hexdigest(key)
|
755
|
+
@cache.namespace = 'n' * 10
|
756
|
+
assert_equal "#{@cache.namespace}:#{hash}-autofixed", @cache.make_cache_key(key)
|
749
757
|
end
|
750
|
-
|
758
|
+
|
751
759
|
def test_servers
|
752
760
|
server = FakeServer.new
|
753
761
|
@cache.servers = []
|
@@ -864,7 +872,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
864
872
|
@cache.servers << server
|
865
873
|
|
866
874
|
@cache.prepend 'key', 'value'
|
867
|
-
|
875
|
+
|
868
876
|
dumped = Marshal.dump('value')
|
869
877
|
|
870
878
|
expected = "prepend my_namespace:key 0 0 5\r\nvalue\r\n"
|
@@ -879,7 +887,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
879
887
|
@cache.servers << server
|
880
888
|
|
881
889
|
@cache.append 'key', 'value'
|
882
|
-
|
890
|
+
|
883
891
|
expected = "append my_namespace:key 0 0 5\r\nvalue\r\n"
|
884
892
|
assert_equal expected, server.socket.written.string
|
885
893
|
end
|
@@ -892,7 +900,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
892
900
|
@cache.servers << server
|
893
901
|
|
894
902
|
@cache.replace 'key', 'value', 150
|
895
|
-
|
903
|
+
|
896
904
|
dumped = Marshal.dump('value')
|
897
905
|
|
898
906
|
expected = "replace my_namespace:key 0 150 #{dumped.length}\r\n#{dumped}\r\n"
|
@@ -907,7 +915,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
907
915
|
@cache.servers << server
|
908
916
|
|
909
917
|
@cache.add 'key', 'value'
|
910
|
-
|
918
|
+
|
911
919
|
dumped = Marshal.dump('value')
|
912
920
|
|
913
921
|
expected = "add my_namespace:key 0 0 #{dumped.length}\r\n#{dumped}\r\n"
|
@@ -982,9 +990,9 @@ class TestMemCache < Test::Unit::TestCase
|
|
982
990
|
server = FakeServer.new
|
983
991
|
@cache.servers = []
|
984
992
|
@cache.servers << server
|
985
|
-
|
993
|
+
|
986
994
|
@cache.delete 'key'
|
987
|
-
|
995
|
+
|
988
996
|
expected = "delete my_namespace:key\r\n"
|
989
997
|
assert_equal expected, server.socket.written.string
|
990
998
|
end
|
@@ -993,9 +1001,9 @@ class TestMemCache < Test::Unit::TestCase
|
|
993
1001
|
server = FakeServer.new
|
994
1002
|
@cache.servers = []
|
995
1003
|
@cache.servers << server
|
996
|
-
|
1004
|
+
|
997
1005
|
@cache.delete 'key', 300
|
998
|
-
|
1006
|
+
|
999
1007
|
expected = "delete my_namespace:key\r\n"
|
1000
1008
|
assert_equal expected, server.socket.written.string
|
1001
1009
|
end
|
@@ -1042,7 +1050,7 @@ class TestMemCache < Test::Unit::TestCase
|
|
1042
1050
|
|
1043
1051
|
assert_match(/flush_all\r\n/, socket.written.string)
|
1044
1052
|
end
|
1045
|
-
|
1053
|
+
|
1046
1054
|
def test_flush_all_for_real
|
1047
1055
|
requirement(memcached_running?, 'A real memcached server must be running for testing flush_all') do
|
1048
1056
|
cache = MemCache.new "localhost:11211", :namespace => "test_flush_all"
|