KellyMahan-memcachedb-client 1.1.1 → 1.1.2
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/History.txt +28 -0
- data/lib/memcache_db.rb +76 -33
- data/test/test_mem_cache_db.rb +44 -9
- metadata +2 -2
- data/lib/continuum_db.rb +0 -77
- data/lib/memcache_util_db.rb +0 -102
data/History.txt
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
|
2
|
+
= 1.1.2
|
3
|
+
|
4
|
+
merged changes from memcache-client VERSION = '1.6.5'
|
5
|
+
|
6
|
+
* Change memcache-client to multithreaded by default. The mutex does not add significant
|
7
|
+
overhead and it is far too easy, now that Sinatra, Rails and Merb are all thread-safe, to
|
8
|
+
use memcache-client in a thread-unsafe manner. Remove some unnecessary mutexing and add
|
9
|
+
a test to verify heavily multithreaded usage does not act unexpectedly.
|
10
|
+
|
11
|
+
|
12
|
+
* Add optional support for the SystemTimer gem when running on Ruby 1.8.x. This gem is
|
13
|
+
highly recommended - it ensures timeouts actually work and halves the overhead of using
|
14
|
+
timeouts. Using this gem, Ruby 1.8.x is actually faster in my performance tests
|
15
|
+
than Ruby 1.9.x. Just "gem install SystemTimer" and it should be picked up automatically.
|
16
|
+
|
17
|
+
= 1.6.4 (2009-02-19)
|
18
|
+
|
19
|
+
* Remove native code altogether. The speedup was only 10% on Ruby 1.8.6 and did not work
|
20
|
+
on Ruby 1.9.1.
|
21
|
+
|
22
|
+
* Removed memcache_util.rb from the distribution. If you are using it, please copy the code
|
23
|
+
into your own project. The file will live in the github repository for a few more months
|
24
|
+
for this purposes. http://github.com/mperham/memcache-client/raw/7a276089aa3c914e47e3960f9740ac7377204970/lib/memcache_util.rb
|
25
|
+
|
26
|
+
* Roll continuum.rb into memcache.rb. The project is again a single Ruby file, with no dependencies.
|
27
|
+
|
28
|
+
|
1
29
|
= 1.1.1
|
2
30
|
|
3
31
|
merged changes from memcache-client 1.6.4
|
data/lib/memcache_db.rb
CHANGED
@@ -2,11 +2,27 @@ $TESTING = defined?($TESTING) && $TESTING
|
|
2
2
|
|
3
3
|
require 'socket'
|
4
4
|
require 'thread'
|
5
|
-
require 'timeout'
|
6
5
|
require 'zlib'
|
7
6
|
require 'digest/sha1'
|
8
7
|
|
9
|
-
|
8
|
+
begin
|
9
|
+
# Try to use the SystemTimer gem instead of Ruby's timeout library
|
10
|
+
# when running on something that looks like Ruby 1.8.x. See:
|
11
|
+
# http://ph7spot.com/articles/system_timer
|
12
|
+
# We don't want to bother trying to load SystemTimer on jruby and
|
13
|
+
# ruby 1.9+.
|
14
|
+
if !defined?(RUBY_ENGINE)
|
15
|
+
require 'system_timer'
|
16
|
+
MemCacheTimerDb = SystemTimer
|
17
|
+
else
|
18
|
+
require 'timeout'
|
19
|
+
MemCacheTimerDb = Timeout
|
20
|
+
end
|
21
|
+
rescue LoadError => e
|
22
|
+
puts "[memcache-client] Could not load SystemTimer gem, falling back to Ruby's slower/unsafe timeout library: #{e.message}"
|
23
|
+
require 'timeout'
|
24
|
+
MemCacheTimerDb = Timeout
|
25
|
+
end
|
10
26
|
|
11
27
|
##
|
12
28
|
# A Ruby client library for memcachedb.
|
@@ -14,17 +30,17 @@ require 'continuum_db'
|
|
14
30
|
|
15
31
|
class MemCacheDb
|
16
32
|
|
17
|
-
|
33
|
+
|
18
34
|
# The version of MemCacheDb you are using.
|
19
35
|
|
20
|
-
VERSION = '1.1.
|
36
|
+
VERSION = '1.1.2'
|
21
37
|
##
|
22
38
|
# Default options for the cache object.
|
23
39
|
|
24
40
|
DEFAULT_OPTIONS = {
|
25
41
|
:namespace => nil,
|
26
42
|
:readonly => false,
|
27
|
-
:multithread =>
|
43
|
+
:multithread => true,
|
28
44
|
:failover => true,
|
29
45
|
:timeout => 0.5,
|
30
46
|
:logger => nil,
|
@@ -56,7 +72,7 @@ class MemCacheDb
|
|
56
72
|
attr_reader :servers
|
57
73
|
|
58
74
|
##
|
59
|
-
# Socket timeout limit with this client, defaults to 0.
|
75
|
+
# Socket timeout limit with this client, defaults to 0.5 sec.
|
60
76
|
# Set to nil to disable timeouts.
|
61
77
|
|
62
78
|
attr_reader :timeout
|
@@ -80,12 +96,14 @@ class MemCacheDb
|
|
80
96
|
#
|
81
97
|
# [:namespace] Prepends this value to all keys added or retrieved.
|
82
98
|
# [:readonly] Raises an exception on cache writes when true.
|
83
|
-
# [:multithread] Wraps cache access in a Mutex for thread safety.
|
99
|
+
# [:multithread] Wraps cache access in a Mutex for thread safety. Defaults to true.
|
84
100
|
# [:failover] Should the client try to failover to another server if the
|
85
101
|
# first server is down? Defaults to true.
|
86
|
-
# [:timeout] Time to use as the socket read timeout. Defaults to 0.
|
87
|
-
# set to nil to disable timeouts (this is a major performance penalty in Ruby 1.8
|
102
|
+
# [:timeout] Time to use as the socket read timeout. Defaults to 0.5 sec,
|
103
|
+
# set to nil to disable timeouts (this is a major performance penalty in Ruby 1.8,
|
104
|
+
# "gem install SystemTimer' to remove most of the penalty).
|
88
105
|
# [:logger] Logger to use for info/debug output, defaults to nil
|
106
|
+
#
|
89
107
|
# Other options are ignored.
|
90
108
|
|
91
109
|
def initialize(*args)
|
@@ -161,9 +179,6 @@ class MemCacheDb
|
|
161
179
|
weight ||= DEFAULT_WEIGHT
|
162
180
|
Server.new self, host, port, weight
|
163
181
|
else
|
164
|
-
if server.multithread != @multithread then
|
165
|
-
raise ArgumentError, "can't mix threaded and non-threaded servers"
|
166
|
-
end
|
167
182
|
server
|
168
183
|
end
|
169
184
|
end
|
@@ -221,6 +236,8 @@ class MemCacheDb
|
|
221
236
|
# cache["a"] = 1
|
222
237
|
# cache["b"] = 2
|
223
238
|
# cache.get_multi "a", "b" # => { "a" => 1, "b" => 2 }
|
239
|
+
#
|
240
|
+
# Note that get_multi assumes the values are marshalled.
|
224
241
|
|
225
242
|
|
226
243
|
def get_range(key1, key2, limit=100)
|
@@ -377,7 +394,6 @@ class MemCacheDb
|
|
377
394
|
raise MemCacheDbError, "Update of readonly cache" if @readonly
|
378
395
|
|
379
396
|
begin
|
380
|
-
@mutex.lock if @multithread
|
381
397
|
@servers.each do |server|
|
382
398
|
with_socket_management(server) do |socket|
|
383
399
|
socket.write "flush_all\r\n"
|
@@ -388,8 +404,6 @@ class MemCacheDb
|
|
388
404
|
end
|
389
405
|
rescue IndexError => err
|
390
406
|
handle_error nil, err
|
391
|
-
ensure
|
392
|
-
@mutex.unlock if @multithread
|
393
407
|
end
|
394
408
|
end
|
395
409
|
|
@@ -522,7 +536,7 @@ class MemCacheDb
|
|
522
536
|
hkey = hash_for(key)
|
523
537
|
|
524
538
|
20.times do |try|
|
525
|
-
entryidx =
|
539
|
+
entryidx = ContinuumDb.binary_search(@continuum, hkey)
|
526
540
|
server = @continuum[entryidx].server
|
527
541
|
return server if server.alive?
|
528
542
|
break unless failover
|
@@ -708,7 +722,7 @@ class MemCacheDb
|
|
708
722
|
|
709
723
|
block.call(socket)
|
710
724
|
|
711
|
-
rescue SocketError => err
|
725
|
+
rescue SocketError, Timeout::Error => err
|
712
726
|
logger.warn { "Socket failure: #{err.message}" } if logger
|
713
727
|
server.mark_dead(err)
|
714
728
|
handle_error(server, err)
|
@@ -775,7 +789,7 @@ class MemCacheDb
|
|
775
789
|
entry_count_for(server, servers.size, total_weight).times do |idx|
|
776
790
|
hash = Digest::SHA1.hexdigest("#{server.host}:#{server.port}:#{idx}")
|
777
791
|
value = Integer("0x#{hash[0..7]}")
|
778
|
-
continuum <<
|
792
|
+
continuum << ContinuumDb::Entry.new(value, server)
|
779
793
|
end
|
780
794
|
end
|
781
795
|
|
@@ -783,7 +797,7 @@ class MemCacheDb
|
|
783
797
|
end
|
784
798
|
|
785
799
|
def entry_count_for(server, total_servers, total_weight)
|
786
|
-
((total_servers *
|
800
|
+
((total_servers * ContinuumDb::POINTS_PER_SERVER * server.weight) / Float(total_weight)).floor
|
787
801
|
end
|
788
802
|
|
789
803
|
def check_multithread_status!
|
@@ -841,7 +855,6 @@ class MemCacheDb
|
|
841
855
|
|
842
856
|
attr_reader :status
|
843
857
|
|
844
|
-
attr_reader :multithread
|
845
858
|
attr_reader :logger
|
846
859
|
|
847
860
|
##
|
@@ -856,9 +869,6 @@ class MemCacheDb
|
|
856
869
|
@port = port.to_i
|
857
870
|
@weight = weight.to_i
|
858
871
|
|
859
|
-
@multithread = memcache.multithread
|
860
|
-
@mutex = Mutex.new
|
861
|
-
|
862
872
|
@sock = nil
|
863
873
|
@retry = nil
|
864
874
|
@status = 'NOT CONNECTED'
|
@@ -888,7 +898,6 @@ class MemCacheDb
|
|
888
898
|
# Returns the connected socket object on success or nil on failure.
|
889
899
|
|
890
900
|
def socket
|
891
|
-
@mutex.lock if @multithread
|
892
901
|
return @sock if @sock and not @sock.closed?
|
893
902
|
|
894
903
|
@sock = nil
|
@@ -911,8 +920,6 @@ class MemCacheDb
|
|
911
920
|
end
|
912
921
|
|
913
922
|
return @sock
|
914
|
-
ensure
|
915
|
-
@mutex.unlock if @multithread
|
916
923
|
end
|
917
924
|
|
918
925
|
##
|
@@ -920,13 +927,10 @@ class MemCacheDb
|
|
920
927
|
# object. The server is not considered dead.
|
921
928
|
|
922
929
|
def close
|
923
|
-
@mutex.lock if @multithread
|
924
930
|
@sock.close if @sock && !@sock.closed?
|
925
931
|
@sock = nil
|
926
932
|
@retry = nil
|
927
933
|
@status = "NOT CONNECTED"
|
928
|
-
ensure
|
929
|
-
@mutex.unlock if @multithread
|
930
934
|
end
|
931
935
|
|
932
936
|
##
|
@@ -955,26 +959,26 @@ end
|
|
955
959
|
class TCPTimeoutSocket
|
956
960
|
|
957
961
|
def initialize(host, port, timeout)
|
958
|
-
|
962
|
+
MemCacheTimerDb.timeout(MemCacheDb::Server::CONNECT_TIMEOUT) do
|
959
963
|
@sock = TCPSocket.new(host, port)
|
960
964
|
@len = timeout
|
961
965
|
end
|
962
966
|
end
|
963
967
|
|
964
968
|
def write(*args)
|
965
|
-
|
969
|
+
MemCacheTimerDb.timeout(@len) do
|
966
970
|
@sock.write(*args)
|
967
971
|
end
|
968
972
|
end
|
969
973
|
|
970
974
|
def gets(*args)
|
971
|
-
|
975
|
+
MemCacheTimerDb.timeout(@len) do
|
972
976
|
@sock.gets(*args)
|
973
977
|
end
|
974
978
|
end
|
975
979
|
|
976
980
|
def read(*args)
|
977
|
-
|
981
|
+
MemCacheTimerDb.timeout(@len) do
|
978
982
|
@sock.read(*args)
|
979
983
|
end
|
980
984
|
end
|
@@ -995,3 +999,42 @@ class TCPTimeoutSocket
|
|
995
999
|
@sock.close
|
996
1000
|
end
|
997
1001
|
end
|
1002
|
+
|
1003
|
+
module ContinuumDb
|
1004
|
+
POINTS_PER_SERVER = 160 # this is the default in libmemcached
|
1005
|
+
|
1006
|
+
# Find the closest index in ContinuumDb with value <= the given value
|
1007
|
+
def self.binary_search(ary, value, &block)
|
1008
|
+
upper = ary.size - 1
|
1009
|
+
lower = 0
|
1010
|
+
idx = 0
|
1011
|
+
|
1012
|
+
while(lower <= upper) do
|
1013
|
+
idx = (lower + upper) / 2
|
1014
|
+
comp = ary[idx].value <=> value
|
1015
|
+
|
1016
|
+
if comp == 0
|
1017
|
+
return idx
|
1018
|
+
elsif comp > 0
|
1019
|
+
upper = idx - 1
|
1020
|
+
else
|
1021
|
+
lower = idx + 1
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
return upper
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
class Entry
|
1028
|
+
attr_reader :value
|
1029
|
+
attr_reader :server
|
1030
|
+
|
1031
|
+
def initialize(val, srv)
|
1032
|
+
@value = val
|
1033
|
+
@server = srv
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
def inspect
|
1037
|
+
"<#{value}, #{server.host}:#{server.port}>"
|
1038
|
+
end
|
1039
|
+
end
|
1040
|
+
end
|
data/test/test_mem_cache_db.rb
CHANGED
@@ -10,9 +10,10 @@ rescue LoadError => e
|
|
10
10
|
puts "Some tests require flexmock, please run `gem install flexmock`"
|
11
11
|
end
|
12
12
|
|
13
|
+
Thread.abort_on_exception = true
|
13
14
|
$TESTING = true
|
14
15
|
|
15
|
-
require File.dirname(__FILE__) + '/../lib/memcache'
|
16
|
+
require File.dirname(__FILE__) + '/../lib/memcache' if not defined?(MemCacheDb)
|
16
17
|
|
17
18
|
class MemCacheDb
|
18
19
|
|
@@ -54,7 +55,7 @@ class Test::Unit::TestCase
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def memcached_running?
|
57
|
-
TCPSocket.new('localhost',
|
58
|
+
TCPSocket.new('localhost', 21201) rescue false
|
58
59
|
end
|
59
60
|
|
60
61
|
def xprofile(name, &block)
|
@@ -79,15 +80,15 @@ end
|
|
79
80
|
|
80
81
|
class FakeServerDb
|
81
82
|
|
82
|
-
|
83
|
+
attr_accessor :host, :port, :socket, :weight, :multithread, :status
|
83
84
|
|
84
85
|
def initialize(socket = nil)
|
85
86
|
@closed = false
|
86
87
|
@host = 'example.com'
|
87
|
-
@port =
|
88
|
+
@port = 21201
|
88
89
|
@socket = socket || FakeSocketDb.new
|
89
90
|
@weight = 1
|
90
|
-
@multithread =
|
91
|
+
@multithread = true
|
91
92
|
@status = "CONNECTED"
|
92
93
|
end
|
93
94
|
|
@@ -117,9 +118,9 @@ class TestMemCacheDb < Test::Unit::TestCase
|
|
117
118
|
|
118
119
|
def test_performance
|
119
120
|
requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
|
120
|
-
host = Socket.gethostname
|
121
121
|
|
122
122
|
cache = MemCacheDb.new(['localhost:21201',"#{host}:21201"])
|
123
|
+
cache.flush_all
|
123
124
|
cache.add('a', 1, 120)
|
124
125
|
with = xprofile 'get' do
|
125
126
|
1000.times do
|
@@ -129,7 +130,7 @@ class TestMemCacheDb < Test::Unit::TestCase
|
|
129
130
|
puts ''
|
130
131
|
puts "1000 gets with socket timeout: #{with} sec"
|
131
132
|
|
132
|
-
cache = MemCacheDb.new(['localhost:21201',"
|
133
|
+
cache = MemCacheDb.new(['localhost:21201',"127.0.0.1:21201"], :timeout => nil)
|
133
134
|
cache.add('a', 1, 120)
|
134
135
|
without = xprofile 'get' do
|
135
136
|
1000.times do
|
@@ -335,8 +336,10 @@ class TestMemCacheDb < Test::Unit::TestCase
|
|
335
336
|
|
336
337
|
def test_multithread_error
|
337
338
|
server = FakeServer.new
|
339
|
+
server.multithread = false
|
340
|
+
|
341
|
+
@cache = MemCacheDb.new(['localhost:1'], :multithread => false)
|
338
342
|
|
339
|
-
# Write two messages to the socket to test failover
|
340
343
|
server.socket.data.write "bogus response\r\nbogus response\r\n"
|
341
344
|
server.socket.data.rewind
|
342
345
|
|
@@ -887,7 +890,7 @@ class TestMemCacheDb < Test::Unit::TestCase
|
|
887
890
|
socket.data.rewind
|
888
891
|
server = FakeServerDb.new socket
|
889
892
|
def server.host() 'localhost'; end
|
890
|
-
def server.port()
|
893
|
+
def server.port() 21201; end
|
891
894
|
|
892
895
|
@cache.servers = []
|
893
896
|
@cache.servers << server
|
@@ -972,5 +975,37 @@ class TestMemCacheDb < Test::Unit::TestCase
|
|
972
975
|
return server
|
973
976
|
end
|
974
977
|
|
978
|
+
def test_crazy_multithreaded_access
|
979
|
+
requirement(memcached_running?, 'A real memcached server must be running for performance testing') do
|
980
|
+
|
981
|
+
cache = MemCacheDb.new(['localhost:21201', '127.0.0.1:21201'])
|
982
|
+
cache.flush_all
|
983
|
+
workers = []
|
984
|
+
|
985
|
+
# Have a bunch of threads perform a bunch of operations at the same time.
|
986
|
+
# Verify the result of each operation to ensure the request and response
|
987
|
+
# are not intermingled between threads.
|
988
|
+
10.times do
|
989
|
+
workers << Thread.new do
|
990
|
+
100.times do
|
991
|
+
cache.set('a', 9)
|
992
|
+
cache.set('b', 11)
|
993
|
+
cache.add('c', 10, 0, true)
|
994
|
+
assert_equal "NOT_STORED\r\n", cache.add('a', 11)
|
995
|
+
assert_equal({ 'a' => 9, 'b' => 11 }, cache.get_multi(['a', 'b']))
|
996
|
+
inc = cache.incr('c', 10)
|
997
|
+
assert_equal 0, inc % 5
|
998
|
+
assert inc > 14
|
999
|
+
assert cache.decr('c', 5) > 14
|
1000
|
+
assert_equal 11, cache.get('b')
|
1001
|
+
end
|
1002
|
+
end
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
workers.each { |w| w.join }
|
1006
|
+
cache.flush_all
|
1007
|
+
end
|
1008
|
+
end
|
1009
|
+
|
975
1010
|
end
|
976
1011
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: KellyMahan-memcachedb-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kelly Mahan
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-25 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
data/lib/continuum_db.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module ContinuumDb
|
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_db.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# A utility wrapper around the MemCacheDb client to simplify cache access. All
|
3
|
-
# methods silently ignore MemCacheDb errors.
|
4
|
-
|
5
|
-
module CacheDb
|
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('MemCacheDb 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 MemCacheDb::MemCacheDbError => err
|
39
|
-
logger.debug "MemCacheDb 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('MemCacheDb Set (%0.6f) %s' % [elapsed, key])
|
56
|
-
value
|
57
|
-
rescue MemCacheDb::MemCacheDbError => err
|
58
|
-
ActiveRecord::Base.logger.debug "MemCacheDb 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('MemCacheDb Add (%0.6f) %s' % [elapsed, key])
|
71
|
-
(response == "STORED\r\n") ? value : nil
|
72
|
-
rescue MemCacheDb::MemCacheDbError => err
|
73
|
-
ActiveRecord::Base.logger.debug "MemCacheDb 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('MemCacheDb Delete (%0.6f) %s' %
|
85
|
-
[elapsed, key])
|
86
|
-
nil
|
87
|
-
rescue MemCacheDb::MemCacheDbError => err
|
88
|
-
logger.debug "MemCacheDb Error: #{err.message}"
|
89
|
-
nil
|
90
|
-
end
|
91
|
-
|
92
|
-
##
|
93
|
-
# Resets all connections to MemCacheDb servers.
|
94
|
-
|
95
|
-
def self.reset
|
96
|
-
CACHE.reset
|
97
|
-
logger.debug 'MemCacheDb Connections Reset'
|
98
|
-
nil
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
|