V Qc@sdZddlZddlZddlZddlZdZdZdZdZdZ ddd YZ d e fd YZ d dd YZ dZ de fdYZde fdYZedZdZedkrendS(sCVS 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) iNi is#cvs.lcks #cvs.rfl.s #cvs.wfl.tErrorcBs#eZdZdZdZRS(cCs ||_dS(N(tmsg(tselfR((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyt__init__`scCs t|jS(N(treprR(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyt__repr__cscCs t|jS(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 jstLockcBsVeZdedZdZdZdZdZdZdZ dZ 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|jdS(Nt__del__(tunlock(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyRzscCsxy'|j|_tj|jddSWqtjk r}d|_|dtkrytj|j}Wntjk rqnX|j|qnt d|j |fqXqdS(Niisfailed to lock %s: %s( RRRtmkdirterrorRtEEXISTtstattsleepRR (RRtst((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyt setlockdir~s    cCs|j|jdS(N(t unlockfilet unlockdir(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyRs cCsP|jrLdG|jGHytj|jWntjk r?nXd|_ndS(Ntunlink(RRR'RR(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR%s  cCsP|jrLdG|jGHytj|jWntjk r?nXd|_ndS(Ntrmdir(RRR(RR(R((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR&s  cCst||j|jdS(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.pyRs( RR tDELAYRRR$RR%R&R"R(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR ns    cCs|dkrt|n|tj}ytj|}|d}Wntk rbd|}nXdtjtjdd!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    tReadLockcBseZedZRS(cCsztj|||d}z<|j|j|_t|jd}|jd}Wd|sk|jn|jXdS(Nitwi( R RR$RRtopentcloseR%R&(RR Rtoktfp((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyRs     (RR R+R(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyR5st WriteLockcBseZedZdZRS(cCs|tj||||jx0|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.pyRs    cCswtt}xdtj|jD]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|dWqtk rI}~PqXqWPt|j||qtS(Ni(tappendR;R R"Rtlist(t repositoriesRtlockstrtinstance((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pytMultipleWriteLocks  cCsddl}|jdr)|jd}nd}d}d}zDdGHt|}dGH|jdGHt|}dGH|jWddgGHd|_dgGH|r|jndgGH|r|jnd gGHd}d gGHd}d gGHXdS( NiiR sattempting write lock ...sgot it.sattempting read lock ...iiiii(tsystargvRR;RR5t exc_traceback(RGR trltwl((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pyttests8        t__main__(((t__doc__RR0R!R-R+R RRRRR R R"R5R;RFRLR(((s*/usr/lib64/python2.7/Demo/pdist/cvslock.pytGs&     ?   !