class Memcached
#:stopdoc:
def self.load_constants(prefix, hash = {})
Lib.constants.grep(/^#{prefix}/).each do |const_name|
hash[const_name[prefix.length..-1].downcase.to_sym] = Lib.const_get(const_name)
end
hash
end
BEHAVIORS = load_constants("MEMCACHED_BEHAVIOR_")
BEHAVIOR_VALUES = {
false => 0,
true => 1
}
HASH_VALUES = {}
BEHAVIOR_VALUES.merge!(load_constants("MEMCACHED_HASH_", HASH_VALUES))
DISTRIBUTION_VALUES = {}
BEHAVIOR_VALUES.merge!(load_constants("MEMCACHED_DISTRIBUTION_", DISTRIBUTION_VALUES))
DIRECT_VALUE_BEHAVIORS = [:retry_timeout, :connect_timeout, :rcv_timeout, :socket_recv_size, :poll_timeout, :socket_send_size, :server_failure_limit]
CONVERSION_FACTORS = {
:rcv_timeout => 1_000_000,
:poll_timeout => 1_000,
:connect_timeout => 1_000
}
#:startdoc:
private
# Set a behavior option for this Memcached instance. Accepts a Symbol behavior and either true, false, or a Symbol for value. Arguments are validated and converted into integers for the struct setter method.
def set_behavior(behavior, value) #:doc:
raise ArgumentError, "No behavior #{behavior.inspect}" unless b_id = BEHAVIORS[behavior]
# Scoped validations; annoying
msg = "Invalid behavior value #{value.inspect} for #{behavior.inspect}"
case behavior
when :hash then raise(ArgumentError, msg) unless HASH_VALUES[value]
when :distribution then raise(ArgumentError, msg) unless DISTRIBUTION_VALUES[value]
when *DIRECT_VALUE_BEHAVIORS then raise(ArgumentError, msg) unless value.is_a?(Numeric) and value >= 0
else
raise(ArgumentError, msg) unless BEHAVIOR_VALUES[value]
end
lib_value = BEHAVIOR_VALUES[value] || (value * (CONVERSION_FACTORS[behavior] || 1)).to_i
#STDERR.puts "Setting #{behavior}:#{b_id} => #{value} (#{lib_value})"
Lib.memcached_behavior_set(@struct, b_id, lib_value)
#STDERR.puts " -> set to #{get_behavior(behavior).inspect}"
end
# Get a behavior value for this Memcached instance. Accepts a Symbol.
def get_behavior(behavior)
raise ArgumentError, "No behavior #{behavior.inspect}" unless b_id = BEHAVIORS[behavior]
value = Lib.memcached_behavior_get(@struct, b_id)
if BEHAVIOR_VALUES.invert.has_key?(value)
# False, nil are valid values so we can not rely on direct lookups
case behavior
# Scoped values; still annoying
when :hash then HASH_VALUES.invert[value]
when :distribution then DISTRIBUTION_VALUES.invert[value]
else
value
end
else
value
end
end
end