U
    yh                      @   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	m
Z
mZmZ zd dlZW n ek
r|   Y nX eeZdd Zd
e
e dddZG dd	 d	ZdS )    N)OptionalTextIOUnionc                  C   s   t jddt jt jd} | D ]x}|\}}}}}z,t  |||}|d |d |W   S  tk
r } z|  td|  W 5 d}~X Y qX qt	ddS )a  
    Find a free port and binds a temporary socket to it so that the port can be "reserved" until used.

    .. note:: the returned socket must be closed before using the port,
              otherwise a ``address already in use`` error will happen.
              The socket should be held and closed as close to the
              consumer of the port as possible since otherwise, there
              is a greater chance of race-condition where a different
              process may see the port as being free and take it.

    Returns: a socket binded to the reserved free port

    Usage::

    sock = find_free_port()
    port = sock.getsockname()[1]
    sock.close()
    use_port(port)
    	localhostN)hostportfamilytype)r   r   r   z Socket creation attempt failed: zFailed to create a socket)
socketgetaddrinfo	AF_UNSPECSOCK_STREAMbindlistenOSErrorcloseprintRuntimeError)addrsaddrr   r	   proto_se r   b/var/www/html/venv/lib/python3.8/site-packages/torch/distributed/elastic/rendezvous/etcd_server.pyfind_free_port   s"       


"r   data_dirc                 C   sL   | r*|   d kr*td |   |   |rHtd| tj|dd d S )Nzstopping etcd serverzdeleting etcd data dir: %sTignore_errors)pollloggerinfo	terminatewaitshutilrmtree)
subprocessr   r   r   r   	stop_etcdB   s    
r)   c                   @   s   e Zd ZdZdee dddZejdddZ	e
dd	d
ZedddZedddZde
e
ee
edf ddddZd ee
ee
edf ddddZdd Zd!e
ddddZddddZdS )"
EtcdServera  
    .. note:: tested on etcd server v3.4.3.

    Starts and stops a local standalone etcd server on a random free
    port. Useful for single node, multi-worker launches or testing,
    where a sidecar etcd server is more convenient than having to
    separately setup an etcd server.

    This class registers a termination handler to shutdown the etcd
    subprocess on exit. This termination handler is NOT a substitute for
    calling the ``stop()`` method.

    The following fallback mechanism is used to find the etcd binary:

    1. Uses env var TORCHELASTIC_ETCD_BINARY_PATH
    2. Uses ``<this file root>/bin/etcd`` if one exists
    3. Uses ``etcd`` from ``PATH``

    Usage
    ::

     server = EtcdServer("/usr/bin/etcd", 2379, "/tmp/default.etcd")
     server.start()
     client = server.get_client()
     # use client
     server.stop()

    Args:
        etcd_binary_path: path of etcd server binary (see above for fallback path)
    Nr   c                 C   sp   d| _ d| _tjt}tj|d}tjd|| _	tj
| j	sJd| _	|rR|n
tjdd| _d | _d | _d S )Nr   zbin/etcdZTORCHELASTIC_ETCD_BINARY_PATHetcdZtorchelastic_etcd_data)prefix)_port_hostospathdirname__file__joinenvironget_etcd_binary_pathisfiletempfilemkdtemp_base_data_dirZ	_etcd_cmd
_etcd_proc)selfr   rootZdefault_etcd_binr   r   r   __init__m   s     zEtcdServer.__init__)returnc                 C   s   | j stdn| j S d S )Nz>No etcd server process started. Call etcd_server.start() first)r<   r   r=   r   r   r   _get_etcd_server_process   s
    z#EtcdServer._get_etcd_server_processc                 C   s   | j S )z)Return the port the server is running on.)r.   rA   r   r   r   get_port   s    zEtcdServer.get_portc                 C   s   | j S )z)Return the host the server is running on.)r/   rA   r   r   r   get_host   s    zEtcdServer.get_hostc                 C   s   | j  d| j S )z,Return the etcd server endpoint (host:port).:)r/   r.   rA   r   r   r   get_endpoint   s    zEtcdServer.get_endpoint<      )timeoutnum_retriesstderrr@   c              
   C   s   d}z2t j| jt|}t j|dd | |||W S  tk
r } z@|d7 }t| j	 t
dt| ||krtj| jdd  W 5 d}~X Y qX qtt| j	| j dS )a  
        Start the server, and waits for it to be ready. When this function returns the sever is ready to take requests.

        Args:
            timeout: time (in seconds) to wait for the server to be ready
                before giving up.
            num_retries: number of retries to start the server. Each retry
                will wait for max ``timeout`` before considering it as failed.
            stderr: the standard error file handle. Valid values are
                `subprocess.PIPE`, `subprocess.DEVNULL`, an existing file
                descriptor (a positive integer), an existing file object, and
                `None`.

        Raises:
            TimeoutError: if the server is not ready within the specified timeout
        r   T)exist_ok   z4Failed to start etcd server, got error: %s, retryingr   N)r0   r1   r4   r;   strmakedirs_start	Exceptionr)   r<   r"   warningr&   r'   atexitregister)r=   rI   rJ   rK   Zcurr_retriesr   r   r   r   r   start   s     
 zEtcdServer.start)r   rI   rK   r@   c                 C   s   t  }t  }| d | _| d }td| jdd|dd| j d| j dd| j d| j d	d| j d| g
}t	d
| |
  |
  tj|d|d| _| | d S )NrM    z--enable-v2z
--data-dirz--listen-client-urlszhttp://rE   z--advertise-client-urlsz--listen-peer-urlszStarting etcd server: [%s]T)	close_fdsrK   )r   getsocknamer.   shlexsplitr4   r7   r/   r"   r#   r   r(   Popenr<   _wait_for_ready)r=   r   rI   rK   sockZ	sock_peerZ	peer_portZetcd_cmdr   r   r   rP      s0    zEtcdServer._startc                 C   s   t j| j| jdddS )zNReturn an etcd client object that can be used to make requests to this server./v2
   r   r   version_prefixread_timeout)r,   Clientr/   r.   rA   r   r   r   
get_client   s       zEtcdServer.get_client)rI   r@   c                 C   s   t j| j | jddd}t | }t |k r|   d k	rX|  j}td| zt	
d|j W d S  tk
r   td Y q$X q$tdd S )Nr^      r`   z*Etcd server process exited with the code: zetcd server ready. version: %srM   z.Timed out waiting for etcd server to be ready!)r,   rc   r/   r.   timerB   r!   
returncoder   r"   r#   versionrQ   sleepTimeoutError)r=   rI   clientZmax_timeexitcoder   r   r   r\      s&       
zEtcdServer._wait_for_readyc                 C   s   t d t| j| j dS )zGStop the server and cleans up auto generated resources (e.g. data dir).zEtcdServer stop method calledN)r"   r#   r)   r<   r;   rA   r   r   r   stop   s    
zEtcdServer.stop)N)rG   rH   N)rG   N)rG   )__name__
__module____qualname____doc__r   rN   r?   r(   r[   rB   intrC   rD   rF   r   r   rU   rP   rd   r\   rm   r   r   r   r   r*   M   s4      (      r*   )N)rS   loggingr0   rY   r&   r
   r(   r9   rf   typingr   r   r   r,   ModuleNotFoundError	getLoggerrn   r"   r   rN   r)   r*   r   r   r   r   <module>	   s"   
%