1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.regionserver;
19
20 import java.util.List;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.classification.InterfaceStability;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
51 @InterfaceStability.Evolving
52 public class ScannerContext {
53 private final Log LOG = LogFactory.getLog(this.getClass());
54
55
56
57
58 LimitFields limits;
59 LimitFields progress;
60
61
62
63
64
65 NextState scannerState;
66 private static final NextState DEFAULT_STATE = NextState.MORE_VALUES;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 boolean keepProgress;
97 private static boolean DEFAULT_KEEP_PROGRESS = false;
98
99 ScannerContext(boolean keepProgress, LimitFields limitsToCopy) {
100 this.limits = new LimitFields();
101 if (limitsToCopy != null) this.limits.copy(limitsToCopy);
102
103
104 progress = new LimitFields(0, LimitFields.DEFAULT_SCOPE, 0, LimitFields.DEFAULT_SCOPE, 0);
105
106 this.keepProgress = keepProgress;
107 this.scannerState = DEFAULT_STATE;
108 }
109
110
111
112
113
114
115
116 boolean getKeepProgress() {
117 return keepProgress;
118 }
119
120 void setKeepProgress(boolean keepProgress) {
121 this.keepProgress = keepProgress;
122 }
123
124
125
126
127 void incrementBatchProgress(int batch) {
128 int currentBatch = progress.getBatch();
129 progress.setBatch(currentBatch + batch);
130 }
131
132
133
134
135 void incrementSizeProgress(long size) {
136 long currentSize = progress.getSize();
137 progress.setSize(currentSize + size);
138 }
139
140
141
142
143 void updateTimeProgress() {
144 progress.setTime(System.currentTimeMillis());
145 }
146
147 int getBatchProgress() {
148 return progress.getBatch();
149 }
150
151 long getSizeProgress() {
152 return progress.getSize();
153 }
154
155 long getTimeProgress() {
156 return progress.getTime();
157 }
158
159 void setProgress(int batchProgress, long sizeProgress, long timeProgress) {
160 setBatchProgress(batchProgress);
161 setSizeProgress(sizeProgress);
162 setTimeProgress(timeProgress);
163 }
164
165 void setSizeProgress(long sizeProgress) {
166 progress.setSize(sizeProgress);
167 }
168
169 void setBatchProgress(int batchProgress) {
170 progress.setBatch(batchProgress);
171 }
172
173 void setTimeProgress(long timeProgress) {
174 progress.setTime(timeProgress);
175 }
176
177
178
179
180
181 void clearProgress() {
182 progress.setFields(0, LimitFields.DEFAULT_SCOPE, 0, LimitFields.DEFAULT_SCOPE, 0);
183 }
184
185
186
187
188
189
190
191
192
193 NextState setScannerState(NextState state) {
194 if (!NextState.isValidState(state)) {
195 throw new IllegalArgumentException("Cannot set to invalid state: " + state);
196 }
197
198 this.scannerState = state;
199 return state;
200 }
201
202
203
204
205
206 boolean partialResultFormed() {
207 return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW
208 || scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW;
209 }
210
211
212
213
214
215 boolean hasBatchLimit(LimitScope checkerScope) {
216 return limits.canEnforceBatchLimitFromScope(checkerScope) && limits.getBatch() > 0;
217 }
218
219
220
221
222
223 boolean hasSizeLimit(LimitScope checkerScope) {
224 return limits.canEnforceSizeLimitFromScope(checkerScope) && limits.getSize() > 0;
225 }
226
227
228
229
230
231 boolean hasTimeLimit(LimitScope checkerScope) {
232 return limits.canEnforceTimeLimitFromScope(checkerScope) && limits.getTime() > 0;
233 }
234
235
236
237
238
239 boolean hasAnyLimit(LimitScope checkerScope) {
240 return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);
241 }
242
243
244
245
246 void setSizeLimitScope(LimitScope scope) {
247 limits.setSizeScope(scope);
248 }
249
250
251
252
253 void setTimeLimitScope(LimitScope scope) {
254 limits.setTimeScope(scope);
255 }
256
257 int getBatchLimit() {
258 return limits.getBatch();
259 }
260
261 long getSizeLimit() {
262 return limits.getSize();
263 }
264
265 long getTimeLimit() {
266 return limits.getTime();
267 }
268
269
270
271
272
273 boolean checkBatchLimit(LimitScope checkerScope) {
274 return hasBatchLimit(checkerScope) && progress.getBatch() >= limits.getBatch();
275 }
276
277
278
279
280
281 boolean checkSizeLimit(LimitScope checkerScope) {
282 return hasSizeLimit(checkerScope) && progress.getSize() >= limits.getSize();
283 }
284
285
286
287
288
289
290 boolean checkTimeLimit(LimitScope checkerScope) {
291 return hasTimeLimit(checkerScope) && progress.getTime() >= limits.getTime();
292 }
293
294
295
296
297
298 boolean checkAnyLimitReached(LimitScope checkerScope) {
299 return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)
300 || checkTimeLimit(checkerScope);
301 }
302
303 @Override
304 public String toString() {
305 StringBuilder sb = new StringBuilder();
306 sb.append("{");
307
308 sb.append("limits:");
309 sb.append(limits);
310
311 sb.append(", progress:");
312 sb.append(progress);
313
314 sb.append(", keepProgress:");
315 sb.append(keepProgress);
316
317 sb.append(", state:");
318 sb.append(scannerState);
319
320 sb.append("}");
321 return sb.toString();
322 }
323
324 public static Builder newBuilder() {
325 return new Builder();
326 }
327
328 public static Builder newBuilder(boolean keepProgress) {
329 return new Builder(keepProgress);
330 }
331
332 public static final class Builder {
333 boolean keepProgress = DEFAULT_KEEP_PROGRESS;
334 LimitFields limits = new LimitFields();
335
336 private Builder() {
337 }
338
339 private Builder(boolean keepProgress) {
340 this.keepProgress = keepProgress;
341 }
342
343 public Builder setKeepProgress(boolean keepProgress) {
344 this.keepProgress = keepProgress;
345 return this;
346 }
347
348 public Builder setSizeLimit(LimitScope sizeScope, long sizeLimit) {
349 limits.setSize(sizeLimit);
350 limits.setSizeScope(sizeScope);
351 return this;
352 }
353
354 public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {
355 limits.setTime(timeLimit);
356 limits.setTimeScope(timeScope);
357 return this;
358 }
359
360 public Builder setBatchLimit(int batchLimit) {
361 limits.setBatch(batchLimit);
362 return this;
363 }
364
365 public ScannerContext build() {
366 return new ScannerContext(keepProgress, limits);
367 }
368 }
369
370
371
372
373 public enum NextState {
374 MORE_VALUES(true, false),
375 NO_MORE_VALUES(false, false),
376 SIZE_LIMIT_REACHED(true, true),
377
378
379
380
381
382 SIZE_LIMIT_REACHED_MID_ROW(true, true),
383 TIME_LIMIT_REACHED(true, true),
384
385
386
387
388
389 TIME_LIMIT_REACHED_MID_ROW(true, true),
390 BATCH_LIMIT_REACHED(true, true);
391
392 private boolean moreValues;
393 private boolean limitReached;
394
395 private NextState(boolean moreValues, boolean limitReached) {
396 this.moreValues = moreValues;
397 this.limitReached = limitReached;
398 }
399
400
401
402
403
404 public boolean hasMoreValues() {
405 return this.moreValues;
406 }
407
408
409
410
411 public boolean limitReached() {
412 return this.limitReached;
413 }
414
415 public static boolean isValidState(NextState state) {
416 return state != null;
417 }
418
419 public static boolean hasMoreValues(NextState state) {
420 return isValidState(state) && state.hasMoreValues();
421 }
422 }
423
424
425
426
427
428 public enum LimitScope {
429
430
431
432
433 BETWEEN_ROWS(0),
434
435
436
437
438
439 BETWEEN_CELLS(1);
440
441
442
443
444
445
446
447
448
449 int depth;
450
451 LimitScope(int depth) {
452 this.depth = depth;
453 }
454
455 int depth() {
456 return depth;
457 }
458
459
460
461
462
463
464
465 boolean canEnforceLimitFromScope(LimitScope checkerScope) {
466 return checkerScope != null && checkerScope.depth() <= depth;
467 }
468 }
469
470
471
472
473
474 private static class LimitFields {
475
476
477
478
479 private static int DEFAULT_BATCH = -1;
480 private static long DEFAULT_SIZE = -1L;
481 private static long DEFAULT_TIME = -1L;
482
483
484
485
486 private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;
487
488
489
490 int batch = DEFAULT_BATCH;
491
492 LimitScope sizeScope = DEFAULT_SCOPE;
493 long size = DEFAULT_SIZE;
494
495 LimitScope timeScope = DEFAULT_SCOPE;
496 long time = DEFAULT_TIME;
497
498
499
500
501 LimitFields() {
502 }
503
504 LimitFields(int batch, LimitScope sizeScope, long size, LimitScope timeScope, long time) {
505 setFields(batch, sizeScope, size, timeScope, time);
506 }
507
508 void copy(LimitFields limitsToCopy) {
509 if (limitsToCopy != null) {
510 setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getSize(),
511 limitsToCopy.getTimeScope(), limitsToCopy.getTime());
512 }
513 }
514
515
516
517
518
519
520
521 void setFields(int batch, LimitScope sizeScope, long size, LimitScope timeScope, long time) {
522 setBatch(batch);
523 setSizeScope(sizeScope);
524 setSize(size);
525 setTimeScope(timeScope);
526 setTime(time);
527 }
528
529 int getBatch() {
530 return this.batch;
531 }
532
533 void setBatch(int batch) {
534 this.batch = batch;
535 }
536
537
538
539
540
541 boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {
542 return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);
543 }
544
545 long getSize() {
546 return this.size;
547 }
548
549 void setSize(long size) {
550 this.size = size;
551 }
552
553
554
555
556 LimitScope getSizeScope() {
557 return this.sizeScope;
558 }
559
560
561
562
563 void setSizeScope(LimitScope scope) {
564 this.sizeScope = scope;
565 }
566
567
568
569
570
571 boolean canEnforceSizeLimitFromScope(LimitScope checkerScope) {
572 return this.sizeScope.canEnforceLimitFromScope(checkerScope);
573 }
574
575 long getTime() {
576 return this.time;
577 }
578
579 void setTime(long time) {
580 this.time = time;
581 }
582
583
584
585
586 LimitScope getTimeScope() {
587 return this.timeScope;
588 }
589
590
591
592
593 void setTimeScope(LimitScope scope) {
594 this.timeScope = scope;
595 }
596
597
598
599
600
601 boolean canEnforceTimeLimitFromScope(LimitScope checkerScope) {
602 return this.sizeScope.canEnforceLimitFromScope(checkerScope);
603 }
604
605 @Override
606 public String toString() {
607 StringBuilder sb = new StringBuilder();
608 sb.append("{");
609
610 sb.append("batch:");
611 sb.append(batch);
612
613 sb.append(", size:");
614 sb.append(size);
615
616 sb.append(", sizeScope:");
617 sb.append(sizeScope);
618
619 sb.append(", time:");
620 sb.append(time);
621
622 sb.append(", timeScope:");
623 sb.append(timeScope);
624
625 sb.append("}");
626 return sb.toString();
627 }
628 }
629 }