m TEc@sdZdkZdkZdkZdkZdklZlZ dk l Z dk l Z dklZlZdklZeidZdefd YZd fd YZd fd YZdS(s[Handy standard storage machinery $Id: BaseStorage.py 68677 2006-06-16 00:52:09Z tseaver $ N(spacksunpack(s TimeStamp(s POSException(sz64soid_repr(sUndoLogCompatiblesZODB.BaseStoraget BaseStoragecBsmtZdZeZdZeZedZdZ dZ dZ dZ dZ dZd Zd ed Zd Zd ZdZdZdZdZdZdZdZeddZdZdZdZedZdZdZ edZ!dZ"edZ#dZ$d Z%d!Z&d"Z'd#Z(d$d%Z)RS(&sAbstract base class that supports storage implementations. A subclass must define the following methods: load() store() close() cleanup() lastSerial() lastTransaction() It must override these hooks: _begin() _vote() _abort() _finish() _clear_temp() If it stores multiple revisions, it should implement loadSerial() loadBefore() iterator() If the subclass wants to implement undo, it should implement the multiple revision methods and: undo() undoInfo() undoLog() If the subclass wants to implement versions, it must implement: abortVersion() commitVersion() modifiedInVersion() versionEmpty() versions() Each storage will have two locks that are accessed via lock acquire and release methods bound to the instance. (Yuck.) _lock_acquire / _lock_release (reentrant) _commit_lock_acquire / _commit_lock_release The commit lock is acquired in tpc_begin() and released in tpc_abort() and tpc_finish(). It is never acquired with the other lock held. The other lock appears to protect _oid and _transaction and perhaps other things. It is always held when load() is called, so presumably the load() implementation should also acquire the lock. t cCs||_tid|iti}|i|_ |i |_ ti }|i|_ |i |_ti}tti|d |df}|_t||_t|dd}|djo t|_n ||_dS(Nscreate storage %sii<t_oid(tnametselft__name__tlogtdebugt threadingtRLocktltacquiret _lock_acquiretreleaset _lock_releasetLockt_commit_lock_acquiret_commit_lock_releasettimettt TimeStamptgmtimet_tstreprt_tidtgetattrtbasetNonetoidtz64R(RRRRR R((t//data/zmath/zope/lib/python/ZODB/BaseStorage.pyt__init__Us        +  cCs3||ij oti||n|igfS(N(t transactionRt _transactiont POSExceptiontStorageTransactionErrorR(RtsrcR ((Rt abortVersionoscCs3||ij oti||n|igfS(N(R RR!R"R#R(RR$tdestR ((Rt commitVersiontscCsdS(N((R((RtcloseyscCsdS(N((R((Rtcleanup|scCs|iS(sReturn a string that can be used to sort storage instances. The key must uniquely identify a storage and must be the same across multiple instantiations of the same storage. N(RR(R((RtsortKeyscCs|iS(N(RR(R((RtgetNamescCst|dS(Ni,(tlenR(R((RtgetSizesicCsdS(N((RRtversiontlengthtfilter((RthistoryscCsdS(Nt((RR((RtmodifiedInVersionscCs|iotin|izx|i}t|d}|djo|d t |d}n&t d|\}t d|d}||_|SWd|i XdS(Niiis>Q(Rt _is_read_onlyR"t ReadOnlyErrorR Rtlasttordtdtchrt _structunpackt last_as_longt _structpackR(RR6R8R;((Rtnew_oids     cCs=|iz!||ijo ||_nWd|iXdS(N(RR tpossible_new_max_oidRR(RR>((Rt set_max_oids  cCsdS(N((Rtdbtlimit((Rt registerDBscCs|iS(N(RR4(R((Rt isReadOnlyscCsdS(Ni((R((Rt supportsUndoscCsdS(Ni((R((RtsupportsVersionsscCsg|izK||ij odSnz!|i|id|_Wd|iXWd|iXdS(N( RR R R!t_abortt _clear_tempRRR(RR ((Rt tpc_aborts    cCsdS(s7Subclasses should redefine this to supply abort actionsN((R((RRFsc Csv|iotin|iz@|i|jodSn|i|i|i||_|i |i }|i }|i }|oti|d}nd}|||f|_|djo\ti}tti|d |df}|i|i|_}t||_nt||_||_||_|i|i|||Wd|iXdS(NiR2ii<( RR4R"R5R R!R RRRGtusert descriptiontdesct _extensiontexttcPickletdumpst_udettidRRtnowRRRt laterThanRRRtstatust_tstatust_begin( RR RQRTRRMRIRRRK((Rt tpc_begins:            $  cCsdS(sMSubclasses should redefine this to supply transaction start actions. N((RRQtuR8te((RRVscCsB|iz&||ij odSn|iWd|iXdS(N(RR R R!t_voteR(RR ((Rttpc_votes cCsdS(sLSubclasses should redefine this to supply transaction vote actions. N((R((RRZscCs|iz||ij odSnz^|dj o||in|i\}}}|i |i||||i |iSWdd|_d|_|i XWd|iXdS(N(RR R R!tfRRRPRXR8RYt_finishRGRR(RR R\RYR8RX((Rt tpc_finishs"      cCsdS(sMSubclasses should redefine this to supply transaction finish actions N((RRQRXR8RY((RR]scCs-|iotintiddS(Nsnon-undoable transaction(RR4R"R5t UndoError(Rttransaction_idttxn((Rtundo#s cCsfS(N((RtfirstR6R0((RtundoLog(scCsdS(Ni((RR.((Rt versionEmpty+scCsfS(N((Rtmax((Rtversions.scCs|iotindS(N(RR4R"R5(RRt referencesf((Rtpack1s cCsK|iz/|i|}|i||\}}|SWd|iXdS(N( RR R3Rtvtloadt pickledatatserialR(RRRlRmRj((Rt getSerial5s cCstiddS(Ns2Retrieval of historical revisions is not supported(R"t Unsupported(RRRm((Rt loadSerial>sc Csd}d}d}x|djo|i|d|d}|pdSnx8|D]0}|d|jo|d}PqS|d}qSWt ||joPn|d9}qW|djodSn|i ||}|||fS(s8Return most recent revision of oid before tid committed.iR2cCs |d S(NR.(R8(R8((Rt[sNRm( tnRt start_timetend_timeRR1RtLR8RQR,Rptdata( RRRQR8RuRrRtRvRs((Rt loadBeforeBs,   cCshS(sgetExtensionMethods This returns a dictionary whose keys are names of extra methods provided by this storage. Storage proxies (such as ZEO) should call this method to determine the extra methods that they need to proxy in addition to the standard storage methods. Dictionary values should be None; this will be a handy place for extra marshalling information, should we need it N((R((RtgetExtensionMethodsls ic Csd}d}h} | i}t|d}|i }x|D]}|i } |djot| }ntt| } | |jo:|od|| fGHnd}| i|}| } n!| }|pd| GHd}n|o |GHn|i|| |ix|D]} | i}|o#t|G| iGt| iGHn|o,|i|| i | i| i| i|q ||d}|i||| i| i|} | | |