use of io.pravega.segmentstore.storage.SegmentHandle in project pravega by pravega.
the class SegmentAttributeBTreeIndex method readPage.
private CompletableFuture<ByteArraySegment> readPage(long offset, int length, boolean cacheResult, Duration timeout) {
// First, check in the cache.
byte[] fromCache = getFromCache(offset, length);
if (fromCache != null) {
return CompletableFuture.completedFuture(new ByteArraySegment(fromCache));
}
// Cache miss; load data from Storage.
SegmentHandle handle = this.handle.get();
if (handle == null) {
// Attribute Segment does not exist.
if (offset == 0 && length == 0) {
// Reading 0 bytes at offset 0 is a valid operation (inexistent Attribute Segment is equivalent to an empty one).
return CompletableFuture.completedFuture(new ByteArraySegment(new byte[0]));
} else {
return Futures.failedFuture(new ArrayIndexOutOfBoundsException(String.format("Attribute Index Segment has not been created yet. Cannot read %d byte(s) from offset (%d).", length, offset)));
}
}
return readPageFromStorage(handle, offset, length, cacheResult, timeout);
}
use of io.pravega.segmentstore.storage.SegmentHandle in project pravega by pravega.
the class SegmentAttributeBTreeIndex method readPageFromStorage.
private CompletableFuture<ByteArraySegment> readPageFromStorage(SegmentHandle handle, PendingRead pr, boolean cacheResult, Duration timeout) {
byte[] buffer = new byte[pr.length];
Futures.completeAfter(() -> this.storage.read(handle, pr.offset, buffer, 0, pr.length, timeout).thenApplyAsync(bytesRead -> {
Preconditions.checkArgument(pr.length == bytesRead, "Unexpected number of bytes read.");
if (cacheResult) {
storeInCache(pr.offset, buffer);
}
return new ByteArraySegment(buffer);
}, this.executor), pr.completion);
return pr.completion;
}
use of io.pravega.segmentstore.storage.SegmentHandle in project pravega by pravega.
the class SegmentAttributeBTreeIndex method seal.
@Override
public CompletableFuture<Void> seal(@NonNull Duration timeout) {
ensureInitialized();
SegmentHandle handle = this.handle.get();
if (handle == null) {
// Empty Attribute Index. There is no point in sealing since we won't be allowed to update anything new from now on.
return CompletableFuture.completedFuture(null);
}
return Futures.exceptionallyExpecting(this.storage.seal(handle, timeout).thenRun(() -> log.info("{}: Sealed.", this.traceObjectId)), ex -> ex instanceof StreamSegmentSealedException, null);
}
use of io.pravega.segmentstore.storage.SegmentHandle in project pravega by pravega.
the class ChunkedSegmentStorageTests method testTruncateWithFailover.
@Test
public void testTruncateWithFailover() throws Exception {
@Cleanup CleanupHelper cleanupHelper = new CleanupHelper();
String testSegmentName = "foo";
val config = ChunkedSegmentStorageConfig.DEFAULT_CONFIG.toBuilder().garbageCollectionDelay(Duration.ZERO).indexBlockSize(3).build();
TestContext testContext = getTestContext(config);
cleanupHelper.add(testContext);
// Create
testContext.chunkedSegmentStorage.create(testSegmentName, null).get();
// Write some data.
long offset = 0;
int i = 2;
long epoch = testContext.chunkedSegmentStorage.getEpoch();
SegmentHandle hWrite = testContext.chunkedSegmentStorage.openWrite(testSegmentName).get();
// Create a new test context and initialize with new epoch.
testContext.chunkedSegmentStorage.write(hWrite, offset, new ByteArrayInputStream(new byte[i]), i, null).join();
TestUtils.checkSegmentBounds(testContext.metadataStore, testSegmentName, offset, offset + i);
TestUtils.checkReadIndexEntries(testContext.chunkedSegmentStorage, testContext.metadataStore, testSegmentName, offset, offset + i, true);
checkDataRead(testSegmentName, testContext, offset, i);
offset += i;
// Fork the context.
testContext = testContext.fork(++epoch);
cleanupHelper.add(testContext);
val oldTestCotext = testContext;
val newTestContext = oldTestCotext.fork(++epoch);
cleanupHelper.add(newTestContext);
// Fence out old store.
oldTestCotext.metadataStore.markFenced();
// Truncate and Read in new epoch.
// Make sure to open segment with new instance before writing garbage to old instance.
hWrite = newTestContext.chunkedSegmentStorage.openWrite(testSegmentName).get();
newTestContext.chunkedSegmentStorage.truncate(hWrite, offset, null).get();
TestUtils.checkSegmentBounds(newTestContext.metadataStore, testSegmentName, offset, offset);
TestUtils.checkReadIndexEntries(newTestContext.chunkedSegmentStorage, newTestContext.metadataStore, testSegmentName, offset, offset, false);
AssertExtensions.assertFutureThrows("openWrite() allowed after fencing", oldTestCotext.chunkedSegmentStorage.openWrite(testSegmentName), ex -> ex instanceof StorageNotPrimaryException);
AssertExtensions.assertFutureThrows("openRead() allowed after fencing", oldTestCotext.chunkedSegmentStorage.openRead(testSegmentName), ex -> ex instanceof StorageNotPrimaryException);
}
use of io.pravega.segmentstore.storage.SegmentHandle in project pravega by pravega.
the class ChunkedSegmentStorageTests method testReadWriteWithMultipleFailoversWithGarbage.
/**
* Test read and write with multiple failovers.
*
* @throws Exception Exception if any.
*/
@Test
public void testReadWriteWithMultipleFailoversWithGarbage() throws Exception {
@Cleanup CleanupHelper cleanupHelper = new CleanupHelper();
String testSegmentName = "foo";
@Cleanup TestContext testContext = getTestContext();
cleanupHelper.add(testContext);
// Create
testContext.chunkedSegmentStorage.create(testSegmentName, null).get();
// Write some data.
long writeAt = 0;
long epoch = CONTAINER_ID;
SegmentHandle hWrite = testContext.chunkedSegmentStorage.openWrite(testSegmentName).get();
ArrayList<Long> lengths = new ArrayList<>();
for (int i = 1; i < 5; i++) {
// Create a new test context and initialize with new epoch.
testContext.chunkedSegmentStorage.write(hWrite, writeAt, new ByteArrayInputStream(new byte[i]), i, null).join();
writeAt += i;
lengths.add((long) i);
// Read in same epoch.
checkDataRead(testSegmentName, testContext, 0, writeAt);
val lengthsArray = Longs.toArray(lengths);
TestUtils.checkSegmentLayout(testContext.metadataStore, testSegmentName, lengthsArray);
TestUtils.checkReadIndexEntries(testContext.chunkedSegmentStorage, testContext.metadataStore, testSegmentName, 0, Arrays.stream(lengthsArray).sum(), false);
// Fork the context.
val oldTestCotext = testContext;
testContext = oldTestCotext.fork(epoch++);
cleanupHelper.add(testContext);
TestUtils.checkSegmentLayout(testContext.metadataStore, testSegmentName, Longs.toArray(lengths));
// Make sure to open segment with new instance before writing garbage to old instance.
hWrite = testContext.chunkedSegmentStorage.openWrite(testSegmentName).get();
// Write some garbage
oldTestCotext.chunkedSegmentStorage.write(hWrite, writeAt, new ByteArrayInputStream(new byte[10]), 10, null).join();
// Fence out old store.
oldTestCotext.metadataStore.markFenced();
AssertExtensions.assertFutureThrows("write() allowed after fencing", oldTestCotext.chunkedSegmentStorage.write(hWrite, writeAt + 10, new ByteArrayInputStream(new byte[10]), 10, null), ex -> ex instanceof StorageNotPrimaryException);
// Read in new epoch.
checkDataRead(testSegmentName, testContext, 0, writeAt);
}
int total = 10;
// Create a new test context and initialize with new epoch.
testContext = testContext.fork(epoch++);
cleanupHelper.add(testContext);
checkDataRead(testSegmentName, testContext, 0, total);
}
Aggregations