# #-- # Copyright (c) 2006-2007, Nicolas Modryzk and John Mettraux, OpenWFE.org # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # . Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # . Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # . Neither the name of the "OpenWFE" nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #++ # # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $ # # # "made in Japan" # # Nicolas Modrzyk at openwfe.org # John Mettraux at openwfe.org # #require 'monitor' require 'fileutils' require 'openwfe/service' require 'openwfe/util/lru' require 'openwfe/flowexpressionid' module OpenWFE # # This cache uses a LruHash (Least Recently Used) to store expressions. # If an expression is not cached, the 'real storage' is consulted. # The real storage is supposed to be the service named # "expressionStorage.1" # class CacheExpressionStorage include ServiceMixin, OwfeServiceLocator DEFAULT_SIZE = 5000 def initialize (service_name, application_context) super() service_init(service_name, application_context) size = @application_context[:expression_cache_size] size = DEFAULT_SIZE unless size linfo { "new() size is #{size}" } @cache = LruHash.new(size) @real_storage = nil # # expstorage observes expool : get_expression_pool.add_observer(:update) do |channel, fei, fe| ldebug { ":update for #{fei}" } self[fei] = fe end get_expression_pool.add_observer(:remove) do |channel, fei| ldebug { ":delete for #{fei}" } self.delete(fei) end end def [] (fei) #ldebug { "[] size is #{@cache.size}" } ldebug { "[] (sz #{@cache.size}) for #{fei.to_debug_s}" } fe = @cache[fei] return fe if fe ldebug { "[] (reload) for #{fei.to_debug_s}" } fe = get_real_storage[fei] return nil unless fe @cache[fei] = fe return fe end def []= (fei, fe) @cache[fei] = fe end def delete (fei) @cache.delete(fei) end def length @cache.length end alias :size :length def clear @cache.clear end alias :purge :clear # # Simply redirects the call to the each_of_kind() method of # the 'real storage'. # def each_of_kind (kind, &block) get_real_storage.each_of_kind(kind, &block) end def each (&block) @cache.each do |k, v| block.call(k, v) end end def to_s expstorage_to_s(self) end protected def get_real_storage return @real_storage if @real_storage @real_storage = @application_context[S_EXPRESSION_STORAGE + ".1"] return @real_storage end end # # Memory consuming in-memory storage. # No memory limit, puts everything in a Hash # class InMemoryExpressionStorage < Hash include ServiceMixin, OwfeServiceLocator def initialize (service_name, application_context) service_init(service_name, application_context) # # expstorage observes expool : get_expression_pool.add_observer(:update) do |channel, fei, fe| #ldebug { ":update for #{fei}" } self[fei] = fe end get_expression_pool.add_observer(:remove) do |channel, fei| #ldebug { ":delete for #{fei}" } self.delete(fei) end end alias :purge :clear def each_of_kind (kind, &block) return unless block self.each_value do |fexp| block.call(fexp) if fexp.kind_of? kind end end def to_s expstorage_to_s(self) end end # # a small help method for expression storages... # def expstorage_to_s (expstorage) s = "\n\n==== #{expstorage.class} ====" expstorage.each do |k, v| s << "\n" if v.kind_of?(RawExpression) s << "*raw" else s << " " end s << v.to_s s << " key/value mismatch !" if k != v.fei end s << "\n==== . ====\n" return s end end