1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.codec.prefixtree.decode;
20
21 import org.apache.hadoop.classification.InterfaceAudience;
22 import org.apache.hadoop.hbase.Cell;
23 import org.apache.hadoop.hbase.CellUtil;
24 import org.apache.hadoop.hbase.codec.prefixtree.PrefixTreeBlockMeta;
25 import org.apache.hadoop.hbase.codec.prefixtree.scanner.CellScannerPosition;
26 import org.apache.hadoop.hbase.codec.prefixtree.scanner.CellSearcher;
27
28 import com.google.common.primitives.UnsignedBytes;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 @InterfaceAudience.Private
45 public class PrefixTreeArraySearcher extends PrefixTreeArrayReversibleScanner implements
46 CellSearcher {
47
48
49
50 public PrefixTreeArraySearcher(PrefixTreeBlockMeta blockMeta, int rowTreeDepth,
51 int rowBufferLength, int qualifierBufferLength) {
52 super(blockMeta, rowTreeDepth, rowBufferLength, qualifierBufferLength);
53 }
54
55
56
57
58 @Override
59 public boolean positionAt(Cell key) {
60 return CellScannerPosition.AT == positionAtOrAfter(key);
61 }
62
63 @Override
64 public CellScannerPosition positionAtOrBefore(Cell key) {
65 reInitFirstNode();
66 int fanIndex = -1;
67
68 while(true){
69
70 int currentNodeDepth = rowLength;
71 int rowTokenComparison = compareToCurrentToken(key);
72 if(rowTokenComparison != 0){
73 return fixRowTokenMissReverse(rowTokenComparison);
74 }
75
76
77 if(rowMatchesAfterCurrentPosition(key)){
78 return positionAtQualifierTimestamp(key, true);
79 }
80
81
82 if(!currentRowNode.hasFan()){
83 if(hasOccurrences()){
84 populateLastNonRowFields();
85 return CellScannerPosition.BEFORE;
86 }else{
87
88 return fixRowFanMissReverse(0);
89 }
90 }
91
92
93 byte searchForByte = CellUtil.getRowByte(key, currentNodeDepth);
94 fanIndex = currentRowNode.whichFanNode(searchForByte);
95 if(fanIndex < 0){
96 int insertionPoint = -fanIndex;
97 return fixRowFanMissReverse(insertionPoint);
98 }
99
100 followFan(fanIndex);
101 }
102 }
103
104
105
106
107
108 @Override
109 public CellScannerPosition positionAtOrAfter(Cell key) {
110 reInitFirstNode();
111 int fanIndex = -1;
112
113 while(true){
114
115 int currentNodeDepth = rowLength;
116 int rowTokenComparison = compareToCurrentToken(key);
117 if(rowTokenComparison != 0){
118 return fixRowTokenMissForward(rowTokenComparison);
119 }
120
121
122 if(rowMatchesAfterCurrentPosition(key)){
123 return positionAtQualifierTimestamp(key, false);
124 }
125
126
127 if(!currentRowNode.hasFan()){
128 if(hasOccurrences()){
129 populateFirstNonRowFields();
130 return CellScannerPosition.AFTER;
131 }else{
132
133 return fixRowFanMissForward(0);
134 }
135 }
136
137
138 byte searchForByte = CellUtil.getRowByte(key, currentNodeDepth);
139 fanIndex = currentRowNode.whichFanNode(searchForByte);
140 if(fanIndex < 0){
141 int insertionPoint = -fanIndex;
142 return fixRowFanMissForward(insertionPoint);
143 }
144
145 followFan(fanIndex);
146 }
147 }
148
149 @Override
150 public boolean seekForwardTo(Cell key) {
151 if(currentPositionIsAfter(key)){
152
153 return false;
154 }
155 return positionAt(key);
156 }
157
158 @Override
159 public CellScannerPosition seekForwardToOrBefore(Cell key) {
160
161
162 if(currentPositionIsAfter(key)){
163
164 return CellScannerPosition.AFTER;
165 }
166
167 return positionAtOrBefore(key);
168 }
169
170 @Override
171 public CellScannerPosition seekForwardToOrAfter(Cell key) {
172
173
174 if(currentPositionIsAfter(key)){
175
176 return CellScannerPosition.AFTER;
177 }
178
179 return positionAtOrAfter(key);
180 }
181
182
183
184
185 @Override
186 public void positionAfterLastCell() {
187 resetToBeforeFirstEntry();
188 beforeFirst = false;
189 afterLast = true;
190 }
191
192
193
194
195 @Override
196 public boolean equals(Object obj) {
197
198 return super.equals(obj);
199 }
200
201
202
203
204 protected boolean currentPositionIsAfter(Cell cell){
205 return compareTo(cell) > 0;
206 }
207
208 protected CellScannerPosition positionAtQualifierTimestamp(Cell key, boolean beforeOnMiss) {
209 int minIndex = 0;
210 int maxIndex = currentRowNode.getLastCellIndex();
211 int diff;
212 while (true) {
213 int midIndex = (maxIndex + minIndex) / 2;
214 diff = populateNonRowFieldsAndCompareTo(midIndex, key);
215
216 if (diff == 0) {
217 return CellScannerPosition.AT;
218 } else if (minIndex == maxIndex) {
219 break;
220 } else if ((minIndex + 1) == maxIndex) {
221 diff = populateNonRowFieldsAndCompareTo(maxIndex, key);
222 if(diff > 0){
223 diff = populateNonRowFieldsAndCompareTo(minIndex, key);
224 }
225 break;
226 } else if (diff < 0) {
227 minIndex = currentCellIndex;
228 } else {
229 maxIndex = currentCellIndex;
230 }
231 }
232
233 if (diff == 0) {
234 return CellScannerPosition.AT;
235
236 } else if (diff < 0) {
237 if (beforeOnMiss) {
238 return CellScannerPosition.BEFORE;
239 }
240 if (advance()) {
241 return CellScannerPosition.AFTER;
242 }
243 return CellScannerPosition.AFTER_LAST;
244
245 } else {
246 if (!beforeOnMiss) {
247 return CellScannerPosition.AFTER;
248 }
249 if (previous()) {
250 return CellScannerPosition.BEFORE;
251 }
252 return CellScannerPosition.BEFORE_FIRST;
253 }
254 }
255
256
257
258
259
260
261 protected boolean rowMatchesAfterCurrentPosition(Cell key) {
262 if (!currentRowNode.hasOccurrences()) {
263 return false;
264 }
265 int thatRowLength = key.getRowLength();
266 if (rowLength != thatRowLength) {
267 return false;
268 }
269 return true;
270 }
271
272
273
274
275
276
277
278 protected int compareToCurrentToken(Cell key) {
279 int startIndex = rowLength - currentRowNode.getTokenLength();
280 int endIndexExclusive = startIndex + currentRowNode.getTokenLength();
281 for (int i = startIndex; i < endIndexExclusive; ++i) {
282 if (i >= key.getRowLength()) {
283 return -1;
284 }
285 byte keyByte = CellUtil.getRowByte(key, i);
286 byte thisByte = rowBuffer[i];
287 if (keyByte == thisByte) {
288 continue;
289 }
290 return UnsignedBytes.compare(keyByte, thisByte);
291 }
292 return 0;
293 }
294
295 protected void followLastFansUntilExhausted(){
296 while(currentRowNode.hasFan()){
297 followLastFan();
298 }
299 }
300
301
302
303
304
305
306
307
308 protected CellScannerPosition fixRowTokenMissReverse(int searcherIsAfterInputKey) {
309 if (searcherIsAfterInputKey < 0) {
310 boolean foundPreviousRow = previousRow(true);
311 if(foundPreviousRow){
312 populateLastNonRowFields();
313 return CellScannerPosition.BEFORE;
314 }else{
315 return CellScannerPosition.BEFORE_FIRST;
316 }
317
318 }else{
319 if(currentRowNode.hasOccurrences()){
320 populateFirstNonRowFields();
321 return CellScannerPosition.BEFORE;
322 }
323 boolean foundNextRow = nextRow();
324 if(foundNextRow){
325 return CellScannerPosition.AFTER;
326 }else{
327 return CellScannerPosition.AFTER_LAST;
328 }
329 }
330 }
331
332
333
334
335
336 protected CellScannerPosition fixRowTokenMissForward(int searcherIsAfterInputKey) {
337 if (searcherIsAfterInputKey < 0) {
338 if(currentRowNode.hasOccurrences()){
339 populateFirstNonRowFields();
340 return CellScannerPosition.AFTER;
341 }
342 boolean foundNextRow = nextRow();
343 if(foundNextRow){
344 return CellScannerPosition.AFTER;
345 }else{
346 return CellScannerPosition.AFTER_LAST;
347 }
348
349 }else{
350 discardCurrentRowNode(true);
351 boolean foundNextRow = nextRow();
352 if(foundNextRow){
353 return CellScannerPosition.AFTER;
354 }else{
355 return CellScannerPosition.AFTER_LAST;
356 }
357 }
358 }
359
360
361
362
363 protected CellScannerPosition fixRowFanMissReverse(int fanInsertionPoint){
364 if(fanInsertionPoint == 0){
365 boolean foundPreviousRow = previousRow(true);
366 if(foundPreviousRow){
367 populateLastNonRowFields();
368 return CellScannerPosition.BEFORE;
369 }
370 return CellScannerPosition.BEFORE_FIRST;
371 }
372
373
374 followFan(fanInsertionPoint - 1);
375 followLastFansUntilExhausted();
376 populateLastNonRowFields();
377 return CellScannerPosition.BEFORE;
378 }
379
380 protected CellScannerPosition fixRowFanMissForward(int fanInsertionPoint){
381 if(fanInsertionPoint >= currentRowNode.getFanOut()){
382 discardCurrentRowNode(true);
383 if (!nextRow()) {
384 return CellScannerPosition.AFTER_LAST;
385 } else {
386 return CellScannerPosition.AFTER;
387 }
388 }
389
390 followFan(fanInsertionPoint);
391 if(hasOccurrences()){
392 populateFirstNonRowFields();
393 return CellScannerPosition.AFTER;
394 }
395
396 if(nextRowInternal()){
397 populateFirstNonRowFields();
398 return CellScannerPosition.AFTER;
399
400 }else{
401 return CellScannerPosition.AFTER_LAST;
402 }
403 }
404
405 }