Search in sources :

Example 21 with ReadResultEntry

use of io.pravega.segmentstore.contracts.ReadResultEntry in project pravega by pravega.

the class ContainerReadIndexTests method testStorageFailedReads.

/**
 * Tests the ability to handle Storage read failures.
 */
@Test
public void testStorageFailedReads() {
    // Create all segments (Storage and Metadata).
    @Cleanup TestContext context = new TestContext();
    ArrayList<Long> segmentIds = createSegments(context);
    createSegmentsInStorage(context);
    // Read beyond Storage actual offset (metadata is corrupt)
    long testSegmentId = segmentIds.get(0);
    UpdateableSegmentMetadata sm = context.metadata.getStreamSegmentMetadata(testSegmentId);
    sm.setStorageLength(1024 * 1024);
    sm.setLength(1024 * 1024);
    AssertExtensions.assertThrows("Unexpected exception when attempting to read beyond the Segment length in Storage.", () -> {
        @Cleanup ReadResult readResult = context.readIndex.read(testSegmentId, 0, 100, TIMEOUT);
        Assert.assertTrue("Unexpected value from hasNext() when there should be at least one ReadResultEntry.", readResult.hasNext());
        ReadResultEntry entry = readResult.next();
        Assert.assertEquals("Unexpected ReadResultEntryType.", ReadResultEntryType.Storage, entry.getType());
        entry.requestContent(TIMEOUT);
        entry.getContent().get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
    }, ex -> ex instanceof ArrayIndexOutOfBoundsException);
    // Segment not exists (exists in metadata, but not in Storage)
    val handle = context.storage.openWrite(sm.getName()).join();
    context.storage.delete(handle, TIMEOUT).join();
    AssertExtensions.assertThrows("Unexpected exception when attempting to from a segment that exists in Metadata, but not in Storage.", () -> {
        @Cleanup ReadResult readResult = context.readIndex.read(testSegmentId, 0, 100, TIMEOUT);
        Assert.assertTrue("Unexpected value from hasNext() when there should be at least one ReadResultEntry.", readResult.hasNext());
        ReadResultEntry entry = readResult.next();
        Assert.assertEquals("Unexpected ReadResultEntryType.", ReadResultEntryType.Storage, entry.getType());
        entry.requestContent(TIMEOUT);
        entry.getContent().get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
    }, ex -> ex instanceof StreamSegmentNotExistsException);
}
Also used : lombok.val(lombok.val) UpdateableSegmentMetadata(io.pravega.segmentstore.server.UpdateableSegmentMetadata) ReadResultEntry(io.pravega.segmentstore.contracts.ReadResultEntry) AtomicLong(java.util.concurrent.atomic.AtomicLong) ReadResult(io.pravega.segmentstore.contracts.ReadResult) Cleanup(lombok.Cleanup) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) Test(org.junit.Test)

Example 22 with ReadResultEntry

use of io.pravega.segmentstore.contracts.ReadResultEntry in project pravega by pravega.

the class StreamSegmentReadResultTests method testNextWaitOnPrevious.

/**
 * Tests the ability to only return a next item if the previous returned item hasn't been consumed yet.
 */
@Test
public void testNextWaitOnPrevious() throws Exception {
    AtomicReference<TestReadResultEntry> nextEntry = new AtomicReference<>();
    StreamSegmentReadResult.NextEntrySupplier nes = (offset, length) -> nextEntry.get();
    // We issue a read, get one item, do not consume it, and then read a second time.
    @Cleanup StreamSegmentReadResult r = new StreamSegmentReadResult(START_OFFSET, MAX_RESULT_LENGTH, nes, "");
    nextEntry.set(TestReadResultEntry.cache(START_OFFSET, MAX_RESULT_LENGTH));
    TestReadResultEntry firstEntry = (TestReadResultEntry) r.next();
    // Immediately request a second item, without properly consuming the first item.
    nextEntry.set(TestReadResultEntry.cache(START_OFFSET + READ_ITEM_LENGTH, MAX_RESULT_LENGTH));
    AssertExtensions.assertThrows("Second read was allowed even though the first read did not complete.", r::next, ex -> ex instanceof IllegalStateException);
    firstEntry.complete(new ReadResultEntryContents(null, READ_ITEM_LENGTH));
    ReadResultEntry secondEntry = r.next();
    ReadResultEntryBase x;
    Assert.assertEquals("Unexpected result from nextEntry.", nextEntry.get(), secondEntry);
}
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) ReadResultEntryContents(io.pravega.segmentstore.contracts.ReadResultEntryContents) ReadResultEntry(io.pravega.segmentstore.contracts.ReadResultEntry) AtomicReference(java.util.concurrent.atomic.AtomicReference) Cleanup(lombok.Cleanup) Test(org.junit.Test)

