You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by tr...@apache.org on 2017/04/28 13:42:41 UTC

[1/7] flink git commit: [FLINK-5810] [flip-6] Introduce a hardened slot manager

Repository: flink
Updated Branches:
  refs/heads/master f3da8f69e -> d75ec5b35


http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorITCase.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorITCase.java b/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorITCase.java
index 579ca3a..6a0bd87 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorITCase.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorITCase.java
@@ -47,13 +47,13 @@ import org.apache.flink.runtime.resourcemanager.ResourceManager;
 import org.apache.flink.runtime.resourcemanager.ResourceManagerConfiguration;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
 import org.apache.flink.runtime.resourcemanager.StandaloneResourceManager;
-import org.apache.flink.runtime.resourcemanager.slotmanager.DefaultSlotManager;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
 import org.apache.flink.runtime.rpc.TestingSerialRpcService;
 import org.apache.flink.runtime.taskexecutor.slot.SlotOffer;
 import org.apache.flink.runtime.taskexecutor.slot.TaskSlotTable;
 import org.apache.flink.runtime.taskexecutor.slot.TimerService;
 import org.apache.flink.runtime.taskmanager.TaskManagerLocation;
+import org.apache.flink.runtime.testingUtils.TestingUtils;
 import org.apache.flink.runtime.util.TestingFatalErrorHandler;
 import org.apache.flink.util.TestLogger;
 import org.hamcrest.Matchers;
