Search in sources :

Example 16 with LogEntryCommit

use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.

the class LegacyLogEntryWriter method writeAllLogEntries.

public void writeAllLogEntries(LogVersionedStoreChannel channel, IOCursor<LogEntry> cursor) throws IOException {
    try (PositionAwarePhysicalFlushableChannel writable = new PositionAwarePhysicalFlushableChannel(channel)) {
        final LogEntryWriter writer = factory.apply(writable);
        List<StorageCommand> commands = new ArrayList<>();
        while (cursor.next()) {
            LogEntry entry = cursor.get();
            if (entry instanceof LogEntryStart) {
                final LogEntryStart startEntry = entry.as();
                writer.writeStartEntry(startEntry.getMasterId(), startEntry.getLocalId(), startEntry.getTimeWritten(), startEntry.getLastCommittedTxWhenTransactionStarted(), startEntry.getAdditionalHeader());
            } else if (entry instanceof LogEntryCommit) {
                if (!commands.isEmpty()) {
                    writer.serialize(new PhysicalTransactionRepresentation(commands));
                    commands = new ArrayList<>();
                }
                final LogEntryCommit commitEntry = (LogEntryCommit) entry;
                writer.writeCommitEntry(commitEntry.getTxId(), commitEntry.getTimeWritten());
            } else if (entry instanceof LogEntryCommand) {
                commands.add(((LogEntryCommand) entry).getXaCommand());
            } else {
                throw new IllegalStateException("Unknown entry: " + entry);
            }
        }
    }
}
Also used : LogEntryStart(org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart) LogEntryCommand(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand) PositionAwarePhysicalFlushableChannel(org.neo4j.kernel.impl.transaction.log.PositionAwarePhysicalFlushableChannel) StorageCommand(org.neo4j.storageengine.api.StorageCommand) LogEntryCommit(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit) ArrayList(java.util.ArrayList) LogEntryWriter(org.neo4j.kernel.impl.transaction.log.entry.LogEntryWriter) LogEntry(org.neo4j.kernel.impl.transaction.log.entry.LogEntry) PhysicalTransactionRepresentation(org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation)

Example 17 with LogEntryCommit

use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.

the class LegacyLogEntryWriterTest method shouldWriteAllTheEntryInSeveralCommitsToTheFile.

@Test
public void shouldWriteAllTheEntryInSeveralCommitsToTheFile() throws IOException {
    // given
    final LogVersionedStoreChannel channel = mock(LogVersionedStoreChannel.class);
    final LogEntryWriter logEntryWriter = mock(LogEntryWriter.class);
    final LegacyLogEntryWriter writer = new LegacyLogEntryWriter(fs, liftToFactory(logEntryWriter));
    final LogEntryStart start1 = new LogEntryStart(0, 1, 2L, 3L, EMPTY_ADDITIONAL_ARRAY, UNSPECIFIED);
    final LogEntryCommand command1 = new LogEntryCommand(new Command.NodeCommand(nodeRecord, nodeRecord));
    final LogEntryCommit commit1 = new OnePhaseCommit(42L, 43L);
    final LogEntryStart start2 = new LogEntryStart(9, 8, 7L, 6L, EMPTY_ADDITIONAL_ARRAY, UNSPECIFIED);
    final LogEntryCommand command2 = new LogEntryCommand(new Command.RelationshipCommand(relRecord, relRecord));
    final LogEntryCommit commit2 = new OnePhaseCommit(84L, 85L);
    // when
    IOCursor<LogEntry> cursor = mockCursor(start1, command1, commit1, start2, command2, commit2);
    writer.writeAllLogEntries(channel, cursor);
    // then
    verify(logEntryWriter, times(1)).writeStartEntry(0, 1, 2L, 3L, EMPTY_ADDITIONAL_ARRAY);
    final TransactionRepresentation expected1 = new PhysicalTransactionRepresentation(Arrays.asList(command1.getXaCommand()));
    verify(logEntryWriter, times(1)).serialize(eq(expected1));
    verify(logEntryWriter, times(1)).writeCommitEntry(42L, 43L);
    verify(logEntryWriter, times(1)).writeStartEntry(9, 8, 7L, 6L, EMPTY_ADDITIONAL_ARRAY);
    final TransactionRepresentation expected2 = new PhysicalTransactionRepresentation(Arrays.asList(command2.getXaCommand()));
    verify(logEntryWriter, times(1)).serialize(eq(expected2));
    verify(logEntryWriter, times(1)).writeCommitEntry(84L, 85L);
}
Also used : LogEntryStart(org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart) LogVersionedStoreChannel(org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel) LogEntryCommand(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand) TransactionRepresentation(org.neo4j.kernel.impl.transaction.TransactionRepresentation) PhysicalTransactionRepresentation(org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation) Command(org.neo4j.kernel.impl.transaction.command.Command) LogEntryCommand(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand) LogEntryCommit(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit) LogEntryWriter(org.neo4j.kernel.impl.transaction.log.entry.LogEntryWriter) OnePhaseCommit(org.neo4j.kernel.impl.transaction.log.entry.OnePhaseCommit) LogEntry(org.neo4j.kernel.impl.transaction.log.entry.LogEntry) PhysicalTransactionRepresentation(org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation) Test(org.junit.Test)

