Class: Memcached

Inherits:
Object
  • Object
show all
Defined in:
lib/memcached/memcached.rb,
lib/memcached.rb,
lib/memcached/auth.rb,
lib/memcached/rails.rb,
lib/memcached/behaviors.rb,
lib/memcached/exceptions.rb,
lib/memcached/experimental.rb,
lib/memcached/marshal_codec.rb

Overview

The Memcached client class.

Direct Known Subclasses

Rails

Defined Under Namespace

Modules: Experimental, MarshalCodec Classes: Error, Rails

Constant Summary collapse

Lib =
Rlibmemcached
VERSION =
File.read("#{File.dirname(__FILE__)}/../CHANGELOG")[/v([\d\.]+)\./, 1]
BEHAVIORS =
load_constants("MEMCACHED_BEHAVIOR_")
BEHAVIOR_VALUES =
{
  false => 0,
  true => 1
}
HASH_VALUES =
{}
DISTRIBUTION_VALUES =
{}
DIRECT_VALUE_BEHAVIORS =
[:retry_timeout, :connect_timeout, :rcv_timeout, :socket_recv_size, :poll_timeout, :socket_send_size, :server_failure_limit, :snd_timeout, :poll_max_retries]
CONVERSION_FACTORS =
{
  :rcv_timeout => 1_000_000,
  :snd_timeout => 1_000_000,
  :poll_timeout => 1_000,
  :connect_timeout => 1_000
}
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 => 60,
  :timeout => 0.25,
  :rcv_timeout => nil,
  :snd_timeout => nil,
  :poll_max_retries => 1,
  :poll_timeout => nil,
  :connect_timeout => 0.25,
  :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,
  :codec => Memcached::MarshalCodec,
  :exception_retry_limit => 5,
  :exceptions_to_retry => [
      Memcached::ServerIsMarkedDead,
      Memcached::ATimeoutOccurred,
      Memcached::ConnectionBindFailure,
      Memcached::ConnectionFailure,
      Memcached::ConnectionSocketCreateFailure,
      Memcached::Failure,
      Memcached::MemoryAllocationFailure,
      Memcached::ReadFailure,
      Memcached::ServerEnd,
      Memcached::ServerError,
      Memcached::SystemError,
      Memcached::UnknownReadFailure,
      Memcached::WriteFailure,
      Memcached::SomeErrorsWereReported]
}
IGNORED =

:stopdoc:

0
ERRNO_HASH =
EXCEPTIONS =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(servers = nil, opts = {}) ⇒ Memcached

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 append to the prefix key. Defaults to the empty string.

:codec

An object to use as the codec for encoded requests. Defaults to Memcached::MarshalCodec.

: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. Defaults to false. Please note that using the binary protocol is usually slower than the ASCII protocol.

: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.

:poll_max_retries

Maximum poll timeout retries before marking a flush failed on timeouts.

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.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/memcached/memcached.rb', line 108

def initialize(servers = nil, opts = {})
  @struct = Lib.memcached_create(nil)

  # Merge option defaults and discard meaningless keys
  @options = DEFAULTS.merge(opts)
  @options.each do |key,_|
     unless DEFAULTS.keys.include? key
       raise ArgumentError, "#{key.inspect} is not a valid configuration parameter."
     end
  end

  # Marginally speed up settings access for hot paths
  @default_ttl = options[:default_ttl]
  @codec = options[:codec]

  if servers == nil || servers == []
    if ENV.key?("MEMCACHE_SERVERS")
      servers = ENV["MEMCACHE_SERVERS"].split(",").map do | s | s.strip end
    else
      servers = "127.0.0.1:11211"
    end
  end

  if !options[:credentials] and ENV["MEMCACHE_USERNAME"] and ENV["MEMCACHE_PASSWORD"]
    options[:credentials] = [ENV["MEMCACHE_USERNAME"], ENV["MEMCACHE_PASSWORD"]]
  end

  instance_eval { send(:extend, Experimental) } if options[:experimental_features]

  # SASL requires binary protocol
  options[:binary_protocol] = true if options[:credentials]

  # UDP requires noreply
  options[:noreply] = true if options[:use_udp]

  # Buffering requires non-blocking
  # FIXME This should all be wrapped up in a single :pipeline option.
  options[:no_block] = true if options[:buffer_requests]

  # Disallow weights without ketama
  options.delete(:ketama_weighted) if options[:distribution] != :consistent_ketama

  # Disallow :sort_hosts with consistent hashing
  if options[:sort_hosts] and options[:distribution] == :consistent
    raise ArgumentError, ":sort_hosts defeats :consistent hashing"
  end

  # Read timeouts
  options[:rcv_timeout] ||= options[:timeout]
  options[:poll_timeout] ||= options[:timeout]

  # Write timeouts
  options[:snd_timeout] ||= options[:timeout]

  # Set the prefix key
  set_prefix_key(options[:prefix_key])

  # Set the behaviors and credentials on the struct
  set_behaviors
  set_credentials

  # Freeze the hash
  options.freeze

  # Set the servers on the struct
  set_servers(servers)

  # Not found exceptions
  if options[:show_backtraces]
    # Raise classes for full context
    @not_found = NotFound
    @not_stored = NotStored
  else
    # Raise fast context-free exception instances
    @not_found = NotFound.new
    @not_found.no_backtrace = true
    @not_stored = NotStored.new
    @not_stored.no_backtrace = true
  end
