Current File : //usr/lib64/python3.6/site-packages/borg/__pycache__/cache.cpython-36.pyc
3

up�dC��@s*ddlZddlZddlZddlZddlmZddlmZddlm	Z	ddl
mZe�Z
ed�Zddl
mZmZdd	lmZmZmZdd
lmZddlmZddlmZdd
lmZmZddlmZmZmZmZddlmZddlmZddlm Z m!Z!ddlm"Z"ddlm#Z#m$Z$ddlm%Z%m&Z&ddlm'Z'ddlm(Z(ddl)m*Z*m+Z+ddl,m-Z-ddl.m/Z/m0Z0m1Z1ddl2m3Z3ddl4m5Z5ddl6m7Z7ddl8m9Z9edd�Z:Gd d!�d!�Z;d"d#�Z<d$d%�Z=d6d&d'�Z>d(d)�Z?d*d+�Z@Gd,d-�d-�ZAGd.d/�d/�ZBGd0d1�d1�ZCGd2d3�d3eC�ZDGd4d5�d5eC�ZEdS)7�N)�	unhexlify)�
namedtuple)�perf_counter�)�
create_loggerzborg.debug.files_cache)�CACHE_README�FILES_CACHE_MODE_DISABLED)�
ChunkIndex�ChunkIndexEntry�CacheSynchronizer)�Location)�Error)�Manifest)�
get_cache_dir�get_security_dir)�
int_to_bigint�
bigint_to_int�
bin_to_hex�parse_stringified_list)�format_file_size)�safe_ns)�yes�hostname_is_unique)�remove_surrogates)�ProgressIndicatorPercent�ProgressIndicatorMessage)�set_ec�EXIT_WARNING)�safe_unlink)�msgpack)�ArchiveItem�ChunkListEntry)�PlaintextKey)�IntegrityCheckedFile�DetachedIntegrityCheckedFile�FileIntegrityError)�Lock)�SaveFile)�cache_if_remote)�LIST_SCAN_LIMIT�FileCacheEntryzage inode size cmtime chunk_idsc@s�eZdZdZdd�Zeddd��Zdd�Zd	d
�Zdd�Z	dd
d�Z
ddd�Zddd�Zdddd�dd�Z
ddd�Zdd�ZdS) �SecurityManageras
    Tracks repositories. Ensures that nothing bad happens (repository swaps,
    replay attacks, unknown repositories etc.).

    This is complicated by the Cache being initially used for this, while
    only some commands actually use the Cache, which meant that other commands
    did not perform these checks.

    Further complications were created by the Cache being a cache, so it
    could be legitimately deleted, which is annoying because Borg didn't
    recognize repositories after that.

    Therefore a second location, the security database (see get_security_dir),
    was introduced which stores this information. However, this means that
    the code has to deal with a cache existing but no security DB entry,
    or inconsistencies between the security DB and the cache which have to
    be reconciled, and also with no cache existing but a security DB entry.
    cCsV||_t|j�|_t|�|_tjj|jd�|_tjj|jd�|_	tjj|jd�|_
dS)Nzkey-type�locationzmanifest-timestamp)�
repositoryr�id_str�dir�	cache_dir�os�path�join�
key_type_file�
location_file�manifest_ts_file)�selfr-�r8�/usr/lib64/python3.6/cache.py�__init__>s
zSecurityManager.__init__NcCs(|pt|j�}tjj|�r$tj|�dS)z:destroy the security dir for ``repository`` or at ``path``N)rr.r1r2�exists�shutil�rmtree)r-r2r8r8r9�destroyFszSecurityManager.destroycCstdd�|j|j|jfD��S)Ncss|]}tjj|�VqdS)N)r1r2r;)�.0�fr8r8r9�	<genexpr>Nsz(SecurityManager.known.<locals>.<genexpr>)�allr4r5r6)r7r8r8r9�knownMszSecurityManager.knowncCsn|j�sdSy.t|jd��}|j�}|t|j�kSQRXWn.tk
rh}ztjd|�WYdd}~XnXdS)NF�rz&Could not read/parse key type file: %s)	rC�openr4�read�str�TYPE�OSError�logger�warning)r7�key�fd�type�excr8r8r9�key_matchesQszSecurityManager.key_matchescCs�tjd|jj|j�|jjj�}tjd|�tjdt|j��tjd|j	�t
|j��}|j|�WdQRXt
|j
��}|jt|j��WdQRXt
|j��}|j|j	�WdQRXdS)Nz#security: saving state for %s to %szsecurity: current location   %szsecurity: key type           %szsecurity: manifest timestamp %s)rJ�debugr-r.r/�	_location�canonical_pathrGrH�	timestampr'r5�writer4r6)r7�manifestrLZcurrent_locationrMr8r8r9�save[szSecurityManager.savecCs,y.t|j��}|j�}WdQRXtjd|�WnVtk
rTtjd|j�d}Yn2tk
r�}ztjd|�d}WYdd}~XnX|r�|jr�||jkr�|j}tjd|�|j	j
j�}|o�||k�r(dj||�d}t
|ddd	d
d�s�tj��tjd�t|j��}|j|�WdQRX|�r(|j�dS)
Nz#security: read previous location %rz-security: previous location file %s not foundz)Could not read previous location file: %sz.security: using previous_location of cache: %rzDWarning: The repository at location {} was previously located at {}
zDo you want to continue? [yN] z	Aborting.zInvalid answer, aborting.FZ BORG_RELOCATED_REPO_ACCESS_IS_OK)�	false_msg�invalid_msg�retry�env_var_overridez<security: updating location stored in cache and security dir)rEr5rFrJrQ�FileNotFoundErrorrIrK�previous_locationr-rRrS�formatr�Cache�RepositoryAccessAbortedr'rUrW)r7�cache_configrMr]rOZrepository_location�msgr8r8r9�assert_location_matcheshs4

