[Zodb-checkins] CVS: ZODB4/Transaction - Manager.py:1.1 Transaction.py:1.1 __init__.py:1.1 interfaces.py:1.1
Jim Fulton
jim@zope.com
Wed, 25 Dec 2002 09:37:37 -0500
Update of /cvs-repository/ZODB4/Transaction
In directory cvs.zope.org:/tmp/cvs-serv27110/Transaction
Added Files:
Manager.py Transaction.py __init__.py interfaces.py
Log Message:
Copied Transaction package from Zope 3 tree.
We're going to delete these files from the Zope 3 tree because they
have been renamed.
=== Added File ZODB4/Transaction/Manager.py ===
import logging
from interfaces import IRollback
from Transaction import Transaction, Status
# XXX need to change asserts of transaction status into explicit checks
# that raise some exception
# XXX need lots of error checking
class TransactionManager(object):
txn_factory = Transaction
def __init__(self):
self.logger = logging.getLogger("txn")
def new(self):
txn = self.txn_factory(self)
self.logger.debug("%s: begin", txn)
return txn
def commit(self, txn):
assert txn._status is Status.ACTIVE
txn._status = Status.PREPARING
prepare_ok = True
self.logger.debug("%s: prepare", txn)
try:
for r in txn._resources:
if prepare_ok and not r.prepare(txn):
prepare_ok = False
except:
txn._status = Status.FAILED
raise
txn._status = Status.PREPARED
# XXX An error below is intolerable. What state to use?
if prepare_ok:
self._commit(txn)
else:
self.abort(txn)
def _commit(self, txn):
self.logger.debug("%s: commit", txn)
# finish the two-phase commit
for r in txn._resources:
r.commit(txn)
txn._status = Status.COMMITTED
def abort(self, txn):
self.logger.debug("%s: abort", txn)
assert txn._status in (Status.ACTIVE, Status.PREPARED, Status.FAILED)
txn._status = Status.PREPARING
for r in txn._resources:
r.abort(txn)
txn._status = Status.ABORTED
def savepoint(self, txn):
self.logger.debug("%s: savepoint", txn)
return Rollback([r.savepoint(txn) for r in txn._resources])
class Rollback(object):
__implements__ = IRollback
def __init__(self, resources):
self._resources = resources
def rollback(self):
for r in self._resources:
r.rollback()
# make the transaction manager visible to client code
import thread
class ThreadedTransactionManager(TransactionManager):
def __init__(self):
TransactionManager.__init__(self)
self._pool = {}
def new(self):
tid = thread.get_ident()
txn = self._pool.get(tid)
if txn is None:
txn = super(ThreadedTransactionManager, self).new()
self._pool[tid] = txn
return txn
def _commit(self, txn):
tid = thread.get_ident()
assert self._pool[tid] is txn
super(ThreadedTransactionManager, self)._commit(txn)
del self._pool[tid]
def abort(self, txn):
tid = thread.get_ident()
assert self._pool[tid] is txn
super(ThreadedTransactionManager, self).abort(txn)
del self._pool[tid]
=== Added File ZODB4/Transaction/Transaction.py ===
# XXX The fact that this module has the same name as the package makes
# explicit imports impossible elsewhere. Pick a new name?
__metaclass__ = type
from interfaces import ITransaction, TransactionError
class Set(dict):
def add(self, k):
self[k] = 1
class Status:
ACTIVE = "Active"
PREPARING = "Preparing"
PREPARED = "Prepared"
FAILED = "Failed"
COMMITTED = "Committed"
ABORTING = "Aborting"
ABORTED = "Aborted"
class Transaction:
__implements__ = ITransaction
def __init__(self, manager=None, parent=None):
self._manager = manager
self._parent = parent
self._status = Status.ACTIVE
self._resources = Set()
def __repr__(self):
return "<%s %X %s>" % (self.__class__.__name__, id(self), self._status)
def begin(self, parent=None):
"""Begin a transaction.
If parent is not None, it is the parent transaction for this one.
"""
assert self._manager is not None
if parent is not None:
t = Transaction(self._manager, self)
return t
def commit(self):
"""Commit a transaction."""
assert self._manager is not None
self._manager.commit(self)
def abort(self):
"""Rollback to initial state."""
assert self._manager is not None
self._manager.abort(self)
def savepoint(self):
"""Save current progress and return a savepoint."""
assert self._manager is not None
return self._manager.savepoint(self)
def join(self, resource):
"""resource is participating in the transaction."""
assert self._manager is not None
if self._status != Status.ACTIVE:
raise TransactionError("Can't join transaction. Status=%s" %
self._status)
self._resources.add(resource)
def status(self):
"""Return the status of the transaction."""
return self._status
=== Added File ZODB4/Transaction/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Manager import ThreadedTransactionManager
_manager = ThreadedTransactionManager()
get_transaction = _manager.new
def set_factory(factory):
_manager.txn_factory = factory
=== Added File ZODB4/Transaction/interfaces.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Interface import Interface
class TransactionError(StandardError):
"""An error occured due to normal transaction processing."""
class ConflictError(TransactionError):
"""Two transactions tried to modify the same object at once
This transaction should be resubmitted.
"""
class RollbackError(TransactionError):
"""An error occurred rolling back a savepoint."""
class IDataManager(Interface):
"""Data management interface for storing objects transactionally
This is currently implemented by ZODB database connections.
"""
def prepare(transaction):
"""Begin two-phase commit of a transaction.
DataManager should return True or False.
"""
def abort(transaction):
"""Abort changes made by transaction."""
def commit(transaction):
"""Commit changes made by transaction."""
def savepoint(transaction):
"""Do tentative commit of changes to this point.
Should return an object implementing IRollback
"""
class IRollback(Interface):
def rollback():
"""Rollback changes since savepoint."""
class ITransaction(Interface):
"""Transaction objects
Application code typically gets these by calling
get_transaction().
"""
def abort():
"""Abort the current transaction."""
def begin():
"""Begin a transaction."""
def commit():
"""Commit a transaction."""
def join(resource):
"""Join a resource manager to the current transaction."""
def status():
"""Return status of the current transaction."""