
    Vj                       d Z ddlm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dlmZmZ dZdZdZd	Zd
ZdZ G d de      ZefddZded	 	 	 	 	 	 	 	 	 ddZdded	 	 	 	 	 	 	 	 	 	 	 ddZej6                  d
eeeeed	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Zd dZd!dZd!dZe dk(  r ejB                   e              yy)"u  aria-atomic-write — 3-Layer atomic writes mit File-Lock + Retry.

Adopted aus Hermes `cron/jobs.py:430` + `cron/scheduler.py:1676` (siehe
`brain/02-Wissen/openclaw-hermes-code-spelunking-2026-05-13.md` §2).

Layer:
1. `tempfile.mkstemp` im selben Verzeichnis (kein cross-device move)
2. `f.flush()` + `os.fsync()` vor rename
3. `os.replace(tmp, target)` (POSIX-atomic)
4. optional `chmod` nach replace
5. `fcntl.flock(LOCK_EX | LOCK_NB)` für coordinated writes
6. Exponential-Backoff-Retry mit stale-timeout bei Lock-Contention

CLI:
    python3 aria-atomic-write.py write <path> < stdin
    python3 aria-atomic-write.py demo  # parallel-write smoke-test
    )annotationsN)Path)AnyIterator     皙?g       @Tg      .@c                      e Zd ZdZy)LockContentionz=Raised when a file-lock could not be acquired within retries.N)__name__
__module____qualname____doc__     '/root/aria/scripts/aria_atomic_write.pyr   r   '   s    Gr   r   c                   t        |       }|j                  j                  dd       t        j                  t        |j                        d|j                   dd      \  }}t        |      }	 t        j                  |d      5 }|j                  |       |j                          t        j                  |j                                ddd       t        j                  ||       t        j                  ||       y# 1 sw Y   6xY w# t        $ r@ t!        j"                  t$              5  |j'                          ddd        # 1 sw Y    xY ww xY w)zIAtomar Bytes nach `path` schreiben. mkstemp + fsync + os.replace + chmod.Tparentsexist_ok.z.tmp)dirprefixsuffixwbN)r   parentmkdirtempfilemkstempstrnameosfdopenwriteflushfsyncfilenochmodreplace	Exception
contextlibsuppressFileNotFoundErrorunlink)pathdatamodetargetfdtmp_strtmp_pathfs           r   atomic_write_bytesr7   +   s   $ZF
MMt4""6;;-q!KB
 G}H
YYr4  	!AGGDMGGIHHQXXZ 	! 	4 


8V$	! 	!    !23 	OO		s=   1D AD4D D
D "E/E	 	E	E	Ezutf-8)encodingr1   c               >    t        | |j                  |      |       y)z"Atomar Text nach `path` schreiben.r1   N)r7   encode)r/   contentr8   r1   s       r   atomic_write_textr=   B   s     tW^^H5DAr      F)indentensure_asciir1   c               P    t        j                  |||      }t        | ||       y)z"Atomar JSON nach `path` schreiben.)r?   r@   r:   N)jsondumpsr=   )r/   r0   r?   r@   r1   payloads         r   atomic_write_jsonrE   M   s"     jjf<HGdG$/r   )	exclusiveretries
base_delayfactor	randomizestale_secondsc             #    K   t        |       }|j                  j                  dd       |rt        j                  nt        j
                  }|t        j                  z  }|}	d}
t        |dz         D ]  }|j                         rg	 t        j                         |j                         j                  z
  }||kD  r2t        j                  t              5  |j                          ddd       	 t#        j$                  t'        |      t"        j(                  t"        j*                  z  d      }	 t        j0                  ||       	 t#        j6                  |t#        j8                          d
t        j                          dj;                                t#        j<                  |       d 	 t        j0                  |t        j>                         t#        j2                  |       t        j                  t              5  |j                          ddd        y t5        d| d|
       # 1 sw Y   IxY w# t         $ r Y Xw xY w# t         $ rC}|}
t        j,                  |	       |	|z  }	|r|	dt/        j.                         z   z  }	Y d}~d}~ww xY w# t         $ ru}t#        j2                  |       |}
||k(  rt5        d| d|dz    d	|       |t        j,                  |	       |	|z  }	|r|	dt/        j.                         z   z  }	Y d}~d}~ww xY w# 1 sw Y    yxY w# t#        j2                  |       t        j                  t              5  |j                          ddd       w # 1 sw Y   w xY wxY w# 	 t        j0                  |t        j>                         t#        j2                  |       t        j                  t              5  |j                          ddd       w # 1 sw Y   w xY w# t#        j2                  |       t        j                  t              5  |j                          ddd       w # 1 sw Y   w xY wxY wxY ww)u   File-Lock mit Exponential-Backoff. Stale-Lock-Recovery: wenn Lock-Datei
    älter als `stale_seconds` ist, wird sie ignoriert (Crashed-Holder-Recovery).
    Tr   N   r   g      ?zlock not acquired on z after z attempts: @
