Parent

Included Modules

Class Index [+]

Quicksearch

Ramaze::LRUHash

A Hash-alike LRU cache that provides fine-grained control over content restrictions.

It allows you to set:

Differences to the original implementation include:

Note that due to calculating object size with Marshal, you might have to do some evaluation as to how large your values will be when marshaled, for example a String will have String#size + 10. This differs from object to object and between versions of Marshal, so be generous.

Copyright (C) 2002 Yoshinori K. Okuji Copyright © 2009 Michael Fellinger

You may redistribute it and/or modify it under the same terms as Ruby.

Constants

CacheObject
VERSION
KeyError

On 1.8 we raise IndexError, on 1.9 we raise KeyError

Public Class Methods

new(options = {}, &hook) click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 34
34:     def initialize(options = {}, &hook)
35:       self.max_value  = options[:max_value]
36:       self.max_total  = options[:max_total]
37:       self.max_count  = options[:max_count]
38:       self.expiration = options[:expiration]
39: 
40:       avoid_insane_options
41: 
42:       self.hook = hook
43: 
44:       self.objs = {}
45:       self.list = []
46: 
47:       self.total_size = 0
48:       self.hits = self.misses = 0
49:     end

Public Instance Methods

[](key) click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 120
120:     def [](key)
121:       expire
122: 
123:       unless objs.key?(key)
124:         self.misses += 1
125:         return
126:       end
127: 
128:       obj = objs[key]
129:       obj.atime = Time.now.to_i
130: 
131:       list.delete_if{|list_key| key == list_key }
132:       list << key
133: 
134:       self.hits += 1
135:       obj.content
136:     end
[]=(key, obj) click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 138
138:     def []=(key, obj)
139:       expire
140: 
141:       invalidate key if key?(key)
142: 
143:       size = Marshal.dump(obj).size
144: 
145:       if max_value && max_value < max_total
146:         warn "%p isn't cached because it exceeds max_value %p" % [obj, max_value]
147:         return obj
148:       end
149: 
150:       if max_value.nil? && max_total && max_total < size
151:         warn "%p isn't cached because it exceeds max_total: %p" % [obj, max_total]
152:         return obj
153:       end
154: 
155:       invalidate list.first if max_count && max_count == list.size
156: 
157:       self.total_size += size
158: 
159:       if max_total
160:         invalidate list.first until total_size < max_total
161:       end
162: 
163:       objs[key] = CacheObject.new(obj, size, Time.now.to_i)
164:       list << key
165: 
166:       obj
167:     end
clear() click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 102
102:     def clear
103:       objs.each{|key, obj| hook.call(key, obj) } if hook
104:       objs.clear
105:       list.clear
106:       self.total_size = 0
107:     end
Also aliased as: invalidate_all
delete(key) click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 88
88:     def delete(key)
89:       return unless objs.key?(key)
90:       obj = objs[key]
91: 
92:       hook.call(key, obj.content) if hook
93:       self.total_size -= obj.size
94:       objs.delete key
95: 
96:       list.delete_if{|list_key| key == list_key }
97: 
98:       obj.content
99:     end
Also aliased as: invalidate
each_key(&block) click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 179
179:     def each_key(&block)
180:       return enum_for(:each_key) unless block_given?
181:       objs.each_key{|key| yield key }
182:       self
183:     end
each_pair() click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 173
173:     def each_pair
174:       return enum_for(:each_pair) unless block_given?
175:       objs.each{|key, obj| yield key, obj.content }
176:       self
177:     end
each_value() click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 185
185:     def each_value
186:       return enum_for(:each_value) unless block_given?
187:       objs.each_value{|obj| yield obj.content }
188:       self
189:     end
empty?() click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 191
191:     def empty?
192:       objs.empty?
193:     end
expire() click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 110
110:     def expire
111:       return unless expiration
112:       now = Time.now.to_i
113: 
114:       list.each_with_index do |key, index|
115:         break unless (objs[key].atime + expiration) <= now
116:         invalidate key
117:       end
118:     end
fetch(key, default = (p_default = true; click to toggle source

Note that this method diverges from the default behaviour of the Ruby Hash. If the cache doesn’t find content for the given key, it will store the given default instead. Optionally it also takes a block, the return value of the block is then stored and returned.

@example

  lru = LRUHash.new
  lru.fetch(:a) # => KeyError: key not found: :a
  lru.fetch(:a, :b) # => :b
  lru.fetch(:a) # => :b
  lru.fetch(:c){|key| key.to_s } # => 'c'
  lru.fetch(:c) # => 'c'
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 208
208:     def fetch(key, default = (p_default = true; nil))
209:       if key?(key)
210:         value = self[key]
211:       elsif p_default.nil?
212:         value = self[key] = default
213:       elsif block_given?
214:         value = self[key] = yield(key)
215:       else
216:         raise KeyError, "key not found: %p" % [key]
217:       end
218: 
219:       value
220:     end
index(given_value) click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 63
63:     def index(given_value)
64:       objs.each do |key, obj|
65:         return key if given_value == obj.content
66:       end
67: 
68:       nil
69:     end
invalidate(key) click to toggle source
Alias for: delete
invalidate_all() click to toggle source
Alias for: clear
key?(key) click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 51
51:     def key?(key)
52:       objs.key?(key)
53:     end
keys() click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 71
71:     def keys
72:       objs.keys
73:     end
length() click to toggle source
Alias for: size
size() click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 75
75:     def size
76:       objs.size
77:     end
Also aliased as: length
statistics() click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 222
222:     def statistics
223:       {:size => total_size, :count => list.size, :hits => hits, :misses => misses}
224:     end
store(key, value) click to toggle source
     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 169
169:     def store(key, value)
170:       self[key] = value
171:     end
to_hash() click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 80
80:     def to_hash
81:       objs.dup
82:     end
value?(given_value) click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 55
55:     def value?(given_value)
56:       objs.each do |key, obj|
57:         return true if given_value == obj.content
58:       end
59: 
60:       false
61:     end
values() click to toggle source
    # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 84
84:     def values
85:       objs.map{|key, obj| obj.content }
86:     end

Private Instance Methods

avoid_insane_options() click to toggle source

Sanity checks.

     # File lib/ramaze/snippets/ramaze/lru_hash.rb, line 229
229:     def avoid_insane_options
230:       if (max_value && max_total) && max_value > max_total
231:         raise ArgumentError, "max_value exceeds max_total (#{max_value} > #{max_total})"
232:       end
233:       if max_value && max_value <= 0
234:         raise ArgumentError, "invalid max_value `#{max_value}'"
235:       end
236:       if max_total && max_total <= 0
237:         raise ArgumentError, "invalid max_total `#{max_total}'"
238:       end
239:       if max_count && max_count <= 0
240:         raise ArgumentError, "invalid max_count `#{max_count}'"
241:       end
242:       if expiration && expiration <= 0
243:         raise ArgumentError, "invalid expiration `#{expiration}'"
244:       end
245:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.