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