Search in sources :

Example 1 with AttributeUpdate

use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.

the class StreamSegmentMapperTests method testCreateAlreadyExists.

/**
 * General test for verifying behavior when a Segment/Transaction is attempted to be created but it already exists.
 *
 * @param segmentName   The name of the segment/transaction to create.
 * @param createSegment A BiFunction that is given an instance of a StreamSegmentMapper and a Collection of AttributeUpdates
 *                      that, when invoked, will create the given segment.
 */
private void testCreateAlreadyExists(String segmentName, BiFunction<StreamSegmentMapper, Collection<AttributeUpdate>, CompletableFuture<?>> createSegment) {
    final String stateSegmentName = StreamSegmentNameUtils.getStateSegmentName(segmentName);
    final Map<UUID, Long> correctAttributes = Collections.singletonMap(UUID.randomUUID(), 123L);
    final Collection<AttributeUpdate> correctAttributeUpdates = correctAttributes.entrySet().stream().map(e -> new AttributeUpdate(e.getKey(), AttributeUpdateType.Replace, e.getValue())).collect(Collectors.toList());
    final Map<UUID, Long> badAttributes = Collections.singletonMap(UUID.randomUUID(), 456L);
    final Collection<AttributeUpdate> badAttributeUpdates = badAttributes.entrySet().stream().map(e -> new AttributeUpdate(e.getKey(), AttributeUpdateType.Replace, e.getValue())).collect(Collectors.toList());
    @Cleanup TestContext context = new TestContext();
    @Cleanup val storage = InMemoryStorageFactory.newStorage(executorService());
    storage.initialize(1);
    val store = new SegmentStateStore(storage, executorService());
    val mapper = new StreamSegmentMapper(context.metadata, context.operationLog, store, context.noOpMetadataCleanup, storage, executorService());
    // 1. Segment Exists, and so does State File (and it's not corrupted) -> Exception must be bubbled up.
    createSegment.apply(mapper, correctAttributeUpdates).join();
    AssertExtensions.assertThrows("createNewStreamSegment did not fail when Segment already exists.", () -> createSegment.apply(mapper, badAttributeUpdates), ex -> ex instanceof StreamSegmentExistsException);
    val state1 = store.get(segmentName, TIMEOUT).join();
    AssertExtensions.assertMapEquals("Unexpected attributes after failed attempt to recreate correctly created segment", correctAttributes, state1.getAttributes());
    // 2. Segment Exists, but with empty State File: State file re-created & no exception bubbled up.
    storage.openWrite(stateSegmentName).thenCompose(handle -> storage.delete(handle, TIMEOUT)).thenCompose(v -> storage.create(stateSegmentName, TIMEOUT)).join();
    Assert.assertNull("Expected a null SegmentState.", store.get(segmentName, TIMEOUT).join());
    createSegment.apply(mapper, correctAttributeUpdates).join();
    val state2 = store.get(segmentName, TIMEOUT).join();
    AssertExtensions.assertMapEquals("Unexpected attributes after successful attempt to complete segment creation (missing state file)", correctAttributes, state2.getAttributes());
    // 3. Segment Exists, but with corrupted State File: State file re-created & no exception bubbled up.
    storage.openWrite(stateSegmentName).thenCompose(handle -> storage.delete(handle, TIMEOUT)).thenCompose(v -> storage.create(stateSegmentName, TIMEOUT)).thenCompose(v -> storage.openWrite(stateSegmentName)).thenCompose(handle -> storage.write(handle, 0, new ByteArrayInputStream(new byte[1]), 1, TIMEOUT)).join();
    AssertExtensions.assertThrows("Expected a DataCorruptionException when reading a corrupted State File.", () -> store.get(segmentName, TIMEOUT), ex -> ex instanceof DataCorruptionException);
    createSegment.apply(mapper, correctAttributeUpdates).join();
    val state3 = store.get(segmentName, TIMEOUT).join();
    AssertExtensions.assertMapEquals("Unexpected attributes after successful attempt to complete segment creation (corrupted state file)", correctAttributes, state3.getAttributes());
    // 4. Segment Exists with non-zero length, but with empty/corrupted State File: State File re-created and exception thrown.
    storage.openWrite(stateSegmentName).thenCompose(handle -> storage.delete(handle, TIMEOUT)).thenCompose(v -> storage.create(stateSegmentName, TIMEOUT)).thenCompose(v -> storage.openWrite(segmentName)).thenCompose(handle -> storage.write(handle, 0, new ByteArrayInputStream(new byte[1]), 1, TIMEOUT)).join();
    AssertExtensions.assertThrows("createNewStreamSegment did not fail when Segment already exists (non-zero length, missing state file).", () -> createSegment.apply(mapper, correctAttributeUpdates), ex -> ex instanceof StreamSegmentExistsException);
    val state4 = store.get(segmentName, TIMEOUT).join();
    AssertExtensions.assertMapEquals("Unexpected attributes after failed attempt to recreate segment with non-zero length", correctAttributes, state4.getAttributes());
}
Also used : Arrays(java.util.Arrays) Storage(io.pravega.segmentstore.storage.Storage) StreamSegmentInformation(io.pravega.segmentstore.contracts.StreamSegmentInformation) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) AssertExtensions(io.pravega.test.common.AssertExtensions) BiFunction(java.util.function.BiFunction) ContainerMetadata(io.pravega.segmentstore.server.ContainerMetadata) TimeoutException(java.util.concurrent.TimeoutException) Cleanup(lombok.Cleanup) UpdateableSegmentMetadata(io.pravega.segmentstore.server.UpdateableSegmentMetadata) SegmentProperties(io.pravega.segmentstore.contracts.SegmentProperties) AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) SegmentHandle(io.pravega.segmentstore.storage.SegmentHandle) ByteArrayInputStream(java.io.ByteArrayInputStream) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) InMemoryStorageFactory(io.pravega.segmentstore.storage.mocks.InMemoryStorageFactory) Duration(java.time.Duration) Map(java.util.Map) Operation(io.pravega.segmentstore.server.logs.operations.Operation) Attributes(io.pravega.segmentstore.contracts.Attributes) Predicate(java.util.function.Predicate) Collection(java.util.Collection) InMemoryStorage(io.pravega.segmentstore.storage.mocks.InMemoryStorage) Set(java.util.Set) CompletionException(java.util.concurrent.CompletionException) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) SegmentMetadataComparer(io.pravega.segmentstore.server.SegmentMetadataComparer) StreamSegmentNameUtils(io.pravega.shared.segment.StreamSegmentNameUtils) List(java.util.List) AsyncMap(io.pravega.common.util.AsyncMap) StreamSegmentExistsException(io.pravega.segmentstore.contracts.StreamSegmentExistsException) ThreadPooledTestSuite(io.pravega.test.common.ThreadPooledTestSuite) Futures(io.pravega.common.concurrent.Futures) MetadataBuilder(io.pravega.segmentstore.server.MetadataBuilder) SegmentRollingPolicy(io.pravega.segmentstore.storage.SegmentRollingPolicy) TooManyActiveSegmentsException(io.pravega.segmentstore.contracts.TooManyActiveSegmentsException) Exceptions(io.pravega.common.Exceptions) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) UpdateableContainerMetadata(io.pravega.segmentstore.server.UpdateableContainerMetadata) SegmentMetadata(io.pravega.segmentstore.server.SegmentMetadata) Timeout(org.junit.rules.Timeout) StreamSegmentMapOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentMapOperation) MathHelpers(io.pravega.common.MathHelpers) Iterator(java.util.Iterator) Executor(java.util.concurrent.Executor) IntentionalException(io.pravega.test.common.IntentionalException) lombok.val(lombok.val) OperationLog(io.pravega.segmentstore.server.OperationLog) Test(org.junit.Test) Service(com.google.common.util.concurrent.Service) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) Rule(org.junit.Rule) AttributeUpdateType(io.pravega.segmentstore.contracts.AttributeUpdateType) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) Assert(org.junit.Assert) Collections(java.util.Collections) InputStream(java.io.InputStream) lombok.val(lombok.val) AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) Cleanup(lombok.Cleanup) StreamSegmentExistsException(io.pravega.segmentstore.contracts.StreamSegmentExistsException) ByteArrayInputStream(java.io.ByteArrayInputStream) AtomicLong(java.util.concurrent.atomic.AtomicLong) DataCorruptionException(io.pravega.segmentstore.server.DataCorruptionException) UUID(java.util.UUID)

