;ò
¢)?Bc           @   sp  d  Z  d k Z d k Z d k Z d k Z d k Z d k Z d k l Z l	 Z	 d Z
 d Z y e e f Wn e j
 o d Z d Z n Xe a d „  Z d e f d	 „  ƒ  YZ d
 e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d f  d „  ƒ  YZ d „  Z d „  Z d „  Z d „  Z d „  Z e d j o- d k Z d k Z e e e i  d ƒ ƒ n d S(   sI  Portable, NFS-safe file locking with timeouts.

This code implements an NFS-safe file-based locking algorithm influenced by
the GNU/Linux open(2) manpage, under the description of the O_EXCL option.
From RH6.1:

        [...] O_EXCL is broken on NFS file systems, programs which rely on it
        for performing locking tasks will contain a race condition.  The
        solution for performing atomic file locking using a lockfile is to
        create a unique file on the same fs (e.g., incorporating hostname and
        pid), use link(2) to make a link to the lockfile.  If link() returns
        0, the lock is successful.  Otherwise, use stat(2) on the unique file
        to check if its link count has increased to 2, in which case the lock
        is also successful.

The assumption made here is that there will be no `outside interference',
e.g. no agent external to this code will have access to link() to the affected
lock files.

LockFile objects support lock-breaking so that you can't wedge a process
forever.  This is especially helpful in a web environment, but may not be
appropriate for all applications.

Locks have a `lifetime', which is the maximum length of time the process
expects to retain the lock.  It is important to pick a good number here
because other processes will not break an existing lock until the expected
lifetime has expired.  Too long and other processes will hang; too short and
you'll end up trampling on existing process locks -- and possibly corrupting
data.  In a distributed (NFS) environment, you also need to make sure that
your clocks are properly synchronized.

Locks can also log their state to a log file.  When running under Mailman, the
log file is placed in a Mailman-specific location, otherwise, the log file is
called `LockFile.log' and placed in the temp directory (calculated from
tempfile.mktemp()).

N(   s   ST_NLINKs   ST_MTIMEi   i
   i   i    c          C   s¥   t  t j o y d k l }  |  d ƒ a  Wq t j
 o` d  k } t i i | i	 ƒ  ƒ d } t i i | d ƒ } d f  d „  ƒ  Y} | | ƒ a  q Xn t  Sd  S(   N(   s   StampedLoggers   locksi    s   LockFile.logs   SimpleUserFilec           B   s   t  Z d „  Z d „  Z RS(   Nc         C   s,   t  | d d ƒ |  _ d t i ƒ  |  _ d  S(   Ns   ai   s   (%d) (   s   opens   paths   selfs   _SimpleUserFile__fps   oss   getpids   _SimpleUserFile__prefix(   s   selfs   path(    (    s    /var/mailman/Mailman/LockFile.pys   __init__c   s    c         C   s3   d t  i  ƒ  } |  i i |  i | d | ƒ d  S(   Ns   %.3fs    (   s   times   nows   selfs   _SimpleUserFile__fps   writes   _SimpleUserFile__prefixs   msg(   s   selfs   msgs   now(    (    s    /var/mailman/Mailman/LockFile.pys   writef   s    (   s   __name__s
   __module__s   __init__s   write(    (    (    s    /var/mailman/Mailman/LockFile.pys   SimpleUserFileb   s   	(   s   _logfiles   Nones   Mailman.Logging.StampedLoggers   StampedLoggers   ImportErrors   tempfiles   oss   paths   splits   mktemps   dirs   joins   SimpleUserFile(   s   StampedLoggers   SimpleUserFiles   tempfiles   paths   dir(    (    s    /var/mailman/Mailman/LockFile.pys   _get_logfileV   s     	s	   LockErrorc           B   s   t  Z d  Z RS(   s-   Base class for all exceptions in this module.(   s   __name__s
   __module__s   __doc__(    (    (    s    /var/mailman/Mailman/LockFile.pys	   LockErroro   s   s   AlreadyLockedErrorc           B   s   t  Z d  Z RS(   s4   An attempt is made to lock an already locked object.(   s   __name__s
   __module__s   __doc__(    (    (    s    /var/mailman/Mailman/LockFile.pys   AlreadyLockedErrorr   s   s   NotLockedErrorc           B   s   t  Z d  Z RS(   s9   An attempt is made to unlock an object that isn't locked.(   s   __name__s
   __module__s   __doc__(    (    (    s    /var/mailman/Mailman/LockFile.pys   NotLockedErroru   s   s   TimeOutErrorc           B   s   t  Z d  Z RS(   s7   The timeout interval elapsed before the lock succeeded.(   s   __name__s
   __module__s   __doc__(    (    (    s    /var/mailman/Mailman/LockFile.pys   TimeOutErrorx   s   s   LockFilec           B   sé   t  Z d  Z d Z e e d „ Z d „  Z d „  Z d „  Z	 e
 e d „ Z d d „ Z e d „ Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d d „ Z d „  Z d „  Z e
 d „ Z d „  Z d „  Z d „  Z d „  Z RS(   s'  A portable way to lock resources by way of the file system.

    This class supports the following methods:

    __init__(lockfile[, lifetime[, withlogging]]):
        Create the resource lock using lockfile as the global lock file.  Each
        process laying claim to this resource lock will create their own
        temporary lock files based on the path specified by lockfile.
        Optional lifetime is the number of seconds the process expects to hold
        the lock.  Optional withlogging, when true, turns on lockfile logging
        (see the module docstring for details).

    set_lifetime(lifetime):
        Set a new lock lifetime.  This takes affect the next time the file is
        locked, but does not refresh a locked file.

    get_lifetime():
        Return the lock's lifetime.

    refresh([newlifetime[, unconditionally]]):
        Refreshes the lifetime of a locked file.  Use this if you realize that
        you need to keep a resource locked longer than you thought.  With
        optional newlifetime, set the lock's lifetime.   Raises NotLockedError
        if the lock is not set, unless optional unconditionally flag is set to
        true.

    lock([timeout]):
        Acquire the lock.  This blocks until the lock is acquired unless
        optional timeout is greater than 0, in which case, a TimeOutError is
        raised when timeout number of seconds (or possibly more) expires
        without lock acquisition.  Raises AlreadyLockedError if the lock is
        already set.

    unlock([unconditionally]):
        Relinquishes the lock.  Raises a NotLockedError if the lock is not
        set, unless optional unconditionally is true.

    locked():
        Return true if the lock is set, otherwise false.  To avoid race
        conditions, this refreshes the lock (on set locks).

    i    c         C   s‡   | |  _ | |  _ t i |  _ t i d 7_ d | t i	 ƒ  t
 i ƒ  |  i f |  _ | |  _ t
 i i |  i ƒ d |  _ t |  _ d S(   s¬  Create the resource lock using lockfile as the global lock file.

        Each process laying claim to this resource lock will create their own
        temporary lock files based on the path specified by lockfile.
        Optional lifetime is the number of seconds the process expects to hold
        the lock.  Optional withlogging, when true, turns on lockfile logging
        (see the module docstring for details).

        i   s   %s.%s.%d.%dN(   s   lockfiles   selfs   _LockFile__lockfiles   lifetimes   _LockFile__lifetimes   LockFiles   COUNTERs   _LockFile__counters   sockets   gethostnames   oss   getpids   _LockFile__tmpfnames   withloggings   _LockFile__withloggings   paths   splits   _LockFile__logprefixs   Trues   _LockFile__owned(   s   selfs   lockfiles   lifetimes   withlogging(    (    s    /var/mailman/Mailman/LockFile.pys   __init__¯   s     		(	c         C   sA   d t  |  ƒ |  i |  i ƒ  o d p d |  i t i ƒ  f Sd  S(   Ns$   <LockFile %s: %s [%s: %ssec] pid=%s>s   lockeds   unlocked(   s   ids   selfs   _LockFile__lockfiles   lockeds   _LockFile__lifetimes   oss   getpid(   s   self(    (    s    /var/mailman/Mailman/LockFile.pys   __repr__Ç   s    c         C   s   | |  _ d S(   sŠ   Set a new lock lifetime.

        This takes affect the next time the file is locked, but does not
        refresh a locked file.
        N(   s   lifetimes   selfs   _LockFile__lifetime(   s   selfs   lifetime(    (    s    /var/mailman/Mailman/LockFile.pys   set_lifetimeÍ   s     c         C   s   |  i Sd S(   s   Return the lock's lifetime.N(   s   selfs   _LockFile__lifetime(   s   self(    (    s    /var/mailman/Mailman/LockFile.pys   get_lifetimeÕ   s     c         C   s[   | t j	 o |  i | ƒ n |  i ƒ  o | o# t d t |  ƒ |  i ƒ  f ‚ n d S(   sC  Refreshes the lifetime of a locked file.

        Use this if you realize that you need to keep a resource locked longer
        than you thought.  With optional newlifetime, set the lock's lifetime.
        Raises NotLockedError if the lock is not set, unless optional
        unconditionally flag is set to true.
        s   %s: %sN(	   s   newlifetimes   Nones   selfs   set_lifetimes   lockeds   unconditionallys   NotLockedErrors   reprs   _LockFile__read(   s   selfs   newlifetimes   unconditionally(    (    s    /var/mailman/Mailman/LockFile.pys   refreshÙ   s
     c         C   s  | o t i ƒ  | } n |  i ƒ  |  i ƒ  |  i d ƒ d } x¿t o·| d 7} y2 t	 i
 |  i |  i ƒ |  i d ƒ |  i ƒ  PWnÎ t j
 oÂ } | i t i j o qY| i t i j o. |  i d | d t ƒt	 i |  i ƒ ‚  qY|  i ƒ  d j o! |  i d |  i ƒ  d t ƒqY|  i ƒ  |  i j o |  i d	 ƒ t ‚ qYn X| o | t i ƒ  j  o' t	 i |  i ƒ |  i d
 ƒ t ‚ n t i ƒ  |  i ƒ  t j o! |  i ƒ  |  i d d t ƒn | d o |  i d ƒ n |  i ƒ  qE Wd S(   s?  Acquire the lock.

        This blocks until the lock is acquired unless optional timeout is
        greater than 0, in which case, a TimeOutError is raised when timeout
        number of seconds (or possibly more) expires without lock acquisition.
        Raises AlreadyLockedError if the lock is already set.
        s   laying claimiÿÿÿÿi   s   got the locks   unexpected link error: %ss	   importanti   s   unexpected linkcount: %ds   already lockeds	   timed outs   lifetime has expired, breakingid   s   waiting for claimN(   s   timeouts   times   timeout_times   selfs   _LockFile__writes   _LockFile__touchs   _LockFile__writelogs	   loopcounts   Trues   oss   links   _LockFile__tmpfnames   _LockFile__lockfiles   OSErrors   es   errnos   ENOENTs   EEXISTs   unlinks   _LockFile__linkcounts   _LockFile__reads   AlreadyLockedErrors   TimeOutErrors   _LockFile__releasetimes
   CLOCK_SLOPs   _LockFile__breaks   _LockFile__sleep(   s   selfs   timeouts   es	   loopcounts   timeout_time(    (    s    /var/mailman/Mailman/LockFile.pys   lockç   sR     

 





	c         C   sÎ   |  i ƒ  } | o | o
 t ‚ n | oJ y t i |  i ƒ Wqw t j
 o# } | i
 t
 i j o ‚  qs qw Xn y t i |  i ƒ Wn/ t j
 o# } | i
 t
 i j o ‚  q½ n X|  i d ƒ d S(   sõ   Unlock the lock.

        If we don't already own the lock (either because of unbalanced unlock
        calls, or because the lock was stolen out from under us), raise a
        NotLockedError, unless optional `unconditionally' is true.
        s   unlockedN(   s   selfs   lockeds   islockeds   unconditionallys   NotLockedErrors   oss   unlinks   _LockFile__lockfiles   OSErrors   es   errnos   ENOENTs   _LockFile__tmpfnames   _LockFile__writelog(   s   selfs   unconditionallys   es   islocked(    (    s    /var/mailman/Mailman/LockFile.pys   unlock:  s      
  c         C   sv   y |  i ƒ  Wn3 t j
 o' } | i t i j o t SqD ‚  n X|  i ƒ  d j o t Sn |  i ƒ  |  i	 j Sd S(   sÈ   Return true if we own the lock, false if we do not.

        Checking the status of the lock resets the lock's lifetime, which
        helps avoid race conditions during the lock status test.
        i   N(
   s   selfs   _LockFile__touchs   OSErrors   es   errnos   EPERMs   Falses   _LockFile__linkcounts   _LockFile__reads   _LockFile__tmpfname(   s   selfs   e(    (    s    /var/mailman/Mailman/LockFile.pys   lockedQ  s     c         C   s   |  i d t ƒ d  S(   Ns   unconditionally(   s   selfs   unlocks   True(   s   self(    (    s    /var/mailman/Mailman/LockFile.pys   finalizef  s    c         C   s   |  i o |  i ƒ  n d  S(   N(   s   selfs   _LockFile__owneds   finalize(   s   self(    (    s    /var/mailman/Mailman/LockFile.pys   __del__i  s    
c         C   s|   |  i ƒ  |  i ƒ  } d |  i t i ƒ  | f |  _ t	 i
 |  i |  i ƒ |  i ƒ  t |  _ t	 i | ƒ |  i d ƒ d  S(   Ns   %s.%s.%ds   transferred the lock(   s   selfs   _LockFile__touchs   _LockFile__reads   winners   _LockFile__lockfiles   sockets   gethostnames   pids   _LockFile__tmpfnames   oss   links   _LockFile__writes   Falses   _LockFile__owneds   unlinks   _LockFile__writelog(   s   selfs   pids   winner(    (    s    /var/mailman/Mailman/LockFile.pys   _transfer_tot  s    

	  c         C   su   d |  i t i ƒ  t i ƒ  f |  _ } x8 |  i ƒ  d j p |  i	 ƒ  | j o t
 i d ƒ q, W|  i d ƒ d  S(   Ns   %s.%s.%di   f0.25s   took possession of the lock(   s   selfs   _LockFile__lockfiles   sockets   gethostnames   oss   getpids   _LockFile__tmpfnames   tmpfnames   _LockFile__linkcounts   _LockFile__reads   times   sleeps   _LockFile__writelog(   s   selfs   tmpfname(    (    s    /var/mailman/Mailman/LockFile.pys   _take_possessionŒ  s
    ) &c         C   s   t  |  _ d  S(   N(   s   Falses   selfs   _LockFile__owned(   s   self(    (    s    /var/mailman/Mailman/LockFile.pys   _disown•  s    c         C   sL   |  i p | o7 t ƒ  } | i d |  i | f ƒ t i	 d | ƒ n d  S(   Ns   %s %s
s   file(
   s   selfs   _LockFile__withloggings	   importants   _get_logfiles   logfs   writes   _LockFile__logprefixs   msgs	   tracebacks   print_stack(   s   selfs   msgs	   importants   logf(    (    s    /var/mailman/Mailman/LockFile.pys
   __writelogœ  s    	c         C   sT   t  i d ƒ } z0 t |  i d ƒ } | i |  i ƒ | i ƒ  Wd  t  i | ƒ Xd  S(   Ni   s   w(	   s   oss   umasks   oldmasks   opens   selfs   _LockFile__tmpfnames   fps   writes   close(   s   selfs   fps   oldmask(    (    s    /var/mailman/Mailman/LockFile.pys   __write¢  s     c         C   sg   y- t  |  i ƒ } | i ƒ  } | i ƒ  | SWn3 t j
 o' } | i	 t	 i
 j o ‚  n t Sn Xd  S(   N(   s   opens   selfs   _LockFile__lockfiles   fps   reads   filenames   closes   EnvironmentErrors   es   errnos   ENOENTs   None(   s   selfs   fps   es   filename(    (    s    /var/mailman/Mailman/LockFile.pys   __read¬  s    
 c         C   sm   t  i  ƒ  |  i } y$ t i | p |  i | | f ƒ Wn/ t j
 o# } | i
 t
 i j o ‚  qi n Xd  S(   N(   s   times   selfs   _LockFile__lifetimes   ts   oss   utimes   filenames   _LockFile__tmpfnames   OSErrors   es   errnos   ENOENT(   s   selfs   filenames   es   t(    (    s    /var/mailman/Mailman/LockFile.pys   __touch¶  s    $ c         C   sR   y t  i |  i ƒ t SWn3 t j
 o' } | i t i j o ‚  n d Sn Xd  S(   Niÿÿÿÿ(	   s   oss   stats   selfs   _LockFile__lockfiles   ST_MTIMEs   OSErrors   es   errnos   ENOENT(   s   selfs   e(    (    s    /var/mailman/Mailman/LockFile.pys   __releasetime¾  s     c         C   sR   y t  i |  i ƒ t SWn3 t j
 o' } | i t i j o ‚  n d Sn Xd  S(   Niÿÿÿÿ(	   s   oss   stats   selfs   _LockFile__lockfiles   ST_NLINKs   OSErrors   es   errnos   ENOENT(   s   selfs   e(    (    s    /var/mailman/Mailman/LockFile.pys   __linkcountÅ  s     c         C   sê   y |  i |  i ƒ Wn/ t j
 o# } | i t i j o ‚  qF n X|  i ƒ  } y t	 i
 |  i ƒ Wn/ t j
 o# } | i t i j o ‚  q˜ n Xy | o t	 i
 | ƒ n Wn/ t j
 o# } | i t i j o ‚  qæ n Xd  S(   N(   s   selfs   _LockFile__touchs   _LockFile__lockfiles   OSErrors   es   errnos   EPERMs   _LockFile__reads   winners   oss   unlinks   ENOENT(   s   selfs   es   winner(    (    s    /var/mailman/Mailman/LockFile.pys   __breakÌ  s"       c         C   s%   t  i  ƒ  d d } t i | ƒ d  S(   Nf2.0f0.01(   s   randoms   intervals   times   sleep(   s   selfs   interval(    (    s    /var/mailman/Mailman/LockFile.pys   __sleepî  s    (   s   __name__s
   __module__s   __doc__s   COUNTERs   DEFAULT_LOCK_LIFETIMEs   Falses   __init__s   __repr__s   set_lifetimes   get_lifetimes   Nones   refreshs   locks   unlocks   lockeds   finalizes   __del__s   _transfer_tos   _take_possessions   _disowns   _LockFile__writelogs   _LockFile__writes   _LockFile__reads   _LockFile__touchs   _LockFile__releasetimes   _LockFile__linkcounts   _LockFile__breaks   _LockFile__sleep(    (    (    s    /var/mailman/Mailman/LockFile.pys   LockFile}   s.   * 			S								
	
			"c          C   sk  d t  i ƒ  } t d d t d d ƒ} d t i ƒ  } d t i ƒ  }  | Gd G| GHt	 } d	 } d	 } d	 } zƒ y2 t i ƒ  } | Gd
 GH| i ƒ  | Gd GHt } Wn t j
 o | Gd GHn0 Xt i ƒ  } | Gd G| | Gd GHt i | ƒ Wd  | oR y/ | i ƒ  t i ƒ  } | Gd G| | Gd GHWqLt j
 o | Gd GHqLXn X| Gd G|  GHt i |  ƒ d  S(   Ns   [%d]s   /tmp/LockTests   withloggings   lifetimeix   i   i   s   workinterval:i    s   acquiring...s   acquired...s	   timed outs   acquisition time:s   secondss   lock hold time:s   lock was brokens   webhit sleep:(   s   oss   getpids   prefixs   LockFiles   Trues   lockfiles   randoms   workintervals   hitwaits   Falses   islockeds   t0s   t1s   t2s   times   locks   TimeOutErrors   sleeps   unlocks   NotLockedError(   s   hitwaits   workintervals   islockeds   t0s   t1s   t2s   prefixs   lockfile(    (    s    /var/mailman/Mailman/LockFile.pys   _dochildõ  s>    	
	
 
c          C   sœ   y) t  d ƒ }  |  i d ƒ } |  i ƒ  Wn_ t j
 oS } | i t i j o ‚  n d  k	 } | i
 t i ƒ  t i ƒ  ƒ i ƒ  } n Xt i | ƒ d  S(   Ns   /dev/randomi(   (   s   opens   fps   reads   ds   closes   EnvironmentErrors   es   errnos   ENOENTs   shas   news   oss   getpids   times	   hexdigests   randoms   seed(   s   fps   es   ds   sha(    (    s    /var/mailman/Mailman/LockFile.pys   _seed  s    	,c          C   s¤   t  i d d ƒ } x‹ t | ƒ D]} } d | d | f GHt i ƒ  } | o t i | d ƒ \ } }  q t
 ƒ  y t ƒ  Wn t j
 o n Xt i d ƒ q Wd  S(   Ni   id   s   Loop %d of %di    (   s   randoms   randints	   loopcounts   ranges   is   oss   forks   pids   waitpids   statuss   _seeds   _dochilds   KeyboardInterrupts   _exit(   s   statuss	   loopcounts   is   pid(    (    s    /var/mailman/Mailman/LockFile.pys   _onetest*  s     c         C   sG   |  o d  Sn t i d t i ƒ \ } } | d j o |  | =n d  S(   Niÿÿÿÿi    (   s   kidss   oss   waitpids   WNOHANGs   pids   status(   s   kidss   statuss   pid(    (    s    /var/mailman/Mailman/LockFile.pys   _reap<  s
    c         C   s   h  } xj t |  ƒ D]\ } t i ƒ  } | o | | | <q t ƒ  y t ƒ  Wn t	 j
 o n Xt i
 d ƒ q Wx | o t | ƒ qv Wd  S(   Ni    (   s   kidss   ranges   numtestss   is   oss   forks   pids   _seeds   _onetests   KeyboardInterrupts   _exits   _reap(   s   numtestss   kidss   is   pid(    (    s    /var/mailman/Mailman/LockFile.pys   _testD  s      s   __main__(!   s   __doc__s   oss   sockets   times   errnos   randoms	   tracebacks   stats   ST_NLINKs   ST_MTIMEs   DEFAULT_LOCK_LIFETIMEs
   CLOCK_SLOPs   Trues   Falses	   NameErrors   Nones   _logfiles   _get_logfiles	   Exceptions	   LockErrors   AlreadyLockedErrors   NotLockedErrors   TimeOutErrors   LockFiles   _dochilds   _seeds   _onetests   _reaps   _tests   __name__s   syss   ints   argv(   s   ST_MTIMEs   _tests   randoms   AlreadyLockedErrors   _dochilds   LockFiles   _get_logfiles   TimeOutErrors   ST_NLINKs   errnos   DEFAULT_LOCK_LIFETIMEs   Trues   _onetests   NotLockedErrors   syss
   CLOCK_SLOPs	   LockErrors   _seeds   Falses   sockets	   tracebacks   times   oss   _reap(    (    s    /var/mailman/Mailman/LockFile.pys   ?5   s>   							ÿ y	(						