Search in sources :

Example 6 with StorageNotPrimaryException

use of io.pravega.segmentstore.storage.StorageNotPrimaryException in project pravega by pravega.

the class UnsealOperationTests method testFenceOut.

/**
 * Tests the ability to detect fence-outs.
 */
@Test
public void testFenceOut() throws Exception {
    @Cleanup val fs = new MockFileSystem();
    val context1 = newContext(1, fs);
    // Create, write and seal a file. Then open-write it a few times, each time with a higher epoch.
    new CreateOperation(SEGMENT_NAME, context1).call();
    val handle = new OpenWriteOperation(SEGMENT_NAME, context1).call();
    new WriteOperation(handle, 0, new ByteArrayInputStream(new byte[1]), 1, context1).run();
    val context2 = newContext(2, fs);
    val handle2 = new OpenWriteOperation(SEGMENT_NAME, context2).call();
    new WriteOperation(handle2, 1, new ByteArrayInputStream(new byte[1]), 1, context2).run();
    val context3 = newContext(3, fs);
    val handle3 = new OpenWriteOperation(SEGMENT_NAME, context3).call();
    new WriteOperation(handle3, 2, new ByteArrayInputStream(new byte[1]), 1, context3).run();
    new SealOperation(handle3, context3).run();
    val context4 = newContext(4, fs);
    new OpenWriteOperation(SEGMENT_NAME, context4).call();
    // Verify Unseal fails due to fence-out while using a lower epoch.
    AssertExtensions.assertThrows("Unseal did not fail when fenced out.", new UnsealOperation(handle2, context2)::run, ex -> ex instanceof StorageNotPrimaryException);
}
Also used : lombok.val(lombok.val) ByteArrayInputStream(java.io.ByteArrayInputStream) Cleanup(lombok.Cleanup) StorageNotPrimaryException(io.pravega.segmentstore.storage.StorageNotPrimaryException) Test(org.junit.Test)

Example 7 with StorageNotPrimaryException

use of io.pravega.segmentstore.storage.StorageNotPrimaryException 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)

Example 8 with StorageNotPrimaryException

use of io.pravega.segmentstore.storage.StorageNotPrimaryException in project pravega by pravega.

the class OpenWriteOperation method fenceOut.

private HDFSSegmentHandle fenceOut(String segmentName, long offset) throws IOException, StorageNotPrimaryException {
    // Create a new, empty file, and verify nobody else beat us to it.
    val newFile = new FileDescriptor(getFilePath(segmentName, offset, this.context.epoch), offset, 0, this.context.epoch, false);
    atomicCreate(newFile.getPath());
    List<FileDescriptor> allFiles;
    try {
        allFiles = checkForFenceOut(segmentName, -1, newFile);
        FileDescriptor lastFile = allFiles.size() == 0 ? null : allFiles.get(allFiles.size() - 1);
        if (lastFile != null && lastFile.getEpoch() > this.context.epoch) {
            throw new StorageNotPrimaryException(segmentName, String.format("Found a file with a higher epoch (%d) than ours (%d): %s.", lastFile.getEpoch(), this.context.epoch, lastFile.getPath()));
        }
    } catch (StorageNotPrimaryException ex) {
        // We lost :(
        deleteFile(newFile);
        throw ex;
    }
    // At this point it is possible that two competing containers get this far for the same segment and both believe
    // they are owners of the lock.
    // 
    // To handle this, we consolidate all previous files into a single one and ensure that file is read-only. If that
    // file ends up being empty, we delete it. As such:
    // 1. Competing containers with lower epochs will not be able to do any damage.
    // 2. The number of files for a segment is always either 1 or 2, regardless of how many calls to OpenWrite we make
    cleanup(allFiles);
    return HDFSSegmentHandle.write(segmentName, allFiles);
}
Also used : lombok.val(lombok.val) StorageNotPrimaryException(io.pravega.segmentstore.storage.StorageNotPrimaryException)

Example 9 with StorageNotPrimaryException

use of io.pravega.segmentstore.storage.StorageNotPrimaryException in project pravega by pravega.

the class OpenWriteOperationTests method testReadOnlyNotSealed.

/**
 * Tests the case when the last file is read only but not sealed.
 * Expected outcome: Create new read-write file; don't touch other files.
 */
@Test
public void testReadOnlyNotSealed() throws Exception {
    @Cleanup val fs = new MockFileSystem();
    val context1 = newContext(1, fs);
    new CreateOperation(SEGMENT_NAME, context1).call();
    val handle1 = new OpenWriteOperation(SEGMENT_NAME, context1).call();
    context1.makeReadOnly(handle1.getLastFile());
    // Read-only file with same epoch: this should be rejected with StorageNotPrimaryException.
    AssertExtensions.assertThrows("OpenWrite did not fail when the last file has the same epoch as the context but is read-only", new OpenWriteOperation(SEGMENT_NAME, context1)::call, ex -> ex instanceof StorageNotPrimaryException);
    checkFenceLowerEpochFile(handle1, fs);
}
Also used : lombok.val(lombok.val) Cleanup(lombok.Cleanup) StorageNotPrimaryException(io.pravega.segmentstore.storage.StorageNotPrimaryException) Test(org.junit.Test)

Example 10 with StorageNotPrimaryException

use of io.pravega.segmentstore.storage.StorageNotPrimaryException in project pravega by pravega.

the class OpenWriteOperationTests method testLargerEpoch.

/**
 * Tests the case when the last file has en epoch larger than ours.
 * Expected outcome: StorageNotPrimaryException and no side effects.
 */
@Test
public void testLargerEpoch() throws Exception {
    @Cleanup val fs = new MockFileSystem();
    val lowContext = newContext(1, fs);
    val highContext = newContext(lowContext.epoch + 1, fs);
    new CreateOperation(SEGMENT_NAME, highContext).call();
    val writeHandle = new OpenWriteOperation(SEGMENT_NAME, highContext).call();
    AssertExtensions.assertThrows("OpenWrite allowed opening a segment that does not have the highest epoch.", new OpenWriteOperation(SEGMENT_NAME, lowContext)::call, ex -> ex instanceof StorageNotPrimaryException);
    Assert.assertEquals("Unexpected number of files in the file system.", 1, fs.getFileCount());
    Assert.assertTrue("Higher epoch file was deleted.", fs.exists(writeHandle.getLastFile().getPath()));
}
Also used : lombok.val(lombok.val) Cleanup(lombok.Cleanup) StorageNotPrimaryException(io.pravega.segmentstore.storage.StorageNotPrimaryException) Test(org.junit.Test)

Aggregations

StorageNotPrimaryException (io.pravega.segmentstore.storage.StorageNotPrimaryException)15 lombok.val (lombok.val)13 Cleanup (lombok.Cleanup)9 Test (org.junit.Test)9 ByteArrayInputStream (java.io.ByteArrayInputStream)5 Path (org.apache.hadoop.fs.Path)3 BadOffsetException (io.pravega.segmentstore.contracts.BadOffsetException)2 ByteArraySegment (io.pravega.common.util.ByteArraySegment)1 FileNotFoundException (java.io.FileNotFoundException)1 FileAlreadyExistsException (org.apache.hadoop.fs.FileAlreadyExistsException)1