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

Problema

A execução de uma compactação offline poderá falhar com SegmentNotFoundException quando houver problemas de integridade do repositório. Um encadeamento de pilha similar ao abaixo poderá ser encontrado 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)
...

Ou a execução de uma compactação offline poderá falhar com a exceção IllegalArgument quando houver problemas de integridade do repositório. Um encadeamento de pilha similar ao abaixo poderá ser encontrado 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)

Ambiente

AEM 6.x

Causa

Um 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 é 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 um erro no código.

No caso, o problema é causado pela coleção de lixo de revisão (Ponto 2). Certifique-se de que a compactação online esteja desabilitada para evitar que outros nós sejam corrompidos.

Resolução

 

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

Importante: execute um back-up completo do seu repositório antes de seguir as etapas abaixo.

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

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

Cuidado:

Este processo irá reverter os dados no sistema para um ponto anterior no tempo.  Caso deseje evitar a perda de alterações no seu sistema, então você poderá tentar a opção abaixo.

Para executar a verificação e restauração:

  1. Baixe o arquivo jar do oak-run a partir daqui http://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/

  2. Pare o AEM.

  3. Execute o comando:

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

    Este comando procura para trás através das revisões até encontrar uma consistente:

    14:00:30.783 [main] INFO o.a.j.o.p.s.f.t.ConsistencyChecker - Encontrado a revisão válida mais recente afdb922d-ba53-4a1b-aa1b-1cb044b535cf:234880

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

  4. Reverta o repositório para esta revisão por meio de edição.

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

    Exclua todas as linhas após a linha que contém a última revisão válida. Se você quiser descobrir a data e a hora para as quais você está revertendo o repositório, execute este comando na pasta do repositório de segmentos (substitua afdb922d-ba53-4a1b-aa1b-1cb044b535cf pela última revisão válida em seu journal.log):

    encontrar. -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. Remova tudo ./crx-quickstart/repository/segmentstore/*.bak.

  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 http://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/.

  7. Execute a limpeza de pontos de verificação para remover pontos de verificação órfãos:

    pontos de verificação java -jar oak-run-*.jar./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, as configurações do TarMK sem o FileDatastore configurado e nas situações em que a corrupção está nos binários, você poderá fazer o seguinte.

Cuidado:

O procedimento abaixo destina-se a usuários avançados.  Ao excluir os nós corrompidos, você precisa ter certeza de que eles não são nós do sistema (como /home, /jcr: system, etc).  Ou se eles são nós do sistema, então você precisa ter certeza de que pode restaurá-los.  Consulte a equipe de Atendimento ao Cliente da AEM para obter ajuda com as etapas documentadas aqui se você estiver inseguro.

  1. Pare o AEM.

  2. Use o console do Oak-run e carregue o script groovy childCount para identificar os nós corrompidos no armazenamento de segmento:

    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:

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

    countNodes (session.workingNode)

    Isso resulta no seguinte resultado indicando o caminho para o(s) nó(s) corrompido(s):

    21:21:42.029 [principal] ERRO oajopsegment.SegmentTracker - segmento não encontrado: 63ae05a4-b506-445c-baa2-cfa1b13b6e2f. O delta da data de criação é de 3 ms.
    aviso incapaz de ler o nó /content/dam/test.txt/jcr:content/renditions/original/jcr:content

    Em alguns casos, o problema está vinculado a propriedades binárias e o script groovy childCount não consegue localizar nenhum nó corrompido.  Nesses casos, você poderá 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 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:

    : carregue 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 do 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 o oak-run.jar versão 1.6.13 e superior, defina o parâmetro da JVM --read-write se encontrar um erro como:

    /> rmNode (session, "/ caminho / para / corrupto / nó")
    Removendo o nó / caminho / para / corrompido / nó
    ERRO java.lang.UnsupportedOperationException:
    Não é possível gravar em um repositório somente leitura
            em org.apache.jackrabbit.oak.segment.SegmentWriterBuilder $ 1.execute (SegmentWriterBuilder.java:171)
            em org.apache.jackrabbit.oak.segment.SegmentWriter.writeNode (SegmentWriter.java:318)
            em org.apache.jackrabbit.oak.segment.SegmentNodeBuilder.getNodeState (SegmentNodeBuilder.java:111)
            em org.apache.jackrabbit.oak.segment.SegmentNodeStore $ Commit.<init> (SegmentNodeStore.java:581)
            em org.apache.jackrabbit.oak.segment.SegmentNodeStore.merge (SegmentNodeStore.java:333)
            em org.apache.jackrabbit.oak.spi.state.NodeStore $ merge.call (origem desconhecida)
            em groovysh_evaluate.rmNode (groovysh_evaluate:11)

  4. Repita o passo 3 para todos os nós encontrados no passo 2.

    Esse comando rmNode acima deverá retornar true para o caminho corrompido, o que significa que ele foi excluído. Certifique-se de que esses três caminhos corrompidos foram excluídos, executando novamente o comando rmNode nesses caminhos. A próxima execução deverá retornar false.

    Caso ainda veja que os mesmos caminhos estão no repositório, então use a versão corrigida do jar do oak-run, ou seja, oak-run-1.2.18-NPR-17596

    O que a versão corrigida do Oak run Jar faz?

    Esta versão do jar pula os binários ilegíveis na compactação substituindo-os por binários de 0 bytes e registrando a exceção e o caminho no syserr. O repositório assim compactado deverá então passar a verificação oak-run, o script de contagem de nós e você também deverá ser capaz de compactá-lo novamente usando uma oak-run não corrigida.

  5. Realize uma limpeza de pontos de verificação listando os pontos de verificação usados 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. Remova os nós assíncronos [Esta etapa é opcional. Não use essa opção a menos que seja necessário executar a reindexação completa]:

    java -Xmx4096m -jar oak-run-1.2.18.jar console /app/AEM6/author/crx-quickstart/repository/segmentstore


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

    rmNode (sessão, "/:async")

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

  8. Pare o AEM.

  9. Execute a compactação offline.

Esta obra está licenciada sob uma licença não adaptada da Creative Commons Attribution-Noncommercial-Share Alike 3.0  As publicações do Twitter™ e do Facebook não são cobertas pelos termos do Creative Commons.

Avisos legais   |   Política de privacidade online