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