/* * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 * (the "License"). You may not use this work except in compliance with the License, which is * available at www.apache.org/licenses/LICENSE-2.0 * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied, as more fully set forth in the License. * * See the NOTICE file distributed with this work for information regarding copyright ownership. */ package alluxio.worker.block.evictor; import alluxio.collections.Pair; import alluxio.worker.block.meta.StorageDirView; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.concurrent.NotThreadSafe; /** * A collection of candidate blocks for eviction organized by directory. * * This class lets you add blocks with the {@link alluxio.worker.block.meta.StorageDir}s they reside * in, the blockIds and the sizes in bytes, then it tells you which StorageDir added so far has the * maximum sum of available bytes and total bytes of added blocks. Assume metadata of StorageDir * will not be changed during adding blocks. * * Example usage can be found in {@link LRUEvictor#freeSpaceWithView}. */ @NotThreadSafe class EvictionDirCandidates { /** * Map from {@link StorageDirView} to pair of list of candidate blockIds and their total size in * bytes. */ private Map<StorageDirView, Pair<List<Long>, Long>> mDirCandidates = new HashMap<>(); /** Maximum sum of available bytes in a StorageDir and all its added blocks. */ private long mMaxBytes = 0; private StorageDirView mDirWithMaxBytes = null; /** * Constructs a new {@link EvictionDirCandidates}. */ public EvictionDirCandidates() {} /** * Adds the block in the directory to this collection. * * @param dir the dir where the block resides * @param blockId blockId of the block * @param blockSizeBytes block size in bytes */ public void add(StorageDirView dir, long blockId, long blockSizeBytes) { Pair<List<Long>, Long> candidate; if (mDirCandidates.containsKey(dir)) { candidate = mDirCandidates.get(dir); } else { candidate = new Pair<List<Long>, Long>(new ArrayList<Long>(), 0L); mDirCandidates.put(dir, candidate); } candidate.getFirst().add(blockId); long blockBytes = candidate.getSecond() + blockSizeBytes; candidate.setSecond(blockBytes); long sum = blockBytes + dir.getAvailableBytes(); if (mMaxBytes < sum) { mMaxBytes = sum; mDirWithMaxBytes = dir; } } /** * The maximum sum of available bytes and total bytes of added blocks in a directory. * * @return maximum bytes, if no directory has been added, return 0 */ public long candidateSize() { return mMaxBytes; } /** * @return list of blockIds in the directory that has the maximum {@link #candidateSize()}, * otherwise an empty list if no directory has been added */ public List<Long> candidateBlocks() { Pair<List<Long>, Long> evict = mDirCandidates.get(mDirWithMaxBytes); if (evict == null) { return new ArrayList<>(); } return evict.getFirst(); } /** * @return the {@link alluxio.worker.block.meta.StorageDir} that has the maximum * {@link #candidateSize()}, otherwise null if no directory has been added */ public StorageDirView candidateDir() { return mDirWithMaxBytes; } }