Ë
    #ïàj}<  ã                   óÆ   — 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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y)z8A thread-based worker pool.

.. spelling::

   joinable
é    N)Ú	pass_none)Ú
ThreadPoolÚWorkerThreadc                   ó   — e Zd ZdZd„ Zd„ Zy)Ú	TrueyZerozDObject which equals and does math like the integer 0 but evals True.c                 ó   — |S ©N© ©ÚselfÚothers     úI/srv/dav/.venv/lib/python3.12/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      s   „ ÙNòór   r   c                   ó4   — e Zd ZdZdZ	 dZ	 dZ	 d„ Zd„ Zd„ Z	y)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                  j                  ‰ «       y)z¢Initialize WorkerThread instance.

        Args:
            server (cheroot.server.HTTPServer): web server object
                receiving this request
        Fr   Nc                 óz   •— ‰j                   ‰j                  d u xr t        xs ‰j                  j                   z   S r	   )Úrequests_seenÚ
start_timeÚ	trueyzeroÚconn©Úsr   s    €r   ú<lambda>z'WorkerThread.__init__.<locals>.<lambda>J   s5   ø€  $×"4Ñ"4à—‘ DÐ(Ò6¬Yò +Ø—9‘9×*Ñ*ñ#€ r   c                 óŽ   •— ‰j                   ‰j                  d u xr t        xs  ‰j                  j                  j                   z   S r	   )Ú
bytes_readr   r   r   Úrfiler   s    €r   r!   z'WorkerThread.__init__.<locals>.<lambda>O   s7   ø€  D§O¡Oà—‘ DÐ(Ò6¬Yò .Ø—9‘9—?‘?×-Ñ-ñ%€ r   c                 óŽ   •— ‰j                   ‰j                  d u xr t        xs  ‰j                  j                  j                   z   S r	   )Úbytes_writtenr   r   r   Úwfiler   s    €r   r!   z'WorkerThread.__init__.<locals>.<lambda>T   s9   ø€  t×'9Ñ'9à—‘ DÐ(Ò6¬Yò 1Ø—9‘9—?‘?×0Ñ0ñ(€ r   c                 ó�   •— ‰j                   ‰j                  d u xr t        xs! t        j                  «       ‰j                  z
  z   S r	   )Ú	work_timer   r   Útimer   s    €r   r!   z'WorkerThread.__init__.<locals>.<lambda>Y   s8   ø€  4§>¡>à—‘ DÐ(Ò6¬Yò 1Ü—9‘9“; §¡Ñ0ñ$€ r   c                 ó8   —  | d   | «       | d   | «      xs dz  S )Nú
Bytes Readú	Work Timeç�íµ ÷Æ°>r
   ©r    s    r   r!   z'WorkerThread.__init__.<locals>.<lambda>^   s)   € ¨¨¨<©¸Ó);Øˆq�‰~˜aÓ Ò( Dñ**€ r   c                 ó8   —  | d   | «       | d   | «      xs dz  S )NúBytes Writtenr-   r.   r
   r/   s    r   r!   z'WorkerThread.__init__.<locals>.<lambda>`   s+   € Ð*<¨!¨OÑ*<¸QÓ*?Øˆq�‰~˜aÓ Ò( Dñ+*€ 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__:   su   ø€ ð ˆŒ
ØˆŒàˆÔØˆŒØˆÔØˆŒØˆŒóó
ó
ó
ñ
 *ñ!*ñ/
ˆŒ
ô4 	×Ñ×!Ñ! $Õ'r   c                 ó,  — | j                   | j                  j                   d   | j                  <   d| _        	 | j	                  «        d	| _        y# t
        t        f$ rY}|j                  xs |}| j                  j                  d|›�t        j                  ¬«       || j                  _        Y d}~Œkd}~wt        $ rG}| j                  j                  d|›d�t        j                  d¬«       || j                  _        ‚ d}~ww xY w# 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.rune   s
  € ð :>¿¹ˆ�‰×ÑÐ*Ñ+¨D¯I©IÑ6ØˆŒ
