private User findUserWithHighestAverageResourceUtilAboveGuarantee() {
   double most = 0.0;
   User mostOverUser = null;
   for (User user : this.userMap.values()) {
     double over = user.getResourcePoolAverageUtilization() - 1.0;
     if ((over > most) && (!user.getTopologiesRunning().isEmpty())) {
       most = over;
       mostOverUser = user;
     }
   }
   return mostOverUser;
 }
  private void evictTopology(TopologyDetails topologyEvict) {
    Collection<WorkerSlot> workersToEvict =
        this.cluster.getUsedSlotsByTopologyId(topologyEvict.getId());
    User submitter = this.userMap.get(topologyEvict.getTopologySubmitter());

    LOG.info(
        "Evicting Topology {} with workers: {} from user {}",
        topologyEvict.getName(),
        workersToEvict,
        topologyEvict.getTopologySubmitter());
    this.nodes.freeSlots(workersToEvict);
    submitter.moveTopoFromRunningToPending(topologyEvict, this.cluster);
  }
  @Override
  public boolean makeSpaceForTopo(TopologyDetails td) {
    LOG.debug(
        "attempting to make space for topo {} from user {}",
        td.getName(),
        td.getTopologySubmitter());
    User submitter = this.userMap.get(td.getTopologySubmitter());
    if (submitter.getCPUResourceGuaranteed() == null
        || submitter.getMemoryResourceGuaranteed() == null
        || submitter.getCPUResourceGuaranteed() == 0.0
        || submitter.getMemoryResourceGuaranteed() == 0.0) {
      return false;
    }

    double cpuNeeded = td.getTotalRequestedCpu() / submitter.getCPUResourceGuaranteed();
    double memoryNeeded =
        (td.getTotalRequestedMemOffHeap() + td.getTotalRequestedMemOnHeap())
            / submitter.getMemoryResourceGuaranteed();

    User evictUser = this.findUserWithHighestAverageResourceUtilAboveGuarantee();
    // check if user has enough resource under his or her resource guarantee to schedule topology
    if ((1.0 - submitter.getCPUResourcePoolUtilization()) >= cpuNeeded
        && (1.0 - submitter.getMemoryResourcePoolUtilization()) >= memoryNeeded) {
      if (evictUser != null) {
        TopologyDetails topologyEvict = evictUser.getRunningTopologyWithLowestPriority();
        LOG.debug(
            "Running Topology {} from user {} is still within user's resource guarantee thus, POTENTIALLY evicting Topology {} from user {} since:"
                + "\n(1.0 - submitter.getCPUResourcePoolUtilization()) = {} >= cpuNeeded = {}"
                + "\nand"
                + "\n(1.0 - submitter.getMemoryResourcePoolUtilization()) = {} >= memoryNeeded = {}",
            td,
            submitter,
            topologyEvict,
            evictUser,
            (1.0 - submitter.getCPUResourcePoolUtilization()),
            cpuNeeded,
            (1.0 - submitter.getMemoryResourcePoolUtilization()),
            memoryNeeded);
        evictTopology(topologyEvict);
        return true;
      }
    } else {
      if (evictUser != null) {
        if ((evictUser.getResourcePoolAverageUtilization() - 1.0)
            > (((cpuNeeded + memoryNeeded) / 2)
                + (submitter.getResourcePoolAverageUtilization() - 1.0))) {
          TopologyDetails topologyEvict = evictUser.getRunningTopologyWithLowestPriority();
          LOG.debug(
              "POTENTIALLY Evicting Topology {} from user {} since:"
                  + "\n((evictUser.getResourcePoolAverageUtilization() - 1.0) = {}"
                  + "\n(cpuNeeded + memoryNeeded) / 2) = {} and (submitter.getResourcePoolAverageUtilization() - 1.0)) = {} Thus,"
                  + "\n(evictUser.getResourcePoolAverageUtilization() - 1.0) = {} > (((cpuNeeded + memoryNeeded) / 2) + (submitter.getResourcePoolAverageUtilization() - 1.0)) = {}",
              topologyEvict,
              evictUser,
              (evictUser.getResourcePoolAverageUtilization() - 1.0),
              ((cpuNeeded + memoryNeeded) / 2),
              (submitter.getResourcePoolAverageUtilization() - 1.0),
              (evictUser.getResourcePoolAverageUtilization() - 1.0),
              (((cpuNeeded + memoryNeeded) / 2)
                  + (submitter.getResourcePoolAverageUtilization() - 1.0)));
          evictTopology(topologyEvict);
          return true;
        }
      }
    }
    // See if there is a lower priority topology that can be evicted from the current user
    // topologies should already be sorted in order of increasing priority.
    // Thus, topology at the front of the queue has the lowest priority
    for (TopologyDetails topo : submitter.getTopologiesRunning()) {
      // check to if there is a topology with a lower priority we can evict
      if (topo.getTopologyPriority() > td.getTopologyPriority()) {
        LOG.debug(
            "POTENTIALLY Evicting Topology {} from user {} (itself) since topology {} has a lower priority than topology {}",
            topo,
            submitter,
            topo,
            td);
        evictTopology(topo);
        return true;
      }
    }
    return false;
  }