~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activesupport/lib/active_support/cache.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
require 'benchmark'
2
 
 
3
 
module ActiveSupport
4
 
  # See ActiveSupport::Cache::Store for documentation.
5
 
  module Cache
6
 
    autoload :FileStore, 'active_support/cache/file_store'
7
 
    autoload :MemoryStore, 'active_support/cache/memory_store'
8
 
    autoload :SynchronizedMemoryStore, 'active_support/cache/synchronized_memory_store'
9
 
    autoload :DRbStore, 'active_support/cache/drb_store'
10
 
    autoload :MemCacheStore, 'active_support/cache/mem_cache_store'
11
 
    autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store'
12
 
 
13
 
    module Strategy
14
 
      autoload :LocalCache, 'active_support/cache/strategy/local_cache'
15
 
    end
16
 
 
17
 
    # Creates a new CacheStore object according to the given options.
18
 
    #
19
 
    # If no arguments are passed to this method, then a new
20
 
    # ActiveSupport::Cache::MemoryStore object will be returned.
21
 
    #
22
 
    # If you pass a Symbol as the first argument, then a corresponding cache
23
 
    # store class under the ActiveSupport::Cache namespace will be created.
24
 
    # For example:
25
 
    #
26
 
    #   ActiveSupport::Cache.lookup_store(:memory_store)
27
 
    #   # => returns a new ActiveSupport::Cache::MemoryStore object
28
 
    #   
29
 
    #   ActiveSupport::Cache.lookup_store(:drb_store)
30
 
    #   # => returns a new ActiveSupport::Cache::DRbStore object
31
 
    #
32
 
    # Any additional arguments will be passed to the corresponding cache store
33
 
    # class's constructor:
34
 
    #
35
 
    #   ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache")
36
 
    #   # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache")
37
 
    #
38
 
    # If the first argument is not a Symbol, then it will simply be returned:
39
 
    #
40
 
    #   ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
41
 
    #   # => returns MyOwnCacheStore.new
42
 
    def self.lookup_store(*store_option)
43
 
      store, *parameters = *([ store_option ].flatten)
44
 
 
45
 
      case store
46
 
      when Symbol
47
 
        store_class_name = (store == :drb_store ? "DRbStore" : store.to_s.camelize)
48
 
        store_class = ActiveSupport::Cache.const_get(store_class_name)
49
 
        store_class.new(*parameters)
50
 
      when nil
51
 
        ActiveSupport::Cache::MemoryStore.new
52
 
      else
53
 
        store
54
 
      end
55
 
    end
56
 
 
57
 
    def self.expand_cache_key(key, namespace = nil)
58
 
      expanded_cache_key = namespace ? "#{namespace}/" : ""
59
 
 
60
 
      if ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
61
 
        expanded_cache_key << "#{ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]}/"
62
 
      end
63
 
 
64
 
      expanded_cache_key << case
65
 
        when key.respond_to?(:cache_key)
66
 
          key.cache_key
67
 
        when key.is_a?(Array)
68
 
          key.collect { |element| expand_cache_key(element) }.to_param
69
 
        when key
70
 
          key.to_param
71
 
        end.to_s
72
 
 
73
 
      expanded_cache_key
74
 
    end
75
 
 
76
 
    # An abstract cache store class. There are multiple cache store
77
 
    # implementations, each having its own additional features. See the classes
78
 
    # under the ActiveSupport::Cache module, e.g.
79
 
    # ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most
80
 
    # popular cache store for large production websites.
81
 
    #
82
 
    # ActiveSupport::Cache::Store is meant for caching strings. Some cache
83
 
    # store implementations, like MemoryStore, are able to cache arbitrary
84
 
    # Ruby objects, but don't count on every cache store to be able to do that.
85
 
    #
86
 
    #   cache = ActiveSupport::Cache::MemoryStore.new
87
 
    #   
88
 
    #   cache.read("city")   # => nil
89
 
    #   cache.write("city", "Duckburgh")
90
 
    #   cache.read("city")   # => "Duckburgh"
91
 
    class Store
92
 
      cattr_accessor :logger
93
 
 
94
 
      attr_reader :silence, :logger_off
95
 
 
96
 
      def silence!
97
 
        @silence = true
98
 
        self
99
 
      end
100
 
 
101
 
      alias silence? silence
102
 
      alias logger_off? logger_off
103
 
 
104
 
      def mute
105
 
        previous_silence, @silence = defined?(@silence) && @silence, true
106
 
        yield
107
 
      ensure
108
 
        @silence = previous_silence
109
 
      end
110
 
 
111
 
      # Fetches data from the cache, using the given key. If there is data in
112
 
      # the cache with the given key, then that data is returned.
113
 
      #
114
 
      # If there is no such data in the cache (a cache miss occurred), then
115
 
      # then nil will be returned. However, if a block has been passed, then
116
 
      # that block will be run in the event of a cache miss. The return value
117
 
      # of the block will be written to the cache under the given cache key,
