use of io.pravega.segmentstore.storage.mocks.InMemorySnapshotInfoStore in project pravega by pravega.
the class SystemJournalTests method testSimpleBootstrapWithMultipleFailoversWithTruncate.
/**
* Tests a scenario when there are multiple fail overs overs.
* The test adds a few chunks to the system segments and then fails over.
* After fail over the zombie instances continue to write junk data to both system segment and journal file.
* The new instance should read the journal log file and recreate the layout of system segments.
*
* @throws Exception Throws exception in case of any error.
*/
@Test
public void testSimpleBootstrapWithMultipleFailoversWithTruncate() throws Exception {
@Cleanup CleanupHelper cleanupHelper = new CleanupHelper();
@Cleanup ChunkStorage chunkStorage = getChunkStorage();
int containerId = 42;
String systemSegmentName = SystemJournal.getChunkStorageSystemSegments(containerId)[0];
long epoch = 0;
val policy = new SegmentRollingPolicy(1024);
val config = getDefaultConfigBuilder(policy).build();
val data = new InMemorySnapshotInfoStore();
val snapshotInfoStore = new SnapshotInfoStore(containerId, snapshotId -> data.setSnapshotId(containerId, snapshotId), () -> data.getSnapshotId(containerId));
long offset = 0;
long offsetToTruncateAt = 0;
ChunkedSegmentStorage oldChunkedSegmentStorage = null;
SegmentHandle oldHandle = null;
long oldOffset = 0;
for (int i = 1; i < 10; i++) {
// Epoch 2
epoch++;
ChunkMetadataStore metadataStoreAfterCrash = getMetadataStore();
cleanupHelper.add(metadataStoreAfterCrash);
ChunkedSegmentStorage segmentStorageInLoop = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStoreAfterCrash, executorService(), config);
cleanupHelper.add(segmentStorageInLoop);
segmentStorageInLoop.initialize(epoch);
segmentStorageInLoop.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
segmentStorageInLoop.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorageInLoop);
checkSystemSegmentsLayout(segmentStorageInLoop);
val h = segmentStorageInLoop.openWrite(systemSegmentName).join();
if (null != oldChunkedSegmentStorage) {
// Add some junk to previous instance after failover
oldChunkedSegmentStorage.write(oldHandle, oldOffset, new ByteArrayInputStream("junk".getBytes()), 4, null).join();
} else {
// Only first time.
for (int j = 1; j < 10; j++) {
val b0 = "JUNK".getBytes();
segmentStorageInLoop.write(h, offset, new ByteArrayInputStream(b0), b0.length, null).join();
offset += b0.length;
}
}
offsetToTruncateAt += 4;
val b1 = "Test".getBytes();
segmentStorageInLoop.write(h, offset, new ByteArrayInputStream(b1), b1.length, null).join();
offset += b1.length;
val b2 = Integer.toString(i).getBytes();
segmentStorageInLoop.write(h, offset, new ByteArrayInputStream(b2), b2.length, null).join();
offset += b2.length;
segmentStorageInLoop.truncate(h, offsetToTruncateAt, null).join();
TestUtils.checkSegmentBounds(metadataStoreAfterCrash, h.getSegmentName(), offsetToTruncateAt, offset);
val length = Math.toIntExact(offset - offsetToTruncateAt);
byte[] readBytes = new byte[length];
val bytesRead = segmentStorageInLoop.read(h, offsetToTruncateAt, readBytes, 0, length, null).get();
Assert.assertEquals(length, readBytes.length);
String s = new String(readBytes);
// Add some garbage
if (null != oldChunkedSegmentStorage) {
oldChunkedSegmentStorage.write(oldHandle, oldOffset + 4, new ByteArrayInputStream("junk".getBytes()), 4, null).join();
}
// Save these instances so that you can write some junk after bootstrap.
oldChunkedSegmentStorage = segmentStorageInLoop;
oldHandle = h;
oldOffset = offset;
}
epoch++;
@Cleanup ChunkMetadataStore metadataStoreFinal = getMetadataStore();
ChunkedSegmentStorage segmentStorageFinal = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStoreFinal, executorService(), config);
cleanupHelper.add(segmentStorageFinal);
segmentStorageFinal.initialize(epoch);
segmentStorageFinal.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
segmentStorageFinal.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorageFinal);
checkSystemSegmentsLayout(segmentStorageFinal);
val info = segmentStorageFinal.getStreamSegmentInfo(systemSegmentName, null).join();
Assert.assertEquals(offset, info.getLength());
Assert.assertEquals(offsetToTruncateAt, info.getStartOffset());
byte[] out = new byte[Math.toIntExact(offset - offsetToTruncateAt)];
val hr = segmentStorageFinal.openRead(systemSegmentName).join();
segmentStorageFinal.read(hr, offsetToTruncateAt, out, 0, Math.toIntExact(offset - offsetToTruncateAt), null).join();
val expected = "Test1Test2Test3Test4Test5Test6Test7Test8Test9";
val actual = new String(out);
Assert.assertEquals(expected, actual);
}
use of io.pravega.segmentstore.storage.mocks.InMemorySnapshotInfoStore in project pravega by pravega.
the class SystemJournalTests method testSimpleBootstrapWithTwoFailovers.
/**
* Tests a scenario when there are two fail overs.
* The test adds a few chunks to the system segments and then fails over.
* After fail over the zombie instance continues to write junk data to both system segment and journal file.
* The new instance should read the journal log file and recreate the layout of system segments.
*
* @throws Exception Throws exception in case of any error.
*/
@Test
public void testSimpleBootstrapWithTwoFailovers() throws Exception {
@Cleanup ChunkStorage chunkStorage = getChunkStorage();
@Cleanup ChunkMetadataStore metadataStoreBeforeCrash = getMetadataStore();
@Cleanup ChunkMetadataStore metadataStoreAfterCrash = getMetadataStore();
int containerId = 42;
String systemSegmentName = SystemJournal.getChunkStorageSystemSegments(containerId)[0];
long epoch = 1;
val policy = new SegmentRollingPolicy(8);
val config = getDefaultConfigBuilder(policy).build();
val data = new InMemorySnapshotInfoStore();
val snapshotInfoStore = new SnapshotInfoStore(containerId, snapshotId -> data.setSnapshotId(containerId, snapshotId), () -> data.getSnapshotId(containerId));
long offset = 0;
// Epoch 1
@Cleanup ChunkedSegmentStorage segmentStorage1 = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStoreBeforeCrash, executorService(), config);
segmentStorage1.initialize(epoch);
segmentStorage1.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
// Bootstrap
segmentStorage1.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorage1);
checkSystemSegmentsLayout(segmentStorage1);
// Simulate some writes to system segment, this should cause some new chunks being added.
val h = segmentStorage1.openWrite(systemSegmentName).join();
val b1 = "Hello".getBytes();
segmentStorage1.write(h, offset, new ByteArrayInputStream(b1), b1.length, null).join();
offset += b1.length;
checkSystemSegmentsLayout(segmentStorage1);
// Epoch 2
epoch++;
@Cleanup ChunkedSegmentStorage segmentStorage2 = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStoreAfterCrash, executorService(), config);
segmentStorage2.initialize(epoch);
segmentStorage2.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
// Bootstrap
segmentStorage2.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorage2);
checkSystemSegmentsLayout(segmentStorage2);
val h2 = segmentStorage2.openWrite(systemSegmentName).join();
// Write Junk Data to from first instance.
segmentStorage1.write(h, offset, new ByteArrayInputStream("junk".getBytes()), 4, null).join();
val b2 = " World".getBytes();
segmentStorage2.write(h2, offset, new ByteArrayInputStream(b2), b2.length, null).join();
offset += b2.length;
checkSystemSegmentsLayout(segmentStorage2);
val info = segmentStorage2.getStreamSegmentInfo(systemSegmentName, null).join();
Assert.assertEquals(b1.length + b2.length, info.getLength());
byte[] out = new byte[b1.length + b2.length];
val hr = segmentStorage2.openRead(systemSegmentName).join();
segmentStorage2.read(hr, 0, out, 0, b1.length + b2.length, null).join();
Assert.assertEquals("Hello World", new String(out));
}
use of io.pravega.segmentstore.storage.mocks.InMemorySnapshotInfoStore in project pravega by pravega.
the class SystemJournalTests method testSystemSegmentNoConcatAllowed.
@Test
public void testSystemSegmentNoConcatAllowed() throws Exception {
@Cleanup ChunkStorage chunkStorage = getChunkStorage();
@Cleanup ChunkMetadataStore metadataStore = getMetadataStore();
int containerId = 42;
int maxLength = 8;
long epoch = 1;
val data = new InMemorySnapshotInfoStore();
val snapshotInfoStore = new SnapshotInfoStore(containerId, snapshotId -> data.setSnapshotId(containerId, snapshotId), () -> data.getSnapshotId(containerId));
@Cleanup val garbageCollector = new GarbageCollector(containerId, chunkStorage, metadataStore, ChunkedSegmentStorageConfig.DEFAULT_CONFIG, executorService());
garbageCollector.initialize(new InMemoryTaskQueueManager()).join();
val policy = new SegmentRollingPolicy(maxLength);
val config = getDefaultConfigBuilder(policy).build();
val journal = new SystemJournal(containerId, chunkStorage, metadataStore, garbageCollector, config, executorService());
val systemSegmentName = NameUtils.getAttributeSegmentName(NameUtils.getMetadataSegmentName(containerId));
Assert.assertTrue(journal.isStorageSystemSegment(systemSegmentName));
// Init
long offset = 0;
// Start container with epoch 1
@Cleanup ChunkedSegmentStorage segmentStorage = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStore, executorService(), config);
segmentStorage.initialize(epoch);
segmentStorage.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
segmentStorage.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorage);
segmentStorage.create("test", null).get();
AssertExtensions.assertFutureThrows("concat() should throw", segmentStorage.concat(SegmentStorageHandle.writeHandle(systemSegmentName), 0, "test", null), ex -> ex instanceof IllegalStateException);
AssertExtensions.assertFutureThrows("concat() should throw", segmentStorage.concat(SegmentStorageHandle.writeHandle("test"), 0, systemSegmentName, null), ex -> ex instanceof IllegalStateException);
}
use of io.pravega.segmentstore.storage.mocks.InMemorySnapshotInfoStore in project pravega by pravega.
the class SystemJournalTests method testSimpleBootstrapWithMultipleFailovers.
private void testSimpleBootstrapWithMultipleFailovers(int containerId, ChunkStorage chunkStorage, ChunkedSegmentStorageConfig config, Consumer<Long> faultInjection) throws Exception {
@Cleanup CleanupHelper cleanupHelper = new CleanupHelper();
String systemSegmentName = SystemJournal.getChunkStorageSystemSegments(containerId)[0];
long epoch = 0;
val data = new InMemorySnapshotInfoStore();
val snapshotInfoStore = new SnapshotInfoStore(containerId, snapshotId -> data.setSnapshotId(containerId, snapshotId), () -> data.getSnapshotId(containerId));
long offset = 0;
ChunkedSegmentStorage oldChunkedSegmentStorage = null;
SegmentHandle oldHandle = null;
for (int i = 1; i < 10; i++) {
// Epoch 2
epoch++;
ChunkMetadataStore metadataStoreAfterCrash = getMetadataStore();
cleanupHelper.add(metadataStoreAfterCrash);
ChunkedSegmentStorage segmentStorageInLoop = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStoreAfterCrash, executorService(), config);
cleanupHelper.add(segmentStorageInLoop);
segmentStorageInLoop.initialize(epoch);
segmentStorageInLoop.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
segmentStorageInLoop.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorageInLoop);
checkSystemSegmentsLayout(segmentStorageInLoop);
val h = segmentStorageInLoop.openWrite(systemSegmentName).join();
if (null != oldChunkedSegmentStorage) {
oldChunkedSegmentStorage.write(oldHandle, offset, new ByteArrayInputStream("junk".getBytes()), 4, null).join();
}
val b1 = "Test".getBytes();
segmentStorageInLoop.write(h, offset, new ByteArrayInputStream(b1), b1.length, null).join();
offset += b1.length;
val b2 = Integer.toString(i).getBytes();
segmentStorageInLoop.write(h, offset, new ByteArrayInputStream(b2), b2.length, null).join();
offset += b2.length;
oldChunkedSegmentStorage = segmentStorageInLoop;
oldHandle = h;
}
if (null != faultInjection) {
faultInjection.accept(epoch);
}
epoch++;
@Cleanup ChunkMetadataStore metadataStoreFinal = getMetadataStore();
@Cleanup ChunkedSegmentStorage segmentStorageFinal = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStoreFinal, executorService(), config);
segmentStorageFinal.initialize(epoch);
segmentStorageFinal.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
segmentStorageFinal.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorageFinal);
checkSystemSegmentsLayout(segmentStorageFinal);
val info = segmentStorageFinal.getStreamSegmentInfo(systemSegmentName, null).join();
Assert.assertEquals(offset, info.getLength());
byte[] out = new byte[Math.toIntExact(offset)];
val hr = segmentStorageFinal.openRead(systemSegmentName).join();
segmentStorageFinal.read(hr, 0, out, 0, Math.toIntExact(offset), null).join();
val expected = "Test1Test2Test3Test4Test5Test6Test7Test8Test9";
val actual = new String(out);
Assert.assertEquals(expected, actual);
}
use of io.pravega.segmentstore.storage.mocks.InMemorySnapshotInfoStore in project pravega by pravega.
the class SystemJournalTests method testSimpleBootstrapWithPartialDataWrite.
/**
* Tests a scenario when journal chunks may be partially written during failure.
*
* @throws Exception Throws exception in case of any error.
*/
@Test
public void testSimpleBootstrapWithPartialDataWrite() throws Exception {
@Cleanup ChunkStorage chunkStorage = getChunkStorage();
if (!chunkStorage.supportsAppend()) {
return;
}
@Cleanup ChunkMetadataStore metadataStore = getMetadataStore();
@Cleanup ChunkMetadataStore metadataStoreAfterCrash = getMetadataStore();
int containerId = 42;
String systemSegmentName = SystemJournal.getChunkStorageSystemSegments(containerId)[0];
long epoch = 1;
val policy = new SegmentRollingPolicy(4);
val config = getDefaultConfigBuilder(policy).build();
val data = new InMemorySnapshotInfoStore();
val snapshotInfoStore = new SnapshotInfoStore(containerId, snapshotId -> data.setSnapshotId(containerId, snapshotId), () -> data.getSnapshotId(containerId));
long offset = 0;
// Epoch 1
@Cleanup ChunkedSegmentStorage segmentStorage1 = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStore, executorService(), config);
segmentStorage1.initialize(epoch);
segmentStorage1.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
// Bootstrap
segmentStorage1.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorage1);
checkSystemSegmentsLayout(segmentStorage1);
// Simulate some writes to system segment, this should cause some new chunks being added.
val h = segmentStorage1.openWrite(systemSegmentName).join();
val b1 = "Hello".getBytes();
segmentStorage1.write(h, offset, new ByteArrayInputStream(b1), b1.length, null).join();
offset += b1.length;
// Inject a fault by adding some garbage at the end
checkSystemSegmentsLayout(segmentStorage1);
val chunkFileName = NameUtils.getSystemJournalFileName(segmentStorage1.getSystemJournal().getContainerId(), segmentStorage1.getSystemJournal().getEpoch(), segmentStorage1.getSystemJournal().getCurrentFileIndex().get());
val chunkInfo = chunkStorage.getInfo(chunkFileName);
chunkStorage.write(ChunkHandle.writeHandle(chunkFileName), chunkInfo.get().getLength(), 1, new ByteArrayInputStream(new byte[1])).get();
// This next write will encounter partially written chunk and is expected to start a new chunk.
val b2 = " World".getBytes();
segmentStorage1.write(h, offset, new ByteArrayInputStream(b2), b2.length, null).join();
offset += b2.length;
checkSystemSegmentsLayout(segmentStorage1);
// Step 2
// Start container with epoch 2
epoch++;
@Cleanup ChunkedSegmentStorage segmentStorage2 = new ChunkedSegmentStorage(containerId, chunkStorage, metadataStoreAfterCrash, executorService(), config);
segmentStorage2.initialize(epoch);
segmentStorage2.getGarbageCollector().initialize(new InMemoryTaskQueueManager()).join();
// Bootstrap
segmentStorage2.bootstrap(snapshotInfoStore, null).join();
deleteGarbage(segmentStorage2);
checkSystemSegmentsLayout(segmentStorage2);
// Validate
val info = segmentStorage2.getStreamSegmentInfo(systemSegmentName, null).join();
Assert.assertEquals(b1.length + b2.length, info.getLength());
byte[] out = new byte[b1.length + b2.length];
val hr = segmentStorage2.openRead(systemSegmentName).join();
segmentStorage2.read(hr, 0, out, 0, b1.length + b2.length, null).join();
Assert.assertEquals("Hello World", new String(out));
}
Aggregations