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 の check run-mode を使用すると、セグメントストアの整合性のある最も新しいリビジョンを確認できます。
このリビジョンを使用して、破損しているセグメントストアを整合性のある最も新しいリビジョンに手動で戻すことができます。

注意: この操作を実行すると、システム内のデータが過去の時点にロールバックされます。
システムの変更が失われないようにするには、代わりに次の オプション 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-1cb044b535cfjournal.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. AEM 6.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. 破損しているノードを手動で削除する。

TarMK に FileDatastore が設定されていない場合や、バイナリが破損している場合、AEM で次の操作を実行できます。

*注意:*次の手順は、パワーユーザーを対象としています。
破損しているノードを削除するときは、それがシステムノード(/home/jcr:system など)でないことを確認する必要があります。
または、システムノードの場合は、それらを復元できることを確認する必要があります。
ここに記載されている手順について不明な点がある場合は、AEM カスタマーケアチームにお問い合わせください。

  1. AEM を停止します。

  2. Oak実行コンソールを使用し、childCount groovy スクリプトを読み込んで、セグメントストア内の破損しているノードを特定します。

    oak-run コンソールシェルを読み込みます。

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

    次の 2 つのコマンドをシェルで実行してスクリプトを読み込み、実行します。

    :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 スクリプトを使用しても破損しているノードを見つけることができないことがあります。

    その場合は、代わりに次のコマンドを使用します。このコマンドを使用すると、走査中に検出されたすべてのバイナリの先頭の 1,024 バイトが読み取られます(このコマンドは低速なので、上記のコマンドを実行しても期待される結果が返さない場合にのみ使用してください)。

    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 パラメーターを設定します。

    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)
    
  4. 手順 2 で見つかったすべてのノードに対して手順 3 を繰り返します。

    上記の rmNode コマンドを破損しているパスに対して実行すると、true が返されます。これは、コマンドによってパスが削除されたことを意味します。

    これらの見つかった 3 つの破損しているパスに対して rmNode コマンドを再実行して、これらのパスを削除します。

    次回の実行では、false が返されます。

    この時点で同じパスがリポジトリに存在する場合は、パッチが適用されたバージョンの oak-run jar を使用します  (つまり oak-run-1.2.18-NPR-17596)。

    パッチが適用されたバージョンの oak-run jar の動作

    このバージョンの jar は、圧縮時に読み取り不可能なバイナリをスキップし、0 バイトのバイナリに置き換えて、例外とパスを syserr に記録します。

    この方法で圧縮したリポジトリはノード数を取得するスクリプトの oak-run check に合格します。これで、パッチの適用されていない oak-run を使用してリポジトリを再度圧縮できるようになります。

  5. 次のコマンドを使用してチェックポイントをリストして、チェックポイントのクリーンアップを実行します。

    複数のチェックポイントがある場合は、それらをクリーンアップします。

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

  6. オフライン圧縮を実行します。

    オフライン圧縮の実行方法がわからない場合は、Oakのオフライン圧縮手順を GitHub Gist で参照してください。

  7. サーバーを起動して、インデックスの作成が完了するまで待ちます。

原因
SegmentNotFoundException は、コンパクションでノードを読み取ろうとしたときにセグメントが存在しない場合に返されます。

これには様々な根本原因があります。

  1. セグメントが手動操作によって削除された(例:rm -rf /)。
  2. セグメントがリビジョンガベージコレクションによって削除された。
  3. コードのバグが原因でセグメントが見つからない。

リビジョンガベージコレクションが原因で問題が発生している場合(原因#2)は、オンライン圧縮を無効にして、他のノードが破損しないようにします。

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f