Search in sources :

Example 1 with Exceptions

use of io.pravega.common.Exceptions in project pravega by pravega.

the class StreamSegmentContainer method deleteStreamSegment.

@Override
public CompletableFuture<Void> deleteStreamSegment(String streamSegmentName, Duration timeout) {
    ensureRunning();
    logRequest("deleteStreamSegment", streamSegmentName);
    this.metrics.deleteSegment();
    TimeoutTimer timer = new TimeoutTimer(timeout);
    // metadata.deleteStreamSegment will delete the given StreamSegment and all Transactions associated with it.
    // It returns a mapping of segment ids to names of StreamSegments that were deleted.
    // As soon as this happens, all operations that deal with those segments will start throwing appropriate exceptions
    // or ignore the segments altogether (such as StorageWriter).
    Collection<SegmentMetadata> deletedSegments = this.metadata.deleteStreamSegment(streamSegmentName);
    val deletionFutures = new ArrayList<CompletableFuture<Void>>();
    for (SegmentMetadata toDelete : deletedSegments) {
        deletionFutures.add(this.storage.openWrite(toDelete.getName()).thenComposeAsync(handle -> this.storage.delete(handle, timer.getRemaining()), this.executor).thenComposeAsync(v -> this.stateStore.remove(toDelete.getName(), timer.getRemaining()), this.executor).exceptionally(ex -> {
            ex = Exceptions.unwrap(ex);
            if (ex instanceof StreamSegmentNotExistsException && toDelete.isTransaction()) {
                // did not get a chance to get updated.
                return null;
            }
            throw new CompletionException(ex);
        }));
    }
    notifyMetadataRemoved(deletedSegments);
    return Futures.allOf(deletionFutures);
}
Also used : SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) lombok.val(lombok.val) ObjectClosedException(io.pravega.common.ObjectClosedException) Storage(io.pravega.segmentstore.storage.Storage) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) IllegalContainerStateException(io.pravega.segmentstore.server.IllegalContainerStateException) Exceptions(io.pravega.common.Exceptions) StorageFactory(io.pravega.segmentstore.storage.StorageFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) SegmentProperties(io.pravega.segmentstore.contracts.SegmentProperties) ReadIndexFactory(io.pravega.segmentstore.server.ReadIndexFactory) AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) Duration(java.time.Duration) AbstractService(com.google.common.util.concurrent.AbstractService) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Operation(io.pravega.segmentstore.server.logs.operations.Operation) StreamSegmentTruncateOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentTruncateOperation) LoggerHelpers(io.pravega.common.LoggerHelpers) WriterFactory(io.pravega.segmentstore.server.WriterFactory) Services(io.pravega.common.concurrent.Services) ContainerOfflineException(io.pravega.segmentstore.server.ContainerOfflineException) TimeoutTimer(io.pravega.common.TimeoutTimer) SegmentStoreMetrics(io.pravega.segmentstore.server.SegmentStoreMetrics) UpdateAttributesOperation(io.pravega.segmentstore.server.logs.operations.UpdateAttributesOperation) Collection(java.util.Collection) lombok.val(lombok.val) OperationLog(io.pravega.segmentstore.server.OperationLog) CompletionException(java.util.concurrent.CompletionException) Writer(io.pravega.segmentstore.server.Writer) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) Service(com.google.common.util.concurrent.Service) Objects(java.util.Objects) Consumer(java.util.function.Consumer) Slf4j(lombok.extern.slf4j.Slf4j) AsyncMap(io.pravega.common.util.AsyncMap) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) OperationLogFactory(io.pravega.segmentstore.server.OperationLogFactory) SegmentContainer(io.pravega.segmentstore.server.SegmentContainer) Preconditions(com.google.common.base.Preconditions) ReadIndex(io.pravega.segmentstore.server.ReadIndex) MergeTransactionOperation(io.pravega.segmentstore.server.logs.operations.MergeTransactionOperation) Futures(io.pravega.common.concurrent.Futures) ReadResult(io.pravega.segmentstore.contracts.ReadResult) StreamSegmentSealOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation) CompletionException(java.util.concurrent.CompletionException) ArrayList(java.util.ArrayList) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) TimeoutTimer(io.pravega.common.TimeoutTimer)

