+
    jHàjdQ  ã                  óh  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIH	t	 ^ RI
HtHtHtHtHtHt ^ RIHt ]'       d   ^ RIHt ]P,                  ! ]4      t ! R R4      t ! R	 R
4      t]P6                  ! 4       t/ tR]R&   / tR]R&   / t R]R&   / t!R]R&   / t"R]R&   R R lt#R R lt$R R lt%R R lt&R R lt'R R  lt(R!R/R" R# llt)R$ R% lt*R& R' lt+R?R( R) llt,R* R+ lt-R, R- lt.R. R/ lt/R0 R1 lt0R2 R3 lt1R4R/R5 R6 llt2R7 R8 lt3]Ph                  R9 R: l4       t5R; R< lt6R= R> lt7R# )@a«  Process-wide shared SessionDB registry.

Each bare ``SessionDB()`` mints its own writer connection, lock, close-time WAL checkpoint
and token writer thread, and one connection's close-time checkpoint can race another's
growth (lost/reordered-page-write corruption). This module owns that boundary: one shared
``SessionDB`` per resolved path per process, refcounted, with generation-aware retirement
when the file is replaced (snapshot restore, recovery swap).

Lifecycle rules:
- ``acquire(path)`` returns the current generation for *path* and bumps its refcount.
- ``close()`` on a shared instance RELEASES one refcount instead of tearing the
  connection down: the registry owns the physical lifecycle and only closes on the
  final release, so legacy call sites return their reference instead of leaking it.
- ``release(db)`` decrements the generation *db was acquired from* (object-keyed, so an
  inode replacement cannot strand a still-owned generation); the final release of a
  retired generation tears it down.
- On inode change the old generation is RETIRED (never lent again) but stays alive until
  its holders release. If the replacement open fails the registry keeps NO path entry.
- All teardown happens OUTSIDE the registry lock: a final release's WAL checkpoint must
  never stall acquisition for every state.db.
- A final close/checkpoint is serialized with the next open for the same path; no new
  generation is published while the previous generation is still tearing down.
- A path can have SEVERAL closes admitted at once (the current generation's final release
  plus a retired generation's drain). The path barrier COUNTS them and is lifted only by
  the last one to settle, so neither ``acquire`` nor ``close_all`` / ``close_all_under``
  can escape while any handle for that path is still inside checkpoint/WAL-unlink.
- Maintenance callers borrow handles with a temporary registry reference instead of
  iterating an unpinned snapshot.
)ÚannotationsN)ÚPath)ÚTYPE_CHECKINGÚDictÚIteratorÚListÚOptionalÚTuple)Ústat_db_file_identity©Ú	SessionDBc                  ó*   € ] tR t^0tRtRtR R ltRtR# )Ú_TeardownBarrieraG  Accounting for every admitted-but-unfinished physical close of one path.

