Bundled memcache client consistently returns server responses and checks for errors

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8766 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Jeremy Kemper 2008-02-01 08:25:46 +00:00
parent 601222f294
commit 09d98f1331

@ -331,7 +331,8 @@ def set(key, value, expiry = 0, raw = false)
@mutex.lock if @multithread @mutex.lock if @multithread
socket.write command socket.write command
result = socket.gets result = socket.gets
raise MemCacheError, $1.strip if result =~ /^SERVER_ERROR (.*)/ raise_on_error_response! result
result
rescue SocketError, SystemCallError, IOError => err rescue SocketError, SystemCallError, IOError => err
server.close server.close
raise MemCacheError, err.message raise MemCacheError, err.message
@ -359,7 +360,9 @@ def add(key, value, expiry = 0, raw = false)
begin begin
@mutex.lock if @multithread @mutex.lock if @multithread
socket.write command socket.write command
socket.gets result = socket.gets
raise_on_error_response! result
result
rescue SocketError, SystemCallError, IOError => err rescue SocketError, SystemCallError, IOError => err
server.close server.close
raise MemCacheError, err.message raise MemCacheError, err.message
@ -383,7 +386,9 @@ def delete(key, expiry = 0)
begin begin
sock.write "delete #{cache_key} #{expiry}\r\n" sock.write "delete #{cache_key} #{expiry}\r\n"
sock.gets result = sock.gets
raise_on_error_response! result
result
rescue SocketError, SystemCallError, IOError => err rescue SocketError, SystemCallError, IOError => err
server.close server.close
raise MemCacheError, err.message raise MemCacheError, err.message
@ -406,7 +411,8 @@ def flush_all
raise MemCacheError, "No connection to server" if sock.nil? raise MemCacheError, "No connection to server" if sock.nil?
sock.write "flush_all\r\n" sock.write "flush_all\r\n"
result = sock.gets result = sock.gets
raise MemCacheError, $2.strip if result =~ /^(SERVER_)?ERROR(.*)/ raise_on_error_response! result
result
rescue SocketError, SystemCallError, IOError => err rescue SocketError, SystemCallError, IOError => err
server.close server.close
raise MemCacheError, err.message raise MemCacheError, err.message
@ -471,8 +477,9 @@ def stats
sock.write "stats\r\n" sock.write "stats\r\n"
stats = {} stats = {}
while line = sock.gets do while line = sock.gets do
raise_on_error_response! line
break if line == "END\r\n" break if line == "END\r\n"
if line =~ /^STAT ([\w]+) ([\w\.\:]+)/ then if line =~ /\ASTAT ([\w]+) ([\w\.\:]+)/ then
name, value = $1, $2 name, value = $1, $2
stats[name] = case name stats[name] = case name
when 'version' when 'version'
@ -482,7 +489,7 @@ def stats
microseconds ||= 0 microseconds ||= 0
Float(seconds) + (Float(microseconds) / 1_000_000) Float(seconds) + (Float(microseconds) / 1_000_000)
else else
if value =~ /^\d+$/ then if value =~ /\A\d+\Z/ then
value.to_i value.to_i
else else
value value
@ -564,6 +571,7 @@ def cache_decr(server, cache_key, amount)
socket = server.socket socket = server.socket
socket.write "decr #{cache_key} #{amount}\r\n" socket.write "decr #{cache_key} #{amount}\r\n"
text = socket.gets text = socket.gets
raise_on_error_response! text
return nil if text == "NOT_FOUND\r\n" return nil if text == "NOT_FOUND\r\n"
return text.to_i return text.to_i
end end
@ -582,6 +590,7 @@ def cache_get(server, cache_key)
raise MemCacheError, "lost connection to #{server.host}:#{server.port}" raise MemCacheError, "lost connection to #{server.host}:#{server.port}"
end end
raise_on_error_response! keyline
return nil if keyline == "END\r\n" return nil if keyline == "END\r\n"
unless keyline =~ /(\d+)\r/ then unless keyline =~ /(\d+)\r/ then
@ -604,8 +613,9 @@ def cache_get_multi(server, cache_keys)
while keyline = socket.gets do while keyline = socket.gets do
return values if keyline == "END\r\n" return values if keyline == "END\r\n"
raise_on_error_response! keyline
unless keyline =~ /^VALUE (.+) (.+) (.+)/ then unless keyline =~ /\AVALUE (.+) (.+) (.+)/ then
server.close server.close
raise MemCacheError, "unexpected response #{keyline.inspect}" raise MemCacheError, "unexpected response #{keyline.inspect}"
end end
@ -627,6 +637,7 @@ def cache_incr(server, cache_key, amount)
socket = server.socket socket = server.socket
socket.write "incr #{cache_key} #{amount}\r\n" socket.write "incr #{cache_key} #{amount}\r\n"
text = socket.gets text = socket.gets
raise_on_error_response! text
return nil if text == "NOT_FOUND\r\n" return nil if text == "NOT_FOUND\r\n"
return text.to_i return text.to_i
end end
@ -681,6 +692,13 @@ def threadsafe_cache_incr(server, cache_key, amount) # :nodoc:
@mutex.unlock @mutex.unlock
end end
def raise_on_error_response!(response)
if response =~ /\A(?:CLIENT_|SERVER_)?ERROR (.*)/
raise MemCacheError, $1.strip
end
end
## ##
# This class represents a memcached server instance. # This class represents a memcached server instance.
@ -820,7 +838,6 @@ def mark_dead(reason = "Unknown error")
@status = sprintf "DEAD: %s, will retry at %s", reason, @retry @status = sprintf "DEAD: %s, will retry at %s", reason, @retry
end end
end end
## ##