ð	Ø×7Ñ7Ô9ð2 ˆD�Jøô1 "¤:Ð.ò 	4Ø+×5Ñ5ÒF¸ˆOØ�K‰K×!Ñ!Ø7¸Ð7JÐKÜ—m‘mð "ô ð %4ˆD�K‰K×!Ñ!ûÜò 	ð �K‰K×!Ñ!ðØ%Ð(ð )\ð\ô ×&Ñ&Øð "ô 	ð %3ˆD�K‰KÔ!Øûð	ûð" ˆD�Jús7   ¹A ÁDÁ AB4Â/D
 Â4DÃ ADÄDÄD
 Ä
	Dc           
      óP
  — 	 | j                   j                  j                  «       }|t        u ry|| _        | j                   j
                  d   }|rt        j                  «       | _        d}	 |j                  «       }	 |r| j                   j                  |«       n|j!                  «        |r¬| 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| _        �Œa# t        $ �r9}d}| j                   j                  d|j                  ›d|j                  ›d|›d�t        j                  ¬	«       Y d}~|r| j                   j                  |«       n|j!                  «        |r¬| 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t.        t0        f$ re}d}| j                   j                  d
|j                  ›d|j                  ›d|›d�t        j2                  ¬	«       t1        t5        |«      «      |‚d}~wt6        $ �r}| j                   j                  d|›�t        j8                  d¬«       Y d}~|r| j                   j                  |«       n|j!                  «        |r¬| 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| _        �Œ7d}~ww xY w# |r| j                   j                  |«       n|j!                  «        |r¬| 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)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ŒIØ#Ÿ{™{×0Ñ0°Ñ;ÐÙÜ"&§)¡)£+�”Ø"ˆNð:!Ø!%×!1Ñ!1Ó!3‘ñ^ "Ø—K‘K×(Ñ(¨Õ.à—J‘J”LÙ#Ø×&Ò&¨$×*<Ñ*<Ñ<Õ&Ø—O’O t§z¡z×'<Ñ'<Ñ<•OØ×&Ò&¨$¯*©*×*BÑ*BÑBÕ&Ø—N’N¤d§i¡i£k°D·O±OÑ&CÑC•NØ&*�D”OØ �”	ñI øô #ó Ø!&�Ø—‘×%Ñ%ð'Ø'+×'7Ñ'7Ð&:¸!Ø×'Ñ'Ð*¨"Ð-=Ð,@ÀðCô "Ÿ,™,ð	 &ô ó ñL "Ø—K‘K×(Ñ(¨Õ.à—J‘J”LÙ#Ø×&Ò&¨$×*<Ñ*<Ñ<Õ&Ø—O’O t§z¡z×'<Ñ'<Ñ<•OØ×&Ò&¨$¯*©*×*BÑ*BÑBÕ&Ø—N’N¤d§i¡i£k°D·O±OÑ&CÑC•NØ&*�D”OØ �–	ûô_ &¤zÐ2ò (à!&�Ø—‘×%Ñ%ð'Ø'+×'7Ñ'7Ð&:¸!Ø×'Ñ'Ð*¨"Ð-=Ð,@ÀðCô "Ÿ-™-ð	 &ô ô !ÜÐ(Ó)óà'ð(ûô !ó ð —‘×%Ñ%ð"Ø"1Ð!4ð6ä!Ÿ-™-Ø"ð	 &ô ó ñ "Ø—K‘K×(Ñ(¨Õ.à—J‘J”LÙ#Ø×&Ò&¨$×*<Ñ*<Ñ<Õ&Ø—O’O t§z¡z×'<Ñ'<Ñ<•OØ×&Ò&¨$¯*©*×*BÑ*BÑBÕ&Ø—N’N¤d§i¡i£k°D·O±OÑ&CÑC•NØ&*�D”OØ �–	ûðGûñ2 "Ø—K‘K×(Ñ(¨Õ.à—J‘J”LÙ#Ø×&Ò&¨$×*<Ñ*<Ñ<Õ&Ø—O’O t§z¡z×'<Ñ'<Ñ<•OØ×&Ò&¨$¯*©*×*BÑ*BÑBÕ&Ø—N’N¤d§i¡i£k°D·O±OÑ&CÑC•NØ&*�D”OØ �•	úsK   Á-E# Å#
P=Å-AJ!Æ8Q  Ê!P=Ê3A LÌP=Ì /P8ÍQ  Ð8P=Ð=Q  Ñ C%T%)
r   r   r   r   r   r4   r3   r8   rL   r?   r
   r   r   r   r   &   s9   „ ñð €DØ?à€Fð8ð €Eð$ò)(òV*óX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y)r   z A 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n4t        |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                  «       | _        y)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   rm   rn   Úaccepted_queue_sizeÚaccepted_queue_timeouts         r   r8   zThreadPool.__init__è   sì   € ð. �Š7Ü˜t C 7¨,Ð7Ó8Ð8à”%˜“,ÒØÜ˜C¤Ô%¨°ªÜð$Ø$' 7¨!ð-óð ð �1ŠWÜ˜“,ˆCà�Š9ÜØ�s�g˜_¨S¨GÐ3LÐMóð ð ˆŒØˆŒØˆŒØˆŒÜ—k‘kÐ*=Ô>ˆŒØ"8ˆÔØ—;‘;—?‘?ˆŒÜ"-×"3Ñ"3Ó"5ˆÕr   c                 óh   — | j                   rt        d«      ‚| j                  | j                  «       y)zaStart the pool of threads.

        :raises RuntimeError: if the pool is already started
        z%Threadpools can only be started once.N)ro   ÚRuntimeErrorÚgrowrm   ©r   s    r   ÚstartzThreadPool.start  s'   € ð
 �=Š=ÜÐFÓGÐGØ�	‰	�$—(‘(Õr   c                 ó°   — t        | j                  D �cg c]  }|j                  �Œ|‘Œ c}«      }t        |t        | j                  «      z
  d«      S c c}w )z3Number of worker threads which are idle. Read-only.r   )Úlenro   r   rn   rv   )r   ÚtÚidless      r   ÚidlezThreadPool.idle#  sH   € ô  §¡Ö@˜1°·±±’QÒ@ÓAˆÜ�5œ3˜t×6Ñ6Ó7Ñ7¸Ó;Ð;ùò As
   ”A¦Ac                 óT   — | j                   j                  |d| j                  ¬«       y)z¥Put request into queue.

        Args:
            obj (:py:class:`~cheroot.server.HTTPConnection`): HTTP connection
                waiting to be processed
        T)ÚblockÚtimeoutN)rr   Úputrs   )r   Úobjs     r   r†   zThreadPool.put)  s    € ð 	�‰�‰˜ 4°×1HÑ1HˆÕIr   c                 ó4  — | j                   D �cg c]  }|j                  «       rŒ|‘Œ c}D ]Y  }| j                   j                  |«       t        j                  t
        «      5  | j                  j                  «        d d d «       Œ[ y c c}w # 1 sw Y   ŒkxY wr	   )ro   Úis_aliveÚremoveÚ
