Class: Memcache

Inherits:
Object show all
Defined in:
lib/memcache.rb,
lib/memcache/server.rb,
lib/memcache/migration.rb,
lib/memcache/pg_server.rb,
lib/memcache/null_server.rb,
lib/memcache/local_server.rb,
lib/memcache/segmented_server.rb

Defined Under Namespace

Classes: LocalServer, Migration, NullServer, PGServer, Pool, SegmentedServer, Server

Constant Summary collapse

DEFAULT_EXPIRY =
0
LOCK_TIMEOUT =
5
WRITE_LOCK_WAIT =
1

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Memcache

Returns a new instance of Memcache.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/memcache.rb', line 15

def initialize(opts)
  @default_expiry    = opts[:default_expiry] || DEFAULT_EXPIRY
  @default_namespace = opts[:namespace]
  default_server = opts[:segment_large_values] ? SegmentedServer : Server

  @servers = (opts[:servers] || [ opts[:server] ]).collect do |server|
    case server
    when Hash
      server = default_server.new(opts.merge(server))
    when String
      host, port = server.split(':')
      server = default_server.new(opts.merge(:host => host, :port => port))
    when Class
      server = server.new
    when :local
      server = Memcache::LocalServer.new
    end
    server
  end
end

Instance Attribute Details

#default_expiryObject (readonly)

Returns the value of attribute default_expiry.



13
14
15
# File 'lib/memcache.rb', line 13

def default_expiry
  @default_expiry
end

#default_namespaceObject (readonly)

Returns the value of attribute default_namespace.



13
14
15
# File 'lib/memcache.rb', line 13

def default_namespace
  @default_namespace
end

#serversObject (readonly)

Returns the value of attribute servers.



13
14
15
# File 'lib/memcache.rb', line 13

def servers
  @servers
end

Class Method Details

.init(yaml_file = nil) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/memcache.rb', line 284

def self.init(yaml_file = nil)
  yaml_file = File.join(Rails.root, 'config', 'memcached.yml')

  if File.exists?(yaml_file)
    yaml = YAML.load_file(yaml_file)
    defaults = (yaml.delete('defaults') || {}).symbolize_keys
    config   = (yaml[Rails.env] || {}).symbolize_keys

    if not config.empty? and not config[:disabled]
      if config[:servers]
        opts = defaults.merge(config.symbolize_keys)
        Object.const_set('CACHE', Memcache.new(opts))
      else
        config.each do |connection, opts|
          opts = defaults.merge(opts.symbolize_keys)
          Memcache.pool[connection] = Memcache.new(opts)
        end
      end
    end
  end
end

Instance Method Details

#[](key) ⇒ Object



276
277
278
# File 'lib/memcache.rb', line 276

def [](key)
  get(key)
end

#[]=(key, value) ⇒ Object



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

def []=(key, value)
  set(key, value)
end

#add(key, value, opts = {}) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/memcache.rb', line 108

def add(key, value, opts = {})
  opts = compatible_opts(opts)

  expiry = opts[:expiry] || default_expiry
  flags  = opts[:flags]  || 0
  key    = cache_key(key)
  data   = marshal(value, opts)
  server(key).add(key, data, expiry, flags) && value
end

#append(key, value) ⇒ Object



138
139
140
141
# File 'lib/memcache.rb', line 138

def append(key, value)
  key = cache_key(key)
  server(key).append(key, value)
end

#cas(key, value, opts = {}) ⇒ Object



128
129
130
131
132
133
134
135
136
# File 'lib/memcache.rb', line 128

def cas(key, value, opts = {})
  raise 'opts must be hash' unless opts.kind_of?(Hash)

  expiry = opts[:expiry] || default_expiry
  flags  = opts[:flags]  || 0
  key    = cache_key(key)
  data   = marshal(value, opts)
  server(key).cas(key, data, opts[:cas], expiry, flags) && value
end

#cloneObject



36
37
38
39
40
41
42
# File 'lib/memcache.rb', line 36

def clone
  self.class.new(
    :default_expiry    => default_expiry,
    :default_namespace => default_namespace,
    :servers           => servers.collect {|s| s.clone}
  )
end

#count(key) ⇒ Object



148
149
150
151
# File 'lib/memcache.rb', line 148

def count(key)
  key = cache_key(key)
  server(key).get(key).to_i
end

#decr(key, amount = 1) ⇒ Object



158
159
160
161
# File 'lib/memcache.rb', line 158

def decr(key, amount = 1)
  key = cache_key(key)
  server(key).decr(key, amount)
end

#delete(key) ⇒ Object



241
242
243
244
# File 'lib/memcache.rb', line 241

def delete(key)
  key = cache_key(key)
  server(key).delete(key)
end

#flush_all(opts = {}) ⇒ Object Also known as: clear



246
247
248
249
250
251
252
253
254
# File 'lib/memcache.rb', line 246

def flush_all(opts = {})
  delay    = opts[:delay].to_i
  interval = opts[:interval].to_i

  servers.each do |server|
    server.flush_all(delay)
    delay += interval
  end
end

#get(keys, opts = {}) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/memcache.rb', line 71

def get(keys, opts = {})
  raise 'opts must be hash' unless opts.kind_of?(Hash)

  if keys.kind_of?(Array)
    multi_get(keys, opts)
  else
    key = cache_key(keys)

    if opts[:expiry]
      value = server(key).gets(key)
      server(key).cas(key, value, value.memcache_cas, opts[:expiry]) if value
    else
      value = server(key).get(key, opts[:cas])
    end
    unmarshal(value, opts)
  end
end

#get_or_add(key, *args) ⇒ Object



172
173
174
175
176
177
178
179
180
181
# File 'lib/memcache.rb', line 172