Example 2 with Exceptions

use of io.pravega.common.Exceptions in project pravega by pravega.

the class Futures method doWhileLoop.

/**
 * Executes a code fragment returning a CompletableFutures while a condition on the returned value is satisfied.
 *
 * @param condition Predicate that indicates whether to proceed with the loop or not.
 * @param loopBody  A Supplier that returns a CompletableFuture which represents the body of the loop. This
 *                  supplier is invoked every time the loopBody needs to execute.
 * @param executor  An Executor that is used to execute the condition and the loop support code.
 * @param <T>       Return type of the executor.
 * @return A CompletableFuture that, when completed, indicates the loop terminated without any exception. If
 * either the loopBody or condition throw/return Exceptions, these will be set as the result of this returned Future.
 */
public static <T> CompletableFuture<Void> doWhileLoop(Supplier<CompletableFuture<T>> loopBody, Predicate<T> condition, Executor executor) {
    CompletableFuture<Void> result = new CompletableFuture<>();
    // We implement the do-while loop using a regular loop, but we execute one iteration before we create the actual Loop object.
    // Since this method has slightly different arguments than loop(), we need to make one adjustment:
    // * After each iteration, we get the result and run it through 'condition' and use that to decide whether to continue.
    AtomicBoolean canContinue = new AtomicBoolean();
    Consumer<T> iterationResultHandler = ir -> canContinue.set(condition.test(ir));
    loopBody.get().thenAccept(iterationResultHandler).thenRunAsync(() -> {
        Loop<T> loop = new Loop<>(canContinue::get, loopBody, iterationResultHandler, result, executor);
        executor.execute(loop);
    }, executor).exceptionally(ex -> {
        // Handle exceptions from the first iteration.
        result.completeExceptionally(ex);
        return null;
    });
    return result;
}
Also used : ScheduledFuture(java.util.concurrent.ScheduledFuture) SneakyThrows(lombok.SneakyThrows) Exceptions(io.pravega.common.Exceptions) TimeoutException(java.util.concurrent.TimeoutException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Callable(java.util.concurrent.Callable) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) Supplier(java.util.function.Supplier) Future(java.util.concurrent.Future) Duration(java.time.Duration) Map(java.util.Map) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Callbacks(io.pravega.common.function.Callbacks) Executor(java.util.concurrent.Executor) Predicate(java.util.function.Predicate) Collection(java.util.Collection) lombok.val(lombok.val) CompletionException(java.util.concurrent.CompletionException) Collectors(java.util.stream.Collectors) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) List(java.util.List) Data(lombok.Data) Preconditions(com.google.common.base.Preconditions) Lombok(lombok.Lombok) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture)

Example 3 with Exceptions

use of io.pravega.common.Exceptions in project pravega by pravega.

the class DataFrameReaderTests method testReadsNoFailure.

/**
 * Tests the happy case: DataFrameReader can read from a DataLog when the are no exceptions.
 */
