
    Dfa<                         d 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	 dZ
 G d d          Z e            Z e            Z G d dej                  Z G d	 d
          ZdS )z8A thread-based worker pool.

.. spelling::

   joinable
    N)	pass_none)WorkerThread
ThreadPoolc                       e Zd ZdZd Zd ZdS )	TrueyZerozDObject which equals and does math like the integer 0 but evals True.c                     |S N selfothers     I/var/www/media/lib/python3.11/site-packages/cheroot/workers/threadpool.py__add__zTrueyZero.__add__           c                     |S r	   r
   r   s     r   __radd__zTrueyZero.__radd__   r   r   N)__name__
__module____qualname____doc__r   r   r
   r   r   r   r      s8        NN      r   r   c                   6    e Zd ZdZdZ	 dZ	 dZ	 d Zd Zd Z	dS )r   aF  Thread which continuously polls a Queue for Connection objects.

    Due to the timing issues of polling a Queue, a WorkerThread does not
    check its own 'ready' flag after it has started. To stop the thread,
    it is necessary to stick a _SHUTDOWNREQUEST object onto the Queue
    (one for each running WorkerThread).
    NFc                      d _         | _        d _        d _        d _        d _        d _         fd fd fd fdd d	 d
 _        t          j	        
                                dS )zInitialize WorkerThread instance.

        Args:
            server (cheroot.server.HTTPServer): web server object
                receiving this request
        Fr   Nc                 L    j         j        d u rt          pj        j         z   S r	   )requests_seen
start_time	trueyzeroconnsr   s    r   <lambda>z'WorkerThread.__init__.<locals>.<lambda>I   s.    $"44' +9*# r   c                 V    j         j        d u rt          pj        j        j         z   S r	   )
bytes_readr   r   r   rfiler   s    r   r!   z'WorkerThread.__init__.<locals>.<lambda>N   s/    DO4' .9?-% r   c                 V    j         j        d u rt          pj        j        j         z   S r	   )bytes_writtenr   r   r   wfiler   s    r   r!   z'WorkerThread.__init__.<locals>.<lambda>S   s0    t'94' 19?0( r   c                 j    j         j        d u rt          pt          j                    j        z
  z   S r	   )	work_timer   r   timer   s    r   r!   z'WorkerThread.__init__.<locals>.<lambda>X   s5    4>4' 19;;0$ r   c                 L     | d         |            | d         |           pdz  S )N
Bytes Read	Work Timeư>r
   r    s    r   r!   z'WorkerThread.__init__.<locals>.<lambda>]   s/    <););+q!!)T* r   c                 L     | d         |            | d         |           pdz  S )NBytes Writtenr-   r.   r
   r/   s    r   r!   z'WorkerThread.__init__.<locals>.<lambda>`   s1    *<!O*<Q*?*?+q!!)T+ r   )Requestsr,   r1   r-   zRead ThroughputzWrite Throughput)readyserverr   r#   r&   r   r)   stats	threadingThread__init__)r   r4   s   ` r   r8   zWorkerThread.__init__9   s     
   
   
   
   
   ! !1
 

