509318396
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
y¾œbœÙ  ã               @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
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mZ ddlmZ ddlmZ ddlT ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlm Z  ddlm!Z! 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) ddl*m+Z+m,Z, ddl-m.Z. e%e/ƒZ$dZ0e+eƒZ1dP\Z2Z3Z4Z5dZ6dZ7dd„ Z8G dd „ d eƒZ9G d!d"„ d"e9ƒ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>dQdRf f f dSdTdUdVdWf f dXdYf dZd;œZ?d<d=„ Z@G d>d?„ d?ƒZAG d@dA„ dAƒZBdBdC„ ZCG dDdE„ dEƒZDdFdG„ ZEG dHdI„ dIƒZFG dJdK„ dKeFƒZGdLddddLdMœdNdO„ZHdS )[é    N)ÚPopenÚPIPEé   )Ú__version__)ÚLZ4)Ú*)ÚErrorÚIntegrityError)Ú
bin_to_hex)Úget_base_dir)Úget_limited_unpacker)Úhostname_is_unique)Úreplace_placeholders)Úsysinfo)Úformat_file_size)Úsafe_unlink)Úprepare_subprocess_env)Úcreate_loggerÚsetup_logging)Úmsgpack)Ú
Repository)Úparse_versionÚformat_version)Úxxh64é   ó   ió   mó   aó   réd   gš™™™™™¹?c             C   sN   t |ƒ }}x<|rHtj| |ƒ}||8 }|s,P ||d… }tj|d ƒ qW |S )z;os.write wrapper so we do not lose data for partial writes.Ng•Ö&è.>)ÚlenÚosÚwriteÚtimeÚsleep)ÚfdÚdataZamountZ	remainingÚcount© r(   ú/usr/lib64/python3.6/remote.pyÚos_write1   s    r*   c               @   s   e Zd ZdZdS )ÚConnectionClosedz Connection closed by remote hostN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r(   r(   r(   r)   r+   D   s   r+   c               @   s   e Zd ZdZdS )ÚConnectionClosedWithHintz$Connection closed by remote host. {}N)r,   r-   r.   r/   r(   r(   r(   r)   r0   H   s   r0   c               @   s   e Zd ZdZdS )ÚPathNotAllowedzRepository path not allowed: {}N)r,   r-   r.   r/   r(   r(   r(   r)   r1   L   s   r1   c               @   s   e Zd ZdZdS )ÚInvalidRPCMethodzRPC method {} is not validN)r,   r-   r.   r/   r(   r(   r(   r)   r2   P   s   r2   c               @   s   e Zd ZdZdS )Ú!UnexpectedRPCDataFormatFromClientz4Borg {}: Got unexpected RPC data format from client.N)r,   r-   r.   r/   r(   r(   r(   r)   r3   T   s   r3   c                   s    e Zd ZdZ‡ fdd„Z‡  ZS )Ú!UnexpectedRPCDataFormatFromServerz.Got unexpected RPC data format from server:
{}c                sf   y|j ƒ d d… }W n@ tk
rT   |d d… }dd„ |D ƒ}tjdj|ƒdƒ}Y nX tƒ j|ƒ d S )Né€   c             S   s   g | ]}d | ‘qS )z%02Xr(   )Ú.0Zbyter(   r(   r)   ú
<listcomp>`   s    z>UnexpectedRPCDataFormatFromServer.__init__.<locals>.<listcomp>ú é   é   é0   )ÚdecodeÚUnicodeDecodeErrorÚtextwrapZfillÚjoinÚsuperÚ__init__)Úselfr&   )Ú	__class__r(   r)   rA   [   s    z*UnexpectedRPCDataFormatFromServer.__init__)r,   r-   r.   r/   rA   Ú__classcell__r(   r(   )rC   r)   r4   X   s   r4   ÚrepairÚ
save_spaceÚlimitÚmarkerÚidr&   ÚkeydataÚclient_dataÚpathÚcreateÚ	lock_waitÚlockÚ	exclusiveÚappend_onlyÚnext_unreservedÚstart_nonce)ÚcheckÚcommitÚrollbackÚdestroyÚ__len__ÚlistÚputÚgetÚdeleteÚsave_keyÚload_keyÚ
break_lockÚ	negotiateÚopenÚget_free_nonceÚcommit_nonce_reservationc                s   ‡ fdd„ˆ D ƒS )Nc                s   i | ]}ˆ | |j ƒ “qS r(   )r<   )r6   Úk)Údr(   r)   ú
<dictcomp>�   s    zdecode_keys.<locals>.<dictcomp>r(   )re   r(   )re   r)   Údecode_keysŽ   s    rg   c               @   sR   e Zd Zd&Z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 S )(ÚRepositoryServerrX   rT   rU   r\   rW   r[   rY   Úscanr`   ra   rZ   rV   r]   r^   r_   rb   rc   Úinject_exceptionc             C   s,   d | _ || _|| _|| _|| _tdƒ| _d S )Nz1.0.8)Ú
repositoryÚrestrict_to_pathsÚrestrict_to_repositoriesrQ   Ústorage_quotar   Úclient_version)rB   rl   rm   rQ   rn   r(   r(   r)   rA   ¨   s    zRepositoryServer.__init__c                sn   y‡ fdd„t t| ƒD ƒS  tk
rh   |dkrPtˆ ƒdkrPt| dd… }n‚ ‡ fdd„t |ƒD ƒS X dS )z5Translate from positional protocol to named protocol.c                s   i | ]\}}ˆ | |“qS r(   r(   )r6   ÚposÚname)Úargvr(   r)   rf   ·   s    z8RepositoryServer.positional_to_named.<locals>.<dictcomp>ra   é   Nc                s   i | ]\}}ˆ | |“qS r(   r(   )r6   rp   rq   )rr   r(   r)   rf   ¾   s    )Ú	enumerateÚ	compatMapÚ
IndexErrorr    )rB   Úmethodrr   Úmappingr(   )rr   r)   Úpositional_to_named´   s    z$RepositoryServer.positional_to_namedc                s$   t tj|ƒjƒ‰ ‡ ‡fdd„ˆD ƒS )zWRemove unknown named parameters from call, because client did (implicitly) say it's ok.c                s   i | ]}|ˆ krˆ| |“qS r(   r(   )r6   rq   )ÚknownÚkwargsr(   r)   rf   Ã   s    z0RepositoryServer.filter_args.<locals>.<dictcomp>)ÚsetÚinspectÚ	signatureÚ
parameters)rB   Úfr{   r(   )rz   r{   r)   Úfilter_argsÀ   s    zRepositoryServer.filter_argsc          "   C   s  t jjƒ }t jjƒ }t jjƒ }tj|tjƒ}tj|tj|tjB ƒ tj|tjƒ}tj|tj|tj @ ƒ tj|tjƒ}tj|tj|tj @ ƒ t	dƒ}�xvt
j
|gg g dƒ\}}}|�rútj|tƒ}	|	sö| jd k	rÞ| jjƒ  nt|djtƒjƒ ƒ d S |j|	ƒ �xö|D �]ì}
t|
tƒ�r@d}|
t }|
t jƒ }t|
t ƒ}n^t|
tƒ�r€t|
ƒdk�r€d}|
\}}}}|jƒ }| j||ƒ}n| jd k	�r–| jjƒ  ttƒ‚yb|| jk�r´t |ƒ‚yt!| |ƒ}W n" t"k
�rä   t!| j|ƒ}Y nX | j#||ƒ}|f |Ž}W �nº t$k
�rº } �zš|�rt%j&|j'|ƒ}t%j(t j)ƒ Ž }d}t|t*ƒ�rX|j+ƒ g}|j%}t|t,j-t,j.t/fƒ�rpnt0j1dj2|ƒƒ y2t3j4t|d|j'j5d	|j6d
|d|d|dt7ƒ iƒ}W nN t8k
�r    t3j4t|d|j'j5d	dd„ |j6D ƒd
|d|d|dt7ƒ iƒ}Y nX t||ƒ nœt|t,j-t,j.t/fƒ�r&ndt|t*ƒ�rP|j%�r@t0j9nt0j:}|j+ƒ }nt0j9}d|j'j5 }dt%j;ƒ t7ƒ f }t0j<|ƒ t0j=||ƒ d}t|t3j4d||j'j5|fƒƒ W Y d d }~X n:X |�rÜt|t3j4t|t>|iƒƒ nt|t3j4d|d |fƒƒ �qW |rš| jjƒ  d S qšW d S )NZserveré
   z<Borg {}: Got connection close before repository was opened.
