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.assertEquals; 021 022import java.io.IOException; 023import java.nio.ByteBuffer; 024import java.util.ArrayList; 025import java.util.List; 026import org.apache.hadoop.hbase.Cell; 027import org.apache.hadoop.hbase.CellUtil; 028import org.apache.hadoop.hbase.HBaseTestingUtil; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.client.Durability; 031import org.apache.hadoop.hbase.client.Put; 032import org.apache.hadoop.hbase.client.Result; 033import org.apache.hadoop.hbase.client.ResultScanner; 034import org.apache.hadoop.hbase.client.Scan; 035import org.apache.hadoop.hbase.client.Table; 036import org.apache.hadoop.hbase.testclassification.FilterTests; 037import org.apache.hadoop.hbase.testclassification.MediumTests; 038import org.apache.hadoop.hbase.util.Bytes; 039import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 040import org.apache.hadoop.hbase.util.Pair; 041import org.junit.jupiter.api.AfterAll; 042import org.junit.jupiter.api.BeforeAll; 043import org.junit.jupiter.api.Tag; 044import org.junit.jupiter.api.Test; 045import org.junit.jupiter.api.TestInfo; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 050 051@Tag(FilterTests.TAG) 052@Tag(MediumTests.TAG) 053public class TestFuzzyRowAndColumnRangeFilter { 054 055 private final static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 056 private static final Logger LOG = LoggerFactory.getLogger(TestFuzzyRowAndColumnRangeFilter.class); 057 058 /** 059 * @throws java.lang.Exception 060 */ 061 @BeforeAll 062 public static void setUpBeforeClass() throws Exception { 063 TEST_UTIL.startMiniCluster(); 064 } 065 066 /** 067 * @throws java.lang.Exception 068 */ 069 @AfterAll 070 public static void tearDownAfterClass() throws Exception { 071 TEST_UTIL.shutdownMiniCluster(); 072 } 073 074 @Test 075 public void Test(TestInfo testInfo) throws Exception { 076 String cf = "f"; 077 Table ht = TEST_UTIL.createTable(TableName.valueOf(testInfo.getTestMethod().get().getName()), 078 Bytes.toBytes(cf), Integer.MAX_VALUE); 079 080 // 10 byte row key - (2 bytes 4 bytes 4 bytes) 081 // 4 byte qualifier 082 // 4 byte value 083 084 for (int i1 = 0; i1 < 2; i1++) { 085 for (int i2 = 0; i2 < 5; i2++) { 086 byte[] rk = new byte[10]; 087 088 ByteBuffer buf = ByteBuffer.wrap(rk); 089 buf.clear(); 090 buf.putShort((short) 2); 091 buf.putInt(i1); 092 buf.putInt(i2); 093 094 for (int c = 0; c < 5; c++) { 095 byte[] cq = new byte[4]; 096 Bytes.putBytes(cq, 0, Bytes.toBytes(c), 0, 4); 097 098 Put p = new Put(rk); 099 p.setDurability(Durability.SKIP_WAL); 100 p.addColumn(Bytes.toBytes(cf), cq, Bytes.toBytes(c)); 101 ht.put(p); 102 LOG.info( 103 "Inserting: rk: " + Bytes.toStringBinary(rk) + " cq: " + Bytes.toStringBinary(cq)); 104 } 105 } 106 } 107 108 TEST_UTIL.flush(); 109 110 // test passes 111 runTest(ht, 0, 10); 112 113 // test fails 114 runTest(ht, 1, 8); 115 } 116 117 private void runTest(Table hTable, int cqStart, int expectedSize) throws IOException { 118 // [0, 2, ?, ?, ?, ?, 0, 0, 0, 1] 119 byte[] fuzzyKey = new byte[10]; 120 ByteBuffer buf = ByteBuffer.wrap(fuzzyKey); 121 buf.clear(); 122 buf.putShort((short) 2); 123 for (int i = 0; i < 4; i++) 124 buf.put((byte) 63); 125 buf.putInt((short) 1); 126 127 byte[] mask = new byte[] { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 }; 128 129 Pair<byte[], byte[]> pair = new Pair<>(fuzzyKey, mask); 130 FuzzyRowFilter fuzzyRowFilter = new FuzzyRowFilter(Lists.newArrayList(pair)); 131 ColumnRangeFilter columnRangeFilter = 132 new ColumnRangeFilter(Bytes.toBytes(cqStart), true, Bytes.toBytes(4), true); 133 // regular test 134 runScanner(hTable, expectedSize, fuzzyRowFilter, columnRangeFilter); 135 // reverse filter order test 136 runScanner(hTable, expectedSize, columnRangeFilter, fuzzyRowFilter); 137 } 138 139 private void runScanner(Table hTable, int expectedSize, Filter... filters) throws IOException { 140 String cf = "f"; 141 Scan scan = new Scan(); 142 scan.addFamily(Bytes.toBytes(cf)); 143 FilterList filterList = new FilterList(filters); 144 scan.setFilter(filterList); 145 146 ResultScanner scanner = hTable.getScanner(scan); 147 List<Cell> results = new ArrayList<>(); 148 Result result; 149 long timeBeforeScan = EnvironmentEdgeManager.currentTime(); 150 while ((result = scanner.next()) != null) { 151 for (Cell kv : result.listCells()) { 152 LOG.info("Got rk: " + Bytes.toStringBinary(CellUtil.cloneRow(kv)) + " cq: " 153 + Bytes.toStringBinary(CellUtil.cloneQualifier(kv))); 154 results.add(kv); 155 } 156 } 157 long scanTime = EnvironmentEdgeManager.currentTime() - timeBeforeScan; 158 scanner.close(); 159 160 LOG.info("scan time = " + scanTime + "ms"); 161 LOG.info("found " + results.size() + " results"); 162 163 assertEquals(expectedSize, results.size()); 164 } 165}