o
    +ke1@                     @   s  d dl Z d dlZd dlZd dlZd dlZddlmZ ddlmZm	Z	 ddl
mZ d\ZZZd\ZZeeZ
G dd	 d	ZG d
d deZG dd de	ZG dd deZG dd deZG dd deZG dd deZG dd dZG dd dZG dd dZdS )    N   )platform)ErrorErrorWithTraceback)create_logger)addremoveZremove2)shared	exclusivec                   @   sB   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dS )TimeoutTimerz
    A timer for timeout checks (can also deal with "never timeout").
    It can also compute and optionally execute a reasonable sleep time (e.g. to avoid
    polling too often or to support thread/process rescheduling).
    Nc                 C   sX   |dur|dk rt d|| _|du r!|du rd}ntd|d }|| _d| _d| _dS )ag  
        Initialize a timer.

        :param timeout: time out interval [s] or None (never timeout, wait forever) [default]
        :param sleep: sleep interval [s] (>= 0: do sleep call, <0: don't call sleep)
                      or None (autocompute: use 10% of timeout [but not more than 60s],
                      or 1s for "never timeout" mode)
        Nr   ztimeout must be >= 0g      ?g      N@g      $@)
ValueErrortimeout_intervalminsleep_interval
start_timeend_time)selftimeoutsleep r   0usr/lib/python3.10/site-packages/borg/locking.py__init__   s   	
zTimeoutTimer.__init__c                 C   s   d | jj| j| j| j| jS )Nz1<{}: start={!r} end={!r} timeout={!r} sleep={!r}>)format	__class____name__r   r   r   r   r   r   r   r   __repr__,   s   zTimeoutTimer.__repr__c                 C   s&   t   | _| jd ur| j| j | _| S N)timer   r   r   r   r   r   r   start1   s   

zTimeoutTimer.startc                 C   s   | j dkrt| j  d S d S )Nr   )r   r   r   r   r   r   r   r   7   s   
zTimeoutTimer.sleepc                 C   s   | j d uot | j kS r   )r   r   r   r   r   r   	timed_out;      zTimeoutTimer.timed_outc                 C   s   |   rdS |   dS )NTF)r    r   r   r   r   r   timed_out_or_sleep>   s   zTimeoutTimer.timed_out_or_sleepNN)
r   
__module____qualname____doc__r   r   r   r   r    r"   r   r   r   r   r      s    
r   c                   @      e Zd ZdZdS )	LockErrorFailed to acquire the lock {}.Nr   r$   r%   r&   r   r   r   r   r(   F       r(   c                   @   r'   )
LockErrorTr)   Nr*   r   r   r   r   r,   J   r+   r,   c                   @   r'   )LockTimeoutz/Failed to create/acquire the lock {} (timeout).Nr*   r   r   r   r   r-   N   r+   r-   c                   @   r'   )
LockFailedz*Failed to create/acquire the lock {} ({}).Nr*   r   r   r   r   r.   R   r+   r.   c                   @   r'   )	NotLockedz/Failed to release the lock {} (was not locked).Nr*   r   r   r   r   r/   V   r+   r/   c                   @   r'   )	NotMyLockz=Failed to release the lock {} (was/is locked, but not by me).Nr*   r   r   r   r   r0   Z   r+   r0   c                   @   sl   e Zd ZdZdddZdd Zdd Zd	d
 ZdddZdd Z	dd Z
dd Zdd Zdd Zdd ZdS )ExclusiveLocka/  An exclusive Lock based on mkdir fs operation being atomic.

    If possible, try to use the contextmanager here like::

        with ExclusiveLock(...) as lock:
            ...

    This makes sure the lock is released again if the block is left, no
    matter how (e.g. if an exception occurred).
    Nc                 C   sP   || _ || _tj|| _|pt | _tj| jd| j | _	d| _
d| _d S )N%s.%d-%xTF)r   r   ospathabspathr   get_process_ididjoinunique_namekill_stale_locksstale_warning_printed)r   r4   r   r   r7   r   r   r   r   i   s   
zExclusiveLock.__init__c                 C      |   S r   acquirer   r   r   r   	__enter__r      zExclusiveLock.__enter__c                 G      |    d S r   releaser   excr   r   r   __exit__u      zExclusiveLock.__exit__c                 C      d| j j d| jdS N<z: >)r   r   r9   r   r   r   r   r   x   r!   zExclusiveLock.__repr__c           
      C   s  |d u r| j }|d u r| j}tj| j\}}tj| j}d }zz'td|d |}tj	||}t
