Example #1
0
 /**
  * Tests the cascading eviction with the first tier filled and the second tier empty resulting in
  * no eviction.
  *
  * @throws Exception if the caching fails
  */
 @Test
 public void cascadingEvictionTest1() throws Exception {
   // Two tiers, each dir in the second tier has more space than any dir in the first tier. Fill in
   // the first tier, leave the second tier empty. Request space from the first tier, blocks should
   // be moved from the first to the second tier without eviction.
   int firstTierOrdinal = TieredBlockStoreTestUtils.TIER_ORDINAL[0];
   long[] firstTierDirCapacity = TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[0];
   int nDir = firstTierDirCapacity.length;
   Map<Long, Double> blockIdToCRF = new HashMap<Long, Double>();
   for (int i = 0; i < nDir; i++) {
     cache(SESSION_ID, BLOCK_ID + i, firstTierDirCapacity[i], firstTierOrdinal, i);
     // update CRF of blocks when blocks are committed
     blockIdToCRF.put(BLOCK_ID + i, calculateAccessWeight(nDir - 1 - i));
   }
   // access blocks in the order: 10, 10, 11. Update CRF of all blocks
   // during each access
   for (int i = 0; i < nDir; i++) {
     for (int j = 0; j <= i; j++) {
       access(BLOCK_ID + j);
       for (int k = 0; k < nDir; k++) {
         if (k == j) {
           blockIdToCRF.put(
               BLOCK_ID + k, blockIdToCRF.get(BLOCK_ID + k) * calculateAccessWeight(1L) + 1.0);
         } else {
           blockIdToCRF.put(
               BLOCK_ID + k, blockIdToCRF.get(BLOCK_ID + k) * calculateAccessWeight(1L));
         }
       }
     }
   }
   List<Map.Entry<Long, Double>> blockCRF = getSortedCRF(blockIdToCRF);
   BlockStoreLocation anyDirInFirstTier =
       BlockStoreLocation.anyDirInTier(TieredBlockStoreTestUtils.TIER_ALIAS[firstTierOrdinal]);
   long smallestCapacity = firstTierDirCapacity[0];
   // request smallest capacity and update access time on the moved block for nDir times, the dir
   // to move blocks from should be in the same order as sorted blockCRF
   for (int i = 0; i < nDir; i++) {
     EvictionPlan plan =
         mEvictor.freeSpaceWithView(smallestCapacity, anyDirInFirstTier, mManagerView);
     Assert.assertTrue(EvictorTestUtils.validCascadingPlan(smallestCapacity, plan, mMetaManager));
     Assert.assertEquals(0, plan.toEvict().size());
     Assert.assertEquals(1, plan.toMove().size());
     long blockId = plan.toMove().get(0).getBlockId();
     long objectBlockId = blockCRF.get(i).getKey();
     Assert.assertEquals(objectBlockId, blockId);
     // update CRF of the chosen block in case that it is chosen again
     for (int j = 0; j < nDir; j++) {
       access(objectBlockId);
     }
   }
 }
Example #2
0
 /**
  * Tests that the eviction in the bottom tier works.
  *
  * @throws Exception if the caching fails
  */
 @Test
 public void evictInBottomTierTest() throws Exception {
   int bottomTierOrdinal =
       TieredBlockStoreTestUtils.TIER_ORDINAL[TieredBlockStoreTestUtils.TIER_ORDINAL.length - 1];
   Map<Long, Double> blockIdToCRF = new HashMap<Long, Double>();
   // capacity increases with index
   long[] bottomTierDirCapacity = TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[bottomTierOrdinal];
   int nDir = bottomTierDirCapacity.length;
   // fill in dirs from larger to smaller capacity with blockId equal to BLOCK_ID plus dir index
   for (int i = 0; i < nDir; i++) {
     cache(SESSION_ID, BLOCK_ID + i, bottomTierDirCapacity[i], bottomTierOrdinal, i);
     // update CRF of blocks when blocks are committed
     blockIdToCRF.put(BLOCK_ID + i, calculateAccessWeight(nDir - 1 - i));
   }
   // access blocks in the order: 10, 10, 11, 10, 11, 12. Update CRF of all blocks
   // during each access
   for (int i = 0; i < nDir; i++) {
     for (int j = 0; j <= i; j++) {
       access(BLOCK_ID + j);
       for (int k = 0; k < nDir; k++) {
         if (k == j) {
           blockIdToCRF.put(
               BLOCK_ID + k, blockIdToCRF.get(BLOCK_ID + k) * calculateAccessWeight(1L) + 1.0);
         } else {
           blockIdToCRF.put(
               BLOCK_ID + k, blockIdToCRF.get(BLOCK_ID + k) * calculateAccessWeight(1L));
         }
       }
     }
   }
   // sort blocks in ascending order of CRF
   List<Entry<Long, Double>> blockCRF = getSortedCRF(blockIdToCRF);
   BlockStoreLocation anyDirInBottomTier =
       BlockStoreLocation.anyDirInTier(TieredBlockStoreTestUtils.TIER_ALIAS[bottomTierOrdinal]);
   // request smallest capacity and update access time on the evicted block for nDir times, the dir
   // to evict blocks from should be in the same order as sorted blockCRF
   for (int i = 0; i < nDir; i++) {
     EvictionPlan plan =
         mEvictor.freeSpaceWithView(bottomTierDirCapacity[0], anyDirInBottomTier, mManagerView);
     Assert.assertNotNull(plan);
     Assert.assertTrue(plan.toMove().isEmpty());
     Assert.assertEquals(1, plan.toEvict().size());
     long toEvictBlockId = plan.toEvict().get(0).getFirst();
     long objectBlockId = blockCRF.get(i).getKey();
     Assert.assertEquals(objectBlockId + " " + toEvictBlockId, objectBlockId, toEvictBlockId);
     // update CRF of the chosen block in case that it is chosen again
     for (int j = 0; j < nDir; j++) {
       access(toEvictBlockId);
     }
   }
 }
