/** * Block until all events are acked by the server. */ private void waitForInflight() { Exceptions.handleInterrupted(() -> waitingInflight.await()); }
@Override @SneakyThrows(Exception.class) public void close() { ReusableLatch waitSignal = null; synchronized (this.stateLock) { if (this.closed) { return; } this.closed = true; if (this.activeCount != 0 || !this.pendingItems.isEmpty()) { // Setup a latch that will be released when the last item completes. this.emptyNotifier = new ReusableLatch(false); waitSignal = this.emptyNotifier; } } if (waitSignal != null) { // We have unfinished items. Wait for them. waitSignal.await(CLOSE_TIMEOUT_MILLIS); } }
@Override public void flush() throws SegmentSealedException { //flushLatch is used to simulate a blocking Flush(). . Exceptions.handleInterrupted(() -> flushLatch.await()); throw new SegmentSealedException(segment.toString()); }
@Test public void endOfStreamNotifierTest() throws Exception { AtomicBoolean listenerInvoked = new AtomicBoolean(); ReusableLatch latch = new ReusableLatch(); when(state.isEndOfData()).thenReturn(false).thenReturn(true); when(sync.getState()).thenReturn(state); Listener<EndOfDataNotification> listener1 = notification -> { log.info("listener 1 invoked"); listenerInvoked.set(true); latch.release(); }; Listener<EndOfDataNotification> listener2 = notification -> { }; EndOfDataNotifier notifier = new EndOfDataNotifier(system, sync, executor); notifier.registerListener(listener1); verify(executor, times(1)).scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(), any(TimeUnit.class)); latch.await(); verify(state, times(2)).isEndOfData(); assertTrue(listenerInvoked.get()); notifier.registerListener(listener2); verify(executor, times(1)).scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(), any(TimeUnit.class)); notifier.unregisterAllListeners(); verify(system, times(1)).removeListeners(EndOfDataNotification.class.getSimpleName()); }
Exceptions.handleInterrupted(() -> waitOn.get(joiner.apply(operation, segment)).await()); return null; }); futures.add(s.create(segment1, TIMEOUT)); futures.add(s.create(segment2, TIMEOUT)); invoked.get(createSegment1Key).await(LOCK_TIMEOUT_MILLIS); invoked.get(createSegment2Key).await(LOCK_TIMEOUT_MILLIS); Assert.assertEquals("Unexpected number of active segments.", 2, s.getSegmentWithOngoingOperationsCount()); AssertExtensions.assertThrows( "Concat was invoked while the at least one of the creates was running.", () -> invoked.get(concatKey).await(LOCK_TIMEOUT_MILLIS), ex -> ex instanceof TimeoutException); invoked.get(concatKey).await(TIMEOUT_MILLIS); AssertExtensions.assertThrows( "Write(target) was invoked while concat was running", () -> invoked.get(writeSegment1Key).await(LOCK_TIMEOUT_MILLIS), ex -> ex instanceof TimeoutException); () -> invoked.get(writeSegment2Key).await(LOCK_TIMEOUT_MILLIS), ex -> ex instanceof TimeoutException); Assert.assertEquals("Unexpected number of active segments.", 2, s.getSegmentWithOngoingOperationsCount()); invoked.get(writeSegment1Key).await(LOCK_TIMEOUT_MILLIS); invoked.get(writeSegment2Key).await(LOCK_TIMEOUT_MILLIS); waitOn.get(writeSegment1Key).release();
Exceptions.handleInterrupted(() -> waitOn.get(segment).await()); return null; }); invoked.get(segment1).await(LOCK_TIMEOUT_MILLIS); Assert.assertEquals("Unexpected number of active segments.", 1, s.getSegmentWithOngoingOperationsCount()); invoked.get(segment2).await(LOCK_TIMEOUT_MILLIS); Assert.assertEquals("Unexpected number of active segments.", 2, s.getSegmentWithOngoingOperationsCount());
Exceptions.handleInterrupted(() -> waitOn.get(operation).await()); return null; }); invoked.get(op1).await(LOCK_TIMEOUT_MILLIS); Assert.assertEquals("Unexpected number of active segments.", 1, s.getSegmentWithOngoingOperationsCount()); AssertExtensions.assertThrows( "Second operation was invoked while the first one was still running.", () -> invoked.get(op2).await(LOCK_TIMEOUT_MILLIS), ex -> ex instanceof TimeoutException); invoked.get(op2).await(LOCK_TIMEOUT_MILLIS); Assert.assertEquals("Unexpected number of active segments.", 1, s.getSegmentWithOngoingOperationsCount()); waitOn.get(op2).release();
completeFirstDataAppendedAck.await(); // wait, simulating a hung/delayed dataAppended acknowledgement. return null; }).doAnswer( invocation -> { firstStoreAppendInvoked.await(); verify(store).append(streamSegmentName, data, updateEventNumber(clientId, 100, Attributes .NULL_ATTRIBUTE_VALUE, eventCount), AppendProcessor.TIMEOUT); AppendProcessor.TIMEOUT)).thenReturn(result); secondStoreAppendInvoked.await(); // wait until the next store append is invoked.
final Consumer<Segment> segmentSealedCallback = segment -> Exceptions.handleInterrupted(() -> latch.await());
assertNull(event3.getEvent()); listenerLatch.await(); assertTrue("Listener invoked", listenerInvoked.get());