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