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.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   * CombinedBlockCache is an abstraction layer that combines
30   * {@link LruBlockCache} and {@link BucketCache}. The smaller lruCache is used
31   * to cache bloom blocks and index blocks.  The larger bucketCache is used to
32   * cache data blocks. {@link #getBlock(BlockCacheKey, boolean, boolean, boolean)} reads
33   * first from the smaller lruCache before looking for the block in the bucketCache.  Blocks evicted
34   * from lruCache are put into the bucket cache. 
35   * Metrics are the combined size and hits and misses of both caches.
36   * 
37   */
38  @InterfaceAudience.Private
39  public class CombinedBlockCache implements BlockCache, HeapSize {
40    private final LruBlockCache lruCache;
41    private final BucketCache bucketCache;
42    private final CombinedCacheStats combinedCacheStats;
43  
44    public CombinedBlockCache(LruBlockCache lruCache, BucketCache bucketCache) {
45      this.lruCache = lruCache;
46      this.bucketCache = bucketCache;
47      this.combinedCacheStats = new CombinedCacheStats(lruCache.getStats(),
48          bucketCache.getStats());
49    }
50  
51    @Override
52    public long heapSize() {
53      return lruCache.heapSize() + bucketCache.heapSize();
54    }
55  
56    @Override
57    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory,
58        final boolean cacheDataInL1) {
59      boolean isMetaBlock = buf.getBlockType().getCategory() != BlockCategory.DATA;
60      if (isMetaBlock || cacheDataInL1) {
61        lruCache.cacheBlock(cacheKey, buf, inMemory, cacheDataInL1);
62      } else {
63        bucketCache.cacheBlock(cacheKey, buf, inMemory, cacheDataInL1);
64      }
65    }
66  
67    @Override
68    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {
69      cacheBlock(cacheKey, buf, false, false);
70    }
71  
72    @Override
73    public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching,
74        boolean repeat, boolean updateCacheMetrics) {
75      // TODO: is there a hole here, or just awkwardness since in the lruCache getBlock
76      // we end up calling bucketCache.getBlock.
77      if (lruCache.containsBlock(cacheKey)) {
78        return lruCache.getBlock(cacheKey, caching, repeat, updateCacheMetrics);
79      }
80      return bucketCache.getBlock(cacheKey, caching, repeat, updateCacheMetrics);
81    }
82  
83    @Override
84    public boolean evictBlock(BlockCacheKey cacheKey) {
85      return lruCache.evictBlock(cacheKey) || bucketCache.evictBlock(cacheKey);
86    }
87  
88    @Override
89    public int evictBlocksByHfileName(String hfileName) {
90      return lruCache.evictBlocksByHfileName(hfileName)
91          + bucketCache.evictBlocksByHfileName(hfileName);
92    }
93  
94    @Override
95    public CacheStats getStats() {
96      return this.combinedCacheStats;
97    }
98  
99    @Override
100   public void shutdown() {
101     lruCache.shutdown();
102     bucketCache.shutdown();
103   }
104 
105   @Override
106   public long size() {
107     return lruCache.size() + bucketCache.size();
108   }
109 
110   @Override
111   public long getFreeSize() {
112     return lruCache.getFreeSize() + bucketCache.getFreeSize();
113   }
114 
115   @Override
116   public long getCurrentSize() {
117     return lruCache.getCurrentSize() + bucketCache.getCurrentSize();
118   }
119 
120   @Override
121   public long getBlockCount() {
122     return lruCache.getBlockCount() + bucketCache.getBlockCount();
123   }
124 
125   private static class CombinedCacheStats extends CacheStats {
126     private final CacheStats lruCacheStats;
127     private final CacheStats bucketCacheStats;
128 
129     CombinedCacheStats(CacheStats lbcStats, CacheStats fcStats) {
130       this.lruCacheStats = lbcStats;
131       this.bucketCacheStats = fcStats;
132     }
133 
134     @Override
135     public long getRequestCount() {
136       return lruCacheStats.getRequestCount()
137           + bucketCacheStats.getRequestCount();
138     }
139 
140     @Override
141     public long getRequestCachingCount() {
142       return lruCacheStats.getRequestCachingCount()
143           + bucketCacheStats.getRequestCachingCount();
144     }
145 
146     @Override
147     public long getMissCount() {
148       return lruCacheStats.getMissCount() + bucketCacheStats.getMissCount();
149     }
150 
151     @Override
152     public long getMissCachingCount() {
153       return lruCacheStats.getMissCachingCount()
154           + bucketCacheStats.getMissCachingCount();
155     }
156 
157     @Override
158     public long getHitCount() {
159       return lruCacheStats.getHitCount() + bucketCacheStats.getHitCount();
160     }
161 
162     @Override
163     public long getHitCachingCount() {
164       return lruCacheStats.getHitCachingCount()
165           + bucketCacheStats.getHitCachingCount();
166     }
167 
168     @Override
169     public long getEvictionCount() {
170       return lruCacheStats.getEvictionCount()
171           + bucketCacheStats.getEvictionCount();
172     }
173 
174     @Override
175     public long getEvictedCount() {
176       return lruCacheStats.getEvictedCount()
177           + bucketCacheStats.getEvictedCount();
178     }
179 
180     @Override
181     public double getHitRatioPastNPeriods() {
182       double ratio = ((double) (lruCacheStats.getSumHitCountsPastNPeriods() + bucketCacheStats
183           .getSumHitCountsPastNPeriods()) / (double) (lruCacheStats
184           .getSumRequestCountsPastNPeriods() + bucketCacheStats
185           .getSumRequestCountsPastNPeriods()));
186       return Double.isNaN(ratio) ? 0 : ratio;
187     }
188 
189     @Override
190     public double getHitCachingRatioPastNPeriods() {
191       double ratio = ((double) (lruCacheStats
192           .getSumHitCachingCountsPastNPeriods() + bucketCacheStats
193           .getSumHitCachingCountsPastNPeriods()) / (double) (lruCacheStats
194           .getSumRequestCachingCountsPastNPeriods() + bucketCacheStats
195           .getSumRequestCachingCountsPastNPeriods()));
196       return Double.isNaN(ratio) ? 0 : ratio;
197     }
198   }
199 
200   @Override
201   public Iterator<CachedBlock> iterator() {
202     return new BlockCachesIterator(getBlockCaches());
203   }
204 
205   @Override
206   public BlockCache[] getBlockCaches() {
207     return new BlockCache [] {this.lruCache, this.bucketCache};
208   }
209 }