Example 2 with AttributeUpdate

use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.

the class StreamSegmentMapperTests method testCreateNewStreamSegment.

/**
 * Tests the ability of the StreamSegmentMapper to create a new StreamSegment.
 */
@Test
public void testCreateNewStreamSegment() {
    final int segmentCount = 10;
    final int transactionsPerSegment = 5;
    @Cleanup TestContext context = new TestContext();
    HashMap<String, SegmentRollingPolicy> storageSegments = new HashMap<>();
    HashMap<String, Integer> expectedRolloverSizes = new HashMap<>();
    setupStorageCreateHandler(context, storageSegments);
    setupStorageGetHandler(context, storageSegments.keySet(), segmentName -> StreamSegmentInformation.builder().name(segmentName).build());
    // Create some Segments and Transaction and verify they are properly created and registered.
    for (int i = 0; i < segmentCount; i++) {
        String segmentName = getName(i);
        val segmentAttributes = createAttributes(ATTRIBUTE_COUNT);
        if (i % 2 == 0) {
            segmentAttributes.add(new AttributeUpdate(Attributes.ROLLOVER_SIZE, AttributeUpdateType.Replace, i + 100));
            expectedRolloverSizes.put(segmentName, i + 100);
        }
        context.mapper.createNewStreamSegment(segmentName, segmentAttributes, TIMEOUT).join();
        assertSegmentCreated(segmentName, segmentAttributes, context);
        for (int j = 0; j < transactionsPerSegment; j++) {
            val transactionAttributes = createAttributes(ATTRIBUTE_COUNT);
            int rolloverSize = j % 2 == 0 ? j + 100 : -1;
            if (rolloverSize >= 0) {
                transactionAttributes.add(new AttributeUpdate(Attributes.ROLLOVER_SIZE, AttributeUpdateType.Replace, rolloverSize));
            }
            String transactionName = context.mapper.createNewTransactionStreamSegment(segmentName, UUID.randomUUID(), transactionAttributes, TIMEOUT).join();
            if (rolloverSize >= 0) {
                expectedRolloverSizes.put(transactionName, rolloverSize);
            }
            assertSegmentCreated(transactionName, transactionAttributes, context);
        }
    }
    for (val e : storageSegments.entrySet()) {
        if (e.getValue() == null) {
            Assert.assertFalse("Segment was expected to have a rollover policy defined.", expectedRolloverSizes.containsKey(e.getKey()));
        } else {
            long expectedValue = expectedRolloverSizes.containsKey(e.getKey()) ? expectedRolloverSizes.get(e.getKey()) : SegmentRollingPolicy.NO_ROLLING.getMaxLength();
            Assert.assertEquals("Unexpected rollover policy set.", expectedValue, e.getValue().getMaxLength());
        }
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) lombok.val(lombok.val) AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) SegmentRollingPolicy(io.pravega.segmentstore.storage.SegmentRollingPolicy) HashMap(java.util.HashMap) Cleanup(lombok.Cleanup) Test(org.junit.Test)

