L'esecuzione di una compattazione offline può non riuscire con SegmentNotFoundException quando sono presenti problemi di integrità dell'archivio.

Problema

L'esecuzione di una compattazione offline può non riuscire con SegmentNotFoundException quando sono presenti problemi di integrità dell'archivio. Una traccia di stack simile a quella sottostante si può trovare nei log:

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

O una compattazione offline può non riuscire con l'eccezione IllegalArgument quando ci sono problemi di integrità dell'archivio. Una traccia di stack simile a quella sottostante si può trovare nei log:

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

Un SegmentNotFoundException viene restituito quando un segmento non è presente mentre la compattazione tenta di leggere il nodo. Le cause root possono essere diverse:

  1. Il segmento viene rimosso con un intervento manuale (ad es. rm -rf /).
  2. Il segmento è stato rimosso con il controllo della raccolta dei rifiuti. 
  3. Impossibile trovare il segmento a causa di un bug nel codice.

Nel caso in cui il problema sia causato dal controllo della raccolta dei rifiuti (punto 2), assicurati che la compattazione online sia disabilitata per evitare che altri nodi vengano corrotti.

Risoluzione

 

Puoi seguire diverse procedure per risolvere la situazione e completare con successo la Compattazione Offline.

Importante:Esegui un backup completo del tuo archivio prima di procedere come segue.

A. Torna all'ultima revisione valida nota dell'archivio dei segmenti.

Il controllo della modalità di esecuzione di oak-run può essere utilizzato per determinare l'ultima revisione valida nota di uno store di segmenti. Questo può essere utilizzato per ripristinare manualmente un'archivio di segmenti corrotti alla sua ultima revisione valida.

Attenzione:

Questo processo riporta i dati del sistema ad un momento precedente.  Per evitare di perdere le modifiche al sistema, prova l'opzione qui sotto.

Per eseguire il controllo e il ripristino:

  1. Scarica il file jar di oak-run da qui http://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/

  2. Interrompi AEM.

  3. Esegui il comando:

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

    Questo comando esegue una ricerca a ritroso attraverso le revisioni finché non ne trova una coerente:

    14:00:30.783 [main] INFO o.a.j.o.p.s.f.t.ConsistencyChecker - Ultima revisione valida trovata afdb922d-ba53-4a1b-aa1b-1cb044b535cf:234880

    (Se il ConsistencyChecker non riesce, passa alla sezione successiva)

  4. Ripristina l'archivio a questa revisione con una modifica.

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

    Elimina tutte le righe dopo la riga contenente l'ultima revisione valida. Per scoprire a quale data e ora stai ripristinando l'archivio, esegui questo comando nella cartella segmentstore (sostituisci afdb922d-ba53-4a1b-aa1b-1cb044b535cf con l'ultima revisione valida nel journal.log):

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

    Il risultato mostra una data e un'ora approssimativa di tale revisione.

  5. Rimuovi tutto ./crx-quickstart/repository/segmentstore/*.bak files.

  6. Se usi AEM 6.0, scarica la versione oak-run corrispondente a quella installata in AEM per i passaggi successivi.  Scaricala da qui http://repo1.maven.org/maven2/org/apache/jackrabbit/oak-run/.

  7. Esegui la pulizia dei checkpoint per rimuovere i checkpoint orfani:

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

  8. Infine, compattare l'archivio:

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

B. Rimuovere manualmente i nodi danneggiati.

In AEM, nelle impostazioni TarMK senza FileDatastore configurato e nelle situazioni in cui la corruzione è nei binari, puoi procedere come segue:

Attenzione:

La procedura che segue è destinata agli utenti esperti.  Quando si eliminano i nodi corrotti è necessario assicurarsi che non siano nodi di sistema (come /home, /jcr:system, ecc.).  Oppure, se si tratta di nodi di sistema, è necessario assicurarti di poterli ripristinare.  In caso di dubbi, consulta il team di assistenza al cliente di AEM per il supporto con i passaggi qui documentati.

  1. Interrompi AEM.

  2. Usa la console di esecuzione di Oak e carica lo script childCount groovy per identificare i nodi corrotti nell'archivio dei segmenti:

    Carica la shell della console di oak-run:

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

    Esegui i due comandi qui sotto nella shell per caricare lo script ed eseguirlo:

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

    countNodes(session.workingNode)

    Questo porta al seguente output che indica il percorso dei nodi danneggiati:

    21:21:42.029 [main] ERROR o.a.j.o.p.segment.SegmentTracker - Segment not found: 63ae05a4-b506-445c-baa2-cfa1b13b6e2f. Il delta della data di creazione è di 3 ms.
    avviso non in grado di leggere il nodo /content/dam/test.txt/jcr:content/renditions/original/jcr:content

    In alcuni casi il problema è legato a proprietà binarie e lo script groovy childCount non è in grado di individuare i nodi danneggiati.  In questi casi puoi utilizzare il seguente comando che leggerà i primi 1024 byte per ogni binario incontrato durante l'attraversamento (nota che questo comando sarà più lento e dovrebbe essere usato solo quando quello precedente non restituisce i risultati attesi):

    countNodes(session.workingNode,true)

  3. Rimuovi tutti i nodi danneggiati identificati elencati nel risultato dell'ultimo comando usando rmNodes.groovy

    Carica la shell della console di oak-run:

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

    Carica lo script groovy:

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

    Esegui il comando rmNode per rimuovere il nodo corrotto, sostituisci /path/to/corrupt/node con il percorso del nodo corrotto da rimuovere.

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

    Dove il percorso del nodo corrotto è il percorso ottenuto al passaggio 2, per esempio: "/content/dam/test.txt/jcr:content/renditions/original/jcr:content/"

    Nota:

    Quando usi oak-run.jar versione 1.6.13 e successive, imposta il parametro JVM --read-write se si verifica un errore come:

    /> 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. Ripeti il passaggio 3 per tutti i nodi trovati nel passaggio 2.

    Questo comando rmNode di cui sopra dovrebbe tornare true per il percorso corrotto, il che significa che lo ha eliminato. Assicurati che questi tre percorsi corrotti trovati vengano eliminati eseguendo nuovamente il comando rmNode su quei percorsi. L'esecuzione successiva dovrebbe restituire un esito false.

    Se vedi ancora che gli stessi percorsi sono presenti nell'archivio, usa la versione patched del file jar di oak-run ad es. oak-run-1.2.18-NPR-17596

    Che cosa fa la versione patched del file jar di Oak run?

    Questa versione di jar salta i binari illeggibili sulla compattazione sostituendoli con binari a 0-byte e registrando l'eccezione e il percorso di syserr. L'archivio così compattato dovrebbe quindi superare il controllo oak-run, lo script di conteggio dei nodi e dovresti essere in grado di compattarlo nuovamente usando un oak-run non patched.

  5. Esegui una pulizia dei checkpoint elencando i checkpoint in uso qui sotto. Se sono presenti più checkpoint, puliscili:

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

  6. Rimuovi i nodi non sincronizzati [Questo passaggio è facoltativo. Non usarlo a meno che non sia necessario per eseguire la reindicizzazione completa]:

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


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

    rmNode(session, "/:async")

  7. Avvia il server in attesa del completamento dell'indicizzazione.

  8. Interrompi AEM.

  9. Esegui la compattazione offline.

Questo prodotto è concesso in licenza in base alla licenza di Attribuzione-Non commerciale-Condividi allo stesso modo 3.0 Unported di Creative Commons.  I post su Twitter™ e Facebook non sono coperti dai termini di Creative Commons.

Note legali   |   Informativa sulla privacy online