lib/perobs/ObjectBase.rb in perobs-2.1.1 vs lib/perobs/ObjectBase.rb in perobs-2.2.0
- old
+ new
@@ -118,27 +118,29 @@
attr_reader :_id, :store, :myself
# New PEROBS objects must always be created by calling # Store.new().
# PEROBS users should never call this method or equivalents of derived
# methods directly.
- def initialize(store)
- @store = store
- unless @store.object_creation_in_progress
- ::Kernel.raise ::RuntimeError,
- "All PEROBS objects must exclusively be created by calling " +
- "Store.new(). Never call the object constructor directly."
- end
- @_id = @store._new_id
+ # @param p [PEROBS::Handle] PEROBS handle
+ def initialize(p)
+ _initialize(p)
+ end
+
+ # This is the real code for initialize. It is called from initialize() but
+ # also when we restore objects from the database. In the later case, we
+ # don't call the regular constructors. But this code must be exercised on
+ # object creation with new() and on restore from DB.
+ # param p [PEROBS::Handle] PEROBS handle
+ def _initialize(p)
+ @store = p.store
+ @_id = p.id
@store._register_in_memory(self, @_id)
ObjectSpace.define_finalizer(self, ObjectBase._finalize(@store, @_id))
@_stash_map = nil
# Allocate a proxy object for this object. User code should only operate
# on this proxy, never on self.
@myself = POXReference.new(@store, @_id)
-
- # Let the store know that we have a modified object.
- @store.cache.cache_write(self)
end
# This method generates the destructor for the objects of this class. It
# is done this way to prevent the Proc object hanging on to a reference to
# self which would prevent the object from being collected. This internal
@@ -148,12 +150,14 @@
end
# This method can be overloaded by derived classes to do some massaging on
# the data after it has been restored from the database. This could either
# be some sanity check or code to migrate the object from one version to
- # another.
- def post_restore
+ # another. It is also the right place to initialize non-persistent
+ # instance variables as initialize() will only be called when objects are
+ # created for the first time.
+ def restore
end
# Two objects are considered equal if their object IDs are the same.
def ==(obj)
return false unless obj.is_a?(ObjectBase)
@@ -179,13 +183,14 @@
# Read the object from database.
db_obj = store.db.get_object(id)
klass = store.class_map.id_to_class(db_obj['class_id'])
# Call the constructor of the specified class.
- obj = store._construct_po(Object.const_get(klass), id)
+ obj = Object.const_get(klass).allocate
+ obj._initialize(Handle.new(store, id))
obj._deserialize(db_obj['data'])
- obj.post_restore
+ obj.restore
obj
end
# Restore the object state from the storage back-end.
@@ -193,52 +198,35 @@
def _restore(level)
# Find the most recently stored state of this object. This could be on
# any previous stash level or in the regular object DB. If the object
# was created during the transaction, there is not previous state to
# restore to.
- id = nil
+ data = nil
if @_stash_map
(level - 1).downto(0) do |lvl|
if @_stash_map[lvl]
- id = @_stash_map[lvl]
+ data = @_stash_map[lvl]
break
end
end
end
- unless id
- if @store.db.include?(@_id)
- id = @_id
- end
- end
- if id
- db_obj = store.db.get_object(id)
+ if data
+ # We have a stashed version that we can restore from.
+ _deserialize(data)
+ elsif @store.db.include?(@_id)
+ # We have no stashed version but can restore from the database.
+ db_obj = store.db.get_object(@_id)
_deserialize(db_obj['data'])
end
end
# Save the object state for this transaction level to the storage
# back-end. The object gets a new ID that is stored in @_stash_map to map
# the stash ID back to the original data.
def _stash(level)
- db_obj = {
- 'class' => self.class.to_s,
- 'data' => _serialize
- }
- @_stash_map = [] unless @_stash_map
+ @_stash_map ||= ::Array.new
# Get a new ID to store this version of the object.
- @_stash_map[level] = stash_id = @store._new_id
- @store.db.put_object(db_obj, stash_id)
- end
-
- # Library internal method. Do not use outside of this library.
- # @private
- def _change_id(id)
- # Unregister the object with the old ID from the write cache to prevent
- # cache corruption. The objects are index by ID in the cache.
- @store.cache.unwrite(self)
- @store._collect(@_id)
- @store._register_in_memory(self, id)
- @_id = id
+ @_stash_map[level] = _serialize
end
end
end