Search in sources :

Example 1 with SimpleLogVersionRepository

use of org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository in project neo4j by neo4j.

the class VersionAwareLogEntryReaderIT method correctlyResetPositionOfObservedZeroWhenChannelSwitchOnExactlyCheckedByte.

@Test
void correctlyResetPositionOfObservedZeroWhenChannelSwitchOnExactlyCheckedByte() throws IOException {
    LogFiles logFiles = LogFilesBuilder.builder(databaseLayout, fs).withLogEntryReader(entryReader).withLogVersionRepository(new SimpleLogVersionRepository()).withTransactionIdStore(new SimpleTransactionIdStore()).withStoreId(StoreId.UNKNOWN).withKernelVersionProvider(() -> KernelVersion.V4_0).build();
    try (Lifespan lifespan = new Lifespan(logFiles)) {
        LogPositionMarker positionMarker = new LogPositionMarker();
        LogFile logFile = logFiles.getLogFile();
        long initialPosition = getLastReadablePosition(logFiles);
        long checkpointsEndDataOffset = DEFAULT_READ_AHEAD_SIZE + initialPosition;
        TransactionLogWriter logWriter = logFile.getTransactionLogWriter();
        do {
            logWriter.legacyCheckPoint(new LogPosition(4, 5));
            logWriter.getCurrentPosition(positionMarker);
        } while (positionMarker.getByteOffset() <= checkpointsEndDataOffset);
        logFile.flush();
        logFiles.getLogFile().rotate();
        fs.truncate(logFiles.getLogFile().getLogFileForVersion(0), checkpointsEndDataOffset);
        try (StoreChannel storeChannel = fs.write(logFiles.getLogFile().getLogFileForVersion(1))) {
            storeChannel.position(CURRENT_FORMAT_LOG_HEADER_SIZE);
            storeChannel.writeAll(ByteBuffer.wrap(new byte[] { 0 }));
        }
        try (ReadableLogChannel logChannel = logFiles.getLogFile().getReader(new LogPosition(0, initialPosition))) {
            LogEntry logEntry = entryReader.readLogEntry(logChannel);
            // we reading expected checkpoint records
            assertThat(logEntry).isInstanceOf(LogEntryInlinedCheckPoint.class);
            LogEntryInlinedCheckPoint checkPoint = (LogEntryInlinedCheckPoint) logEntry;
            LogPosition logPosition = checkPoint.getLogPosition();
            assertEquals(4, logPosition.getLogVersion());
            assertEquals(5, logPosition.getByteOffset());
            // set position to the end of the buffer to cause channel switch on next byte read
            ((PositionableChannel) logChannel).setCurrentPosition(checkpointsEndDataOffset);
            while (entryReader.readLogEntry(logChannel) != null) {
            // read to the end
            }
            // channel should be switched now and position should be just after the header
            LogPosition position = entryReader.lastPosition();
            assertEquals(CURRENT_FORMAT_LOG_HEADER_SIZE, position.getByteOffset());
            assertEquals(1, position.getLogVersion());
        }
    }
}
Also used : ReadableLogChannel(org.neo4j.kernel.impl.transaction.log.ReadableLogChannel) SimpleTransactionIdStore(org.neo4j.kernel.impl.transaction.SimpleTransactionIdStore) StoreChannel(org.neo4j.io.fs.StoreChannel) LogFiles(org.neo4j.kernel.impl.transaction.log.files.LogFiles) SimpleLogVersionRepository(org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository) PositionableChannel(org.neo4j.io.fs.PositionableChannel) LogPositionMarker(org.neo4j.kernel.impl.transaction.log.LogPositionMarker) LogFile(org.neo4j.kernel.impl.transaction.log.files.LogFile) TransactionLogWriter(org.neo4j.kernel.impl.transaction.log.TransactionLogWriter) Lifespan(org.neo4j.kernel.lifecycle.Lifespan) LogPosition(org.neo4j.kernel.impl.transaction.log.LogPosition) Test(org.junit.jupiter.api.Test)

Example 2 with SimpleLogVersionRepository

use of org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository in project neo4j by neo4j.

the class LogFilesBuilderTest method buildActiveFilesOnlyContext.

