[Checkins] SVN: zc.beforestorage/tags/0.1.1/doc.txt Removed unwanted title.

Jim Fulton jim at zope.com
Thu Feb 7 13:10:26 EST 2008


Log message for revision 83632:
  Removed unwanted title.
  

Changed:
  A   zc.beforestorage/tags/0.1.1/doc.txt

-=-
Added: zc.beforestorage/tags/0.1.1/doc.txt
===================================================================
--- zc.beforestorage/tags/0.1.1/doc.txt	                        (rev 0)
+++ zc.beforestorage/tags/0.1.1/doc.txt	2008-02-07 18:10:26 UTC (rev 83632)
@@ -0,0 +1,293 @@
+==============
+Before Storage
+==============
+
+ZODB storages typically store multiple object revisions to support
+features such as multi-version concurrency control and undo.  In the
+case of the mod popular storage implementation, old revisions aren't
+discarded until a pack.  This feature has often been exploited to
+perform time travel, allowing one to look at a database as it existed
+in at some point in time.  In the past, this has been possible with
+file storage by specifying a time at which to open the file
+storage. This works fairly well, but is very slow for large databases
+because existing index files can't easily be used.  Time travel is
+also supported for individual objects through the ZODB history
+mechanism.
+
+The introduction of multi-version concurrency control provided new
+opertunities for time travel.  Using the storage loadBefore method,
+one can load transaction records written before a given time.  ZODB
+3.9 will provide an option to the database open method for opening
+connections as of a point in time.
+
+Demo storage can be quite useful for testing, and especially staging
+applications. In a common configuration, they allow for storing
+changes to a base database without changing the underlying database.
+Zope functional testing frameworks leverage demo storages to easily
+roll-back database state after a test to a non-empty state before a
+test.  A significant limitation of demo storages is that they can't be
+used with base storages that change.  This means that they generaly
+can't be used with ZEO.  It isn't enough to have a read-only
+connecttions, if the underlying database is still being changed by
+other clients.
+
+The "before" storage provides another way to leverage the loadBefore
+method to support time travel and a means to provide an unchanging
+view into a ZEO server.  A before storage is a database adapter that
+provides a read-only view of an underlying storage as of a particular
+point in time.
+
+Change history
+==============
+
+0.1.1 (2008-02-07)
+******************
+
+Fixed a packaging bug that caused some files to be omitted.
+
+0.1 (2008-01-??)
+----------------
+
+Initial release.
+
+Using ZConfig to configure Before storages
+==========================================
+
+To use before storages from ZConfig configuration files, you need to
+import zc.beforestorage and then use a before storage section.
+
+    >>> import ZODB.config
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %import zc.beforestorage
+    ...
+    ... <before>
+    ...     before 2008-01-21
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """)
+
+    >>> storage
+    <Before: my.fs before 2008-01-21 00:00:00.000000>
+
+    >>> storage.close()
+
+If we leave off the before option, we'll use the current time:
+
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %import zc.beforestorage
+    ...
+    ... <before>
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """)
+
+    >>> storage
+    <Before: my.fs before 2008-01-21 18:22:48.000000>
+
+    >>> storage.close()
+
+Demonstration (doctest)
+=======================
+
+Note that most people will configure the storage through ZConfig.  If
+you are one of those people, you may want to stop here. :)  The
+examples below show you how to use the storage from Python, but they
+also exercise lots of details you might not be interested in.
+
+To see how this works at the Python level, we'll create a file
+storage, and use a before storage to provide views on it.
+
+    >>> import ZODB.FileStorage
+    >>> fs = ZODB.FileStorage.FileStorage('Data.fs')
+    >>> from ZODB.DB import DB
+    >>> db = DB(fs)
+    >>> conn = db.open()
+    >>> root = conn.root()
+    >>> import persistent.mapping
+    
+We'll record transaction identifiers, which we'll use to when opening
+the before storage.
+
+    >>> import transaction
+    >>> transactions = [root._p_serial]
+    >>> for i in range(1, 11):
+    ...     root[i] = persistent.mapping.PersistentMapping()
+    ...     transaction.get().note("trans %s" % i)
+    ...     transaction.commit()
+    ...     transactions.append(root._p_serial)
+
+We create a before storage by calling the Before constructer
+with an existing storage and a timestamp:
+
+    >>> import zc.beforestorage
+    >>> b5 = zc.beforestorage.Before(fs, transactions[5])
+    >>> db5 = DB(b5)
+    >>> conn5 = db5.open()
+    >>> root5 = conn5.root()
+    >>> len(root5)
+    4
+
+here we see the database as it was before the 5th transaction was
+committed.  If we try to access a later object, we'll get a
+POSKeyError:
+
+    >>> conn5.get(root[5]._p_oid)
+    Traceback (most recent call last):
+    ...
+    POSKeyError: 0x05
+
+Similarly, while we can access earlier object revisions, we can't
+access revisions at the before time or later:
+
+    >>> _ = b5.loadSerial(root._p_oid, transactions[2])
+
+    >>> b5.loadSerial(root._p_oid, transactions[5])
+    Traceback (most recent call last):
+    ...
+    POSKeyError: 0x00
+    
+    >>> conn5.get(root[5]._p_oid)
+    Traceback (most recent call last):
+    ...
+    POSKeyError: 0x05
+
+Let's run through the storage methods:
+
+    >>> b5.getName()
+    'Data.fs before 2008-01-21 18:22:56.000000'
+
+    >>> b5.getSize() == fs.getSize()
+    True
+
+    >>> for hd in b5.history(root._p_oid, size=3):
+    ...     print hd['description']
+    trans 4
+    trans 3
+    trans 2
+
+    >>> b5.isReadOnly()
+    True
+
+    >>> transactions[4] <= b5.lastTransaction() < transactions[5]
+    True
+
+    >>> len(b5) == len(fs)
+    True
+
+    >>> p, s1, s2 = b5.loadBefore(root._p_oid, transactions[5])
+    >>> p == fs.loadSerial(root._p_oid, transactions[4])
+    True
+    >>> s1 == transactions[4]
+    True
+    >>> s2 is None
+    True
+
+    >>> p, s1, s2 = b5.loadBefore(root._p_oid, transactions[4])
+    >>> p == fs.loadSerial(root._p_oid, transactions[3])
+    True
+    >>> s1 == transactions[3]
+    True
+    >>> s2 == transactions[4]
+    True
+
+    >>> b5.lastTid(root._p_oid) == transactions[4]
+    True
+
+    >>> b5.new_oid()
+    Traceback (most recent call last):
+    ...
+    ReadOnlyError
+
+    >>> from ZODB.TimeStamp import TimeStamp
+    >>> b5.pack(TimeStamp(transactions[3]).timeTime(), lambda p: [])
+    Traceback (most recent call last):
+    ...
+    ReadOnlyError
+    
+    >>> b5.registerDB(db5)
+
+    >>> b5.sortKey() == fs.sortKey()
+    True
+
+    >>> b5.tpc_begin(transaction.get())
+    Traceback (most recent call last):
+    ...
+    ReadOnlyError
+
+    >>> b5.store(root._p_oid, transactions[4], b5.load(root._p_oid)[0], '',
+    ...          transaction.get())
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    StorageTransactionError: ...
+
+    >>> b5.tpc_vote(transaction.get())
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    StorageTransactionError: ...
+
+    >>> b5.tpc_finish(transaction)
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    ...
+    StorageTransactionError: ...
+
+    >>> b5.tpc_transaction()
+    >>> b5.tpc_abort(transaction)
+
+Before storages don't support undo:
+
+    >>> b5.supportsUndo
+    Traceback (most recent call last):
+    ...
+    AttributeError: Before instance has no attribute 'supportsUndo'
+
+(Don't even ask about versions. :)
+
+Closing a before storage closes the underlying storage:
+
+    >>> b5.close()
+    >>> fs.load(root._p_oid, '')
+    Traceback (most recent call last):
+    ...
+    ValueError: I/O operation on closed file
+
+If we ommit a timestamp when creating a before storage, the current
+time will be used:
+
+    >>> fs = ZODB.FileStorage.FileStorage('Data.fs')
+    >>> from ZODB.DB import DB
+    >>> db = DB(fs)
+    >>> conn = db.open()
+    >>> root = conn.root()
+
+    >>> bnow = zc.beforestorage.Before(fs)
+    >>> dbnow = DB(bnow)
+    >>> connnow = dbnow.open()
+    >>> rootnow = connnow.root()
+    
+    >>> for i in range(1, 11):
+    ...     root[i] = persistent.mapping.PersistentMapping()
+    ...     transaction.get().note("trans %s" % i)
+    ...     transaction.commit()
+    ...     transactions.append(root._p_serial)
+    
+    >>> len(rootnow)
+    10
+
+The timestamp may be passed directory, or as an ISO time.  For
+example:
+
+    >>> b5 = zc.beforestorage.Before(fs, '2008-01-21T18:22:56')
+    >>> db5 = DB(b5)
+    >>> conn5 = db5.open()
+    >>> root5 = conn5.root()
+    >>> len(root5)
+    4


Property changes on: zc.beforestorage/tags/0.1.1/doc.txt
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list