lib/madeleine/automatic.rb in madeleine-0.7.1 vs lib/madeleine/automatic.rb in madeleine-0.7.2

- old
+ new

@@ -5,12 +5,12 @@ module Madeleine # Automatic commands for Madeleine # # Author:: Stephen Sykes <sds@stephensykes.com> -# Copyright:: Copyright (C) 2003-2004 -# Version:: 0.41 +# Copyright:: Copyright (C) 2003-2006 +# Version:: 0.42 # # This module provides a way of automatically generating command objects for madeleine to # store. It works by making a proxy object for all objects of any classes in which it is included. # Method calls to these objects are intercepted, and stored as a command before being # passed on to the real receiver. The command objects remember which object the command was @@ -50,12 +50,12 @@ # end # # mad = AutomaticSnapshotMadeleine.new("storage_directory") { A.new(param1, ...) } # # mad.system.some_method(paramA, ...) # logged as a command by madeleine -# print mad.foo # not logged -# print mad.bigfoo # not logged +# print mad.system.foo # not logged +# print mad.system.bigfoo # not logged # mad.take_snapshot # module Automatic # @@ -74,10 +74,11 @@ def self.included(klass) class <<klass alias_method :_old_new, :new def new(*args, &block) + @read_only_methods ||= [] Prox.new(_old_new(*args, &block)) end # # Called when a method added - remember symbol if read only # This is a good place to add in any superclass's read only methods also @@ -151,10 +152,11 @@ # add new objects to the list in AutomaticSnapshotMadeleine # class Automatic_marshaller #:nodoc: def Automatic_marshaller.load(io) restored_obj = Deserialize.load(io, Thread.current[:system].marshaller) +p restored_obj if restored_obj.class != Prox ObjectSpace.each_object(Prox) {|o| Thread.current[:system].restore(o) if (o.sysid == restored_obj.sysid)} restored_obj end def Automatic_marshaller.dump(obj, io = nil) Thread.current[:system].marshaller.dump(obj, io) @@ -266,18 +268,23 @@ Thread.critical = true @@systems ||= {} # holds systems by sysid @@systems[@sysid] = self Thread.critical = false @marshaller = marshaller # until attrb + begin @persister = persister.new(directory_name, Automatic_marshaller, &new_system_block) @list.delete_if {|k,v| # set all the prox objects that now exist to have the right sysid begin - ObjectSpace._id2ref(v).sysid = @sysid + obj = ObjectSpace._id2ref(v) + raise unless obj.respond_to?(:sysid=) + obj.sysid = @sysid false rescue RangeError true # Id was to a GC'd object, delete it + rescue RuntimeError + true # GC'd object, and id was reused for something else end } ensure Thread.current[:system] = false end @@ -332,11 +339,14 @@ # Close method changes the sysid for Prox objects so they can't be mistaken for real ones in a new # system before GC gets them # def close begin - @list.each_key {|k| myid2ref(k).sysid = nil} + @list.each_key {|k| + ref = myid2ref(k) + ref.sysid = nil if ref.class == Prox + } rescue RangeError # do nothing end @persister.close end @@ -387,9 +397,10 @@ # and return deserialized object using the right marshaller # If detection didn't work, raise up the exception # def Deserialize.load(io, marshaller=Marshal) begin + raise "Must detect with YAML" if marshaller == YAML marshaller.load(io) rescue Exception => e io.rewind detected_marshaller = detect(io) if (detected_marshaller == ZMarshal)