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 static org.junit.jupiter.api.Assertions.assertEquals;
021
022import java.io.IOException;
023import org.apache.hadoop.conf.Configuration;
024import org.apache.hadoop.hbase.HBaseTestingUtil;
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.junit.jupiter.api.Tag;
033import org.junit.jupiter.api.Test;
034
035/**
036 * A test similar to TestHRegion, but with in-memory flush families. Also checks wal truncation
037 * after in-memory compaction.
038 */
039@Tag(VerySlowRegionServerTests.TAG)
040@Tag(LargeTests.TAG)
041public class TestHRegionWithInMemoryFlush extends TestHRegion {
042
043  /**
044   * @return A region on which you must call {@link HBaseTestingUtil#closeRegionAndWAL(HRegion)}
045   *         when done.
046   */
047  @Override
048  protected HRegion initHRegion(TableName tableName, byte[] startKey, byte[] stopKey,
049    Configuration conf, boolean isReadOnly, Durability durability, WAL wal, byte[]... families)
050    throws IOException {
051    boolean[] inMemory = new boolean[families.length];
052    for (int i = 0; i < inMemory.length; i++) {
053      inMemory[i] = true;
054    }
055    ChunkCreator.initialize(MemStoreLAB.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, null,
056      MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT);
057    return TEST_UTIL.createLocalHRegionWithInMemoryFlags(tableName, startKey, stopKey, conf,
058      isReadOnly, durability, wal, inMemory, families);
059  }
060
061  @Override
062  protected int getTestCountForTestWritesWhileScanning() {
063    return 10;
064  }
065
066  /**
067   * testWritesWhileScanning is flakey when called out of this class. Need to dig in. Meantime go
068   * easy on it. See if that helps.
069   */
070  @Override
071  protected int getNumQualifiersForTestWritesWhileScanning() {
072    return 10;
073  }
074
075  /**
076   * A test case of HBASE-21041
077   */
078  @Override
079  @Test
080  public void testFlushAndMemstoreSizeCounting() throws Exception {
081    byte[] family = Bytes.toBytes("family");
082    this.region = initHRegion(tableName, method, CONF, family);
083    int count = 0;
084    for (byte[] row : HBaseTestingUtil.ROWS) {
085      Put put = new Put(row);
086      put.addColumn(family, family, row);
087      region.put(put);
088      // In memory flush every 1000 puts
089      if (count++ % 1000 == 0) {
090        ((CompactingMemStore) (region.getStore(family).memstore)).flushInMemory();
091      }
092    }
093    region.flush(true);
094    // After flush, data size should be zero
095    assertEquals(0, region.getMemStoreDataSize());
096    // After flush, a new active mutable segment is created, so the heap size
097    // should equal to MutableSegment.DEEP_OVERHEAD
098    assertEquals(MutableSegment.DEEP_OVERHEAD, region.getMemStoreHeapSize());
099    // After flush, offheap size should be zero
100    assertEquals(0, region.getMemStoreOffHeapSize());
101  }
102}