A path can own more than one close at a time: the current generation's final
release and a retired generation's drain are admitted independently under
``_lock`` and only meet at the lifecycle mutex. One event per path is honest
only if the LAST admitted teardown settles it. Signalling on the first lets
``close_all()`` return and ``acquire()`` publish a replacement while an older
handle is still inside ``PRAGMA wal_checkpoint``/sidecar unlink -- the exact
overlap (#102827) this registry exists to forbid.
c               ó   € V ^8„  d   QhRR/# )é   ÚreturnÚNone© )Úformats   "Ú:/home/ubuntu/.hermes/hermes-agent/hermes_state_registry.pyÚ__annotate__Ú_TeardownBarrier.__annotate__>   s   € ÷ ñ ˜$ñ ó    c                	óH   € \         P                  ! 4       V n        ^ V n        R# )é    N)Ú	threadingÚEventÚeventÚpending)Úselfs   &r   Ú__init__Ú_TeardownBarrier.__init__>   s   € Ü—_’_Ó&ˆŒ
ØˆŽr   )r   r   N©Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú	__slots__r    Ú__static_attributes__r   r   r   r   r   0   s   † ñ	ð %€I÷ñ r   r   c                  ó*   € ] tR t^CtRtRtR R ltRtR# )Ú_GenerationzCOne shared SessionDB generation: instance, refcount, file identity.c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úpathr   Údbr   ÚidentityzOptional[tuple[int, int]]r   r   r   )r   s   "r   r   Ú_Generation.__annotate__H   s*   € ÷ ñ ˜Tð  yð Ð<Uð ÐZ^ñ r   c                	óF   € Wn         W n        ^V n        W0n        RV n        R# )é   FN)r-   r.   Úrefcountr/   Úretired)r   r-   r.   r/   s   &&&&r   r    Ú_Generation.__init__H   s   € ØŒ	ØŒØˆŒØ ŒØˆŽr   )r.   r/   r-   r3   r4   Nr"   r   r   r   r+   r+   C   s   † ÙMàA€I÷ñ r   r+   zdict[Path, _Generation]Ú_generationszdict[int, _Generation]Ú_retiredzdict[Path, threading.Event]Ú_openingúdict[Path, _TeardownBarrier]Ú_tearing_downzdict[Path, threading.Lock]Ú_path_lifecycle_locksc               ó    € V ^8„  d   QhRRRR/# )r   r-   r   r   r   r   )r   s   "r   r   r   e   s   € ÷ #ñ #˜4ð # Iñ #r   c                ó    € ^ RI Hp V! V R7      # )zVConstruct the SessionDB for *path* (call-time import avoids cycles; tests patch this).r   )Údb_path)Úhermes_stater   )r-   r   s   & r   Ú_open_session_dbr@   e   s   € å&á˜TÔ"Ð"r   c               ó    € V ^8„  d   QhRRRR/# ©r   r.   r   r   r   r   )r   s   "r   r   r   l   s   € ÷ 9ñ 9�)ð 9 ñ 9r   c                ó¨   € \         P                  ! \        4      ;_uu_ 4        RV n        RRR4       \	        V R4       R#   + '       g   i     L; i)z@Close a shared instance, clearing its registry-owned flag first.FNzError closing shared SessionDB)Ú
contextlibÚsuppressÚ	ExceptionÚ_shared_registry_ownedÚ_close_quietly©r.   s   &r   Ú	_teardownrJ   l   s4   € ä	×	Ò	œY×	'Õ	'Ø$)ˆÔ!÷ 
(ä�2Ð7Ö8÷ 
(×	'ús   £AÁA	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r.   r   Údebug_messageÚstrr   r   r   )r   s   "r   r   r   s   s!   € ÷ 
7ñ 
7�yð 
7°ð 
7¸ñ 
7r   c                ó  €  V P                  4        R#   \         d`   p^ RIHp \	        Y#4      '       d'   \
        P                  R\        T 4      T4        Rp?R# \
        P                  TRR7        Rp?R# Rp?ii ; i)z·close() that never propagates. A lost WAL generation whose capture failed is data at risk,
not teardown noise: the handle stays open and the operator has to act, so that one surfaces.)ÚRetiredGenerationCaptureErrorz,SessionDB for %s did not settle at close: %sT)Úexc_infoN)	ÚcloserF   Úhermes_state_dbfilerO   Ú
isinstanceÚloggerÚerrorÚ_db_path_ofÚdebug)r.   rL   ÚexcrO   s   &&  r   rH   rH   s   s[   € ð7Ø
�‰Ž
øÜô 7ÝEÜ�c×9Ò9Ü�L‰LÐGÌÐUWËÐZ]×^Ò^ä�L‰L˜°ˆL×6Ò6ûð7ús   ‚ ”A>Ÿ7A9ÁA9Á9A>c               ó    € V ^8„  d   QhRRRR/# )r   r-   r   r   zthreading.Lockr   )r   s   "r   r   r   €   s   € ÷ ñ  dð ¨~ñ r   c                ót   € \         P                  V 4      pVf   \        P                  ! 4       pV\         V &   V# )z?Return the lifecycle mutex for *path* (caller holds ``_lock``).)r;   Úgetr   ÚLock)r-   Úlocks   & r   Ú_path_lifecycle_lock_lockedr^   €   s3   € ä ×$Ñ$ TÓ*€DØ‚|Ü�~Š~ÓˆØ&*Ô˜dÑ#Ø€Kr   c               ó    € V ^8„  d   QhRRRR/# )r   r-   r   r   r   r   )r   s   "r   r   r   ‰   s   € ÷ ñ  ð Ð*:ñ r   c                ó�   € \         P                  V 4      pVf   \        4       ;p\         V &   V;P                  ^,          un        V# )z÷Register one pending physical close for *path* (caller holds ``_lock``).

