class Memcache::Server
Constants
- CONNECT_TIMEOUT
- DEFAULT_PORT
- ESCAPE
- READ_RETRY_DELAY
- UNESCAPE
Attributes
host[R]
port[R]
retry_at[R]
status[R]
Public Class Methods
new(opts)
click to toggle source
# File lib/memcache/server.rb, line 13 def initialize(opts) @host = opts[:host] @port = opts[:port] || DEFAULT_PORT @strict_reads = opts[:strict_reads] @status = 'NOT CONNECTED' @retry_at = nil @socket = nil end
Public Instance Methods
add(key, value, expiry = 0, flags = 0)
click to toggle source
# File lib/memcache/server.rb, line 138 def add(key, value, expiry = 0, flags = 0) response = write_command("add #{cache_key(key)} #{flags.to_i} #{expiry.to_i} #{value.to_s.size}", value) response == "STORED\r\n" ? value : nil end
alive?()
click to toggle source
# File lib/memcache/server.rb, line 34 def alive? @retry_at.nil? or @retry_at < Time.now end
append(key, value)
click to toggle source
# File lib/memcache/server.rb, line 148 def append(key, value) response = write_command("append #{cache_key(key)} 0 0 #{value.to_s.size}", value) response == "STORED\r\n" end
cas(key, value, cas, expiry = 0, flags = 0)
click to toggle source
# File lib/memcache/server.rb, line 133 def cas(key, value, cas, expiry = 0, flags = 0) response = write_command("cas #{cache_key(key)} #{flags.to_i} #{expiry.to_i} #{value.to_s.size} #{cas.to_i}", value) response == "STORED\r\n" ? value : nil end
clone()
click to toggle source
# File lib/memcache/server.rb, line 22 def clone self.class.new(:host => host, :port => port, :strict_reads => strict_reads?) end
close(error = nil)
click to toggle source
# File lib/memcache/server.rb, line 42 def close(error = nil) # Close the socket. If there is an error, mark the server dead. @socket.close if @socket and not @socket.closed? @socket = nil if error @retry_at = Time.now + READ_RETRY_DELAY @status = "DEAD: %s: %s, will retry at %s" % [error.class, error.message, @retry_at] else @retry_at = nil @status = "NOT CONNECTED" end end
count()
click to toggle source
# File lib/memcache/server.rb, line 72 def count stats['curr_items'] end
decr(key, amount = 1)
click to toggle source
# File lib/memcache/server.rb, line 117 def decr(key, amount = 1) raise Error, "decr requires unsigned value" if amount < 0 response = write_command("decr #{cache_key(key)} #{amount}") response == "NOT_FOUND\r\n" ? nil : response.slice(0..-3).to_i end
delete(key)
click to toggle source
# File lib/memcache/server.rb, line 123 def delete(key) write_command("delete #{cache_key(key)}") == "DELETED\r\n" ? true : nil end
flush_all(delay = nil)
click to toggle source
# File lib/memcache/server.rb, line 76 def flush_all(delay = nil) write_command("flush_all #{delay}") end
get(keys, cas = nil)
click to toggle source
# File lib/memcache/server.rb, line 80 def get(keys, cas = nil) return get([keys], cas)[keys.to_s] unless keys.kind_of?(Array) return {} if keys.empty? method = cas ? 'gets' : 'get' results = {} keys = keys.collect {|key| cache_key(key)} read_command("#{method} #{keys.join(' ')}") do |response| if cas key, flags, length, cas = match_response!(response, /^VALUE ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+)/) else key, flags, length = match_response!(response, /^VALUE ([^\s]+) ([^\s]+) ([^\s]+)/) end value = socket.read(length.to_i) match_response!(socket.read(2), "\r\n") result = { :value => value, :flags => flags.to_i, } result[:cas] = cas if cas key = input_key(key) results[key] = result end results end
incr(key, amount = 1)
click to toggle source
# File lib/memcache/server.rb, line 111 def incr(key, amount = 1) raise Error, "incr requires unsigned value" if amount < 0 response = write_command("incr #{cache_key(key)} #{amount}") response == "NOT_FOUND\r\n" ? nil : response.slice(0..-3).to_i end
inspect()
click to toggle source
# File lib/memcache/server.rb, line 26 def inspect "<#{self.class.name}: %s:%d (%s)>" % [@host, @port, @status] end
name()
click to toggle source
# File lib/memcache/server.rb, line 30 def name "#{host}:#{port}" end
prepend(key, value)
click to toggle source
# File lib/memcache/server.rb, line 153 def prepend(key, value) response = write_command("prepend #{cache_key(key)} 0 0 #{value.to_s.size}", value) response == "STORED\r\n" end
replace(key, value, expiry = 0, flags = 0)
click to toggle source
# File lib/memcache/server.rb, line 143 def replace(key, value, expiry = 0, flags = 0) response = write_command("replace #{cache_key(key)} #{flags.to_i} #{expiry.to_i} #{value.to_s.size}", value) response == "STORED\r\n" ? value : nil end
set(key, value, expiry = 0, flags = 0)
click to toggle source
# File lib/memcache/server.rb, line 127 def set(key, value, expiry = 0, flags = 0) return delete(key) if value.nil? write_command("set #{cache_key(key)} #{flags.to_i} #{expiry.to_i} #{value.to_s.size}", value) value end
stats()
click to toggle source
# File lib/memcache/server.rb, line 56 def stats stats = {} read_command('stats') do |response| key, value = match_response!(response, /^STAT ([\w]+) (-?[\w\.\:]+)/) if ['rusage_user', 'rusage_system'].include?(key) seconds, microseconds = value.split(/:/, 2) microseconds ||= 0 stats[key] = Float(seconds) + (Float(microseconds) / 1_000_000) else stats[key] = (value =~ /^-?\d+$/ ? value.to_i : value) end end stats end
strict_reads?()
click to toggle source
# File lib/memcache/server.rb, line 38 def strict_reads? @strict_reads end
Protected Instance Methods
cache_key(key)
click to toggle source
Calls superclass method
Memcache::Base#cache_key
# File lib/memcache/server.rb, line 176 def cache_key(key) key = key.gsub(/[\s\]/) {|c| ESCAPE[c]} super(key) end
input_key(key)
click to toggle source
# File lib/memcache/server.rb, line 170 def input_key(key) key = key[prefix.size..-1] if prefix # Remove prefix from key. key = key.gsub(/\./) {|c| UNESCAPE[c]} key end
Private Instance Methods
match_response!(response, regexp)
click to toggle source
# File lib/memcache/server.rb, line 183 def match_response!(response, regexp) # Make sure that the response matches the protocol. unexpected_eof! if response.nil? match = response.match(regexp) raise ServerError, "unexpected response: #{response.inspect}" unless match match.to_a[1, match.size] end
read_command(command) { |response| ... }
click to toggle source
# File lib/memcache/server.rb, line 223 def read_command(command, &block) raise ConnectionError, "Server #{name} dead, will retry at #{retry_at}" unless alive? send_command(command) do |response| while response do return if response == "END\r\n" yield(response) response = socket.gets end unexpected_eof! end rescue Exception => e puts "Memcache read error: #{e.class} #{e.to_s}" raise(e) if strict_reads? end
send_command(*command) { |response| ... }
click to toggle source
# File lib/memcache/server.rb, line 192 def send_command(*command) command = command.join("\r\n") socket.write("#{command}\r\n") response = socket.gets unexpected_eof! if response.nil? if response =~ /^(ERROR|CLIENT_ERROR|SERVER_ERROR) (.*)\r\n/ raise ($1 == 'SERVER_ERROR' ? ServerError : ClientError), $2 end block_given? ? yield(response) : response rescue Exception => e close(e) # Mark dead. raise e if e.kind_of?(Error) raise ConnectionError.new(e) end
socket()
click to toggle source
# File lib/memcache/server.rb, line 238 def socket if @socket.nil? or @socket.closed? # Attempt to connect. @socket = timeout(CONNECT_TIMEOUT) do TCPSocket.new(host, port) end if Socket.constants.include? 'TCP_NODELAY' @socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 end @retry_at = nil @status = 'CONNECTED' end @socket end
unexpected_eof!()
click to toggle source
# File lib/memcache/server.rb, line 254 def unexpected_eof! raise Error, 'unexpected end of file' end
write_command(*command, &block)
click to toggle source
# File lib/memcache/server.rb, line 209 def write_command(*command, &block) retried = false begin send_command(*command, &block) rescue Exception => e puts "Memcache write error: #{e.class} #{e.to_s}" unless retried retried = true retry end raise(e) end end