Commit 4d75c428 authored by Jim Fulton's avatar Jim Fulton Committed by GitHub

Merge pull request #79 from zopefoundation/work-with-transaction-changes

Fixed: ZEO needed changes to work with recent transaction changes.
parents bc74c389 ec23bd8b
Changelog Changelog
========= =========
- Fixed: ZEO needed changes to work with recent transaction changes.
5.0.3 (2016-11-18) 5.0.3 (2016-11-18)
------------------ ------------------
......
...@@ -26,9 +26,9 @@ if (3, 0) < sys.version_info < (3, 4): ...@@ -26,9 +26,9 @@ if (3, 0) < sys.version_info < (3, 4):
sys.exit(1) sys.exit(1)
install_requires = [ install_requires = [
'ZODB >= 5.0.0a5, < 5.1.0', 'ZODB >= 5.1.1',
'six', 'six',
'transaction >= 1.6.0, < 2.0.0', 'transaction >= 2.0.3',
'persistent >= 4.1.0', 'persistent >= 4.1.0',
'zc.lockfile', 'zc.lockfile',
'ZConfig', 'ZConfig',
......
...@@ -823,7 +823,7 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage): ...@@ -823,7 +823,7 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
try: try:
self._async( self._async(
'tpc_begin', id(txn), 'tpc_begin', id(txn),
txn.user, txn.description, txn._extension, tid, status) txn.user, txn.description, txn.extension, tid, status)
except ClientDisconnected: except ClientDisconnected:
self.tpc_end(txn) self.tpc_end(txn)
raise raise
......
...@@ -28,7 +28,6 @@ import sys ...@@ -28,7 +28,6 @@ import sys
import tempfile import tempfile
import threading import threading
import time import time
import transaction
import warnings import warnings
import ZEO.asyncio.server import ZEO.asyncio.server
import ZODB.blob import ZODB.blob
...@@ -42,6 +41,7 @@ from ZEO._compat import Pickler, Unpickler, PY3, BytesIO ...@@ -42,6 +41,7 @@ from ZEO._compat import Pickler, Unpickler, PY3, BytesIO
from ZEO.Exceptions import AuthError from ZEO.Exceptions import AuthError
from ZEO.monitor import StorageStats from ZEO.monitor import StorageStats
from ZEO.asyncio.server import Delay, MTDelay, Result from ZEO.asyncio.server import Delay, MTDelay, Result
from ZODB.Connection import TransactionMetaData
from ZODB.loglevels import BLATHER from ZODB.loglevels import BLATHER
from ZODB.POSException import StorageError, StorageTransactionError from ZODB.POSException import StorageError, StorageTransactionError
from ZODB.POSException import TransactionError, ReadOnlyError, ConflictError from ZODB.POSException import TransactionError, ReadOnlyError, ConflictError
...@@ -308,11 +308,8 @@ class ZEOStorage: ...@@ -308,11 +308,8 @@ class ZEOStorage:
raise StorageTransactionError("Multiple simultaneous tpc_begin" raise StorageTransactionError("Multiple simultaneous tpc_begin"
" requests from one client.") " requests from one client.")
t = transaction.Transaction() t = TransactionMetaData(user, description, ext)
t.id = id t.id = id
t.user = user
t.description = description
t._extension = ext
self.serials = [] self.serials = []
self.conflicts = {} self.conflicts = {}
......
...@@ -18,7 +18,7 @@ from __future__ import print_function ...@@ -18,7 +18,7 @@ from __future__ import print_function
import sys import sys
import time import time
from ZODB.Transaction import Transaction from ZODB.Connection import TransactionMetaData
from ZODB.tests.MinPO import MinPO from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_pickle from ZODB.tests.StorageTestBase import zodb_pickle
from ZEO.ClientStorage import ClientStorage from ZEO.ClientStorage import ClientStorage
...@@ -57,7 +57,7 @@ def main(): ...@@ -57,7 +57,7 @@ def main():
revid = ZERO revid = ZERO
data = MinPO("timeout.py") data = MinPO("timeout.py")
pickled_data = zodb_pickle(data) pickled_data = zodb_pickle(data)
t = Transaction() t = TransactionMetaData()
t.user = "timeout.py" t.user = "timeout.py"
storage.tpc_begin(t) storage.tpc_begin(t)
storage.store(oid, revid, pickled_data, '', t) storage.store(oid, revid, pickled_data, '', t)
......
...@@ -48,7 +48,7 @@ from ZODB.FileStorage import FileStorage ...@@ -48,7 +48,7 @@ from ZODB.FileStorage import FileStorage
#from BDBStorage.BDBFullStorage import BDBFullStorage #from BDBStorage.BDBFullStorage import BDBFullStorage
#from Standby.primary import PrimaryStorage #from Standby.primary import PrimaryStorage
#from Standby.config import RS_PORT #from Standby.config import RS_PORT
from ZODB.Transaction import Transaction from ZODB.Connection import TransactionMetaData
from ZODB.utils import p64 from ZODB.utils import p64
from functools import reduce from functools import reduce
...@@ -149,7 +149,7 @@ class ReplayTxn(TxnStat): ...@@ -149,7 +149,7 @@ class ReplayTxn(TxnStat):
def replay(self): def replay(self):
ZERO = '\0'*8 ZERO = '\0'*8
t0 = now() t0 = now()
t = Transaction() t = TransactionMetaData()
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
for obj in self._objects: for obj in self._objects:
oid = obj.oid oid = obj.oid
......
...@@ -13,11 +13,10 @@ ...@@ -13,11 +13,10 @@
############################################################################## ##############################################################################
"""Tests of the ZEO cache""" """Tests of the ZEO cache"""
from ZODB.Connection import TransactionMetaData
from ZODB.tests.MinPO import MinPO from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_unpickle from ZODB.tests.StorageTestBase import zodb_unpickle
from transaction import Transaction
class TransUndoStorageWithCache: class TransUndoStorageWithCache:
def checkUndoInvalidation(self): def checkUndoInvalidation(self):
...@@ -35,8 +34,8 @@ class TransUndoStorageWithCache: ...@@ -35,8 +34,8 @@ class TransUndoStorageWithCache:
tid = info[0]['id'] tid = info[0]['id']
# Now start an undo transaction # Now start an undo transaction
t = Transaction() t = TransactionMetaData()
t.note('undo1') t.note(u'undo1')
oids = self._begin_undos_vote(t, tid) oids = self._begin_undos_vote(t, tid)
# Make sure this doesn't load invalid data into the cache # Make sure this doesn't load invalid data into the cache
......
...@@ -17,7 +17,7 @@ import threading ...@@ -17,7 +17,7 @@ import threading
import time import time
from persistent.TimeStamp import TimeStamp from persistent.TimeStamp import TimeStamp
import transaction from ZODB.Connection import TransactionMetaData
from ZODB.tests.StorageTestBase import zodb_pickle, MinPO from ZODB.tests.StorageTestBase import zodb_pickle, MinPO
import ZEO.ClientStorage import ZEO.ClientStorage
...@@ -89,7 +89,7 @@ class CommitLockTests: ...@@ -89,7 +89,7 @@ class CommitLockTests:
self._storages = [] self._storages = []
def _start_txn(self): def _start_txn(self):
txn = transaction.Transaction() txn = TransactionMetaData()
self._storage.tpc_begin(txn) self._storage.tpc_begin(txn)
oid = self._storage.new_oid() oid = self._storage.new_oid()
self._storage.store(oid, ZERO, zodb_pickle(MinPO(1)), '', txn) self._storage.store(oid, ZERO, zodb_pickle(MinPO(1)), '', txn)
...@@ -104,7 +104,7 @@ class CommitLockTests: ...@@ -104,7 +104,7 @@ class CommitLockTests:
for i in range(self.NUM_CLIENTS): for i in range(self.NUM_CLIENTS):
storage = self._duplicate_client() storage = self._duplicate_client()
txn = transaction.Transaction() txn = TransactionMetaData()
tid = self._get_timestamp() tid = self._get_timestamp()
t = WorkerThread(self, storage, txn) t = WorkerThread(self, storage, txn)
......
...@@ -24,6 +24,7 @@ from ZEO.Exceptions import ClientDisconnected ...@@ -24,6 +24,7 @@ from ZEO.Exceptions import ClientDisconnected
from ZEO.asyncio.marshal import encode from ZEO.asyncio.marshal import encode
from ZEO.tests import forker from ZEO.tests import forker
from ZODB.Connection import TransactionMetaData
from ZODB.DB import DB from ZODB.DB import DB
from ZODB.POSException import ReadOnlyError, ConflictError from ZODB.POSException import ReadOnlyError, ConflictError
from ZODB.tests.StorageTestBase import StorageTestBase from ZODB.tests.StorageTestBase import StorageTestBase
...@@ -32,7 +33,6 @@ from ZODB.tests.StorageTestBase import zodb_pickle, zodb_unpickle ...@@ -32,7 +33,6 @@ from ZODB.tests.StorageTestBase import zodb_pickle, zodb_unpickle
import ZODB.tests.util import ZODB.tests.util
import transaction import transaction
from transaction import Transaction
from . import testssl from . import testssl
...@@ -863,7 +863,7 @@ class ReconnectionTests(CommonSetupTearDown): ...@@ -863,7 +863,7 @@ class ReconnectionTests(CommonSetupTearDown):
self._storage = self.openClientStorage() self._storage = self.openClientStorage()
self._dostore() self._dostore()
oids = [self._storage.new_oid() for i in range(5)] oids = [self._storage.new_oid() for i in range(5)]
txn = Transaction() txn = TransactionMetaData()
self._storage.tpc_begin(txn) self._storage.tpc_begin(txn)
for oid in oids: for oid in oids:
data = zodb_pickle(MinPO(oid)) data = zodb_pickle(MinPO(oid))
...@@ -957,7 +957,7 @@ class TimeoutTests(CommonSetupTearDown): ...@@ -957,7 +957,7 @@ class TimeoutTests(CommonSetupTearDown):
def checkTimeout(self): def checkTimeout(self):
self._storage = storage = self.openClientStorage() self._storage = storage = self.openClientStorage()
txn = Transaction() txn = TransactionMetaData()
storage.tpc_begin(txn) storage.tpc_begin(txn)
storage.tpc_vote(txn) storage.tpc_vote(txn)
time.sleep(2) time.sleep(2)
...@@ -977,7 +977,7 @@ class TimeoutTests(CommonSetupTearDown): ...@@ -977,7 +977,7 @@ class TimeoutTests(CommonSetupTearDown):
def checkTimeoutOnAbort(self): def checkTimeoutOnAbort(self):
storage = self.openClientStorage() storage = self.openClientStorage()
txn = Transaction() txn = TransactionMetaData()
storage.tpc_begin(txn) storage.tpc_begin(txn)
storage.tpc_vote(txn) storage.tpc_vote(txn)
storage.tpc_abort(txn) storage.tpc_abort(txn)
...@@ -985,7 +985,7 @@ class TimeoutTests(CommonSetupTearDown): ...@@ -985,7 +985,7 @@ class TimeoutTests(CommonSetupTearDown):
def checkTimeoutOnAbortNoLock(self): def checkTimeoutOnAbortNoLock(self):
storage = self.openClientStorage() storage = self.openClientStorage()
txn = Transaction() txn = TransactionMetaData()
storage.tpc_begin(txn) storage.tpc_begin(txn)
storage.tpc_abort(txn) storage.tpc_abort(txn)
storage.close() storage.close()
...@@ -998,7 +998,7 @@ class TimeoutTests(CommonSetupTearDown): ...@@ -998,7 +998,7 @@ class TimeoutTests(CommonSetupTearDown):
oid = storage.new_oid() oid = storage.new_oid()
obj = MinPO(7) obj = MinPO(7)
# Now do a store, sleeping before the finish so as to cause a timeout # Now do a store, sleeping before the finish so as to cause a timeout
t = Transaction() t = TransactionMetaData()
old_connection_count = storage.connection_count_for_tests old_connection_count = storage.connection_count_for_tests
storage.tpc_begin(t) storage.tpc_begin(t)
revid1 = storage.store(oid, ZERO, zodb_pickle(obj), '', t) revid1 = storage.store(oid, ZERO, zodb_pickle(obj), '', t)
...@@ -1051,7 +1051,7 @@ class MSTThread(threading.Thread): ...@@ -1051,7 +1051,7 @@ class MSTThread(threading.Thread):
c.__serials = {} c.__serials = {}
# Begin a transaction # Begin a transaction
t = Transaction() t = TransactionMetaData()
for c in clients: for c in clients:
#print("%s.%s.%s begin" % (tname, c.__name, i)) #print("%s.%s.%s begin" % (tname, c.__name, i))
c.tpc_begin(t) c.tpc_begin(t)
......
...@@ -83,7 +83,7 @@ class StressTask: ...@@ -83,7 +83,7 @@ class StressTask:
def commit(self): def commit(self):
cn = self.cn cn = self.cn
key = self.startnum key = self.startnum
self.tm.get().note("add key %s" % key) self.tm.get().note(u"add key %s" % key)
try: try:
self.tm.get().commit() self.tm.get().commit()
except ConflictError as msg: except ConflictError as msg:
...@@ -155,7 +155,7 @@ class StressThread(FailableThread): ...@@ -155,7 +155,7 @@ class StressThread(FailableThread):
while not self.stop.isSet(): while not self.stop.isSet():
try: try:
tree[key] = self.threadnum tree[key] = self.threadnum
tm.get().note("add key %s" % key) tm.get().note(u"add key %s" % key)
tm.commit() tm.commit()
self.commitdict[self] = 1 self.commitdict[self] = 1
if self.sleep: if self.sleep:
...@@ -218,7 +218,7 @@ class LargeUpdatesThread(FailableThread): ...@@ -218,7 +218,7 @@ class LargeUpdatesThread(FailableThread):
break break
else: else:
# print("%d set #%d" % (self.threadnum, len(keys))) # print("%d set #%d" % (self.threadnum, len(keys)))
transaction.get().note("keys %s" % ", ".join(map(str, keys))) transaction.get().note(u"keys %s" % ", ".join(map(str, keys)))
try: try:
transaction.commit() transaction.commit()
self.commitdict[self] = 1 self.commitdict[self] = 1
......
...@@ -17,6 +17,8 @@ import transaction ...@@ -17,6 +17,8 @@ import transaction
import six import six
import gc import gc
from ZODB.Connection import TransactionMetaData
from ..asyncio.testing import AsyncRPC from ..asyncio.testing import AsyncRPC
class IterationTests: class IterationTests:
...@@ -28,14 +30,16 @@ class IterationTests: ...@@ -28,14 +30,16 @@ class IterationTests:
# First, confirm that it ran # First, confirm that it ran
self.assertTrue(self._storage._iterators._last_gc > 0) self.assertTrue(self._storage._iterators._last_gc > 0)
gc_enabled = gc.isenabled() gc_enabled = gc.isenabled()
gc.disable() # make sure there's no race conditions cleaning out the weak refs # make sure there's no race conditions cleaning out the weak refs
gc.disable()
try: try:
self.assertEquals(0, len(self._storage._iterator_ids)) self.assertEquals(0, len(self._storage._iterator_ids))
except AssertionError: except AssertionError:
# Ok, we have ids. That should also mean that the # Ok, we have ids. That should also mean that the
# weak dictionary has the same length. # weak dictionary has the same length.
self.assertEqual(len(self._storage._iterators), len(self._storage._iterator_ids)) self.assertEqual(len(self._storage._iterators),
len(self._storage._iterator_ids))
# Now if we do a collection and re-ask for iterator_gc # Now if we do a collection and re-ask for iterator_gc
# everything goes away as expected. # everything goes away as expected.
gc.enable() gc.enable()
...@@ -44,7 +48,8 @@ class IterationTests: ...@@ -44,7 +48,8 @@ class IterationTests:
self._storage._iterator_gc() self._storage._iterator_gc()
self.assertEqual(len(self._storage._iterators), len(self._storage._iterator_ids)) self.assertEqual(len(self._storage._iterators),
len(self._storage._iterator_ids))
self.assertEquals(0, len(self._storage._iterator_ids)) self.assertEquals(0, len(self._storage._iterator_ids))
finally: finally:
if gc_enabled: if gc_enabled:
...@@ -126,7 +131,7 @@ class IterationTests: ...@@ -126,7 +131,7 @@ class IterationTests:
iid = list(self._storage._iterator_ids)[0] iid = list(self._storage._iterator_ids)[0]
t = transaction.Transaction() t = TransactionMetaData()
self._storage._iterators._last_gc = -1 self._storage._iterators._last_gc = -1
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
self._storage.tpc_abort(t) self._storage.tpc_abort(t)
...@@ -143,7 +148,7 @@ class IterationTests: ...@@ -143,7 +148,7 @@ class IterationTests:
six.advance_iterator(self._storage.iterator()) six.advance_iterator(self._storage.iterator())
iid = list(self._storage._iterator_ids)[0] iid = list(self._storage._iterator_ids)[0]
t = transaction.Transaction() t = TransactionMetaData()
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
# Show that after disconnecting, the client side GCs the iterators # Show that after disconnecting, the client side GCs the iterators
# as well. I'm calling this directly to avoid accidentally # as well. I'm calling this directly to avoid accidentally
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
import threading import threading
import transaction from ZODB.Connection import TransactionMetaData
from ZODB.tests.StorageTestBase import zodb_pickle, MinPO from ZODB.tests.StorageTestBase import zodb_pickle, MinPO
import ZEO.Exceptions import ZEO.Exceptions
...@@ -24,7 +24,7 @@ ZERO = '\0'*8 ...@@ -24,7 +24,7 @@ ZERO = '\0'*8
class BasicThread(threading.Thread): class BasicThread(threading.Thread):
def __init__(self, storage, doNextEvent, threadStartedEvent): def __init__(self, storage, doNextEvent, threadStartedEvent):
self.storage = storage self.storage = storage
self.trans = transaction.Transaction() self.trans = TransactionMetaData()
self.doNextEvent = doNextEvent self.doNextEvent = doNextEvent
self.threadStartedEvent = threadStartedEvent self.threadStartedEvent = threadStartedEvent
self.gotValueError = 0 self.gotValueError = 0
......
...@@ -28,7 +28,6 @@ import sys ...@@ -28,7 +28,6 @@ import sys
import tempfile import tempfile
import threading import threading
import time import time
import transaction
import warnings import warnings
from .zrpc.error import DisconnectedError from .zrpc.error import DisconnectedError
import ZODB.blob import ZODB.blob
...@@ -43,6 +42,7 @@ from ZEO.Exceptions import AuthError ...@@ -43,6 +42,7 @@ from ZEO.Exceptions import AuthError
from .monitor import StorageStats, StatsServer from .monitor import StorageStats, StatsServer
from .zrpc.connection import ManagedServerConnection, Delay, MTDelay, Result from .zrpc.connection import ManagedServerConnection, Delay, MTDelay, Result
from .zrpc.server import Dispatcher from .zrpc.server import Dispatcher
from ZODB.Connection import TransactionMetaData
from ZODB.loglevels import BLATHER from ZODB.loglevels import BLATHER
from ZODB.POSException import StorageError, StorageTransactionError from ZODB.POSException import StorageError, StorageTransactionError
from ZODB.POSException import TransactionError, ReadOnlyError, ConflictError from ZODB.POSException import TransactionError, ReadOnlyError, ConflictError
...@@ -375,11 +375,8 @@ class ZEOStorage: ...@@ -375,11 +375,8 @@ class ZEOStorage:
raise StorageTransactionError("Multiple simultaneous tpc_begin" raise StorageTransactionError("Multiple simultaneous tpc_begin"
" requests from one client.") " requests from one client.")
t = transaction.Transaction() t = TransactionMetaData(user, description, ext)
t.id = id t.id = id
t.user = user
t.description = description
t._extension = ext
self.serials = [] self.serials = []
self.invalidated = [] self.invalidated = []
......
...@@ -20,6 +20,8 @@ from ZEO.ClientStorage import ClientStorage ...@@ -20,6 +20,8 @@ from ZEO.ClientStorage import ClientStorage
from ZEO.tests import forker, Cache, CommitLockTests, ThreadTests from ZEO.tests import forker, Cache, CommitLockTests, ThreadTests
from ZEO.tests import IterationTests from ZEO.tests import IterationTests
from ZEO._compat import PY3 from ZEO._compat import PY3
from ZODB.Connection import TransactionMetaData
from ZODB.tests import StorageTestBase, BasicStorage, \ from ZODB.tests import StorageTestBase, BasicStorage, \
TransactionalUndoStorage, \ TransactionalUndoStorage, \
PackableStorage, Synchronization, ConflictResolution, RevisionStorage, \ PackableStorage, Synchronization, ConflictResolution, RevisionStorage, \
...@@ -551,7 +553,7 @@ class CommonBlobTests: ...@@ -551,7 +553,7 @@ class CommonBlobTests:
data = zodb_pickle(blob) data = zodb_pickle(blob)
self.assert_(os.path.exists(tfname)) self.assert_(os.path.exists(tfname))
t = transaction.Transaction() t = TransactionMetaData()
try: try:
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
self._storage.storeBlob(oid, ZERO, data, tfname, '', t) self._storage.storeBlob(oid, ZERO, data, tfname, '', t)
...@@ -590,7 +592,7 @@ class CommonBlobTests: ...@@ -590,7 +592,7 @@ class CommonBlobTests:
oid = self._storage.new_oid() oid = self._storage.new_oid()
data = zodb_pickle(blob) data = zodb_pickle(blob)
t = transaction.Transaction() t = TransactionMetaData()
try: try:
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
self._storage.storeBlob(oid, ZERO, data, tfname, '', t) self._storage.storeBlob(oid, ZERO, data, tfname, '', t)
...@@ -614,7 +616,7 @@ class CommonBlobTests: ...@@ -614,7 +616,7 @@ class CommonBlobTests:
oid = self._storage.new_oid() oid = self._storage.new_oid()
with open('blob_file', 'wb') as f: with open('blob_file', 'wb') as f:
f.write(b'I am a happy blob.') f.write(b'I am a happy blob.')
t = transaction.Transaction() t = TransactionMetaData()
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
self._storage.storeBlob( self._storage.storeBlob(
oid, ZODB.utils.z64, 'foo', 'blob_file', '', t) oid, ZODB.utils.z64, 'foo', 'blob_file', '', t)
...@@ -655,7 +657,7 @@ class BlobAdaptedFileStorageTests(FullGenericTests, CommonBlobTests): ...@@ -655,7 +657,7 @@ class BlobAdaptedFileStorageTests(FullGenericTests, CommonBlobTests):
data = zodb_pickle(blob) data = zodb_pickle(blob)
self.assert_(os.path.exists(tfname)) self.assert_(os.path.exists(tfname))
t = transaction.Transaction() t = TransactionMetaData()
try: try:
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
self._storage.storeBlob(oid, ZERO, data, tfname, '', t) self._storage.storeBlob(oid, ZERO, data, tfname, '', t)
...@@ -918,24 +920,25 @@ def tpc_finish_error(): ...@@ -918,24 +920,25 @@ def tpc_finish_error():
>>> conn = db.open() >>> conn = db.open()
>>> conn.root.x = 1 >>> conn.root.x = 1
>>> t = conn.transaction_manager.get() >>> t = conn.transaction_manager.get()
>>> conn._storage.tpc_begin(t) >>> conn.tpc_begin(t)
>>> conn.commit(t) >>> conn.commit(t)
>>> _ = client.tpc_vote(t) >>> transaction_meta_data = t.data(conn)
>>> _ = client.tpc_vote(transaction_meta_data)
Cause some breakage by messing with the clients transaction Cause some breakage by messing with the clients transaction
buffer, sadly, using implementation details: buffer, sadly, using implementation details:
>>> tbuf = t.data(client) >>> tbuf = client._check_trans(transaction_meta_data, 'test')
>>> tbuf.client_resolved = None >>> tbuf.client_resolved = None
tpc_finish will fail: tpc_finish will fail:
>>> client.tpc_finish(t) # doctest: +ELLIPSIS >>> client.tpc_finish(transaction_meta_data) # doctest: +ELLIPSIS
Traceback (most recent call last): Traceback (most recent call last):
... ...
AttributeError: ... AttributeError: ...
>>> client.tpc_abort(t) >>> client.tpc_abort(transaction_meta_data)
>>> t.abort() >>> t.abort()
But we can still load the saved data: But we can still load the saved data:
......
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