1 /** 2 * Copyright 2009 The Apache Software Foundation 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package org.apache.hadoop.hbase.io.hfile; 21 22 import com.google.common.collect.MinMaxPriorityQueue; 23 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 public class CachedBlockQueue implements HeapSize { 40 41 private MinMaxPriorityQueue<CachedBlock> queue; 42 43 private long heapSize; 44 private long maxSize; 45 46 /** 47 * @param maxSize the target size of elements in the queue 48 * @param blockSize expected average size of blocks 49 */ 50 public CachedBlockQueue(long maxSize, long blockSize) { 51 int initialSize = (int)(maxSize / blockSize); 52 if(initialSize == 0) initialSize++; 53 queue = MinMaxPriorityQueue.expectedSize(initialSize).create(); 54 heapSize = 0; 55 this.maxSize = maxSize; 56 } 57 58 /** 59 * Attempt to add the specified cached block to this queue. 60 * 61 * <p>If the queue is smaller than the max size, or if the specified element 62 * is ordered before the smallest element in the queue, the element will be 63 * added to the queue. Otherwise, there is no side effect of this call. 64 * @param cb block to try to add to the queue 65 */ 66 public void add(CachedBlock cb) { 67 if(heapSize < maxSize) { 68 queue.add(cb); 69 heapSize += cb.heapSize(); 70 } else { 71 CachedBlock head = queue.peek(); 72 if(cb.compareTo(head) > 0) { 73 heapSize += cb.heapSize(); 74 heapSize -= head.heapSize(); 75 if(heapSize > maxSize) { 76 queue.poll(); 77 } else { 78 heapSize += head.heapSize(); 79 } 80 queue.add(cb); 81 } 82 } 83 } 84 85 /** 86 * @return The next element in this queue, or {@code null} if the queue is 87 * empty. 88 */ 89 public CachedBlock poll() { 90 return queue.poll(); 91 } 92 93 /** 94 * @return The last element in this queue, or {@code null} if the queue is 95 * empty. 96 */ 97 public CachedBlock pollLast() { 98 return queue.pollLast(); 99 } 100 101 /** 102 * Total size of all elements in this queue. 103 * @return size of all elements currently in queue, in bytes 104 */ 105 public long heapSize() { 106 return heapSize; 107 } 108 }