2424import org .apache .hadoop .hbase .io .HeapSize ;
2525import org .apache .hadoop .hbase .io .hfile .bucket .BucketCache ;
2626import org .apache .yetus .audience .InterfaceAudience ;
27+ import org .slf4j .Logger ;
28+ import org .slf4j .LoggerFactory ;
2729
2830/**
2931 * CombinedBlockCache is an abstraction layer that combines {@link FirstLevelBlockCache} and
@@ -39,6 +41,8 @@ public class CombinedBlockCache implements ResizableBlockCache, HeapSize {
3941 protected final BlockCache l2Cache ;
4042 protected final CombinedCacheStats combinedCacheStats ;
4143
44+ private static final Logger LOG = LoggerFactory .getLogger (CombinedBlockCache .class );
45+
4246 public CombinedBlockCache (FirstLevelBlockCache l1Cache , BlockCache l2Cache ) {
4347 this .l1Cache = l1Cache ;
4448 this .l2Cache = l2Cache ;
@@ -78,17 +82,59 @@ public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {
7882 @ Override
7983 public Cacheable getBlock (BlockCacheKey cacheKey , boolean caching , boolean repeat ,
8084 boolean updateCacheMetrics ) {
81- // We are not in a position to exactly look at LRU cache or BC as BlockType may not be getting
82- // passed always.
85+ Cacheable block = null ;
86+ // We don't know the block type. We should try to get it on one of the caches only,
87+ // but not both otherwise we'll over compute on misses. Here we check if the key is on L1,
88+ // if so, call getBlock on L1 and that will compute the hit. Otherwise, we'll try to get it from
89+ // L2 and whatever happens, we'll update the stats there.
8390 boolean existInL1 = l1Cache .containsBlock (cacheKey );
84- if (!existInL1 && updateCacheMetrics && !repeat ) {
85- // If the block does not exist in L1, the containsBlock should be counted as one miss.
86- l1Cache .getStats ().miss (caching , cacheKey .isPrimary (), cacheKey .getBlockType ());
91+ // if we know it's in L1, just delegate call to l1 and return it
92+ if (existInL1 ) {
93+ block = l1Cache .getBlock (cacheKey , caching , repeat , false );
94+ } else {
95+ block = l2Cache .getBlock (cacheKey , caching , repeat , false );
96+ }
97+ if (updateCacheMetrics ) {
98+ boolean metaBlock = isMetaBlock (cacheKey .getBlockType ());
99+ if (metaBlock ) {
100+ if (!existInL1 && block != null ) {
101+ LOG .warn ("Cache key {} had block type {}, but was found in L2 cache." , cacheKey ,
102+ cacheKey .getBlockType ());
103+ updateBlockMetrics (block , cacheKey , l2Cache , caching );
104+ } else {
105+ updateBlockMetrics (block , cacheKey , l1Cache , caching );
106+ }
107+ } else {
108+ if (existInL1 ) {
109+ LOG .warn ("Cache key {} had block type {}, but was found in L1 cache." , cacheKey ,
110+ cacheKey .getBlockType ());
111+ updateBlockMetrics (block , cacheKey , l1Cache , caching );
112+ } else {
113+ updateBlockMetrics (block , cacheKey , l2Cache , caching );
114+ }
115+ }
116+ }
117+ return block ;
118+ }
119+
120+ private void updateBlockMetrics (Cacheable block , BlockCacheKey key , BlockCache cache ,
121+ boolean caching ) {
122+ if (block == null ) {
123+ cache .getStats ().miss (caching , key .isPrimary (), key .getBlockType ());
124+ } else {
125+ cache .getStats ().hit (caching , key .isPrimary (), key .getBlockType ());
126+
87127 }
128+ }
88129
89- return existInL1
90- ? l1Cache .getBlock (cacheKey , caching , repeat , updateCacheMetrics )
91- : l2Cache .getBlock (cacheKey , caching , repeat , updateCacheMetrics );
130+ private Cacheable getBlockWithType (BlockCacheKey cacheKey , boolean caching , boolean repeat ,
131+ boolean updateCacheMetrics ) {
132+ boolean metaBlock = isMetaBlock (cacheKey .getBlockType ());
133+ if (metaBlock ) {
134+ return l1Cache .getBlock (cacheKey , caching , repeat , updateCacheMetrics );
135+ } else {
136+ return l2Cache .getBlock (cacheKey , caching , repeat , updateCacheMetrics );
137+ }
92138 }
93139
94140 @ Override
0 commit comments