Search in sources :

Example 1 with CheckpointOperationBase

use of io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase in project pravega by pravega.

the class RecoveryProcessor method recoverOperation.

protected void recoverOperation(DataFrameRecord<Operation> dataFrameRecord, OperationMetadataUpdater metadataUpdater) throws ServiceHaltException {
    // Update Metadata Sequence Number.
    Operation operation = dataFrameRecord.getItem();
    metadataUpdater.setOperationSequenceNumber(operation.getSequenceNumber());
    // Update the metadata with the information from the Operation.
    try {
        log.debug("{} Recovering {}.", this.traceObjectId, operation);
        metadataUpdater.preProcessOperation(operation);
        metadataUpdater.acceptOperation(operation);
    } catch (StreamSegmentException | ContainerException ex) {
        // Metadata update failures should not happen during recovery.
        throw new DataCorruptionException(String.format("Unable to update metadata for Log Operation '%s'.", operation), ex);
    }
    // Update in-memory structures.
    this.stateUpdater.process(operation);
    // Perform necessary read index cleanups if possible.
    if (operation instanceof CheckpointOperationBase) {
        this.stateUpdater.cleanupReadIndex();
    }
}
Also used : ContainerException(io.pravega.segmentstore.contracts.ContainerException) StreamSegmentException(io.pravega.segmentstore.contracts.StreamSegmentException) MetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation) Operation(io.pravega.segmentstore.server.logs.operations.Operation) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) CheckpointOperationBase(io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase)

Example 2 with CheckpointOperationBase

use of io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase in project pravega by pravega.

the class OperationProcessorTests method performLogOperationChecks.

