Collabortation Diagrams
Caution
This document hasn’t been reviewed since 2005 and is likely out of date.
This file contains several collaboration diagrams for the ZODB.
Simple fetch, modify, commit
Participants
DB
:ZODB.DB.DB
C
:ZODB.Connection.Connection
S
:ZODB.FileStorage.FileStorage
T
:transaction.interfaces.ITransaction
TM
:transaction.interfaces.ITransactionManager
o1
,o2
, …: pre-existing persistent objects
Scenario
DB.open()
create C
TM.registerSynch(C)
TM.begin()
create T
C.get(1) # fetches o1
C.get(2) # fetches o2
C.get(3) # fetches o3
o1.modify() # anything that modifies o1
C.register(o1)
T.join(C)
o2.modify()
C.register(o2)
# T.join(C) does not happen again
o1.modify()
# C.register(o1) doesn't happen again, because o1 was already
# in the changed state.
T.commit()
C.beforeCompletion(T)
C.tpc_begin(T)
S.tpc_begin(T)
C.commit(T)
S.store(1, ..., T)
S.store(2, ..., T)
# o3 is not stored, because it wasn't modified
C.tpc_vote(T)
S.tpc_vote(T)
C.tpc_finish(T)
S.tpc_finish(T, f) # f is a callback function, which arranges
# to call DB.invalidate (next)
DB.invalidate(tid, {1: 1, 2: 1}, C)
C2.invalidate(tid, {1: 1, 2: 1}) # for all connections
# C2 to DB, where C2
# is not C
TM.free(T)
C.afterCompletion(T)
C._flush_invalidations()
# Processes invalidations that may have come in from other
# transactions.
Simple fetch, modify, abort
Participants
DB
:ZODB.DB.DB
C
:ZODB.Connection.Connection
S
:ZODB.FileStorage.FileStorage
T
:transaction.interfaces.ITransaction
TM
:transaction.interfaces.ITransactionManager
o1
,o2
, …: pre-existing persistent objects
Scenario
DB.open()
create C
TM.registerSynch(C)
TM.begin()
create T
C.get(1) # fetches o1
C.get(2) # fetches o2
C.get(3) # fetches o3
o1.modify() # anything that modifies o1
C.register(o1)
T.join(C)
o2.modify()
C.register(o2)
# T.join(C) does not happen again
o1.modify()
# C.register(o1) doesn't happen again, because o1 was already
# in the changed state.
T.abort()
C.beforeCompletion(T)
C.abort(T)
C._cache.invalidate(1) # toss changes to o1
C._cache.invalidate(2) # toss changes to o2
# o3 wasn't modified, and its cache entry isn't invalidated.
TM.free(T)
C.afterCompletion(T)
C._flush_invalidations()
# Processes invalidations that may have come in from other
# transactions.
Rollback of a savepoint
Participants
T
:transaction.interfaces.ITransaction
o1
,o2
,o3
: some persistent objectsC1
,C2
,C3
: resource managersS1
,S2
: Transaction savepoint objectss11
,s21
,s22
: resource-manager savepoints
Scenario
create T
o1.modify()
C1.regisiter(o1)
T.join(C1)
T.savepoint()
C1.savepoint()
return s11
return S1 = Savepoint(T, [r11])
o1.modify()
C1.regisiter(o1)
o2.modify()
C2.regisiter(o2)
T.join(C2)
T.savepoint()
C1.savepoint()
return s21
C2.savepoint()
return s22
return S2 = Savepoint(T, [r21, r22])
o3.modify()
C3.regisiter(o3)
T.join(C3)
S1.rollback()
S2.rollback()
T.discard()
C1.discard()
C2.discard()
C3.discard()
o3.invalidate()
S2.discard()
s21.discard() # roll back changes since previous, which is r11
C1.discard(s21)
o1.invalidate()
# truncates temporary storage to s21's position
s22.discard() # roll back changes since previous, which is r11
C1.discard(s22)
o2.invalidate()
# truncates temporary storage to beginning, because
# s22 was the first savepoint. (Perhaps conection
# savepoints record the log position before the
# data were written, which is 0 in this case.
T.commit()
C1.beforeCompletion(T)
C2.beforeCompletion(T)
C3.beforeCompletion(T)
C1.tpc_begin(T)
S1.tpc_begin(T)
C2.tpc_begin(T)
C3.tpc_begin(T)
C1.commit(T)
S1.store(1, ..., T)
C2.commit(T)
C3.commit(T)
C1.tpc_vote(T)
S1.tpc_vote(T)
C2.tpc_vote(T)
C3.tpc_vote(T)
C1.tpc_finish(T)
S1.tpc_finish(T, f) # f is a callback function, which arranges
c# to call DB.invalidate (next)
DB.invalidate(tid, {1: 1}, C)
TM.free(T)
C1.afterCompletion(T)
C1._flush_invalidations()
C2.afterCompletion(T)
C2._flush_invalidations()
C3.afterCompletion(T)
C3._flush_invalidations()