Example 18 with LogEntryCommit

use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.

the class TransactionLogsRecoveryTest method shouldRecoverExistingData.

@Test
void shouldRecoverExistingData() throws Exception {
    LogFile logFile = logFiles.getLogFile();
    Path file = logFile.getLogFileForVersion(logVersion);
    writeSomeData(file, pair -> {
        LogEntryWriter writer = pair.first();
        Consumer<LogPositionMarker> consumer = pair.other();
        LogPositionMarker marker = new LogPositionMarker();
        // last committed tx
        int previousChecksum = BASE_TX_CHECKSUM;
        consumer.accept(marker);
        LogPosition lastCommittedTxPosition = marker.newPosition();
        writer.writeStartEntry(2L, 3L, previousChecksum, new byte[0]);
        lastCommittedTxStartEntry = new LogEntryStart(2L, 3L, previousChecksum, new byte[0], lastCommittedTxPosition);
        previousChecksum = writer.writeCommitEntry(4L, 5L);
        lastCommittedTxCommitEntry = new LogEntryCommit(4L, 5L, previousChecksum);
        // check point pointing to the previously committed transaction
        var checkpointFile = logFiles.getCheckpointFile();
        var checkpointAppender = checkpointFile.getCheckpointAppender();
        checkpointAppender.checkPoint(LogCheckPointEvent.NULL, lastCommittedTxPosition, Instant.now(), "test");
        // tx committed after checkpoint
        consumer.accept(marker);
        writer.writeStartEntry(6L, 4L, previousChecksum, new byte[0]);
        expectedStartEntry = new LogEntryStart(6L, 4L, previousChecksum, new byte[0], marker.newPosition());
        previousChecksum = writer.writeCommitEntry(5L, 7L);
        expectedCommitEntry = new LogEntryCommit(5L, 7L, previousChecksum);
        return true;
    });
    LifeSupport life = new LifeSupport();
    var recoveryRequired = new AtomicBoolean();
    var recoveredTransactions = new MutableInt();
    RecoveryMonitor monitor = new RecoveryMonitor() {

        @Override
        public void recoveryRequired(LogPosition recoveryPosition) {
            recoveryRequired.set(true);
        }

        @Override
        public void recoveryCompleted(int numberOfRecoveredTransactions, long recoveryTimeInMilliseconds) {
            recoveredTransactions.setValue(numberOfRecoveredTransactions);
        }
    };
    try {
        StorageEngine storageEngine = mock(StorageEngine.class);
        final LogEntryReader reader = logEntryReader();
        TransactionMetadataCache metadataCache = new TransactionMetadataCache();
        LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore(logFiles, metadataCache, reader, monitors, false);
        CorruptedLogsTruncator logPruner = new CorruptedLogsTruncator(storeDir, logFiles, fileSystem, INSTANCE);
        monitors.addMonitorListener(monitor);
        life.add(new TransactionLogsRecovery(new DefaultRecoveryService(storageEngine, transactionIdStore, txStore, versionRepository, logFiles, NO_MONITOR, mock(Log.class), false) {

            private int nr;

            @Override
            public RecoveryApplier getRecoveryApplier(TransactionApplicationMode mode, PageCacheTracer cacheTracer, String tracerTag) {
                RecoveryApplier actual = super.getRecoveryApplier(mode, cacheTracer, tracerTag);
                if (mode == TransactionApplicationMode.REVERSE_RECOVERY) {
                    return actual;
                }
                return new RecoveryApplier() {

                    @Override
                    public void close() throws Exception {
                        actual.close();
                    }

                    @Override
                    public boolean visit(CommittedTransactionRepresentation tx) throws Exception {
                        actual.visit(tx);
                        switch(nr++) {
                            case 0:
                                assertEquals(lastCommittedTxStartEntry, tx.getStartEntry());
                                assertEquals(lastCommittedTxCommitEntry, tx.getCommitEntry());
                                break;
                            case 1:
                                assertEquals(expectedStartEntry, tx.getStartEntry());
                                assertEquals(expectedCommitEntry, tx.getCommitEntry());
                                break;
                            default:
                                fail("Too many recovered transactions");
                        }
                        return false;
                    }
                };
            }
        }, logPruner, schemaLife, monitor, ProgressReporter.SILENT, false, EMPTY_CHECKER, NULL));
        life.start();
        assertTrue(recoveryRequired.get());
        assertEquals(2, recoveredTransactions.getValue());
    } finally {
        life.shutdown();
    }
}
Also used : LogEntryReader(org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader) PhysicalLogicalTransactionStore(org.neo4j.kernel.impl.transaction.log.PhysicalLogicalTransactionStore) LogicalTransactionStore(org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore) StorageEngine(org.neo4j.storageengine.api.StorageEngine) LogPositionMarker(org.neo4j.kernel.impl.transaction.log.LogPositionMarker) LogFile(org.neo4j.kernel.impl.transaction.log.files.LogFile) LogEntryCommit(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit) TransactionApplicationMode(org.neo4j.storageengine.api.TransactionApplicationMode) LifeSupport(org.neo4j.kernel.lifecycle.LifeSupport) LogEntryWriter(org.neo4j.kernel.impl.transaction.log.entry.LogEntryWriter) LogPosition(org.neo4j.kernel.impl.transaction.log.LogPosition) Path(java.nio.file.Path) LogEntryStart(org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart) PhysicalLogicalTransactionStore(org.neo4j.kernel.impl.transaction.log.PhysicalLogicalTransactionStore) CommittedTransactionRepresentation(org.neo4j.kernel.impl.transaction.CommittedTransactionRepresentation) Log(org.neo4j.logging.Log) PageCacheTracer(org.neo4j.io.pagecache.tracing.PageCacheTracer) TransactionMetadataCache(org.neo4j.kernel.impl.transaction.log.TransactionMetadataCache) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MutableInt(org.apache.commons.lang3.mutable.MutableInt) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 19 with LogEntryCommit