private void performLogOperationChecks(Collection<OperationWithCompletion> operations, InMemoryLog memoryLog, DurableDataLog dataLog, TruncationMarkerRepository truncationMarkers, int maxCount) throws Exception {
    // Log Operation based checks
    val successfulOps = operations.stream().filter(oc -> !oc.completion.isCompletedExceptionally()).map(oc -> oc.operation).limit(maxCount).collect(Collectors.toList());
    @Cleanup DataFrameReader<Operation> dataFrameReader = new DataFrameReader<>(dataLog, new OperationSerializer(), CONTAINER_ID);
    long lastSeqNo = -1;
    Iterator<Operation> memoryLogIterator;
    if (successfulOps.isEmpty()) {
        memoryLogIterator = Collections.emptyIterator();
    } else {
        val memoryLogOps = readUpToSequenceNumber(memoryLog, successfulOps.get(successfulOps.size() - 1).getSequenceNumber());
        memoryLogIterator = memoryLogOps.iterator();
    }
    OperationComparer memoryLogComparer = new OperationComparer(true);
    for (Operation expectedOp : successfulOps) {
        // Verify that the operations have been completed and assigned sequential Sequence Numbers.
        AssertExtensions.assertGreaterThan("Operations were not assigned sequential Sequence Numbers.", lastSeqNo, expectedOp.getSequenceNumber());
        lastSeqNo = expectedOp.getSequenceNumber();
        // MemoryLog: verify that the operations match that of the expected list.
        Assert.assertTrue("No more items left to read from MemoryLog. Expected: " + expectedOp, memoryLogIterator.hasNext());
        // Use memoryLogComparer: we are actually expecting the same object here.
        Operation actual = memoryLogIterator.next();
        memoryLogComparer.assertEquals("Unexpected Operation in MemoryLog.", expectedOp, actual);
        // DataLog: read back using DataFrameReader and verify the operations match that of the expected list.
        DataFrameRecord<Operation> dataFrameRecord = dataFrameReader.getNext();
        Assert.assertNotNull("No more items left to read from DataLog. Expected: " + expectedOp, dataFrameRecord);
        // We are reading the raw operation from the DataFrame, so expect different objects (but same contents).
        if (expectedOp instanceof CheckpointOperationBase) {
            // Checkpoint operations are different. While they do serialize their contents, we do not hold on to that
            // since they may be pretty big and serve no purpose after serialization. There are other tests in this suite
            // and in ContainerMetadataUpdateTransactionTests and DurableLogTests that verify we can properly read
            // their contents during recovery.
            val actualEntry = (CheckpointOperationBase) dataFrameRecord.getItem();
            Assert.assertNull("Expected in-memory checkpoint operation to not have contents set.", ((CheckpointOperationBase) expectedOp).getContents());
            Assert.assertNotNull("Expected serialized checkpoint operation to have contents set.", actualEntry.getContents());
            Assert.assertEquals(" Unexpected Sequence Number", expectedOp.getSequenceNumber(), actualEntry.getSequenceNumber());
        } else {
            // All other operations.
            OperationComparer.DEFAULT.assertEquals(expectedOp, dataFrameRecord.getItem());
        }
        // Check truncation markers if this is the last Operation to be written.
        if (dataFrameRecord.getLastFullDataFrameAddress() != null && dataFrameRecord.getLastFullDataFrameAddress().getSequence() != dataFrameRecord.getLastUsedDataFrameAddress().getSequence()) {
            // This operation spans multiple DataFrames. The TruncationMarker should be set on the last DataFrame
            // that ends with a part of it.
            AssertExtensions.assertEventuallyEquals("Unexpected truncation marker for Operation SeqNo " + expectedOp.getSequenceNumber() + " when it spans multiple DataFrames.", dataFrameRecord.getLastFullDataFrameAddress(), () -> truncationMarkers.getClosestTruncationMarker(expectedOp.getSequenceNumber()), 100, TIMEOUT.toMillis());
        } else if (dataFrameRecord.isLastFrameEntry()) {
            // The operation was the last one in the frame. This is a Truncation Marker.
            AssertExtensions.assertEventuallyEquals("Unexpected truncation marker for Operation SeqNo " + expectedOp.getSequenceNumber() + " when it is the last entry in a DataFrame.", dataFrameRecord.getLastUsedDataFrameAddress(), () -> truncationMarkers.getClosestTruncationMarker(expectedOp.getSequenceNumber()), 100, TIMEOUT.toMillis());
        } else {
            // The operation is not the last in the frame, and it doesn't span multiple frames either.
            // There could be data after it that is not safe to truncate. The correct Truncation Marker is the
            // same as the one for the previous operation.
            LogAddress expectedTruncationMarker = truncationMarkers.getClosestTruncationMarker(expectedOp.getSequenceNumber() - 1);
            LogAddress dataFrameAddress = truncationMarkers.getClosestTruncationMarker(expectedOp.getSequenceNumber());
            Assert.assertEquals("Unexpected truncation marker for Operation SeqNo " + expectedOp.getSequenceNumber() + " when it is in the middle of a DataFrame.", expectedTruncationMarker, dataFrameAddress);
        }
    }
}
Also used : lombok.val(lombok.val) OperationSerializer(io.pravega.segmentstore.server.logs.operations.OperationSerializer) Storage(io.pravega.segmentstore.storage.Storage) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) OperationPriority(io.pravega.segmentstore.server.logs.operations.OperationPriority) ThrottleSourceListener(io.pravega.segmentstore.storage.ThrottleSourceListener) SneakyThrows(lombok.SneakyThrows) AssertExtensions(io.pravega.test.common.AssertExtensions) RequiredArgsConstructor(lombok.RequiredArgsConstructor) Cleanup(lombok.Cleanup) LogAddress(io.pravega.segmentstore.storage.LogAddress) StreamSegmentSealedException(io.pravega.segmentstore.contracts.StreamSegmentSealedException) CheckpointOperationBase(io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase) InMemoryStorageFactory(io.pravega.segmentstore.storage.mocks.InMemoryStorageFactory) Duration(java.time.Duration) CachePolicy(io.pravega.segmentstore.server.CachePolicy) Operation(io.pravega.segmentstore.server.logs.operations.Operation) Mockito.doReturn(org.mockito.Mockito.doReturn) CloseableIterator(io.pravega.common.util.CloseableIterator) ServiceListeners(io.pravega.segmentstore.server.ServiceListeners) SegmentStoreMetrics(io.pravega.segmentstore.server.SegmentStoreMetrics) CancellationException(java.util.concurrent.CancellationException) Predicate(java.util.function.Predicate) Collection(java.util.Collection) CompletionException(java.util.concurrent.CompletionException) DataLogWriterNotPrimaryException(io.pravega.segmentstore.storage.DataLogWriterNotPrimaryException) Collectors(java.util.stream.Collectors) ErrorInjector(io.pravega.test.common.ErrorInjector) List(java.util.List) ByteArraySegment(io.pravega.common.util.ByteArraySegment) DirectMemoryCache(io.pravega.segmentstore.storage.cache.DirectMemoryCache) Queue(java.util.Queue) WriteSettings(io.pravega.segmentstore.storage.WriteSettings) CacheManager(io.pravega.segmentstore.server.CacheManager) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) ObjectClosedException(io.pravega.common.ObjectClosedException) MetadataBuilder(io.pravega.segmentstore.server.MetadataBuilder) Getter(lombok.Getter) StreamSegmentException(io.pravega.segmentstore.contracts.StreamSegmentException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Mockito.spy(org.mockito.Mockito.spy) AtomicReference(java.util.concurrent.atomic.AtomicReference) Supplier(java.util.function.Supplier) TruncationMarkerRepository(io.pravega.segmentstore.server.TruncationMarkerRepository) CacheStorage(io.pravega.segmentstore.storage.cache.CacheStorage) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) UpdateableContainerMetadata(io.pravega.segmentstore.server.UpdateableContainerMetadata) Runnables(com.google.common.util.concurrent.Runnables) ReadIndexConfig(io.pravega.segmentstore.server.reading.ReadIndexConfig) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Timeout(org.junit.rules.Timeout) DurableDataLogException(io.pravega.segmentstore.storage.DurableDataLogException) OperationComparer(io.pravega.segmentstore.server.logs.operations.OperationComparer) ContainerReadIndex(io.pravega.segmentstore.server.reading.ContainerReadIndex) Mockito.anyLong(org.mockito.Mockito.anyLong) DurableDataLog(io.pravega.segmentstore.storage.DurableDataLog) Iterator(java.util.Iterator) IntentionalException(io.pravega.test.common.IntentionalException) lombok.val(lombok.val) MetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation) IOException(java.io.IOException) Test(org.junit.Test) TestDurableDataLog(io.pravega.segmentstore.server.TestDurableDataLog) Service(com.google.common.util.concurrent.Service) TimeUnit(java.util.concurrent.TimeUnit) Mockito(org.mockito.Mockito) AbstractMap(java.util.AbstractMap) Rule(org.junit.Rule) StorageOperation(io.pravega.segmentstore.server.logs.operations.StorageOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) QueueStats(io.pravega.segmentstore.storage.QueueStats) ReadIndex(io.pravega.segmentstore.server.ReadIndex) Assert(org.junit.Assert) Collections(java.util.Collections) CompositeArrayView(io.pravega.common.util.CompositeArrayView) OperationSerializer(io.pravega.segmentstore.server.logs.operations.OperationSerializer) OperationComparer(io.pravega.segmentstore.server.logs.operations.OperationComparer) Operation(io.pravega.segmentstore.server.logs.operations.Operation) MetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation) StorageOperation(io.pravega.segmentstore.server.logs.operations.StorageOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) CheckpointOperationBase(io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase) Cleanup(lombok.Cleanup) LogAddress(io.pravega.segmentstore.storage.LogAddress)

