Class: Memcached

The Memcached client class.

Child modules and classes

Module Memcached::Experimental
Class Memcached::Error
Class Memcached::Rails

Constants

NameValue
Lib Rlibmemcached
VERSION File.read("#{File.dirname(__FILE__)}/../CHANGELOG")[/v([\d\.]+)\./, 1]
FLAGS 0x0
DEFAULTS { :hash => :fnv1_32, :no_block => false, :noreply => false, :distribution => :consistent_ketama, :ketama_weighted => true, :buffer_requests => false, :cache_lookups => true, :support_cas => false, :tcp_nodelay => false, :show_backtraces => false, :retry_timeout => 30, :timeout => 0.25, :rcv_timeout => nil, :poll_timeout => nil, :connect_timeout => 4, :prefix_key => '', :prefix_delimiter => '', :hash_with_prefix_key => true, :default_ttl => 604800, :default_weight => 8, :sort_hosts => false, :auto_eject_hosts => true, :server_failure_limit => 2, :verify_key => true, :use_udp => false, :binary_protocol => false, :credentials => nil, :experimental_features => false, :exception_retry_limit => 5, :exceptions_to_retry => [ Memcached::ServerIsMarkedDead, Memcached::ATimeoutOccurred, Memcached::ConnectionBindFailure, Memcached::ConnectionFailure, Memcached::ConnectionSocketCreateFailure, Memcached::Failure, Memcached::MemoryAllocationFailure, Memcached::ReadFailure, Memcached::ServerError, Memcached::SystemError, Memcached::UnknownReadFailure, Memcached::WriteFailure]

Attributes

NameRead/write?
options R

Public Class Methods


new (servers = nil, opts = {})

Create a new Memcached instance. Accepts string or array of server strings, as well an an optional configuration hash.

  Memcached.new('localhost', ...) # A single server
  Memcached.new(['web001:11212', 'web002:11212'], ...) # Two servers with custom ports
  Memcached.new(['web001:11211:2', 'web002:11211:8'], ...) # Two servers with default ports and explicit weights

Weights only affect Ketama hashing. If you use Ketama hashing and don‘t specify a weight, the client will poll each server‘s stats and use its size as the weight.

Valid option parameters are:

:prefix_key:A string to prepend to every key, for namespacing. Max length is 127. Defaults to the empty string.
:prefix_delimiter:A character to postpend to the prefix key. Defaults to the empty string.
:hash:The name of a hash function to use. Possible values are: :crc, :default, :fnv1_32, :fnv1_64, :fnv1a_32, :fnv1a_64, :hsieh, :md5, :murmur, and :none. :fnv1_32 is fast and well known, and is the default. Use :md5 for compatibility with other ketama clients. :none is for use when there is a single server, and performs no actual hashing.
:distribution:Either :modula, :consistent_ketama, :consistent_wheel, or :ketama. Defaults to :ketama.
:server_failure_limit:How many consecutive failures to allow before marking a host as dead. Has no effect unless :retry_timeout is also set.
:retry_timeout:How long to wait until retrying a dead server. Has no effect unless :server_failure_limit is non-zero. Defaults to 30.
:auto_eject_hosts:Whether to temporarily eject dead hosts from the pool. Defaults to true. Note that in the event of an ejection, :auto_eject_hosts will remap the entire pool unless :distribution is set to :consistent.
:exception_retry_limit:How many times to retry before raising exceptions in :exceptions_to_retry. Defaults to 5.
:exceptions_to_retry:Which exceptions to retry. Defaults to ServerIsMarkedDead, ATimeoutOccurred, ConnectionBindFailure, ConnectionFailure, ConnectionSocketCreateFailure, Failure, MemoryAllocationFailure, ReadFailure, ServerError, SystemError, UnknownReadFailure, and WriteFailure.
:cache_lookups:Whether to cache hostname lookups for the life of the instance. Defaults to true.
:support_cas:Flag CAS support in the client. Accepts true or false. Defaults to false because it imposes a slight performance penalty. Note that your server must also support CAS or you will trigger ProtocolError exceptions.
:tcp_nodelay:Turns on the no-delay feature for connecting sockets. Accepts true or false. Performance may or may not change, depending on your system.
:no_block:Whether to use pipelining for writes. Defaults to false.
:buffer_requests:Whether to use an internal write buffer. Accepts true or false. Calling get or closing the connection will force the buffer to flush. Client behavior is undefined unless :no_block is enabled. Defaults to false.
:noreply:Ask server not to reply for storage commands. Client behavior is undefined unless :no_block and :buffer_requests are enabled. Defaults to false.
:show_backtraces:Whether NotFound and NotStored exceptions should include backtraces. Generating backtraces is slow, so this is off by default. Turn it on to ease debugging.
:connect_timeout:How long to wait for a connection to a server. Defaults to 2 seconds. Set to 0 if you want to wait forever.
:timeout:How long to wait for a response from the server. Defaults to 0.25 seconds. Set to 0 if you want to wait forever.
:default_ttl:The ttl to use on set if no ttl is specified, in seconds. Defaults to one week. Set to 0 if you want things to never expire.
:default_weight:The weight to use if :ketama_weighted is true, but no weight is specified for a server.
:hash_with_prefix_key:Whether to include the prefix when calculating which server a key falls on. Defaults to true.
:use_udp:Use the UDP protocol to reduce connection overhead. Defaults to false.
:binary_protocol:Use the binary protocol to reduce query processing overhead. Defaults to false.
:sort_hosts:Whether to force the server list to stay sorted. This defeats consistent hashing and is rarely useful.
:verify_key:Validate keys before accepting them. Never disable this.

Please note that when :no_block => true, update methods do not raise on errors. For example, if you try to set an invalid key, it will appear to succeed. The actual setting of the key occurs after libmemcached has returned control to your program, so there is no way to backtrack and raise the exception.

     # File lib/memcached/memcached.rb, line 102
102:   def initialize(servers = nil, opts = {})
103:     @struct = Lib.memcached_create(nil)
104: 
105:     # Merge option defaults and discard meaningless keys
106:     @options = DEFAULTS.merge(opts)
107:     @options.delete_if { |k,v| not DEFAULTS.keys.include? k }
108:     @default_ttl = options[:default_ttl]
109: 
110:     if servers == nil || servers == []
111:       if ENV.key?("MEMCACHE_SERVERS")
112:         servers = ENV["MEMCACHE_SERVERS"].split(",").map do | s | s.strip end
113:       else
114:         servers = "127.0.0.1:11211"
115:       end
116:     end
117: 
118:     if options[:credentials] == nil && ENV.key?("MEMCACHE_USERNAME") && ENV.key?("MEMCACHE_PASSWORD")
119:       options[:credentials] = [ENV["MEMCACHE_USERNAME"], ENV["MEMCACHE_PASSWORD"]]
120:     end
121: 
122:     instance_eval { send(:extend, Experimental) } if options[:experimental_features]
123:  
124:     options[:binary_protocol] = true if options[:credentials] != nil
125: 
126:     # Force :buffer_requests to use :no_block
127:     # XXX Deleting the :no_block key should also work, but libmemcached doesn't seem to set it
128:     # consistently
129:     options[:no_block] = true if options[:buffer_requests]
130: 
131:     # Disallow weights without ketama
132:     options.delete(:ketama_weighted) if options[:distribution] != :consistent_ketama
133: 
134:     # Disallow :sort_hosts with consistent hashing
135:     if options[:sort_hosts] and options[:distribution] == :consistent
136:       raise ArgumentError, ":sort_hosts defeats :consistent hashing"
137:     end
138: 
139:     # Read timeouts
140:     options[:rcv_timeout] ||= options[:timeout] || 0
141:     options[:poll_timeout] ||= options[:timeout] || 0
142: 
143:     # Set the prefix key. Support the legacy name.
144:     set_prefix_key(options.delete(:prefix_key) || options.delete(:namespace))
145: 
146:     # Set the behaviors and credentials on the struct
147:     set_behaviors
148:     set_credentials
149: 
150:     # Freeze the hash
151:     options.freeze
152: 
153:     # Set the servers on the struct
154:     set_servers(servers)
155: 
156:     # Not found exceptions
157:     unless options[:show_backtraces]
158:       @not_found = NotFound.new
159:       @not_found.no_backtrace = true
160:       @not_stored = NotStored.new
161:       @not_stored.no_backtrace = true
162:     end
163:   end

Public Instance Methods


add (key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)

Add a key/value pair. Raises Memcached::NotStored if the key already exists on the server. The parameters are the same as set.

     # File lib/memcached/memcached.rb, line 327
327:   def add(key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)
328:     value = marshal ? Marshal.dump(value) : value.to_s
329:     begin
330:       check_return_code(
331:         Lib.memcached_add(@struct, key, value, ttl, flags),
332:         key
333:       )
334:     rescue => e
335:       tries ||= 0
336:       raise unless tries < options[:exception_retry_limit] && should_retry(e)
337:       tries += 1
338:       retry 
339:     end
340:   end

append (key, value)

Appends a string to a key‘s value. Accepts a String key and a String value. Raises Memcached::NotFound if the key does not exist on the server.

Note that the key must be initialized to an unmarshalled string first, via set, add, or replace with marshal set to false.

     # File lib/memcached/memcached.rb, line 394
394:   def append(key, value)
395:     # Requires memcached 1.2.4
396:     check_return_code(
397:       Lib.memcached_append(@struct, key, value.to_s, IGNORED, IGNORED),
398:       key
399:     )
400:   rescue => e
401:     tries ||= 0
402:     raise unless tries < options[:exception_retry_limit] && should_retry(e)
403:     tries += 1
404:     retry 
405:   end

cas (key, ttl=@default_ttl, marshal=true, flags=FLAGS) {|value| ...}

Reads a key‘s value from the server and yields it to a block. Replaces the key‘s value with the result of the block as long as the key hasn‘t been updated in the meantime, otherwise raises Memcached::NotStored. Accepts a String key and a block.

Also accepts an optional ttl value.

CAS stands for "compare and swap", and avoids the need for manual key mutexing. CAS support must be enabled in Memcached.new or a Memcached::ClientError will be raised. Note that CAS may be buggy in memcached itself. :retry_on_exceptions does not apply to this method

     # File lib/memcached/memcached.rb, line 427
427:   def cas(key, ttl=@default_ttl, marshal=true, flags=FLAGS)
428:     raise ClientError, "CAS not enabled for this Memcached instance" unless options[:support_cas]
429: 
430:     begin
431:       value, flags, ret = Lib.memcached_get_rvalue(@struct, key)
432:       check_return_code(ret, key)
433:     rescue => e
434:       tries_for_get ||= 0
435:       raise unless tries_for_get < options[:exception_retry_limit] && should_retry(e)
436:       tries_for_get += 1
437:       retry 
438:     end
439:     
440:     cas = @struct.result.cas
441: 
442:     value = Marshal.load(value) if marshal
443:     value = yield value
444:     value = Marshal.dump(value) if marshal
445: 
446:     begin
447:       check_return_code(
448:         Lib.memcached_cas(@struct, key, value, ttl, flags, cas),
449:         key
450:       )
451:     rescue => e
452:       tries_for_cas ||= 0
453:       raise unless tries_for_cas < options[:exception_retry_limit] && should_retry(e)
454:       tries_for_cas += 1
455:       retry 
456:     end
457:   end

clone ()

Safely copy this instance. Returns a Memcached instance.

clone is useful for threading, since each thread must have its own unshared Memcached object.

     # File lib/memcached/memcached.rb, line 225
225:   def clone
226:     # FIXME Memory leak
227:     # memcached = super
228:     # struct = Lib.memcached_clone(nil, @struct)
229:     # memcached.instance_variable_set('@struct', struct)
230:     # memcached
231:     self.class.new(servers, options.merge(:prefix_key => prefix_key))
232:   end


decrement (key, offset=1)

Decrement a key‘s value. The parameters and exception behavior are the same as increment.

     # File lib/memcached/memcached.rb, line 359
359:   def decrement(key, offset=1)
360:     ret, value = Lib.memcached_decrement(@struct, key, offset)
361:     check_return_code(ret, key)
362:     value
363:   rescue => e
364:     tries ||= 0
365:     raise unless tries < options[:exception_retry_limit] && should_retry(e)
366:     tries += 1
367:     retry 
368:   end

delete (key)

Deletes a key/value pair from the server. Accepts a String key. Raises Memcached::NotFound if the key does not exist.

     # File lib/memcached/memcached.rb, line 464
464:   def delete(key)
465:     check_return_code(
466:       Lib.memcached_delete(@struct, key, IGNORED),
467:       key
468:     )
469:   rescue => e
470:     tries ||= 0
471:     raise unless tries < options[:exception_retry_limit] && should_retry(e)
472:     tries += 1
473:     retry 
474:   end

flush ()

Flushes all key/value pairs from all the servers.

     # File lib/memcached/memcached.rb, line 477
477:   def flush
478:     check_return_code(
479:       Lib.memcached_flush(@struct, IGNORED)
480:     )
481:   rescue => e
482:     tries ||= 0
483:     raise unless tries < options[:exception_retry_limit] && should_retry(e)
484:     tries += 1
485:     retry 
486:   end

get (keys, marshal=true)

Gets a key‘s value from the server. Accepts a String key or array of String keys.

Also accepts a marshal value, which defaults to true. Set marshal to false if you want the value to be returned directly as a String. Otherwise it will be assumed to be a marshalled Ruby object and unmarshalled.

If you pass a String key, and the key does not exist on the server, Memcached::NotFound will be raised. If you pass an array of keys, memcached‘s multiget mode will be used, and a hash of key/value pairs will be returned. The hash will contain only the keys that were found.

The multiget behavior is subject to change in the future; however, for multiple lookups, it is much faster than normal mode.

Note that when you rescue Memcached::NotFound exceptions, you should use a the block rescue syntax instead of the inline syntax. Block rescues are very fast, but inline rescues are very slow.

     # File lib/memcached/memcached.rb, line 500
500:   def get(keys, marshal=true)
501:     if keys.is_a? Array
502:       # Multi get
503:       ret = Lib.memcached_mget(@struct, keys);
504:       check_return_code(ret, keys)
505: 
506:       hash = {}
507:       keys.each do
508:         value, key, flags, ret = Lib.memcached_fetch_rvalue(@struct)
509:         break if ret == Lib::MEMCACHED_END
510:         if ret != Lib::MEMCACHED_NOTFOUND
511:           check_return_code(ret, key)
512:           # Assign the value
513:           hash[key] = (marshal ? Marshal.load(value) : value)
514:         end
515:       end
516:       hash
517:     else
518:       # Single get
519:       value, flags, ret = Lib.memcached_get_rvalue(@struct, keys)
520:       check_return_code(ret, keys)
521:       marshal ? Marshal.load(value) : value
522:     end
523:   rescue => e
524:     tries ||= 0
525:     raise unless tries < options[:exception_retry_limit] && should_retry(e)
526:     tries += 1
527:     retry
528:   end

get_from_last (key, marshal=true)

Gets a key‘s value from the previous server. Only useful with random distribution.

     # File lib/memcached/memcached.rb, line 531
531:   def get_from_last(key, marshal=true)
532:     raise ArgumentError, "get_from_last() is not useful unless :random distribution is enabled." unless options[:distribution] == :random
533:     value, flags, ret = Lib.memcached_get_from_last_rvalue(@struct, key)
534:     check_return_code(ret, key)
535:     marshal ? Marshal.load(value) : value
536:   end

increment (key, offset=1)

Increment a key‘s value. Accepts a String key. Raises Memcached::NotFound if the key does not exist.

Also accepts an optional offset paramater, which defaults to 1. offset must be an integer.

Note that the key must be initialized to an unmarshalled integer first, via set, add, or replace with marshal set to false.

     # File lib/memcached/memcached.rb, line 347
347:   def increment(key, offset=1)
348:     ret, value = Lib.memcached_increment(@struct, key, offset)
349:     check_return_code(ret, key)
350:     value
351:   rescue => e
352:     tries ||= 0
353:     raise unless tries < options[:exception_retry_limit] && should_retry(e)
354:     tries += 1
355:     retry 
356:   end




prefix_key ()

Return the current prefix key.

     # File lib/memcached/memcached.rb, line 215
215:   def prefix_key
216:     @struct.prefix_key[0..-1 - options[:prefix_delimiter].size] if @struct.prefix_key.size > 0
217:   end

prefix_key ()

report the prefix_key

     # File lib/memcached/memcached.rb, line 277
277:   def prefix_key
278:     @struct.prefix_key[0..-1 - options[:prefix_delimiter].size]
279:   end

prefix_key= (key)

change the prefix_key after we‘re in motion

     # File lib/memcached/memcached.rb, line 266
266:   def prefix_key=(key)
267:     unless key.size < Lib::MEMCACHED_PREFIX_KEY_MAX_SIZE
268:       raise ArgumentError, "Max prefix_key size is #{Lib::MEMCACHED_PREFIX_KEY_MAX_SIZE - 1}"
269:     end
270:     check_return_code(
271:       Lib.memcached_callback_set(@struct, Lib::MEMCACHED_CALLBACK_PREFIX_KEY, "#{key}#{options[:prefix_delimiter]}")
272:     )
273:   end

prepend (key, value)

Prepends a string to a key‘s value. The parameters and exception behavior are the same as append.

     # File lib/memcached/memcached.rb, line 408
408:   def prepend(key, value)
409:     # Requires memcached 1.2.4
410:     check_return_code(
411:       Lib.memcached_prepend(@struct, key, value.to_s, IGNORED, IGNORED),
412:       key
413:     )
414:   rescue => e
415:     tries ||= 0
416:     raise unless tries < options[:exception_retry_limit] && should_retry(e)
417:     tries += 1
418:     retry 
419:   end

quit ()

Disconnect from all currently connected servers

     # File lib/memcached/memcached.rb, line 250
250:   def quit
251:     Lib.memcached_quit(@struct)
252:     self
253:   end

replace (key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)

Replace a key/value pair. Raises Memcached::NotFound if the key does not exist on the server. The parameters are the same as set.

     # File lib/memcached/memcached.rb, line 376
376:   def replace(key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)
377:     value = marshal ? Marshal.dump(value) : value.to_s
378:     begin
379:       check_return_code(
380:          Lib.memcached_replace(@struct, key, value, ttl, flags),
381:         key
382:       )
383:     rescue => e
384:       tries ||= 0
385:       raise unless tries < options[:exception_retry_limit] && should_retry(e)
386:       tries += 1
387:       retry 
388:     end
389:   end

reset (current_servers = nil, with_prefix_key = true)

Reset the state of the libmemcached struct. This is useful for changing the server list at runtime.

     # File lib/memcached/memcached.rb, line 235
235:   def reset(current_servers = nil, with_prefix_key = true)
236:     # Store state and teardown
237:     current_servers ||= servers
238:     prev_prefix_key = prefix_key
239: 
240:     # Create
241:     # FIXME Duplicates logic with initialize()
242:     @struct = Lib.memcached_create(nil)
243:     set_prefix_key(prev_prefix_key) if with_prefix_key
244:     set_behaviors
245:     set_credentials
246:     set_servers(current_servers)
247:   end

server_by_key (key)

Return the server used by a particular key.

     # File lib/memcached/memcached.rb, line 541
541:   def server_by_key(key)
542:     ret = Lib.memcached_server_by_key(@struct, key)
543:     if ret.is_a?(Array)
544:       check_return_code(ret.last)
545:       inspect_server(ret.first)
546:     else
547:       check_return_code(ret)
548:     end
549:   end

servers ()

Return the array of server strings used to configure this instance.

     # File lib/memcached/memcached.rb, line 193
193:   def servers
194:     server_structs.map do |server|
195:       inspect_server(server)
196:     end
197:   end

set (key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)

Set a key/value pair. Accepts a String key and an arbitrary Ruby object. Overwrites any existing value on the server.

Accepts an optional ttl value to specify the maximum lifetime of the key on the server. ttl can be either an integer number of seconds, or a Time elapsed time object. 0 means no ttl. Note that there is no guarantee that the key will persist as long as the ttl, but it will not persist longer.

Also accepts a marshal value, which defaults to true. Set marshal to false if you want the value to be set directly.

     # File lib/memcached/memcached.rb, line 310
310:   def set(key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)
311:     value = marshal ? Marshal.dump(value) : value.to_s
312:     begin
313:       check_return_code(
314:         Lib.memcached_set(@struct, key, value, ttl, flags),
315:         key
316:       )
317:     rescue => e
318:       tries ||= 0
319:       retry if e.instance_of?(ClientError) && !tries
320:       raise unless tries < options[:exception_retry_limit] && should_retry(e)
321:       tries += 1
322:       retry 
323:     end
324:   end


set_prefix_key (key)

Set the prefix key.

     # File lib/memcached/memcached.rb, line 200
200:   def set_prefix_key(key)
201:     check_return_code(
202:       if key
203:         key += options[:prefix_delimiter]
204:         raise ArgumentError, "Max prefix key + prefix delimiter size is #{Lib::MEMCACHED_PREFIX_KEY_MAX_SIZE - 1}" unless
205:           key.size < Lib::MEMCACHED_PREFIX_KEY_MAX_SIZE
206:         Lib.memcached_callback_set(@struct, Lib::MEMCACHED_CALLBACK_PREFIX_KEY, key)
207:       else
208:         Lib.memcached_callback_set(@struct, Lib::MEMCACHED_CALLBACK_PREFIX_KEY, "")
209:       end
210:     )
211:   end

set_servers (servers)

Set the server list. FIXME Does not necessarily free any existing server structs.

     # File lib/memcached/memcached.rb, line 167
167:   def set_servers(servers)
168:     Array(servers).each_with_index do |server, index|
169:       # Socket
170:       check_return_code(
171:         if server.is_a?(String) and File.socket?(server)
172:           args = [@struct, server, options[:default_weight].to_i]
173:           Lib.memcached_server_add_unix_socket_with_weight(*args)
174:         # Network
175:         elsif server.is_a?(String) and server =~ /^[\w\d\.-]+(:\d{1,5}){0,2}$/
176:           host, port, weight = server.split(":")
177:           args = [@struct, host, port.to_i, (weight || options[:default_weight]).to_i]
178:           if options[:use_udp]
179:             Lib.memcached_server_add_udp_with_weight(*args)
180:           else
181:             Lib.memcached_server_add_with_weight(*args)
182:           end
183:         else
184:           raise ArgumentError, "Servers must be either in the format 'host:port[:weight]' (e.g., 'localhost:11211' or  'localhost:11211:10') for a network server, or a valid path to a Unix domain socket (e.g., /var/run/memcached)."
185:         end
186:       )
187:     end
188:     # For inspect
189:     @servers = send(:servers)
190:   end

should_retry (e)

Should retry the exception

     # File lib/memcached/memcached.rb, line 256
256:   def should_retry(e)
257:     options[:exceptions_to_retry].each {|ex_class| return true if e.instance_of?(ex_class)}
258:     false
259:   end

stats (subcommand = nil)

Return a Hash of statistics responses from the set of servers. Each value is an array with one entry for each server, in the same order the servers were defined.

     # File lib/memcached/memcached.rb, line 552
552:   def stats(subcommand = nil)
553:     stats = Hash.new([])
554: 
555:     stat_struct, ret = Lib.memcached_stat(@struct, subcommand)
556:     check_return_code(ret)
557: 
558:     keys, ret = Lib.memcached_stat_get_keys(@struct, stat_struct)
559:     check_return_code(ret)
560: 
561:     keys.each do |key|
562:        server_structs.size.times do |index|
563: 
564:          value, ret = Lib.memcached_stat_get_rvalue(
565:            @struct,
566:            Lib.memcached_select_stat_at(@struct, stat_struct, index),
567:            key)
568:          check_return_code(ret, key)
569: 
570:          value = case value
571:            when /^\d+\.\d+$/ then value.to_f
572:            when /^\d+$/ then value.to_i
573:            else value
574:          end
575: 
576:          stats[key.to_sym] += [value]
577:        end
578:     end
579: 
580:     Lib.memcached_stat_free(@struct, stat_struct)
581:     stats
582:   rescue Memcached::SomeErrorsWereReported => _
583:     e = _.class.new("Error getting stats")
584:     e.set_backtrace(_.backtrace)
585:     raise e
586:   end

Private Instance Methods


check_return_code (ret, key = nil)

Checks the return code from Rlibmemcached against the exception list. Raises the corresponding exception if the return code is not Memcached::Success or Memcached::ActionQueued. Accepts an integer return code and an optional key, for exception messages.

     # File lib/memcached/memcached.rb, line 593
593:   def check_return_code(ret, key = nil) #:doc:
594:     if ret == 0 # Memcached::Success
595:     elsif ret == Lib::MEMCACHED_BUFFERED # Memcached::ActionQueued
596:     elsif ret == Lib::MEMCACHED_NOTFOUND and @not_found
597:       raise @not_found
598:     elsif ret == Lib::MEMCACHED_NOTSTORED and @not_stored
599:       raise @not_stored
600:     else
601:       message = "Key #{inspect_keys(key, (detect_failure if ret == Lib::MEMCACHED_SERVER_MARKED_DEAD)).inspect}"
602:       if key.is_a?(String)
603:         if ret == Lib::MEMCACHED_ERRNO
604:           if (server = Lib.memcached_server_by_key(@struct, key)).is_a?(Array)
605:             errno = server.first.cached_errno
606:             message = "Errno #{errno}: #{ERRNO_HASH[errno].inspect}. #{message}"
607:           end
608:         elsif ret == Lib::MEMCACHED_SERVER_ERROR
609:           if (server = Lib.memcached_server_by_key(@struct, key)).is_a?(Array)
610:             message = "\"#{server.first.cached_server_error}\". #{message}."
611:           end
612:         end
613:       end
614:       raise EXCEPTIONS[ret], message
615:     end
616:   end

set_behavior (behavior, value)

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.

    # File lib/memcached/behaviors.rb, line 39
39:   def set_behavior(behavior, value) #:doc:
40:     raise ArgumentError, "No behavior #{behavior.inspect}" unless b_id = BEHAVIORS[behavior]
41: 
42:     # Scoped validations; annoying
43:     msg =  "Invalid behavior value #{value.inspect} for #{behavior.inspect}"
44:     case behavior
45:       when :hash then raise(ArgumentError, msg) unless HASH_VALUES[value]
46:       when :distribution then raise(ArgumentError, msg) unless DISTRIBUTION_VALUES[value]
47:       when *DIRECT_VALUE_BEHAVIORS then raise(ArgumentError, msg) unless value.is_a?(Numeric) and value >= 0
48:       else
49:         raise(ArgumentError, msg) unless BEHAVIOR_VALUES[value]
50:     end
51: 
52:     lib_value = BEHAVIOR_VALUES[value] || (value * (CONVERSION_FACTORS[behavior] || 1)).to_i
53:     #STDERR.puts "Setting #{behavior}:#{b_id} => #{value} (#{lib_value})"
54:     Lib.memcached_behavior_set(@struct, b_id, lib_value)
55:     #STDERR.puts " -> set to #{get_behavior(behavior).inspect}"
56:   end