001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.io.hfile; 020 021import org.apache.yetus.audience.InterfaceAudience; 022import org.apache.hadoop.hbase.io.HeapSize; 023import org.apache.hadoop.hbase.util.Bytes; 024import org.apache.hadoop.hbase.util.ClassSize; 025 026/** 027 * Represents an entry in the {@link LruBlockCache}. 028 * 029 * <p>Makes the block memory-aware with {@link HeapSize} and Comparable 030 * to sort by access time for the LRU. It also takes care of priority by 031 * either instantiating as in-memory or handling the transition from single 032 * to multiple access. 033 */ 034@InterfaceAudience.Private 035public class LruCachedBlock implements HeapSize, Comparable<LruCachedBlock> { 036 037 public final static long PER_BLOCK_OVERHEAD = ClassSize.align( 038 ClassSize.OBJECT + (3 * ClassSize.REFERENCE) + (3 * Bytes.SIZEOF_LONG) + 039 ClassSize.STRING + ClassSize.BYTE_BUFFER); 040 041 private final BlockCacheKey cacheKey; 042 private final Cacheable buf; 043 private volatile long accessTime; 044 private long size; 045 private BlockPriority priority; 046 /** 047 * Time this block was cached. Presumes we are created just before we are added to the cache. 048 */ 049 private final long cachedTime = System.nanoTime(); 050 051 public LruCachedBlock(BlockCacheKey cacheKey, Cacheable buf, long accessTime) { 052 this(cacheKey, buf, accessTime, false); 053 } 054 055 public LruCachedBlock(BlockCacheKey cacheKey, Cacheable buf, long accessTime, 056 boolean inMemory) { 057 this.cacheKey = cacheKey; 058 this.buf = buf; 059 this.accessTime = accessTime; 060 // We approximate the size of this class by the size of its name string 061 // plus the size of its byte buffer plus the overhead associated with all 062 // the base classes. We also include the base class 063 // sizes in the PER_BLOCK_OVERHEAD variable rather than align()ing them with 064 // their buffer lengths. This variable is used elsewhere in unit tests. 065 this.size = ClassSize.align(cacheKey.heapSize()) 066 + ClassSize.align(buf.heapSize()) + PER_BLOCK_OVERHEAD; 067 if(inMemory) { 068 this.priority = BlockPriority.MEMORY; 069 } else { 070 this.priority = BlockPriority.SINGLE; 071 } 072 } 073 074 /** 075 * Block has been accessed. 076 * @param accessTime Last access; this is actually a incremented sequence number rather than an 077 * actual time. 078 */ 079 public void access(long accessTime) { 080 this.accessTime = accessTime; 081 if(this.priority == BlockPriority.SINGLE) { 082 this.priority = BlockPriority.MULTI; 083 } 084 } 085 086 /** 087 * @return Time we were cached at in nano seconds. 088 */ 089 public long getCachedTime() { 090 return this.cachedTime; 091 } 092 093 @Override 094 public long heapSize() { 095 return size; 096 } 097 098 @Override 099 public int compareTo(LruCachedBlock that) { 100 // Newer accessed blocks sort before older ones. 101 if (this.accessTime == that.accessTime) return 0; 102 return this.accessTime < that.accessTime ? 1 : -1; 103 } 104 105 @Override 106 public int hashCode() { 107 return (int)(accessTime ^ (accessTime >>> 32)); 108 } 109 110 @Override 111 public boolean equals(Object obj) { 112 if (this == obj) { 113 return true; 114 } 115 if (obj == null || getClass() != obj.getClass()) { 116 return false; 117 } 118 LruCachedBlock other = (LruCachedBlock) obj; 119 return compareTo(other) == 0; 120 } 121 122 public Cacheable getBuffer() { 123 return this.buf; 124 } 125 126 public BlockCacheKey getCacheKey() { 127 return this.cacheKey; 128 } 129 130 public BlockPriority getPriority() { 131 return this.priority; 132 } 133}