From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master
---
jnpf-biz-common/jnpf-audit-sdk/src/main/java/jnpf/audit/sdk/AuditSpoolLock.java | 328 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 328 insertions(+), 0 deletions(-)
diff --git a/jnpf-biz-common/jnpf-audit-sdk/src/main/java/jnpf/audit/sdk/AuditSpoolLock.java b/jnpf-biz-common/jnpf-audit-sdk/src/main/java/jnpf/audit/sdk/AuditSpoolLock.java
new file mode 100644
index 0000000..1cebdb1
--- /dev/null
+++ b/jnpf-biz-common/jnpf-audit-sdk/src/main/java/jnpf/audit/sdk/AuditSpoolLock.java
@@ -0,0 +1,328 @@
+package jnpf.audit.sdk;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.DisposableBean;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.file.Files;
+
+/**
+ * spool 鍙屽眰閿佸崗璁紙Codex 鎵规浜屽楠� #1/#2 缁堝眬淇锛涙壒娆′簩涓夎疆 #A/#D 鍔犲浐锛夈��
+ *
+ * <p>{@link AuditSpoolWriter} 涓� {@link AuditSpoolReplayer} <b>鍏变韩鍚屼竴瀹炰緥</b>锛堢敱
+ * {@code AuditSdkAutoConfiguration} 娉ㄥ叆鍗曚緥锛夛紝鎶婂郊姝ょ殑 spool 鏂囦欢鎿嶄綔涓茶鍖栵紝浠庢牴涓婃秷闄や袱鏉$珵鎬侊細
+ * <ul>
+ * <li><b>Codex #1锛圕ritical锛�</b>锛歸riter 姣忔 open-append-close 涓� replayer 鐨�
+ * "璁ら rename + readAllLines" 涔嬮棿鐨勭獥鍙b�斺�攚riter 鎭板湪 replayer 鏀瑰悕鏃ф枃浠跺悗缁忓凡鎵撳紑鐨� FD
+ * 鍐欏叆琚敼鍚� inode锛屼簨浠堕殢 {@code .replaying} 琚垹鑰屾案涔呬涪澶便��</li>
+ * <li><b>Codex #2锛圛mportant锛�</b>锛氳棰� rename 涓� setLastModified 鍒锋柊绉熺害鏄袱涓嫭绔嬫搷浣滐紝
+ * 瀹炰緥 B 鍙湪瀹炰緥 A rename 鎴愬姛鍚庛�佸埛鏂� mtime 鍓嶆妸瀹冨綋瀛ゅ効鎶㈣蛋銆�</li>
+ * </ul>
+ * 涓ゆ潯绔炴�佺殑姝g‘鎬т粠姝ょ敱鏈攣淇濊瘉锛堜笉鍐嶄緷璧� 60 绉掗潤榛樼獥鍙h繖绉嶆椿璺冨害鍚彂寮忥紱闈欓粯绐楀彛闄嶇骇涓虹函浼樺寲锛夈��
+ *
+ * <h3>涓ゅ眰缁撴瀯</h3>
+ * <ol>
+ * <li><b>杩涚▼鍐呭眰</b>锛氬崟涓�鐩戣鍣� {@link #monitor}锛寃riter/replayer 鎵�鏈変复鐣屽尯鍏辩敤锛屼繚璇佸悓 JVM 涓茶銆�
+ * 瀹冨悓鏃朵繚璇佸悓 JVM 鍐� {@link FileChannel#tryLock()} 璇锋眰姘镐笉閲嶅彔鈥斺�斿惁鍒� JDK 浼氭姏
+ * {@link OverlappingFileLockException}锛團ileLock 鏄� JVM 绾ц�岄潪绾跨▼绾э級锛屾晠鏈被鍏堝彇杩涚▼鍐呴攣銆�
+ * 鍦� {@code synchronized} 鍧楀唴鑾�/鏀� FileLock锛屽ぉ鐒舵棤閲嶅彔銆�</li>
+ * <li><b>璺ㄨ繘绋嬪眰</b>锛歴pool 鐩綍涓嬪父椹荤殑 {@code spool.lock} 鏂囦欢 + {@link FileChannel#lock()} 绯�
+ * 鐙崰 {@link FileLock}銆傞攣鏂囦欢 {@link RandomAccessFile}/{@link FileChannel} 鎯版�ф墦寮�銆佸父椹伙紝
+ * {@link DisposableBean#destroy()} 鏃堕噴鏀俱��</li>
+ * </ol>
+ *
+ * <h3>闄嶇骇涓庣粓灞�锛堢粷涓嶈涓氬姟/鍙戦�佺嚎绋嬪穿婧冿級</h3>
+ * <ul>
+ * <li>鎵撳紑閿佹枃浠舵垨 {@code tryLock} 鎶� {@link IOException}锛堜笉鏀寔鐨勬枃浠剁郴缁熺瓑锛夆啋 缃�
+ * {@link #fileLockDisabled}锛屼箣鍚�<b>涓嶅啀灏濊瘯璺ㄨ繘绋嬮攣</b>锛寋@link #warnDegradeOnce} 鍘婚噸 warn 涓�娆°��</li>
+ * <li><b>writer 璺緞</b> {@link #lockAndRun(IoRunnable, IoRunnable)}锛氭嬁鍒拌法杩涚▼ FileLock 鈫� 鎵ц
+ * {@code lockedAction}锛堟甯歌拷鍔犲叡浜椿鍔ㄦ枃浠讹級锛�<b>鏈嬁鍒�</b>锛堣秴鏃�/涓柇/涓嶅彲鐢�/宸查攢姣侊級鈫� 鎵ц
+ * {@code degradedAction}锛圕odex#A锛氬啓鍞竴鍚� {@code .retry} 搴旀�ユ鈥斺�斾竴浜嬩欢涓�鏂囦欢锛屾棤鍏变韩鍚�=鏃�
+ * rename 绔炴�侊紝澶╃劧鏄噸鏀惧崗璁殑杈撳叆锛屽畞澶氭枃浠朵笉涓簨浠讹級銆傝繘绋嬪唴 {@link #monitor} 鍏ㄧ▼鎸佹湁銆�</li>
+ * <li><b>replayer 璺緞</b> {@link #tryLockAndRun}锛氶潪闃诲 {@code tryLock} 鎷夸笉鍒帮紙浠栬繘绋嬫寔鏈夛級灏�<b>璺宠繃鏈疆</b>
+ * 锛堣繑鍥� {@code false}锛屼笅杞啀鏉ワ級锛涢檷绾ф�佷粎杩涚▼鍐呴攣鎵ц杩斿洖 {@code true}锛堣閫�鍖栬矾寰勪粎鍦�"鍗曞疄渚�
+ * 鎷撴墤"涓嬪畨鍏ㄢ�斺�斿瀹炰緥鍏变韩鍚屼竴 spool 鍗锋椂璺ㄨ繘绋嬩簰鏂ュ畬鍏ㄥけ鏁堬紝闇�杩愮淮淇濊瘉涓嶆敮鎸� FileLock 鐨勬枃浠剁郴缁�
+ * 鍙崟瀹炰緥閮ㄧ讲锛屾棦鏈夊缓璁級锛�<b>宸查攢姣佹�佺洿鎺ヨ繑鍥� {@code false}銆佷笉鎵ц action</b>锛圕odex 鍥涜疆
+ * Critical#1锛岃涓嬩竴鏉★級銆�</li>
+ * <li><b>Codex#D 缁堟浣�</b> {@link #destroyed}锛歿@link #destroy()} 鍚� {@link #ensureChannelOpen} 鎷掔粷
+ * 閲嶅紑 channel鈥斺�旇繜鍒扮殑鏀跺熬/鍐欏叆璋冪敤锛坽@link #lockAndRun(IoRunnable, IoRunnable)}锛�"濮嬬粓鎵ц"璇箟锛�
+ * 鍙蛋杩涚▼鍐呴攣鎵ц degradedAction锛坽@link #warnPostDestroyOnce} 鍘婚噸 warn 涓�娆★級锛屾潨缁�"宸� close
+ * 鐨� raf/channel 琚噸寮�銆佸仠鏈哄悗鍙堟寔鏈夎法杩涚▼閿�"銆�</li>
+ * <li><b>Codex 鍥涜疆 Critical#1</b>锛坉estroyed 鎬佽棰嗘湭鎷掔粷锛夛細{@link #tryLockAndRun}锛堣棰�/瀛ゅ効鍥炴敹
+ * 璺緞锛�"鍙欢鍚庡埌涓嬭疆"璇箟锛夊湪 destroyed 鍚�<b>鐩存帴杩斿洖 {@code false}锛屼笉鎵ц action</b>鈥斺�旇�岄潪鍍�
+ * 鏃х増閭f牱閫�鍖栦负"浠呰繘绋嬪唴閿佹墽琛屽苟杩斿洖 true"銆傚仠鏈虹獥鍙e唴涓嶅簲璇ュ啀瀵� spool 鏂囦欢鍋氫换浣曡棰嗭細璁ら
+ * 寤跺悗鍒颁笅涓�杞�/涓嬩竴涓瓨娲诲疄渚嬪鐞嗘棤瀹筹紝鑰屽啓鍏ヨ矾寰� {@link #lockAndRun(IoRunnable, IoRunnable)}
+ * 蹇呴』"濮嬬粓鎵ц"锛堜簨浠朵笉鑳戒涪锛夛紝浜岃�呰涔夋湁鎰忎笉鍚岋紝涓嶅彲娣风敤鍚屼竴濂� destroyed 澶勭悊銆�</li>
+ * </ul>
+ *
+ * <p><b>娈嬩綑澹版槑</b>锛氬崟鏂囦欢閲嶆斁锛坮eadAllLines鈫掔綉缁� deliver鈫掓敹灏撅級瓒� 10 鍒嗛挓浠嶅彲鑳借鍏跺畠杩涚▼褰撳鍎�
+ * 鎶㈣蛋 鈫� 鍚庢灉=閲嶅閲嶆斁锛岃惤搴撴寜 client_event_id 骞傜瓑淇濊瘉涓嶄涪涓嶉噸鍏ュ簱锛屽彲鎺ュ彈銆倇@code spool.lock}
+ * 鑷韩姘镐笉鍙備笌鎵弿/閲嶆斁/鍒犻櫎锛坽@link AuditSpoolReplayer} 鎵弿杩囨护宸叉寜 {@link #LOCK_FILE_NAME} 鎺掗櫎锛夈��
+ */
+@Slf4j
+public class AuditSpoolLock implements DisposableBean {
+
+ /** 璺ㄨ繘绋嬮攣鏂囦欢鍚嶁�斺�斿父椹� spool 鐩綍锛屾案涓嶅弬涓庢壂鎻�/閲嶆斁/鍒犻櫎銆� */
+ static final String LOCK_FILE_NAME = "spool.lock";
+
+ /** writer 璺緞 FileLock 鑾峰彇鐨勬渶闀跨瓑寰咃紙甯﹂噸璇曪級锛涜秴鏃跺悗闄嶇骇涓哄敮涓�鍚嶅簲鎬ユ銆� */
+ private static final long WRITER_LOCK_WAIT_MS = 5_000L;
+ /** 閲嶈瘯杞闂撮殧銆� */
+ private static final long RETRY_SLEEP_MS = 50L;
+
+ /**
+ * 杩涚▼鍐呭眰锛歸riter/replayer 鎵�鏈変复鐣屽尯鍏辩敤鐨勫崟涓�鐩戣鍣紝淇濊瘉鍚� JVM 涓茶锛�
+ * 浜︿繚璇佸悓 JVM 鍐� FileLock 璇锋眰姘镐笉閲嶅彔锛堝惁鍒欐姏 {@link OverlappingFileLockException}锛夈��
+ */
+ private final Object monitor = new Object();
+
+ private final File spoolDir;
+ private final File lockFile;
+
+ /** 璺ㄨ繘绋嬪眰甯搁┗鍙ユ焺锛宒estroy 鏃堕噴鏀撅紱浠呭湪鎸佹湁 {@link #monitor} 鏃惰鍐欍�� */
+ private RandomAccessFile raf;
+ private FileChannel channel;
+
+ /** 闄嶇骇鏍囧織锛欶ileLock 涓嶆敮鎸�/閿佹枃浠舵墦涓嶅紑鏃剁疆浣嶏紝涔嬪悗涓嶅啀灏濊瘯璺ㄨ繘绋嬮攣锛涗粎鍦ㄦ寔鏈� {@link #monitor} 鏃惰鍐欍�� */
+ private boolean fileLockDisabled = false;
+ /** warn 鍘婚噸鏍囧織锛涗粎鍦ㄦ寔鏈� {@link #monitor} 鏃惰鍐欍�� */
+ private boolean degradeWarned = false;
+ /** Codex#D锛氱粓姝綅鈥斺�攄estroy 鍚庢嫆缁濋噸寮� channel锛岃繜鍒拌皟鐢ㄥ彧璧拌繘绋嬪唴閿併�備粎鍦ㄦ寔鏈� {@link #monitor} 鏃跺啓銆� */
+ private volatile boolean destroyed = false;
+ /**
+ * 宸查攢姣佸悗杩熷埌璋冪敤鐨� warn 鍘婚噸鏍囧織锛涗粎鍦ㄦ寔鏈� {@link #monitor} 鏃惰鍐欍�備袱鏉¤皟鐢ㄨ矾寰勫叡鐢ㄤ竴涓幓閲嶅紑鍏筹細
+ * {@link #acquireFileLockWithTimeout()}锛坵riter/{@code lockAndRun} 璺緞锛宒estroyed 鈫� 杩斿洖 {@code null}
+ * 鈫� 璋冪敤鏂硅蛋 degradedAction锛屼粎杩涚▼鍐呴攣鎵ц锛変笌 {@link #tryLockAndRun}锛坮eplayer/璁ら璺緞锛宒estroyed 鈫�
+ * 鐩存帴杩斿洖 {@code false}銆佷笉鎵ц action鈥斺�擟odex 鍥涜疆 Critical#1锛夈��
+ */
+ private boolean postDestroyWarned = false;
+
+ public AuditSpoolLock(String spoolDir) {
+ this.spoolDir = new File(spoolDir);
+ this.lockFile = new File(this.spoolDir, LOCK_FILE_NAME);
+ }
+
+ /** 鍙姏 {@link IOException} 鐨勬棤杩斿洖鍥炶皟锛圝DK8 鍑芥暟寮忔帴鍙o級銆� */
+ @FunctionalInterface
+ public interface IoRunnable {
+ void run() throws IOException;
+ }
+
+ /**
+ * writer 璇箟锛圕odex#A 闄嶇骇闅旂锛夛細<b>濮嬬粓鎵ц</b>锛屼絾鎸夋槸鍚︽寔鏈夎法杩涚▼閿佷簩閫変竴鎵ц銆�
+ *
+ * <p>椤哄簭锛氳繘绋嬪唴 {@link #monitor} 鈫� 灏藉姏鑾� FileLock锛堝甫瓒呮椂閲嶈瘯锛屽叡鏈�澶� {@link #WRITER_LOCK_WAIT_MS}锛夈��
+ * <ul>
+ * <li>鎷垮埌 FileLock 鈫� 鎵ц {@code lockedAction}锛堟甯歌拷鍔犲叡浜椿鍔ㄦ枃浠讹級锛屽�掑簭閲婃斁銆�</li>
+ * <li>鏈嬁鍒帮紙瓒呮椂/涓柇/涓嶅彲鐢�/宸查攢姣侊級鈫� 鎵ц {@code degradedAction}锛堝啓鍞竴鍚� {@code .retry} 搴旀�ユ锛夈��
+ * 姝ゆ椂<b>缁濅笉</b>鍐嶈拷鍔犲叡浜椿鍔ㄥ悕鈥斺�斿敮涓�鍚嶆枃浠舵棤鍏变韩銆佹棤 rename 绔炴�侊紝澶╃劧鏄噸鏀惧崗璁殑杈撳叆
+ * 锛圕odex#A锛氬璁′簨浠跺畞鍙鍑犱釜鏂囦欢涔熶笉涓㈠純锛夈��</li>
+ * </ul>
+ *
+ * @param lockedAction 鎸佹湁璺ㄨ繘绋嬮攣鏃舵墽琛岀殑鍔ㄤ綔锛堝叡浜椿鍔ㄦ枃浠惰拷鍔狅級
+ * @param degradedAction 鏈寔閿佹椂鎵ц鐨勯檷绾у姩浣滐紙鍞竴鍚嶅簲鎬ユ鍐欏叆锛�
+ * @throws IOException 鎵�閫夊姩浣滄姏鍑虹殑 IO 寮傚父锛岀敱璋冪敤鏂规寜鍘熸湁鍏滃簳澶勭悊
+ */
+ void lockAndRun(IoRunnable lockedAction, IoRunnable degradedAction) throws IOException {
+ synchronized (monitor) {
+ FileLock fileLock = acquireFileLockWithTimeout();
+ if (fileLock == null) {
+ // Codex#A锛氭湭鎸佹湁璺ㄨ繘绋嬮攣锛堣秴鏃�/涓柇/涓嶅彲鐢�/宸查攢姣侊級鈫� 璧伴檷绾у姩浣滐紙鍐欏敮涓�鍚嶏紝娑堢伃鍏变韩锛�
+ degradedAction.run();
+ return;
+ }
+ try {
+ lockedAction.run();
+ } finally {
+ releaseQuietly(fileLock);
+ }
+ }
+ }
+
+ /**
+ * writer 璇箟渚挎嵎閲嶈浇锛氶檷绾у姩浣滀笌鎸侀攣鍔ㄤ綔<b>鐩稿悓</b>銆�
+ *
+ * <p>閫傜敤浜庢敹灏剧瓑"鎿嶄綔瀵硅薄鏈氨鏄敮涓�鍚�/owner-token 鍚�"鐨勮皟鐢ㄦ柟锛堝 {@link AuditSpoolReplayer} 鐨�
+ * {@code finishReplay}锛氬啓 {@code .retry}/{@code .bad}銆佸垹 owner-token 鐨� {@code .replaying.<uuid>}
+ * 閮芥槸鍞竴鍚嶏紝浠呰繘绋嬪唴閿佸嵆瀹夊叏锛屾棤闇� FileLock 涔熷彲姝g‘钀藉湴锛夈��
+ */
+ void lockAndRun(IoRunnable action) throws IOException {
+ lockAndRun(action, action);
+ }
+
+ /**
+ * replayer 璇箟锛欶ileLock 琚�<b>鍒殑杩涚▼</b>鎸佹湁鍒欒烦杩囷紙杩斿洖 {@code false}锛屼笉鎵ц {@code action}锛屼笅杞啀鏉ワ級銆�
+ *
+ * <p>椤哄簭锛氳繘绋嬪唴 {@link #monitor} 鈫� 宸查攢姣佸垯鐩存帴鎷掔粷 鈫� 闈為樆濉� {@link FileChannel#tryLock()} 鈫� 鎵ц 鈫� 鍊掑簭閲婃斁銆�
+ * 涓嶆敮鎸� FileLock锛堥檷绾ф�侊級鈫� 浠呰繘绋嬪唴閿佹墽琛屽苟杩斿洖 {@code true}锛堜粎鍗曞疄渚嬫嫇鎵戝畨鍏紝瑙佺被 Javadoc锛夈��
+ *
+ * <p><b>Codex 鍥涜疆 Critical#1锛坉estroyed 鎬佽棰嗘湭鎷掔粷锛�</b>锛氭棫鐗� destroyed 涓� fileLockDisabled 璧板悓涓�
+ * 鍒嗘敮鈥斺�斾粎杩涚▼鍐呴攣鎵ц {@code action} 骞惰繑鍥� {@code true}锛屽嵆鍋滄満鍚庝粛浼�"璁ら"銆傝棰�/瀛ゅ効鍥炴敹鏄彲寤跺悗
+ * 鍒颁笅涓�杞垨涓嬩竴涓瓨娲诲疄渚嬪鐞嗙殑鎿嶄綔锛屽仠鏈虹獥鍙e唴娌℃湁蹇呰銆佷篃涓嶅簲璇ュ啀瀵� spool 鏂囦欢鍔ㄦ墜锛屾晠 destroyed
+ * 鍗曠嫭鍒ゆ柇銆佺洿鎺ヨ繑鍥� {@code false}銆�<b>涓嶆墽琛� action</b>鈥斺�斾笌"蹇呴』濮嬬粓鎵ц"鐨勫啓鍏ヨ涔�
+ * {@link #lockAndRun(IoRunnable, IoRunnable)} 鏄庣‘鍖哄垎寮�銆�
+ *
+ * @return {@code true}=宸叉墽琛岋紙鎷垮埌 FileLock 鎴栧凡闄嶇骇锛夛紱{@code false}=FileLock 琚粬杩涚▼鎸佹湁鏈疆璺宠繃锛�
+ * 鎴栧凡閿�姣佺洿鎺ユ嫆缁�
+ * @throws IOException {@code action} 鎶涘嚭鐨� IO 寮傚父
+ */
+ boolean tryLockAndRun(IoRunnable action) throws IOException {
+ synchronized (monitor) {
+ if (destroyed) {
+ // Codex 鍥涜疆 Critical#1锛歞estroyed 鍚庣洿鎺ユ嫆缁濊棰嗭紝涓嶆墽琛� action銆佷笉閫�鍖栦负浠呰繘绋嬪唴閿佹墽琛屻��
+ warnPostDestroyOnce();
+ return false;
+ }
+ ensureChannelOpen();
+ if (fileLockDisabled || channel == null) {
+ // fileLockDisabled锛堜笉鏀寔 FileLock 鐨勬枃浠剁郴缁燂級淇濇寔鍘熸湁閫�鍖栬涓猴細浠呰繘绋嬪唴閿佹墽琛� action銆�
+ // 璇ラ��鍖栬矾寰勪粎鍦�"鍗曞疄渚嬫嫇鎵�"涓嬪畨鍏ㄢ�斺�斿瀹炰緥鍏变韩鍚屼竴 spool 鍗锋椂璺ㄨ繘绋嬩簰鏂ュ畬鍏ㄥけ鏁堬紝
+ // 闇�杩愮淮淇濊瘉涓嶆敮鎸� FileLock 鐨勬枃浠剁郴缁熷彧鍗曞疄渚嬮儴缃诧紙鏃㈡湁寤鸿锛岃绫� Javadoc锛夈��
+ action.run();
+ return true;
+ }
+ FileLock fileLock;
+ try {
+ fileLock = channel.tryLock(); // 闈為樆濉烇紝鏁存枃浠剁嫭鍗�
+ } catch (OverlappingFileLockException overlap) {
+ // 鐞嗚涓嶅彲杈撅細monitor 宸蹭覆琛屽寲鍚� JVM锛孎ileLock 璇锋眰涓嶄細閲嶅彔銆傞槻寰℃�у綋浣�"琚崰"璺宠繃鏈疆銆�
+ return false;
+ } catch (IOException unsupported) {
+ markDegraded(unsupported); // 涓嶆敮鎸佺殑 FS 绛� 鈫� 闄嶇骇锛屼粎杩涚▼鍐呴攣鎵ц
+ action.run();
+ return true;
+ }
+ if (fileLock == null) {
+ return false; // 鍒殑杩涚▼鎸佹湁 鈫� 璺宠繃鏈疆
+ }
+ try {
+ action.run();
+ return true;
+ } finally {
+ releaseQuietly(fileLock);
+ }
+ }
+ }
+
+ /**
+ * 甯﹁秴鏃堕噸璇曡幏鍙� FileLock锛涙嬁涓嶅埌杩斿洖 {@code null}锛堣皟鐢ㄦ柟璧伴檷绾у姩浣滐級銆傝皟鐢ㄦ柟蹇呴』鎸佹湁 {@link #monitor}銆�
+ */
+ private FileLock acquireFileLockWithTimeout() {
+ ensureChannelOpen();
+ if (fileLockDisabled || destroyed || channel == null) {
+ if (destroyed) {
+ warnPostDestroyOnce();
+ }
+ return null; // 宸查檷绾�/宸查攢姣�/鏈紑 channel锛氳皟鐢ㄦ柟璧伴檷绾у姩浣�
+ }
+ long deadline = System.currentTimeMillis() + WRITER_LOCK_WAIT_MS;
+ while (true) {
+ try {
+ FileLock lock = channel.tryLock();
+ if (lock != null) {
+ return lock;
+ }
+ } catch (OverlappingFileLockException overlap) {
+ // 鐞嗚涓嶅彲杈撅紙monitor 涓茶鍖栵級锛涘綋浣滅灛鏃讹紝钀藉叆閲嶈瘯/瓒呮椂閫昏緫
+ } catch (IOException unsupported) {
+ markDegraded(unsupported); // 涓嶆敮鎸� 鈫� 闄嶇骇
+ return null;
+ }
+ if (System.currentTimeMillis() >= deadline) {
+ // 瓒呮椂 鈫� 璧伴檷绾у姩浣滐紙鍞竴鍚嶅簲鎬ユ锛屽璁′簨浠跺畞鍙鏂囦欢涔熶笉涓級锛涗笉缃� fileLockDisabled锛堜粬杩涚▼鏈鎸佹湁锛屽睘鐬椂锛�
+ warnDegradeOnce("FileLock 鑾峰彇瓒呮椂(" + WRITER_LOCK_WAIT_MS + "ms)锛屾湰娆″啓鍏ラ檷绾т负鍞竴鍚嶅簲鎬ユ");
+ return null;
+ }
+ try {
+ Thread.sleep(RETRY_SLEEP_MS);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ return null; // 琚腑鏂� 鈫� 璧伴檷绾у姩浣滐紙鍞竴鍚嶅簲鎬ユ锛夛紝灏藉揩瀹屾垚鍐欏叆
+ }
+ }
+ }
+
+ /**
+ * 鎯版�ф墦寮� {@code spool.lock} 甯搁┗鍙ユ焺锛涙墦寮�澶辫触鍗抽檷绾с��<b>宸查攢姣佸垯鎷掔粷閲嶅紑</b>锛圕odex#D锛夈��
+ * 璋冪敤鏂瑰繀椤绘寔鏈� {@link #monitor}銆�
+ */
+ private void ensureChannelOpen() {
+ if (channel != null || fileLockDisabled || destroyed) {
+ return; // Codex#D锛歞estroyed 鏃朵笉閲嶅紑 channel锛岃繜鍒拌皟鐢ㄨ蛋杩涚▼鍐呴攣
+ }
+ try {
+ if (!spoolDir.exists()) {
+ Files.createDirectories(spoolDir.toPath());
+ }
+ raf = new RandomAccessFile(lockFile, "rw");
+ channel = raf.getChannel();
+ } catch (IOException openFail) {
+ markDegraded(openFail); // 鏃犳硶鎵撳紑閿佹枃浠� 鈫� 浠呰繘绋嬪唴閿�
+ }
+ }
+
+ /** 缃案涔呴檷绾ф爣蹇楀苟 warn 涓�娆°�傝皟鐢ㄦ柟蹇呴』鎸佹湁 {@link #monitor}銆� */
+ private void markDegraded(Throwable cause) {
+ fileLockDisabled = true;
+ warnDegradeOnce("璺ㄨ繘绋� FileLock 涓嶅彲鐢紝闄嶇骇锛堝啓鍏ヨ蛋鍞竴鍚嶅簲鎬ユ/閲嶆斁璧颁粎杩涚▼鍐呴攣锛�: " + cause);
+ }
+
+ /** warn 鍘婚噸銆傝皟鐢ㄦ柟蹇呴』鎸佹湁 {@link #monitor}銆� */
+ private void warnDegradeOnce(String msg) {
+ if (!degradeWarned) {
+ degradeWarned = true;
+ log.warn("[audit] spool 閿侀檷绾�: {}", msg);
+ }
+ }
+
+ /** Codex#D锛氬凡閿�姣佸悗杩熷埌璋冪敤鐨� warn 鍘婚噸銆傝皟鐢ㄦ柟蹇呴』鎸佹湁 {@link #monitor}銆� */
+ private void warnPostDestroyOnce() {
+ if (!postDestroyWarned) {
+ postDestroyWarned = true;
+ log.warn("[audit] spool 閿佸凡閿�姣侊紝杩熷埌璋冪敤鎸夎矾寰勯檷绾э紙鍐欏叆璺緞=浠呰繘绋嬪唴閿佹墽琛岋紝"
+ + "璁ら璺緞=鐩存帴鎷掔粷锛屼笉鍐嶉噸寮�璺ㄨ繘绋� channel锛�");
+ }
+ }
+
+ private void releaseQuietly(FileLock fileLock) {
+ if (fileLock == null) {
+ return;
+ }
+ try {
+ fileLock.release();
+ } catch (IOException releaseFail) {
+ log.warn("[audit] spool FileLock 閲婃斁澶辫触: {}", releaseFail.toString());
+ }
+ }
+
+ /**
+ * Codex#D锛氱疆缁堟浣嶃�侀噴鏀捐法杩涚▼鍙ユ焺銆傜疆 {@link #destroyed} 鍚� {@link #ensureChannelOpen} 姘镐笉鍐嶉噸寮�
+ * channel锛岃繜鍒扮殑鏀跺熬/鍐欏叆璋冪敤鍙蛋杩涚▼鍐呴攣锛堜笉浼氬洜 {@code ensureChannelOpen} 澶嶆椿涓�涓仠鏈哄悗浠嶆寔鏈夌殑璺ㄨ繘绋嬮攣锛夈��
+ */
+ @Override
+ public void destroy() {
+ synchronized (monitor) {
+ destroyed = true;
+ closeQuietly(channel);
+ closeQuietly(raf);
+ channel = null;
+ raf = null;
+ }
+ }
+
+ private static void closeQuietly(Closeable c) {
+ if (c != null) {
+ try {
+ c.close();
+ } catch (IOException ignore) {
+ // 鍋滄満閲婃斁锛屽拷鐣�
+ }
+ }
+ }
+}
--
Gitblit v1.8.0