Search in sources :

Example 6 with ObjectClosedException

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

the class DataFrameBuilder method append.

/**
 * Appends a LogItem to the DataFrameBuilder. If any exceptions happened during serialization, whatever contents was
 * written to the DataFrame will be discarded. Note that if a LogItem spans multiple DataFrames, in case of failure,
 * the content serialized to already committed DataFrames will not be discarded. That case will have to be dealt with
 * upon reading DataFrames from the DataFrameLog.
 *
 * Any exceptions that resulted from the Data Frame failing to commit will be routed through the dataFrameCommitFailureCallback
 * callback, as well as being thrown from this exception.
 *
 * @param logItem The LogItem to append.
 * @throws NullPointerException If logItem is null.
 * @throws IllegalArgumentException If attempted to add LogItems out of order (based on Sequence Number).
 * @throws IOException          If the LogItem failed to serialize to the DataLog, or if one of the DataFrames containing
 *                              the LogItem failed to commit to the DataFrameLog.
 * @throws ObjectClosedException If the DataFrameBuilder is closed (or in in a failed state) and cannot be used anymore.
 */
void append(T logItem) throws IOException {
    Exceptions.checkNotClosed(this.closed.get(), this);
    long seqNo = logItem.getSequenceNumber();
    Exceptions.checkArgument(this.lastSerializedSequenceNumber < seqNo, "logItem", "Invalid sequence number. Expected: greater than %d, given: %d.", this.lastSerializedSequenceNumber, seqNo);
    // Remember the last Started SeqNo, in case of failure.
    long previousLastStartedSequenceNumber = this.lastStartedSequenceNumber;
    try {
        // Indicate to the output stream that are about to write a new record.
        this.outputStream.startNewRecord();
        // Completely serialize the entry. Note that this may span more than one Data Frame.
        this.lastStartedSequenceNumber = seqNo;
        this.serializer.serialize(this.outputStream, logItem);
        // Indicate to the output stream that have finished writing the record.
        this.outputStream.endRecord();
        this.lastSerializedSequenceNumber = seqNo;
    } catch (Exception ex) {
        if (this.closed.get()) {
            // to indicate that we are closed by throwing ObjectClosedException.
            throw new ObjectClosedException(this, ex);
        } else if (ex instanceof ObjectClosedException) {
            // TargetLog has closed. We need to close too.
            close();
        } else {
            // Discard any information that we have about this record (pretty much revert back to where startNewEntry()
            // would have begun writing).
            this.outputStream.discardRecord();
            this.lastStartedSequenceNumber = previousLastStartedSequenceNumber;
        }
        throw ex;
    }
}
Also used : ObjectClosedException(io.pravega.common.ObjectClosedException) ObjectClosedException(io.pravega.common.ObjectClosedException) CancellationException(java.util.concurrent.CancellationException) IOException(java.io.IOException)

Example 7 with ObjectClosedException

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

the class OperationProcessorTests method testConcurrentStopAndCommit.

/**
 * Tests a scenario where the OperationProcessor is shut down while a DataFrame is being processed and will eventually
 * complete successfully - however its operation should be cancelled.
 */
@Test
public void testConcurrentStopAndCommit() throws Exception {
    @Cleanup TestContext context = new TestContext();
    // Generate some test data.
    val segmentId = createStreamSegmentsInMetadata(1, context.metadata).stream().findFirst().orElse(-1L);
    List<Operation> operations = Collections.singletonList(new StreamSegmentAppendOperation(segmentId, new byte[1], null));
    CompletableFuture<LogAddress> appendCallback = new CompletableFuture<>();
    // Setup an OperationProcessor with a custom DurableDataLog and start it.
    @Cleanup DurableDataLog dataLog = new ManualAppendOnlyDurableDataLog(() -> appendCallback);
    dataLog.initialize(TIMEOUT);
    @Cleanup OperationProcessor operationProcessor = new OperationProcessor(context.metadata, context.stateUpdater, dataLog, getNoOpCheckpointPolicy(), executorService());
    operationProcessor.startAsync().awaitRunning();
    // Process all generated operations.
    OperationWithCompletion completionFuture = processOperations(operations, operationProcessor).stream().findFirst().orElse(null);
    operationProcessor.stopAsync();
    appendCallback.complete(new TestLogAddress(1));
    // Stop the processor.
    operationProcessor.awaitTerminated();
    // Wait for the operation to complete. The operation should have been cancelled (due to the OperationProcessor
    // shutting down) - no other exception (or successful completion is accepted).
    AssertExtensions.assertThrows("Operation did not fail with the right exception.", () -> completionFuture.completion, ex -> ex instanceof CancellationException || ex instanceof ObjectClosedException);
}
Also used : lombok.val(lombok.val) DurableDataLog(io.pravega.segmentstore.storage.DurableDataLog) TestDurableDataLog(io.pravega.segmentstore.server.TestDurableDataLog) ProbeOperation(io.pravega.segmentstore.server.logs.operations.ProbeOperation) Operation(io.pravega.segmentstore.server.logs.operations.Operation) StorageOperation(io.pravega.segmentstore.server.logs.operations.StorageOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) Cleanup(lombok.Cleanup) LogAddress(io.pravega.segmentstore.storage.LogAddress) CompletableFuture(java.util.concurrent.CompletableFuture) CancellationException(java.util.concurrent.CancellationException) ObjectClosedException(io.pravega.common.ObjectClosedException) Test(org.junit.Test)

