Java Code Examples for org.apache.flink.runtime.jobmaster.LogicalSlot#releaseSlot()
The following examples show how to use
org.apache.flink.runtime.jobmaster.LogicalSlot#releaseSlot() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ScheduleWithCoLocationHintTest.java From flink with Apache License 2.0 | 5 votes |
@Test public void scheduleWithReleaseNoResource() throws Exception { JobVertexID jid1 = new JobVertexID(); JobVertexID jid2 = new JobVertexID(); JobVertexID jid3 = new JobVertexID(); testingSlotProvider.addTaskManager(1); testingSlotProvider.addTaskManager(1); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); SlotSharingGroup sharingGroup = new SlotSharingGroup(); CoLocationConstraint c1 = new CoLocationConstraint(new CoLocationGroup()); LogicalSlot s1 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertex(jid1, 0, 1, sharingGroup), sharingGroup.getSlotSharingGroupId(), c1), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); s1.releaseSlot(); testingSlotProvider.allocateSlot(new ScheduledUnit(getTestVertex(jid2, 0, 1, null)), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); testingSlotProvider.allocateSlot(new ScheduledUnit(getTestVertex(jid2, 1, 2, null)), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); try { testingSlotProvider.allocateSlot(new ScheduledUnit(getTestVertex(jid3, 0, 1, sharingGroup), sharingGroup.getSlotSharingGroupId(), c1), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); fail("Scheduled even though no resource was available."); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof NoResourceAvailableException); } assertEquals(0, testingSlotProvider.getNumberOfLocalizedAssignments()); assertEquals(0, testingSlotProvider.getNumberOfNonLocalizedAssignments()); assertEquals(3, testingSlotProvider.getNumberOfUnconstrainedAssignments()); }
Example 2
Source File: ExecutionVertexSchedulingTest.java From flink with Apache License 2.0 | 5 votes |
@Test public void testSlotReleasedWhenScheduledQueued() { try { final ExecutionJobVertex ejv = getExecutionJobVertex(new JobVertexID()); final ExecutionVertex vertex = new ExecutionVertex(ejv, 0, new IntermediateResult[0], AkkaUtils.getDefaultTimeout()); // a slot than cannot be deployed to final LogicalSlot slot = new TestingLogicalSlotBuilder().createTestingLogicalSlot(); slot.releaseSlot(new Exception("Test Exception")); assertFalse(slot.isAlive()); final CompletableFuture<LogicalSlot> future = new CompletableFuture<>(); assertEquals(ExecutionState.CREATED, vertex.getExecutionState()); // try to deploy to the slot vertex.scheduleForExecution( TestingSlotProviderStrategy.from(new TestingSlotProvider(ignore -> future)), LocationPreferenceConstraint.ALL, Collections.emptySet()); // future has not yet a slot assertEquals(ExecutionState.SCHEDULED, vertex.getExecutionState()); future.complete(slot); // will have failed assertEquals(ExecutionState.FAILED, vertex.getExecutionState()); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } }
Example 3
Source File: ScheduleWithCoLocationHintTest.java From flink with Apache License 2.0 | 5 votes |
@Test public void nonColocationFollowsCoLocation() throws Exception { JobVertexID jid1 = new JobVertexID(); JobVertexID jid2 = new JobVertexID(); TaskManagerLocation loc1 = testingSlotProvider.addTaskManager(1); TaskManagerLocation loc2 = testingSlotProvider.addTaskManager(1); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); SlotSharingGroup sharingGroup = new SlotSharingGroup(); CoLocationGroup ccg = new CoLocationGroup(); CoLocationConstraint cc1 = new CoLocationConstraint(ccg); CoLocationConstraint cc2 = new CoLocationConstraint(ccg); LogicalSlot s1 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid1, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc1), slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s2 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid1, 1, 2, sharingGroup, loc2), sharingGroup.getSlotSharingGroupId(), cc2), slotProfileForLocation(loc2), TestingUtils.infiniteTime()).get(); LogicalSlot s3 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid2, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId()), slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s4 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid2, 1, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId()), slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); // check that each slot got two assertEquals(s1.getTaskManagerLocation(), s3.getTaskManagerLocation()); assertEquals(s2.getTaskManagerLocation(), s4.getTaskManagerLocation()); s1.releaseSlot(); s2.releaseSlot(); s3.releaseSlot(); s4.releaseSlot(); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); }
Example 4
Source File: ExecutionVertexSchedulingTest.java From Flink-CEPplus with Apache License 2.0 | 5 votes |
@Test public void testSlotReleasedWhenScheduledQueued() { try { final ExecutionJobVertex ejv = getExecutionVertex(new JobVertexID()); final ExecutionVertex vertex = new ExecutionVertex(ejv, 0, new IntermediateResult[0], AkkaUtils.getDefaultTimeout()); // a slot than cannot be deployed to final LogicalSlot slot = new TestingLogicalSlot(); slot.releaseSlot(new Exception("Test Exception")); assertFalse(slot.isAlive()); final CompletableFuture<LogicalSlot> future = new CompletableFuture<>(); assertEquals(ExecutionState.CREATED, vertex.getExecutionState()); // try to deploy to the slot vertex.scheduleForExecution( new TestingSlotProvider(ignore -> future), true, LocationPreferenceConstraint.ALL, Collections.emptySet()); // future has not yet a slot assertEquals(ExecutionState.SCHEDULED, vertex.getExecutionState()); future.complete(slot); // will have failed assertEquals(ExecutionState.FAILED, vertex.getExecutionState()); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } }
Example 5
Source File: ScheduleWithCoLocationHintTest.java From flink with Apache License 2.0 | 5 votes |
@Test public void nonColocationFollowsCoLocation() throws Exception { JobVertexID jid1 = new JobVertexID(); JobVertexID jid2 = new JobVertexID(); TaskManagerLocation loc1 = testingSlotProvider.addTaskManager(1); TaskManagerLocation loc2 = testingSlotProvider.addTaskManager(1); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); SlotSharingGroup sharingGroup = new SlotSharingGroup(); CoLocationGroup ccg = new CoLocationGroup(); CoLocationConstraint cc1 = new CoLocationConstraint(ccg); CoLocationConstraint cc2 = new CoLocationConstraint(ccg); LogicalSlot s1 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid1, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc1), false, slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s2 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid1, 1, 2, sharingGroup, loc2), sharingGroup.getSlotSharingGroupId(), cc2), false, slotProfileForLocation(loc2), TestingUtils.infiniteTime()).get(); LogicalSlot s3 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid2, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId()), false, slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s4 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid2, 1, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId()), false, slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); // check that each slot got two assertEquals(s1.getTaskManagerLocation(), s3.getTaskManagerLocation()); assertEquals(s2.getTaskManagerLocation(), s4.getTaskManagerLocation()); s1.releaseSlot(); s2.releaseSlot(); s3.releaseSlot(); s4.releaseSlot(); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); }
Example 6
Source File: ExecutionVertexSchedulingTest.java From flink with Apache License 2.0 | 5 votes |
@Test public void testSlotReleasedWhenScheduledImmediately() { try { final ExecutionJobVertex ejv = getExecutionVertex(new JobVertexID()); final ExecutionVertex vertex = new ExecutionVertex(ejv, 0, new IntermediateResult[0], AkkaUtils.getDefaultTimeout()); // a slot than cannot be deployed to final LogicalSlot slot = new TestingLogicalSlotBuilder().createTestingLogicalSlot(); slot.releaseSlot(new Exception("Test Exception")); assertFalse(slot.isAlive()); CompletableFuture<LogicalSlot> future = new CompletableFuture<>(); future.complete(slot); assertEquals(ExecutionState.CREATED, vertex.getExecutionState()); // try to deploy to the slot vertex.scheduleForExecution( TestingSlotProviderStrategy.from(new TestingSlotProvider((i) -> future), false), LocationPreferenceConstraint.ALL, Collections.emptySet()); // will have failed assertEquals(ExecutionState.FAILED, vertex.getExecutionState()); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } }
Example 7
Source File: ExecutionGraphSchedulingTest.java From flink with Apache License 2.0 | 5 votes |
/** * Tests that a partially completed eager scheduling operation fails if a * completed slot is released. See FLINK-9099. */ @Test public void testSlotReleasingFailsSchedulingOperation() throws Exception { final int parallelism = 2; final JobVertex jobVertex = new JobVertex("Testing job vertex"); jobVertex.setInvokableClass(NoOpInvokable.class); jobVertex.setParallelism(parallelism); final JobGraph jobGraph = new JobGraph(jobVertex); jobGraph.setAllowQueuedScheduling(true); jobGraph.setScheduleMode(ScheduleMode.EAGER); final ProgrammedSlotProvider slotProvider = new ProgrammedSlotProvider(parallelism); final LogicalSlot slot = createSingleLogicalSlot(new DummySlotOwner(), new SimpleAckingTaskManagerGateway(), new SlotRequestId()); slotProvider.addSlot(jobVertex.getID(), 0, CompletableFuture.completedFuture(slot)); final CompletableFuture<LogicalSlot> slotFuture = new CompletableFuture<>(); slotProvider.addSlot(jobVertex.getID(), 1, slotFuture); final ExecutionGraph executionGraph = createExecutionGraph(jobGraph, slotProvider); executionGraph.start(ComponentMainThreadExecutorServiceAdapter.forMainThread()); executionGraph.scheduleForExecution(); assertThat(executionGraph.getState(), is(JobStatus.RUNNING)); final ExecutionJobVertex executionJobVertex = executionGraph.getJobVertex(jobVertex.getID()); final ExecutionVertex[] taskVertices = executionJobVertex.getTaskVertices(); assertThat(taskVertices[0].getExecutionState(), is(ExecutionState.SCHEDULED)); assertThat(taskVertices[1].getExecutionState(), is(ExecutionState.SCHEDULED)); // fail the single allocated slot --> this should fail the scheduling operation slot.releaseSlot(new FlinkException("Test failure")); assertThat(executionGraph.getTerminationFuture().get(), is(JobStatus.FAILED)); }
Example 8
Source File: ScheduleWithCoLocationHintTest.java From flink with Apache License 2.0 | 5 votes |
@Test public void scheduleWithIntermediateRelease() throws Exception { JobVertexID jid1 = new JobVertexID(); JobVertexID jid2 = new JobVertexID(); JobVertexID jid3 = new JobVertexID(); JobVertexID jid4 = new JobVertexID(); testingSlotProvider.addTaskManager(1); testingSlotProvider.addTaskManager(1); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); SlotSharingGroup sharingGroup = new SlotSharingGroup(); CoLocationConstraint c1 = new CoLocationConstraint(new CoLocationGroup()); LogicalSlot s1 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertex(jid1, 0, 1, sharingGroup), sharingGroup.getSlotSharingGroupId(), c1), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); LogicalSlot s2 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertex(jid2, 0, 1, sharingGroup), sharingGroup.getSlotSharingGroupId(), c1), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); LogicalSlot sSolo = testingSlotProvider.allocateSlot(new ScheduledUnit(getTestVertex(jid4, 0, 1, null)), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); ResourceID taskManager = s1.getTaskManagerLocation().getResourceID(); s1.releaseSlot(); s2.releaseSlot(); sSolo.releaseSlot(); LogicalSlot sNew = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertex(jid3, 0, 1, sharingGroup), sharingGroup.getSlotSharingGroupId(), c1), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); assertEquals(taskManager, sNew.getTaskManagerLocation().getResourceID()); assertEquals(2, testingSlotProvider.getNumberOfLocalizedAssignments()); assertEquals(0, testingSlotProvider.getNumberOfNonLocalizedAssignments()); assertEquals(2, testingSlotProvider.getNumberOfUnconstrainedAssignments()); }
Example 9
Source File: SlotPoolSlotSharingTest.java From flink with Apache License 2.0 | 4 votes |
/** * Tests queued slot scheduling with a single slot sharing group */ @Test public void testQueuedSharedSlotScheduling() throws Exception { final BlockingQueue<AllocationID> allocationIds = new ArrayBlockingQueue<>(2); final TestingResourceManagerGateway testingResourceManagerGateway = slotPoolResource.getTestingResourceManagerGateway(); testingResourceManagerGateway.setRequestSlotConsumer( (SlotRequest slotRequest) -> allocationIds.offer(slotRequest.getAllocationId())); final TaskManagerLocation taskManagerLocation = new LocalTaskManagerLocation(); final SlotPoolImpl slotPool = slotPoolResource.getSlotPool(); slotPool.registerTaskManager(taskManagerLocation.getResourceID()); final SlotSharingGroupId slotSharingGroupId = new SlotSharingGroupId(); final JobVertexID jobVertexId1 = new JobVertexID(); final JobVertexID jobVertexId2 = new JobVertexID(); final SlotProvider slotProvider = slotPoolResource.getSlotProvider(); CompletableFuture<LogicalSlot> logicalSlotFuture1 = slotProvider.allocateSlot( new ScheduledUnit( jobVertexId1, slotSharingGroupId, null), true, SlotProfile.noRequirements(), TestingUtils.infiniteTime()); CompletableFuture<LogicalSlot> logicalSlotFuture2 = slotProvider.allocateSlot( new ScheduledUnit( jobVertexId2, slotSharingGroupId, null), true, SlotProfile.noRequirements(), TestingUtils.infiniteTime()); assertFalse(logicalSlotFuture1.isDone()); assertFalse(logicalSlotFuture2.isDone()); final AllocationID allocationId1 = allocationIds.take(); CompletableFuture<LogicalSlot> logicalSlotFuture3 = slotProvider.allocateSlot( new ScheduledUnit( jobVertexId1, slotSharingGroupId, null), true, SlotProfile.noRequirements(), TestingUtils.infiniteTime()); CompletableFuture<LogicalSlot> logicalSlotFuture4 = slotProvider.allocateSlot( new ScheduledUnit( jobVertexId2, slotSharingGroupId, null), true, SlotProfile.noRequirements(), TestingUtils.infiniteTime()); assertFalse(logicalSlotFuture3.isDone()); assertFalse(logicalSlotFuture4.isDone()); allocationIds.take(); // this should fulfill the first two slot futures boolean offerFuture = slotPool.offerSlot( taskManagerLocation, new SimpleAckingTaskManagerGateway(), new SlotOffer( allocationId1, 0, ResourceProfile.UNKNOWN)); assertTrue(offerFuture); LogicalSlot logicalSlot1 = logicalSlotFuture1.get(); LogicalSlot logicalSlot2 = logicalSlotFuture2.get(); assertEquals(logicalSlot1.getTaskManagerLocation(), logicalSlot2.getTaskManagerLocation()); assertEquals(allocationId1, logicalSlot1.getAllocationId()); assertEquals(allocationId1, logicalSlot2.getAllocationId()); assertFalse(logicalSlotFuture3.isDone()); assertFalse(logicalSlotFuture4.isDone()); // release the shared slot by releasing the individual tasks logicalSlot1.releaseSlot(null); logicalSlot2.releaseSlot(null); LogicalSlot logicalSlot3 = logicalSlotFuture3.get(); LogicalSlot logicalSlot4 = logicalSlotFuture4.get(); assertEquals(logicalSlot3.getTaskManagerLocation(), logicalSlot4.getTaskManagerLocation()); assertEquals(allocationId1, logicalSlot3.getAllocationId()); assertEquals(allocationId1, logicalSlot4.getAllocationId()); }
Example 10
Source File: SlotPoolImplTest.java From flink with Apache License 2.0 | 4 votes |
@Test public void testOfferSlot() throws Exception { final CompletableFuture<SlotRequest> slotRequestFuture = new CompletableFuture<>(); resourceManagerGateway.setRequestSlotConsumer(slotRequestFuture::complete); try (SlotPoolImpl slotPool = createSlotPoolImpl()) { setupSlotPool(slotPool, resourceManagerGateway, mainThreadExecutor); Scheduler scheduler = setupScheduler(slotPool, mainThreadExecutor); slotPool.registerTaskManager(taskManagerLocation.getResourceID()); CompletableFuture<LogicalSlot> future = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); assertFalse(future.isDone()); final SlotRequest slotRequest = slotRequestFuture.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS); final SlotOffer slotOffer = new SlotOffer( slotRequest.getAllocationId(), 0, DEFAULT_TESTING_PROFILE); final TaskManagerLocation invalidTaskManagerLocation = new LocalTaskManagerLocation(); // slot from unregistered resource assertFalse(slotPool.offerSlot(invalidTaskManagerLocation, taskManagerGateway, slotOffer)); final SlotOffer nonRequestedSlotOffer = new SlotOffer( new AllocationID(), 0, DEFAULT_TESTING_PROFILE); // we'll also accept non requested slots assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, nonRequestedSlotOffer)); // accepted slot assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); LogicalSlot slot = future.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS); assertTrue(slot.isAlive()); // duplicated offer with using slot assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); assertTrue(slot.isAlive()); final SlotOffer anotherSlotOfferWithSameAllocationId = new SlotOffer( slotRequest.getAllocationId(), 1, DEFAULT_TESTING_PROFILE); assertFalse(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, anotherSlotOfferWithSameAllocationId)); TaskManagerLocation anotherTaskManagerLocation = new LocalTaskManagerLocation(); assertFalse(slotPool.offerSlot(anotherTaskManagerLocation, taskManagerGateway, slotOffer)); // duplicated offer with free slot slot.releaseSlot(); assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); assertFalse(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, anotherSlotOfferWithSameAllocationId)); assertFalse(slotPool.offerSlot(anotherTaskManagerLocation, taskManagerGateway, slotOffer)); } }
Example 11
Source File: SlotPoolImplTest.java From flink with Apache License 2.0 | 4 votes |
@Test public void testAllocateWithFreeSlot() throws Exception { final CompletableFuture<SlotRequest> slotRequestFuture = new CompletableFuture<>(); resourceManagerGateway.setRequestSlotConsumer(slotRequestFuture::complete); try (SlotPoolImpl slotPool = createSlotPoolImpl()) { setupSlotPool(slotPool, resourceManagerGateway, mainThreadExecutor); Scheduler scheduler = setupScheduler(slotPool, mainThreadExecutor); slotPool.registerTaskManager(taskManagerLocation.getResourceID()); CompletableFuture<LogicalSlot> future1 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); assertFalse(future1.isDone()); final SlotRequest slotRequest = slotRequestFuture.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS); final SlotOffer slotOffer = new SlotOffer( slotRequest.getAllocationId(), 0, DEFAULT_TESTING_PROFILE); assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); LogicalSlot slot1 = future1.get(1, TimeUnit.SECONDS); assertTrue(future1.isDone()); // return this slot to pool slot1.releaseSlot(); CompletableFuture<LogicalSlot> future2 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); // second allocation fulfilled by previous slot returning LogicalSlot slot2 = future2.get(1, TimeUnit.SECONDS); assertTrue(future2.isDone()); assertNotEquals(slot1, slot2); assertFalse(slot1.isAlive()); assertTrue(slot2.isAlive()); assertEquals(slot1.getTaskManagerLocation(), slot2.getTaskManagerLocation()); assertEquals(slot1.getPhysicalSlotNumber(), slot2.getPhysicalSlotNumber()); } }
Example 12
Source File: SlotPoolImplTest.java From flink with Apache License 2.0 | 4 votes |
@Test public void testAllocationFulfilledByReturnedSlot() throws Exception { final ArrayBlockingQueue<SlotRequest> slotRequestQueue = new ArrayBlockingQueue<>(2); resourceManagerGateway.setRequestSlotConsumer(slotRequest -> { while (!slotRequestQueue.offer(slotRequest)) { // noop } }); try (SlotPoolImpl slotPool = createSlotPoolImpl()) { setupSlotPool(slotPool, resourceManagerGateway, mainThreadExecutor); Scheduler scheduler = setupScheduler(slotPool, mainThreadExecutor); slotPool.registerTaskManager(taskManagerLocation.getResourceID()); CompletableFuture<LogicalSlot> future1 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); CompletableFuture<LogicalSlot> future2 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); assertFalse(future1.isDone()); assertFalse(future2.isDone()); final List<SlotRequest> slotRequests = new ArrayList<>(2); for (int i = 0; i < 2; i++) { slotRequests.add(slotRequestQueue.poll(timeout.toMilliseconds(), TimeUnit.MILLISECONDS)); } final SlotOffer slotOffer = new SlotOffer( slotRequests.get(0).getAllocationId(), 0, DEFAULT_TESTING_PROFILE); assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); LogicalSlot slot1 = future1.get(1, TimeUnit.SECONDS); assertTrue(future1.isDone()); assertFalse(future2.isDone()); // return this slot to pool slot1.releaseSlot(); // second allocation fulfilled by previous slot returning LogicalSlot slot2 = future2.get(1, TimeUnit.SECONDS); assertTrue(future2.isDone()); assertNotEquals(slot1, slot2); assertFalse(slot1.isAlive()); assertTrue(slot2.isAlive()); assertEquals(slot1.getTaskManagerLocation(), slot2.getTaskManagerLocation()); assertEquals(slot1.getPhysicalSlotNumber(), slot2.getPhysicalSlotNumber()); assertEquals(slot1.getAllocationId(), slot2.getAllocationId()); } }
Example 13
Source File: Execution.java From flink with Apache License 2.0 | 4 votes |
/** * Deploys the execution to the previously assigned resource. * * @throws JobException if the execution cannot be deployed to the assigned resource */ public void deploy() throws JobException { assertRunningInJobMasterMainThread(); final LogicalSlot slot = assignedResource; checkNotNull(slot, "In order to deploy the execution we first have to assign a resource via tryAssignResource."); // Check if the TaskManager died in the meantime // This only speeds up the response to TaskManagers failing concurrently to deployments. // The more general check is the rpcTimeout of the deployment call if (!slot.isAlive()) { throw new JobException("Target slot (TaskManager) for deployment is no longer alive."); } // make sure exactly one deployment call happens from the correct state // note: the transition from CREATED to DEPLOYING is for testing purposes only ExecutionState previous = this.state; if (previous == SCHEDULED || previous == CREATED) { if (!transitionState(previous, DEPLOYING)) { // race condition, someone else beat us to the deploying call. // this should actually not happen and indicates a race somewhere else throw new IllegalStateException("Cannot deploy task: Concurrent deployment call race."); } } else { // vertex may have been cancelled, or it was already scheduled throw new IllegalStateException("The vertex must be in CREATED or SCHEDULED state to be deployed. Found state " + previous); } if (this != slot.getPayload()) { throw new IllegalStateException( String.format("The execution %s has not been assigned to the assigned slot.", this)); } try { // race double check, did we fail/cancel and do we need to release the slot? if (this.state != DEPLOYING) { slot.releaseSlot(new FlinkException("Actual state of execution " + this + " (" + state + ") does not match expected state DEPLOYING.")); return; } if (LOG.isInfoEnabled()) { LOG.info(String.format("Deploying %s (attempt #%d) to %s", vertex.getTaskNameWithSubtaskIndex(), attemptNumber, getAssignedResourceLocation())); } final TaskDeploymentDescriptor deployment = TaskDeploymentDescriptorFactory .fromExecutionVertex(vertex, attemptNumber) .createDeploymentDescriptor( slot.getAllocationId(), slot.getPhysicalSlotNumber(), taskRestore, producedPartitions.values()); // null taskRestore to let it be GC'ed taskRestore = null; final TaskManagerGateway taskManagerGateway = slot.getTaskManagerGateway(); final ComponentMainThreadExecutor jobMasterMainThreadExecutor = vertex.getExecutionGraph().getJobMasterMainThreadExecutor(); // We run the submission in the future executor so that the serialization of large TDDs does not block // the main thread and sync back to the main thread once submission is completed. CompletableFuture.supplyAsync(() -> taskManagerGateway.submitTask(deployment, rpcTimeout), executor) .thenCompose(Function.identity()) .whenCompleteAsync( (ack, failure) -> { // only respond to the failure case if (failure != null) { if (failure instanceof TimeoutException) { String taskname = vertex.getTaskNameWithSubtaskIndex() + " (" + attemptId + ')'; markFailed(new Exception( "Cannot deploy task " + taskname + " - TaskManager (" + getAssignedResourceLocation() + ") not responding after a rpcTimeout of " + rpcTimeout, failure)); } else { markFailed(failure); } } }, jobMasterMainThreadExecutor); } catch (Throwable t) { markFailed(t); ExceptionUtils.rethrow(t); } }
Example 14
Source File: ScheduleWithCoLocationHintTest.java From flink with Apache License 2.0 | 4 votes |
@Test public void testGetsNonLocalFromSharingGroupFirst() throws Exception { JobVertexID jid1 = new JobVertexID(); JobVertexID jid2 = new JobVertexID(); JobVertexID jid3 = new JobVertexID(); TaskManagerLocation loc1 = testingSlotProvider.addTaskManager(1); TaskManagerLocation loc2 = testingSlotProvider.addTaskManager(1); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); SlotSharingGroup sharingGroup = new SlotSharingGroup(); CoLocationGroup ccg = new CoLocationGroup(); CoLocationConstraint cc1 = new CoLocationConstraint(ccg); CoLocationConstraint cc2 = new CoLocationConstraint(ccg); // schedule something into the shared group so that both instances are in the sharing group LogicalSlot s1 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid1, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId()), false, slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s2 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid1, 1, 2, sharingGroup, loc2), sharingGroup.getSlotSharingGroupId()), false, slotProfileForLocation(loc2), TestingUtils.infiniteTime()).get(); // schedule one locally to instance 1 LogicalSlot s3 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid2, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc1), false, slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); // schedule with co location constraint (yet unassigned) and a preference for // instance 1, but it can only get instance 2 LogicalSlot s4 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid2, 1, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc2), false, slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); // schedule something into the assigned co-location constraints and check that they override the // other preferences LogicalSlot s5 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid3, 0, 2, sharingGroup, loc2), sharingGroup.getSlotSharingGroupId(), cc1), false, slotProfileForLocation(loc2), TestingUtils.infiniteTime()).get(); LogicalSlot s6 = testingSlotProvider.allocateSlot( new ScheduledUnit(getTestVertexWithLocation(jid3, 1, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc2), false, slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); // check that each slot got three assertEquals(s1.getTaskManagerLocation(), s3.getTaskManagerLocation()); assertEquals(s2.getTaskManagerLocation(), s4.getTaskManagerLocation()); assertEquals(s1.getTaskManagerLocation(), s5.getTaskManagerLocation()); assertEquals(s2.getTaskManagerLocation(), s6.getTaskManagerLocation()); // check the scheduler's bookkeeping assertEquals(0, testingSlotProvider.getNumberOfAvailableSlots()); assertEquals(5, testingSlotProvider.getNumberOfLocalizedAssignments()); assertTrue(1 == testingSlotProvider.getNumberOfNonLocalizedAssignments() || 1 == testingSlotProvider.getNumberOfHostLocalizedAssignments()); assertEquals(0, testingSlotProvider.getNumberOfUnconstrainedAssignments()); // release some slots, be sure that new available ones come up s1.releaseSlot(); s2.releaseSlot(); s3.releaseSlot(); s4.releaseSlot(); s5.releaseSlot(); s6.releaseSlot(); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); }
Example 15
Source File: SlotPoolImplTest.java From flink with Apache License 2.0 | 4 votes |
@Test public void testAllocationFulfilledByReturnedSlot() throws Exception { final ArrayBlockingQueue<SlotRequest> slotRequestQueue = new ArrayBlockingQueue<>(2); resourceManagerGateway.setRequestSlotConsumer(slotRequest -> { while (!slotRequestQueue.offer(slotRequest)) { // noop } }); try (SlotPoolImpl slotPool = createSlotPoolImpl()) { setupSlotPool(slotPool, resourceManagerGateway, mainThreadExecutor); Scheduler scheduler = setupScheduler(slotPool, mainThreadExecutor); slotPool.registerTaskManager(taskManagerLocation.getResourceID()); CompletableFuture<LogicalSlot> future1 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), timeout); CompletableFuture<LogicalSlot> future2 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), timeout); assertFalse(future1.isDone()); assertFalse(future2.isDone()); final List<SlotRequest> slotRequests = new ArrayList<>(2); for (int i = 0; i < 2; i++) { slotRequests.add(slotRequestQueue.poll(timeout.toMilliseconds(), TimeUnit.MILLISECONDS)); } final SlotOffer slotOffer = new SlotOffer( slotRequests.get(0).getAllocationId(), 0, DEFAULT_TESTING_PROFILE); assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); LogicalSlot slot1 = future1.get(1, TimeUnit.SECONDS); assertTrue(future1.isDone()); assertFalse(future2.isDone()); // return this slot to pool slot1.releaseSlot(); // second allocation fulfilled by previous slot returning LogicalSlot slot2 = future2.get(1, TimeUnit.SECONDS); assertTrue(future2.isDone()); assertNotEquals(slot1, slot2); assertFalse(slot1.isAlive()); assertTrue(slot2.isAlive()); assertEquals(slot1.getTaskManagerLocation(), slot2.getTaskManagerLocation()); assertEquals(slot1.getPhysicalSlotNumber(), slot2.getPhysicalSlotNumber()); assertEquals(slot1.getAllocationId(), slot2.getAllocationId()); } }
Example 16
Source File: SchedulerIsolatedTasksTest.java From flink with Apache License 2.0 | 4 votes |
@Test public void testScheduleImmediately() throws Exception { assertEquals(0, testingSlotProvider.getNumberOfAvailableSlots()); testingSlotProvider.addTaskManager(2); testingSlotProvider.addTaskManager(1); testingSlotProvider.addTaskManager(2); assertEquals(5, testingSlotProvider.getNumberOfAvailableSlots()); // schedule something into all slots LogicalSlot s1 = testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); LogicalSlot s2 = testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); LogicalSlot s3 = testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); LogicalSlot s4 = testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); LogicalSlot s5 = testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); // the slots should all be different assertTrue(areAllDistinct(s1, s2, s3, s4, s5)); try { testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); fail("Scheduler accepted scheduling request without available resource."); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof NoResourceAvailableException); } // release some slots again s3.releaseSlot(); s4.releaseSlot(); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); // now we can schedule some more slots LogicalSlot s6 = testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); LogicalSlot s7 = testingSlotProvider.allocateSlot(new ScheduledUnit(getDummyTask()), false, SlotProfile.noRequirements(), TestingUtils.infiniteTime()).get(); assertTrue(areAllDistinct(s1, s2, s3, s4, s5, s6, s7)); // release all s1.releaseSlot(); s2.releaseSlot(); s5.releaseSlot(); s6.releaseSlot(); s7.releaseSlot(); assertEquals(5, testingSlotProvider.getNumberOfAvailableSlots()); // check that slots that are released twice (accidentally) do not mess things up s1.releaseSlot(); s2.releaseSlot(); s5.releaseSlot(); s6.releaseSlot(); s7.releaseSlot(); assertEquals(5, testingSlotProvider.getNumberOfAvailableSlots()); }
Example 17
Source File: Execution.java From flink with Apache License 2.0 | 4 votes |
/** * Deploys the execution to the previously assigned resource. * * @throws JobException if the execution cannot be deployed to the assigned resource */ public void deploy() throws JobException { assertRunningInJobMasterMainThread(); final LogicalSlot slot = assignedResource; checkNotNull(slot, "In order to deploy the execution we first have to assign a resource via tryAssignResource."); // Check if the TaskManager died in the meantime // This only speeds up the response to TaskManagers failing concurrently to deployments. // The more general check is the rpcTimeout of the deployment call if (!slot.isAlive()) { throw new JobException("Target slot (TaskManager) for deployment is no longer alive."); } // make sure exactly one deployment call happens from the correct state // note: the transition from CREATED to DEPLOYING is for testing purposes only ExecutionState previous = this.state; if (previous == SCHEDULED || previous == CREATED) { if (!transitionState(previous, DEPLOYING)) { // race condition, someone else beat us to the deploying call. // this should actually not happen and indicates a race somewhere else throw new IllegalStateException("Cannot deploy task: Concurrent deployment call race."); } } else { // vertex may have been cancelled, or it was already scheduled throw new IllegalStateException("The vertex must be in CREATED or SCHEDULED state to be deployed. Found state " + previous); } if (this != slot.getPayload()) { throw new IllegalStateException( String.format("The execution %s has not been assigned to the assigned slot.", this)); } try { // race double check, did we fail/cancel and do we need to release the slot? if (this.state != DEPLOYING) { slot.releaseSlot(new FlinkException("Actual state of execution " + this + " (" + state + ") does not match expected state DEPLOYING.")); return; } LOG.info("Deploying {} (attempt #{}) with attempt id {} to {} with allocation id {}", vertex.getTaskNameWithSubtaskIndex(), attemptNumber, vertex.getCurrentExecutionAttempt().getAttemptId(), getAssignedResourceLocation(), slot.getAllocationId()); final TaskDeploymentDescriptor deployment = TaskDeploymentDescriptorFactory .fromExecutionVertex(vertex, attemptNumber) .createDeploymentDescriptor( slot.getAllocationId(), slot.getPhysicalSlotNumber(), taskRestore, producedPartitions.values()); // null taskRestore to let it be GC'ed taskRestore = null; final TaskManagerGateway taskManagerGateway = slot.getTaskManagerGateway(); final ComponentMainThreadExecutor jobMasterMainThreadExecutor = vertex.getExecutionGraph().getJobMasterMainThreadExecutor(); // We run the submission in the future executor so that the serialization of large TDDs does not block // the main thread and sync back to the main thread once submission is completed. CompletableFuture.supplyAsync(() -> taskManagerGateway.submitTask(deployment, rpcTimeout), executor) .thenCompose(Function.identity()) .whenCompleteAsync( (ack, failure) -> { // only respond to the failure case if (failure != null) { if (failure instanceof TimeoutException) { String taskname = vertex.getTaskNameWithSubtaskIndex() + " (" + attemptId + ')'; markFailed(new Exception( "Cannot deploy task " + taskname + " - TaskManager (" + getAssignedResourceLocation() + ") not responding after a rpcTimeout of " + rpcTimeout, failure)); } else { markFailed(failure); } } }, jobMasterMainThreadExecutor); } catch (Throwable t) { markFailed(t); if (isLegacyScheduling()) { ExceptionUtils.rethrow(t); } } }
Example 18
Source File: ScheduleWithCoLocationHintTest.java From flink with Apache License 2.0 | 4 votes |
@Test public void testScheduleOutOfOrder() throws Exception { JobVertexID jid1 = new JobVertexID(); JobVertexID jid2 = new JobVertexID(); TaskManagerLocation loc1 = testingSlotProvider.addTaskManager(1); testingSlotProvider.addTaskManager(1); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); SlotSharingGroup sharingGroup = new SlotSharingGroup(); CoLocationGroup ccg = new CoLocationGroup(); CoLocationConstraint cc1 = new CoLocationConstraint(ccg); CoLocationConstraint cc2 = new CoLocationConstraint(ccg); // schedule something from the second job vertex id before the first is filled, // and give locality preferences that hint at using the same shared slot for both // co location constraints (which we seek to prevent) LogicalSlot s1 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid1, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc1), slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s2 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid2, 0, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc2), slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s3 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid2, 1, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc1), slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); LogicalSlot s4 = testingSlotProvider.allocateSlot( new ScheduledUnit(getExecution(jid1, 1, 2, sharingGroup, loc1), sharingGroup.getSlotSharingGroupId(), cc2), slotProfileForLocation(loc1), TestingUtils.infiniteTime()).get(); // check that each slot got three assertEquals(s1.getTaskManagerLocation(), s3.getTaskManagerLocation()); assertEquals(s2.getTaskManagerLocation(), s4.getTaskManagerLocation()); // check the testingSlotProvider's bookkeeping assertEquals(0, testingSlotProvider.getNumberOfAvailableSlots()); assertEquals(3, testingSlotProvider.getNumberOfLocalizedAssignments()); assertTrue(1 == testingSlotProvider.getNumberOfNonLocalizedAssignments() || 1 == testingSlotProvider.getNumberOfHostLocalizedAssignments()); assertEquals(0, testingSlotProvider.getNumberOfUnconstrainedAssignments()); // release some slots, be sure that new available ones come up s1.releaseSlot(); s2.releaseSlot(); s3.releaseSlot(); s4.releaseSlot(); assertEquals(2, testingSlotProvider.getNumberOfAvailableSlots()); }
Example 19
Source File: SlotPoolImplTest.java From Flink-CEPplus with Apache License 2.0 | 4 votes |
@Test public void testAllocateWithFreeSlot() throws Exception { final CompletableFuture<SlotRequest> slotRequestFuture = new CompletableFuture<>(); resourceManagerGateway.setRequestSlotConsumer(slotRequestFuture::complete); try (SlotPoolImpl slotPool = new SlotPoolImpl(jobId)) { setupSlotPool(slotPool, resourceManagerGateway, mainThreadExecutor); Scheduler scheduler = setupScheduler(slotPool, mainThreadExecutor); slotPool.registerTaskManager(taskManagerLocation.getResourceID()); CompletableFuture<LogicalSlot> future1 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); assertFalse(future1.isDone()); final SlotRequest slotRequest = slotRequestFuture.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS); final SlotOffer slotOffer = new SlotOffer( slotRequest.getAllocationId(), 0, DEFAULT_TESTING_PROFILE); assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); LogicalSlot slot1 = future1.get(1, TimeUnit.SECONDS); assertTrue(future1.isDone()); // return this slot to pool slot1.releaseSlot(); CompletableFuture<LogicalSlot> future2 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); // second allocation fulfilled by previous slot returning LogicalSlot slot2 = future2.get(1, TimeUnit.SECONDS); assertTrue(future2.isDone()); assertNotEquals(slot1, slot2); assertFalse(slot1.isAlive()); assertTrue(slot2.isAlive()); assertEquals(slot1.getTaskManagerLocation(), slot2.getTaskManagerLocation()); assertEquals(slot1.getPhysicalSlotNumber(), slot2.getPhysicalSlotNumber()); } }
Example 20
Source File: SlotPoolImplTest.java From Flink-CEPplus with Apache License 2.0 | 4 votes |
@Test public void testAllocationFulfilledByReturnedSlot() throws Exception { final ArrayBlockingQueue<SlotRequest> slotRequestQueue = new ArrayBlockingQueue<>(2); resourceManagerGateway.setRequestSlotConsumer(slotRequest -> { while (!slotRequestQueue.offer(slotRequest)) { // noop } }); try (SlotPoolImpl slotPool = new SlotPoolImpl(jobId)) { setupSlotPool(slotPool, resourceManagerGateway, mainThreadExecutor); Scheduler scheduler = setupScheduler(slotPool, mainThreadExecutor); slotPool.registerTaskManager(taskManagerLocation.getResourceID()); CompletableFuture<LogicalSlot> future1 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); CompletableFuture<LogicalSlot> future2 = scheduler.allocateSlot( new SlotRequestId(), new DummyScheduledUnit(), SlotProfile.noLocality(DEFAULT_TESTING_PROFILE), true, timeout); assertFalse(future1.isDone()); assertFalse(future2.isDone()); final List<SlotRequest> slotRequests = new ArrayList<>(2); for (int i = 0; i < 2; i++) { slotRequests.add(slotRequestQueue.poll(timeout.toMilliseconds(), TimeUnit.MILLISECONDS)); } final SlotOffer slotOffer = new SlotOffer( slotRequests.get(0).getAllocationId(), 0, DEFAULT_TESTING_PROFILE); assertTrue(slotPool.offerSlot(taskManagerLocation, taskManagerGateway, slotOffer)); LogicalSlot slot1 = future1.get(1, TimeUnit.SECONDS); assertTrue(future1.isDone()); assertFalse(future2.isDone()); // return this slot to pool slot1.releaseSlot(); // second allocation fulfilled by previous slot returning LogicalSlot slot2 = future2.get(1, TimeUnit.SECONDS); assertTrue(future2.isDone()); assertNotEquals(slot1, slot2); assertFalse(slot1.isAlive()); assertTrue(slot2.isAlive()); assertEquals(slot1.getTaskManagerLocation(), slot2.getTaskManagerLocation()); assertEquals(slot1.getPhysicalSlotNumber(), slot2.getPhysicalSlotNumber()); assertEquals(slot1.getAllocationId(), slot2.getAllocationId()); } }