Example 3 with CheckpointOperationBase

use of io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase in project pravega by pravega.

the class ContainerMetadataUpdateTransaction method acceptOperation.

/**
 * Accepts the given Operation. The Operation's effects are reflected in the pending transaction.
 * This method has no effect on Metadata Operations.
 * See OperationMetadataUpdater.acceptOperation for more details on behavior.
 *
 * @param operation The operation to accept.
 * @throws MetadataUpdateException If the given operation was rejected given the current state of the metadata.
 * @throws NullPointerException    If the operation is null.
 */
void acceptOperation(Operation operation) throws MetadataUpdateException {
    checkNotSealed();
    if (operation instanceof SegmentOperation) {
        val segmentMetadata = getSegmentUpdateTransaction(((SegmentOperation) operation).getStreamSegmentId());
        segmentMetadata.setLastUsed(operation.getSequenceNumber());
        if (operation instanceof StreamSegmentAppendOperation) {
            segmentMetadata.acceptOperation((StreamSegmentAppendOperation) operation);
        } else if (operation instanceof StreamSegmentSealOperation) {
            segmentMetadata.acceptOperation((StreamSegmentSealOperation) operation);
        } else if (operation instanceof MergeSegmentOperation) {
            MergeSegmentOperation mto = (MergeSegmentOperation) operation;
            SegmentMetadataUpdateTransaction sourceMetadata = getSegmentUpdateTransaction(mto.getSourceSegmentId());
            sourceMetadata.acceptAsSourceSegment(mto);
            sourceMetadata.setLastUsed(operation.getSequenceNumber());
            segmentMetadata.acceptAsTargetSegment(mto, sourceMetadata);
        } else if (operation instanceof UpdateAttributesOperation) {
            segmentMetadata.acceptOperation((UpdateAttributesOperation) operation);
        } else if (operation instanceof StreamSegmentTruncateOperation) {
            segmentMetadata.acceptOperation((StreamSegmentTruncateOperation) operation);
        } else if (operation instanceof DeleteSegmentOperation) {
            segmentMetadata.acceptOperation((DeleteSegmentOperation) operation);
        }
    }
    if (operation instanceof CheckpointOperationBase) {
        if (operation instanceof MetadataCheckpointOperation) {
            // A MetadataCheckpointOperation represents a valid truncation point. Record it as such.
            this.newTruncationPoints.add(operation.getSequenceNumber());
        }
        // Checkpoint operation has been serialized and we no longer need its contents. Clear it and release any
        // memory it used.
        ((CheckpointOperationBase) operation).clearContents();
    } else if (operation instanceof StreamSegmentMapOperation) {
        acceptMetadataOperation((StreamSegmentMapOperation) operation);
    }
}
Also used : lombok.val(lombok.val) DeleteSegmentOperation(io.pravega.segmentstore.server.logs.operations.DeleteSegmentOperation) StreamSegmentSealOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation) StreamSegmentTruncateOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentTruncateOperation) StorageMetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.StorageMetadataCheckpointOperation) MetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation) UpdateAttributesOperation(io.pravega.segmentstore.server.logs.operations.UpdateAttributesOperation) MergeSegmentOperation(io.pravega.segmentstore.server.logs.operations.MergeSegmentOperation) SegmentOperation(io.pravega.segmentstore.server.SegmentOperation) DeleteSegmentOperation(io.pravega.segmentstore.server.logs.operations.DeleteSegmentOperation) StreamSegmentMapOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentMapOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) CheckpointOperationBase(io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase) MergeSegmentOperation(io.pravega.segmentstore.server.logs.operations.MergeSegmentOperation)

