001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.io.hfile;
019
020import java.util.Iterator;
021import java.util.Map;
022import java.util.Optional;
023import org.apache.hadoop.conf.Configuration;
024import org.apache.hadoop.fs.Path;
025import org.apache.hadoop.hbase.conf.ConfigurationObserver;
026import org.apache.hadoop.hbase.util.Pair;
027import org.apache.yetus.audience.InterfaceAudience;
028
029/**
030 * Block cache interface. Anything that implements the {@link Cacheable} interface can be put in the
031 * cache.
032 */
033@InterfaceAudience.Private
034public interface BlockCache extends Iterable<CachedBlock>, ConfigurationObserver {
035  /**
036   * Add block to cache.
037   * @param cacheKey The block's cache key.
038   * @param buf      The block contents wrapped in a ByteBuffer.
039   * @param inMemory Whether block should be treated as in-memory
040   */
041  void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory);
042
043  /**
044   * Add block to cache.
045   * @param cacheKey      The block's cache key.
046   * @param buf           The block contents wrapped in a ByteBuffer.
047   * @param inMemory      Whether block should be treated as in-memory
048   * @param waitWhenCache Whether to wait for the cache to be flushed mainly when BucketCache is
049   *                      configured.
050   */
051  default void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory,
052    boolean waitWhenCache) {
053    cacheBlock(cacheKey, buf, inMemory);
054  }
055
056  /**
057   * Add block to cache (defaults to not in-memory).
058   * @param cacheKey The block's cache key.
059   * @param buf      The object to cache.
060   */
061  void cacheBlock(BlockCacheKey cacheKey, Cacheable buf);
062
063  /**
064   * Fetch block from cache.
065   * @param cacheKey           Block to fetch.
066   * @param caching            Whether this request has caching enabled (used for stats)
067   * @param repeat             Whether this is a repeat lookup for the same block (used to avoid
068   *                           double counting cache misses when doing double-check locking)
069   * @param updateCacheMetrics Whether to update cache metrics or not
070   * @return Block or null if block is not in 2 cache.
071   */
072  Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,
073    boolean updateCacheMetrics);
074
075  /**
076   * Fetch block from cache.
077   * @param cacheKey           Block to fetch.
078   * @param caching            Whether this request has caching enabled (used for stats)
079   * @param repeat             Whether this is a repeat lookup for the same block (used to avoid
080   *                           double counting cache misses when doing double-check locking)
081   * @param updateCacheMetrics Whether to update cache metrics or not
082   * @param blockType          BlockType
083   * @return Block or null if block is not in 2 cache.
084   */
085  default Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,
086    boolean updateCacheMetrics, BlockType blockType) {
087    return getBlock(cacheKey, caching, repeat, updateCacheMetrics);
088  }
089
090  /**
091   * Evict block from cache.
092   * @param cacheKey Block to evict
093   * @return true if block existed and was evicted, false if not
094   */
095  boolean evictBlock(BlockCacheKey cacheKey);
096
097  /**
098   * Evicts all blocks for the given HFile.
099   * @return the number of blocks evicted
100   */
101  int evictBlocksByHfileName(String hfileName);
102
103  /**
104   * Get the statistics for this block cache.
105   */
106  CacheStats getStats();
107
108  /**
109   * Shutdown the cache.
110   */
111  void shutdown();
112
113  /**
114   * Returns the total size of the block cache, in bytes.
115   * @return size of cache, in bytes
116   */
117  long size();
118
119  /**
120   * Returns the Max size of the block cache, in bytes.
121   * @return size of cache, in bytes
122   */
123  long getMaxSize();
124
125  /**
126   * Returns the free size of the block cache, in bytes.
127   * @return free space in cache, in bytes
128   */
129  long getFreeSize();
130
131  /**
132   * Returns the occupied size of the block cache, in bytes.
133   * @return occupied space in cache, in bytes
134   */
135  long getCurrentSize();
136
137  /**
138   * Returns the occupied size of data blocks, in bytes.
139   * @return occupied space in cache, in bytes
140   */
141  long getCurrentDataSize();
142
143  /**
144   * Returns the number of blocks currently cached in the block cache.
145   * @return number of blocks in the cache
146   */
147  long getBlockCount();
148
149  /**
150   * Returns the number of data blocks currently cached in the block cache.
151   * @return number of blocks in the cache
152   */
153  long getDataBlockCount();
154
155  /** Returns Iterator over the blocks in the cache. */
156  @Override
157  Iterator<CachedBlock> iterator();
158
159  /** Returns The list of sub blockcaches that make up this one; returns null if no sub caches. */
160  BlockCache[] getBlockCaches();
161
162  /**
163   * Check if block type is meta or index block
164   * @param blockType block type of a given HFile block
165   * @return true if block type is non-data block
166   */
167  default boolean isMetaBlock(BlockType blockType) {
168    return blockType != null && blockType.getCategory() != BlockType.BlockCategory.DATA;
169  }
170
171  /**
172   * Notifies the cache implementation that the given file has been fully cached (all its blocks
173   * made into the cache).
174   * @param fileName        the file that has been completely cached.
175   * @param totalBlockCount the total of blocks cached for this file.
176   * @param dataBlockCount  number of DATA block type cached.
177   * @param size            the size, in bytes, cached.
178   */
179  default void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,
180    long size) {
181    // noop
182  }
183
184  /**
185   * Checks whether there's enough space left in the cache to accommodate the passed block. This
186   * method may not be overridden by all implementing classes. In such cases, the returned Optional
187   * will be empty. For subclasses implementing this logic, the returned Optional would contain the
188   * boolean value reflecting if the passed block fits into the remaining cache space available.
189   * @param block the block we want to check if fits into the cache.
190   * @return empty optional if this method is not supported, otherwise the returned optional
191   *         contains the boolean value informing if the block fits into the cache available space.
192   */
193  default Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {
194    return Optional.empty();
195  }
196
197  /**
198   * Checks whether blocks for the passed file should be cached or not. This method may not be
199   * overridden by all implementing classes. In such cases, the returned Optional will be empty. For
200   * subclasses implementing this logic, the returned Optional would contain the boolean value
201   * reflecting if the passed file should indeed be cached.
202   * @param fileName to check if it should be cached.
203   * @return empty optional if this method is not supported, otherwise the returned optional
204   *         contains the boolean value informing if the file should be cached.
205   */
206  default Optional<Boolean> shouldCacheFile(String fileName) {
207    return Optional.empty();
208  }
209
210  /**
211   * Checks whether the block for the passed key is already cached. This method may not be
212   * overridden by all implementing classes. In such cases, the returned Optional will be empty. For
213   * subclasses implementing this logic, the returned Optional would contain the boolean value
214   * reflecting if the block for the passed key is already cached or not.
215   * @param key for the block we want to check if it's already in the cache.
216   * @return empty optional if this method is not supported, otherwise the returned optional
217   *         contains the boolean value informing if the block is already cached.
218   */
219  default Optional<Boolean> isAlreadyCached(BlockCacheKey key) {
220    return Optional.empty();
221  }
222
223  /**
224   * Returns an Optional containing the size of the block related to the passed key. If the block is
225   * not in the cache, returned optional will be empty. Also, this method may not be overridden by
226   * all implementing classes. In such cases, the returned Optional will be empty.
227   * @param key for the block we want to check if it's already in the cache.
228   * @return empty optional if this method is not supported, otherwise the returned optional
229   *         contains the boolean value informing if the block is already cached.
230   */
231  default Optional<Integer> getBlockSize(BlockCacheKey key) {
232    return Optional.empty();
233  }
234
235  /**
236   * Returns an Optional containing the map of files that have been fully cached (all its blocks are
237   * present in the cache. This method may not be overridden by all implementing classes. In such
238   * cases, the returned Optional will be empty.
239   * @return empty optional if this method is not supported, otherwise the returned optional
240   *         contains a map of all files that have been fully cached.
241   */
242  default Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {
243    return Optional.empty();
244  }
245
246  /**
247   * Returns an Optional containing a map of regions and the percentage of how much of it has been
248   * cached so far.
249   * @return empty optional if this method is not supported, otherwise the returned optional
250   *         contains a map of current regions caching percentage.
251   */
252  default Optional<Map<String, Long>> getRegionCachedInfo() {
253    return Optional.empty();
254  }
255
256  /**
257   * Evict all blocks for the given file name between the passed offset values.
258   * @param hfileName  The file for which blocks should be evicted.
259   * @param initOffset the initial offset for the range of blocks to be evicted.
260   * @param endOffset  the end offset for the range of blocks to be evicted.
261   * @return number of blocks evicted.
262   */
263  default int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {
264    return 0;
265  }
266
267  /**
268   * API to check whether or not, the cache is enabled.
269   * @return returns true if the cache is enabled, false otherwise.
270   */
271  default boolean isCacheEnabled() {
272    return true;
273  }
274
275  /**
276   * Wait for the block cache implementation to be completely enabled. Some block cache
277   * implementations may take longer to initialise, and this initialisation may be asynchronous.
278   * @param timeout time to wait for the cache to become enabled.
279   * @return boolean true if the cache is enabled, false otherwise.
280   */
281  default boolean waitForCacheInitialization(long timeout) {
282    return true;
283  }
284
285  /**
286   * Allows for BlockCache implementations to provide a mean to refresh their configurations. Since
287   * HBASE-29249, CacheConfig implements PropagatingConfigurationObserver and registers itself
288   * together with the used BlockCache implementation for notifications of dynamic configuration
289   * changes. The default is a noop.
290   * @param config the new configuration to be updated.
291   */
292  default void onConfigurationChange(Configuration config) {
293    // noop
294  }
295}