
    g0                     \    d dl Z d dlZd dlZd dlZd dlmZ  G d de      Z G d de      Zy)    N)loggerc                   *    e Zd ZdZddZd Zd Zd Zy)	TimedLocka  
    Enforce request rate limit if applicable. This uses the lock so there
    is synchronized access to the API. When N threads enter this method, the
    first will pass trough, since there there was no last request recorded.
    The last request time will be set. Then, the second thread will unlock,
    and see that the last request was X seconds ago. It will sleep
    (request_limit - X) seconds, and then continue. Then the third one will
    unblock, and so on. After all threads finish, the total time will at
    least be (N * request_limit) seconds. If some request takes longer than
    request_limit seconds, the next unblocked thread will wait less.
    c                     t        j                         | _        d| _        || _        t        j                         | _        y)z!
        Set up the lock
        r   N)	threadingLocklock	last_usedminimum_deltaqueueQueue)selfr   s     /opt/Tautulli/plexpy/lock.py__init__zTimedLock.__init__'   s.     NN$	*[[]
    c                 X   | j                   j                          t        j                         | j                  z
  }| j                  |z
  }|dk\  r+t        j                  d|       t        j                  |       | j                  j                         s}	 | j                  j                  d      }t        j                  d|       t        j                  |       | j                  j                          | j                  j                         s|yy# t        j                  $ r Y w xY w)z3
        Called when with lock: is invoked
        r   zSleeping %s (interval)FzSleeping %s (queued)N)r	   acquiretimer
   r   r   debugsleepr   emptygetEmpty	task_done)r   deltasleep_amountsecondss       r   	__enter__zTimedLock.__enter__0   s     					dnn,))E11LL1<@JJ|$**""$**../3W=

7# JJ  " **""$
 ;; s   AD D)(D)c                 j    t        j                          | _        | j                  j                          y)z5
        Called when exiting the with block.
        N)r   r
   r	   releaser   typevalue	tracebacks       r   __exit__zTimedLock.__exit__D   s!     		r   c                 f    t        j                  d|       | j                  j                  |       y)z
        Asynchronously add time to the next request. Can be called outside
        of the lock context, but it is possible for the next lock holder
        to not check the queue until after something adds time to it.
        zAdding %s to queueN)r   infor   put)r   r   s     r   snoozezTimedLock.snoozeK   s#     	('2

wr   N)r   )__name__
__module____qualname____doc__r   r   r%   r)    r   r   r   r      s    
##(	 r   r   c                       e Zd ZdZd Zd Zy)FakeLockzA
    If no locking or request throttling is needed, use this
    c                      y)z%
        Do nothing on enter
        Nr.   )r   s    r   r   zFakeLock.__enter__\        	r   c                      y)z$
        Do nothing on exit
        Nr.   r!   s       r   r%   zFakeLock.__exit__b   r2   r   N)r*   r+   r,   r-   r   r%   r.   r   r   r0   r0   W   s    r   r0   )r   r   r   plexpyr   objectr   r0   r.   r   r   <module>r6      s/   $     :  : zv r   