Admission shares the lock section that removes the generation, so a peer
release, ``acquire`` or ``close_all`` taking the lock next always sees this
teardown accounted for.
)r:   r[   r   r   ©r-   Úbarriers   & r   Ú_admit_teardown_lockedrc   ‰   s>   € ô ×Ñ Ó%€GØ‚Ü(8Ó(:Ð:ˆ”- Ñ%Ø‡O‚O�qÕ…OØ€Nr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r-   r   rb   r   r   r   r   )r   s   "r   r   r   —   s"   € ÷ ñ ˜4ð Ð*:ð ¸tñ r   c                óX  € \         ;_uu_ 4        V;P                  ^,          un        VP                  ^ 8”  d    RRR4       R# \        P                  V 4      VJ d   \        P	                  V R4       VP
                  P                  4        RRR4       R#   + '       g   i     R# ; i)zGSettle one admitted teardown; only the last one lifts the path barrier.N)Ú_lockr   r:   r[   Úpopr   Úsetra   s   &&r   Ú_finish_teardownri   —   sl   € ç	ŽØ�Š˜1Õ�Ø�?‰?˜QÔØ÷ 
‰ô ×Ñ˜TÓ" gÓ-Ü×Ñ˜d DÔ)Ø�‰×ÑÔ÷ 
��Šús   �,BÁA	BÂB)	rb   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r-   r   r.   r   rb   zOptional[_TeardownBarrier]r   r   r   )r   s   "r   r   r   ¢   s0   € ÷ ,ñ ,Ø
ð,àð,ð (ð	,ð
 
ñ,r   c               ó   € \         ;_uu_ 4        \        V 4      pRRR4        X;_uu_ 4        \        V4       RRR4       Ve   \        W4       R# R#   + '       g   i     LB; i  + '       g   i     L6; i  Te   \        Y4       i i ; i)zHClose *db* under its path lifecycle mutex, then settle its barrier slot.N)rf   r^   rJ   ri   )r-   r.   rb   Úlifecycle_locks   &&$ r   Ú_teardown_generationrm   ¢   si   € ÷ 
ŽÜ4°TÓ:ˆ÷ 
ð,ßŠ^Ü�bŒM÷ ð ÒÜ˜TÖ+ñ ÷ 
�ú÷ �^ûð ÒÜ˜TÕ+ð ús,   �A¤
A; ®A(ºA; ÁA%	Á(A8	Á3A; Á;Bc               ó    € V ^8„  d   QhRRRR/# )r   r.   r   r   úOptional[Path]r   )r   s   "r   r   r   ³   s   € ÷ ñ �Ið  .ñ r   c                óp   € \        V RR4      p Vf   R# \        V4      #   \        \        3 d     R# i ; i)z7``Path(db.db_path)`` or None when absent/unconvertible.r>   N)Úgetattrr   Ú	TypeErrorÚ
ValueError)r.   r-   s   & r   rV   rV   ³   s?   € ä�2�y $Ó'€DðØ’|ˆtÐ3¬¨d«Ð3øÜ”zÐ"ô Úðús   �  •
   5´5c               ó$   € V ^8„  d   QhRRRRRR/# )r   r-   r   Úopeningzthreading.Eventr   r   r   )r   s   "r   r   r   ¼   s!   € ÷ ñ ˜$ð ¨ð ¸Tñ r   c                ó„   € \         P                  V 4      VJ d   \         P                  V R4       VP                  4        R# )zLDrop the per-path construction marker and wake waiters (caller holds _lock).N)r8   r[   rg   rh   )r-   ru   s   &&r   Ú_finish_openingrw   ¼   s*   € ä‡|�|�DÓ˜WÓ$Ü�‰�T˜4Ô Ø‡K�K†Mr   c               ó    € V ^8„  d   QhRRRR/# )r   r>   ro   r   r   r   )r   s   "r   r   r   Ã   s   € ÷ Nñ N�^ð N¨yñ Nr   c                ó  € ^ RI Hp V e   \        V 4      M\        V! 4       4      p VP                  4       p Rp\
        ;_uu_ 4        \        P                  V4      pVeˆ   \        V4      pVeJ   VP                  e<   WeP                  8w  d,   RVn
        \        V V\        \        VP                  4      &   M/V;P                  ^,          un        VP                  uuRRR4       # \        P                  V4      pVe   VP                   pME\"        P                  V4      pVf+   \$        P&                  ! 4       ;p\"        V&   \)        V4      p	MTpRRR4       Ve   VP+                  4        EK<   X	;_uu_ 4        \-        V4      p
RV
n        \        V4      pRRR4       \
        ;_uu_ 4        \        P                  T4      pTfV   \        P                  T4      pTe'   T;P                  ^,          un        TP                  pM\5        TX
X4      \        T&   T
p\3        TX4       RRR4       Xe*   \7        TX
4       TP                   P+                  4        EK+  XX
Jd   \7        Y:4       T#   \         d    Tp ELNi ; i  + '       g   i     EL>; i  + '       g   i     EL
; i  \0         d9    \
        ;_uu_ 4        \3        TX4       RRR4       h   + '       g   i     h ; ii ; i  + '       g   i     LÒ; i)ah  Return the shared SessionDB for *db_path*, incrementing its refcount. If the file was
replaced (different inode) since the generation opened, that generation is RETIRED
but stays alive for its holders, and a fresh one is opened in its place. Raises
whatever ``SessionDB.__init__`` raises; on a replacement-open failure the registry
holds NO entry for the path.)Ú_default_db_pathNT)r?   rz   r   ÚresolveÚOSErrorrf   r6   r[   Ú_stat_db_file_identityr/   r4   r7   Úidr.   r3   r:   r   r8   r   r   r^   Úwaitr@   rG   ÚBaseExceptionrw   r+   rm   )r>   rz   Úraw_pathr-   Úwait_forÚ
generationÚcurrentÚteardownru   rl   r.   r/   ÚexistingÚwinners   &             r   Úacquirerˆ   Ã   sv  € õ .à 'Ò 3Œt�GŒ}¼Ñ>NÓ>PÓ9Q€HðØ×ÑÓ!ˆð Ø.2ˆßŽUÜ%×)Ñ)¨$Ó/ˆJØÒ%Ü0°Ó6�ØÒ&¨:×+>Ñ+>Ò+JÈw×ZmÑZmÔOmð *.�JÔ&Ü$ TÐ*Ø2<”HœR 
§¡Ó.Ò/à×'Ò'¨1Õ,Õ'Ø%Ÿ=™=÷ ŠUô %×(Ñ(¨Ó.ˆHØÒ#Ø#Ÿ>™>‘ä"Ÿ,™, tÓ,�Ø’?Ü/8¯ªÓ/@Ð@�Gœh t™nÜ%@ÀÓ%F‘Nà&�H÷/ ð0 Òð �M‰MŒOÚð	ß’Ü% dÓ+�Ø,0�Ô)Ü1°$Ó7�÷  ÷ ŽUÜ$×(Ñ(¨Ó.ˆHØÒÜ'×+Ñ+¨DÓ1�ØÒ'Ø×%Ò%¨Õ*Õ%Ø%Ÿ[™[‘Fä)4°T¸2¸xÓ)H”L Ñ&Ø�FÜ˜D 'Ô*÷ ð Òô !  rÔ*Ø�N‰N×ÑÔ!ÚØ˜ÓÜ  Ô*ØˆøôG ô Ø‹ðú÷
 �UˆUú÷B  —�ûô ô 	ß–Ü  gÔ.÷ à÷ –àúð	ú÷
 �Uúst   §I5 ÁBJ	Ã)A+J	Å4
