docs: public int freeSlot(AllocationID allocationId, Throwable cause) throws SlotNotFoundException {
  		checkInit();
  
  		TaskSlot taskSlot = getTaskSlot(allocationId);
  
  		if (taskSlot != null) {
  			if (LOG.isDebugEnabled()) {
  				LOG.debug("Free slot {}.", taskSlot, cause);
  			} else {
  				LOG.info("Free slot {}.", taskSlot);
  			}
  
  			final JobID jobId = taskSlot.getJobId();
  
  			if (taskSlot.markFree()) {
  				// remove the allocation id to task slot mapping
  				allocationIDTaskSlotMap.remove(allocationId);
  
  				// unregister a potential timeout
  				timerService.unregisterTimeout(allocationId);
  
  				Set<AllocationID> slots = slotsPerJob.get(jobId);
  
  				if (slots == null) {
  					throw new IllegalStateException("There are no more slots allocated for the job " + jobId +
  						". This indicates a programming bug.");
  				}
  
  				slots.remove(allocationId);
  
  				if (slots.isEmpty()) {
  					slotsPerJob.remove(jobId);
  				}
  
  				return taskSlot.getIndex();
  			} else {
  				// we couldn't free the task slot because it still contains task, fail the tasks
  				// and set the slot state to releasing so that it gets eventually freed
  				taskSlot.markReleasing();
  
  				Iterator<Task> taskIterator = taskSlot.getTasks();
  
  				while (taskIterator.hasNext()) {
  					taskIterator.next().failExternally(cause);
  				}
  
  				return -1;
  			}
  		} else {
  			throw new SlotNotFoundException(allocationId);
  		}
  	}