use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.

the class RecoveryProgressIndicatorTest method reportProgressOnRecovery.

@Test
void reportProgressOnRecovery() throws Throwable {
    RecoveryService recoveryService = mock(RecoveryService.class, Answers.RETURNS_MOCKS);
    CorruptedLogsTruncator logsTruncator = mock(CorruptedLogsTruncator.class);
    RecoveryMonitor recoveryMonitor = mock(RecoveryMonitor.class);
    TransactionCursor reverseTransactionCursor = mock(TransactionCursor.class);
    TransactionCursor transactionCursor = mock(TransactionCursor.class);
    CommittedTransactionRepresentation transactionRepresentation = mock(CommittedTransactionRepresentation.class);
    int transactionsToRecover = 5;
    int expectedMax = transactionsToRecover * 2;
    int lastCommittedTransactionId = 14;
    LogPosition transactionLogPosition = new LogPosition(0, CURRENT_FORMAT_LOG_HEADER_SIZE);
    LogPosition checkpointLogPosition = new LogPosition(0, CURRENT_FORMAT_LOG_HEADER_SIZE);
    int firstTxIdAfterLastCheckPoint = 10;
    RecoveryStartInformation startInformation = new RecoveryStartInformation(transactionLogPosition, checkpointLogPosition, firstTxIdAfterLastCheckPoint);
    when(reverseTransactionCursor.next()).thenAnswer(new NextTransactionAnswer(transactionsToRecover));
    when(transactionCursor.next()).thenAnswer(new NextTransactionAnswer(transactionsToRecover));
    when(reverseTransactionCursor.get()).thenReturn(transactionRepresentation);
    when(transactionCursor.get()).thenReturn(transactionRepresentation);
    when(transactionRepresentation.getCommitEntry()).thenReturn(new LogEntryCommit(lastCommittedTransactionId, 1L, BASE_TX_CHECKSUM));
    when(recoveryService.getRecoveryStartInformation()).thenReturn(startInformation);
    when(recoveryService.getTransactionsInReverseOrder(transactionLogPosition)).thenReturn(reverseTransactionCursor);
    when(recoveryService.getTransactions(transactionLogPosition)).thenReturn(transactionCursor);
    AssertableProgressReporter progressReporter = new AssertableProgressReporter(expectedMax);
    TransactionLogsRecovery recovery = new TransactionLogsRecovery(recoveryService, logsTruncator, new LifecycleAdapter(), recoveryMonitor, progressReporter, true, EMPTY_CHECKER, PageCacheTracer.NULL);
    recovery.init();
    progressReporter.verify();
}
Also used : CommittedTransactionRepresentation(org.neo4j.kernel.impl.transaction.CommittedTransactionRepresentation) LifecycleAdapter(org.neo4j.kernel.lifecycle.LifecycleAdapter) TransactionCursor(org.neo4j.kernel.impl.transaction.log.TransactionCursor) LogEntryCommit(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit) LogPosition(org.neo4j.kernel.impl.transaction.log.LogPosition) Test(org.junit.jupiter.api.Test)

