Commit 7e130cfb authored by Tim Peters's avatar Tim Peters

Connection (and IDataManager) grows a public .transaction_manager

attribute.

The related txn_mgr spelling of various method arguments is
now deprecated, and a "transaction_manager" spelling is added.
parent c50008cb
What's new in ZODB3 3.4b3? What's new in ZODB3 3.4b4?
========================== ==========================
Release date: DD-MMM-2005 Release date: DD-MMM-2005
...@@ -6,8 +6,25 @@ Following is combined news from the "internal releases" (to support ...@@ -6,8 +6,25 @@ Following is combined news from the "internal releases" (to support
ongoing Zope 2.8 and Zope3 development) since the last public ZODB 3.4 ongoing Zope 2.8 and Zope3 development) since the last public ZODB 3.4
release. These are the dates of the internal releases: release. These are the dates of the internal releases:
- 3.4b3 27-May-2005
- 3.4b2 26-May-2005 - 3.4b2 26-May-2005
Connection, DB
--------------
- (3.4b3) ``.transaction_manager`` is now a public attribute of
IDataManager, and is the instance of ITransactionManager used by the
data manager as its transaction manager. There was previously no way
to ask a data manager which transaction manager it was using. It's
intended that ``transaction_manager`` be treated as read-only.
- (3.4b3) For sanity, the ``txn_mgr`` argument to ``DB.open()``,
``Connection.__init__()``, and ``Connection._setDB()`` has been renamed
to ``transaction_manager``. ``txn_mgr`` is still accepted, but is
deprecated and will be removed in ZODB 3.6. Any code that was using
the private ``._txn_mgr`` attribute of ``Connection`` will break
immediately.
Development Development
----------- -----------
...@@ -940,20 +957,21 @@ transaction. This default TM is available as ``transaction.manager``. The ...@@ -940,20 +957,21 @@ transaction. This default TM is available as ``transaction.manager``. The
and is an explicit replacement for the ``Connection.setLocalTransaction()`` and is an explicit replacement for the ``Connection.setLocalTransaction()``
method: method:
A transaction manager instance can be passed as the txn_mgr argument to A transaction manager instance can be passed as the transaction_manager
``DB.open()``. If you do, the connection will use the specified argument to ``DB.open()``. If you do, the connection will use the specified
transaction manager instead of the default TM. The current transaction is transaction manager instead of the default TM. The current transaction is
obtained by calling ``get()`` on a TM. For example: obtained by calling ``get()`` on a TM. For example:
>>> tm = transaction.TransactionManager() >>> tm = transaction.TransactionManager()
>>> cn = db.open(txn_mgr=tm) >>> cn = db.open(transaction_manager=tm)
[...] [...]
>>> tm.get().commit() >>> tm.get().commit()
The ``setLocalTransaction()`` and ``getTransaction()`` methods of The ``setLocalTransaction()`` and ``getTransaction()`` methods of
Connection are deprecated. Use an explicit TM passed via ``txn_mgr=`` to Connection are deprecated. Use an explicit TM passed via
``DB.open()`` instead. The ``setLocalTransaction()`` method still works, ``transaction_manager=`` to ``DB.open()`` instead. The
but it returns a TM instead of a Transaction. ``setLocalTransaction()`` method still works, but it returns a TM instead of
a Transaction.
A TM creates Transaction objects, which are used for exactly one A TM creates Transaction objects, which are used for exactly one
transaction. Transaction objects still have ``commit()``, ``abort()``, transaction. Transaction objects still have ``commit()``, ``abort()``,
......
...@@ -73,7 +73,7 @@ class StressTask: ...@@ -73,7 +73,7 @@ class StressTask:
self.sleep = sleep self.sleep = sleep
self.added_keys = [] self.added_keys = []
self.tm = transaction.TransactionManager() self.tm = transaction.TransactionManager()
self.cn = self.db.open(txn_mgr=self.tm) self.cn = self.db.open(transaction_manager=self.tm)
self.cn.sync() self.cn.sync()
def doStep(self): def doStep(self):
......
...@@ -74,9 +74,20 @@ class Connection(ExportImport, object): ...@@ -74,9 +74,20 @@ class Connection(ExportImport, object):
# Connection methods, ZODB.IConnection # Connection methods, ZODB.IConnection
def __init__(self, version='', cache_size=400, def __init__(self, version='', cache_size=400,
cache_deactivate_after=None, mvcc=True, txn_mgr=None, cache_deactivate_after=None, mvcc=True,
txn_mgr=DEPRECATED_ARGUMENT,
transaction_manager=None,
synch=True): synch=True):
"""Create a new Connection.""" """Create a new Connection."""
if txn_mgr is not DEPRECATED_ARGUMENT:
deprecated36("use transaction_manager= instead of txn_mgr=")
if transaction_manager is None:
transaction_manager = txn_mgr
else:
raise ValueError("cannot specify both transaction_manager= "
"and txn_mgr=")
self._log = logging.getLogger("ZODB.Connection") self._log = logging.getLogger("ZODB.Connection")
self._debug_info = () self._debug_info = ()
self._opened = None # time.time() when DB.open() opened us self._opened = None # time.time() when DB.open() opened us
...@@ -110,7 +121,8 @@ class Connection(ExportImport, object): ...@@ -110,7 +121,8 @@ class Connection(ExportImport, object):
# If a transaction manager is passed to the constructor, use # If a transaction manager is passed to the constructor, use
# it instead of the global transaction manager. The instance # it instead of the global transaction manager. The instance
# variable will hold a TM instance. # variable will hold a TM instance.
self._txn_mgr = txn_mgr or transaction.manager self.transaction_manager = transaction_manager or transaction.manager
# _synch is a boolean; if True, the Connection will register # _synch is a boolean; if True, the Connection will register
# with the TM to receive afterCompletion() calls. # with the TM to receive afterCompletion() calls.
self._synch = synch self._synch = synch
...@@ -248,7 +260,7 @@ class Connection(ExportImport, object): ...@@ -248,7 +260,7 @@ class Connection(ExportImport, object):
# Return the connection to the pool. # Return the connection to the pool.
if self._db is not None: if self._db is not None:
if self._synch: if self._synch:
self._txn_mgr.unregisterSynch(self) self.transaction_manager.unregisterSynch(self)
self._db._closeConnection(self) self._db._closeConnection(self)
# _closeConnection() set self._db to None. However, we can't # _closeConnection() set self._db to None. However, we can't
# assert that here, because self may have been reused (by # assert that here, because self may have been reused (by
...@@ -296,7 +308,7 @@ class Connection(ExportImport, object): ...@@ -296,7 +308,7 @@ class Connection(ExportImport, object):
def sync(self): def sync(self):
"""Manually update the view on the database.""" """Manually update the view on the database."""
self._txn_mgr.abort() self.transaction_manager.abort()
self._storage_sync() self._storage_sync()
def getDebugInfo(self): def getDebugInfo(self):
...@@ -831,7 +843,7 @@ class Connection(ExportImport, object): ...@@ -831,7 +843,7 @@ class Connection(ExportImport, object):
# to the object. # to the object.
if self._needs_to_join: if self._needs_to_join:
self._txn_mgr.get().join(self) self.transaction_manager.get().join(self)
self._needs_to_join = False self._needs_to_join = False
if obj is not None: if obj is not None:
...@@ -855,7 +867,8 @@ class Connection(ExportImport, object): ...@@ -855,7 +867,8 @@ class Connection(ExportImport, object):
# return a list of [ghosts....not recently used.....recently used] # return a list of [ghosts....not recently used.....recently used]
return everything.items() + items return everything.items() + items
def _setDB(self, odb, mvcc=None, txn_mgr=None, synch=None): def _setDB(self, odb, mvcc=None, txn_mgr=DEPRECATED_ARGUMENT,
transaction_manager=None, synch=None):
"""Register odb, the DB that this Connection uses. """Register odb, the DB that this Connection uses.
This method is called by the DB every time a Connection This method is called by the DB every time a Connection
...@@ -868,12 +881,20 @@ class Connection(ExportImport, object): ...@@ -868,12 +881,20 @@ class Connection(ExportImport, object):
Parameters: Parameters:
odb: database that owns the Connection odb: database that owns the Connection
mvcc: boolean indicating whether MVCC is enabled mvcc: boolean indicating whether MVCC is enabled
txn_mgr: transaction manager to use. None means transaction_manager: transaction manager to use. None means
used the default transaction manager. use the default transaction manager.
synch: boolean indicating whether Connection should synch: boolean indicating whether Connection should
register for afterCompletion() calls. register for afterCompletion() calls.
""" """
if txn_mgr is not DEPRECATED_ARGUMENT:
deprecated36("use transaction_manager= instead of txn_mgr=")
if transaction_manager is None:
transaction_manager = txn_mgr
else:
raise ValueError("cannot specify both transaction_manager= "
"and txn_mgr=")
# TODO: Why do we go to all the trouble of setting _db and # TODO: Why do we go to all the trouble of setting _db and
# other attributes on open and clearing them on close? # other attributes on open and clearing them on close?
# A Connection is only ever associated with a single DB # A Connection is only ever associated with a single DB
...@@ -887,14 +908,14 @@ class Connection(ExportImport, object): ...@@ -887,14 +908,14 @@ class Connection(ExportImport, object):
self._synch = synch self._synch = synch
if mvcc is not None: if mvcc is not None:
self._mvcc = mvcc self._mvcc = mvcc
self._txn_mgr = txn_mgr or transaction.manager self.transaction_manager = transaction_manager or transaction.manager
if self._reset_counter != global_reset_counter: if self._reset_counter != global_reset_counter:
# New code is in place. Start a new cache. # New code is in place. Start a new cache.
self._resetCache() self._resetCache()
else: else:
self._flush_invalidations() self._flush_invalidations()
if self._synch: if self._synch:
self._txn_mgr.registerSynch(self) self.transaction_manager.registerSynch(self)
self._reader = ObjectReader(self, self._cache, self._db.classFactory) self._reader = ObjectReader(self, self._cache, self._db.classFactory)
# Multi-database support # Multi-database support
...@@ -972,8 +993,10 @@ class Connection(ExportImport, object): ...@@ -972,8 +993,10 @@ class Connection(ExportImport, object):
to control which TM the Connection uses. to control which TM the Connection uses.
""" """
deprecated36("getTransaction() is deprecated. " deprecated36("getTransaction() is deprecated. "
"Use the txn_mgr argument to DB.open() instead.") "Use the transaction_manager argument "
return self._txn_mgr.get() "to DB.open() instead, or access "
".transaction_manager directly on the Connection.")
return self.transaction_manager.get()
def setLocalTransaction(self): def setLocalTransaction(self):
"""Use a transaction bound to the connection rather than the thread. """Use a transaction bound to the connection rather than the thread.
...@@ -985,14 +1008,15 @@ class Connection(ExportImport, object): ...@@ -985,14 +1008,15 @@ class Connection(ExportImport, object):
which TM the Connection uses. which TM the Connection uses.
""" """
deprecated36("setLocalTransaction() is deprecated. " deprecated36("setLocalTransaction() is deprecated. "
"Use the txn_mgr argument to DB.open() instead.") "Use the transaction_manager argument "
if self._txn_mgr is transaction.manager: "to DB.open() instead.")
if self.transaction_manager is transaction.manager:
if self._synch: if self._synch:
self._txn_mgr.unregisterSynch(self) self.transaction_manager.unregisterSynch(self)
self._txn_mgr = transaction.TransactionManager() self.transaction_manager = transaction.TransactionManager()
if self._synch: if self._synch:
self._txn_mgr.registerSynch(self) self.transaction_manager.registerSynch(self)
return self._txn_mgr return self.transaction_manager
# DEPRECATED methods # DEPRECATED methods
########################################################################## ##########################################################################
......
...@@ -497,7 +497,8 @@ class DB(object): ...@@ -497,7 +497,8 @@ class DB(object):
def open(self, version='', def open(self, version='',
transaction=DEPRECATED_ARGUMENT, temporary=DEPRECATED_ARGUMENT, transaction=DEPRECATED_ARGUMENT, temporary=DEPRECATED_ARGUMENT,
force=DEPRECATED_ARGUMENT, waitflag=DEPRECATED_ARGUMENT, force=DEPRECATED_ARGUMENT, waitflag=DEPRECATED_ARGUMENT,
mvcc=True, txn_mgr=None, synch=True): mvcc=True, txn_mgr=DEPRECATED_ARGUMENT,
transaction_manager=None, synch=True):
"""Return a database Connection for use by application code. """Return a database Connection for use by application code.
The optional `version` argument can be used to specify that a The optional `version` argument can be used to specify that a
...@@ -511,8 +512,8 @@ class DB(object): ...@@ -511,8 +512,8 @@ class DB(object):
- `version`: the "version" that all changes will be made - `version`: the "version" that all changes will be made
in, defaults to no version. in, defaults to no version.
- `mvcc`: boolean indicating whether MVCC is enabled - `mvcc`: boolean indicating whether MVCC is enabled
- `txn_mgr`: transaction manager to use. None means - `transaction_manager`: transaction manager to use. None means
used the default transaction manager. use the default transaction manager.
- `synch`: boolean indicating whether Connection should - `synch`: boolean indicating whether Connection should
register for afterCompletion() calls. register for afterCompletion() calls.
""" """
...@@ -532,6 +533,14 @@ class DB(object): ...@@ -532,6 +533,14 @@ class DB(object):
if transaction is not DEPRECATED_ARGUMENT: if transaction is not DEPRECATED_ARGUMENT:
deprecated36("DB.open() transaction= ignored.") deprecated36("DB.open() transaction= ignored.")
if txn_mgr is not DEPRECATED_ARGUMENT:
deprecated36("use transaction_manager= instead of txn_mgr=")
if transaction_manager is None:
transaction_manager = txn_mgr
else:
raise ValueError("cannot specify both transaction_manager= "
"and txn_mgr=")
self._a() self._a()
try: try:
# pool <- the _ConnectionPool for this version # pool <- the _ConnectionPool for this version
...@@ -551,14 +560,15 @@ class DB(object): ...@@ -551,14 +560,15 @@ class DB(object):
size = self._version_cache_size size = self._version_cache_size
else: else:
size = self._cache_size size = self._cache_size
c = self.klass(version=version, cache_size=size, c = self.klass(version=version, cache_size=size, mvcc=mvcc,
mvcc=mvcc, txn_mgr=txn_mgr) transaction_manager=transaction_manager)
pool.push(c) pool.push(c)
result = pool.pop() result = pool.pop()
assert result is not None assert result is not None
# Tell the connection it belongs to self. # Tell the connection it belongs to self.
result._setDB(self, mvcc=mvcc, txn_mgr=txn_mgr, synch=synch) result._setDB(self, mvcc=mvcc, synch=synch,
transaction_manager=transaction_manager)
# A good time to do some cache cleanup. # A good time to do some cache cleanup.
self._connectionMap(lambda c: c.cacheGC()) self._connectionMap(lambda c: c.cacheGC())
......
...@@ -65,7 +65,7 @@ class ExportImport: ...@@ -65,7 +65,7 @@ class ExportImport:
return customImporters[magic](self, f, clue) return customImporters[magic](self, f, clue)
raise ExportError("Invalid export header") raise ExportError("Invalid export header")
t = self._txn_mgr.get() t = self.transaction_manager.get()
if clue: if clue:
t.note(clue) t.note(clue)
......
...@@ -113,7 +113,8 @@ class IConnection(Interface): ...@@ -113,7 +113,8 @@ class IConnection(Interface):
""" """
def __init__(version='', cache_size=400, def __init__(version='', cache_size=400,
cache_deactivate_after=None, mvcc=True, txn_mgr=None, cache_deactivate_after=None, mvcc=True,
transaction_manager=None,
synch=True): synch=True):
"""Create a new Connection. """Create a new Connection.
...@@ -126,8 +127,8 @@ class IConnection(Interface): ...@@ -126,8 +127,8 @@ class IConnection(Interface):
cache_size: the target size of the in-memory object cache, measured cache_size: the target size of the in-memory object cache, measured
in objects. in objects.
mvcc: boolean indicating whether MVCC is enabled mvcc: boolean indicating whether MVCC is enabled
txn_mgr: transaction manager to use. None means used the default transaction_manager: transaction manager to use. None means use the
transaction manager. default transaction manager.
synch: boolean indicating whether Connection should register for synch: boolean indicating whether Connection should register for
afterCompletion() calls. afterCompletion() calls.
""" """
......
...@@ -82,7 +82,7 @@ without having to use threads. ...@@ -82,7 +82,7 @@ without having to use threads.
>>> import transaction >>> import transaction
>>> tm = transaction.TransactionManager() >>> tm = transaction.TransactionManager()
>>> connection = some_database.open(txn_mgr=tm) >>> connection = some_database.open(transaction_manager=tm)
>>> connection.root()['C'] = C >>> connection.root()['C'] = C
>>> tm.commit() >>> tm.commit()
...@@ -128,7 +128,7 @@ Then the class will return to it's prior state: ...@@ -128,7 +128,7 @@ Then the class will return to it's prior state:
We can open another connection and access the class there. We can open another connection and access the class there.
>>> tm2 = transaction.TransactionManager() >>> tm2 = transaction.TransactionManager()
>>> connection2 = some_database.open(txn_mgr=tm2) >>> connection2 = some_database.open(transaction_manager=tm2)
>>> C2 = connection2.root()['C'] >>> C2 = connection2.root()['C']
>>> c2 = C2('other') >>> c2 = C2('other')
...@@ -248,8 +248,8 @@ connections to a variable first to prevent getting them from the ...@@ -248,8 +248,8 @@ connections to a variable first to prevent getting them from the
connection pool: connection pool:
>>> old = connection, connection2 >>> old = connection, connection2
>>> connection = some_database.open(txn_mgr=tm) >>> connection = some_database.open(transaction_manager=tm)
>>> connection2 = some_database.open(txn_mgr=tm2) >>> connection2 = some_database.open(transaction_manager=tm2)
Now, we can read the object: Now, we can read the object:
......
...@@ -69,7 +69,7 @@ path at some point when serving pages. ...@@ -69,7 +69,7 @@ path at some point when serving pages.
>>> tm = transaction.ThreadTransactionManager() >>> tm = transaction.ThreadTransactionManager()
>>> st.sync_called = False >>> st.sync_called = False
>>> dummy = tm.begin() # we're doing this _before_ opening a connection >>> dummy = tm.begin() # we're doing this _before_ opening a connection
>>> cn = db.open(txn_mgr=tm) >>> cn = db.open(transaction_manager=tm)
>>> rt = cn.root() # make a change >>> rt = cn.root() # make a change
>>> rt['c'] = 3 >>> rt['c'] = 3
>>> st.sync_called >>> st.sync_called
...@@ -88,7 +88,7 @@ And try the same thing with a non-threaded TM: ...@@ -88,7 +88,7 @@ And try the same thing with a non-threaded TM:
>>> tm = transaction.TransactionManager() >>> tm = transaction.TransactionManager()
>>> st.sync_called = False >>> st.sync_called = False
>>> dummy = tm.begin() # we're doing this _before_ opening a connection >>> dummy = tm.begin() # we're doing this _before_ opening a connection
>>> cn = db.open(txn_mgr=tm) >>> cn = db.open(transaction_manager=tm)
>>> rt = cn.root() # make a change >>> rt = cn.root() # make a change
>>> rt['d'] = 4 >>> rt['d'] = 4
>>> st.sync_called >>> st.sync_called
......
...@@ -172,9 +172,9 @@ class ZODBTests(unittest.TestCase): ...@@ -172,9 +172,9 @@ class ZODBTests(unittest.TestCase):
# Test of transactions that apply to only the connection, # Test of transactions that apply to only the connection,
# not the thread. # not the thread.
tm1 = transaction.TransactionManager() tm1 = transaction.TransactionManager()
conn1 = self._db.open(txn_mgr=tm1) conn1 = self._db.open(transaction_manager=tm1)
tm2 = transaction.TransactionManager() tm2 = transaction.TransactionManager()
conn2 = self._db.open(txn_mgr=tm2) conn2 = self._db.open(transaction_manager=tm2)
try: try:
r1 = conn1.root() r1 = conn1.root()
r2 = conn2.root() r2 = conn2.root()
...@@ -246,10 +246,13 @@ class ZODBTests(unittest.TestCase): ...@@ -246,10 +246,13 @@ class ZODBTests(unittest.TestCase):
self.assert_(msg in [ self.assert_(msg in [
"This will be removed in ZODB 3.6:\n" "This will be removed in ZODB 3.6:\n"
"setLocalTransaction() is deprecated. " "setLocalTransaction() is deprecated. "
"Use the txn_mgr argument to DB.open() instead.", "Use the transaction_manager argument "
"to DB.open() instead.",
"This will be removed in ZODB 3.6:\n" "This will be removed in ZODB 3.6:\n"
"getTransaction() is deprecated. " "getTransaction() is deprecated. "
"Use the txn_mgr argument to DB.open() instead."]) "Use the transaction_manager argument "
"to DB.open() instead, or access "
".transaction_manager directly on the Connection."])
finally: finally:
conn1.close() conn1.close()
conn2.close() conn2.close()
...@@ -267,7 +270,7 @@ class ZODBTests(unittest.TestCase): ...@@ -267,7 +270,7 @@ class ZODBTests(unittest.TestCase):
# consistent with the objects read earlier in the transaction. # consistent with the objects read earlier in the transaction.
tm1 = transaction.TransactionManager() tm1 = transaction.TransactionManager()
conn = self._db.open(mvcc=False, txn_mgr=tm1) conn = self._db.open(mvcc=False, transaction_manager=tm1)
r1 = conn.root() r1 = conn.root()
r1["p"] = self.obj r1["p"] = self.obj
self.obj.child1 = P() self.obj.child1 = P()
...@@ -275,7 +278,7 @@ class ZODBTests(unittest.TestCase): ...@@ -275,7 +278,7 @@ class ZODBTests(unittest.TestCase):
# start a new transaction with a new connection # start a new transaction with a new connection
tm2 = transaction.TransactionManager() tm2 = transaction.TransactionManager()
cn2 = self._db.open(mvcc=False, txn_mgr=tm2) cn2 = self._db.open(mvcc=False, transaction_manager=tm2)
# start a new transaction with the other connection # start a new transaction with the other connection
r2 = cn2.root() r2 = cn2.root()
...@@ -324,7 +327,7 @@ class ZODBTests(unittest.TestCase): ...@@ -324,7 +327,7 @@ class ZODBTests(unittest.TestCase):
# load some objects from one connection # load some objects from one connection
tm = transaction.TransactionManager() tm = transaction.TransactionManager()
cn2 = self._db.open(mvcc=False, txn_mgr=tm) cn2 = self._db.open(mvcc=False, transaction_manager=tm)
r2 = cn2.root() r2 = cn2.root()
real_data2 = r2["real_data"] real_data2 = r2["real_data"]
index2 = r2["index"] index2 = r2["index"]
...@@ -374,7 +377,7 @@ class ZODBTests(unittest.TestCase): ...@@ -374,7 +377,7 @@ class ZODBTests(unittest.TestCase):
# root --> "p" -> value = 1 # root --> "p" -> value = 1
# --> "q" -> value = 2 # --> "q" -> value = 2
tm1 = transaction.TransactionManager() tm1 = transaction.TransactionManager()
conn = self._db.open(txn_mgr=tm1) conn = self._db.open(transaction_manager=tm1)
r1 = conn.root() r1 = conn.root()
p = P() p = P()
p.value = 1 p.value = 1
...@@ -390,7 +393,7 @@ class ZODBTests(unittest.TestCase): ...@@ -390,7 +393,7 @@ class ZODBTests(unittest.TestCase):
# Start new txn T2 with a new connection. # Start new txn T2 with a new connection.
tm2 = transaction.TransactionManager() tm2 = transaction.TransactionManager()
cn2 = self._db.open(txn_mgr=tm2) cn2 = self._db.open(transaction_manager=tm2)
r2 = cn2.root() r2 = cn2.root()
p2 = r2["p"] p2 = r2["p"]
self.assertEqual(p._p_oid, p2._p_oid) self.assertEqual(p._p_oid, p2._p_oid)
...@@ -438,7 +441,7 @@ class ZODBTests(unittest.TestCase): ...@@ -438,7 +441,7 @@ class ZODBTests(unittest.TestCase):
# Provoke a ReadConflictError. # Provoke a ReadConflictError.
tm2 = transaction.TransactionManager() tm2 = transaction.TransactionManager()
cn2 = self._db.open(mvcc=False, txn_mgr=tm2) cn2 = self._db.open(mvcc=False, transaction_manager=tm2)
r2 = cn2.root() r2 = cn2.root()
data2 = r2["data"] data2 = r2["data"]
......
...@@ -43,7 +43,7 @@ independently, even though they'll be run from a single thread. ...@@ -43,7 +43,7 @@ independently, even though they'll be run from a single thread.
>>> import transaction >>> import transaction
>>> tm1 = transaction.TransactionManager() >>> tm1 = transaction.TransactionManager()
>>> cn1 = db.open(txn_mgr=tm1) >>> cn1 = db.open(transaction_manager=tm1)
The test will just use some MinPO objects. The next few lines just The test will just use some MinPO objects. The next few lines just
setup an initial database state. setup an initial database state.
...@@ -57,7 +57,7 @@ setup an initial database state. ...@@ -57,7 +57,7 @@ setup an initial database state.
Now open a second connection. Now open a second connection.
>>> tm2 = transaction.TransactionManager() >>> tm2 = transaction.TransactionManager()
>>> cn2 = db.open(txn_mgr=tm2) >>> cn2 = db.open(transaction_manager=tm2)
Connection high-water mark Connection high-water mark
-------------------------- --------------------------
...@@ -281,7 +281,7 @@ non-current revision to load. ...@@ -281,7 +281,7 @@ non-current revision to load.
>>> ts = TestStorage() >>> ts = TestStorage()
>>> db = DB(ts) >>> db = DB(ts)
>>> cn1 = db.open(txn_mgr=tm1) >>> cn1 = db.open(transaction_manager=tm1)
>>> r1 = cn1.root() >>> r1 = cn1.root()
>>> r1["a"] = MinPO(0) >>> r1["a"] = MinPO(0)
>>> r1["b"] = MinPO(0) >>> r1["b"] = MinPO(0)
...@@ -318,7 +318,7 @@ activate "b" will result in a ReadConflictError. ...@@ -318,7 +318,7 @@ activate "b" will result in a ReadConflictError.
>>> ts = TestStorage() >>> ts = TestStorage()
>>> db = DB(ts) >>> db = DB(ts)
>>> cn1 = db.open(txn_mgr=tm1) >>> cn1 = db.open(transaction_manager=tm1)
>>> r1 = cn1.root() >>> r1 = cn1.root()
>>> r1["a"] = MinPO(0) >>> r1["a"] = MinPO(0)
>>> r1["b"] = MinPO(0) >>> r1["b"] = MinPO(0)
......
...@@ -226,6 +226,14 @@ class IDataManager(zope.interface.Interface): ...@@ -226,6 +226,14 @@ class IDataManager(zope.interface.Interface):
the transaction. the transaction.
""" """
transaction_manager = zope.interface.Attribute(
"""The transaction manager (TM) used by this data manager.
This is a public attribute, intended for read-only use. The value
is an instance of ITransactionManager, typically set by the data
manager's constructor.
""")
def abort(transaction): def abort(transaction):
"""Abort a transaction and forget all changes. """Abort a transaction and forget all changes.
......
...@@ -46,11 +46,11 @@ from ZODB.utils import positive_id ...@@ -46,11 +46,11 @@ from ZODB.utils import positive_id
class TransactionTests(unittest.TestCase): class TransactionTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.txn_mgr = transaction.TransactionManager() mgr = self.transaction_manager = transaction.TransactionManager()
self.sub1 = DataObject(self.txn_mgr) self.sub1 = DataObject(mgr)
self.sub2 = DataObject(self.txn_mgr) self.sub2 = DataObject(mgr)
self.sub3 = DataObject(self.txn_mgr) self.sub3 = DataObject(mgr)
self.nosub1 = DataObject(self.txn_mgr, nost=1) self.nosub1 = DataObject(mgr, nost=1)
# basic tests with two sub trans jars # basic tests with two sub trans jars
# really we only need one, so tests for # really we only need one, so tests for
...@@ -60,7 +60,7 @@ class TransactionTests(unittest.TestCase): ...@@ -60,7 +60,7 @@ class TransactionTests(unittest.TestCase):
self.sub1.modify() self.sub1.modify()
self.sub2.modify() self.sub2.modify()
self.txn_mgr.commit() self.transaction_manager.commit()
assert self.sub1._p_jar.ccommit_sub == 0 assert self.sub1._p_jar.ccommit_sub == 0
assert self.sub1._p_jar.ctpc_finish == 1 assert self.sub1._p_jar.ctpc_finish == 1
...@@ -70,13 +70,13 @@ class TransactionTests(unittest.TestCase): ...@@ -70,13 +70,13 @@ class TransactionTests(unittest.TestCase):
self.sub1.modify() self.sub1.modify()
self.sub2.modify() self.sub2.modify()
self.txn_mgr.abort() self.transaction_manager.abort()
assert self.sub2._p_jar.cabort == 1 assert self.sub2._p_jar.cabort == 1
def testTransactionNote(self): def testTransactionNote(self):
t = self.txn_mgr.get() t = self.transaction_manager.get()
t.note('This is a note.') t.note('This is a note.')
self.assertEqual(t.description, 'This is a note.') self.assertEqual(t.description, 'This is a note.')
...@@ -92,7 +92,7 @@ class TransactionTests(unittest.TestCase): ...@@ -92,7 +92,7 @@ class TransactionTests(unittest.TestCase):
self.nosub1.modify() self.nosub1.modify()
self.txn_mgr.commit() self.transaction_manager.commit()
assert self.nosub1._p_jar.ctpc_finish == 1 assert self.nosub1._p_jar.ctpc_finish == 1
...@@ -100,7 +100,7 @@ class TransactionTests(unittest.TestCase): ...@@ -100,7 +100,7 @@ class TransactionTests(unittest.TestCase):
self.nosub1.modify() self.nosub1.modify()
self.txn_mgr.abort() self.transaction_manager.abort()
assert self.nosub1._p_jar.ctpc_finish == 0 assert self.nosub1._p_jar.ctpc_finish == 0
assert self.nosub1._p_jar.cabort == 1 assert self.nosub1._p_jar.cabort == 1
...@@ -123,7 +123,7 @@ class TransactionTests(unittest.TestCase): ...@@ -123,7 +123,7 @@ class TransactionTests(unittest.TestCase):
self.sub1.modify(tracing='sub') self.sub1.modify(tracing='sub')
self.nosub1.modify(tracing='nosub') self.nosub1.modify(tracing='nosub')
self.txn_mgr.commit(1) self.transaction_manager.commit(1)
assert self.sub1._p_jar.ctpc_finish == 1 assert self.sub1._p_jar.ctpc_finish == 1
...@@ -131,7 +131,7 @@ class TransactionTests(unittest.TestCase): ...@@ -131,7 +131,7 @@ class TransactionTests(unittest.TestCase):
# in a subtrans # in a subtrans
assert self.nosub1._p_jar.ctpc_finish == 0 assert self.nosub1._p_jar.ctpc_finish == 0
self.txn_mgr.abort() self.transaction_manager.abort()
assert self.nosub1._p_jar.cabort == 1 assert self.nosub1._p_jar.cabort == 1
assert self.sub1._p_jar.cabort_sub == 1 assert self.sub1._p_jar.cabort_sub == 1
...@@ -156,7 +156,7 @@ class TransactionTests(unittest.TestCase): ...@@ -156,7 +156,7 @@ class TransactionTests(unittest.TestCase):
self.sub2.modify() self.sub2.modify()
try: try:
self.txn_mgr.abort() self.transaction_manager.abort()
except TestTxnException: pass except TestTxnException: pass
assert self.nosub1._p_jar.cabort == 1 assert self.nosub1._p_jar.cabort == 1
...@@ -170,7 +170,7 @@ class TransactionTests(unittest.TestCase): ...@@ -170,7 +170,7 @@ class TransactionTests(unittest.TestCase):
self.sub1.modify(nojar=1) self.sub1.modify(nojar=1)
try: try:
self.txn_mgr.commit() self.transaction_manager.commit()
except TestTxnException: pass except TestTxnException: pass
assert self.nosub1._p_jar.ctpc_finish == 0 assert self.nosub1._p_jar.ctpc_finish == 0
...@@ -185,7 +185,7 @@ class TransactionTests(unittest.TestCase): ...@@ -185,7 +185,7 @@ class TransactionTests(unittest.TestCase):
self.sub1.modify(nojar=1) self.sub1.modify(nojar=1)
try: try:
self.txn_mgr.commit() self.transaction_manager.commit()
except TestTxnException: pass except TestTxnException: pass
assert self.nosub1._p_jar.ctpc_finish == 0 assert self.nosub1._p_jar.ctpc_finish == 0
...@@ -211,7 +211,7 @@ class TransactionTests(unittest.TestCase): ...@@ -211,7 +211,7 @@ class TransactionTests(unittest.TestCase):
self.sub1.modify(nojar=1) self.sub1.modify(nojar=1)
try: try:
self.txn_mgr.commit() self.transaction_manager.commit()
except TestTxnException: pass except TestTxnException: pass
assert self.nosub1._p_jar.ctpc_abort == 1 assert self.nosub1._p_jar.ctpc_abort == 1
...@@ -225,7 +225,7 @@ class TransactionTests(unittest.TestCase): ...@@ -225,7 +225,7 @@ class TransactionTests(unittest.TestCase):
self.sub1.modify(nojar=1) self.sub1.modify(nojar=1)
try: try:
self.txn_mgr.commit() self.transaction_manager.commit()
except TestTxnException: except TestTxnException:
pass pass
...@@ -266,8 +266,8 @@ class TransactionTests(unittest.TestCase): ...@@ -266,8 +266,8 @@ class TransactionTests(unittest.TestCase):
class DataObject: class DataObject:
def __init__(self, txn_mgr, nost=0): def __init__(self, transaction_manager, nost=0):
self.txn_mgr = txn_mgr self.transaction_manager = transaction_manager
self.nost = nost self.nost = nost
self._p_jar = None self._p_jar = None
...@@ -277,7 +277,7 @@ class DataObject: ...@@ -277,7 +277,7 @@ class DataObject:
self._p_jar = NoSubTransactionJar(tracing=tracing) self._p_jar = NoSubTransactionJar(tracing=tracing)
else: else:
self._p_jar = SubTransactionJar(tracing=tracing) self._p_jar = SubTransactionJar(tracing=tracing)
self.txn_mgr.get().join(self._p_jar) self.transaction_manager.get().join(self._p_jar)
class TestTxnException(Exception): class TestTxnException(Exception):
pass pass
......
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