o
    iG                     @   s6   d Z ddlZddlZddlZddlZG dd dZdS )zn
Control Interface Command Handlers

Provides handlers for all control commands with access to arbiter state.
    Nc                   @   s0  e Zd ZdZdd ZdefddZdefddZdefd	d
ZdefddZ	defddZ
d.dedefddZd.dedefddZdedefddZd.dedefddZd.dedefddZdededefddZdefdd Zdefd!d"Zd/d$edefd%d&Zdefd'd(Zdefd)d*Zdefd+d,Zd-S )0CommandHandlersz
    Command handlers with access to arbiter state.

    All handler methods return dictionaries that will be sent
    as the response data.
    c                 C   s
   || _ dS )z
        Initialize handlers with arbiter reference.

        Args:
            arbiter: The Gunicorn arbiter instance
        N)arbiter)selfr    r   I/home/ubuntu/.local/lib/python3.10/site-packages/gunicorn/ctl/handlers.py__init__   s   
zCommandHandlers.__init__returnc              
   C   s   g }t  }| jj D ].\}}z|j }t|| d}W n tt	fy+   d}Y nw |
||j|j|j|d q|jdd d |t|dS )a}  
        Return list of HTTP workers.

        Returns:
            Dictionary with workers list containing:
            - pid: Worker process ID
            - age: Worker age (spawn order)
            - requests: Number of requests handled (if available)
            - booted: Whether worker has finished booting
            - last_heartbeat: Seconds since last heartbeat
           N)pidagebootedabortedlast_heartbeatc                 S      | d S Nr   r   wr   r   r   <lambda>A       z.CommandHandlers.show_workers.<locals>.<lambda>key)workerscount)time	monotonicr   WORKERSitemstmplast_updateroundOSError
ValueErrorappendr   r   r   sortlen)r   r   nowr
   workerr   r   r   r   r   show_workers"   s$   

	zCommandHandlers.show_workersc                 C   s  | j jsddg g dS t| j dd}g }g }|rt|drt }|j D ]5\}}z|j	 }t
|| d}W n tttfyF   d}Y nw |||jt|dg t|dd|d	 q&t|d
r|j D ]\}	}
t|j|	g }||	|
dt||d qfd| j j||dS )a%  
        Return dirty workers and apps information.

        Returns:
            Dictionary with:
            - enabled: Whether dirty arbiter is running
            - pid: Dirty arbiter PID
            - workers: List of dirty worker info
            - apps: List of dirty app specs
        FN)enabledr
   r   appsdirty_arbiterr   r	   	app_pathsr   )r
   r   r)   r   r   	app_specsworker_count)import_pathr-   current_workersworker_pidsT)r   dirty_arbiter_pidgetattrhasattrr   r   r   r   r   r   r   r    r!   AttributeErrorr"   r   r,   listapp_worker_mapgetr$   )r   r*   r   r)   r%   r
   r&   r   r   pathspecr0   r   r   r   
show_dirtyE   sN   




	
zCommandHandlers.show_dirtyc                 C   s   | j j}i }g d}|D ]6}z+t||}t|rt|}nt|dr4t|tttt	t
ttdfs4t|}|||< W q tyB   Y qw |S )zz
        Return current effective configuration.

        Returns:
            Dictionary of configuration values
        )bindr   worker_classthreadstimeoutgraceful_timeout	keepalivemax_requestsmax_requests_jitterworker_connectionspreload_appdaemonpidfile	proc_namereloaddirty_workers
dirty_appsdirty_timeoutcontrol_socketcontrol_socket_disable	__class__N)r   cfgr2   callablestrr3   
isinstanceintfloatboolr5   dicttyper4   )r   rO   configconfig_keysr   valuer   r   r   show_config   s"   	

zCommandHandlers.show_configc              
   C   sx   t | jdi }|d}d}|rtt | d}|| jjt| jj| jj|dd|dd|dd| jj	p9dd	S )
a  
        Return server statistics.

        Returns:
            Dictionary with:
            - uptime: Seconds since arbiter started
            - pid: Arbiter PID
            - workers_current: Current number of workers
            - workers_spawned: Total workers spawned
            - workers_killed: Total workers killed (if tracked)
            - reloads: Number of reloads (if tracked)
        _stats
