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