Trs   FÚ
s   exception_classs   exception_argss   exception_fulls   exception_shorts   exception_traces   sysinfoc             S   s$   g | ]}t |tttfƒr|nd ‘qS )N)Ú
isinstanceÚstrÚbytesÚint)r6   Úxr(   r(   r)   r7     s   z*RepositoryServer.serve.<locals>.<listcomp>z%s Exception in RPC callz%s
%sz3Remote Exception (see remote log for the traceback)r   )?ÚsysÚstdinÚfilenoÚstdoutÚfcntlÚF_GETFLÚF_SETFLr!   Ú
O_NONBLOCKr   ÚselectÚreadÚBUFSIZErk   Úcloser*   Úformatr   ÚencodeÚfeedr„   ÚdictÚMSGIDÚMSGr<   rg   ÚARGSÚtupler    ry   r3   Úrpc_methodsr2   ÚgetattrÚAttributeErrorr�   ÚBaseExceptionÚ	tracebackÚformat_exception_onlyrC   Úformat_exceptionÚexc_infor   Úget_messager   ÚDoesNotExistÚAlreadyExistsr1   ÚloggingÚdebugr?   r   Úpackbr,   Úargsr   Ú	TypeErrorÚERRORÚDEBUGÚ
format_excÚerrorÚlogÚRESULT)rB   Ústdin_fdÚ	stdout_fdÚ	stderr_fdZflÚunpackerÚrÚwZesr&   ÚunpackedÚ
dictFormatÚmsgidrw   r«   Ú_r€   ÚresÚeZex_shortZex_fullZex_traceÚmsgZtb_log_levelÚtbÚexcr(   r(   r)   ÚserveÅ   s¶    








.
zRepositoryServer.servec             C   sZ   |t krt S t|tƒrL|d | _tjtjdƒjƒ}tdd|d� t	j
dƒ nt| _dtiS )Ns   client_versionÚ T)Zis_serveÚjsonÚlevelz2Initialized logging system for JSON-based protocolÚserver_version)ÚRPC_PROTOCOL_VERSIONr„   r˜   ro   r¨   ZgetLevelNameÚ	getLoggerrÅ   r   Úloggerr©   ÚBORG_VERSION)rB   rK   rÅ   r(   r(   r)   r`   6  s    

zRepositoryServer.negotiatec             C   s¶   t |tƒrtj|ƒ}|jdƒr8tjjtƒ |dd … ƒ}nr|jdƒr\tjjtƒ |dd … ƒ}nN|jdƒr|tjj|dd … ƒ}n.|jdƒr”tjj|ƒ}n|jdƒrª|dd … }tjj	|ƒS )	Nz/~/r:   z~/r   z/~r   ú~z/./)
r„   r†   r!   ÚfsdecodeÚ
startswithrL   r?   r   Ú
expanduserÚrealpath)rB   rL   r(   r(   r)   Ú_resolve_pathG  s    






zRepositoryServer._resolve_pathFNTc          
   C   sì   t jd|ƒ | j|ƒ}t jd|ƒ tjj|dƒ}| jrpx8| jD ]&}	tjjtjj|	ƒdƒ}
|j|
ƒr>P q>W t	|ƒ‚| j
r®x6| j
D ]$}tjjtjj|ƒdƒ}||kr~P q~W t	|ƒ‚| rº| jp¼|}t|||||| j||d�| _| jjƒ  | jjS )NzResolving repository path %rzResolved repository path to %rrÃ   )rN   rO   rQ   rn   rP   Úmake_parent_dirs)r¨   r©   rÐ   r!   rL   r?   rl   rÏ   rÍ   r1   rm   rQ   r   rn   rk   Ú	__enter__rI   )rB   rL   rM   rN   rO   rP   rQ   rÑ   Zpath_with_sepZrestrict_to_pathZrestrict_to_path_with_sepZrestrict_to_repositoryZrestrict_to_repository_with_sepr(   r(   r)   ra   W  s0    




zRepositoryServer.openc             C   s¬   |j ƒ }d}d}|dkr$tj|ƒ‚n„|dkr8tj|ƒ‚np|dkrLtj|ƒ‚n\|dkr^t|ƒ‚nJ|dkrptdƒ‚n8|d	kr†tj||ƒ‚n"|d
kr˜t|ƒ‚n|dkr¨dd  d S )Nztest stringztest string2r¦   r§   ÚCheckNeededr	   r1   ZfooÚObjectNotFoundr2   Zdivider   )	r<   r   r¦   r§   rÓ   r	   r1   rÔ   r2   )rB   ZkindÚs1Ús2r(   r(   r)   rj   z  s&    


z!RepositoryServer.inject_exception)rX   rT   rU   r\   rW   r[   rY   ri   r`   ra   rZ   rV   r]   r^   r_   rb   rc   rj   )FNTNFF)r,   r-   r.   r�   rA   ry   r�   rÂ   r`   rÐ   ra   rj   r(   r(   r(   r)   rh   ’   s6                    q 
"rh   c               @   s   e Zd Zdd„ Zdd„ ZdS )ÚSleepingBandwidthLimiterc             C   s0   |r&t |t ƒ| _tjƒ | _| j| _nd | _d S )N)r‡   ÚRATELIMIT_PERIODÚ	ratelimitr#   Ú	monotonicÚratelimit_lastÚratelimit_quota)rB   rG   r(   r(   r)   rA   ‘  s
    

z!SleepingBandwidthLimiter.__init__c             C   sÊ   | j r¦tjƒ }| jt |krN|  j| j 7  _| jd| j  krHd| j  | _|| _| jdkrŠ| jt | }tj|ƒ |  j| j 7  _tjƒ | _t|ƒ| jkr¦|d | j… }tj	||ƒ}| j rÆ|  j|8  _|S )Nr   r   )
rÙ   r#   rÚ   rÛ   rØ   rÜ   r$   r    r!   r"   )rB   r%   Úto_sendZnowZtosleepÚwrittenr(   r(   r)   r"   ™  s$    


zSleepingBandwidthLimiter.writeN)r,   r-   r.   rA   r"   r(   r(   r(   r)   r×   �  s   r×   c                s   ‡ ‡fdd„}|S )a~  Check version requirements and use self.call to do the remote method call.

    <since> specifies the version in which borg introduced this method,
    calling this method when connected to an older version will fail without transmiting
    anything to the server.

    Further kwargs can be used to encode version specific restrictions.
    If a previous hardcoded behaviour is parameterized in a version, this allows calls that
    use the previously hardcoded behaviour to pass through and generates an error if another
    behaviour is requested by the client.

    e.g. when 'append_only' was introduced in 1.0.7 the previous behaviour was what now is append_only=False.
    Thus @api(..., append_only={'since': parse_version('1.0.7'), 'previously': False}) allows calls
    with append_only=False for all version but rejects calls using append_only=True on versions older than 1.0.7.
    c                s   t jˆ ƒ‡ ‡‡fdd„ƒ}|S )Nc       
         s   t jˆ ƒ}|j| f|ž|Ž}i }i }xh|jjƒ D ]Z\}}|dkrBq0||jkrt|dkrd|j| ||< qŠ|j| ||< q0|j|jk	r0|j||< q0W | jˆk rª| j	ˆ j
tˆƒƒ‚xbˆjƒ D ]V\}}	|	d | jkrÌq´d|	kræ|| |	d kræq´| j	djˆ j
||| ƒt|	d ƒƒ‚q´W | jˆ j
|f|ŽS )NrB   ÚwaitÚsinceÚ
previouslyz{0} {1}={2!s})r}   r~   Zbindr   ÚitemsZ	argumentsÚdefaultÚemptyrÆ   ÚRPCServerOutdatedr,   r   r•   Úcall)
rB   r«   r{   ZsigZ
bound_argsZnamedZextrarq   ZparamZrestriction)r€   Úkwargs_decoratorrà   r(   r)   Údo_rpc¿  s.    


z&api.<locals>.decorator.<locals>.do_rpc)Ú	functoolsÚwraps)r€   rè   )rç   rà   )r€   r)   Ú	decorator¾  s    zapi.<locals>.decoratorr(   )rà   rç   rë   r(   )rç   rà   r)   Úapi®  s    !rì   c               @   s0  e Zd Zg ZG dd„ deƒZG dd„ deƒZdZdMdd	„Z	d
d„ Z
dd„ Zdd„ Zdd„ Zedd„ ƒZdd„ Zdd„ Zdd„ Zdd„ ZdNdd„Zeedƒedƒdd œed!ƒdd œd"�dOd#d$„ƒZeedƒd%�dPd&d'„ƒZeedƒd%�dQd(d)„ƒZeedƒd%�d*d+„ ƒZeedƒd%�d,d-„ ƒZeedƒd%�d.d/„ ƒZeedƒd%�dRd0d1„ƒZeed2ƒd%�dSd3d4„ƒZd5d6„ ZdTd7d8„Z eedƒd%�dUd9d:„ƒZ!eedƒd%�dVd;d<„ƒZ"eedƒd%�d=d>„ ƒZ#eedƒd%�d?d@„ ƒZ$eedƒd%�dAdB„ ƒZ%eedƒd%�dCdD„ ƒZ&eedƒd%�dEdF„ ƒZ'dGdH„ Z(dWdIdJ„Z)dKdL„ Z*dS )XÚRemoteRepositoryc               @   sL   e Zd Zdd„ Zdd„ Zedd„ ƒZedd„ ƒZed	d
„ ƒZedd„ ƒZ	dS )zRemoteRepository.RPCErrorc             C   s
   || _ d S )N)r¹   )rB   r¹   r(   r(   r)   rA   æ  s    z"RemoteRepository.RPCError.__init__c             C   s(   d| j krdj| j d ƒjƒ S | jS d S )Ns   exception_shortó   
)r¹   r?   r<   Úexception_class)rB   r(   r(   r)   r¥   ë  s    
z%RemoteRepository.RPCError.get_messagec             C   s   | j jddƒS )Ns   exception_traceT)r¹   r[   )rB   r(   r(   r)   r¡   ñ  s    z#RemoteRepository.RPCError.tracebackc             C   s   | j d jƒ S )Ns   exception_class)r¹   r<   )rB   r(   r(   r)   rï   õ  s    z)RemoteRepository.RPCError.exception_classc             C   s.   d| j krdj| j d ƒjƒ S | jƒ d S d S )Ns   exception_fullrî   z4
Remote Exception (see remote log for the traceback))r¹   r?   r<   r¥   )rB   r(   r(   r)   Úexception_fullù  s    
z(RemoteRepository.RPCError.exception_fullc             C   s    d| j kr| j d jƒ S dS d S )Ns   sysinforÃ   )r¹   r<   )rB   r(   r(   r)   r      s    
z!RemoteRepository.RPCError.sysinfoN)
r,   r-   r.   rA   r¥   Úpropertyr¡   rï   rð   r   r(   r(   r(   r)   ÚRPCErrorå  s   rò   c               @   s(   e Zd ZdZedd„ ƒZedd„ ƒZdS )z"RemoteRepository.RPCServerOutdatedz2Borg server is too old for {}. Required version {}c             C   s
   | j d S )Nr   )r«   )rB   r(   r(   r)   rw   
  s    z)RemoteRepository.RPCServerOutdated.methodc             C   s
   | j d S )Nr   )r«   )rB   r(   r(   r)   Úrequired_version  s    z3RemoteRepository.RPCServerOutdated.required_versionN)r,   r-   r.   r/   rñ   rw   ró   r(   r(   r(   r)   rå     s   rå   FNTc	                sÖ  | ˆ_ ˆ_g ˆ_dˆ_dˆ_dˆ_dˆ_dˆ_i ˆ_t	ƒ ˆ_
i ˆ_i ˆ_d ˆ_t|rf|jrf|jd ndƒˆ_tdƒˆ_tdƒˆ_d ˆ_|ˆ_|jdk}	t|	 d�}
ˆj||	ƒ}|	sÂˆj|ƒ| }tjd|ƒ t|dttt|
d	�ˆ_ˆjjj ƒ ˆ_!ˆjj"j ƒ ˆ_#ˆjj$j ƒ ˆ_%t&j&ˆj!t&j't&j&ˆj!t&j(ƒt)j*B ƒ t&j&ˆj#t&j't&j&ˆj#t&j(ƒt)j*B ƒ t&j&ˆj%t&j't&j&ˆj%t&j(ƒt)j*B ƒ ˆj#ˆj%gˆ_+ˆj!ˆj#ˆj%gˆ_,�yyˆj-d
ddt.iiƒ}W n  t/k
�rÖ   t0dƒd ‚Y nX |t1k�rêdˆ_2n4t3|t4ƒ�rd|k�rdˆ_2|d ˆ_nt5d| ƒ‚‡ ‡‡‡‡‡‡fdd„}ˆj2�rF|ƒ  nhy
|ƒ  W n\ ˆj6k
�r¬ } z<|j7dk�rt‚ d}t8j$j9|ƒ tdƒˆ_dt:d< |ƒ  W Y d d }~X nX W n  t5k
�rÐ   ˆj;ƒ  ‚ Y nX d S )Nr   ó    i   Zclientz1.0.8Z__testsuite__)ÚsystemzSSH command line: %s)ÚbufsizerŠ   rŒ   ÚstderrÚenvr`   rK   s   client_versionzIs borg working on the server?Fs   server_versionTz8Server insisted on using unsupported protocol version %sc            	      s"   ˆj ˆjjˆˆˆˆˆ ˆd�ˆ_d S )N)rL   rM   rN   rO   rP   rQ   rÑ   )ra   ÚlocationrL   rI   r(   )rQ   rM   rP   rO   rN   rÑ   rB   r(   r)   Údo_openI  s    z*RemoteRepository.__init__.<locals>.do_openr¬   ao  Please note:
If you see a TypeError complaining about the number of positional arguments
given to open(), you can ignore it if it comes from a borg version < 1.0.7.
This TypeError is a cosmetic side effect of the compatibility code borg
clients >= 1.0.7 have to support older borg servers.
This problem will go away as soon as the server has been upgraded to 1.0.7+.
z1.0.6rL   rM   rN   rO   ra   )rL   rM   rN   rO   )<rù   Z	_locationÚpreload_idsr»   Úrx_bytesÚtx_bytesrÝ   Ústderr_receivedÚchunkid_to_msgidsr|   Úignore_responsesÚ	responsesÚasync_responsesÚshutdown_timer×   Zremote_ratelimitrÙ   r   r¶   r   rÆ   ÚpÚ_argsÚhostr   Úborg_cmdÚssh_cmdrÉ   r©   r   r   rŠ   r‹   r³   rŒ   r´   r÷   rµ   r�   r�   rŽ   r!   r�   Úr_fdsÚx_fdsræ   rÊ   r+   r0   rÇ   rº   r„   r˜   Ú	Exceptionrò   rï   r‰   r"   ru   r”   )rB   rù   rM   rP   rN   rO   rQ   rÑ   r«   Útestingrø   r  Úversionrú   Úerrr¿   r(   )rQ   rM   rP   rO   rN   rÑ   rB   r)   rA     sx    


