use of org.apache.flink.runtime.jobmanager.slots.SlotOwner in project flink by apache.
the class ExecutionGraphUtilsTest method testReleaseSlots.
@Test
public void testReleaseSlots() {
final JobID jid = new JobID();
final SlotOwner owner = mock(SlotOwner.class);
final SimpleSlot slot1 = new SimpleSlot(createAllocatedSlot(jid, 0), owner, 0);
final SimpleSlot slot2 = new SimpleSlot(createAllocatedSlot(jid, 1), owner, 1);
final SimpleSlot slot3 = new SimpleSlot(createAllocatedSlot(jid, 2), owner, 2);
final FlinkCompletableFuture<SimpleSlot> incompleteFuture = new FlinkCompletableFuture<>();
final FlinkCompletableFuture<SimpleSlot> completeFuture = new FlinkCompletableFuture<>();
completeFuture.complete(slot2);
final FlinkCompletableFuture<SimpleSlot> disposedSlotFuture = new FlinkCompletableFuture<>();
slot3.releaseSlot();
disposedSlotFuture.complete(slot3);
// release all futures
ExecutionGraphUtils.releaseSlotFuture(incompleteFuture);
ExecutionGraphUtils.releaseSlotFuture(completeFuture);
ExecutionGraphUtils.releaseSlotFuture(disposedSlotFuture);
// only now complete the incomplete future
incompleteFuture.complete(slot1);
// verify that each slot was returned once to the owner
verify(owner, times(1)).returnAllocatedSlot(eq(slot1));
verify(owner, times(1)).returnAllocatedSlot(eq(slot2));
verify(owner, times(1)).returnAllocatedSlot(eq(slot3));
}
use of org.apache.flink.runtime.jobmanager.slots.SlotOwner in project flink by apache.
the class ExecutionGraphUtilsTest method testReleaseSlotsWithNulls.
@Test
public void testReleaseSlotsWithNulls() {
final JobID jid = new JobID();
final SlotOwner owner = mock(SlotOwner.class);
final Execution mockExecution = mock(Execution.class);
final SimpleSlot slot1 = new SimpleSlot(createAllocatedSlot(jid, 0), owner, 0);
final SimpleSlot slot2 = new SimpleSlot(createAllocatedSlot(jid, 1), owner, 1);
final SimpleSlot slot3 = new SimpleSlot(createAllocatedSlot(jid, 2), owner, 2);
final SimpleSlot slot4 = new SimpleSlot(createAllocatedSlot(jid, 3), owner, 3);
final SimpleSlot slot5 = new SimpleSlot(createAllocatedSlot(jid, 4), owner, 4);
ExecutionAndSlot[] slots1 = new ExecutionAndSlot[] { null, new ExecutionAndSlot(mockExecution, FlinkCompletableFuture.completed(slot1)), null, new ExecutionAndSlot(mockExecution, FlinkCompletableFuture.completed(slot2)), null };
ExecutionAndSlot[] slots2 = new ExecutionAndSlot[] { new ExecutionAndSlot(mockExecution, FlinkCompletableFuture.completed(slot3)), new ExecutionAndSlot(mockExecution, FlinkCompletableFuture.completed(slot4)), new ExecutionAndSlot(mockExecution, FlinkCompletableFuture.completed(slot5)) };
List<ExecutionAndSlot[]> resources = Arrays.asList(null, slots1, new ExecutionAndSlot[0], null, slots2);
ExecutionGraphUtils.releaseAllSlotsSilently(resources);
verify(owner, times(1)).returnAllocatedSlot(eq(slot1));
verify(owner, times(1)).returnAllocatedSlot(eq(slot2));
verify(owner, times(1)).returnAllocatedSlot(eq(slot3));
verify(owner, times(1)).returnAllocatedSlot(eq(slot4));
verify(owner, times(1)).returnAllocatedSlot(eq(slot5));
}
use of org.apache.flink.runtime.jobmanager.slots.SlotOwner in project flink by apache.
the class ExecutionGraphSchedulingTest method testExecutionJobVertexAllocateResourcesReleasesOnException.
/**
* Tests that the {@link ExecutionJobVertex#allocateResourcesForAll(SlotProvider, boolean)} method
* releases partially acquired resources upon exception.
*/
@Test
public void testExecutionJobVertexAllocateResourcesReleasesOnException() throws Exception {
final int parallelism = 8;
final JobVertex vertex = new JobVertex("vertex");
vertex.setParallelism(parallelism);
vertex.setInvokableClass(NoOpInvokable.class);
final JobID jobId = new JobID();
final JobGraph jobGraph = new JobGraph(jobId, "test", vertex);
// set up some available slots and some slot owner that accepts released slots back
final List<SimpleSlot> returnedSlots = new ArrayList<>();
final SlotOwner recycler = new SlotOwner() {
@Override
public boolean returnAllocatedSlot(Slot slot) {
returnedSlots.add((SimpleSlot) slot);
return true;
}
};
// slot provider that hand out parallelism / 3 slots, then throws an exception
final SlotProvider slotProvider = mock(SlotProvider.class);
final TaskManagerGateway taskManager = mock(TaskManagerGateway.class);
final List<SimpleSlot> availableSlots = new ArrayList<>(Arrays.asList(createSlot(taskManager, jobId, recycler), createSlot(taskManager, jobId, recycler), createSlot(taskManager, jobId, recycler)));
when(slotProvider.allocateSlot(any(ScheduledUnit.class), anyBoolean())).then(new Answer<Future<SimpleSlot>>() {
@Override
public Future<SimpleSlot> answer(InvocationOnMock invocation) {
if (availableSlots.isEmpty()) {
throw new TestRuntimeException();
} else {
return FlinkCompletableFuture.completed(availableSlots.remove(0));
}
}
});
final ExecutionGraph eg = createExecutionGraph(jobGraph, slotProvider);
final ExecutionJobVertex ejv = eg.getJobVertex(vertex.getID());
// acquire resources and check that all are back after the failure
final int numSlotsToExpectBack = availableSlots.size();
try {
ejv.allocateResourcesForAll(slotProvider, false);
fail("should have failed with an exception");
} catch (TestRuntimeException e) {
// expected
}
assertEquals(numSlotsToExpectBack, returnedSlots.size());
}
use of org.apache.flink.runtime.jobmanager.slots.SlotOwner in project flink by apache.
the class ExecutionGraphSchedulingTest method testExecutionGraphScheduleReleasesResourcesOnException.
/**
* Tests that the {@link ExecutionGraph#scheduleForExecution()} method
* releases partially acquired resources upon exception.
*/
@Test
public void testExecutionGraphScheduleReleasesResourcesOnException() throws Exception {
// [pipelined]
// we construct a simple graph (source) ----------------> (target)
final int parallelism = 3;
final JobVertex sourceVertex = new JobVertex("source");
sourceVertex.setParallelism(parallelism);
sourceVertex.setInvokableClass(NoOpInvokable.class);
final JobVertex targetVertex = new JobVertex("target");
targetVertex.setParallelism(parallelism);
targetVertex.setInvokableClass(NoOpInvokable.class);
targetVertex.connectNewDataSetAsInput(sourceVertex, DistributionPattern.ALL_TO_ALL, ResultPartitionType.PIPELINED);
final JobID jobId = new JobID();
final JobGraph jobGraph = new JobGraph(jobId, "test", sourceVertex, targetVertex);
// set up some available slots and some slot owner that accepts released slots back
final List<SimpleSlot> returnedSlots = new ArrayList<>();
final SlotOwner recycler = new SlotOwner() {
@Override
public boolean returnAllocatedSlot(Slot slot) {
returnedSlots.add((SimpleSlot) slot);
return true;
}
};
final TaskManagerGateway taskManager = mock(TaskManagerGateway.class);
final List<SimpleSlot> availableSlots = new ArrayList<>(Arrays.asList(createSlot(taskManager, jobId, recycler), createSlot(taskManager, jobId, recycler), createSlot(taskManager, jobId, recycler), createSlot(taskManager, jobId, recycler), createSlot(taskManager, jobId, recycler)));
// slot provider that hand out parallelism / 3 slots, then throws an exception
final SlotProvider slotProvider = mock(SlotProvider.class);
when(slotProvider.allocateSlot(any(ScheduledUnit.class), anyBoolean())).then(new Answer<Future<SimpleSlot>>() {
@Override
public Future<SimpleSlot> answer(InvocationOnMock invocation) {
if (availableSlots.isEmpty()) {
throw new TestRuntimeException();
} else {
return FlinkCompletableFuture.completed(availableSlots.remove(0));
}
}
});
final ExecutionGraph eg = createExecutionGraph(jobGraph, slotProvider);
// acquire resources and check that all are back after the failure
final int numSlotsToExpectBack = availableSlots.size();
try {
eg.setScheduleMode(ScheduleMode.EAGER);
eg.scheduleForExecution();
fail("should have failed with an exception");
} catch (TestRuntimeException e) {
// expected
}
assertEquals(numSlotsToExpectBack, returnedSlots.size());
}
use of org.apache.flink.runtime.jobmanager.slots.SlotOwner in project flink by apache.
the class ExecutionGraphSchedulingTest method testOneSlotFailureAbortsDeploy.
/**
* This test verifies that if one slot future fails, the deployment will be aborted.
*/
@Test
public void testOneSlotFailureAbortsDeploy() throws Exception {
// [pipelined]
// we construct a simple graph (source) ----------------> (target)
final int parallelism = 6;
final JobVertex sourceVertex = new JobVertex("source");
sourceVertex.setParallelism(parallelism);
sourceVertex.setInvokableClass(NoOpInvokable.class);
final JobVertex targetVertex = new JobVertex("target");
targetVertex.setParallelism(parallelism);
targetVertex.setInvokableClass(NoOpInvokable.class);
targetVertex.connectNewDataSetAsInput(sourceVertex, DistributionPattern.POINTWISE, ResultPartitionType.PIPELINED);
final JobID jobId = new JobID();
final JobGraph jobGraph = new JobGraph(jobId, "test", sourceVertex, targetVertex);
//
// Create the slots, futures, and the slot provider
final TaskManagerGateway taskManager = mock(TaskManagerGateway.class);
final SlotOwner slotOwner = mock(SlotOwner.class);
final SimpleSlot[] sourceSlots = new SimpleSlot[parallelism];
final SimpleSlot[] targetSlots = new SimpleSlot[parallelism];
@SuppressWarnings({ "unchecked", "rawtypes" }) final FlinkCompletableFuture<SimpleSlot>[] sourceFutures = new FlinkCompletableFuture[parallelism];
@SuppressWarnings({ "unchecked", "rawtypes" }) final FlinkCompletableFuture<SimpleSlot>[] targetFutures = new FlinkCompletableFuture[parallelism];
for (int i = 0; i < parallelism; i++) {
sourceSlots[i] = createSlot(taskManager, jobId, slotOwner);
targetSlots[i] = createSlot(taskManager, jobId, slotOwner);
sourceFutures[i] = new FlinkCompletableFuture<>();
targetFutures[i] = new FlinkCompletableFuture<>();
}
ProgrammedSlotProvider slotProvider = new ProgrammedSlotProvider(parallelism);
slotProvider.addSlots(sourceVertex.getID(), sourceFutures);
slotProvider.addSlots(targetVertex.getID(), targetFutures);
final ExecutionGraph eg = createExecutionGraph(jobGraph, slotProvider);
TerminalJobStatusListener testListener = new TerminalJobStatusListener();
eg.registerJobStatusListener(testListener);
for (int i = 0; i < parallelism; i += 2) {
sourceFutures[i].complete(sourceSlots[i]);
targetFutures[i + 1].complete(targetSlots[i + 1]);
}
//
// kick off the scheduling
eg.setScheduleMode(ScheduleMode.EAGER);
eg.setQueuedSchedulingAllowed(true);
eg.scheduleForExecution();
// fail one slot
sourceFutures[1].completeExceptionally(new TestRuntimeException());
// wait until the job failed as a whole
testListener.waitForTerminalState(2000);
// wait until all slots are back
verify(slotOwner, new Timeout(2000, times(6))).returnAllocatedSlot(any(Slot.class));
// no deployment calls must have happened
verify(taskManager, times(0)).submitTask(any(TaskDeploymentDescriptor.class), any(Time.class));
// all completed futures must have been returns
for (int i = 0; i < parallelism; i += 2) {
assertTrue(sourceSlots[i].isCanceled());
assertTrue(targetSlots[i + 1].isCanceled());
}
}
Aggregations