Example #3
0
  /**
   * Tests the cascading eviction with the first and second tier filled resulting in blocks in the
   * second tier are evicted.
   *
   * @throws Exception if the caching fails
   */
  @Test
  public void cascadingEvictionTest2() throws Exception {
    // Two tiers, the second tier has more dirs than the first tier and each dir in the second tier
    // has more space than any dir in the first tier. Fill in all dirs and request space from the
    // first tier, blocks should be moved from the first to the second tier, and some blocks in the
    // second tier should be evicted to hold blocks moved from the first tier.
    long blockId = BLOCK_ID;
    long totalBlocks = 0;
    for (int tierOrdinal : TieredBlockStoreTestUtils.TIER_ORDINAL) {
      totalBlocks += TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[tierOrdinal].length;
    }
    Map<Long, Double> blockIdToCRF = new HashMap<Long, Double>();
    for (int tierOrdinal : TieredBlockStoreTestUtils.TIER_ORDINAL) {
      long[] tierCapacity = TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[tierOrdinal];
      for (int dirIdx = 0; dirIdx < tierCapacity.length; dirIdx++) {
        cache(SESSION_ID, blockId, tierCapacity[dirIdx], tierOrdinal, dirIdx);
        // update CRF of blocks when blocks are committed
        blockIdToCRF.put(blockId, calculateAccessWeight(totalBlocks - 1 - (blockId - BLOCK_ID)));
        blockId++;
      }
    }

    // access blocks in the order: 10, 10, 11, 10, 11, 12, 10, 11, 12, 13, 10, 11, 12, 13, 14
    // Update CRF of all blocks during each access
    for (int i = 0; i < totalBlocks; i++) {
      for (int j = 0; j <= i; j++) {
        access(BLOCK_ID + j);
        for (int k = 0; k < totalBlocks; k++) {
          if (k == j) {
            blockIdToCRF.put(
                BLOCK_ID + k, blockIdToCRF.get(BLOCK_ID + k) * calculateAccessWeight(1L) + 1.0);
          } else {
            blockIdToCRF.put(
                BLOCK_ID + k, blockIdToCRF.get(BLOCK_ID + k) * calculateAccessWeight(1L));
          }
        }
      }
    }

    List<Map.Entry<Long, Double>> blockCRF = getSortedCRF(blockIdToCRF);
    // sorted blocks in the first tier
    List<Long> blocksInFirstTier = new ArrayList<Long>();
    // sorted blocks in the second tier
    List<Long> blocksInSecondTier = new ArrayList<Long>();
    for (int i = 0; i < blockCRF.size(); i++) {
      long block = blockCRF.get(i).getKey();
      if (block - BLOCK_ID < TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[0].length) {
        blocksInFirstTier.add(block);
      } else if (block - BLOCK_ID
          < TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[0].length
              + TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[1].length) {
        blocksInSecondTier.add(block);
      }
    }
    BlockStoreLocation anyDirInFirstTier =
        BlockStoreLocation.anyDirInTier(TieredBlockStoreTestUtils.TIER_ALIAS[0]);
    int nDirInFirstTier = TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[0].length;
    long smallestCapacity = TieredBlockStoreTestUtils.TIER_CAPACITY_BYTES[0][0];
    for (int i = 0; i < nDirInFirstTier; i++) {
      EvictionPlan plan =
          mEvictor.freeSpaceWithView(smallestCapacity, anyDirInFirstTier, mManagerView);
      Assert.assertTrue(EvictorTestUtils.validCascadingPlan(smallestCapacity, plan, mMetaManager));
      // block with minimum CRF in the first tier needs to be moved to the second tier
      Assert.assertEquals(1, plan.toMove().size());
      long blockIdMovedInFirstTier = plan.toMove().get(0).getBlockId();
      long objectBlockIdInFirstTier = blocksInFirstTier.get(i);
      Assert.assertEquals(objectBlockIdInFirstTier, blockIdMovedInFirstTier);
      // cached block with minimum CRF in the second tier will be evicted to hold blocks moved
      // from first tier
      Assert.assertEquals(1, plan.toEvict().size());
      long blockIdEvictedInSecondTier = plan.toEvict().get(0).getFirst();
      long objectBlockIdInSecondTier = blocksInSecondTier.get(i);
      Assert.assertEquals(objectBlockIdInSecondTier, blockIdEvictedInSecondTier);
      // update CRF of the chosen blocks in case that they are chosen again
      for (int j = 0; j < totalBlocks; j++) {
        access(blockIdMovedInFirstTier);
      }
      for (int j = 0; j < totalBlocks; j++) {
        access(blockIdEvictedInSecondTier);
      }
    }
  }