Example 8 with ObjectClosedException

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

the class StreamSegmentReadResultTests method testClose.

/**
 * Tests the ability to close the result and cancel any items that were returned.
 */
@Test
public void testClose() {
    AtomicReference<TestReadResultEntry> nextEntry = new AtomicReference<>();
    StreamSegmentReadResult.NextEntrySupplier nes = (offset, length) -> nextEntry.get();
    // We issue a read with length = MAX_RESULT_LENGTH, but we only get to read one item from it.
    StreamSegmentReadResult r = new StreamSegmentReadResult(START_OFFSET, MAX_RESULT_LENGTH, nes, "");
    nextEntry.set(TestReadResultEntry.cache(START_OFFSET, MAX_RESULT_LENGTH));
    ReadResultEntry resultEntry = r.next();
    // Close the result and verify we cannot read from it anymore and that the pending future is now canceled.
    r.close();
    Assert.assertTrue("Already returned result future is not canceled after closing the ReadResult.", resultEntry.getContent().isCancelled());
    Assert.assertFalse("hasNext() did not return false after closing ", r.hasNext());
    AssertExtensions.assertThrows("next() did not throw an appropriate exception when the ReadResult is closed.", r::next, ex -> ex instanceof ObjectClosedException);
}
Also used : ObjectClosedException(io.pravega.common.ObjectClosedException) Rule(org.junit.Rule) ReadResultEntryContents(io.pravega.segmentstore.contracts.ReadResultEntryContents) AssertExtensions(io.pravega.test.common.AssertExtensions) BiFunction(java.util.function.BiFunction) ReadResultEntry(io.pravega.segmentstore.contracts.ReadResultEntry) Timeout(org.junit.rules.Timeout) Cleanup(lombok.Cleanup) Test(org.junit.Test) ReadResultEntryType(io.pravega.segmentstore.contracts.ReadResultEntryType) Assert(org.junit.Assert) AtomicReference(java.util.concurrent.atomic.AtomicReference) ReadResultEntry(io.pravega.segmentstore.contracts.ReadResultEntry) ObjectClosedException(io.pravega.common.ObjectClosedException) AtomicReference(java.util.concurrent.atomic.AtomicReference) Test(org.junit.Test)

Example 9 with ObjectClosedException

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

the class WriteQueueTests method testClose.

/**
 * Tests the close() method.
 */
@Test
public void testClose() {
    val q = new WriteQueue();
    val expectedWrites = new ArrayList<Write>();
    for (int i = 0; i < ITEM_COUNT; i++) {
        val w = new Write(new ByteArraySegment(new byte[i]), new TestWriteLedger(i), CompletableFuture.completedFuture(null));
        q.add(w);
        expectedWrites.add(w);
    }
    val removedWrites = q.close();
    AssertExtensions.assertListEquals("Unexpected writes removed.", expectedWrites, removedWrites, Object::equals);
    val clearStats = q.getStatistics();
    Assert.assertEquals("Unexpected getSize after clear.", 0, clearStats.getSize());
    Assert.assertEquals("Unexpected getAverageFillRate after clear.", 0, clearStats.getAverageItemFillRatio(), 0);
    Assert.assertEquals("Unexpected getExpectedProcessingTimeMillis after clear.", 0, clearStats.getExpectedProcessingTimeMillis());
    AssertExtensions.assertThrows("add() worked after close().", () -> q.add(new Write(new ByteArraySegment(new byte[1]), new TestWriteLedger(0), CompletableFuture.completedFuture(null))), ex -> ex instanceof ObjectClosedException);
    AssertExtensions.assertThrows("getWritesToExecute() worked after close().", () -> q.getWritesToExecute(1), ex -> ex instanceof ObjectClosedException);
    AssertExtensions.assertThrows("removeFinishedWrites() worked after close().", q::removeFinishedWrites, ex -> ex instanceof ObjectClosedException);
}
Also used : lombok.val(lombok.val) ByteArraySegment(io.pravega.common.util.ByteArraySegment) ObjectClosedException(io.pravega.common.ObjectClosedException) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 10 with ObjectClosedException

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

