use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.
the class AppendProcessor method storeAppend.
private CompletableFuture<Void> storeAppend(Append append) {
long lastEventNumber;
synchronized (lock) {
lastEventNumber = latestEventNumbers.get(Pair.of(append.getSegment(), append.getWriterId()));
}
List<AttributeUpdate> attributes = Arrays.asList(new AttributeUpdate(append.getWriterId(), AttributeUpdateType.ReplaceIfEquals, append.getEventNumber(), lastEventNumber), new AttributeUpdate(EVENT_COUNT, AttributeUpdateType.Accumulate, append.getEventCount()));
ByteBuf buf = append.getData().asReadOnly();
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
if (append.isConditional()) {
return store.append(append.getSegment(), append.getExpectedLength(), bytes, attributes, TIMEOUT);
} else {
return store.append(append.getSegment(), bytes, attributes, TIMEOUT);
}
}
use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.
the class PravegaRequestProcessor method updateSegmentAttribute.
@Override
public void updateSegmentAttribute(UpdateSegmentAttribute updateSegmentAttribute) {
long requestId = updateSegmentAttribute.getRequestId();
String segmentName = updateSegmentAttribute.getSegmentName();
UUID attributeId = updateSegmentAttribute.getAttributeId();
long newValue = updateSegmentAttribute.getNewValue();
long expectedValue = updateSegmentAttribute.getExpectedValue();
if (!verifyToken(segmentName, updateSegmentAttribute.getRequestId(), updateSegmentAttribute.getDelegationToken(), READ, "Update Segment Attribute")) {
return;
}
long trace = LoggerHelpers.traceEnter(log, "updateSegmentAttribute", updateSegmentAttribute);
val update = new AttributeUpdate(attributeId, AttributeUpdateType.ReplaceIfEquals, newValue, expectedValue);
segmentStore.updateAttributes(segmentName, Collections.singletonList(update), TIMEOUT).whenComplete((v, e) -> {
LoggerHelpers.traceLeave(log, "updateSegmentAttribute", trace, e);
if (e == null) {
connection.send(new SegmentAttributeUpdated(requestId, true));
} else {
if (Exceptions.unwrap(e) instanceof BadAttributeUpdateException) {
log.debug("Updating segment attribute {} failed due to: {}", update, e.getMessage());
connection.send(new SegmentAttributeUpdated(requestId, false));
} else {
handleException(requestId, segmentName, "Update attribute", e);
}
}
}).exceptionally(e -> handleException(requestId, segmentName, "Update attribute", e));
}
use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.
the class SegmentMetadataUpdateTransaction method preProcessAttributes.
/**
* Pre-processes a collection of attributes.
* After this method returns, all AttributeUpdates in the given collection will have the actual (and updated) value
* of that attribute in the Segment.
*
* @param attributeUpdates The Updates to process (if any).
* @throws BadAttributeUpdateException If any of the given AttributeUpdates is invalid given the current state of
* the segment.
* @throws TooManyAttributesException If, as a result of applying the given updates, the Segment would exceed the
* maximum allowed number of Attributes.
*/
private void preProcessAttributes(Collection<AttributeUpdate> attributeUpdates) throws BadAttributeUpdateException, TooManyAttributesException {
if (attributeUpdates == null) {
return;
}
int newAttributeCount = this.attributeValues.size();
for (AttributeUpdate u : attributeUpdates) {
AttributeUpdateType updateType = u.getUpdateType();
long previousValue = this.attributeValues.getOrDefault(u.getAttributeId(), SegmentMetadata.NULL_ATTRIBUTE_VALUE);
// Perform validation, and set the AttributeUpdate.value to the updated value, if necessary.
switch(updateType) {
case ReplaceIfGreater:
// Verify value against existing value, if any.
boolean hasValue = previousValue != SegmentMetadata.NULL_ATTRIBUTE_VALUE;
if (hasValue && u.getValue() <= previousValue) {
throw new BadAttributeUpdateException(this.name, u, String.format("Expected greater than '%s'.", previousValue));
}
break;
case ReplaceIfEquals:
// Verify value against existing value, if any.
if (u.getComparisonValue() != previousValue) {
throw new BadAttributeUpdateException(this.name, u, String.format("Expected existing value to be '%s', actual '%s'.", u.getComparisonValue(), previousValue));
}
break;
case None:
// Verify value is not already set.
if (previousValue != SegmentMetadata.NULL_ATTRIBUTE_VALUE) {
throw new BadAttributeUpdateException(this.name, u, String.format("Attribute value already set (%s).", previousValue));
}
break;
case Accumulate:
if (previousValue != SegmentMetadata.NULL_ATTRIBUTE_VALUE) {
u.setValue(previousValue + u.getValue());
}
break;
case Replace:
break;
default:
throw new BadAttributeUpdateException(this.name, u, "Unexpected update type: " + updateType);
}
if (previousValue == SegmentMetadata.NULL_ATTRIBUTE_VALUE && u.getValue() != SegmentMetadata.NULL_ATTRIBUTE_VALUE) {
// This attribute did not exist and is about to be added.
newAttributeCount++;
} else if (previousValue != SegmentMetadata.NULL_ATTRIBUTE_VALUE && u.getValue() == SegmentMetadata.NULL_ATTRIBUTE_VALUE) {
// This attribute existed and is about to be removed.
newAttributeCount--;
}
}
if (newAttributeCount > SegmentMetadata.MAXIMUM_ATTRIBUTE_COUNT && newAttributeCount > this.attributeValues.size()) {
// attributes of existing segments, but not increase their count.
throw new TooManyAttributesException(this.name, SegmentMetadata.MAXIMUM_ATTRIBUTE_COUNT);
}
}
use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.
the class SegmentStateMapperTests method testGetSegmentInfoFromStorage.
/**
* Tests the ability to retrieve Segment Info from Storage (base info and its State).
*/
@Test
public void testGetSegmentInfoFromStorage() {
final UUID attributeId = UUID.randomUUID();
@Cleanup val s = createStorage();
val stateStore = new InMemoryStateStore();
val m = new SegmentStateMapper(stateStore, s);
// Save some state.
val info = s.create("s", TIMEOUT).thenCompose(si -> s.openWrite(si.getName())).thenCompose(handle -> s.write(handle, 0, new ByteArrayInputStream(new byte[10]), 10, TIMEOUT).thenCompose(v -> s.seal(handle, TIMEOUT)).thenCompose(v -> s.getStreamSegmentInfo(handle.getSegmentName(), TIMEOUT))).join();
val expectedInfo = StreamSegmentInformation.from(info).startOffset(info.getLength() / 2).build();
val attributes = Collections.singleton(new AttributeUpdate(attributeId, AttributeUpdateType.Replace, 100L));
val expectedAttributes = Collections.singletonMap(attributeId, 100L);
m.saveState(expectedInfo, attributes, TIMEOUT).join();
// Retrieve the state and verify it.
val actual = m.getSegmentInfoFromStorage(expectedInfo.getName(), TIMEOUT).join();
Assert.assertEquals("Unexpected Name.", expectedInfo.getName(), actual.getName());
Assert.assertEquals("Unexpected Length.", expectedInfo.getLength(), actual.getLength());
Assert.assertEquals("Unexpected Sealed status.", expectedInfo.isSealed(), actual.isSealed());
Assert.assertEquals("Unexpected Start Offset.", expectedInfo.getStartOffset(), actual.getStartOffset());
AssertExtensions.assertMapEquals("Unexpected Attributes.", expectedAttributes, actual.getAttributes());
}
use of io.pravega.segmentstore.contracts.AttributeUpdate in project pravega by pravega.
the class SegmentStateMapperTests method testStateOperations.
/**
* Tests the ability to Save and later retrieve a State from the State Store.
*/
@Test
public void testStateOperations() {
final UUID attributeId = UUID.randomUUID();
@Cleanup val s = createStorage();
val stateStore = new InMemoryStateStore();
val m = new SegmentStateMapper(stateStore, s);
// Save some state.
val sp = StreamSegmentInformation.builder().name("s").length(10).startOffset(4).sealed(true).build();
val attributes = Collections.singleton(new AttributeUpdate(attributeId, AttributeUpdateType.Replace, 100L));
val expectedAttributes = Collections.singletonMap(attributeId, 100L);
m.saveState(sp, attributes, TIMEOUT).join();
// Get raw state.
val state = m.getState(sp.getName(), TIMEOUT).join();
Assert.assertEquals("Unexpected SegmentName.", sp.getName(), state.getSegmentName());
Assert.assertEquals("Unexpected StartOffset.", sp.getStartOffset(), state.getStartOffset());
AssertExtensions.assertMapEquals("Unexpected Attributes.", expectedAttributes, state.getAttributes());
// Combine a state with raw properties.
val rawSp = StreamSegmentInformation.builder().name(sp.getName()).length(10).startOffset(0).sealed(true).build();
val si = m.attachState(rawSp, TIMEOUT).join();
Assert.assertEquals("Unexpected StartOffset.", sp.getStartOffset(), si.getProperties().getStartOffset());
AssertExtensions.assertMapEquals("Unexpected Attributes.", expectedAttributes, si.getProperties().getAttributes());
}
Aggregations