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  
29  /**
30   * CombinedBlockCache is an abstraction layer that combines
31   * {@link LruBlockCache} and {@link BucketCache}. The smaller lruCache is used
32   * to cache bloom blocks and index blocks.  The larger l2Cache is used to
33   * cache data blocks. {@link #getBlock(BlockCacheKey, boolean, boolean, boolean)} reads
34   * first from the smaller lruCache before looking for the block in the l2Cache.  Blocks evicted
35   * from lruCache are put into the bucket cache. 
36   * Metrics are the combined size and hits and misses of both caches.
37   * 
38   */
39  @InterfaceAudience.Private
40  public class CombinedBlockCache implements ResizableBlockCache, HeapSize {
41    protected final LruBlockCache lruCache;
42    protected final BlockCache l2Cache;
43    protected final CombinedCacheStats combinedCacheStats;
44  
45    public CombinedBlockCache(LruBlockCache lruCache, BlockCache l2Cache) {
46      this.lruCache = lruCache;
47      this.l2Cache = l2Cache;
48      this.combinedCacheStats = new CombinedCacheStats(lruCache.getStats(),
49          l2Cache.getStats());
50    }
51  
52    @Override
53    public long heapSize() {
54      long l2size = 0;
55      if (l2Cache instanceof HeapSize) {
56        l2size = ((HeapSize) l2Cache).heapSize();
57      }
58      return lruCache.heapSize() + l2size;
59    }
60  
61    @Override
62    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory,
63        final boolean cacheDataInL1) {
64      boolean isMetaBlock = buf.getBlockType().getCategory() != BlockCategory.DATA;
65      if (isMetaBlock || cacheDataInL1) {
66        lruCache.cacheBlock(cacheKey, buf, inMemory, cacheDataInL1);
67      } else {
68        l2Cache.cacheBlock(cacheKey, buf, inMemory, false);
69      }
70    }
71  
72    @Override
73    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {
74      cacheBlock(cacheKey, buf, false, false);
75    }
76  
77    @Override
78    public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching,
79        boolean repeat, boolean updateCacheMetrics) {
80      // TODO: is there a hole here, or just awkwardness since in the lruCache getBlock
81      // we end up calling l2Cache.getBlock.
82      if (lruCache.containsBlock(cacheKey)) {
83        return lruCache.getBlock(cacheKey, caching, repeat, updateCacheMetrics);
84      }
85      Cacheable result = l2Cache.getBlock(cacheKey, caching, repeat, updateCacheMetrics);
86  
87      return result;
88    }
89  
90    @Override
91    public boolean evictBlock(BlockCacheKey cacheKey) {
92      return lruCache.evictBlock(cacheKey) || l2Cache.evictBlock(cacheKey);
93    }
94  
95    @Override
96    public int evictBlocksByHfileName(String hfileName) {
97      return lruCache.evictBlocksByHfileName(hfileName)
98          + l2Cache.evictBlocksByHfileName(hfileName);
99    }
100 
101   @Override
102   public CacheStats getStats() {
103     return this.combinedCacheStats;
104   }
105 
106   @Override
107   public void shutdown() {
108     lruCache.shutdown();
109     l2Cache.shutdown();
110   }
111 
112   @Override
113   public long size() {
114     return lruCache.size() + l2Cache.size();
115   }
116 
117   @Override
118   public long getFreeSize() {
119     return lruCache.getFreeSize() + l2Cache.getFreeSize();
120   }
121 
122   @Override
123   public long getCurrentSize() {
124     return lruCache.getCurrentSize() + l2Cache.getCurrentSize();
125   }
126 
127   @Override
128   public long getBlockCount() {
129     return lruCache.getBlockCount() + l2Cache.getBlockCount();
130   }
131 
132   public static class CombinedCacheStats extends CacheStats {
133     private final CacheStats lruCacheStats;
134     private final CacheStats bucketCacheStats;
135 
136     CombinedCacheStats(CacheStats lbcStats, CacheStats fcStats) {
137       super("CombinedBlockCache");
138       this.lruCacheStats = lbcStats;
139       this.bucketCacheStats = fcStats;
140     }
141 
142     @Override
143     public long getDataMissCount() {
144       return lruCacheStats.getDataMissCount() + bucketCacheStats.getDataMissCount();
145     }
146 
147     @Override
148     public long getLeafIndexMissCount() {
149       return lruCacheStats.getLeafIndexMissCount() + bucketCacheStats.getLeafIndexMissCount();
150     }
151 
152     @Override
153     public long getBloomChunkMissCount() {
154       return lruCacheStats.getBloomChunkMissCount() + bucketCacheStats.getBloomChunkMissCount();
155     }
156 
157     @Override
158     public long getMetaMissCount() {
159       return lruCacheStats.getMetaMissCount() + bucketCacheStats.getMetaMissCount();
160     }
161 
162     @Override
163     public long getRootIndexMissCount() {
164       return lruCacheStats.getRootIndexMissCount() + bucketCacheStats.getRootIndexMissCount();
165     }
166 
167     @Override
168     public long getIntermediateIndexMissCount() {
169       return lruCacheStats.getIntermediateIndexMissCount() +
170           bucketCacheStats.getIntermediateIndexMissCount();
171     }
172 
173     @Override
174     public long getFileInfoMissCount() {
175       return lruCacheStats.getFileInfoMissCount() + bucketCacheStats.getFileInfoMissCount();
176     }
177 
178     @Override
179     public long getGeneralBloomMetaMissCount() {
180       return lruCacheStats.getGeneralBloomMetaMissCount() +
181           bucketCacheStats.getGeneralBloomMetaMissCount();
182     }
183 
184     @Override
185     public long getDeleteFamilyBloomMissCount() {
186       return lruCacheStats.getDeleteFamilyBloomMissCount() +
187           bucketCacheStats.getDeleteFamilyBloomMissCount();
188     }
189 
190     @Override
191     public long getTrailerMissCount() {
192       return lruCacheStats.getTrailerMissCount() + bucketCacheStats.getTrailerMissCount();
193     }
194 
195     @Override
196     public long getDataHitCount() {
197       return lruCacheStats.getDataHitCount() + bucketCacheStats.getDataHitCount();
198     }
199 
200     @Override
201     public long getLeafIndexHitCount() {
202       return lruCacheStats.getLeafIndexHitCount() + bucketCacheStats.getLeafIndexHitCount();
203     }
204 
205     @Override
206     public long getBloomChunkHitCount() {
207       return lruCacheStats.getBloomChunkHitCount() + bucketCacheStats.getBloomChunkHitCount();
208     }
209 
210     @Override
211     public long getMetaHitCount() {
212       return lruCacheStats.getMetaHitCount() + bucketCacheStats.getMetaHitCount();
213     }
214 
215     @Override
216     public long getRootIndexHitCount() {
217       return lruCacheStats.getRootIndexHitCount() + bucketCacheStats.getRootIndexHitCount();
218     }
219 
220     @Override
221     public long getIntermediateIndexHitCount() {
222       return lruCacheStats.getIntermediateIndexHitCount() +
223           bucketCacheStats.getIntermediateIndexHitCount();
224     }
225 
226     @Override
227     public long getFileInfoHitCount() {
228       return lruCacheStats.getFileInfoHitCount() + bucketCacheStats.getFileInfoHitCount();
229     }
230 
231     @Override
232     public long getGeneralBloomMetaHitCount() {
233       return lruCacheStats.getGeneralBloomMetaHitCount() +
234           bucketCacheStats.getGeneralBloomMetaHitCount();
235     }
236 
237     @Override
238     public long getDeleteFamilyBloomHitCount() {
239       return lruCacheStats.getDeleteFamilyBloomHitCount() +
240           bucketCacheStats.getDeleteFamilyBloomHitCount();
241     }
242 
243     @Override
244     public long getTrailerHitCount() {
245       return lruCacheStats.getTrailerHitCount() + bucketCacheStats.getTrailerHitCount();
246     }
247 
248     @Override
249     public long getRequestCount() {
250       return lruCacheStats.getRequestCount()
251           + bucketCacheStats.getRequestCount();
252     }
253 
254     @Override
255     public long getRequestCachingCount() {
256       return lruCacheStats.getRequestCachingCount()
257           + bucketCacheStats.getRequestCachingCount();
258     }
259 
260     @Override
261     public long getMissCount() {
262       return lruCacheStats.getMissCount() + bucketCacheStats.getMissCount();
263     }
264 
265     @Override
266     public long getPrimaryMissCount() {
267       return lruCacheStats.getPrimaryMissCount() + bucketCacheStats.getPrimaryMissCount();
268     }
269 
270     @Override
271     public long getMissCachingCount() {
272       return lruCacheStats.getMissCachingCount()
273           + bucketCacheStats.getMissCachingCount();
274     }
275 
276     @Override
277     public long getHitCount() {
278       return lruCacheStats.getHitCount() + bucketCacheStats.getHitCount();
279     }
280 
281     @Override
282     public long getPrimaryHitCount() {
283       return lruCacheStats.getPrimaryHitCount() + bucketCacheStats.getPrimaryHitCount();
284     }
285     @Override
286     public long getHitCachingCount() {
287       return lruCacheStats.getHitCachingCount()
288           + bucketCacheStats.getHitCachingCount();
289     }
290 
291     @Override
292     public long getEvictionCount() {
293       return lruCacheStats.getEvictionCount()
294           + bucketCacheStats.getEvictionCount();
295     }
296 
297     @Override
298     public long getEvictedCount() {
299       return lruCacheStats.getEvictedCount()
300           + bucketCacheStats.getEvictedCount();
301     }
302 
303     @Override
304     public long getPrimaryEvictedCount() {
305       return lruCacheStats.getPrimaryEvictedCount()
306           + bucketCacheStats.getPrimaryEvictedCount();
307     }
308 
309     @Override
310     public double getHitRatioPastNPeriods() {
311       double ratio = ((double) (lruCacheStats.getSumHitCountsPastNPeriods() + bucketCacheStats
312           .getSumHitCountsPastNPeriods()) / (double) (lruCacheStats
313           .getSumRequestCountsPastNPeriods() + bucketCacheStats
314           .getSumRequestCountsPastNPeriods()));
315       return Double.isNaN(ratio) ? 0 : ratio;
316     }
317 
318     @Override
319     public double getHitCachingRatioPastNPeriods() {
320       double ratio = ((double) (lruCacheStats
321           .getSumHitCachingCountsPastNPeriods() + bucketCacheStats
322           .getSumHitCachingCountsPastNPeriods()) / (double) (lruCacheStats
323           .getSumRequestCachingCountsPastNPeriods() + bucketCacheStats
324           .getSumRequestCachingCountsPastNPeriods()));
325       return Double.isNaN(ratio) ? 0 : ratio;
326     }
327   }
328 
329   @Override
330   public Iterator<CachedBlock> iterator() {
331     return new BlockCachesIterator(getBlockCaches());
332   }
333 
334   @Override
335   public BlockCache[] getBlockCaches() {
336     return new BlockCache [] {this.lruCache, this.l2Cache};
337   }
338 
339   @Override
340   public void setMaxSize(long size) {
341     this.lruCache.setMaxSize(size);
342   }
343 }