z'SecurityManager.assert_location_matchescCs�y.t|j��}|j�}WdQRXtjd|�WnVtk
rTtjd|j�d}Yn2tk
r�}ztjd|�d}WYdd}~XnX|r�t||j	p�d�}tjd|�|r�||j	kr�t
|t�r�tj
��ntj��dS)Nz$security: read manifest timestamp %rz.security: manifest timestamp file %s not found�z)Could not read previous location file: %sz4security: determined newest manifest timestamp as %s)rEr6rFrJrQr\rIrK�maxrT�
isinstancer"r_�RepositoryIDNotUnique�RepositoryReplay)r7rVrLrarMrTrOr8r8r9�assert_no_manifest_replay�s"

z)SecurityManager.assert_no_manifest_replaycCsF|r&|jdk	r&|jt|j�kr&tj��|j�rB|j|�rBtj��dS)N)�key_typerGrHr_�EncryptionMethodMismatchrCrP)r7rLrar8r8r9�assert_key_type�szSecurityManager.assert_key_typeT)ra�warn_if_unencrypted�	lock_waitcCsr|j|||�|r"|j|||�nBt|j|d�}|j�rX|�|j|||�WdQRXn|j||�tjd�dS)N)rnz/security: repository checks ok, allowing access)�assert_access_unknown�_assert_secure�CacheConfigr-r;rJrQ)r7rVrLrarmrnr8r8r9�
assert_secure�szSecurityManager.assert_securecCsF|j|�|j||�|j|||�|j�sBtjd�|j||�dS)Nz3security: remembering previously unknown repository)rcrlrirCrJrQrW)r7rVrLrar8r8r9rp�s

zSecurityManager._assert_securecCsf|jrb|j�rbd
}|p,t|ddddd�}|rZ|rBtjd�n
tjd	�|j||�ntj��dS)NzKWarning: Attempting to access a previously unknown unencrypted repository!
zDo you want to continue? [yN] z	Aborting.zInvalid answer, aborting.FZ*BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK)rXrYrZr[zIsecurity: remembering unknown unencrypted repository (explicitly allowed)z-security: initializing unencrypted repositoryziWarning: Attempting to access a previously unknown unencrypted repository!
Do you want to continue? [yN] )Zlogically_encryptedrCrrJrQrWr_�CacheInitAbortedError)r7rmrVrLrbZallow_accessr8r8r9ro�s

z%SecurityManager.assert_access_unknown)N)N)N)N)N)�__name__�
__module__�__qualname__�__doc__r:�staticmethodr>rCrPrWrcrirlrrrpror8r8r8r9r+*s

 


