1 /** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 package org.apache.hadoop.hbase.io.hfile; 20 21 import com.google.common.collect.MinMaxPriorityQueue; 22 23 import org.apache.hadoop.hbase.classification.InterfaceAudience; 24 import org.apache.hadoop.hbase.io.HeapSize; 25 26 /** 27 * A memory-bound queue that will grow until an element brings 28 * total size >= maxSize. From then on, only entries that are sorted larger 29 * than the smallest current entry will be inserted/replaced. 30 * 31 * <p>Use this when you want to find the largest elements (according to their 32 * ordering, not their heap size) that consume as close to the specified 33 * maxSize as possible. Default behavior is to grow just above rather than 34 * just below specified max. 35 * 36 * <p>Object used in this queue must implement {@link HeapSize} as well as 37 * {@link Comparable}. 38 */ 39 @InterfaceAudience.Private 40 public class LruCachedBlockQueue implements HeapSize { 41 42 private MinMaxPriorityQueue<LruCachedBlock> queue; 43 44 private long heapSize; 45 private long maxSize; 46 47 /** 48 * @param maxSize the target size of elements in the queue 49 * @param blockSize expected average size of blocks 50 */ 51 public LruCachedBlockQueue(long maxSize, long blockSize) { 52 int initialSize = (int)(maxSize / blockSize); 53 if(initialSize == 0) initialSize++; 54 queue = MinMaxPriorityQueue.expectedSize(initialSize).create(); 55 heapSize = 0; 56 this.maxSize = maxSize; 57 } 58 59 /** 60 * Attempt to add the specified cached block to this queue. 61 * 62 * <p>If the queue is smaller than the max size, or if the specified element 63 * is ordered before the smallest element in the queue, the element will be 64 * added to the queue. Otherwise, there is no side effect of this call. 65 * @param cb block to try to add to the queue 66 */ 67 public void add(LruCachedBlock cb) { 68 if(heapSize < maxSize) { 69 queue.add(cb); 70 heapSize += cb.heapSize(); 71 } else { 72 LruCachedBlock head = queue.peek(); 73 if(cb.compareTo(head) > 0) { 74 heapSize += cb.heapSize(); 75 heapSize -= head.heapSize(); 76 if(heapSize > maxSize) { 77 queue.poll(); 78 } else { 79 heapSize += head.heapSize(); 80 } 81 queue.add(cb); 82 } 83 } 84 } 85 86 /** 87 * @return The next element in this queue, or {@code null} if the queue is 88 * empty. 89 */ 90 public LruCachedBlock poll() { 91 return queue.poll(); 92 } 93 94 /** 95 * @return The last element in this queue, or {@code null} if the queue is 96 * empty. 97 */ 98 public LruCachedBlock pollLast() { 99 return queue.pollLast(); 100 } 101 102 /** 103 * Total size of all elements in this queue. 104 * @return size of all elements currently in queue, in bytes 105 */ 106 public long heapSize() { 107 return heapSize; 108 } 109 }