8 	!!$'''''r   c                    | j         | j        j         d         | j        <   d| _        	 |                                  n# t
          t          f$ rH}|j        p|}| j                            d|t          j
                   || j        _        Y d}~nMd}~wt          $ r=}| j                            d|dt          j        d           || j        _         d}~ww xY wd	| _        dS # d	| _        w xY w)
a0  Set up incoming HTTP connection processing loop.

        This is the thread's entry-point. It performs lop-layer
        exception handling and interrupt processing.
        :exc:`KeyboardInterrupt` and :exc:`SystemExit` bubbling up
        from the inner-layer code constitute a global server interrupt
        request. When they happen, the worker thread exits.

        :raises BaseException: when an unexpected non-interrupt
                               exception leaks from the inner layers

        # noqa: DAR401 KeyboardInterrupt SystemExit
        zWorker ThreadsTz%Setting the server interrupt flag to levelNzAA fatal exception happened. Setting the server interrupt flag to z and giving up.

Please, report this on the Cheroot tracker at <https://github.com/cherrypy/cheroot/issues/new/choose>, providing a full reproducer with as much context and details as possible.r;   	tracebackF)r5   r4   namer3   &_process_connections_until_interruptedKeyboardInterrupt
SystemExit	__cause__	error_logloggingDEBUG	interruptBaseExceptionCRITICAL)r   interrupt_excinterrupt_causeunderlying_excs       r   runzWorkerThread.runf   sE    :>*+DI6
	779999!:. 	4 	4 	4+5FOK!!LLLm "    %4DK!!!!!! 	 	 	 K!!\%\ \ \ & " 	 	 	 %3DK!	" DJJJDJs8   = C' C>BC' C8CCC' '	C0c           
         	 | j         j                                        }|t          u rdS || _        | j         j        d         }|rt          j                    | _        d}	 |                                }nd# t          $ r}d}| j         
                    d|j        d|j        d|dt          j        	           Y d}~|r| j                             |           n|                                 |ry| xj        |j        z  c_        | xj        |j        j        z  c_        | xj        |j        j        z  c_        | xj        t          j                    | j        z
  z  c_        d| _        d| _        ud}~wt.          t0          f$ r^}d}| j         
                    d
|j        d|j        d|dt          j        	           t1          t5          |                    |d}~wt6          $ r}| j         
                    d|t          j        d           Y d}~|r| j                             |           n|                                 |ry| xj        |j        z  c_        | xj        |j        j        z  c_        | xj        |j        j        z  c_        | xj        t          j                    | j        z
  z  c_        d| _        d| _        d}~ww xY w	 |r| j                             |           n|                                 |ry| xj        |j        z  c_        | xj        |j        j        z  c_        | xj        |j        j        z  c_        | xj        t          j                    | j        z
  z  c_        d| _        d| _        n# |r| j                             |           n|                                 |ry| xj        |j        z  c_        | xj        |j        j        z  c_        | xj        |j        j        z  c_        | xj        t          j                    | j        z
  z  c_        d| _        d| _        w xY wH)a  Process incoming HTTP connections in an infinite loop.

        Retrieves incoming connections from thread pool, processing
        them one by one.

        :raises SystemExit: on the internal requests to stop the
                            server instance
        TNEnabledFz8Got a connection error while handling a connection from :z ()r:   z?Got a server shutdown request while handling a connection from z8Unhandled error while processing an incoming connection r<   )r4   requestsget_SHUTDOWNREQUESTr   r5   r*   r   communicateConnectionErrorrC   remote_addrremote_portrD   INFOput_conncloser   r#   r$   r&   r'   r)   r@   rA   rE   strrG   ERROR)r   r   is_stats_enabledkeep_conn_openconnection_errorshutdown_requestunhandled_errors          r   r?   z3WorkerThread._process_connections_until_interrupted   s   D	!;'++--D'''DI#{0; ."&)++"N:!!%!1!1!3!3"   !&%%E'+'7E E'E E.>E E E ",	 &    L " !K((....JJLLL# +&&$*<<&&OOtz'<<OO&&$**BB&&NNdikkDO&CCNN&*DO 		_ &z2 ( ( (!&%%E'+'7E E'E E.>E E E "-	 &    !()) '( !    %%7"17 7!-"	 &     " !K((....JJLLL# +&&$*<<&&OOtz'<<OO&&$**BB&&NNdikkDO&CCNN&*DO 		G- ^ " !K((....JJLLL# +&&$*<<&&OOtz'<<OO&&$**BB&&NNdikkDO&CCNN&*DO 		 " !K((....JJLLL# +&&$*<<&&OOtz'<<OO&&$**BB&&NNdikkDO&CCNN&*DO 	    ID	!sP   !A7 5N 7