J1 Å>JÆJ1 Æ2A;K7É5JÊJÊ	J	ÊJ.	Ê(J1 Ê.J1 Ê1K4Ë
K Ë	K4Ë K0Ë+	K4Ë7L	c               ó    € V ^8„  d   QhRRRR/# )r   r.   r   r   Úboolr   )r   s   "r   r   r     s   € ÷ !ñ !�	ð !˜dñ !r   c                óî  € V f   R# \        V 4      pRp\        ;_uu_ 4        \        P                  V4      pVfO   \	        V 4      pVf    RRR4       R# \
        P                  V4      pVe   VP                  V Jd    RRR4       R# V;P                  ^,          un        VP                  ^ 8*  pV'       d‚   VP                  '       d   \        P                  VR4       MC\
        P                  VP                  4      VJ d!   \
        P                  VP                  R4       \        VP                  4      pRRR4       X'       d   \        XP                  WR7       R#   + '       g   i     L1; i)aK  Decrement the refcount of a shared SessionDB. ``True`` if *db* was shared; ``False``
if it is not registry-managed (caller owns close()). The final release tears the
generation down OUTSIDE the registry lock. Lookup is object-keyed, so holders of an
old generation release into its retired record, not into whatever the path names.NF)rb   T)r~   rf   r7   r[   rV   r6   r.   r3   r4   rg   r-   rc   rm   )r.   ÚkeyÚteardown_barrierrƒ   r-   Úneeds_teardowns   &     r   Úreleaser�     s  € ð
 