$$$


zRemoteRepository.__init__c             C   s>   t | jƒr tjdt | jƒf ƒ | jr:| jƒ  ds:tdƒ‚d S )Nz2still %d cached responses left in RemoteRepositoryFz&cleanup happened in Repository.__del__)r    r  r¨   r©   r  r”   ÚAssertionError)rB   r(   r(   r)   Ú__del__i  s
    
zRemoteRepository.__del__c             C   s   d| j j| jjƒ f S )Nz<%s %s>)rC   r,   rù   Zcanonical_path)rB   r(   r(   r)   Ú__repr__p  s    zRemoteRepository.__repr__c             C   s   | S )Nr(   )rB   r(   r(   r)   rÒ   s  s    zRemoteRepository.__enter__c             C   sP   z"|d k	r t jƒ d | _| jƒ  W d tjdt| jƒt| jƒ| j	ƒ | j
ƒ  X d S )Né   zDRemoteRepository: %s bytes sent, %s bytes received, %d messages sent)r#   rÚ   r  rV   rÉ   r©   r   rý   rü   r»   r”   )rB   Úexc_typeÚexc_valÚexc_tbr(   r(   r)   Ú__exit__v  s    zRemoteRepository.__exit__c             C   s
   t | jƒS )N)r
   rI   )rB   r(   r(   r)   Úid_strƒ  s    zRemoteRepository.id_strc             C   sX  g }|dk	rî|j d|j ƒ tjƒ }|jtjƒr<|j dƒ n^|jtjƒrT|j dƒ nF|jtjƒrbn8|jtjƒrz|j dƒ n |jtj	ƒr’|j dƒ nt