@Test
void buildActiveFilesOnlyContext() throws IOException {
    TransactionLogFilesContext context = activeFilesBuilder(databaseLayout, fileSystem, pageCache).withLogEntryReader(logEntryReader()).withLogVersionRepository(new SimpleLogVersionRepository()).withTransactionIdStore(new SimpleTransactionIdStore()).buildContext();
    assertEquals(fileSystem, context.getFileSystem());
    assertNotNull(context.getLogEntryReader());
    assertEquals(Long.MAX_VALUE, context.getRotationThreshold().get());
    assertEquals(TransactionIdStore.BASE_TX_ID, context.getLastCommittedTransactionId());
    assertEquals(0, context.getLogVersionRepository().getCurrentLogVersion());
}
Also used : SimpleTransactionIdStore(org.neo4j.kernel.impl.transaction.SimpleTransactionIdStore) SimpleLogVersionRepository(org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository) Test(org.junit.jupiter.api.Test)

Example 3 with SimpleLogVersionRepository

use of org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository in project neo4j by neo4j.

the class LogFilesBuilderTest method buildContextWithRotationThreshold.

@Test
void buildContextWithRotationThreshold() throws IOException {
    TransactionLogFilesContext context = builder(databaseLayout, fileSystem).withLogVersionRepository(new SimpleLogVersionRepository(2)).withTransactionIdStore(new SimpleTransactionIdStore()).withLogEntryReader(logEntryReader()).withRotationThreshold(ByteUnit.mebiBytes(1)).buildContext();
    assertEquals(fileSystem, context.getFileSystem());
    assertNotNull(context.getLogEntryReader());
    assertEquals(ByteUnit.mebiBytes(1), context.getRotationThreshold().get());
    assertEquals(1, context.getLastCommittedTransactionId());
    assertEquals(2, context.getLogVersionRepository().getCurrentLogVersion());
}
Also used : SimpleTransactionIdStore(org.neo4j.kernel.impl.transaction.SimpleTransactionIdStore) SimpleLogVersionRepository(org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository) Test(org.junit.jupiter.api.Test)

Example 4 with SimpleLogVersionRepository

use of org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository in project neo4j by neo4j.

the class TransactionLogFileRotateAndReadRaceIT method shouldNotSeeEmptyLogFileWhenReadingTransactionStream.

@Test
void shouldNotSeeEmptyLogFileWhenReadingTransactionStream() throws Exception {
    // GIVEN
    LogVersionRepository logVersionRepository = new SimpleLogVersionRepository();
    Config cfg = Config.newBuilder().set(GraphDatabaseSettings.neo4j_home, databaseLayout.getNeo4jLayout().homeDirectory()).set(GraphDatabaseSettings.preallocate_logical_logs, false).set(GraphDatabaseSettings.logical_log_rotation_threshold, ByteUnit.kibiBytes(128)).build();
    LogFiles logFiles = LogFilesBuilder.builder(databaseLayout, fs).withLogVersionRepository(logVersionRepository).withTransactionIdStore(new SimpleTransactionIdStore()).withLogEntryReader(new VersionAwareLogEntryReader(new TestCommandReaderFactory())).withConfig(cfg).withStoreId(StoreId.UNKNOWN).build();
    life.add(logFiles);
    LogFile logFile = logFiles.getLogFile();
    var writer = logFile.getTransactionLogWriter();
    LogPositionMarker startPosition = new LogPositionMarker();
    writer.getCurrentPosition(startPosition);
    // WHEN
    AtomicBoolean end = new AtomicBoolean();
    byte[] dataChunk = new byte[100];
    // one thread constantly writing to and rotating the channel
    CountDownLatch startSignal = new CountDownLatch(1);
    Future<Void> writeFuture = t2.execute(() -> {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        startSignal.countDown();
        int rotations = 0;
        while (!end.get()) {
            int bytesToWrite = random.nextInt(1, dataChunk.length);
            writer.getChannel().put(dataChunk, bytesToWrite);
            if (logFile.rotationNeeded()) {
                logFile.rotate();
                // Let's just close the gap to the reader so that it gets closer to the "hot zone"
                // where the rotation happens.
                writer.getCurrentPosition(startPosition);
                if (++rotations > LIMIT_ROTATIONS) {
                    end.set(true);
                }
            }
        }
        return null;
    });
    assertTrue(startSignal.await(10, SECONDS));
    // one thread reading through the channel
    try {
        int reads = 0;
        while (!end.get()) {
            try (ReadableLogChannel reader = logFile.getReader(startPosition.newPosition())) {
                deplete(reader);
            }
            if (++reads > LIMIT_READS) {
                end.set(true);
            }
        }
    } finally {
        writeFuture.get();
    }
// THEN simply getting here means this was successful
}
Also used : SimpleTransactionIdStore(org.neo4j.kernel.impl.transaction.SimpleTransactionIdStore) Config(org.neo4j.configuration.Config) LogFiles(org.neo4j.kernel.impl.transaction.log.files.LogFiles) SimpleLogVersionRepository(org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository) TestCommandReaderFactory(org.neo4j.kernel.impl.api.TestCommandReaderFactory) CountDownLatch(java.util.concurrent.CountDownLatch) LogVersionRepository(org.neo4j.storageengine.api.LogVersionRepository) SimpleLogVersionRepository(org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository) LogFile(org.neo4j.kernel.impl.transaction.log.files.LogFile) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) VersionAwareLogEntryReader(org.neo4j.kernel.impl.transaction.log.entry.VersionAwareLogEntryReader) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) Test(org.junit.jupiter.api.Test)

