SegmentNotFoundException 和 IllegalArgumentException

說明

環境
Adobe Experience Manager

問題

方案1
執行離線壓縮可能會失敗,具有 SegmentNotFoundException 存放庫存在完整性問題時。

你觀察 SegmentNotFoundException 在AEM記錄檔中,AEM無法如預期運作。

方案2

執行離線壓縮可能會失敗,具有 SegmentNotFoundException 存放庫存在完整性問題時。

記錄中會顯示類似下列的堆疊追蹤:

13:51:21.523 main ERROR o.a.j.o.p.segment.SegmentTracker - Segment not found: 4d139bc4-150c-4f0a-b82a-40a4e519fe8a. Creation date delta is 4 ms.
org.apache.jackrabbit.oak.plugins.segment.SegmentNotFoundException: Segment 4d139bc4-150c-4f0a-b82a-40a4e519fe8a 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-40a4e519fe8a 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)

原因

A SegmentNotFoundException 當壓縮嘗試讀取節點時,區段不存在時會傳回。
對此可能有不同的根本原因:

  1. 區段已透過手動干預移除(例如: rm -rf /)。
  2. 該區段已被修訂垃圾收藏集移除。
  3. 由於程式碼中的一些錯誤,無法找到該區段。

如果問題是由修訂垃圾收集引起(原因#2), 確保禁用聯機壓縮 以避免更多節點損壞。

解決方法

解決方法

我們可以遵循多種程序來解決這種情況,並成功完成離線壓縮。

重要:​在執行以下步驟之前,請對存放庫執行完整備份。

A. 還原到區段存放區的最後一個已知良好修訂。

Oak-run 的檢查執行模式可用於確定區段存放區的最後一個已知良好修訂。這可用於將損壞的區段存放區手動還原為其最新的良好修訂。

警告:此流程會將系統中的資料復原到之前的時間點。如果您希望避免丟失系統中的更改,則可以嘗試 選項B 在下方。

要執行檢查和還原,請執行以下步驟:

  1. 下載 oak-run 從這裡收到jar檔案 https://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/

  2. 停止 AEM。

  3. 執行此命令:

    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 失敗,請前往下一區段)

  4. 通過編輯將儲存庫還原為此修訂:

    /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

    輸出將顯示該修訂的大致日期和時間。

  5. 移除所有 ./crx-quickstart/repository/segmentstore/*.bak files.

  6. 如果使用 AEM6.0,則下載與 AEM 中安裝的內容相符的 Oak-run 版本以完成其餘步驟。

    從這裡下載 https://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/.

  7. 執行 查核點清理 若要移除孤立查核點:

    java -jar oak-run-*.jar checkpoints ./crx-quickstart/repository/segmentstore rm-unreferenced

  8. 最後,壓縮存放庫:

    java -jar oak-run-*.jar compact ./crx-quickstart/repository/segmentstore/

B. 手動移除損壞的節點。

在 AEM 中,TarMK 設定未包含已設定的 FileDatastore 而且二進位檔案中有損壞的情況,您可以執行以下操作。

*注意:*以下程序適用於進階使用者。刪除損壞的節點時,您需要確保這些節點不是系統節點(例如 /home, /jcr:system等)。
或者,如果它們是系統節點,則需要確保可以恢復它們。
如果您不確定,請洽詢AEM客戶服務團隊,以取得此處說明的步驟協助。

  1. 停止 AEM。

  2. 使用Oak執行主控台並載入 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)

  3. 使用刪除最後一個命令輸出中列出的所有已識別的損壞節點 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參數(如果發生以下錯誤):

    / rmNode(session,"/path/to/corrupt/node")Removing node /path/to/corrupt/nodeERROR java.lang.UnsupportedOperationException:Cannot write to read-only storeat 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)
    
  4. 對步驟 2 中找到的所有節點重複步驟 3。

    上面這個 rmNode 命令應該會對損壞的路徑傳回 true,這表示它刪除了它。

    重新執行 rmNode 命令。

    下次執行時,應會傳回 false.

    如果您仍看到存放庫中有相同的路徑,請使用修補版本的oak-run jar(即 oak-run-1.2.18-NPR-17596)。

    修補的oak-run jar版本有什麼作用?

    此版本的jar會在壓縮作業中略過無法讀取的二進位檔,將其取代為0位元組二進位檔,並記錄例外狀況和syser的路徑。

    如此壓縮的存放庫應接著傳遞oak-run檢查、節點計數指令碼,您也應能使用未修補的oak-run再次壓縮。

  5. 透過使用以下查核點清單來執行查核點清理。

    如果有多個查核點,則將其清理掉:

    nohup java -Xmx4096m -jar oak-run-1.2.18.jar checkpoints /app/AEM6/author/crx-quickstart/repository/segmentstore rm-allnohup.out &

  6. 執行離線壓縮。

    如果您不知道如何執行離線壓縮,請參閱 Oak離線壓縮指示 在GitHub Gist上。

  7. 啟動伺服器並等待索引完成。

本頁內容