dƒ‚x4|jD ]*}d|kr¶d	| }d
|kr¢|j d| ƒ q¢W d|krî|jrî|j d|j ƒ g }tƒ �s|j dƒ |�r&|tjdddg | | j S |j�p:tjjddƒ}t|ƒ}||dg | S dS )z return a borg serve command lineNz--umask=%03oz--debugz--infoz--errorz
--criticalz log level missing, fix this codeÚ.zborg.debug.rk   z--debug-topic=%srn   z--storage-quota=%szBORG_HOSTNAME_IS_UNIQUE=noz-mzborg.archiverrÂ   ZBORG_REMOTE_PATHÚborg)ÚappendÚumaskr¨   rÈ   ZisEnabledForr®   ÚINFOZWARNINGr­   ÚCRITICALÚ
ValueErrorZdebug_topicsrn   r   r‰   Ú
executableÚextra_test_argsÚremote_pathr!   Úenvironr[   r   )rB   r«   r  ZoptsZroot_loggerZtopicZenv_varsr!  r(   r(   r)   r  ‡  s<    
zRemoteRepository.borg_cmdc             C   sj   | j jptjjddƒ}tj|ƒ}|jr8|dt|jƒg7 }|j	rV|j
d|j	|jf ƒ n|j
d|j ƒ |S )zEreturn a ssh command line that can be prefixed to a borg command lineZBORG_RSHZsshz-pz%s@%sz%s)r  Úrshr!   r"  r[   ÚshlexÚsplitZportr…   Úuserr  r  )rB   rù   r#  r«   r(   r(   r)   r  ¸  s    
zRemoteRepository.ssh_cmdc                s   ‡ fdd„t | D ƒS )Nc                s   g | ]}ˆ | ‘qS r(   r(   )r6   rq   )r{   r(   r)   r7   Å  s    z8RemoteRepository.named_to_positional.<locals>.<listcomp>)ru   )rB   rw   r{   r(   )r{   r)   Únamed_to_positionalÄ  s    z$RemoteRepository.named_to_positionalc             K   s"   x| j ||gf|ŽD ]}|S W d S )N)Ú	call_many)rB   Úcmdr«   ÚkwÚrespr(   r(   r)   ræ   Ç  s    zRemoteRepository.callc             #   sŽ  | r|dkrd S ‡ fdd„}‡ fdd„}t |ƒ}g }�x>|sD|�rvˆ jrttjƒ ˆ jkrttjdt|ƒtˆ jƒƒ d S xj|rÞyJˆ jj	|d ƒ}	|j	dƒ d|	kr¨||	ƒ n|	t
 V  | rÂ| rÂd S W qv tk
rÚ   P Y qvX qvW |dk�rNxbyˆ jjƒ \}
}	W n, tk
�r*   |�r"ˆ j�r"P nd S Y qìX d|	k�r@||	ƒ qì|	t
 V  qìW ˆ j�sr|�sdˆ j�r|t|ƒtk �r|ˆ jg}ng }tjˆ j|ˆ jd	ƒ\}}}|�r¨td