@Test
public void testReadsNoFailure() throws Exception {
    // Fail every X records (write-wise).
    int failEvery = 7;
    ArrayList<TestLogItem> records = DataFrameTestHelpers.generateLogItems(100, SMALL_RECORD_MIN_SIZE, SMALL_RECORD_MAX_SIZE, 0);
    records.addAll(DataFrameTestHelpers.generateLogItems(100, LARGE_RECORD_MIN_SIZE, LARGE_RECORD_MAX_SIZE, records.size()));
    // Have every other 'failEvery' record fail after writing 90% of itself.
    for (int i = 0; i < records.size(); i += failEvery) {
        records.get(i).failSerializationAfterComplete(0.9, new IOException("intentional " + i));
    }
    HashSet<Integer> failedIndices = new HashSet<>();
    try (TestDurableDataLog dataLog = TestDurableDataLog.create(CONTAINER_ID, FRAME_SIZE, executorService())) {
        dataLog.initialize(TIMEOUT);
        BiConsumer<Throwable, DataFrameBuilder.CommitArgs> errorCallback = (ex, a) -> Assert.fail(String.format("Unexpected error occurred upon commit. %s", ex));
        val args = new DataFrameBuilder.Args(Callbacks::doNothing, Callbacks::doNothing, errorCallback, executorService());
        try (DataFrameBuilder<TestLogItem> b = new DataFrameBuilder<>(dataLog, SERIALIZER, args)) {
            for (int i = 0; i < records.size(); i++) {
                try {
                    b.append(records.get(i));
                } catch (IOException ex) {
                    failedIndices.add(i);
                }
            }
            b.flush();
        }
        TestSerializer logItemFactory = new TestSerializer();
        DataFrameReader<TestLogItem> reader = new DataFrameReader<>(dataLog, logItemFactory, CONTAINER_ID);
        List<TestLogItem> readItems = readAll(reader);
        checkReadResult(records, failedIndices, readItems);
    }
}
Also used : ObjectClosedException(io.pravega.common.ObjectClosedException) Callbacks(io.pravega.common.function.Callbacks) DurableDataLog(io.pravega.segmentstore.storage.DurableDataLog) AssertExtensions(io.pravega.test.common.AssertExtensions) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Exceptions(io.pravega.common.Exceptions) lombok.val(lombok.val) IOException(java.io.IOException) Test(org.junit.Test) TestDurableDataLog(io.pravega.segmentstore.server.TestDurableDataLog) ErrorInjector(io.pravega.test.common.ErrorInjector) DataLogNotAvailableException(io.pravega.segmentstore.storage.DataLogNotAvailableException) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) List(java.util.List) Rule(org.junit.Rule) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) Duration(java.time.Duration) BiConsumer(java.util.function.BiConsumer) Timeout(org.junit.rules.Timeout) SerializationException(io.pravega.common.io.SerializationException) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) Assert(org.junit.Assert) lombok.val(lombok.val) TestDurableDataLog(io.pravega.segmentstore.server.TestDurableDataLog) IOException(java.io.IOException) Callbacks(io.pravega.common.function.Callbacks) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 4 with Exceptions

use of io.pravega.common.Exceptions in project pravega by pravega.

the class StorageWriterTests method testWithStorageCorruptionErrors.

/**
 * Tests the StorageWriter in a Scenario where the Storage component throws data corruption exceptions (i.e., badOffset,
 * and after reconciliation, the data is still corrupt).
 */