end

Instance Attribute Details

#optionsObject (readonly)

:startdoc:



61
62
63
# File 'lib/memcached/memcached.rb', line 61

def options
  @options
end

Class Method Details

.load_constants(prefix, hash = {}) ⇒ Object

:stopdoc:



6
7
8
9
10
11
# File 'lib/memcached/behaviors.rb', line 6

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

Instance Method Details

#add(key, value, ttl = @default_ttl, encode = true, flags = FLAGS) ⇒ Object

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



332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/memcached/memcached.rb', line 332

def add(key, value, ttl=@default_ttl, encode=true, flags=FLAGS)
  value, flags = @codec.encode(key, value, flags) if encode
  begin
    check_return_code(
      Lib.memcached_add(@struct, key, value, ttl, flags),
      key
    )
  rescue => e
    tries ||= 0
    raise unless tries < options[:exception_retry_limit] && should_retry(e)
    tries += 1
    retry
  end
end

#append(key, value) ⇒ Object

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 unencoded string first, via set, add, or replace with encode set to false.



399
400
401
402
403
404
405
406
407
408
409
410
# File 'lib/memcached/memcached.rb', line 399

def append(key, value)
  # Requires memcached 1.2.4
  check_return_code(
    Lib.memcached_append(@struct, key, value.to_s, IGNORED, IGNORED),
    key
  )
rescue => e
  tries ||= 0
  raise unless tries < options[:exception_retry_limit] && should_retry(e)
  tries += 1
  retry
end

#cas(key, ttl = @default_ttl, encode = true, flags = FLAGS) ⇒ Object Also known as: compare_and_swap

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

Raises:

  • (ClientError)


432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# File 'lib/memcached/memcached.rb', line 432

def cas(key, ttl=@default_ttl, encode=true, flags=FLAGS)
  raise ClientError, "CAS not enabled for this Memcached instance" unless options[:support_cas]

  begin
    value, flags, ret = Lib.memcached_get_rvalue(@struct, key)
    check_return_code(ret, key)
  rescue => e
    tries_for_get ||= 0
    raise unless tries_for_get < options[:exception_retry_limit] && should_retry(e)
    tries_for_get += 1
    retry
  end

  cas = @struct.result.cas

  value = @codec.decode(key, value, flags) if encode
  value = yield value
  value, flags = @codec.encode(key, value, flags) if encode

  begin
    check_return_code(
      Lib.memcached_cas(@struct, key, value, ttl, flags, cas),
      key
    )
  rescue => e
    tries_for_cas ||= 0
    raise unless tries_for_cas < options[:exception_retry_limit] && should_retry(e)
    tries_for_cas += 1
    retry
  end
end

#cloneObject Also known as: dup

Safely copy this instance. Returns a Memcached instance.

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



249
250
251
252
253
254
# File 'lib/memcached/memcached.rb', line 249

def clone
  memcached = super
  struct = Lib.memcached_clone(nil, @struct)
  memcached.instance_variable_set('@struct', struct)
  memcached
end

#decrement(key, offset = 1) ⇒ Object Also known as: decr

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



364
365
366
367
368
369
370
371
372
373
# File 'lib/memcached/memcached.rb', line 364

def decrement(key, offset=1)
  ret, value = Lib.memcached_decrement(@struct, key, offset)
  check_return_code(ret, key)
  value
rescue => e
  tries ||= 0
  raise unless tries < options[:exception_retry_limit] && should_retry(e)
  tries += 1
  retry
end

#delete(key) ⇒ Object

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



469
470
471
472
473
474
475
476
477
478
479
# File 'lib/memcached/memcached.rb', line 469

def delete(key)
  check_return_code(
    Lib.memcached_delete(@struct, key, IGNORED),
    key
  )
rescue => e
  tries ||= 0
  raise unless tries < options[:exception_retry_limit] && should_retry(e)
  tries += 1
  retry
end

#destroy_credentialsObject



2
3
4
5
6
# File 'lib/memcached/auth.rb', line 2

def destroy_credentials
  if options[:credentials] != nil
    check_return_code(Lib.memcached_destroy_sasl_auth_data(@struct))
  end
