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.util.ArrayList;
021import java.util.List;
022import org.apache.hadoop.hbase.Cell;
023import org.apache.hadoop.hbase.HBaseClassTestRule;
024import org.apache.hadoop.hbase.HBaseTestCase;
025import org.apache.hadoop.hbase.HBaseTestingUtility;
026import org.apache.hadoop.hbase.HColumnDescriptor;
027import org.apache.hadoop.hbase.HTableDescriptor;
028import org.apache.hadoop.hbase.KeyValueUtil;
029import org.apache.hadoop.hbase.TableName;
030import org.apache.hadoop.hbase.client.Scan;
031import org.apache.hadoop.hbase.io.compress.Compression;
032import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
033import org.apache.hadoop.hbase.io.hfile.CacheConfig;
034import org.apache.hadoop.hbase.io.hfile.CacheStats;
035import org.apache.hadoop.hbase.testclassification.RegionServerTests;
036import org.apache.hadoop.hbase.testclassification.SmallTests;
037import org.apache.hadoop.hbase.util.Bytes;
038import org.junit.Assert;
039import org.junit.Before;
040import org.junit.ClassRule;
041import org.junit.Test;
042import org.junit.experimental.categories.Category;
043
044@SuppressWarnings("deprecation")
045@Category({RegionServerTests.class, SmallTests.class})
046public class TestBlocksScanned extends HBaseTestCase {
047
048  @ClassRule
049  public static final HBaseClassTestRule CLASS_RULE =
050      HBaseClassTestRule.forClass(TestBlocksScanned.class);
051
052  private static byte [] FAMILY = Bytes.toBytes("family");
053  private static byte [] COL = Bytes.toBytes("col");
054  private static byte [] START_KEY = Bytes.toBytes("aaa");
055  private static byte [] END_KEY = Bytes.toBytes("zzz");
056  private static int BLOCK_SIZE = 70;
057
058  private static HBaseTestingUtility TEST_UTIL = null;
059
060  @Override
061  @Before
062  public void setUp() throws Exception {
063    super.setUp();
064    TEST_UTIL = new HBaseTestingUtility();
065    CacheConfig.instantiateBlockCache(TEST_UTIL.getConfiguration());
066  }
067
068  @Test
069  public void testBlocksScanned() throws Exception {
070    byte [] tableName = Bytes.toBytes("TestBlocksScanned");
071    HTableDescriptor table = new HTableDescriptor(TableName.valueOf(tableName));
072
073    table.addFamily(
074        new HColumnDescriptor(FAMILY)
075        .setMaxVersions(10)
076        .setBlockCacheEnabled(true)
077        .setBlocksize(BLOCK_SIZE)
078        .setCompressionType(Compression.Algorithm.NONE)
079        );
080    _testBlocksScanned(table);
081  }
082
083  @Test
084  public void testBlocksScannedWithEncoding() throws Exception {
085    byte [] tableName = Bytes.toBytes("TestBlocksScannedWithEncoding");
086    HTableDescriptor table = new HTableDescriptor(TableName.valueOf(tableName));
087
088    table.addFamily(
089        new HColumnDescriptor(FAMILY)
090        .setMaxVersions(10)
091        .setBlockCacheEnabled(true)
092        .setDataBlockEncoding(DataBlockEncoding.FAST_DIFF)
093        .setBlocksize(BLOCK_SIZE)
094        .setCompressionType(Compression.Algorithm.NONE)
095        );
096    _testBlocksScanned(table);
097  }
098
099  private void _testBlocksScanned(HTableDescriptor table) throws Exception {
100    HRegion r = createNewHRegion(table, START_KEY, END_KEY, TEST_UTIL.getConfiguration());
101    addContent(r, FAMILY, COL);
102    r.flush(true);
103
104    CacheStats stats = new CacheConfig(TEST_UTIL.getConfiguration()).getBlockCache().getStats();
105    long before = stats.getHitCount() + stats.getMissCount();
106    // Do simple test of getting one row only first.
107    Scan scan = new Scan().withStartRow(Bytes.toBytes("aaa")).withStopRow(Bytes.toBytes("aaz"))
108        .setReadType(Scan.ReadType.PREAD);
109    scan.addColumn(FAMILY, COL);
110    scan.setMaxVersions(1);
111
112    InternalScanner s = r.getScanner(scan);
113    List<Cell> results = new ArrayList<>();
114    while (s.next(results));
115    s.close();
116
117    int expectResultSize = 'z' - 'a';
118    assertEquals(expectResultSize, results.size());
119
120    int kvPerBlock = (int) Math.ceil(BLOCK_SIZE /
121        (double) KeyValueUtil.ensureKeyValue(results.get(0)).getLength());
122    Assert.assertEquals(2, kvPerBlock);
123
124    long expectDataBlockRead = (long) Math.ceil(expectResultSize / (double) kvPerBlock);
125    long expectIndexBlockRead = expectDataBlockRead;
126
127    assertEquals(expectIndexBlockRead+expectDataBlockRead, stats.getHitCount() + stats.getMissCount() - before);
128  }
129}