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.client;
019
020import static org.junit.Assert.assertEquals;
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.hbase.ArrayBackedTag;
023import org.apache.hadoop.hbase.HBaseClassTestRule;
024import org.apache.hadoop.hbase.HBaseTestingUtility;
025import org.apache.hadoop.hbase.HConstants;
026import org.apache.hadoop.hbase.KeyValue;
027import org.apache.hadoop.hbase.TableName;
028import org.apache.hadoop.hbase.Tag;
029import org.apache.hadoop.hbase.io.hfile.HFile;
030import org.apache.hadoop.hbase.testclassification.MediumTests;
031import org.apache.hadoop.hbase.util.Bytes;
032import org.junit.AfterClass;
033import org.junit.BeforeClass;
034import org.junit.ClassRule;
035import org.junit.Rule;
036import org.junit.Test;
037import org.junit.experimental.categories.Category;
038import org.junit.rules.TestName;
039
040@Category(MediumTests.class)
041public class TestResultSizeEstimation {
042
043  @ClassRule
044  public static final HBaseClassTestRule CLASS_RULE =
045      HBaseClassTestRule.forClass(TestResultSizeEstimation.class);
046
047  final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
048
049  final static int TAG_DATA_SIZE = 2048;
050  final static int SCANNER_DATA_LIMIT = TAG_DATA_SIZE + 256;
051
052  @Rule
053  public TestName name = new TestName();
054
055  @BeforeClass
056  public static void setUpBeforeClass() throws Exception {
057    Configuration conf = TEST_UTIL.getConfiguration();
058    // Need HFileV3
059    conf.setInt(HFile.FORMAT_VERSION_KEY, HFile.MIN_FORMAT_VERSION_WITH_TAGS);
060    // effectively limit max result size to one entry if it has tags
061    conf.setLong(HConstants.HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE_KEY, SCANNER_DATA_LIMIT);
062    conf.setBoolean(ScannerCallable.LOG_SCANNER_ACTIVITY, true);
063    TEST_UTIL.startMiniCluster(1);
064  }
065
066  @AfterClass
067  public static void tearDownAfterClass() throws Exception {
068    TEST_UTIL.shutdownMiniCluster();
069  }
070
071  @Test
072  public void testResultSizeEstimation() throws Exception {
073    byte [] ROW1 = Bytes.toBytes("testRow1");
074    byte [] ROW2 = Bytes.toBytes("testRow2");
075    byte [] FAMILY = Bytes.toBytes("testFamily");
076    byte [] QUALIFIER = Bytes.toBytes("testQualifier");
077    byte [] VALUE = Bytes.toBytes("testValue");
078
079    final TableName tableName = TableName.valueOf(name.getMethodName());
080    byte[][] FAMILIES = new byte[][] { FAMILY };
081    Table table = TEST_UTIL.createTable(tableName, FAMILIES);
082    Put p = new Put(ROW1);
083    p.add(new KeyValue(ROW1, FAMILY, QUALIFIER, Long.MAX_VALUE, VALUE));
084    table.put(p);
085    p = new Put(ROW2);
086    p.add(new KeyValue(ROW2, FAMILY, QUALIFIER, Long.MAX_VALUE, VALUE));
087    table.put(p);
088
089    Scan s = new Scan();
090    s.setMaxResultSize(SCANNER_DATA_LIMIT);
091    ResultScanner rs = table.getScanner(s);
092    int count = 0;
093    while(rs.next() != null) {
094      count++;
095    }
096    assertEquals("Result size estimation did not work properly", 2, count);
097    rs.close();
098    table.close();
099  }
100
101  @Test
102  public void testResultSizeEstimationWithTags() throws Exception {
103    byte [] ROW1 = Bytes.toBytes("testRow1");
104    byte [] ROW2 = Bytes.toBytes("testRow2");
105    byte [] FAMILY = Bytes.toBytes("testFamily");
106    byte [] QUALIFIER = Bytes.toBytes("testQualifier");
107    byte [] VALUE = Bytes.toBytes("testValue");
108
109    final TableName tableName = TableName.valueOf(name.getMethodName());
110    byte[][] FAMILIES = new byte[][] { FAMILY };
111    Table table = TEST_UTIL.createTable(tableName, FAMILIES);
112    Put p = new Put(ROW1);
113    p.add(new KeyValue(ROW1, FAMILY, QUALIFIER, Long.MAX_VALUE, VALUE,
114      new Tag[] { new ArrayBackedTag((byte)1, new byte[TAG_DATA_SIZE]) }));
115    table.put(p);
116    p = new Put(ROW2);
117    p.add(new KeyValue(ROW2, FAMILY, QUALIFIER, Long.MAX_VALUE, VALUE,
118      new Tag[] { new ArrayBackedTag((byte)1, new byte[TAG_DATA_SIZE]) }));
119    table.put(p);
120
121    Scan s = new Scan();
122    s.setMaxResultSize(SCANNER_DATA_LIMIT);
123    ResultScanner rs = table.getScanner(s);
124    int count = 0;
125    while(rs.next() != null) {
126      count++;
127    }
128    assertEquals("Result size estimation did not work properly", 2, count);
129    rs.close();
130    table.close();
131  }
132}