Search in sources :

Example 16 with RawSnapshotWriter

use of org.apache.kafka.snapshot.RawSnapshotWriter in project kafka by apache.

the class MockLogTest method testFailToIncreaseLogStartPastHighWatermark.

@Test
public void testFailToIncreaseLogStartPastHighWatermark() throws IOException {
    int offset = 10;
    int epoch = 0;
    OffsetAndEpoch snapshotId = new OffsetAndEpoch(2 * offset, epoch);
    appendBatch(3 * offset, epoch);
    log.updateHighWatermark(new LogOffsetMetadata(offset));
    try (RawSnapshotWriter snapshot = log.storeSnapshot(snapshotId).get()) {
        snapshot.freeze();
    }
    assertThrows(OffsetOutOfRangeException.class, () -> log.deleteBeforeSnapshot(snapshotId));
}
Also used : RawSnapshotWriter(org.apache.kafka.snapshot.RawSnapshotWriter) Test(org.junit.jupiter.api.Test)

Example 17 with RawSnapshotWriter

use of org.apache.kafka.snapshot.RawSnapshotWriter in project kafka by apache.

the class MockLogTest method testTruncateWillRemoveOlderSnapshot.

@Test
public void testTruncateWillRemoveOlderSnapshot() throws IOException {
    int numberOfRecords = 10;
    int epoch = 1;
    OffsetAndEpoch sameEpochSnapshotId = new OffsetAndEpoch(numberOfRecords, epoch);
    appendBatch(numberOfRecords, epoch);
    log.updateHighWatermark(new LogOffsetMetadata(sameEpochSnapshotId.offset));
    try (RawSnapshotWriter snapshot = log.createNewSnapshot(sameEpochSnapshotId).get()) {
        snapshot.freeze();
    }
    OffsetAndEpoch greaterEpochSnapshotId = new OffsetAndEpoch(2 * numberOfRecords, epoch + 1);
    appendBatch(numberOfRecords, epoch);
    try (RawSnapshotWriter snapshot = log.storeSnapshot(greaterEpochSnapshotId).get()) {
        snapshot.freeze();
    }
    assertTrue(log.truncateToLatestSnapshot());
    assertEquals(Optional.empty(), log.readSnapshot(sameEpochSnapshotId));
}
Also used : RawSnapshotWriter(org.apache.kafka.snapshot.RawSnapshotWriter) Test(org.junit.jupiter.api.Test)

Example 18 with RawSnapshotWriter

use of org.apache.kafka.snapshot.RawSnapshotWriter in project kafka by apache.

the class KafkaRaftClient method handleFetchSnapshotResponse.

