private boolean canRead(CancellationToken cancellationToken) { if (cancellationToken.isCancellationRequested()) { return false; } synchronized (this) { return !this.closed; } }
@Override protected void doStop() { this.stopToken.requestCancellation(); super.doStop(); }
/** * Tests that RequestCancellation cancels futures. */ @Test public void testRequestCancellation() { final int futureCount = 10; CancellationToken token = new CancellationToken(); ArrayList<CompletableFuture<Void>> futures = new ArrayList<>(); Predicate<Integer> isAlreadyCompleted = i -> i % 2 == 0; // Every other future is already completed. for (int i = 0; i < futureCount; i++) { val f = new CompletableFuture<Void>(); if (isAlreadyCompleted.test(i)) { f.complete(null); } futures.add(f); token.register(f); } token.requestCancellation(); for (int i = 0; i < futures.size(); i++) { if (isAlreadyCompleted.test(i)) { Assert.assertTrue("Already completed future was cancelled.", Futures.isSuccessful(futures.get(i))); } else { AssertExtensions.assertThrows( "Future was not cancelled.", futures.get(i)::join, ex -> ex instanceof CancellationException); } } }
/** * Verifies that CancellationToken.NONE has no effect. */ @Test public void testNonCancellableToken() { final int futureCount = 10; CancellationToken token = CancellationToken.NONE; ArrayList<CompletableFuture<Void>> futures = new ArrayList<>(); Predicate<Integer> isAlreadyCompleted = i -> i % 2 == 0; // Every other future is already completed. for (int i = 0; i < futureCount; i++) { val f = new CompletableFuture<Void>(); if (isAlreadyCompleted.test(i)) { f.complete(null); } futures.add(f); token.register(f); } token.requestCancellation(); for (int i = 0; i < futures.size(); i++) { if (isAlreadyCompleted.test(i)) { Assert.assertTrue("Already completed future was cancelled.", Futures.isSuccessful(futures.get(i))); } else { Assert.assertFalse("Non-completed future was completed.", futures.get(i).isDone()); } } } }
/** * Creates a new instance of the MetadataCleaner class. * * @param config Container Configuration to use. * @param metadata An EvictableMetadata to operate on. * @param metadataStore SegmentStateStore to serialize SegmentState in. * @param cleanupCallback A callback to invoke every time cleanup happened. * @param traceObjectId An identifier to use for logging purposes. This will be included at the beginning of all * log calls initiated by this Service. * @param executor The Executor to use for async callbacks and operations. */ MetadataCleaner(@NonNull ContainerConfig config, @NonNull EvictableMetadata metadata, @NonNull MetadataStore metadataStore, @NonNull Consumer<Collection<SegmentMetadata>> cleanupCallback, @NonNull ScheduledExecutorService executor, String traceObjectId) { super(traceObjectId, executor); this.config = config; this.metadata = metadata; this.metadataStore = metadataStore; this.cleanupCallback = cleanupCallback; this.lastIterationSequenceNumber = new AtomicLong(metadata.getOperationSequenceNumber()); this.stopToken = new CancellationToken(); }
private CompletableFuture<Void> delay() { val result = Futures.delayedFuture(this.config.getSegmentMetadataExpiration(), this.executor); this.stopToken.register(result); return result; } }
/** * Creates a new instance of the Consumer class. * * @param streamName The name of the Stream to monitor. * @param config Test Configuration. * @param dataSource Data Source. * @param testState A TestState representing the current state of the test. This will be used for reporting purposes. * @param store A StoreAdapter to execute operations on. * @param executorService The Executor Service to use for async tasks. */ Consumer(String streamName, TestConfig config, ProducerDataSource dataSource, TestState testState, StoreAdapter store, ScheduledExecutorService executorService) { super(config, dataSource, store, executorService); Preconditions.checkArgument(canUseStoreAdapter(store), "StoreAdapter does not support all required features; cannot create a consumer for it."); this.logId = String.format("Consumer[%s]", streamName); this.streamName = Preconditions.checkNotNull(streamName, "streamName"); this.testState = Preconditions.checkNotNull(testState, "testState"); this.reader = store.createReader(); this.catchupReadsSupported = store.isFeatureSupported(StoreAdapter.Feature.RandomRead); this.storageReadsSupported = store.isFeatureSupported(StoreAdapter.Feature.StorageDirect); this.cancellationToken = new CancellationToken(); this.lastSequenceNumbers = new ConcurrentHashMap<>(); this.catchupQueue = new BlockingDrainingQueue<>(); this.storageQueue = new ArrayDeque<>(); this.storageReadQueue = new ArrayDeque<>(); }
private boolean canRun() { synchronized (this.readBuffer) { return !this.cancellationToken.isCancellationRequested() && !this.isClosed; } }
private boolean canRun() { return isRunning() && !this.cancellationToken.isCancellationRequested(); }
@Override protected CompletableFuture<Void> doRun() { return Futures.loop( () -> !this.stopToken.isCancellationRequested(), () -> delay().thenCompose(v -> runOnce()), this.executor); }
/** * Runs in a loop as long as the CancellationToken is not cancelled. Checks, on a periodic basis, if the Segment's * length changed in Storage. If so, it reads the outstanding data and interprets it as an ordered sequence of Events, * which are then passed on via the given event handler. */ CompletableFuture<Void> run() { return Futures.loop( () -> !this.cancellationToken.isCancellationRequested(), () -> SegmentStoreReader.this.storage .getStreamSegmentInfo(segmentName, SegmentStoreReader.this.testConfig.getTimeout()) .thenComposeAsync(this::performRead, SegmentStoreReader.this.executor), SegmentStoreReader.this.executor); }
@Override public boolean processEntry(ReadResultEntry entry) { if (!entry.getContent().isDone()) { // Make sure we only request content if it's not already available. entry.requestContent(getRequestContentTimeout()); } val contents = entry.getContent().join(); this.readLength.addAndGet(contents.getLength()); this.callback.accept(contents.getData(), entry.getStreamSegmentOffset(), contents.getLength()); return !this.cancellationToken.isCancellationRequested(); }