ƒ‚�x¸|D �]®}|ˆ jk�rÄtj|tƒ}|�sÚtƒ ‚ˆ  jt|ƒ7  _ˆ jj|ƒ xÈˆ jD ]¾}	t|	tƒ�r|	t  }
nPt|	t!ƒ�rbt|	ƒdk�rb|	\}}
}}|�rTt |
d|i}	nt |
t
|i}	nt"|ƒ‚|
ˆ jk�r²ˆ jj#|
ƒ d|	k�r˜|	ˆ j|
< n|	t
 d k	�r¼|	ˆ j|
< n
|	ˆ j|
< �q W nš|ˆ j$k�r°tj|dƒ}|�sètƒ ‚ˆ  jt|ƒ7  _ˆ j%�rˆ j%| }dˆ _%|j&dd�}|�r@|d j'dƒ �r@|j	ƒ ˆ _%x|D ]}t(|j)dƒƒ �qFW �q°W |r:�x˜ˆ j �r|�s„ˆ j�rt|ƒtk �r|�rr|�rÞ|dk�s°t*dƒ‚|d d ˆ j+k�rr|j,||j	dƒd ƒƒ n”|j	dƒ}|dk�r|d ˆ j+k�r|j,||d ƒƒ n\ˆ  j-d	7  _-|j,ˆ j-ƒ ˆ j.�rTt/j0t ˆ j-t1|t2|iƒˆ _nt/j0d	ˆ j-|ˆ j3||ƒfƒˆ _ˆ j �rlˆ j�rlˆ jj	dƒ}d|i}ˆ  j-d	7  _-ˆ j+j4|g ƒj,ˆ j-ƒ ˆ j.�ràt/j0t ˆ j-t1dt2|iƒˆ _nt/j0d	ˆ j-dˆ j3d|ƒfƒˆ _�qlW ˆ jr:y4ˆ j5j6ˆ jˆ jƒ}ˆ  j7|7  _7ˆ j|d … ˆ _W q: t8k
�rr } z|j9t9j:k�rb‚ W Y d d }~X q:X q:W ˆ  jt;|ƒO  _d S )Nr  c                s&   ˆ j |  jdƒ}ˆ j |  s"ˆ j | = |S )Nr   )rÿ   Úpop)Zchunkidr»   )rB   r(   r)   Úpop_preload_msgidÏ  s    
z5RemoteRepository.call_many.<locals>.pop_preload_msgidc                s|  | d j ƒ }d| k}| jdƒ}|dkr8tjˆ jjƒ‚�n@|dkrRtjˆ jjƒ‚�n&|dkrltjˆ jjƒ‚�n|dkr”|r‚tdƒ‚nt|d j ƒ ƒ‚nä|d	krÀ|r¬tj	dƒ‚ntj	|d j ƒ ƒ‚n¸|d
krè|rÖt
dƒ‚nt
|d j ƒ ƒ‚n�|dk�rtj|d j ƒ ƒ‚nr|dk�rB|�r(tjdˆ jjƒ‚ntj|d j ƒ ˆ jjƒ‚n6|dk�rn|�r\tdƒ‚nt|d j ƒ ƒ‚n
ˆ j| ƒ‚d S )Ns   exception_classs   exception_argsr¦   r§   rÓ   r	   z(not available)r   ÚAtticRepositoryr1   z	(unknown)ÚParentPathDoesNotExistrÔ   r2   )r<   r[   r   r¦   rù   Z	processedr§   rÓ   r	   r.  r1   r/  rÔ   r2   rò   )r¹   r°   Z
old_serverr«   )rB   r(   r)   Úhandle_errorÕ  s@    






