class OpportunisticContainerAllocator {

  public List<Container> allocateContainers(ResourceBlacklistRequest blackList,
      List<ResourceRequest> oppResourceReqs,
      ApplicationAttemptId applicationAttemptId,
      OpportunisticContainerContext opportContext, long rmIdentifier,
      String appSubmitter) throws YarnException {

    // Update black list.
    if (blackList != null) {
      opportContext.getBlacklist().removeAll(blackList.getBlacklistRemovals());
      opportContext.getBlacklist().addAll(blackList.getBlacklistAdditions());
    }

    // Add OPPORTUNISTIC requests to the outstanding ones.
    opportContext.addToOutstandingReqs(oppResourceReqs);

    Set<String> nodeBlackList = new HashSet<>(opportContext.getBlacklist());
    List<Container> allocatedContainers = new ArrayList<>();

    // Satisfy the outstanding OPPORTUNISTIC requests.
    boolean continueLoop = true;
    while (continueLoop) {
      continueLoop = false;
      List<Map<Resource, List<Allocation>>> allocations = new ArrayList<>();
      for (SchedulerRequestKey schedulerKey :
          opportContext.getOutstandingOpReqs().descendingKeySet()) {
        // Allocated containers :
        //  Key = Requested Capability,
        //  Value = List of Containers of given cap (the actual container size
        //          might be different than what is requested, which is why
        //          we need the requested capability (key) to match against
        //          the outstanding reqs)
        Map<Resource, List<Allocation>> allocation = allocate(
            rmIdentifier, opportContext, schedulerKey, applicationAttemptId,
            appSubmitter, nodeBlackList);
        if (allocation.size() > 0) {
          allocations.add(allocation);
          continueLoop = true;
        }
      }
      for (Map<Resource, List<Allocation>> allocation : allocations) {
        for (Map.Entry<Resource, List<Allocation>> e : allocation.entrySet()) {
          opportContext.matchAllocationToOutstandingRequest(
              e.getKey(), e.getValue());
          for (Allocation alloc : e.getValue()) {
            allocatedContainers.add(alloc.getContainer());
          }
        }
      }
    }

    return allocatedContainers;
  }

  public  OpportunisticContainerAllocator(
      BaseContainerTokenSecretManager tokenSecretManager);

}