ó V Qc@sôdZddlZddlZddlZddlZdZdZdZdZdZ ddd „ƒYZ d e fd „ƒYZ d dd „ƒYZ d„Z de fd„ƒYZde fd„ƒYZed„Zd„ZedkrðeƒndS(sûCVS locking algorithm. CVS locking strategy ==================== As reverse engineered from the CVS 1.3 sources (file lock.c): - Locking is done on a per repository basis (but a process can hold write locks for multiple directories); all lock files are placed in the repository and have names beginning with "#cvs.". - Before even attempting to lock, a file "#cvs.tfl." is created (and removed again), to test that we can write the repository. [The algorithm can still be fooled (1) if the repository's mode is changed while attempting to lock; (2) if this file exists and is writable but the directory is not.] - While creating the actual read/write lock files (which may exist for a long time), a "meta-lock" is held. The meta-lock is a directory named "#cvs.lock" in the repository. The meta-lock is also held while a write lock is held. - To set a read lock: - acquire the meta-lock - create the file "#cvs.rfl." - release the meta-lock - To set a write lock: - acquire the meta-lock - check that there are no files called "#cvs.rfl.*" - if there are, release the meta-lock, sleep, try again - create the file "#cvs.wfl." - To release a write lock: - remove the file "#cvs.wfl." - rmdir the meta-lock - To release a read lock: - remove the file "#cvs.rfl." Additional notes ---------------- - A process should read-lock at most one repository at a time. - A process may write-lock as many repositories as it wishes (to avoid deadlocks, I presume it should always lock them top-down in the directory hierarchy). - A process should make sure it removes all its lock files and directories when it crashes. - Limitation: one user id should not be committing files into the same repository at the same time. Turn this into Python code -------------------------- rl = ReadLock(repository, waittime) wl = WriteLock(repository, waittime) list = MultipleWriteLock([repository1, repository2, ...], waittime) iÿÿÿÿNi is#cvs.lcks #cvs.rfl.s #cvs.wfl.tErrorcBs#eZd„Zd„Zd„ZRS(cCs ||_dS(N(tmsg(tselfR((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyt__init__`scCs t|jƒS(N(treprR(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyt__repr__cscCs t|jƒS(N(tstrR(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyt__str__fs(t__name__t __module__RRR(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR^s  tLockedcBseZRS((RR (((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR jstLockcBsVeZded„Zd„Zd„Zd„Zd„Zd„Zd„Z d„Z RS( t.cCsx||_||_d|_d|_ttjƒƒ}|jt ƒ|_ |jt |ƒ|_ |jt |ƒ|_dS(N(t repositorytdelaytNonetlockdirtlockfileRtostgetpidtjointCVSLCKtcvslcktCVSRFLtcvsrfltCVSWFLtcvswfl(RR Rtpid((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyRps    cCsdGH|jƒdS(Nt__del__(tunlock(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyRzscCs¿x¸y'|j|_tj|jdƒdSWqtjk r·}d|_|dtkr›ytj|jƒ}Wntjk r‡qnX|j|ƒqnt d|j |fƒ‚qXqdS(Niÿisfailed to lock %s: %s( RRRtmkdirterrorRtEEXISTtstattsleepRR (RRtst((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyt setlockdir~s    cCs|jƒ|jƒdS(N(t unlockfilet unlockdir(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyRs cCsP|jrLdG|jGHytj|jƒWntjk r?nXd|_ndS(Ntunlink(RRR'RR(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR%”s  cCsP|jrLdG|jGHytj|jƒWntjk r?nXd|_ndS(Ntrmdir(RRR(RR(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR&s  cCst||j|jƒdS(N(R"R R(RR#((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR"¦scCstjj|j|ƒS(N(RtpathRR (Rtname((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR©s( RR tDELAYRRR$RR%R&R"R(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR ns    cCsŸ|dkrt|ƒ‚n|tj}ytj|ƒ}|d}Wntk rbd|}nXdtjtjƒƒdd!Gd|G|GHtj|ƒdS(Nisuid %ds[%s]i isWaiting for %s's lock in( R R!tST_UIDtpwdtgetpwuidtKeyErrorttimetctimeR"(R#R Rtuidtpwenttuser((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR"­s    tReadLockcBseZed„ZRS(cCsztj|||ƒd}z<|jƒ|j|_t|jdƒ}|jƒd}Wd|sk|jƒn|jƒXdS(Nitwi( R RR$RRtopentcloseR%R&(RR Rtoktfp((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR½s     (RR R+R(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR5»st WriteLockcBseZed„Zd„ZRS(cCs|tj|||ƒ|jƒx0|jƒ}|s6Pn|jƒ|j|ƒq |j|_t|jdƒ}|j ƒdS(NR6( R RR$t readers_existR&R"RRR7R8(RR RR2R:((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyRÎs    cCswttƒ}xdtj|jƒD]P}|| tkrytj|j|ƒƒ}Wntjk rjqnX|SqWdS(N( tlenRRtlistdirR R!RRR(RtnR*R#((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR<Ûs (RR R+RR<(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR;Ìs cCsixbg}xC|D]:}y|jt|dƒƒWqtk rI}~PqXqWPt|j||ƒqtS(Ni(tappendR;R R"Rtlist(t repositoriesRtlockstrtinstance((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pytMultipleWriteLockçs  cCsòddl}|jdr)|jd}nd}d}d}zDdGHt|ƒ}dGH|jƒdGHt|ƒ}dGH|jƒWddgGHd|_dgGH|r®|jƒndgGH|rÉ|jƒnd gGHd}d gGHd}d gGHXdS( NiÿÿÿÿiR sattempting write lock ...sgot it.sattempting read lock ...iiiii(tsystargvRR;RR5t exc_traceback(RGR trltwl((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyttestös8        t__main__(((t__doc__RR0R!R-R+R RRRRR R R"R5R;RFRLR(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pytGs&     ?   !