the class OrderedItemProcessorTests method testFailures.

@Test
public void testFailures() {
    final int itemCount = 2 * CAPACITY;
    val processedItems = Collections.synchronizedCollection(new HashSet<Integer>());
    val processFutures = Collections.synchronizedList(new ArrayList<CompletableFuture<Integer>>());
    Function<Integer, CompletableFuture<Integer>> itemProcessor = i -> {
        if (!processedItems.add(i)) {
            Assert.fail("Duplicate item detected: " + i);
        }
        CompletableFuture<Integer> result = new CompletableFuture<>();
        processFutures.add(result);
        return result;
    };
    val resultFutures = new ArrayList<CompletableFuture<Integer>>();
    @Cleanup val p = new TestProcessor(CAPACITY, itemProcessor, executorService());
    // Fill up to capacity, and beyond.
    for (int i = 0; i < itemCount; i++) {
        resultFutures.add(p.process(i));
    }
    // Fail an item.
    val failedIndex = CAPACITY / 2;
    processFutures.get(failedIndex).completeExceptionally(new IntentionalException());
    AssertExtensions.assertThrows("Failed item did not have its result failed as well.", resultFutures.get(failedIndex)::join, ex -> ex instanceof IntentionalException);
    // Verify all queued-up items have been failed, but none of the initial ones (that have already begun processing)
    for (int i = CAPACITY; i < itemCount; i++) {
        AssertExtensions.assertThrows("Queued-up item did not fail when a previous item failed.", resultFutures.get(i)::join, ex -> ex instanceof OrderedItemProcessor.ProcessingException && ex.getCause() instanceof IntentionalException);
    }
    for (int i = 0; i < CAPACITY; i++) {
        if (i != failedIndex) {
            Assert.assertFalse("Already-processing future was completed as well.", resultFutures.get(i).isDone());
        }
    }
    // Verify we can't add anything else ...
    AssertExtensions.assertThrows("failure did not cause OrderedItemProcessor to close.", () -> p.process(Integer.MAX_VALUE), ex -> ex instanceof ObjectClosedException);
}
Also used : lombok.val(lombok.val) ObjectClosedException(io.pravega.common.ObjectClosedException) Setter(lombok.Setter) Getter(lombok.Getter) AssertExtensions(io.pravega.test.common.AssertExtensions) Cleanup(lombok.Cleanup) Random(java.util.Random) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) Timeout(org.junit.rules.Timeout) Executor(java.util.concurrent.Executor) Semaphore(java.util.concurrent.Semaphore) IntentionalException(io.pravega.test.common.IntentionalException) lombok.val(lombok.val) Test(org.junit.Test) TimeUnit(java.util.concurrent.TimeUnit) Rule(org.junit.Rule) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) Assert(org.junit.Assert) Collections(java.util.Collections) Futures(io.pravega.common.concurrent.Futures) ArrayList(java.util.ArrayList) Cleanup(lombok.Cleanup) IntentionalException(io.pravega.test.common.IntentionalException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CompletableFuture(java.util.concurrent.CompletableFuture) ObjectClosedException(io.pravega.common.ObjectClosedException) Test(org.junit.Test)

Aggregations

ObjectClosedException (io.pravega.common.ObjectClosedException)10 Test (org.junit.Test)7 ArrayList (java.util.ArrayList)4 Cleanup (lombok.Cleanup)4 lombok.val (lombok.val)4 ByteArraySegment (io.pravega.common.util.ByteArraySegment)3 DurableDataLog (io.pravega.segmentstore.storage.DurableDataLog)3 AssertExtensions (io.pravega.test.common.AssertExtensions)3 IntentionalException (io.pravega.test.common.IntentionalException)3 Duration (java.time.Duration)3 Collections (java.util.Collections)3 Assert (org.junit.Assert)3 Rule (org.junit.Rule)3 Timeout (org.junit.rules.Timeout)3 Exceptions (io.pravega.common.Exceptions)2 Futures (io.pravega.common.concurrent.Futures)2 TestDurableDataLog (io.pravega.segmentstore.server.TestDurableDataLog)2 Operation (io.pravega.segmentstore.server.logs.operations.Operation)2 ProbeOperation (io.pravega.segmentstore.server.logs.operations.ProbeOperation)2 StreamSegmentAppendOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation)2