private boolean handleFetchSnapshotResponse(RaftResponse.Inbound responseMetadata, long currentTimeMs) {
    FetchSnapshotResponseData data = (FetchSnapshotResponseData) responseMetadata.data;
    Errors topLevelError = Errors.forCode(data.errorCode());
    if (topLevelError != Errors.NONE) {
        return handleTopLevelError(topLevelError, responseMetadata);
    }
    if (data.topics().size() != 1 && data.topics().get(0).partitions().size() != 1) {
        return false;
    }
    Optional<FetchSnapshotResponseData.PartitionSnapshot> partitionSnapshotOpt = FetchSnapshotResponse.forTopicPartition(data, log.topicPartition());
    if (!partitionSnapshotOpt.isPresent()) {
        return false;
    }
    FetchSnapshotResponseData.PartitionSnapshot partitionSnapshot = partitionSnapshotOpt.get();
    FetchSnapshotResponseData.LeaderIdAndEpoch currentLeaderIdAndEpoch = partitionSnapshot.currentLeader();
    OptionalInt responseLeaderId = optionalLeaderId(currentLeaderIdAndEpoch.leaderId());
    int responseEpoch = currentLeaderIdAndEpoch.leaderEpoch();
    Errors error = Errors.forCode(partitionSnapshot.errorCode());
    Optional<Boolean> handled = maybeHandleCommonResponse(error, responseLeaderId, responseEpoch, currentTimeMs);
    if (handled.isPresent()) {
        return handled.get();
    }
    FollowerState state = quorum.followerStateOrThrow();
    if (Errors.forCode(partitionSnapshot.errorCode()) == Errors.SNAPSHOT_NOT_FOUND || partitionSnapshot.snapshotId().endOffset() < 0 || partitionSnapshot.snapshotId().epoch() < 0) {
        /* The leader deleted the snapshot before the follower could download it. Start over by
             * reseting the fetching snapshot state and sending another fetch request.
             */
        logger.trace("Leader doesn't know about snapshot id {}, returned error {} and snapshot id {}", state.fetchingSnapshot(), partitionSnapshot.errorCode(), partitionSnapshot.snapshotId());
        state.setFetchingSnapshot(Optional.empty());
        state.resetFetchTimeout(currentTimeMs);
        return true;
    }
    OffsetAndEpoch snapshotId = new OffsetAndEpoch(partitionSnapshot.snapshotId().endOffset(), partitionSnapshot.snapshotId().epoch());
    RawSnapshotWriter snapshot;
    if (state.fetchingSnapshot().isPresent()) {
        snapshot = state.fetchingSnapshot().get();
    } else {
        throw new IllegalStateException(String.format("Received unexpected fetch snapshot response: %s", partitionSnapshot));
    }
    if (!snapshot.snapshotId().equals(snapshotId)) {
        throw new IllegalStateException(String.format("Received fetch snapshot response with an invalid id. Expected %s; Received %s", snapshot.snapshotId(), snapshotId));
    }
    if (snapshot.sizeInBytes() != partitionSnapshot.position()) {
        throw new IllegalStateException(String.format("Received fetch snapshot response with an invalid position. Expected %s; Received %s", snapshot.sizeInBytes(), partitionSnapshot.position()));
    }
    final UnalignedMemoryRecords records;
    if (partitionSnapshot.unalignedRecords() instanceof MemoryRecords) {
        records = new UnalignedMemoryRecords(((MemoryRecords) partitionSnapshot.unalignedRecords()).buffer());
    } else if (partitionSnapshot.unalignedRecords() instanceof UnalignedMemoryRecords) {
        records = (UnalignedMemoryRecords) partitionSnapshot.unalignedRecords();
    } else {
        throw new IllegalStateException(String.format("Received unexpected fetch snapshot response: %s", partitionSnapshot));
    }
    snapshot.append(records);
    if (snapshot.sizeInBytes() == partitionSnapshot.size()) {
        // Finished fetching the snapshot.
        snapshot.freeze();
        state.setFetchingSnapshot(Optional.empty());
        if (log.truncateToLatestSnapshot()) {
            updateFollowerHighWatermark(state, OptionalLong.of(log.highWatermark().offset));
        } else {
            throw new IllegalStateException(String.format("Full log truncation expected but didn't happen. Snapshot of %s, log end offset %s, last fetched %s", snapshot.snapshotId(), log.endOffset(), log.lastFetchedEpoch()));
        }
    }
    state.resetFetchTimeout(currentTimeMs);
    return true;
}
Also used : FetchSnapshotResponseData(org.apache.kafka.common.message.FetchSnapshotResponseData) OptionalInt(java.util.OptionalInt) Errors(org.apache.kafka.common.protocol.Errors) RawSnapshotWriter(org.apache.kafka.snapshot.RawSnapshotWriter) UnalignedMemoryRecords(org.apache.kafka.common.record.UnalignedMemoryRecords) MemoryRecords(org.apache.kafka.common.record.MemoryRecords) UnalignedMemoryRecords(org.apache.kafka.common.record.UnalignedMemoryRecords)

Example 19 with RawSnapshotWriter

use of org.apache.kafka.snapshot.RawSnapshotWriter in project kafka by apache.

the class KafkaRaftClient method maybeSendFetchOrFetchSnapshot.

private long maybeSendFetchOrFetchSnapshot(FollowerState state, long currentTimeMs) {
    final Supplier<ApiMessage> requestSupplier;
    if (state.fetchingSnapshot().isPresent()) {
        RawSnapshotWriter snapshot = state.fetchingSnapshot().get();
        long snapshotSize = snapshot.sizeInBytes();
        requestSupplier = () -> buildFetchSnapshotRequest(snapshot.snapshotId(), snapshotSize);
    } else {
        requestSupplier = this::buildFetchRequest;
    }
    return maybeSendRequest(currentTimeMs, state.leaderId(), requestSupplier);
}
Also used : RawSnapshotWriter(org.apache.kafka.snapshot.RawSnapshotWriter) ApiMessage(org.apache.kafka.common.protocol.ApiMessage)

Aggregations

RawSnapshotWriter (org.apache.kafka.snapshot.RawSnapshotWriter)19 Test (org.junit.jupiter.api.Test)17 MemoryRecords (org.apache.kafka.common.record.MemoryRecords)2 SimpleRecord (org.apache.kafka.common.record.SimpleRecord)2 ByteBuffer (java.nio.ByteBuffer)1 ArrayList (java.util.ArrayList)1 OptionalInt (java.util.OptionalInt)1 FetchSnapshotResponseData (org.apache.kafka.common.message.FetchSnapshotResponseData)1 ApiMessage (org.apache.kafka.common.protocol.ApiMessage)1 Errors (org.apache.kafka.common.protocol.Errors)1 Record (org.apache.kafka.common.record.Record)1 Records (org.apache.kafka.common.record.Records)1 UnalignedMemoryRecords (org.apache.kafka.common.record.UnalignedMemoryRecords)1 RawSnapshotReader (org.apache.kafka.snapshot.RawSnapshotReader)1