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);
}
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);
}
}
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);
}
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);
}
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()));
}
Aggregations