View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.io.hfile;
19  
20  import java.io.IOException;
21  import java.lang.management.ManagementFactory;
22  import java.lang.management.MemoryUsage;
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.HColumnDescriptor;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.io.hfile.BlockType.BlockCategory;
31  import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache;
32  import org.apache.hadoop.util.StringUtils;
33  
34  import com.google.common.annotations.VisibleForTesting;
35  
36  /**
37   * Stores all of the cache objects and configuration for a single HFile.
38   */
39  @InterfaceAudience.Private
40  public class CacheConfig {
41    private static final Log LOG = LogFactory.getLog(CacheConfig.class.getName());
42  
43    /**
44     * Configuration key to cache data blocks on write. There are separate
45     * switches for bloom blocks and non-root index blocks.
46     */
47    public static final String CACHE_BLOCKS_ON_WRITE_KEY =
48        "hbase.rs.cacheblocksonwrite";
49  
50    /**
51     * Configuration key to cache leaf and intermediate-level index blocks on
52     * write.
53     */
54    public static final String CACHE_INDEX_BLOCKS_ON_WRITE_KEY =
55        "hfile.block.index.cacheonwrite";
56  
57    /**
58     * Configuration key to cache compound bloom filter blocks on write.
59     */
60    public static final String CACHE_BLOOM_BLOCKS_ON_WRITE_KEY =
61        "hfile.block.bloom.cacheonwrite";
62  
63    /**
64     * TODO: Implement this (jgray)
65     * Configuration key to cache data blocks in compressed format.
66     */
67    public static final String CACHE_DATA_BLOCKS_COMPRESSED_KEY =
68        "hbase.rs.blockcache.cachedatacompressed";
69  
70    /**
71     * Configuration key to evict all blocks of a given file from the block cache
72     * when the file is closed.
73     */
74    public static final String EVICT_BLOCKS_ON_CLOSE_KEY =
75        "hbase.rs.evictblocksonclose";
76  
77    /**
78     * Configuration keys for Bucket cache
79     */
80  
81    /**
82     * Current ioengine options in include: heap, offheap and file:PATH (where PATH is the path
83     * to the file that will host the file-based cache.  See BucketCache#getIOEngineFromName() for
84     * list of supported ioengine options.
85     * 
86     * <p>Set this option and a non-zero {@link #BUCKET_CACHE_SIZE_KEY} to enable bucket cache.
87     */
88    public static final String BUCKET_CACHE_IOENGINE_KEY = "hbase.bucketcache.ioengine";
89  
90    /**
91     * When using bucket cache, this is a float that EITHER represents a percentage of total heap
92     * memory size to give to the cache (if < 1.0) OR, it is the capacity in megabytes of the cache.
93     */
94    public static final String BUCKET_CACHE_SIZE_KEY = "hbase.bucketcache.size";
95  
96    /**
97     * If the chosen ioengine can persist its state across restarts, the path to the file to
98     * persist to.
99     */
100   public static final String BUCKET_CACHE_PERSISTENT_PATH_KEY = 
101       "hbase.bucketcache.persistent.path";
102 
103   /**
104    * If the bucket cache is used in league with the lru on-heap block cache (meta blocks such
105    * as indices and blooms are kept in the lru blockcache and the data blocks in the
106    * bucket cache).
107    */
108   public static final String BUCKET_CACHE_COMBINED_KEY = 
109       "hbase.bucketcache.combinedcache.enabled";
110 
111   public static final String BUCKET_CACHE_WRITER_THREADS_KEY = "hbase.bucketcache.writer.threads";
112   public static final String BUCKET_CACHE_WRITER_QUEUE_KEY = 
113       "hbase.bucketcache.writer.queuelength";
114 
115   /**
116    * A comma-delimited array of values for use as bucket sizes.
117    */
118   public static final String BUCKET_CACHE_BUCKETS_KEY = "hbase.bucketcache.bucket.sizes";
119 
120   /**
121    * Defaults for Bucket cache
122    */
123   public static final boolean DEFAULT_BUCKET_CACHE_COMBINED = true;
124   public static final int DEFAULT_BUCKET_CACHE_WRITER_THREADS = 3;
125   public static final int DEFAULT_BUCKET_CACHE_WRITER_QUEUE = 64;
126   public static final float DEFAULT_BUCKET_CACHE_COMBINED_PERCENTAGE = 0.9f;
127 
128  /**
129    * Configuration key to prefetch all blocks of a given file into the block cache
130    * when the file is opened.
131    */
132   public static final String PREFETCH_BLOCKS_ON_OPEN_KEY =
133       "hbase.rs.prefetchblocksonopen";
134 
135   // Defaults
136 
137   public static final boolean DEFAULT_CACHE_DATA_ON_READ = true;
138   public static final boolean DEFAULT_CACHE_DATA_ON_WRITE = false;
139   public static final boolean DEFAULT_IN_MEMORY = false;
140   public static final boolean DEFAULT_CACHE_INDEXES_ON_WRITE = false;
141   public static final boolean DEFAULT_CACHE_BLOOMS_ON_WRITE = false;
142   public static final boolean DEFAULT_EVICT_ON_CLOSE = false;
143   public static final boolean DEFAULT_COMPRESSED_CACHE = false;
144   public static final boolean DEFAULT_PREFETCH_ON_OPEN = false;
145 
146   /** Local reference to the block cache, null if completely disabled */
147   private final BlockCache blockCache;
148 
149   /**
150    * Whether blocks should be cached on read (default is on if there is a
151    * cache but this can be turned off on a per-family or per-request basis).
152    * If off we will STILL cache meta blocks; i.e. INDEX and BLOOM types.
153    * This cannot be disabled.
154    */
155   private boolean cacheDataOnRead;
156 
157   /** Whether blocks should be flagged as in-memory when being cached */
158   private final boolean inMemory;
159 
160   /** Whether data blocks should be cached when new files are written */
161   private boolean cacheDataOnWrite;
162 
163   /** Whether index blocks should be cached when new files are written */
164   private final boolean cacheIndexesOnWrite;
165 
166   /** Whether compound bloom filter blocks should be cached on write */
167   private final boolean cacheBloomsOnWrite;
168 
169   /** Whether blocks of a file should be evicted when the file is closed */
170   private boolean evictOnClose;
171 
172   /** Whether data blocks should be stored in compressed form in the cache */
173   private final boolean cacheCompressed;
174 
175   /** Whether data blocks should be prefetched into the cache */
176   private final boolean prefetchOnOpen;
177 
178   /**
179    * If true and if more than one tier in this cache deploy -- e.g. CombinedBlockCache has an L1
180    * and an L2 tier -- then cache data blocks up in the L1 tier (The meta blocks are likely being
181    * cached up in L1 already.  At least this is the case if CombinedBlockCache).
182    */
183   private boolean cacheDataInL1;
184 
185   /**
186    * Create a cache configuration using the specified configuration object and
187    * family descriptor.
188    * @param conf hbase configuration
189    * @param family column family configuration
190    */
191   public CacheConfig(Configuration conf, HColumnDescriptor family) {
192     this(CacheConfig.instantiateBlockCache(conf),
193         family.isBlockCacheEnabled(),
194         family.isInMemory(),
195         // For the following flags we enable them regardless of per-schema settings
196         // if they are enabled in the global configuration.
197         conf.getBoolean(CACHE_BLOCKS_ON_WRITE_KEY,
198             DEFAULT_CACHE_DATA_ON_WRITE) || family.shouldCacheDataOnWrite(),
199         conf.getBoolean(CACHE_INDEX_BLOCKS_ON_WRITE_KEY,
200             DEFAULT_CACHE_INDEXES_ON_WRITE) || family.shouldCacheIndexesOnWrite(),
201         conf.getBoolean(CACHE_BLOOM_BLOCKS_ON_WRITE_KEY,
202             DEFAULT_CACHE_BLOOMS_ON_WRITE) || family.shouldCacheBloomsOnWrite(),
203         conf.getBoolean(EVICT_BLOCKS_ON_CLOSE_KEY,
204             DEFAULT_EVICT_ON_CLOSE) || family.shouldEvictBlocksOnClose(),
205         conf.getBoolean(CACHE_DATA_BLOCKS_COMPRESSED_KEY, DEFAULT_COMPRESSED_CACHE),
206         conf.getBoolean(PREFETCH_BLOCKS_ON_OPEN_KEY,
207             DEFAULT_PREFETCH_ON_OPEN) || family.shouldPrefetchBlocksOnOpen(),
208         conf.getBoolean(HColumnDescriptor.CACHE_DATA_IN_L1,
209             HColumnDescriptor.DEFAULT_CACHE_DATA_IN_L1) || family.shouldCacheDataInL1()
210      );
211   }
212 
213   /**
214    * Create a cache configuration using the specified configuration object and
215    * defaults for family level settings.
216    * @param conf hbase configuration
217    */
218   public CacheConfig(Configuration conf) {
219     this(CacheConfig.instantiateBlockCache(conf),
220         DEFAULT_CACHE_DATA_ON_READ,
221         DEFAULT_IN_MEMORY, // This is a family-level setting so can't be set
222                            // strictly from conf
223         conf.getBoolean(CACHE_BLOCKS_ON_WRITE_KEY, DEFAULT_CACHE_DATA_ON_WRITE),
224         conf.getBoolean(CACHE_INDEX_BLOCKS_ON_WRITE_KEY,
225             DEFAULT_CACHE_INDEXES_ON_WRITE),
226             conf.getBoolean(CACHE_BLOOM_BLOCKS_ON_WRITE_KEY,
227                 DEFAULT_CACHE_BLOOMS_ON_WRITE),
228         conf.getBoolean(EVICT_BLOCKS_ON_CLOSE_KEY, DEFAULT_EVICT_ON_CLOSE),
229         conf.getBoolean(CACHE_DATA_BLOCKS_COMPRESSED_KEY,
230             DEFAULT_COMPRESSED_CACHE),
231         conf.getBoolean(PREFETCH_BLOCKS_ON_OPEN_KEY, DEFAULT_PREFETCH_ON_OPEN),
232         conf.getBoolean(HColumnDescriptor.CACHE_DATA_IN_L1,
233           HColumnDescriptor.DEFAULT_CACHE_DATA_IN_L1)
234      );
235   }
236 
237   /**
238    * Create a block cache configuration with the specified cache and
239    * configuration parameters.
240    * @param blockCache reference to block cache, null if completely disabled
241    * @param cacheDataOnRead whether DATA blocks should be cached on read (we always cache INDEX
242    * blocks and BLOOM blocks; this cannot be disabled).
243    * @param inMemory whether blocks should be flagged as in-memory
244    * @param cacheDataOnWrite whether data blocks should be cached on write
245    * @param cacheIndexesOnWrite whether index blocks should be cached on write
246    * @param cacheBloomsOnWrite whether blooms should be cached on write
247    * @param evictOnClose whether blocks should be evicted when HFile is closed
248    * @param cacheCompressed whether to store blocks as compressed in the cache
249    * @param prefetchOnOpen whether to prefetch blocks upon open
250    * @param cacheDataInL1 If more than one cache tier deployed, if true, cache this column families
251    * data blocks up in the L1 tier.
252    */
253   CacheConfig(final BlockCache blockCache,
254       final boolean cacheDataOnRead, final boolean inMemory,
255       final boolean cacheDataOnWrite, final boolean cacheIndexesOnWrite,
256       final boolean cacheBloomsOnWrite, final boolean evictOnClose,
257       final boolean cacheCompressed, final boolean prefetchOnOpen,
258       final boolean cacheDataInL1) {
259     this.blockCache = blockCache;
260     this.cacheDataOnRead = cacheDataOnRead;
261     this.inMemory = inMemory;
262     this.cacheDataOnWrite = cacheDataOnWrite;
263     this.cacheIndexesOnWrite = cacheIndexesOnWrite;
264     this.cacheBloomsOnWrite = cacheBloomsOnWrite;
265     this.evictOnClose = evictOnClose;
266     this.cacheCompressed = cacheCompressed;
267     this.prefetchOnOpen = prefetchOnOpen;
268     this.cacheDataInL1 = cacheDataInL1;
269     LOG.info(this);
270   }
271 
272   /**
273    * Constructs a cache configuration copied from the specified configuration.
274    * @param cacheConf
275    */
276   public CacheConfig(CacheConfig cacheConf) {
277     this(cacheConf.blockCache, cacheConf.cacheDataOnRead, cacheConf.inMemory,
278         cacheConf.cacheDataOnWrite, cacheConf.cacheIndexesOnWrite,
279         cacheConf.cacheBloomsOnWrite, cacheConf.evictOnClose,
280         cacheConf.cacheCompressed, cacheConf.prefetchOnOpen,
281         cacheConf.cacheDataInL1);
282   }
283 
284   /**
285    * Checks whether the block cache is enabled.
286    */
287   public boolean isBlockCacheEnabled() {
288     return this.blockCache != null;
289   }
290 
291   /**
292    * Returns the block cache.
293    * @return the block cache, or null if caching is completely disabled
294    */
295   public BlockCache getBlockCache() {
296     return this.blockCache;
297   }
298 
299   /**
300    * Returns whether the DATA blocks of this HFile should be cached on read or not (we always
301    * cache the meta blocks, the INDEX and BLOOM blocks).
302    * @return true if blocks should be cached on read, false if not
303    */
304   public boolean shouldCacheDataOnRead() {
305     return isBlockCacheEnabled() && cacheDataOnRead;
306   }
307 
308   /**
309    * Should we cache a block of a particular category? We always cache
310    * important blocks such as index blocks, as long as the block cache is
311    * available.
312    */
313   public boolean shouldCacheBlockOnRead(BlockCategory category) {
314     boolean shouldCache = isBlockCacheEnabled()
315         && (cacheDataOnRead ||
316             category == BlockCategory.INDEX ||
317             category == BlockCategory.BLOOM ||
318             (prefetchOnOpen &&
319                 (category != BlockCategory.META &&
320                  category != BlockCategory.UNKNOWN)));
321     return shouldCache;
322   }
323 
324   /**
325    * @return true if blocks in this file should be flagged as in-memory
326    */
327   public boolean isInMemory() {
328     return isBlockCacheEnabled() && this.inMemory;
329   }
330 
331   /**
332    * @return True if cache data blocks in L1 tier (if more than one tier in block cache deploy).
333    */
334   public boolean isCacheDataInL1() {
335     return isBlockCacheEnabled() && this.cacheDataInL1;
336   }
337 
338   /**
339    * @return true if data blocks should be written to the cache when an HFile is
340    *         written, false if not
341    */
342   public boolean shouldCacheDataOnWrite() {
343     return isBlockCacheEnabled() && this.cacheDataOnWrite;
344   }
345 
346   /**
347    * Only used for testing.
348    * @param cacheDataOnWrite whether data blocks should be written to the cache
349    *                         when an HFile is written
350    */
351   @VisibleForTesting
352   public void setCacheDataOnWrite(boolean cacheDataOnWrite) {
353     this.cacheDataOnWrite = cacheDataOnWrite;
354   }
355 
356   /**
357    * Only used for testing.
358    * @param cacheDataInL1 Whether to cache data blocks up in l1 (if a multi-tier cache
359    * implementation).
360    */
361   @VisibleForTesting
362   public void setCacheDataInL1(boolean cacheDataInL1) {
363     this.cacheDataInL1 = cacheDataInL1;
364   }
365 
366   /**
367    * @return true if index blocks should be written to the cache when an HFile
368    *         is written, false if not
369    */
370   public boolean shouldCacheIndexesOnWrite() {
371     return isBlockCacheEnabled() && this.cacheIndexesOnWrite;
372   }
373 
374   /**
375    * @return true if bloom blocks should be written to the cache when an HFile
376    *         is written, false if not
377    */
378   public boolean shouldCacheBloomsOnWrite() {
379     return isBlockCacheEnabled() && this.cacheBloomsOnWrite;
380   }
381 
382   /**
383    * @return true if blocks should be evicted from the cache when an HFile
384    *         reader is closed, false if not
385    */
386   public boolean shouldEvictOnClose() {
387     return isBlockCacheEnabled() && this.evictOnClose;
388   }
389 
390   /**
391    * Only used for testing.
392    * @param evictOnClose whether blocks should be evicted from the cache when an
393    *                     HFile reader is closed
394    */
395   public void setEvictOnClose(boolean evictOnClose) {
396     this.evictOnClose = evictOnClose;
397   }
398 
399   /**
400    * @return true if blocks should be compressed in the cache, false if not
401    */
402   public boolean shouldCacheCompressed() {
403     return isBlockCacheEnabled() && this.cacheCompressed;
404   }
405 
406   /**
407    * @return true if blocks should be prefetched into the cache on open, false if not
408    */
409   public boolean shouldPrefetchOnOpen() {
410     return isBlockCacheEnabled() && this.prefetchOnOpen;
411   }
412 
413   @Override
414   public String toString() {
415     if (!isBlockCacheEnabled()) {
416       return "CacheConfig:disabled";
417     }
418     return "blockCache=" + getBlockCache() +
419       ", cacheDataOnRead=" + shouldCacheDataOnRead() +
420       ", cacheDataOnWrite=" + shouldCacheDataOnWrite() +
421       ", cacheIndexesOnWrite=" + shouldCacheIndexesOnWrite() +
422       ", cacheBloomsOnWrite=" + shouldCacheBloomsOnWrite() +
423       ", cacheEvictOnClose=" + shouldEvictOnClose() +
424       ", cacheCompressed=" + shouldCacheCompressed() +
425       ", prefetchOnOpen=" + shouldPrefetchOnOpen();
426   }
427 
428   // Static block cache reference and methods
429 
430   /**
431    * Static reference to the block cache, or null if no caching should be used
432    * at all.
433    */
434   // Clear this if in tests you'd make more than one block cache instance.
435   @VisibleForTesting
436   static BlockCache GLOBAL_BLOCK_CACHE_INSTANCE;
437 
438   /** Boolean whether we have disabled the block cache entirely. */
439   @VisibleForTesting
440   static boolean blockCacheDisabled = false;
441 
442   static long getLruCacheSize(final Configuration conf, final MemoryUsage mu) {
443     float cachePercentage = conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
444       HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
445     if (cachePercentage <= 0.0001f) {
446       blockCacheDisabled = true;
447       return -1;
448     }
449     if (cachePercentage > 1.0) {
450       throw new IllegalArgumentException(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY +
451         " must be between 0.0 and 1.0, and not > 1.0");
452     }
453 
454     // Calculate the amount of heap to give the heap.
455     return (long) (mu.getMax() * cachePercentage);
456   }
457 
458   /**
459    * @param c Configuration to use.
460    * @param mu JMX Memory Bean
461    * @return An L1 instance.  Currently an instance of LruBlockCache.
462    */
463   private static LruBlockCache getL1(final Configuration c, final MemoryUsage mu) {
464     long lruCacheSize = getLruCacheSize(c, mu);
465     int blockSize = c.getInt("hbase.offheapcache.minblocksize", HConstants.DEFAULT_BLOCKSIZE);
466     LOG.info("Allocating LruBlockCache size=" +
467       StringUtils.byteDesc(lruCacheSize) + ", blockSize=" + StringUtils.byteDesc(blockSize));
468     return new LruBlockCache(lruCacheSize, blockSize, true, c);
469   }
470 
471   /**
472    * @param c Configuration to use.
473    * @param mu JMX Memory Bean
474    * @return Returns L2 block cache instance (for now it is BucketCache BlockCache all the time)
475    * or null if not supposed to be a L2.
476    */
477   private static BucketCache getL2(final Configuration c, final MemoryUsage mu) {
478     // Check for L2.  ioengine name must be non-null.
479     String bucketCacheIOEngineName = c.get(BUCKET_CACHE_IOENGINE_KEY, null);
480     if (bucketCacheIOEngineName == null || bucketCacheIOEngineName.length() <= 0) return null;
481 
482     int blockSize = c.getInt("hbase.offheapcache.minblocksize", HConstants.DEFAULT_BLOCKSIZE);
483     float bucketCachePercentage = c.getFloat(BUCKET_CACHE_SIZE_KEY, 0F);
484     long bucketCacheSize = (long) (bucketCachePercentage < 1? mu.getMax() * bucketCachePercentage:
485       bucketCachePercentage * 1024 * 1024);
486     if (bucketCacheSize <= 0) {
487       throw new IllegalStateException("bucketCacheSize <= 0; Check " +
488         BUCKET_CACHE_SIZE_KEY + " setting and/or server java heap size");
489     }
490     int writerThreads = c.getInt(BUCKET_CACHE_WRITER_THREADS_KEY,
491       DEFAULT_BUCKET_CACHE_WRITER_THREADS);
492     int writerQueueLen = c.getInt(BUCKET_CACHE_WRITER_QUEUE_KEY,
493       DEFAULT_BUCKET_CACHE_WRITER_QUEUE);
494     String persistentPath = c.get(BUCKET_CACHE_PERSISTENT_PATH_KEY);
495     String[] configuredBucketSizes = c.getStrings(BUCKET_CACHE_BUCKETS_KEY);
496     int [] bucketSizes = null;
497     if (configuredBucketSizes != null) {
498       bucketSizes = new int[configuredBucketSizes.length];
499       for (int i = 0; i < configuredBucketSizes.length; i++) {
500         bucketSizes[i] = Integer.parseInt(configuredBucketSizes[i]);
501       }
502     }
503     BucketCache bucketCache = null;
504     try {
505       int ioErrorsTolerationDuration = c.getInt(
506         "hbase.bucketcache.ioengine.errors.tolerated.duration",
507         BucketCache.DEFAULT_ERROR_TOLERATION_DURATION);
508       // Bucket cache logs its stats on creation internal to the constructor.
509       bucketCache = new BucketCache(bucketCacheIOEngineName,
510         bucketCacheSize, blockSize, bucketSizes, writerThreads, writerQueueLen, persistentPath,
511         ioErrorsTolerationDuration);
512     } catch (IOException ioex) {
513       LOG.error("Can't instantiate bucket cache", ioex); throw new RuntimeException(ioex);
514     }
515     return bucketCache;
516   }
517 
518   /**
519    * Returns the block cache or <code>null</code> in case none should be used.
520    * Sets GLOBAL_BLOCK_CACHE_INSTANCE
521    *
522    * @param conf  The current configuration.
523    * @return The block cache or <code>null</code>.
524    */
525   public static synchronized BlockCache instantiateBlockCache(Configuration conf) {
526     if (GLOBAL_BLOCK_CACHE_INSTANCE != null) return GLOBAL_BLOCK_CACHE_INSTANCE;
527     if (blockCacheDisabled) return null;
528     MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
529     LruBlockCache l1 = getL1(conf, mu);
530     BucketCache l2 = getL2(conf, mu);
531     if (l2 == null) {
532       GLOBAL_BLOCK_CACHE_INSTANCE = l1;
533     } else {
534       boolean combinedWithLru = conf.getBoolean(BUCKET_CACHE_COMBINED_KEY,
535         DEFAULT_BUCKET_CACHE_COMBINED);
536       if (combinedWithLru) {
537         GLOBAL_BLOCK_CACHE_INSTANCE = new CombinedBlockCache(l1, l2);
538       } else {
539         // L1 and L2 are not 'combined'.  They are connected via the LruBlockCache victimhandler
540         // mechanism.  It is a little ugly but works according to the following: when the
541         // background eviction thread runs, blocks evicted from L1 will go to L2 AND when we get
542         // a block from the L1 cache, if not in L1, we will search L2.
543         l1.setVictimCache(l2);
544         GLOBAL_BLOCK_CACHE_INSTANCE = l1;
545       }
546     }
547     return GLOBAL_BLOCK_CACHE_INSTANCE;
548   }
549 }