Example 3 with AttributeUpdate

use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.

the class StreamSegmentMapperTests method createAttributes.

private Collection<AttributeUpdate> createAttributes(int count) {
    Collection<AttributeUpdate> result = new ArrayList<>(count);
    for (int i = 0; i < count; i++) {
        AttributeUpdateType ut = AttributeUpdateType.values()[i % AttributeUpdateType.values().length];
        result.add(new AttributeUpdate(UUID.randomUUID(), ut, i, i));
    }
    return result;
}
Also used : AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) AttributeUpdateType(io.pravega.segmentstore.contracts.AttributeUpdateType) ArrayList(java.util.ArrayList)

Example 4 with AttributeUpdate

use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.

the class ContainerMetadataUpdateTransactionTests method testMaxAttributeLimit.

/**
 * Tests the ability of the ContainerMetadataUpdateTransaction to enforce the maximum attribute limit on Segments.
 */
@Test
public void testMaxAttributeLimit() throws Exception {
    // We check all operations that can update attributes.
    val ops = new HashMap<String, Function<Collection<AttributeUpdate>, Operation>>();
    ops.put("UpdateAttributes", u -> new UpdateAttributesOperation(SEGMENT_ID, u));
    ops.put("Append", u -> new StreamSegmentAppendOperation(SEGMENT_ID, DEFAULT_APPEND_DATA, u));
    // Set the maximum allowed number of attributes on a segment.
    UpdateableContainerMetadata metadata = createMetadata();
    val initialUpdates = new ArrayList<AttributeUpdate>(SegmentMetadata.MAXIMUM_ATTRIBUTE_COUNT);
    val expectedValues = new HashMap<UUID, Long>();
    for (int i = 0; i < SegmentMetadata.MAXIMUM_ATTRIBUTE_COUNT; i++) {
        UUID attributeId;
        do {
            attributeId = UUID.randomUUID();
        } while (expectedValues.containsKey(attributeId));
        initialUpdates.add(new AttributeUpdate(attributeId, AttributeUpdateType.None, i));
        expectedValues.put(attributeId, (long) i);
    }
    // And load them up into an UpdateTransaction.
    val txn = createUpdateTransaction(metadata);
    val initialOp = new UpdateAttributesOperation(SEGMENT_ID, initialUpdates);
    txn.preProcessOperation(initialOp);
    txn.acceptOperation(initialOp);
    // invokes preProcessOperation() - which is responsible with validation, so no changes are made to the UpdateTransaction.
    for (val opGenerator : ops.entrySet()) {
        // Value replacement.
        val replacementUpdates = new ArrayList<AttributeUpdate>();
        int i = 0;
        for (val e : expectedValues.entrySet()) {
            AttributeUpdate u;
            switch((i++) % 4) {
                case 0:
                    u = new AttributeUpdate(e.getKey(), AttributeUpdateType.ReplaceIfEquals, e.getValue() + 1, e.getValue());
                    break;
                case 1:
                    u = new AttributeUpdate(e.getKey(), AttributeUpdateType.ReplaceIfGreater, e.getValue() + 1);
                    break;
                case 2:
                    u = new AttributeUpdate(e.getKey(), AttributeUpdateType.Accumulate, 1);
                    break;
                default:
                    u = new AttributeUpdate(e.getKey(), AttributeUpdateType.Replace, 1);
                    break;
            }
            replacementUpdates.add(u);
        }
        // This should not throw anything.
        txn.preProcessOperation(opGenerator.getValue().apply(replacementUpdates));
        // Removal - this should not throw anything either.
        val toRemoveId = initialUpdates.get(0).getAttributeId();
        val toRemoveUpdate = new AttributeUpdate(toRemoveId, AttributeUpdateType.Replace, SegmentMetadata.NULL_ATTRIBUTE_VALUE);
        txn.preProcessOperation(opGenerator.getValue().apply(Collections.singleton(toRemoveUpdate)));
        // Addition - this should throw.
        UUID toAddId;
        do {
            toAddId = UUID.randomUUID();
        } while (expectedValues.containsKey(toAddId));
        val toAddUpdate = new AttributeUpdate(toAddId, AttributeUpdateType.None, 1);
        AssertExtensions.assertThrows("Too many attributes were accepted for operation " + opGenerator.getKey(), () -> txn.preProcessOperation(opGenerator.getValue().apply(Collections.singleton(toAddUpdate))), ex -> ex instanceof TooManyAttributesException);
        // Removal+Addition+Replacement: this particular setup should not throw anything.
        val mixedUpdates = Arrays.asList(new AttributeUpdate(toAddId, AttributeUpdateType.None, 1), new AttributeUpdate(toRemoveId, AttributeUpdateType.Replace, SegmentMetadata.NULL_ATTRIBUTE_VALUE), new AttributeUpdate(initialUpdates.get(1).getAttributeId(), AttributeUpdateType.Replace, 10));
        txn.preProcessOperation(opGenerator.getValue().apply(mixedUpdates));
    }
}
Also used : lombok.val(lombok.val) AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) TooManyAttributesException(io.pravega.segmentstore.contracts.TooManyAttributesException) UpdateAttributesOperation(io.pravega.segmentstore.server.logs.operations.UpdateAttributesOperation) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Collection(java.util.Collection) StorageMetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.StorageMetadataCheckpointOperation) Operation(io.pravega.segmentstore.server.logs.operations.Operation) StreamSegmentMapOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentMapOperation) StreamSegmentTruncateOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentTruncateOperation) UpdateAttributesOperation(io.pravega.segmentstore.server.logs.operations.UpdateAttributesOperation) MetadataCheckpointOperation(io.pravega.segmentstore.server.logs.operations.MetadataCheckpointOperation) StorageOperation(io.pravega.segmentstore.server.logs.operations.StorageOperation) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) MergeTransactionOperation(io.pravega.segmentstore.server.logs.operations.MergeTransactionOperation) StreamSegmentSealOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentSealOperation) UpdateableContainerMetadata(io.pravega.segmentstore.server.UpdateableContainerMetadata) StreamSegmentAppendOperation(io.pravega.segmentstore.server.logs.operations.StreamSegmentAppendOperation) UUID(java.util.UUID) Test(org.junit.Test)