Example 5 with SimpleLogVersionRepository

use of org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository in project neo4j by neo4j.

the class LogPruningIT method pruningStrategyShouldBeDynamic.

@Test
void pruningStrategyShouldBeDynamic() throws IOException {
    LogFiles logFiles = LogFilesBuilder.builder(db.databaseLayout(), fs).withLogVersionRepository(new SimpleLogVersionRepository()).withLastCommittedTransactionIdSupplier(() -> 1).withCommandReaderFactory(db.getDependencyResolver().resolveDependency(StorageEngineFactory.class).commandReaderFactory()).withTransactionIdStore(new SimpleTransactionIdStore()).build();
    // Force transaction log rotation
    writeTransactionsAndRotateTwice();
    // Checkpoint to make sure strategy is evaluated
    checkPointer.forceCheckPoint(triggerInfo);
    // Make sure file is still there since we have disable pruning. 3 transaction logs and 1 separate checkpoint file.
    assertThat(countTransactionLogs(logFiles)).isEqualTo(4);
    // Change pruning to true
    config.setDynamic(keep_logical_logs, FALSE, "LogPruningIT");
    // Checkpoint to make sure strategy is evaluated
    checkPointer.forceCheckPoint(triggerInfo);
    // Make sure file is removed
    assertThat(countTransactionLogs(logFiles)).isEqualTo(3);
}
Also used : SimpleTransactionIdStore(org.neo4j.kernel.impl.transaction.SimpleTransactionIdStore) LogFiles(org.neo4j.kernel.impl.transaction.log.files.LogFiles) SimpleLogVersionRepository(org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository) Test(org.junit.jupiter.api.Test)

Aggregations

SimpleLogVersionRepository (org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository)17 SimpleTransactionIdStore (org.neo4j.kernel.impl.transaction.SimpleTransactionIdStore)17 Test (org.junit.jupiter.api.Test)13 LogFiles (org.neo4j.kernel.impl.transaction.log.files.LogFiles)8 Lifespan (org.neo4j.kernel.lifecycle.Lifespan)5 LogPosition (org.neo4j.kernel.impl.transaction.log.LogPosition)4 BeforeEach (org.junit.jupiter.api.BeforeEach)3 LogFile (org.neo4j.kernel.impl.transaction.log.files.LogFile)3 LogVersionRepository (org.neo4j.storageengine.api.LogVersionRepository)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 Config (org.neo4j.configuration.Config)2 TestCommandReaderFactory (org.neo4j.kernel.impl.api.TestCommandReaderFactory)2 VersionAwareLogEntryReader (org.neo4j.kernel.impl.transaction.log.entry.VersionAwareLogEntryReader)2 DatabaseHealth (org.neo4j.monitoring.DatabaseHealth)2 IOException (java.io.IOException)1 Path (java.nio.file.Path)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ThreadLocalRandom (java.util.concurrent.ThreadLocalRandom)1 DisabledOnOs (org.junit.jupiter.api.condition.DisabledOnOs)1 EnabledOnOs (org.junit.jupiter.api.condition.EnabledOnOs)1