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