use of io.pravega.segmentstore.contracts.StreamSegmentNotExistsException in project pravega by pravega.
the class StreamSegmentContainerTests method checkStorage.
private static void checkStorage(HashMap<String, ByteArrayOutputStream> segmentContents, HashMap<String, Long> lengths, TestContext context) {
for (String segmentName : segmentContents.keySet()) {
// 1. Deletion status
SegmentProperties sp = null;
try {
sp = context.container.getStreamSegmentInfo(segmentName, false, TIMEOUT).join();
} catch (Exception ex) {
if (!(Exceptions.unwrap(ex) instanceof StreamSegmentNotExistsException)) {
throw ex;
}
}
if (sp == null) {
Assert.assertFalse("Segment is marked as deleted in metadata but was not deleted in Storage " + segmentName, context.storage.exists(segmentName, TIMEOUT).join());
// No need to do other checks.
continue;
}
// 2. Seal Status
SegmentProperties storageProps = context.storage.getStreamSegmentInfo(segmentName, TIMEOUT).join();
Assert.assertEquals("Segment seal status disagree between Metadata and Storage for segment " + segmentName, sp.isSealed(), storageProps.isSealed());
// 3. Contents.
long expectedLength = lengths.get(segmentName);
Assert.assertEquals("Unexpected Storage length for segment " + segmentName, expectedLength, storageProps.getLength());
byte[] expectedData = segmentContents.get(segmentName).toByteArray();
byte[] actualData = new byte[expectedData.length];
val readHandle = context.storage.openRead(segmentName).join();
int actualLength = context.storage.read(readHandle, 0, actualData, 0, actualData.length, TIMEOUT).join();
Assert.assertEquals("Unexpected number of bytes read from Storage for segment " + segmentName, expectedLength, actualLength);
Assert.assertArrayEquals("Unexpected data written to storage for segment " + segmentName, expectedData, actualData);
}
}
use of io.pravega.segmentstore.contracts.StreamSegmentNotExistsException in project pravega by pravega.
the class StreamSegmentContainerTests method testSegmentDelete.
/**
* Tests the ability to delete StreamSegments.
*/
@Test
public void testSegmentDelete() throws Exception {
final int appendsPerSegment = 1;
@Cleanup TestContext context = new TestContext();
context.container.startAsync().awaitRunning();
// 1. Create the StreamSegments.
ArrayList<String> segmentNames = createSegments(context);
HashMap<String, ArrayList<String>> transactionsBySegment = createTransactions(segmentNames, context);
// 2. Add some appends.
ArrayList<CompletableFuture<Void>> appendFutures = new ArrayList<>();
for (int i = 0; i < appendsPerSegment; i++) {
for (String segmentName : segmentNames) {
appendFutures.add(context.container.append(segmentName, getAppendData(segmentName, i), null, TIMEOUT));
for (String transactionName : transactionsBySegment.get(segmentName)) {
appendFutures.add(context.container.append(transactionName, getAppendData(transactionName, i), null, TIMEOUT));
}
}
}
Futures.allOf(appendFutures).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
// 3. Delete the first half of the segments.
ArrayList<CompletableFuture<Void>> deleteFutures = new ArrayList<>();
for (int i = 0; i < segmentNames.size() / 2; i++) {
String segmentName = segmentNames.get(i);
deleteFutures.add(context.container.deleteStreamSegment(segmentName, TIMEOUT));
}
Futures.allOf(deleteFutures).get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
// 4. Verify that only the first half of the segments (and their Transactions) were deleted, and not the others.
for (int i = 0; i < segmentNames.size(); i++) {
ArrayList<String> toCheck = new ArrayList<>();
toCheck.add(segmentNames.get(i));
toCheck.addAll(transactionsBySegment.get(segmentNames.get(i)));
boolean expectedDeleted = i < segmentNames.size() / 2;
if (expectedDeleted) {
// Verify the segments and their Transactions are not there anymore.
for (String sn : toCheck) {
AssertExtensions.assertThrows("getStreamSegmentInfo did not throw expected exception when called on a deleted StreamSegment.", context.container.getStreamSegmentInfo(sn, false, TIMEOUT)::join, ex -> ex instanceof StreamSegmentNotExistsException);
AssertExtensions.assertThrows("append did not throw expected exception when called on a deleted StreamSegment.", context.container.append(sn, "foo".getBytes(), null, TIMEOUT)::join, ex -> ex instanceof StreamSegmentNotExistsException);
AssertExtensions.assertThrows("read did not throw expected exception when called on a deleted StreamSegment.", context.container.read(sn, 0, 1, TIMEOUT)::join, ex -> ex instanceof StreamSegmentNotExistsException);
Assert.assertFalse("Segment not deleted in storage.", context.storage.exists(sn, TIMEOUT).join());
}
} else {
// Verify the segments and their Transactions are still there.
for (String sn : toCheck) {
SegmentProperties props = context.container.getStreamSegmentInfo(sn, false, TIMEOUT).join();
Assert.assertFalse("Not-deleted segment (or one of its Transactions) was marked as deleted in metadata.", props.isDeleted());
// Verify we can still append and read from this segment.
context.container.append(sn, "foo".getBytes(), null, TIMEOUT).join();
@Cleanup ReadResult rr = context.container.read(sn, 0, 1, TIMEOUT).join();
// Verify the segment still exists in storage.
context.storage.getStreamSegmentInfo(sn, TIMEOUT).join();
}
}
}
context.container.stopAsync().awaitTerminated();
}
use of io.pravega.segmentstore.contracts.StreamSegmentNotExistsException in project pravega by pravega.
the class StreamSegmentMapperTests method testGetOrAssignStreamSegmentIdWithFailures.
/**
* Tests the ability of the StreamSegmentMapper to generate/return the Id of an existing StreamSegment, when dealing
* with Storage failures (or inexistent StreamSegments).
*/
@Test
public void testGetOrAssignStreamSegmentIdWithFailures() {
final String segmentName = "Segment";
final String transactionName = StreamSegmentNameUtils.getTransactionNameFromId(segmentName, UUID.randomUUID());
HashSet<String> storageSegments = new HashSet<>();
storageSegments.add(segmentName);
storageSegments.add(transactionName);
@Cleanup TestContext context = new TestContext();
setupOperationLog(context);
// 1. Unable to access storage.
context.storage.getInfoHandler = sn -> Futures.failedFuture(new IntentionalException());
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception when the Storage access failed.", () -> context.mapper.getOrAssignStreamSegmentId(segmentName, TIMEOUT), ex -> ex instanceof IntentionalException);
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception when the Storage access failed.", () -> context.mapper.getOrAssignStreamSegmentId(transactionName, TIMEOUT), ex -> ex instanceof IntentionalException);
// 2a. StreamSegmentNotExists (Stand-Alone segment)
setupStorageGetHandler(context, storageSegments, sn -> StreamSegmentInformation.builder().name(sn).build());
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a non-existent stand-alone StreamSegment.", () -> context.mapper.getOrAssignStreamSegmentId(segmentName + "foo", TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
// 2b. Transaction does not exist.
final String inexistentTransactionName = StreamSegmentNameUtils.getTransactionNameFromId(segmentName, UUID.randomUUID());
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a non-existent Transaction.", () -> context.mapper.getOrAssignStreamSegmentId(inexistentTransactionName, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
// 2c. Transaction exists, but not its parent.
final String noValidParentTransactionName = StreamSegmentNameUtils.getTransactionNameFromId("foo", UUID.randomUUID());
storageSegments.add(noValidParentTransactionName);
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a Transaction with an inexistent parent.", () -> context.mapper.getOrAssignStreamSegmentId(noValidParentTransactionName, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
// 2d. Attribute fetch failure.
val testStateStore = new TestStateStore();
val badMapper = new StreamSegmentMapper(context.metadata, context.operationLog, testStateStore, context.noOpMetadataCleanup, context.storage, executorService());
val segmentName2 = segmentName + "2";
val transactionName2 = StreamSegmentNameUtils.getTransactionNameFromId(segmentName2, UUID.randomUUID());
context.storage.getInfoHandler = sn -> CompletableFuture.completedFuture(StreamSegmentInformation.builder().name(sn).build());
testStateStore.getHandler = () -> Futures.failedFuture(new IntentionalException("intentional"));
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a Segment when attributes could not be retrieved.", () -> badMapper.getOrAssignStreamSegmentId(segmentName2, TIMEOUT), ex -> ex instanceof IntentionalException);
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a Transaction when attributes could not be retrieved.", () -> badMapper.getOrAssignStreamSegmentId(transactionName2, TIMEOUT), ex -> ex instanceof IntentionalException);
}
use of io.pravega.segmentstore.contracts.StreamSegmentNotExistsException 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.StreamSegmentNotExistsException in project pravega by pravega.
the class PravegaRequestProcessor method abortTransaction.
@Override
public void abortTransaction(AbortTransaction abortTx) {
long requestId = abortTx.getRequestId();
if (!verifyToken(abortTx.getSegment(), abortTx.getRequestId(), abortTx.getDelegationToken(), READ_UPDATE, "Abort Transaction")) {
return;
}
String transactionName = StreamSegmentNameUtils.getTransactionNameFromId(abortTx.getSegment(), abortTx.getTxid());
log.debug("Aborting transaction {} ", abortTx);
segmentStore.deleteStreamSegment(transactionName, TIMEOUT).thenRun(() -> connection.send(new TransactionAborted(requestId, abortTx.getSegment(), abortTx.getTxid()))).exceptionally(e -> {
if (Exceptions.unwrap(e) instanceof StreamSegmentNotExistsException) {
connection.send(new TransactionAborted(requestId, abortTx.getSegment(), abortTx.getTxid()));
return null;
} else {
return handleException(requestId, transactionName, "Abort transaction", e);
}
});
}
Aggregations