@Test
public void testWithStorageCorruptionErrors() throws Exception {
    @Cleanup TestContext context = new TestContext(DEFAULT_CONFIG);
    // Create a bunch of segments and Transactions.
    ArrayList<Long> segmentIds = createSegments(context);
    // Append data.
    HashMap<Long, ByteArrayOutputStream> segmentContents = new HashMap<>();
    appendDataBreadthFirst(segmentIds, segmentContents, context);
    // Corrupt (one segment should suffice).
    byte[] corruptionData = "foo".getBytes();
    SegmentHandle corruptedSegmentHandle = InMemoryStorage.newHandle(context.metadata.getStreamSegmentMetadata(segmentIds.get(0)).getName(), false);
    Supplier<Exception> exceptionSupplier = () -> {
        // Corrupt data. We use an internal method (append) to atomically write data at the end of the segment.
        // GetLength+Write would not work well because there may be concurrent writes that modify the data between
        // requesting the length and attempting to write, thus causing the corruption to fail.
        // NOTE: this is a synchronous call, but append() is also a sync method. If append() would become async,
        // care must be taken not to block a thread while waiting for it.
        context.storage.append(corruptedSegmentHandle, new ByteArrayInputStream(corruptionData), corruptionData.length);
        // Return some other kind of exception.
        return new TimeoutException("Intentional");
    };
    // We only try to corrupt data once.
    AtomicBoolean corruptionHappened = new AtomicBoolean();
    context.storage.setWriteAsyncErrorInjector(new ErrorInjector<>(c -> !corruptionHappened.getAndSet(true), exceptionSupplier));
    AssertExtensions.assertThrows("StorageWriter did not fail when a fatal data corruption error occurred.", () -> {
        // The Corruption may happen early enough so the "awaitRunning" isn't complete yet. In that case,
        // the writer will never reach its 'Running' state. As such, we need to make sure at least one of these
        // will throw (either start or, if the failure happened after start, make sure it eventually fails and shuts down).
        context.writer.startAsync().awaitRunning();
        ServiceListeners.awaitShutdown(context.writer, TIMEOUT, true);
    }, ex -> ex instanceof IllegalStateException);
    ServiceListeners.awaitShutdown(context.writer, TIMEOUT, false);
    Assert.assertTrue("Unexpected failure cause for StorageWriter.", Exceptions.unwrap(context.writer.failureCause()) instanceof ReconciliationFailureException);
}
Also used : AssertExtensions(io.pravega.test.common.AssertExtensions) ContainerMetadata(io.pravega.segmentstore.server.ContainerMetadata) TimeoutException(java.util.concurrent.TimeoutException) Cleanup(lombok.Cleanup) UpdateableSegmentMetadata(io.pravega.segmentstore.server.UpdateableSegmentMetadata) SegmentProperties(io.pravega.segmentstore.contracts.SegmentProperties) SegmentHandle(io.pravega.segmentstore.storage.SegmentHandle) ByteArrayInputStream(java.io.ByteArrayInputStream) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) Operation(io.pravega.segmentstore.server.logs.operations.Operation) StreamSegmentTruncateOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentTruncateOperation) ServiceListeners(io.pravega.segmentstore.server.ServiceListeners) Collection(java.util.Collection) InMemoryStorage(io.pravega.segmentstore.storage.mocks.InMemoryStorage) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) ErrorInjector(io.pravega.test.common.ErrorInjector) StreamSegmentNameUtils(io.pravega.shared.segment.StreamSegmentNameUtils) List(java.util.List) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) TestStorage(io.pravega.segmentstore.server.TestStorage) MetadataBuilder(io.pravega.segmentstore.server.MetadataBuilder) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Exceptions(io.pravega.common.Exceptions) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) Function(java.util.function.Function) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) EvictableMetadata(io.pravega.segmentstore.server.EvictableMetadata) UpdateableContainerMetadata(io.pravega.segmentstore.server.UpdateableContainerMetadata) SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) Timeout(org.junit.rules.Timeout) StreamSegmentMapOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentMapOperation) 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) TimeUnit(java.util.concurrent.TimeUnit) Rule(org.junit.Rule) CachedStreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.CachedStreamSegmentAppendOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) Assert(org.junit.Assert) MergeTransactionOperation(io.pravega.segmentstore.server.logs.operations.MergeTransactionOperation) StreamSegmentSealOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation) HashMap(java.util.HashMap) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Cleanup(lombok.Cleanup) SegmentHandle(io.pravega.segmentstore.storage.SegmentHandle) TimeoutException(java.util.concurrent.TimeoutException) IntentionalException(io.pravega.test.common.IntentionalException) IOException(java.io.IOException) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ByteArrayInputStream(java.io.ByteArrayInputStream) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.Test)

Example 5 with Exceptions

use of io.pravega.common.Exceptions in project pravega by pravega.

the class SegmentAggregator method flushPendingAppends.

/**
 * Flushes all Append Operations that can be flushed up to the maximum allowed flush size.
 *
 * @param timeout  Timeout for the operation.
 * @return A CompletableFuture that, when completed, will contain the result from the flush operation.
 */