Example 23 with ReadResultEntry

use of io.pravega.segmentstore.contracts.ReadResultEntry in project pravega by pravega.

the class StreamSegmentReadResultTests method testNextFullyConsumed.

/**
 * Tests the next() method which ends when the result is fully consumed (via offsets).
 */
@Test
public void testNextFullyConsumed() {
    AtomicReference<TestReadResultEntry> nextEntry = new AtomicReference<>();
    StreamSegmentReadResult.NextEntrySupplier nes = (offset, length) -> nextEntry.get();
    // We issue a read with length = MAX_RESULT_LENGTH, and return items, 1 byte at a time.
    @Cleanup StreamSegmentReadResult r = new StreamSegmentReadResult(START_OFFSET, MAX_RESULT_LENGTH, nes, "");
    int expectedConsumedLength = 0;
    for (int i = 0; i < MAX_RESULT_LENGTH; i += READ_ITEM_LENGTH) {
        // Setup an item to be returned.
        final long expectedStartOffset = START_OFFSET + i;
        final int expectedReadLength = MAX_RESULT_LENGTH - i;
        nextEntry.set(TestReadResultEntry.cache(expectedStartOffset, expectedReadLength));
        // Get the result and verify we get exactly what we supplied.
        Assert.assertTrue("hasNext() returned false even though we haven't consumed the entire result.", r.hasNext());
        ReadResultEntry resultEntry = r.next();
        Assert.assertEquals("Unexpected result from nextEntry.", nextEntry.get(), resultEntry);
        // Verify the StreamSegmentReadResult does not update itself after returning a result.
        Assert.assertEquals("getStreamSegmentStartOffset changed while iterating.", START_OFFSET, r.getStreamSegmentStartOffset());
        Assert.assertEquals("getMaxResultLength changed while iterating.", MAX_RESULT_LENGTH, r.getMaxResultLength());
        Assert.assertEquals("Unexpected value from getConsumedLength after returning a value but before completing result future.", expectedConsumedLength, r.getConsumedLength());
        // Verify the StreamSegmentReadResult updates itself after the last returned result's future is completed.
        nextEntry.get().complete(new ReadResultEntryContents(null, READ_ITEM_LENGTH));
        expectedConsumedLength += READ_ITEM_LENGTH;
        Assert.assertEquals("Unexpected value from getConsumedLength after returning a value and completing result future.", expectedConsumedLength, r.getConsumedLength());
    }
    // Verify we have reached the end.
    Assert.assertEquals("Unexpected state of the StreamSegmentReadResult when consuming the entire result.", r.getMaxResultLength(), r.getConsumedLength());
    Assert.assertFalse("hasNext() did not return false when the entire result is consumed.", r.hasNext());
    ReadResultEntry resultEntry = r.next();
    Assert.assertNull("next() did not return null when it was done.", resultEntry);
}
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) ReadResultEntryContents(io.pravega.segmentstore.contracts.ReadResultEntryContents) ReadResultEntry(io.pravega.segmentstore.contracts.ReadResultEntry) AtomicReference(java.util.concurrent.atomic.AtomicReference) Cleanup(lombok.Cleanup) Test(org.junit.Test)

Example 24 with ReadResultEntry

use of io.pravega.segmentstore.contracts.ReadResultEntry 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 25 with ReadResultEntry

use of io.pravega.segmentstore.contracts.ReadResultEntry in project pravega by pravega.

the class PravegaRequestProcessor method handleReadResult.

/**
 * Handles a readResult.
 * If there are cached entries that can be returned without blocking only these are returned.
 * Otherwise the call will request the data and setup a callback to return the data when it is available.
 * If no data is available but it was detected that the Segment had been truncated beyond the current offset,
 * an appropriate message is sent back over the connection.
 */
