1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.filter;
19
20 import static org.junit.Assert.*;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.hbase.HBaseTestingUtility;
33 import org.apache.hadoop.hbase.HColumnDescriptor;
34 import org.apache.hadoop.hbase.HRegionInfo;
35 import org.apache.hadoop.hbase.HTableDescriptor;
36 import org.apache.hadoop.hbase.KeyValue;
37 import org.apache.hadoop.hbase.KeyValueTestUtil;
38 import org.apache.hadoop.hbase.client.HTable;
39 import org.apache.hadoop.hbase.client.Put;
40 import org.apache.hadoop.hbase.client.Result;
41 import org.apache.hadoop.hbase.client.ResultScanner;
42 import org.apache.hadoop.hbase.client.Scan;
43 import org.apache.hadoop.hbase.regionserver.HRegion;
44 import org.apache.hadoop.hbase.regionserver.InternalScanner;
45 import org.apache.hadoop.hbase.util.Bytes;
46 import org.junit.Test;
47 import org.junit.After;
48 import org.junit.AfterClass;
49 import org.junit.Before;
50 import org.junit.BeforeClass;
51
52 class StringRange {
53 private String start = null;
54 private String end = null;
55 private boolean startInclusive = true;
56 private boolean endInclusive = false;
57
58 public StringRange(String start, boolean startInclusive, String end,
59 boolean endInclusive) {
60 this.start = start;
61 this.startInclusive = startInclusive;
62 this.end = end;
63 this.endInclusive = endInclusive;
64 }
65
66 public String getStart() {
67 return this.start;
68 }
69
70 public String getEnd() {
71 return this.end;
72 }
73
74 public boolean isStartInclusive() {
75 return this.startInclusive;
76 }
77
78 public boolean isEndInclusive() {
79 return this.endInclusive;
80 }
81
82 @Override
83 public int hashCode() {
84 int hashCode = 0;
85 if (this.start != null) {
86 hashCode ^= this.start.hashCode();
87 }
88
89 if (this.end != null) {
90 hashCode ^= this.end.hashCode();
91 }
92 return hashCode;
93 }
94
95 @Override
96 public String toString() {
97 String result = (this.startInclusive ? "[" : "(")
98 + (this.start == null ? null : this.start) + ", "
99 + (this.end == null ? null : this.end)
100 + (this.endInclusive ? "]" : ")");
101 return result;
102 }
103
104 public boolean inRange(String value) {
105 boolean afterStart = true;
106 if (this.start != null) {
107 int startCmp = value.compareTo(this.start);
108 afterStart = this.startInclusive ? startCmp >= 0 : startCmp > 0;
109 }
110
111 boolean beforeEnd = true;
112 if (this.end != null) {
113 int endCmp = value.compareTo(this.end);
114 beforeEnd = this.endInclusive ? endCmp <= 0 : endCmp < 0;
115 }
116
117 return afterStart && beforeEnd;
118 }
119 }
120
121 public class TestColumnRangeFilter {
122
123 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
124
125 private final Log LOG = LogFactory.getLog(this.getClass());
126
127
128
129
130 @BeforeClass
131 public static void setUpBeforeClass() throws Exception {
132 TEST_UTIL.startMiniCluster();
133 }
134
135
136
137
138 @AfterClass
139 public static void tearDownAfterClass() throws Exception {
140 TEST_UTIL.shutdownMiniCluster();
141 }
142
143
144
145
146 @Before
147 public void setUp() throws Exception {
148
149 }
150
151
152
153
154 @After
155 public void tearDown() throws Exception {
156
157 }
158
159 @Test
160 public void TestColumnRangeFilterClient() throws Exception {
161 String family = "Family";
162 String table = "TestColumnRangeFilterClient";
163 HTable ht = TEST_UTIL.createTable(Bytes.toBytes(table),
164 Bytes.toBytes(family), Integer.MAX_VALUE);
165
166 List<String> rows = generateRandomWords(10, 8);
167 long maxTimestamp = 2;
168 List<String> columns = generateRandomWords(20000, 8);
169
170 List<KeyValue> kvList = new ArrayList<KeyValue>();
171
172 Map<StringRange, List<KeyValue>> rangeMap = new HashMap<StringRange, List<KeyValue>>();
173
174 rangeMap.put(new StringRange(null, true, "b", false),
175 new ArrayList<KeyValue>());
176 rangeMap.put(new StringRange("p", true, "q", false),
177 new ArrayList<KeyValue>());
178 rangeMap.put(new StringRange("r", false, "s", true),
179 new ArrayList<KeyValue>());
180 rangeMap.put(new StringRange("z", false, null, false),
181 new ArrayList<KeyValue>());
182 String valueString = "ValueString";
183
184 for (String row : rows) {
185 Put p = new Put(Bytes.toBytes(row));
186 p.setWriteToWAL(false);
187 for (String column : columns) {
188 for (long timestamp = 1; timestamp <= maxTimestamp; timestamp++) {
189 KeyValue kv = KeyValueTestUtil.create(row, family, column, timestamp,
190 valueString);
191 p.add(kv);
192 kvList.add(kv);
193 for (StringRange s : rangeMap.keySet()) {
194 if (s.inRange(column)) {
195 rangeMap.get(s).add(kv);
196 }
197 }
198 }
199 }
200 ht.put(p);
201 }
202
203 TEST_UTIL.flush();
204
205 ColumnRangeFilter filter;
206 Scan scan = new Scan();
207 scan.setMaxVersions();
208 for (StringRange s : rangeMap.keySet()) {
209 filter = new ColumnRangeFilter(s.getStart() == null ? null
210 : Bytes.toBytes(s.getStart()), s.isStartInclusive(),
211 s.getEnd() == null ? null : Bytes.toBytes(s.getEnd()),
212 s.isEndInclusive());
213 scan.setFilter(filter);
214 ResultScanner scanner = ht.getScanner(scan);
215 List<KeyValue> results = new ArrayList<KeyValue>();
216 LOG.info("scan column range: " + s.toString());
217 long timeBeforeScan = System.currentTimeMillis();
218
219 Result result;
220 while ((result = scanner.next()) != null) {
221 for (KeyValue kv : result.list()) {
222 results.add(kv);
223 }
224 }
225 long scanTime = System.currentTimeMillis() - timeBeforeScan;
226 LOG.info("scan time = " + scanTime + "ms");
227 LOG.info("found " + results.size() + " results");
228 LOG.info("Expecting " + rangeMap.get(s).size() + " results");
229
230
231
232
233
234
235
236
237 assertEquals(rangeMap.get(s).size(), results.size());
238 }
239 }
240
241 List<String> generateRandomWords(int numberOfWords, int maxLengthOfWords) {
242 Set<String> wordSet = new HashSet<String>();
243 for (int i = 0; i < numberOfWords; i++) {
244 int lengthOfWords = (int) (Math.random() * maxLengthOfWords) + 1;
245 char[] wordChar = new char[lengthOfWords];
246 for (int j = 0; j < wordChar.length; j++) {
247 wordChar[j] = (char) (Math.random() * 26 + 97);
248 }
249 String word = new String(wordChar);
250 wordSet.add(word);
251 }
252 List<String> wordList = new ArrayList<String>(wordSet);
253 return wordList;
254 }
255 }