[elephant-cvs] CVS elephant/doc
ieslick
ieslick at common-lisp.net
Tue Apr 24 03:02:27 UTC 2007
Update of /project/elephant/cvsroot/elephant/doc
In directory clnet:/tmp/cvs-serv23327/doc
Modified Files:
IntroTalk1.ppt user-guide.texinfo
Log Message:
More documentation edits; performance and feature enhancements for map-index (from-end, collect); fix bug in slot initialization under from-oid
Binary files /project/elephant/cvsroot/elephant/doc/IntroTalk1.ppt 2007/04/23 04:58:15 1.1 and /project/elephant/cvsroot/elephant/doc/IntroTalk1.ppt 2007/04/24 03:02:26 1.2 differ
--- /project/elephant/cvsroot/elephant/doc/user-guide.texinfo 2007/04/22 03:35:09 1.13
+++ /project/elephant/cvsroot/elephant/doc/user-guide.texinfo 2007/04/24 03:02:26 1.14
@@ -340,53 +340,186 @@
(initialization of slots, slot-access, etc).
All persistent classes create objects that inherit from the
- at code{persistent} class. The persistent class has two slots that
-contain a unique object identifier (oid) and a reference to the
- at code{store-controller} specification they are associated with.
+ at code{persistent} class. The @code{persistent} class provides two
+slots that contain a unique object identifier (oid) and a reference to
+the @code{store-controller} specification they are associated with.
Persistent slots do not take up any storage space in memory, instead
-the slot access protocol is changed into calls to the configured data
-store via the store controller. Typically, data stores then perform
-reads and writes to disk.
+the @code{persistent-metaclass} slot access protocol redirects slot
+accesses into calls to the store controller. Typically, the
+underlying data store will then perform the necessary serialization,
+deserialization to read and write data to disk.
When a reference to a @code{persistent} instance itself is written to
the database, for example as a key or value in a @code{btree}, only
the unique ID and class of the instance is stored. When read, a
persistent object instance is re-created (see below). This means that
serialization of persistent objects is exceedingly cheap compared to
-standard objects, but slot access time can be much more expensive.
+standard objects. The subsection on instance creation below will
+discuss the lifecycle of a persistent object in more detail.
@subsection Persistent Class Definition
To create persistent classes, the user needs to specify the
@code{persistent-metaclass} to the class initarg @code{:metaclass}.
-The only differences between standard and persistent class definitions
-is the specification of a slot storage policy and an index policy.
+
+ at lisp
+(defclass my-pclass ()
+ ((slot1 :accessor slot1 :initarg :slot1 :initform 1))
+ (:metaclass persistent-metaclass))
+ at end lisp
+
+The only differences between the syntax of standard and persistent
+class definitions is the ability to specify a slot storage policy and
+an index policy. Slot value storage policies are specified by a
+boolean argument to the slot initargs @code{:persistent},
+ at code{:transient} and @code{:indexed}. Slots are @code{:persistent}
+and not @code{:indexed} by default.
+
The @code{defpclass} macro is provided as a convenience to hide the
@code{:metaclass} slot option.
-Slot value storage policies are specified by a boolean argument to the
-new slot initargs @code{:persistent}, @code{:transient} and
- at code{indexed}. Slots are @code{:persistent} by default.
-
@lisp
-(defclass my-pclass ()
+(defpclass my-pclass ()
((pslot1 :accessor pslot1 :initarg :pslot1 :initform 'one)
(pslot2 :accessor pslot2 :initarg :pslot2 :initform 'two :persistent t)
- (tslot1 :accessor tslot1 :initarg :tslot1 :initform 'three :transient t))
- (:metaclass persistent-metaclass))
+ (tslot1 :accessor tslot1 :initarg :tslot1 :initform 'three :transient t)))
@end lisp
-In the definition above, @code{pslot1} and @code{pslot2} are
-persistent while @code{tslot1} is transient and stored in memory.
+In the definition above the class @code{my-pclass} is an instance of
+the metaclass @code{persistent-metaclass}. According to this
+definition @code{pslot1} and @code{pslot2} are persistent while
+ at code{tslot1} is transient and stored in memory.
Slot storage class implications are straightforward. Persistent slot
-writes are durably stored to disk. Transient slots are initialized on
-instance creation according to initforms or initargs. Transient slot
-values are never stored to nor loaded from the database.
+writes are durably stored to disk and reads are made from disk and can
+be part of a ACID compliant transaction . Transient slots are
+initialized on instance creation according to initforms or initargs.
+Transient slot values are never stored to nor loaded from the database
+and their accesses cannot be protected by transactions. (Ordinary
+multi-process synchronization would be required instead).
+
+Persistent classes have their metaobject protocols modified through
+specializations on @code{persistent-metaclass}. These specializations
+create special slot metaobjects: @code{transient-slot-definition},
+ at code{persistent-slot-definition} and direct and effective versions of
+each. For the MOP aficionado the highlights of the new class
+initialization protocols are as follows:
+
+ at itemize
+ at item @code{shared-initialize :around} ensures that this class inherits from
+ @code{persistent-object} and @code{persistent} if it doesn't
+ already and that the class option @code{:index} results in class indexes
+ being indexed;.
+ at item @code{direct-slot-initialization-class} returns the appropriate slot
+ metaobject based on the values of the @code{:transient} and @code{:persistent}
+ slot definition keywords. It also does some simple error checking for invalid
+ combinations, for example, indexed transient slots.
+ at item @code{effective-slot-definition-class} performs the same role as the above for
+ effective slots.
+ at item @code{slot-definition-allocation} returns the @code{:database} allocation for
+ persistent slot definitions so the underlying lisp will not allocate instance or
+ class storage under some lisps.
+ at item @code{compute-effective-slot-definition-initargs} performs some error checking
+ to ensure a subclass does not try to make an inherited persistent slot transient.
+ at item @code{finalize-inheritance} called before the first instance is created in order
+ to finalize the list of persistent slots to account for any
+ forward referenced classes in the inheritence list. Similarly the
+ list of indexed slots is computed. This function is also called by the class indexing
+ code if any calls are made that depend on knowing which slots are indexed.
+ at end itemize
+
+Reinitialization is discussed in the section on class redefinition.
+
+ at subsection Instance Creation
+
+To the user, persistent objects are created as usual with a call to
+ at code{make-instance}. Initforms and slot initargs behave as the user
+expects. The call to @code{make-instance} of a persistent class will
+fail unless there is a default @code{store-controller} instance in the
+variable @code{*store-controller*} or the @code{:sc} keyword argument
+is provided a valid store controller object. The store controller is
+required to provide a unique object id, initialize the specification
+pointer of the instance and to store the values of any initialized
+slots. The initialization process is as follows:
+
+ at itemize
+ at item @code{initialize-instance :before} is called to initialize the
+ @code{oid} slot and the data store specification slot @code{dbcn-spc-pst}.
+ The oid is set by the argument @code{:from-oid} or by calling the store
+ controller for a new oid.
+ at item @code{shared-initialize :around} is called to ensure that the underlying
+ lisp does not bypass the metaobject protocol during slot
+ initialization by manually initializing the persistent slots
+ and passing the transient slots to the underlying lisp.
+ Finally it adds the instance to the class index so that any inverted indicies
+ are updated appropriately.
+ at end itemize
+
+Persistent slots are initialized under the following conditions:
+
+ at enumerate
+ at item An initarg is provided to @code{make-instance}
+ at item The database slot value is unbound, an initform exists and from-oid was not provided
+ at end enumerate
+
+ at subsection Persistent Class Lifecycle
+
+
+
+The initialize instance protocol and persistent slot initialization
+provides us some insight into how persistent class instances are
+recreated in a fresh lisp image. To get a persistent instance, the
+instance must be retrieved from the database via the root or a class
+index. When a reference to an instance is deserialized, the deserializer
+looks in a
+
+Because the oid is already known
+when we deserialize the class reference from the database, the use the
+ at code{:from-oid} argument to indicate that this object already exists.
+Because any initializable values are set
+
+
+ The two properties of
+ at code{persistent} can be specified explicitly during instance
+creation:
+
+ at lisp
+(make-instance 'my-pclass :from-oid 100 :sc *store-controller*)
+ at end lisp
+
+These three elements, class, oid and store controller is all that is
+needed to create a new instance
+
+
+If you do make an instance with a specified OID which already exists
+in the database, @code{initargs} to @code{make-instanc} take
+precedence over values in the database, which take precedences over
+any @code{initforms} defined in the class.
+
+Think of it this way. If you get a value from a persistent index and that value is a persistent object, then you want object identity, the ability to inspect it's type, slot access, etc. The only way to do that is to create something in memory which provides this. The only way to that is to make sure your lisp has had the chance to construct everything it needs via make-instance.
+
+The :from-oid argument to make-instance overrides some of the normal make-instance behavior by inhibiting all initform initialization as the object's slots are assumed to already be valid, so you have exactly the behavior you want.
+
+There are two caveats to this nice model: transient slots and make-instance methods.
+
+Transient Slots: they have the semantics of ordinary lisp slots - you cannot expect them to persist between images or after their placeholder has been garbage collected. If you drop all references to an object with transient slots, those slots are reclaimed by the GC. If you try to access them again later, they are reset to their default state (unbound, initforms or make-instance computations).
+
+Make-instance specializers: If you override the typical make-instance via :before, :after, :around or specialized on your class, you have to make sure that you predicate on :from-oid (this will be documented in the new manual) to avoid resetting persistent values. If :from-oid is given a value, then you can assume the object is being reconstituted and you don't need to do anything special for the persistent slots.
+
+However, if you want to use persistent slots to compute the value of some transient slots, then a make-instance specializer is a good place to do it. indexed-btree is an example of this, an in-memory hash is cached in the transient slot for reads and writes are mirrored to a serialized hash in a persistent slot.
+
+ at subsection Using Persistent Slots
+
+* What happens to persistent objects when store-controller is closed?
+
+ at subsection Using Transient Slots
+
+The best policy for initializing transient slots is an @code{:after}
+method on @code{initialize-instance}.
During a given lisp session transient values will be cached regardless
of how often you retrieve an object from the store as long as there is
-a reference to it stored in memory or tere are zero references but the
+a reference to it in memory or there are zero references but the
object has not yet been collected by the lisp garbage collector.
After collection, if you retrieve an object from the store its
transient slots will be reset to the slot initforms from the class
@@ -394,6 +527,11 @@
or persistent slots during the initial call to @code{make-instance} or
by manually creating the instance from an oid (see below).
+A good policy is to initialize transient values using an @code{:after}
+method on @code{initialize-instance} to initialize transient values
+using system defaults or from persistent slot values. That way
+whether the slots are valid when the object is pulled from
+
@lisp
(setf pobj1 (make-instance 'my-pclass :pslot1 1 :tslot3 3))
=> #<MY-PCLASS>
@@ -431,48 +569,6 @@
behavior of indexed classes and class slots are discussed in depth in
@ref{Class Indices}.
- at subsection Instance Creation
-
-To the user, persistent objects are created normally with a call to
- at code{make-instance} with the desired slot initargs as illustrated in
-the last section. However, this call will fail unless there is a
-default @code{store-controller} instance in the variable
- at code{*store-controller*} or the @code{:sc} keyword argument is
-provided with a valid store controller object.
-
-An instance of the class is created and any initforms and initarg
-values are written to transient or persistent slots as one would
-expect.
-
-* Default store controller & instance creation
-* What happens to persistent objects when store-controller is closed?
-
-The best policy for initializing transient slots is an @code{:after}
-method on @code{initialize-instance}.
-
-The two properties of @code{persistent} can be specified explicitly
-during instance creation:
-
- at lisp
-(make-instance 'my-pclass :from-oid 100 :sc *store-controller*)
- at end lisp
-
-These three elements, class, oid and store controller is all that is
-needed to create a new instance
-
-If you do make an instance with a specified OID which already exists
-in the database, @code{initargs} to @code{make-instanc} take
-precedence over values in the database, which take precedences over
-any @code{initforms} defined in the class.
-
-A good policy is to initialize transient values using an @code{:after}
-method on @code{initialize-instance} to initialize transient values
-using system defaults or from persistent slot values. That way
-whether the slots are valid when the object is pulled from
-
-Also currently there is a bug where @code{initforms} are always
-evaluated, so beware. (What is the current model here?)
-
@subsection Class Redefinition
This section discusses the appropriate model a user should employ in
More information about the Elephant-cvs
mailing list