private void handleReadResult(ReadSegment request, ReadResult result) {
    String segment = request.getSegment();
    ArrayList<ReadResultEntryContents> cachedEntries = new ArrayList<>();
    ReadResultEntry nonCachedEntry = collectCachedEntries(request.getOffset(), result, cachedEntries);
    boolean truncated = nonCachedEntry != null && nonCachedEntry.getType() == Truncated;
    boolean endOfSegment = nonCachedEntry != null && nonCachedEntry.getType() == EndOfStreamSegment;
    boolean atTail = nonCachedEntry != null && nonCachedEntry.getType() == Future;
    if (!cachedEntries.isEmpty() || endOfSegment) {
        // We managed to collect some data. Send it.
        ByteBuffer data = copyData(cachedEntries);
        SegmentRead reply = new SegmentRead(segment, request.getOffset(), atTail, endOfSegment, data);
        connection.send(reply);
    } else if (truncated) {
        // We didn't collect any data, instead we determined that the current read offset was truncated.
        // Determine the current Start Offset and send that back.
        segmentStore.getStreamSegmentInfo(segment, false, TIMEOUT).thenAccept(info -> connection.send(new SegmentIsTruncated(nonCachedEntry.getStreamSegmentOffset(), segment, info.getStartOffset()))).exceptionally(e -> handleException(nonCachedEntry.getStreamSegmentOffset(), segment, "Read segment", e));
    } else {
        Preconditions.checkState(nonCachedEntry != null, "No ReadResultEntries returned from read!?");
        nonCachedEntry.requestContent(TIMEOUT);
        nonCachedEntry.getContent().thenAccept(contents -> {
            ByteBuffer data = copyData(Collections.singletonList(contents));
            connection.send(new SegmentRead(segment, nonCachedEntry.getStreamSegmentOffset(), false, endOfSegment, data));
        }).exceptionally(e -> {
            if (Exceptions.unwrap(e) instanceof StreamSegmentTruncatedException) {
                // The Segment may have been truncated in Storage after we got this entry but before we managed
                // to make a read. In that case, send the appropriate error back.
                connection.send(new SegmentIsTruncated(nonCachedEntry.getStreamSegmentOffset(), segment, nonCachedEntry.getStreamSegmentOffset()));
            } else {
                handleException(nonCachedEntry.getStreamSegmentOffset(), segment, "Read segment", e);
            }
            return null;
        }).exceptionally(e -> handleException(nonCachedEntry.getStreamSegmentOffset(), segment, "Read segment", e));
    }
}
Also used : SCALE_POLICY_RATE(io.pravega.segmentstore.contracts.Attributes.SCALE_POLICY_RATE) Arrays(java.util.Arrays) READ(io.pravega.auth.AuthHandler.Permissions.READ) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) SEGMENT_CREATE_LATENCY(io.pravega.shared.MetricsNames.SEGMENT_CREATE_LATENCY) AuthHandler(io.pravega.auth.AuthHandler) SegmentIsTruncated(io.pravega.shared.protocol.netty.WireCommands.SegmentIsTruncated) CREATION_TIME(io.pravega.segmentstore.contracts.Attributes.CREATION_TIME) MetricsNames.nameFromSegment(io.pravega.shared.MetricsNames.nameFromSegment) GetStreamSegmentInfo(io.pravega.shared.protocol.netty.WireCommands.GetStreamSegmentInfo) ReadResultEntryContents(io.pravega.segmentstore.contracts.ReadResultEntryContents) Duration(java.time.Duration) Map(java.util.Map) SegmentCreated(io.pravega.shared.protocol.netty.WireCommands.SegmentCreated) StreamSegmentStore(io.pravega.segmentstore.contracts.StreamSegmentStore) Attributes(io.pravega.segmentstore.contracts.Attributes) CancellationException(java.util.concurrent.CancellationException) ContainerNotFoundException(io.pravega.segmentstore.contracts.ContainerNotFoundException) Slf4j(lombok.extern.slf4j.Slf4j) CreateSegment(io.pravega.shared.protocol.netty.WireCommands.CreateSegment) SealSegment(io.pravega.shared.protocol.netty.WireCommands.SealSegment) SegmentSealed(io.pravega.shared.protocol.netty.WireCommands.SegmentSealed) EndOfStreamSegment(io.pravega.segmentstore.contracts.ReadResultEntryType.EndOfStreamSegment) SegmentAttribute(io.pravega.shared.protocol.netty.WireCommands.SegmentAttribute) SEGMENT_READ_LATENCY(io.pravega.shared.MetricsNames.SEGMENT_READ_LATENCY) Exceptions(io.pravega.common.Exceptions) BadAttributeUpdateException(io.pravega.segmentstore.contracts.BadAttributeUpdateException) GetSegmentAttribute(io.pravega.shared.protocol.netty.WireCommands.GetSegmentAttribute) ArrayList(java.util.ArrayList) READ_UPDATE(io.pravega.auth.AuthHandler.Permissions.READ_UPDATE) SegmentRead(io.pravega.shared.protocol.netty.WireCommands.SegmentRead) AccessLevel(lombok.AccessLevel) Future(io.pravega.segmentstore.contracts.ReadResultEntryType.Future) FailingRequestProcessor(io.pravega.shared.protocol.netty.FailingRequestProcessor) StreamHelpers(io.pravega.common.io.StreamHelpers) StreamSegmentTruncatedException(io.pravega.segmentstore.contracts.StreamSegmentTruncatedException) StatsLogger(io.pravega.shared.metrics.StatsLogger) OpStatsLogger(io.pravega.shared.metrics.OpStatsLogger) lombok.val(lombok.val) SEGMENT_WRITE_EVENTS(io.pravega.shared.MetricsNames.SEGMENT_WRITE_EVENTS) IOException(java.io.IOException) WireCommands(io.pravega.shared.protocol.netty.WireCommands) WrongHost(io.pravega.shared.protocol.netty.WireCommands.WrongHost) SegmentDeleted(io.pravega.shared.protocol.netty.WireCommands.SegmentDeleted) CreateTransaction(io.pravega.shared.protocol.netty.WireCommands.CreateTransaction) Truncated(io.pravega.segmentstore.contracts.ReadResultEntryType.Truncated) SegmentTruncated(io.pravega.shared.protocol.netty.WireCommands.SegmentTruncated) RequestProcessor(io.pravega.shared.protocol.netty.RequestProcessor) OperationUnsupported(io.pravega.shared.protocol.netty.WireCommands.OperationUnsupported) Preconditions(com.google.common.base.Preconditions) TransactionInfo(io.pravega.shared.protocol.netty.WireCommands.TransactionInfo) AbortTransaction(io.pravega.shared.protocol.netty.WireCommands.AbortTransaction) AuthenticationException(io.pravega.common.auth.AuthenticationException) Cache(io.pravega.segmentstore.contracts.ReadResultEntryType.Cache) SneakyThrows(lombok.SneakyThrows) ByteBuffer(java.nio.ByteBuffer) AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) StreamSegmentSealedException(io.pravega.segmentstore.contracts.StreamSegmentSealedException) UpdateSegmentAttribute(io.pravega.shared.protocol.netty.WireCommands.UpdateSegmentAttribute) UpdateSegmentPolicy(io.pravega.shared.protocol.netty.WireCommands.UpdateSegmentPolicy) SegmentStatsRecorder(io.pravega.segmentstore.server.host.stat.SegmentStatsRecorder) CommitTransaction(io.pravega.shared.protocol.netty.WireCommands.CommitTransaction) Collection(java.util.Collection) UUID(java.util.UUID) Math.min(java.lang.Math.min) StreamSegmentNameUtils(io.pravega.shared.segment.StreamSegmentNameUtils) MetricsProvider(io.pravega.shared.metrics.MetricsProvider) List(java.util.List) StreamSegmentExistsException(io.pravega.segmentstore.contracts.StreamSegmentExistsException) PassingTokenVerifier(io.pravega.segmentstore.server.host.delegationtoken.PassingTokenVerifier) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) DelegationTokenVerifier(io.pravega.segmentstore.server.host.delegationtoken.DelegationTokenVerifier) Math.max(java.lang.Math.max) SegmentIsSealed(io.pravega.shared.protocol.netty.WireCommands.SegmentIsSealed) ReadResult(io.pravega.segmentstore.contracts.ReadResult) TransactionAborted(io.pravega.shared.protocol.netty.WireCommands.TransactionAborted) DeleteSegment(io.pravega.shared.protocol.netty.WireCommands.DeleteSegment) SegmentPolicyUpdated(io.pravega.shared.protocol.netty.WireCommands.SegmentPolicyUpdated) Getter(lombok.Getter) NoSuchSegment(io.pravega.shared.protocol.netty.WireCommands.NoSuchSegment) CompletableFuture(java.util.concurrent.CompletableFuture) GetTransactionInfo(io.pravega.shared.protocol.netty.WireCommands.GetTransactionInfo) DynamicLogger(io.pravega.shared.metrics.DynamicLogger) SEGMENT_WRITE_BYTES(io.pravega.shared.MetricsNames.SEGMENT_WRITE_BYTES) ReadResultEntry(io.pravega.segmentstore.contracts.ReadResultEntry) SEGMENT_READ_BYTES(io.pravega.shared.MetricsNames.SEGMENT_READ_BYTES) SCALE_POLICY_TYPE(io.pravega.segmentstore.contracts.Attributes.SCALE_POLICY_TYPE) TransactionCommitted(io.pravega.shared.protocol.netty.WireCommands.TransactionCommitted) TYPE_PLUS_LENGTH_SIZE(io.pravega.shared.protocol.netty.WireCommands.TYPE_PLUS_LENGTH_SIZE) StreamSegmentInfo(io.pravega.shared.protocol.netty.WireCommands.StreamSegmentInfo) TransactionCreated(io.pravega.shared.protocol.netty.WireCommands.TransactionCreated) TruncateSegment(io.pravega.shared.protocol.netty.WireCommands.TruncateSegment) ReadSegment(io.pravega.shared.protocol.netty.WireCommands.ReadSegment) SegmentAlreadyExists(io.pravega.shared.protocol.netty.WireCommands.SegmentAlreadyExists) LoggerHelpers(io.pravega.common.LoggerHelpers) StreamSegmentMergedException(io.pravega.segmentstore.contracts.StreamSegmentMergedException) Timer(io.pravega.common.Timer) SegmentAttributeUpdated(io.pravega.shared.protocol.netty.WireCommands.SegmentAttributeUpdated) VisibleForTesting(com.google.common.annotations.VisibleForTesting) AttributeUpdateType(io.pravega.segmentstore.contracts.AttributeUpdateType) Collections(java.util.Collections) ReadResultEntryContents(io.pravega.segmentstore.contracts.ReadResultEntryContents) SegmentRead(io.pravega.shared.protocol.netty.WireCommands.SegmentRead) SegmentIsTruncated(io.pravega.shared.protocol.netty.WireCommands.SegmentIsTruncated) ReadResultEntry(io.pravega.segmentstore.contracts.ReadResultEntry) ArrayList(java.util.ArrayList) StreamSegmentTruncatedException(io.pravega.segmentstore.contracts.StreamSegmentTruncatedException) ByteBuffer(java.nio.ByteBuffer)

