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.regionserver;
019
020import java.io.IOException;
021
022import org.apache.hadoop.conf.Configuration;
023import org.apache.hadoop.hbase.HBaseClassTestRule;
024import org.apache.hadoop.hbase.HBaseTestingUtility;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.client.Durability;
027import org.apache.hadoop.hbase.client.Put;
028import org.apache.hadoop.hbase.testclassification.LargeTests;
029import org.apache.hadoop.hbase.testclassification.VerySlowRegionServerTests;
030import org.apache.hadoop.hbase.util.Bytes;
031import org.apache.hadoop.hbase.wal.WAL;
032import org.apache.hadoop.hbase.wal.WALFactory;
033import org.junit.Assert;
034import org.junit.ClassRule;
035import org.junit.Test;
036import org.junit.experimental.categories.Category;
037import org.slf4j.Logger;
038import org.slf4j.LoggerFactory;
039
040
041/**
042 * A test similar to TestHRegion, but with in-memory flush families.
043 * Also checks wal truncation after in-memory compaction.
044 */
045@Category({VerySlowRegionServerTests.class, LargeTests.class})
046@SuppressWarnings("deprecation")
047public class TestHRegionWithInMemoryFlush extends TestHRegion {
048
049  @ClassRule
050  public static final HBaseClassTestRule CLASS_RULE =
051      HBaseClassTestRule.forClass(TestHRegionWithInMemoryFlush.class);
052
053  // Do not spin up clusters in here. If you need to spin up a cluster, do it
054  // over in TestHRegionOnCluster.
055  private static final Logger LOG = LoggerFactory.getLogger(TestHRegionWithInMemoryFlush.class);
056
057  /**
058   * @return A region on which you must call
059   *         {@link HBaseTestingUtility#closeRegionAndWAL(HRegion)} when done.
060   */
061  @Override
062  public HRegion initHRegion(TableName tableName, byte[] startKey, byte[] stopKey,
063      Configuration conf, boolean isReadOnly, Durability durability, WAL wal, byte[]... families)
064      throws IOException {
065    boolean[] inMemory = new boolean[families.length];
066    for(int i = 0; i < inMemory.length; i++) {
067      inMemory[i] = true;
068    }
069    ChunkCreator.initialize(MemStoreLAB.CHUNK_SIZE_DEFAULT, false, 0, 0,
070      0, null, MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT);
071    return TEST_UTIL.createLocalHRegionWithInMemoryFlags(tableName, startKey, stopKey,
072        conf, isReadOnly, durability, wal, inMemory, families);
073  }
074
075  @Override int getTestCountForTestWritesWhileScanning() {
076    return 10;
077  }
078
079  /**
080   * testWritesWhileScanning is flakey when called out of this class. Need to dig in. Meantime
081   * go easy on it. See if that helps.
082   */
083  @Override int getNumQualifiersForTestWritesWhileScanning() {
084    return 10;
085  }
086
087  /**
088   * A test case of HBASE-21041
089   * @throws Exception Exception
090   */
091  @Override
092  @Test
093  public void testFlushAndMemstoreSizeCounting() throws Exception {
094    byte[] family = Bytes.toBytes("family");
095    this.region = initHRegion(tableName, method, CONF, family);
096    final WALFactory wals = new WALFactory(CONF, method);
097    int count = 0;
098    try {
099      for (byte[] row : HBaseTestingUtility.ROWS) {
100        Put put = new Put(row);
101        put.addColumn(family, family, row);
102        region.put(put);
103        //In memory flush every 1000 puts
104        if (count++ % 1000 == 0) {
105          ((CompactingMemStore) (region.getStore(family).memstore))
106              .flushInMemory();
107        }
108      }
109      region.flush(true);
110      // After flush, data size should be zero
111      Assert.assertEquals(0, region.getMemStoreDataSize());
112      // After flush, a new active mutable segment is created, so the heap size
113      // should equal to MutableSegment.DEEP_OVERHEAD
114      Assert.assertEquals(MutableSegment.DEEP_OVERHEAD, region.getMemStoreHeapSize());
115      // After flush, offheap size should be zero
116      Assert.assertEquals(0, region.getMemStoreOffHeapSize());
117
118    } finally {
119      HBaseTestingUtility.closeRegionAndWAL(this.region);
120      this.region = null;
121      wals.close();
122    }
123  }
124}
125