end

#exist(key) ⇒ Object

Check if a key exists on the server. It will return nil if the value is found, or raise Memcached::NotFound if the key does not exist.



542
543
544
545
546
547
# File 'lib/memcached/memcached.rb', line 542

def exist(key)
  check_return_code(
    Lib.memcached_exist(@struct, key),
    key
  )
end

#flushObject

Flushes all key/value pairs from all the servers.



482
483
484
485
486
487
488
489
490
491
# File 'lib/memcached/memcached.rb', line 482

def flush
  check_return_code(
    Lib.memcached_flush(@struct, IGNORED)
  )
rescue => e
  tries ||= 0
  raise unless tries < options[:exception_retry_limit] && should_retry(e)
  tries += 1
  retry
end

#get(keys, decode = true) ⇒ Object

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

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

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.



505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
# File 'lib/memcached/memcached.rb', line 505

def get(keys, decode=true)
  if keys.is_a? Array
    # Multi get
    ret = Lib.memcached_mget(@struct, keys);
    check_return_code(ret, keys)

    hash = {}
    value, key, flags, ret = Lib.memcached_fetch_rvalue(@struct)
    while ret != 21 do # Lib::MEMCACHED_END
      if ret == 0 # Lib::MEMCACHED_SUCCESS
        hash[key] = decode ? [value, flags] : value
      elsif ret != 16 # Lib::MEMCACHED_NOTFOUND
        check_return_code(ret, key)
      end
      value, key, flags, ret = Lib.memcached_fetch_rvalue(@struct)
    end
    if decode
      hash.each do |key, value_and_flags|
        hash[key] = @codec.decode(key, *value_and_flags)
      end
    end
    hash
  else
    # Single get
    value, flags, ret = Lib.memcached_get_rvalue(@struct, keys)
    check_return_code(ret, keys)
    decode ? @codec.decode(keys, value, flags) : value
  end
rescue => e
  tries ||= 0
  raise unless tries < options[:exception_retry_limit] && should_retry(e)
  tries += 1
  retry
end

#get_from_last(key, decode = true) ⇒ Object

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

Raises:

  • (ArgumentError)


550
551
552
553
554
555
# File 'lib/memcached/memcached.rb', line 550

def get_from_last(key, decode=true)
  raise ArgumentError, "get_from_last() is not useful unless :random distribution is enabled." unless options[:distribution] == :random
  value, flags, ret = Lib.memcached_get_from_last_rvalue(@struct, key)
  check_return_code(ret, key)
  decode ? @codec.decode(key, value, flags) : value
end

#increment(key, offset = 1) ⇒ Object Also known as: incr

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 unencoded integer first, via set, add, or replace with encode set to false.



352
353
354
355
356
357
358
359
360
361
# File 'lib/memcached/memcached.rb', line 352

def increment(key, offset=1)
  ret, value = Lib.memcached_increment(@struct, key, offset)
  check_return_code(ret, key)
  value
rescue => e
  tries ||= 0
  raise unless tries < options[:exception_retry_limit] && should_retry(e)
  tries += 1
  retry
end

#prefix_keyObject

Return the current prefix key.



236
237
238
239
240
241
242
# File 'lib/memcached/memcached.rb', line 236

def prefix_key
  if @struct.prefix_key.size > 0
    @struct.prefix_key[0..-1 - options[:prefix_delimiter].size]
  else
    ""
  end
end

#prepend(key, value) ⇒ Object

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



413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/memcached/memcached.rb', line 413

def prepend(key, value)
  # Requires memcached 1.2.4
  check_return_code(
    Lib.memcached_prepend(@struct, key, value.to_s, IGNORED, IGNORED),
    key
  )
rescue => e
  tries ||= 0
  raise unless tries < options[:exception_retry_limit] && should_retry(e)
  tries += 1
  retry
end

#quitObject

Disconnect from all currently connected servers



273
274
275
276
# File 'lib/memcached/memcached.rb', line 273

def quit
  Lib.memcached_quit(@struct)
  self
end

#replace(key, value, ttl = @default_ttl, encode = true, flags = FLAGS) ⇒ Object

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



381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/memcached/memcached.rb', line 381

def replace(key, value, ttl=@default_ttl, encode=true, flags=FLAGS)
  value, flags = @codec.encode(key, value, flags) if encode
  begin
    check_return_code(
      Lib.memcached_replace(@struct, key, value, ttl, flags),
      key
    )
  rescue => e
    tries ||= 0
    raise unless tries < options[:exception_retry_limit] && should_retry(e)
    tries += 1
    retry
  end
end

#reset(current_servers = nil) ⇒ Object

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



257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/memcached/memcached.rb', line 257