Aggregations

ReadResultEntry (io.pravega.segmentstore.contracts.ReadResultEntry)25 ReadResultEntryContents (io.pravega.segmentstore.contracts.ReadResultEntryContents)20 ReadResult (io.pravega.segmentstore.contracts.ReadResult)19 Cleanup (lombok.Cleanup)17 Test (org.junit.Test)17 lombok.val (lombok.val)11 ReadResultEntryType (io.pravega.segmentstore.contracts.ReadResultEntryType)8 ArrayList (java.util.ArrayList)8 ByteArrayOutputStream (java.io.ByteArrayOutputStream)7 StreamSegmentStore (io.pravega.segmentstore.contracts.StreamSegmentStore)6 UpdateableSegmentMetadata (io.pravega.segmentstore.server.UpdateableSegmentMetadata)6 AssertExtensions (io.pravega.test.common.AssertExtensions)6 CompletableFuture (java.util.concurrent.CompletableFuture)6 Assert (org.junit.Assert)6 Rule (org.junit.Rule)6 Timeout (org.junit.rules.Timeout)6 StreamSegmentSealedException (io.pravega.segmentstore.contracts.StreamSegmentSealedException)5 StreamSegmentTruncatedException (io.pravega.segmentstore.contracts.StreamSegmentTruncatedException)5 UUID (java.util.UUID)5 StreamSegmentNotExistsException (io.pravega.segmentstore.contracts.StreamSegmentNotExistsException)4