SegmentNotFoundException 和 IllegalArgumentException
執行離線壓縮可能會失敗,並出現 SegmentNotFoundException 或 IllegalArgumentException。 本文探討如何解決錯誤並成功完成離線壓縮。 不過,在繼續之前,請對存放庫執行完整備份。
說明 description
環境
Adobe Experience Manager (AEM)
問題
案例1
當存放庫有完整性問題時,執行離線壓縮可能會失敗並出現 SegmentNotFoundException。
您在AEM記錄檔中觀察到 SegmentNotFoundException,並且AEM未按預期運作。
案例2
當存放庫有完整性問題時,執行離線壓縮可能會失敗並出現 SegmentNotFoundException。
棧疊追蹤類似於以下在記錄中顯示的追蹤:
13:51:21.523 [ main] ERROR o.a.j.o.p.segment.SegmentTracker - Segment not found: 4d139bc4-150c-4f0a-b82a-4867593098a. Creation date delta is 4 ms.
org.apache.jackrabbit.oak.plugins.segment.SegmentNotFoundException: Segment 4d139bc4-150c-4f0a-b82a-4867593098a not found
at org.apache.jackrabbit.oak.plugins.segment.file.FileStore.readSegment(FileStore.java:855) [ oak-run-1.0.22.jar:1.0.22]
at org.apache.jackrabbit.oak.plugins.segment.SegmentTracker.getSegment(SegmentTracker.java:134) ~[ oak-run-1.0.22.jar:1.0.22]
at org.apache.jackrabbit.oak.plugins.segment.SegmentId.getSegment(SegmentId.java:101) [ oak-run-1.0.22.jar:1.0.22]
...
Exception in thread "main" org.apache.jackrabbit.oak.plugins.segment.SegmentNotFoundException: Segment 4d139bc4-150c-4f0a-b82a-4867593098a not found
at org.apache.jackrabbit.oak.plugins.segment.file.FileStore.readSegment(FileStore.java:855)
at org.apache.jackrabbit.oak.plugins.segment.SegmentTracker.getSegment(SegmentTracker.java:134)
at org.apache.jackrabbit.oak.plugins.segment.SegmentId.getSegment(SegmentId.java:101)
...
案例3
當存放庫有完整性問題時,執行離線壓縮可能會失敗並出現 IllegalArgument 例外狀況。
棧疊追蹤類似於以下在記錄中顯示的追蹤:
java.lang.IllegalArgumentException
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:77)
at org.apache.jackrabbit.oak.plugins.segment.ListRecord.(ListRecord.java:41)
at org.apache.jackrabbit.oak.plugins.segment.ListRecord.getEntry(ListRecord.java:64)
at org.apache.jackrabbit.oak.plugins.segment.ListRecord.getEntries(ListRecord.java:81)
at org.apache.jackrabbit.oak.plugins.segment.SegmentStream.read(SegmentStream.java:153)
at org.apache.jackrabbit.oak.commons.IOUtils.readFully(IOUtils.java:53)
at org.apache.jackrabbit.oak.plugins.segment.Compactor.getBlobKey(Compactor.java:412)
at org.apache.jackrabbit.oak.plugins.segment.Compactor.compact(Compactor.java:362)
at org.apache.jackrabbit.oak.plugins.segment.Compactor.compact(Compactor.java:321)
at org.apache.jackrabbit.oak.plugins.segment.Compactor.access$500(Compactor.java:54)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff.propertyAdded(Compactor.java:227)
at org.apache.jackrabbit.oak.plugins.segment.CancelableDiff.propertyAdded(CancelableDiff.java:47)
at org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.compareAgainstEmptyState(EmptyNodeState.java:156)
at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:434)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff.diff(Compactor.java:214)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff.childNodeAdded(Compactor.java:263)
at org.apache.jackrabbit.oak.plugins.segment.CancelableDiff.childNodeAdded(CancelableDiff.java:74)
at org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.compareAgainstEmptyState(EmptyNodeState.java:161)
at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:434)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff. diff (Compactor.java:214)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff.childNodeAdded(Compactor.java:263)
at org.apache.jackrabbit.oak.plugins.segment.CancelableDiff.childNodeAdded(CancelableDiff.java:74)
at org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.compareAgainstEmptyState(EmptyNodeState.java:161)
at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:434)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff. diff (Compactor.java:214)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff.childNodeAdded(Compactor.java:263)
at org.apache.jackrabbit.oak.plugins.segment.CancelableDiff.childNodeAdded(CancelableDiff.java:74)
at org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.compareAgainstEmptyState(EmptyNodeState.java:161)
at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:434)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff. diff (Compactor.java:214)
at org.apache.jackrabbit.oak.plugins.segment.Compactor$CompactDiff.childNodeAdded(Compactor.java:263)
at org.apache.jackrabbit.oak.plugins.segment.CancelableDiff.childNodeAdded(CancelableDiff.java:74)
解析度 resolution
我們可以遵循多種程序來解決這種情況,並成功完成離線壓縮。
重要: 在執行以下步驟之前,請對存放庫執行完整備份。
A. 還原到區段存放區的最後一個已知良好修訂。
Oak-run的檢查執行模式可用於確定區段存放區的最後一個已知良好修訂。
這可用於將損壞的區段存放區手動還原為其最新的良好修訂。
*警告:*此程式會將系統中的資料復原到之前的時間點。
如果您想要避免遺失系統中的變更,則可改為嘗試下方的 選項B。
若要執行檢查和還原,請遵循下列步驟:
-
從這裡https://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/下載
oak-run
jar檔案。 -
停止 AEM。
-
執行此命令:
java -jar oak-run-*.jar check --bin=-1 crx-quickstart/repository/segmentstore/
此命令會向後搜尋修訂,直到找到一致的修訂:
14:00:30.783 [ main] INFO o.a.j.o.p.s.f.t.ConsistencyChecker - Found latest good revision afdb922d-ba53-4a1b-aa1b-1cb044b535cf:234880
(如果ConsistencyChecker失敗,請前往下一區段。)
-
透過編輯將存放庫恢復到此版本:
/crx-quickstart/repository/segmentstore/journal.log
刪除包含最新良好修訂的行之後的所有行。
如果您想瞭解將存放庫還原到什麼日期和時間,請在
segmentstore
資料夾中執行此命令(將 afdb922d-ba53-4a1b-aa1b-1cb044b535cf 取代為journal.log
中的最新良好修訂):find . -type f -name "data*.tar" -exec sh -c "tar -tvf {} |grep afdb922d-ba53-4a1b-aa1b-1cb044b535cf" \; -print
輸出將顯示該修訂的大致日期和時間。
-
移除所有
./crx-quickstart/repository/segmentstore/*.bak files.
-
如果使用AEM 6.0,則下載與AEM中安裝的內容相符的Oak-run版本以完成其餘步驟。
從這裡https://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/下載。
-
執行 查核點清理 以移除孤立的查核點:
java -jar oak-run-*.jar checkpoints ./crx-quickstart/repository/segmentstore rm-unreferenced
-
最後,壓縮存放庫:
java -jar oak-run-*.jar compact ./crx-quickstart/repository/segmentstore/
B. 手動移除損壞的節點。
在 AEM 中,TarMK 設定未包含已設定的 FileDatastore 而且二進位檔案中有損壞的情況,您可以執行以下操作。
*注意:*以下程式適用於超級使用者。
刪除損壞的節點時,您需要確保它們不是系統節點(例如/home
、/jcr:system
等)。
或者,如果它們是系統節點,那麼您需要確保可將其還原。
如果您不確定,請向AEM客戶服務團隊尋求此處記錄的步驟的協助。
-
停止 AEM。
-
使用Oak run主控台並載入
childCount
groovy指令碼來識別區段存放區中的損壞節點:載入 Oak-run 主控台殼層:
java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
在殼層中執行以下兩個命令來載入指令碼並執行:
:load
https://gist.githubusercontent.com/stillalex/e7067bcb86c89bef66c8/raw/d7a5a9b839c3bb0ae5840252022f871fd38374d3/childCount.groovy
countNodes(session.workingNode)
這將導致以下顯示損壞節點路徑的輸出:
21:21:42.029 [ main] ERROR o.a.j.o.p.segment.SegmentTracker - Segment not found: 63ae05a4-b506-445c-baa2-cfa1b13b6e2f. Creation date delta is 3 ms.
warning unable to read node /content/dam/test.txt/jcr:content/renditions/original/jcr:content
在某些情況下,該問題與二進位屬性有關,並且
childCount
groovy指令碼無法找到任何損壞的節點。在這些情況下,您可以改用以下命令,它將讀取周遊期間遇到的每個二進位檔案的前1024個位元組(請注意,此命令會較慢,並且僅應在上述命令未傳回預期結果時使用):
countNodes(session.workingNode,true)
-
使用
rmNodes.groovy
移除最後一個命令輸出中列出的所有已識別損壞節點。載入 Oak-run 主控台殼層:
java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
載入 groovy 指令碼:
:load
https://gist.githubusercontent.com/stillalex/43c49af065e3dd1fd5bf/raw/9e726a59f75b46e7b474f7ac763b0888d5a3f0c3/rmNode.groovy
執行
rmNode
命令以移除損壞的節點,將/path/to/corrupt/node
替換為您需要移除的損壞節點的路徑。rmNode(session, "/path/to/corrupt/node")
其中損壞的節點路徑為步驟2中取得的路徑,例如:
/content/dam/test.txt/jcr:content/renditions/original/jcr:content/
。
注意:使用oak-run.jar
版本1.6.13及更高版本時,如果您遇到錯誤,請設定--read-write
JVM引數,例如:code language-none /> rmNode(session,"/path/to/corrupt/node") Removing node /path/to/corrupt/node ERROR java.lang.UnsupportedOperationException: Cannot write to read-only store at org.apache.jackrabbit.oak.segment.SegmentWriterBuilder$1.execute (SegmentWriterBuilder.java:171) at org.apache.jackrabbit.oak.segment.SegmentWriter.writeNode (SegmentWriter.java:318) at org.apache.jackrabbit.oak.segment.SegmentNodeBuilder.getNodeState (SegmentNodeBuilder.java:111) at org.apache.jackrabbit.oak.segment.SegmentNodeStore$Commit.<init> (SegmentNodeStore.java:581) at org.apache.jackrabbit.oak.segment.SegmentNodeStore.merge (SegmentNodeStore.java:333) at org.apache.jackrabbit.oak.spi.state.NodeStore$merge.call (Unknown Source) at groovysh_evaluate.rmNode (groovysh_evaluate:11)
-
對步驟 2 中找到的所有節點重複步驟 3。
上面這個
rmNode
命令應該會對損壞的路徑傳回 true,這表示它刪除了它。請確保透過重新執行這些路徑上的
rmNode
命令來刪除這些找到的三個損壞的路徑。下次執行應該會傳回
false
。如果您仍然看到存放庫中存在相同的路徑,則使用修補版本的Oak-run jar (即 oak-run-1.2.18-NPR-17596)。
Oak-run jar修補版本有什麼作用?
此版本的jar在壓縮時會略過無法讀取的二進位檔案,將它們替換為0位元組的二進位檔案並記錄例外狀況和syserr的路徑。
如此壓縮的存放庫應該會通過Oak-run檢查、節點計數指令碼,並且您還應該能夠使用未修補的Oak-run再次壓縮它。
-
透過使用以下查核點清單來執行查核點清理。
如果有多個查核點,則將其清理掉:
nohup java -Xmx4096m -jar oak-run-1.2.18.jar checkpoints /app/AEM6/author/crx-quickstart/repository/segmentstore rm-all>>nohup.out &
-
執行離線壓縮。
如果您不知道如何執行離線壓縮,請參閱GitHub Gist上的Oak離線壓縮指示。
-
啟動伺服器並等待索引完成。
原因
如果在壓縮嘗試讀取節點時區段不存在,則會傳回 SegmentNotFoundException。
對此可能有不同的根本原因:
- 該區段已被手動介入移除(例如:rm -rf /)。
- 該區段已被修訂垃圾收藏集移除。
- 由於程式碼中的一些錯誤,無法找到該區段。
如果問題是由修訂垃圾收藏集所造成(原因#2),請確定已停用線上壓縮,以避免進一步的節點損毀。