mò €ã¸Ec@sdZdkZdkZdkZdkZdkZdkZdklZdk l Z dk l Z e ƒZd„Zdfd„ƒYZde fd „ƒYZd e fd „ƒYZd „Zd „Zde fd„ƒYZdfd„ƒYZdfd„ƒYZdfd„ƒYZdS(s·Transaction objects manage resources for an individual activity. Compatibility issues -------------------- The implementation of Transaction objects involves two layers of backwards compatibility, because this version of transaction supports both ZODB 3 and ZODB 4. Zope is evolving towards the ZODB4 interfaces. Transaction has two methods for a resource manager to call to participate in a transaction -- register() and join(). join() takes a resource manager and adds it to the list of resources. register() is for backwards compatibility. It takes a persistent object and registers its _p_jar attribute. TODO: explain adapter Subtransactions --------------- Note: Subtransactions are deprecated! Use savepoint/rollback instead. A subtransaction applies the transaction notion recursively. It allows a set of modifications within a transaction to be committed or aborted as a group. A subtransaction is a strictly local activity; its changes are not visible to any other database connection until the top-level transaction commits. In addition to its use to organize a large transaction, subtransactions can be used to optimize memory use. ZODB must keep modified objects in memory until a transaction commits and it can write the changes to the storage. A subtransaction uses a temporary disk storage for its commits, allowing modified objects to be flushed from memory when the subtransaction commits. The commit() and abort() methods take an optional subtransaction argument that defaults to false. If it is a true, the operation is performed on a subtransaction. Subtransactions add a lot of complexity to the transaction implementation. Some resource managers support subtransactions, but they are not required to. (ZODB Connection is the only standard resource manager that supports subtransactions.) Resource managers that do support subtransactions implement abort_sub() and commit_sub() methods and support a second argument to tpc_begin(). The second argument to tpc_begin() indicates that a subtransaction commit is beginning (if it is true). In a subtransaction, there is no tpc_vote() call, because sub-transactions don't need 2-phase commit. If a sub-transaction abort or commit fails, we can abort the outer transaction. The tpc_finish() or tpc_abort() call applies just to that subtransaction. Once a resource manager is involved in a subtransaction, all subsequent transactions will be treated as subtransactions until abort_sub() or commit_sub() is called. abort_sub() will undo all the changes of the subtransactions. commit_sub() will begin a top-level transaction and store all the changes from subtransactions. After commit_sub(), the transaction must still call tpc_vote() and tpc_finish(). If the resource manager does not support subtransactions, nothing happens when the subtransaction commits. Instead, the resource manager is put on a list of managers to commit when the actual top-level transaction commits. If this happens, it will not be possible to abort subtransactions. Two-phase commit ---------------- A transaction commit involves an interaction between the transaction object and one or more resource managers. The transaction manager calls the following four methods on each resource manager; it calls tpc_begin() on each resource manager before calling commit() on any of them. 1. tpc_begin(txn) 2. commit(txn) 3. tpc_vote(txn) 4. tpc_finish(txn) Subtransaction commit --------------------- Note: Subtransactions are deprecated! When a subtransaction commits, the protocol is different. 1. tpc_begin() is passed a second argument, which indicates that a subtransaction is being committed. 2. tpc_vote() is not called. Once a subtransaction has been committed, the top-level transaction commit will start with a commit_sub() call instead of a tpc_begin() call. Before-commit hook ------------------ Sometimes, applications want to execute some code when a transaction is committed. For example, one might want to delay object indexing until a transaction commits, rather than indexing every time an object is changed. Or someone might want to check invariants only after a set of operations. A pre-commit hook is available for such use cases: use addBeforeCommitHook(), passing it a callable and arguments. The callable will be called with its arguments at the start of the commit (but not for substransaction commits). After-commit hook ------------------ Sometimes, applications want to execute code after a transaction is committed or aborted. For example, one might want to launch non transactional code after a successful commit. Or still someone might want to launch asynchronous code after. A post-commit hook is available for such use cases: use addAfterCommitHook(), passing it a callable and arguments. The callable will be called with a Boolean value representing the status of the commit operation as first argument (true if successfull or false iff aborted) preceding its arguments at the start of the commit (but not for substransaction commits). Error handling -------------- When errors occur during two-phase commit, the transaction manager aborts all the resource managers. The specific methods it calls depend on whether the error occurs before or after the call to tpc_vote() on that transaction manager. If the resource manager has not voted, then the resource manager will have one or more uncommitted objects. There are two cases that lead to this state; either the transaction manager has not called commit() for any objects on this resource manager or the call that failed was a commit() for one of the objects of this resource manager. For each uncommitted object, including the object that failed in its commit(), call abort(). Once uncommitted objects are aborted, tpc_abort() or abort_sub() is called on each resource manager. Synchronization --------------- You can register sychronization objects (synchronizers) with the tranasction manager. The synchronizer must implement beforeCompletion() and afterCompletion() methods. The transaction manager calls beforeCompletion() when it starts a top-level two-phase commit. It calls afterCompletion() when a top-level transaction is committed or aborted. The methods are passed the current Transaction as their only argument. N(sStringIO(s interface(s interfacescCst||tƒtj S(N(tgetattrtobjtattrt_marker(RR((t7/data/zmath/zope/lib/python/transaction/_transaction.pyt myhasattrºstStatuscBs tZdZdZdZdZRS(NtActivet Committingt Committeds Commit failed(t__name__t __module__tACTIVEt COMMITTINGt COMMITTEDt COMMITFAILED(((RR½st TransactioncBs2tZeieieiƒdZdZ dZ dZ dZ ddd„Z d„Zd„Zed„Zd„Zd„Zd „Zeed „Zd „Zd „Zd „Zfdd„Zd„Zd„Zd„Zfdd„Zed„Z d„Z!d„Z"eed„Z#d„Z$dd„Z%d„Z&RS(NitcCs´ti|_g|_|djodkl}|ƒ}n||_ ||_ h|_ h|_ h|_tidtiƒƒ|_|iidƒd|_g|_g|_dS(N(sWeakSetstxn.%dsnew transaction(RR tselftstatust _resourcest synchronizerstNonet ZODB.utilstWeakSett_synchronizerstmanagert_managert _adapterst_votedt _extensiontloggingt getLoggertthreadt get_identtlogtdebugt_failure_tracebackt_before_committ _after_commit(RRRR((Rt__init__ßs            cCsAdkl}|idj pt‚|d|iiƒƒ‚dS(N(sTransactionFailedErrors3An operation previously failed, with traceback: %s(tZODB.POSExceptiontTransactionFailedErrorRR%RtAssertionErrortgetvalue(RR*((Rt_prior_operation_faileds cCsÏ|itijo|iƒn|itij o tdti|ifƒ‚nt|dƒot |ƒ}n|i i |ƒ|i o=t ||ƒ}x+|i iƒD]}|ii |ƒq­WndS(Ns#expected txn status %r, but it's %rtprepare(RRRRR-R t ValueErrorRtresourcetDataManagerAdapterRtappendt_savepoint2indextAbortSavepointtdatamanager_savepointtkeysttransaction_savepointt _savepoints(RR0R5R7((Rtjoins  cCs¤|itijo|iƒnyt|||iŒ}Wn!|i |iƒ|i ƒnX|i djot iƒ|_ n|id7_|i|i |<|S(Ni(RRRRR-t Savepointt optimisticRt savepointt_cleanupt_saveAndRaiseCommitishErrorR3RtweakreftWeakKeyDictionaryt_savepoint_index(RR;R<((RR<0scCsU|i}||}x;|iƒD]-\}}||jod|_||=q q WdS(N( RR3tsavepoint2indexR<tindextitemstiRt transaction(RR<RCRBRE((Rt_remove_and_invalidate_afterDs     cCs4x |iiƒD]}d|_qW|iiƒdS(N(RR3R6R<RRFtclear(RR<((Rt_invalidate_all_savepointsNs cCsÂt|d|ƒ}|djotdƒ‚n|ii|ƒ}|djo:t |ƒ}|i i |ƒ||i|<|i |ƒn7t |ƒtt |i ƒjpt‚|i i |ƒdS(Nt_p_jarsRegister with no manager(RRRRR/RRtgettadaptertMultiObjectResourceAdaptertobjectsR2R9tidtmapR+(RRRRL((RtregisterTs     &cso|tjo d}n#|odkl}|dƒnˆioˆiƒn|oˆidt ƒˆ_ dSnˆi t i joˆiƒnˆiƒˆii‡d†ƒt iˆ_ yˆiƒt iˆ_ Wn8ˆiƒ\}}}ˆidtƒ|||‚nEXˆioˆiiˆƒnˆii‡d†ƒˆidt ƒˆiidƒdS( Ni(s deprecated37ssubtransactions are deprecated; instead of transaction.commit(1), use transaction.savepoint(optimistic=True) in contexts where a subtransaction abort will never occur, or sp=transaction.savepoint() if later rollback is possible and then sp.rollback() instead of transaction.abort(1)R;cs |iˆƒS(N(tstbeforeCompletionR(RR(R(Rt‡sRcs |iˆƒS(N(RRtafterCompletionR(RR(R(RRT”stcommit(tsubtransactionRtdeprecation_wngRt deprecated37RR3RIR<tTruet_subtransaction_savepointRRRR-t_callBeforeCommitHooksRRPR t_commitResourcesRt_saveAndGetCommitishErrortttvttbt_callAfterCommitHookstFalseRtfreeR#R$(RRWRXRaRYR`R_((RRRVms6        cCs†ti|_tƒ}|_tiƒ\}}}t i tidƒd|ƒt i|d|ƒ|it i||ƒƒ|||fS(Ni(RRRRtStringIOtftR%tsystexc_infoR_R`Rat tracebackt print_stackt _getframeRtprint_tbt writelinestformat_exception_only(RRfR_R`Ra((RR^˜s cCs%|iƒ\}}}|||‚dS(N(RR^R_R`Ra(RRaR_R`((RR>¥scCs t|iƒS(N(titerRR&(R((RtgetBeforeCommitHooks©scCs:|djo h}n|ii|t|ƒ|fƒdS(N(tkwsRRR&R2thookttupletargs(RRrRtRq((RtaddBeforeCommitHook¬s  cOs.dkl}|dƒ|i|||ƒdS(N(s deprecated38s4Use addBeforeCommitHook instead of beforeCommitHook.(Rt deprecated38RRuRrRtRq(RRrRtRqRv((RtbeforeCommitHook±s  cCs7x'|iD]\}}}|||Žq Wg|_dS(N(RR&RrRtRq(RRrRtRq((RR\·s cCs t|iƒS(N(RoRR'(R((RtgetAfterCommitHooksÀscCs:|djo h}n|ii|t|ƒ|fƒdS(N(RqRRR'R2RrRsRt(RRrRtRq((RtaddAfterCommitHookÃs  cCsÐ|ipdSnxW|iD]L\}}}y||||ŽWq|iid|dti ƒƒqXqWxK|i D]@}y|i |ƒWqv|iid|dti ƒƒqvXqvWg|_g|_ dS(Ns&Error in after commit hook exec in %s RhsError in abort() on manager %s(RR'RrRtRqRR#terrorRgRhRtrmtabortR&(RRRtRrRqR{((RRbÈs$      cs:tˆiƒ}|itƒyÄx|D]}|iˆƒq&Wx/|D]'}|iˆƒˆi i d|ƒqDWx.|D]&}|i ˆƒt ˆi t|ƒRpRuRwR\RxRyRbR]R=R|RŽR“R–(((RRÈs<  )  !   +      $ 0  RMcBs_tZdZd„Zd„Zd„Zd„Zd„Zd„Zd„Z d„Z d „Z RS( séAdapt the old-style register() call to the new-style join(). With join(), a resource mananger like a Connection registers with the transaction manager. With register(), an individual object is passed to register(). cCs||_g|_d|_dS(Ni(tjarRRRNt ncommitted(RR›((RR(as  cCs d|ii|it|ƒfS(Ns<%s for %s at %s>(Rt __class__R RRO(R((Rt__repr__fscCs |iiƒS(N(RRtsortKey(R((RRŸjscCs|ii|ƒdS(N(RRRttxn(RR ((RRmscCs|ii|ƒdS(N(RRRƒR (RR ((RRƒpscCs|ii|ƒdS(N(RRR†R (RR ((RR†sscCs:x3|iD](}|ii||ƒ|id7_q WdS(Ni(RRNtoRRVR Rœ(RR R¡((RRVvs cCs|ii|ƒdS(N(RRR‚R (RR ((RR‚{scCs§d}x}|iD]r}y|ii||ƒWq|djoti ƒ\}}}n|i i dt|ƒdti ƒƒqXqW|dj o|||‚ndS(NsFailed to abort object: %sRh(RRaRRNR¡RR|R RgRhR_R`R#Rzt object_hint(RR R¡R_R`Ra((RR|~s   ! ( R R t__doc__R(RžRŸRRƒR†RVR‚R|(((RRMYs         cCst|iƒ|iƒƒS(N(tcmptrm1RŸtrm2(R¥R¦((RR€scCsVdkl}|ii}t|dtƒ}|tj o||ƒ}nd||fS(s[Return a string describing the object. This function does not raise an exception. (soid_reprt_p_oids %s oid=%sN( Rtoid_reprR¡RR tklassRRtoid(R¡RªR©R¨((RR¢s   R1cBsVtZdZd„Zd„Zd„Zd„Zd„Zd„Zd„Z d„Z RS( s‹Adapt zodb 4-style data managers to zodb3 style Adapt transaction.interfaces.IDataManager to ZODB.interfaces.IPureDatamanager cCs ||_dS(N(t datamanagerRt _datamanager(RR«((RR(­scCsdS(N((RRF((RRV²scCs|ii|ƒdS(N(RR¬R|RF(RRF((RR|·scCsdS(N((RRF((RRºscCs|ii|ƒdS(N(RR¬R|RF(RRF((RR†¿scCs|ii|ƒdS(N(RR¬RVRF(RRF((RRƒÂscCs|ii|ƒdS(N(RR¬R.RF(RRF((RR‚ÅscCs |iiƒS(N(RR¬RŸ(R((RRŸÈs( R R R£R(RVR|RR†RƒR‚RŸ(((RR1¡s        R:cBs?tZdZeieiƒed„ƒZd„Z d„Z RS(sƒTransaction savepoint. Transaction savepoints coordinate savepoints for data managers participating in a transaction. cCs |idj S(N(RRFR(R((RRTÓscGsŠ||_g|_}xm|D]e}y |i}Wn9tj o-|pt d|ƒ‚nt |ƒ}n X|ƒ}|i |ƒqWdS(NsSavepoints unsupported( RFRR8t savepointst resourcesR«R<tAttributeErrorR;t TypeErrortNoRollbackSavepointR2(RRFR;R®R­R«R<((RR(Õs    cCsj|i}|djo ti‚n|i|ƒy"x|iD]}|iƒq=WWn|i ƒnXdS(N( RRFRR‡RˆRGR8R<RŠR>(RRFR<((RRŠås     ( R R R£R—R˜R‡t ISavepointtpropertyR‰R(RŠ(((RR:Ës  R4cBstZd„Zd„ZRS(NcCs||_||_dS(N(R«RRF(RR«RF((RR(ôs cCs|ii|iƒdS(N(RR«R|RF(R((RRŠøs(R R R(RŠ(((RR4òs R±cBstZd„Zd„ZRS(NcCs ||_dS(N(R«R(RR«((RR(ýscCstd|iƒ‚dS(NsSavepoints unsupported(R°RR«(R((RRŠs(R R R(RŠ(((RR±ûs (R£RRgR!twarningsR?Rit cStringIORetzopeR—RFR‡tobjectRRRRRMR€R¢R1R:R4R±(RR?RRR:R!R´R‡RiR¢R4RgRMRRR€R—R±R1Re((Rt?¡s*           ÿ’4  *'