contextlibÚsuppressÚ
IndexErrorrv   Úpopleft)r   r€   s     r   Ú_clear_dead_threadszThreadPool._clear_dead_threads2  sw   € à!Ÿ]™]Ö?˜°!·*±*µ,’!Ò?ò 	2ˆAØ�M‰M× Ñ  Ô#Ü×$Ñ$¤ZÓ0ñ 2Ø×'Ñ'×/Ñ/Ô1÷2ð 2ñ	2ùÒ?÷2ð 2ús   �B	¥B	Á#BÂB	c                 ól  — t        | j                   t        | j                  «      z
  d«      }t        ||«      }t	        |«      D �cg c]  }| j                  «       ‘Œ }}|D ]1  }|j                  rŒt        j                  d«       |j                  sŒ"Œ3 | j                  j                  |«       yc c}w )z.Spawn new worker threads (not above self.max).r   gš™™™™™¹?N)
rn   r   ro   rm   ÚrangeÚ_spawn_workerr3   r*   ÚsleepÚextend)r   ÚamountÚbudgetÚn_newÚiÚworkersÚworkers          r   r{   zThreadPool.grow9  s�   € ä�T—X‘X¤ D§M¡MÓ 2Ñ2°AÓ6ˆÜ�F˜FÓ#ˆä16°u³Ö>¨A�4×%Ñ%Õ'Ð>ˆÐ>Øò 	 ˆFØ—l“lÜ—
‘
˜3”ð —l”lð	 ð 	�‰×Ñ˜WÕ%ùò	 ?s   ÁB1c                 óx   — t        | j                  «      }d|j                  ›�|_        |j                  «        |S )Nz
CP Server )r   r4   r>   r}   )r   rš   s     r   r’   zThreadPool._spawn_workerD  s0   € Ü˜dŸk™kÓ*ˆØ" 6§;¡; /Ð2ˆŒØ�‰ŒØˆr   c                 ód  — |t        | j                  «      z  }| j                  «        |dk  ryt        t        | j                  «      | j
                  z
  d«      }t        ||«      }t        |«      D ]<  }| j                  j                  d«       | j                  j                  t        «       Œ> y)z-Kill off worker threads (not below self.min).r   N)r   rv   r�   rn   ro   rm   r‘   Úappendrr   r†   rS   )r   r•   Ún_extraÚn_to_removeÚ_s        r   ÚshrinkzThreadPool.shrinkJ  s˜   € ð 	”#�d×-Ñ-Ó.Ñ.ˆØ× Ñ Ô"Ø�QŠ;Øô ”c˜$Ÿ-™-Ó(¨4¯8©8Ñ3°QÓ7ˆô ˜& 'Ó*ˆô
 �{Ó#ò 	.ˆAØ×#Ñ#×*Ñ*¨4Ô0Ø�K‰K�O‰OÔ,Õ-ñ	.r   c                 ó  — |�|dk  rd}t        j                  dd¬«       |€t        d«      }nt        j                  «       |z   }| j                  D ]!  }| j
                  j                  t        «       Œ# t        t        f}| j                  «       D ]j  }|xr |t        j                  «       z
  }	 |j                  |«       |j                  «       r+| j                  |j                  «       |j                  «        Œl y# |$ r Y Œuw xY w)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.é   )Ú
