This file is indexed.

/usr/share/pyshared/transaction/tests/savepointsample.py is in python-transaction 1.1.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
##############################################################################
#
# Copyright (c) 2004 Zope Foundation 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.
#
##############################################################################
"""Savepoint data manager implementation example.

Sample data manager implementation that illustrates how to implement
savepoints.

See savepoint.txt in the transaction package.
"""

import UserDict
from zope import interface
import transaction.interfaces

class SampleDataManager(UserDict.DictMixin):
    """Sample implementation of data manager that doesn't support savepoints

    This data manager stores named simple values, like strings and numbers.
    """

    interface.implements(transaction.interfaces.IDataManager)

    def __init__(self, transaction_manager=None):
        if transaction_manager is None:
            # Use the thread-local transaction manager if none is provided:
            import transaction
            transaction_manager = transaction.manager
        self.transaction_manager = transaction_manager

        # Our committed and uncommitted data:
        self.committed = {}
        self.uncommitted = self.committed.copy()

        # Our transaction state:
        #
        #   If our uncommitted data is modified, we'll join a transaction
        #   and keep track of the transaction we joined.  Any commit
        #   related messages we get should be for this same transaction
        self.transaction = None

        #   What phase, if any, of two-phase commit we are in:
        self.tpc_phase = None


    #######################################################################
    # Provide a mapping interface to uncommitted data.  We provide
    # a basic subset of the interface. DictMixin does the rest.

    def __getitem__(self, name):
        return self.uncommitted[name]

    def __setitem__(self, name, value):
        self._join() # join the current transaction, if we haven't already
        self.uncommitted[name] = value

    def __delitem__(self, name):
        self._join() # join the current transaction, if we haven't already
        del self.uncommitted[name]

    def keys(self):
        return self.uncommitted.keys()

    #
    #######################################################################

    #######################################################################
    # Transaction methods

    def _join(self):
        # If this is the first change in the transaction, join the transaction
        if self.transaction is None:
            self.transaction = self.transaction_manager.get()
            self.transaction.join(self)

    def _resetTransaction(self):
        self.last_note = getattr(self.transaction, 'description', None)
        self.transaction = None
        self.tpc_phase = None

    def abort(self, transaction):
        """Throw away changes made before the commit process has started
        """
        assert ((transaction is self.transaction) or (self.transaction is None)
                ), "Must not change transactions"
        assert self.tpc_phase is None, "Must be called outside of tpc"
        self.uncommitted = self.committed.copy()
        self._resetTransaction()

    def tpc_begin(self, transaction):
        """Enter two-phase commit
        """
        assert transaction is self.transaction, "Must not change transactions"
        assert self.tpc_phase is None, "Must be called outside of tpc"
        self.tpc_phase = 1

    def commit(self, transaction):
        """Record data modified during the transaction
        """
        assert transaction is self.transaction, "Must not change transactions"
        assert self.tpc_phase == 1, "Must be called in first phase of tpc"

        # In our simple example, we don't need to do anything.
        # A more complex data manager would typically write to some sort
        # of log.

    def tpc_vote(self, transaction):
        assert transaction is self.transaction, "Must not change transactions"
        assert self.tpc_phase == 1, "Must be called in first phase of tpc"
        # This particular data manager is always ready to vote.
        # Real data managers will usually need to take some steps to
        # make sure that the finish will succeed
        self.tpc_phase = 2

    def tpc_finish(self, transaction):
        assert transaction is self.transaction, "Must not change transactions"
        assert self.tpc_phase == 2, "Must be called in second phase of tpc"
        self.committed = self.uncommitted.copy()
        self._resetTransaction()

    def tpc_abort(self, transaction):
        assert transaction is self.transaction, "Must not change transactions"
        assert self.tpc_phase is not None, "Must be called inside of tpc"
        self.uncommitted = self.committed.copy()
        self._resetTransaction()

    #
    #######################################################################

    #######################################################################
    # Other data manager methods

    def sortKey(self):
        # Commit operations on multiple data managers are performed in
        # sort key order.  This important to avoid deadlock when data
        # managers are shared among multiple threads or processes and
        # use locks to manage that sharing.  We aren't going to bother
        # with that here.
        return str(id(self))

    #
    #######################################################################

class SampleSavepointDataManager(SampleDataManager):
    """Sample implementation of a savepoint-supporting data manager

    This extends the basic data manager with savepoint support.
    """

    interface.implements(transaction.interfaces.ISavepointDataManager)

    def savepoint(self):
        # When we create the savepoint, we save the existing database state.
        return SampleSavepoint(self, self.uncommitted.copy())

    def _rollback_savepoint(self, savepoint):
        # When we rollback the savepoint, we restore the saved data.
        # Caution:  without the copy(), further changes to the database
        # could reflect in savepoint.data, and then `savepoint` would no
        # longer contain the originally saved data, and so `savepoint`
        # couldn't restore the original state if a rollback to this
        # savepoint was done again.  IOW, copy() is necessary.
        self.uncommitted = savepoint.data.copy()

class SampleSavepoint:

    interface.implements(transaction.interfaces.IDataManagerSavepoint)

    def __init__(self, data_manager, data):
        self.data_manager = data_manager
        self.data = data

    def rollback(self):
        self.data_manager._rollback_savepoint(self)