[elephant-cvs] CVS elephant/doc
ieslick
ieslick at common-lisp.net
Sat Apr 21 17:22:36 UTC 2007
Update of /project/elephant/cvsroot/elephant/doc
In directory clnet:/tmp/cvs-serv3920/doc
Modified Files:
elephant-design.texinfo elephant.texinfo installation.texinfo
make-ref.lisp reference.texinfo scenarios.texinfo
tutorial.texinfo user-guide.texinfo
Log Message:
Check for cross-store loading errors in multi-store operation; more documentation; backend language to data store language
--- /project/elephant/cvsroot/elephant/doc/elephant-design.texinfo 2007/04/01 14:33:29 1.3
+++ /project/elephant/cvsroot/elephant/doc/elephant-design.texinfo 2007/04/21 17:22:35 1.4
@@ -1,8 +1,8 @@
@c -*-texinfo-*-
- at node Elephant Design
+ at node Elephant Architecture
@comment node-name, next, previous, up
- at chapter Elephant Design
+ at chapter Elephant Architecture
@cindex design
Elephant's early architecture was tightly coupled to the Berkeley DB
--- /project/elephant/cvsroot/elephant/doc/elephant.texinfo 2007/04/12 02:47:23 1.8
+++ /project/elephant/cvsroot/elephant/doc/elephant.texinfo 2007/04/21 17:22:35 1.9
@@ -20,8 +20,8 @@
@titlepage
@title Elephant User Manual
- at subtitle Elephant version 0.6.1
- at author Ben Lee and Ian Eslick
+ at subtitle Elephant version 0.9
+ at author Ian Eslick and Ben Lee
@c The following two commands
@c start the copyright page.
@@ -50,9 +50,9 @@
* Tutorial:: A basic ``getting started'' tutorial.
* Installation:: Installation and test-suite procedures.
* User Guide:: In depth discussion of all Elephant facilities and features.
-* Usage Scenarios:: Design scenarios for Elephant applications.
* User API Reference:: Function and class documentation of the user API.
-* Elephant Design:: An overview of elephant's internal architecture.
+* Design Patterns:: Design scenarios for Elephant applications.
+* Elephant Architecture:: An overview of elephant's internal architecture.
* Data Store API Reference:: Function level documentation for data store implementors.
* Copyright and License:: Your rights and freedoms.
@end menu
@@ -78,8 +78,8 @@
@include tutorial.texinfo
@include installation.texinfo
@include user-guide.texinfo
- at include scenarios.texinfo
@include reference.texinfo
+ at include scenarios.texinfo
@include elephant-design.texinfo
@include data-store-reference.texinfo
@include copying.texinfo
--- /project/elephant/cvsroot/elephant/doc/installation.texinfo 2007/04/12 02:47:23 1.9
+++ /project/elephant/cvsroot/elephant/doc/installation.texinfo 2007/04/21 17:22:35 1.10
@@ -9,9 +9,9 @@
* Requirements:: Supported lisps and required libraries.
* Configuring Elephant:: Setting up Elephant and the configuration file.
* Loading Elephant:: Loading Elephant and the data store loading protocol.
-* Berkeley DB Data Store:: Installing support for the Berkeley DB data store
+* Berkeley DB:: Installing support for the Berkeley DB data store
* Berkeley DB Example:: An example of installing and running the Berkeley DB data store.
-* CL-SQL Data Store:: Install and connecting to the CL-SQL data store
+* CL-SQL:: Install and connecting to the CL-SQL data store
* CL-SQL Example:: An example of using the CL-SQL data store.
* Elephant on Windows:: More details about running Elephant on Windows
* Test Suites:: How to run and interpret the output of the regression test suite
@@ -88,8 +88,8 @@
of you with asdf-install on your system)
In addition to these libraries, each data store has their own
-dependencies as discussed in @ref{Berkeley DB Data Store} and
- at ref{CL-SQL Data Store}.
+dependencies as discussed in @ref{Berkeley DB} and
+ at ref{CL-SQL}.
@node Configuring Elephant
@comment node-name, next, previous, up
@@ -224,9 +224,9 @@
database and return the @code{store-controller} subclass instance for
that backend.
- at node Berkeley DB Data Store
+ at node Berkeley DB
@comment node-name, next, previous, up
- at section Berkeley DB Data Store
+ at section Berkeley DB
The Berkeley DB Data Store started out as a very simple data dictionary in the
Berkeley Unix operating system. There are many ``Xdb'' systems that use the
@@ -275,9 +275,9 @@
in your application.
- at node CL-SQL Data Store
+ at node CL-SQL
@comment node-name, next, previous, up
- at section CL-SQL Data Store
+ at section CL-SQL
Although originally designed as an interface to the BerkeleyDB system,
the original Elephant system has been experimenetally extended to
--- /project/elephant/cvsroot/elephant/doc/make-ref.lisp 2007/04/12 02:47:23 1.8
+++ /project/elephant/cvsroot/elephant/doc/make-ref.lisp 2007/04/21 17:22:35 1.9
@@ -1,5 +1,7 @@
(require 'asdf)
(asdf:operate 'asdf:load-op 'elephant :force t)
+(in-package :elephant)
+
(load (merge-pathnames
#p"src/elephant/query"
(asdf:component-pathname (asdf:find-system 'elephant))))
@@ -19,8 +21,6 @@
(sb-posix:chdir include-dir-path)
(load docstrings-path)
-(in-package :elephant)
-
(defclass simple-store-controller (store-controller)
())
--- /project/elephant/cvsroot/elephant/doc/reference.texinfo 2007/04/12 02:47:23 1.10
+++ /project/elephant/cvsroot/elephant/doc/reference.texinfo 2007/04/21 17:22:35 1.11
@@ -8,8 +8,8 @@
@menu
* Store Controllers:: Connecting to a data store.
-* Persistent Class:: Defining persistent classes and creating and manipulating persistent indices.
-* Class Indexing:: Convenient indexing of persistent classes.
+* Persistent Objects:: Defining persistent classes and creating and manipulating persistent indices.
+* Persistent Object Indexing:: Convenient indexing of persistent classes.
* Persistent Sets:: Maintaining persistent collections the easy way.
@c * Query Interfaces:: Finding instances.
* BTrees:: BTrees and indices, a low level persistent data structure.
--- /project/elephant/cvsroot/elephant/doc/scenarios.texinfo 2007/04/19 22:25:51 1.6
+++ /project/elephant/cvsroot/elephant/doc/scenarios.texinfo 2007/04/21 17:22:35 1.7
@@ -11,7 +11,7 @@
* Persistent System Objects:: Making persistent objects a natural part of your system
* Elephant as Database:: Using Elephant as a database for records and user data instead of using a SQL relational Database
* Multithreaded Web Applications:: Elephant is a natural match for web applications
-* Graph-oriented Applications:: Elephant is good, but not optimized, for graph-oriented applications.
+ at c * Graph-oriented Applications:: Elephant is good, but not optimized, for graph-oriented applications.
* Real-World Application Examples:: See some real-world applications Elephant has been used for and a brief discussion of how it was used and any novel uses of Elephant.
@end menu
@@ -32,6 +32,92 @@
that they will be motivated to contribute design patterns of their own.
+ at node Persistent System Objects
+ at comment node-name, next, previous, up
+ at section Persistent System Objects
+
+The simplest design pattern supported by Elephant is the use of
+persistent objects in the place of standard objects. Typically you
+can just modify the old class definition to inherit the
+ at code{persistent-metaclass}. Depending on your application, objects
+may need to have transient slots for performance reasons. We'll
+create a dummy class to illustrate:
+
+ at lisp
+(defclass system-object ()
+ ((appname :accessor system-appname :initarg :name)
+ (url :accessor system-url :initarg :url)
+ (state :accessor system-state :initarg :state :initform 'idle))
+ (:metaclass persistent-metaclass))
+ at end lisp
+
+When starting up your application you need to recover references to
+any persistent objects that were created in a prior session or
+initialize a new one.
+
+If you are storing system objects in parameters, you can just call
+an initialization function on startup:
+
+ at lisp
+(defparameter *system* nil)
+
+(defun initialize-system (appname)
+ (let ((system-object (get-from-root '*system*)))
+ (setf *system
+ (if system-object system-object
+ (make-instance 'system-object :name appname)))))
+
+*system*
+=> #<SYSTEM-OBJECT ...>
+ at end lisp
+
+And now you can use your parameter as you did before. If you want to
+avoid calling initialization functions, you can just accesss system
+objects through functions instead of parameters.
+
+ at lisp
+(defparameter *system* nil)
+
+(defun sys-object ()
+ (unless *system
+ (let ((appname (get-application-name))
+ (url (get-system-url)))
+ (setf *system* (make-instance 'system-object :name appname :url url))))
+ *system*)
+
+(sys-object)
+=> #<SYSTEM-OBJECT ...>
+ at end lisp
+
+One constraint to keep in mind is that slot access will be slower as
+it has to synchronize to disk. This is usually not noticable for
+objects that are accessed on the order of seconds instead of
+milliseconds. For objects read constantly, but where you want to save
+any written values it helps to have a transient slot to cache values.
+You can override some methods to ensure that the persistent value is
+always updated, but that reads happen from the cached value and that
+the cached value is restored whenever the object is loaded.
+
+ at lisp
+(defclass system-object ()
+ ((appname :accessor system-appname :initarg :name)
+ (url :accessor system-url :initarg :url)
+ (laststate :accessor system-laststate :initarg :state :initform 'idle)
+ (state :accessor system-state :initarg :state :transient t)
+ (:metaclass persistent-metaclass))
+
+(defmethod (setf system-state) :after (state (sys system-state))
+ (setf (system-laststate sys) state))
+
+(defmethod initialize-instance :after ((sys system-state) &rest rest)
+ (declare (ignore rest))
+ (when (slot-boundp sys 'laststate)
+ (setf (system-state sys) (system-laststate sys))))
+ at end lisp
+
+And now you have an instant read cache for a slot value. This pattern
+is used several times within the Elephant implementation.
+
@node File System Replacement
@comment node-name, next, previous, up
@section File System Replacement
@@ -43,11 +129,14 @@
Because Elephant's serializer supports most lisp types, Elephant can
greatly simplify ease these concerns and allow you to work directly
with your natural in-memory representations with almost no work to
-encode/decode formats or manage files in the file system.
+encode/decode formats or manage files in the file
+system at footnote{Example provided by Ian Eslick, April 2007}.
The simplest way to accomplish this is to simply open a store
-controller and use the root btree as a key-value store instead of a
-file system directory. You might hide some of the details like this:
+controller and initialize a key-value pair in the root btree as a
+instead of a filename and file data in some system directory. Like
+the initialization process described for standard objects, you can
+hide some of the details like this:
@lisp
(defvar *resources* (make-hash-table))
@@ -97,7 +186,7 @@
conditions that allowed restarts that initialized values or allowed
users to update the hash in the background and continue computation.
- at footnote{Example provided by Ian Eslick, April 2007}
+
@node Checkpointing Conventional Program State
@comment node-name, next, previous, up
@@ -123,29 +212,27 @@
@subsection Assumptions
-To get speed, we want all our objects to be standard lisp objects that
-are in memory and have no special harnesses that would interfere with
-using the full power of lisp. At some point in execution, we want to
-store the current state of a bunch of objects to disk, but make it
-easy to reproduce the exact state at a later point in time. For
-simplicity, we'll assume that we are talking about collections of CLOS
-objects.
-
-An additional complication is that many programs have sets of
-interdependant objects. These could be complex program graphs, the
-state of an active search process or a standard OO system that uses a
-bunch of program objects to function. This means that we need to
-persist not just object state, but also references and any object that
-is referred to.
+To maintain processing speed and convenience we would like all our
+objects to be standard lisp objects without special harnesses that
+would interfere with applying the full power of lisp. At some point
+during execution, we want to store the current state of a set of
+objects to disk and yet make it easy to reproduce the original state
+at a later point in time. For simplicity, we'll limit ourselves
+to collections of CLOS objects.
+
+A complication is that many programs have sets of interdependant
+objects. These could be complex program graphs, the state of an
+ongoing search process or a standard OO system that uses a bunch of
+different program object types to run. This means that we need to
+persist not just object state, but also references to other objects.
Using CLOS reflection we can provide a general solution to capturing
objects, slot values and references. However to reproduce references,
-we'll need to be able to find the object referenced and the only
-general way to do that is to store it as well. Thus a snapshot is a
-closed set of self-referential objects.
+we'll need to be able to find the object referenced and the only way
+to do that is to store it as well. Thus we want to create a snapshot
+of a closed set of self-referential objects.
-The assumptions required to implement the simple checkpointing
-implemented here is:
+The assumptions underlying the snapshot mechanism is:
@itemize
@item @strong{Use standard CLOS objects and references to other CLOS objects.}
@@ -166,7 +253,149 @@
fine.
@end itemize
- at subsection Implementation: The Snapshot Set
+ at subsection Snapshot Set
+
+The snapshot implementation is called a @code{snapshot-set}. The next
+section will go into detail, but a walkthrough will help make it
+clearer at footnote{Example provided by Ian Eslick, April 2007}.
+
+A snapshot set is quite easy to use. Load the complete code and play
+with this simple walk through. The code can be located in the
+Elephant source tree under @code{src/conrib/eslick/snapshot-set.lisp}.
+
+The first step is to create a @code{snapshot-set} object,
+
+ at lisp
+(setf my-set (make-instance 'snapshot-set))
+ at end lisp
+
+and add it to the root so we don't lose track of it.
+
+ at lisp
+(add-to-root 'my-set my-set)
+ at end lisp
+
+Then we need some objects to play with.
+
+ at lisp
+(defclass my-test-class ()
+ ((value :accessor test-value :initarg :value)
+ (reference :accessor test-reference :initarg :reference)))
+
+(setf obj1 (make-instance 'my-test-class :value 1 :reference nil))
+(setf obj2 (make-instance 'my-test-class :value 2 :reference obj1))
+(setf obj3 (make-instance 'my-test-class :value 3 :reference obj2))
+
+(register-object obj3 my-set)
+(snapshot my-set)
+ at end lisp
+
+Now your set should have persistent versions of all three classes that
+are reachable from @code{obj3}.
+
+ at lisp
+(map-set (lambda (x) (print (test-value x))) my-set)
+=>
+3
+2
+1
+ at end lisp
+
+Of course such fully connected objects are not always common, so we'll
+demonstrate using hash tables to create root indexes into our objects
+and sidestep registration calls entirely. We'll create a fresh set to
+work with.
+
+ at lisp
+(setf my-set (make-instance 'snapshot-set))
+(add-to-root 'my-set my-set)
+
+(setf obj4 (make-instance 'my-test-class :value 4 :reference obj1))
+(setf obj5 (make-instance 'my-test-class :value 5 :reference nil))
+
+(setf hash (make-hash-table))
+(setf (snapshot-root my-set) hash)
+
+(setf (gethash 'obj3 hash) obj3)
+(setf (gethash 'obj4 hash) obj4)
+(setf (gethash 'obj5 hash) obj5)
+
+(snapshot my-set)
+ at end lisp
+
+To properly simulate restoring objects, we need to drop our old hash
+table as well as clear the persistent object cache so the snapshot set
+transient object is reset.
+
+ at lisp
+(setf my-set nil)
+(setf hash nil)
+(elephant::flush-instance-cache *store-controller*)
+ at end lisp
+
+Now we'll pretend we're startup up a new session.
+
+ at lisp
+(setf my-set (get-from-root 'my-set))
+(setf hash (snapshot-root my-set))
+ at end lisp
+
+The cache is automatically populated by the implicit @code{restore}
+call during snapshot-set initialization, and our hash table should now
+have all the proper references. We'll pull out a few.
+
+ at lisp
+(setf o4 (gethash 'obj4 hash))
+(setf o3 (gethash 'obj3 hash))
+(setf o2 (test-reference o3))
+
+(not (or (eq o4 obj4)
+ (eq o3 obj3)
+ (eq o2 obj2)))
+=> t
+ at end lisp
+
+The new objects should not be eq the old ones as we have restored
+fresh copies from the disk.
+
+If you review the setup above, @code{obj3} references @code{obj2}
+which references @code{obj1} and @code{obj4} also references
+ at code{obj1}. So if the objects were properly restored, these
+references should be @code{eq}.
+
+ at lisp
+(eq (test-reference o2) (test-reference o4))
+=> t
+ at end lisp
+
+And finally we can demonstrate the restorative power of snapshot sets.
+
+ at lisp
+(remhash 'obj5 hash)
+
+(gethash 'obj5 hash)
+=> nil nil
+
+(restore my-set)
+(setf hash (snapshot-root my-set))
+
+(gethash 'obj5 hash)
+=> #<MY-TEST-CLASS ..> t
+
+(test-value *)
+=> 5
+ at end lisp
+
+This means that while our set object was not reset, the restore
+operation properly restored the old reference structure of our root
+hash object. Unfortunately, in this implementation you have to reset
+your lisp pointers to get access to the restored objects.
+
+A future version could traverse the existing object cache, dropping
+new references and restoring old ones so that in-memory lisp pointers
+were still valid.
+
+ at subsection Snapshot Set Implementation
In this section we walk through the implementation of the snapshot set
in detail as it provides:
@@ -323,7 +552,7 @@
standard object would get an immediately serialized version rather
than a reference. This of course makes it impossible to restore
multiple references to a single object. The approach taken here is to
-instantiate a @emphasize{proxy} object which is a copy of the original
+instantiate a @emph{proxy} object which is a copy of the original
class and stores references to normal values in its slots. Any
references to hashes or standard classes are replaced with a reference
object that records the unique id of the object so it can be properly
@@ -391,144 +620,6 @@
obj)))
@end lisp
-A full set of source code for @code{snapshot-sets} can be found in the
-Elephant source tree under @code{src/conrib/eslick/snapshot-set.lisp}.
-
- at subsection Using Snapshot Sets
-
-A snapshot set is quite easy to use. Load the complete code and play
-with this simple walk through. First we need to create a set object,
-
- at lisp
-(setf my-set (make-instance 'snapshot-set))
- at end lisp
-
-and add it to the root so we don't lose track of it.
-
- at lisp
-(add-to-root 'my-set my-set)
- at end lisp
-
-Then we need some objects to play with.
-
- at lisp
-(defclass my-test-class ()
- ((value :accessor test-value :initarg :value)
- (reference :accessor test-reference :initarg :reference)))
-
-(setf obj1 (make-instance 'my-test-class :value 1 :reference nil))
-(setf obj2 (make-instance 'my-test-class :value 2 :reference obj1))
-(setf obj3 (make-instance 'my-test-class :value 3 :reference obj2))
-
-(register-object obj3 my-set)
-(snapshot my-set)
- at end lisp
-
-Now your set should have persistent versions of all three classes that
-are reachable from @code{obj3}.
-
- at lisp
-(map-set (lambda (x) (print (test-value x))) my-set)
-=>
-3
-2
-1
- at end lisp
-
-Of course such fully connected objects are not always common, so we'll
-demonstrate using hash tables to create root indexes into our objects
-and sidestep registration calls entirely. We'll create a fresh set to
-work with.
-
- at lisp
-(setf my-set (make-instance 'snapshot-set))
-(add-to-root 'my-set my-set)
-
-(setf obj4 (make-instance 'my-test-class :value 4 :reference obj1))
-(setf obj5 (make-instance 'my-test-class :value 5 :reference nil))
-
-(setf hash (make-hash-table))
-(setf (snapshot-root my-set) hash)
[286 lines skipped]
--- /project/elephant/cvsroot/elephant/doc/tutorial.texinfo 2007/04/12 02:47:23 1.16
+++ /project/elephant/cvsroot/elephant/doc/tutorial.texinfo 2007/04/21 17:22:35 1.17
@@ -1048,7 +1048,7 @@
more than two levels of transactional accesses with the top using
with-transaction and the bottom using ensure-transaction.
-See @ref{Transaction Details} for more details and @ref{Usage Scenarios}
+See @ref{Transaction Details} for more details and @ref{Design Patterns}
for examples of how systems can be designed and tuned using transactions.
@node Advanced Topics
@@ -1114,4 +1114,4 @@
lisps.
@end itemize
-Further, @pxref{Usage Scenarios} for information about Elephant design patterns, solutions to common problems and other scenarios with multiple possible solutions.
+Further, @pxref{Design Patterns} for information about Elephant design patterns, solutions to common problems and other scenarios with multiple possible solutions.
--- /project/elephant/cvsroot/elephant/doc/user-guide.texinfo 2007/04/12 02:47:23 1.11
+++ /project/elephant/cvsroot/elephant/doc/user-guide.texinfo 2007/04/21 17:22:35 1.12
@@ -12,8 +12,8 @@
* Class Indices:: In-depth discussion about indexing persistent indices.
@c * Querying persistent instances:: Retrieving instances of classes.
* Using BTrees:: Using the native btree.
-* Secondary Indices:: Alternative ways to index collections.
* Using Cursors:: Low-level access to BTrees.
+* BTree Indices:: Alternative ways to index collections.
* Transaction Details:: Develop a deeper understanding of transactions and avoid the pitfalls.
* Multi-repository Operation:: Specifying repositories.
* Multi-threaded Applications:: What considerations are required for safe multi-threading
@@ -23,6 +23,8 @@
* Performance Tuning:: How to get the most from Elephant.
* Berkeley DB Data Store:: Commands and concerns specific to the :BDB data store
* CL-SQL Data Store:: Commands and concerns specific to the :CLSQL data store
+* Postmodern Data Store::
+* Native Lisp Data Store::
@end menu
@node The Store Controller
@@ -280,7 +282,7 @@
to other objects can copy every reachable object! This is a direct
and dire consequence of the ``store-by-value'' restriction.
(@pxref{Persistent Classes and Objects} for how to design around the
-store-by-value restriction}).
+store-by-value restriction).
This list describes how aggregates are handled by the serializer.
@@ -332,19 +334,26 @@
@section Persistent Classes and Objects
Persistent classes are instances of the @code{persistent-metaclass}
-metaclass. All instances of this persistent class have a unique ID
-and a pointer to the @code{store-controller} specification they are
-associated with. Accesses to slot values become direct reads and
-writes to the data store and are thus always persisted. When the
-instance itself is writtent to the database, for example as a key or
-value in a @code{btree}, only the unique ID is stored.
-
-Thus serialization of persistent objects is exceedingly cheap compared
-to standard objects, but slot access can be much more expensive.
-Persistent objects are excellent at, for example, storing the link
-structure of a graph. A graph of persistent objects can itself be
-persisted by storing the head node of a fully-connected graph to the
-store controller root.
+metaclass. All persistent classes keep track of which slots are
+ at code{:persistent}, @code{:transient} and/or @code{:indexed} and are
+used as specializers in the persistence meta-object protocols
+(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.
+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.
+
+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.
@subsection Persistent Class Definition
@@ -352,10 +361,12 @@
@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.
+The @code{defpclass} macro is provided as a convenience to hide the
+ at code{:metaclass} slot option.
-Storage policies are specified by a boolean argument to the slot
-initargs @code{:persistent} or @code{:transient}. Slots are
- at code{:persistent} by default
+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 ()
@@ -365,15 +376,23 @@
(:metaclass persistent-metaclass))
@end lisp
+In the definition above, @code{pslot1} and @code{pslot2} are
+persistent while @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 to initargs. Transient
-slot values are never stored to nor loaded from the database.
+instance creation according to initforms or initargs. Transient slot
+values are never stored to nor loaded from the database.
-During a given lisp session transient values will be cached as long as
-they are not collected by the Lisps GC. After GC, if you retrieve an
-object from the store its transient slots will be reset to the slot
-initforms from the class definition.
+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
+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
+definition. You can only use @code{:initargs} to initialize transient
+or persistent slots during the initial call to @code{make-instance} or
+by manually creating the instance from an oid (see below).
@lisp
(setf pobj1 (make-instance 'my-pclass :pslot1 1 :tslot3 3))
@@ -403,27 +422,31 @@
@end lisp
The implications of this behavior is that you need to think carefully
-about using transient values. Primarily you cannot make assumptions
-about the state of transient values in objects loaded from the store
-unless you know that they were loaded and cannot be GC'ed.
-
-Finally, the index policy tells the data store whether to maintain an
-inverted index that maps slot values back to their parent objects.
-The :index options and behaviors of persistent classes are discussed in
-depth in @ref{Class Indices}.
+about how to use transient values. Essentially you cannot make
+assumptions about the state of transient values in objects loaded from
+the store unless you know that they were loaded and cannot be GC'ed.
+
+The @code{:index} option tells Elephant whether to maintain an
+inverted index that maps slot values to their parent objects. The
+behavior of indexed classes and class slots are discussed in depth in
+ at ref{Class Indices}.
@subsection Instance Creation
-Persistent objects are instances of the persistent classes defined
-above. All persistent objects inherit from the class
- at code{persistent} and share two properties: a unique ID and a
-reference to the specification of the @code{store-controller} in which
-they reside. This is ensured by the instance creation protocol
-implemented by @code{persistent-metaclass}.
+To the user, persistent objects are created as usual 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. This tells the
+metaobject protocol implementing persistent slot creation where to
+allocate storage for this instance's slots and
-Instances are created as normal, with a call to make-instance and
-appropriate initargs.
+* 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:
@@ -440,12 +463,60 @@
precedence over values in the database, which take precedences over
any @code{initforms} defined in the class.
-* Default store controller & instance creation
-* What happens to persistent objects when store-controller is closed?
+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?)
+
+ at subsection Class Redefinition
+
+This section discusses the appropriate model a user should employ in
+thinking about the behavior of persistent object when their clases are
+redefined.
+
+- What happens when you redefine a class online?
+- Drop & add slots? Change slot status?
+- What if you connect to an old database with a new class specification?
+ (ref to class indicies behavior)
+
+ at subsection Synchronizing Code and Database
+
+
+ at subsection Persistent objects and the MOP
+This section provides increased detail on the use of the MOP to create
+and support persistent objects.
+new slot types
+- transient-slot
+- persistent-slot
-:: User-defined persistent objects
+slot instantiation protocols
+- effective-slot-definition
+- direct-slot-definition-class
+- compute-effective-slot-definition
+- compute-effective-slot-definition-initargs
+
+class initialization protocols
+- shared-initialize :around (class)
+- finalize-inheritance :around (class)
+- reinitialize-instance :around (class)
+
+instance initialization protocols
+- initialize-instance :before (instance)
+- shared-initialize :around
+- update-instance-for-redefinied-class
+- update-instance-for-different-class
+
+slot access protocol
+- slot-value-using-class (setf)
+- slot-boundp-using-class
+- slot-makunbound-using-clas
+
+ at subsection Overriding methods on persistent objects
* slot types
* caching
@@ -458,20 +529,6 @@
the specification to work properly with persistent slots. However the
proper behavior has been verified on SBCL, Allegro and Lispworks.
-:: Initialization
-
-Also currently there is a bug where @code{initforms} are always
-evaluated, so beware. (What is the current model here?)
-
-:: Class Redefinition and Evolution
-
-* What happens when you redefine a class online?
-* Drop & add slots? Change slot status?
-* What if you connect to an old database with a new class specification?
- (ref to class indicies behavior)
-
-:: Storage and Performance Considerations
-
@node Class Indices
@comment node-name, next, previous, up
@section Class Indices
@@ -642,15 +699,15 @@
blocks of data is relatively inexpensive after a seek and comparisons
on objects that are stored in memory is cheap.
- at node Secondary Indices
+ at node Using Cursors
@comment node-name, next, previous, up
- at section Secondary Indices
+ at section Using Cursors
Empty.
- at node Using Cursors
+ at node BTree Indicies
@comment node-name, next, previous, up
- at section Using Cursors
+ at section BTree Indicies
Empty.
@@ -665,7 +722,6 @@
throwing a condition when @code{with-transaction} forms are nested
dynamically.
-
;; Transaction architecture:
;;
;; User and designer considerations:
@@ -847,28 +903,20 @@
@code{*inhibit-slot-writes*} in your user method using
@code{with-inhibited-slot-copy} a convenience macro.
- at node Garbage Collection
- at comment node-name, next, previous, up
- at section Garbage Collection
-
-GC is not implemented, but migration (@pxref{Repository Migration and
-Upgrade}) will consolidate storage and recover OIDs which emulates GC.
-No online solution is currently supported.
-
@node Performance Tuning
@comment node-name, next, previous, up
- at section Performance
+ at section Performance Tuning
Performance is usually measured in transactions per second. Database
reads are cheap. To get more transactions throughput, consider
setting
@lisp
-* (db-env-set-flags (controller-environment *store-controller*) 1
- :txn-nosync t)
+(db-env-set-flags (controller-environment *store-controller*)
+ 1 :txn-nosync t)
@end lisp
-or look at other flags in the sleepycat docs. This will greatly
+or look at other flags in the Berkeley DB docs. This will greatly
increase your throughput at the cost of some durability; I get around
a 100x improvement. Durability can be recovered with judicious use of
checkpointing and replication, though this is currently not supported
@@ -906,13 +954,29 @@
mode is not suitable for use in web servers or other typically
multi-threaded applications.
+ at node Garbage Collection
+ at comment node-name, next, previous, up
+ at section Garbage Collection
+
+GC is not implemented, but migration (@pxref{Repository Migration and
+Upgrade}) will consolidate storage and recover OIDs which emulates GC.
+No online solution is currently supported.
+
+
@node Berkeley DB Data Store
@comment node-name, next, previous, up
@section Berkeley DB Data Store
-
@node CL-SQL Data Store
@comment node-name, next, previous, up
@section CL-SQL Data Store
+
+ at node Postmodern Data Store
+ at comment node-name, next, previous, up
+ at section Postmodern Data Store
+
+ at node Native Lisp Data Store
+ at comment node-name, next, previous, up
+ at section Native Lisp Data Store
More information about the Elephant-cvs
mailing list