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.regionserver;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertFalse;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.lang.management.ManagementFactory;
27  import java.util.Iterator;
28  
29  import org.apache.hadoop.conf.Configuration;
30  import org.apache.hadoop.hbase.CoordinatedStateManager;
31  import org.apache.hadoop.hbase.HBaseConfiguration;
32  import org.apache.hadoop.hbase.HConstants;
33  import org.apache.hadoop.hbase.Server;
34  import org.apache.hadoop.hbase.ServerName;
35  import org.apache.hadoop.hbase.testclassification.SmallTests;
36  import org.apache.hadoop.hbase.client.ClusterConnection;
37  import org.apache.hadoop.hbase.io.hfile.BlockCache;
38  import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;
39  import org.apache.hadoop.hbase.io.hfile.CacheStats;
40  import org.apache.hadoop.hbase.io.hfile.Cacheable;
41  import org.apache.hadoop.hbase.io.hfile.CachedBlock;
42  import org.apache.hadoop.hbase.io.hfile.ResizableBlockCache;
43  import org.apache.hadoop.hbase.io.util.HeapMemorySizeUtil;
44  import org.apache.hadoop.hbase.regionserver.HeapMemoryManager.TunerContext;
45  import org.apache.hadoop.hbase.regionserver.HeapMemoryManager.TunerResult;
46  import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
47  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
48  import org.junit.Test;
49  import org.junit.experimental.categories.Category;
50  
51  @Category(SmallTests.class)
52  public class TestHeapMemoryManager {
53  
54    private long maxHeapSize = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax();
55  
56    @Test
57    public void testAutoTunerShouldBeOffWhenMaxMinRangesForMemstoreIsNotGiven() throws Exception {
58      Configuration conf = HBaseConfiguration.create();
59      conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.75f);
60      conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.05f);
61      HeapMemoryManager manager = new HeapMemoryManager(new BlockCacheStub(0),
62          new MemstoreFlusherStub(0), new RegionServerStub(conf));
63      assertFalse(manager.isTunerOn());
64    }
65  
66    @Test
67    public void testAutoTunerShouldBeOffWhenMaxMinRangesForBlockCacheIsNotGiven() throws Exception {
68      Configuration conf = HBaseConfiguration.create();
69      conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f);
70      conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.05f);
71      HeapMemoryManager manager = new HeapMemoryManager(new BlockCacheStub(0),
72          new MemstoreFlusherStub(0), new RegionServerStub(conf));
73      assertFalse(manager.isTunerOn());
74    }
75  
76    @Test
77    public void testWhenMemstoreAndBlockCacheMaxMinChecksFails() throws Exception {
78      BlockCacheStub blockCache = new BlockCacheStub(0);
79      MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub(0);
80      Configuration conf = HBaseConfiguration.create();
81      conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f);
82      conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.06f);
83      try {
84        new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub(conf));
85        fail();
86      } catch (RuntimeException e) {
87      }
88      conf = HBaseConfiguration.create();
89      conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.2f);
90      conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f);
91      try {
92        new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub(conf));
93        fail();
94      } catch (RuntimeException e) {
95      }
96    }
97  
98    @Test
99    public void testWhenClusterIsWriteHeavy() throws Exception {
100     BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4));
101     MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4));
102     Configuration conf = HBaseConfiguration.create();
103     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f);
104     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.10f);
105     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f);
106     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.05f);
107     conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000);
108     // Let the system start with default values for memstore heap and block cache size.
109     HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher,
110         new RegionServerStub(conf));
111     long oldMemstoreHeapSize = memStoreFlusher.memstoreSize;
112     long oldBlockCacheSize = blockCache.maxSize;
113     heapMemoryManager.start();
114     memStoreFlusher.flushType = FlushType.ABOVE_HIGHER_MARK;
115     memStoreFlusher.requestFlush(null);
116     memStoreFlusher.requestFlush(null);
117     memStoreFlusher.requestFlush(null);
118     memStoreFlusher.flushType = FlushType.ABOVE_LOWER_MARK;
119     memStoreFlusher.requestFlush(null);
120     Thread.sleep(1500); // Allow the tuner to run once and do necessary memory up
121     assertHeapSpaceDelta(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE, oldMemstoreHeapSize,
122         memStoreFlusher.memstoreSize);
123     assertHeapSpaceDelta(-(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE), oldBlockCacheSize,
124         blockCache.maxSize);
125     oldMemstoreHeapSize = memStoreFlusher.memstoreSize;
126     oldBlockCacheSize = blockCache.maxSize;
127     // Do some more flushes before the next run of HeapMemoryTuner
128     memStoreFlusher.flushType = FlushType.ABOVE_HIGHER_MARK;
129     memStoreFlusher.requestFlush(null);
130     memStoreFlusher.requestFlush(null);
131     Thread.sleep(1500);
132     assertHeapSpaceDelta(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE, oldMemstoreHeapSize,
133         memStoreFlusher.memstoreSize);
134     assertHeapSpaceDelta(-(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE), oldBlockCacheSize,
135         blockCache.maxSize);
136   }
137 
138   @Test
139   public void testWhenClusterIsReadHeavy() throws Exception {
140     BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4));
141     MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4));
142     Configuration conf = HBaseConfiguration.create();
143     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f);
144     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.10f);
145     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f);
146     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.05f);
147     conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000);
148     // Let the system start with default values for memstore heap and block cache size.
149     HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher,
150         new RegionServerStub(conf));
151     long oldMemstoreHeapSize = memStoreFlusher.memstoreSize;
152     long oldBlockCacheSize = blockCache.maxSize;
153     heapMemoryManager.start();
154     blockCache.evictBlock(null);
155     blockCache.evictBlock(null);
156     blockCache.evictBlock(null);
157     Thread.sleep(1500); // Allow the tuner to run once and do necessary memory up
158     assertHeapSpaceDelta(-(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE), oldMemstoreHeapSize,
159         memStoreFlusher.memstoreSize);
160     assertHeapSpaceDelta(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE, oldBlockCacheSize,
161         blockCache.maxSize);
162     oldMemstoreHeapSize = memStoreFlusher.memstoreSize;
163     oldBlockCacheSize = blockCache.maxSize;
164     // Do some more evictions before the next run of HeapMemoryTuner
165     blockCache.evictBlock(null);
166     Thread.sleep(1500);
167     assertHeapSpaceDelta(-(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE), oldMemstoreHeapSize,
168         memStoreFlusher.memstoreSize);
169     assertHeapSpaceDelta(DefaultHeapMemoryTuner.DEFAULT_STEP_VALUE, oldBlockCacheSize,
170         blockCache.maxSize);
171   }
172 
173   @Test
174   public void testPluggingInHeapMemoryTuner() throws Exception {
175     BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4));
176     MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4));
177     Configuration conf = HBaseConfiguration.create();
178     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.78f);
179     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.05f);
180     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.75f);
181     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.02f);
182     conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000);
183     conf.setClass(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_CLASS, CustomHeapMemoryTuner.class,
184         HeapMemoryTuner.class);
185     // Let the system start with default values for memstore heap and block cache size.
186     HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher,
187         new RegionServerStub(conf));
188     heapMemoryManager.start();
189     // Now we wants to be in write mode. Set bigger memstore size from CustomHeapMemoryTuner
190     CustomHeapMemoryTuner.memstoreSize = 0.78f;
191     CustomHeapMemoryTuner.blockCacheSize = 0.02f;
192     Thread.sleep(1500); // Allow the tuner to run once and do necessary memory up
193     assertHeapSpace(0.78f, memStoreFlusher.memstoreSize);// Memstore
194     assertHeapSpace(0.02f, blockCache.maxSize);// BlockCache
195     // Now we wants to be in read mode. Set bigger memstore size from CustomHeapMemoryTuner
196     CustomHeapMemoryTuner.blockCacheSize = 0.75f;
197     CustomHeapMemoryTuner.memstoreSize = 0.05f;
198     Thread.sleep(1500); // Allow the tuner to run once and do necessary memory up
199     assertHeapSpace(0.75f, blockCache.maxSize);// BlockCache
200     assertHeapSpace(0.05f, memStoreFlusher.memstoreSize);// Memstore
201   }
202 
203   @Test
204   public void testWhenSizeGivenByHeapTunerGoesOutsideRange() throws Exception {
205     BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4));
206     MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4));
207     Configuration conf = HBaseConfiguration.create();
208     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.7f);
209     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.1f);
210     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f);
211     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.1f);
212     conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000);
213     conf.setClass(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_CLASS, CustomHeapMemoryTuner.class,
214         HeapMemoryTuner.class);
215     HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher,
216         new RegionServerStub(conf));
217     heapMemoryManager.start();
218     CustomHeapMemoryTuner.memstoreSize = 0.78f;
219     CustomHeapMemoryTuner.blockCacheSize = 0.02f;
220     Thread.sleep(1500); // Allow the tuner to run once and do necessary memory up
221     // Even if the tuner says to set the memstore to 78%, HBase makes it as 70% as that is the
222     // upper bound. Same with block cache as 10% is the lower bound.
223     assertHeapSpace(0.7f, memStoreFlusher.memstoreSize);
224     assertHeapSpace(0.1f, blockCache.maxSize);
225   }
226 
227   @Test
228   public void testWhenCombinedHeapSizesFromTunerGoesOutSideMaxLimit() throws Exception {
229     BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4));
230     MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4));
231     Configuration conf = HBaseConfiguration.create();
232     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.7f);
233     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.1f);
234     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f);
235     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.1f);
236     conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000);
237     conf.setClass(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_CLASS, CustomHeapMemoryTuner.class,
238         HeapMemoryTuner.class);
239     HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher,
240         new RegionServerStub(conf));
241     long oldMemstoreSize = memStoreFlusher.memstoreSize;
242     long oldBlockCacheSize = blockCache.maxSize;
243     heapMemoryManager.start();
244     CustomHeapMemoryTuner.memstoreSize = 0.7f;
245     CustomHeapMemoryTuner.blockCacheSize = 0.3f;
246     Thread.sleep(1500);
247     assertEquals(oldMemstoreSize, memStoreFlusher.memstoreSize);
248     assertEquals(oldBlockCacheSize, blockCache.maxSize);
249   }
250 
251   @Test
252   public void testWhenL2BlockCacheIsOnHeap() throws Exception {
253     HeapMemoryManager heapMemoryManager = null;
254     BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4));
255     MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.3));
256     Configuration conf = HBaseConfiguration.create();
257     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.7f);
258     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.1f);
259     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f);
260     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.1f);
261 
262     conf.setFloat(HeapMemorySizeUtil.MEMSTORE_SIZE_KEY, 0.4F);
263     conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.3F);
264     conf.setFloat(HConstants.BUCKET_CACHE_SIZE_KEY, 0.1F);
265     conf.set(HConstants.BUCKET_CACHE_IOENGINE_KEY, "heap");
266 
267     conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000);
268     conf.setClass(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_CLASS, CustomHeapMemoryTuner.class,
269         HeapMemoryTuner.class);
270 
271     try {
272       heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub(
273           conf));
274       fail("Should have failed as the collective heap memory need is above 80%");
275     } catch (Exception e) {
276     }
277 
278     // Change the max/min ranges for memstore and bock cache so as to pass the criteria check
279     conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.6f);
280     conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.6f);
281     heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub(
282         conf));
283     long oldMemstoreSize = memStoreFlusher.memstoreSize;
284     long oldBlockCacheSize = blockCache.maxSize;
285     heapMemoryManager.start();
286     CustomHeapMemoryTuner.memstoreSize = 0.4f;
287     CustomHeapMemoryTuner.blockCacheSize = 0.4f;
288     Thread.sleep(1500);
289     // The size should not get changes as the collection of memstore size and L1 and L2 block cache
290     // size will cross the ax allowed 80% mark
291     assertEquals(oldMemstoreSize, memStoreFlusher.memstoreSize);
292     assertEquals(oldBlockCacheSize, blockCache.maxSize);
293     CustomHeapMemoryTuner.memstoreSize = 0.1f;
294     CustomHeapMemoryTuner.blockCacheSize = 0.5f;
295     Thread.sleep(1500);
296     assertHeapSpace(0.1f, memStoreFlusher.memstoreSize);
297     assertHeapSpace(0.5f, blockCache.maxSize);
298   }
299 
300   private void assertHeapSpace(float expectedHeapPercentage, long currentHeapSpace) {
301     long expected = (long) (this.maxHeapSize * expectedHeapPercentage);
302     assertEquals(expected, currentHeapSpace);
303   }
304 
305   private void assertHeapSpaceDelta(float expectedDeltaPercent, long oldHeapSpace, long newHeapSpace) {
306     long expctedMinDelta = (long) (this.maxHeapSize * expectedDeltaPercent);
307     if (expectedDeltaPercent > 0) {
308       assertTrue(expctedMinDelta <= (newHeapSpace - oldHeapSpace));
309     } else {
310       assertTrue(expctedMinDelta <= (oldHeapSpace - newHeapSpace));
311     }
312   }
313 
314   private static class BlockCacheStub implements ResizableBlockCache {
315     CacheStats stats = new CacheStats("test");
316     long maxSize = 0;
317 
318     public BlockCacheStub(long size){
319       this.maxSize = size;
320     }
321 
322     @Override
323     public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory,
324         boolean cacheDataInL1) {
325 
326     }
327 
328     @Override
329     public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {
330 
331     }
332 
333     @Override
334     public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,
335         boolean updateCacheMetrics) {
336       return null;
337     }
338 
339     @Override
340     public boolean evictBlock(BlockCacheKey cacheKey) {
341       stats.evicted(0);
342       return false;
343     }
344 
345     @Override
346     public int evictBlocksByHfileName(String hfileName) {
347       stats.evicted(0); // Just assuming only one block for file here.
348       return 0;
349     }
350 
351     @Override
352     public CacheStats getStats() {
353       return this.stats;
354     }
355 
356     @Override
357     public void shutdown() {
358 
359     }
360 
361     @Override
362     public long size() {
363       return 0;
364     }
365 
366     @Override
367     public long getFreeSize() {
368       return 0;
369     }
370 
371     @Override
372     public long getCurrentSize() {
373       return 0;
374     }
375 
376     @Override
377     public long getBlockCount() {
378       return 0;
379     }
380 
381     @Override
382     public void setMaxSize(long size) {
383       this.maxSize = size;
384     }
385 
386     @Override
387     public Iterator<CachedBlock> iterator() {
388       return null;
389     }
390 
391     @Override
392     public BlockCache[] getBlockCaches() {
393       return null;
394     }
395   }
396 
397   private static class MemstoreFlusherStub implements FlushRequester {
398 
399     long memstoreSize;
400 
401     FlushRequestListener listener;
402 
403     FlushType flushType = FlushType.NORMAL;
404 
405     public MemstoreFlusherStub(long memstoreSize) {
406       this.memstoreSize = memstoreSize;
407     }
408 
409     @Override
410     public void requestFlush(HRegion region) {
411       this.listener.flushRequested(flushType, region);
412     }
413 
414     @Override
415     public void requestDelayedFlush(HRegion region, long delay) {
416 
417     }
418 
419     @Override
420     public void registerFlushRequestListener(FlushRequestListener listener) {
421       this.listener = listener;
422     }
423 
424     @Override
425     public boolean unregisterFlushRequestListener(FlushRequestListener listener) {
426       return false;
427     }
428 
429     @Override
430     public void setGlobalMemstoreLimit(long globalMemStoreSize) {
431       this.memstoreSize = globalMemStoreSize;
432     }
433   }
434 
435   private static class RegionServerStub implements Server {
436     private Configuration conf;
437     private boolean stopped = false;
438 
439     public RegionServerStub(Configuration conf) {
440       this.conf = conf;
441     }
442 
443     @Override
444     public void abort(String why, Throwable e) {
445 
446     }
447 
448     @Override
449     public boolean isAborted() {
450       return false;
451     }
452 
453     @Override
454     public void stop(String why) {
455       this.stopped = true;
456     }
457 
458     @Override
459     public boolean isStopped() {
460       return this.stopped;
461     }
462 
463     @Override
464     public Configuration getConfiguration() {
465       return this.conf;
466     }
467 
468     @Override
469     public ZooKeeperWatcher getZooKeeper() {
470       return null;
471     }
472 
473     @Override
474     public CoordinatedStateManager getCoordinatedStateManager() {
475       return null;
476     }
477 
478     @Override
479     public ClusterConnection getConnection() {
480       return null;
481     }
482 
483     @Override
484     public MetaTableLocator getMetaTableLocator() {
485       return null;
486     }
487 
488     @Override
489     public ServerName getServerName() {
490       return ServerName.valueOf("server1",4000,12345);
491     }
492   }
493 
494   static class CustomHeapMemoryTuner implements HeapMemoryTuner {
495     static float blockCacheSize = 0.4f;
496     static float memstoreSize = 0.4f;
497 
498     @Override
499     public Configuration getConf() {
500       return null;
501     }
502 
503     @Override
504     public void setConf(Configuration arg0) {
505 
506     }
507 
508     @Override
509     public TunerResult tune(TunerContext context) {
510       TunerResult result = new TunerResult(true);
511       result.setBlockCacheSize(blockCacheSize);
512       result.setMemstoreSize(memstoreSize);
513       return result;
514     }
515   }
516 }