@@ -102,7 +102,6 @@ public class TaskExecutorITCase extends TestLogger {
 		ResourceManagerConfiguration resourceManagerConfiguration = new ResourceManagerConfiguration(
 			Time.milliseconds(500L),
 			Time.milliseconds(500L));
-		SlotManagerFactory slotManagerFactory = new DefaultSlotManager.Factory();
 		JobLeaderIdService jobLeaderIdService = new JobLeaderIdService(
 			testingHAServices,
 			rpcService.getScheduledExecutor(),
@@ -121,6 +120,11 @@ public class TaskExecutorITCase extends TestLogger {
 		final TaskSlotTable taskSlotTable = new TaskSlotTable(Arrays.asList(resourceProfile), new TimerService<AllocationID>(scheduledExecutorService, 100L));
 		final JobManagerTable jobManagerTable = new JobManagerTable();
 		final JobLeaderService jobLeaderService = new JobLeaderService(taskManagerLocation);
+		final SlotManager slotManager = new SlotManager(
+			rpcService.getScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime());
 
 		ResourceManager<ResourceID> resourceManager = new StandaloneResourceManager(
 			rpcService,
@@ -129,7 +133,7 @@ public class TaskExecutorITCase extends TestLogger {
 			resourceManagerConfiguration,
 			testingHAServices,
 			heartbeatServices,
-			slotManagerFactory,
+			slotManager,
 			metricRegistry,
 			jobLeaderIdService,
 			testingFatalErrorHandler);
@@ -168,7 +172,7 @@ public class TaskExecutorITCase extends TestLogger {
 		rpcService.registerGateway(jmAddress, jmGateway);
 
 		final AllocationID allocationId = new AllocationID();
-		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile);
+		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, jmAddress);
 		final SlotOffer slotOffer = new SlotOffer(allocationId, 0, resourceProfile);
 
 		try {

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorTest.java
index 1d1840e..d3d4d43 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/taskexecutor/TaskExecutorTest.java
@@ -65,10 +65,8 @@ import org.apache.flink.runtime.metrics.groups.TaskMetricGroup;
 import org.apache.flink.runtime.query.TaskKvStateRegistry;
 import org.apache.flink.runtime.registration.RegistrationResponse;
 import org.apache.flink.runtime.resourcemanager.ResourceManagerGateway;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestRegistered;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestRejected;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestReply;
 import org.apache.flink.runtime.rpc.TestingSerialRpcService;
+import org.apache.flink.runtime.taskexecutor.exceptions.SlotAllocationException;
 import org.apache.flink.runtime.taskexecutor.slot.SlotOffer;
 import org.apache.flink.runtime.taskexecutor.slot.TaskSlotTable;
 import org.apache.flink.runtime.taskexecutor.slot.TimerService;
@@ -101,6 +99,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.*;
 
 public class TaskExecutorTest extends TestLogger {
@@ -703,10 +702,7 @@ public class TaskExecutorTest extends TestLogger {
 			resourceManagerLeaderRetrievalService.notifyListener(resourceManagerAddress, resourceManagerLeaderId);
 
 			// request slots from the task manager under the given allocation id
-			TMSlotRequestReply reply = taskManager.requestSlot(slotId, jobId, allocationId, jobManagerAddress, resourceManagerLeaderId);
-
-			// this is hopefully successful :-)
-			assertTrue(reply instanceof TMSlotRequestRegistered);
+			taskManager.requestSlot(slotId, jobId, allocationId, jobManagerAddress, resourceManagerLeaderId);
 
 			// now inform the task manager about the new job leader
 			jobManagerLeaderRetrievalService.notifyListener(jobManagerAddress, jobManagerLeaderId);
@@ -820,7 +816,11 @@ public class TaskExecutorTest extends TestLogger {
 			// been properly started.
 			jobLeaderService.addJob(jobId, jobManagerAddress);
 
-			verify(resourceManagerGateway).notifySlotAvailable(eq(resourceManagerLeaderId), eq(registrationId), eq(new SlotID(resourceId, 1)));
+			verify(resourceManagerGateway).notifySlotAvailable(
+				eq(resourceManagerLeaderId),
+				eq(registrationId),
+				eq(new SlotID(resourceId, 1)),
+				eq(allocationId2));
 
 			assertTrue(taskSlotTable.existsActiveSlot(jobId, allocationId1));
 			assertFalse(taskSlotTable.existsActiveSlot(jobId, allocationId2));
@@ -903,15 +903,19 @@ public class TaskExecutorTest extends TestLogger {
 
 			// test that allocating a slot works
 			final SlotID slotID = new SlotID(resourceID, 0);
-			TMSlotRequestReply tmSlotRequestReply = taskManager.requestSlot(slotID, jobId, new AllocationID(), jobManagerAddress, leaderId);
-			assertTrue(tmSlotRequestReply instanceof TMSlotRequestRegistered);
+			taskManager.requestSlot(slotID, jobId, new AllocationID(), jobManagerAddress, leaderId);
 
 			// TODO: Figure out the concrete allocation behaviour between RM and TM. Maybe we don't need the SlotID...
 			// test that we can't allocate slots which are blacklisted due to pending confirmation of the RM
 			final SlotID unconfirmedFreeSlotID = new SlotID(resourceID, 1);
-			TMSlotRequestReply tmSlotRequestReply2 =
+
+			try {
 				taskManager.requestSlot(unconfirmedFreeSlotID, jobId, new AllocationID(), jobManagerAddress, leaderId);
-			assertTrue(tmSlotRequestReply2 instanceof TMSlotRequestRejected);
+
+				fail("The slot request should have failed.");
+			} catch (SlotAllocationException e) {
+				// expected
+			}
 
 			// re-register
 			verify(rmGateway1).registerTaskExecutor(
@@ -920,9 +924,7 @@ public class TaskExecutorTest extends TestLogger {
 
 			// now we should be successful because the slots status has been synced
 			// test that we can't allocate slots which are blacklisted due to pending confirmation of the RM
-			TMSlotRequestReply tmSlotRequestReply3 =
-				taskManager.requestSlot(unconfirmedFreeSlotID, jobId, new AllocationID(), jobManagerAddress, leaderId);
-			assertTrue(tmSlotRequestReply3 instanceof TMSlotRequestRegistered);
+			taskManager.requestSlot(unconfirmedFreeSlotID, jobId, new AllocationID(), jobManagerAddress, leaderId);
 
 			// check if a concurrent error occurred
 			testingFatalErrorHandler.rethrowError();
@@ -1100,7 +1102,11 @@ public class TaskExecutorTest extends TestLogger {
 			// acknowledge the offered slots
 			offerResultFuture.complete(Collections.singleton(offer1));
 
-			verify(resourceManagerGateway).notifySlotAvailable(eq(resourceManagerLeaderId), eq(registrationId), eq(new SlotID(resourceId, 1)));
+			verify(resourceManagerGateway).notifySlotAvailable(
+				eq(resourceManagerLeaderId),
+				eq(registrationId),
+				eq(new SlotID(resourceId, 1)),
+				any(AllocationID.class));
 
 			assertTrue(taskSlotTable.existsActiveSlot(jobId, allocationId1));
 			assertFalse(taskSlotTable.existsActiveSlot(jobId, allocationId2));

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala b/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
index f58faf2..03b5172 100644
--- a/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
+++ b/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
@@ -28,11 +28,13 @@ import com.google.common.util.concurrent.MoreExecutors
 import com.typesafe.config.ConfigFactory
 import grizzled.slf4j.Logger
 import org.apache.flink.api.common.JobExecutionResult
+import org.apache.flink.api.common.time.Time
 import org.apache.flink.configuration.{ConfigConstants, Configuration, HighAvailabilityOptions, TaskManagerOptions}
 import org.apache.flink.runtime.akka.AkkaUtils
 import org.apache.flink.runtime.client.JobClient
 import org.apache.flink.runtime.clusterframework.FlinkResourceManager
 import org.apache.flink.runtime.clusterframework.types.ResourceID
+import org.apache.flink.runtime.concurrent.{ScheduledExecutor, ScheduledExecutorServiceAdapter}
 import org.apache.flink.runtime.highavailability.HighAvailabilityServices
 import org.apache.flink.runtime.instance.{ActorGateway, AkkaActorGateway}
 import org.apache.flink.runtime.jobgraph.JobGraph
@@ -78,6 +80,10 @@ object TestingUtils {
   }
 
   def getDefaultTestingActorSystemConfig = testConfig
+
+  def infiniteTime: Time = {
+    Time.milliseconds(Long.MaxValue);
+  }
   
 
   def startTestingCluster(numSlots: Int, numTMs: Int = 1,
@@ -114,6 +120,12 @@ object TestingUtils {
     }
   }
 
+  def defaultScheduledExecutor: ScheduledExecutor = {
+    val scheduledExecutorService = defaultExecutor
+
+    new ScheduledExecutorServiceAdapter(scheduledExecutorService)
+  }
+
   /** Returns an [[ExecutionContext]] which uses the current thread to execute the runnable.
     *
     * @return Direct [[ExecutionContext]] which executes runnables directly

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-yarn/src/main/java/org/apache/flink/yarn/YarnFlinkApplicationMasterRunner.java
----------------------------------------------------------------------
diff --git a/flink-yarn/src/main/java/org/apache/flink/yarn/YarnFlinkApplicationMasterRunner.java b/flink-yarn/src/main/java/org/apache/flink/yarn/YarnFlinkApplicationMasterRunner.java
index 65d12b5..a6b66d7 100644
--- a/flink-yarn/src/main/java/org/apache/flink/yarn/YarnFlinkApplicationMasterRunner.java
+++ b/flink-yarn/src/main/java/org/apache/flink/yarn/YarnFlinkApplicationMasterRunner.java
@@ -208,7 +208,7 @@ public class YarnFlinkApplicationMasterRunner extends AbstractYarnFlinkApplicati
 			resourceManagerConfiguration,
 			haServices,
 			heartbeatServices,
-			resourceManagerRuntimeServices.getSlotManagerFactory(),
+			resourceManagerRuntimeServices.getSlotManager(),
 			metricRegistry,
 			resourceManagerRuntimeServices.getJobLeaderIdService(),
 			this);

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-yarn/src/main/java/org/apache/flink/yarn/YarnResourceManager.java
----------------------------------------------------------------------
diff --git a/flink-yarn/src/main/java/org/apache/flink/yarn/YarnResourceManager.java b/flink-yarn/src/main/java/org/apache/flink/yarn/YarnResourceManager.java
index 74359c8..63e6a4c 100644
--- a/flink-yarn/src/main/java/org/apache/flink/yarn/YarnResourceManager.java
+++ b/flink-yarn/src/main/java/org/apache/flink/yarn/YarnResourceManager.java
@@ -28,12 +28,13 @@ import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
 import org.apache.flink.runtime.heartbeat.HeartbeatServices;
 import org.apache.flink.runtime.highavailability.HighAvailabilityServices;
+import org.apache.flink.runtime.instance.InstanceID;
 import org.apache.flink.runtime.metrics.MetricRegistry;
 import org.apache.flink.runtime.resourcemanager.JobLeaderIdService;
 import org.apache.flink.runtime.resourcemanager.ResourceManager;
 import org.apache.flink.runtime.resourcemanager.ResourceManagerConfiguration;
 import org.apache.flink.runtime.resourcemanager.exceptions.ResourceManagerException;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
 import org.apache.flink.runtime.rpc.FatalErrorHandler;
 import org.apache.flink.runtime.rpc.RpcService;
 import org.apache.hadoop.yarn.api.ApplicationConstants;
@@ -115,7 +116,7 @@ public class YarnResourceManager extends ResourceManager<ResourceID> implements
 			ResourceManagerConfiguration resourceManagerConfiguration,
 			HighAvailabilityServices highAvailabilityServices,
 			HeartbeatServices heartbeatServices,
-			SlotManagerFactory slotManagerFactory,
+			SlotManager slotManager,
 			MetricRegistry metricRegistry,
 			JobLeaderIdService jobLeaderIdService,
 			FatalErrorHandler fatalErrorHandler) {
@@ -126,7 +127,7 @@ public class YarnResourceManager extends ResourceManager<ResourceID> implements
 			resourceManagerConfiguration,
 			highAvailabilityServices,
 			heartbeatServices,
-			slotManagerFactory,
+			slotManager,
 			metricRegistry,
 			jobLeaderIdService,
 			fatalErrorHandler);
@@ -223,6 +224,11 @@ public class YarnResourceManager extends ResourceManager<ResourceID> implements
 	}
 
 	@Override
+	public void stopWorker(InstanceID instanceId) {
+		// TODO: Implement to stop the worker
+	}
+
+	@Override
 	protected ResourceID workerStarted(ResourceID resourceID) {
 		return resourceID;
 	}


[7/7] flink git commit: [FLINK-5810] [flip-6] Use single timeout task for SlotManager

Posted by tr...@apache.org.
[FLINK-5810] [flip-6] Use single timeout task for SlotManager


Project: http://git-wip-us.apache.org/repos/asf/flink/repo
Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/d75ec5b3
Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/d75ec5b3
Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/d75ec5b3

Branch: refs/heads/master
Commit: d75ec5b3551573d4eb1886c8e75dfdf6dc328da1
Parents: d16a5a2
Author: Till Rohrmann <tr...@apache.org>
Authored: Thu Apr 27 17:46:29 2017 +0200
Committer: Till Rohrmann <tr...@apache.org>
Committed: Fri Apr 28 15:28:26 2017 +0200

----------------------------------------------------------------------
 .../slotmanager/PendingSlotRequest.java         |  35 +--
 .../slotmanager/SlotManager.java                | 219 ++++++++------
 .../slotmanager/TaskManagerRegistration.java    |  38 +--
 .../clusterframework/ResourceManagerTest.java   |   8 +-
 .../slotmanager/SlotManagerTest.java            | 291 +++++++++----------
 .../slotmanager/SlotProtocolTest.java           |   2 -
 .../src/test/resources/log4j-test.properties    |   2 +-
 .../runtime/testingUtils/TestingUtils.scala     |   4 +-
 8 files changed, 295 insertions(+), 304 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
index 1195791..ffe1bfc 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
@@ -27,8 +27,6 @@ import org.apache.flink.runtime.resourcemanager.SlotRequest;
 import org.apache.flink.util.Preconditions;
 
 import javax.annotation.Nullable;
-import java.util.UUID;
-import java.util.concurrent.ScheduledFuture;
 
 public class PendingSlotRequest {
 
@@ -37,14 +35,12 @@ public class PendingSlotRequest {
 	@Nullable
 	private CompletableFuture<Acknowledge> requestFuture;
 
-	@Nullable
-	private UUID timeoutIdentifier;
-
-	@Nullable
-	private ScheduledFuture<?> timeoutFuture;
+	/** Timestamp when this pending slot request has been created. */
+	private final long creationTimestamp;
 
 	public PendingSlotRequest(SlotRequest slotRequest) {
 		this.slotRequest = Preconditions.checkNotNull(slotRequest);
+		creationTimestamp = System.currentTimeMillis();
 	}
 
 	// ------------------------------------------------------------------------
@@ -57,11 +53,6 @@ public class PendingSlotRequest {
 		return slotRequest.getResourceProfile();
 	}
 
-	@Nullable
-	public UUID getTimeoutIdentifier() {
-		return timeoutIdentifier;
-	}
-
 	public JobID getJobId() {
 		return slotRequest.getJobId();
 	}
@@ -70,6 +61,10 @@ public class PendingSlotRequest {
 		return slotRequest.getTargetAddress();
 	}
 
+	public long getCreationTimestamp() {
+		return creationTimestamp;
+	}
+
 	public boolean isAssigned() {
 		return null != requestFuture;
 	}
@@ -82,20 +77,4 @@ public class PendingSlotRequest {
 	public CompletableFuture<Acknowledge> getRequestFuture() {
 		return requestFuture;
 	}
-
-	public void cancelTimeout() {
-		if (timeoutFuture != null) {
-			timeoutFuture.cancel(true);
-
-			timeoutIdentifier = null;
-			timeoutFuture = null;
-		}
-	}
-
-	public void registerTimeout(ScheduledFuture<?> newTimeoutFuture, UUID newTimeoutIdentifier) {
-		cancelTimeout();
-
-		timeoutFuture = newTimeoutFuture;
-		timeoutIdentifier = newTimeoutIdentifier;
-	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
index f09b73a..829a06d 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
@@ -64,11 +64,10 @@ import java.util.concurrent.TimeoutException;
  * {@link ResourceManagerActions#allocateResource(ResourceProfile)}.
  *
  * In order to free resources and avoid resource leaks, idling task managers (task managers whose
- * slots are currently not used) and not fulfilled pending slot requests time out triggering their
- * release and failure, respectively.
+ * slots are currently not used) and pending slot requests time out triggering their release and
+ * failure, respectively.
  */
 public class SlotManager implements AutoCloseable {
-
 	private static final Logger LOG = LoggerFactory.getLogger(SlotManager.class);
 
 	/** Scheduled executor for timeouts */
@@ -107,6 +106,10 @@ public class SlotManager implements AutoCloseable {
 	/** Callbacks for resource (de-)allocations */
 	private ResourceManagerActions resourceManagerActions;
 
+	private ScheduledFuture<?> taskManagerTimeoutCheck;
+
+	private ScheduledFuture<?> slotRequestTimeoutCheck;
+
 	/** True iff the component has been started */
 	private boolean started;
 
@@ -128,6 +131,10 @@ public class SlotManager implements AutoCloseable {
 
 		leaderId = null;
 		resourceManagerActions = null;
+		mainThreadExecutor = null;
+		taskManagerTimeoutCheck = null;
+		slotRequestTimeoutCheck = null;
+
 		started = false;
 	}
 
@@ -142,17 +149,52 @@ public class SlotManager implements AutoCloseable {
 	 * @param newResourceManagerActions to use for resource (de-)allocations
 	 */
 	public void start(UUID newLeaderId, Executor newMainThreadExecutor, ResourceManagerActions newResourceManagerActions) {
+		LOG.info("Starting the SlotManager.");
+
 		leaderId = Preconditions.checkNotNull(newLeaderId);
 		mainThreadExecutor = Preconditions.checkNotNull(newMainThreadExecutor);
 		resourceManagerActions = Preconditions.checkNotNull(newResourceManagerActions);
 
 		started = true;
+
+		taskManagerTimeoutCheck = scheduledExecutor.scheduleWithFixedDelay(new Runnable() {
+			@Override
+			public void run() {
+				mainThreadExecutor.execute(new Runnable() {
+					@Override
+					public void run() {
+						checkTaskManagerTimeouts();
+					}
+				});
+			}
+		}, 0L, taskManagerTimeout.toMilliseconds(), TimeUnit.MILLISECONDS);
+
+		slotRequestTimeoutCheck = scheduledExecutor.scheduleWithFixedDelay(new Runnable() {
+			@Override
+			public void run() {
+				mainThreadExecutor.execute(new Runnable() {
+					@Override
+					public void run() {
+						checkSlotRequestTimeouts();
+					}
+				});
+			}
+		}, 0L, slotRequestTimeout.toMilliseconds(), TimeUnit.MILLISECONDS);
 	}
 
 	/**
 	 * Suspends the component. This clears the internal state of the slot manager.
 	 */
 	public void suspend() {
+		LOG.info("Suspending the SlotManager.");
+
+		// stop the timeout checks for the TaskManagers and the SlotRequests
+		taskManagerTimeoutCheck.cancel(false);
+		slotRequestTimeoutCheck.cancel(false);
+
+		taskManagerTimeoutCheck = null;
+		slotRequestTimeoutCheck = null;
+
 		for (PendingSlotRequest pendingSlotRequest : pendingSlotRequests.values()) {
 			cancelPendingSlotRequest(pendingSlotRequest);
 		}
@@ -177,6 +219,8 @@ public class SlotManager implements AutoCloseable {
 	 */
 	@Override
 	public void close() throws Exception {
+		LOG.info("Closing the SlotManager.");
+
 		suspend();
 	}
 
@@ -249,6 +293,8 @@ public class SlotManager implements AutoCloseable {
 	public void registerTaskManager(final TaskExecutorConnection taskExecutorConnection, SlotReport initialSlotReport) {
 		checkInit();
 
+		LOG.info("Register TaskManager {} at the SlotManager.", taskExecutorConnection.getInstanceID());
+
 		// we identify task managers by their instance id
 		if (taskManagerRegistrations.containsKey(taskExecutorConnection.getInstanceID())) {
 			reportSlotStatus(taskExecutorConnection.getInstanceID(), initialSlotReport);
@@ -272,8 +318,13 @@ public class SlotManager implements AutoCloseable {
 					taskExecutorConnection);
 			}
 
-			if (!anySlotUsed(taskManagerRegistration.getSlots())) {
-				registerTaskManagerTimeout(taskManagerRegistration);
+			// determine if the task manager is idle or not
+			boolean idle = !anySlotUsed(taskManagerRegistration.getSlots());
+
+			if (idle) {
+				taskManagerRegistration.markIdle();
+			} else {
+				taskManagerRegistration.markUsed();
 			}
 		}
 
@@ -292,9 +343,7 @@ public class SlotManager implements AutoCloseable {
 		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.remove(instanceId);
 
 		if (null != taskManagerRegistration) {
-			removeSlots(taskManagerRegistration.getSlots());
-
-			taskManagerRegistration.cancelTimeout();
+			internalUnregisterTaskManager(taskManagerRegistration);
 
 			return true;
 		} else {
@@ -334,8 +383,11 @@ public class SlotManager implements AutoCloseable {
 			}
 
 			if (idle) {
-				// no slot of this task manager is being used --> register timer to free this resource
-				registerTaskManagerTimeout(taskManagerRegistration);
+				// no slot of this task manager is being used --> mark this task manager to be idle which allows it to
+				// time out
+				taskManagerRegistration.markIdle();
+			} else {
+				taskManagerRegistration.markUsed();
 			}
 
 			return true;
@@ -371,9 +423,14 @@ public class SlotManager implements AutoCloseable {
 
 					TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(slot.getInstanceId());
 
-					if (null != taskManagerRegistration && !anySlotUsed(taskManagerRegistration.getSlots())) {
-						registerTaskManagerTimeout(taskManagerRegistration);
+					if (null != taskManagerRegistration) {
+						if (anySlotUsed(taskManagerRegistration.getSlots())) {
+							taskManagerRegistration.markUsed();
+						} else {
+							taskManagerRegistration.markIdle();
+						}
 					}
+
 				} else {
 					LOG.debug("Received request to free slot {} with expected allocation id {}, " +
 						"but actual allocation id {} differs. Ignoring the request.", slotId, allocationId, slot.getAllocationId());
@@ -524,8 +581,8 @@ public class SlotManager implements AutoCloseable {
 				TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(slot.getInstanceId());
 
 				if (null != taskManagerRegistration) {
-					// disable any registered time out for the task manager
-					taskManagerRegistration.cancelTimeout();
+					// mark this TaskManager to be used to exempt it from timing out
+					taskManagerRegistration.markUsed();
 				}
 			}
 
@@ -551,24 +608,6 @@ public class SlotManager implements AutoCloseable {
 		if (taskManagerSlot != null) {
 			allocateSlot(taskManagerSlot, pendingSlotRequest);
 		} else {
-			final UUID timeoutIdentifier = UUID.randomUUID();
-			final AllocationID allocationId = pendingSlotRequest.getAllocationId();
-
-			// register timeout for slot request
-			ScheduledFuture<?> timeoutFuture = scheduledExecutor.schedule(new Runnable() {
-				@Override
-				public void run() {
-					mainThreadExecutor.execute(new Runnable() {
-						@Override
-						public void run() {
-							timeoutSlotRequest(allocationId, timeoutIdentifier);
-						}
-					});
-				}
-			}, slotRequestTimeout.toMilliseconds(), TimeUnit.MILLISECONDS);
-
-			pendingSlotRequest.registerTimeout(timeoutFuture, timeoutIdentifier);
-
 			resourceManagerActions.allocateResource(pendingSlotRequest.getResourceProfile());
 		}
 	}
@@ -591,6 +630,16 @@ public class SlotManager implements AutoCloseable {
 		taskManagerSlot.setAssignedSlotRequest(pendingSlotRequest);
 		pendingSlotRequest.setRequestFuture(completableFuture);
 
+		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(taskManagerSlot.getInstanceId());
+
+		if (taskManagerRegistration != null) {
+			// mark the task manager to be used since we have a pending slot request assigned ot one of its slots
+			taskManagerRegistration.markUsed();
+		} else {
+			throw new IllegalStateException("Could not find a registered task manager for instance id " +
+				taskManagerSlot.getInstanceId() + '.');
+		}
+
 		// RPC call to the task manager
 		Future<Acknowledge> requestFuture = gateway.requestSlot(
 			slotId,
@@ -717,7 +766,7 @@ public class SlotManager implements AutoCloseable {
 			TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(taskManagerSlot.getInstanceId());
 
 			if (null != taskManagerRegistration && !anySlotUsed(taskManagerRegistration.getSlots())) {
-				registerTaskManagerTimeout(taskManagerRegistration);
+				taskManagerRegistration.markIdle();
 			}
 		} else {
 			LOG.debug("There was no slot with {} registered. Probably this slot has been already freed.", slotId);
@@ -778,8 +827,6 @@ public class SlotManager implements AutoCloseable {
 	 * @param pendingSlotRequest to cancel
 	 */
 	private void cancelPendingSlotRequest(PendingSlotRequest pendingSlotRequest) {
-		pendingSlotRequest.cancelTimeout();
-
 		CompletableFuture<Acknowledge> request = pendingSlotRequest.getRequestFuture();
 
 		if (null != request) {
@@ -791,54 +838,50 @@ public class SlotManager implements AutoCloseable {
 	// Internal timeout methods
 	// ---------------------------------------------------------------------------------------------
 
-	private void timeoutTaskManager(InstanceID instanceId, UUID timeoutIdentifier) {
-		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.remove(instanceId);
+	private void checkTaskManagerTimeouts() {
+		if (!taskManagerRegistrations.isEmpty()) {
+			long currentTime = System.currentTimeMillis();
+
+			Iterator<Map.Entry<InstanceID, TaskManagerRegistration>> taskManagerRegistrationIterator = taskManagerRegistrations.entrySet().iterator();
+
+			while (taskManagerRegistrationIterator.hasNext()) {
+				TaskManagerRegistration taskManagerRegistration = taskManagerRegistrationIterator.next().getValue();
 
-		if (null != taskManagerRegistration) {
-			if (Objects.equals(timeoutIdentifier, taskManagerRegistration.getTimeoutIdentifier())) {
 				if (anySlotUsed(taskManagerRegistration.getSlots())) {
-					LOG.debug("Cannot release the task manager with instance id {}, because some " +
-						"of its slots are still being used.", instanceId);
-				} else {
-					unregisterTaskManager(instanceId);
+					taskManagerRegistration.markUsed();
+				} else if (currentTime - taskManagerRegistration.getIdleSince() >= taskManagerTimeout.toMilliseconds()) {
+					taskManagerRegistrationIterator.remove();
 
-					resourceManagerActions.releaseResource(instanceId);
-				}
-			} else {
-				taskManagerRegistrations.put(instanceId, taskManagerRegistration);
+					internalUnregisterTaskManager(taskManagerRegistration);
 
-				LOG.debug("Expected timeout identifier {} differs from the task manager's " +
-					"timeout identifier {}. Ignoring the task manager timeout call.",
-					timeoutIdentifier, taskManagerRegistration.getTimeoutIdentifier());
+					resourceManagerActions.releaseResource(taskManagerRegistration.getInstanceId());
+				}
 			}
-		} else {
-			LOG.debug("Could not find a registered task manager with instance id {}. Ignoring the task manager timeout call.", instanceId);
 		}
 	}
 
-	private void timeoutSlotRequest(AllocationID allocationId, UUID timeoutIdentifier) {
-		PendingSlotRequest pendingSlotRequest = pendingSlotRequests.remove(allocationId);
+	private void checkSlotRequestTimeouts() {
+		if (!pendingSlotRequests.isEmpty()) {
+			long currentTime = System.currentTimeMillis();
 
-		if (null != pendingSlotRequest) {
-			if (Objects.equals(timeoutIdentifier, pendingSlotRequest.getTimeoutIdentifier())) {
-				if (!pendingSlotRequest.isAssigned()) {
+			Iterator<Map.Entry<AllocationID, PendingSlotRequest>> slotRequestIterator = pendingSlotRequests.entrySet().iterator();
+
+			while (slotRequestIterator.hasNext()) {
+				PendingSlotRequest slotRequest = slotRequestIterator.next().getValue();
+
+				if (currentTime - slotRequest.getCreationTimestamp() >= slotRequestTimeout.toMilliseconds()) {
+					slotRequestIterator.remove();
+
+					if (slotRequest.isAssigned()) {
+						cancelPendingSlotRequest(slotRequest);
+					}
 
 					resourceManagerActions.notifyAllocationFailure(
-						pendingSlotRequest.getJobId(),
-						allocationId,
+						slotRequest.getJobId(),
+						slotRequest.getAllocationId(),
 						new TimeoutException("The allocation could not be fulfilled in time."));
-				} else {
-					LOG.debug("Cannot fail pending slot request {} because it has been assigned.", allocationId);
 				}
-			} else {
-				pendingSlotRequests.put(allocationId, pendingSlotRequest);
-
-				LOG.debug("Expected timeout identifier {} differs from the pending slot request's " +
-					"timeout identifier {}. Ignoring the slot request timeout call.",
-					timeoutIdentifier, pendingSlotRequest.getTimeoutIdentifier());
 			}
-		} else {
-			LOG.debug("Could not find pending slot request with allocation id {}. Ignoring the slot request timeout call.", allocationId);
 		}
 	}
 
@@ -846,6 +889,12 @@ public class SlotManager implements AutoCloseable {
 	// Internal utility methods
 	// ---------------------------------------------------------------------------------------------
 
+	private void internalUnregisterTaskManager(TaskManagerRegistration taskManagerRegistration) {
+		Preconditions.checkNotNull(taskManagerRegistration);
+
+		removeSlots(taskManagerRegistration.getSlots());
+	}
+
 	private boolean checkDuplicateRequest(AllocationID allocationId) {
 		return pendingSlotRequests.containsKey(allocationId) || fulfilledSlotRequests.containsKey(allocationId);
 	}
@@ -853,38 +902,18 @@ public class SlotManager implements AutoCloseable {
 	private boolean anySlotUsed(Iterable<SlotID> slotsToCheck) {
 
 		if (null != slotsToCheck) {
-			boolean idle = true;
-
 			for (SlotID slotId : slotsToCheck) {
 				TaskManagerSlot taskManagerSlot = slots.get(slotId);
 
 				if (null != taskManagerSlot) {
-					idle &= taskManagerSlot.isFree();
+					if (taskManagerSlot.isAllocated()) {
+						return true;
+					}
 				}
 			}
-
-			return !idle;
-		} else {
-			return false;
 		}
-	}
-
-	private void registerTaskManagerTimeout(final TaskManagerRegistration taskManagerRegistration) {
-		final UUID timeoutIdentifier = UUID.randomUUID();
-
-		ScheduledFuture<?> timeoutFuture = scheduledExecutor.schedule(new Runnable() {
-			@Override
-			public void run() {
-				mainThreadExecutor.execute(new Runnable() {
-					@Override
-					public void run() {
-						timeoutTaskManager(taskManagerRegistration.getInstanceId(), timeoutIdentifier);
-					}
-				});
-			}
-		}, taskManagerTimeout.toMilliseconds(), TimeUnit.MILLISECONDS);
 
-		taskManagerRegistration.registerTimeout(timeoutFuture, timeoutIdentifier);
+		return false;
 	}
 
 	private void checkInit() {
@@ -911,11 +940,11 @@ public class SlotManager implements AutoCloseable {
 	}
 
 	@VisibleForTesting
-	boolean hasTimeoutRegistered(InstanceID instanceId) {
+	boolean isTaskManagerIdle(InstanceID instanceId) {
 		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(instanceId);
 
 		if (null != taskManagerRegistration) {
-			return taskManagerRegistration.getTimeoutIdentifier() != null;
+			return taskManagerRegistration.isIdle();
 		} else {
 			return false;
 		}

http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
index 3a15cb3..7d3764c 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
@@ -25,8 +25,6 @@ import org.apache.flink.util.Preconditions;
 
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.UUID;
-import java.util.concurrent.ScheduledFuture;
 
 public class TaskManagerRegistration {
 
@@ -34,9 +32,8 @@ public class TaskManagerRegistration {
 
 	private final HashSet<SlotID> slots;
 
-	private UUID timeoutIdentifier;
-
-	private ScheduledFuture<?> timeoutFuture;
+	/** Timestamp when the last time becoming idle. Otherwise Long.MAX_VALUE. */
+	private long idleSince;
 
 	public TaskManagerRegistration(
 		TaskExecutorConnection taskManagerConnection,
@@ -47,8 +44,7 @@ public class TaskManagerRegistration {
 
 		this.slots = new HashSet<>(slots);
 
-		timeoutIdentifier = null;
-		timeoutFuture = null;
+		idleSince = Long.MAX_VALUE;
 	}
 
 	public TaskExecutorConnection getTaskManagerConnection() {
@@ -59,31 +55,27 @@ public class TaskManagerRegistration {
 		return taskManagerConnection.getInstanceID();
 	}
 
-	public UUID getTimeoutIdentifier() {
-		return timeoutIdentifier;
-	}
-
 	public Iterable<SlotID> getSlots() {
 		return slots;
 	}
 
-	public boolean containsSlot(SlotID slotId) {
-		return slots.contains(slotId);
+	public long getIdleSince() {
+		return idleSince;
 	}
 
-	public void cancelTimeout() {
-		if (null != timeoutFuture) {
-			timeoutFuture.cancel(false);
+	public boolean isIdle() {
+		return idleSince != Long.MAX_VALUE;
+	}
 
-			timeoutFuture = null;
-			timeoutIdentifier = null;
-		}
+	public void markIdle() {
+		idleSince = System.currentTimeMillis();
 	}
 
-	public void registerTimeout(ScheduledFuture<?> newTimeoutFuture, UUID newTimeoutIdentifier) {
-		cancelTimeout();
+	public void markUsed() {
+		idleSince = Long.MAX_VALUE;
+	}
 
-		timeoutFuture = newTimeoutFuture;
-		timeoutIdentifier = newTimeoutIdentifier;
+	public boolean containsSlot(SlotID slotId) {
+		return slots.contains(slotId);
 	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
index 41c2e16..c740518 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
@@ -488,13 +488,17 @@ public class ResourceManagerTest extends TestLogger {
 		final ScheduledExecutor scheduledExecutor = mock(ScheduledExecutor.class);
 		final HeartbeatServices heartbeatServices = new TestingHeartbeatServices(heartbeatInterval, heartbeatTimeout, scheduledExecutor);
 
-		final TestingSlotManagerFactory slotManagerFactory = new TestingSlotManagerFactory();
 		final MetricRegistry metricRegistry = mock(MetricRegistry.class);
 		final JobLeaderIdService jobLeaderIdService = new JobLeaderIdService(
 			highAvailabilityServices,
 			rpcService.getScheduledExecutor(),
 			Time.minutes(5L));
 		final TestingFatalErrorHandler testingFatalErrorHandler = new TestingFatalErrorHandler();
+		final SlotManager slotManager = new SlotManager(
+			TestingUtils.defaultScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime());
 
 		try {
 			final StandaloneResourceManager resourceManager = new StandaloneResourceManager(
@@ -504,7 +508,7 @@ public class ResourceManagerTest extends TestLogger {
 				resourceManagerConfiguration,
 				highAvailabilityServices,
 				heartbeatServices,
-				slotManagerFactory,
+				slotManager,
 				metricRegistry,
 				jobLeaderIdService,
 				testingFatalErrorHandler);

http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
index fff2829..39c5f25 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
@@ -25,10 +25,9 @@ import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
 import org.apache.flink.runtime.clusterframework.types.TaskManagerSlot;
-import org.apache.flink.runtime.concurrent.CompletableFuture;
-import org.apache.flink.runtime.concurrent.Executors;
-import org.apache.flink.runtime.concurrent.ScheduledExecutor;
+import org.apache.flink.runtime.concurrent.*;
 import org.apache.flink.runtime.concurrent.impl.FlinkCompletableFuture;
+import org.apache.flink.runtime.concurrent.impl.FlinkFuture;
 import org.apache.flink.runtime.instance.InstanceID;
 import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
@@ -38,7 +37,6 @@ import org.apache.flink.runtime.taskexecutor.SlotReport;
 import org.apache.flink.runtime.taskexecutor.SlotStatus;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
 import org.apache.flink.runtime.taskexecutor.exceptions.SlotAllocationException;
-import org.apache.flink.runtime.taskexecutor.exceptions.SlotOccupiedException;
 import org.apache.flink.runtime.testingUtils.TestingUtils;
 import org.apache.flink.util.TestLogger;
 import org.junit.Test;
@@ -46,9 +44,11 @@ import org.mockito.ArgumentCaptor;
 
 import java.util.Arrays;
 import java.util.UUID;
+import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -648,7 +648,7 @@ public class SlotManagerTest extends TestLogger {
 	 */
 	@Test
 	public void testTaskManagerTimeout() throws Exception {
-		final long tmTimeout = 50L;
+		final long tmTimeout = 500L;
 
 		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 		final UUID leaderId = UUID.randomUUID();
@@ -661,7 +661,7 @@ public class SlotManagerTest extends TestLogger {
 		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile);
 		final SlotReport slotReport = new SlotReport(slotStatus);
 
-		final Executor mainThreadExecutor = mock(Executor.class);
+		final Executor mainThreadExecutor = TestingUtils.defaultExecutor();
 
 		try (SlotManager slotManager = new SlotManager(
 			TestingUtils.defaultScheduledExecutor(),
@@ -671,24 +671,21 @@ public class SlotManagerTest extends TestLogger {
 
 			slotManager.start(leaderId, mainThreadExecutor, resourceManagerActions);
 
-			slotManager.registerTaskManager(taskManagerConnection, slotReport);
-
-			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
-
-			verify(mainThreadExecutor, timeout(tmTimeout * 10L)).execute(runnableArgumentCaptor.capture());
+			mainThreadExecutor.execute(new Runnable() {
+				@Override
+				public void run() {
+					slotManager.registerTaskManager(taskManagerConnection, slotReport);
+				}
+			});
 
-			// the only runnable being executed by the main thread executor should be the timeout runnable
-			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
-
-			timeoutRunnable.run();
-
-			verify(resourceManagerActions, times(1)).releaseResource(eq(taskManagerConnection.getInstanceID()));
+			verify(resourceManagerActions, timeout(100L * tmTimeout).times(1))
+				.releaseResource(eq(taskManagerConnection.getInstanceID()));
 		}
 	}
 
 	/**
 	 * Tests that slot requests time out after the specified request timeout. If a slot request
-	 * times out, then the request is cancelled, removed from the slot manager and the resourc
+	 * times out, then the request is cancelled, removed from the slot manager and the resource
 	 * manager is notified about the failed allocation.
 	 */
 	@Test
@@ -703,7 +700,7 @@ public class SlotManagerTest extends TestLogger {
 		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
 		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
 
-		final Executor mainThreadExecutor = mock(Executor.class);
+		final Executor mainThreadExecutor = TestingUtils.defaultExecutor();
 
 		try (SlotManager slotManager = new SlotManager(
 			TestingUtils.defaultScheduledExecutor(),
@@ -713,21 +710,27 @@ public class SlotManagerTest extends TestLogger {
 
 			slotManager.start(leaderId, mainThreadExecutor, resourceManagerActions);
 
-			assertTrue(slotManager.registerSlotRequest(slotRequest));
-
-			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
-
-			verify(mainThreadExecutor, timeout(allocationTimeout * 10L)).execute(runnableArgumentCaptor.capture());
-
-			// the only runnable being executed by the main thread executor should be the timeout runnable
-			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
+			final AtomicReference<Exception> atomicException = new AtomicReference<>(null);
 
-			timeoutRunnable.run();
+			mainThreadExecutor.execute(new Runnable() {
+				@Override
+				public void run() {
+					try {
+						assertTrue(slotManager.registerSlotRequest(slotRequest));
+					} catch (Exception e) {
+						atomicException.compareAndSet(null, e);
+					}
+				}
+			});
 
-			verify(resourceManagerActions, times(1)).notifyAllocationFailure(
+			verify(resourceManagerActions, timeout(100L * allocationTimeout).times(1)).notifyAllocationFailure(
 				eq(jobId),
 				eq(allocationId),
 				any(TimeoutException.class));
+
+			if (atomicException.get() != null) {
+				throw atomicException.get();
+			}
 		}
 	}
 
@@ -815,6 +818,7 @@ public class SlotManagerTest extends TestLogger {
 	@Test
 	@SuppressWarnings("unchecked")
 	public void testSlotReportWhileActiveSlotRequest() throws Exception {
+		final long verifyTimeout = 1000L;
 		final UUID leaderId = UUID.randomUUID();
 		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 
@@ -842,20 +846,37 @@ public class SlotManagerTest extends TestLogger {
 		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
 		final SlotReport slotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
 
-		// we have to manually trigger the future call backs to simulate the main thread executor behaviour
-		final Executor mainThreadExecutorMock = mock(Executor.class);
+		final Executor mainThreadExecutor = TestingUtils.defaultExecutor();
 
-		try (SlotManager slotManager = new SlotManager(
+		try (final SlotManager slotManager = new SlotManager(
 			TestingUtils.defaultScheduledExecutor(),
 			TestingUtils.infiniteTime(),
 			TestingUtils.infiniteTime(),
 			TestingUtils.infiniteTime())) {
 
-			slotManager.start(leaderId, mainThreadExecutorMock, resourceManagerActions);
-
-			slotManager.registerTaskManager(taskManagerConnection, slotReport);
+			slotManager.start(leaderId, mainThreadExecutor, resourceManagerActions);
 
-			slotManager.registerSlotRequest(slotRequest);
+			Future<Void> registrationFuture = FlinkFuture.supplyAsync(new Callable<Void>() {
+				@Override
+				public Void call() throws Exception {
+					slotManager.registerTaskManager(taskManagerConnection, slotReport);
+
+					return null;
+				}
+			}, mainThreadExecutor)
+			.thenAccept(new AcceptFunction<Void>() {
+				@Override
+				public void accept(Void value) {
+					try {
+						slotManager.registerSlotRequest(slotRequest);
+					} catch (SlotManagerException e) {
+						throw new RuntimeException("Could not register slots.", e);
+					}
+				}
+			});
+
+			// check that no exception has been thrown
+			registrationFuture.get();
 
 			ArgumentCaptor<SlotID> slotIdCaptor = ArgumentCaptor.forClass(SlotID.class);
 
@@ -867,26 +888,33 @@ public class SlotManagerTest extends TestLogger {
 				eq(leaderId),
 				any(Time.class));
 
-			final SlotID requestedSlotdId = slotIdCaptor.getValue();
-			final SlotID freeSlotId = requestedSlotdId.equals(slotId1) ? slotId2 : slotId1;
+			final SlotID requestedSlotId = slotIdCaptor.getValue();
+			final SlotID freeSlotId = requestedSlotId.equals(slotId1) ? slotId2 : slotId1;
+
+			Future<Boolean> freeSlotFuture = FlinkFuture.supplyAsync(new Callable<Boolean>() {
+				@Override
+				public Boolean call() throws Exception {
+					return slotManager.getSlot(freeSlotId).isFree();
+				}
+			}, mainThreadExecutor);
 
-			assertTrue(slotManager.getSlot(freeSlotId).isFree());
+			assertTrue(freeSlotFuture.get());
 
 			final SlotStatus newSlotStatus1 = new SlotStatus(slotIdCaptor.getValue(), resourceProfile, new JobID(), new AllocationID());
 			final SlotStatus newSlotStatus2 = new SlotStatus(freeSlotId, resourceProfile);
 			final SlotReport newSlotReport = new SlotReport(Arrays.asList(newSlotStatus1, newSlotStatus2));
 
-			// this should update the slot with the pending slot request triggering the reassignment of it
-			slotManager.reportSlotStatus(taskManagerConnection.getInstanceID(), newSlotReport);
+			FlinkFuture.supplyAsync(new Callable<Void>() {
+				@Override
+				public Void call() throws Exception {
+					// this should update the slot with the pending slot request triggering the reassignment of it
+					slotManager.reportSlotStatus(taskManagerConnection.getInstanceID(), newSlotReport);
 
-			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
-			verify(mainThreadExecutorMock).execute(runnableArgumentCaptor.capture());
+					return null;
+				}
+			}, mainThreadExecutor);
 
-			Runnable requestFailureRunnable = runnableArgumentCaptor.getValue();
-
-			requestFailureRunnable.run();
-
-			verify(taskExecutorGateway, times(2)).requestSlot(
+			verify(taskExecutorGateway, timeout(verifyTimeout).times(2)).requestSlot(
 				slotIdCaptor.capture(),
 				eq(jobId),
 				eq(allocationId),
@@ -894,16 +922,18 @@ public class SlotManagerTest extends TestLogger {
 				eq(leaderId),
 				any(Time.class));
 
-			verify(mainThreadExecutorMock, times(2)).execute(runnableArgumentCaptor.capture());
-			Runnable requestSuccessRunnable = runnableArgumentCaptor.getValue();
+			final SlotID requestedSlotId2 = slotIdCaptor.getValue();
 
-			requestSuccessRunnable.run();
-
-			final SlotID requestedSlotId = slotIdCaptor.getValue();
+			assertEquals(slotId2, requestedSlotId2);
 
-			assertEquals(slotId2, requestedSlotId);
+			Future<TaskManagerSlot> requestedSlotFuture = FlinkFuture.supplyAsync(new Callable<TaskManagerSlot>() {
+				@Override
+				public TaskManagerSlot call() throws Exception {
+					return slotManager.getSlot(requestedSlotId2);
+				}
+			}, mainThreadExecutor);
 
-			TaskManagerSlot slot = slotManager.getSlot(requestedSlotId);
+			TaskManagerSlot slot = requestedSlotFuture.get();
 
 			assertTrue(slot.isAllocated());
 			assertEquals(allocationId, slot.getAllocationId());
@@ -916,11 +946,12 @@ public class SlotManagerTest extends TestLogger {
 	 */
 	@Test
 	public void testTimeoutForUnusedTaskManager() throws Exception {
-		final long taskManagerTimeout = 123456L;
+		final long taskManagerTimeout = 50L;
+		final long verifyTimeout = taskManagerTimeout * 10L;
 
 		final UUID leaderId = UUID.randomUUID();
 		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
-		final ScheduledExecutor scheduledExecutor = mock(ScheduledExecutor.class);
+		final ScheduledExecutor scheduledExecutor = TestingUtils.defaultScheduledExecutor();
 
 		final ResourceID resourceId = ResourceID.generate();
 
@@ -946,21 +977,34 @@ public class SlotManagerTest extends TestLogger {
 		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
 		final SlotReport initialSlotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
 
-		try (SlotManager slotManager = new SlotManager(
+		final Executor mainThreadExecutor = TestingUtils.defaultExecutor();
+
+		try (final SlotManager slotManager = new SlotManager(
 			scheduledExecutor,
 			TestingUtils.infiniteTime(),
 			TestingUtils.infiniteTime(),
 			Time.of(taskManagerTimeout, TimeUnit.MILLISECONDS))) {
 
-			slotManager.start(leaderId, Executors.directExecutor(), resourceManagerActions);
-
-			slotManager.registerSlotRequest(slotRequest);
+			slotManager.start(leaderId, mainThreadExecutor, resourceManagerActions);
 
-			slotManager.registerTaskManager(taskManagerConnection, initialSlotReport);
+			FlinkFuture.supplyAsync(new Callable<Void>() {
+				@Override
+				public Void call() throws Exception {
+					slotManager.registerSlotRequest(slotRequest);
+
+					return null;
+				}
+			}, mainThreadExecutor)
+			.thenAccept(new AcceptFunction<Void>() {
+				@Override
+				public void accept(Void value) {
+					slotManager.registerTaskManager(taskManagerConnection, initialSlotReport);
+				}
+			});
 
 			ArgumentCaptor<SlotID> slotIdArgumentCaptor = ArgumentCaptor.forClass(SlotID.class);
 
-			verify(taskExecutorGateway).requestSlot(
+			verify(taskExecutorGateway, timeout(verifyTimeout)).requestSlot(
 				slotIdArgumentCaptor.capture(),
 				eq(jobId),
 				eq(allocationId),
@@ -968,103 +1012,48 @@ public class SlotManagerTest extends TestLogger {
 				eq(leaderId),
 				any(Time.class));
 
-			assertFalse(slotManager.hasTimeoutRegistered(taskManagerConnection.getInstanceID()));
-
-			SlotID slotId = slotIdArgumentCaptor.getValue();
-			TaskManagerSlot slot = slotManager.getSlot(slotId);
-
-			assertTrue(slot.isAllocated());
-			assertEquals(allocationId, slot.getAllocationId());
-
-			slotManager.freeSlot(slotId, allocationId);
+			Future<Boolean> idleFuture = FlinkFuture.supplyAsync(new Callable<Boolean>() {
+				@Override
+				public Boolean call() throws Exception {
+					return slotManager.isTaskManagerIdle(taskManagerConnection.getInstanceID());
+				}
+			}, mainThreadExecutor);
 
-			assertTrue(slotManager.hasTimeoutRegistered(taskManagerConnection.getInstanceID()));
+			// check that the TaskManaer is not idle
+			assertFalse(idleFuture.get());
 
-			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
+			final SlotID slotId = slotIdArgumentCaptor.getValue();
 
-			// filter out the schedule call for the task manager which will be registered using the
-			// taskManagerTimeout value
-			verify(scheduledExecutor).schedule(runnableArgumentCaptor.capture(), eq(taskManagerTimeout), eq(TimeUnit.MILLISECONDS));
+			Future<TaskManagerSlot> slotFuture = FlinkFuture.supplyAsync(new Callable<TaskManagerSlot>() {
+				@Override
+				public TaskManagerSlot call() throws Exception {
+					return slotManager.getSlot(slotId);
+				}
+			}, mainThreadExecutor);
 
-			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
+			TaskManagerSlot slot = slotFuture.get();
 
-			timeoutRunnable.run();
-
-			verify(resourceManagerActions, times(1)).releaseResource(eq(taskManagerConnection.getInstanceID()));
-		}
-	}
-
-	/**
-	 * Tests that the slot manager re-registers a timeout for a rejected slot request.
-	 */
-	@Test
-	public void testTimeoutForRejectedSlotRequest() throws Exception {
-
-		final long slotRequestTimeout = 1337L;
-		final ScheduledExecutor scheduledExecutor = mock(ScheduledExecutor.class);
-
-		final ResourceID resourceId = ResourceID.generate();
-		final SlotID slotId = new SlotID(resourceId, 0);
-		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
-		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile);
-		final SlotReport slotReport = new SlotReport(slotStatus);
-
-		final UUID leaderId = UUID.randomUUID();
-		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
-
-		final JobID jobId = new JobID();
-		final AllocationID allocationId = new AllocationID();
-		final AllocationID allocationId2 = new AllocationID();
-		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
-
-		CompletableFuture<Acknowledge> requestFuture = new FlinkCompletableFuture<>();
-
-		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
-		when(taskExecutorGateway.requestSlot(
-			eq(slotId),
-			eq(jobId),
-			eq(allocationId),
-			anyString(),
-			eq(leaderId),
-			any(Time.class))).thenReturn(requestFuture);
-
-		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
-
-		try (SlotManager slotManager = new SlotManager(
-			scheduledExecutor,
-			TestingUtils.infiniteTime(),
-			Time.milliseconds(slotRequestTimeout),
-			TestingUtils.infiniteTime())) {
-
-			slotManager.start(leaderId, Executors.directExecutor(), resourceManagerActions);
-
-			slotManager.registerTaskManager(taskManagerConnection, slotReport);
-
-			slotManager.registerSlotRequest(slotRequest);
-
-			verify(taskExecutorGateway).requestSlot(
-				eq(slotId),
-				eq(jobId),
-				eq(allocationId),
-				anyString(),
-				eq(leaderId),
-				any(Time.class));
-
-			requestFuture.completeExceptionally(new SlotOccupiedException("Slot is already occupied", allocationId2));
-
-			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
-			verify(scheduledExecutor).schedule(runnableArgumentCaptor.capture(), eq(slotRequestTimeout), eq(TimeUnit.MILLISECONDS));
+			assertTrue(slot.isAllocated());
+			assertEquals(allocationId, slot.getAllocationId());
 
-			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
+			Future<Boolean> idleFuture2 = FlinkFuture.supplyAsync(new Callable<Void>() {
+				@Override
+				public Void call() throws Exception {
+					slotManager.freeSlot(slotId, allocationId);
 
-			timeoutRunnable.run();
+					return null;
+				}
+			}, mainThreadExecutor)
+			.thenApply(new ApplyFunction<Void, Boolean>() {
+				@Override
+				public Boolean apply(Void value) {
+					return slotManager.isTaskManagerIdle(taskManagerConnection.getInstanceID());
+				}
+			});
 
-			verify(resourceManagerActions).notifyAllocationFailure(eq(jobId), eq(allocationId), any(Exception.class));
+			assertTrue(idleFuture2.get());
 
-			TaskManagerSlot slot = slotManager.getSlot(slotId);
-
-			assertTrue(slot.isAllocated());
-			assertEquals(allocationId2, slot.getAllocationId());
+			verify(resourceManagerActions, timeout(verifyTimeout).times(1)).releaseResource(eq(taskManagerConnection.getInstanceID()));
 		}
 	}
 

http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
index c09316c..a1ab1ab 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
@@ -76,7 +76,6 @@ public class SlotProtocolTest extends TestLogger {
 	@Test
 	public void testSlotsUnavailableRequest() throws Exception {
 		final JobID jobID = new JobID();
-		final ResourceID jmResourceId = new ResourceID(jmAddress);
 
 		final UUID rmLeaderID = UUID.randomUUID();
 
@@ -133,7 +132,6 @@ public class SlotProtocolTest extends TestLogger {
 	@Test
 	public void testSlotAvailableRequest() throws Exception {
 		final JobID jobID = new JobID();
-		final ResourceID jmResourceId = new ResourceID(jmAddress);
 
 		final UUID rmLeaderID = UUID.randomUUID();
 

http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/test/resources/log4j-test.properties
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/resources/log4j-test.properties b/flink-runtime/src/test/resources/log4j-test.properties
index 7ba1633..812a256 100644
--- a/flink-runtime/src/test/resources/log4j-test.properties
+++ b/flink-runtime/src/test/resources/log4j-test.properties
@@ -16,7 +16,7 @@
 # limitations under the License.
 ################################################################################
 
-log4j.rootLogger=OFF, console
+log4j.rootLogger=DEBUG, console
 
 # -----------------------------------------------------------------------------
 # Console (use 'console')

http://git-wip-us.apache.org/repos/asf/flink/blob/d75ec5b3/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala b/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
index 03b5172..876e26b 100644
--- a/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
+++ b/flink-runtime/src/test/scala/org/apache/flink/runtime/testingUtils/TestingUtils.scala
@@ -82,7 +82,7 @@ object TestingUtils {
   def getDefaultTestingActorSystemConfig = testConfig
 
   def infiniteTime: Time = {
-    Time.milliseconds(Long.MaxValue);
+    Time.milliseconds(Integer.MAX_VALUE);
   }
   
 
@@ -113,7 +113,7 @@ object TestingUtils {
   def defaultExecutor: ScheduledExecutorService = {
     synchronized {
       if (sharedExecutorInstance == null || sharedExecutorInstance.isShutdown) {
-        sharedExecutorInstance = Executors.newSingleThreadScheduledExecutor()
+        sharedExecutorInstance = Executors.newSingleThreadScheduledExecutor();
       }
 
       sharedExecutorInstance


[5/7] flink git commit: [FLINK-5810] [flip-6] Multiple small cleanups across Resource Manager related code

Posted by tr...@apache.org.
[FLINK-5810] [flip-6] Multiple small cleanups across Resource Manager related code


Project: http://git-wip-us.apache.org/repos/asf/flink/repo
Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/759f46ea
Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/759f46ea
Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/759f46ea

Branch: refs/heads/master
Commit: 759f46ea6716e2f9da98002ed881be2fe6d7ab39
Parents: 59aefb5
Author: Stephan Ewen <se...@apache.org>
Authored: Thu Mar 16 18:53:21 2017 +0100
Committer: Till Rohrmann <tr...@apache.org>
Committed: Fri Apr 28 15:28:25 2017 +0200

----------------------------------------------------------------------
 .../types/ResourceIDRetrievable.java            |  4 +++-
 .../runtime/clusterframework/types/SlotID.java  | 20 ++++++--------------
 .../runtime/concurrent/ScheduledExecutor.java   |  2 +-
 .../flink/runtime/messages/Acknowledge.java     |  3 ++-
 .../registration/TaskExecutorConnection.java    |  7 ++++---
 .../slotmanager/PendingSlotRequest.java         | 10 +++++++++-
 .../taskexecutor/TaskExecutorGateway.java       |  2 --
 .../slotmanager/SlotProtocolTest.java           | 16 ++++++++--------
 8 files changed, 33 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceIDRetrievable.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceIDRetrievable.java b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceIDRetrievable.java
index b45d53c..e65840d 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceIDRetrievable.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceIDRetrievable.java
@@ -22,6 +22,8 @@ package org.apache.flink.runtime.clusterframework.types;
  */
 public interface ResourceIDRetrievable {
 
+	/**
+	 * Gets the ResourceID of the object.
+	 */
 	ResourceID getResourceID();
-
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/SlotID.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/SlotID.java b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/SlotID.java
index d6409b6..83c28b4 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/SlotID.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/SlotID.java
@@ -24,7 +24,11 @@ import static org.apache.flink.util.Preconditions.checkArgument;
 import static org.apache.flink.util.Preconditions.checkNotNull;
 
 /**
- * Unique identifier for a slot which located in TaskManager.
+ * Unique identifier for a slot on a TaskManager. This ID is constant across the
+ * life time of the TaskManager.
+ * 
+ * <p>In contrast, the {@link AllocationID} represents the a slot allocation and changes
+ * every time the slot is allocated by a JobManager.
  */
 public class SlotID implements ResourceIDRetrievable, Serializable {
 
@@ -66,10 +70,7 @@ public class SlotID implements ResourceIDRetrievable, Serializable {
 
 		SlotID slotID = (SlotID) o;
 
-		if (slotNumber != slotID.slotNumber) {
-			return false;
-		}
-		return resourceId.equals(slotID.resourceId);
+		return slotNumber == slotID.slotNumber && resourceId.equals(slotID.resourceId);
 	}
 
 	@Override
@@ -83,13 +84,4 @@ public class SlotID implements ResourceIDRetrievable, Serializable {
 	public String toString() {
 		return resourceId + "_" + slotNumber;
 	}
-
-	/**
-	 * Generate a random slot id.
-	 *
-	 * @return A random slot id.
-	 */
-	public static SlotID generate() {
-		return new SlotID(ResourceID.generate(), 0);
-	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/ScheduledExecutor.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/ScheduledExecutor.java b/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/ScheduledExecutor.java
index c1b47e2..d09cfc3 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/ScheduledExecutor.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/ScheduledExecutor.java
@@ -82,7 +82,7 @@ public interface ScheduledExecutor extends Executor {
 	 * @param delay the time between the end of the current and the start of the next execution
 	 * @param unit the time unit of the initial delay and the delay parameter
 	 * @return a ScheduledFuture representing the repeatedly executed task. This future never
-	 * completes unless th exectuion of the given task fails or if the future is cancelled
+	 * completes unless the execution of the given task fails or if the future is cancelled
 	 */
 	ScheduledFuture<?> scheduleWithFixedDelay(
 		Runnable command,

http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/main/java/org/apache/flink/runtime/messages/Acknowledge.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/messages/Acknowledge.java b/flink-runtime/src/main/java/org/apache/flink/runtime/messages/Acknowledge.java
index 4bbc50a..2c08ec9 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/messages/Acknowledge.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/messages/Acknowledge.java
@@ -62,8 +62,9 @@ public class Acknowledge implements Serializable {
 
 	/**
 	 * Read resolve to preserve the singleton object property.
+	 * (per best practices, this should have visibility 'protected')
 	 */
-	private Object readResolve() throws java.io.ObjectStreamException {
+	protected Object readResolve() throws java.io.ObjectStreamException {
 		return INSTANCE;
 	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java
index e4522f2..babe5b9 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java
@@ -21,6 +21,8 @@ package org.apache.flink.runtime.resourcemanager.registration;
 import org.apache.flink.runtime.instance.InstanceID;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
 
+import static org.apache.flink.util.Preconditions.checkNotNull;
+
 /**
  * This class is responsible for grouping the TaskExecutorGateway and the InstanceID
  * of a registered task executor.
@@ -29,11 +31,11 @@ public class TaskExecutorConnection {
 
 	private final InstanceID instanceID;
 
-	private TaskExecutorGateway taskExecutorGateway;
+	private final TaskExecutorGateway taskExecutorGateway;
 
 	public TaskExecutorConnection(TaskExecutorGateway taskExecutorGateway) {
 		this.instanceID = new InstanceID();
-		this.taskExecutorGateway = taskExecutorGateway;
+		this.taskExecutorGateway = checkNotNull(taskExecutorGateway);
 	}
 
 	public InstanceID getInstanceID() {
@@ -43,5 +45,4 @@ public class TaskExecutorConnection {
 	public TaskExecutorGateway getTaskExecutorGateway() {
 		return taskExecutorGateway;
 	}
-
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
index 894f146..1195791 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
@@ -26,6 +26,7 @@ import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
 import org.apache.flink.util.Preconditions;
 
+import javax.annotation.Nullable;
 import java.util.UUID;
 import java.util.concurrent.ScheduledFuture;
 
@@ -33,16 +34,21 @@ public class PendingSlotRequest {
 
 	private final SlotRequest slotRequest;
 
+	@Nullable
 	private CompletableFuture<Acknowledge> requestFuture;
 
+	@Nullable
 	private UUID timeoutIdentifier;
 
+	@Nullable
 	private ScheduledFuture<?> timeoutFuture;
 
 	public PendingSlotRequest(SlotRequest slotRequest) {
 		this.slotRequest = Preconditions.checkNotNull(slotRequest);
 	}
 
+	// ------------------------------------------------------------------------
+
 	public AllocationID getAllocationId() {
 		return slotRequest.getAllocationId();
 	}
@@ -51,6 +57,7 @@ public class PendingSlotRequest {
 		return slotRequest.getResourceProfile();
 	}
 
+	@Nullable
 	public UUID getTimeoutIdentifier() {
 		return timeoutIdentifier;
 	}
@@ -67,10 +74,11 @@ public class PendingSlotRequest {
 		return null != requestFuture;
 	}
 
-	public void setRequestFuture(CompletableFuture<Acknowledge> requestFuture) {
+	public void setRequestFuture(@Nullable CompletableFuture<Acknowledge> requestFuture) {
 		this.requestFuture = requestFuture;
 	}
 
+	@Nullable
 	public CompletableFuture<Acknowledge> getRequestFuture() {
 		return requestFuture;
 	}

http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
index bedf8ec..d4afdbd 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
@@ -31,7 +31,6 @@ import org.apache.flink.runtime.executiongraph.PartitionInfo;
 import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.rpc.RpcGateway;
 import org.apache.flink.runtime.rpc.RpcTimeout;
-import org.apache.flink.runtime.taskexecutor.exceptions.SlotAllocationException;
 import org.apache.flink.runtime.taskmanager.Task;
 
 import java.util.UUID;
@@ -47,7 +46,6 @@ public interface TaskExecutorGateway extends RpcGateway {
 	 * @param slotId slot id for the request
 	 * @param allocationId id for the request
 	 * @param resourceManagerLeaderId current leader id of the ResourceManager
-	 * @throws SlotAllocationException if the slot allocation fails
 	 * @return answer to the slot request
 	 */
 	Future<Acknowledge> requestSlot(

http://git-wip-us.apache.org/repos/asf/flink/blob/759f46ea/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
index a72969e..c09316c 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
@@ -24,6 +24,7 @@ import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
 import org.apache.flink.runtime.concurrent.Executors;
+import org.apache.flink.runtime.concurrent.ScheduledExecutor;
 import org.apache.flink.runtime.concurrent.ScheduledExecutorServiceAdapter;
 import org.apache.flink.runtime.concurrent.impl.FlinkFuture;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
@@ -33,8 +34,8 @@ import org.apache.flink.runtime.taskexecutor.SlotStatus;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
 import org.apache.flink.runtime.testingUtils.TestingUtils;
 import org.apache.flink.util.TestLogger;
+
 import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 
@@ -54,13 +55,12 @@ public class SlotProtocolTest extends TestLogger {
 
 	private static final long timeout = 10000L;
 
+	private static final ScheduledExecutorService scheduledExecutorService = 
+			new ScheduledThreadPoolExecutor(1);
 
-	private static ScheduledExecutorService scheduledExecutorService;
 
-	@BeforeClass
-	public static void beforeClass() {
-		scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
-	}
+	private static final ScheduledExecutor scheduledExecutor = 
+			new ScheduledExecutorServiceAdapter(scheduledExecutorService);
 
 	@AfterClass
 	public static void afterClass() {
@@ -81,7 +81,7 @@ public class SlotProtocolTest extends TestLogger {
 		final UUID rmLeaderID = UUID.randomUUID();
 
 		try (SlotManager slotManager = new SlotManager(
-			new ScheduledExecutorServiceAdapter(scheduledExecutorService),
+			scheduledExecutor,
 			TestingUtils.infiniteTime(),
 			TestingUtils.infiniteTime(),
 			TestingUtils.infiniteTime())) {
@@ -144,7 +144,7 @@ public class SlotProtocolTest extends TestLogger {
 			.thenReturn(mock(FlinkFuture.class));
 
 		try (SlotManager slotManager = new SlotManager(
-			new ScheduledExecutorServiceAdapter(scheduledExecutorService),
+			scheduledExecutor,
 			TestingUtils.infiniteTime(),
 			TestingUtils.infiniteTime(),
 			TestingUtils.infiniteTime())) {


[4/7] flink git commit: [FLINK-5810] [flip-6] Introduce a hardened slot manager

Posted by tr...@apache.org.
[FLINK-5810] [flip-6] Introduce a hardened slot manager

Harden the slot manager so that it better deals with lost and out of order messages
from the TaskManager. The basic idea is that the TaskManager are considered the ground
truth and the SlotManager tries to maintain a consistent view of what is reported to it
by the TaskManagers. This has the assumption that the TaskManagers regularly report their
slot status to the SlotManager piggy backed on the heartbeat signals to the ResourceManager.
That way it is possible to handle lost and out of order messages because the SlotManager
will eventually converge on a consistent view of the actual slot allocation.

Additionally, the hardened SlotManager registers for idle TaskManagers and pending slot
requests a timeout. If the timoeut expires, then the TaskManagers are released and the
slot request is failed. This prevents resource leaks and wasteful resource allocation.

This closes #3394.


Project: http://git-wip-us.apache.org/repos/asf/flink/repo
Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/59aefb57
Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/59aefb57
Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/59aefb57

Branch: refs/heads/master
Commit: 59aefb57160f04e090e6620af1dd70fd4c121ae6
Parents: f3da8f6
Author: Till Rohrmann <tr...@apache.org>
Authored: Thu Feb 9 11:59:45 2017 +0100
Committer: Till Rohrmann <tr...@apache.org>
Committed: Fri Apr 28 15:27:48 2017 +0200

----------------------------------------------------------------------
 .../clusterframework/types/ResourceSlot.java    |   72 -
 .../clusterframework/types/TaskManagerSlot.java |  114 ++
 .../flink/runtime/concurrent/Executors.java     |    2 +
 .../apache/flink/runtime/instance/SlotPool.java |   42 +-
 .../flink/runtime/jobmaster/JobMaster.java      |    2 +-
 .../resourcemanager/ResourceManager.java        |  142 +-
 .../resourcemanager/ResourceManagerGateway.java |    9 +-
 .../resourcemanager/ResourceManagerRunner.java  |    2 +-
 .../ResourceManagerRuntimeServices.java         |   25 +-
 ...urceManagerRuntimeServicesConfiguration.java |   14 +-
 .../runtime/resourcemanager/SlotRequest.java    |   14 +-
 .../StandaloneResourceManager.java              |   12 +-
 .../jobmanager/RMSlotRequestRegistered.java     |   33 -
 .../jobmanager/RMSlotRequestRejected.java       |   34 -
 .../messages/jobmanager/RMSlotRequestReply.java |   41 -
 .../taskexecutor/SlotAvailableReply.java        |   47 -
 .../taskexecutor/TMSlotRequestRegistered.java   |   35 -
 .../taskexecutor/TMSlotRequestRejected.java     |   35 -
 .../taskexecutor/TMSlotRequestReply.java        |   58 -
 .../registration/TaskExecutorConnection.java    |   47 +
 .../registration/TaskExecutorRegistration.java  |   51 -
 .../registration/WorkerRegistration.java        |    6 +-
 .../slotmanager/DefaultSlotManager.java         |   69 -
 .../slotmanager/PendingSlotRequest.java         |   93 ++
 .../slotmanager/ResourceManagerActions.java     |   34 +
 .../slotmanager/SlotManager.java                | 1086 ++++++++++-----
 .../slotmanager/SlotManagerConfiguration.java   |   74 ++
 .../slotmanager/SlotManagerException.java       |   34 +
 .../slotmanager/SlotManagerFactory.java         |   31 -
 .../slotmanager/TaskManagerRegistration.java    |   89 ++
 .../flink/runtime/taskexecutor/SlotReport.java  |   15 +-
 .../flink/runtime/taskexecutor/SlotStatus.java  |   19 +-
 .../runtime/taskexecutor/TaskExecutor.java      |   69 +-
 .../taskexecutor/TaskExecutorGateway.java       |    3 +-
 .../exceptions/SlotOccupiedException.java       |   47 +
 .../taskexecutor/slot/TaskSlotTable.java        |   10 +
 .../clusterframework/ResourceManagerTest.java   |   10 +-
 .../flink/runtime/instance/SlotPoolRpcTest.java |    2 +-
 .../flink/runtime/instance/SlotPoolTest.java    |    4 +-
 .../resourcemanager/ResourceManagerHATest.java  |   13 +-
 .../ResourceManagerJobMasterTest.java           |   12 +-
 .../ResourceManagerTaskExecutorTest.java        |   11 +-
 .../resourcemanager/TestingSlotManager.java     |   86 --
 .../TestingSlotManagerFactory.java              |   30 -
 .../slotmanager/SlotManagerTest.java            | 1254 +++++++++++++-----
 .../slotmanager/SlotProtocolTest.java           |  328 +----
 .../taskexecutor/TaskExecutorITCase.java        |   14 +-
 .../runtime/taskexecutor/TaskExecutorTest.java  |   38 +-
 .../runtime/testingUtils/TestingUtils.scala     |   12 +
 .../yarn/YarnFlinkApplicationMasterRunner.java  |    2 +-
 .../apache/flink/yarn/YarnResourceManager.java  |   12 +-
 51 files changed, 2540 insertions(+), 1798 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceSlot.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceSlot.java b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceSlot.java
deleted file mode 100644
index 0b9367d..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceSlot.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.clusterframework.types;
-
-import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorRegistration;
-
-import static org.apache.flink.util.Preconditions.checkNotNull;
-
-/**
- * A ResourceSlot represents a slot located in TaskManager from ResourceManager's view. It has a unique
- * identification and resource profile which we can compare to the resource request.
- */
-public class ResourceSlot implements ResourceIDRetrievable {
-
-	/** The unique identification of this slot */
-	private final SlotID slotId;
-
-	/** The resource profile of this slot */
-	private final ResourceProfile resourceProfile;
-
-	/** Gateway to the TaskExecutor which owns the slot */
-	private final TaskExecutorRegistration taskExecutorRegistration;
-
-	public ResourceSlot(SlotID slotId, ResourceProfile resourceProfile, TaskExecutorRegistration taskExecutorRegistration) {
-		this.slotId = checkNotNull(slotId);
-		this.resourceProfile = checkNotNull(resourceProfile);
-		this.taskExecutorRegistration = checkNotNull(taskExecutorRegistration);
-	}
-
-	@Override
-	public ResourceID getResourceID() {
-		return slotId.getResourceID();
-	}
-
-	public SlotID getSlotId() {
-		return slotId;
-	}
-
-	public ResourceProfile getResourceProfile() {
-		return resourceProfile;
-	}
-
-	public TaskExecutorRegistration getTaskExecutorRegistration() {
-		return taskExecutorRegistration;
-	}
-
-	/**
-	 * Check whether required resource profile can be matched by this slot.
-	 *
-	 * @param required The required resource profile
-	 * @return true if requirement can be matched
-	 */
-	public boolean isMatchingRequirement(ResourceProfile required) {
-		return resourceProfile.isMatching(required);
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/TaskManagerSlot.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/TaskManagerSlot.java b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/TaskManagerSlot.java
new file mode 100644
index 0000000..cb9d349
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/TaskManagerSlot.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.clusterframework.types;
+
+import org.apache.flink.runtime.instance.InstanceID;
+import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorConnection;
+import org.apache.flink.runtime.resourcemanager.slotmanager.PendingSlotRequest;
+
+import static org.apache.flink.util.Preconditions.checkNotNull;
+
+/**
+ * A TaskManagerSlot represents a slot located in a TaskManager. It has a unique identification and
+ * resource profile associated.
+ */
+public class TaskManagerSlot {
+
+	/** The unique identification of this slot */
+	private final SlotID slotId;
+
+	/** The resource profile of this slot */
+	private final ResourceProfile resourceProfile;
+
+	/** Gateway to the TaskExecutor which owns the slot */
+	private final TaskExecutorConnection taskManagerConnection;
+
+	/** Allocation id for which this slot has been allocated */
+	private AllocationID allocationId;
+
+	/** Assigned slot request if there is currently an ongoing request */
+	private PendingSlotRequest assignedSlotRequest;
+
+	public TaskManagerSlot(
+			SlotID slotId,
+			ResourceProfile resourceProfile,
+			TaskExecutorConnection taskManagerConnection,
+			AllocationID allocationId) {
+		this.slotId = checkNotNull(slotId);
+		this.resourceProfile = checkNotNull(resourceProfile);
+		this.taskManagerConnection = checkNotNull(taskManagerConnection);
+
+		this.allocationId = allocationId;
+		this.assignedSlotRequest = null;
+	}
+
+	public SlotID getSlotId() {
+		return slotId;
+	}
+
+	public ResourceProfile getResourceProfile() {
+		return resourceProfile;
+	}
+
+	public TaskExecutorConnection getTaskManagerConnection() {
+		return taskManagerConnection;
+	}
+
+	public AllocationID getAllocationId() {
+		return allocationId;
+	}
+
+	public void setAllocationId(AllocationID allocationId) {
+		this.allocationId = allocationId;
+	}
+
+	public PendingSlotRequest getAssignedSlotRequest() {
+		return assignedSlotRequest;
+	}
+
+	public void setAssignedSlotRequest(PendingSlotRequest assignedSlotRequest) {
+		this.assignedSlotRequest = assignedSlotRequest;
+	}
+
+	public InstanceID getInstanceId() {
+		return taskManagerConnection.getInstanceID();
+	}
+
+	/**
+	 * Check whether required resource profile can be matched by this slot.
+	 *
+	 * @param required The required resource profile
+	 * @return true if requirement can be matched
+	 */
+	public boolean isMatchingRequirement(ResourceProfile required) {
+		return resourceProfile.isMatching(required);
+	}
+
+	public boolean isFree() {
+		return !isAllocated() && !hasPendingSlotRequest();
+	}
+
+	public boolean isAllocated() {
+		return null != allocationId;
+	}
+
+	public boolean hasPendingSlotRequest() {
+		return null != assignedSlotRequest;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/Executors.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/Executors.java b/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/Executors.java
index 63b6a25..e8a9be9 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/Executors.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/concurrent/Executors.java
@@ -92,6 +92,8 @@ public class Executors {
 					executorService.shutdownNow();
 
 					wasInterrupted = true;
+
+					Thread.currentThread().interrupt();
 				}
 
 				timeLeft = endTime - System.currentTimeMillis();

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/instance/SlotPool.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/instance/SlotPool.java b/flink-runtime/src/main/java/org/apache/flink/runtime/instance/SlotPool.java
index 6d482b4..8cf6a9b 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/instance/SlotPool.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/instance/SlotPool.java
@@ -35,11 +35,9 @@ import org.apache.flink.runtime.jobmanager.scheduler.ScheduledUnit;
 import org.apache.flink.runtime.jobmanager.slots.AllocatedSlot;
 import org.apache.flink.runtime.jobmanager.slots.SlotAndLocality;
 import org.apache.flink.runtime.jobmanager.slots.SlotOwner;
+import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.resourcemanager.ResourceManagerGateway;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestRegistered;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestRejected;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestReply;
 import org.apache.flink.runtime.rpc.RpcEndpoint;
 import org.apache.flink.runtime.rpc.RpcMethod;
 import org.apache.flink.runtime.rpc.RpcService;
@@ -129,6 +127,8 @@ public class SlotPool extends RpcEndpoint<SlotPoolGateway> {
 	/** The gateway to communicate with resource manager */
 	private ResourceManagerGateway resourceManagerGateway;
 
+	private String jobManagerAddress;
+
 	// ------------------------------------------------------------------------
 
 	public SlotPool(RpcService rpcService, JobID jobId) {
@@ -172,10 +172,12 @@ public class SlotPool extends RpcEndpoint<SlotPoolGateway> {
 	/**
 	 * Start the slot pool to accept RPC calls.
 	 *
-	 * @param jobManagerLeaderId The necessary leader id for running the job.
+	 * @param newJobManagerLeaderId The necessary leader id for running the job.
+	 * @param newJobManagerAddress for the slot requests which are sent to the resource manager
 	 */
-	public void start(UUID jobManagerLeaderId) throws Exception {
-		this.jobManagerLeaderId = jobManagerLeaderId;
+	public void start(UUID newJobManagerLeaderId, String newJobManagerAddress) throws Exception {
+		this.jobManagerLeaderId = checkNotNull(newJobManagerLeaderId);
+		this.jobManagerAddress = checkNotNull(newJobManagerAddress);
 
 		// TODO - start should not throw an exception
 		try {
@@ -315,33 +317,15 @@ public class SlotPool extends RpcEndpoint<SlotPoolGateway> {
 
 		pendingRequests.put(allocationID, new PendingRequest(allocationID, future, resources));
 
-		Future<RMSlotRequestReply> rmResponse = resourceManagerGateway.requestSlot(
+		Future<Acknowledge> rmResponse = resourceManagerGateway.requestSlot(
 				jobManagerLeaderId, resourceManagerLeaderId,
-				new SlotRequest(jobId, allocationID, resources),
+				new SlotRequest(jobId, allocationID, resources, jobManagerAddress),
 				resourceManagerRequestsTimeout);
 
-		// on success, trigger let the slot pool know
-		Future<Void> slotRequestProcessingFuture = rmResponse.thenAcceptAsync(new AcceptFunction<RMSlotRequestReply>() {
+		Future<Void> slotRequestProcessingFuture = rmResponse.thenAcceptAsync(new AcceptFunction<Acknowledge>() {
 			@Override
-			public void accept(RMSlotRequestReply reply) {
-				if (reply.getAllocationID() != null && reply.getAllocationID().equals(allocationID)) {
-					if (reply instanceof RMSlotRequestRegistered) {
-						slotRequestToResourceManagerSuccess(allocationID);
-					}
-					else if (reply instanceof RMSlotRequestRejected) {
-						slotRequestToResourceManagerFailed(allocationID,
-								new Exception("ResourceManager rejected slot request"));
-					}
-					else {
-						slotRequestToResourceManagerFailed(allocationID, 
-								new Exception("Unknown ResourceManager response: " + reply));
-					}
-				}
-				else {
-					future.completeExceptionally(new Exception(String.format(
-							"Bug: ResourceManager response had wrong AllocationID. Request: %s , Response: %s", 
-							allocationID, reply.getAllocationID())));
-				}
+			public void accept(Acknowledge value) {
+				slotRequestToResourceManagerSuccess(allocationID);
 			}
 		}, getMainThreadExecutor());
 

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/jobmaster/JobMaster.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/jobmaster/JobMaster.java b/flink-runtime/src/main/java/org/apache/flink/runtime/jobmaster/JobMaster.java
index ab43577..99dbc86 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/jobmaster/JobMaster.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/jobmaster/JobMaster.java
@@ -345,7 +345,7 @@ public class JobMaster extends RpcEndpoint<JobMasterGateway> {
 		try {
 			// start the slot pool make sure the slot pool now accepts messages for this leader
 			log.debug("Staring SlotPool component");
-			slotPool.start(leaderSessionID);
+			slotPool.start(leaderSessionID, getAddress());
 		} catch (Exception e) {
 			log.error("Faild to start job {} ({})", jobGraph.getName(), jobGraph.getJobID(), e);
 

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManager.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManager.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManager.java
index f17dbe5..2ef8276 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManager.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManager.java
@@ -22,6 +22,7 @@ import org.apache.flink.annotation.VisibleForTesting;
 import org.apache.flink.api.common.JobID;
 import org.apache.flink.runtime.clusterframework.ApplicationStatus;
 import org.apache.flink.runtime.clusterframework.messages.InfoMessage;
+import org.apache.flink.runtime.clusterframework.types.AllocationID;
 import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
@@ -40,14 +41,13 @@ import org.apache.flink.runtime.instance.InstanceID;
 import org.apache.flink.runtime.jobmaster.JobMasterRegistrationSuccess;
 import org.apache.flink.runtime.leaderelection.LeaderContender;
 import org.apache.flink.runtime.leaderelection.LeaderElectionService;
+import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.metrics.MetricRegistry;
 import org.apache.flink.runtime.resourcemanager.exceptions.ResourceManagerException;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestRejected;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestReply;
 import org.apache.flink.runtime.resourcemanager.registration.JobManagerRegistration;
 import org.apache.flink.runtime.resourcemanager.registration.WorkerRegistration;
 import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.ResourceManagerActions;
 import org.apache.flink.runtime.rpc.FatalErrorHandler;
 import org.apache.flink.runtime.rpc.RpcEndpoint;
 import org.apache.flink.runtime.rpc.RpcMethod;
@@ -56,6 +56,7 @@ import org.apache.flink.runtime.jobmaster.JobMaster;
 import org.apache.flink.runtime.jobmaster.JobMasterGateway;
 import org.apache.flink.runtime.registration.RegistrationResponse;
 
+import org.apache.flink.runtime.rpc.exceptions.LeaderSessionIDException;
 import org.apache.flink.runtime.taskexecutor.SlotReport;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorRegistrationSuccess;
@@ -68,7 +69,6 @@ import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executor;
 import java.util.concurrent.TimeoutException;
 
 import static org.apache.flink.util.Preconditions.checkNotNull;
@@ -114,17 +114,14 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	/** The heartbeat manager with job managers. */
 	private final HeartbeatManager<Void, Void> jobManagerHeartbeatManager;
 
-	/** The factory to construct the SlotManager. */
-	private final SlotManagerFactory slotManagerFactory;
-
 	/** Registry to use for metrics */
 	private final MetricRegistry metricRegistry;
 
 	/** Fatal error handler */
 	private final FatalErrorHandler fatalErrorHandler;
 
-	/** The SlotManager created by the slotManagerFactory when the ResourceManager is started. */
-	private SlotManager slotManager;
+	/** The slot manager maintains the available slots */
+	private final SlotManager slotManager;
 
 	/** The service to elect a ResourceManager leader. */
 	private LeaderElectionService leaderElectionService;
@@ -142,7 +139,7 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 			ResourceManagerConfiguration resourceManagerConfiguration,
 			HighAvailabilityServices highAvailabilityServices,
 			HeartbeatServices heartbeatServices,
-			SlotManagerFactory slotManagerFactory,
+			SlotManager slotManager,
 			MetricRegistry metricRegistry,
 			JobLeaderIdService jobLeaderIdService,
 			FatalErrorHandler fatalErrorHandler) {
@@ -152,7 +149,7 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 		this.resourceId = checkNotNull(resourceId);
 		this.resourceManagerConfiguration = checkNotNull(resourceManagerConfiguration);
 		this.highAvailabilityServices = checkNotNull(highAvailabilityServices);
-		this.slotManagerFactory = checkNotNull(slotManagerFactory);
+		this.slotManager = checkNotNull(slotManager);
 		this.metricRegistry = checkNotNull(metricRegistry);
 		this.jobLeaderIdService = checkNotNull(jobLeaderIdService);
 		this.fatalErrorHandler = checkNotNull(fatalErrorHandler);
@@ -187,13 +184,6 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 		// start a leader
 		super.start();
 
-		try {
-			// SlotManager should start first
-			slotManager = slotManagerFactory.create(createResourceManagerServices());
-		} catch (Exception e) {
-			throw new ResourceManagerException("Could not create the slot manager.", e);
-		}
-
 		leaderElectionService = highAvailabilityServices.getResourceManagerLeaderElectionService();
 
 		try {
@@ -220,19 +210,25 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 		jobManagerHeartbeatManager.stop();
 
 		try {
-			super.shutDown();
+			slotManager.close();
 		} catch (Exception e) {
 			exception = ExceptionUtils.firstOrSuppressed(e, exception);
 		}
 
-		clearState();
-
 		try {
 			leaderElectionService.stop();
 		} catch (Exception e) {
 			exception = ExceptionUtils.firstOrSuppressed(e, exception);
 		}
 
+		try {
+			super.shutDown();
+		} catch (Exception e) {
+			exception = ExceptionUtils.firstOrSuppressed(e, exception);
+		}
+
+		clearState();
+
 		if (exception != null) {
 			ExceptionUtils.rethrowException(exception, "Error while shutting the ResourceManager down.");
 		}
@@ -397,10 +393,10 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	 */
 	@RpcMethod
 	public Future<RegistrationResponse> registerTaskExecutor(
-		final UUID resourceManagerLeaderId,
-		final String taskExecutorAddress,
+			final UUID resourceManagerLeaderId,
+			final String taskExecutorAddress,
 		final ResourceID taskExecutorResourceId,
-		final SlotReport slotReport) {
+			final SlotReport slotReport) {
 
 		if (Objects.equals(leaderSessionId, resourceManagerLeaderId)) {
 			Future<TaskExecutorGateway> taskExecutorGatewayFuture = getRpcService().connect(taskExecutorAddress, TaskExecutorGateway.class);
@@ -415,6 +411,9 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 						if (oldRegistration != null) {
 							// TODO :: suggest old taskExecutor to stop itself
 							log.info("Replacing old instance of worker for ResourceID {}", taskExecutorResourceId);
+
+							// remove old task manager registration from slot manager
+							slotManager.unregisterTaskManager(oldRegistration.getInstanceID());
 						}
 
 						WorkerType newWorker = workerStarted(taskExecutorResourceId);
@@ -422,7 +421,8 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 							new WorkerRegistration<>(taskExecutorGateway, newWorker);
 
 						taskExecutors.put(taskExecutorResourceId, registration);
-						slotManager.registerTaskExecutor(taskExecutorResourceId, registration, slotReport);
+
+						slotManager.registerTaskManager(registration, slotReport);
 
 						taskManagerHeartbeatManager.monitorTarget(taskExecutorResourceId, new HeartbeatTarget<Void>() {
 							@Override
@@ -483,26 +483,34 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	 * @return Slot assignment
 	 */
 	@RpcMethod
-	public RMSlotRequestReply requestSlot(
+	public Acknowledge requestSlot(
 			UUID jobMasterLeaderID,
 			UUID resourceManagerLeaderID,
-			SlotRequest slotRequest) {
+			SlotRequest slotRequest) throws ResourceManagerException, LeaderSessionIDException {
 
-		log.info("Request slot with profile {} for job {} with allocation id {}.",
-			slotRequest.getResourceProfile(),
-			slotRequest.getJobId(),
-			slotRequest.getAllocationId());
+		if (!Objects.equals(resourceManagerLeaderID, leaderSessionId)) {
+			throw new LeaderSessionIDException(resourceManagerLeaderID, leaderSessionId);
+		}
 
 		JobID jobId = slotRequest.getJobId();
 		JobManagerRegistration jobManagerRegistration = jobManagerRegistrations.get(jobId);
 
-		if (jobManagerRegistration != null
-				&& jobMasterLeaderID.equals(jobManagerRegistration.getLeaderID())
-				&& resourceManagerLeaderID.equals(leaderSessionId)) {
-			return slotManager.requestSlot(slotRequest);
+		if (null != jobManagerRegistration) {
+			if (Objects.equals(jobMasterLeaderID, jobManagerRegistration.getLeaderID())) {
+				log.info("Request slot with profile {} for job {} with allocation id {}.",
+					slotRequest.getResourceProfile(),
+					slotRequest.getJobId(),
+					slotRequest.getAllocationId());
+
+				slotManager.registerSlotRequest(slotRequest);
+
+				return Acknowledge.get();
+			} else {
+				throw new LeaderSessionIDException(jobMasterLeaderID, jobManagerRegistration.getLeaderID());
+			}
+
 		} else {
-			log.info("Ignoring slot request for unknown JobMaster with JobID {}", jobId);
-			return new RMSlotRequestRejected(slotRequest.getAllocationId());
+			throw new ResourceManagerException("Could not find registered job manager for job " + jobId + '.');
 		}
 	}
 
@@ -511,23 +519,23 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	 * @param resourceManagerLeaderId TaskExecutor's resource manager leader id
 	 * @param instanceID TaskExecutor's instance id
 	 * @param slotId The slot id of the available slot
-	 * @return SlotAvailableReply
 	 */
 	@RpcMethod
 	public void notifySlotAvailable(
 			final UUID resourceManagerLeaderId,
 			final InstanceID instanceID,
-			final SlotID slotId) {
+			final SlotID slotId,
+			final AllocationID allocationId) {
 
-		if (resourceManagerLeaderId.equals(leaderSessionId)) {
+		if (Objects.equals(resourceManagerLeaderId, leaderSessionId)) {
 			final ResourceID resourceId = slotId.getResourceID();
 			WorkerRegistration<WorkerType> registration = taskExecutors.get(resourceId);
 
 			if (registration != null) {
 				InstanceID registrationId = registration.getInstanceID();
 
-				if (registrationId.equals(instanceID)) {
-					slotManager.notifySlotAvailable(resourceId, slotId);
+				if (Objects.equals(registrationId, instanceID)) {
+					slotManager.freeSlot(slotId, allocationId);
 				} else {
 					log.debug("Invalid registration id for slot available message. This indicates an" +
 						" outdated request.");
@@ -587,8 +595,8 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	/**
 	 * Cleanup application and shut down cluster
 	 *
-	 * @param finalStatus
-	 * @param optionalDiagnostics
+	 * @param finalStatus of the Flink application
+	 * @param optionalDiagnostics for the Flink application
 	 */
 	@RpcMethod
 	public void shutDownCluster(final ApplicationStatus finalStatus, final String optionalDiagnostics) {
@@ -597,12 +605,12 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	}
 
 	@RpcMethod
-	public Integer getNumberOfRegisteredTaskManagers(UUID leaderSessionId) throws LeaderIdMismatchException {
-		if (this.leaderSessionId != null && this.leaderSessionId.equals(leaderSessionId)) {
+	public Integer getNumberOfRegisteredTaskManagers(UUID requestLeaderSessionId) throws LeaderIdMismatchException {
+		if (Objects.equals(leaderSessionId, requestLeaderSessionId)) {
 			return taskExecutors.size();
 		}
 		else {
-			throw new LeaderIdMismatchException(this.leaderSessionId, leaderSessionId);
+			throw new LeaderIdMismatchException(leaderSessionId, requestLeaderSessionId);
 		}
 	}
 
@@ -628,7 +636,6 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 		jobManagerRegistrations.clear();
 		jmResourceIdRegistrations.clear();
 		taskExecutors.clear();
-		slotManager.clearState();
 
 		try {
 			jobLeaderIdService.clear();
@@ -686,7 +693,7 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 			log.info("Task manager {} failed because {}.", resourceID, cause);
 
 			// TODO :: suggest failed task executor to stop itself
-			slotManager.notifyTaskManagerFailure(resourceID);
+			slotManager.unregisterTaskManager(workerRegistration.getInstanceID());
 
 			workerRegistration.getTaskExecutorGateway().disconnectResourceManager(cause);
 		} else {
@@ -702,11 +709,7 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	 * @return True if the given leader id matches the actual leader id and is not null; otherwise false
 	 */
 	protected boolean isValid(UUID resourceManagerLeaderId) {
-		if (resourceManagerLeaderId == null) {
-			return false;
-		} else {
-			return resourceManagerLeaderId.equals(leaderSessionId);
-		}
+		return Objects.equals(resourceManagerLeaderId, leaderSessionId);
 	}
 
 	protected void removeJob(JobID jobId) {
@@ -725,7 +728,7 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 		if (jobManagerRegistrations.containsKey(jobId)) {
 			JobManagerRegistration jobManagerRegistration = jobManagerRegistrations.get(jobId);
 
-			if (jobManagerRegistration.getLeaderID().equals(oldJobLeaderId)) {
+			if (Objects.equals(jobManagerRegistration.getLeaderID(), oldJobLeaderId)) {
 				disconnectJobManager(jobId, new Exception("Job leader lost leadership."));
 			} else {
 				log.debug("Discarding job leader lost leadership, because a new job leader was found for job {}. ", jobId);
@@ -806,6 +809,8 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 
 				leaderSessionId = newLeaderSessionID;
 
+				slotManager.start(leaderSessionId, getMainThreadExecutor(), new ResourceManagerActionsImpl());
+
 				getRpcService().execute(new Runnable() {
 					@Override
 					public void run() {
@@ -829,6 +834,8 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 
 				clearState();
 
+				slotManager.suspend();
+
 				leaderSessionId = null;
 			}
 		});
@@ -874,6 +881,8 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	@VisibleForTesting
 	public abstract void startNewWorker(ResourceProfile resourceProfile);
 
+	public abstract void stopWorker(InstanceID instanceId);
+
 	/**
 	 * Callback when a worker was started.
 	 * @param resourceID The worker resource id
@@ -884,30 +893,21 @@ public abstract class ResourceManager<WorkerType extends Serializable>
 	//  Static utility classes
 	// ------------------------------------------------------------------------
 
-	protected ResourceManagerServices createResourceManagerServices() {
-		return new DefaultResourceManagerServices();
-	}
-
-	private class DefaultResourceManagerServices implements ResourceManagerServices {
-
-		@Override
-		public UUID getLeaderID() {
-			return ResourceManager.this.leaderSessionId;
-		}
+	private class ResourceManagerActionsImpl implements ResourceManagerActions {
 
 		@Override
-		public void allocateResource(ResourceProfile resourceProfile) {
-			ResourceManager.this.startNewWorker(resourceProfile);
+		public void releaseResource(InstanceID instanceId) {
+			stopWorker(instanceId);
 		}
 
 		@Override
-		public Executor getAsyncExecutor() {
-			return ResourceManager.this.getRpcService().getExecutor();
+		public void allocateResource(ResourceProfile resourceProfile) throws ResourceManagerException {
+			startNewWorker(resourceProfile);
 		}
 
 		@Override
-		public Executor getMainThreadExecutor() {
-			return ResourceManager.this.getMainThreadExecutor();
+		public void notifyAllocationFailure(JobID jobId, AllocationID allocationId, Exception cause) {
+			log.info("Slot request with allocation id {} for job {} failed.", allocationId, jobId, cause);
 		}
 	}
 

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerGateway.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerGateway.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerGateway.java
index 530113f..fcbedcb 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerGateway.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerGateway.java
@@ -21,11 +21,12 @@ package org.apache.flink.runtime.resourcemanager;
 import org.apache.flink.api.common.JobID;
 import org.apache.flink.api.common.time.Time;
 import org.apache.flink.runtime.clusterframework.ApplicationStatus;
+import org.apache.flink.runtime.clusterframework.types.AllocationID;
 import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
 import org.apache.flink.runtime.concurrent.Future;
 import org.apache.flink.runtime.instance.InstanceID;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestReply;
+import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.rpc.RpcGateway;
 import org.apache.flink.runtime.rpc.RpcTimeout;
 import org.apache.flink.runtime.jobmaster.JobMaster;
@@ -66,7 +67,7 @@ public interface ResourceManagerGateway extends RpcGateway {
 	 * @param slotRequest The slot to request
 	 * @return The confirmation that the slot gets allocated
 	 */
-	Future<RMSlotRequestReply> requestSlot(
+	Future<Acknowledge> requestSlot(
 		UUID resourceManagerLeaderID,
 		UUID jobMasterLeaderID,
 		SlotRequest slotRequest,
@@ -96,11 +97,13 @@ public interface ResourceManagerGateway extends RpcGateway {
 	 * @param resourceManagerLeaderId The ResourceManager leader id
 	 * @param instanceId TaskExecutor's instance id
 	 * @param slotID The SlotID of the freed slot
+	 * @param oldAllocationId to which the slot has been allocated
 	 */
 	void notifySlotAvailable(
 		UUID resourceManagerLeaderId,
 		InstanceID instanceId,
-		SlotID slotID);
+		SlotID slotID,
+		AllocationID oldAllocationId);
 
 	/**
 	 * Registers an infoMessage listener

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRunner.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRunner.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRunner.java
index c6d64db..d0c411c 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRunner.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRunner.java
@@ -76,7 +76,7 @@ public class ResourceManagerRunner implements FatalErrorHandler {
 			resourceManagerConfiguration,
 			highAvailabilityServices,
 			heartbeatServices,
-			resourceManagerRuntimeServices.getSlotManagerFactory(),
+			resourceManagerRuntimeServices.getSlotManager(),
 			metricRegistry,
 			resourceManagerRuntimeServices.getJobLeaderIdService(),
 			this);

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServices.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServices.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServices.java
index 56edde4..ed8f1e0 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServices.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServices.java
@@ -20,8 +20,8 @@ package org.apache.flink.runtime.resourcemanager;
 
 import org.apache.flink.runtime.concurrent.ScheduledExecutor;
 import org.apache.flink.runtime.highavailability.HighAvailabilityServices;
-import org.apache.flink.runtime.resourcemanager.slotmanager.DefaultSlotManager;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerConfiguration;
 import org.apache.flink.util.Preconditions;
 
 /**
@@ -29,16 +29,16 @@ import org.apache.flink.util.Preconditions;
  */
 public class ResourceManagerRuntimeServices {
 
-	private final SlotManagerFactory slotManagerFactory;
+	private final SlotManager slotManager;
 	private final JobLeaderIdService jobLeaderIdService;
 
-	public ResourceManagerRuntimeServices(SlotManagerFactory slotManagerFactory, JobLeaderIdService jobLeaderIdService) {
-		this.slotManagerFactory = Preconditions.checkNotNull(slotManagerFactory);
+	public ResourceManagerRuntimeServices(SlotManager slotManager, JobLeaderIdService jobLeaderIdService) {
+		this.slotManager = Preconditions.checkNotNull(slotManager);
 		this.jobLeaderIdService = Preconditions.checkNotNull(jobLeaderIdService);
 	}
 
-	public SlotManagerFactory getSlotManagerFactory() {
-		return slotManagerFactory;
+	public SlotManager getSlotManager() {
+		return slotManager;
 	}
 
 	public JobLeaderIdService getJobLeaderIdService() {
@@ -58,12 +58,19 @@ public class ResourceManagerRuntimeServices {
 			HighAvailabilityServices highAvailabilityServices,
 			ScheduledExecutor scheduledExecutor) throws Exception {
 
-		final SlotManagerFactory slotManagerFactory = new DefaultSlotManager.Factory();
+		final SlotManagerConfiguration slotManagerConfiguration = configuration.getSlotManagerConfiguration();
+
+		final SlotManager slotManager = new SlotManager(
+			scheduledExecutor,
+			slotManagerConfiguration.getTaskManagerRequestTimeout(),
+			slotManagerConfiguration.getSlotRequestTimeout(),
+			slotManagerConfiguration.getTaskManagerTimeout());
+
 		final JobLeaderIdService jobLeaderIdService = new JobLeaderIdService(
 			highAvailabilityServices,
 			scheduledExecutor,
 			configuration.getJobTimeout());
 
-		return new ResourceManagerRuntimeServices(slotManagerFactory, jobLeaderIdService);
+		return new ResourceManagerRuntimeServices(slotManager, jobLeaderIdService);
 	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServicesConfiguration.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServicesConfiguration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServicesConfiguration.java
index 6de5f4d..79d1c02 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServicesConfiguration.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManagerRuntimeServicesConfiguration.java
@@ -22,6 +22,7 @@ import org.apache.flink.api.common.time.Time;
 import org.apache.flink.configuration.Configuration;
 import org.apache.flink.configuration.ResourceManagerOptions;
 import org.apache.flink.runtime.resourcemanager.exceptions.ConfigurationException;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerConfiguration;
 import org.apache.flink.util.Preconditions;
 import scala.concurrent.duration.Duration;
 
@@ -32,14 +33,21 @@ public class ResourceManagerRuntimeServicesConfiguration {
 
 	private final Time jobTimeout;
 
-	public ResourceManagerRuntimeServicesConfiguration(Time jobTimeout) {
+	private final SlotManagerConfiguration slotManagerConfiguration;
+
+	public ResourceManagerRuntimeServicesConfiguration(Time jobTimeout, SlotManagerConfiguration slotManagerConfiguration) {
 		this.jobTimeout = Preconditions.checkNotNull(jobTimeout);
+		this.slotManagerConfiguration = Preconditions.checkNotNull(slotManagerConfiguration);
 	}
 
 	public Time getJobTimeout() {
 		return jobTimeout;
 	}
 
+	public SlotManagerConfiguration getSlotManagerConfiguration() {
+		return slotManagerConfiguration;
+	}
+
 	// ---------------------------- Static methods ----------------------------------
 
 	public static ResourceManagerRuntimeServicesConfiguration fromConfiguration(Configuration configuration) throws ConfigurationException {
@@ -54,6 +62,8 @@ public class ResourceManagerRuntimeServicesConfiguration {
 				"value " + ResourceManagerOptions.JOB_TIMEOUT + '.', e);
 		}
 
-		return new ResourceManagerRuntimeServicesConfiguration(jobTimeout);
+		final SlotManagerConfiguration slotManagerConfiguration = SlotManagerConfiguration.fromConfiguration(configuration);
+
+		return new ResourceManagerRuntimeServicesConfiguration(jobTimeout, slotManagerConfiguration);
 	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/SlotRequest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/SlotRequest.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/SlotRequest.java
index 896421b..779e913 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/SlotRequest.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/SlotRequest.java
@@ -42,10 +42,18 @@ public class SlotRequest implements Serializable {
 	/** The resource profile of the required slot */
 	private final ResourceProfile resourceProfile;
 
-	public SlotRequest(JobID jobId, AllocationID allocationId, ResourceProfile resourceProfile) {
+	/** Address of the emitting job manager */
+	private final String targetAddress;
+
+	public SlotRequest(
+			JobID jobId,
+			AllocationID allocationId,
+			ResourceProfile resourceProfile,
+			String targetAddress) {
 		this.jobId = checkNotNull(jobId);
 		this.allocationId = checkNotNull(allocationId);
 		this.resourceProfile = checkNotNull(resourceProfile);
+		this.targetAddress = checkNotNull(targetAddress);
 	}
 
 	/**
@@ -71,4 +79,8 @@ public class SlotRequest implements Serializable {
 	public ResourceProfile getResourceProfile() {
 		return resourceProfile;
 	}
+
+	public String getTargetAddress() {
+		return targetAddress;
+	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/StandaloneResourceManager.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/StandaloneResourceManager.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/StandaloneResourceManager.java
index 389ca5c..a921a29 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/StandaloneResourceManager.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/StandaloneResourceManager.java
@@ -23,9 +23,10 @@ import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
 import org.apache.flink.runtime.heartbeat.HeartbeatServices;
 import org.apache.flink.runtime.highavailability.HighAvailabilityServices;
+import org.apache.flink.runtime.instance.InstanceID;
 import org.apache.flink.runtime.metrics.MetricRegistry;
 import org.apache.flink.runtime.resourcemanager.exceptions.ResourceManagerException;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
 import org.apache.flink.runtime.rpc.FatalErrorHandler;
 import org.apache.flink.runtime.rpc.RpcService;
 
@@ -44,7 +45,7 @@ public class StandaloneResourceManager extends ResourceManager<ResourceID> {
 			ResourceManagerConfiguration resourceManagerConfiguration,
 			HighAvailabilityServices highAvailabilityServices,
 			HeartbeatServices heartbeatServices,
-			SlotManagerFactory slotManagerFactory,
+			SlotManager slotManager,
 			MetricRegistry metricRegistry,
 			JobLeaderIdService jobLeaderIdService,
 			FatalErrorHandler fatalErrorHandler) {
@@ -55,7 +56,7 @@ public class StandaloneResourceManager extends ResourceManager<ResourceID> {
 			resourceManagerConfiguration,
 			highAvailabilityServices,
 			heartbeatServices,
-			slotManagerFactory,
+			slotManager,
 			metricRegistry,
 			jobLeaderIdService,
 			fatalErrorHandler);
@@ -75,6 +76,11 @@ public class StandaloneResourceManager extends ResourceManager<ResourceID> {
 	}
 
 	@Override
+	public void stopWorker(InstanceID instanceId) {
+
+	}
+
+	@Override
 	protected ResourceID workerStarted(ResourceID resourceID) {
 		return resourceID;
 	}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRegistered.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRegistered.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRegistered.java
deleted file mode 100644
index 01bc532..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRegistered.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.messages.jobmanager;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-
-/**
- * Acknowledgment by the ResourceManager for a SlotRequest from the JobManager
- */
-public class RMSlotRequestRegistered extends RMSlotRequestReply {
-
-	private static final long serialVersionUID = 4760320859275256855L;
-
-	public RMSlotRequestRegistered(AllocationID allocationID) {
-		super(allocationID);
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRejected.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRejected.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRejected.java
deleted file mode 100644
index 649d61c..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestRejected.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.messages.jobmanager;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-
-/**
- * Rejection message by the ResourceManager for a SlotRequest from the JobManager
- */
-public class RMSlotRequestRejected extends RMSlotRequestReply {
-
-	private static final long serialVersionUID = 9049346740895325144L;
-
-	public RMSlotRequestRejected(AllocationID allocationID) {
-		super(allocationID);
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestReply.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestReply.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestReply.java
deleted file mode 100644
index 66e1911..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/jobmanager/RMSlotRequestReply.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.messages.jobmanager;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-
-import java.io.Serializable;
-
-/**
- * Acknowledgment by the ResourceManager for a SlotRequest from the JobManager
- */
-public abstract class RMSlotRequestReply implements Serializable {
-
-	private static final long serialVersionUID = 42;
-
-	private final AllocationID allocationID;
-
-	public RMSlotRequestReply(AllocationID allocationID) {
-		this.allocationID = allocationID;
-	}
-
-	public AllocationID getAllocationID() {
-		return allocationID;
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/SlotAvailableReply.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/SlotAvailableReply.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/SlotAvailableReply.java
deleted file mode 100644
index f2e0105..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/SlotAvailableReply.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.flink.runtime.resourcemanager.messages.taskexecutor;
-
-import org.apache.flink.runtime.clusterframework.types.SlotID;
-
-import java.io.Serializable;
-import java.util.UUID;
-
-/**
- * Sent by the ResourceManager to the TaskExecutor confirm receipt of
- * {@code org.apache.flink.runtime.resourcemanager.ResourceManagerGateway.notifySlotAvailable}.
- */
-public class SlotAvailableReply implements Serializable {
-
-	private final UUID resourceManagerLeaderID;
-
-	private final SlotID slotID;
-
-	public SlotAvailableReply(UUID resourceManagerLeaderID, SlotID slotID) {
-		this.resourceManagerLeaderID = resourceManagerLeaderID;
-		this.slotID = slotID;
-	}
-
-	public UUID getResourceManagerLeaderID() {
-		return resourceManagerLeaderID;
-	}
-
-	public SlotID getSlotID() {
-		return slotID;
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRegistered.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRegistered.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRegistered.java
deleted file mode 100644
index c0f0f49..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRegistered.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.messages.taskexecutor;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-import org.apache.flink.runtime.clusterframework.types.ResourceID;
-import org.apache.flink.runtime.instance.InstanceID;
-
-/**
- * Acknowledgment by the TaskExecutor for a SlotRequest from the ResourceManager
- */
-public class TMSlotRequestRegistered extends TMSlotRequestReply {
-
-	private static final long serialVersionUID = 4760320859275256855L;
-
-	public TMSlotRequestRegistered(InstanceID instanceID, ResourceID resourceID, AllocationID allocationID) {
-		super(instanceID, resourceID, allocationID);
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRejected.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRejected.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRejected.java
deleted file mode 100644
index 9b10a35..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestRejected.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.messages.taskexecutor;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-import org.apache.flink.runtime.clusterframework.types.ResourceID;
-import org.apache.flink.runtime.instance.InstanceID;
-
-/**
- * Rejection by the TaskExecutor for a SlotRequest from the ResourceManager
- */
-public class TMSlotRequestRejected extends TMSlotRequestReply {
-
-	private static final long serialVersionUID = 9049346740895325144L;
-
-	public TMSlotRequestRejected(InstanceID instanceID, ResourceID resourceID, AllocationID allocationID) {
-		super(instanceID, resourceID, allocationID);
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestReply.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestReply.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestReply.java
deleted file mode 100644
index b23b6e9..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/messages/taskexecutor/TMSlotRequestReply.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.messages.taskexecutor;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-import org.apache.flink.runtime.clusterframework.types.ResourceID;
-import org.apache.flink.runtime.instance.InstanceID;
-
-import java.io.Serializable;
-
-/**
- * Acknowledgment by the TaskExecutor for a SlotRequest from the ResourceManager
- */
-public abstract class TMSlotRequestReply implements Serializable {
-
-	private static final long serialVersionUID = 42;
-
-	private final InstanceID instanceID;
-
-	private final ResourceID resourceID;
-
-	private final AllocationID allocationID;
-
-	protected TMSlotRequestReply(InstanceID instanceID, ResourceID resourceID, AllocationID allocationID) {
-		this.instanceID = instanceID;
-		this.resourceID = resourceID;
-		this.allocationID = allocationID;
-	}
-
-	public InstanceID getInstanceID() {
-		return instanceID;
-	}
-
-	public ResourceID getResourceID() {
-		return resourceID;
-	}
-
-	public AllocationID getAllocationID() {
-		return allocationID;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java
new file mode 100644
index 0000000..e4522f2
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorConnection.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.resourcemanager.registration;
+
+import org.apache.flink.runtime.instance.InstanceID;
+import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
+
+/**
+ * This class is responsible for grouping the TaskExecutorGateway and the InstanceID
+ * of a registered task executor.
+ */
+public class TaskExecutorConnection {
+
+	private final InstanceID instanceID;
+
+	private TaskExecutorGateway taskExecutorGateway;
+
+	public TaskExecutorConnection(TaskExecutorGateway taskExecutorGateway) {
+		this.instanceID = new InstanceID();
+		this.taskExecutorGateway = taskExecutorGateway;
+	}
+
+	public InstanceID getInstanceID() {
+		return instanceID;
+	}
+
+	public TaskExecutorGateway getTaskExecutorGateway() {
+		return taskExecutorGateway;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorRegistration.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorRegistration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorRegistration.java
deleted file mode 100644
index bfa9c00..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/TaskExecutorRegistration.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.registration;
-
-import org.apache.flink.runtime.instance.InstanceID;
-import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
-
-import java.io.Serializable;
-
-/**
- * This class is responsible for grouping the TaskExecutorGateway and the InstanceID
- * of a registered task executor.
- */
-public class TaskExecutorRegistration implements Serializable {
-
-	private static final long serialVersionUID = -2062957799469434614L;
-
-	private final InstanceID instanceID;
-
-	private TaskExecutorGateway taskExecutorGateway;
-
-	public TaskExecutorRegistration(TaskExecutorGateway taskExecutorGateway) {
-		this.instanceID = new InstanceID();
-		this.taskExecutorGateway = taskExecutorGateway;
-	}
-
-	public InstanceID getInstanceID() {
-		return instanceID;
-	}
-
-	public TaskExecutorGateway getTaskExecutorGateway() {
-		return taskExecutorGateway;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/WorkerRegistration.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/WorkerRegistration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/WorkerRegistration.java
index 7ee7a1f..8f949b0 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/WorkerRegistration.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/registration/WorkerRegistration.java
@@ -24,11 +24,9 @@ import org.apache.flink.util.Preconditions;
 import java.io.Serializable;
 
 /**
- * This class extends the {@link TaskExecutorRegistration}, adding the worker information.
+ * This class extends the {@link TaskExecutorConnection}, adding the worker information.
  */
-public class WorkerRegistration<WorkerType extends Serializable> extends TaskExecutorRegistration {
-
-	private static final long serialVersionUID = -2062957799469434614L;
+public class WorkerRegistration<WorkerType extends Serializable> extends TaskExecutorConnection {
 
 	private final WorkerType worker;
 

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/DefaultSlotManager.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/DefaultSlotManager.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/DefaultSlotManager.java
deleted file mode 100644
index 9508936..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/DefaultSlotManager.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager.slotmanager;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-import org.apache.flink.runtime.clusterframework.types.ResourceSlot;
-import org.apache.flink.runtime.clusterframework.types.SlotID;
-import org.apache.flink.runtime.resourcemanager.ResourceManagerServices;
-import org.apache.flink.runtime.resourcemanager.SlotRequest;
-
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * A slot manager that answers requests with slots without any special logic. The first slot
- * in the maps to match a request is chosen.
- */
-public class DefaultSlotManager extends SlotManager {
-
-	public DefaultSlotManager(ResourceManagerServices rmServices) {
-		super(rmServices);
-	}
-
-	@Override
-	protected ResourceSlot chooseSlotToUse(SlotRequest request, Map<SlotID, ResourceSlot> freeSlots) {
-		final Iterator<ResourceSlot> slotIterator = freeSlots.values().iterator();
-		if (slotIterator.hasNext()) {
-			return slotIterator.next();
-		} else {
-			return null;
-		}
-	}
-
-	@Override
-	protected SlotRequest chooseRequestToFulfill(ResourceSlot offeredSlot, Map<AllocationID, SlotRequest> pendingRequests) {
-		final Iterator<SlotRequest> requestIterator = pendingRequests.values().iterator();
-		if (requestIterator.hasNext()) {
-			return requestIterator.next();
-		} else {
-			return null;
-		}
-	}
-
-	// ------------------------------------------------------------------------
-
-	public static class Factory implements SlotManagerFactory {
-
-		@Override
-		public SlotManager create(ResourceManagerServices rmServices) {
-			return new DefaultSlotManager(rmServices);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
new file mode 100644
index 0000000..894f146
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/PendingSlotRequest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.resourcemanager.slotmanager;
+
+import org.apache.flink.api.common.JobID;
+import org.apache.flink.runtime.clusterframework.types.AllocationID;
+import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
+import org.apache.flink.runtime.concurrent.CompletableFuture;
+import org.apache.flink.runtime.messages.Acknowledge;
+import org.apache.flink.runtime.resourcemanager.SlotRequest;
+import org.apache.flink.util.Preconditions;
+
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
+
+public class PendingSlotRequest {
+
+	private final SlotRequest slotRequest;
+
+	private CompletableFuture<Acknowledge> requestFuture;
+
+	private UUID timeoutIdentifier;
+
+	private ScheduledFuture<?> timeoutFuture;
+
+	public PendingSlotRequest(SlotRequest slotRequest) {
+		this.slotRequest = Preconditions.checkNotNull(slotRequest);
+	}
+
+	public AllocationID getAllocationId() {
+		return slotRequest.getAllocationId();
+	}
+
+	public ResourceProfile getResourceProfile() {
+		return slotRequest.getResourceProfile();
+	}
+
+	public UUID getTimeoutIdentifier() {
+		return timeoutIdentifier;
+	}
+
+	public JobID getJobId() {
+		return slotRequest.getJobId();
+	}
+
+	public String getTargetAddress() {
+		return slotRequest.getTargetAddress();
+	}
+
+	public boolean isAssigned() {
+		return null != requestFuture;
+	}
+
+	public void setRequestFuture(CompletableFuture<Acknowledge> requestFuture) {
+		this.requestFuture = requestFuture;
+	}
+
+	public CompletableFuture<Acknowledge> getRequestFuture() {
+		return requestFuture;
+	}
+
+	public void cancelTimeout() {
+		if (timeoutFuture != null) {
+			timeoutFuture.cancel(true);
+
+			timeoutIdentifier = null;
+			timeoutFuture = null;
+		}
+	}
+
+	public void registerTimeout(ScheduledFuture<?> newTimeoutFuture, UUID newTimeoutIdentifier) {
+		cancelTimeout();
+
+		timeoutFuture = newTimeoutFuture;
+		timeoutIdentifier = newTimeoutIdentifier;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/ResourceManagerActions.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/ResourceManagerActions.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/ResourceManagerActions.java
new file mode 100644
index 0000000..c8b288e
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/ResourceManagerActions.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.resourcemanager.slotmanager;
+
+import org.apache.flink.api.common.JobID;
+import org.apache.flink.runtime.clusterframework.types.AllocationID;
+import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
+import org.apache.flink.runtime.instance.InstanceID;
+import org.apache.flink.runtime.resourcemanager.exceptions.ResourceManagerException;
+
+public interface ResourceManagerActions {
+
+	void releaseResource(InstanceID instanceId);
+
+	void allocateResource(ResourceProfile resourceProfile) throws ResourceManagerException;
+
+	void notifyAllocationFailure(JobID jobId, AllocationID allocationId, Exception cause);
+}


[6/7] flink git commit: [FLINK-5810] [flip-6] Make slot registration static

Posted by tr...@apache.org.
[FLINK-5810] [flip-6] Make slot registration static


Project: http://git-wip-us.apache.org/repos/asf/flink/repo
Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/d16a5a29
Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/d16a5a29
Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/d16a5a29

Branch: refs/heads/master
Commit: d16a5a297008fc9665889dd56e24ff81472db2c6
Parents: 759f46e
Author: Till Rohrmann <tr...@apache.org>
Authored: Thu Apr 27 15:53:36 2017 +0200
Committer: Till Rohrmann <tr...@apache.org>
Committed: Fri Apr 28 15:28:26 2017 +0200

----------------------------------------------------------------------
 .../slotmanager/SlotManager.java                | 76 +++++++++++---------
 .../slotmanager/TaskManagerRegistration.java    | 22 +++---
 .../flink/runtime/taskexecutor/SlotReport.java  |  4 --
 .../slotmanager/SlotManagerTest.java            | 30 ++++----
 4 files changed, 70 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flink/blob/d16a5a29/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
index 31edbf3..f09b73a 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
@@ -250,12 +250,33 @@ public class SlotManager implements AutoCloseable {
 		checkInit();
 
 		// we identify task managers by their instance id
-		if (!taskManagerRegistrations.containsKey(taskExecutorConnection.getInstanceID())) {
-			TaskManagerRegistration taskManagerRegistration = new TaskManagerRegistration(taskExecutorConnection);
+		if (taskManagerRegistrations.containsKey(taskExecutorConnection.getInstanceID())) {
+			reportSlotStatus(taskExecutorConnection.getInstanceID(), initialSlotReport);
+		} else {
+			// first register the TaskManager
+			ArrayList<SlotID> reportedSlots = new ArrayList<>();
+
+			for (SlotStatus slotStatus : initialSlotReport) {
+				reportedSlots.add(slotStatus.getSlotID());
+			}
+
+			TaskManagerRegistration taskManagerRegistration = new TaskManagerRegistration(taskExecutorConnection, reportedSlots);
 			taskManagerRegistrations.put(taskExecutorConnection.getInstanceID(), taskManagerRegistration);
+
+			// next register the new slots
+			for (SlotStatus slotStatus : initialSlotReport) {
+				registerSlot(
+					slotStatus.getSlotID(),
+					slotStatus.getAllocationID(),
+					slotStatus.getResourceProfile(),
+					taskExecutorConnection);
+			}
+
+			if (!anySlotUsed(taskManagerRegistration.getSlots())) {
+				registerTaskManagerTimeout(taskManagerRegistration);
+			}
 		}
 
-		reportSlotStatus(taskExecutorConnection.getInstanceID(), initialSlotReport);
 	}
 
 	/**
@@ -296,31 +317,22 @@ public class SlotManager implements AutoCloseable {
 		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(instanceId);
 
 		if (null != taskManagerRegistration) {
-			ArrayList<SlotID> slotsToRemove = new ArrayList<>(taskManagerRegistration.getSlots());
 			boolean idle = true;
 
 			for (SlotStatus slotStatus : slotReport) {
-				if (slotsToRemove.remove(slotStatus.getSlotID())) {
-					// slot which was already registered
-					updateSlot(slotStatus.getSlotID(), slotStatus.getAllocationID());
+
+				// We assume that the slots of a TaskManager don't change over its lifetime and they are registered
+				// once when the TaskManager is registered
+				if (taskManagerRegistration.containsSlot(slotStatus.getSlotID()) && updateSlot(slotStatus.getSlotID(), slotStatus.getAllocationID())) {
+					TaskManagerSlot slot = slots.get(slotStatus.getSlotID());
+					idle &= slot.isFree();
 				} else {
-					// new slot
-					registerSlot(
-						taskManagerRegistration,
-						slotStatus.getSlotID(),
-						slotStatus.getAllocationID(),
-						slotStatus.getResourceProfile(),
-						taskManagerRegistration.getTaskManagerConnection());
+					// sanity check to guarantee that slots of a TaskManager don't change
+					throw new IllegalStateException("Reported a slot status for slot " +  slotStatus.getSlotID() +
+						" which has not been registered.");
 				}
-
-				TaskManagerSlot slot = slots.get(slotStatus.getSlotID());
-
-				idle &= slot.isFree();
 			}
 
-			// remove the slots for which we haven't received a slot status message
-			removeSlots(slotsToRemove);
-
 			if (idle) {
 				// no slot of this task manager is being used --> register timer to free this resource
 				registerTaskManagerTimeout(taskManagerRegistration);
@@ -439,20 +451,21 @@ public class SlotManager implements AutoCloseable {
 	 * the given slot id. The given resource profile defines the available resources for the slot.
 	 * The task manager connection can be used to communicate with the task manager.
 	 *
-	 * @param taskManagerRegistration Task manager for which to register the given slot
 	 * @param slotId identifying the slot on the task manager
 	 * @param allocationId which is currently deployed in the slot
 	 * @param resourceProfile of the slot
 	 * @param taskManagerConnection to communicate with the remote task manager
 	 */
 	private void registerSlot(
-			TaskManagerRegistration taskManagerRegistration,
 			SlotID slotId,
 			AllocationID allocationId,
 			ResourceProfile resourceProfile,
 			TaskExecutorConnection taskManagerConnection) {
 
-		Preconditions.checkNotNull(taskManagerRegistration);
+		if (slots.containsKey(slotId)) {
+			// remove the old slot first
+			removeSlot(slotId);
+		}
 
 		TaskManagerSlot slot = new TaskManagerSlot(
 			slotId,
@@ -462,8 +475,6 @@ public class SlotManager implements AutoCloseable {
 
 		slots.put(slotId, slot);
 
-		taskManagerRegistration.addSlot(slotId);
-
 		if (slot.isFree()) {
 			handleFreeSlot(slot);
 		}
@@ -478,8 +489,9 @@ public class SlotManager implements AutoCloseable {
 	 *
 	 * @param slotId to update
 	 * @param allocationId specifying the current allocation of the slot
+	 * @return True if the slot could be updated; otherwise false
 	 */
-	private void updateSlot(SlotID slotId, AllocationID allocationId) {
+	private boolean updateSlot(SlotID slotId, AllocationID allocationId) {
 		TaskManagerSlot slot = slots.get(slotId);
 
 		if (null != slot) {
@@ -516,8 +528,12 @@ public class SlotManager implements AutoCloseable {
 					taskManagerRegistration.cancelTimeout();
 				}
 			}
+
+			return true;
 		} else {
 			LOG.debug("Trying to update unknown slot with slot id {}.", slotId);
+
+			return false;
 		}
 	}
 
@@ -670,12 +686,6 @@ public class SlotManager implements AutoCloseable {
 			AllocationID oldAllocationId = slot.getAllocationId();
 
 			fulfilledSlotRequests.remove(oldAllocationId);
-
-			TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(slot.getInstanceId());
-
-			if (null != taskManagerRegistration) {
-				taskManagerRegistration.removeSlot(slotId);
-			}
 		} else {
 			LOG.debug("There was no slot registered with slot id {}.", slotId);
 		}

http://git-wip-us.apache.org/repos/asf/flink/blob/d16a5a29/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
index 8e23dbb..3a15cb3 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
@@ -23,8 +23,8 @@ import org.apache.flink.runtime.instance.InstanceID;
 import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorConnection;
 import org.apache.flink.util.Preconditions;
 
+import java.util.Collection;
 import java.util.HashSet;
-import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ScheduledFuture;
 
@@ -38,10 +38,14 @@ public class TaskManagerRegistration {
 
 	private ScheduledFuture<?> timeoutFuture;
 
-	public TaskManagerRegistration(TaskExecutorConnection taskManagerConnection) {
-		this.taskManagerConnection = Preconditions.checkNotNull(taskManagerConnection);
+	public TaskManagerRegistration(
+		TaskExecutorConnection taskManagerConnection,
+		Collection<SlotID> slots) {
 
-		slots = new HashSet<>(4);
+		this.taskManagerConnection = Preconditions.checkNotNull(taskManagerConnection, "taskManagerConnection");
+		Preconditions.checkNotNull(slots, "slots");
+
+		this.slots = new HashSet<>(slots);
 
 		timeoutIdentifier = null;
 		timeoutFuture = null;
@@ -59,16 +63,12 @@ public class TaskManagerRegistration {
 		return timeoutIdentifier;
 	}
 
-	public Set<SlotID> getSlots() {
+	public Iterable<SlotID> getSlots() {
 		return slots;
 	}
 
-	public boolean removeSlot(SlotID slotId) {
-		return slots.remove(slotId);
-	}
-
-	public void addSlot(SlotID slotId) {
-		slots.add(slotId);
+	public boolean containsSlot(SlotID slotId) {
+		return slots.contains(slotId);
 	}
 
 	public void cancelTimeout() {

http://git-wip-us.apache.org/repos/asf/flink/blob/d16a5a29/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
index 7a9da28..94ecaff 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
@@ -49,10 +49,6 @@ public class SlotReport implements Serializable, Iterable<SlotStatus> {
 		this.slotsStatus = checkNotNull(slotsStatus);
 	}
 
-	public Collection<SlotStatus> getSlotsStatus() {
-		return slotsStatus;
-	}
-
 	@Override
 	public Iterator<SlotStatus> iterator() {
 		return slotsStatus.iterator();

http://git-wip-us.apache.org/repos/asf/flink/blob/d16a5a29/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
index b0b5d32..fff2829 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
@@ -587,8 +587,7 @@ public class SlotManagerTest extends TestLogger {
 
 	/**
 	 * Tests that slots are updated with respect to the latest incoming slot report. This means that
-	 * slot for which not report has been received will be removed and those for which a report was
-	 * received are updated accordingly.
+	 * slots for which a report was received are updated accordingly.
 	 */
 	@Test
 	public void testUpdateSlotReport() throws Exception {
@@ -601,7 +600,6 @@ public class SlotManagerTest extends TestLogger {
 		final ResourceID resourceId = ResourceID.generate();
 		final SlotID slotId1 = new SlotID(resourceId, 0);
 		final SlotID slotId2 = new SlotID(resourceId, 1);
-		final SlotID slotId3 = new SlotID(resourceId, 2);
 
 
 		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
@@ -609,10 +607,9 @@ public class SlotManagerTest extends TestLogger {
 		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
 
 		final SlotStatus newSlotStatus2 = new SlotStatus(slotId2, resourceProfile, jobId, allocationId);
-		final SlotStatus slotStatus3 = new SlotStatus(slotId3, resourceProfile);
 
 		final SlotReport slotReport1 = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
-		final SlotReport slotReport2 = new SlotReport(Arrays.asList(newSlotStatus2, slotStatus3));
+		final SlotReport slotReport2 = new SlotReport(Arrays.asList(newSlotStatus2, slotStatus1));
 
 		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
 		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
@@ -623,20 +620,21 @@ public class SlotManagerTest extends TestLogger {
 
 			slotManager.registerTaskManager(taskManagerConnection, slotReport1);
 
-			TaskManagerSlot slot = slotManager.getSlot(slotId2);
+			TaskManagerSlot slot1 = slotManager.getSlot(slotId1);
+			TaskManagerSlot slot2 = slotManager.getSlot(slotId2);
 
 			assertTrue(2 == slotManager.getNumberRegisteredSlots());
 
-			assertTrue(slot.isFree());
+			assertTrue(slot1.isFree());
+			assertTrue(slot2.isFree());
 
 			assertTrue(slotManager.reportSlotStatus(taskManagerConnection.getInstanceID(), slotReport2));
 
 			assertTrue(2 == slotManager.getNumberRegisteredSlots());
 
 			// the slot manager should have removed slotId1
-			assertNull(slotManager.getSlot(slotId1));
-
-			assertNotNull(slotManager.getSlot(slotId3));
+			assertNotNull(slotManager.getSlot(slotId1));
+			assertNotNull(slotManager.getSlot(slotId2));
 
 			// slotId2 should have been allocated for allocationId
 			assertEquals(allocationId, slotManager.getSlot(slotId2).getAllocationId());
@@ -840,7 +838,6 @@ public class SlotManagerTest extends TestLogger {
 		final ResourceID resourceId = ResourceID.generate();
 		final SlotID slotId1 = new SlotID(resourceId, 0);
 		final SlotID slotId2 = new SlotID(resourceId, 1);
-		final SlotID slotId3 = new SlotID(resourceId, 2);
 		final SlotStatus slotStatus1 = new SlotStatus(slotId1, resourceProfile);
 		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
 		final SlotReport slotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
@@ -870,11 +867,16 @@ public class SlotManagerTest extends TestLogger {
 				eq(leaderId),
 				any(Time.class));
 
+			final SlotID requestedSlotdId = slotIdCaptor.getValue();
+			final SlotID freeSlotId = requestedSlotdId.equals(slotId1) ? slotId2 : slotId1;
+
+			assertTrue(slotManager.getSlot(freeSlotId).isFree());
+
 			final SlotStatus newSlotStatus1 = new SlotStatus(slotIdCaptor.getValue(), resourceProfile, new JobID(), new AllocationID());
-			final SlotStatus newSlotStatus2 = new SlotStatus(slotId3, resourceProfile);
+			final SlotStatus newSlotStatus2 = new SlotStatus(freeSlotId, resourceProfile);
 			final SlotReport newSlotReport = new SlotReport(Arrays.asList(newSlotStatus1, newSlotStatus2));
 
-			// this should remove the unused slot, replacing it with slotId3 and retry the pending slot request
+			// this should update the slot with the pending slot request triggering the reassignment of it
 			slotManager.reportSlotStatus(taskManagerConnection.getInstanceID(), newSlotReport);
 
 			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
@@ -899,7 +901,7 @@ public class SlotManagerTest extends TestLogger {
 
 			final SlotID requestedSlotId = slotIdCaptor.getValue();
 
-			assertEquals(slotId3, requestedSlotId);
+			assertEquals(slotId2, requestedSlotId);
 
 			TaskManagerSlot slot = slotManager.getSlot(requestedSlotId);
 


[2/7] flink git commit: [FLINK-5810] [flip-6] Introduce a hardened slot manager

Posted by tr...@apache.org.
http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerTaskExecutorTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerTaskExecutorTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerTaskExecutorTest.java
index bae7086..85b7eb4 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerTaskExecutorTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerTaskExecutorTest.java
@@ -26,12 +26,14 @@ import org.apache.flink.runtime.heartbeat.HeartbeatServices;
 import org.apache.flink.runtime.highavailability.TestingHighAvailabilityServices;
 import org.apache.flink.runtime.leaderelection.TestingLeaderElectionService;
 import org.apache.flink.runtime.metrics.MetricRegistry;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
 import org.apache.flink.runtime.rpc.FatalErrorHandler;
 import org.apache.flink.runtime.rpc.TestingSerialRpcService;
 import org.apache.flink.runtime.registration.RegistrationResponse;
 import org.apache.flink.runtime.taskexecutor.SlotReport;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorRegistrationSuccess;
+import org.apache.flink.runtime.testingUtils.TestingUtils;
 import org.apache.flink.runtime.util.TestingFatalErrorHandler;
 import org.apache.flink.util.TestLogger;
 import org.junit.After;
@@ -152,10 +154,15 @@ public class ResourceManagerTaskExecutorTest extends TestLogger {
 		TestingHighAvailabilityServices highAvailabilityServices = new TestingHighAvailabilityServices();
 		HeartbeatServices heartbeatServices = new HeartbeatServices(5L, 5L);
 		highAvailabilityServices.setResourceManagerLeaderElectionService(rmLeaderElectionService);
-		TestingSlotManagerFactory slotManagerFactory = new TestingSlotManagerFactory();
 		ResourceManagerConfiguration resourceManagerConfiguration = new ResourceManagerConfiguration(
 			Time.seconds(5L),
 			Time.seconds(5L));
+			
+		SlotManager slotManager = new SlotManager(
+			rpcService.getScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime());
 
 		MetricRegistry metricRegistry = mock(MetricRegistry.class);
 		JobLeaderIdService jobLeaderIdService = new JobLeaderIdService(
@@ -171,7 +178,7 @@ public class ResourceManagerTaskExecutorTest extends TestLogger {
 				resourceManagerConfiguration,
 				highAvailabilityServices,
 				heartbeatServices,
-				slotManagerFactory,
+				slotManager,
 				metricRegistry,
 				jobLeaderIdService,
 				fatalErrorHandler);

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManager.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManager.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManager.java
deleted file mode 100644
index 67b208d..0000000
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManager.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.flink.runtime.resourcemanager;
-
-import org.apache.flink.runtime.clusterframework.types.AllocationID;
-import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
-import org.apache.flink.runtime.clusterframework.types.ResourceSlot;
-import org.apache.flink.runtime.clusterframework.types.SlotID;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
-import org.mockito.Mockito;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-
-public class TestingSlotManager extends SlotManager {
-
-	public TestingSlotManager() {
-		this(new TestingResourceManagerServices());
-	}
-
-	public TestingSlotManager(ResourceManagerServices rmServices) {
-		super(rmServices);
-	}
-
-	@Override
-	protected ResourceSlot chooseSlotToUse(SlotRequest request, Map<SlotID, ResourceSlot> freeSlots) {
-		final Iterator<ResourceSlot> slotIterator = freeSlots.values().iterator();
-		if (slotIterator.hasNext()) {
-			return slotIterator.next();
-		} else {
-			return null;
-		}
-	}
-
-	@Override
-	protected SlotRequest chooseRequestToFulfill(ResourceSlot offeredSlot, Map<AllocationID, SlotRequest> pendingRequests) {
-		final Iterator<SlotRequest> requestIterator = pendingRequests.values().iterator();
-		if (requestIterator.hasNext()) {
-			return requestIterator.next();
-		} else {
-			return null;
-		}
-	}
-
-	private static class TestingResourceManagerServices implements ResourceManagerServices {
-
-		private final UUID leaderID = UUID.randomUUID();
-
-		@Override
-		public UUID getLeaderID() {
-			return leaderID;
-		}
-
-		@Override
-		public void allocateResource(ResourceProfile resourceProfile) {
-
-		}
-
-		@Override
-		public Executor getAsyncExecutor() {
-			return Mockito.mock(Executor.class);
-		}
-
-		@Override
-		public Executor getMainThreadExecutor() {
-			return Mockito.mock(Executor.class);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManagerFactory.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManagerFactory.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManagerFactory.java
deleted file mode 100644
index 6b5f6b2..0000000
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/TestingSlotManagerFactory.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.flink.runtime.resourcemanager;
-
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
-
-public class TestingSlotManagerFactory implements SlotManagerFactory {
-
-	@Override
-	public SlotManager create(ResourceManagerServices rmServices) {
-		return new TestingSlotManager(rmServices);
-	}
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
index 041747d..b0b5d32 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerTest.java
@@ -23,510 +23,1058 @@ import org.apache.flink.api.common.time.Time;
 import org.apache.flink.runtime.clusterframework.types.AllocationID;
 import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
-import org.apache.flink.runtime.clusterframework.types.ResourceSlot;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
+import org.apache.flink.runtime.clusterframework.types.TaskManagerSlot;
+import org.apache.flink.runtime.concurrent.CompletableFuture;
+import org.apache.flink.runtime.concurrent.Executors;
+import org.apache.flink.runtime.concurrent.ScheduledExecutor;
 import org.apache.flink.runtime.concurrent.impl.FlinkCompletableFuture;
-import org.apache.flink.runtime.resourcemanager.ResourceManagerServices;
+import org.apache.flink.runtime.instance.InstanceID;
+import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestReply;
-import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorRegistration;
+import org.apache.flink.runtime.resourcemanager.exceptions.ResourceManagerException;
+import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorConnection;
 import org.apache.flink.runtime.taskexecutor.SlotReport;
 import org.apache.flink.runtime.taskexecutor.SlotStatus;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
-import org.junit.BeforeClass;
+import org.apache.flink.runtime.taskexecutor.exceptions.SlotAllocationException;
+import org.apache.flink.runtime.taskexecutor.exceptions.SlotOccupiedException;
+import org.apache.flink.runtime.testingUtils.TestingUtils;
+import org.apache.flink.util.TestLogger;
 import org.junit.Test;
-import org.mockito.Mockito;
+import org.mockito.ArgumentCaptor;
 
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.Arrays;
 import java.util.UUID;
 import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class SlotManagerTest extends TestLogger {
 
-public class SlotManagerTest {
-
-	private static final double DEFAULT_TESTING_CPU_CORES = 1.0;
+	/**
+	 * Tests that we can register task manager and their slots at the slot manager.
+	 */
+	@Test
+	public void testTaskManagerRegistration() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 
-	private static final int DEFAULT_TESTING_MEMORY = 512;
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
 
-	private static final ResourceProfile DEFAULT_TESTING_PROFILE =
-		new ResourceProfile(DEFAULT_TESTING_CPU_CORES, DEFAULT_TESTING_MEMORY);
+		ResourceID resourceId = ResourceID.generate();
+		final SlotID slotId1 = new SlotID(resourceId, 0);
+		final SlotID slotId2 = new SlotID(resourceId, 1);
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotStatus slotStatus1 = new SlotStatus(slotId1, resourceProfile);
+		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
+		final SlotReport slotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
 
-	private static final ResourceProfile DEFAULT_TESTING_BIG_PROFILE =
-		new ResourceProfile(DEFAULT_TESTING_CPU_CORES * 2, DEFAULT_TESTING_MEMORY * 2);
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
 
-	private static TaskExecutorRegistration taskExecutorRegistration;
+			assertTrue("The number registered slots does not equal the expected number.",2 == slotManager.getNumberRegisteredSlots());
 
-	@BeforeClass
-	public static void setUp() {
-		taskExecutorRegistration = Mockito.mock(TaskExecutorRegistration.class);
-		TaskExecutorGateway gateway = Mockito.mock(TaskExecutorGateway.class);
-		Mockito.when(taskExecutorRegistration.getTaskExecutorGateway()).thenReturn(gateway);
-		Mockito.when(gateway.requestSlot(any(SlotID.class), any(JobID.class), any(AllocationID.class), any(String.class), any(UUID.class), any(Time.class)))
-			.thenReturn(new FlinkCompletableFuture<TMSlotRequestReply>());
+			assertNotNull(slotManager.getSlot(slotId1));
+			assertNotNull(slotManager.getSlot(slotId2));
+		}
 	}
 
 	/**
-	 * Tests that there are no free slots when we request, need to allocate from cluster manager master
+	 * Tests that un-registration of task managers will free and remove all registered slots.
 	 */
 	@Test
-	public void testRequestSlotWithoutFreeSlot() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE));
-
-		assertEquals(0, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(1, slotManager.getPendingRequestCount());
-		assertEquals(1, slotManager.getAllocatedContainers().size());
-		assertEquals(DEFAULT_TESTING_PROFILE, slotManager.getAllocatedContainers().get(0));
+	public void testTaskManagerUnregistration() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final JobID jobId = new JobID();
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			any(SlotID.class),
+			any(JobID.class),
+			any(AllocationID.class),
+			anyString(),
+			eq(leaderId),
+			any(Time.class))).thenReturn(new FlinkCompletableFuture<Acknowledge>());
+
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		ResourceID resourceId = ResourceID.generate();
+		final SlotID slotId1 = new SlotID(resourceId, 0);
+		final SlotID slotId2 = new SlotID(resourceId, 1);
+		final AllocationID allocationId1 = new AllocationID();
+		final AllocationID allocationId2 = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotStatus slotStatus1 = new SlotStatus(slotId1, resourceProfile, jobId, allocationId1);
+		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
+		final SlotReport slotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
+
+		final SlotRequest slotRequest = new SlotRequest(
+			new JobID(),
+			allocationId2,
+			resourceProfile,
+			"foobar");
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
+
+			assertTrue("The number registered slots does not equal the expected number.",2 == slotManager.getNumberRegisteredSlots());
+
+			TaskManagerSlot slot1 = slotManager.getSlot(slotId1);
+			TaskManagerSlot slot2 = slotManager.getSlot(slotId2);
+
+			assertTrue(slot1.isAllocated());
+			assertTrue(slot2.isFree());
+
+			assertTrue(slotManager.registerSlotRequest(slotRequest));
+
+			assertFalse(slot2.isFree());
+			assertTrue(slot2.hasPendingSlotRequest());
+
+			PendingSlotRequest pendingSlotRequest = slotManager.getSlotRequest(allocationId2);
+
+			assertTrue("The pending slot request should have been assigned to slot 2", pendingSlotRequest.isAssigned());
+
+			slotManager.unregisterTaskManager(taskManagerConnection.getInstanceID());
+
+			assertTrue(0 == slotManager.getNumberRegisteredSlots());
+			assertFalse(pendingSlotRequest.isAssigned());
+		}
 	}
 
 	/**
-	 * Tests that there are some free slots when we request, and the request is fulfilled immediately
+	 * Tests that a slot request with no free slots will trigger the resource allocation
 	 */
 	@Test
-	public void testRequestSlotWithFreeSlot() {
-		TestingSlotManager slotManager = new TestingSlotManager();
+	public void testSlotRequestWithoutFreeSlots() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotRequest slotRequest = new SlotRequest(
+			new JobID(),
+			new AllocationID(),
+			resourceProfile,
+			"localhost");
 
-		directlyProvideFreeSlots(slotManager, DEFAULT_TESTING_PROFILE, 1);
-		assertEquals(1, slotManager.getFreeSlotCount());
+		ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE));
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-		assertEquals(0, slotManager.getAllocatedContainers().size());
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+
+			slotManager.registerSlotRequest(slotRequest);
+
+			verify(resourceManagerActions).allocateResource(eq(resourceProfile));
+		}
 	}
 
 	/**
-	 * Tests that there are some free slots when we request, but none of them are suitable
+	 * Tests that the slot request fails if we cannot allocate more resources.
 	 */
 	@Test
-	public void testRequestSlotWithoutSuitableSlot() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-
-		directlyProvideFreeSlots(slotManager, DEFAULT_TESTING_PROFILE, 2);
-		assertEquals(2, slotManager.getFreeSlotCount());
-
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_BIG_PROFILE));
-		assertEquals(0, slotManager.getAllocatedSlotCount());
-		assertEquals(2, slotManager.getFreeSlotCount());
-		assertEquals(1, slotManager.getPendingRequestCount());
-		assertEquals(1, slotManager.getAllocatedContainers().size());
-		assertEquals(DEFAULT_TESTING_BIG_PROFILE, slotManager.getAllocatedContainers().get(0));
+	public void testSlotRequestWithResourceAllocationFailure() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotRequest slotRequest = new SlotRequest(
+			new JobID(),
+			new AllocationID(),
+			resourceProfile,
+			"localhost");
+
+		ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		doThrow(new ResourceManagerException("Test exception")).when(resourceManagerActions).allocateResource(any(ResourceProfile.class));
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+
+			slotManager.registerSlotRequest(slotRequest);
+
+			fail("The slot request should have failed with a ResourceManagerException.");
+
+		} catch (ResourceManagerException e) {
+			// expected exception
+		}
 	}
 
 	/**
-	 * Tests that we send duplicated slot request
+	 * Tests that a slot request which can be fulfilled will trigger a slot allocation.
 	 */
 	@Test
-	public void testDuplicatedSlotRequest() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		directlyProvideFreeSlots(slotManager, DEFAULT_TESTING_PROFILE, 1);
-
-		SlotRequest request1 = new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE);
-		SlotRequest request2 = new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_BIG_PROFILE);
-
-		slotManager.requestSlot(request1);
-		slotManager.requestSlot(request2);
-		slotManager.requestSlot(request2);
-		slotManager.requestSlot(request1);
-
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(1, slotManager.getPendingRequestCount());
-		assertEquals(1, slotManager.getAllocatedContainers().size());
-		assertEquals(DEFAULT_TESTING_BIG_PROFILE, slotManager.getAllocatedContainers().get(0));
+	public void testSlotRequestWithFreeSlot() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceID resourceID = ResourceID.generate();
+		final JobID jobId = new JobID();
+		final SlotID slotId = new SlotID(resourceID, 0);
+		final String targetAddress = "localhost";
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotRequest slotRequest = new SlotRequest(
+			jobId,
+			allocationId,
+			resourceProfile,
+			targetAddress);
+
+		ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+
+			// accept an incoming slot request
+			final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+			when(taskExecutorGateway.requestSlot(
+				eq(slotId),
+				eq(jobId),
+				eq(allocationId),
+				anyString(),
+				eq(leaderId),
+				any(Time.class))).thenReturn(FlinkCompletableFuture.completed(Acknowledge.get()));
+
+			final TaskExecutorConnection taskExecutorConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+			final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile);
+			final SlotReport slotReport = new SlotReport(slotStatus);
+
+			slotManager.registerTaskManager(
+				taskExecutorConnection,
+				slotReport);
+
+			assertTrue("The slot request should be accepted", slotManager.registerSlotRequest(slotRequest));
+
+			verify(taskExecutorGateway).requestSlot(eq(slotId), eq(jobId), eq(allocationId), eq(targetAddress), eq(leaderId), any(Time.class));
+
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
+
+			assertEquals("The slot has not been allocated to the expected allocation id.", allocationId, slot.getAllocationId());
+		}
 	}
 
 	/**
-	 * Tests that we send multiple slot requests
+	 * Checks that un-registering a pending slot request will cancel it, removing it from all
+	 * assigned task manager slots and then remove it from the slot manager.
 	 */
 	@Test
-	public void testRequestMultipleSlots() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		directlyProvideFreeSlots(slotManager, DEFAULT_TESTING_PROFILE, 5);
+	public void testUnregisterPendingSlotRequest() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final SlotID slotId = new SlotID(ResourceID.generate(), 0);
+		final AllocationID allocationId = new AllocationID();
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			any(SlotID.class),
+			any(JobID.class),
+			any(AllocationID.class),
+			anyString(),
+			eq(leaderId),
+			any(Time.class))).thenReturn(new FlinkCompletableFuture<Acknowledge>());
+
+		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
+		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile);
+		final SlotReport slotReport = new SlotReport(slotStatus);
 
-		// request 3 normal slots
-		for (int i = 0; i < 3; ++i) {
-			slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE));
-		}
+		final SlotRequest slotRequest = new SlotRequest(new JobID(), allocationId, resourceProfile, "foobar");
 
-		// request 2 big slots
-		for (int i = 0; i < 2; ++i) {
-			slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_BIG_PROFILE));
-		}
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
 
-		// request 1 normal slot again
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE));
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
 
-		assertEquals(4, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
-		assertEquals(2, slotManager.getPendingRequestCount());
-		assertEquals(2, slotManager.getAllocatedContainers().size());
-		assertEquals(DEFAULT_TESTING_BIG_PROFILE, slotManager.getAllocatedContainers().get(0));
-		assertEquals(DEFAULT_TESTING_BIG_PROFILE, slotManager.getAllocatedContainers().get(1));
+			slotManager.registerSlotRequest(slotRequest);
+
+			assertNotNull(slotManager.getSlotRequest(allocationId));
+
+			assertTrue(slot.hasPendingSlotRequest());
+
+			slotManager.unregisterSlotRequest(allocationId);
+
+			assertNull(slotManager.getSlotRequest(allocationId));
+
+			slot = slotManager.getSlot(slotId);
+			assertTrue(slot.isFree());
+		}
 	}
 
 	/**
-	 * Tests that a new slot appeared in SlotReport, and we used it to fulfill a pending request
+	 * Tests that pending slot requests are tried to be fulfilled upon new slot registrations.
 	 */
 	@Test
-	public void testNewlyAppearedFreeSlotFulfillPendingRequest() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE));
-		assertEquals(1, slotManager.getPendingRequestCount());
-
-		SlotID slotId = SlotID.generate();
-		SlotStatus slotStatus = new SlotStatus(slotId, DEFAULT_TESTING_PROFILE);
-		SlotReport slotReport = new SlotReport(Collections.singletonList(slotStatus));
-		slotManager.registerTaskExecutor(slotId.getResourceID(), taskExecutorRegistration, slotReport);
-
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-		assertTrue(slotManager.isAllocated(slotId));
+	public void testFulfillingPendingSlotRequest() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceID resourceID = ResourceID.generate();
+		final JobID jobId = new JobID();
+		final SlotID slotId = new SlotID(resourceID, 0);
+		final String targetAddress = "localhost";
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotRequest slotRequest = new SlotRequest(
+			jobId,
+			allocationId,
+			resourceProfile,
+			targetAddress);
+
+		ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+
+		// accept an incoming slot request
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			eq(slotId),
+			eq(jobId),
+			eq(allocationId),
+			anyString(),
+			eq(leaderId),
+			any(Time.class))).thenReturn(FlinkCompletableFuture.completed(Acknowledge.get()));
+
+		final TaskExecutorConnection taskExecutorConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile);
+		final SlotReport slotReport = new SlotReport(slotStatus);
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+
+			assertTrue("The slot request should be accepted", slotManager.registerSlotRequest(slotRequest));
+
+			verify(resourceManagerActions, times(1)).allocateResource(eq(resourceProfile));
+
+			slotManager.registerTaskManager(
+				taskExecutorConnection,
+				slotReport);
+
+			verify(taskExecutorGateway).requestSlot(eq(slotId), eq(jobId), eq(allocationId), eq(targetAddress), eq(leaderId), any(Time.class));
+
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
+
+			assertEquals("The slot has not been allocated to the expected allocation id.", allocationId, slot.getAllocationId());
+		}
 	}
 
 	/**
-	 * Tests that a new slot appeared in SlotReport, but we have no pending request
+	 * Tests that freeing a slot will correctly reset the slot and mark it as a free slot
 	 */
 	@Test
-	public void testNewlyAppearedFreeSlot() {
-		TestingSlotManager slotManager = new TestingSlotManager();
+	public void testFreeSlot() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceID resourceID = ResourceID.generate();
+		final JobID jobId = new JobID();
+		final SlotID slotId = new SlotID(resourceID, 0);
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+
+		ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+
+		// accept an incoming slot request
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
 
-		SlotID slotId = SlotID.generate();
-		SlotStatus slotStatus = new SlotStatus(slotId, DEFAULT_TESTING_PROFILE);
-		SlotReport slotReport = new SlotReport(Collections.singletonList(slotStatus));
-		slotManager.registerTaskExecutor(slotId.getResourceID(), taskExecutorRegistration, slotReport);
+		final TaskExecutorConnection taskExecutorConnection = new TaskExecutorConnection(taskExecutorGateway);
 
-		assertEquals(0, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
+		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile, jobId, allocationId);
+		final SlotReport slotReport = new SlotReport(slotStatus);
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+
+			slotManager.registerTaskManager(
+				taskExecutorConnection,
+				slotReport);
+
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
+
+			assertEquals("The slot has not been allocated to the expected allocation id.", allocationId, slot.getAllocationId());
+
+			// this should be ignored since the allocation id does not match
+			slotManager.freeSlot(slotId, new AllocationID());
+
+			assertTrue(slot.isAllocated());
+			assertEquals("The slot has not been allocated to the expected allocation id.", allocationId, slot.getAllocationId());
+
+			slotManager.freeSlot(slotId, allocationId);
+
+			assertTrue(slot.isFree());
+			assertNull(slot.getAllocationId());
+		}
 	}
 
 	/**
-	 * Tests that a new slot appeared in SlotReport, but it't not suitable for all the pending requests
+	 * Tests that a second pending slot request is detected as a duplicate if the allocation ids are
+	 * the same.
 	 */
 	@Test
-	public void testNewlyAppearedFreeSlotNotMatchPendingRequests() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_BIG_PROFILE));
-		assertEquals(1, slotManager.getPendingRequestCount());
-
-		SlotID slotId = SlotID.generate();
-		SlotStatus slotStatus = new SlotStatus(slotId, DEFAULT_TESTING_PROFILE);
-		SlotReport slotReport = new SlotReport(Collections.singletonList(slotStatus));
-		slotManager.registerTaskExecutor(slotId.getResourceID(), taskExecutorRegistration, slotReport);
-
-		assertEquals(0, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
-		assertEquals(1, slotManager.getPendingRequestCount());
-		assertFalse(slotManager.isAllocated(slotId));
+	public void testDuplicatePendingSlotRequest() throws Exception {
+
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile1 = new ResourceProfile(1.0, 2);
+		final ResourceProfile resourceProfile2 = new ResourceProfile(2.0, 1);
+		final SlotRequest slotRequest1 = new SlotRequest(new JobID(), allocationId, resourceProfile1, "foobar");
+		final SlotRequest slotRequest2 = new SlotRequest(new JobID(), allocationId, resourceProfile2, "barfoo");
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			assertTrue(slotManager.registerSlotRequest(slotRequest1));
+			assertFalse(slotManager.registerSlotRequest(slotRequest2));
+		}
+
+		// check that we have only called the resource allocation only for the first slot request,
+		// since the second request is a duplicate
+		verify(resourceManagerActions, times(1)).allocateResource(any(ResourceProfile.class));
 	}
 
 	/**
-	 * Tests that a new slot appeared in SlotReport, and it's been reported using by some job
+	 * Tests that if we have received a slot report with some allocated slots, then we don't accept
+	 * slot requests with allocated allocation ids.
 	 */
 	@Test
-	public void testNewlyAppearedInUseSlot() {
-		TestingSlotManager slotManager = new TestingSlotManager();
+	public void testDuplicatePendingSlotRequestAfterSlotReport() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final JobID jobId = new JobID();
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
+		final SlotID slotId = new SlotID(ResourceID.generate(), 0);
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile, jobId, allocationId);
+		final SlotReport slotReport = new SlotReport(slotStatus);
 
-		SlotID slotId = SlotID.generate();
-		SlotStatus slotStatus = new SlotStatus(slotId, DEFAULT_TESTING_PROFILE, new JobID(), new AllocationID());
-		SlotReport slotReport = new SlotReport(Collections.singletonList(slotStatus));
-		slotManager.registerTaskExecutor(slotId.getResourceID(), taskExecutorRegistration, slotReport);
+		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertTrue(slotManager.isAllocated(slotId));
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
+
+			assertFalse(slotManager.registerSlotRequest(slotRequest));
+		}
 	}
 
 	/**
-	 * Tests that we had a slot in-use and is freed again subsequently.
+	 * Tests that duplicate slot requests (requests with an already registered allocation id) are
+	 * also detected after a pending slot request has been fulfilled but not yet freed.
 	 */
 	@Test
-	public void testExistingInUseSlotUpdateStatus() {
-		TestingSlotManager slotManager = new TestingSlotManager();
+	public void testDuplicatePendingSlotRequestAfterSuccessfulAllocation() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile1 = new ResourceProfile(1.0, 2);
+		final ResourceProfile resourceProfile2 = new ResourceProfile(2.0, 1);
+		final SlotRequest slotRequest1 = new SlotRequest(new JobID(), allocationId, resourceProfile1, "foobar");
+		final SlotRequest slotRequest2 = new SlotRequest(new JobID(), allocationId, resourceProfile2, "barfoo");
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			any(SlotID.class),
+			any(JobID.class),
+			any(AllocationID.class),
+			anyString(),
+			eq(leaderId),
+			any(Time.class))).thenReturn(FlinkCompletableFuture.completed(Acknowledge.get()));
+
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		final SlotID slotId = new SlotID(ResourceID.generate(), 0);
+		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile1);
+		final SlotReport slotReport = new SlotReport(slotStatus);
 
-		SlotID slotId = SlotID.generate();
-		SlotStatus slotStatus = new SlotStatus(slotId, DEFAULT_TESTING_PROFILE, new JobID(), new AllocationID());
-		SlotReport slotReport = new SlotReport(Collections.singletonList(slotStatus));
-		slotManager.registerTaskExecutor(slotId.getResourceID(), taskExecutorRegistration, slotReport);
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
+			assertTrue(slotManager.registerSlotRequest(slotRequest1));
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertTrue(slotManager.isAllocated(slotId));
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
 
-		// slot is freed again
-		slotManager.notifySlotAvailable(slotId.getResourceID(), slotId);
+			assertEquals("The slot has not been allocated to the expected allocation id.", allocationId, slot.getAllocationId());
 
-		assertEquals(0, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
-		assertFalse(slotManager.isAllocated(slotId));
+			assertFalse(slotManager.registerSlotRequest(slotRequest2));
+		}
+
+		// check that we have only called the resource allocation only for the first slot request,
+		// since the second request is a duplicate
+		verify(resourceManagerActions, never()).allocateResource(any(ResourceProfile.class));
 	}
 
 	/**
-	 * Tests multiple slot requests with one slots.
+	 * Tests that an already registered allocation id can be reused after the initial slot request
+	 * has been freed.
 	 */
 	@Test
-	public void testMultipleSlotRequestsWithOneSlot() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		final AllocationID allocationID = new AllocationID();
+	public void testAcceptingDuplicateSlotRequestAfterAllocationRelease() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile1 = new ResourceProfile(1.0, 2);
+		final ResourceProfile resourceProfile2 = new ResourceProfile(2.0, 1);
+		final SlotRequest slotRequest1 = new SlotRequest(new JobID(), allocationId, resourceProfile1, "foobar");
+		final SlotRequest slotRequest2 = new SlotRequest(new JobID(), allocationId, resourceProfile2, "barfoo");
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			any(SlotID.class),
+			any(JobID.class),
+			any(AllocationID.class),
+			anyString(),
+			eq(leaderId),
+			any(Time.class))).thenReturn(FlinkCompletableFuture.completed(Acknowledge.get()));
+
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		final SlotID slotId = new SlotID(ResourceID.generate(), 0);
+		final SlotStatus slotStatus = new SlotStatus(slotId, new ResourceProfile(2.0, 2));
+		final SlotReport slotReport = new SlotReport(slotStatus);
 
-		SlotRequest request1 = new SlotRequest(new JobID(), allocationID, DEFAULT_TESTING_PROFILE);
-		slotManager.requestSlot(request1);
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
+			assertTrue(slotManager.registerSlotRequest(slotRequest1));
 
-		final ResourceID resourceID = ResourceID.generate();
-		final SlotStatus slotStatus = new SlotStatus(new SlotID(resourceID, 0), DEFAULT_TESTING_PROFILE);
-		final SlotReport slotReport = new SlotReport(slotStatus);
-		slotManager.registerTaskExecutor(resourceID, taskExecutorRegistration, slotReport);
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
 
-		// another request pending
-		SlotRequest request2 = new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE);
-		slotManager.requestSlot(request2);
+			assertEquals("The slot has not been allocated to the expected allocation id.", allocationId, slot.getAllocationId());
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(1, slotManager.getPendingRequestCount());
-		assertTrue(slotManager.isAllocated(allocationID));
-		assertTrue(slotManager.isAllocated(request1.getAllocationId()));
+			slotManager.freeSlot(slotId, allocationId);
 
-		// but slot is reported empty in a report in the meantime which shouldn't affect the state
-		slotManager.notifySlotAvailable(resourceID, slotStatus.getSlotID());
+			// check that the slot has been freed
+			assertTrue(slot.isFree());
+			assertNull(slot.getAllocationId());
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-		assertTrue(slotManager.isAllocated(slotStatus.getSlotID()));
-		assertTrue(slotManager.isAllocated(request2.getAllocationId()));
+			assertTrue(slotManager.registerSlotRequest(slotRequest2));
 
-		// but slot is reported empty in a report in the meantime which shouldn't affect the state
-		slotManager.notifySlotAvailable(resourceID, slotStatus.getSlotID());
+			assertEquals("The slot has not been allocated to the expected allocation id.", allocationId, slot.getAllocationId());
+		}
 
-		assertEquals(0, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
+		// check that we have only called the resource allocation only for the first slot request,
+		// since the second request is a duplicate
+		verify(resourceManagerActions, never()).allocateResource(any(ResourceProfile.class));
 	}
 
 	/**
-	 * Tests that we did some allocation but failed / rejected by TaskManager, request will retry
+	 * Tests that the slot manager ignores slot reports of unknown origin (not registered
+	 * task managers).
 	 */
 	@Test
-	public void testSlotAllocationFailedAtTaskManager() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		ResourceSlot slot = new ResourceSlot(SlotID.generate(), DEFAULT_TESTING_PROFILE, taskExecutorRegistration);
-		slotManager.addFreeSlot(slot);
+	public void testReceivingUnknownSlotReport() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 
-		SlotRequest request = new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE);
-		slotManager.requestSlot(request);
+		final InstanceID unknownInstanceID = new InstanceID();
+		final SlotID unknownSlotId = new SlotID(ResourceID.generate(), 0);
+		final ResourceProfile unknownResourceProfile = new ResourceProfile(1.0, 1);
+		final SlotStatus unknownSlotStatus = new SlotStatus(unknownSlotId, unknownResourceProfile);
+		final SlotReport unknownSlotReport = new SlotReport(unknownSlotStatus);
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-		assertTrue(slotManager.isAllocated(slot.getSlotId()));
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			// check that we don't have any slots registered
+			assertTrue(0 == slotManager.getNumberRegisteredSlots());
 
-		slotManager.handleSlotRequestFailedAtTaskManager(request, slot.getSlotId());
+			// this should not update anything since the instance id is not known to the slot manager
+			assertFalse(slotManager.reportSlotStatus(unknownInstanceID, unknownSlotReport));
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
+			assertTrue(0 == slotManager.getNumberRegisteredSlots());
+		}
 	}
 
-
 	/**
-	 * Tests that we did some allocation but failed / rejected by TaskManager, and slot is occupied by another request
-	 * This can only occur after reconnect of the TaskExecutor.
+	 * Tests that slots are updated with respect to the latest incoming slot report. This means that
+	 * slot for which not report has been received will be removed and those for which a report was
+	 * received are updated accordingly.
 	 */
 	@Test
-	public void testSlotAllocationFailedAtTaskManagerOccupiedByOther() {
-		TestingSlotManager slotManager = new TestingSlotManager();
-		final SlotID slotID = SlotID.generate();
-		SlotStatus slot = new SlotStatus(slotID, DEFAULT_TESTING_PROFILE);
-		SlotReport slotReport = new SlotReport(slot);
-		slotManager.registerTaskExecutor(slotID.getResourceID(), taskExecutorRegistration, slotReport);
-
-		SlotRequest request = new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE);
-		slotManager.requestSlot(request);
-
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-
-		// slot is set empty by a reconnect of the TaskExecutor
-		slotManager.registerTaskExecutor(slotID.getResourceID(), taskExecutorRegistration, slotReport);
-
-		assertEquals(0, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-
-		// another request takes the slot
-		SlotRequest request2 = new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE);
-		slotManager.requestSlot(request2);
-
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-		assertFalse(slotManager.isAllocated(request.getAllocationId()));
-		assertTrue(slotManager.isAllocated(request2.getAllocationId()));
-
-		// original request should be retried
-		slotManager.handleSlotRequestFailedAtTaskManager(request, slotID);
-
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-		assertFalse(slotManager.isAllocated(request.getAllocationId()));
-		assertTrue(slotManager.isAllocated(request2.getAllocationId()));
+	public void testUpdateSlotReport() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+
+		final JobID jobId = new JobID();
+		final AllocationID allocationId = new AllocationID();
+
+		final ResourceID resourceId = ResourceID.generate();
+		final SlotID slotId1 = new SlotID(resourceId, 0);
+		final SlotID slotId2 = new SlotID(resourceId, 1);
+		final SlotID slotId3 = new SlotID(resourceId, 2);
+
+
+		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
+		final SlotStatus slotStatus1 = new SlotStatus(slotId1, resourceProfile);
+		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
+
+		final SlotStatus newSlotStatus2 = new SlotStatus(slotId2, resourceProfile, jobId, allocationId);
+		final SlotStatus slotStatus3 = new SlotStatus(slotId3, resourceProfile);
+
+		final SlotReport slotReport1 = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
+		final SlotReport slotReport2 = new SlotReport(Arrays.asList(newSlotStatus2, slotStatus3));
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+			// check that we don't have any slots registered
+			assertTrue(0 == slotManager.getNumberRegisteredSlots());
+
+			slotManager.registerTaskManager(taskManagerConnection, slotReport1);
+
+			TaskManagerSlot slot = slotManager.getSlot(slotId2);
+
+			assertTrue(2 == slotManager.getNumberRegisteredSlots());
+
+			assertTrue(slot.isFree());
+
+			assertTrue(slotManager.reportSlotStatus(taskManagerConnection.getInstanceID(), slotReport2));
+
+			assertTrue(2 == slotManager.getNumberRegisteredSlots());
+
+			// the slot manager should have removed slotId1
+			assertNull(slotManager.getSlot(slotId1));
+
+			assertNotNull(slotManager.getSlot(slotId3));
+
+			// slotId2 should have been allocated for allocationId
+			assertEquals(allocationId, slotManager.getSlot(slotId2).getAllocationId());
+		}
 	}
 
+	/**
+	 * Tests that idle task managers time out after the configured timeout. A timed out task manager
+	 * will be removed from the slot manager and the resource manager will be notified about the
+	 * timeout.
+	 */
 	@Test
-	public void testNotifyTaskManagerFailure() {
-		TestingSlotManager slotManager = new TestingSlotManager();
+	public void testTaskManagerTimeout() throws Exception {
+		final long tmTimeout = 50L;
 
-		ResourceID resource1 = ResourceID.generate();
-		ResourceID resource2 = ResourceID.generate();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final UUID leaderId = UUID.randomUUID();
 
-		ResourceSlot slot11 = new ResourceSlot(new SlotID(resource1, 1), DEFAULT_TESTING_PROFILE, taskExecutorRegistration);
-		ResourceSlot slot12 = new ResourceSlot(new SlotID(resource1, 2), DEFAULT_TESTING_PROFILE, taskExecutorRegistration);
-		ResourceSlot slot21 = new ResourceSlot(new SlotID(resource2, 1), DEFAULT_TESTING_PROFILE, taskExecutorRegistration);
-		ResourceSlot slot22 = new ResourceSlot(new SlotID(resource2, 2), DEFAULT_TESTING_PROFILE, taskExecutorRegistration);
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
 
-		slotManager.addFreeSlot(slot11);
-		slotManager.addFreeSlot(slot21);
+		final SlotID slotId = new SlotID(ResourceID.generate(), 0);
+		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
+		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile);
+		final SlotReport slotReport = new SlotReport(slotStatus);
 
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE));
-		slotManager.requestSlot(new SlotRequest(new JobID(), new AllocationID(), DEFAULT_TESTING_PROFILE));
+		final Executor mainThreadExecutor = mock(Executor.class);
 
-		assertEquals(2, slotManager.getAllocatedSlotCount());
-		assertEquals(0, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
+		try (SlotManager slotManager = new SlotManager(
+			TestingUtils.defaultScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			Time.milliseconds(tmTimeout))) {
 
-		slotManager.addFreeSlot(slot12);
-		slotManager.addFreeSlot(slot22);
+			slotManager.start(leaderId, mainThreadExecutor, resourceManagerActions);
 
-		assertEquals(2, slotManager.getAllocatedSlotCount());
-		assertEquals(2, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
 
-		slotManager.notifyTaskManagerFailure(resource2);
+			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
+			verify(mainThreadExecutor, timeout(tmTimeout * 10L)).execute(runnableArgumentCaptor.capture());
 
-		// notify an not exist resource failure
-		slotManager.notifyTaskManagerFailure(ResourceID.generate());
+			// the only runnable being executed by the main thread executor should be the timeout runnable
+			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
 
-		assertEquals(1, slotManager.getAllocatedSlotCount());
-		assertEquals(1, slotManager.getFreeSlotCount());
-		assertEquals(0, slotManager.getPendingRequestCount());
-	}
+			timeoutRunnable.run();
 
-	// ------------------------------------------------------------------------
-	//  testing utilities
-	// ------------------------------------------------------------------------
-
-	private void directlyProvideFreeSlots(
-		final SlotManager slotManager,
-		final ResourceProfile resourceProfile,
-		final int freeSlotNum)
-	{
-		for (int i = 0; i < freeSlotNum; ++i) {
-			slotManager.addFreeSlot(new ResourceSlot(SlotID.generate(), new ResourceProfile(resourceProfile), taskExecutorRegistration));
+			verify(resourceManagerActions, times(1)).releaseResource(eq(taskManagerConnection.getInstanceID()));
 		}
 	}
 
-	// ------------------------------------------------------------------------
-	//  testing classes
-	// ------------------------------------------------------------------------
+	/**
+	 * Tests that slot requests time out after the specified request timeout. If a slot request
+	 * times out, then the request is cancelled, removed from the slot manager and the resourc
+	 * manager is notified about the failed allocation.
+	 */
+	@Test
+	public void testSlotRequestTimeout() throws Exception {
+		final long allocationTimeout = 50L;
+
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final UUID leaderId = UUID.randomUUID();
+		final JobID jobId = new JobID();
+		final AllocationID allocationId = new AllocationID();
+
+		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
+		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
 
-	private static class TestingSlotManager extends SlotManager {
+		final Executor mainThreadExecutor = mock(Executor.class);
 
-		private static TestingRmServices testingRmServices = new TestingRmServices();
+		try (SlotManager slotManager = new SlotManager(
+			TestingUtils.defaultScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			Time.milliseconds(allocationTimeout),
+			TestingUtils.infiniteTime())) {
 
-		TestingSlotManager() {
-			super(testingRmServices);
-			testingRmServices.allocatedContainers.clear();
+			slotManager.start(leaderId, mainThreadExecutor, resourceManagerActions);
+
+			assertTrue(slotManager.registerSlotRequest(slotRequest));
+
+			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
+
+			verify(mainThreadExecutor, timeout(allocationTimeout * 10L)).execute(runnableArgumentCaptor.capture());
+
+			// the only runnable being executed by the main thread executor should be the timeout runnable
+			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
+
+			timeoutRunnable.run();
+
+			verify(resourceManagerActions, times(1)).notifyAllocationFailure(
+				eq(jobId),
+				eq(allocationId),
+				any(TimeoutException.class));
 		}
+	}
 
-		/**
-		 * Choose slot randomly if it matches requirement
-		 *
-		 * @param request   The slot request
-		 * @param freeSlots All slots which can be used
-		 * @return The chosen slot or null if cannot find a match
-		 */
-		@Override
-		protected ResourceSlot chooseSlotToUse(SlotRequest request, Map<SlotID, ResourceSlot> freeSlots) {
-			for (ResourceSlot slot : freeSlots.values()) {
-				if (slot.isMatchingRequirement(request.getResourceProfile())) {
-					return slot;
-				}
+	/**
+	 * Tests that a slot request is retried if it times out on the task manager side
+	 */
+	@Test
+	@SuppressWarnings("unchecked")
+	public void testTaskManagerSlotRequestTimeoutHandling() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+
+		final JobID jobId = new JobID();
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
+		final FlinkCompletableFuture<Acknowledge> slotRequestFuture1 = new FlinkCompletableFuture<>();
+		final FlinkCompletableFuture<Acknowledge> slotRequestFuture2 = new FlinkCompletableFuture<>();
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			any(SlotID.class),
+			any(JobID.class),
+			eq(allocationId),
+			anyString(),
+			any(UUID.class),
+			any(Time.class))).thenReturn(slotRequestFuture1, slotRequestFuture2);
+
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		final ResourceID resourceId = ResourceID.generate();
+		final SlotID slotId1 = new SlotID(resourceId, 0);
+		final SlotID slotId2 = new SlotID(resourceId, 1);
+		final SlotStatus slotStatus1 = new SlotStatus(slotId1, resourceProfile);
+		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
+		final SlotReport slotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
+
+		try (SlotManager slotManager = createSlotManager(leaderId, resourceManagerActions)) {
+
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
+
+			slotManager.registerSlotRequest(slotRequest);
+
+			ArgumentCaptor<SlotID> slotIdCaptor = ArgumentCaptor.forClass(SlotID.class);
+
+			verify(taskExecutorGateway, times(1)).requestSlot(
+				slotIdCaptor.capture(),
+				eq(jobId),
+				eq(allocationId),
+				anyString(),
+				eq(leaderId),
+				any(Time.class));
+
+			TaskManagerSlot failedSlot = slotManager.getSlot(slotIdCaptor.getValue());
+
+			// let the first attempt fail --> this should trigger a second attempt
+			slotRequestFuture1.completeExceptionally(new SlotAllocationException("Test exception."));
+
+			verify(taskExecutorGateway, times(2)).requestSlot(
+				slotIdCaptor.capture(),
+				eq(jobId),
+				eq(allocationId),
+				anyString(),
+				eq(leaderId),
+				any(Time.class));
+
+			// the second attempt succeeds
+			slotRequestFuture2.complete(Acknowledge.get());
+
+			TaskManagerSlot slot = slotManager.getSlot(slotIdCaptor.getValue());
+
+			assertTrue(slot.isAllocated());
+			assertEquals(allocationId, slot.getAllocationId());
+
+			if (!failedSlot.getSlotId().equals(slot.getSlotId())) {
+				assertTrue(failedSlot.isFree());
 			}
-			return null;
 		}
+	}
 
-		/**
-		 * Choose request randomly if offered slot can match its requirement
-		 *
-		 * @param offeredSlot     The free slot
-		 * @param pendingRequests All the pending slot requests
-		 * @return The chosen request's AllocationID or null if cannot find a match
-		 */
-		@Override
-		protected SlotRequest chooseRequestToFulfill(ResourceSlot offeredSlot,
-			Map<AllocationID, SlotRequest> pendingRequests)
-		{
-			for (Map.Entry<AllocationID, SlotRequest> pendingRequest : pendingRequests.entrySet()) {
-				if (offeredSlot.isMatchingRequirement(pendingRequest.getValue().getResourceProfile())) {
-					return pendingRequest.getValue();
-				}
-			}
-			return null;
+	/**
+	 * Tests that pending slot requests are rejected if a slot report with a different allocation
+	 * is received.
+	 */
+	@Test
+	@SuppressWarnings("unchecked")
+	public void testSlotReportWhileActiveSlotRequest() throws Exception {
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+
+		final JobID jobId = new JobID();
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(42.0, 1337);
+		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
+		final FlinkCompletableFuture<Acknowledge> slotRequestFuture1 = new FlinkCompletableFuture<>();
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			any(SlotID.class),
+			any(JobID.class),
+			eq(allocationId),
+			anyString(),
+			any(UUID.class),
+			any(Time.class))).thenReturn(slotRequestFuture1, FlinkCompletableFuture.completed(Acknowledge.get()));
+
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		final ResourceID resourceId = ResourceID.generate();
+		final SlotID slotId1 = new SlotID(resourceId, 0);
+		final SlotID slotId2 = new SlotID(resourceId, 1);
+		final SlotID slotId3 = new SlotID(resourceId, 2);
+		final SlotStatus slotStatus1 = new SlotStatus(slotId1, resourceProfile);
+		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
+		final SlotReport slotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
+
+		// we have to manually trigger the future call backs to simulate the main thread executor behaviour
+		final Executor mainThreadExecutorMock = mock(Executor.class);
+
+		try (SlotManager slotManager = new SlotManager(
+			TestingUtils.defaultScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime())) {
+
+			slotManager.start(leaderId, mainThreadExecutorMock, resourceManagerActions);
+
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
+
+			slotManager.registerSlotRequest(slotRequest);
+
+			ArgumentCaptor<SlotID> slotIdCaptor = ArgumentCaptor.forClass(SlotID.class);
+
+			verify(taskExecutorGateway, times(1)).requestSlot(
+				slotIdCaptor.capture(),
+				eq(jobId),
+				eq(allocationId),
+				anyString(),
+				eq(leaderId),
+				any(Time.class));
+
+			final SlotStatus newSlotStatus1 = new SlotStatus(slotIdCaptor.getValue(), resourceProfile, new JobID(), new AllocationID());
+			final SlotStatus newSlotStatus2 = new SlotStatus(slotId3, resourceProfile);
+			final SlotReport newSlotReport = new SlotReport(Arrays.asList(newSlotStatus1, newSlotStatus2));
+
+			// this should remove the unused slot, replacing it with slotId3 and retry the pending slot request
+			slotManager.reportSlotStatus(taskManagerConnection.getInstanceID(), newSlotReport);
+
+			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
+			verify(mainThreadExecutorMock).execute(runnableArgumentCaptor.capture());
+
+			Runnable requestFailureRunnable = runnableArgumentCaptor.getValue();
+
+			requestFailureRunnable.run();
+
+			verify(taskExecutorGateway, times(2)).requestSlot(
+				slotIdCaptor.capture(),
+				eq(jobId),
+				eq(allocationId),
+				anyString(),
+				eq(leaderId),
+				any(Time.class));
+
+			verify(mainThreadExecutorMock, times(2)).execute(runnableArgumentCaptor.capture());
+			Runnable requestSuccessRunnable = runnableArgumentCaptor.getValue();
+
+			requestSuccessRunnable.run();
+
+			final SlotID requestedSlotId = slotIdCaptor.getValue();
+
+			assertEquals(slotId3, requestedSlotId);
+
+			TaskManagerSlot slot = slotManager.getSlot(requestedSlotId);
+
+			assertTrue(slot.isAllocated());
+			assertEquals(allocationId, slot.getAllocationId());
 		}
+	}
+
+	/**
+	 * Tests that formerly used task managers can again timeout after all of their slots have
+	 * been freed.
+	 */
+	@Test
+	public void testTimeoutForUnusedTaskManager() throws Exception {
+		final long taskManagerTimeout = 123456L;
+
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
+		final ScheduledExecutor scheduledExecutor = mock(ScheduledExecutor.class);
+
+		final ResourceID resourceId = ResourceID.generate();
+
+		final JobID jobId = new JobID();
+		final AllocationID allocationId = new AllocationID();
+		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
+		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
+
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			any(SlotID.class),
+			eq(jobId),
+			eq(allocationId),
+			anyString(),
+			eq(leaderId),
+			any(Time.class))).thenReturn(FlinkCompletableFuture.completed(Acknowledge.get()));
+
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
+
+		final SlotID slotId1 = new SlotID(resourceId, 0);
+		final SlotID slotId2 = new SlotID(resourceId, 1);
+		final SlotStatus slotStatus1 = new SlotStatus(slotId1, resourceProfile);
+		final SlotStatus slotStatus2 = new SlotStatus(slotId2, resourceProfile);
+		final SlotReport initialSlotReport = new SlotReport(Arrays.asList(slotStatus1, slotStatus2));
+
+		try (SlotManager slotManager = new SlotManager(
+			scheduledExecutor,
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			Time.of(taskManagerTimeout, TimeUnit.MILLISECONDS))) {
+
+			slotManager.start(leaderId, Executors.directExecutor(), resourceManagerActions);
+
+			slotManager.registerSlotRequest(slotRequest);
+
+			slotManager.registerTaskManager(taskManagerConnection, initialSlotReport);
+
+			ArgumentCaptor<SlotID> slotIdArgumentCaptor = ArgumentCaptor.forClass(SlotID.class);
+
+			verify(taskExecutorGateway).requestSlot(
+				slotIdArgumentCaptor.capture(),
+				eq(jobId),
+				eq(allocationId),
+				anyString(),
+				eq(leaderId),
+				any(Time.class));
+
+			assertFalse(slotManager.hasTimeoutRegistered(taskManagerConnection.getInstanceID()));
+
+			SlotID slotId = slotIdArgumentCaptor.getValue();
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
+
+			assertTrue(slot.isAllocated());
+			assertEquals(allocationId, slot.getAllocationId());
+
+			slotManager.freeSlot(slotId, allocationId);
+
+			assertTrue(slotManager.hasTimeoutRegistered(taskManagerConnection.getInstanceID()));
+
+			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
+
+			// filter out the schedule call for the task manager which will be registered using the
+			// taskManagerTimeout value
+			verify(scheduledExecutor).schedule(runnableArgumentCaptor.capture(), eq(taskManagerTimeout), eq(TimeUnit.MILLISECONDS));
+
+			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
 
-		List<ResourceProfile> getAllocatedContainers() {
-			return testingRmServices.allocatedContainers;
+			timeoutRunnable.run();
+
+			verify(resourceManagerActions, times(1)).releaseResource(eq(taskManagerConnection.getInstanceID()));
 		}
+	}
 
+	/**
+	 * Tests that the slot manager re-registers a timeout for a rejected slot request.
+	 */
+	@Test
+	public void testTimeoutForRejectedSlotRequest() throws Exception {
 
-		private static class TestingRmServices implements ResourceManagerServices {
+		final long slotRequestTimeout = 1337L;
+		final ScheduledExecutor scheduledExecutor = mock(ScheduledExecutor.class);
 
-			private final UUID leaderID;
+		final ResourceID resourceId = ResourceID.generate();
+		final SlotID slotId = new SlotID(resourceId, 0);
+		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 1);
+		final SlotStatus slotStatus = new SlotStatus(slotId, resourceProfile);
+		final SlotReport slotReport = new SlotReport(slotStatus);
 
-			private final List<ResourceProfile> allocatedContainers;
+		final UUID leaderId = UUID.randomUUID();
+		final ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 
-			public TestingRmServices() {
-				this.leaderID = UUID.randomUUID();
-				this.allocatedContainers = new LinkedList<>();
-			}
+		final JobID jobId = new JobID();
+		final AllocationID allocationId = new AllocationID();
+		final AllocationID allocationId2 = new AllocationID();
+		final SlotRequest slotRequest = new SlotRequest(jobId, allocationId, resourceProfile, "foobar");
 
-			@Override
-			public UUID getLeaderID() {
-				return leaderID;
-			}
+		CompletableFuture<Acknowledge> requestFuture = new FlinkCompletableFuture<>();
 
-			@Override
-			public void allocateResource(ResourceProfile resourceProfile) {
-				allocatedContainers.add(resourceProfile);
-			}
+		final TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+		when(taskExecutorGateway.requestSlot(
+			eq(slotId),
+			eq(jobId),
+			eq(allocationId),
+			anyString(),
+			eq(leaderId),
+			any(Time.class))).thenReturn(requestFuture);
 
-			@Override
-			public Executor getAsyncExecutor() {
-				return Mockito.mock(Executor.class);
-			}
+		final TaskExecutorConnection taskManagerConnection = new TaskExecutorConnection(taskExecutorGateway);
 
-			@Override
-			public Executor getMainThreadExecutor() {
-				return Mockito.mock(Executor.class);
-			}
+		try (SlotManager slotManager = new SlotManager(
+			scheduledExecutor,
+			TestingUtils.infiniteTime(),
+			Time.milliseconds(slotRequestTimeout),
+			TestingUtils.infiniteTime())) {
+
+			slotManager.start(leaderId, Executors.directExecutor(), resourceManagerActions);
+
+			slotManager.registerTaskManager(taskManagerConnection, slotReport);
 
+			slotManager.registerSlotRequest(slotRequest);
+
+			verify(taskExecutorGateway).requestSlot(
+				eq(slotId),
+				eq(jobId),
+				eq(allocationId),
+				anyString(),
+				eq(leaderId),
+				any(Time.class));
+
+			requestFuture.completeExceptionally(new SlotOccupiedException("Slot is already occupied", allocationId2));
+
+			ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
+			verify(scheduledExecutor).schedule(runnableArgumentCaptor.capture(), eq(slotRequestTimeout), eq(TimeUnit.MILLISECONDS));
+
+			Runnable timeoutRunnable = runnableArgumentCaptor.getValue();
+
+			timeoutRunnable.run();
+
+			verify(resourceManagerActions).notifyAllocationFailure(eq(jobId), eq(allocationId), any(Exception.class));
+
+			TaskManagerSlot slot = slotManager.getSlot(slotId);
+
+			assertTrue(slot.isAllocated());
+			assertEquals(allocationId2, slot.getAllocationId());
 		}
 	}
+
+	private SlotManager createSlotManager(UUID leaderId, ResourceManagerActions resourceManagerActions) {
+		SlotManager slotManager = new SlotManager(
+			TestingUtils.defaultScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime());
+
+		slotManager.start(leaderId, Executors.directExecutor(), resourceManagerActions);
+
+		return slotManager;
+	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
index 37690b5..a72969e 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotProtocolTest.java
@@ -19,47 +19,29 @@ package org.apache.flink.runtime.resourcemanager.slotmanager;
 
 import org.apache.flink.api.common.JobID;
 import org.apache.flink.api.common.time.Time;
-import org.apache.flink.runtime.clusterframework.FlinkResourceManager;
 import org.apache.flink.runtime.clusterframework.types.AllocationID;
 import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
-import org.apache.flink.runtime.concurrent.Future;
-import org.apache.flink.runtime.concurrent.impl.FlinkCompletableFuture;
-import org.apache.flink.runtime.heartbeat.HeartbeatServices;
-import org.apache.flink.runtime.highavailability.HighAvailabilityServices;
-import org.apache.flink.runtime.highavailability.TestingHighAvailabilityServices;
-import org.apache.flink.runtime.jobmaster.JobMasterGateway;
-import org.apache.flink.runtime.leaderelection.TestingLeaderElectionService;
-import org.apache.flink.runtime.leaderelection.TestingLeaderRetrievalService;
-import org.apache.flink.runtime.metrics.MetricRegistry;
-import org.apache.flink.runtime.registration.RegistrationResponse;
-import org.apache.flink.runtime.resourcemanager.JobLeaderIdService;
-import org.apache.flink.runtime.resourcemanager.ResourceManager;
-import org.apache.flink.runtime.resourcemanager.ResourceManagerConfiguration;
-import org.apache.flink.runtime.resourcemanager.ResourceManagerServices;
+import org.apache.flink.runtime.concurrent.Executors;
+import org.apache.flink.runtime.concurrent.ScheduledExecutorServiceAdapter;
+import org.apache.flink.runtime.concurrent.impl.FlinkFuture;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
-import org.apache.flink.runtime.resourcemanager.StandaloneResourceManager;
-import org.apache.flink.runtime.resourcemanager.TestingSlotManager;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestReply;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestReply;
-import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorRegistration;
-import org.apache.flink.runtime.rpc.FatalErrorHandler;
-import org.apache.flink.runtime.rpc.RpcService;
-import org.apache.flink.runtime.rpc.TestingSerialRpcService;
+import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorConnection;
 import org.apache.flink.runtime.taskexecutor.SlotReport;
 import org.apache.flink.runtime.taskexecutor.SlotStatus;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
+import org.apache.flink.runtime.testingUtils.TestingUtils;
 import org.apache.flink.util.TestLogger;
 import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 
 import java.util.Collections;
 import java.util.UUID;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 import static org.mockito.Matchers.any;
@@ -70,128 +52,75 @@ import static org.mockito.Mockito.verify;
 
 public class SlotProtocolTest extends TestLogger {
 
-	private static TestingSerialRpcService testRpcService;
+	private static final long timeout = 10000L;
+
+
+	private static ScheduledExecutorService scheduledExecutorService;
 
 	@BeforeClass
 	public static void beforeClass() {
-		testRpcService = new TestingSerialRpcService();
+		scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
 	}
 
 	@AfterClass
 	public static void afterClass() {
-		testRpcService.stopService();
-		testRpcService = null;
-	}
-
-	@Before
-	public void beforeTest(){
-		testRpcService.clearGateways();
+		Executors.gracefulShutdown(timeout, TimeUnit.MILLISECONDS, scheduledExecutorService);
 	}
 
 	/**
 	 * Tests whether
-	 * 1) SlotRequest is routed to the SlotManager
-	 * 2) SlotRequest is confirmed
-	 * 3) SlotRequest leads to a container allocation
-	 * 4) Slot becomes available and TaskExecutor gets a SlotRequest
+	 * 1) SlotManager accepts a slot request
+	 * 2) SlotRequest leads to a container allocation
+	 * 3) Slot becomes available and TaskExecutor gets a SlotRequest
 	 */
 	@Test
 	public void testSlotsUnavailableRequest() throws Exception {
-		final String rmAddress = "/rm1";
-		final String jmAddress = "/jm1";
 		final JobID jobID = new JobID();
-		final ResourceID rmResourceId = new ResourceID(rmAddress);
 		final ResourceID jmResourceId = new ResourceID(jmAddress);
 
-		testRpcService.registerGateway(jmAddress, mock(JobMasterGateway.class));
-
-		final TestingHighAvailabilityServices testingHaServices = new TestingHighAvailabilityServices();
 		final UUID rmLeaderID = UUID.randomUUID();
-		final UUID jmLeaderID = UUID.randomUUID();
-		TestingLeaderElectionService rmLeaderElectionService =
-			configureHA(testingHaServices, jobID, rmAddress, rmLeaderID, jmAddress, jmLeaderID);
-
-		ResourceManagerConfiguration resourceManagerConfiguration = new ResourceManagerConfiguration(
-			Time.seconds(5L),
-			Time.seconds(5L));
-
-		JobLeaderIdService jobLeaderIdService = new JobLeaderIdService(
-			testingHaServices,
-			testRpcService.getScheduledExecutor(),
-			Time.seconds(5L));
-
-		final TestingSlotManagerFactory slotManagerFactory = new TestingSlotManagerFactory();
-
-		final HeartbeatServices heartbeatServices = mock(HeartbeatServices.class);
-
-		SpiedResourceManager resourceManager =
-			new SpiedResourceManager(
-				rmResourceId,
-				testRpcService,
-				resourceManagerConfiguration,
-				testingHaServices,
-				heartbeatServices,
-				slotManagerFactory,
-				mock(MetricRegistry.class),
-				jobLeaderIdService,
-				mock(FatalErrorHandler.class));
-		resourceManager.start();
-		rmLeaderElectionService.isLeader(rmLeaderID);
-
-		Future<RegistrationResponse> registrationFuture =
-			resourceManager.registerJobManager(rmLeaderID, jmLeaderID, jmResourceId, jmAddress, jobID);
-		try {
-			registrationFuture.get(5, TimeUnit.SECONDS);
-		} catch (Exception e) {
-			Assert.fail("JobManager registration Future didn't become ready.");
-		}
 
-		final SlotManager slotManager = slotManagerFactory.slotManager;
+		try (SlotManager slotManager = new SlotManager(
+			new ScheduledExecutorServiceAdapter(scheduledExecutorService),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime())) {
 
-		final AllocationID allocationID = new AllocationID();
-		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 100);
+			ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 
-		SlotRequest slotRequest = new SlotRequest(jobID, allocationID, resourceProfile);
-		RMSlotRequestReply slotRequestReply =
-			resourceManager.requestSlot(jmLeaderID, rmLeaderID, slotRequest);
+			slotManager.start(rmLeaderID, Executors.directExecutor(), resourceManagerActions);
 
-		// 1) SlotRequest is routed to the SlotManager
-		verify(slotManager).requestSlot(slotRequest);
+			final AllocationID allocationID = new AllocationID();
+			final ResourceProfile resourceProfile = new ResourceProfile(1.0, 100);
+			final String targetAddress = "foobar";
 
-		// 2) SlotRequest is confirmed
-		Assert.assertEquals(
-			slotRequestReply.getAllocationID(),
-			allocationID);
+			SlotRequest slotRequest = new SlotRequest(jobID, allocationID, resourceProfile, targetAddress);
 
-		// 3) SlotRequest leads to a container allocation
-		Assert.assertEquals(1, resourceManager.startNewWorkerCalled);
+			slotManager.registerSlotRequest(slotRequest);
 
-		Assert.assertFalse(slotManager.isAllocated(allocationID));
+			verify(resourceManagerActions).allocateResource(eq(slotRequest.getResourceProfile()));
 
-		// slot becomes available
-		final String tmAddress = "/tm1";
-		TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
-		Mockito
-			.when(
+			// slot becomes available
+			TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
+			Mockito.when(
 				taskExecutorGateway
 					.requestSlot(any(SlotID.class), any(JobID.class), any(AllocationID.class), any(String.class), any(UUID.class), any(Time.class)))
-			.thenReturn(new FlinkCompletableFuture<TMSlotRequestReply>());
-		testRpcService.registerGateway(tmAddress, taskExecutorGateway);
-
-		final ResourceID resourceID = ResourceID.generate();
-		final SlotID slotID = new SlotID(resourceID, 0);
-
-		final SlotStatus slotStatus =
-			new SlotStatus(slotID, resourceProfile);
-		final SlotReport slotReport =
-			new SlotReport(Collections.singletonList(slotStatus));
-		// register slot at SlotManager
-		slotManager.registerTaskExecutor(
-			resourceID, new TaskExecutorRegistration(taskExecutorGateway), slotReport);
-
-		// 4) Slot becomes available and TaskExecutor gets a SlotRequest
-		verify(taskExecutorGateway, timeout(5000))
-			.requestSlot(eq(slotID), eq(jobID), eq(allocationID), any(String.class), any(UUID.class), any(Time.class));
+				.thenReturn(mock(FlinkFuture.class));
+
+			final ResourceID resourceID = ResourceID.generate();
+			final SlotID slotID = new SlotID(resourceID, 0);
+
+			final SlotStatus slotStatus =
+				new SlotStatus(slotID, resourceProfile);
+			final SlotReport slotReport =
+				new SlotReport(Collections.singletonList(slotStatus));
+			// register slot at SlotManager
+			slotManager.registerTaskManager(new TaskExecutorConnection(taskExecutorGateway), slotReport);
+
+			// 4) Slot becomes available and TaskExecutor gets a SlotRequest
+			verify(taskExecutorGateway, timeout(5000L))
+				.requestSlot(eq(slotID), eq(jobID), eq(allocationID), any(String.class), any(UUID.class), any(Time.class));
+		}
 	}
 
 	/**
@@ -203,159 +132,48 @@ public class SlotProtocolTest extends TestLogger {
 	 */
 	@Test
 	public void testSlotAvailableRequest() throws Exception {
-		final String rmAddress = "/rm1";
-		final String jmAddress = "/jm1";
-		final String tmAddress = "/tm1";
 		final JobID jobID = new JobID();
-		final ResourceID rmResourceId = new ResourceID(rmAddress);
 		final ResourceID jmResourceId = new ResourceID(jmAddress);
 
-		testRpcService.registerGateway(jmAddress, mock(JobMasterGateway.class));
-
-		final TestingHighAvailabilityServices testingHaServices = new TestingHighAvailabilityServices();
 		final UUID rmLeaderID = UUID.randomUUID();
-		final UUID jmLeaderID = UUID.randomUUID();
-		TestingLeaderElectionService rmLeaderElectionService =
-			configureHA(testingHaServices, jobID, rmAddress, rmLeaderID, jmAddress, jmLeaderID);
 
 		TaskExecutorGateway taskExecutorGateway = mock(TaskExecutorGateway.class);
 		Mockito.when(
 			taskExecutorGateway
 				.requestSlot(any(SlotID.class), any(JobID.class), any(AllocationID.class), any(String.class), any(UUID.class), any(Time.class)))
-			.thenReturn(new FlinkCompletableFuture<TMSlotRequestReply>());
-		testRpcService.registerGateway(tmAddress, taskExecutorGateway);
-
-		ResourceManagerConfiguration resourceManagerConfiguration = new ResourceManagerConfiguration(
-			Time.seconds(5L),
-			Time.seconds(5L));
-
-		JobLeaderIdService jobLeaderIdService = new JobLeaderIdService(
-			testingHaServices,
-			testRpcService.getScheduledExecutor(),
-			Time.seconds(5L));
-
-		TestingSlotManagerFactory slotManagerFactory = new TestingSlotManagerFactory();
-
-		HeartbeatServices heartbeatServices = mock(HeartbeatServices.class);
-
-		ResourceManager<ResourceID> resourceManager =
-			Mockito.spy(new StandaloneResourceManager(
-				testRpcService,
-				FlinkResourceManager.RESOURCE_MANAGER_NAME,
-				rmResourceId,
-				resourceManagerConfiguration,
-				testingHaServices,
-				heartbeatServices,
-				slotManagerFactory,
-				mock(MetricRegistry.class),
-				jobLeaderIdService,
-				mock(FatalErrorHandler.class)));
-		resourceManager.start();
-		rmLeaderElectionService.isLeader(rmLeaderID);
-
-		Thread.sleep(1000);
-
-		Future<RegistrationResponse> registrationFuture =
-			resourceManager.registerJobManager(rmLeaderID, jmLeaderID, jmResourceId, jmAddress, jobID);
-		try {
-			registrationFuture.get(5L, TimeUnit.SECONDS);
-		} catch (Exception e) {
-			Assert.fail("JobManager registration Future didn't become ready.");
-		}
-
-		final SlotManager slotManager = slotManagerFactory.slotManager;
+			.thenReturn(mock(FlinkFuture.class));
 
-		final ResourceID resourceID = ResourceID.generate();
-		final AllocationID allocationID = new AllocationID();
-		final ResourceProfile resourceProfile = new ResourceProfile(1.0, 100);
-		final SlotID slotID = new SlotID(resourceID, 0);
+		try (SlotManager slotManager = new SlotManager(
+			new ScheduledExecutorServiceAdapter(scheduledExecutorService),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime())) {
 
-		final SlotStatus slotStatus =
-			new SlotStatus(slotID, resourceProfile);
-		final SlotReport slotReport =
-			new SlotReport(Collections.singletonList(slotStatus));
-		// register slot at SlotManager
-		slotManager.registerTaskExecutor(
-			resourceID, new TaskExecutorRegistration(taskExecutorGateway), slotReport);
+			ResourceManagerActions resourceManagerActions = mock(ResourceManagerActions.class);
 
-		SlotRequest slotRequest = new SlotRequest(jobID, allocationID, resourceProfile);
-		RMSlotRequestReply slotRequestReply =
-			resourceManager.requestSlot(jmLeaderID, rmLeaderID, slotRequest);
+			slotManager.start(rmLeaderID, Executors.directExecutor(), resourceManagerActions);
 
-		// 1) a SlotRequest is routed to the SlotManager
-		verify(slotManager).requestSlot(slotRequest);
+			final ResourceID resourceID = ResourceID.generate();
+			final AllocationID allocationID = new AllocationID();
+			final ResourceProfile resourceProfile = new ResourceProfile(1.0, 100);
+			final SlotID slotID = new SlotID(resourceID, 0);
 
-		// 2) a SlotRequest is confirmed
-		Assert.assertEquals(
-			slotRequestReply.getAllocationID(),
-			allocationID);
-
-		// 3) a SlotRequest leads to an allocation of a registered slot
-		Assert.assertTrue(slotManager.isAllocated(slotID));
-		Assert.assertTrue(slotManager.isAllocated(allocationID));
-
-		// 4) a SlotRequest is routed to the TaskExecutor
-		verify(taskExecutorGateway, timeout(5000))
-			.requestSlot(eq(slotID), eq(jobID), eq(allocationID), any(String.class), any(UUID.class), any(Time.class));
-	}
-
-	private static TestingLeaderElectionService configureHA(
-			TestingHighAvailabilityServices testingHA, JobID jobID, String rmAddress, UUID rmID, String jmAddress, UUID jmID) {
-		final TestingLeaderElectionService rmLeaderElectionService = new TestingLeaderElectionService();
-		testingHA.setResourceManagerLeaderElectionService(rmLeaderElectionService);
-		final TestingLeaderRetrievalService rmLeaderRetrievalService = new TestingLeaderRetrievalService(rmAddress, rmID);
-		testingHA.setResourceManagerLeaderRetriever(rmLeaderRetrievalService);
-
-		final TestingLeaderElectionService jmLeaderElectionService = new TestingLeaderElectionService();
-		testingHA.setJobMasterLeaderElectionService(jobID, jmLeaderElectionService);
-		final TestingLeaderRetrievalService jmLeaderRetrievalService = new TestingLeaderRetrievalService(jmAddress, jmID);
-		testingHA.setJobMasterLeaderRetriever(jobID, jmLeaderRetrievalService);
-
-		return rmLeaderElectionService;
-	}
-
-	private static class SpiedResourceManager extends StandaloneResourceManager {
-
-		private int startNewWorkerCalled = 0;
-
-		public SpiedResourceManager(
-				ResourceID resourceId,
-				RpcService rpcService,
-				ResourceManagerConfiguration resourceManagerConfiguration,
-				HighAvailabilityServices highAvailabilityServices,
-				HeartbeatServices heartbeatServices,
-				SlotManagerFactory slotManagerFactory,
-				MetricRegistry metricRegistry,
-				JobLeaderIdService jobLeaderIdService,
-				FatalErrorHandler fatalErrorHandler) {
-			super(
-				rpcService,
-				FlinkResourceManager.RESOURCE_MANAGER_NAME,
-				resourceId,
-				resourceManagerConfiguration,
-				highAvailabilityServices,
-				heartbeatServices,
-				slotManagerFactory,
-				metricRegistry,
-				jobLeaderIdService,
-				fatalErrorHandler);
-		}
-
-
-		@Override
-		public void startNewWorker(ResourceProfile resourceProfile) {
-			startNewWorkerCalled++;
-		}
-	}
+			final SlotStatus slotStatus =
+				new SlotStatus(slotID, resourceProfile);
+			final SlotReport slotReport =
+				new SlotReport(Collections.singletonList(slotStatus));
+			// register slot at SlotManager
+			slotManager.registerTaskManager(
+				new TaskExecutorConnection(taskExecutorGateway), slotReport);
 
-	private static class TestingSlotManagerFactory implements SlotManagerFactory {
+			final String targetAddress = "foobar";
 
-		private SlotManager slotManager;
+			SlotRequest slotRequest = new SlotRequest(jobID, allocationID, resourceProfile, targetAddress);
+			slotManager.registerSlotRequest(slotRequest);
 
-		@Override
-		public SlotManager create(ResourceManagerServices rmServices) {
-			this.slotManager = Mockito.spy(new TestingSlotManager(rmServices));
-			return this.slotManager;
+			// a SlotRequest is routed to the TaskExecutor
+			verify(taskExecutorGateway, timeout(5000))
+				.requestSlot(eq(slotID), eq(jobID), eq(allocationID), any(String.class), any(UUID.class), any(Time.class));
 		}
 	}
 }


[3/7] flink git commit: [FLINK-5810] [flip-6] Introduce a hardened slot manager

Posted by tr...@apache.org.
http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
index f055971..31edbf3 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManager.java
@@ -21,519 +21,893 @@ package org.apache.flink.runtime.resourcemanager.slotmanager;
 import org.apache.flink.annotation.VisibleForTesting;
 import org.apache.flink.api.common.time.Time;
 import org.apache.flink.runtime.clusterframework.types.AllocationID;
-import org.apache.flink.runtime.clusterframework.types.ResourceID;
-import org.apache.flink.runtime.clusterframework.types.ResourceSlot;
+import org.apache.flink.runtime.clusterframework.types.ResourceProfile;
+import org.apache.flink.runtime.clusterframework.types.TaskManagerSlot;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
 import org.apache.flink.runtime.concurrent.BiFunction;
+import org.apache.flink.runtime.concurrent.CompletableFuture;
 import org.apache.flink.runtime.concurrent.Future;
-import org.apache.flink.runtime.resourcemanager.ResourceManagerServices;
+import org.apache.flink.runtime.concurrent.ScheduledExecutor;
+import org.apache.flink.runtime.concurrent.impl.FlinkCompletableFuture;
+import org.apache.flink.runtime.instance.InstanceID;
+import org.apache.flink.runtime.messages.Acknowledge;
 import org.apache.flink.runtime.resourcemanager.SlotRequest;
-import org.apache.flink.runtime.resourcemanager.messages.jobmanager.RMSlotRequestRegistered;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestRejected;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestReply;
-import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorRegistration;
+import org.apache.flink.runtime.resourcemanager.exceptions.ResourceManagerException;
+import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorConnection;
 import org.apache.flink.runtime.taskexecutor.SlotReport;
 import org.apache.flink.runtime.taskexecutor.SlotStatus;
+import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
+import org.apache.flink.runtime.taskexecutor.exceptions.SlotAllocationException;
+import org.apache.flink.runtime.taskexecutor.exceptions.SlotOccupiedException;
 import org.apache.flink.util.Preconditions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
-
-import static org.apache.flink.util.Preconditions.checkNotNull;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
- * SlotManager is responsible for receiving slot requests and do slot allocations. It allows to request
- * slots from registered TaskManagers and issues container allocation requests in case of there are not
- * enough available slots. Besides, it should sync its slot allocation with TaskManager's heartbeat.
- * <p>
- * The main operation principle of SlotManager is:
- * <ul>
- * <li>1. All slot allocation status should be synced with TaskManager, which is the ground truth.</li>
- * <li>2. All slots that have registered must be tracked, either by free pool or allocated pool.</li>
- * <li>3. All slot requests will be handled by best efforts, there is no guarantee that one request will be
- * fulfilled in time or correctly allocated. Conflicts or timeout or some special error will happen, it should
- * be handled outside SlotManager. SlotManager will make each decision based on the information it currently
- * holds.</li>
- * </ul>
- * <b>IMPORTANT:</b> This class is <b>Not Thread-safe</b>.
+ * The slot manager is responsible for maintaining a view on all registered task manager slots,
+ * their allocation and all pending slot requests. Whenever a new slot is registered or and
+ * allocated slot is freed, then it tries to fulfill another pending slot request. Whenever there
+ * are not enough slots available the slot manager will notify the resource manager about it via
+ * {@link ResourceManagerActions#allocateResource(ResourceProfile)}.
+ *
+ * In order to free resources and avoid resource leaks, idling task managers (task managers whose
+ * slots are currently not used) and not fulfilled pending slot requests time out triggering their
+ * release and failure, respectively.
  */
-public abstract class SlotManager {
+public class SlotManager implements AutoCloseable {
+
+	private static final Logger LOG = LoggerFactory.getLogger(SlotManager.class);
+
+	/** Scheduled executor for timeouts */
+	private final ScheduledExecutor scheduledExecutor;
+
+	/** Timeout for slot requests to the task manager */
+	private final Time taskManagerRequestTimeout;
+
+	/** Timeout after which an allocation is discarded */
+	private final Time slotRequestTimeout;
+
+	/** Timeout after which an unused TaskManager is released */
+	private final Time taskManagerTimeout;
+
+	/** Map for all registered slots */
+	private final HashMap<SlotID, TaskManagerSlot> slots;
 
-	protected final Logger LOG = LoggerFactory.getLogger(getClass());
+	/** Index of all currently free slots */
+	private final LinkedHashMap<SlotID, TaskManagerSlot> freeSlots;
 
-	/** The Resource allocation provider */
-	protected final ResourceManagerServices rmServices;
+	/** All currently registered task managers */
+	private final HashMap<InstanceID, TaskManagerRegistration> taskManagerRegistrations;
 
-	/** All registered task managers with ResourceID and gateway. */
-	private final Map<ResourceID, TaskExecutorRegistration> taskManagers;
+	/** Map of fulfilled and active allocations for request deduplication purposes */
+	private final HashMap<AllocationID, SlotID> fulfilledSlotRequests;
 
-	/** All registered slots, including free and allocated slots */
-	private final Map<ResourceID, Map<SlotID, ResourceSlot>> registeredSlots;
+	/** Map of pending/unfulfilled slot allocation requests */
+	private final HashMap<AllocationID, PendingSlotRequest> pendingSlotRequests;
 
-	/** All pending slot requests, waiting available slots to fulfil */
-	private final Map<AllocationID, SlotRequest> pendingSlotRequests;
+	/** Leader id of the containing component */
+	private UUID leaderId;
 
-	/** All free slots that can be used to be allocated */
-	private final Map<SlotID, ResourceSlot> freeSlots;
+	/** Executor for future callbacks which have to be "synchronized" */
+	private Executor mainThreadExecutor;
 
-	/** All allocations, we can lookup allocations either by SlotID or AllocationID */
-	private final AllocationMap allocationMap;
+	/** Callbacks for resource (de-)allocations */
+	private ResourceManagerActions resourceManagerActions;
 
-	private final Time timeout;
+	/** True iff the component has been started */
+	private boolean started;
 
-	public SlotManager(ResourceManagerServices rmServices) {
-		this.rmServices = checkNotNull(rmServices);
-		this.registeredSlots = new HashMap<>(16);
-		this.pendingSlotRequests = new LinkedHashMap<>(16);
-		this.freeSlots = new HashMap<>(16);
-		this.allocationMap = new AllocationMap();
-		this.taskManagers = new HashMap<>();
-		this.timeout = Time.seconds(10);
+	public SlotManager(
+			ScheduledExecutor scheduledExecutor,
+			Time taskManagerRequestTimeout,
+			Time slotRequestTimeout,
+			Time taskManagerTimeout) {
+		this.scheduledExecutor = Preconditions.checkNotNull(scheduledExecutor);
+		this.taskManagerRequestTimeout = Preconditions.checkNotNull(taskManagerRequestTimeout);
+		this.slotRequestTimeout = Preconditions.checkNotNull(slotRequestTimeout);
+		this.taskManagerTimeout = Preconditions.checkNotNull(taskManagerTimeout);
+
+		slots = new HashMap<>(16);
+		freeSlots = new LinkedHashMap<>(16);
+		taskManagerRegistrations = new HashMap<>(4);
+		fulfilledSlotRequests = new HashMap<>(16);
+		pendingSlotRequests = new HashMap<>(16);
+
+		leaderId = null;
+		resourceManagerActions = null;
+		started = false;
 	}
 
-	// ------------------------------------------------------------------------
-	//  slot managements
-	// ------------------------------------------------------------------------
+	// ---------------------------------------------------------------------------------------------
+	// Component lifecycle methods
+	// ---------------------------------------------------------------------------------------------
 
 	/**
-	 * Request a slot with requirements, we may either fulfill the request or pending it. Trigger container
-	 * allocation if we don't have enough resource. If we have free slot which can match the request, record
-	 * this allocation and forward the request to TaskManager through ResourceManager (we want this done by
-	 * RPC's main thread to avoid race condition).
+	 * Starts the slot manager with the given leader id and resource manager actions.
 	 *
-	 * @param request The detailed request of the slot
-	 * @return RMSlotRequestRegistered The confirmation message to be send to the caller
+	 * @param newLeaderId to use for communication with the task managers
+	 * @param newResourceManagerActions to use for resource (de-)allocations
+	 */
+	public void start(UUID newLeaderId, Executor newMainThreadExecutor, ResourceManagerActions newResourceManagerActions) {
+		leaderId = Preconditions.checkNotNull(newLeaderId);
+		mainThreadExecutor = Preconditions.checkNotNull(newMainThreadExecutor);
+		resourceManagerActions = Preconditions.checkNotNull(newResourceManagerActions);
+
+		started = true;
+	}
+
+	/**
+	 * Suspends the component. This clears the internal state of the slot manager.
 	 */
-	public RMSlotRequestRegistered requestSlot(final SlotRequest request) {
-		final AllocationID allocationId = request.getAllocationId();
-		if (isRequestDuplicated(request)) {
-			LOG.warn("Duplicated slot request, AllocationID:{}", allocationId);
-			return new RMSlotRequestRegistered(allocationId);
+	public void suspend() {
+		for (PendingSlotRequest pendingSlotRequest : pendingSlotRequests.values()) {
+			cancelPendingSlotRequest(pendingSlotRequest);
 		}
 
-		// try to fulfil the request with current free slots
-		final ResourceSlot slot = chooseSlotToUse(request, freeSlots);
-		if (slot != null) {
-			LOG.info("Assigning SlotID({}) to AllocationID({}), JobID:{}", slot.getSlotId(),
-				allocationId, request.getJobId());
+		pendingSlotRequests.clear();
+
+		ArrayList<InstanceID> registeredTaskManagers = new ArrayList<>(taskManagerRegistrations.keySet());
+
+		for (InstanceID registeredTaskManager : registeredTaskManagers) {
+			unregisterTaskManager(registeredTaskManager);
+		}
 
-			// record this allocation in bookkeeping
-			allocationMap.addAllocation(slot.getSlotId(), allocationId);
-			// remove selected slot from free pool
-			freeSlots.remove(slot.getSlotId());
+		leaderId = null;
+		resourceManagerActions = null;
+		started = false;
+	}
+
+	/**
+	 * Closes the slot manager.
+	 *
+	 * @throws Exception if the close operation fails
+	 */
+	@Override
+	public void close() throws Exception {
+		suspend();
+	}
+
+	// ---------------------------------------------------------------------------------------------
+	// Public API
+	// ---------------------------------------------------------------------------------------------
+
+	/**
+	 * Requests a slot with the respective resource profile.
+	 *
+	 * @param slotRequest specifying the requested slot specs
+	 * @return true if the slot request was registered; false if the request is a duplicate
+	 * @throws SlotManagerException if the slot request failed (e.g. not enough resources left)
+	 */
+	public boolean registerSlotRequest(SlotRequest slotRequest) throws SlotManagerException {
+		checkInit();
 
-			sendSlotRequest(slot, request);
+		if (checkDuplicateRequest(slotRequest.getAllocationId())) {
+			LOG.debug("Ignoring a duplicate slot request with allocation id {}.", slotRequest.getAllocationId());
+
+			return false;
 		} else {
-			LOG.info("Cannot fulfil slot request, try to allocate a new container for it, " +
-				"AllocationID:{}, JobID:{}", allocationId, request.getJobId());
-			Preconditions.checkState(rmServices != null,
-				"Attempted to allocate resources but no ResourceManagerServices set.");
-			rmServices.allocateResource(request.getResourceProfile());
-			pendingSlotRequests.put(allocationId, request);
+			PendingSlotRequest pendingSlotRequest = new PendingSlotRequest(slotRequest);
+
+			pendingSlotRequests.put(slotRequest.getAllocationId(), pendingSlotRequest);
+
+			try {
+				internalRequestSlot(pendingSlotRequest);
+			} catch (ResourceManagerException e) {
+				// requesting the slot failed --> remove pending slot request
+				pendingSlotRequests.remove(slotRequest.getAllocationId());
+
+				throw new SlotManagerException("Could not fulfill slot request " + slotRequest.getAllocationId() + '.', e);
+			}
+
+			return true;
 		}
+	}
+
+	/**
+	 * Cancels and removes a pending slot request with the given allocation id. If there is no such
+	 * pending request, then nothing is done.
+	 *
+	 * @param allocationId identifying the pending slot request
+	 * @return True if a pending slot request was found; otherwise false
+	 */
+	public boolean unregisterSlotRequest(AllocationID allocationId) {
+		checkInit();
+
+		PendingSlotRequest pendingSlotRequest = pendingSlotRequests.remove(allocationId);
+
+		if (null != pendingSlotRequest) {
+			cancelPendingSlotRequest(pendingSlotRequest);
+
+			return true;
+		} else {
+			LOG.debug("No pending slot request with allocation id {} found.", allocationId);
 
-		return new RMSlotRequestRegistered(allocationId);
+			return false;
+		}
 	}
 
 	/**
-	 * Notifies the SlotManager that a slot is available again after being allocated.
-	 * @param slotID slot id of available slot
+	 * Registers a new task manager at the slot manager. This will make the task managers slots
+	 * known and, thus, available for allocation.
+	 *
+	 * @param taskExecutorConnection for the new task manager
+	 * @param initialSlotReport for the new task manager
 	 */
-	public void notifySlotAvailable(ResourceID resourceID, SlotID slotID) {
-		if (!allocationMap.isAllocated(slotID)) {
-			throw new IllegalStateException("Slot was not previously allocated but " +
-				"TaskManager reports it as available again");
+	public void registerTaskManager(final TaskExecutorConnection taskExecutorConnection, SlotReport initialSlotReport) {
+		checkInit();
+
+		// we identify task managers by their instance id
+		if (!taskManagerRegistrations.containsKey(taskExecutorConnection.getInstanceID())) {
+			TaskManagerRegistration taskManagerRegistration = new TaskManagerRegistration(taskExecutorConnection);
+			taskManagerRegistrations.put(taskExecutorConnection.getInstanceID(), taskManagerRegistration);
 		}
-		allocationMap.removeAllocation(slotID);
-		final Map<SlotID, ResourceSlot> slots = registeredSlots.get(resourceID);
-		ResourceSlot freeSlot = slots.get(slotID);
-		if (freeSlot == null) {
-			throw new IllegalStateException("Slot was not registered with SlotManager but " +
-				"TaskManager reported it to be available.");
+
+		reportSlotStatus(taskExecutorConnection.getInstanceID(), initialSlotReport);
+	}
+
+	/**
+	 * Unregisters the task manager identified by the given instance id and its associated slots
+	 * from the slot manager.
+	 *
+	 * @param instanceId identifying the task manager to unregister
+	 * @return True if there existed a registered task manager with the given instance id
+	 */
+	public boolean unregisterTaskManager(InstanceID instanceId) {
+		checkInit();
+
+		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.remove(instanceId);
+
+		if (null != taskManagerRegistration) {
+			removeSlots(taskManagerRegistration.getSlots());
+
+			taskManagerRegistration.cancelTimeout();
+
+			return true;
+		} else {
+			LOG.debug("There is no task manager registered with instance ID {}. Ignoring this message.", instanceId);
+
+			return false;
 		}
-		handleFreeSlot(freeSlot);
 	}
 
 	/**
-	 * The slot request to TaskManager may be either failed by rpc communication (timeout, network error, etc.)
-	 * or really rejected by TaskManager. We shall retry this request by:
-	 * <ul>
-	 * <li>1. verify and clear all the previous allocate information for this request
-	 * <li>2. try to request slot again
-	 * </ul>
-	 * <p>
-	 * This may cause some duplicate allocation, e.g. the slot request to TaskManager is successful but the response
-	 * is lost somehow, so we may request a slot in another TaskManager, this causes two slots assigned to one request,
-	 * but it can be taken care of by rejecting registration at JobManager.
+	 * Reports the current slot allocations for a task manager identified by the given instance id.
 	 *
-	 * @param originalRequest The original slot request
-	 * @param slotId          The target SlotID
+	 * @param instanceId identifying the task manager for which to report the slot status
+	 * @param slotReport containing the status for all of its slots
+	 * @return true if the slot status has been updated successfully, otherwise false
 	 */
-	void handleSlotRequestFailedAtTaskManager(final SlotRequest originalRequest, final SlotID slotId) {
-		final AllocationID originalAllocationId = originalRequest.getAllocationId();
-		LOG.info("Slot request failed at TaskManager, SlotID:{}, AllocationID:{}, JobID:{}",
-			slotId, originalAllocationId, originalRequest.getJobId());
-
-		if (allocationMap.isAllocated(slotId)) {
-			final AllocationID expectedAllocationId = allocationMap.getAllocationID(slotId);
-
-			// check whether we have an agreement on whom this slot belongs to
-			if (originalAllocationId.equals(expectedAllocationId)) {
-				LOG.info("De-allocate this request and retry");
-				allocationMap.removeAllocation(expectedAllocationId);
-				pendingSlotRequests.put(originalRequest.getAllocationId(), originalRequest);
-				ResourceSlot slot = checkNotNull(getRegisteredSlot(slotId));
-				// treat this slot as empty and retry with a different request
-				handleFreeSlot(slot);
-			} else {
-				LOG.error("Slot request failed for slot {} with allocation id {}:" +
-						" Allocation id did not match the expected allocation id {}.",
-					slotId, originalAllocationId, expectedAllocationId);
+	public boolean reportSlotStatus(InstanceID instanceId, SlotReport slotReport) {
+		checkInit();
+
+		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(instanceId);
+
+		if (null != taskManagerRegistration) {
+			ArrayList<SlotID> slotsToRemove = new ArrayList<>(taskManagerRegistration.getSlots());
+			boolean idle = true;
+
+			for (SlotStatus slotStatus : slotReport) {
+				if (slotsToRemove.remove(slotStatus.getSlotID())) {
+					// slot which was already registered
+					updateSlot(slotStatus.getSlotID(), slotStatus.getAllocationID());
+				} else {
+					// new slot
+					registerSlot(
+						taskManagerRegistration,
+						slotStatus.getSlotID(),
+						slotStatus.getAllocationID(),
+						slotStatus.getResourceProfile(),
+						taskManagerRegistration.getTaskManagerConnection());
+				}
+
+				TaskManagerSlot slot = slots.get(slotStatus.getSlotID());
+
+				idle &= slot.isFree();
+			}
+
+			// remove the slots for which we haven't received a slot status message
+			removeSlots(slotsToRemove);
+
+			if (idle) {
+				// no slot of this task manager is being used --> register timer to free this resource
+				registerTaskManagerTimeout(taskManagerRegistration);
 			}
+
+			return true;
 		} else {
-			LOG.error("Slot request failed for slot {} with allocation id {}: " +
-					"Slot was not previously registered.",
-				slotId, originalAllocationId);
+			LOG.debug("Received slot report for unknown task manager with instance id {}. Ignoring this report.", instanceId);
+
+			return false;
 		}
 	}
 
 	/**
-	 * Registers a TaskExecutor
-	 * @param resourceID TaskExecutor's ResourceID
-	 * @param registration TaskExecutor's registration
-	 * @param slotReport TaskExecutor's free and allocated slots
+	 * Free the given slot from the given allocation. If the slot is still allocated by the given
+	 * allocation id, then the slot will be marked as free and will be subject to new slot requests.
+	 *
+	 * @param slotId identifying the slot to free
+	 * @param allocationId with which the slot is presumably allocated
 	 */
-	public void registerTaskExecutor(
-			ResourceID resourceID,
-			TaskExecutorRegistration registration,
-			SlotReport slotReport) {
+	public void freeSlot(SlotID slotId, AllocationID allocationId) {
+		checkInit();
 
-		if (taskManagers.get(resourceID) != null) {
-			notifyTaskManagerFailure(resourceID);
-		}
+		TaskManagerSlot slot = slots.get(slotId);
+
+		if (null != slot) {
+			if (slot.isAllocated()) {
+				if (Objects.equals(allocationId, slot.getAllocationId())) {
+					// free the slot
+					slot.setAllocationId(null);
+					fulfilledSlotRequests.remove(allocationId);
 
-		this.taskManagers.put(resourceID, registration);
+					if (slot.isFree()) {
+						handleFreeSlot(slot);
+					}
 
-		for (SlotStatus slotStatus : slotReport.getSlotsStatus()) {
-			final SlotID slotId = slotStatus.getSlotID();
+					TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(slot.getInstanceId());
 
-			final TaskExecutorRegistration taskExecutorRegistration = taskManagers.get(slotId.getResourceID());
-			if (taskExecutorRegistration == null) {
-				LOG.info("Received SlotStatus but ResourceID {} is unknown to the SlotManager",
-					slotId.getResourceID());
-				return;
+					if (null != taskManagerRegistration && !anySlotUsed(taskManagerRegistration.getSlots())) {
+						registerTaskManagerTimeout(taskManagerRegistration);
+					}
+				} else {
+					LOG.debug("Received request to free slot {} with expected allocation id {}, " +
+						"but actual allocation id {} differs. Ignoring the request.", slotId, allocationId, slot.getAllocationId());
+				}
+			} else {
+				LOG.debug("Slot {} has not been allocated.", allocationId);
 			}
+		} else {
+			LOG.debug("Trying to free a slot {} which has not been registered. Ignoring this message.", slotId);
+		}
+	}
 
-			final ResourceSlot slot = new ResourceSlot(slotId, slotStatus.getProfiler(), taskExecutorRegistration);
+	// ---------------------------------------------------------------------------------------------
+	// Behaviour methods
+	// ---------------------------------------------------------------------------------------------
 
-			registerNewSlot(slot);
-			LOG.info("New slot appeared, SlotID:{}, AllocationID:{}", slotId, slotStatus.getAllocationID());
+	/**
+	 * Finds a matching slot request for a given resource profile. If there is no such request,
+	 * the method returns null.
+	 *
+	 * Note: If you want to change the behaviour of the slot manager wrt slot allocation and
+	 * request fulfillment, then you should override this method.
+	 *
+	 * @param slotResourceProfile defining the resources of an available slot
+	 * @return A matching slot request which can be deployed in a slot with the given resource
+	 * profile. Null if there is no such slot request pending.
+	 */
+	protected PendingSlotRequest findMatchingRequest(ResourceProfile slotResourceProfile) {
 
-			if (slotStatus.getAllocationID() != null) {
-				// slot in use, record this in bookkeeping
-				allocationMap.addAllocation(slotId, slotStatus.getAllocationID());
-			} else {
-				handleFreeSlot(slot);
+		for (PendingSlotRequest pendingSlotRequest : pendingSlotRequests.values()) {
+			if (!pendingSlotRequest.isAssigned() && slotResourceProfile.isMatching(pendingSlotRequest.getResourceProfile())) {
+				return pendingSlotRequest;
 			}
 		}
+
+		return null;
 	}
 
 	/**
-	 * Callback for TaskManager failures. In case that a TaskManager fails, we have to clean up all its slots.
+	 * Finds a matching slot for a given resource profile. A matching slot has at least as many
+	 * resources available as the given resource profile. If there is no such slot available, then
+	 * the method returns null.
 	 *
-	 * @param resourceId The ResourceID of the TaskManager
+	 * Note: If you want to change the behaviour of the slot manager wrt slot allocation and
+	 * request fulfillment, then you should override this method.
+	 *
+	 * @param requestResourceProfile specifying the resource requirements for the a slot request
+	 * @return A matching slot which fulfills the given resource profile. Null if there is no such
+	 * slot available.
 	 */
-	public void notifyTaskManagerFailure(final ResourceID resourceId) {
-		LOG.info("Resource:{} been notified failure", resourceId);
-		taskManagers.remove(resourceId);
-		final Map<SlotID, ResourceSlot> slotIdsToRemove = registeredSlots.remove(resourceId);
-		if (slotIdsToRemove != null) {
-			for (SlotID slotId : slotIdsToRemove.keySet()) {
-				LOG.info("Removing Slot: {} upon resource failure", slotId);
-				if (freeSlots.containsKey(slotId)) {
-					freeSlots.remove(slotId);
-				} else if (allocationMap.isAllocated(slotId)) {
-					allocationMap.removeAllocation(slotId);
-				} else {
-					LOG.error("BUG! {} is neither in free pool nor in allocated pool", slotId);
-				}
+	protected TaskManagerSlot findMatchingSlot(ResourceProfile requestResourceProfile) {
+		Iterator<Map.Entry<SlotID, TaskManagerSlot>> iterator = freeSlots.entrySet().iterator();
+
+		while (iterator.hasNext()) {
+			TaskManagerSlot taskManagerSlot = iterator.next().getValue();
+
+			// sanity check
+			Preconditions.checkState(taskManagerSlot.isFree());
+
+			if (taskManagerSlot.getResourceProfile().isMatching(requestResourceProfile)) {
+				iterator.remove();
+				return taskManagerSlot;
 			}
 		}
+
+		return null;
 	}
 
-	// ------------------------------------------------------------------------
-	//  internal behaviors
-	// ------------------------------------------------------------------------
+	// ---------------------------------------------------------------------------------------------
+	// Internal slot operations
+	// ---------------------------------------------------------------------------------------------
 
 	/**
-	 * When we have a free slot, try to fulfill the pending request first. If any request can be fulfilled,
-	 * record this allocation in bookkeeping and send slot request to TaskManager, else we just add this slot
-	 * to the free pool.
+	 * Registers a slot for the given task manager at the slot manager. The slot is identified by
+	 * the given slot id. The given resource profile defines the available resources for the slot.
+	 * The task manager connection can be used to communicate with the task manager.
 	 *
-	 * @param freeSlot The free slot
+	 * @param taskManagerRegistration Task manager for which to register the given slot
+	 * @param slotId identifying the slot on the task manager
+	 * @param allocationId which is currently deployed in the slot
+	 * @param resourceProfile of the slot
+	 * @param taskManagerConnection to communicate with the remote task manager
 	 */
-	private void handleFreeSlot(final ResourceSlot freeSlot) {
-		SlotRequest chosenRequest = chooseRequestToFulfill(freeSlot, pendingSlotRequests);
+	private void registerSlot(
+			TaskManagerRegistration taskManagerRegistration,
+			SlotID slotId,
+			AllocationID allocationId,
+			ResourceProfile resourceProfile,
+			TaskExecutorConnection taskManagerConnection) {
+
+		Preconditions.checkNotNull(taskManagerRegistration);
+
+		TaskManagerSlot slot = new TaskManagerSlot(
+			slotId,
+			resourceProfile,
+			taskManagerConnection,
+			allocationId);
+
+		slots.put(slotId, slot);
+
+		taskManagerRegistration.addSlot(slotId);
+
+		if (slot.isFree()) {
+			handleFreeSlot(slot);
+		}
 
-		if (chosenRequest != null) {
-			final AllocationID allocationId = chosenRequest.getAllocationId();
-			final SlotRequest slotRequest = pendingSlotRequests.remove(allocationId);
+		if (slot.isAllocated()) {
+			fulfilledSlotRequests.put(slot.getAllocationId(), slotId);
+		}
+	}
+
+	/**
+	 * Updates a slot with the given allocation id.
+	 *
+	 * @param slotId to update
+	 * @param allocationId specifying the current allocation of the slot
+	 */
+	private void updateSlot(SlotID slotId, AllocationID allocationId) {
+		TaskManagerSlot slot = slots.get(slotId);
+
+		if (null != slot) {
+			// we assume the given allocation id to be the ground truth (coming from the TM)
+			slot.setAllocationId(allocationId);
+
+			if (null != allocationId) {
+				if (slot.hasPendingSlotRequest()){
+					// we have a pending slot request --> check whether we have to reject it
+					PendingSlotRequest pendingSlotRequest = slot.getAssignedSlotRequest();
+
+					if (Objects.equals(pendingSlotRequest.getAllocationId(), allocationId)) {
+						// we can cancel the slot request because it has been fulfilled
+						cancelPendingSlotRequest(pendingSlotRequest);
+
+						// remove the pending slot request, since it has been completed
+						pendingSlotRequests.remove(pendingSlotRequest.getAllocationId());
+					} else {
+						// this will try to find a new slot for the request
+						rejectPendingSlotRequest(
+							pendingSlotRequest,
+							new Exception("Task manager reported slot " + slotId + " being already allocated."));
+					}
+
+					slot.setAssignedSlotRequest(null);
+				}
 
-			LOG.info("Assigning SlotID({}) to AllocationID({}), JobID:{}", freeSlot.getSlotId(),
-				allocationId, chosenRequest.getJobId());
-			allocationMap.addAllocation(freeSlot.getSlotId(), allocationId);
+				fulfilledSlotRequests.put(allocationId, slotId);
 
-			sendSlotRequest(freeSlot, slotRequest);
+				TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(slot.getInstanceId());
+
+				if (null != taskManagerRegistration) {
+					// disable any registered time out for the task manager
+					taskManagerRegistration.cancelTimeout();
+				}
+			}
 		} else {
-			freeSlots.put(freeSlot.getSlotId(), freeSlot);
+			LOG.debug("Trying to update unknown slot with slot id {}.", slotId);
 		}
 	}
 
-	private void sendSlotRequest(final ResourceSlot freeSlot, final SlotRequest slotRequest) {
+	/**
+	 * Tries to allocate a slot for the given slot request. If there is no slot available, the
+	 * resource manager is informed to allocate more resources and a timeout for the request is
+	 * registered.
+	 *
+	 * @param pendingSlotRequest to allocate a slot for
+	 * @throws ResourceManagerException if the resource manager cannot allocate more resource
+	 */
+	private void internalRequestSlot(PendingSlotRequest pendingSlotRequest) throws ResourceManagerException {
+		TaskManagerSlot taskManagerSlot = findMatchingSlot(pendingSlotRequest.getResourceProfile());
 
-		final AllocationID allocationID = slotRequest.getAllocationId();
-		final TaskExecutorRegistration registration = freeSlot.getTaskExecutorRegistration();
-		final Future<TMSlotRequestReply> slotRequestReplyFuture =
-			registration.getTaskExecutorGateway()
-				.requestSlot(
-					freeSlot.getSlotId(),
-					slotRequest.getJobId(),
-					allocationID,
-					"foobar", // TODO: set proper JM address
-					rmServices.getLeaderID(),
-					timeout);
+		if (taskManagerSlot != null) {
+			allocateSlot(taskManagerSlot, pendingSlotRequest);
+		} else {
+			final UUID timeoutIdentifier = UUID.randomUUID();
+			final AllocationID allocationId = pendingSlotRequest.getAllocationId();
+
+			// register timeout for slot request
+			ScheduledFuture<?> timeoutFuture = scheduledExecutor.schedule(new Runnable() {
+				@Override
+				public void run() {
+					mainThreadExecutor.execute(new Runnable() {
+						@Override
+						public void run() {
+							timeoutSlotRequest(allocationId, timeoutIdentifier);
+						}
+					});
+				}
+			}, slotRequestTimeout.toMilliseconds(), TimeUnit.MILLISECONDS);
+
+			pendingSlotRequest.registerTimeout(timeoutFuture, timeoutIdentifier);
 
-		slotRequestReplyFuture.handleAsync(new BiFunction<TMSlotRequestReply, Throwable, Void>() {
+			resourceManagerActions.allocateResource(pendingSlotRequest.getResourceProfile());
+		}
+	}
+
+	/**
+	 * Allocates the given slot for the given slot request. This entails sending a registration
+	 * message to the task manager and treating failures.
+	 *
+	 * @param taskManagerSlot to allocate for the given slot request
+	 * @param pendingSlotRequest to allocate the given slot for
+	 */
+	private void allocateSlot(TaskManagerSlot taskManagerSlot, PendingSlotRequest pendingSlotRequest) {
+		TaskExecutorConnection taskExecutorConnection = taskManagerSlot.getTaskManagerConnection();
+		TaskExecutorGateway gateway = taskExecutorConnection.getTaskExecutorGateway();
+
+		final CompletableFuture<Acknowledge> completableFuture = new FlinkCompletableFuture<>();
+		final AllocationID allocationId = pendingSlotRequest.getAllocationId();
+		final SlotID slotId = taskManagerSlot.getSlotId();
+
+		taskManagerSlot.setAssignedSlotRequest(pendingSlotRequest);
+		pendingSlotRequest.setRequestFuture(completableFuture);
+
+		// RPC call to the task manager
+		Future<Acknowledge> requestFuture = gateway.requestSlot(
+			slotId,
+			pendingSlotRequest.getJobId(),
+			allocationId,
+			pendingSlotRequest.getTargetAddress(),
+			leaderId,
+			taskManagerRequestTimeout);
+
+		requestFuture.handle(new BiFunction<Acknowledge, Throwable, Void>() {
+			@Override
+			public Void apply(Acknowledge acknowledge, Throwable throwable) {
+				if (acknowledge != null) {
+					completableFuture.complete(acknowledge);
+				} else {
+					completableFuture.completeExceptionally(throwable);
+				}
+
+				return null;
+			}
+		});
+
+		completableFuture.handleAsync(new BiFunction<Acknowledge, Throwable, Void>() {
 			@Override
-			public Void apply(TMSlotRequestReply slotRequestReply, Throwable throwable) {
-				TaskExecutorRegistration current = taskManagers.get(slotRequestReply.getResourceID());
-				if (current != null && current.getInstanceID().equals(slotRequestReply.getInstanceID())) {
-					if (throwable != null || slotRequestReply instanceof TMSlotRequestRejected) {
-						handleSlotRequestFailedAtTaskManager(slotRequest, freeSlot.getSlotId());
+			public Void apply(Acknowledge acknowledge, Throwable throwable) {
+				if (acknowledge != null) {
+					updateSlot(slotId, allocationId);
+				} else {
+					if (throwable instanceof SlotOccupiedException) {
+						SlotOccupiedException exception = (SlotOccupiedException) throwable;
+						updateSlot(slotId, exception.getAllocationId());
 					} else {
-						LOG.debug("Successfully registered slot {} ", freeSlot.getSlotId());
+						removeSlotRequestFromSlot(slotId, allocationId);
+					}
+
+					if (!(throwable instanceof CancellationException)) {
+						handleFailedSlotRequest(slotId, allocationId, throwable);
+					} else {
+						LOG.debug("Slot allocation request {} has been cancelled.", allocationId, throwable);
 					}
-				} else {
-					LOG.debug("Discarding message from obsolete TaskExecutor with InstanceID {}",
-						slotRequestReply.getInstanceID());
 				}
+
 				return null;
 			}
-		}, rmServices.getMainThreadExecutor());
+		}, mainThreadExecutor);
 	}
 
 	/**
-	 * Check whether the request is duplicated. We use AllocationID to identify slot request, for each
-	 * formerly received slot request, it is either in pending list or already been allocated.
+	 * Handles a free slot. It first tries to find a pending slot request which can be fulfilled.
+	 * If there is no such request, then it will add the slot to the set of free slots.
 	 *
-	 * @param request The slot request
-	 * @return <tt>true</tt> if the request is duplicated
+	 * @param freeSlot to find a new slot request for
 	 */
-	private boolean isRequestDuplicated(final SlotRequest request) {
-		final AllocationID allocationId = request.getAllocationId();
-		return pendingSlotRequests.containsKey(allocationId)
-			|| allocationMap.isAllocated(allocationId);
+	private void handleFreeSlot(TaskManagerSlot freeSlot) {
+		PendingSlotRequest pendingSlotRequest = findMatchingRequest(freeSlot.getResourceProfile());
+
+		if (null != pendingSlotRequest) {
+			allocateSlot(freeSlot, pendingSlotRequest);
+		} else {
+			freeSlots.put(freeSlot.getSlotId(), freeSlot);
+		}
 	}
 
 	/**
-	 * Registers a new slot with the SlotManager.
+	 * Removes the given set of slots from the slot manager.
 	 *
-	 * @param slot The ResourceSlot which will be registered
+	 * @param slotsToRemove identifying the slots to remove from the slot manager
 	 */
-	private void registerNewSlot(final ResourceSlot slot) {
-		final SlotID slotId = slot.getSlotId();
-		final ResourceID resourceId = slotId.getResourceID();
-		if (!registeredSlots.containsKey(resourceId)) {
-			registeredSlots.put(resourceId, new HashMap<SlotID, ResourceSlot>());
+	private void removeSlots(Iterable<SlotID> slotsToRemove) {
+		for (SlotID slotId : slotsToRemove) {
+			removeSlot(slotId);
 		}
-		registeredSlots.get(resourceId).put(slotId, slot);
 	}
 
-	private ResourceSlot getRegisteredSlot(final SlotID slotId) {
-		final ResourceID resourceId = slotId.getResourceID();
-		if (!registeredSlots.containsKey(resourceId)) {
-			return null;
+	/**
+	 * Removes the given slot from the slot manager.
+	 *
+	 * @param slotId identifying the slot to remove
+	 */
+	private void removeSlot(SlotID slotId) {
+		TaskManagerSlot slot = slots.remove(slotId);
+
+		if (null != slot) {
+			freeSlots.remove(slotId);
+
+			if (slot.hasPendingSlotRequest()) {
+				// reject the pending slot request --> triggering a new allocation attempt
+				rejectPendingSlotRequest(
+					slot.getAssignedSlotRequest(),
+					new Exception("The assigned slot " + slot.getSlotId() + " was removed."));
+			}
+
+			AllocationID oldAllocationId = slot.getAllocationId();
+
+			fulfilledSlotRequests.remove(oldAllocationId);
+
+			TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(slot.getInstanceId());
+
+			if (null != taskManagerRegistration) {
+				taskManagerRegistration.removeSlot(slotId);
+			}
+		} else {
+			LOG.debug("There was no slot registered with slot id {}.", slotId);
 		}
-		return registeredSlots.get(resourceId).get(slotId);
 	}
 
-	// ------------------------------------------------------------------------
-	//  Framework specific behavior
-	// ------------------------------------------------------------------------
+	// ---------------------------------------------------------------------------------------------
+	// Internal request handling methods
+	// ---------------------------------------------------------------------------------------------
 
 	/**
-	 * Choose a slot to use among all free slots, the behavior is framework specified.
+	 * Removes a pending slot request identified by the given allocation id from a slot identified
+	 * by the given slot id.
 	 *
-	 * @param request   The slot request
-	 * @param freeSlots All slots which can be used
-	 * @return The slot we choose to use, <tt>null</tt> if we did not find a match
+	 * @param slotId identifying the slot
+	 * @param allocationId identifying the presumable assigned pending slot request
 	 */
-	protected abstract ResourceSlot chooseSlotToUse(final SlotRequest request,
-		final Map<SlotID, ResourceSlot> freeSlots);
+	private void removeSlotRequestFromSlot(SlotID slotId, AllocationID allocationId) {
+		TaskManagerSlot taskManagerSlot = slots.get(slotId);
+
+		if (null != taskManagerSlot) {
+			if (taskManagerSlot.hasPendingSlotRequest() && Objects.equals(allocationId, taskManagerSlot.getAssignedSlotRequest().getAllocationId())) {
+				taskManagerSlot.setAssignedSlotRequest(null);
+			}
+
+			if (taskManagerSlot.isFree()) {
+				handleFreeSlot(taskManagerSlot);
+			}
+
+			TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(taskManagerSlot.getInstanceId());
+
+			if (null != taskManagerRegistration && !anySlotUsed(taskManagerRegistration.getSlots())) {
+				registerTaskManagerTimeout(taskManagerRegistration);
+			}
+		} else {
+			LOG.debug("There was no slot with {} registered. Probably this slot has been already freed.", slotId);
+		}
+	}
 
 	/**
-	 * Choose a pending request to fulfill when we have a free slot, the behavior is framework specified.
+	 * Handles a failed slot request. The slot manager tries to find a new slot fulfilling
+	 * the resource requirements for the failed slot request.
 	 *
-	 * @param offeredSlot     The free slot
-	 * @param pendingRequests All the pending slot requests
-	 * @return The chosen SlotRequest, <tt>null</tt> if we did not find a match
+	 * @param slotId identifying the slot which was assigned to the slot request before
+	 * @param allocationId identifying the failed slot request
+	 * @param cause of the failure
 	 */
-	protected abstract SlotRequest chooseRequestToFulfill(final ResourceSlot offeredSlot,
-		final Map<AllocationID, SlotRequest> pendingRequests);
+	private void handleFailedSlotRequest(SlotID slotId, AllocationID allocationId, Throwable cause) {
+		PendingSlotRequest pendingSlotRequest = pendingSlotRequests.get(allocationId);
+
+		LOG.debug("Slot request with allocation id {} failed for slot {}.", allocationId, slotId, cause);
+
+		if (null != pendingSlotRequest) {
+			pendingSlotRequest.setRequestFuture(null);
+
+			try {
+				internalRequestSlot(pendingSlotRequest);
+			} catch (ResourceManagerException e) {
+				pendingSlotRequests.remove(allocationId);
 
-	// ------------------------------------------------------------------------
-	//  Helper classes
-	// ------------------------------------------------------------------------
+				resourceManagerActions.notifyAllocationFailure(
+					pendingSlotRequest.getJobId(),
+					allocationId,
+					e);
+			}
+		} else {
+			LOG.debug("There was not pending slot request with allocation id {}. Probably the request has been fulfilled or cancelled.", allocationId);
+		}
+	}
 
 	/**
-	 * We maintain all the allocations with SlotID and AllocationID. We are able to get or remove the allocation info
-	 * either by SlotID or AllocationID.
+	 * Rejects the pending slot request by failing the request future with a
+	 * {@link SlotAllocationException}.
+	 *
+	 * @param pendingSlotRequest to reject
+	 * @param cause of the rejection
 	 */
-	private static class AllocationMap {
+	private void rejectPendingSlotRequest(PendingSlotRequest pendingSlotRequest, Exception cause) {
+		CompletableFuture<Acknowledge> request = pendingSlotRequest.getRequestFuture();
 
-		/** All allocated slots (by SlotID) */
-		private final Map<SlotID, AllocationID> allocatedSlots;
+		if (null != request) {
+			request.completeExceptionally(new SlotAllocationException(cause));
+		} else {
+			LOG.debug("Cannot reject pending slot request {}, since no request has been sent.", pendingSlotRequest.getAllocationId());
+		}
+	}
 
-		/** All allocated slots (by AllocationID), it'a a inverse view of allocatedSlots */
-		private final Map<AllocationID, SlotID> allocatedSlotsByAllocationId;
+	/**
+	 * Cancels the given slot request.
+	 *
+	 * @param pendingSlotRequest to cancel
+	 */
+	private void cancelPendingSlotRequest(PendingSlotRequest pendingSlotRequest) {
+		pendingSlotRequest.cancelTimeout();
 
-		AllocationMap() {
-			this.allocatedSlots = new HashMap<>(16);
-			this.allocatedSlotsByAllocationId = new HashMap<>(16);
-		}
+		CompletableFuture<Acknowledge> request = pendingSlotRequest.getRequestFuture();
 
-		/**
-		 * Add a allocation
-		 *
-		 * @param slotId       The slot id
-		 * @param allocationId The allocation id
-		 */
-		void addAllocation(final SlotID slotId, final AllocationID allocationId) {
-			allocatedSlots.put(slotId, allocationId);
-			allocatedSlotsByAllocationId.put(allocationId, slotId);
+		if (null != request) {
+			request.cancel(false);
 		}
+	}
+
+	// ---------------------------------------------------------------------------------------------
+	// Internal timeout methods
+	// ---------------------------------------------------------------------------------------------
+
+	private void timeoutTaskManager(InstanceID instanceId, UUID timeoutIdentifier) {
+		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.remove(instanceId);
 
-		/**
-		 * De-allocation with slot id
-		 *
-		 * @param slotId The slot id
-		 */
-		void removeAllocation(final SlotID slotId) {
-			if (allocatedSlots.containsKey(slotId)) {
-				final AllocationID allocationId = allocatedSlots.get(slotId);
-				allocatedSlots.remove(slotId);
-				allocatedSlotsByAllocationId.remove(allocationId);
+		if (null != taskManagerRegistration) {
+			if (Objects.equals(timeoutIdentifier, taskManagerRegistration.getTimeoutIdentifier())) {
+				if (anySlotUsed(taskManagerRegistration.getSlots())) {
+					LOG.debug("Cannot release the task manager with instance id {}, because some " +
+						"of its slots are still being used.", instanceId);
+				} else {
+					unregisterTaskManager(instanceId);
+
+					resourceManagerActions.releaseResource(instanceId);
+				}
+			} else {
+				taskManagerRegistrations.put(instanceId, taskManagerRegistration);
+
+				LOG.debug("Expected timeout identifier {} differs from the task manager's " +
+					"timeout identifier {}. Ignoring the task manager timeout call.",
+					timeoutIdentifier, taskManagerRegistration.getTimeoutIdentifier());
 			}
+		} else {
+			LOG.debug("Could not find a registered task manager with instance id {}. Ignoring the task manager timeout call.", instanceId);
 		}
+	}
 
-		/**
-		 * De-allocation with allocation id
-		 *
-		 * @param allocationId The allocation id
-		 */
-		void removeAllocation(final AllocationID allocationId) {
-			if (allocatedSlotsByAllocationId.containsKey(allocationId)) {
-				SlotID slotId = allocatedSlotsByAllocationId.get(allocationId);
-				allocatedSlotsByAllocationId.remove(allocationId);
-				allocatedSlots.remove(slotId);
+	private void timeoutSlotRequest(AllocationID allocationId, UUID timeoutIdentifier) {
+		PendingSlotRequest pendingSlotRequest = pendingSlotRequests.remove(allocationId);
+
+		if (null != pendingSlotRequest) {
+			if (Objects.equals(timeoutIdentifier, pendingSlotRequest.getTimeoutIdentifier())) {
+				if (!pendingSlotRequest.isAssigned()) {
+
+					resourceManagerActions.notifyAllocationFailure(
+						pendingSlotRequest.getJobId(),
+						allocationId,
+						new TimeoutException("The allocation could not be fulfilled in time."));
+				} else {
+					LOG.debug("Cannot fail pending slot request {} because it has been assigned.", allocationId);
+				}
+			} else {
+				pendingSlotRequests.put(allocationId, pendingSlotRequest);
+
+				LOG.debug("Expected timeout identifier {} differs from the pending slot request's " +
+					"timeout identifier {}. Ignoring the slot request timeout call.",
+					timeoutIdentifier, pendingSlotRequest.getTimeoutIdentifier());
 			}
+		} else {
+			LOG.debug("Could not find pending slot request with allocation id {}. Ignoring the slot request timeout call.", allocationId);
 		}
+	}
 
-		/**
-		 * Check whether allocation exists by slot id
-		 *
-		 * @param slotId The slot id
-		 * @return true if the allocation exists
-		 */
-		boolean isAllocated(final SlotID slotId) {
-			return allocatedSlots.containsKey(slotId);
-		}
+	// ---------------------------------------------------------------------------------------------
+	// Internal utility methods
+	// ---------------------------------------------------------------------------------------------
 
-		/**
-		 * Check whether allocation exists by allocation id
-		 *
-		 * @param allocationId The allocation id
-		 * @return true if the allocation exists
-		 */
-		boolean isAllocated(final AllocationID allocationId) {
-			return allocatedSlotsByAllocationId.containsKey(allocationId);
-		}
+	private boolean checkDuplicateRequest(AllocationID allocationId) {
+		return pendingSlotRequests.containsKey(allocationId) || fulfilledSlotRequests.containsKey(allocationId);
+	}
 
-		AllocationID getAllocationID(final SlotID slotId) {
-			return allocatedSlots.get(slotId);
-		}
+	private boolean anySlotUsed(Iterable<SlotID> slotsToCheck) {
 
-		SlotID getSlotID(final AllocationID allocationId) {
-			return allocatedSlotsByAllocationId.get(allocationId);
-		}
+		if (null != slotsToCheck) {
+			boolean idle = true;
 
-		public int size() {
-			return allocatedSlots.size();
-		}
+			for (SlotID slotId : slotsToCheck) {
+				TaskManagerSlot taskManagerSlot = slots.get(slotId);
 
-		public void clear() {
-			allocatedSlots.clear();
-			allocatedSlotsByAllocationId.clear();
+				if (null != taskManagerSlot) {
+					idle &= taskManagerSlot.isFree();
+				}
+			}
+
+			return !idle;
+		} else {
+			return false;
 		}
 	}
 
-	/**
-	 * Clears the state of the SlotManager after leadership revokal
-	 */
-	public void clearState() {
-		taskManagers.clear();
-		registeredSlots.clear();
-		pendingSlotRequests.clear();
-		freeSlots.clear();
-		allocationMap.clear();
-	}
+	private void registerTaskManagerTimeout(final TaskManagerRegistration taskManagerRegistration) {
+		final UUID timeoutIdentifier = UUID.randomUUID();
 
-	// ------------------------------------------------------------------------
-	//  Testing utilities
-	// ------------------------------------------------------------------------
+		ScheduledFuture<?> timeoutFuture = scheduledExecutor.schedule(new Runnable() {
+			@Override
+			public void run() {
+				mainThreadExecutor.execute(new Runnable() {
+					@Override
+					public void run() {
+						timeoutTaskManager(taskManagerRegistration.getInstanceId(), timeoutIdentifier);
+					}
+				});
+			}
+		}, taskManagerTimeout.toMilliseconds(), TimeUnit.MILLISECONDS);
 
-	@VisibleForTesting
-	boolean isAllocated(final SlotID slotId) {
-		return allocationMap.isAllocated(slotId);
+		taskManagerRegistration.registerTimeout(timeoutFuture, timeoutIdentifier);
 	}
 
-	@VisibleForTesting
-	boolean isAllocated(final AllocationID allocationId) {
-		return allocationMap.isAllocated(allocationId);
+	private void checkInit() {
+		Preconditions.checkState(started, "The slot manager has not been started.");
 	}
 
-	/**
-	 * Add free slots directly to the free pool, this will not trigger pending requests allocation
-	 *
-	 * @param slot The resource slot
-	 */
-	@VisibleForTesting
-	void addFreeSlot(final ResourceSlot slot) {
-		final ResourceID resourceId = slot.getResourceID();
-		final SlotID slotId = slot.getSlotId();
+	// ---------------------------------------------------------------------------------------------
+	// Testing methods
+	// ---------------------------------------------------------------------------------------------
 
-		if (!registeredSlots.containsKey(resourceId)) {
-			registeredSlots.put(resourceId, new HashMap<SlotID, ResourceSlot>());
-		}
-		registeredSlots.get(resourceId).put(slot.getSlotId(), slot);
-		freeSlots.put(slotId, slot);
+	@VisibleForTesting
+	TaskManagerSlot getSlot(SlotID slotId) {
+		return slots.get(slotId);
 	}
 
 	@VisibleForTesting
-	int getAllocatedSlotCount() {
-		return allocationMap.size();
+	int getNumberRegisteredSlots() {
+		return slots.size();
 	}
 
 	@VisibleForTesting
-	int getFreeSlotCount() {
-		return freeSlots.size();
+	PendingSlotRequest getSlotRequest(AllocationID allocationId) {
+		return pendingSlotRequests.get(allocationId);
 	}
 
 	@VisibleForTesting
-	int getPendingRequestCount() {
-		return pendingSlotRequests.size();
+	boolean hasTimeoutRegistered(InstanceID instanceId) {
+		TaskManagerRegistration taskManagerRegistration = taskManagerRegistrations.get(instanceId);
+
+		if (null != taskManagerRegistration) {
+			return taskManagerRegistration.getTimeoutIdentifier() != null;
+		} else {
+			return false;
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerConfiguration.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerConfiguration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerConfiguration.java
new file mode 100644
index 0000000..d21c251
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerConfiguration.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.resourcemanager.slotmanager;
+
+import org.apache.flink.api.common.time.Time;
+import org.apache.flink.configuration.ConfigConstants;
+import org.apache.flink.configuration.ConfigOption;
+import org.apache.flink.configuration.ConfigOptions;
+import org.apache.flink.configuration.Configuration;
+import org.apache.flink.runtime.resourcemanager.exceptions.ConfigurationException;
+import org.apache.flink.util.Preconditions;
+import scala.concurrent.duration.Duration;
+
+public class SlotManagerConfiguration {
+
+	private final Time taskManagerRequestTimeout;
+	private final Time slotRequestTimeout;
+	private final Time taskManagerTimeout;
+
+	public SlotManagerConfiguration(
+			Time taskManagerRequestTimeout,
+			Time slotRequestTimeout,
+			Time taskManagerTimeout) {
+		this.taskManagerRequestTimeout = Preconditions.checkNotNull(taskManagerRequestTimeout);
+		this.slotRequestTimeout = Preconditions.checkNotNull(slotRequestTimeout);
+		this.taskManagerTimeout = Preconditions.checkNotNull(taskManagerTimeout);
+	}
+
+	public Time getTaskManagerRequestTimeout() {
+		return taskManagerRequestTimeout;
+	}
+
+	public Time getSlotRequestTimeout() {
+		return slotRequestTimeout;
+	}
+
+	public Time getTaskManagerTimeout() {
+		return taskManagerTimeout;
+	}
+
+	public static SlotManagerConfiguration fromConfiguration(Configuration configuration) throws ConfigurationException {
+		ConfigOption<String> timeoutOption = ConfigOptions
+			.key(ConfigConstants.AKKA_ASK_TIMEOUT)
+			.defaultValue(ConfigConstants.DEFAULT_AKKA_ASK_TIMEOUT);
+
+		final String strTimeout = configuration.getString(timeoutOption);
+		final Time timeout;
+
+		try {
+			timeout = Time.milliseconds(Duration.apply(strTimeout).toMillis());
+		} catch (NumberFormatException e) {
+			throw new ConfigurationException("Could not parse the resource manager's timeout " +
+				"value " + timeoutOption + '.', e);
+		}
+
+		return new SlotManagerConfiguration(timeout, timeout, timeout);
+	}
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerException.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerException.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerException.java
new file mode 100644
index 0000000..c322c81
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.resourcemanager.slotmanager;
+
+import org.apache.flink.runtime.resourcemanager.exceptions.ResourceManagerException;
+
+public class SlotManagerException extends ResourceManagerException {
+
+	private static final long serialVersionUID = -3723028616920379071L;
+
+	public SlotManagerException(String message) {
+		super(message);
+	}
+
+	public SlotManagerException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerFactory.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerFactory.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerFactory.java
deleted file mode 100644
index b4e9c99..0000000
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/SlotManagerFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.flink.runtime.resourcemanager.slotmanager;
-
-import org.apache.flink.runtime.resourcemanager.ResourceManagerServices;
-
-/**
- * Factory to create a SlotManager and provide it with dependencies.
- */
-public interface SlotManagerFactory {
-
-	/**
-	 * Creates a SlotManager and provides it with ResourceManager services.
-	 */
-	SlotManager create(ResourceManagerServices rmServices);
-}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
new file mode 100644
index 0000000..8e23dbb
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/slotmanager/TaskManagerRegistration.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.resourcemanager.slotmanager;
+
+import org.apache.flink.runtime.clusterframework.types.SlotID;
+import org.apache.flink.runtime.instance.InstanceID;
+import org.apache.flink.runtime.resourcemanager.registration.TaskExecutorConnection;
+import org.apache.flink.util.Preconditions;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
+
+public class TaskManagerRegistration {
+
+	private final TaskExecutorConnection taskManagerConnection;
+
+	private final HashSet<SlotID> slots;
+
+	private UUID timeoutIdentifier;
+
+	private ScheduledFuture<?> timeoutFuture;
+
+	public TaskManagerRegistration(TaskExecutorConnection taskManagerConnection) {
+		this.taskManagerConnection = Preconditions.checkNotNull(taskManagerConnection);
+
+		slots = new HashSet<>(4);
+
+		timeoutIdentifier = null;
+		timeoutFuture = null;
+	}
+
+	public TaskExecutorConnection getTaskManagerConnection() {
+		return taskManagerConnection;
+	}
+
+	public InstanceID getInstanceId() {
+		return taskManagerConnection.getInstanceID();
+	}
+
+	public UUID getTimeoutIdentifier() {
+		return timeoutIdentifier;
+	}
+
+	public Set<SlotID> getSlots() {
+		return slots;
+	}
+
+	public boolean removeSlot(SlotID slotId) {
+		return slots.remove(slotId);
+	}
+
+	public void addSlot(SlotID slotId) {
+		slots.add(slotId);
+	}
+
+	public void cancelTimeout() {
+		if (null != timeoutFuture) {
+			timeoutFuture.cancel(false);
+
+			timeoutFuture = null;
+			timeoutIdentifier = null;
+		}
+	}
+
+	public void registerTimeout(ScheduledFuture<?> newTimeoutFuture, UUID newTimeoutIdentifier) {
+		cancelTimeout();
+
+		timeoutFuture = newTimeoutFuture;
+		timeoutIdentifier = newTimeoutIdentifier;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
index 54adce6..7a9da28 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotReport.java
@@ -19,8 +19,9 @@
 package org.apache.flink.runtime.taskexecutor;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
+import java.util.Iterator;
 
 import static org.apache.flink.util.Preconditions.checkNotNull;
 
@@ -29,12 +30,12 @@ import static org.apache.flink.util.Preconditions.checkNotNull;
  * which slots are available and allocated, and what jobs (JobManagers) the allocated slots
  * have been allocated to.
  */
-public class SlotReport implements Serializable {
+public class SlotReport implements Serializable, Iterable<SlotStatus> {
 
 	private static final long serialVersionUID = -3150175198722481689L;
 
 	/** The slots status of the TaskManager */
-	private final List<SlotStatus> slotsStatus;
+	private final Collection<SlotStatus> slotsStatus;
 
 	public SlotReport() {
 		this(Collections.<SlotStatus>emptyList());
@@ -44,12 +45,16 @@ public class SlotReport implements Serializable {
 		this(Collections.singletonList(slotStatus));
 	}
 
-	public SlotReport(final List<SlotStatus> slotsStatus) {
+	public SlotReport(final Collection<SlotStatus> slotsStatus) {
 		this.slotsStatus = checkNotNull(slotsStatus);
 	}
 
-	public List<SlotStatus> getSlotsStatus() {
+	public Collection<SlotStatus> getSlotsStatus() {
 		return slotsStatus;
 	}
 
+	@Override
+	public Iterator<SlotStatus> iterator() {
+		return slotsStatus.iterator();
+	}
 }

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotStatus.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotStatus.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotStatus.java
index 0f57bb1..a3bc4a6 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotStatus.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/SlotStatus.java
@@ -38,7 +38,7 @@ public class SlotStatus implements Serializable {
 	private final SlotID slotID;
 
 	/** the resource profile of the slot */
-	private final ResourceProfile profiler;
+	private final ResourceProfile resourceProfile;
 
 	/** if the slot is allocated, allocationId identify its allocation; else, allocationId is null */
 	private final AllocationID allocationID;
@@ -46,16 +46,17 @@ public class SlotStatus implements Serializable {
 	/** if the slot is allocated, jobId identify which job this slot is allocated to; else, jobId is null */
 	private final JobID jobID;
 
-	public SlotStatus(SlotID slotID, ResourceProfile profiler) {
-		this(slotID, profiler, null, null);
+	public SlotStatus(SlotID slotID, ResourceProfile resourceProfile) {
+		this(slotID, resourceProfile, null, null);
 	}
 
 	public SlotStatus(
-			SlotID slotID, ResourceProfile profiler,
+			SlotID slotID,
+			ResourceProfile resourceProfile,
 			JobID jobID,
 			AllocationID allocationID) {
 		this.slotID = checkNotNull(slotID, "slotID cannot be null");
-		this.profiler = checkNotNull(profiler, "profile cannot be null");
+		this.resourceProfile = checkNotNull(resourceProfile, "profile cannot be null");
 		this.allocationID = allocationID;
 		this.jobID = jobID;
 	}
@@ -74,8 +75,8 @@ public class SlotStatus implements Serializable {
 	 *
 	 * @return The resource profile
 	 */
-	public ResourceProfile getProfiler() {
-		return profiler;
+	public ResourceProfile getResourceProfile() {
+		return resourceProfile;
 	}
 
 	/**
@@ -110,7 +111,7 @@ public class SlotStatus implements Serializable {
 		if (!slotID.equals(that.slotID)) {
 			return false;
 		}
-		if (!profiler.equals(that.profiler)) {
+		if (!resourceProfile.equals(that.resourceProfile)) {
 			return false;
 		}
 		if (allocationID != null ? !allocationID.equals(that.allocationID) : that.allocationID != null) {
@@ -123,7 +124,7 @@ public class SlotStatus implements Serializable {
 	@Override
 	public int hashCode() {
 		int result = slotID.hashCode();
-		result = 31 * result + profiler.hashCode();
+		result = 31 * result + resourceProfile.hashCode();
 		result = 31 * result + (allocationID != null ? allocationID.hashCode() : 0);
 		result = 31 * result + (jobID != null ? jobID.hashCode() : 0);
 		return result;

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutor.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutor.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutor.java
index d04cabb..5b8c8ee 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutor.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutor.java
@@ -61,8 +61,6 @@ import org.apache.flink.runtime.registration.RegistrationConnectionListener;
 import org.apache.flink.runtime.resourcemanager.ResourceManagerGateway;
 import org.apache.flink.runtime.metrics.groups.TaskManagerMetricGroup;
 import org.apache.flink.runtime.metrics.groups.TaskMetricGroup;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestRegistered;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestReply;
 import org.apache.flink.runtime.rpc.FatalErrorHandler;
 import org.apache.flink.runtime.rpc.RpcEndpoint;
 import org.apache.flink.runtime.rpc.RpcMethod;
@@ -71,6 +69,7 @@ import org.apache.flink.runtime.rpc.RpcServiceUtils;
 import org.apache.flink.runtime.taskexecutor.exceptions.CheckpointException;
 import org.apache.flink.runtime.taskexecutor.exceptions.PartitionException;
 import org.apache.flink.runtime.taskexecutor.exceptions.SlotAllocationException;
+import org.apache.flink.runtime.taskexecutor.exceptions.SlotOccupiedException;
 import org.apache.flink.runtime.taskexecutor.exceptions.TaskException;
 import org.apache.flink.runtime.taskexecutor.exceptions.TaskSubmissionException;
 import org.apache.flink.runtime.taskexecutor.rpc.RpcCheckpointResponder;
@@ -99,6 +98,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.TimeoutException;
 
@@ -315,7 +315,7 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 			throw new TaskSubmissionException(message);
 		}
 
-		if (!jobManagerConnection.getLeaderId().equals(jobManagerLeaderId)) {
+		if (!Objects.equals(jobManagerConnection.getLeaderId(), jobManagerLeaderId)) {
 			final String message = "Rejecting the task submission because the job manager leader id " +
 				jobManagerLeaderId + " does not match the expected job manager leader id " +
 				jobManagerConnection.getLeaderId() + '.';
@@ -355,30 +355,30 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 		PartitionProducerStateChecker partitionStateChecker = jobManagerConnection.getPartitionStateChecker();
 
 		Task task = new Task(
-				jobInformation,
-				taskInformation,
-				tdd.getExecutionAttemptId(),
-				tdd.getAllocationId(),
-				tdd.getSubtaskIndex(),
-				tdd.getAttemptNumber(),
-				tdd.getProducedPartitions(),
-				tdd.getInputGates(),
-				tdd.getTargetSlotNumber(),
-				tdd.getTaskStateHandles(),
-				memoryManager,
-				ioManager,
-				networkEnvironment,
-				broadcastVariableManager,
-				taskManagerActions,
-				inputSplitProvider,
-				checkpointResponder,
-				libraryCache,
-				fileCache,
-				taskManagerConfiguration,
-				taskMetricGroup,
-				resultPartitionConsumableNotifier,
-				partitionStateChecker,
-				getRpcService().getExecutor());
+			jobInformation,
+			taskInformation,
+			tdd.getExecutionAttemptId(),
+			tdd.getAllocationId(),
+			tdd.getSubtaskIndex(),
+			tdd.getAttemptNumber(),
+			tdd.getProducedPartitions(),
+			tdd.getInputGates(),
+			tdd.getTargetSlotNumber(),
+			tdd.getTaskStateHandles(),
+			memoryManager,
+			ioManager,
+			networkEnvironment,
+			broadcastVariableManager,
+			taskManagerActions,
+			inputSplitProvider,
+			checkpointResponder,
+			libraryCache,
+			fileCache,
+			taskManagerConfiguration,
+			taskMetricGroup,
+			resultPartitionConsumableNotifier,
+			partitionStateChecker,
+			getRpcService().getExecutor());
 
 		log.info("Received task {}.", task.getTaskInfo().getTaskNameWithSubtasks());
 
@@ -561,7 +561,6 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 	// ----------------------------------------------------------------------
 
 	/**
-	 * /**
 	 * Requests a slot from the TaskManager
 	 *
 	 * @param slotId identifying the requested slot
@@ -573,12 +572,14 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 	 * @return answer to the slot request
 	 */
 	@RpcMethod
-	public TMSlotRequestReply requestSlot(
+	public Acknowledge requestSlot(
 		final SlotID slotId,
 		final JobID jobId,
 		final AllocationID allocationId,
 		final String targetAddress,
 		final UUID rmLeaderId) throws SlotAllocationException {
+		// TODO: Filter invalid requests from the resource manager by using the instance/registration Id
+
 		log.info("Receive slot request {} for job {} from resource manager with leader id {}.",
 			allocationId, jobId, rmLeaderId);
 
@@ -608,7 +609,8 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 			final String message = "The slot " + slotId + " has already been allocated for a different job.";
 
 			log.info(message);
-			throw new SlotAllocationException(message);
+
+			throw new SlotOccupiedException(message, taskSlotTable.getCurrentAllocation(slotId.getSlotNumber()));
 		}
 
 		if (jobManagerTable.contains(jobId)) {
@@ -635,7 +637,7 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 			}
 		}
 
-		return new TMSlotRequestRegistered(resourceManagerConnection.getRegistrationId(), getResourceID(), allocationId);
+		return Acknowledge.get();
 	}
 
 	// ----------------------------------------------------------------------
@@ -1046,7 +1048,8 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 				resourceManagerGateway.notifySlotAvailable(
 					resourceManagerConnection.getTargetLeaderId(),
 					resourceManagerConnection.getRegistrationId(),
-					new SlotID(getResourceID(), freedSlotIndex));
+					new SlotID(getResourceID(), freedSlotIndex),
+					allocationId);
 			}
 		} catch (SlotNotFoundException e) {
 			log.debug("Could not free slot for allocation id {}.", allocationId, e);
@@ -1079,7 +1082,7 @@ public class TaskExecutor extends RpcEndpoint<TaskExecutorGateway> {
 	private boolean isJobManagerConnectionValid(JobID jobId, UUID leaderId) {
 		JobManagerConnection jmConnection = jobManagerTable.get(jobId);
 
-		return jmConnection != null && jmConnection.getLeaderId().equals(leaderId);
+		return jmConnection != null && Objects.equals(jmConnection.getLeaderId(), leaderId);
 	}
 
 	// ------------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
index 2bbf0e6..bedf8ec 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutorGateway.java
@@ -25,7 +25,6 @@ import org.apache.flink.runtime.clusterframework.types.AllocationID;
 import org.apache.flink.runtime.clusterframework.types.ResourceID;
 import org.apache.flink.runtime.clusterframework.types.SlotID;
 import org.apache.flink.runtime.concurrent.Future;
-import org.apache.flink.runtime.resourcemanager.messages.taskexecutor.TMSlotRequestReply;
 import org.apache.flink.runtime.deployment.TaskDeploymentDescriptor;
 import org.apache.flink.runtime.executiongraph.ExecutionAttemptID;
 import org.apache.flink.runtime.executiongraph.PartitionInfo;
@@ -51,7 +50,7 @@ public interface TaskExecutorGateway extends RpcGateway {
 	 * @throws SlotAllocationException if the slot allocation fails
 	 * @return answer to the slot request
 	 */
-	Future<TMSlotRequestReply> requestSlot(
+	Future<Acknowledge> requestSlot(
 		SlotID slotId,
 		JobID jobId,
 		AllocationID allocationId,

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/exceptions/SlotOccupiedException.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/exceptions/SlotOccupiedException.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/exceptions/SlotOccupiedException.java
new file mode 100644
index 0000000..93e67a8
--- /dev/null
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/exceptions/SlotOccupiedException.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.runtime.taskexecutor.exceptions;
+
+import org.apache.flink.runtime.clusterframework.types.AllocationID;
+import org.apache.flink.util.Preconditions;
+
+public class SlotOccupiedException extends SlotAllocationException {
+	private static final long serialVersionUID = -3986333914244338888L;
+
+	private final AllocationID allocationId;
+
+	public SlotOccupiedException(String message, AllocationID allocationId) {
+		super(message);
+		this.allocationId = Preconditions.checkNotNull(allocationId);
+	}
+
+	public SlotOccupiedException(String message, Throwable cause, AllocationID allocationId) {
+		super(message, cause);
+		this.allocationId = Preconditions.checkNotNull(allocationId);
+	}
+
+	public SlotOccupiedException(Throwable cause, AllocationID allocationId) {
+		super(cause);
+		this.allocationId = Preconditions.checkNotNull(allocationId);
+	}
+
+	public AllocationID getAllocationId() {
+		return allocationId;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/TaskSlotTable.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/TaskSlotTable.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/TaskSlotTable.java
index 081d8f8..5c51c7c 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/TaskSlotTable.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/TaskSlotTable.java
@@ -509,6 +509,16 @@ public class TaskSlotTable implements TimeoutListener<AllocationID> {
 		return new TaskIterator(jobId);
 	}
 
+	/**
+	 * Get the current allocation for the task slot with the given index.
+	 *
+	 * @param index identifying the slot for which the allocation id shall be retrieved
+	 * @return Allocation id of the specified slot if allocated; otherwise null
+	 */
+	public AllocationID getCurrentAllocation(int index) {
+		return taskSlots.get(index).getAllocationId();
+	}
+
 	// ---------------------------------------------------------------------
 	// TimeoutListener methods
 	// ---------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
index e4e20b9..41c2e16 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/clusterframework/ResourceManagerTest.java
@@ -49,7 +49,7 @@ import org.apache.flink.runtime.registration.RegistrationResponse;
 import org.apache.flink.runtime.resourcemanager.JobLeaderIdService;
 import org.apache.flink.runtime.resourcemanager.ResourceManagerConfiguration;
 import org.apache.flink.runtime.resourcemanager.StandaloneResourceManager;
-import org.apache.flink.runtime.resourcemanager.TestingSlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
 import org.apache.flink.runtime.rpc.TestingSerialRpcService;
 import org.apache.flink.runtime.taskexecutor.SlotReport;
 import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
@@ -391,10 +391,14 @@ public class ResourceManagerTest extends TestLogger {
 		final ScheduledExecutor scheduledExecutor = mock(ScheduledExecutor.class);
 		final HeartbeatServices heartbeatServices = new TestingHeartbeatServices(heartbeatInterval, heartbeatTimeout, scheduledExecutor);
 
-		final TestingSlotManagerFactory slotManagerFactory = new TestingSlotManagerFactory();
 		final MetricRegistry metricRegistry = mock(MetricRegistry.class);
 		final JobLeaderIdService jobLeaderIdService = mock(JobLeaderIdService.class);
 		final TestingFatalErrorHandler testingFatalErrorHandler = new TestingFatalErrorHandler();
+		final SlotManager slotManager = new SlotManager(
+			rpcService.getScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime());
 
 		try {
 			final StandaloneResourceManager resourceManager = new StandaloneResourceManager(
@@ -404,7 +408,7 @@ public class ResourceManagerTest extends TestLogger {
 				resourceManagerConfiguration,
 				highAvailabilityServices,
 				heartbeatServices,
-				slotManagerFactory,
+				slotManager,
 				metricRegistry,
 				jobLeaderIdService,
 				testingFatalErrorHandler);

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolRpcTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolRpcTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolRpcTest.java
index 89fd22f..b444640 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolRpcTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolRpcTest.java
@@ -80,7 +80,7 @@ public class SlotPoolRpcTest {
 				Time.days(1), Time.days(1),
 				Time.milliseconds(100) // this is the timeout for the request tested here
 		);
-		pool.start(UUID.randomUUID());
+		pool.start(UUID.randomUUID(), "foobar");
 
 		Future<SimpleSlot> future = pool.allocateSlot(mock(ScheduledUnit.class), DEFAULT_TESTING_PROFILE, null);
 

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolTest.java
index b4149b2..cf95461 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/instance/SlotPoolTest.java
@@ -78,7 +78,9 @@ public class SlotPoolTest extends TestLogger {
 
 		mainThreadValidatorUtil.enterMainThread();
 
-		slotPool.start(UUID.randomUUID());
+		final String jobManagerAddress = "foobar";
+
+		slotPool.start(UUID.randomUUID(), jobManagerAddress);
 
 		this.resourceManagerGateway = mock(ResourceManagerGateway.class);
 		when(resourceManagerGateway

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerHATest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerHATest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerHATest.java
index 49bc570..986f848 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerHATest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerHATest.java
@@ -25,9 +25,10 @@ import org.apache.flink.runtime.heartbeat.HeartbeatServices;
 import org.apache.flink.runtime.highavailability.TestingHighAvailabilityServices;
 import org.apache.flink.runtime.leaderelection.TestingLeaderElectionService;
 import org.apache.flink.runtime.metrics.MetricRegistry;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerConfiguration;
 import org.apache.flink.runtime.rpc.RpcService;
 import org.apache.flink.runtime.rpc.TestingSerialRpcService;
+import org.apache.flink.runtime.testingUtils.TestingUtils;
 import org.apache.flink.runtime.util.TestingFatalErrorHandler;
 import org.apache.flink.util.TestLogger;
 import org.junit.Assert;
@@ -57,13 +58,17 @@ public class ResourceManagerHATest extends TestLogger {
 			Time.seconds(5L),
 			Time.seconds(5L));
 
-		ResourceManagerRuntimeServicesConfiguration resourceManagerRuntimeServicesConfiguration = new ResourceManagerRuntimeServicesConfiguration(Time.seconds(5L));
+		ResourceManagerRuntimeServicesConfiguration resourceManagerRuntimeServicesConfiguration = new ResourceManagerRuntimeServicesConfiguration(
+			Time.seconds(5L),
+			new SlotManagerConfiguration(
+				TestingUtils.infiniteTime(),
+				TestingUtils.infiniteTime(),
+				TestingUtils.infiniteTime()));
 		ResourceManagerRuntimeServices resourceManagerRuntimeServices = ResourceManagerRuntimeServices.fromConfiguration(
 			resourceManagerRuntimeServicesConfiguration,
 			highAvailabilityServices,
 			rpcService.getScheduledExecutor());
 
-		SlotManagerFactory slotManagerFactory = new TestingSlotManagerFactory();
 		MetricRegistry metricRegistry = mock(MetricRegistry.class);
 
 		TestingFatalErrorHandler testingFatalErrorHandler = new TestingFatalErrorHandler();
@@ -76,7 +81,7 @@ public class ResourceManagerHATest extends TestLogger {
 				resourceManagerConfiguration,
 				highAvailabilityServices,
 				heartbeatServices,
-				slotManagerFactory,
+				resourceManagerRuntimeServices.getSlotManager(),
 				metricRegistry,
 				resourceManagerRuntimeServices.getJobLeaderIdService(),
 				testingFatalErrorHandler);

http://git-wip-us.apache.org/repos/asf/flink/blob/59aefb57/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerJobMasterTest.java
----------------------------------------------------------------------
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerJobMasterTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerJobMasterTest.java
index 6a151ac..4836f74 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerJobMasterTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/resourcemanager/ResourceManagerJobMasterTest.java
@@ -31,10 +31,11 @@ import org.apache.flink.runtime.jobmaster.JobMasterRegistrationSuccess;
 import org.apache.flink.runtime.leaderelection.TestingLeaderElectionService;
 import org.apache.flink.runtime.leaderelection.TestingLeaderRetrievalService;
 import org.apache.flink.runtime.metrics.MetricRegistry;
-import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManagerFactory;
+import org.apache.flink.runtime.resourcemanager.slotmanager.SlotManager;
 import org.apache.flink.runtime.rpc.FatalErrorHandler;
 import org.apache.flink.runtime.rpc.TestingSerialRpcService;
 import org.apache.flink.runtime.registration.RegistrationResponse;
+import org.apache.flink.runtime.testingUtils.TestingUtils;
 import org.apache.flink.runtime.util.TestingFatalErrorHandler;
 import org.apache.flink.util.TestLogger;
 import org.junit.After;
@@ -240,12 +241,17 @@ public class ResourceManagerJobMasterTest extends TestLogger {
 		ResourceManagerConfiguration resourceManagerConfiguration = new ResourceManagerConfiguration(
 			Time.seconds(5L),
 			Time.seconds(5L));
-		SlotManagerFactory slotManagerFactory = new TestingSlotManagerFactory();
 		MetricRegistry metricRegistry = mock(MetricRegistry.class);
 		JobLeaderIdService jobLeaderIdService = new JobLeaderIdService(
 			highAvailabilityServices,
 			rpcService.getScheduledExecutor(),
 			Time.minutes(5L));
+			
+		final SlotManager slotManager = new SlotManager(
+			rpcService.getScheduledExecutor(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime(),
+			TestingUtils.infiniteTime());
 
 		ResourceManager resourceManager = new StandaloneResourceManager(
 			rpcService,
@@ -254,7 +260,7 @@ public class ResourceManagerJobMasterTest extends TestLogger {
 			resourceManagerConfiguration,
 			highAvailabilityServices,
 			heartbeatServices,
-			slotManagerFactory,
+			slotManager,
 			metricRegistry,
 			jobLeaderIdService,
 			fatalErrorHandler);