View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  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,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.io.hfile;
20  
21  import java.io.IOException;
22  import java.util.List;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.classification.InterfaceAudience;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.io.HeapSize;
29  import org.apache.hadoop.hbase.io.hfile.slab.SlabCache;
30  import org.apache.hadoop.util.StringUtils;
31  
32  /**
33   * DoubleBlockCache is an abstraction layer that combines two caches, the
34   * smaller onHeapCache and the larger offHeapCache. CacheBlock attempts to cache
35   * the block in both caches, while readblock reads first from the faster on heap
36   * cache before looking for the block in the off heap cache. Metrics are the
37   * combined size and hits and misses of both caches.
38   *
39   **/
40  @InterfaceAudience.Private
41  public class DoubleBlockCache implements BlockCache, HeapSize {
42  
43    static final Log LOG = LogFactory.getLog(DoubleBlockCache.class.getName());
44  
45    private final LruBlockCache onHeapCache;
46    private final SlabCache offHeapCache;
47    private final CacheStats stats;
48  
49    /**
50     * Default constructor. Specify maximum size and expected average block size
51     * (approximation is fine).
52     * <p>
53     * All other factors will be calculated based on defaults specified in this
54     * class.
55     *
56     * @param onHeapSize maximum size of the onHeapCache, in bytes.
57     * @param offHeapSize maximum size of the offHeapCache, in bytes.
58     * @param onHeapBlockSize average block size of the on heap cache.
59     * @param offHeapBlockSize average block size for the off heap cache
60     * @param conf configuration file. currently used only by the off heap cache.
61     */
62    public DoubleBlockCache(long onHeapSize, long offHeapSize,
63        long onHeapBlockSize, long offHeapBlockSize, Configuration conf) {
64  
65      LOG.info("Creating on-heap cache of size "
66          + StringUtils.humanReadableInt(onHeapSize)
67          + "bytes with an average block size of "
68          + StringUtils.humanReadableInt(onHeapBlockSize) + " bytes.");
69      onHeapCache = new LruBlockCache(onHeapSize, onHeapBlockSize, conf);
70  
71      LOG.info("Creating off-heap cache of size "
72          + StringUtils.humanReadableInt(offHeapSize)
73          + "bytes with an average block size of "
74          + StringUtils.humanReadableInt(offHeapBlockSize) + " bytes.");
75      offHeapCache = new SlabCache(offHeapSize, offHeapBlockSize);
76  
77      offHeapCache.addSlabByConf(conf);
78      this.stats = new CacheStats();
79    }
80  
81    @Override
82    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {
83      onHeapCache.cacheBlock(cacheKey, buf, inMemory);
84      offHeapCache.cacheBlock(cacheKey, buf);
85    }
86  
87    @Override
88    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {
89      onHeapCache.cacheBlock(cacheKey, buf);
90      offHeapCache.cacheBlock(cacheKey, buf);
91    }
92  
93    @Override
94    public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,
95        boolean updateCacheMetrics) {
96      Cacheable cachedBlock;
97  
98      if ((cachedBlock = onHeapCache.getBlock(cacheKey, caching, repeat,
99          updateCacheMetrics)) != null) {
100       if (updateCacheMetrics) stats.hit(caching);
101       return cachedBlock;
102 
103     } else if ((cachedBlock = offHeapCache.getBlock(cacheKey, caching, repeat,
104         updateCacheMetrics)) != null) {
105       if (caching) {
106         onHeapCache.cacheBlock(cacheKey, cachedBlock);
107       }
108       if (updateCacheMetrics) stats.hit(caching);
109       return cachedBlock;
110     }
111 
112     if (!repeat && updateCacheMetrics) stats.miss(caching);
113     return null;
114   }
115 
116   @Override
117   public boolean evictBlock(BlockCacheKey cacheKey) {
118     stats.evict();
119     boolean cacheA = onHeapCache.evictBlock(cacheKey);
120     boolean cacheB = offHeapCache.evictBlock(cacheKey);
121     boolean evicted = cacheA || cacheB;
122     if (evicted) {
123       stats.evicted();
124     }
125     return evicted;
126   }
127 
128   @Override
129   public CacheStats getStats() {
130     return this.stats;
131   }
132 
133   @Override
134   public void shutdown() {
135     onHeapCache.shutdown();
136     offHeapCache.shutdown();
137   }
138 
139   @Override
140   public long heapSize() {
141     return onHeapCache.heapSize() + offHeapCache.heapSize();
142   }
143 
144   public long size() {
145     return onHeapCache.size() + offHeapCache.size();
146   }
147 
148   public long getFreeSize() {
149     return onHeapCache.getFreeSize() + offHeapCache.getFreeSize();
150   }
151 
152   public long getCurrentSize() {
153     return onHeapCache.getCurrentSize() + offHeapCache.getCurrentSize();
154   }
155 
156   public long getEvictedCount() {
157     return onHeapCache.getEvictedCount() + offHeapCache.getEvictedCount();
158   }
159 
160   @Override
161   public int evictBlocksByHfileName(String hfileName) {
162     onHeapCache.evictBlocksByHfileName(hfileName);
163     offHeapCache.evictBlocksByHfileName(hfileName);
164     return 0;
165   }
166 
167   @Override
168   public List<BlockCacheColumnFamilySummary> getBlockCacheColumnFamilySummaries(
169       Configuration conf) throws IOException {
170     return onHeapCache.getBlockCacheColumnFamilySummaries(conf);
171   }
172 
173   @Override
174   public long getBlockCount() {
175     return onHeapCache.getBlockCount() + offHeapCache.getBlockCount();
176   }
177 
178 }