@SneakyThrows private Void attemptReconcile(Throwable ex, String segmentName, Duration timeout) { ex = Exceptions.unwrap(ex); boolean reconciled = false; if (isPossibleEndOfSegment(ex)) { // If we get a Sealed/Merged/NotExists exception, verify that the segment really is in that state. try { SegmentProperties sp = this.streamSegmentStore.getStreamSegmentInfo(segmentName, timeout) .get(timeout.toMillis(), TimeUnit.MILLISECONDS); reconciled = sp.isSealed() || sp.isDeleted(); } catch (Throwable ex2) { reconciled = isPossibleEndOfSegment(Exceptions.unwrap(ex2)); } } if (reconciled) { return null; } else { throw ex; } }
@Override public void getStreamSegmentInfo(GetStreamSegmentInfo getStreamSegmentInfo) { String segmentName = getStreamSegmentInfo.getSegmentName(); final String operation = "getStreamSegmentInfo"; if (!verifyToken(segmentName, getStreamSegmentInfo.getRequestId(), getStreamSegmentInfo.getDelegationToken(), operation)) { return; } segmentStore.getStreamSegmentInfo(segmentName, TIMEOUT) .thenAccept(properties -> { if (properties != null) { StreamSegmentInfo result = new StreamSegmentInfo(getStreamSegmentInfo.getRequestId(), properties.getName(), true, properties.isSealed(), properties.isDeleted(), properties.getLastModified().getTime(), properties.getLength(), properties.getStartOffset()); log.trace("Read stream segment info: {}", result); connection.send(result); } else { log.trace("getStreamSegmentInfo could not find segment {}", segmentName); connection.send(new StreamSegmentInfo(getStreamSegmentInfo.getRequestId(), segmentName, false, true, true, 0, 0, 0)); } }) .exceptionally(e -> handleException(getStreamSegmentInfo.getRequestId(), segmentName, operation, e)); }
protected void assertEquals(String message, SegmentProperties expected, SegmentProperties actual) { Assert.assertEquals(message + " getName() mismatch.", expected.getName(), actual.getName()); Assert.assertEquals(message + " isDeleted() mismatch.", expected.isDeleted(), actual.isDeleted()); Assert.assertEquals(message + " getLength() mismatch.", expected.getLength(), actual.getLength()); Assert.assertEquals(message + " isSealed() mismatch.", expected.isSealed(), actual.isSealed()); Assert.assertEquals(message + " getStartOffset() mismatch.", expected.getStartOffset(), actual.getStartOffset()); }
Assert.assertFalse("Not-deleted segment was marked as deleted in metadata.", props.isDeleted());
/** * Invokes the {@link Connector#getMapSegmentId()} callback in order to assign an Id to a Segment. Upon completion, * this operation will have mapped the given Segment to a new internal Segment Id if none was provided in the given * SegmentInfo. If the given SegmentInfo already has a SegmentId set, then all efforts will be made to map that Segment * with the requested Segment Id. * * @param segmentInfo The SegmentInfo for the StreamSegment to generate and persist. * @param pin If true, this Segment's metadata will be pinned to memory. * @param timeout Timeout for the operation. * @return A CompletableFuture that, when completed, will contain the internal SegmentId that was assigned (or the * one supplied via SegmentInfo, if any). If the operation failed, then this Future will complete with that exception. */ protected CompletableFuture<Long> submitAssignment(SegmentInfo segmentInfo, boolean pin, Duration timeout) { SegmentProperties properties = segmentInfo.getProperties(); if (properties.isDeleted()) { // Stream does not exist. Fail the request with the appropriate exception. failAssignment(properties.getName(), new StreamSegmentNotExistsException("StreamSegment does not exist.")); return Futures.failedFuture(new StreamSegmentNotExistsException(properties.getName())); } long existingSegmentId = this.connector.containerMetadata.getStreamSegmentId(properties.getName(), true); if (isValidSegmentId(existingSegmentId)) { // Looks like someone else beat us to it. completeAssignment(properties.getName(), existingSegmentId); return CompletableFuture.completedFuture(existingSegmentId); } else { return this.connector.getMapSegmentId() .apply(segmentInfo.getSegmentId(), segmentInfo.getProperties(), pin, timeout) .thenApply(id -> completeAssignment(properties.getName(), id)); } }
private void checkActiveSegments(SegmentContainer container, int expectedCount) { val initialActiveSegments = container.getActiveSegments(); int ignoredSegments = 0; for (SegmentProperties sp : initialActiveSegments) { if (sp.getName().equals(EXPECTED_METADATA_SEGMENT_NAME)) { ignoredSegments++; continue; } val expectedSp = container.getStreamSegmentInfo(sp.getName(), TIMEOUT).join(); Assert.assertEquals("Unexpected length (from getActiveSegments) for segment " + sp.getName(), expectedSp.getLength(), sp.getLength()); Assert.assertEquals("Unexpected sealed (from getActiveSegments) for segment " + sp.getName(), expectedSp.isSealed(), sp.isSealed()); Assert.assertEquals("Unexpected deleted (from getActiveSegments) for segment " + sp.getName(), expectedSp.isDeleted(), sp.isDeleted()); SegmentMetadataComparer.assertSameAttributes("Unexpected attributes (from getActiveSegments) for segment " + sp.getName(), expectedSp.getAttributes(), sp); } Assert.assertEquals("Unexpected result from getActiveSegments with freshly created segments.", expectedCount + ignoredSegments, initialActiveSegments.size()); }
Assert.assertEquals("Unexpected length for segment " + segmentName, expectedLength, sp.getLength()); Assert.assertEquals("Unexpected value for isSealed for segment " + segmentName, expectSealed, sp.isSealed()); Assert.assertFalse("Unexpected value for isDeleted for segment " + segmentName, sp.isDeleted());
/** * Creates a new {@link StreamSegmentInformationBuilder} with information already populated from the given SegmentProperties. * * @param base The SegmentProperties to use as a base. * @return The Builder. */ public static StreamSegmentInformationBuilder from(SegmentProperties base) { return StreamSegmentInformation.builder() .name(base.getName()) .startOffset(base.getStartOffset()) .length(base.getLength()) .sealed(base.isSealed()) .deleted(base.isDeleted()) .lastModified(base.getLastModified()) .attributes(base.getAttributes()); }
private StreamSegmentMetadata toMetadata(long segmentId, SegmentProperties sp) { StreamSegmentMetadata sm = new StreamSegmentMetadata(sp.getName(), segmentId, CONTAINER_ID); sm.updateAttributes(sp.getAttributes()); sm.setLength(sp.getLength()); sm.setStartOffset(sp.getStartOffset()); if (sp.isSealed()) { sm.markSealed(); } if (sp.isDeleted()) { sm.markDeleted(); } return sm; }