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 boolean midRowResultFormed() {
215 return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW
216 || scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW
217 || scannerState == NextState.BATCH_LIMIT_REACHED;
218 }
219
220
221
222
223
224 boolean hasBatchLimit(LimitScope checkerScope) {
225 return limits.canEnforceBatchLimitFromScope(checkerScope) && limits.getBatch() > 0;
226 }
227
228
229
230
231
232 boolean hasSizeLimit(LimitScope checkerScope) {
233 return limits.canEnforceSizeLimitFromScope(checkerScope) && limits.getSize() > 0;
234 }
235
236
237
238
239
240 boolean hasTimeLimit(LimitScope checkerScope) {
241 return limits.canEnforceTimeLimitFromScope(checkerScope) && limits.getTime() > 0;
242 }
243
244
245
246
247
248 boolean hasAnyLimit(LimitScope checkerScope) {
249 return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);
250 }
251
252
253
254
255 void setSizeLimitScope(LimitScope scope) {
256 limits.setSizeScope(scope);
257 }
258
259
260
261
262 void setTimeLimitScope(LimitScope scope) {
263 limits.setTimeScope(scope);
264 }
265
266 int getBatchLimit() {
267 return limits.getBatch();
268 }
269
270 long getSizeLimit() {
271 return limits.getSize();
272 }
273
274 long getTimeLimit() {
275 return limits.getTime();
276 }
277
278
279
280
281
282 boolean checkBatchLimit(LimitScope checkerScope) {
283 return hasBatchLimit(checkerScope) && progress.getBatch() >= limits.getBatch();
284 }
285
286
287
288
289
290 boolean checkSizeLimit(LimitScope checkerScope) {
291 return hasSizeLimit(checkerScope) && progress.getSize() >= limits.getSize();
292 }
293
294
295
296
297
298
299 boolean checkTimeLimit(LimitScope checkerScope) {
300 return hasTimeLimit(checkerScope) && progress.getTime() >= limits.getTime();
301 }
302
303
304
305
306
307 boolean checkAnyLimitReached(LimitScope checkerScope) {
308 return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)
309 || checkTimeLimit(checkerScope);
310 }
311
312 @Override
313 public String toString() {
314 StringBuilder sb = new StringBuilder();
315 sb.append("{");
316
317 sb.append("limits:");
318 sb.append(limits);
319
320 sb.append(", progress:");
321 sb.append(progress);
322
323 sb.append(", keepProgress:");
324 sb.append(keepProgress);
325
326 sb.append(", state:");
327 sb.append(scannerState);
328
329 sb.append("}");
330 return sb.toString();
331 }
332
333 public static Builder newBuilder() {
334 return new Builder();
335 }
336
337 public static Builder newBuilder(boolean keepProgress) {
338 return new Builder(keepProgress);
339 }
340
341 public static final class Builder {
342 boolean keepProgress = DEFAULT_KEEP_PROGRESS;
343 LimitFields limits = new LimitFields();
344
345 private Builder() {
346 }
347
348 private Builder(boolean keepProgress) {
349 this.keepProgress = keepProgress;
350 }
351
352 public Builder setKeepProgress(boolean keepProgress) {
353 this.keepProgress = keepProgress;
354 return this;
355 }
356
357 public Builder setSizeLimit(LimitScope sizeScope, long sizeLimit) {
358 limits.setSize(sizeLimit);
359 limits.setSizeScope(sizeScope);
360 return this;
361 }
362
363 public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {
364 limits.setTime(timeLimit);
365 limits.setTimeScope(timeScope);
366 return this;
367 }
368
369 public Builder setBatchLimit(int batchLimit) {
370 limits.setBatch(batchLimit);
371 return this;
372 }
373
374 public ScannerContext build() {
375 return new ScannerContext(keepProgress, limits);
376 }
377 }
378
379
380
381
382 public enum NextState {
383 MORE_VALUES(true, false),
384 NO_MORE_VALUES(false, false),
385 SIZE_LIMIT_REACHED(true, true),
386
387
388
389
390
391 SIZE_LIMIT_REACHED_MID_ROW(true, true),
392 TIME_LIMIT_REACHED(true, true),
393
394
395
396
397
398 TIME_LIMIT_REACHED_MID_ROW(true, true),
399 BATCH_LIMIT_REACHED(true, true);
400
401 private boolean moreValues;
402 private boolean limitReached;
403
404 private NextState(boolean moreValues, boolean limitReached) {
405 this.moreValues = moreValues;
406 this.limitReached = limitReached;
407 }
408
409
410
411
412
413 public boolean hasMoreValues() {
414 return this.moreValues;
415 }
416
417
418
419
420 public boolean limitReached() {
421 return this.limitReached;
422 }
423
424 public static boolean isValidState(NextState state) {
425 return state != null;
426 }
427
428 public static boolean hasMoreValues(NextState state) {
429 return isValidState(state) && state.hasMoreValues();
430 }
431 }
432
433
434
435
436
437 public enum LimitScope {
438
439
440
441
442 BETWEEN_ROWS(0),
443
444
445
446
447
448 BETWEEN_CELLS(1);
449
450
451
452
453
454
455
456
457
458 int depth;
459
460 LimitScope(int depth) {
461 this.depth = depth;
462 }
463
464 int depth() {
465 return depth;
466 }
467
468
469
470
471
472
473
474 boolean canEnforceLimitFromScope(LimitScope checkerScope) {
475 return checkerScope != null && checkerScope.depth() <= depth;
476 }
477 }
478
479
480
481
482
483 private static class LimitFields {
484
485
486
487
488 private static int DEFAULT_BATCH = -1;
489 private static long DEFAULT_SIZE = -1L;
490 private static long DEFAULT_TIME = -1L;
491
492
493
494
495 private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;
496
497
498
499 int batch = DEFAULT_BATCH;
500
501 LimitScope sizeScope = DEFAULT_SCOPE;
502 long size = DEFAULT_SIZE;
503
504 LimitScope timeScope = DEFAULT_SCOPE;
505 long time = DEFAULT_TIME;
506
507
508
509
510 LimitFields() {
511 }
512
513 LimitFields(int batch, LimitScope sizeScope, long size, LimitScope timeScope, long time) {
514 setFields(batch, sizeScope, size, timeScope, time);
515 }
516
517 void copy(LimitFields limitsToCopy) {
518 if (limitsToCopy != null) {
519 setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getSize(),
520 limitsToCopy.getTimeScope(), limitsToCopy.getTime());
521 }
522 }
523
524
525
526
527
528
529
530 void setFields(int batch, LimitScope sizeScope, long size, LimitScope timeScope, long time) {
531 setBatch(batch);
532 setSizeScope(sizeScope);
533 setSize(size);
534 setTimeScope(timeScope);
535 setTime(time);
536 }
537
538 int getBatch() {
539 return this.batch;
540 }
541
542 void setBatch(int batch) {
543 this.batch = batch;
544 }
545
546
547
548
549
550 boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {
551 return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);
552 }
553
554 long getSize() {
555 return this.size;
556 }
557
558 void setSize(long size) {
559 this.size = size;
560 }
561
562
563
564
565 LimitScope getSizeScope() {
566 return this.sizeScope;
567 }
568
569
570
571
572 void setSizeScope(LimitScope scope) {
573 this.sizeScope = scope;
574 }
575
576
577
578
579
580 boolean canEnforceSizeLimitFromScope(LimitScope checkerScope) {
581 return this.sizeScope.canEnforceLimitFromScope(checkerScope);
582 }
583
584 long getTime() {
585 return this.time;
586 }
587
588 void setTime(long time) {
589 this.time = time;
590 }
591
592
593
594
595 LimitScope getTimeScope() {
596 return this.timeScope;
597 }
598
599
600
601
602 void setTimeScope(LimitScope scope) {
603 this.timeScope = scope;
604 }
605
606
607
608
609
610 boolean canEnforceTimeLimitFromScope(LimitScope checkerScope) {
611 return this.timeScope.canEnforceLimitFromScope(checkerScope);
612 }
613
614 @Override
615 public String toString() {
616 StringBuilder sb = new StringBuilder();
617 sb.append("{");
618
619 sb.append("batch:");
620 sb.append(batch);
621
622 sb.append(", size:");
623 sb.append(size);
624
625 sb.append(", sizeScope:");
626 sb.append(sizeScope);
627
628 sb.append(", time:");
629 sb.append(time);
630
631 sb.append(", timeScope:");
632 sb.append(timeScope);
633
634 sb.append("}");
635 return sb.toString();
636 }
637 }
638 }