‚zÙÜ
ˆR‹&€CØ37Ðß	ŽÜ—\‘\ #Ó&ˆ
ØÒÜ˜r“?ˆDØŠ|Ø÷ 
‰ô &×)Ñ)¨$Ó/ˆJØÒ! Z§]¡]¸"Ó%<à÷ 
‰ð 	×Ò˜qÕ ÕØ#×,Ñ,°Ñ1ˆßØ×!×!Ð!Ü—‘˜S $Õ'Ü×!Ñ! *§/¡/Ó2°jÓ@Ü× Ñ  §¡°$Ô7ô  6°j·o±oÓFÐ÷' 
÷, Ü˜ZŸ_™_¨bÕKÙ÷1 
�ús$   ¢*E$Á*E$Â
/E$Â:E$ÃA/E$Å$E4	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r-   r   Úrootr   rŠ   r   )r   s   "r   r   r   8  s&   € ÷ Jñ J˜ð J Tð J¨dñ Jr   c                ó  €  \         P                  P                  \        V P	                  4       4      4      p\         P                  P                  \        VP	                  4       4      4      pW#8H  ;'       g'    VP                  V\         P                  ,           4      #   \
         dT    \         P                  P                  \        T 4      4      p\         P                  P                  \        T4      4      p L�i ; i)zDTrue when *path* is *root* or a file inside it (normcase, resolved).)Úosr-   ÚnormcaserM   r{   r|   Ú
startswithÚsep)r-   r‘   Úpath_keyÚroot_keys   &&  r   Ú_path_is_underr™   8  s­   € ð/Ü—7‘7×#Ñ#¤C¨¯©«Ó$7Ó8ˆÜ—7‘7×#Ñ#¤C¨¯©«Ó$7Ó8ˆð Ñ×IÐI 8×#6Ñ#6°xÄ"Ç&Á&Õ7HÓ#IÐIøô ô /Ü—7‘7×#Ñ#¤C¨£IÓ.ˆÜ—7‘7×#Ñ#¤C¨£IÓ.Šð/ús   ‚A,B  Â AC>Ã=C>c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úgenerationszlist[_Generation]Úteardown_barriersr9   Úactive_teardownszlist[_TeardownBarrier]r   Úintr   )r   s   "r   r   r   C  s0   € ÷ ñ Ø"ðà3ðð -ðð 	ñ	r   c                óB  € / pV  F.  pVP                  VP                  . 4      P                  V4       K0  	  VP                  4        Fk  w  rV\        ;_uu_ 4        \        V4      pRRR4        X;_uu_ 4        V F  p\        VP                  4       K  	  RRR4       \        WQV,          4       Km  	  V F  pVP                  P                  4        K  	  \        V 4      #   + '       g   i     L†; i  + '       g   i     Lg; i  \        YQT,          4       i ; i)zSClose *generations* outside the registry lock; wait for already-admitted teardowns.N)Ú
setdefaultr-   ÚappendÚitemsrf   r^   rJ   r.   ri   r   r   Úlen)	r›   rœ   r�   Úby_pathrƒ   r-   Úpath_generationsrl   rb   s	   &&&      r   Ú_teardown_swept_generationsr¦   C  sÔ   € ð .0€GÛ!ˆ
Ø×Ñ˜:Ÿ?™?¨BÓ/×6Ñ6°zÖBñ "à")§-¡-¦/ÑˆßŽUÜ8¸Ó>ˆN÷ ð	<ß’Û"2�JÜ˜jŸm™mÖ,ñ #3÷  ô ˜T°TÕ#:Ö;ñ #2ó $ˆØ�‰×ÑÖñ $äˆ{ÓÐ÷ �Uú÷  —ûô ˜T°TÕ#:Õ;ús0   ÁC$Á/
D
Á9C7ÂD
Ã$C4Ã7DÄD
Ä
Dc               ó   € V ^8„  d   QhRR/# )r   r   rž   r   )r   s   "r   r   r   Z  s   € ÷ Yñ Y�3ñ Yr   c                 ó  € / p \         ;_uu_ 4        \        \        P                  4       4      p\        \        P                  4       4      \        \
        P                  4       4      ,           pV Uu0 uF  q3P                  kK  	  up F  p\        V4      W&   K  	  \        P                  4        \
        P                  4        V F
  pRVn	        K  	  RRR4       \        XV X4      # u upi   + '       g   i     L"; i)z’Close every shared SessionDB regardless of refcount; returns the count. For gateway