z0RemoteRepository.call_many.<locals>.handle_errorzPshutdown_time reached, shutting down with %d waiting_for and %d async_responses.r   s   exception_classr   zFD exception occurredrs   i €  rô   T)Úkeependsó   rî   zutf-8r[   z&is_preload is only supported for 'get'rI   éÿÿÿÿ)r2  rî   )<rY   r  r#   rÚ   rÉ   r©   r    r  r  r,  r²   ÚKeyErrorÚpopitemr   rÝ   rû   ÚMAX_INFLIGHTr³   r‘   r	  r
  r  r´   r!   r’   r“   r+   rü   r¶   r—   r„   r˜   r™   rœ   r4   Úremoverµ   rþ   Ú
splitlinesÚendswithÚhandle_remote_liner<   r  rÿ   r  r»   rº   r   rª   rš   r›   r'  Ú
setdefaultrÙ   r"   rý   ÚOSErrorÚerrnoZEAGAINr|   )rB   r)  Úcallsrß   Úis_preloadedÚ
async_waitr-  r0  Zwaiting_forr¹   r»   Zw_fdsr·   r¸   rˆ   r%   r&   r¼   r°   r½   ÚlinesÚliner«   Zchunk_idrÞ   r¾   r(   )rB   r)   r(  Ë  sÖ    )






$





*
$zRemoteRepository.call_manyz1.0.0z1.0.7)rà   rá   z1.1.9)rà   rQ   rÑ   c             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rL   rM   rN   rO   rP   rQ   rÑ   r(   r(   r)   ra   �  s    zRemoteRepository.open)rà   c             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rE   rF   r(   r(   r)   rT   ˆ  s    zRemoteRepository.checkc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rF   r(   r(   r)   rU   Œ  s    zRemoteRepository.commitc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   r(   r(   r)   rV   �  s    zRemoteRepository.rollbackc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   r(   r(   r)   rW   ”  s    zRemoteRepository.destroyc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   r(   r(   r)   rX   ˜  s    zRemoteRepository.__len__c             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rG   rH   r(   r(   r)   rY   œ  s    zRemoteRepository.listz1.1.0b3c             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rG   rH   r(   r(   r)   ri      s    zRemoteRepository.scanc             C   s   x| j |gƒD ]}|S W d S )N)Úget_many)rB   rI   r+  r(   r(   r)   r[   ¤  s    zRemoteRepository.getc             c   s.   x(| j ddd„ |D ƒ|d�D ]
}|V  qW d S )Nr[   c             S   s   g | ]}d |i‘qS )rI   r(   )r6   rI   r(   r(   r)   r7   ©  s    z-RemoteRepository.get_many.<locals>.<listcomp>)r?  )r(  )rB   Úidsr?  r+  r(   r(   r)   rC  ¨  s     zRemoteRepository.get_manyc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rI   r&   rß   r(   r(   r)   rZ   ¬  s    zRemoteRepository.putc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rI   rß   r(   r(   r)   r\   °  s    zRemoteRepository.deletec             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rJ   r(   r(   r)   r]   ´  s    zRemoteRepository.save_keyc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   r(   r(   r)   r^   ¸  s    zRemoteRepository.load_keyc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   r(   r(   r)   rb   ¼  s    zRemoteRepository.get_free_noncec             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   rR   rS   r(   r(   r)   rc   À  s    z)RemoteRepository.commit_nonce_reservationc             C   s   dS )z;actual remoting is done via self.call in the @api decoratorNr(   )rB   r(   r(   r)   r_   Ä  s    zRemoteRepository.break_lockc             C   s2   | j r.| j jjƒ  | j jjƒ  | j jƒ  d | _ d S )N)r  rŠ   r”   rŒ   rß   )rB   r(   r(   r)   r”   È  s
    
zRemoteRepository.closec             C   s"   x| j dg d|d�D ]}|S W d S )Nr  T)r>  rß   r@  )r(  )rB   rß   r+  r(   r(   r)   Úasync_responseÏ  s    zRemoteRepository.async_responsec             C   s   |  j |7  _ d S )N)rû   )rB   rD  r(   r(   r)   ÚpreloadÓ  s    zRemoteRepository.preload)FFNTFFN)TFT)FNTFFF)FF)F)NN)NN)F)T)T)T)+r,   r-   r.   r   r  rò   r   rå   rº   rA   r  r  rÒ   r  rñ   r  r  r  r'  ræ   r(  rì   r   ra   rT   rU   rV   rW   rX   rY   ri   r[   rC  rZ   r\   r]   r^   rb   rc   r_   r”   rE  rF  r(   r(   r(   r)   rí   â  s^   " 
S1
 7 

rí   c             C   s  | j dƒst‚| jdƒ�rbtj| ƒ}|d dkrFtjd|d | ƒ d	S |d dkrÔtt|d
 tj	ƒ}t
|tƒsrt‚tj|d ƒ}d|d  |d< tjdƒjrÀ||jƒ krÀtjjtj|ƒd ƒ n|j|d|d ƒ nŒ|d jdƒ�rtjdƒ}|jƒ tjk�rtjdƒj�r>d|k�r&d|d  |d< tjjtj|ƒd ƒ n"d|k�rtjjd|d  d ƒ nª| jdƒ�rÔ| jddƒ\}}}tt|tj	ƒ}|jdƒ�r¬tj||jƒ ƒ n&|jddƒ\}}tj|ƒj||jƒ ƒ n8tjdƒj�rütjdƒjd| jƒ  ƒ ntjjd|  ƒ d	S )zv
    Handle a remote log line.

    This function is remarkably complex because it handles multiple wire formats.
    úrƒ   ú{ÚtypeÚprogress_messageÚprogress_percentÚlog_messagez3Dropped remote log message with unknown type %r: %sNZ	levelnamerq   zRemote: Úmessager  z%sZ	progress_zborg.output.progressz$LOG r8   r   zRemote:r   rÃ   )rG  rƒ   )rJ  rK  rL  )r9  r  rÍ   rÄ   ÚloadsrÉ   Zwarningrž   r¨   r  r„   r‡   rÈ   ZgetEffectiveLevelr‰   r÷   r"   Údumpsr±   r  r%  ÚrstripÚstrip)rB  r¿   rÅ   Ztarget_loggerZprogress_loggerr¼   Zlognamer(   r(   r)   r:  ×  sB    



