B
    è¹`ý  ã               @   s®   d dl Z d dlZd dlZd dlZyd dlZW n ek
rD   dZY nX d dlmZ d dlm	Z	 d dl
mZmZ d dlmZ d dlmZmZ G dd„ deƒZG d	d
„ d
e	ƒZdS )é    N)ÚNamespaceManager)ÚSynchronizerImpl)ÚSyncDictÚmachine_identifier)Úsha1)Ústring_typeÚPY2c                   s~   e Zd ZdZdZeƒ Zd‡ fdd„	Zdd„ Z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‡  ZS )ÚRedisNamespaceManageraz  Provides the :class:`.NamespaceManager` API over Redis.

    Provided ``url`` can be both a redis connection string or
    an already existing StrictRedis instance.

    The data will be stored into redis keys, with their name
    starting with ``beaker_cache:``. So make sure you provide
    a specific database number if you don't want to mix them
    with your own data.
    i   Nc                sX   t t| ƒ |¡ d | _|| _td kr,tdƒ‚t|tƒrNtj	 
|tjj|¡| _n|| _d S )Nzredis is not available)Úsuperr	   Ú__init__Zlock_dirÚtimeoutÚredisÚRuntimeErrorÚ
isinstancer   ÚclientsÚgetÚStrictRedisÚfrom_urlÚclient)ÚselfÚ	namespaceÚurlr   Úkw)Ú	__class__© úZ/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/beaker/ext/redisnm.pyr   !   s    
zRedisNamespaceManager.__init__c             C   s`   t |tƒs| d¡}t|ƒ| jt| jƒ tdƒ d krRtsF| d¡}t|ƒ 	¡ }d| j|f S )NÚasciizbeaker_cache:é   zutf-8zbeaker_cache:%s:%s)
r   ÚstrÚdecodeÚlenÚMAX_KEY_LENGTHr   r   Úencoder   Ú	hexdigest)r   Úkeyr   r   r   Ú_format_key.   s    

$
z!RedisNamespaceManager._format_keyc             C   s   t |  |¡| jƒS )N)ÚRedisSynchronizerr%   r   )r   r$   r   r   r   Úget_creation_lock7   s    z'RedisNamespaceManager.get_creation_lockc             C   s,   | j  |  |¡¡}|d kr"t|ƒ‚t |¡S )N)r   r   r%   ÚKeyErrorÚpickleÚloads)r   r$   Úentryr   r   r   Ú__getitem__:   s    z!RedisNamespaceManager.__getitem__c             C   s   | j  |  |¡¡S )N)r   Úexistsr%   )r   r$   r   r   r   Ú__contains__@   s    z"RedisNamespaceManager.__contains__c             C   s   || kS )Nr   )r   r$   r   r   r   Úhas_keyC   s    zRedisNamespaceManager.has_keyc             C   s^   t  |¡}|d kr"| jd k	r"| j}|d k	rF| j |  |¡t|ƒ|¡ n| j |  |¡|¡ d S )N)r)   Údumpsr   r   Úsetexr%   ÚintÚset)r   r$   ÚvalueZ
expiretimer   r   r   Ú	set_valueF   s    
zRedisNamespaceManager.set_valuec             C   s   |   ||¡ d S )N)r5   )r   r$   r4   r   r   r   Ú__setitem__O   s    z!RedisNamespaceManager.__setitem__c             C   s   | j  |  |¡¡ d S )N)r   Údeleter%   )r   r$   r   r   r   Ú__delitem__R   s    z!RedisNamespaceManager.__delitem__c             C   s"   x|   ¡ D ]}| j |¡ q
W d S )N)Úkeysr   r7   )r   Úkr   r   r   Ú	do_removeU   s    zRedisNamespaceManager.do_removec             C   s   | j  d| j ¡S )Nzbeaker_cache:%s:*)r   r9   r   )r   r   r   r   r9   Y   s    zRedisNamespaceManager.keys)N)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r!   r   r   r   r%   r'   r,   r.   r/   r5   r6   r8   r;   r9   Ú__classcell__r   r   )r   r   r	      s   
	
	r	   c                   sR   e Zd ZdZdZeƒ Z‡ fdd„Zdd„ Zdd„ Z	d	d
„ Z
dd„ Zdd„ Z‡  ZS )r&   zéSynchronizer based on redis.

    Provided ``url`` can be both a redis connection string or
    an already existing StrictRedis instance.

    This Synchronizer only supports 1 reader or 1 writer at time, not concurrent readers.
    i„  c                sD   t t| ƒ ¡  d| | _t|tƒr:tj |t	j
j|¡| _n|| _d S )Nzbeaker_lock:%s)r
   r&   r   Ú
identifierr   r   r	   r   r   r   r   r   r   )r   rA   r   )r   r   r   r   j   s
    

zRedisSynchronizer.__init__c             C   s    d| j t ¡ t ¡ jf  d¡S )Nz%s-%s-%sr   )Ú
MACHINE_IDÚosÚgetpidÚ	threadingÚcurrent_threadÚidentr"   )r   r   r   r   Ú_get_owner_idr   s    zRedisSynchronizer._get_owner_idc             C   s   |   ¡  d S )N)Údo_release_write_lock)r   r   r   r   Údo_release_read_lockw   s    z&RedisSynchronizer.do_release_read_lockc             C   s   |   |¡ d S )N)Údo_acquire_write_lock)r   Úwaitr   r   r   Údo_acquire_read_lockz   s    z&RedisSynchronizer.do_acquire_read_lockc                s.   | j ‰ |  ¡ ‰‡ ‡fdd„}| j |ˆ ¡ d S )Nc                s    |   ˆ ¡}|ˆkr|  ˆ ¡ d S )N)r   r7   )ÚpipeZ
lock_value)rA   Úowner_idr   r   Úexecute_release€   s    
z@RedisSynchronizer.do_release_write_lock.<locals>.execute_release)rA   rH   r   Ztransaction)r   rP   r   )rA   rO   r   rI   }   s    z'RedisSynchronizer.do_release_write_lockc             C   s@   |   ¡ }x2| jj| j|| jddr&dS |s.dS t d¡ q
W d S )NT)ÚexZnxFgš™™™™™É?)rH   r   r3   rA   ÚLOCK_EXPIRATIONÚtimeÚsleep)r   rL   rO   r   r   r   rK   †   s    z'RedisSynchronizer.do_acquire_write_lock)r<   r=   r>   r?   rR   r   rB   r   rH   rJ   rM   rI   rK   r@   r   r   )r   r   r&   ]   s   	r&   )rC   rE   rS   r)   r   ÚImportErrorZbeaker.containerr   Zbeaker.synchronizationr   Zbeaker.utilr   r   Zbeaker.crypto.utilr   Zbeaker._compatr   r   r	   r&   r   r   r   r   Ú<module>   s   
K