private CompletableFuture<FlushResult> flushPendingAppends(Duration timeout) {
    // Gather an InputStream made up of all the operations we can flush.
    FlushArgs flushArgs;
    try {
        flushArgs = getFlushArgs();
    } catch (DataCorruptionException ex) {
        return Futures.failedFuture(ex);
    }
    long traceId = LoggerHelpers.traceEnterWithContext(log, this.traceObjectId, "flushPendingAppends");
    if (flushArgs.getLength() == 0) {
        // Nothing to flush.
        FlushResult result = new FlushResult();
        LoggerHelpers.traceLeave(log, this.traceObjectId, "flushPendingAppends", traceId, result);
        return CompletableFuture.completedFuture(result);
    }
    // Flush them.
    InputStream inputStream = flushArgs.getStream();
    return this.storage.write(this.handle.get(), this.metadata.getStorageLength(), inputStream, flushArgs.getLength(), timeout).thenApplyAsync(v -> {
        FlushResult result = updateStatePostFlush(flushArgs);
        LoggerHelpers.traceLeave(log, this.traceObjectId, "flushPendingAppends", traceId, result);
        return result;
    }, this.executor).exceptionally(ex -> {
        if (Exceptions.unwrap(ex) instanceof BadOffsetException) {
            // We attempted to write at an offset that already contained other data. This can happen for a number of
            // reasons, but we do not have enough information here to determine why. We need to enter reconciliation
            // mode, and hope for the best.
            setState(AggregatorState.ReconciliationNeeded);
        }
        // Rethrow all exceptions.
        throw new CompletionException(ex);
    });
}
Also used : Storage(io.pravega.segmentstore.storage.Storage) Getter(lombok.Getter) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) SneakyThrows(lombok.SneakyThrows) Exceptions(io.pravega.common.Exceptions) RequiredArgsConstructor(lombok.RequiredArgsConstructor) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) UpdateableSegmentMetadata(io.pravega.segmentstore.server.UpdateableSegmentMetadata) SegmentProperties(io.pravega.segmentstore.contracts.SegmentProperties) AbstractTimer(io.pravega.common.AbstractTimer) StreamSegmentSealedException(io.pravega.segmentstore.contracts.StreamSegmentSealedException) SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) SegmentHandle(io.pravega.segmentstore.storage.SegmentHandle) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) Operation(io.pravega.segmentstore.server.logs.operations.Operation) StreamSegmentTruncateOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentTruncateOperation) LoggerHelpers(io.pravega.common.LoggerHelpers) TimeoutTimer(io.pravega.common.TimeoutTimer) Executor(java.util.concurrent.Executor) CompletionException(java.util.concurrent.CompletionException) ThreadSafe(javax.annotation.concurrent.ThreadSafe) GuardedBy(javax.annotation.concurrent.GuardedBy) AtomicLong(java.util.concurrent.atomic.AtomicLong) Slf4j(lombok.extern.slf4j.Slf4j) CachedStreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.CachedStreamSegmentAppendOperation) StorageOperation(io.pravega.segmentstore.server.logs.operations.StorageOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) Preconditions(com.google.common.base.Preconditions) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) ArrayDeque(java.util.ArrayDeque) MergeTransactionOperation(io.pravega.segmentstore.server.logs.operations.MergeTransactionOperation) Futures(io.pravega.common.concurrent.Futures) StreamSegmentSealOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation) InputStream(java.io.InputStream) InputStream(java.io.InputStream) CompletionException(java.util.concurrent.CompletionException) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException)

Aggregations

Exceptions (io.pravega.common.Exceptions)6 Duration (java.time.Duration)6 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 Preconditions (com.google.common.base.Preconditions)4 SegmentProperties (io.pravega.segmentstore.contracts.SegmentProperties)4 DataCorruptionException (io.pravega.segmentstore.server.DataCorruptionException)4 SegmentMetadata (io.pravega.segmentstore.server.SegmentMetadata)4 MergeTransactionOperation (io.pravega.segmentstore.server.logs.operations.MergeTransactionOperation)4 Operation (io.pravega.segmentstore.server.logs.operations.Operation)4 StreamSegmentAppendOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation)4 StreamSegmentSealOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation)4 StreamSegmentTruncateOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentTruncateOperation)4 Collection (java.util.Collection)4 CompletableFuture (java.util.concurrent.CompletableFuture)4 CompletionException (java.util.concurrent.CompletionException)4 LoggerHelpers (io.pravega.common.LoggerHelpers)3 TimeoutTimer (io.pravega.common.TimeoutTimer)3 Futures (io.pravega.common.concurrent.Futures)3 StreamSegmentNotExistsException (io.pravega.segmentstore.contracts.StreamSegmentNotExistsException)3 UpdateableSegmentMetadata (io.pravega.segmentstore.server.UpdateableSegmentMetadata)3