r:  c               @   sL   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zddd„Z	dd„ Z
dS )ÚRepositoryNoCacheaR  A not caching Repository wrapper, passes through to repository.

    Just to have same API (including the context manager) as RepositoryCache.

    *transform* is a callable taking two arguments, key and raw repository data.
    The return value is returned from get()/get_many(). By default, the raw
    repository data is returned.
    Nc             C   s   || _ |pdd„ | _d S )Nc             S   s   |S )Nr(   )Úkeyr&   r(   r(   r)   Ú<lambda>,  s    z,RepositoryNoCache.__init__.<locals>.<lambda>)rk   Ú	transform)rB   rk   rU  r(   r(   r)   rA   *  s    zRepositoryNoCache.__init__c             C   s   d S )Nr(   )rB   r(   r(   r)   r”   .  s    zRepositoryNoCache.closec             C   s   | S )Nr(   )rB   r(   r(   r)   rÒ   1  s    zRepositoryNoCache.__enter__c             C   s   | j ƒ  d S )N)r”   )rB   r  r  r  r(   r(   r)   r  4  s    zRepositoryNoCache.__exit__c             C   s   t | j|gdd�ƒS )NF)Úcache)ÚnextrC  )rB   rS  r(   r(   r)   r[   7  s    zRepositoryNoCache.getTc             c   s2   x,t || jj|ƒƒD ]\}}| j||ƒV  qW d S )N)Úziprk   rC  rU  )rB   ÚkeysrV  rS  r&   r(   r(   r)   rC  :  s    zRepositoryNoCache.get_manyc             C   s   d S )Nr(   )rB   r(   r(   r)   Úlog_instrumentation>  s    z%RepositoryNoCache.log_instrumentation)N)T)r,   r-   r.   r/   rA   r”   rÒ   r  r[   rC  rZ  r(   r(   r(   r)   rR  !  s   

rR  c                   s\   e Zd ZdZd‡ fdd„	Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
ddd„Z‡  ZS )ÚRepositoryCacheaf  
    A caching Repository wrapper.

    Caches Repository GET operations locally.

    *pack* and *unpack* complement *transform* of the base class.
    *pack* receives the output of *transform* and should return bytes,
    which are stored in the cache. *unpack* receives these bytes and
    should return the initial data (as returned by *transform*).
    Nc                sv   t ƒ j||ƒ |pdd„ | _|p&dd„ | _tƒ | _tjdd�| _| j	ƒ  d| _
d| _d| _d| _d| _d| _d| _d S )Nc             S   s   | S )Nr(   )r&   r(   r(   r)   rT  P  s    z*RepositoryCache.__init__.<locals>.<lambda>c             S   s   | S )Nr(   )r&   r(   r(   r)   rT  Q  s    zborg-cache-)Úprefixr   g        )r@   rA   ÚpackÚunpackr|   rV  ÚtempfileZmkdtempÚbasedirÚquery_size_limitÚsizeÚhitsÚmissesÚslow_missesÚslow_latÚ	evictionsÚenospc)rB   rk   r]  r^  rU  )rC   r(   r)   rA   N  s    zRepositoryCache.__init__c             C   s0   t j| jƒ}|j|j }tt|d dƒƒ| _d S )Ng      Ð?r   é   l        )r!   Ústatvfsr`  Úf_bavailÚf_frsizer‡   ÚminÚ
size_limit)rB   Zstat_fsZavailable_spacer(   r(   r)   ra  ^  s    z RepositoryCache.query_size_limitc             C   s   t jj| jt|ƒƒS )N)r!   rL   r?   r`  r
   )rB   rS  r(   r(   r)   Úkey_filenamec  s    zRepositoryCache.key_filenamec             C   sr   | j ƒ  td| j ƒ}xV| j|krl| jrl| jjƒ }| j|ƒ}|  jtj|ƒj	8  _tj
