use of org.apache.flink.core.testutils.OneShotLatch in project flink by apache.
the class StreamTaskTest method testEmptySubtaskStateLeadsToStatelessAcknowledgment.
/**
* FLINK-5985
*
* This test ensures that empty snapshots (no op/keyed stated whatsoever) will be reported as stateless tasks. This
* happens by translating an empty {@link SubtaskState} into reporting 'null' to #acknowledgeCheckpoint.
*/
@Test
public void testEmptySubtaskStateLeadsToStatelessAcknowledgment() throws Exception {
final long checkpointId = 42L;
final long timestamp = 1L;
TaskInfo mockTaskInfo = mock(TaskInfo.class);
when(mockTaskInfo.getTaskNameWithSubtasks()).thenReturn("foobar");
when(mockTaskInfo.getIndexOfThisSubtask()).thenReturn(0);
Environment mockEnvironment = mock(Environment.class);
// latch blocks until the async checkpoint thread acknowledges
final OneShotLatch checkpointCompletedLatch = new OneShotLatch();
final List<SubtaskState> checkpointResult = new ArrayList<>(1);
// we remember what is acknowledged (expected to be null as our task will snapshot empty states).
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
SubtaskState subtaskState = invocationOnMock.getArgumentAt(2, SubtaskState.class);
checkpointResult.add(subtaskState);
checkpointCompletedLatch.trigger();
return null;
}
}).when(mockEnvironment).acknowledgeCheckpoint(anyLong(), any(CheckpointMetrics.class), any(SubtaskState.class));
when(mockEnvironment.getTaskInfo()).thenReturn(mockTaskInfo);
StreamTask<?, AbstractStreamOperator<?>> streamTask = mock(StreamTask.class, Mockito.CALLS_REAL_METHODS);
CheckpointMetaData checkpointMetaData = new CheckpointMetaData(checkpointId, timestamp);
streamTask.setEnvironment(mockEnvironment);
// mock the operators
StreamOperator<?> statelessOperator = mock(StreamOperator.class, withSettings().extraInterfaces(StreamCheckpointedOperator.class));
// mock the returned empty snapshot result (all state handles are null)
OperatorSnapshotResult statelessOperatorSnapshotResult = new OperatorSnapshotResult();
when(statelessOperator.snapshotState(anyLong(), anyLong(), any(CheckpointOptions.class))).thenReturn(statelessOperatorSnapshotResult);
// set up the task
StreamOperator<?>[] streamOperators = { statelessOperator };
OperatorChain<Void, AbstractStreamOperator<Void>> operatorChain = mock(OperatorChain.class);
when(operatorChain.getAllOperators()).thenReturn(streamOperators);
Whitebox.setInternalState(streamTask, "isRunning", true);
Whitebox.setInternalState(streamTask, "lock", new Object());
Whitebox.setInternalState(streamTask, "operatorChain", operatorChain);
Whitebox.setInternalState(streamTask, "cancelables", new CloseableRegistry());
Whitebox.setInternalState(streamTask, "configuration", new StreamConfig(new Configuration()));
Whitebox.setInternalState(streamTask, "asyncOperationsThreadPool", Executors.newCachedThreadPool());
streamTask.triggerCheckpoint(checkpointMetaData, CheckpointOptions.forFullCheckpoint());
checkpointCompletedLatch.await(30, TimeUnit.SECONDS);
streamTask.cancel();
// ensure that 'null' was acknowledged as subtask state
Assert.assertNull(checkpointResult.get(0));
}
use of org.apache.flink.core.testutils.OneShotLatch in project flink by apache.
the class StreamTaskTest method testAsyncCheckpointingConcurrentCloseAfterAcknowledge.
/**
* FLINK-5667
*
* Tests that a concurrent cancel operation does not discard the state handles of an
* acknowledged checkpoint. The situation can only happen if the cancel call is executed
* after Environment.acknowledgeCheckpoint() and before the
* CloseableRegistry.unregisterClosable() call.
*/
@Test
public void testAsyncCheckpointingConcurrentCloseAfterAcknowledge() throws Exception {
final long checkpointId = 42L;
final long timestamp = 1L;
final OneShotLatch acknowledgeCheckpointLatch = new OneShotLatch();
final OneShotLatch completeAcknowledge = new OneShotLatch();
TaskInfo mockTaskInfo = mock(TaskInfo.class);
when(mockTaskInfo.getTaskNameWithSubtasks()).thenReturn("foobar");
when(mockTaskInfo.getIndexOfThisSubtask()).thenReturn(0);
Environment mockEnvironment = mock(Environment.class);
when(mockEnvironment.getTaskInfo()).thenReturn(mockTaskInfo);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
acknowledgeCheckpointLatch.trigger();
// block here so that we can issue the concurrent cancel call
completeAcknowledge.await();
return null;
}
}).when(mockEnvironment).acknowledgeCheckpoint(anyLong(), any(CheckpointMetrics.class), any(SubtaskState.class));
StreamTask<?, AbstractStreamOperator<?>> streamTask = mock(StreamTask.class, Mockito.CALLS_REAL_METHODS);
CheckpointMetaData checkpointMetaData = new CheckpointMetaData(checkpointId, timestamp);
streamTask.setEnvironment(mockEnvironment);
StreamOperator<?> streamOperator = mock(StreamOperator.class, withSettings().extraInterfaces(StreamCheckpointedOperator.class));
KeyGroupsStateHandle managedKeyedStateHandle = mock(KeyGroupsStateHandle.class);
KeyGroupsStateHandle rawKeyedStateHandle = mock(KeyGroupsStateHandle.class);
OperatorStateHandle managedOperatorStateHandle = mock(OperatorStateHandle.class);
OperatorStateHandle rawOperatorStateHandle = mock(OperatorStateHandle.class);
OperatorSnapshotResult operatorSnapshotResult = new OperatorSnapshotResult(new DoneFuture<>(managedKeyedStateHandle), new DoneFuture<>(rawKeyedStateHandle), new DoneFuture<>(managedOperatorStateHandle), new DoneFuture<>(rawOperatorStateHandle));
when(streamOperator.snapshotState(anyLong(), anyLong(), any(CheckpointOptions.class))).thenReturn(operatorSnapshotResult);
StreamOperator<?>[] streamOperators = { streamOperator };
OperatorChain<Void, AbstractStreamOperator<Void>> operatorChain = mock(OperatorChain.class);
when(operatorChain.getAllOperators()).thenReturn(streamOperators);
StreamStateHandle streamStateHandle = mock(StreamStateHandle.class);
CheckpointStreamFactory.CheckpointStateOutputStream outStream = mock(CheckpointStreamFactory.CheckpointStateOutputStream.class);
when(outStream.closeAndGetHandle()).thenReturn(streamStateHandle);
CheckpointStreamFactory mockStreamFactory = mock(CheckpointStreamFactory.class);
when(mockStreamFactory.createCheckpointStateOutputStream(anyLong(), anyLong())).thenReturn(outStream);
AbstractStateBackend mockStateBackend = mock(AbstractStateBackend.class);
when(mockStateBackend.createStreamFactory(any(JobID.class), anyString())).thenReturn(mockStreamFactory);
Whitebox.setInternalState(streamTask, "isRunning", true);
Whitebox.setInternalState(streamTask, "lock", new Object());
Whitebox.setInternalState(streamTask, "operatorChain", operatorChain);
Whitebox.setInternalState(streamTask, "cancelables", new CloseableRegistry());
Whitebox.setInternalState(streamTask, "asyncOperationsThreadPool", Executors.newFixedThreadPool(1));
Whitebox.setInternalState(streamTask, "configuration", new StreamConfig(new Configuration()));
Whitebox.setInternalState(streamTask, "stateBackend", mockStateBackend);
streamTask.triggerCheckpoint(checkpointMetaData, CheckpointOptions.forFullCheckpoint());
acknowledgeCheckpointLatch.await();
ArgumentCaptor<SubtaskState> subtaskStateCaptor = ArgumentCaptor.forClass(SubtaskState.class);
// check that the checkpoint has been completed
verify(mockEnvironment).acknowledgeCheckpoint(eq(checkpointId), any(CheckpointMetrics.class), subtaskStateCaptor.capture());
SubtaskState subtaskState = subtaskStateCaptor.getValue();
// check that the subtask state contains the expected state handles
assertEquals(managedKeyedStateHandle, subtaskState.getManagedKeyedState());
assertEquals(rawKeyedStateHandle, subtaskState.getRawKeyedState());
assertEquals(new ChainedStateHandle<>(Collections.singletonList(managedOperatorStateHandle)), subtaskState.getManagedOperatorState());
assertEquals(new ChainedStateHandle<>(Collections.singletonList(rawOperatorStateHandle)), subtaskState.getRawOperatorState());
// check that the state handles have not been discarded
verify(managedKeyedStateHandle, never()).discardState();
verify(rawKeyedStateHandle, never()).discardState();
verify(managedOperatorStateHandle, never()).discardState();
verify(rawOperatorStateHandle, never()).discardState();
streamTask.cancel();
completeAcknowledge.trigger();
// canceling the stream task after it has acknowledged the checkpoint should not discard
// the state handles
verify(managedKeyedStateHandle, never()).discardState();
verify(rawKeyedStateHandle, never()).discardState();
verify(managedOperatorStateHandle, never()).discardState();
verify(rawOperatorStateHandle, never()).discardState();
}
use of org.apache.flink.core.testutils.OneShotLatch in project flink by apache.
the class SystemProcessingTimeServiceTest method testQuiescing.
@Test
public void testQuiescing() throws Exception {
final Object lock = new Object();
final AtomicReference<Throwable> errorRef = new AtomicReference<>();
final SystemProcessingTimeService timer = new SystemProcessingTimeService(new ReferenceSettingExceptionHandler(errorRef), lock);
try {
final OneShotLatch latch = new OneShotLatch();
final ReentrantLock scopeLock = new ReentrantLock();
timer.registerTimer(System.currentTimeMillis() + 20, new ProcessingTimeCallback() {
@Override
public void onProcessingTime(long timestamp) throws Exception {
scopeLock.lock();
try {
latch.trigger();
// delay a bit before leaving the method
Thread.sleep(5);
} finally {
scopeLock.unlock();
}
}
});
// after the task triggered, shut the timer down cleanly, waiting for the task to finish
latch.await();
timer.quiesceAndAwaitPending();
// should be able to immediately acquire the lock, since the task must have exited by now
assertTrue(scopeLock.tryLock());
// should be able to schedule more tasks (that never get executed)
ScheduledFuture<?> future = timer.registerTimer(System.currentTimeMillis() - 5, new ProcessingTimeCallback() {
@Override
public void onProcessingTime(long timestamp) throws Exception {
throw new Exception("test");
}
});
assertNotNull(future);
// nothing should be scheduled right now
assertEquals(0, timer.getNumTasksScheduled());
// triggerable did, in fact, not trigger
if (errorRef.get() != null) {
throw new Exception(errorRef.get());
}
} finally {
timer.shutdownService();
}
}
Aggregations