module Xampl require "xamplr/persisters/caches" class InMemoryPersister < Persister def initialize(name=nil, format=nil, capacity=20) super(name, format) @module_map = {} @capacity = capacity @cache = {} @new_cache = {} end def InMemoryPersister.kind :in_memory end def kind InMemoryPersister.kind end def fresh_cache return XamplCache.new(@capacity) end def sync_done if @new_cache then @new_cache.each{ | name1, map1 | if map1 then cache_map1 = @cache[name1] @cache[name1] = cache_map1 = {} unless cache_map1 map1.each{ | name2, map2 | if map2 then cache_map2 = cache_map1[name2] cache_map1[name2] = cache_map2 = self.fresh_cache unless cache_map2 map2.each{ | pid, xampl | cache_map2[pid] = xampl } end } end } end @new_cache = {} end def rollback_cleanup @new_cache.each{ | name, map | if map then map.each{ | name2, map2 | if map2 then map2.each{ | pid, xampl | @changed.delete(xampl) xampl.invalidate } end } end } @changed.each{ | xampl, ignore| xampl.force_load } @new_cache = {} super end def cache(xampl) return Xampl.store_in_map(@new_cache, xampl) { xampl } end def uncache(xampl) @changed.delete(xampl) Xampl.remove_from_map(@cache, xampl) return Xampl.remove_from_map(@new_cache, xampl) end def clear_cache @new_cache = {} @cache = {} end def write(xampl) raise XamplException.new(:no_index_so_no_persist) unless xampl.get_the_index #return false unless xampl.get_the_index if Xampl.store_in_map(@module_map, xampl) { represent(xampl) } then @write_count = @write_count + 1 xampl.changes_accepted return true else return false end end def read_from_cache(klass, pid, target=nil) xampl = Xampl.lookup_in_map(@cache, klass, pid) if xampl then if target and target != xampl then target.invalidate raise XamplException.new(:cache_conflict) end unless xampl.load_needed then @cache_hits = @cache_hits + 1 return xampl, target end return xampl, xampl end xampl = Xampl.lookup_in_map(@new_cache, klass, pid) if xampl then if target and target != xampl then target.invalidate raise XamplException.new(:cache_conflict) end unless xampl.load_needed then @cache_hits = @cache_hits + 1 return xampl, target end return xampl, xampl end return nil, target end def xxread_from_cache(klass, pid, target=nil) xampl = Xampl.lookup_in_map(@cache, klass, pid) if (nil != xampl) then puts "READ CACHE pid #{pid} -- #{target} #{xampl}" if target and target != xampl if target and target != xampl then target.invalidate raise XamplException.new(:cache_conflict) end unless xampl.load_needed then @cache_hits = @cache_hits + 1 return xampl end target = xampl end xampl = Xampl.lookup_in_map(@new_cache, klass, pid) if (nil != xampl) then puts "READ CACHE pid #{pid} -- #{target} #{xampl}" if target and target != xampl if target and target != xampl then target.invalidate raise XamplException.new(:cache_conflict) end unless xampl.load_needed then @cache_hits = @cache_hits + 1 return xampl end target = xampl end return xampl end def read(klass, pid, target=nil) xampl, target = read_from_cache(klass, pid, target) return xampl if xampl and !target representation = Xampl.lookup_in_map(@module_map, klass, pid) return nil unless representation xampl = realise(representation, target) Xampl.store_in_cache(@cache, xampl, self) { xampl } xampl.introduce_persister(self) @read_count = @read_count + 1 xampl.changes_accepted @changed.delete(xampl) return xampl end end Xampl.register_persister_kind(InMemoryPersister) end