|d W d    n1 sBw   Y  W n ty] } z	t| jt|d d }~ww t|| }		 z	t|| j W n= ty   |  r|  Y W |d urzt| W n   Y zt| W S    Y S S |   |	 rt| jd Y n#w d }| W |d urzt| W n   Y zt| W S    Y S S qf|d urzt| W n   Y zt| W w    Y w w )Nz.tmp.wb)r   r   r3   r4   splitbasenamer9   tempfilemkdtempr8   openOSErrorr.   strr   r   replaceby_meunlinkrmdirkill_stale_lockr"   r-   )
r   r   r   parent_path	base_nameZunique_base_nameZ	temp_pathZtemp_unique_nameerrtimerr   r   r   r>   {   s~   zExclusiveLock.acquirec              
   C   s   |   s	t| j|  st| jt| j z	t| j W d S  t	yA } z|j
t
jt
jt
jfvr6|W Y d }~d S d }~ww r   )	is_lockedr/   r4   rV   r0   r3   rW   r9   rX   rS   errno	ENOTEMPTYEEXISTENOENT)r   r\   r   r   r   rC      s   

zExclusiveLock.releasec                 C   s   t j| jS r   )r3   r4   existsr   r   r   r   r^         zExclusiveLock.is_lockedc                 C   s   t j| jS r   )r3   r4   rc   r9   r   r   r   r   rV      rd   zExclusiveLock.by_mec           
      C   s  zt | j}W n	 ty   Y nw |D ]}z|dd\}}|dd\}}t|}t|d}W n tyD   td|| j Y  dS w t	
