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