Search in sources :

Example 6 with BadOffsetException

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

the class IdempotentStorageTestBase method testParallelWriteTwoHosts.

// endregion
// region synchronization unit tests
/**
 * This test case simulates two hosts writing at the same offset at the same time.
 */
@Test(timeout = 30000)
public void testParallelWriteTwoHosts() {
    String segmentName = "foo_write";
    int appendCount = 5;
    try (Storage s1 = createStorage();
        Storage s2 = createStorage()) {
        s1.initialize(DEFAULT_EPOCH);
        s1.create(segmentName, TIMEOUT).join();
        SegmentHandle writeHandle1 = s1.openWrite(segmentName).join();
        SegmentHandle writeHandle2 = s2.openWrite(segmentName).join();
        long offset = 0;
        byte[] writeData = String.format("Segment_%s_Append", segmentName).getBytes();
        for (int j = 0; j < appendCount; j++) {
            ByteArrayInputStream dataStream1 = new ByteArrayInputStream(writeData);
            ByteArrayInputStream dataStream2 = new ByteArrayInputStream(writeData);
            CompletableFuture f1 = s1.write(writeHandle1, offset, dataStream1, writeData.length, TIMEOUT);
            CompletableFuture f2 = s2.write(writeHandle2, offset, dataStream2, writeData.length, TIMEOUT);
            assertMayThrow("Write expected to complete OR throw BadOffsetException." + "threw an unexpected exception.", () -> CompletableFuture.allOf(f1, f2), ex -> ex instanceof BadOffsetException);
            // Make sure at least one operation is success.
            Assert.assertTrue("At least one of the two parallel writes should succeed.", !f1.isCompletedExceptionally() || !f2.isCompletedExceptionally());
            offset += writeData.length;
        }
        Assert.assertTrue("Writes at the same offset are expected to be idempotent.", s1.getStreamSegmentInfo(segmentName, TIMEOUT).join().getLength() == offset);
        offset = 0;
        byte[] readBuffer = new byte[writeData.length];
        for (int j = 0; j < appendCount; j++) {
            int bytesRead = s1.read(writeHandle1, j * readBuffer.length, readBuffer, 0, readBuffer.length, TIMEOUT).join();
            Assert.assertEquals(String.format("Unexpected number of bytes read from offset %d.", offset), readBuffer.length, bytesRead);
            AssertExtensions.assertArrayEquals(String.format("Unexpected read result from offset %d.", offset), readBuffer, 0, readBuffer, 0, bytesRead);
        }
        s1.delete(writeHandle1, TIMEOUT).join();
    }
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) Storage(io.pravega.segmentstore.storage.Storage) ByteArrayInputStream(java.io.ByteArrayInputStream) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) SegmentHandle(io.pravega.segmentstore.storage.SegmentHandle) Test(org.junit.Test)

Example 7 with BadOffsetException

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

the class IdempotentStorageTestBase method testWrite.

/**
 * Tests the write() method.
 *
 * @throws Exception if an unexpected error occurred.
 */