shutdown, after all agents and cron jobs finished. Idempotent.TN)rf   Úlistr:   Úvaluesr6   r7   r-   rc   Úclearr4   r¦   )rœ   r�   r›   rƒ   r-   s        r   Ú	close_allr¬   Z  s¿   € ð 79Ðß	ŽÜ¤× 4Ñ 4Ó 6Ó7ÐÜœ<×.Ñ.Ó0Ó1´D¼¿¹Ó9JÓ4KÕKˆÙ7BÓC±{¨—_”_±{ÔCˆDÜ&<¸TÓ&BÐÓ#ñ Dä×ÑÔÜ�‰ÔÛ%ˆJØ!%ˆJÖñ &÷ 
ô ' {Ð4EÐGWÓXÐXùò D÷ 
�ús   ‘A!C/Á2C*ÂAC/Ã*C/Ã/C?	c               ó    € V ^8„  d   QhRRRR/# )r   Ú	directoryz
str | Pathr   rž   r   )r   s   "r   r   r   j  s   € ÷ $Yñ $Y˜zð $Y¨cñ $Yr   c           
     óÞ  €  \        V 4      P                  4       P                  4       p/ p\        ;_uu_ 4        \        \        P                  4       4      \        \        P                  4       4      ,            Uu. uF#  p\        VP                  V4      '       g   K!  VNK%  	  pp\        P                  4        UUu. uF  w  rV\        WQ4      '       g   K  VNK  	  pppV Uu0 uF  q3P                  kK  	  ppV F  p\        V4      W%&   K  	  V Fv  pRVn        \        P                  VP                  4      VJ d!   \        P!                  VP                  R4       \        P!                  \#        VP$                  4      R4       Kx  	  RRR4       \'        XVX4      #   \         d    \        T 4      P                  4       p ELŸi ; iu upi u uppi u upi   + '       g   i     LX; i)a1  Force-close every shared SessionDB whose file lives under *directory*; returns the count.

Profile delete rmtree (and a same-name recreate) fails while this process still holds
``state.db``. Same contract as ``MemoryStore.release_all_under``: a live holder is
expected to fail afterward; a process that holds none is a no-op returning 0.

A final ``release()`` can drop the generation and admit teardown before the physical
close finishes. Wait for those directory-matching barriers even when no generation
remains, otherwise rmtree still sees the open handle.
TN)r   Ú
expanduserr{   r|   rf   r©   r6   rª   r7   r™   r-   r:   r¢   rc   r4   r[   rg   r~   r.   r¦   )	r®   r‘   rœ   rƒ   r›   r-   rb   r�   Úselected_pathss	   &        r   Úclose_all_underr²   j  sŽ  € ð,Ü�I‹×)Ñ)Ó+×3Ñ3Ó5ˆð 79Ðß	Žô #¤<×#6Ñ#6Ó#8Ó9¼DÄÇÁÓARÓ<SÖSó
áS�
Ü˜jŸo™o¨t×4÷ ˆJÙSð 	ð 
ô *7×)<Ñ)<Ô)>ô
Ù)>™˜Ü˜d×)÷ ˆGÑ)>ð 	ñ 
ñ =HÓH¹K¨jŸ/œ/¹KˆÐHÛ"ˆDÜ&<¸TÓ&BÐÓ#ñ #ã%ˆJØ!%ˆJÔÜ×Ñ 
§¡Ó0°JÓ>Ü× Ñ  §¡°$Ô7Ü�L‰Lœ˜JŸM™MÓ*¨DÖ1ñ	 &÷ 
ô( ' {Ð4EÐGWÓXÐXøô/ ô ,Ü�I‹×)Ñ)Ó+‹ð,üò
ùó
ùò I÷ 
�úsT   ‚'F! ¹AGÁ;GÂGÂ$GÂ=G
ÃG
ÃGÃ$GÃ8BGÆ!$G	ÇG	ÇGÇG,	Úexcludec               ó$   € V ^8„  d   QhRRRRRR/# )r   r>   r   r³   zOptional[SessionDB]r   z	list[str]r   )r   s   "r   r   r   ‘  s$   € ÷ 
ñ 
Øð
Ø2ð
àñ
r   c               ó¨  €  \        V 4      P                  4       p\        ;_uu_ 4        \        P                  4        Uu. uFL  pVP                  VJg   K  VP                  V8X  g   K(  VP                  '       d   K<  RVP                   R2NKN  	  upuuRRR4       #   \         d    \        T 4      p Lœi ; iu upi   + '       g   i     R# ; i)uÄ  Describe every other LIVE SessionDB generation THIS process holds for *db_path*.

The registry is path-keyed, so it can answer the in-process half of "is this store quiet?"
that a ``/proc`` descriptor scan structurally cannot: that scan skips our own pid, so it only
ever proves other PROCESSES are away.

RETIRED generations are deliberately not holders here. A generation is retired only after its
file was replaced, which is exactly when ``SessionDB`` fences it: every write raises
``StateDbReplacedError`` and the close-time checkpoint is disabled, so it is not the live writer
this gate protects. It also leaves ``_retired`` only when its last holder releases, and a
gateway handle does not release before shutdown â€” counting it made ONE inode replacement
(recovery swap, backup restore, snapshot) skip auto-VACUUM for that path for the rest of the
process lifetime, turning the unbounded growth this maintenance exists to bound into a
permanent condition.
z/in-process live SessionDB generation (refcount Ú)N)
r   r{   r|   rf   r6   rª   r.   r-   r4   r3   )r>   r³   r-   rƒ   s   &$  r   Úother_generations_for_pathr·   ‘  s»   € ð$Ü�G‹}×$Ñ$Ó&ˆ÷ 
Žô +×1Ñ1Ô3ó
á3�
Ø�}‰} GÐ+ô Uð —‘ 4Ñ'ô Uð ×&Õ&ô	 UÐ=¸j×>QÑ>QÐ=RÐRSÓTÙ3ñ
÷ 
Šøô ô Ü�G‹}Šðüò
÷ 
�ˆús@   ‚B ©C Á B;ÁB;Á*B;Á>B;ÂC ÂB8Â7B8Â;C Ã C	c               ó   € V ^8„  d   QhRR/# )r   r   zlist[SessionDB]r   )r   s   "r   r   r   ±  s   € ÷ Fñ F ñ Fr   c                 óè   € \         ;_uu_ 4        \        P                  4        U u. uF"  q P                  '       d   K  V P                  NK$  	  up uuRRR4       # u up i   + '       g   i     R# ; i)zËSnapshot of every live (non-retired) shared SessionDB (refcounts untouched), for
in-process maintenance. A concurrent final release may close an instance, in which
case the callee sees ``_conn is None``.N)rf   r6   rª   r4   r.   )Úgs    r   Úlive_shared_session_dbsr»   ±  sD   € ÷ 
ŽÜ*×1Ñ1Ô3ÓEÑ3˜¿9½9”�—”Ñ3ÑE÷ 
ŠùÚE÷ 
�ˆús!   �A ¦A¾AÁA ÁA Á A1	c               ó   € V ^8„  d   QhRR/# )r   r   zIterator[list[SessionDB]]r   )r   s   "r   r   r   º  s   € ÷ ñ Ð(Añ r   c               #  óâ  "  € \         ;_uu_ 4        \        P                  4        U u. uF  q P                  '       d   K  V NK  	  pp V U u. uF  q P                  NK  	  pp V F  p V ;P
                  ^,          un        K  	  RRR4        Xx € \        V4       F  p\        V4       K  	  R# u up i u up i   + '       g   i     L>; i  \        X4       F  p\        T4       K  	  i ; i5i)a¢  Borrow live handles with registry references pinned for the whole block.

