See also: cl-prevalence.
Most stuff here from the Common Lisp Prevalence website. This code was written by Sven Van Caekenberghe using OpenMCL, an open source Common Lisp implementation for MacOS X (Darwin) and LinuxPPC. CMUCL is known to run this code successfully.
Release 1, June 10, 2003: First Public Release
This is a proof of concept implementation of Object Prevalence. Object Prevalence is a simple but interesting concept first proposed by Klaus Wuestefeld in 2001. IBM developerWorks has a reasonable Introduction to Object Prevalence article. (But see also the 1987 paper by Birrell, Jones and Wobber entitled A Simple and Efficient Implementation for Small Databases where most of these concepts are worked out in detail minus the cool sounding name! gwking).
The main Java implementation is called Prevayler, and it's available from here. Prevayler claims whopping benchmarks, because it stores objects in RAM. However, Prevayler garantees that "if you pull the plug, your object will 'prevail' ." (This quote from Klaus from a magazine article).
- Most databases are only a couple of hundreds of megabytes big, often even less.
- Most computers can easily take a couple of hundreds of megabytes of data in RAM, big servers can hold many gigabytes.
- Mapping objects to databases is at least tedious and time consuming, but often also complex and error prone.
- Let's throw away the database and just consider the domain model objects as the database.
- Let's make sure we can serialize and deserialize our objects to and from a some persistent medium such as a file system.
- If we store our complete set of domain model objects to a persistent medium we create a snapshot.
- We query by using the data structure manipulation functionality of our programming language, running from RAM, queries will be extremely fast.
- Let's agree to only change our object model using transaction objects that combine the data and the functionality to execute the transaction.
- In order to preserve the ACID properties of our system, we log each transaction to some persistent medium by serializing it after we execute it. The is called the transaction log.
- When the system goes down (intentionally or unintentionally) we restore its latest state by first reading in the latest snapshot and by re-executing each transaction from the transaction log.
- Transactions must be deterministic and re-entrant (so they also need to record the current time if necessary).
- In a multi-threaded system, transactions are globally serialized.
NOTE: This is exactly what Smalltalk does (before 2001 :).
Another try at common lisp prevalence is available at the bknr website. It doesn't use XML serialization as Sven's code does, but instead writes LISP snapshot and transaction-log files that can be restored using
An alternative to prevalence use an object database like Elephant. Elephant is transparent like prevalence (automatically serializing lisp values) but backed by Sleepycat/Berkeley DB, an embedded database, as well as relational databases. Since the cache is mapped to in-process memory, reads are very fast. Sleepycat is very mature, and supports many advanced features.
The simplest way to do a web site with persistent data is just to use the reader and printer to serialize your objects. You can go more complex than that, if you want, and that's what bknr does, for instance. lisppaste serializes its transactions as XML; cl-blog just uses serialized sexprs. I have no idea what cliki looks like on disk.
manardb may be a more efficient implementation of prevalence; it can also store very large datasets.