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.filter; 019 020import static org.junit.Assert.assertArrayEquals; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertFalse; 023 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.List; 027import org.apache.hadoop.hbase.Cell; 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HBaseTestingUtility; 030import org.apache.hadoop.hbase.HColumnDescriptor; 031import org.apache.hadoop.hbase.HRegionInfo; 032import org.apache.hadoop.hbase.HTableDescriptor; 033import org.apache.hadoop.hbase.HTestConst; 034import org.apache.hadoop.hbase.KeyValue; 035import org.apache.hadoop.hbase.TableName; 036import org.apache.hadoop.hbase.client.Put; 037import org.apache.hadoop.hbase.client.Scan; 038import org.apache.hadoop.hbase.regionserver.HRegion; 039import org.apache.hadoop.hbase.regionserver.InternalScanner; 040import org.apache.hadoop.hbase.testclassification.SmallTests; 041import org.apache.hadoop.hbase.util.Bytes; 042import org.junit.AfterClass; 043import org.junit.BeforeClass; 044import org.junit.ClassRule; 045import org.junit.Test; 046import org.junit.experimental.categories.Category; 047 048/** 049 * To test behavior of filters at server from region side. 050 */ 051@Category(SmallTests.class) 052public class TestFilterFromRegionSide { 053 054 @ClassRule 055 public static final HBaseClassTestRule CLASS_RULE = 056 HBaseClassTestRule.forClass(TestFilterFromRegionSide.class); 057 058 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 059 private static HRegion REGION; 060 061 private static TableName TABLE_NAME = TableName.valueOf("TestFilterFromRegionSide"); 062 063 private static int NUM_ROWS = 5; 064 private static byte[] ROW = Bytes.toBytes("testRow"); 065 private static byte[][] ROWS = HTestConst.makeNAscii(ROW, NUM_ROWS); 066 067 // Should keep this value below 10 to keep generation of expected kv's simple. If above 10 then 068 // table/row/cf1/... will be followed by table/row/cf10/... instead of table/row/cf2/... which 069 // breaks the simple generation of expected kv's 070 private static int NUM_FAMILIES = 5; 071 private static byte[] FAMILY = Bytes.toBytes("testFamily"); 072 private static byte[][] FAMILIES = HTestConst.makeNAscii(FAMILY, NUM_FAMILIES); 073 074 private static int NUM_QUALIFIERS = 5; 075 private static byte[] QUALIFIER = Bytes.toBytes("testQualifier"); 076 private static byte[][] QUALIFIERS = HTestConst.makeNAscii(QUALIFIER, NUM_QUALIFIERS); 077 078 private static int VALUE_SIZE = 1024; 079 private static byte[] VALUE = Bytes.createMaxByteArray(VALUE_SIZE); 080 081 private static int NUM_COLS = NUM_FAMILIES * NUM_QUALIFIERS; 082 083 @BeforeClass 084 public static void setUpBeforeClass() throws Exception { 085 HTableDescriptor htd = new HTableDescriptor(TABLE_NAME); 086 for (byte[] family : FAMILIES) { 087 HColumnDescriptor hcd = new HColumnDescriptor(family); 088 htd.addFamily(hcd); 089 } 090 HRegionInfo info = new HRegionInfo(htd.getTableName(), null, null, false); 091 REGION = HBaseTestingUtility 092 .createRegionAndWAL(info, TEST_UTIL.getDataTestDir(), TEST_UTIL.getConfiguration(), htd); 093 for(Put put:createPuts(ROWS, FAMILIES, QUALIFIERS, VALUE)){ 094 REGION.put(put); 095 } 096 } 097 098 private static ArrayList<Put> createPuts(byte[][] rows, byte[][] families, byte[][] qualifiers, 099 byte[] value) throws IOException { 100 Put put; 101 ArrayList<Put> puts = new ArrayList<>(); 102 103 for (byte[] row1 : rows) { 104 put = new Put(row1); 105 for (byte[] family : families) { 106 for (int qual = 0; qual < qualifiers.length; qual++) { 107 KeyValue kv = new KeyValue(row1, family, qualifiers[qual], qual, value); 108 put.add(kv); 109 } 110 } 111 puts.add(put); 112 } 113 114 return puts; 115 } 116 117 @AfterClass 118 public static void tearDownAfterClass() throws Exception { 119 REGION.close(); 120 } 121 122 @Test 123 public void testFirstKeyOnlyFilterAndBatch() throws IOException { 124 Scan scan = new Scan(); 125 scan.setFilter(new FirstKeyOnlyFilter()); 126 scan.setBatch(1); 127 InternalScanner scanner = REGION.getScanner(scan); 128 List<Cell> results = new ArrayList<>(); 129 for (int i = 0; i < NUM_ROWS; i++) { 130 results.clear(); 131 scanner.next(results); 132 assertEquals(1, results.size()); 133 Cell cell = results.get(0); 134 assertArrayEquals(ROWS[i], 135 Bytes.copy(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength())); 136 } 137 assertFalse(scanner.next(results)); 138 scanner.close(); 139 } 140 141 public static class FirstSeveralCellsFilter extends FilterBase{ 142 private int count = 0; 143 144 @Override 145 public void reset() { 146 count = 0; 147 } 148 149 @Override 150 public boolean filterRowKey(Cell cell) throws IOException { 151 return false; 152 } 153 154 @Override 155 public ReturnCode filterCell(final Cell v) { 156 if (count++ < NUM_COLS) { 157 return ReturnCode.INCLUDE; 158 } 159 return ReturnCode.SKIP; 160 } 161 162 public static Filter parseFrom(final byte [] pbBytes){ 163 return new FirstSeveralCellsFilter(); 164 } 165 } 166 167 @Test 168 public void testFirstSeveralCellsFilterAndBatch() throws IOException { 169 Scan scan = new Scan(); 170 scan.setFilter(new FirstSeveralCellsFilter()); 171 scan.setBatch(NUM_COLS); 172 InternalScanner scanner = REGION.getScanner(scan); 173 List<Cell> results = new ArrayList<>(); 174 for (int i = 0; i < NUM_ROWS; i++) { 175 results.clear(); 176 scanner.next(results); 177 assertEquals(NUM_COLS, results.size()); 178 Cell cell = results.get(0); 179 assertArrayEquals(ROWS[i], 180 Bytes.copy(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength())); 181 assertArrayEquals(FAMILIES[0], 182 Bytes.copy(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength())); 183 assertArrayEquals(QUALIFIERS[0], Bytes.copy(cell.getQualifierArray(), 184 cell.getQualifierOffset(), cell.getQualifierLength())); 185 } 186 assertFalse(scanner.next(results)); 187 scanner.close(); 188 } 189}