SegmentNotFoundException e IllegalArgumentException

Última atualização em 2023-07-24

Descrição

Ambiente
Experience Manager

Problema/Sintomas

Cenário 1
A execução de uma compactação offline pode falhar com SegmentNotFoundException quando houver problemas de integridade do repositório.

Você observa SegmentNotFoundException nos arquivos de log do AEM e o AEM não está funcionando como esperado.

Cenário 2

A execução de uma compactação offline pode falhar com SegmentNotFoundException quando houver problemas de integridade do repositório.

Um rastreamento de pilha semelhante ao abaixo é exibido nos logs:

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)
...

Cenário 3

A execução de uma compactação offline pode falhar com IllegalArgument Exceção quando há problemas de integridade do repositório.

Um rastreamento de pilha semelhante ao abaixo é exibido nos logs:

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)

Resolução

Solução

Existem vários procedimentos que podemos seguir para resolver a situação e concluir a compactação offline com êxito.

Importante: faça um backup completo do seu repositório antes de seguir as etapas abaixo.

A. Reverta para a última revisão válida do armazenamento de segmentos.

O modo de verificação de execução do oak-run pode ser usado para determinar a última revisão válida de um armazenamento de segmento.
Isso pode ser usado para reverter manualmente um armazenamento de segmento corrompido para sua última revisão válida.

Cuidado: esse processo reverterá os dados no sistema para um ponto no tempo anterior.
Se você quiser evitar a perda de alterações em seu sistema, tente Opção B abaixo em vez disso.

Para executar a verificação e restauração, siga estas etapas:

  1. Baixe o oak-run Arquivo jar de aqui https://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/

  2. Pare o AEM.

  3. Execute este comando:

    java -jar oak-run-*.jar check --bin=-1 crx-quickstart/repository/segmentstore/

    Este comando faz uma pesquisa retroativa nas revisões até encontrar uma consistente:

    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

    (Caso o ConsistencyChecker falhe, vá para a próxima seção)

  4. Reverta o repositório para essa revisão ao editar:

    /crx-quickstart/repository/segmentstore/journal.log

    Exclua todas as linhas após a linha que contém a última revisão válida.

    Se quiser descobrir a data e a hora em que o repositório está sendo revertido, execute este comando no segmentstore pasta (substituir afdb922d-ba53-4a1b-aa1b-1cb044b535cf com a última boa revisão em seu journal.log):

    find . -type f -name "data*.tar" -exec sh -c "tar -tvf {} |grep afdb922d-ba53-4a1b-aa1b-1cb044b535cf" \; -print

    A saída mostraria uma data e hora aproximadas dessa revisão.

  5. Remover tudo ./crx-quickstart/repository/segmentstore/*.bak files.

  6. Se estiver usando o AEM6.0, baixe a versão do oak-run que corresponde ao que está instalado no AEM para as etapas restantes.

    Baixe aqui https://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/.

  7. Executar limpeza de ponto de verificação para remover pontos de verificação órfãos:

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

  8. Por fim, compacte o repositório:

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

B. Remova os nós corrompidos manualmente.

No AEM, em configurações do TarMK sem o FileDatastore configurado e em situações em que a corrupção está nos binários, você pode fazer o seguinte.

Cuidado: o procedimento abaixo é destinado a usuários avançados.
Ao excluir os nós corrompidos, você precisa garantir que eles não sejam nós do sistema (como /home, /jcr:system, etc.).
Ou, se eles forem nós do sistema, você precisa garantir que possa restaurá-los.
Consulte a Equipe de atendimento ao cliente do AEM para obter assistência com as etapas documentadas aqui, caso não tenha certeza.

  1. Pare o AEM.

  2. Use o console de execução do Oak e carregue o childCount script groovy para identificar os nós corrompidos no armazenamento de segmentos:

    Carregue o shell do console do oak-run:

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

    Execute os dois comandos abaixo no shell para carregar o script e executá-lo:

    :load

    https://gist.githubusercontent.com/stillalex/e7067bcb86c89bef66c8/raw/d7a5a9b839c3bb0ae5840252022f871fd38374d3/childCount.groovy

    countNodes(session.workingNode)

    Isso resulta na seguinte saída indicando o caminho para o(s) nó(s) corrompido(s):

    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

    Em alguns casos, o problema está vinculado a propriedades binárias e à variável childCount o script groovy não consegue localizar nenhum nó corrompido.

    Nesses casos, você pode usar o seguinte comando, que lerá os primeiros 1024 bytes para cada binário encontrado durante a travessia (observe que este comando será mais lento e só deverá ser usado quando o comando acima não retornar os resultados esperados):

    countNodes(session.workingNode,true)

  3. Remova todos os nós corrompidos identificados listados na saída do último comando usando rmNodes.groovy.

    Carregue o shell do console do oak-run:

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

    Carregue o script groovy:

    :load

    https://gist.githubusercontent.com/stillalex/43c49af065e3dd1fd5bf/raw/9e726a59f75b46e7b474f7ac763b0888d5a3f0c3/rmNode.groovy

    Execute o comando rmNode para remover o nó corrompido, substitua /path/to/corrupt/node pelo caminho para o nó corrompido que você precisa remover.

    rmNode(session, "/path/to/corrupt/node")

    Onde o caminho do nó corrompido é o caminho obtido na etapa 2, por exemplo: /content/dam/test.txt/jcr:content/renditions/original/jcr:content/. Observação: ao usar oak-run.jar versão 1.6.13 e superior, definir --read-write Parâmetro JVM se você encontrar um erro como:

    /> 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. Repita a etapa 3 para todos os nós encontrados na etapa 2.

    O comando rmNode acima deve retornar verdadeiro para o caminho corrompido, o que significa que ele o excluiu.

    Verifique se esses três caminhos corrompidos foram excluídos executando novamente o comando rmNode nesses caminhos.

    Para a próxima execução, ele deve retornar false.

    Se você ainda vir que os mesmos caminhos estão no repositório, use a versão corrigida do jar de execução do oak (ou seja, oak-run-1.2.18-NPR-17596).

    O que a versão corrigida do jar de execução do oak faz?

    Esta versão do jar ignora binários ilegíveis na compactação, substituindo-os por binários de 0 bytes e registrando a exceção e o caminho para o servidor.

    O repositório assim compactado deve passar na verificação oak-run e no script de contagem de nós, e você também deve ser capaz de compactá-lo novamente usando uma oak-run não corrigida.

  5. Execute uma limpeza de ponto de verificação listando pontos de verificação seguindo as etapas abaixo.

    Se houver mais de um ponto de verificação, limpe-os:

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

  6. Execute uma compactação offline.

    Caso não saiba como executar a compactação offline, consulte Instruções de compactação offline do Oak no GitHub Gist.

  7. Inicie o servidor e aguarde a conclusão da indexação.

Causa
A SegmentNotFoundException é retornado quando um segmento não está presente enquanto a compactação tenta ler o nó.

Pode haver diferentes causas raiz para isso:

  1. O segmento foi removido por intervenção manual (Por exemplo: rm -rf /).
  2. O segmento foi removido pela coleção de lixo de revisão.
  3. O segmento não pode ser encontrado devido a algum erro no código.

Caso o problema seja causado pela coleção de lixo de revisão (Causa #2), verifique se a compactação online está desativada para evitar que outros nós sejam corrompidos.

Nesta página