K<E6=N 6K
AG##K0*KN KN B5Q)
r   r   r   r   r   r4   r3   r8   rL   r?   r
   r   r   r   r   %   sr          D?F8 E$+( +( +(Z* * *XM! M! M! M! M!r   r   c                       e Zd ZdZ	 	 ddZd Zed             Zd Zd Z	d	 Z
d
 Zd ZddZeed                         Zd Zed             ZdS )r   zA Request Queue for an HTTPServer which pools threads.

    ThreadPool objects must provide min, get(), put(obj), start()
    and stop(timeout) attributes.
    
   c                    |dk     rt          d|d          |t          d          k    rnCt          |t                    r|dk    rt	          d|d          |dk     rt          d          }||k     rt          d|d	|d
          || _        || _        || _        g | _        t          j
        |          | _        || _        | j        j        | _        t          j                    | _        dS )an  Initialize HTTP requests queue instance.

        Args:
            server (cheroot.server.HTTPServer): web server object
                receiving this request
            min (int): minimum number of worker threads
            max (int): maximum number of worker threads (-1/inf for no max)
            accepted_queue_size (int): maximum number of active
                requests in queue
            accepted_queue_timeout (int): timeout for putting request
                into queue

        :raises ValueError: if the min/max values are invalid
        :raises TypeError: if the max is not an integer or inf
           zmin=z must be > 0infr   zIExpected an integer or the infinity value for the `max` argument but got .zmax=z must be > min=z (or infinity for no max))maxsizeN)
ValueErrorfloat
isinstanceint	TypeErrorr4   minmax_threadsqueueQueue_queue_queue_put_timeoutrR   collectionsdeque_pending_shutdowns)r   r4   ro   rp   accepted_queue_sizeaccepted_queue_timeouts         r   r8   zThreadPool.__init__   s"   & 777C777888%,,C%% 	-$'- - -   1WW,,C99MsMMSMMM   k*=>>>"8;?"-"3"5"5r   c                 f    | j         rt          d          |                     | j                   dS )zaStart the pool of threads.

        :raises RuntimeError: if the pool is already started
        z%Threadpools can only be started once.N)rq   RuntimeErrorgrowro   r   s    r   startzThreadPool.start  s8    
 = 	HFGGG		$(r   c                     t          d | j        D                       }t          |t          | j                  z
  d          S )z3Number of worker threads which are idle. Read-only.c                      g | ]}|j         	|S r	   r   .0ts     r   
<listcomp>z#ThreadPool.idle.<locals>.<listcomp>#  s    @@@1Qr   r   )lenrq   rp   rx   )r   idless     r   idlezThreadPool.idle   sB     @@@@@AA53t6777;;;r   c                 J    | j                             |d| j                   dS )zPut request into queue.

        Args:
            obj (:py:class:`~cheroot.server.HTTPConnection`): HTTP connection
                waiting to be processed
        T)blocktimeoutN)rt   putru   )r   objs     r   r   zThreadPool.put&  s'     	41HIIIIIr   c                     d | j         D             D ]F}| j                             |           	 | j                                         7# t          $ r Y Cw xY wd S )Nc                 :    g | ]}|                                 |S r
   )is_aliver   s     r   r   z2ThreadPool._clear_dead_threads.<locals>.<listcomp>1  s%    ???!**,,?!???r   )rq   removerx   popleft
IndexError)r   r   s     r   _clear_dead_threadszThreadPool._clear_dead_threads/  s~    ??T]??? 	 	AM  ###'//1111   		 	s   A		
AAc                 4    t           j         t           j                  z
  d          }t          ||          } fdt	          |          D             }|D ]$}|j        st          j        d           |j        % j                            |           dS )z.Spawn new worker threads (not above self.max).r   c                 8    g | ]}                                 S r
   )_spawn_worker)r   ir   s     r   r   z#ThreadPool.grow.<locals>.<listcomp>=  s%    >>>A4%%''>>>r   g?N)	rp   r   rq   ro   ranger3   r*   sleepextend)r   amountbudgetn_newworkersworkers   `     r   r}   zThreadPool.grow8  s    TXDM 2 22A66FF##>>>>u>>> 	 	Fl 