Example 5 with AttributeUpdate

use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.

the class ContainerMetadataUpdateTransactionTests method verifyAttributeUpdates.

private void verifyAttributeUpdates(String stepName, ContainerMetadata containerMetadata, Collection<AttributeUpdate> attributeUpdates, Map<UUID, Long> expectedValues) {
    // Verify that the Attribute Updates have their expected values and that the updater has internalized the attribute updates.
    val transactionMetadata = containerMetadata.getStreamSegmentMetadata(SEGMENT_ID);
    val expectedTransactionAttributes = new HashMap<UUID, Long>(expectedValues);
    attributeUpdates.forEach(au -> expectedTransactionAttributes.put(au.getAttributeId(), au.getValue()));
    SegmentMetadataComparer.assertSameAttributes("Unexpected attributes in transaction metadata " + stepName + ".", expectedTransactionAttributes, transactionMetadata);
    for (AttributeUpdate au : attributeUpdates) {
        Assert.assertEquals("Unexpected updated value for AttributeUpdate[" + au.getUpdateType() + "] " + stepName, (long) expectedValues.get(au.getAttributeId()), au.getValue());
    }
}
Also used : lombok.val(lombok.val) AttributeUpdate(io.pravega.segmentstore.contracts.AttributeUpdate) HashMap(java.util.HashMap)

