@Override public boolean deleteScope(String scopeName) { NameUtils.validateUserScopeName(scopeName); log.info("Deleting scope: {}", scopeName); return Futures.getThrowingException(controller.deleteScope(scopeName)); }
@Override public boolean createScope(String scopeName) { NameUtils.validateUserScopeName(scopeName); log.info("Creating scope: {}", scopeName); return Futures.getThrowingException(controller.createScope(scopeName)); }
@Override public boolean truncateStream(String scopeName, String streamName, StreamCut streamCut) { NameUtils.validateUserStreamName(streamName); NameUtils.validateUserScopeName(scopeName); Preconditions.checkNotNull(streamCut); log.info("Truncating scope/stream: {}/{} with stream cut: {}", scopeName, streamName, streamCut); return Futures.getThrowingException(controller.truncateStream(scopeName, streamName, streamCut)); }
@Override public boolean sealStream(String scopeName, String streamName) { NameUtils.validateUserStreamName(streamName); NameUtils.validateUserScopeName(scopeName); log.info("Sealing scope/stream: {}/{}", scopeName, streamName); return Futures.getThrowingException(controller.sealStream(scopeName, streamName)); }
@Override public boolean deleteStream(String scopeName, String streamName) { NameUtils.validateUserStreamName(streamName); NameUtils.validateUserScopeName(scopeName); log.info("Deleting scope/stream: {}/{}", scopeName, streamName); return Futures.getThrowingException(controller.deleteStream(scopeName, streamName)); }
@Override public StreamInfo getStreamInfo(String scopeName, String streamName) { NameUtils.validateUserStreamName(streamName); NameUtils.validateUserScopeName(scopeName); log.info("Fetching StreamInfo for scope/stream: {}/{}", scopeName, streamName); return Futures.getThrowingException(getStreamInfo(Stream.of(scopeName, streamName))); }
@Override public ByteStreamWriter createByteStreamWriter(String streamName) { StreamSegments segments = Futures.getThrowingException(controller.getCurrentSegments(scope, streamName)); Preconditions.checkArgument(segments.getSegments().size() == 1, "Stream is configured with more than one segment"); Segment segment = segments.getSegments().iterator().next(); EventWriterConfig config = EventWriterConfig.builder().build(); String delegationToken = segments.getDelegationToken(); return new BufferedByteStreamWriterImpl(new ByteStreamWriterImpl(outputStreamFactory.createOutputStreamForSegment(segment, config, delegationToken), metaStreamFactory.createSegmentMetadataClient(segment, delegationToken))); }
connection = Futures.getThrowingException(getConnection()); } catch (SegmentSealedException | NoSuchSegmentException e) {
@Override public long fetchCurrentSegmentLength() { Exceptions.checkNotClosed(closed.get(), this); val future = RETRY_SCHEDULE.retryingOn(ConnectionFailedException.class) .throwingOn(NoSuchSegmentException.class) .runAsync(() -> getStreamSegmentInfo(delegationToken), connectionFactory.getInternalExecutor()); return Futures.getThrowingException(future).getWriteOffset(); }
@Override public boolean compareAndSetAttribute(SegmentAttribute attribute, long expectedValue, long newValue) { Exceptions.checkNotClosed(closed.get(), this); val future = RETRY_SCHEDULE.retryingOn(ConnectionFailedException.class) .throwingOn(NoSuchSegmentException.class) .runAsync(() -> updatePropertyAsync(attribute.getValue(), expectedValue, newValue, delegationToken), connectionFactory.getInternalExecutor()); return Futures.getThrowingException(future).isSuccess(); }
@Override public long fetchProperty(SegmentAttribute attribute) { Exceptions.checkNotClosed(closed.get(), this); val future = RETRY_SCHEDULE.retryingOn(ConnectionFailedException.class) .throwingOn(NoSuchSegmentException.class) .runAsync(() -> getPropertyAsync(attribute.getValue(), delegationToken), connectionFactory.getInternalExecutor()); return Futures.getThrowingException(future).getValue(); }
/** * @see SegmentOutputStream#flush() */ @Override public void flush() throws SegmentSealedException { int numInflight = state.getNumInflight(); log.debug("Flushing writer: {} with {} inflight events", writerId, numInflight); if (numInflight != 0) { try { ClientConnection connection = Futures.getThrowingException(getConnection()); connection.send(new KeepAlive()); } catch (Exception e) { failConnection(e); } state.waitForInflight(); Exceptions.checkNotClosed(state.isClosed(), this); /* SegmentSealedException is thrown if either of the below conditions are true - resendToSuccessorsCallback has been invoked. - the segment corresponds to an aborted Transaction. */ if (state.needSuccessors.get() || (StreamSegmentNameUtils.isTransactionSegment(segmentName) && state.isAlreadySealed())) { throw new SegmentSealedException(segmentName + " sealed for writer " + writerId); } } }
@Override public boolean createStream(String scopeName, String streamName, StreamConfiguration config) { NameUtils.validateUserStreamName(streamName); NameUtils.validateUserScopeName(scopeName); log.info("Creating scope/stream: {}/{} with configuration: {}", scopeName, streamName, config); return Futures.getThrowingException(controller.createStream(scopeName, streamName, StreamConfiguration.builder() .scalingPolicy(config.getScalingPolicy()) .retentionPolicy(config.getRetentionPolicy()) .build())); }
@Override public boolean updateStream(String scopeName, String streamName, StreamConfiguration config) { NameUtils.validateUserStreamName(streamName); NameUtils.validateUserScopeName(scopeName); log.info("Updating scope/stream: {}/{} with configuration: {}", scopeName, streamName, config); return Futures.getThrowingException(controller.updateStream(scopeName, streamName, StreamConfiguration.builder() .scalingPolicy(config.getScalingPolicy()) .retentionPolicy(config.getRetentionPolicy()) .build())); }
@Override public SegmentInfo getSegmentInfo() { val future = RETRY_SCHEDULE.retryingOn(ConnectionFailedException.class) .throwingOn(NoSuchSegmentException.class) .runAsync(() -> getStreamSegmentInfo(delegationToken), connectionFactory.getInternalExecutor()); StreamSegmentInfo info = Futures.getThrowingException(future); return new SegmentInfo(segmentId, info.getStartOffset(), info.getWriteOffset(), info.isSealed(), info.getLastModified()); }
@Test(timeout = 10000) public void testCloseAbortsRead() throws InterruptedException, ExecutionException { Segment segment = new Segment("scope", "testRetry", 4); PravegaNodeUri endpoint = new PravegaNodeUri("localhost", SERVICE_PORT); MockConnectionFactoryImpl connectionFactory = new MockConnectionFactoryImpl(); MockController controller = new MockController(endpoint.getEndpoint(), endpoint.getPort(), connectionFactory); @Cleanup AsyncSegmentInputStreamImpl in = new AsyncSegmentInputStreamImpl(controller, connectionFactory, segment, ""); ClientConnection c = mock(ClientConnection.class); connectionFactory.provideConnection(endpoint, c); in.getConnection().get(); // Make sure connection is established. CompletableFuture<SegmentRead> read = in.read(1234, 5678); assertFalse(read.isDone()); in.close(); assertThrows(ConnectionClosedException.class, () -> Futures.getThrowingException(read)); verify(c).close(); }
@Test(timeout = 10000) public void testConnectAndFailedSetupAppendDueToTruncation() throws Exception { AtomicBoolean callbackInvoked = new AtomicBoolean(); Consumer<Segment> resendToSuccessorsCallback = segment -> { callbackInvoked.set(true); }; UUID cid = UUID.randomUUID(); PravegaNodeUri uri = new PravegaNodeUri("endpoint", SERVICE_PORT); MockConnectionFactoryImpl cf = new MockConnectionFactoryImpl(); ScheduledExecutorService executor = mock(ScheduledExecutorService.class); implementAsDirectExecutor(executor); // Ensure task submitted to executor is run inline. cf.setExecutor(executor); MockController controller = new MockController(uri.getEndpoint(), uri.getPort(), cf); ClientConnection connection = mock(ClientConnection.class); cf.provideConnection(uri, connection); @Cleanup SegmentOutputStreamImpl output = new SegmentOutputStreamImpl(SEGMENT, controller, cf, cid, resendToSuccessorsCallback, RETRY_SCHEDULE, ""); output.reconnect(); verify(connection).send(new SetupAppend(1, cid, SEGMENT, "")); cf.getProcessor(uri).noSuchSegment(new WireCommands.NoSuchSegment(1, SEGMENT, "SomeException")); CompletableFuture<ClientConnection> connectionFuture = output.getConnection(); assertThrows(NoSuchSegmentException.class, () -> Futures.getThrowingException(connectionFuture)); assertTrue(callbackInvoked.get()); }