r+cCst|�}|j||j|d�dS)N)rn)r+rrrL)r-rVrnZsmr8r8r9rr�srrcCs�|jj�}t|�}t|�}|j|jkr�|j|jkr�|j|jkr�|j|jkr�|jr�|jr�|jjd�r�|jjd�r�|jdd�|jdd�kr�|S|SdS)Nz/~/z/./�)	rRrSr�proto�user�hostZportr2�
startswith)Zcache_locationr-Z
repo_locationZrlZclr8r8r9� recanonicalize_relative_location�s
04r~cCs|ptjjt�|j�S)N)r1r2r3rr.)r-r2r8r8r9r0�sr0cCstjjdd�}|rd|SdS)NZBORG_FILES_CACHE_SUFFIXrdzfiles.�files)r1�environ�get)�suffixr8r8r9�files_cache_name�sr�cCsdd�tj|�D�dS)NcSs"g|]}|dks|jd�r|�qS)rzfiles.)r})r?�fnr8r8r9�
<listcomp>�sz-discover_files_cache_name.<locals>.<listcomp>r)r1�listdir)r2r8r8r9�discover_files_cache_name�sr�c@s`eZdZddd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	ddd�Z
dd�Zdd�ZdS)rqNcCs4||_t||�|_tjj|jd�|_d|_||_dS)N�config)r-r0r2r1r3�config_path�lockrn)r7r-r2rnr8r8r9r:�s
zCacheConfig.__init__cCs|j�|S)N)rE)r7r8r8r9�	__enter__�szCacheConfig.__enter__cCs|j�dS)N)�close)r7�exc_type�exc_val�exc_tbr8r8r9�__exit__�szCacheConfig.__exit__cCstjj|j�S)N)r1r2r;r�)r7r8r8r9r;�szCacheConfig.existsc	Cs�|j�st�tjdd�}|jd�|jddd�|jdd|jj�|jddd�|jd�|jddd�t|j	��}|j
|�WdQRXdS)	N)�
interpolation�cache�version�1r-rVrd�	integrity)r;�AssertionError�configparser�ConfigParser�add_section�setr-r.r'r�rU)r7r�rMr8r8r9�creates

zCacheConfig.createcCs2ttjj|jd�d|jt�d�j�|_|j�dS)Nr�T)�	exclusiveZtimeoutZkill_stale_locks)	r&r1r2r3rnr�acquirer��load)r7r8r8r9rEszCacheConfig.opencCsttjdd�|_t|j��}|jj|�WdQRX|j|j�|jjdd�|_t	|jjdd��|_
|jjdddd�|_|jjdddd�|_t
t|jjddd	d���|_t
t|jjdd
d	d���|_y@t|jjd��|_|jjdd�|jjd�kr�i|_tjd�Wn(tjk
�r(tjd
�i|_YnX|jjdddd�}|�rRt||j�|_nd|_|jj
dd|jjj��dS)N)r�r�r-rVrT)Zfallbackrj�ignored_featuresrd�mandatory_featuresr�zHCache integrity data not available: old Borg version modified the cache.zTCache integrity: No integrity data found (files, chunks). Cache is from old version.r])r�r��_configrEr�Z	read_file�_check_upgrader��idr�manifest_idrTrjr�rr�r��dict�itemsr��poprJrK�NoSectionErrorrQr~r-r]rRrS)r7rMr]r8r8r9r�s.
zCacheConfig.loadc	Cs�|r�|jjdd|j�|jjdd|j�|jjdddj|j��|jjdddj|j��|jjd�sp|jjd�x&|j	j
�D]\}}|jjd||�q|W|jjdd|j�|r�|jjddt|j��t
|j��}|jj|�WdQRXdS)	Nr�rVrTr��,r�r�rj)r�r�r.rTr3r�r�Zhas_sectionr�r�r�rGrHr'r�rU)r7rVrL�file�integrity_datarMr8r8r9rW3szCacheConfig.savecCs|jdk	r|jj�d|_dS)N)r��release)r7r8r8r9r�Cs

zCacheConfig.closecCsjy8|jjdd�}d}||kr6|j�td|||f��Wn,tjk
rd|j�td|�d�YnXdS)Nr�r�rz0%s has unexpected cache version %d (wanted: %d).z#%s does not look like a Borg cache.)r�Zgetintr��	Exceptionr�r�)r7r�Z
cache_versionZwanted_versionr8r8r9r�HszCacheConfig._check_upgrade)NN)NN)
rtrurvr:r�r�r;r�rEr�rWr�r�r8r8r8r9rq�s
 
rqc	@s�eZdZdZGdd�de�ZGdd�de�ZGdd�de�ZGdd	�d	e�ZGd
d�de�Z	e
dd
d��Ze
ddd��Zddddddde
df	dd�ZdS)r_zClient Side cache
    c@seZdZdZdS)zCache.RepositoryIDNotUniquez`Cache is newer than repository - do you have multiple, independently updated repos with same ID?N)rtrurvrwr8r8r8r9rgXsrgc@seZdZdZdS)zCache.RepositoryReplayz�Cache, or information obtained from the security directory is newer than repository - this is either an attack or unsafe (multiple repos with same ID)N)rtrurvrwr8r8r8r9rh[srhc@seZdZdZdS)zCache.CacheInitAbortedErrorzCache initialization abortedN)rtrurvrwr8r8r8r9rs^srsc@seZdZdZdS)zCache.RepositoryAccessAbortedzRepository access abortedN)rtrurvrwr8r8r8r9r`asr`c@seZdZdZdS)zCache.EncryptionMethodMismatchzLRepository encryption method changed since last access, refusing to continueN)rtrurvrwr8r8r8r9rkdsrkNcCs(t||�}ttjj|d�dd�j�dS)Nr�T)r�)r0r&r1r2r3�
break_lock)r-r2r8r8r9r�gs
zCache.break_lockcCsH|ptjjt�|j�}tjj|d�}tjj|�rDtj|�tj|�dS)z3destroy the cache for ``repository`` or at ``path``r�N)	r1r2r3rr.r;�remover<r=)r-r2r�r8r8r9r>ls

z
Cache.destroyTFc
	s�|rd�krd�n"|r6d�kr6djt��td������������f	dd�}