Aggregations

AttributeUpdate (io.pravega.segmentstore.contracts.AttributeUpdate)71 lombok.val (lombok.val)51 AttributeUpdateCollection (io.pravega.segmentstore.contracts.AttributeUpdateCollection)36 ArrayList (java.util.ArrayList)34 HashMap (java.util.HashMap)34 Test (org.junit.Test)32 AttributeId (io.pravega.segmentstore.contracts.AttributeId)31 AttributeUpdateType (io.pravega.segmentstore.contracts.AttributeUpdateType)31 CompletableFuture (java.util.concurrent.CompletableFuture)30 BadAttributeUpdateException (io.pravega.segmentstore.contracts.BadAttributeUpdateException)25 DynamicAttributeUpdate (io.pravega.segmentstore.contracts.DynamicAttributeUpdate)24 StreamSegmentNotExistsException (io.pravega.segmentstore.contracts.StreamSegmentNotExistsException)24 Collection (java.util.Collection)24 Collections (java.util.Collections)24 Map (java.util.Map)24 Attributes (io.pravega.segmentstore.contracts.Attributes)23 Duration (java.time.Duration)23 Exceptions (io.pravega.common.Exceptions)22 Collectors (java.util.stream.Collectors)22 Cleanup (lombok.Cleanup)22