use of io.pravega.segmentstore.server.UpdateableContainerMetadata in project pravega by pravega.
the class ContainerMetadataUpdateTransactionTests method testPreProcessStreamSegmentSeal.
// endregion
// region StreamSegmentSealOperation
/**
* Tests the preProcess method with StreamSegmentSeal operations.
* Scenarios:
* * Recovery Mode
* * Non-recovery mode
* * StreamSegment is Merged (both in-transaction and in-metadata)
* * StreamSegment is Sealed (both in-transaction and in-metadata)
*/
@Test
public void testPreProcessStreamSegmentSeal() throws Exception {
UpdateableContainerMetadata metadata = createMetadata();
StreamSegmentSealOperation sealOp = createSeal();
// When everything is OK (in recovery mode) - nothing should change.
metadata.enterRecoveryMode();
val txn1 = createUpdateTransaction(metadata);
txn1.preProcessOperation(sealOp);
AssertExtensions.assertLessThan("Unexpected StreamSegmentLength after call to preProcess in recovery mode.", 0, sealOp.getStreamSegmentOffset());
checkNoSequenceNumberAssigned(sealOp, "call to preProcess in recovery mode");
Assert.assertFalse("preProcess(Seal) seems to have changed the Updater internal state in recovery mode.", txn1.getStreamSegmentMetadata(SEGMENT_ID).isSealed());
Assert.assertFalse("preProcess(Seal) seems to have changed the metadata in recovery mode.", metadata.getStreamSegmentMetadata(SEGMENT_ID).isSealed());
// When everything is OK (no recovery mode).
metadata.exitRecoveryMode();
val txn2 = createUpdateTransaction(metadata);
txn2.preProcessOperation(sealOp);
Assert.assertEquals("Unexpected StreamSegmentLength after call to preProcess in non-recovery mode.", SEGMENT_LENGTH, sealOp.getStreamSegmentOffset());
checkNoSequenceNumberAssigned(sealOp, "call to preProcess in non-recovery mode");
Assert.assertFalse("preProcess(Seal) seems to have changed the Updater internal state.", txn2.getStreamSegmentMetadata(SEGMENT_ID).isSealed());
Assert.assertFalse("preProcess(Seal) seems to have changed the metadata.", metadata.getStreamSegmentMetadata(SEGMENT_ID).isSealed());
// When StreamSegment is merged (via transaction).
StreamSegmentSealOperation transactionSealOp = new StreamSegmentSealOperation(SEALED_TRANSACTION_ID);
MergeTransactionOperation mergeOp = createMerge();
txn2.preProcessOperation(mergeOp);
txn2.acceptOperation(mergeOp);
Assert.assertFalse("Transaction should not be merged in metadata (yet).", metadata.getStreamSegmentMetadata(SEALED_TRANSACTION_ID).isMerged());
AssertExtensions.assertThrows("Unexpected behavior for preProcess(Seal) when Segment is merged (in transaction).", () -> txn2.preProcessOperation(transactionSealOp), ex -> ex instanceof StreamSegmentMergedException);
// When StreamSegment is merged (via metadata).
txn2.commit(metadata);
Assert.assertTrue("Transaction should have been merged in metadata.", metadata.getStreamSegmentMetadata(SEALED_TRANSACTION_ID).isMerged());
AssertExtensions.assertThrows("Unexpected behavior for preProcess(Seal) when Segment is merged (in metadata).", () -> txn2.preProcessOperation(transactionSealOp), ex -> ex instanceof StreamSegmentMergedException);
// When StreamSegment is sealed (via transaction).
txn2.acceptOperation(sealOp);
Assert.assertFalse("StreamSegment should not be sealed in metadata (yet).", metadata.getStreamSegmentMetadata(SEGMENT_ID).isSealed());
AssertExtensions.assertThrows("Unexpected behavior for preProcess(Seal) when Segment is sealed (in transaction).", () -> txn2.preProcessOperation(createSeal()), ex -> ex instanceof StreamSegmentSealedException);
// When StreamSegment is sealed (via metadata).
txn2.commit(metadata);
Assert.assertTrue("StreamSegment should have been sealed in metadata.", metadata.getStreamSegmentMetadata(SEGMENT_ID).isSealed());
AssertExtensions.assertThrows("Unexpected behavior for preProcess(Seal) when Segment is sealed (in metadata).", () -> txn2.preProcessOperation(createSeal()), ex -> ex instanceof StreamSegmentSealedException);
}
use of io.pravega.segmentstore.server.UpdateableContainerMetadata in project pravega by pravega.
the class ContainerMetadataUpdateTransactionTests method testGetActiveSegmentCount.
/**
* Tests the correctness of getActiveSegmentCount(), especially in the case when the real ContainerMetadata has
* changed its value.
*/
@Test
public void testGetActiveSegmentCount() throws Exception {
// Create a base metadata and make sure it has one active segment.
UpdateableContainerMetadata metadata = createMetadata();
int expected = 3;
Assert.assertEquals("Unexpected initial Active Segment Count for base metadata.", expected, metadata.getActiveSegmentCount());
// Create an UpdateTransaction for it and map a new segment.
val txn1 = new ContainerMetadataUpdateTransaction(metadata, metadata, 0);
Assert.assertEquals("Unexpected Active Segment Count for first transaction.", expected, txn1.getActiveSegmentCount());
val map1 = createMap("NewSegment1");
txn1.preProcessOperation(map1);
map1.setSequenceNumber(metadata.nextOperationSequenceNumber());
txn1.acceptOperation(map1);
expected++;
Assert.assertEquals("Unexpected Active Segment Count for first transaction after map.", expected, txn1.getActiveSegmentCount());
// Create a second UpdateTransaction for it and map a new segment.
val txn2 = new ContainerMetadataUpdateTransaction(txn1, metadata, 0);
Assert.assertEquals("Unexpected Active Segment Count for second transaction.", expected, txn2.getActiveSegmentCount());
val map2 = createMap("NewSegment2");
txn2.preProcessOperation(map2);
map2.setSequenceNumber(metadata.nextOperationSequenceNumber());
txn2.acceptOperation(map2);
expected++;
Assert.assertEquals("Unexpected Active Segment Count for first transaction after map.", expected, txn2.getActiveSegmentCount());
// Clean up base metadata - simplest way to deactivate segments (even if this will cause a TxnCommit to fail,
// but we don't test that here).
metadata.enterRecoveryMode();
metadata.reset();
metadata.exitRecoveryMode();
expected = 0;
// Check Active Segment Count after the cleanup.
Assert.assertEquals("Unexpected Active Segment Count for base metadata after cleanup.", expected, metadata.getActiveSegmentCount());
Assert.assertEquals("Unexpected Active Segment Count for first transaction after cleanup.", expected + 1, txn1.getActiveSegmentCount());
Assert.assertEquals("Unexpected Active Segment Count for second transaction after cleanup.", expected + 2, txn2.getActiveSegmentCount());
}
use of io.pravega.segmentstore.server.UpdateableContainerMetadata in project pravega by pravega.
the class ContainerMetadataUpdateTransactionTests method testPreProcessStreamSegmentTruncate.
// endregion
// region StreamSegmentTruncate
/**
* Tests the preProcess method with StreamSegmentTruncate operations.
* Scenarios:
* * Recovery Mode
* * Non-recovery mode
* * Invalid states or arguments (Segment not sealed, bad offsets, Transaction Segment).
*/
@Test
public void testPreProcessStreamSegmentTruncate() throws Exception {
final UpdateableContainerMetadata metadata = createMetadata();
// When trying to truncate beyond last offset.
val txn = createUpdateTransaction(metadata);
AssertExtensions.assertThrows("preProcess did not throw when offset is too large.", () -> txn.preProcessOperation(createTruncate(SEGMENT_LENGTH + 1)), ex -> ex instanceof BadOffsetException);
// Actually truncate the segment, and re-verify bounds.
val op1 = createTruncate(SEGMENT_LENGTH / 2);
txn.preProcessOperation(op1);
txn.acceptOperation(op1);
txn.commit(metadata);
AssertExtensions.assertThrows("preProcess did not throw when offset is too small (on truncated segment).", () -> txn.preProcessOperation(createTruncate(op1.getStreamSegmentOffset() - 1)), ex -> ex instanceof BadOffsetException);
AssertExtensions.assertThrows("preProcess did not throw when offset is too large (on truncated segment).", () -> txn.preProcessOperation(createTruncate(SEGMENT_LENGTH + 1)), ex -> ex instanceof BadOffsetException);
// For a transaction
AssertExtensions.assertThrows("preProcess did not throw for a Transaction Segment.", () -> txn.preProcessOperation(new StreamSegmentTruncateOperation(SEALED_TRANSACTION_ID, SEALED_TRANSACTION_LENGTH / 2)), ex -> ex instanceof MetadataUpdateException);
// Now verify that a valid offset does work (not throwing means the test passes).
txn.preProcessOperation(createTruncate(op1.getStreamSegmentOffset()));
txn.preProcessOperation(createTruncate(op1.getStreamSegmentOffset() + 1));
txn.preProcessOperation(createTruncate(SEGMENT_LENGTH));
}
use of io.pravega.segmentstore.server.UpdateableContainerMetadata in project pravega by pravega.
the class ContainerMetadataUpdateTransactionTests method testStreamSegmentAppendWithOffset.
/**
* Tests the ability of the ContainerMetadataUpdateTransaction to process (and accept) StreamSegmentAppendOperations with
* predefined offsets.
*/
@Test
public void testStreamSegmentAppendWithOffset() throws Exception {
UpdateableContainerMetadata metadata = createMetadata();
val txn = createUpdateTransaction(metadata);
// Append #1 (at offset 0).
long offset = metadata.getStreamSegmentMetadata(SEGMENT_ID).getLength();
StreamSegmentAppendOperation appendOp = createAppendWithOffset(offset);
txn.preProcessOperation(appendOp);
Assert.assertEquals("Unexpected StreamSegmentOffset after call to preProcess in non-recovery mode.", offset, appendOp.getStreamSegmentOffset());
checkNoSequenceNumberAssigned(appendOp, "call to preProcess in non-recovery mode");
Assert.assertEquals("preProcess(Append) seems to have changed the Updater internal state.", offset, txn.getStreamSegmentMetadata(SEGMENT_ID).getLength());
Assert.assertEquals("preProcess(Append) seems to have changed the metadata.", offset, metadata.getStreamSegmentMetadata(SEGMENT_ID).getLength());
txn.acceptOperation(appendOp);
// Append #2 (after Append #1)
offset = appendOp.getStreamSegmentOffset() + appendOp.getLength();
appendOp = createAppendWithOffset(offset);
txn.preProcessOperation(appendOp);
Assert.assertEquals("Unexpected StreamSegmentOffset after call to preProcess in non-recovery mode.", offset, appendOp.getStreamSegmentOffset());
checkNoSequenceNumberAssigned(appendOp, "call to preProcess in non-recovery mode");
Assert.assertEquals("preProcess(Append) seems to have changed the Updater internal state.", offset, txn.getStreamSegmentMetadata(SEGMENT_ID).getLength());
Assert.assertEquals("preProcess(Append) seems to have changed the metadata.", SEGMENT_LENGTH, metadata.getStreamSegmentMetadata(SEGMENT_ID).getLength());
txn.acceptOperation(appendOp);
// Append #3 (wrong offset)
offset = appendOp.getStreamSegmentOffset() + appendOp.getLength() - 1;
StreamSegmentAppendOperation badAppendOp = createAppendWithOffset(offset);
AssertExtensions.assertThrows("preProcessOperations accepted an append with the wrong offset.", () -> txn.preProcessOperation(badAppendOp), ex -> ex instanceof BadOffsetException);
AssertExtensions.assertThrows("acceptOperation accepted an append that was rejected during preProcessing.", () -> txn.acceptOperation(badAppendOp), ex -> ex instanceof MetadataUpdateException);
}
use of io.pravega.segmentstore.server.UpdateableContainerMetadata in project pravega by pravega.
the class ContainerMetadataUpdateTransactionTests method createMetadata.
private UpdateableContainerMetadata createMetadata() {
UpdateableContainerMetadata metadata = createBlankMetadata();
UpdateableSegmentMetadata segmentMetadata = metadata.mapStreamSegmentId(SEGMENT_NAME, SEGMENT_ID);
segmentMetadata.setLength(SEGMENT_LENGTH);
// Different from Length.
segmentMetadata.setStorageLength(SEGMENT_LENGTH - 1);
segmentMetadata = metadata.mapStreamSegmentId(SEALED_TRANSACTION_NAME, SEALED_TRANSACTION_ID, SEGMENT_ID);
segmentMetadata.setLength(SEALED_TRANSACTION_LENGTH);
segmentMetadata.setStorageLength(SEALED_TRANSACTION_LENGTH);
segmentMetadata.markSealed();
segmentMetadata = metadata.mapStreamSegmentId(NOTSEALED_TRANSACTION_NAME, NOTSEALED_TRANSACTION_ID, SEGMENT_ID);
segmentMetadata.setLength(0);
segmentMetadata.setStorageLength(0);
return metadata;
}
Aggregations