@Override
  public void archiveCompletedReservations(long tick) {
    // Since we are looking for old reservations, read lock is optimal
    LOG.debug("Running archival at time: {}", tick);
    List<InMemoryReservationAllocation> expiredReservations =
        new ArrayList<InMemoryReservationAllocation>();
    readLock.lock();
    // archive reservations and delete the ones which are beyond
    // the reservation policy "window"
    try {
      long archivalTime = tick - policy.getValidWindow();
      ReservationInterval searchInterval =
          new ReservationInterval(archivalTime, archivalTime);
      SortedMap<ReservationInterval, Set<InMemoryReservationAllocation>> reservations =
          currentReservations.headMap(searchInterval, true);
      if (!reservations.isEmpty()) {
        for (Set<InMemoryReservationAllocation> reservationEntries : reservations
            .values()) {
          for (InMemoryReservationAllocation reservation : reservationEntries) {
            if (reservation.getEndTime() <= archivalTime) {
              expiredReservations.add(reservation);
            }
          }
        }
      }
    } finally {
      readLock.unlock();
    }
    if (expiredReservations.isEmpty()) {
      return;
    }
    // Need write lock only if there are any reservations to be deleted
    writeLock.lock();
    try {
      for (InMemoryReservationAllocation expiredReservation : expiredReservations) {
        removeReservation(expiredReservation);
      }
    } finally {
      writeLock.unlock();
    }
  }
@Test
  public void testArchiveCompletedReservations() {
    SharingPolicy sharingPolicy = mock(SharingPolicy.class);
    Plan plan =
        new InMemoryPlan(queueMetrics, sharingPolicy, agent, totalCapacity, 1L,
            resCalc, minAlloc, maxAlloc, planName, replanner, true, context);
    ReservationId reservationID1 =
        ReservationSystemTestUtil.getNewReservationId();
    // First add a reservation
    int[] alloc1 = { 10, 10, 10, 10, 10, 10 };
    int start = 100;
    ReservationAllocation rAllocation =
        createReservationAllocation(reservationID1, start, alloc1);
    Assert.assertNull(plan.getReservationById(reservationID1));
    try {
      plan.addReservation(rAllocation, false);
    } catch (PlanningException e) {
      Assert.fail(e.getMessage());
    }
    doAssertions(plan, rAllocation);
    checkAllocation(plan, alloc1, start, 0);

    // Now add another one
    ReservationId reservationID2 =
        ReservationSystemTestUtil.getNewReservationId();
    int[] alloc2 = { 0, 5, 10, 5, 0 };
    rAllocation =
        createReservationAllocation(reservationID2, start, alloc2, true);
    Assert.assertNull(plan.getReservationById(reservationID2));
    try {
      plan.addReservation(rAllocation, false);
    } catch (PlanningException e) {
      Assert.fail(e.getMessage());
    }
    Assert.assertNotNull(plan.getReservationById(reservationID2));

    RLESparseResourceAllocation userCons =
        plan.getConsumptionForUserOverTime(user, start, start + alloc2.length);

    for (int i = 0; i < alloc2.length; i++) {
      assertEquals(
          Resource.newInstance(1024 * (alloc1[i] + alloc2[i] + i),
              alloc1[i] + alloc2[i] + i),
          plan.getTotalCommittedResources(start + i));
      assertEquals(
          Resource.newInstance(1024 * (alloc1[i] + alloc2[i] + i),
              alloc1[i] + alloc2[i] + i),
          userCons.getCapacityAtTime(start + i));
    }

    // Now archive completed reservations
    when(clock.getTime()).thenReturn(106L);
    when(sharingPolicy.getValidWindow()).thenReturn(1L);
    try {
      // will only remove 2nd reservation as only that has fallen out of the
      // archival window
      plan.archiveCompletedReservations(clock.getTime());
    } catch (PlanningException e) {
      Assert.fail(e.getMessage());
    }
    Assert.assertNotNull(plan.getReservationById(reservationID1));
    Assert.assertNull(plan.getReservationById(reservationID2));
    checkAllocation(plan, alloc1, start, 0);

    when(clock.getTime()).thenReturn(107L);
    try {
      // will remove 1st reservation also as it has fallen out of the archival
      // window
      plan.archiveCompletedReservations(clock.getTime());
    } catch (PlanningException e) {
      Assert.fail(e.getMessage());
    }

    userCons =
        plan.getConsumptionForUserOverTime(user, start, start + alloc1.length);

    Assert.assertNull(plan.getReservationById(reservationID1));
    for (int i = 0; i < alloc1.length; i++) {
      assertEquals(Resource.newInstance(0, 0),
          plan.getTotalCommittedResources(start + i));
      assertEquals(Resource.newInstance(0, 0),
          userCons.getCapacityAtTime(start + i));
    }
  }