[Zodb-checkins] SVN: ZODB/branches/3.4/src/ Interface repairs,
of many kinds.
Tim Peters
tim.one at comcast.net
Mon Apr 25 18:02:07 EDT 2005
Log message for revision 30179:
Interface repairs, of many kinds.
Changed:
U ZODB/branches/3.4/src/ZODB/Connection.py
U ZODB/branches/3.4/src/transaction/interfaces.py
-=-
Modified: ZODB/branches/3.4/src/ZODB/Connection.py
===================================================================
--- ZODB/branches/3.4/src/ZODB/Connection.py 2005-04-25 21:59:11 UTC (rev 30178)
+++ ZODB/branches/3.4/src/ZODB/Connection.py 2005-04-25 22:02:07 UTC (rev 30179)
@@ -330,8 +330,8 @@
# the savepoint, then they won't have _p_oid or _p_jar after
# they've been unadded. This will make the code in _abort
# confused.
-
+
self._abort()
if self._savepoint_storage is not None:
@@ -341,7 +341,7 @@
def _abort(self):
"""Abort a transaction and forget all changes."""
-
+
for obj in self._registered_objects:
oid = obj._p_oid
assert oid is not None
@@ -444,7 +444,7 @@
self._commit_savepoint(transaction)
# No need to call _commit since savepoint did.
-
+
else:
self._commit(transaction)
@@ -575,7 +575,7 @@
if self._savepoint_storage is not None:
self._abort_savepoint()
-
+
self._storage.tpc_abort(transaction)
# Note: If we invalidate a non-justifiable object (i.e. a
@@ -626,11 +626,15 @@
def tpc_finish(self, transaction):
"""Indicate confirmation that the transaction is done."""
+
def callback(tid):
- d = {}
- for oid in self._modified:
- d[oid] = 1
+ d = dict.fromkeys(self._modified)
self._db.invalidate(tid, d, self)
+# It's important that the storage calls the passed function
+# while it still has its lock. We don't want another thread
+# to be able to read any updated data until we've had a chance
+# to send an invalidation message to all of the other
+# connections!
self._storage.tpc_finish(transaction, callback)
self._tpc_cleanup()
@@ -653,7 +657,7 @@
# Transaction-manager synchronization -- ISynchronizer
##########################################################################
-
+
##########################################################################
# persistent.interfaces.IPersistentDatamanager
@@ -815,7 +819,7 @@
# registering the object, because joining may take a
# savepoint, and the savepoint should not reflect the change
# to the object.
-
+
if self._needs_to_join:
self._txn_mgr.get().join(self)
self._needs_to_join = False
@@ -823,7 +827,7 @@
if obj is not None:
self._registered_objects.append(obj)
-
+
# persistent.interfaces.IPersistentDatamanager
##########################################################################
@@ -1076,11 +1080,11 @@
def __init__(self, base_version, storage):
self._storage = storage
for method in (
- 'getName', 'new_oid', 'modifiedInVersion', 'getSize',
+ 'getName', 'new_oid', 'modifiedInVersion', 'getSize',
'undoLog', 'versionEmpty', 'sortKey',
):
setattr(self, method, getattr(storage, method))
-
+
self._base_version = base_version
self._file = tempfile.TemporaryFile()
# position: current file position
@@ -1089,7 +1093,7 @@
# index: map oid to pos of last committed version
self.index = {}
self.creating = []
-
+
def __len__(self):
return len(self.index)
Modified: ZODB/branches/3.4/src/transaction/interfaces.py
===================================================================
--- ZODB/branches/3.4/src/transaction/interfaces.py 2005-04-25 21:59:11 UTC (rev 30178)
+++ ZODB/branches/3.4/src/transaction/interfaces.py 2005-04-25 22:02:07 UTC (rev 30179)
@@ -71,7 +71,8 @@
Objects with this interface may represent different transactions
during their lifetime (.begin() can be called to start a new
- transaction using the same instance).
+ transaction using the same instance, although that example is
+ deprecated and will go away in ZODB 3.6).
"""
user = zope.interface.Attribute(
@@ -123,29 +124,21 @@
"""
def join(datamanager):
- """Add a datamanager to the transaction.
+ """Add a data manager to the transaction.
- If the data manager supports savepoints, it must call join *before*
- making any changes: if the transaction has made any savepoints, then
- the transaction will take a savepoint of the data manager when join
- is called, and this savepoint must reflect the state of the data
- manager before any changes that caused the data manager to join the
- transaction.
-
- The datamanager must implement the
- transactions.interfaces.IDataManager interface, and be
- adaptable to ZODB.interfaces.IDataManager.
+ `datamanager` must provide the transactions.interfaces.IDataManager
+ interface.
"""
def note(text):
"""Add text to the transaction description.
- If a description has already been set, text is added to the
- end of the description following two newline characters.
- Surrounding whitespace is stripped from text.
+ This modifies the `.description` attribute; see its docs for more
+ detail. First surrounding whitespace is stripped from `text`. If
+ `.description` is currently an empty string, then the stripped text
+ becomes its value, else two newlines and the stripped text are
+ appended to `.description`.
"""
- # Unsure: does impl do the right thing with ''? Not clear what
- # the "right thing" is.
def setUser(user_name, path="/"):
"""Set the user name.
@@ -153,19 +146,23 @@
path should be provided if needed to further qualify the
identified user. This is a convenience method used by Zope.
It sets the .user attribute to str(path) + " " + str(user_name).
+ This sets the `.user` attribute; see its docs for more detail.
"""
def setExtendedInfo(name, value):
"""Add extension data to the transaction.
- name is the name of the extension property to set; value must
- be a picklable value.
+ name is the name of the extension property to set, of Python type
+ str; value must be pickleable. Multiple calls may be made to set
+ multiple extension properties, provided the names are distinct.
- Storage implementations may limit the amount of extension data
- which can be stored.
+ Storages record the extension data, as meta-data, when a transaction
+ commits.
+
+ A storage may impose a limit on the size of extension data; behavior
+ is undefined if such a limit is exceeded (for example, a storage may
+ raise an exception, or remove `<name, value>` pairs).
"""
- # Unsure: is this allowed to cause an exception here, during
- # the two-phase commit, or can it toss data silently?
def beforeCommitHook(hook, *args, **kws):
"""Register a hook to call before the transaction is committed.
@@ -195,7 +192,6 @@
class ITransactionDeprecated(zope.interface.Interface):
"""Deprecated parts of the transaction API."""
- # TODO: deprecated36
def begin(info=None):
"""Begin a new transaction.
@@ -207,6 +203,7 @@
def register(object):
"""Register the given object for transaction control."""
+
class IDataManager(zope.interface.Interface):
"""Objects that manage transactional storage.
@@ -219,10 +216,6 @@
the transaction.
"""
- # Two-phase commit protocol. These methods are called by the
- # ITransaction object associated with the transaction being
- # committed.
-
def abort(transaction):
"""Abort a transaction and forget all changes.
@@ -232,6 +225,11 @@
that are not yet in a two-phase commit.
"""
+ # Two-phase commit protocol. These methods are called by the ITransaction
+ # object associated with the transaction being committed. The sequence
+ # of calls normally follows this regular expression:
+ # tpc_begin commit tpc_vote (tpc_finish | tpc_abort)
+
def tpc_begin(transaction):
"""Begin commit of a transaction, starting the two-phase commit.
@@ -242,27 +240,15 @@
def commit(transaction):
"""Commit modifications to registered objects.
- Save the object as part of the data to be made persistent if
- the transaction commits.
+ Save changes to be made persistent if the transaction commits (if
+ tpc_finish is called later). If tpc_abort is called later, changes
+ must not persist.
- This includes conflict detection and handling. If no conflicts or
- errors occur it saves the objects in the storage.
+ This includes conflict detection and handling. If no conflicts or
+ errors occur, the data manager should be prepared to make the
+ changes persist when tpc_finish is called.
"""
- def tpc_abort(transaction):
- """Abort a transaction.
-
- This is called by a transaction manager to end a two-phase commit on
- the data manager.
-
- This is always called after a tpc_begin call.
-
- transaction is the ITransaction instance associated with the
- transaction being committed.
-
- This should never fail.
- """
-
def tpc_vote(transaction):
"""Verify that a data manager can commit the transaction.
@@ -276,18 +262,27 @@
def tpc_finish(transaction):
"""Indicate confirmation that the transaction is done.
+ Make all changes to objects modified by this transaction persist.
+
transaction is the ITransaction instance associated with the
transaction being committed.
- This should never fail. If this raises an exception, the
+ This should never fail. If this raises an exception, the
database is not expected to maintain consistency; it's a
serious error.
+ """
- It's important that the storage calls the passed function
- while it still has its lock. We don't want another thread
- to be able to read any updated data until we've had a chance
- to send an invalidation message to all of the other
- connections!
+ def tpc_abort(transaction):
+ """Abort a transaction.
+
+ This is called by a transaction manager to end a two-phase commit on
+ the data manager. Abandon all changes to objects modified by this
+ transaction.
+
+ transaction is the ITransaction instance associated with the
+ transaction being committed.
+
+ This should never fail.
"""
def sortKey():
@@ -321,7 +316,7 @@
responsibility for, validity. It isn't the responsibility of
data-manager savepoints to prevent multiple rollbacks or rollbacks after
transaction termination. Preventing invalid savepoint rollback is the
- responsibility of transaction rollbacks. Application code should never
+ responsibility of transaction rollbacks. Application code should never
use data-manager savepoints.
"""
More information about the Zodb-checkins
mailing list