z: ) r   r   r   fcntlLOCK_EXLOCK_SHLOCK_NBrangeexiststimestatst_mtimer+   r,   r-   r.   OSErrorr"   openr    O_CREATO_WRONLYsleeprandomflockcloser   r$   getpidr;   r&   LOCK_UN)	lock_pathrF   rG   rH   rI   rJ   rK   lpflagdelaylast_errattemptager3   excs                  r   	file_lockrk   Z   sP     
iBIIOOD4O0%5==5==DEMMDE%)H1% ,99;iikBGGI$6$66&#,,->? $		$	R"**r{{":EBB	KKD!
	 HHRBIIK=$))+b9@@BCHHRL B.(():;  IIK Y,Z 0BxjA
BBO$ $   	HJJuVOEv}}..	  	HHRLH'!$+B4ww{m;seT JJuVOEv}}..	*  (():;  IIK     	 B.(():;  IIK      (():;  IIK     s)  BQAH9H,%H9.?I	.JA'M>-$L&.Q?LQ,H6	1H99	IQIQ		J8J
QJQ	L!A*LQLQL#	Q&/M;M/	&	M;/M84M;;Q>Q $O8$.QO,	#	Q,O51Q8/Q	'Q8	Q	Q
Q	QQc                    t         j                  j                         }t        | |       t	        d|  dt        |       dt         j                         y)Nzwrote z (z chars)filer   )sysstdinreadr=   printlenstderr)r2   r<   s     r   
_cli_writeru      s@    iinnGfg&	F6("S\N'
2Dr   c                 n   dd l } t        d      t        d      j                  j                  dd       t	        j
                  t              5  j                          d d d        dfd}t        d      D cg c]  }| j                  |d| f	       }}|D ]  }|j                           |D ]  }|j                           t        d
       t        j                                t        dt        j                         j                                       y# 1 sw Y   xY wc c}w )Nr   z/tmp/aria-atomic-demo/out.txtz/tmp/aria-atomic-demo/.out.lockTr   c           	        t              5  j                         rj                         nd}t        j                  d       t        ||  dt        j                          dz          d d d        y # 1 sw Y   y xY w)N r	   -rO   )rk   rU   	read_textrV   r]   r=   r"   ra   )tagexistinglockr2   s     r   workerz_cli_demo.<locals>.worker   si    t_ 	K-3]]_v'')"HJJtfhC5"))+b1I&IJ	K 	K 	Ks   AA55A>   P)r2   argsz--- demo output ---zline count: )r{   r    returnNone)multiprocessingr   r   r   r+   r,   r-   r.   rT   Processstartjoinrr   rz   rs   
splitlines)mpr~   iprocspr}   r2   s        @@r   	_cli_demor      s    12F12D
MMt4			.	/ K BGqJARZZvqWJZ7JEJ 		 		
 	&


	LV--/::<=>
?@#  Ks   D& D2&D/c                    t        t        j                        dk  rt        t               yt        j                  d   } | dk(  rTt        t        j                        dk  rt        dt        j
                         yt        t        j                  d         S | dk(  r
t               S t        d|  t        j
                         y)	Nr>   rM   r$      z(usage: aria-atomic-write.py write <path>rm   demozunknown command: )rs   ro   argvrr   r   rt   ru   r   )cmds    r   mainr      s    
388}qg
((1+C
g~sxx=1<3::N#((1+&&
f}{	cU
##**5r   __main__)r/   
Path | strr0   bytesr1   intr   r   )
r/   r   r<   r    r8   r    r1   r   r   r   )r/   r   r0   r   r?   r   r@   boolr1   r   r   r   )rc   r   rF   r   rG   r   rH   floatrI   r   rJ   r   rK   r   r   zIterator[None])r2   r    r   r   )r   r   )"r   
__future__r   r+   rP   rB   r"   r^   ro   r   rV   pathlibr   typingr   r   DEFAULT_MODEDEFAULT_RETRIESDEFAULT_BASE_DELAYDEFAULT_FACTORDEFAULT_RANDOMIZEDEFAULT_STALE_SECONDSRuntimeErrorr   r7   r=   rE   contextmanagerrk   ru   r   r   r   exitr   r   r   <module>r      s  " #    	  
        H\ H CO 6 B
BB 	B
 B 
B 
0

0

0 	
0
 
0 
0 

0  "*"'0@C@C @C 	@C
 @C @C @C @C @C @CH4  zCHHTV r   