118
 
      # and that return value will be returned.
119
 
      #
120
 
      #   cache.write("today", "Monday")
121
 
      #   cache.fetch("today")  # => "Monday"
122
 
      #   
123
 
      #   cache.fetch("city")   # => nil
124
 
      #   cache.fetch("city") do
125
 
      #     "Duckburgh"
126
 
      #   end
127
 
      #   cache.fetch("city")   # => "Duckburgh"
128
 
      #
129
 
      # You may also specify additional options via the +options+ argument.
130
 
      # Setting <tt>:force => true</tt> will force a cache miss:
131
 
      #
132
 
      #   cache.write("today", "Monday")
133
 
      #   cache.fetch("today", :force => true)  # => nil
134
 
      #
135
 
      # Other options will be handled by the specific cache store implementation.
136
 
      # Internally, #fetch calls #read, and calls #write on a cache miss.
137
 
      # +options+ will be passed to the #read and #write calls.
138
 
      #
139
 
      # For example, MemCacheStore's #write method supports the +:expires_in+
140
 
      # option, which tells the memcached server to automatically expire the
141
 
      # cache item after a certain period. We can use this option with #fetch
142
 
      # too:
143
 
      #
144
 
      #   cache = ActiveSupport::Cache::MemCacheStore.new
145
 
      #   cache.fetch("foo", :force => true, :expires_in => 5.seconds) do
146
 
      #     "bar"
147
 
      #   end
148
 
      #   cache.fetch("foo")  # => "bar"
149
 
      #   sleep(6)
150
 
      #   cache.fetch("foo")  # => nil
151
 
      def fetch(key, options = {})
152
 
        @logger_off = true
153
 
        if !options[:force] && value = read(key, options)
154
 
          @logger_off = false
155
 
          log("hit", key, options)
156
 
          value
157
 
        elsif block_given?
158
 
          @logger_off = false
159
 
          log("miss", key, options)
160
 
 
161
 
          value = nil
162
 
          ms = Benchmark.ms { value = yield }
163
 
 
164
 
          @logger_off = true
165
 
          write(key, value, options)
166
 
          @logger_off = false
167
 
 
168
 
          log('write (will save %.2fms)' % ms, key, nil)
169
 
 
170
 
          value
171
 
        end
172
 
      end
173
 
 
174
 
      # Fetches data from the cache, using the given key. If there is data in
175
 
      # the cache with the given key, then that data is returned. Otherwise,
176
 
      # nil is returned.
177
 
      #
178
 
      # You may also specify additional options via the +options+ argument.
179
 
      # The specific cache store implementation will decide what to do with
180
 
      # +options+.
181
 
      def read(key, options = nil)
182
 
        log("read", key, options)
183
 
      end
184
 
 
185
 
      # Writes the given value to the cache, with the given key.
186
 
      #
187
 
      # You may also specify additional options via the +options+ argument.
188
 
      # The specific cache store implementation will decide what to do with
189
 
      # +options+.
190
 
      # 
191
 
      # For example, MemCacheStore supports the +:expires_in+ option, which
192
 
      # tells the memcached server to automatically expire the cache item after
193
 
      # a certain period:
194
 
      #
195
 
      #   cache = ActiveSupport::Cache::MemCacheStore.new
196
 
      #   cache.write("foo", "bar", :expires_in => 5.seconds)
197
 
      #   cache.read("foo")  # => "bar"
198
 
      #   sleep(6)
199
 
      #   cache.read("foo")  # => nil
200
 
      def write(key, value, options = nil)
201
 
        log("write", key, options)
202
 
      end
203
 
 
204
 
      def delete(key, options = nil)
205
 
        log("delete", key, options)
206
 
      end
207
 
 
208
 
      def delete_matched(matcher, options = nil)
209
 
        log("delete matched", matcher.inspect, options)
210
 
      end
211
 
 
212
 
      def exist?(key, options = nil)
213
 
        log("exist?", key, options)
214
 
      end
215
 
 
216
 
      def increment(key, amount = 1)
217
 
        log("incrementing", key, amount)
218
 
        if num = read(key)
219
 
          write(key, num + amount)
220
 
        else
221
 
          nil
222
 
        end
223
 
      end
224
 
 
225
 
      def decrement(key, amount = 1)
226
 
        log("decrementing", key, amount)
227
 
        if num = read(key)
228
 
          write(key, num - amount)
229
 
        else
230
 
          nil
231
 
        end
232
 
      end
233
 
 
234
 
      private
235
 
        def expires_in(options)
236
 
          expires_in = options && options[:expires_in]
237
 
 
238
 
          raise ":expires_in must be a number" if expires_in && !expires_in.is_a?(Numeric)
239
 
 
240
 
          expires_in || 0
241
 
        end
242
 
 
243
 
        def log(operation, key, options)
244
 
          logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !silence? && !logger_off?
245
 
        end
246
 
    end
247
 
  end
248
 
end