stacklevelre   )ÚwarningsÚwarningri   r*   ro   rr   r†   rS   rz   r@   Ú_clear_threadsÚjoinr‰   Ú_force_closer   )r   r…   ÚendtimeÚ_workerÚignored_errorsrš   Úremaining_times          r   ÚstopzThreadPool.stop`  sú   € ð Ð 7¨Q¢;ØˆGÜ×Ñð;àõð ˆ?Ü˜E“l‰Gä—i‘i“k GÑ+ˆGð —}‘}ò 	.ˆGØ�K‰K�O‰OÔ,Õ-ð	.ô äð
ˆð ×)Ñ)Ó+ò 		ˆFØ$Ò>¨´4·9±9³;Ñ)>ˆNðØ—‘˜NÔ+Ø—?‘?Ô$à×%Ñ% f§k¡kÔ2Ø—K‘K”Møñ		øð "ò Ùðús   Â1AD Ä DÄDc                 óø   — | j                   j                  ry 	 	 | j                  j                  t        j                  «       y # t
        $ r | j                  j                  «        Y y w xY w# t        $ r Y y w xY wr	   )r$   ÚclosedÚsocketÚshutdownÚSHUT_RDrl   ÚOSError)r   s    r   r©   zThreadPool._force_close�  sh   € ð �:‰:×ÒØð		ð'Ø—‘×$Ñ$¤V§^¡^Õ4øÜò 'à—‘×$Ñ$Ö&ð'ûô ò 	ñ ð	ús)   š)A Á#A*Á'A- Á)A*Á*A- Á-	A9Á8A9c                 óR   — | j                   dd g c}| j                   dd d„ |D «       S )z3Clear self._threads and yield all joinable threads.Nc              3   óL   K  — | ]  }|t        j                  «       ur|–— Œ y ­wr	   )r6   Úcurrent_thread)Ú.0Úthreads     r   ú	<genexpr>z,ThreadPool._clear_threads.<locals>.<genexpr>¡  s)   è ø€ ò 
àØœY×5Ñ5Ó7Ñ7ô ñ
ùs   ‚"$)ro   )r   Úthreadss     r   r§   zThreadPool._clear_threads�  s4   € ð %)§M¡M±!Ð$4°bÐ!ˆ�—‘™qÐ!ñ
à!ô
ð 	
r   c                 ó6   — | j                   j                  «       S )zReturn the queue size.)rr   Úqsizer|   s    r   r½   zThreadPool.qsize§  s   € ð �{‰{× Ñ Ó"Ð"r   N)é
   éÿÿÿÿr¿   r¾   )é   )r   r   r   r   r8   r}   Úpropertyr‚   r†   r�   r{   r’   r¡   r®   Ústaticmethodr   r©   r§   r½   r
   r   r   r   r   á   s‰   „ ñð ØØØ!ó06òdð ñ<ó ð<ò
Jò2ò	&òò.ó,+ðZ Øñó ó ðò
ð ñ#ó ñ#r   r   )r   rt   r‹   rD   rp   r±   r6   r*   r¥   Újaraco.functoolsr   Ú__all__r   r   ÚobjectrS   r7   r   r   r
   r   r   ú<module>rÆ      sj   ðñó Û Û Û Û Û Û Û å &ð )€÷ñ ñ ‹K€	á“8Ð ôx!�9×#Ñ#ô x!÷vI#ò I#r   