View Javadoc

1   /**
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements. See the NOTICE file distributed with this
6    * work for additional information regarding copyright ownership. The ASF
7    * licenses this file to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance with the License.
9    * 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, WITHOUT
15   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16   * License for the specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.hadoop.hbase.io.hfile;
20  
21  import java.util.Iterator;
22  
23  import org.apache.hadoop.hbase.classification.InterfaceAudience;
24  import org.apache.hadoop.hbase.io.HeapSize;
25  import org.apache.hadoop.hbase.io.hfile.BlockType.BlockCategory;
26  import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache;
27  
28  import com.google.common.annotations.VisibleForTesting;
29  
30  
31  /**
32   * CombinedBlockCache is an abstraction layer that combines
33   * {@link LruBlockCache} and {@link BucketCache}. The smaller lruCache is used
34   * to cache bloom blocks and index blocks.  The larger l2Cache is used to
35   * cache data blocks. {@link #getBlock(BlockCacheKey, boolean, boolean, boolean)} reads
36   * first from the smaller lruCache before looking for the block in the l2Cache.  Blocks evicted
37   * from lruCache are put into the bucket cache. 
38   * Metrics are the combined size and hits and misses of both caches.
39   * 
40   */
41  @InterfaceAudience.Private
42  public class CombinedBlockCache implements ResizableBlockCache, HeapSize {
43    protected final LruBlockCache lruCache;
44    protected final BlockCache l2Cache;
45    protected final CombinedCacheStats combinedCacheStats;
46  
47    public CombinedBlockCache(LruBlockCache lruCache, BlockCache l2Cache) {
48      this.lruCache = lruCache;
49      this.l2Cache = l2Cache;
50      this.combinedCacheStats = new CombinedCacheStats(lruCache.getStats(),
51          l2Cache.getStats());
52    }
53  
54    @Override
55    public long heapSize() {
56      long l2size = 0;
57      if (l2Cache instanceof HeapSize) {
58        l2size = ((HeapSize) l2Cache).heapSize();
59      }
60      return lruCache.heapSize() + l2size;
61    }
62  
63    @Override
64    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory,
65        final boolean cacheDataInL1) {
66      boolean metaBlock = buf.getBlockType().getCategory() != BlockCategory.DATA;
67      if (metaBlock || cacheDataInL1) {
68        lruCache.cacheBlock(cacheKey, buf, inMemory, cacheDataInL1);
69      } else {
70        l2Cache.cacheBlock(cacheKey, buf, inMemory, false);
71      }
72    }
73  
74    @Override
75    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {
76      cacheBlock(cacheKey, buf, false, false);
77    }
78  
79    @Override
80    public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching,
81        boolean repeat, boolean updateCacheMetrics) {
82      // TODO: is there a hole here, or just awkwardness since in the lruCache getBlock
83      // we end up calling l2Cache.getBlock.
84      return lruCache.containsBlock(cacheKey)?
85          lruCache.getBlock(cacheKey, caching, repeat, updateCacheMetrics):
86          l2Cache.getBlock(cacheKey, caching, repeat, updateCacheMetrics);
87    }
88  
89    @Override
90    public boolean evictBlock(BlockCacheKey cacheKey) {
91      return lruCache.evictBlock(cacheKey) || l2Cache.evictBlock(cacheKey);
92    }
93  
94    @Override
95    public int evictBlocksByHfileName(String hfileName) {
96      return lruCache.evictBlocksByHfileName(hfileName)
97          + l2Cache.evictBlocksByHfileName(hfileName);
98    }
99  
100   @Override
101   public CacheStats getStats() {
102     return this.combinedCacheStats;
103   }
104 
105   @Override
106   public void shutdown() {
107     lruCache.shutdown();
108     l2Cache.shutdown();
109   }
110 
111   @Override
112   public long size() {
113     return lruCache.size() + l2Cache.size();
114   }
115 
116   @Override
117   public long getFreeSize() {
118     return lruCache.getFreeSize() + l2Cache.getFreeSize();
119   }
120 
121   @Override
122   public long getCurrentSize() {
123     return lruCache.getCurrentSize() + l2Cache.getCurrentSize();
124   }
125 
126   @Override
127   public long getBlockCount() {
128     return lruCache.getBlockCount() + l2Cache.getBlockCount();
129   }
130 
131   public static class CombinedCacheStats extends CacheStats {
132     private final CacheStats lruCacheStats;
133     private final CacheStats bucketCacheStats;
134 
135     CombinedCacheStats(CacheStats lbcStats, CacheStats fcStats) {
136       super("CombinedBlockCache");
137       this.lruCacheStats = lbcStats;
138       this.bucketCacheStats = fcStats;
139     }
140 
141     @Override
142     public long getDataMissCount() {
143       return lruCacheStats.getDataMissCount() + bucketCacheStats.getDataMissCount();
144     }
145 
146     @Override
147     public long getLeafIndexMissCount() {
148       return lruCacheStats.getLeafIndexMissCount() + bucketCacheStats.getLeafIndexMissCount();
149     }
150 
151     @Override
152     public long getBloomChunkMissCount() {
153       return lruCacheStats.getBloomChunkMissCount() + bucketCacheStats.getBloomChunkMissCount();
154     }
155 
156     @Override
157     public long getMetaMissCount() {
158       return lruCacheStats.getMetaMissCount() + bucketCacheStats.getMetaMissCount();
159     }
160 
161     @Override
162     public long getRootIndexMissCount() {
163       return lruCacheStats.getRootIndexMissCount() + bucketCacheStats.getRootIndexMissCount();
164     }
165 
166     @Override
167     public long getIntermediateIndexMissCount() {
168       return lruCacheStats.getIntermediateIndexMissCount() +
169           bucketCacheStats.getIntermediateIndexMissCount();
170     }
171 
172     @Override
173     public long getFileInfoMissCount() {
174       return lruCacheStats.getFileInfoMissCount() + bucketCacheStats.getFileInfoMissCount();
175     }
176 
177     @Override
178     public long getGeneralBloomMetaMissCount() {
179       return lruCacheStats.getGeneralBloomMetaMissCount() +
180           bucketCacheStats.getGeneralBloomMetaMissCount();
181     }
182 
183     @Override
184     public long getDeleteFamilyBloomMissCount() {
185       return lruCacheStats.getDeleteFamilyBloomMissCount() +
186           bucketCacheStats.getDeleteFamilyBloomMissCount();
187     }
188 
189     @Override
190     public long getTrailerMissCount() {
191       return lruCacheStats.getTrailerMissCount() + bucketCacheStats.getTrailerMissCount();
192     }
193 
194     @Override
195     public long getDataHitCount() {
196       return lruCacheStats.getDataHitCount() + bucketCacheStats.getDataHitCount();
197     }
198 
199     @Override
200     public long getLeafIndexHitCount() {
201       return lruCacheStats.getLeafIndexHitCount() + bucketCacheStats.getLeafIndexHitCount();
202     }
203 
204     @Override
205     public long getBloomChunkHitCount() {
206       return lruCacheStats.getBloomChunkHitCount() + bucketCacheStats.getBloomChunkHitCount();
207     }
208 
209     @Override
210     public long getMetaHitCount() {
211       return lruCacheStats.getMetaHitCount() + bucketCacheStats.getMetaHitCount();
212     }
213 
214     @Override
215     public long getRootIndexHitCount() {
216       return lruCacheStats.getRootIndexHitCount() + bucketCacheStats.getRootIndexHitCount();
217     }
218 
219     @Override
220     public long getIntermediateIndexHitCount() {
221       return lruCacheStats.getIntermediateIndexHitCount() +
222           bucketCacheStats.getIntermediateIndexHitCount();
223     }
224 
225     @Override
226     public long getFileInfoHitCount() {
227       return lruCacheStats.getFileInfoHitCount() + bucketCacheStats.getFileInfoHitCount();
228     }
229 
230     @Override
231     public long getGeneralBloomMetaHitCount() {
232       return lruCacheStats.getGeneralBloomMetaHitCount() +
233           bucketCacheStats.getGeneralBloomMetaHitCount();
234     }
235 
236     @Override
237     public long getDeleteFamilyBloomHitCount() {
238       return lruCacheStats.getDeleteFamilyBloomHitCount() +
239           bucketCacheStats.getDeleteFamilyBloomHitCount();
240     }
241 
242     @Override
243     public long getTrailerHitCount() {
244       return lruCacheStats.getTrailerHitCount() + bucketCacheStats.getTrailerHitCount();
245     }
246 
247     @Override
248     public long getRequestCount() {
249       return lruCacheStats.getRequestCount()
250           + bucketCacheStats.getRequestCount();
251     }
252 
253     @Override
254     public long getRequestCachingCount() {
255       return lruCacheStats.getRequestCachingCount()
256           + bucketCacheStats.getRequestCachingCount();
257     }
258 
259     @Override
260     public long getMissCount() {
261       return lruCacheStats.getMissCount() + bucketCacheStats.getMissCount();
262     }
263 
264     @Override
265     public long getPrimaryMissCount() {
266       return lruCacheStats.getPrimaryMissCount() + bucketCacheStats.getPrimaryMissCount();
267     }
268 
269     @Override
270     public long getMissCachingCount() {
271       return lruCacheStats.getMissCachingCount()
272           + bucketCacheStats.getMissCachingCount();
273     }
274 
275     @Override
276     public long getHitCount() {
277       return lruCacheStats.getHitCount() + bucketCacheStats.getHitCount();
278     }
279 
280     @Override
281     public long getPrimaryHitCount() {
282       return lruCacheStats.getPrimaryHitCount() + bucketCacheStats.getPrimaryHitCount();
283     }
284     @Override
285     public long getHitCachingCount() {
286       return lruCacheStats.getHitCachingCount()
287           + bucketCacheStats.getHitCachingCount();
288     }
289 
290     @Override
291     public long getEvictionCount() {
292       return lruCacheStats.getEvictionCount()
293           + bucketCacheStats.getEvictionCount();
294     }
295 
296     @Override
297     public long getEvictedCount() {
298       return lruCacheStats.getEvictedCount()
299           + bucketCacheStats.getEvictedCount();
300     }
301 
302     @Override
303     public long getPrimaryEvictedCount() {
304       return lruCacheStats.getPrimaryEvictedCount()
305           + bucketCacheStats.getPrimaryEvictedCount();
306     }
307 
308     @Override
309     public void rollMetricsPeriod() {
310       lruCacheStats.rollMetricsPeriod();
311       bucketCacheStats.rollMetricsPeriod();
312     }
313     
314     @Override
315     public long getFailedInserts() {
316       return lruCacheStats.getFailedInserts() + bucketCacheStats.getFailedInserts();
317     }
318 
319     @Override
320     public long getSumHitCountsPastNPeriods() {
321       return lruCacheStats.getSumHitCountsPastNPeriods()
322           + bucketCacheStats.getSumHitCountsPastNPeriods();
323     }
324     
325     @Override
326     public long getSumRequestCountsPastNPeriods() {
327       return lruCacheStats.getSumRequestCountsPastNPeriods()
328           + bucketCacheStats.getSumRequestCountsPastNPeriods();
329     }
330     
331     @Override
332     public long getSumHitCachingCountsPastNPeriods() {
333       return lruCacheStats.getSumHitCachingCountsPastNPeriods()
334           + bucketCacheStats.getSumHitCachingCountsPastNPeriods();
335     }
336 
337     @Override
338     public long getSumRequestCachingCountsPastNPeriods() {
339       return lruCacheStats.getSumRequestCachingCountsPastNPeriods()
340           + bucketCacheStats.getSumRequestCachingCountsPastNPeriods();
341     }
342   }
343 
344   @Override
345   public Iterator<CachedBlock> iterator() {
346     return new BlockCachesIterator(getBlockCaches());
347   }
348 
349   @Override
350   public BlockCache[] getBlockCaches() {
351     return new BlockCache [] {this.lruCache, this.l2Cache};
352   }
353 
354   @Override
355   public void setMaxSize(long size) {
356     this.lruCache.setMaxSize(size);
357   }
358 
359   @Override
360   public void returnBlock(BlockCacheKey cacheKey, Cacheable block) {
361     // A noop
362     this.lruCache.returnBlock(cacheKey, block);
363     this.l2Cache.returnBlock(cacheKey, block);
364   }
365 
366   @VisibleForTesting
367   public int getRefCount(BlockCacheKey cacheKey) {
368     return ((BucketCache) this.l2Cache).getRefCount(cacheKey);
369   }
370 }