@Override
  public RLESparseResourceAllocation getAvailableResourceOverTime(String user,
      ReservationId oldId, long start, long end, long period)
      throws PlanningException {
    readLock.lock();
    try {

      // for non-periodic return simple available resources
      if (period == 0) {

        // create RLE of totCapacity
        TreeMap<Long, Resource> totAvailable = new TreeMap<Long, Resource>();
        totAvailable.put(start, Resources.clone(totalCapacity));
        RLESparseResourceAllocation totRLEAvail =
            new RLESparseResourceAllocation(totAvailable, resCalc);

        // subtract used from available
        RLESparseResourceAllocation netAvailable;

        netAvailable = RLESparseResourceAllocation.merge(resCalc,
            Resources.clone(totalCapacity), totRLEAvail, rleSparseVector,
            RLEOperator.subtractTestNonNegative, start, end);

        // remove periodic component
        netAvailable = RLESparseResourceAllocation.merge(resCalc,
            Resources.clone(totalCapacity), netAvailable, periodicRle,
            RLEOperator.subtractTestNonNegative, start, end);

        // add back in old reservation used resources if any
        ReservationAllocation old = reservationTable.get(oldId);
        if (old != null) {

          RLESparseResourceAllocation addBackPrevious =
              old.getResourcesOverTime(start, end);
          netAvailable = RLESparseResourceAllocation.merge(resCalc,
              Resources.clone(totalCapacity), netAvailable, addBackPrevious,
              RLEOperator.add, start, end);
        }
        // lower it if this is needed by the sharing policy
        netAvailable = getSharingPolicy().availableResources(netAvailable, this,
            user, oldId, start, end);
        return netAvailable;
      } else {

        if (periodicRle.getTimePeriod() % period != 0) {
          throw new PlanningException("The reservation periodicity (" + period
              + ") must be" + " an exact divider of the system maxPeriod ("
              + periodicRle.getTimePeriod() + ")");
        }

        if (period < (end - start)) {
          throw new PlanningException(
              "Invalid input: (end - start) = (" + end + " - " + start + ") = "
                  + (end - start) + " > period = " + period);
        }

        // find the minimum resources available among all the instances that fit
        // in the LCM
        long numInstInLCM = periodicRle.getTimePeriod() / period;

        RLESparseResourceAllocation minOverLCM =
            getAvailableResourceOverTime(user, oldId, start, end, 0);
        for (int i = 1; i < numInstInLCM; i++) {

          long rStart = start + i * period;
          long rEnd = end + i * period;

          // recursive invocation of non-periodic range (to pick raw-info)
          RLESparseResourceAllocation snapShot =
              getAvailableResourceOverTime(user, oldId, rStart, rEnd, 0);

          // time-align on start
          snapShot.shift(-(i * period));

          // pick the minimum amount of resources in each time interval
          minOverLCM =
              RLESparseResourceAllocation.merge(resCalc, getTotalCapacity(),
                  minOverLCM, snapShot, RLEOperator.min, start, end);

        }

        return minOverLCM;

      }
    } finally {
      readLock.unlock();
    }
  }
@Test(expected = PlanningException.class)
  public void testOutOfRange() throws PlanningException {
    maxPeriodicity = 100;
    Plan plan = new InMemoryPlan(queueMetrics, policy, agent, totalCapacity, 1L,
        resCalc, minAlloc, maxAlloc, planName, replanner, true, maxPeriodicity,
        context, new UTCClock());

    // we expect the plan to complaint as the range 330-150 > 50
    RLESparseResourceAllocation availableBefore =
        plan.getAvailableResourceOverTime(user, null, 150, 330, 50);
  }