You are not logged in Log in Join
You are here: Home » Members » k_vertigo » ShortStories » Transactions » TMPlus.py » View File

Log in
Name

Password

 

TMPlus.py

fixes/workarounds to TM.py for db adapters
File details
Size
2 K
File type
text/plain

File contents

##############################################################################
#
# Copyright (c) 2001 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
# 
##############################################################################
"""

Provide support for linking an external transaction manager with Zope's

This file includes two fixes to the standard TM.

  1. Fixes a bug in the TM whereby tpc_abort was ignored. this
     was the likely cause of external transaction manager's never
     recieving a commit or abort statement and hanging.

  2. Worksaround a bug in Zope's transaction machinery. This
     bug is a corner case. it would cause loss of data integrity
     if a external transaction manager were involved in a
     zope transaction that involved a subtransaction commit, in
     which the overall transaction was aborted.

"""


class TM:
    """Mix-in class that provides transaction management support

    A sub class should call self._register() whenever it performs
    any transaction-dependent operations (e.g. sql statements).

    The sub class will need to override _finish, to finallize work,
    _abort, to roll-back work, and perhaps _begin, if any work is needed
    at the start of a transaction.
    """

    _registered=None
    
    def _begin(self): pass

    def _register(self):
        if not self._registered:
            try:
                get_transaction().register(Surrogate(self))
                self._begin()
                self._registered = 1
                self._finalize = 0
            except: pass

    def tpc_begin(self, *ignored): pass
    commit = tpc_begin

    def _finish(self):
        self.db.commit()

    def _abort(self):
        self.db.rollback()

    def tpc_vote(self, *ignored):
        self._finalize = 1

    def tpc_finish(self, *ignored):
        if self._finalize:
            try: self._finish()
            finally: self._registered=0

    def abort(self, *ignored):
        try: self._abort()
        finally: self._registered = 0

    tpc_abort = abort        

class Surrogate:

    def __init__(self, db):
        self._p_jar=db
        self.__inform_commit__=db.tpc_finish
        self.__inform_abort__=db.tpc_abort