def get_or_add(key, *args)
  # Pseudo-atomic get and update.
  if block_given?
    opts = args[0] || {}
    get(key) || add(key, yield, opts) || get(key)
  else
    opts = args[1] || {}
    get(key) || add(key, args[0], opts) || get(key)
  end
end

#get_or_set(key, *args) ⇒ Object



183
184
185
186
187
188
189
190
191
# File 'lib/memcache.rb', line 183

def get_or_set(key, *args)
  if block_given?
    opts = args[0] || {}
    get(key) || set(key, yield, opts)
  else
    opts = args[1] || {}
    get(key) || set(key, args[0], opts)
  end
end

#get_some(keys, opts = {}) ⇒ Object



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

def get_some(keys, opts = {})
  keys = keys.collect {|key| key.to_s}

  records = opts[:disable] ? {} : self.get(keys, opts)
  if opts[:validation]
    records.delete_if do |key, value|
      not opts[:validation].call(key, value)
    end
  end

  keys_to_fetch = keys - records.keys
  method = opts[:overwrite] ? :set : :add
  if keys_to_fetch.any?
    yield(keys_to_fetch).each do |key, value|
      self.send(method, key, value, opts) unless opts[:disable] or opts[:disable_write]
      records[key] = value
    end
  end
  records
end

#in_namespace(namespace) ⇒ Object



60
61
62
63
64
65
66
67
68
69
# File 'lib/memcache.rb', line 60

def in_namespace(namespace)
  # Temporarily change the namespace for convenience.
  begin
    old_namespace = self.namespace
    self.namespace = "#{old_namespace}#{namespace}"
    yield
  ensure
    self.namespace = old_namespace
  end
end

#incr(key, amount = 1) ⇒ Object



153
154
155
156
# File 'lib/memcache.rb', line 153

def incr(key, amount = 1)
  key = cache_key(key)
  server(key).incr(key, amount)
end

#inspectObject



44
45
46
# File 'lib/memcache.rb', line 44

def inspect
  "<Memcache: %d servers, ns: %p>" % [@servers.length, namespace]
end

#lock(key, opts = {}) ⇒ Object



214
215
216
217
218
# File 'lib/memcache.rb', line 214

def lock(key, opts = {})
  # Returns false if the lock already exists.
  expiry = opts[:expiry] || LOCK_TIMEOUT
  add(lock_key(key), Socket.gethostname, :expiry => expiry, :raw => true)
end

#lock_key(key) ⇒ Object



233
234
235
# File 'lib/memcache.rb', line 233

def lock_key(key)
  "lock:#{key}"
end

#locked?(key) ⇒ Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/memcache.rb', line 237

def locked?(key)
  get(lock_key(key), :raw => true)
end

#namespaceObject



48
49
50
# File 'lib/memcache.rb', line 48

def namespace
  @namespace || default_namespace
end

#namespace=(namespace) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/memcache.rb', line 52

def namespace=(namespace)
  if default_namespace == namespace
    @namespace = nil
  else
    @namespace = namespace
  end
end

#prepend(key, value) ⇒ Object



143
144
145
146
# File 'lib/memcache.rb', line 143

def prepend(key, value)
  key = cache_key(key)
  server(key).prepend(key, value)
end

#read(keys, opts = {}) ⇒ Object



89
90
91
# File 'lib/memcache.rb', line 89

def read(keys, opts = {})
  get(keys, opts.merge(:raw => true))
end

#replace(key, value, opts = {}) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/memcache.rb', line 118

def replace(key, value, opts = {})
  opts = compatible_opts(opts)

  expiry = opts[:expiry] || default_expiry
  flags  = opts[:flags]  || 0
  key    = cache_key(key)
  data   = marshal(value, opts)
  server(key).replace(key, data, expiry, flags) && value
end

#resetObject



256
257
258
# File 'lib/memcache.rb', line 256

def reset
  servers.each {|server| server.close if server.respond_to?(:close)}
end

#set(key, value, opts = {}) ⇒ Object



93
94
95
96
97
98
99
100
101
102
# File 'lib/memcache.rb', line 93

def set(key, value, opts = {})
  opts = compatible_opts(opts)

  expiry = opts[:expiry] || default_expiry
  flags  = opts[:flags]  || 0
  key    = cache_key(key)
  data   = marshal(value, opts)
  server(key).set(key, data, expiry, flags)
  value
end

#stats(field = nil) ⇒ Object



260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/memcache.rb', line 260

def stats(field = nil)
  if field
    servers.collect do |server|
      server.stats[field]
    end
  else
    stats = {}
    servers.each do |server|
      stats[server.name] = server.stats
    end
    stats
  end
end

#unlock(key) ⇒ Object



220
221
222
# File 'lib/memcache.rb', line 220

def unlock(key)
  delete(lock_key(key))
end

#update(key, opts = {}) ⇒ Object



163
164
165
166
167
168
169
170
# File 'lib/memcache.rb', line 163

def update(key, opts = {})
  value = get(key, :cas => true)
  if value
    cas(key, yield(value), opts.merge!(:cas => value.memcache_cas))
  else
    add(key, yield(value), opts)
  end
end

#with_lock(key, opts = {}) ⇒ Object



224
225
226
227
228
229
230
231
# File 'lib/memcache.rb', line 224

def with_lock(key, opts = {})
  until lock(key) do
    return if opts[:ignore]
    sleep(WRITE_LOCK_WAIT) # just wait
  end
  yield
  unlock(key) unless opts[:keep]
end

#write(key, value, opts = {}) ⇒ Object



104
105
106
# File 'lib/memcache.rb', line 104

def write(key, value, opts = {})
  set(key, value, opts.merge(:raw => true))
end