|||rO dS | jsa| js^td| d| _ dS zt t j| j| td	| W q ty }	 z| jstd
|t|	 d| _W Y d }	~	 dS d }	~	ww z	t | j W dS  ty }	 z!|	jtjtjtjfv rW Y d }	~	dS tdt|	 W Y d }	~	dS d }	~	ww )N-r   rL      z9Found malformed lock %s in %s. Please check/fix manually.FzLFound stale lock %s, but not deleting because self.kill_stale_locks = False.TzKilled stale lock %s.z0Found stale lock %s, but cannot delete due to %szFailed to remove lock dir: %s)r3   listdirr4   FileNotFoundErrorrsplitintr   loggererrorr   process_aliver:   r;   warningrW   r8   rS   rT   rX   r_   r`   ra   rb   )
r   namesnameZhost_pidZ
thread_strhostZpid_strpidthreadr\   r   r   r   rY      sT   	zExclusiveLock.kill_stale_lockc                 C   sD   |   r t| jD ]}ttj| j| q
t| j d S d S r   )r^   r3   rg   r4   rW   r8   rX   )r   rp   r   r   r   
break_lock   s
   zExclusiveLock.break_lockc                 C   sz   | j |ksJ tj| jd| }|  r4|  r4t|d W d   n1 s)w   Y  t| j ||| _ | _dS )0migrate the lock ownership from old_id to new_idr2   rM   N)	r7   r3   r4   r8   r^   rV   rR   rW   r9   )r   old_idnew_idZnew_unique_namer   r   r   migrate_lock   s   zExclusiveLock.migrate_lockNNNr#   )r   r$   r%   r&   r   r?   rF   r   r>   rC   r^   rV   rY   rt   rx   r   r   r   r   r1   ^   s    

	
*1r1   c                   @   sR   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd ZdS )
LockRosterz
    A Lock Roster to track shared/exclusive lockers.

    Note: you usually should call the methods with an exclusive lock held,
    to avoid conflicting access by multiple threads/processes/machines.
    Nc                 C   s   || _ |pt | _d| _d S )NT)r4   r   r6   r7   r:   )r   r4   r7   r   r   r   r     s   
zLockRoster.__init__c           	   	   C   s   zdt | j}t|}W d    n1 sw   Y  | jr_ttfD ]?}z|| }W n	 ty3   Y q"w t }|D ]\}}}t	
|||rN||||f q9td|||| q9t|||< q"W |S W |S  ttfyr   i }Y |S w )Nz:Removed stale %s roster lock for host %s pid %d thread %d.)rR   r4   jsonloadr:   SHARED	EXCLUSIVEKeyErrorsetr   rm   r   rk   rn   listrh   r   )	r   fdatakeyentrieselementsrq   rr   rs   r   r   r   r|   	  s6   zLockRoster.loadc                 C   s>   t | jd}t|| W d    d S 1 sw   Y  d S )Nw)rR   r4   r{   dump)r   r   r   r   r   r   save"  s   "zLockRoster.savec                 C   s(   z	t | j W d S  ty   Y d S w r   )r3   rW   r4   rh   r   r   r   r   r   &  s
   zLockRoster.removec                 C   s   |   }dd ||g D S )Nc                 S      h | ]}t |qS r   tuple.0er   r   r   	<setcomp>.      z!LockRoster.get.<locals>.<setcomp>)r|   get)r   r   rosterr   r   r   r   ,  s   zLockRoster.getc                    s   t  fdd|D S )Nc                 3   s    | ]	}  | V  qd S r   )r   )r   r   r   r   r   	<genexpr>1  s    z#LockRoster.empty.<locals>.<genexpr>)all)r   keysr   r   r   empty0  s   zLockRoster.emptyc                 C   s   |   }zdd || D }W n ty   t }Y nw |tkr'|| j n|tkr2|| j n|tkr=|	| j nt
d| tdd |D ||< | | d S )Nc                 S   r   r   r   r   r   r   r   r   6  r   z$LockRoster.modify.<locals>.<setcomp>zUnknown LockRoster op %rc                 s   s    | ]}t |V  qd S r   )r   r   r   r   r   r   D  s    z$LockRoster.modify.<locals>.<genexpr>)r|   r   r   ADDr   r7   REMOVEdiscardREMOVE2r   r   r   r   )r   r   opr   r   r   r   r   modify3  s   
zLockRoster.modifyc                 C   sz   | j |ksJ | jd}| _z*z| |t W n ty#   || _ Y nw || _ | |t W || _dS W || _dS || _w )ru   FN)r7   r:   r   r   r   r   )r   r   rv   rw   Zkillingr   r   r   rx   G  s   

zLockRoster.migrate_lockr   )r   r$   r%   r&   r   r|   r   r   r   r   r   rx   r   r   r   r   rz      s    
rz   c                   @   st   e Zd ZdZdddZdd Zdd	 Zd
d ZdddZdd Z	dd Z
dd Zdd Zdd Zdd Zdd ZdS )Locka  
    A Lock for a resource that can be accessed in a shared or exclusive way.
    Typically, write access to a resource needs an exclusive lock (1 writer,
    no one is allowed reading) and read access to a resource needs a shared
    lock (multiple readers are allowed).

    If possible, try to use the contextmanager here like::

        with Lock(...) as lock:
            ...

    This makes sure the lock is released again if the block is left, no
    matter how (e.g. if an exception occurred).
    FNc                 C   sP   || _ || _|| _|| _|pt | _t|d |d| _t	|d ||d| _
d S )Nz.roster)r7   z
.exclusive)r7   r   )r4   is_exclusiver   r   r   r6   r7   rz   _rosterr1   _lock)r   r4   r
   r   r   r7   r   r   r   r   j  s   zLock.__init__c                 C   r<   r   r=   r   r   r   r   r?   w  r@   zLock.__enter__c                 G   rA   r   rB   rD   r   r   r   rF   z  rG   zLock.__exit__c                 C   rH   rI   )r   r   r7   r   r   r   r   r   }  r!   zLock.__repr__c                 C   s   |d u r| j }|p| jpd}|r| || | jtt n%| j |d ur-| j|t | jt	t W d    n1 s>w   Y  || _ | S )Ng?)
r   r   _wait_for_readers_finishingr   r   r~   r   r   r   r}   )r   r
   r   r   r   r   r   r>     s   zLock.acquirec                 C   s   t | j| }	 | j  z%|d ur| j|t t| j	t
dkr'W d S |d ur2| j|t W n	   | j   | j  | rKt| jq	)NTr   )r   r   r   r   r>   r   r   r   lenr   r}   r   rC   r"   r-   r4   )r   r   r   r]   r   r   r   r     s$   



z Lock._wait_for_readers_finishingc                 C   s   | j r| jtt | jttr| j  | j	  d S | j$ | jtt | jttr<| j  W d    d S W d    d S 1 sGw   Y  d S r   )
r   r   r   r~   r   r   r}   r   r   rC   r   r   r   r   rC     s   
"zLock.releasec                 C   s   | j s| jdtd d S d S )NTr
   r   )r   r>   r}   r   r   r   r   upgrade  s   zLock.upgradec                 C   s   | j r| jdtd d S d S )NFr   )r   r>   r~   r   r   r   r   	downgrade  s   zLock.downgradec                 C   s   | j o| j o| j S r   )r   r   r^   rV   r   r   r   r   got_exclusive_lock  s   zLock.got_exclusive_lockc                 C   s   | j   | j  d S r   )r   r   r   rt   r   r   r   r   rt     s   
zLock.break_lockc                 C   s   | j |ksJ || _ | jr| j|| | jt|| d S | j | j|| | jt|| W d    d S 1 s<w   Y  d S r   )r7   r   r   rx   r   r~   r}   )r   rv   rw   r   r   r   rx     s   "zLock.migrate_lock)FNNNry   )r   r$   r%   r&   r   r?   rF   r   r>   r   rC   r   r   r   rt   rx   r   r   r   r   r   [  s    

r   )r_   r{   r3   rP   r    r   helpersr   r   rk   r   r   r   r   r}   r~   r   r   r(   r,   r-   r.   r/   r0   r1   rz   r   r   r   r   r   <module>   s,    
5  ^