KellyMahan-memcachedb-client 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|