use of io.pravega.segmentstore.contracts.StreamSegmentExistsException in project pravega by pravega.
the class StreamSegmentMapperTests method testCreateTransactionAlreadyExists.
/**
* Tests the ability of the StreamSegmentMapper to create a new Transaction if the Transaction already exists (partially
* or fully).
*/
@Test
public void testCreateTransactionAlreadyExists() {
final String parentSegmentName = "NewSegment";
final UUID txnId = UUID.randomUUID();
final String txnName = StreamSegmentNameUtils.getTransactionNameFromId(parentSegmentName, txnId);
testCreateAlreadyExists(txnName, (mapper, attributes) -> mapper.createNewStreamSegment(parentSegmentName, null, TIMEOUT).exceptionally(ex -> {
if (Exceptions.unwrap(ex) instanceof StreamSegmentExistsException) {
return null;
}
throw new CompletionException(ex);
}).thenCompose(v -> mapper.createNewTransactionStreamSegment(parentSegmentName, txnId, attributes, TIMEOUT)));
}
use of io.pravega.segmentstore.contracts.StreamSegmentExistsException 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());
}
use of io.pravega.segmentstore.contracts.StreamSegmentExistsException in project pravega by pravega.
the class AppendProcessor method handleException.
private void handleException(UUID writerId, long requestId, String segment, String doingWhat, Throwable u) {
if (u == null) {
IllegalStateException exception = new IllegalStateException("No exception to handle.");
log.error("Append processor: Error {} on segment = '{}'", doingWhat, segment, exception);
throw exception;
}
u = Exceptions.unwrap(u);
if (u instanceof StreamSegmentExistsException) {
log.warn("Segment '{}' already exists and {} cannot perform operation '{}'.", segment, writerId, doingWhat);
connection.send(new SegmentAlreadyExists(requestId, segment));
} else if (u instanceof StreamSegmentNotExistsException) {
log.warn("Segment '{}' does not exist and {} cannot perform operation '{}'.", segment, writerId, doingWhat);
connection.send(new NoSuchSegment(requestId, segment));
} else if (u instanceof StreamSegmentSealedException) {
log.info("Segment '{}' is sealed and {} cannot perform operation '{}'.", segment, writerId, doingWhat);
connection.send(new SegmentIsSealed(requestId, segment));
} else if (u instanceof ContainerNotFoundException) {
int containerId = ((ContainerNotFoundException) u).getContainerId();
log.warn("Wrong host. Segment '{}' (Container {}) is not owned and {} cannot perform operation '{}'.", segment, containerId, writerId, doingWhat);
connection.send(new WrongHost(requestId, segment, ""));
} else if (u instanceof BadAttributeUpdateException) {
log.warn("Bad attribute update by {} on segment {}.", writerId, segment, u);
connection.send(new InvalidEventNumber(writerId, requestId));
connection.close();
} else if (u instanceof TooManyAttributesException) {
log.warn("Attribute limit would be exceeded by {} on segment {}.", writerId, segment, u);
connection.send(new InvalidEventNumber(writerId, requestId));
connection.close();
} else if (u instanceof AuthenticationException) {
log.warn("Token check failed while being written by {} on segment {}.", writerId, segment, u);
connection.send(new WireCommands.AuthTokenCheckFailed(requestId));
connection.close();
} else if (u instanceof UnsupportedOperationException) {
log.warn("Unsupported Operation '{}'.", doingWhat, u);
connection.send(new OperationUnsupported(requestId, doingWhat));
} else {
log.error("Error (Segment = '{}', Operation = 'append')", segment, u);
// Closing connection should reinitialize things, and hopefully fix the problem
connection.close();
}
}
use of io.pravega.segmentstore.contracts.StreamSegmentExistsException in project pravega by pravega.
the class StreamSegmentMapper method createNewStreamSegment.
// endregion
// region Create Segments
/**
* Creates a new StreamSegment with given name (in Storage) and persists the given attributes (in Storage).
*
* @param streamSegmentName The case-sensitive StreamSegment Name.
* @param attributes The initial attributes for the StreamSegment, if any.
* @param timeout Timeout for the operation.
* @return A CompletableFuture that, when completed normally, will indicate the operation completed normally.
* If the operation failed, this will contain the exception that caused the failure.
*/
public CompletableFuture<Void> createNewStreamSegment(String streamSegmentName, Collection<AttributeUpdate> attributes, Duration timeout) {
long traceId = LoggerHelpers.traceEnterWithContext(log, traceObjectId, "createNewStreamSegment", streamSegmentName);
long segmentId = this.containerMetadata.getStreamSegmentId(streamSegmentName, true);
if (isValidStreamSegmentId(segmentId)) {
// Quick fail: see if this is an active Segment, and if so, don't bother with anything else.
return Futures.failedFuture(new StreamSegmentExistsException(streamSegmentName));
}
CompletableFuture<Void> result = createSegmentInStorageWithRecovery(streamSegmentName, attributes, new TimeoutTimer(timeout));
if (log.isTraceEnabled()) {
result.thenAccept(v -> LoggerHelpers.traceLeave(log, traceObjectId, "createNewStreamSegment", traceId, streamSegmentName));
}
return result;
}
use of io.pravega.segmentstore.contracts.StreamSegmentExistsException in project pravega by pravega.
the class ClientAdapterBase method createStream.
@Override
public CompletableFuture<Void> createStream(String streamName, Duration timeout) {
ensureRunning();
return CompletableFuture.runAsync(() -> {
if (this.streamWriters.containsKey(streamName)) {
throw new CompletionException(new StreamSegmentExistsException(streamName));
}
StreamConfiguration config = StreamConfiguration.builder().streamName(streamName).scalingPolicy(ScalingPolicy.fixed(this.testConfig.getSegmentsPerStream())).scope(SCOPE).build();
if (!getStreamManager().createStream(SCOPE, streamName, config)) {
throw new CompletionException(new StreamingException(String.format("Unable to create Stream '%s'.", streamName)));
}
int writerCount = Math.max(1, this.testConfig.getProducerCount() / this.testConfig.getStreamCount());
List<EventStreamWriter<byte[]>> writers = new ArrayList<>(writerCount);
if (this.streamWriters.putIfAbsent(streamName, writers) == null) {
for (int i = 0; i < writerCount; i++) {
writers.add(getClientFactory().createEventWriter(streamName, SERIALIZER, WRITER_CONFIG));
}
}
}, this.testExecutor);
}
Aggregations