Example 4 with CheckpointOperationBase

use of io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase in project pravega by pravega.

the class DurableLogTests method assertRecoveredOperationsMatch.

private void assertRecoveredOperationsMatch(List<Operation> expected, List<Operation> actual) {
    Assert.assertEquals("Recovered operations do not match original ones. Collections differ in size.", expected.size(), actual.size());
    for (int i = 0; i < expected.size(); i++) {
        Operation expectedItem = expected.get(i);
        Operation actualItem = actual.get(i);
        if (expectedItem instanceof CheckpointOperationBase) {
            Assert.assertNull("Recovered Checkpoint Operation did not have contents cleared up.", ((CheckpointOperationBase) actualItem).getContents());
            Assert.assertEquals(" Unexpected Sequence Number", expectedItem.getSequenceNumber(), actualItem.getSequenceNumber());
        } else {
            OperationComparer.DEFAULT.assertEquals(String.format("Recovered operations do not match original ones. Elements at index %d differ. Expected '%s', found '%s'.", i, expectedItem, actualItem), expectedItem, actualItem);
        }
    }
}
Also used : StorageMetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.StorageMetadataCheckpointOperation) MergeSegmentOperation(io.pravega.segmentstore.server.logs.operations.MergeSegmentOperation) Operation(io.pravega.segmentstore.server.logs.operations.Operation) StreamSegmentMapOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentMapOperation) MetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation) CachedStreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.CachedStreamSegmentAppendOperation) StorageOperation(io.pravega.segmentstore.server.logs.operations.StorageOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) DeleteSegmentOperation(io.pravega.segmentstore.server.logs.operations.DeleteSegmentOperation) StreamSegmentSealOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation) CheckpointOperationBase(io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase)

Example 5 with CheckpointOperationBase

use of io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase in project pravega by pravega.

the class OperationProcessorTests method performFailureRecoveryChecks.