@Override
@Test(timeout = 30000)
public void testWrite() throws Exception {
    String segmentName = "foo_write";
    int appendCount = 100;
    try (Storage s = createStorage()) {
        s.initialize(DEFAULT_EPOCH);
        s.create(segmentName, TIMEOUT).join();
        // Invalid handle.
        val readOnlyHandle = s.openRead(segmentName).join();
        assertThrows("write() did not throw for read-only handle.", () -> s.write(readOnlyHandle, 0, new ByteArrayInputStream("h".getBytes()), 1, TIMEOUT), ex -> ex instanceof IllegalArgumentException);
        assertThrows("write() did not throw for handle pointing to inexistent segment.", () -> s.write(createInexistentSegmentHandle(s, false), 0, new ByteArrayInputStream("h".getBytes()), 1, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
        val writeHandle = s.openWrite(segmentName).join();
        long offset = 0;
        for (int j = 0; j < appendCount; j++) {
            byte[] writeData = String.format("Segment_%s_Append_%d", segmentName, j).getBytes();
            ByteArrayInputStream dataStream = new ByteArrayInputStream(writeData);
            s.write(writeHandle, offset, dataStream, writeData.length, TIMEOUT).join();
            offset += writeData.length;
        }
        // Check bad offset.
        final long finalOffset = offset;
        assertThrows("write() did not throw bad offset write (larger).", () -> s.write(writeHandle, finalOffset + 1, new ByteArrayInputStream("h".getBytes()), 1, TIMEOUT), ex -> ex instanceof BadOffsetException);
        // Check post-delete write.
        s.delete(writeHandle, TIMEOUT).join();
        assertThrows("write() did not throw for a deleted StreamSegment.", () -> s.write(writeHandle, 0, new ByteArrayInputStream(new byte[1]), 1, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
    }
}
Also used : lombok.val(lombok.val) Storage(io.pravega.segmentstore.storage.Storage) ByteArrayInputStream(java.io.ByteArrayInputStream) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) Test(org.junit.Test)

Example 8 with BadOffsetException

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

the class FileSystemStorageTest method testWrite.

// region Write tests with metrics checks
/**
 * Tests the write() method.
 *
 * @throws Exception if an unexpected error occurred.
 */
@Override
@Test(timeout = 30000)
public void testWrite() throws Exception {
    String segmentName = "foo_write";
    int appendCount = 100;
    try (Storage s = createStorage()) {
        s.initialize(DEFAULT_EPOCH);
        s.create(segmentName, TIMEOUT).join();
        long expectedMetricsSize = FileSystemMetrics.WRITE_BYTES.get();
        long expectedMetricsSuccesses = FileSystemMetrics.WRITE_LATENCY.toOpStatsData().getNumSuccessfulEvents();
        // Invalid handle.
        val readOnlyHandle = s.openRead(segmentName).join();
        assertThrows("write() did not throw for read-only handle.", () -> s.write(readOnlyHandle, 0, new ByteArrayInputStream("h".getBytes()), 1, TIMEOUT), ex -> ex instanceof IllegalArgumentException);
        assertThrows("write() did not throw for handle pointing to inexistent segment.", () -> s.write(createInexistentSegmentHandle(s, false), 0, new ByteArrayInputStream("h".getBytes()), 1, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
        Assert.assertEquals("WRITE_BYTES should not change in case of unsuccessful writes", expectedMetricsSize, FileSystemMetrics.WRITE_BYTES.get());
        Assert.assertEquals("WRITE_LATENCY should not increase the count of successful events in case of unsuccessful writes", expectedMetricsSuccesses, FileSystemMetrics.WRITE_LATENCY.toOpStatsData().getNumSuccessfulEvents());
        val writeHandle = s.openWrite(segmentName).join();
        long offset = 0;
        for (int j = 0; j < appendCount; j++) {
            byte[] writeData = String.format("Segment_%s_Append_%d", segmentName, j).getBytes();
            ByteArrayInputStream dataStream = new ByteArrayInputStream(writeData);
            s.write(writeHandle, offset, dataStream, writeData.length, TIMEOUT).join();
            expectedMetricsSize += writeData.length;
            expectedMetricsSuccesses += 1;
            Assert.assertEquals("WRITE_LATENCY should increase the count of successful events in case of successful writes", expectedMetricsSuccesses, FileSystemMetrics.WRITE_LATENCY.toOpStatsData().getNumSuccessfulEvents());
            Assert.assertEquals("WRITE_BYTES should increase by the size of successful writes", expectedMetricsSize, FileSystemMetrics.WRITE_BYTES.get());
            offset += writeData.length;
        }
        // Check bad offset.
        final long finalOffset = offset;
        assertThrows("write() did not throw bad offset write (larger).", () -> s.write(writeHandle, finalOffset + 1, new ByteArrayInputStream("h".getBytes()), 1, TIMEOUT), ex -> ex instanceof BadOffsetException);
        Assert.assertEquals("WRITE_BYTES should not change in case of unsuccessful writes", expectedMetricsSize, FileSystemMetrics.WRITE_BYTES.get());
        Assert.assertEquals("WRITE_LATENCY should not increase the count of successful events in case of unsuccessful writes", expectedMetricsSuccesses, FileSystemMetrics.WRITE_LATENCY.toOpStatsData().getNumSuccessfulEvents());
        // Check post-delete write.
        s.delete(writeHandle, TIMEOUT).join();
        assertThrows("write() did not throw for a deleted StreamSegment.", () -> s.write(writeHandle, 0, new ByteArrayInputStream(new byte[1]), 1, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
        Assert.assertEquals("WRITE_BYTES should not change in case of unsuccessful writes", expectedMetricsSize, FileSystemMetrics.WRITE_BYTES.get());
        Assert.assertEquals("WRITE_LATENCY should not increase the count of successful events in case of unsuccessful writes", expectedMetricsSuccesses, FileSystemMetrics.WRITE_LATENCY.toOpStatsData().getNumSuccessfulEvents());
    }
}
Also used : lombok.val(lombok.val) Storage(io.pravega.segmentstore.storage.Storage) ByteArrayInputStream(java.io.ByteArrayInputStream) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) Test(org.junit.Test)

Example 9 with BadOffsetException

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

the class ConcatOperationTests method testInvalidInput.

/**
 * Tests various combinations of bad input to the Concat command.
 */
@Test
public void testInvalidInput() throws Exception {
    @Cleanup val fs = new MockFileSystem();
    val context = newContext(1, fs);
    val targetHandle = createNonEmptySegment(TARGET_SEGMENT, context, null);
    val sourceHandle = createNonEmptySegment(SOURCE_SEGMENT, context, null);
    // Same source and target.
    AssertExtensions.assertThrows("ConcatOperation worked with same source and target.", () -> new ConcatOperation(targetHandle, WRITE_LENGTH, TARGET_SEGMENT, context).run(), ex -> ex instanceof IllegalArgumentException);
    // Verify source is not sealed.
    AssertExtensions.assertThrows("ConcatOperation worked on non-sealed source segment.", new ConcatOperation(targetHandle, WRITE_LENGTH, SOURCE_SEGMENT, context)::run, ex -> ex instanceof IllegalStateException);
    // Seal it.
    new SealOperation(sourceHandle, context).run();
    // Verify target offset.
    AssertExtensions.assertThrows("ConcatOperation worked with bad offset.", new ConcatOperation(targetHandle, WRITE_LENGTH - 1, SOURCE_SEGMENT, context)::run, ex -> ex instanceof BadOffsetException);
    // Verify target is sealed.
    new SealOperation(targetHandle, context).run();
    AssertExtensions.assertThrows("ConcatOperation worked with sealed target.", new ConcatOperation(targetHandle, WRITE_LENGTH, SOURCE_SEGMENT, context)::run, ex -> ex instanceof AclException);
}
Also used : lombok.val(lombok.val) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) AclException(org.apache.hadoop.hdfs.protocol.AclException) Cleanup(lombok.Cleanup) Test(org.junit.Test)

Example 10 with BadOffsetException

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

the class RollingStorage method serializeHandle.

private void serializeHandle(RollingSegmentHandle handle) throws StreamSegmentException {
    ByteArraySegment handleData = HandleSerializer.serialize(handle);
    try {
        this.baseStorage.write(handle.getHeaderHandle(), 0, handleData.getReader(), handleData.getLength());
        handle.setHeaderLength(handleData.getLength());
        log.debug("Header for '{}' fully serialized to '{}'.", handle.getSegmentName(), handle.getHeaderHandle().getSegmentName());
    } catch (BadOffsetException ex) {
        // If we get BadOffsetException when writing the Handle, it means it was modified externally.
        throw new StorageNotPrimaryException(handle.getSegmentName(), ex);
    }
}
Also used : ByteArraySegment(io.pravega.common.util.ByteArraySegment) BadOffsetException(io.pravega.segmentstore.contracts.BadOffsetException) StorageNotPrimaryException(io.pravega.segmentstore.storage.StorageNotPrimaryException)

Aggregations

BadOffsetException (io.pravega.segmentstore.contracts.BadOffsetException)21 Test (org.junit.Test)12 StreamSegmentNotExistsException (io.pravega.segmentstore.contracts.StreamSegmentNotExistsException)8 ByteArrayInputStream (java.io.ByteArrayInputStream)7 lombok.val (lombok.val)6 StreamSegmentSealedException (io.pravega.segmentstore.contracts.StreamSegmentSealedException)5 StorageOperation (io.pravega.segmentstore.server.logs.operations.StorageOperation)5 Storage (io.pravega.segmentstore.storage.Storage)5 DataCorruptionException (io.pravega.segmentstore.server.DataCorruptionException)4 StreamSegmentAppendOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation)4 StreamSegmentTruncateOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentTruncateOperation)4 Cleanup (lombok.Cleanup)4 SegmentProperties (io.pravega.segmentstore.contracts.SegmentProperties)3 MergeTransactionOperation (io.pravega.segmentstore.server.logs.operations.MergeTransactionOperation)3 Operation (io.pravega.segmentstore.server.logs.operations.Operation)3 StreamSegmentSealOperation (io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation)3 SegmentHandle (io.pravega.segmentstore.storage.SegmentHandle)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3 InputStream (java.io.InputStream)3 CompletableFuture (java.util.concurrent.CompletableFuture)3