def reset(current_servers = nil)
  # Store state and teardown
  current_servers ||= servers
  prev_prefix_key = prefix_key
  quit

  # Create
  # FIXME Duplicates logic with initialize()
  @struct = Lib.memcached_create(nil)
  set_prefix_key(prev_prefix_key)
  set_behaviors
  set_credentials
  set_servers(current_servers)
end

#server_by_key(key) ⇒ Object

Return the server used by a particular key.



560
561
562
563
564
565
566
567
568
569
# File 'lib/memcached/memcached.rb', line 560

def server_by_key(key)
  ret = Lib.memcached_server_by_key(@struct, key)
  if ret.is_a?(Array)
    check_return_code(ret.last)
    inspect_server(ret.first)
  else
    check_return_code(ret)
  end
rescue ABadKeyWasProvidedOrCharactersOutOfRange
end

#serversObject

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



215
216
217
218
219
# File 'lib/memcached/memcached.rb', line 215

def servers
  server_structs.map do |server|
    inspect_server(server)
  end
end

#set(key, value, ttl = @default_ttl, encode = true, flags = FLAGS) ⇒ Object

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, in seconds. ttl must be a FixNum. 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 an encode value, which defaults to true and uses the default Marshal codec. Set encode to false, and pass a String as the value, if you want to set a raw byte array.



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/memcached/memcached.rb', line 315

def set(key, value, ttl=@default_ttl, encode=true, flags=FLAGS)
  value, flags = @codec.encode(key, value, flags) if encode
  begin
    check_return_code(
      Lib.memcached_set(@struct, key, value, ttl, flags),
      key
    )
  rescue => e
    tries ||= 0
    retry if e.instance_of?(ClientError) && !tries
    raise unless tries < options[:exception_retry_limit] && should_retry(e)
    tries += 1
    retry
  end
end

#set_prefix_key(key) ⇒ Object

Set the prefix key.



222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/memcached/memcached.rb', line 222

def set_prefix_key(key)
  check_return_code(
    if key
      key += options[:prefix_delimiter]
      raise ArgumentError, "Max prefix key + prefix delimiter size is #{Lib::MEMCACHED_PREFIX_KEY_MAX_SIZE - 1}" unless
        key.size < Lib::MEMCACHED_PREFIX_KEY_MAX_SIZE
      Lib.memcached_callback_set(@struct, Lib::MEMCACHED_CALLBACK_PREFIX_KEY, key)
    else
      Lib.memcached_callback_set(@struct, Lib::MEMCACHED_CALLBACK_PREFIX_KEY, "")
    end
  )
end

#set_servers(servers) ⇒ Object

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



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/memcached/memcached.rb', line 191

def set_servers(servers)
  Array(servers).each_with_index do |server, index|
    # Socket
    check_return_code(
      if server.is_a?(String) and File.socket?(server)
        args = [@struct, server, options[:default_weight].to_i]
        Lib.memcached_server_add_unix_socket_with_weight(*args)
      # Network
      elsif server.is_a?(String) and server =~ /^[\w\d\.-]+(:\d{1,5}){0,2}$/
        host, port, weight = server.split(":")
        args = [@struct, host, port.to_i, (weight || options[:default_weight]).to_i]
        if options[:use_udp]
          Lib.memcached_server_add_udp_with_weight(*args)
        else
          Lib.memcached_server_add_with_weight(*args)
        end
      else
        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)."
      end
    )
  end
end

#should_retry(e) ⇒ Object

Should retry the exception



279
280
281
282
# File 'lib/memcached/memcached.rb', line 279

def should_retry(e)
  options[:exceptions_to_retry].each {|ex_class| return true if e.instance_of?(ex_class)}
  false
end

#stats(subcommand = nil) ⇒ Object

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.



572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
# File 'lib/memcached/memcached.rb', line 572

def stats(subcommand = nil)
  stats = Hash.new([])

  stat_struct, ret = Lib.memcached_stat(@struct, subcommand)
  check_return_code(ret)

  keys, ret = Lib.memcached_stat_get_keys(@struct, stat_struct)
  check_return_code(ret)

  keys.each do |key|
     server_structs.size.times do |index|

       value, ret = Lib.memcached_stat_get_value(
         @struct,
         Lib.memcached_select_stat_at(@struct, stat_struct, index),
         key)
       check_return_code(ret, key)

       value = case value
         when /^\d+\.\d+$/ then value.to_f
         when /^\d+$/ then value.to_i
         else value
       end

       stats[key.to_sym] += [value]
     end
  end

  Lib.memcached_stat_free(@struct, stat_struct)
  stats
rescue Memcached::SomeErrorsWereReported => _
  e = _.class.new("Error getting stats")
  e.set_backtrace(_.backtrace)
  raise e
end