Maintenance must not operate on the unowned snapshot returned by
:func:`live_shared_session_dbs`: the last real owner could otherwise
release and physically close the connection between the snapshot and the
maintenance call. Each borrowed generation gets one temporary reference;
the ``finally`` block releases it even when maintenance raises.
N)rf   r6   rª   r4   r.   r3   Úreversedr�   )rƒ   Úborrowed_generationsÚborrowedr.   s       r   Úborrow_live_shared_session_dbsrÁ   ¹  sÀ   é € ÷ 
Žä)5×)<Ñ)<Ô)>ó 
Ù)>˜:×FXÕFX�JˆJÑ)>ð 	ð  
ñ 5IÓIÑ4H j—M”MÑ4HˆÐIÛ.ˆJØ×Ò 1Õ$×ñ /÷ 
ðØŠä˜8Ö$ˆBÜ�BŽKó %ùò 
ùò J÷	 
�ûô ˜8Ö$ˆBÜ�BŽKò %üsW   ‚C/‘B:¨B0Á B0ÁB:ÁB5Á $B:ÂC/ÂC ÂC/Â0
B:Â:C
	ÃC/ÃC,Ã,C/c               ó   € V ^8„  d   QhRR/# )r   r   zdict[str, int]r   )r   s   "r   r   r   Ñ  s   € ÷ 