start_timeNr	   workers_spawnedr   workers_killedreloads)uptimer
   workers_currentworkers_targetr^   r_   r`   r1   )
r2   r   r7   r   r   r
   r$   r   num_workersr1   )r   statsr]   ra   r   r   r   
show_stats   s   





zCommandHandlers.show_statsc              	   C   s   g }| j jD ]E}t|}|| d}z%|j}|jtjkr"d|d< n|jtjkr-d|d< n
|jtj	kr7d|d< W n t
yE   d|d< Y nw || q|t|dS )zo
        Return bound socket information.

        Returns:
            Dictionary with listeners list
        )addressfdunixrW   tcptcp6unknown)	listenersr   )r   	LISTENERSrQ   filenosockfamilysocketAF_UNIXAF_INETAF_INET6	Exceptionr"   r$   )r   rm   lnraddrlistener_inforp   r   r   r   show_listeners   s(   

zCommandHandlers.show_listeners   r   c                 C   s@   t dt|}| jj}| j j|7  _| j  ||| jjdS )z
        Increase worker count.

        Args:
            count: Number of workers to add (default 1)

        Returns:
            Dictionary with added count and new total
        r{   )addedprevioustotalmaxrS   r   rd   wakeup)r   r   	old_countr   r   r   
worker_add   s   

zCommandHandlers.worker_addc                 C   sJ   t dt|}| jj}t d|| }|| }|| j_| j  |||dS )z
        Decrease worker count.

        Args:
            count: Number of workers to remove (default 1)

        Returns:
            Dictionary with removed count and new total
        r{   )removedr}   r~   r   )r   r   r   	new_countactual_removedr   r   r   worker_remove   s   

zCommandHandlers.worker_remover
   c              
   C   st   t |}|| jjvrdd| ddS zt|tj d|dW S  ty9 } zdt|dW  Y d}~S d}~ww )z
        Gracefully terminate a specific worker.

        Args:
            pid: Worker process ID

        Returns:
            Dictionary with killed PID or error
        FzWorker z
 not foundsuccesserrorT)r   killedN)	rS   r   r   oskillsignalSIGTERMr    rQ   )r   r
   er   r   r   worker_kill  s    

zCommandHandlers.worker_killc                 C   ,   | j js	dddS tdt|}| d|S )a  
        Spawn additional dirty workers.

        Sends a MANAGE message to the dirty arbiter to spawn workers.

        Args:
            count: Number of dirty workers to add (default 1)

        Returns:
            Dictionary with added count or error
        FDirty arbiter not runningr   r{   addr   r1   r   rS   _send_manage_messager   r   r   r   r   	dirty_add4     zCommandHandlers.dirty_addc                 C   r   )a  
        Remove dirty workers.

        Sends a MANAGE message to the dirty arbiter to remove workers.

        Args:
            count: Number of dirty workers to remove (default 1)

        Returns:
            Dictionary with removed count or error
        Fr   r   r{   remover   r   r   r   r   dirty_removeI  r   zCommandHandlers.dirty_remove	operationc              
   C   s^  d}t | jdr| jjrt| jjdd}|stjd}|s#dddS zrdd	lm}m	}m
} |d
kr4|n|}ttjtj}|d || |jd||d}	|||	 ||}
|  |
d|jkrp|
dddiW S |
d|jkr|
di }d|dt|dW S dd|
d dW S  ty } zdt|dW  Y d}~S d}~ww )z
        Send a worker management message to the dirty arbiter.

        Args:
            operation: "add" or "remove"
            count: Number of workers to add/remove

        Returns:
            Dictionary with result or error
        Nr*   socket_pathGUNICORN_DIRTY_SOCKETFz%Cannot find dirty arbiter socket pathr   r   )DirtyProtocolMANAGE_OP_ADDMANAGE_OP_REMOVEr   g      $@r{   )rW   idopr   rW   resultr   Tr   messagezUnexpected response type: )r3   r   r*   r2   r   environr7   gunicorn.dirty.protocolr   r   r   rr   rs   SOCK_STREAM
settimeoutconnectMSG_TYPE_MANAGEwrite_messageread_messagecloseMSG_TYPE_RESPONSEMSG_TYPE_ERRORrQ   rv   )r   r   r   dirty_socket_pathr   r   r   r   rp   requestresponser   r   r   r   r   r   ^  sR   



z$CommandHandlers._send_manage_messagec                 C      t | jjtj ddiS )zv
        Trigger graceful reload (equivalent to SIGHUP).

        Returns:
            Dictionary with status
        status	reloading)r   r   r   r
   r   SIGHUPr   r   r   r   rH     s   zCommandHandlers.reloadc                 C   r   )zp
        Reopen log files (equivalent to SIGUSR1).

        Returns:
            Dictionary with status
        r   	reopening)r   r   r   r
   r   SIGUSR1r   r   r   r   reopen  s   zCommandHandlers.reopengracefulmodec                 C   s8   |dkrt | jjtj n	t | jjtj d|dS )z
        Initiate shutdown.

        Args:
            mode: "graceful" (SIGTERM) or "quick" (SIGINT)

        Returns:
            Dictionary with status
        quickshutting_down)r   r   )r   r   r   r
   r   SIGINTr   )r   r   r   r   r   shutdown  s   

zCommandHandlers.shutdownc           
   
   C   s   t  }| jjddd}g }| jj D ]-\}}z|j }t|| d}W n t	t
fy3   d}Y nw ||d|j|j|d q|jdd	 d
 d}g }	| jjr^| jjddd}|  }	||t|||	t|	dS )z
        Return overview of all processes (arbiter, web workers, dirty arbiter, dirty workers).

        Returns:
            Dictionary with complete process hierarchy
        r   master)r
   rW   roler	   Nweb)r
   rW   r   r   r   c                 S   r   r   r   r   r   r   r   r     r   z*CommandHandlers.show_all.<locals>.<lambda>r   r*   zdirty master)r   web_workersweb_worker_countr*   rI   dirty_worker_count)r   r   r   r
   r   r   r   r   r   r    r!   r"   r   r   r#   r1   _query_dirty_workersr$   )
r   r%   arbiter_infor   r
   r&   r   r   dirty_arbiter_inforI   r   r   r   show_all  sH   

	zCommandHandlers.show_allc                 C   s   d}t | jdr| jjrt| jjdd}|stjd}|s g S zEddlm} t		t	j
t	j}|d || |jdd	}||| ||}|  |d
|jkrc|di }|dg W S W g S  tyo   Y g S w )z
        Query the dirty arbiter for worker information.

        Connects to the dirty arbiter socket and sends a status request.

        Returns:
            List of dirty worker info dicts, or empty list on error
        Nr*   r   r   r   )r   g       @zctl-status-1)rW   r   rW   r   r   )r3   r   r*   r2   r   r   r7   r   r   rr   rs   r   r   r   MSG_TYPE_STATUSr   r   r   r   rv   )r   r   r   rp   r   r   r   r   r   r   r     s6   



z$CommandHandlers._query_dirty_workersc                 C   s,   ddddddddd	d
dddddd}d|iS )z|
        Return list of available commands.

        Returns:
            Dictionary with commands and descriptions
        z8Show all processes (arbiter, web workers, dirty workers)z#List HTTP workers with their statuszList dirty workers and appsz$Show current effective configurationzShow server statisticszShow bound socketszSpawn N workers (default 1)zRemove N workers (default 1)z$Gracefully terminate specific workerz!Spawn N dirty workers (default 1)z"Remove N dirty workers (default 1)zGraceful reload (HUP)zReopen log files (USR1)zShutdown server (TERM/INT)zShow this help message)zshow allzshow workersz
show dirtyzshow configz
show statszshow listenerszworker add [N]zworker remove [N]zworker kill <PID>zdirty add [N]zdirty remove [N]rH   r   zshutdown [graceful|quick]helpcommandsr   )r   r   r   r   r   r   1  s"   zCommandHandlers.helpN)r{   )r   )__name__
__module____qualname____doc__r   rV   r'   r:   r[   rf   rz   rS   r   r   r   r   r   rQ   r   rH   r   r   r   r5   r   r   r   r   r   r   r      s(    	#<# E
;-r   )r   r   r   rr   r   r   r   r   r   r   <module>   s   