|ƒ |  jd7  _qW d S )NgÍÌÌÌÌÌì?r   )ra  r‡   rn  rb  rV  r,  ro  r!   ÚstatÚst_sizeÚunlinkrg  )rB   Ztarget_sizerS  Úfiler(   r(   r)   Úbackofff  s    


zRepositoryCache.backoffc       	      C   sî   | j ||ƒ}|s|S | j|ƒ}| j|ƒ}y$t|dƒ�}|j|ƒ W d Q R X W nj tk
r¶ } zNyt|ƒ W n tk
r~   Y nX |jtj	kr¤|  j
d7  _
| jƒ  n‚ W Y d d }~X n4X |  jt|ƒ7  _| jj|ƒ | j| jkrê| jƒ  |S )NÚwbr   )rU  r]  ro  ra   r"   r<  r   ÚFileNotFoundErrorr=  ZENOSPCrh  rt  rb  r    rV  Úaddrn  )	rB   rS  r&   rV  ÚtransformedZpackedrs  r%   Zos_errorr(   r(   r)   Ú	add_entryp  s,    


zRepositoryCache.add_entryc             C   s>   t jdt| jƒt| jƒt| jƒ| j| j| j	| j
| j| jƒ
 d S )NzyRepositoryCache: current items %d, size %s / %s, %d hits, %d misses, %d slow misses (+%.1fs), %d evictions, %d ENOSPC hit)rÉ   r©   r    rV  r   rb  rn  rc  rd  re  rf  rg  rh  )rB   r(   r(   r)   rZ  Š  s    z#RepositoryCache.log_instrumentationc             C   s"   | j ƒ  | jjƒ  tj| jƒ d S )N)rZ  rV  ÚclearÚshutilZrmtreer`  )rB   r(   r(   r)   r”   ‘  s    
zRepositoryCache.closeTc             #   s  ‡ fdd„|D ƒ}t |ˆ jj|ƒƒ}xà|D ]Ø}|ˆ jkrxˆ j|ƒ}t|dƒ�$}ˆ  jd7  _ˆ j|jƒ ƒV  W d Q R X q*xˆ|D ]4\}}	||kr~ˆ j	||	|ƒ}
ˆ  j
d7  _
|
V  P q~W tjƒ }ˆ jj|ƒ}	ˆ  jtjƒ | 7  _ˆ j	||	|ƒ}
ˆ  jd7  _|
V  q*W x|D ]}�qW d S )Nc                s   g | ]}|ˆ j kr|‘qS r(   )rV  )r6   rS  )rB   r(   r)   r7   —  s    z,RepositoryCache.get_many.<locals>.<listcomp>Úrbr   )rX  rk   rC  rV  ro  ra   rc  r^  r’   ry  rd  r#   Zperf_counterr[   rf  re  )rB   rY  rV  Zunknown_keysZrepository_iteratorrS  rs  r%   Zkey_r&   rx  Zt0r¼   r(   )rB   r)   rC  –  s,    




zRepositoryCache.get_many)NNN)T)r,   r-   r.   r/   rA   ra  ro  rt  ry  rZ  r”   rC  rD   r(   r(   )rC   r)   r[  B  s   

r[  F)Údecrypted_cacher]  r^  rU  Úforce_cachec               s„   |r|s|s|rt dƒ‚n@|rZ|‰tjdƒ‰ tƒ ‰‡ ‡fdd„}‡ ‡fdd„}‡fdd„}t| tƒsh|rvt| |||ƒS t| |ƒS d	S )
a¬  
    Return a Repository(No)Cache for *repository*.

    If *decrypted_cache* is a key object, then get and get_many will return a tuple
    (csize, plaintext) instead of the actual data in the repository. The cache will
    store decrypted data, which increases CPU efficiency (by avoiding repeatedly decrypting
    and more importantly MAC and ID checking cached objects).
    Internally, objects are compressed with LZ4.
    z:decrypted_cache and pack/unpack/transform are incompatiblez=I8sc                s&   | \}}ˆj |ƒ}ˆ j|t|ƒƒ| S )N)Úcompressr]  r   )r&   ÚcsizeÚ	decryptedÚ
compressed)Úcache_structÚ
compressorr(   r)   r]  Å  s    
zcache_if_remote.<locals>.packc                sP   t | ƒ} ˆ j| d ˆ j… ƒ\}}| ˆ jd … }|t|ƒkrBtdƒ‚|ˆj|ƒfS )Nz)detected corrupted data in metadata cache)Ú
memoryviewr^  rb  r   r	   Z
decompress)r&   r€  Zchecksumr‚  )rƒ  r„  r(   r)   r^  Ê  s    zcache_if_remote.<locals>.unpackc                s   t |ƒ}ˆ j| |ƒ}||fS )N)r    Zdecrypt)Zid_r&   r€  r�  )rS  r(   r)   rU  Ò  s    z"cache_if_remote.<locals>.transformN)r  ÚstructÚStructr   r„   rí   r[  rR  )rk   r}  r]  r^  rU  r~  r(   )rƒ  r„  rS  r)   Úcache_if_remote³  s    


rˆ  )r   r   r   r   )rE   rF   )rF   )rG   rH   )rI   r&   )rI   )rI   )rJ   )rK   )rL   rM   rN   rO   rP   rQ   )rR   rS   )Ir=  r�   ré   r}   rÄ   r¨   r!   r‘   r$  r{  r†  r‰   r_  r>   r#   r¡   Ú
subprocessr   r   rÃ   r   r  r   Z	constantsZhelpersr   r	   r
   r   r   r   r   r   r   r   r   rÉ   r   r   r   rk   r   r  r   r   Zalgorithms.checksumsr   r,   rÇ   rÊ   r™   rš   r›   r²   r6  rØ   r*   r+   r0   r1   r2   r3   r4   ru   rg   rh   r×   rì   rí   r:  rR  r[  rˆ  r(   r(   r(   r)   Ú<module>   sš   #   4   xJ!q