# # Simple Ruby Cache # Ken Wronkiewicz # # Version 1.00 - Inital release - Ken Wronkiewicz # # Docs on https://www.wirewd.com/hacks/marginal/simplecache/ # # Copyright (c) 2007 Ken Wronkiewicz # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. class Simplecache NOCACHE = :NOCACHE class Meta def initialize(data, forceexpire) @added = Time.new @used = Time.new @expires = Time.new + forceexpire @data = data end def do_access() @used = Time.new return @data; end attr_reader :added, :used, :data, :expires end class CacheControl def initialize(data, msg) @data = data; @msg = msg end attr_reader :data, :msg end def initialize(desiredcount, forceexpire) @desiredcount = desiredcount; @expire = forceexpire @data = Hash.new() end def has_key?(key) return @data.has_key?(key) end def clear @data.clear() @meta.clear() end def expire # first we want to expire any nodes. now = Time.new(); @data.delete_if { |key,value| if value.expires() < now return true else return false end } # now, see if we still need to expire some numtodelete = 0; if(@desiredcount != nil) x = @data.size() - @desiredcount if x > 0 numtodelete = x; end end if numtodelete != 0 sorted = @data.sort { |a,b| a[1].used <=> b[1].used } sorted[0,numtodelete].each { |x| @data.delete(x[0]) } end end def work(key) if @data.has_key?(key) # expire *just* this node if it got too old and fall through. if @data[key].expires < Time.new() @data.delete(key) else return @data[key].do_access() end end data = yield if data.class != Simplecache::CacheControl @data[key] = Simplecache::Meta::new(data,@expire) return data else if data.msg == Simplecache::NOCACHE return data.data end end end end