Commit ba7bc537 authored by Tim Peters's avatar Tim Peters

Act as if a 3.3c1 release were being made. Maybe it will

be.  Besides "the usual" release fiddling, repaired many
out-of-date pieces of the ZODB programming guide; I'm sure
many remain, though.
parent 5bb7199b
What's new in ZODB3 3.3 ? What's new in ZODB3 3.3 release candidate 1?
========================= ============================================
Release date: DD-MMM-YYYY Release date: 14-Sep-2004
Connection Connection
---------- ----------
ZODB intends to raise ConnnectionStateError if an attempt is made to close ZODB intends to raise ``ConnnectionStateError`` if an attempt is made to
a connection while modifications are pending (the connection is involved in close a connection while modifications are pending (the connection is
a transaction that hasn't been ``abort()``'ed or ``commit()``'ed). It was involved in a transaction that hasn't been ``abort()``'ed or
missing the case where the only pending modifications were made in ``commit()``'ed). It was missing the case where the only pending
subtransactions. This has been fixed. If an attempt to close a connection modifications were made in subtransactions. This has been fixed. If an
with pending subtransactions is made now:: attempt to close a connection with pending subtransactions is made now::
ConnnectionStateError: Cannot close a connection with a pending subtransaction ConnnectionStateError: Cannot close a connection with a pending subtransaction
...@@ -91,7 +91,7 @@ transaction ...@@ -91,7 +91,7 @@ transaction
>>> ... >>> ...
>>> txn.commit() >>> txn.commit()
can't work as intended ib 3.3, because ``txn`` is no longer the current can't work as intended in 3.3, because ``txn`` is no longer the current
``Transaction`` object the instant ``txn.begin()`` returns. ``Transaction`` object the instant ``txn.begin()`` returns.
BTrees BTrees
...@@ -110,12 +110,12 @@ Collector #1488 (TemporaryStorage -- going backward in time). This ...@@ -110,12 +110,12 @@ Collector #1488 (TemporaryStorage -- going backward in time). This
confusion was really due to that the detail on a ConflictError exception confusion was really due to that the detail on a ConflictError exception
didn't make sense. It called the current revision "was", and the old didn't make sense. It called the current revision "was", and the old
revision "now". The detail is much more informative now. For example, revision "now". The detail is much more informative now. For example,
if the exception said: if the exception said::
ConflictError: database conflict error (oid 0xcb22, ConflictError: database conflict error (oid 0xcb22,
serial was 0x03441422948b4399, now 0x034414228c3728d5) serial was 0x03441422948b4399, now 0x034414228c3728d5)
before, it now says: before, it now says::
ConflictError: database conflict error (oid 0xcb22, ConflictError: database conflict error (oid 0xcb22,
serial this txn started with 0x034414228c3728d5 2002-04-14 20:50:32.863000, serial this txn started with 0x034414228c3728d5 2002-04-14 20:50:32.863000,
...@@ -131,20 +131,20 @@ the old serial). ...@@ -131,20 +131,20 @@ the old serial).
Tools Tools
----- -----
FileStorage.FileIterator was confused about how to read a transaction's ``FileStorage.FileIterator`` was confused about how to read a transaction's
user and description fields, which caused several tools to display user and description fields, which caused several tools to display
binary gibberish for these values. binary gibberish for these values.
ZODB.utils.oid_repr() changed to add a leading "0x", and to strip leading ``ZODB.utils.oid_repr()`` changed to add a leading "0x", and to strip
zeroes. This is used, e.g., in the detail of a POSKeyError exception, to leading zeroes. This is used, e.g., in the detail of a ``POSKeyError``
identify the missing oid. Before, the output was ambiguous. For example, exception, to identify the missing oid. Before, the output was ambiguous.
oid 17 was displayed as 0000000000000011. As a Python integer, that's For example, oid 17 was displayed as 0000000000000011. As a Python
octal 9. Or was it meant to be decimal 11? Or was it meant to be hex? integer, that's octal 9. Or was it meant to be decimal 11? Or was it
Now it displays as 0x11. meant to be hex? Now it displays as 0x11.
fsrefs.py: fsrefs.py:
When run with -v, produced tracebacks for objects whose creation was When run with ``-v``, produced tracebacks for objects whose creation was
merely undone. This was confusing. Tracebacks are now produced only merely undone. This was confusing. Tracebacks are now produced only
if there's "a real" problem loading an oid. if there's "a real" problem loading an oid.
...@@ -156,13 +156,13 @@ fsrefs.py: ...@@ -156,13 +156,13 @@ fsrefs.py:
Now makes two passes, so that an accurate report can be given of all Now makes two passes, so that an accurate report can be given of all
invalid references. invalid references.
analyze.py produced spurious "len of unsized object" messages when ``analyze.py`` produced spurious "len of unsized object" messages when
finding a data record for an object uncreation or version abort. These finding a data record for an object uncreation or version abort. These
no longer appear. no longer appear.
fsdump.py's get_pickle_metadata() function (which is used by several ``fsdump.py``'s ``get_pickle_metadata()`` function (which is used by several
tools) was confused about what to do when the ZODB pickle started with tools) was confused about what to do when the ZODB pickle started with
a pickle GLOBAL opcode. It actually loaded the class then, which it a pickle ``GLOBAL`` opcode. It actually loaded the class then, which it
intends never to do, leading to stray messages on stdout when the class intends never to do, leading to stray messages on stdout when the class
wasn't available, and leading to a strange return value even when it was wasn't available, and leading to a strange return value even when it was
available (the repr of the type object was returned as "the module name", available (the repr of the type object was returned as "the module name",
......
ZODB3 3.3 beta 2 ZODB3 3.3 release candidate 1
================ =============================
Introduction Introduction
------------ ------------
......
...@@ -239,15 +239,25 @@ transaction.commit() ...@@ -239,15 +239,25 @@ transaction.commit()
\end{verbatim} \end{verbatim}
The \module{transaction} module defines a few top-level functions for The \module{transaction} module defines a few top-level functions for
working with transactions. \method{commit()} writes any modified working with transactions. \function{commit()} writes any modified
objects to disk, making the changes permanent. \method{abort()} rolls objects to disk, making the changes permanent. \function{abort()} rolls
back any changes that have been made, restoring the original state of back any changes that have been made, restoring the original state of
the objects. If you're familiar with database transactional the objects. If you're familiar with database transactional
semantics, this is all what you'd expect. \method{get()} returns a semantics, this is all what you'd expect. \function{get()} returns a
\class{Transaction} object that has additional methods like \class{Transaction} object that has additional methods like
\method{status()}, to check the current state of the transaction, and
\method{note()}, to add a note to the transaction metadata. \method{note()}, to add a note to the transaction metadata.
More precisely, the \module{transaction} module exposes an instance of
the \class{ThreadTransactionManager} transaction manager class as
\code{transaction.manager}, and the \module{transaction} functions
\function{get()} and \function{begin()} redirect to the same-named
methods of \code{transaction.manager}. The \function{commit()} and
\function{abort()} functions apply the methods of the same names to
the \class{Transaction} object returned by \code{transaction.manager.get()}.
This is for convenience. It's also possible to create your own transaction
manager instances, and to tell \code{DB.open()} to use your transaction
manager instead.
Because the integration with Python is so complete, it's a lot like Because the integration with Python is so complete, it's a lot like
having transactional semantics for your program's variables, and you having transactional semantics for your program's variables, and you
can experiment with transactions at the Python interpreter's prompt: can experiment with transactions at the Python interpreter's prompt:
......
...@@ -4,12 +4,36 @@ ...@@ -4,12 +4,36 @@
% Undoing % Undoing
% Versions % Versions
% Multithreaded ZODB Programs % Multithreaded ZODB Programs
\section{Transactions and Versioning} \section{Transactions and Versioning}
%\subsection{Committing and Aborting} \subsection{Committing and Aborting}
% XXX There seems very little to say about commit/abort...
Changes made during a transaction don't appear in the database until
the transaction commits. This is done by calling the \method{commit()}
method of the current \class{Transaction} object, where the latter is
obtained from the \method{get()} method of the current transaction
manager. If the default thread transaction manager is being used, then
\code{transaction.commit()} suffices.
Similarly, a transaction can be explicitly aborted (all changes within
the transaction thrown away) by invoking the \method{abort()} method
of the current \class{Transaction} object, or simply
\code{transaction.abort()} if using the default thread transaction manager.
Prior to ZODB 3.3, if a commit failed (meaning the \code{commit()} call
raised an exception), the transaction was implicitly aborted and a new
transaction was implicitly started. This could be very surprising if the
exception was suppressed, and especially if the failing commit was one
in a sequence of subtransaction commits.
So, starting with ZODB 3.3, if a commit fails, all further attempts to
commit, join, or register with the transaction raise
\exception{ZODB.POSException.TransactionFailedError}. You must explicitly
start a new transaction then, either by calling the \method{abort()} method
of the current transaction, or by calling the \method{begin()} method of the
current transaction's transaction manager.
\subsection{Subtransactions} \subsection{Subtransactions}
...@@ -29,20 +53,20 @@ performed at intervals, say, every 10,000 objects. Those 10,000 ...@@ -29,20 +53,20 @@ performed at intervals, say, every 10,000 objects. Those 10,000
objects are then written to permanent storage and can be purged from objects are then written to permanent storage and can be purged from
the cache to free more space. the cache to free more space.
To commit a subtransaction instead of a full transaction, To commit a subtransaction instead of a full transaction,
pass a true value to the \method{commit()} pass a true value to the \method{commit()}
or \method{abort()} method of the \class{Transaction} object. or \method{abort()} method of the \class{Transaction} object.
\begin{verbatim} \begin{verbatim}
# Commit a subtransaction # Commit a subtransaction
get_transaction().commit(1) transaction.commit(True)
# Abort a subtransaction # Abort a subtransaction
get_transaction().abort(1) transaction.abort(True)
\end{verbatim} \end{verbatim}
A new subtransaction is automatically started on committing or A new subtransaction is automatically started upon successful committing
aborting the previous subtransaction. or aborting the previous subtransaction.
\subsection{Undoing Changes} \subsection{Undoing Changes}
...@@ -57,7 +81,7 @@ storage instance. ...@@ -57,7 +81,7 @@ storage instance.
If a database supports undo, then the \method{undoLog(\var{start}, If a database supports undo, then the \method{undoLog(\var{start},
\var{end}\optional{, func})} method on the \class{DB} instance returns \var{end}\optional{, func})} method on the \class{DB} instance returns
the log of past transactions, returning transactions between the times the log of past transactions, returning transactions between the times
\var{start} and \var{end}, measured in seconds from the epoch. \var{start} and \var{end}, measured in seconds from the epoch.
If present, \var{func} is a function that acts as a filter on the If present, \var{func} is a function that acts as a filter on the
transactions to be returned; it's passed a dictionary representing transactions to be returned; it's passed a dictionary representing
each transaction, and only transactions for which \var{func} returns each transaction, and only transactions for which \var{func} returns
...@@ -65,7 +89,7 @@ true will be included in the list of transactions returned to the ...@@ -65,7 +89,7 @@ true will be included in the list of transactions returned to the
caller of \method{undoLog()}. The dictionary contains keys for caller of \method{undoLog()}. The dictionary contains keys for
various properties of the transaction. The most important keys are various properties of the transaction. The most important keys are
\samp{id}, for the transaction ID, and \samp{time}, for the time at \samp{id}, for the transaction ID, and \samp{time}, for the time at
which the transaction was committed. which the transaction was committed.
\begin{verbatim} \begin{verbatim}
>>> print storage.undoLog(0, sys.maxint) >>> print storage.undoLog(0, sys.maxint)
...@@ -83,7 +107,7 @@ which the transaction was committed. ...@@ -83,7 +107,7 @@ which the transaction was committed.
To store a description and a user name on a commit, get the current To store a description and a user name on a commit, get the current
transaction and call the \method{note(\var{text})} method to store a transaction and call the \method{note(\var{text})} method to store a
description, and the description, and the
\method{setUser(\var{user_name})} method to store the user name. \method{setUser(\var{user_name})} method to store the user name.
While \method{setUser()} overwrites the current user name and replaces While \method{setUser()} overwrites the current user name and replaces
it with the new value, the \method{note()} method always adds the text it with the new value, the \method{note()} method always adds the text
to the transaction's description, so it can be called several times to to the transaction's description, so it can be called several times to
...@@ -91,8 +115,8 @@ log several different changes made in the course of a single ...@@ -91,8 +115,8 @@ log several different changes made in the course of a single
transaction. transaction.
\begin{verbatim} \begin{verbatim}
get_transaction().setUser('amk') transaction.get().setUser('amk')
get_transaction().note('Change ownership') transaction.get().note('Change ownership')
\end{verbatim} \end{verbatim}
To undo a transaction, call the \method{DB.undo(\var{id})} method, To undo a transaction, call the \method{DB.undo(\var{id})} method,
...@@ -115,6 +139,11 @@ that calls undo may not see the changes to the object until it calls ...@@ -115,6 +139,11 @@ that calls undo may not see the changes to the object until it calls
\subsection{Versions} \subsection{Versions}
\begin{notice}[warning]
Versions should be avoided. They're going to be deprecated,
replaced by better approaches to long-running transactions.
\end{notice}
While many subtransactions can be contained within a single regular While many subtransactions can be contained within a single regular
transaction, it's also possible to contain many regular transactions transaction, it's also possible to contain many regular transactions
within a long-running transaction, called a version in ZODB within a long-running transaction, called a version in ZODB
...@@ -155,7 +184,7 @@ different version or from an unversioned connection will cause a ...@@ -155,7 +184,7 @@ different version or from an unversioned connection will cause a
from ZODB.POSException import VersionLockError from ZODB.POSException import VersionLockError
try: try:
get_transaction().commit() transaction.commit()
except VersionLockError, (obj_id, version): except VersionLockError, (obj_id, version):
print ('Cannot commit; object %s ' print ('Cannot commit; object %s '
'locked by version %s' % (obj_id, version)) 'locked by version %s' % (obj_id, version))
...@@ -169,5 +198,5 @@ the version having a lock on it. ...@@ -169,5 +198,5 @@ the version having a lock on it.
ZODB databases can be accessed from multithreaded Python programs. ZODB databases can be accessed from multithreaded Python programs.
The \class{Storage} and \class{DB} instances can be shared among The \class{Storage} and \class{DB} instances can be shared among
several threads, as long as individual \class{Connection} instances several threads, as long as individual \class{Connection} instances
are created for each thread. are created for each thread.
...@@ -99,6 +99,7 @@ transaction: ...@@ -99,6 +99,7 @@ transaction:
\begin{verbatim} \begin{verbatim}
from ZEO import ClientStorage from ZEO import ClientStorage
from ZODB import DB from ZODB import DB
import transaction
# Change next line to connect to your ZEO server # Change next line to connect to your ZEO server
addr = 'kronos.example.com', 1975 addr = 'kronos.example.com', 1975
...@@ -112,7 +113,7 @@ root['list'] = ['a', 'b', 1.0, 3] ...@@ -112,7 +113,7 @@ root['list'] = ['a', 'b', 1.0, 3]
root['dict'] = {'a':1, 'b':4} root['dict'] = {'a':1, 'b':4}
# Commit the transaction # Commit the transaction
get_transaction().commit() transaction.commit()
\end{verbatim} \end{verbatim}
If this code runs properly, then your ZEO server is working correctly. If this code runs properly, then your ZEO server is working correctly.
......
\documentclass{howto} \documentclass{howto}
\title{ZODB/ZEO Programming Guide} \title{ZODB/ZEO Programming Guide}
\release{3.3b2} \release{3.3c1}
\date{\today} \date{\today}
\author{A.M.\ Kuchling} \author{A.M.\ Kuchling}
......
No preview for this file type
...@@ -216,7 +216,7 @@ class MyDistribution(Distribution): ...@@ -216,7 +216,7 @@ class MyDistribution(Distribution):
doclines = __doc__.split("\n") doclines = __doc__.split("\n")
setup(name="ZODB3", setup(name="ZODB3",
version="3.3b2", version="3.3c1",
maintainer="Zope Corporation", maintainer="Zope Corporation",
maintainer_email="zodb-dev@zope.org", maintainer_email="zodb-dev@zope.org",
url = "http://www.zope.org/Wikis/ZODB", url = "http://www.zope.org/Wikis/ZODB",
......
...@@ -22,4 +22,4 @@ ZEO is now part of ZODB; ZODB's home on the web is ...@@ -22,4 +22,4 @@ ZEO is now part of ZODB; ZODB's home on the web is
""" """
# The next line must use double quotes, so release.py recognizes it. # The next line must use double quotes, so release.py recognizes it.
version = "2.3b2" version = "2.3c1"
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
############################################################################## ##############################################################################
# The next line must use double quotes, so release.py recognizes it. # The next line must use double quotes, so release.py recognizes it.
__version__ = "3.3b2" __version__ = "3.3c1"
import sys import sys
import __builtin__ import __builtin__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment