memcached 0.10 → 0.11
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +4 -2
- data/COMPATIBILITY +1 -0
- data/Manifest +1 -1
- data/README +4 -4
- data/Rakefile +30 -0
- data/TODO +3 -3
- data/ext/rlibmemcached.i +20 -37
- data/ext/rlibmemcached_wrap.c +815 -799
- data/lib/memcached.rb +4 -0
- data/lib/memcached/behaviors.rb +8 -7
- data/lib/memcached/memcached.rb +53 -76
- data/lib/memcached/rails.rb +1 -1
- data/memcached.gemspec +103 -56
- data/test/profile/benchmark.rb +1 -1
- data/test/profile/profile.rb +1 -1
- data/test/profile/valgrind.rb +1 -1
- data/test/unit/memcached_test.rb +136 -121
- data/test/unit/rails_test.rb +1 -1
- metadata +17 -8
- metadata.gz.sig +0 -0
- data/test/profile/key.rb +0 -41
data/test/profile/benchmark.rb
CHANGED
data/test/profile/profile.rb
CHANGED
data/test/profile/valgrind.rb
CHANGED
data/test/unit/memcached_test.rb
CHANGED
@@ -4,18 +4,20 @@ require "#{File.dirname(__FILE__)}/../test_helper"
|
|
4
4
|
class MemcachedTest < Test::Unit::TestCase
|
5
5
|
|
6
6
|
def setup
|
7
|
-
@servers = ['
|
8
|
-
|
7
|
+
@servers = ['localhost:43042', 'localhost:43043']
|
8
|
+
|
9
|
+
# Maximum allowed prefix key size
|
10
|
+
@prefix_key = 'prefix_key_'
|
9
11
|
|
10
12
|
@options = {
|
11
|
-
:
|
13
|
+
:prefix_key => @prefix_key,
|
12
14
|
:hash => :default,
|
13
15
|
:distribution => :modula
|
14
16
|
}
|
15
17
|
@cache = Memcached.new(@servers, @options)
|
16
18
|
|
17
19
|
@nb_options = {
|
18
|
-
:
|
20
|
+
:prefix_key => @prefix_key,
|
19
21
|
:no_block => true,
|
20
22
|
:buffer_requests => true,
|
21
23
|
:hash => :default
|
@@ -25,24 +27,30 @@ class MemcachedTest < Test::Unit::TestCase
|
|
25
27
|
@value = OpenStruct.new(:a => 1, :b => 2, :c => GenericClass)
|
26
28
|
@marshalled_value = Marshal.dump(@value)
|
27
29
|
end
|
28
|
-
|
29
|
-
def teardown
|
30
|
-
ObjectSpace.each_object(Memcached) do |cache|
|
31
|
-
cache.destroy rescue Memcached::ClientError
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
30
|
+
|
35
31
|
# Initialize
|
36
32
|
|
37
33
|
def test_initialize
|
38
|
-
cache = Memcached.new @servers, :
|
39
|
-
assert_equal 'test', cache.options[:
|
34
|
+
cache = Memcached.new @servers, :prefix_key => 'test'
|
35
|
+
assert_equal 'test', cache.options[:prefix_key]
|
40
36
|
assert_equal 2, cache.send(:server_structs).size
|
37
|
+
assert_equal 'localhost', cache.send(:server_structs).first.hostname
|
38
|
+
assert_equal 'localhost', cache.send(:server_structs).last.hostname
|
39
|
+
assert_equal 43043, cache.send(:server_structs).last.port
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_initialize_with_ip_addresses
|
43
|
+
cache = Memcached.new ['127.0.0.1:43042', '127.0.0.1:43043'], :prefix_key => 'test'
|
41
44
|
assert_equal '127.0.0.1', cache.send(:server_structs).first.hostname
|
42
45
|
assert_equal '127.0.0.1', cache.send(:server_structs).last.hostname
|
43
|
-
assert_equal 43043, cache.send(:server_structs).last.port
|
44
46
|
end
|
45
47
|
|
48
|
+
def test_initialize_without_port
|
49
|
+
cache = Memcached.new ['localhost'], :prefix_key => 'test'
|
50
|
+
assert_equal 'localhost', cache.send(:server_structs).first.hostname
|
51
|
+
assert_equal 11211, cache.send(:server_structs).first.port
|
52
|
+
end
|
53
|
+
|
46
54
|
def test_options_are_set
|
47
55
|
Memcached::DEFAULTS.merge(@nb_options).each do |key, expected|
|
48
56
|
value = @nb_cache.options[key]
|
@@ -55,19 +63,29 @@ class MemcachedTest < Test::Unit::TestCase
|
|
55
63
|
@cache.options[:no_block] = true
|
56
64
|
end
|
57
65
|
end
|
58
|
-
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
assert_raise(Memcached::ClientError) do
|
63
|
-
cache.get key
|
66
|
+
|
67
|
+
def test_behaviors_are_set
|
68
|
+
Memcached::BEHAVIORS.keys.each do |key, value|
|
69
|
+
assert_not_nil @cache.send(:get_behavior, key)
|
64
70
|
end
|
65
71
|
end
|
66
|
-
|
72
|
+
|
67
73
|
def test_initialize_with_invalid_server_strings
|
68
|
-
assert_raise(ArgumentError) { Memcached.new "
|
69
|
-
assert_raise(ArgumentError) { Memcached.new "
|
70
|
-
assert_raise(ArgumentError) { Memcached.new "
|
74
|
+
assert_raise(ArgumentError) { Memcached.new ":43042" }
|
75
|
+
assert_raise(ArgumentError) { Memcached.new "localhost:memcached" }
|
76
|
+
assert_raise(ArgumentError) { Memcached.new "local host:43043:1" }
|
77
|
+
end
|
78
|
+
|
79
|
+
if ENV['USER'] == "eweaver"
|
80
|
+
def test_initialize_with_resolvable_hosts
|
81
|
+
`hostname` =~ /(chloe|mackenzie)/
|
82
|
+
host = "#{$1}.lan"
|
83
|
+
cache = Memcached.new ["#{host}:43042"]
|
84
|
+
assert_equal host, cache.send(:server_structs).first.hostname
|
85
|
+
|
86
|
+
cache.set(key, @value)
|
87
|
+
assert_equal @value, cache.get(key)
|
88
|
+
end
|
71
89
|
end
|
72
90
|
|
73
91
|
def test_initialize_with_invalid_options
|
@@ -75,10 +93,16 @@ class MemcachedTest < Test::Unit::TestCase
|
|
75
93
|
Memcached.new @servers, :sort_hosts => true, :distribution => :consistent
|
76
94
|
end
|
77
95
|
end
|
96
|
+
|
97
|
+
def test_initialize_with_invalid_prefix_key
|
98
|
+
assert_raise(ArgumentError) do
|
99
|
+
Memcached.new @servers, :prefix_key => "prefix_key__"
|
100
|
+
end
|
101
|
+
end
|
78
102
|
|
79
|
-
def
|
103
|
+
def test_initialize_without_prefix_key
|
80
104
|
cache = Memcached.new @servers
|
81
|
-
assert_equal nil, cache.options[:
|
105
|
+
assert_equal nil, cache.options[:prefix_key]
|
82
106
|
assert_equal 2, cache.send(:server_structs).size
|
83
107
|
end
|
84
108
|
|
@@ -120,7 +144,6 @@ class MemcachedTest < Test::Unit::TestCase
|
|
120
144
|
)
|
121
145
|
assert_equal @servers.sort,
|
122
146
|
cache.servers
|
123
|
-
cache.destroy
|
124
147
|
|
125
148
|
# Original with sort_hosts
|
126
149
|
cache = Memcached.new(@servers.sort,
|
@@ -129,7 +152,6 @@ class MemcachedTest < Test::Unit::TestCase
|
|
129
152
|
)
|
130
153
|
assert_equal @servers.sort,
|
131
154
|
cache.servers
|
132
|
-
cache.destroy
|
133
155
|
|
134
156
|
# Reversed
|
135
157
|
cache = Memcached.new(@servers.sort.reverse,
|
@@ -138,7 +160,6 @@ class MemcachedTest < Test::Unit::TestCase
|
|
138
160
|
)
|
139
161
|
assert_equal @servers.sort.reverse,
|
140
162
|
cache.servers
|
141
|
-
cache.destroy
|
142
163
|
|
143
164
|
# Reversed with sort_hosts
|
144
165
|
cache = Memcached.new(@servers.sort.reverse,
|
@@ -147,12 +168,11 @@ class MemcachedTest < Test::Unit::TestCase
|
|
147
168
|
)
|
148
169
|
assert_equal @servers.sort,
|
149
170
|
cache.servers
|
150
|
-
cache.destroy
|
151
171
|
end
|
152
172
|
|
153
173
|
def test_initialize_single_server
|
154
|
-
cache = Memcached.new '
|
155
|
-
assert_equal nil, cache.options[:
|
174
|
+
cache = Memcached.new 'localhost:43042'
|
175
|
+
assert_equal nil, cache.options[:prefix_key]
|
156
176
|
assert_equal 1, cache.send(:server_structs).size
|
157
177
|
end
|
158
178
|
|
@@ -167,16 +187,6 @@ class MemcachedTest < Test::Unit::TestCase
|
|
167
187
|
result = @cache.get key
|
168
188
|
assert_equal @value, result
|
169
189
|
end
|
170
|
-
|
171
|
-
def test_get_with_namespace
|
172
|
-
@cache.set key, @value
|
173
|
-
result = @cache.get key, false
|
174
|
-
direct_result = Rlibmemcached.memcached_get(
|
175
|
-
@cache.instance_variable_get("@struct"),
|
176
|
-
"#{@namespace}#{key}"
|
177
|
-
).first
|
178
|
-
assert_equal result, direct_result
|
179
|
-
end
|
180
190
|
|
181
191
|
def test_get_nil
|
182
192
|
@cache.set key, nil, 0
|
@@ -190,6 +200,29 @@ class MemcachedTest < Test::Unit::TestCase
|
|
190
200
|
result = @cache.get key
|
191
201
|
end
|
192
202
|
end
|
203
|
+
|
204
|
+
def test_get_with_prefix_key
|
205
|
+
# Prefix_key
|
206
|
+
cache = Memcached.new(
|
207
|
+
# We can only use one server because the key is hashed separately from the prefix key
|
208
|
+
@servers.first,
|
209
|
+
:prefix_key => @prefix_key,
|
210
|
+
:hash => :default,
|
211
|
+
:distribution => :modula
|
212
|
+
)
|
213
|
+
cache.set key, @value
|
214
|
+
assert_equal @value, cache.get(key)
|
215
|
+
|
216
|
+
# No prefix_key specified
|
217
|
+
cache = Memcached.new(
|
218
|
+
@servers.first,
|
219
|
+
:hash => :default,
|
220
|
+
:distribution => :modula
|
221
|
+
)
|
222
|
+
assert_nothing_raised do
|
223
|
+
assert_equal @value, cache.get("#{@prefix_key}#{key}")
|
224
|
+
end
|
225
|
+
end
|
193
226
|
|
194
227
|
def test_values_with_null_characters_are_not_truncated
|
195
228
|
value = OpenStruct.new(:a => Object.new) # Marshals with a null \000
|
@@ -197,7 +230,7 @@ class MemcachedTest < Test::Unit::TestCase
|
|
197
230
|
result = @cache.get key, false
|
198
231
|
non_wrapped_result = Rlibmemcached.memcached_get(
|
199
232
|
@cache.instance_variable_get("@struct"),
|
200
|
-
|
233
|
+
key
|
201
234
|
).first
|
202
235
|
assert result.size > non_wrapped_result.size
|
203
236
|
end
|
@@ -268,7 +301,7 @@ class MemcachedTest < Test::Unit::TestCase
|
|
268
301
|
assert_nothing_raised do
|
269
302
|
@cache.get key
|
270
303
|
end
|
271
|
-
sleep(
|
304
|
+
sleep(2)
|
272
305
|
assert_raise(Memcached::NotFound) do
|
273
306
|
@cache.get key
|
274
307
|
end
|
@@ -434,7 +467,7 @@ class MemcachedTest < Test::Unit::TestCase
|
|
434
467
|
def test_cas
|
435
468
|
cache = Memcached.new(
|
436
469
|
@servers,
|
437
|
-
:
|
470
|
+
:prefix_key => @prefix_key,
|
438
471
|
:support_cas => true
|
439
472
|
)
|
440
473
|
value2 = OpenStruct.new(:d => 3, :e => 4, :f => GenericClass)
|
@@ -468,81 +501,60 @@ class MemcachedTest < Test::Unit::TestCase
|
|
468
501
|
current
|
469
502
|
end
|
470
503
|
end
|
471
|
-
|
472
|
-
cache.destroy
|
473
504
|
end
|
474
|
-
|
475
|
-
# Namespace and key validation
|
476
|
-
|
477
|
-
def test_ns
|
478
|
-
assert_equal "#{@namespace}i_have_a_space",
|
479
|
-
Rlibmemcached.ns(@namespace, "i have a space")
|
480
|
-
|
481
|
-
# STR2CSTR doesn't handle strings with nulls very well, so this is what happens
|
482
|
-
assert_equal "#{@namespace}with_____",
|
483
|
-
Rlibmemcached.ns(@namespace, "with\000null")
|
484
|
-
|
485
|
-
assert_equal "#{@namespace}ch__teau",
|
486
|
-
Rlibmemcached.ns(@namespace, "ch\303\242teau")
|
487
|
-
|
488
|
-
assert_equal "#{@namespace}#{'x'*251}"[0..249],
|
489
|
-
Rlibmemcached.ns(@namespace, 'x'*251)
|
490
|
-
end
|
491
|
-
|
505
|
+
|
492
506
|
# Error states
|
493
507
|
|
494
508
|
def test_key_with_spaces
|
495
|
-
value = "value"
|
496
509
|
key = "i have a space"
|
497
|
-
|
498
|
-
@cache.set key, value
|
510
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
511
|
+
@cache.set key, @value
|
499
512
|
end
|
500
|
-
|
501
|
-
|
513
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
514
|
+
@cache.get(key)
|
502
515
|
end
|
503
|
-
# Spaces were stripped
|
504
|
-
assert_not_equal(key,
|
505
|
-
@cache.get([key]).keys.first)
|
506
516
|
end
|
507
517
|
|
508
518
|
def test_key_with_null
|
509
|
-
value = "value"
|
510
519
|
key = "with\000null"
|
511
|
-
|
512
|
-
@cache.set key, value
|
520
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
521
|
+
@cache.set key, @value
|
513
522
|
end
|
514
|
-
|
515
|
-
|
523
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
524
|
+
@cache.get(key)
|
525
|
+
end
|
526
|
+
|
527
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
528
|
+
response = @cache.get([key])
|
516
529
|
end
|
517
|
-
# Multiget returns
|
518
|
-
response = @cache.get([key])
|
519
|
-
assert_equal 1, response.size
|
520
|
-
# Nulls were stripped
|
521
|
-
assert_not_equal(key, response.keys.first)
|
522
530
|
end
|
523
531
|
|
524
|
-
def
|
525
|
-
value = "value"
|
532
|
+
def test_key_with_invalid_control_characters
|
526
533
|
key = "ch\303\242teau"
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
@cache.get(
|
534
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
535
|
+
@cache.set key, @value
|
536
|
+
end
|
537
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
538
|
+
@cache.get(key)
|
539
|
+
end
|
540
|
+
|
541
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
542
|
+
response = @cache.get([key])
|
543
|
+
end
|
532
544
|
end
|
533
545
|
|
534
546
|
def test_key_too_long
|
535
547
|
key = "x"*251
|
536
|
-
|
548
|
+
assert_raises(Memcached::ClientError) do
|
537
549
|
@cache.set key, @value
|
538
550
|
end
|
539
|
-
|
540
|
-
|
541
|
-
|
551
|
+
assert_raises(Memcached::ClientError) do
|
552
|
+
@cache.get(key)
|
553
|
+
end
|
554
|
+
|
555
|
+
assert_raises(Memcached::ClientError) do
|
556
|
+
@cache.get([key])
|
542
557
|
end
|
543
|
-
# Key was truncated
|
544
|
-
assert_not_equal(key,
|
545
|
-
@cache.get([key]).keys.first)
|
546
558
|
end
|
547
559
|
|
548
560
|
def test_set_object_too_large
|
@@ -568,7 +580,9 @@ class MemcachedTest < Test::Unit::TestCase
|
|
568
580
|
assert_not_equal cache, @cache
|
569
581
|
|
570
582
|
# Definitely check that the structs are unlinked
|
571
|
-
cache.
|
583
|
+
assert_not_equal @cache.instance_variable_get('@struct').object_id,
|
584
|
+
cache.instance_variable_get('@struct').object_id
|
585
|
+
|
572
586
|
assert_nothing_raised do
|
573
587
|
@cache.set key, @value
|
574
588
|
end
|
@@ -584,7 +598,7 @@ class MemcachedTest < Test::Unit::TestCase
|
|
584
598
|
end
|
585
599
|
ret = Rlibmemcached.memcached_set(
|
586
600
|
cache.instance_variable_get("@struct"),
|
587
|
-
|
601
|
+
key,
|
588
602
|
@marshalled_value,
|
589
603
|
0,
|
590
604
|
Memcached::FLAGS
|
@@ -598,7 +612,7 @@ class MemcachedTest < Test::Unit::TestCase
|
|
598
612
|
end
|
599
613
|
ret = Rlibmemcached.memcached_set(
|
600
614
|
@nb_cache.instance_variable_get("@struct"),
|
601
|
-
|
615
|
+
key,
|
602
616
|
@marshalled_value,
|
603
617
|
0,
|
604
618
|
Memcached::FLAGS
|
@@ -614,7 +628,7 @@ class MemcachedTest < Test::Unit::TestCase
|
|
614
628
|
end
|
615
629
|
|
616
630
|
def test_no_block_set_invalid_key
|
617
|
-
|
631
|
+
assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
|
618
632
|
@nb_cache.set "I'm so bad", @value
|
619
633
|
end
|
620
634
|
end
|
@@ -636,40 +650,47 @@ class MemcachedTest < Test::Unit::TestCase
|
|
636
650
|
# Server removal and consistent hashing
|
637
651
|
|
638
652
|
def test_missing_server
|
639
|
-
# XXX Does this test actually do anything? :hash behaves oddly
|
640
653
|
cache = Memcached.new(
|
641
|
-
[@servers.last, '
|
642
|
-
:
|
654
|
+
[@servers.last, 'localhost:43041'], # Use a server that isn't running
|
655
|
+
:prefix_key => @prefix_key,
|
643
656
|
:failover => true,
|
644
657
|
:hash => :md5
|
645
658
|
)
|
646
659
|
|
647
|
-
#
|
660
|
+
# Hit first server
|
648
661
|
key = 'test_missing_server3'
|
649
|
-
|
650
|
-
|
662
|
+
cache.set(key, @value)
|
663
|
+
cache.get(key) == @value
|
664
|
+
|
665
|
+
# Hit second server
|
666
|
+
key = 'test_missing_server'
|
651
667
|
assert_raise(Memcached::SystemError) do
|
652
668
|
cache.set(key, @value)
|
653
669
|
cache.get(key)
|
654
670
|
end
|
655
671
|
|
656
|
-
#
|
657
|
-
assert_equal 0, cache.send(:hash, key)
|
658
|
-
|
672
|
+
# Hit first server on retry
|
659
673
|
assert_nothing_raised do
|
660
674
|
cache.set(key, @value)
|
661
675
|
cache.get(key)
|
662
676
|
end
|
663
677
|
end
|
664
678
|
|
679
|
+
def test_sweep_servers_with_missing_server_first
|
680
|
+
cache = Memcached.new(['127.0.0.1:00000'] + @servers)
|
681
|
+
assert_nothing_raised do
|
682
|
+
cache.send(:sweep_servers)
|
683
|
+
end
|
684
|
+
end
|
685
|
+
|
665
686
|
def test_consistent_hashing
|
666
687
|
|
667
688
|
keys = %w(EN6qtgMW n6Oz2W4I ss4A8Brr QShqFLZt Y3hgP9bs CokDD4OD Nd3iTSE1 24vBV4AU H9XBUQs5 E5j8vUq1 AzSh8fva PYBlK2Pi Ke3TgZ4I AyAIYanO oxj8Xhyd eBFnE6Bt yZyTikWQ pwGoU7Pw 2UNDkKRN qMJzkgo2 keFXbQXq pBl2QnIg ApRl3mWY wmalTJW1 TLueug8M wPQL4Qfg uACwus23 nmOk9R6w lwgZJrzJ v1UJtKdG RK629Cra U2UXFRqr d9OQLNl8 KAm1K3m5 Z13gKZ1v tNVai1nT LhpVXuVx pRib1Itj I1oLUob7 Z1nUsd5Q ZOwHehUa aXpFX29U ZsnqxlGz ivQRjOdb mB3iBEAj)
|
668
689
|
|
669
690
|
# Five servers
|
670
691
|
cache = Memcached.new(
|
671
|
-
@servers + ['
|
672
|
-
:
|
692
|
+
@servers + ['localhost:43044', 'localhost:43045', 'localhost:43046'],
|
693
|
+
:prefix_key => @prefix_key
|
673
694
|
)
|
674
695
|
|
675
696
|
cache.flush
|
@@ -679,8 +700,8 @@ class MemcachedTest < Test::Unit::TestCase
|
|
679
700
|
|
680
701
|
# Pull a server
|
681
702
|
cache = Memcached.new(
|
682
|
-
@servers + ['
|
683
|
-
:
|
703
|
+
@servers + ['localhost:43044', 'localhost:43046'],
|
704
|
+
:prefix_key => @prefix_key
|
684
705
|
)
|
685
706
|
|
686
707
|
failed = 0
|
@@ -721,13 +742,7 @@ class MemcachedTest < Test::Unit::TestCase
|
|
721
742
|
assert_not_equal original_struct,
|
722
743
|
@cache.instance_variable_get("@struct")
|
723
744
|
end
|
724
|
-
|
725
|
-
# Private hash generation method
|
726
|
-
|
727
|
-
def test_hash_generation
|
728
|
-
assert [0, 1].include?(@cache.send(:hash, key))
|
729
|
-
end
|
730
|
-
|
745
|
+
|
731
746
|
private
|
732
747
|
|
733
748
|
def key
|