1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.client;
21
22 import org.apache.hadoop.classification.InterfaceAudience;
23 import org.apache.hadoop.classification.InterfaceStability;
24 import org.apache.hadoop.hbase.HConstants;
25 import org.apache.hadoop.hbase.filter.Filter;
26 import org.apache.hadoop.hbase.filter.IncompatibleFilterException;
27 import org.apache.hadoop.hbase.io.TimeRange;
28 import org.apache.hadoop.hbase.util.Bytes;
29
30 import java.io.IOException;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.NavigableSet;
36 import java.util.TreeMap;
37 import java.util.TreeSet;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 @InterfaceAudience.Public
83 @InterfaceStability.Stable
84 public class Scan extends OperationWithAttributes {
85 private static final String RAW_ATTR = "_raw_";
86 private static final String ISOLATION_LEVEL = "_isolationlevel_";
87
88 private byte [] startRow = HConstants.EMPTY_START_ROW;
89 private byte [] stopRow = HConstants.EMPTY_END_ROW;
90 private int maxVersions = 1;
91 private int batch = -1;
92
93 private int storeLimit = -1;
94 private int storeOffset = 0;
95 private boolean getScan;
96
97
98
99 static public final String SCAN_ATTRIBUTES_METRICS_ENABLE = "scan.attributes.metrics.enable";
100 static public final String SCAN_ATTRIBUTES_METRICS_DATA = "scan.attributes.metrics.data";
101
102
103
104
105 static public final String SCAN_ATTRIBUTES_TABLE_NAME = "scan.attributes.table.name";
106
107
108
109
110 private int caching = -1;
111 private long maxResultSize = -1;
112 private boolean cacheBlocks = true;
113 private Filter filter = null;
114 private TimeRange tr = new TimeRange();
115 private Map<byte [], NavigableSet<byte []>> familyMap =
116 new TreeMap<byte [], NavigableSet<byte []>>(Bytes.BYTES_COMPARATOR);
117 private Boolean loadColumnFamiliesOnDemand = null;
118
119
120
121
122 public Scan() {}
123
124 public Scan(byte [] startRow, Filter filter) {
125 this(startRow);
126 this.filter = filter;
127 }
128
129
130
131
132
133
134
135
136 public Scan(byte [] startRow) {
137 this.startRow = startRow;
138 }
139
140
141
142
143
144
145 public Scan(byte [] startRow, byte [] stopRow) {
146 this.startRow = startRow;
147 this.stopRow = stopRow;
148
149 this.getScan = isStartRowAndEqualsStopRow();
150 }
151
152
153
154
155
156
157
158 public Scan(Scan scan) throws IOException {
159 startRow = scan.getStartRow();
160 stopRow = scan.getStopRow();
161 maxVersions = scan.getMaxVersions();
162 batch = scan.getBatch();
163 storeLimit = scan.getMaxResultsPerColumnFamily();
164 storeOffset = scan.getRowOffsetPerColumnFamily();
165 caching = scan.getCaching();
166 maxResultSize = scan.getMaxResultSize();
167 cacheBlocks = scan.getCacheBlocks();
168 getScan = scan.isGetScan();
169 filter = scan.getFilter();
170 loadColumnFamiliesOnDemand = scan.getLoadColumnFamiliesOnDemandValue();
171 TimeRange ctr = scan.getTimeRange();
172 tr = new TimeRange(ctr.getMin(), ctr.getMax());
173 Map<byte[], NavigableSet<byte[]>> fams = scan.getFamilyMap();
174 for (Map.Entry<byte[],NavigableSet<byte[]>> entry : fams.entrySet()) {
175 byte [] fam = entry.getKey();
176 NavigableSet<byte[]> cols = entry.getValue();
177 if (cols != null && cols.size() > 0) {
178 for (byte[] col : cols) {
179 addColumn(fam, col);
180 }
181 } else {
182 addFamily(fam);
183 }
184 }
185 for (Map.Entry<String, byte[]> attr : scan.getAttributesMap().entrySet()) {
186 setAttribute(attr.getKey(), attr.getValue());
187 }
188 }
189
190
191
192
193
194 public Scan(Get get) {
195 this.startRow = get.getRow();
196 this.stopRow = get.getRow();
197 this.filter = get.getFilter();
198 this.cacheBlocks = get.getCacheBlocks();
199 this.maxVersions = get.getMaxVersions();
200 this.storeLimit = get.getMaxResultsPerColumnFamily();
201 this.storeOffset = get.getRowOffsetPerColumnFamily();
202 this.tr = get.getTimeRange();
203 this.familyMap = get.getFamilyMap();
204 this.getScan = true;
205 }
206
207 public boolean isGetScan() {
208 return this.getScan || isStartRowAndEqualsStopRow();
209 }
210
211 private boolean isStartRowAndEqualsStopRow() {
212 return this.startRow != null && this.startRow.length > 0 &&
213 Bytes.equals(this.startRow, this.stopRow);
214 }
215
216
217
218
219
220
221
222 public Scan addFamily(byte [] family) {
223 familyMap.remove(family);
224 familyMap.put(family, null);
225 return this;
226 }
227
228
229
230
231
232
233
234
235
236 public Scan addColumn(byte [] family, byte [] qualifier) {
237 NavigableSet<byte []> set = familyMap.get(family);
238 if(set == null) {
239 set = new TreeSet<byte []>(Bytes.BYTES_COMPARATOR);
240 }
241 if (qualifier == null) {
242 qualifier = HConstants.EMPTY_BYTE_ARRAY;
243 }
244 set.add(qualifier);
245 familyMap.put(family, set);
246 return this;
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260
261 public Scan setTimeRange(long minStamp, long maxStamp)
262 throws IOException {
263 tr = new TimeRange(minStamp, maxStamp);
264 return this;
265 }
266
267
268
269
270
271
272
273
274
275
276
277 public Scan setTimeStamp(long timestamp) {
278 try {
279 tr = new TimeRange(timestamp, timestamp+1);
280 } catch(IOException e) {
281
282 }
283 return this;
284 }
285
286
287
288
289
290
291
292 public Scan setStartRow(byte [] startRow) {
293 this.startRow = startRow;
294 return this;
295 }
296
297
298
299
300
301
302
303 public Scan setStopRow(byte [] stopRow) {
304 this.stopRow = stopRow;
305 return this;
306 }
307
308
309
310
311
312 public Scan setMaxVersions() {
313 this.maxVersions = Integer.MAX_VALUE;
314 return this;
315 }
316
317
318
319
320
321
322 public Scan setMaxVersions(int maxVersions) {
323 this.maxVersions = maxVersions;
324 return this;
325 }
326
327
328
329
330
331 public void setBatch(int batch) {
332 if (this.hasFilter() && this.filter.hasFilterRow()) {
333 throw new IncompatibleFilterException(
334 "Cannot set batch on a scan using a filter" +
335 " that returns true for filter.hasFilterRow");
336 }
337 this.batch = batch;
338 }
339
340
341
342
343
344 public void setMaxResultsPerColumnFamily(int limit) {
345 this.storeLimit = limit;
346 }
347
348
349
350
351
352 public void setRowOffsetPerColumnFamily(int offset) {
353 this.storeOffset = offset;
354 }
355
356
357
358
359
360
361
362 public void setCaching(int caching) {
363 this.caching = caching;
364 }
365
366
367
368
369 public long getMaxResultSize() {
370 return maxResultSize;
371 }
372
373
374
375
376
377
378
379
380 public void setMaxResultSize(long maxResultSize) {
381 this.maxResultSize = maxResultSize;
382 }
383
384
385
386
387
388
389 public Scan setFilter(Filter filter) {
390 this.filter = filter;
391 return this;
392 }
393
394
395
396
397
398
399 public Scan setFamilyMap(Map<byte [], NavigableSet<byte []>> familyMap) {
400 this.familyMap = familyMap;
401 return this;
402 }
403
404
405
406
407
408 public Map<byte [], NavigableSet<byte []>> getFamilyMap() {
409 return this.familyMap;
410 }
411
412
413
414
415 public int numFamilies() {
416 if(hasFamilies()) {
417 return this.familyMap.size();
418 }
419 return 0;
420 }
421
422
423
424
425 public boolean hasFamilies() {
426 return !this.familyMap.isEmpty();
427 }
428
429
430
431
432 public byte[][] getFamilies() {
433 if(hasFamilies()) {
434 return this.familyMap.keySet().toArray(new byte[0][0]);
435 }
436 return null;
437 }
438
439
440
441
442 public byte [] getStartRow() {
443 return this.startRow;
444 }
445
446
447
448
449 public byte [] getStopRow() {
450 return this.stopRow;
451 }
452
453
454
455
456 public int getMaxVersions() {
457 return this.maxVersions;
458 }
459
460
461
462
463 public int getBatch() {
464 return this.batch;
465 }
466
467
468
469
470 public int getMaxResultsPerColumnFamily() {
471 return this.storeLimit;
472 }
473
474
475
476
477
478
479 public int getRowOffsetPerColumnFamily() {
480 return this.storeOffset;
481 }
482
483
484
485
486 public int getCaching() {
487 return this.caching;
488 }
489
490
491
492
493 public TimeRange getTimeRange() {
494 return this.tr;
495 }
496
497
498
499
500 public Filter getFilter() {
501 return filter;
502 }
503
504
505
506
507 public boolean hasFilter() {
508 return filter != null;
509 }
510
511
512
513
514
515
516
517
518
519
520
521 public void setCacheBlocks(boolean cacheBlocks) {
522 this.cacheBlocks = cacheBlocks;
523 }
524
525
526
527
528
529
530 public boolean getCacheBlocks() {
531 return cacheBlocks;
532 }
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550 public void setLoadColumnFamiliesOnDemand(boolean value) {
551 this.loadColumnFamiliesOnDemand = value;
552 }
553
554
555
556
557 public Boolean getLoadColumnFamiliesOnDemandValue() {
558 return this.loadColumnFamiliesOnDemand;
559 }
560
561
562
563
564 public boolean doLoadColumnFamiliesOnDemand() {
565 return (this.loadColumnFamiliesOnDemand != null)
566 && this.loadColumnFamiliesOnDemand.booleanValue();
567 }
568
569
570
571
572
573
574
575 @Override
576 public Map<String, Object> getFingerprint() {
577 Map<String, Object> map = new HashMap<String, Object>();
578 List<String> families = new ArrayList<String>();
579 if(this.familyMap.size() == 0) {
580 map.put("families", "ALL");
581 return map;
582 } else {
583 map.put("families", families);
584 }
585 for (Map.Entry<byte [], NavigableSet<byte[]>> entry :
586 this.familyMap.entrySet()) {
587 families.add(Bytes.toStringBinary(entry.getKey()));
588 }
589 return map;
590 }
591
592
593
594
595
596
597
598
599 @Override
600 public Map<String, Object> toMap(int maxCols) {
601
602 Map<String, Object> map = getFingerprint();
603
604 Map<String, List<String>> familyColumns =
605 new HashMap<String, List<String>>();
606 map.put("families", familyColumns);
607
608 map.put("startRow", Bytes.toStringBinary(this.startRow));
609 map.put("stopRow", Bytes.toStringBinary(this.stopRow));
610 map.put("maxVersions", this.maxVersions);
611 map.put("batch", this.batch);
612 map.put("caching", this.caching);
613 map.put("maxResultSize", this.maxResultSize);
614 map.put("cacheBlocks", this.cacheBlocks);
615 map.put("loadColumnFamiliesOnDemand", this.loadColumnFamiliesOnDemand);
616 List<Long> timeRange = new ArrayList<Long>();
617 timeRange.add(this.tr.getMin());
618 timeRange.add(this.tr.getMax());
619 map.put("timeRange", timeRange);
620 int colCount = 0;
621
622 for (Map.Entry<byte [], NavigableSet<byte[]>> entry :
623 this.familyMap.entrySet()) {
624 List<String> columns = new ArrayList<String>();
625 familyColumns.put(Bytes.toStringBinary(entry.getKey()), columns);
626 if(entry.getValue() == null) {
627 colCount++;
628 --maxCols;
629 columns.add("ALL");
630 } else {
631 colCount += entry.getValue().size();
632 if (maxCols <= 0) {
633 continue;
634 }
635 for (byte [] column : entry.getValue()) {
636 if (--maxCols <= 0) {
637 continue;
638 }
639 columns.add(Bytes.toStringBinary(column));
640 }
641 }
642 }
643 map.put("totalColumns", colCount);
644 if (this.filter != null) {
645 map.put("filter", this.filter.toString());
646 }
647
648 if (getId() != null) {
649 map.put("id", getId());
650 }
651 return map;
652 }
653
654
655
656
657
658
659
660
661
662
663
664 public void setRaw(boolean raw) {
665 setAttribute(RAW_ATTR, Bytes.toBytes(raw));
666 }
667
668
669
670
671 public boolean isRaw() {
672 byte[] attr = getAttribute(RAW_ATTR);
673 return attr == null ? false : Bytes.toBoolean(attr);
674 }
675
676
677
678
679
680
681
682
683
684
685
686
687 public void setIsolationLevel(IsolationLevel level) {
688 setAttribute(ISOLATION_LEVEL, level.toBytes());
689 }
690
691
692
693
694
695
696 public IsolationLevel getIsolationLevel() {
697 byte[] attr = getAttribute(ISOLATION_LEVEL);
698 return attr == null ? IsolationLevel.READ_COMMITTED :
699 IsolationLevel.fromBytes(attr);
700 }
701 }