����fdd�}|
sn|
�St����}|j�r�|�|j�jk}WdQRX|r�tjd�|
�Stjd	�|�S)
N�d�irdcst���������d�	S)N)	r-rLrVr2�syncrm�progressrn�
cache_mode)�
LocalCacher8)	r�rLrnrVr2r�r-r�rmr8r9�local~szCache.__new__.<locals>.localcst����d�S)N)r-rLrVrn)�
AdHocCacher8)rLrnrVr-r8r9�adhoc�szCache.__new__.<locals>.adhocz%Cache: choosing local cache (in sync)zKCache: choosing ad-hoc cache (local cache does not exist or is not in sync))r3r�rqr;r�r�rJrQ)�clsr-rLrVr2r�Zdo_filesrmr�rnZpermit_adhoc_cacher�Zignore_inoder�r�raZ
cache_in_syncr8)	r�rLrnrVr2r�r-r�rmr9�__new__us"

z
Cache.__new__)N)N)rtrurvrwr
rgrhrsr`rkrxr�r>rr�r8r8r8r9r_Usr_c@sFeZdZdZdd�Zedddddd	d
g�Zdd�Zd
d�Zdd�Z	dS)�CacheStatsMixinz�All archives:   {0.total_size:>20s} {0.total_csize:>20s} {0.unique_csize:>20s}

                       Unique chunks         Total chunks
Chunk index:    {0.total_unique_chunks:20d} {0.total_chunks:20d}cCs|jj|j��S)N)�
str_formatr^�format_tuple)r7r8r8r9�__str__�szCacheStatsMixin.__str__�Summary�
total_size�total_csizeZunique_size�unique_csizeZtotal_unique_chunksZtotal_chunkscCs|j|jj��j�}|S)N)r��chunksZ	summarize�_asdict)r7�statsr8r8r9r��szCacheStatsMixin.statscCs2|j�}xdD]}t||�||<qW|jf|�S)Nr�r�r�)r�r�r�)r�rr�)r7r�Zfieldr8r8r9r��s
zCacheStatsMixin.format_tuplecCs|j�dS)Nr�)r�)r7r8r8r9�chunks_stored_size�sz"CacheStatsMixin.chunks_stored_sizeN)
rtrurvr�r�rr�r�r�r�r8r8r8r9r��sr�c@s�eZdZdZdddddefdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd/d#d$�Zd0d%d&�Zd1d'd(�Zd2d)d*�Zd+d,�Zd-d.�ZdS)3r�z0
    Persistent, local (client-side) cache.
    NTFc

Cs�||_||_||_||_|	|_d|_d|_t||�|_t	|�|_
t|j|j|�|_t
jj|j�sx|j
j|||�|j�|j�yT|j
j|||jd�|j�s�|j�|j�|r�|jj|jjkr�|j�|j�Wn|j��YnXdS)aO
        :param warn_if_unencrypted: print warning if accessing unknown unencrypted repository
        :param lock_wait: timeout for lock acquisition (int [s] or None [wait forever])
        :param sync: do :meth:`.sync`
        :param cache_mode: what shall be compared in the file stat infos vs. cached stat infos comparison
        NF)ra)r-rLrVr�r�rT�
txn_activer0r2r+�security_managerrqrar1r;ror�rErr�check_cache_compatibility�
wipe_cache�update_compatibilityr�r�r��commitr�)
r7r-rLrVr2r�rmr�rnr�r8r8r9r:�s2
zLocalCache.__init__cCs|S)Nr8)r7r8r8r9r��szLocalCache.__enter__cCs|j�dS)N)r�)r7r�r�r�r8r8r9r��szLocalCache.__exit__cCs�tj|j�ttjj|jd�d��}|jt�WdQRX|jj�t	�jtjj|jd��tjtjj|jd��t
tjj|jt��dd��WdQRXdS)z0Create a new empty cache at `self.path`
        ZREADME�wNr�zchunks.archive.dT)�binary)r1�makedirsr2rEr3rUrrar�r	r'r�)r7rMr8r8r9r��s
zLocalCache.createc	Csd|jj�ttjj|jd�d|jjjd�d��}tj	|�|_
WdQRXd|jkrXd|_n|j
�dS)Nr�F)r2rUr�r�)rar�r#r1r2r3r�r�r	rFr�r�r�_read_files)r7rMr8r8r9�_do_open�s

zLocalCache._do_opencCs2tjj|j�std|j��|jj�|j�dS)Nz"%s Does not look like a Borg cache)r1r2�isdirr�rarE�rollback)r7r8r8r9rEs
zLocalCache.opencCs|jdk	r|jj�d|_dS)N)rar�)r7r8r8r9r�s

zLocalCache.closec
Cs�i|_d|_tjd�tjd�d}y�ttjj|jt	��d|j
jjt	��d���}t
jdd�}x�|jd�}|snP|j|�y<x6|D].\}}t|�}t
j|j|jd	d
��|j|<q�WWq^ttfk
r�}zdt|�}PWYdd}~Xq^Xq^WWdQRXWn^tk
�r*}zdt|�}WYdd}~Xn0tk
�rX}	zd
t|	�}WYdd}	~	XnX|dk	�r~tj|�tjd�i|_tjdt|j��dS)NzReading files cache ...zFILES-CACHE-LOAD: starting...F)r2rUr�T)Zuse_list�@ir)�agez#The files cache seems invalid. [%s]z#The files cache can't be read. [%s]z"The files cache is corrupted. [%s]z:Continuing without files cache - expect lower performance.z.FILES-CACHE-LOAD: finished, %d entries loaded.i)r�_newest_cmtimerJrQ�files_cache_loggerr#r1r2r3r�rar�r�rZUnpackerrF�feedr*�packb�_replacer��	TypeError�
ValueErrorrGrIr%rK�len)
r7rbrM�u�data�	path_hash�item�entryrO�fier8r8r9r�s<



&&


zLocalCache._read_filescCstdd�}tjj|jd�}tj|�|jd�tjtjj|jd�|�|jd�tjtjj|jd�|�|jd�ytjtjj|jt��|�Wn8t	k
r�t
tjj|t��d	d
��WdQRXYnXtjtjj|jd�tjj|jd��d	|_|j
�dS)Nzcache.begin_transaction)�msgidztxn.tmpz.Initializing cache transaction: Reading configr�z.Initializing cache transaction: Reading chunksr�z-Initializing cache transaction: Reading filesT)r�z
txn.active)rr1r2r3�mkdir�outputr<�copyr�r\r'�renamer��finish)r7�pi�txn_dirr8r8r9�	begin_txn,s"




zLocalCache.begin_txncCs�|js
dS|jj|j|j�tdd�}|jdk	�r4|jdkrBd|_tt	j
jdd��}|jd	�t
jd
�tt	jj|jt��dd��v}d
}xj|jj�D]\\}}ttj|��}|jd
kr�t|j�|jks�|jd
kr�|j|kr�tj||f|�|d7}q�WWdQRXt
jd|�t
jd|j�t
jd|�|j|jjt�<|jd�tt	jj|jd�dd��}|jj|�WdQRX|j|jjd<|jd�|jj|j|j�t	j t	jj|jd�t	jj|jd��t!j"t	jj|jd��d|_|j#�dS)zCommit transaction
        Nzcache.commit)r���?rZBORG_FILES_CACHE_TTL�zSaving files cachezFILES-CACHE-SAVE: starting...T)r2rUrz>FILES-CACHE-KILL: removed all old entries with age >= TTL [%d]zCFILES-CACHE-KILL: removed all current entries with newest cmtime %dz7FILES-CACHE-SAVE: finished, %d remaining entries saved.zSaving chunks cacher�zSaving cache configz
txn.activeztxn.tmpFll����)$r�r�rWrVrLrrr��intr1r�r�r�r�rQr#r2r3r�r�r*r�unpackbr�r�cmtime�packr�rar�r�rUr�r<r=r�)r7r�ZttlrMZentry_countr�r�r�r8r8r9r�@sB





zLocalCache.commitcCs�tjjtjj|jd��r.tjtjj|jd��tjj|jd�}tjj|�r�tjtjj|d�|j�tjtjj|d�|j�tjtjj|t|��|j�tj|tjj|jd��tjjtjj|jd��r�tjtjj|jd��d|_	|j
�dS)z3Roll back partial and aborted transactions
        ztxn.tmpz
txn.activer�r�FN)r1r2r;r3r<r=r�r�r�r�r�)r7r�r8r8r9r�iszLocalCache.rollbackcsJtjj�jd��t��d�
d�d�d�
d�	d�fdd�	���fdd���fdd	���fd
d��d �fd
d�	����	�
fdd����
���fdd����fdd�����fdd���fdd���������	�
��
����fdd�}��fdd�}�jjtjjf��j	�t
�j�jd��&�|�tjj
���_|�j��_WdQRXdS)!a�Re-synchronize chunks cache with repository.

        Maintains a directory with known backup archive indexes, so it only
        needs to fetch infos from repo and build a chunk index once per backup
        archive.
        If out of sync, missing archive indexes get added, outdated indexes
        get removed and a new master chunks index is built by merging all
        archive indexes.
        zchunks.archive.drrdcst|�}tjj�||�}|S)N)rr1r2r3)r�r�Zid_hexr2)�archive_pathr8r9�mkpath�szLocalCache.sync.<locals>.mkpathcs>�jr4tj��}tdd�|D��tdd�|D��BSt�SdS)Ncss"|]}t|�dkrt|�VqdS)r�N)r�r)r?r�r8r8r9rA�sz;LocalCache.sync.<locals>.cached_archives.<locals>.<genexpr>css4|],}t|�dkr|jd�rt|dd��VqdS)�Hz.compactNr�)r��endswithr)r?r�r8r8r9rA�s)�do_cacher1r�r�)Zfns)r�r7r8r9�cached_archives�s

z(LocalCache.sync.<locals>.cached_archivescstdd��jjj�D��S)Ncss|]}|jVqdS)N)r�)r?�infor8r8r9rA�sz9LocalCache.sync.<locals>.repo_archives.<locals>.<genexpr>)r�rV�archives�listr8)r7r8r9�
repo_archives�sz&LocalCache.sync.<locals>.repo_archivescsx|D]}�|�qWdS)Nr8)�idsr�)�cleanup_cached_archiver8r9�cleanup_outdated�s
z)LocalCache.sync.<locals>.cleanup_outdatedTcs�y$tj�|��tj�|�d�Wntk
r8YnX|sBdSy,tj�|dd��tj�|dd�d�Wntk
r�YnXdS)Nz
.integrityz.compact)r�)r1�unlinkr\)r��cleanup_compact)r�r8r9r��sz/LocalCache.sync.<locals>.cleanup_cached_archivecs�|j�}g}t��rlxZ|D]L}�j|�}|r\||j|jd�}|j|jksRtd��|||<q|j|�qWn|}xVt|�j	j
|��D]@\}}||jt|�d�}|||<|�|<�d7��t|�7�q�WdS)z�
            Archives created with AdHocCache will have csize=0 in all chunk list entries whose
            chunks were already in the repository.

            Scan *chunk_idx* for entries where csize=0 and fill in the correct information.
            )�csizezChunk size mismatchrN)Zzero_csize_idsr�r�r�r�sizer��append�zipr-�get_many)�	chunk_idxZall_missing_idsZ	fetch_ids�id_Zalready_fetched_entryr�r�)�chunks_fetched_size_index�decrypted_repository�fetched_bytes_for_csize�fetched_chunks_for_csizer8r9�fetch_missing_csize�s"



z,LocalCache.sync.<locals>.fetch_missing_csizec
s�|j|�\}}|j|dt|�|��jj|dd�\}}}t|d�}|jdkrTtd��t|�}xVt	|j
|j|j
��D]>\}	\}}|j|	dt|�|��t|�7��d7�|j|�qrW�j
r̈|��||�dS)NrT)Zforce_tam_not_required)Z
internal_dictz Unknown archive metadata version)r��addr�rLZunpack_and_verify_archiver r�r�rrr�rr�r�)
�
archive_idrrrr��archiveZverified�_r�Zitem_id)r�processed_item_metadata_bytes�processed_item_metadata_chunksr7�write_archive_indexr8r9�fetch_and_build_idx�s

"z,LocalCache.sync.<locals>.fetch_and_build_idxcs��|j�7��|dd�}�|dd�}y0t|dt|�dd��}|j|�WdQRXWntk
rpt|�YnXtj||�dS)Nz.compact)r�z.tmpT)r2rU�filename)Zcompactr$rrUr�rr1r�)rrr�Zfn_tmprM)�"compact_chunks_archive_saved_spacer�r8r9r�sz,LocalCache.sync.<locals>.write_archive_indexcs��|�}tjd|�yvy:t|ddd��}tj|dd�}WdQRX�|dd�|Stk
r�t|dd��}tj|�}WdQRXYnXWn>tk
r�}z"tjd||��|�tt	�dSd}~XnXtj
d	|��|��||�|S)
Nz-Reading cached archive chunk index for %s ...z.compactF)r2rUT)Zpermit_compact)rz1Cached archive chunk index of %s is corrupted: %sz6Found non-compact index for %s, converting to compact.)rJr�r$r	rFr\r%�errorrrrQ)r�archive_nameZarchive_chunk_idx_pathrM�archive_chunk_idxr�)r�r�rr8r9�read_archive_index�s(
z+LocalCache.sync.<locals>.read_archive_indexcsHi}x*�jjj�D]}|j|kr|j||j<qWt|�t|�ksDt�|S)N)rVr�r�r��namer�r�)�archive_idsZ
archive_namesr�)r7r8r9�get_archive_ids_to_namess
z1LocalCache.sync.<locals>.get_archive_ids_to_namesc	s�tjd���}��}tjdt|�t|�t||�t||��|j��||�tt�
j�tj�}|�r��
jsxdnt|�}t	t|�dddd�}�|�}x�|j
�D]�\}}|jt|�gd��
j�r*||kr�||�}|dkr�|j
|�||k�rtjd|�t�}�|�|�tjd	�|j|�q�|�p6t|�}tjd
|��|�|�q�W�
j�sd�|�|j�tjdt����tjdt�	��
�tjd
t���tjd�|S)NzSynchronizing chunks cache...zIArchives: %d, w/ cached Idx: %d, w/ outdated Idx: %d, w/o cached Idx: %d.g�������?z3%3.0f%% Syncing chunks cache. Processing archive %sz
cache.sync)�total�steprbr�)r�z.Fetching and building archive index for %s ...z$Merging into master chunks index ...z!Fetching archive index for %s ...zlCache sync: had to fetch %s (%d chunks) because no archive had a csize set for them (due to --no-cache-sync)z0Cache sync: processed %s (%d chunks) of metadataz;Cache sync: compact chunks.archive.d storage saved %s byteszDone.)rJr�r��clearr�r-r	�MAX_LOAD_FACTORr�rr��showrr��merger�rQr)	rZ
cached_idsrZmaster_index_capacityr�Zarchive_ids_to_namesrrr)r�rrrrrrr
rrrrr�r7r8r9�create_master_idxsT







z*LocalCache.sync.<locals>.create_master_idxcspytjtjj�jd��WnYnXytjtjj�jd��WnYnXytj��WnYnXdS)z?bring old cache dirs into the desired state (cleanup and adapt)zchunks.archivezchunks.archive.tmpN)r1rr2r3r�r8)r�r7r8r9�legacy_cleanupQsz'LocalCache.sync.<locals>.legacy_cleanup)Zdecrypted_cacheN)rd)T)r1r2r3r	rVZcheck_repository_compatibilityrZ	OperationZREADr�r(r-rLr�r�r�)r7r&r'r8)r�r�r
r�rrrrrrr
rr�rrrr�r7rr9r�{s2

!&3zLocalCache.synccCs*tj}|jj|@rdS|jj|ks&dSdS)NFT)r�SUPPORTED_REPO_FEATURESrar�r�)r7�my_featuresr8r8r9r�msz$LocalCache.check_cache_compatibilitycCs�tjd�tjj|jd�}tjj|�rRtjtjj|jd��tjtjj|jd��t	�|_
ttjj|jt��dd��WdQRXd|j
_|j
jjddd�t�|j
_t�|j
_dS)Nz9Discarding incompatible cache and forcing a cache rebuildzchunks.archive.dT)r�rdr�rV)rJrKr1r2r3r�r<r=r�r	r�r'r�rar�r�r�r�r�)r7r�r8r8r9r�ys


zLocalCache.wipe_cachecCs^|jj�}tj}t�}x|j�D]\}}|j|�q W|jjj||�|jj	j||@�dS)N)
rVZget_all_mandatory_featuresrr(r�r��updaterar�r�)r7Zoperation_to_features_mapr)Z
repo_featuresZ	operationZfeaturesr8r8r9r��s
zLocalCache.update_compatibilityc
Cs�|js|j�t|�}|j||�}|r8|r8|j||�S|jj|�}t|�}	|jj|||d�|j	j
|d||	�|j||	|�t|||	�S)N)�waitr)
r�r�r��
seen_chunk�chunk_increfrL�encryptr-�putr�rr*r!)
r7r��chunkr��	overwriter+r�refcountr�rr8r8r9�	add_chunk�s
zLocalCache.add_chunkcCsJ|jj|tddd��\}}}|dk	rF|dk	rF||krFtd|||f��|S)Nrz@chunk has same id [%r], but different size (stored: %d new: %d)!)r�r�r
r�)r7r�rr2Zstored_sizerr8r8r9r,�s
zLocalCache.seen_chunkcCs:|js|j�|jj|�\}}}|j||d�t|||�S)NF)r�r�r��increfr*r!)r7r�r�r�count�_sizerr8r8r9r-�s
zLocalCache.chunk_increfcCsj|js|j�|jj|�\}}}|dkrT|j|=|jj||d�|j||d�n|j||d�dS)Nr)r+TF)r�r�r��decrefr-�deleter*)r7r�r�r+r5rrr8r8r9�chunk_decref�szLocalCache.chunk_decrefcCs4tj|j�sdS|j}d|kr,tjd�dSd|krBtjd�dS|jj|�}|sbtjd|�dStt	j
|��}d|kr�|j|jkr�tjd	|�dSd|kr�|j
|jkr�tjd|�dSd
|ko�t|j�|jk�r�tjd|�dSd|k�rt|j�|jk�rtjd|�dSt	j|j|jdd��|j|<d
|jfS)aj
        Check if we know the file that has this path_hash (know == it is in our files cache) and
        whether it is unchanged (the size/inode number/cmtime is same for stuff we check in this cache_mode).

        :param hashed_path: the file's path as we gave it to hash(hashed_path)
        :param path_hash: hash(hashed_path), to save some memory in the files cache
        :param st: the file's stat() result
        :return: known, ids (known is True if we have infos about this file in the cache,
                             ids is the list of chunk ids IF the file has not changed, otherwise None).
        FNr�zUNKNOWN: files cache disabledrDzUNKNOWN: rechunking enforcedz*UNKNOWN: no file metadata in cache for: %r�sz(KNOWN-CHANGED: file size has changed: %rTr�z0KNOWN-CHANGED: file inode number has changed: %r�cz)KNOWN-CHANGED: file ctime has changed: %r�mz)KNOWN-CHANGED: file mtime has changed: %rr)�inoder�)FN)FN)FN)FN)TN)TN)TN)TN)�stat�S_ISREG�st_moder�r�rQrr�r*rr�r�st_sizer=�st_inorr��st_ctime_ns�st_mtime_nsr�r��	chunk_ids)r7�hashed_pathr��str�r�r8r8r9�file_known_and_unchanged�s8

	z#LocalCache.file_known_and_unchangedc	Cs�tj|j�sdS|j}d|kr,tjd�dSd|krDd}t|j�}nd|krZd}t|j�}t	d|j
|jt|�|d�}t
j|�|j|<t|jp�d|�|_tjd	|jd
t|j�d�||�dS)Nr�z*FILES-CACHE-NOUPDATE: files cache disabledr;Zctimer<�mtimer)r�r=rr�rEz)FILES-CACHE-UPDATE: put %r [has %s] <- %rz[%d entries])rE)r>r?r@r�r�rQrrCrDr*rBrArrr�rrer�r�r�rE)	r7rFr�rGr�r�Zcmtime_typeZ	cmtime_nsr�r8r8r9�
memorize_file�s$

zLocalCache.memorize_file)FT)N)N)T)rtrurvrwrr:r�r�r�r�rEr�r�r�r�r�r�r�r�r�r3r,r-r9rHrJr8r8r8r9r��s0(
!)s


	

4r�c@s�eZdZdZdZddd�Zdd�Zd	d
�ZdZdZ	dd
�Z
dd�Zd dd�Zd!dd�Z
d"dd�Zd#dd�Zdd�Zdd�Zdd�ZdS)$r�a�
    Ad-hoc, non-persistent cache.

    Compared to the standard LocalCache the AdHocCache does not maintain accurate reference count,
    nor does it provide a files cache (which would require persistence). Chunks that were not added
    during the current AdHocCache lifetime won't have correct size/csize set (0 bytes) and will
    have an infinite reference count (MAX_VALUE).
    z�All archives:                unknown              unknown              unknown

                       Unique chunks         Total chunks
Chunk index:    {0.total_unique_chunks:20d}             unknownTNcCsB||_||_||_d|_t|�|_|jj|||d�tjd�dS)NF)rnz1Note: --no-cache-sync is an experimental feature.)	r-rLrV�_txn_activer+r�rrrJrK)r7r-rLrVrmrnr8r8r9r:s
zAdHocCache.__init__cCs|S)Nr8)r7r8r8r9r�"szAdHocCache.__enter__cCsdS)Nr8)r7r�r�r�r8r8r9r�%szAdHocCache.__exit__r�cCstjd�dS)Nz$UNKNOWN: files cache not implementedF)FN)r�rQ)r7rFr�rGr8r8r9rH+s
z#AdHocCache.file_known_and_unchangedcCsdS)Nr8)r7rFr�rGr�r8r8r9rJ/szAdHocCache.memorize_fileFc
Cs�|std��|js|j�t|�}|j||�}|rD|j|||d�S|jj|�}t|�}	|jj	|||d�|j
j|d||	�|j||	|�t
|||	�S)NuHAdHocCache does not permit overwrites — trying to use it for recreate?)r)r+r)r�rK�
_begin_txnr�r,r-rLr.r-r/r�rr*r!)
r7r�r0r�r1r+rr2r�rr8r8r9r32szAdHocCache.add_chunkcCsN|js|j�|jj|tddd��}|jrH|rH|jrH|j|d�|j|<|jS)Nr)r)rKrLr�r�r
r2rr�)r7r�rr�r8r8r9r,AszAdHocCache.seen_chunkcCsJ|js|j�|jj|�\}}}|p&|}|s0t�|j||d�t|||�S)NF)rKrLr�r4r�r*r!)r7r�r�rr5r6rr8r8r9r-LszAdHocCache.chunk_increfcCsj|js|j�|jj|�\}}}|dkrT|j|=|jj||d�|j||d�n|j||d�dS)Nr)r+TF)rKrLr�r7r-r8r*)r7r�r�r+r5rrr8r8r9r9WszAdHocCache.chunk_decrefcCs&|js
dS|jj|j|j�d|_dS)NF)rKr�rWrVrL)r7r8r8r9r�bszAdHocCache.commitcCsd|_|`dS)NF)rKr�)r7r8r8r9r�hszAdHocCache.rollbackcCsd|_t|j�}t|tjd�}t|�|_t|ddd�}t�}d}d}xb|jj	t
|d�}|d7}|shP|jt|�d	�|d}ttj
ddd
�}x|D]}	||j|	<q�WqJWt|j�|ks�t�|j|jj=t�|p�d}
|j�tjd||
|t|d
|
��dS)NTg�������?z!Downloading chunk list... %3.0f%%zcache.download_chunks)r rbr�r)�limit�markerr)Zincrease)r2rrg{�G�z�?zBAdHocCache: downloaded %d chunk IDs in %.2f s (%d requests), ~%s/s�"���)rKr�r-r�r	r#r�rrr�r)r$r
Z	MAX_VALUEr�rVZMANIFEST_IDr�rJrQr)r7Z
num_chunksZcapacityr�Zt0Znum_requestsrN�resultZ
init_entryr	Zdurationr8r8r9rLns2


zAdHocCache._begin_txn)TN)FT)N)N)T)rtrurvrwr�r:r�r�rr�rHrJr3r,r-r9r�r�rLr8r8r8r9r�s 





r�)N)Fr�r1r<r>Zbinasciir�collectionsrZtimerrJrr�Z	constantsrrZ	hashindexr	r
rZhelpersrr
rrrrrrrrrrrrrrrrrrr�r r!Z
crypto.keyr"Zcrypto.file_integrityr#r$r%Zlockingr&�platformr'Zremoter(r-r)r*r+rrr~r0r�r�rqr_r�r�r�r8r8r8r9�<module>s`
%
eES