mperham-memcache-client 1.6.3 → 1.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -2
- data/lib/memcache.rb +56 -3
- data/test/test_mem_cache.rb +26 -0
- metadata +4 -15
- data/lib/continuum.rb +0 -77
- data/lib/memcache_util.rb +0 -102
data/History.txt
CHANGED
@@ -1,7 +1,18 @@
|
|
1
|
-
= 1.6.
|
1
|
+
= 1.6.4 (2009-02-19)
|
2
|
+
|
3
|
+
* Remove native code altogether. The speedup was only 10% on Ruby 1.8.6 and did not work
|
4
|
+
on Ruby 1.9.1.
|
5
|
+
|
6
|
+
* Removed memcache_util.rb from the distribution. If you are using it, please copy the code
|
7
|
+
into your own project. The file will live in the github repository for a few more months
|
8
|
+
for this purposes. http://github.com/mperham/memcache-client/raw/7a276089aa3c914e47e3960f9740ac7377204970/lib/memcache_util.rb
|
9
|
+
|
10
|
+
* Roll continuum.rb into memcache.rb. The project is again a single Ruby file, with no dependencies.
|
11
|
+
|
12
|
+
= 1.6.3 (2009-02-14)
|
2
13
|
|
3
14
|
* Remove gem native extension in preference to RubyInline. This allows the gem to install
|
4
|
-
and work on JRuby.
|
15
|
+
and work on JRuby and Ruby 1.8.5 when the native code fails to compile.
|
5
16
|
|
6
17
|
= 1.6.2 (2009-02-04)
|
7
18
|
|
data/lib/memcache.rb
CHANGED
@@ -6,8 +6,6 @@ require 'timeout'
|
|
6
6
|
require 'zlib'
|
7
7
|
require 'digest/sha1'
|
8
8
|
|
9
|
-
require 'continuum'
|
10
|
-
|
11
9
|
##
|
12
10
|
# A Ruby client library for memcached.
|
13
11
|
#
|
@@ -17,7 +15,7 @@ class MemCache
|
|
17
15
|
##
|
18
16
|
# The version of MemCache you are using.
|
19
17
|
|
20
|
-
VERSION = '1.6.
|
18
|
+
VERSION = '1.6.4'
|
21
19
|
|
22
20
|
##
|
23
21
|
# Default options for the cache object.
|
@@ -120,6 +118,8 @@ class MemCache
|
|
120
118
|
|
121
119
|
logger.info { "memcache-client #{VERSION} #{Array(servers).inspect}" } if logger
|
122
120
|
|
121
|
+
Thread.current[:memcache_client] = self.object_id if !@multithread
|
122
|
+
|
123
123
|
self.servers = servers
|
124
124
|
end
|
125
125
|
|
@@ -606,6 +606,8 @@ class MemCache
|
|
606
606
|
# failures (but does still apply to unexpectedly lost connections etc.).
|
607
607
|
|
608
608
|
def with_socket_management(server, &block)
|
609
|
+
check_multithread_status!
|
610
|
+
|
609
611
|
@mutex.lock if @multithread
|
610
612
|
retried = false
|
611
613
|
|
@@ -697,6 +699,18 @@ class MemCache
|
|
697
699
|
((total_servers * Continuum::POINTS_PER_SERVER * server.weight) / Float(total_weight)).floor
|
698
700
|
end
|
699
701
|
|
702
|
+
def check_multithread_status!
|
703
|
+
return if @multithread
|
704
|
+
|
705
|
+
if Thread.current[:memcache_client] != self.object_id
|
706
|
+
raise MemCacheError, <<-EOM
|
707
|
+
You are accessing this memcache-client instance from multiple threads but have not enabled multithread support.
|
708
|
+
Normally: MemCache.new(['localhost:11211'], :multithread => true)
|
709
|
+
In Rails: config.cache_store = [:mem_cache_store, 'localhost:11211', { :multithread => true }]
|
710
|
+
EOM
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
700
714
|
##
|
701
715
|
# This class represents a memcached server instance.
|
702
716
|
|
@@ -894,3 +908,42 @@ class TCPTimeoutSocket
|
|
894
908
|
@sock.close
|
895
909
|
end
|
896
910
|
end
|
911
|
+
|
912
|
+
module Continuum
|
913
|
+
POINTS_PER_SERVER = 160 # this is the default in libmemcached
|
914
|
+
|
915
|
+
# Find the closest index in Continuum with value <= the given value
|
916
|
+
def self.binary_search(ary, value, &block)
|
917
|
+
upper = ary.size - 1
|
918
|
+
lower = 0
|
919
|
+
idx = 0
|
920
|
+
|
921
|
+
while(lower <= upper) do
|
922
|
+
idx = (lower + upper) / 2
|
923
|
+
comp = ary[idx].value <=> value
|
924
|
+
|
925
|
+
if comp == 0
|
926
|
+
return idx
|
927
|
+
elsif comp > 0
|
928
|
+
upper = idx - 1
|
929
|
+
else
|
930
|
+
lower = idx + 1
|
931
|
+
end
|
932
|
+
end
|
933
|
+
return upper
|
934
|
+
end
|
935
|
+
|
936
|
+
class Entry
|
937
|
+
attr_reader :value
|
938
|
+
attr_reader :server
|
939
|
+
|
940
|
+
def initialize(val, srv)
|
941
|
+
@value = val
|
942
|
+
@server = srv
|
943
|
+
end
|
944
|
+
|
945
|
+
def inspect
|
946
|
+
"<#{value}, #{server.host}:#{server.port}>"
|
947
|
+
end
|
948
|
+
end
|
949
|
+
end
|
data/test/test_mem_cache.rb
CHANGED
@@ -333,6 +333,32 @@ class TestMemCache < Test::Unit::TestCase
|
|
333
333
|
assert !server.alive?
|
334
334
|
end
|
335
335
|
|
336
|
+
def test_multithread_error
|
337
|
+
server = FakeServer.new
|
338
|
+
|
339
|
+
# Write two messages to the socket to test failover
|
340
|
+
server.socket.data.write "bogus response\r\nbogus response\r\n"
|
341
|
+
server.socket.data.rewind
|
342
|
+
|
343
|
+
@cache.servers = []
|
344
|
+
@cache.servers << server
|
345
|
+
|
346
|
+
assert_nothing_raised do
|
347
|
+
@cache.set 'a', 1
|
348
|
+
end
|
349
|
+
|
350
|
+
passed = true
|
351
|
+
Thread.new do
|
352
|
+
begin
|
353
|
+
@cache.set 'b', 2
|
354
|
+
passed = false
|
355
|
+
rescue MemCache::MemCacheError => me
|
356
|
+
passed = me.message =~ /multiple threads/
|
357
|
+
end
|
358
|
+
end
|
359
|
+
assert passed
|
360
|
+
end
|
361
|
+
|
336
362
|
def test_initialize
|
337
363
|
cache = MemCache.new :namespace => 'my_namespace', :readonly => true
|
338
364
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mperham-memcache-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Hodel
|
@@ -11,19 +11,10 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2009-02-
|
14
|
+
date: 2009-02-13 00:00:00 -08:00
|
15
15
|
default_executable:
|
16
|
-
dependencies:
|
17
|
-
|
18
|
-
name:
|
19
|
-
- RubyInline
|
20
|
-
version_requirement:
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
-
requirements:
|
23
|
-
- - ">="
|
24
|
-
- !ruby/object:Gem::Version
|
25
|
-
version: "0"
|
26
|
-
version:
|
16
|
+
dependencies: []
|
17
|
+
|
27
18
|
description: A Ruby library for accessing memcached.
|
28
19
|
email: mperham@gmail.com
|
29
20
|
executables: []
|
@@ -37,9 +28,7 @@ files:
|
|
37
28
|
- LICENSE.txt
|
38
29
|
- History.txt
|
39
30
|
- Rakefile
|
40
|
-
- lib/continuum.rb
|
41
31
|
- lib/memcache.rb
|
42
|
-
- lib/memcache_util.rb
|
43
32
|
has_rdoc: false
|
44
33
|
homepage: http://github.com/mperham/memcache-client
|
45
34
|
post_install_message:
|
data/lib/continuum.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module Continuum
|
2
|
-
POINTS_PER_SERVER = 160 # this is the default in libmemcached
|
3
|
-
|
4
|
-
class << self
|
5
|
-
|
6
|
-
begin
|
7
|
-
require 'inline'
|
8
|
-
inline do |builder|
|
9
|
-
builder.c <<-EOM
|
10
|
-
int binary_search(VALUE ary, unsigned int r) {
|
11
|
-
int upper = RARRAY_LEN(ary) - 1;
|
12
|
-
int lower = 0;
|
13
|
-
int idx = 0;
|
14
|
-
ID value = rb_intern("value");
|
15
|
-
|
16
|
-
while (lower <= upper) {
|
17
|
-
idx = (lower + upper) / 2;
|
18
|
-
|
19
|
-
VALUE continuumValue = rb_funcall(RARRAY_PTR(ary)[idx], value, 0);
|
20
|
-
unsigned int l = NUM2UINT(continuumValue);
|
21
|
-
if (l == r) {
|
22
|
-
return idx;
|
23
|
-
}
|
24
|
-
else if (l > r) {
|
25
|
-
upper = idx - 1;
|
26
|
-
}
|
27
|
-
else {
|
28
|
-
lower = idx + 1;
|
29
|
-
}
|
30
|
-
}
|
31
|
-
return upper;
|
32
|
-
}
|
33
|
-
EOM
|
34
|
-
end
|
35
|
-
rescue Exception => e
|
36
|
-
puts "Unable to generate native code, falling back to Ruby: #{e.message}"
|
37
|
-
|
38
|
-
# slow but pure ruby version
|
39
|
-
# Find the closest index in Continuum with value <= the given value
|
40
|
-
def binary_search(ary, value, &block)
|
41
|
-
upper = ary.size - 1
|
42
|
-
lower = 0
|
43
|
-
idx = 0
|
44
|
-
|
45
|
-
while(lower <= upper) do
|
46
|
-
idx = (lower + upper) / 2
|
47
|
-
comp = ary[idx].value <=> value
|
48
|
-
|
49
|
-
if comp == 0
|
50
|
-
return idx
|
51
|
-
elsif comp > 0
|
52
|
-
upper = idx - 1
|
53
|
-
else
|
54
|
-
lower = idx + 1
|
55
|
-
end
|
56
|
-
end
|
57
|
-
return upper
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
class Entry
|
65
|
-
attr_reader :value
|
66
|
-
attr_reader :server
|
67
|
-
|
68
|
-
def initialize(val, srv)
|
69
|
-
@value = val
|
70
|
-
@server = srv
|
71
|
-
end
|
72
|
-
|
73
|
-
def inspect
|
74
|
-
"<#{value}, #{server.host}:#{server.port}>"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/lib/memcache_util.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# A utility wrapper around the MemCache client to simplify cache access. All
|
3
|
-
# methods silently ignore MemCache errors.
|
4
|
-
|
5
|
-
module Cache
|
6
|
-
|
7
|
-
##
|
8
|
-
# Try to return a logger object that does not rely
|
9
|
-
# on ActiveRecord for logging.
|
10
|
-
def self.logger
|
11
|
-
@logger ||= if defined? Rails.logger # Rails 2.1 +
|
12
|
-
Rails.logger
|
13
|
-
elsif defined? RAILS_DEFAULT_LOGGER # Rails 1.2.2 +
|
14
|
-
RAILS_DEFAULT_LOGGER
|
15
|
-
else
|
16
|
-
ActiveRecord::Base.logger # ... very old Rails.
|
17
|
-
end
|
18
|
-
end
|
19
|
-
##
|
20
|
-
# Returns the object at +key+ from the cache if successful, or nil if either
|
21
|
-
# the object is not in the cache or if there was an error attermpting to
|
22
|
-
# access the cache.
|
23
|
-
#
|
24
|
-
# If there is a cache miss and a block is given the result of the block will
|
25
|
-
# be stored in the cache with optional +expiry+, using the +add+ method rather
|
26
|
-
# than +set+.
|
27
|
-
|
28
|
-
def self.get(key, expiry = 0)
|
29
|
-
start_time = Time.now
|
30
|
-
value = CACHE.get key
|
31
|
-
elapsed = Time.now - start_time
|
32
|
-
logger.debug('MemCache Get (%0.6f) %s' % [elapsed, key])
|
33
|
-
if value.nil? and block_given? then
|
34
|
-
value = yield
|
35
|
-
add key, value, expiry
|
36
|
-
end
|
37
|
-
value
|
38
|
-
rescue MemCache::MemCacheError => err
|
39
|
-
logger.debug "MemCache Error: #{err.message}"
|
40
|
-
if block_given? then
|
41
|
-
value = yield
|
42
|
-
put key, value, expiry
|
43
|
-
end
|
44
|
-
value
|
45
|
-
end
|
46
|
-
|
47
|
-
##
|
48
|
-
# Sets +value+ in the cache at +key+, with an optional +expiry+ time in
|
49
|
-
# seconds.
|
50
|
-
|
51
|
-
def self.put(key, value, expiry = 0)
|
52
|
-
start_time = Time.now
|
53
|
-
CACHE.set key, value, expiry
|
54
|
-
elapsed = Time.now - start_time
|
55
|
-
logger.debug('MemCache Set (%0.6f) %s' % [elapsed, key])
|
56
|
-
value
|
57
|
-
rescue MemCache::MemCacheError => err
|
58
|
-
ActiveRecord::Base.logger.debug "MemCache Error: #{err.message}"
|
59
|
-
nil
|
60
|
-
end
|
61
|
-
|
62
|
-
##
|
63
|
-
# Sets +value+ in the cache at +key+, with an optional +expiry+ time in
|
64
|
-
# seconds. If +key+ already exists in cache, returns nil.
|
65
|
-
|
66
|
-
def self.add(key, value, expiry = 0)
|
67
|
-
start_time = Time.now
|
68
|
-
response = CACHE.add key, value, expiry
|
69
|
-
elapsed = Time.now - start_time
|
70
|
-
logger.debug('MemCache Add (%0.6f) %s' % [elapsed, key])
|
71
|
-
(response == "STORED\r\n") ? value : nil
|
72
|
-
rescue MemCache::MemCacheError => err
|
73
|
-
ActiveRecord::Base.logger.debug "MemCache Error: #{err.message}"
|
74
|
-
nil
|
75
|
-
end
|
76
|
-
|
77
|
-
##
|
78
|
-
# Deletes +key+ from the cache in +delay+ seconds.
|
79
|
-
|
80
|
-
def self.delete(key, delay = nil)
|
81
|
-
start_time = Time.now
|
82
|
-
CACHE.delete key, delay
|
83
|
-
elapsed = Time.now - start_time
|
84
|
-
logger.debug('MemCache Delete (%0.6f) %s' %
|
85
|
-
[elapsed, key])
|
86
|
-
nil
|
87
|
-
rescue MemCache::MemCacheError => err
|
88
|
-
logger.debug "MemCache Error: #{err.message}"
|
89
|
-
nil
|
90
|
-
end
|
91
|
-
|
92
|
-
##
|
93
|
-
# Resets all connections to MemCache servers.
|
94
|
-
|
95
|
-
def self.reset
|
96
|
-
CACHE.reset
|
97
|
-
logger.debug 'MemCache Connections Reset'
|
98
|
-
nil
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
|