ñ 
ˆ~ñ 
r   c                 óä   € \         ;_uu_ 4        R\        \        4      R\        \        4      R\	        R \        P                  4        4       4      /uuRRR4       #   + '       g   i     R# ; i)z?Registry census for tests and diagnostics (no locks held long).Úlive_generationsÚretired_generationsÚtotal_refcountsc              3  ó8   "  € T F  qP                   x € K  	  R # 5i©N)r3   )Ú.0rº   s   & r   Ú	<genexpr>Ústats.<locals>.<genexpr>Ö  s   é € Ð"MÑ7L°!§:¦:Ó7Lùs   ‚N)rf   r£   r6   r7   Úsumrª   r   r   r   ÚstatsrÍ   Ñ  sD   € ç	Žà¤¤LÓ 1Ð3HÌ#ÌhË-ØœsÑ"M´|×7JÑ7JÔ7LÓ"MÓMð
÷ 
��‹ús   �AAÁA/	c               ó    € V ^8„  d   QhRRRR/# rB   r   )r   s   "r   r   r   Ú  s   € ÷ Eñ E˜ð E tñ Er   c                óD   € \        V 4      '       g   \        V R4       R# R# )z¤Release a shared instance, or close it when it is not registry-managed. Drop-in for a
plain ``db.close()``: read-only opens, CLI one-shots and test fakes fall back.z&release_or_close fallback close failedN)r�   rH   rI   s   &r   Úrelease_or_closerÐ   Ú  s   € ô �2�;Š;Ü�rÐCÖDñ r   rÈ   )8Ú__conditional_annotations__r'   Ú
__future__r   rD   Úloggingr“   r   Úpathlibr   Útypingr   r   r   r   r   r	   Úhermes_state_commonr
   r}   r?   r   Ú	getLoggerr#   rT   r   r+   r\   rf   r6   Ú__annotations__r7   r8   r:   r;   r@   rJ   rH   r^   rc   ri   rm   rV   rw   rˆ   r�   r™   r¦   r¬   r²   r·   r»   ÚcontextmanagerrÁ   rÍ   rÐ   )rÑ   s   @r   Ú<module>rÚ      s5  øðôõ< #ã Û Û 	Û Ý ß G× Gå OçÝ&à	×	Ò	˜8Ó	$€÷ñ ÷&
ñ 
ð 	�ŠÓ€ð )+€Ð%Ó *Ø#%€Ð
 Ó %ð )+€Ð
%Ó *ð /1€Ð+Ó 0ð 57Ð Ð1Ó 6õ#õ9õ
7õõõð,ð +/÷	,õ"õ÷Nõb!õHJõõ.Yõ $YðN
Ø59÷
õ@Fð ×Ñôó ðõ.
÷Er   