Example 20 with LogEntryCommit

use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.

the class DetachedLogTailScanner method getFirstTransactionIdAfterCheckpoint.

private StartCommitEntries getFirstTransactionIdAfterCheckpoint(LogFile logFile, LogPosition logPosition) throws IOException {
    boolean corruptedTransactionLogs = false;
    LogEntryStart start = null;
    LogEntryCommit commit = null;
    LogPosition lookupPosition = null;
    long logVersion = logPosition.getLogVersion();
    try {
        while (logFile.versionExists(logVersion)) {
            lookupPosition = lookupPosition == null ? logPosition : logFile.extractHeader(logVersion).getStartPosition();
            try (var reader = logFile.getReader(lookupPosition, NO_MORE_CHANNELS);
                var cursor = new LogEntryCursor(logEntryReader, reader)) {
                LogEntry entry;
                while ((start == null || commit == null) && cursor.next()) {
                    entry = cursor.get();
                    if (commit == null && entry instanceof LogEntryCommit) {
                        commit = (LogEntryCommit) entry;
                    } else if (start == null && entry instanceof LogEntryStart) {
                        start = (LogEntryStart) entry;
                    }
                }
            }
            if ((start != null) && (commit != null)) {
                return new StartCommitEntries(start, commit);
            }
            verifyReaderPosition(logVersion, logEntryReader.lastPosition());
            logVersion++;
        }
    } catch (Error | ClosedByInterruptException e) {
        // These should not be parsing errors
        throw e;
    } catch (Throwable t) {
        monitor.corruptedLogFile(logVersion, t);
        if (failOnCorruptedLogFiles) {
            throwUnableToCleanRecover(t);
        }
        corruptedTransactionLogs = true;
    }
    return new StartCommitEntries(start, commit, corruptedTransactionLogs);
}
Also used : LogEntryStart(org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart) LogEntryCursor(org.neo4j.kernel.impl.transaction.log.LogEntryCursor) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) LogEntryCommit(org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit) LogEntry(org.neo4j.kernel.impl.transaction.log.entry.LogEntry) LogPosition(org.neo4j.kernel.impl.transaction.log.LogPosition)

Aggregations

LogEntryCommit (org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit)25 LogEntry (org.neo4j.kernel.impl.transaction.log.entry.LogEntry)14 LogEntryStart (org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart)14 CommittedTransactionRepresentation (org.neo4j.kernel.impl.transaction.CommittedTransactionRepresentation)10 LogPosition (org.neo4j.kernel.impl.transaction.log.LogPosition)8 LogEntryCommand (org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand)7 LogEntryCursor (org.neo4j.kernel.impl.transaction.log.LogEntryCursor)6 Test (org.junit.jupiter.api.Test)5 TransactionRepresentation (org.neo4j.kernel.impl.transaction.TransactionRepresentation)5 LogVersionedStoreChannel (org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel)5 ArrayList (java.util.ArrayList)4 PhysicalTransactionRepresentation (org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation)4 StorageCommand (org.neo4j.storageengine.api.StorageCommand)4 ClosedByInterruptException (java.nio.channels.ClosedByInterruptException)3 Test (org.junit.Test)3 LogEntryReader (org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader)3 LogEntryWriter (org.neo4j.kernel.impl.transaction.log.entry.LogEntryWriter)3 CountDownLatch (java.util.concurrent.CountDownLatch)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 IOCursor (org.neo4j.cursor.IOCursor)2