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)