private void performFailureRecoveryChecks(List<OperationWithCompletion> operations, TestDurableDataLog dataLog) throws Exception {
    boolean encounteredFailure = false;
    val successfulOps = new ArrayList<Operation>();
    for (val oc : operations) {
        encounteredFailure |= oc.completion.isCompletedExceptionally();
        if (encounteredFailure) {
            Assert.assertTrue("Found a non-errorred operation after an errorred operation.", oc.completion.isCompletedExceptionally());
        } else {
            Assert.assertTrue(oc.completion.isDone());
            successfulOps.add(oc.operation);
        }
    }
    @Cleanup DataFrameReader<Operation> dataFrameReader = new DataFrameReader<>(dataLog, new OperationSerializer(), CONTAINER_ID);
    long lastSeqNo = -1;
    for (Operation expectedOp : successfulOps) {
        // Verify that the operations have been completed and assigned sequential Sequence Numbers.
        AssertExtensions.assertGreaterThan("Operations were not assigned sequential Sequence Numbers.", lastSeqNo, expectedOp.getSequenceNumber());
        lastSeqNo = expectedOp.getSequenceNumber();
        // DataLog: read back using DataFrameReader and verify the operations match that of the expected list.
        DataFrameRecord<Operation> dataFrameRecord = dataFrameReader.getNext();
        Assert.assertNotNull("No more items left to read from DataLog. Expected: " + expectedOp, dataFrameRecord);
        // We are reading the raw operation from the DataFrame, so expect different objects (but same contents).
        if (expectedOp instanceof CheckpointOperationBase) {
            // Checkpoint operations are different. While they do serialize their contents, we do not hold on to that
            // since they may be pretty big and serve no purpose after serialization. There are other tests in this suite
            // and in ContainerMetadataUpdateTransactionTests and DurableLogTests that verify we can properly read
            // their contents during recovery.
            val actualEntry = (CheckpointOperationBase) dataFrameRecord.getItem();
            Assert.assertNull("Expected in-memory checkpoint operation to not have contents set.", ((CheckpointOperationBase) expectedOp).getContents());
            Assert.assertNotNull("Expected serialized checkpoint operation to have contents set.", actualEntry.getContents());
            Assert.assertEquals(" Unexpected Sequence Number", expectedOp.getSequenceNumber(), actualEntry.getSequenceNumber());
        } else {
            // All other operations.
            OperationComparer.DEFAULT.assertEquals(expectedOp, dataFrameRecord.getItem());
        }
    }
}
Also used : lombok.val(lombok.val) OperationSerializer(io.pravega.segmentstore.server.logs.operations.OperationSerializer) ArrayList(java.util.ArrayList) Operation(io.pravega.segmentstore.server.logs.operations.Operation) MetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation) StorageOperation(io.pravega.segmentstore.server.logs.operations.StorageOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) CheckpointOperationBase(io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase) Cleanup(lombok.Cleanup)

Aggregations

CheckpointOperationBase (io.pravega.segmentstore.server.logs.operations.CheckpointOperationBase)5 MetadataCheckpointOperation (io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation)5 Operation (io.pravega.segmentstore.server.logs.operations.Operation)4 StreamSegmentAppendOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation)4 StorageOperation (io.pravega.segmentstore.server.logs.operations.StorageOperation)3 StreamSegmentException (io.pravega.segmentstore.contracts.StreamSegmentException)2 DeleteSegmentOperation (io.pravega.segmentstore.server.logs.operations.DeleteSegmentOperation)2 MergeSegmentOperation (io.pravega.segmentstore.server.logs.operations.MergeSegmentOperation)2 OperationSerializer (io.pravega.segmentstore.server.logs.operations.OperationSerializer)2 StorageMetadataCheckpointOperation (io.pravega.segmentstore.server.logs.operations.StorageMetadataCheckpointOperation)2 StreamSegmentMapOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentMapOperation)2 StreamSegmentSealOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation)2 lombok.val (lombok.val)2 Runnables (com.google.common.util.concurrent.Runnables)1 Service (com.google.common.util.concurrent.Service)1 ObjectClosedException (io.pravega.common.ObjectClosedException)1 ByteArraySegment (io.pravega.common.util.ByteArraySegment)1 CloseableIterator (io.pravega.common.util.CloseableIterator)1 CompositeArrayView (io.pravega.common.util.CompositeArrayView)1 ContainerException (io.pravega.segmentstore.contracts.ContainerException)1