blob: 44b06de18d501b138f008fcc6da1a7461359426b [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.client.RegionLocator;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.JVMClusterUtil;
import org.apache.hadoop.hbase.util.Threads;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
/**
* Test HBASE-3694 whether the GlobalMemStoreSize is the same as the summary
* of all the online region's MemStoreSize
*/
@Category({MiscTests.class, MediumTests.class})
public class TestGlobalMemStoreSize {
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestGlobalMemStoreSize.class);
private static final Logger LOG = LoggerFactory.getLogger(TestGlobalMemStoreSize.class);
private static int regionServerNum = 4;
private static int regionNum = 16;
// total region num = region num + meta regions
private static int totalRegionNum = regionNum + 1;
private HBaseTestingUtility TEST_UTIL;
private MiniHBaseCluster cluster;
@Rule
public TestName name = new TestName();
/**
* Test the global mem store size in the region server is equal to sum of each
* region's mem store size
* @throws Exception
*/
@Test
public void testGlobalMemStore() throws Exception {
// Start the cluster
LOG.info("Starting cluster");
Configuration conf = HBaseConfiguration.create();
TEST_UTIL = new HBaseTestingUtility(conf);
TEST_UTIL.startMiniCluster(regionServerNum);
cluster = TEST_UTIL.getHBaseCluster();
LOG.info("Waiting for active/ready master");
cluster.waitForActiveAndReadyMaster();
// Create a table with regions
final TableName table = TableName.valueOf(name.getMethodName());
byte [] family = Bytes.toBytes("family");
LOG.info("Creating table with " + regionNum + " regions");
Table ht = TEST_UTIL.createMultiRegionTable(table, family, regionNum);
int numRegions = -1;
try (RegionLocator r = TEST_UTIL.getConnection().getRegionLocator(table)) {
numRegions = r.getStartKeys().length;
}
assertEquals(regionNum,numRegions);
waitForAllRegionsAssigned();
for (HRegionServer server : getOnlineRegionServers()) {
long globalMemStoreSize = 0;
for (RegionInfo regionInfo :
ProtobufUtil.getOnlineRegions(null, server.getRSRpcServices())) {
globalMemStoreSize += server.getRegion(regionInfo.getEncodedName()).getMemStoreDataSize();
}
assertEquals(server.getRegionServerAccounting().getGlobalMemStoreDataSize(),
globalMemStoreSize);
}
// check the global memstore size after flush
int i = 0;
for (HRegionServer server : getOnlineRegionServers()) {
LOG.info("Starting flushes on " + server.getServerName() +
", size=" + server.getRegionServerAccounting().getGlobalMemStoreDataSize());
for (RegionInfo regionInfo :
ProtobufUtil.getOnlineRegions(null, server.getRSRpcServices())) {
HRegion r = server.getRegion(regionInfo.getEncodedName());
flush(r, server);
}
LOG.info("Post flush on " + server.getServerName());
long now = System.currentTimeMillis();
long timeout = now + 1000;
while(server.getRegionServerAccounting().getGlobalMemStoreDataSize() != 0 &&
timeout < System.currentTimeMillis()) {
Threads.sleep(10);
}
long size = server.getRegionServerAccounting().getGlobalMemStoreDataSize();
if (size > 0) {
// If size > 0, see if its because the meta region got edits while
// our test was running....
for (RegionInfo regionInfo :
ProtobufUtil.getOnlineRegions(null, server.getRSRpcServices())) {
HRegion r = server.getRegion(regionInfo.getEncodedName());
long l = r.getMemStoreDataSize();
if (l > 0) {
// Only meta could have edits at this stage. Give it another flush
// clear them.
assertTrue(regionInfo.isMetaRegion());
LOG.info(r.toString() + " " + l + ", reflushing");
r.flush(true);
}
}
}
size = server.getRegionServerAccounting().getGlobalMemStoreDataSize();
assertEquals("Server=" + server.getServerName() + ", i=" + i++, 0, size);
}
ht.close();
TEST_UTIL.shutdownMiniCluster();
}
/**
* Flush and log stats on flush
* @param r
* @param server
* @throws IOException
*/
private void flush(final HRegion r, final HRegionServer server)
throws IOException {
LOG.info("Flush " + r.toString() + " on " + server.getServerName() +
", " + r.flush(true) + ", size=" +
server.getRegionServerAccounting().getGlobalMemStoreDataSize());
}
private List<HRegionServer> getOnlineRegionServers() {
List<HRegionServer> list = new ArrayList<>();
for (JVMClusterUtil.RegionServerThread rst :
cluster.getRegionServerThreads()) {
if (rst.getRegionServer().isOnline()) {
list.add(rst.getRegionServer());
}
}
return list;
}
/**
* Wait until all the regions are assigned.
*/
private void waitForAllRegionsAssigned() throws IOException {
while (true) {
int regionCount = HBaseTestingUtility.getAllOnlineRegions(cluster).size();
if (regionCount >= totalRegionNum) break;
LOG.debug("Waiting for there to be "+ totalRegionNum
+" regions, but there are " + regionCount + " right now.");
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
}