2 l W%%%%%r   c                     t          | j                  }d                    |j                  |_        |                                 |S )NzCP Server {worker_name!s})worker_name)r   r4   formatr>   r   )r   r   s     r   r   zThreadPool._spawn_workerC  s@    dk**'Fv{F++ 	 	r   c                 v   |t          | j                  z  }|                                  |dk    rdS t          t          | j                  | j        z
  d          }t          ||          }t          |          D ];}| j                            d           | j        	                    t                     <dS )z-Kill off worker threads (not below self.min).r   N)r   rx   r   rp   rq   ro   r   appendrt   r   rS   )r   r   n_extran_to_remove_s        r   shrinkzThreadPool.shrinkL  s     	#d-...  """Q;;F c$-((483Q77 &'**
 {## 	. 	.A#**4000KOO,----	. 	.r      c                    ||dk     rd}t          j        dd           |t          j                    |z   }| j        D ]!}| j                            t                     "t          t          f}| 	                                D ]}}|o|t          j                    z
  }	 |
                    |           |                                r.|                     |j                   |
                                 s# |$ r Y zw xY wdS )z|Terminate all worker threads.

        Args:
            timeout (int): time to wait for threads to stop gracefully
        Nr   zZIn the future, negative timeouts to Server.stop() will be equivalent to a timeout of zero.   )
stacklevel)warningswarningr*   rq   rt   r   rS   r|   r@   _clear_threadsjoinr   _force_closer   )r   r   endtimer   ignored_errorsremaining_times         r   stopzThreadPool.stopb  s4    7Q;;G;    ikkG+G m 	. 	.FKOO,----
 
 ))++ 		 		F$>49;;)>NN+++??$$ "%%fk222KKMMM!   		 		s   AC77C?>C?c                     | j         j        rd S 	 	 | j                            t          j                   d S # t
          $ r | j                                         Y d S w xY w# t          $ r Y d S w xY wr	   )r$   closedsocketshutdownSHUT_RDrn   OSErrorr   s    r   r   zThreadPool._force_close  s     : 	F		'$$V^44444 ' ' '$$&&&&&&'  	 	 	 DD	s'   $7 #AA! AA! !
A/.A/c                 R    | j         dd         g c}| j         dd<   d |D             S )z3Clear self._threads and yield all joinable threads.Nc              3   D   K   | ]}|t          j                    u|V  d S r	   )r6   current_thread)r   threads     r   	<genexpr>z,ThreadPool._clear_threads.<locals>.<genexpr>  sB       
 
Y57777 7777
 
r   )rq   )r   threadss     r   r   zThreadPool._clear_threads  sG     %)M!!!$4b!qqq!
 
!
 
 
 	
r   c                 4    | j                                         S )zReturn the queue size.)rt   qsizer~   s    r   r   zThreadPool.qsize  s     {  """r   N)rc   rd   rd   rc   )r   )r   r   r   r   r8   r   propertyr   r   r   r}   r   r   r   staticmethodr   r   r   r   r
   r   r   r   r      s         ?A#%,6 ,6 ,6 ,6\   < < X<
J J J  	& 	& 	&  . . .,) ) ) )V   Y \
 
 
 # # X# # #r   r   )r   rv   rD   r6   r*   r   r   rr   jaraco.functoolsr   __all__r   r   objectrS   r7   r   r   r
   r   r   <module>r      s"                 & & & & & & )        IKK	688 z! z! z! z! z!9# z! z! z!zH# H# H# H# H# H# H# H# H# H#r   