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 java.nio.BufferOverflowException;
23 import java.nio.ByteBuffer;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Comparator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.NavigableMap;
30 import java.util.TreeMap;
31
32 import org.apache.hadoop.hbase.classification.InterfaceAudience;
33 import org.apache.hadoop.hbase.classification.InterfaceStability;
34 import org.apache.hadoop.hbase.Cell;
35 import org.apache.hadoop.hbase.CellScannable;
36 import org.apache.hadoop.hbase.CellScanner;
37 import org.apache.hadoop.hbase.CellUtil;
38 import org.apache.hadoop.hbase.KeyValue;
39 import org.apache.hadoop.hbase.KeyValueUtil;
40 import org.apache.hadoop.hbase.classification.InterfaceAudience;
41 import org.apache.hadoop.hbase.classification.InterfaceStability;
42 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
43 import org.apache.hadoop.hbase.util.Bytes;
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 @InterfaceAudience.Public
79 @InterfaceStability.Stable
80 public class Result implements CellScannable, CellScanner {
81 private Cell[] cells;
82 private Boolean exists;
83 private boolean stale = false;
84
85
86 private transient byte [] row = null;
87
88 private transient NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> familyMap = null;
89
90 private static ThreadLocal<byte[]> localBuffer = new ThreadLocal<byte[]>();
91 private static final int PAD_WIDTH = 128;
92 public static final Result EMPTY_RESULT = new Result();
93
94 private final static int INITIAL_CELLSCANNER_INDEX = -1;
95
96
97
98
99 private int cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
100 private ClientProtos.RegionLoadStats stats;
101
102
103
104
105
106
107
108 public Result() {
109 super();
110 }
111
112
113
114
115 @Deprecated
116 public Result(KeyValue [] cells) {
117 this.cells = cells;
118 }
119
120
121
122
123 @Deprecated
124 public Result(List<KeyValue> kvs) {
125
126 this(kvs.toArray(new Cell[kvs.size()]), null, false);
127 }
128
129
130
131
132
133
134 public static Result create(List<Cell> cells) {
135 return new Result(cells.toArray(new Cell[cells.size()]), null, false);
136 }
137
138 public static Result create(List<Cell> cells, Boolean exists) {
139 return create(cells, exists, false);
140 }
141
142 public static Result create(List<Cell> cells, Boolean exists, boolean stale) {
143 if (exists != null){
144 return new Result(null, exists, stale);
145 }
146 return new Result(cells.toArray(new Cell[cells.size()]), null, stale);
147 }
148
149
150
151
152
153
154 public static Result create(Cell[] cells) {
155 return new Result(cells, null, false);
156 }
157
158 public static Result create(Cell[] cells, Boolean exists, boolean stale) {
159 if (exists != null){
160 return new Result(null, exists, stale);
161 }
162 return new Result(cells, null, stale);
163 }
164
165
166 private Result(Cell[] cells, Boolean exists, boolean stale) {
167 this.cells = cells;
168 this.exists = exists;
169 this.stale = stale;
170 }
171
172
173
174
175
176
177 public byte [] getRow() {
178 if (this.row == null) {
179 this.row = this.cells == null || this.cells.length == 0? null: CellUtil.cloneRow(this.cells[0]);
180 }
181 return this.row;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public Cell[] rawCells() {
205 return cells;
206 }
207
208
209
210
211
212
213
214
215
216
217
218 @Deprecated
219 public KeyValue[] raw() {
220 KeyValue[] kvs = new KeyValue[cells.length];
221 for (int i = 0 ; i < kvs.length; i++) {
222 kvs[i] = KeyValueUtil.ensureKeyValue(cells[i]);
223 }
224 return kvs;
225 }
226
227
228
229
230
231
232
233
234 public List<Cell> listCells() {
235 return isEmpty()? null: Arrays.asList(rawCells());
236 }
237
238
239
240
241
242
243
244
245
246
247
248 @Deprecated
249 public List<KeyValue> list() {
250 return isEmpty() ? null : Arrays.asList(raw());
251 }
252
253
254
255
256 @Deprecated
257 public List<KeyValue> getColumn(byte [] family, byte [] qualifier) {
258 return KeyValueUtil.ensureKeyValues(getColumnCells(family, qualifier));
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 public List<Cell> getColumnCells(byte [] family, byte [] qualifier) {
277 List<Cell> result = new ArrayList<Cell>();
278
279 Cell [] kvs = rawCells();
280
281 if (kvs == null || kvs.length == 0) {
282 return result;
283 }
284 int pos = binarySearch(kvs, family, qualifier);
285 if (pos == -1) {
286 return result;
287 }
288
289 for (int i = pos ; i < kvs.length ; i++ ) {
290 if (CellUtil.matchingColumn(kvs[i], family,qualifier)) {
291 result.add(kvs[i]);
292 } else {
293 break;
294 }
295 }
296
297 return result;
298 }
299
300 protected int binarySearch(final Cell [] kvs,
301 final byte [] family,
302 final byte [] qualifier) {
303 Cell searchTerm =
304 KeyValueUtil.createFirstOnRow(CellUtil.cloneRow(kvs[0]),
305 family, qualifier);
306
307
308 int pos = Arrays.binarySearch(kvs, searchTerm, KeyValue.COMPARATOR);
309
310 if (pos < 0) {
311 pos = (pos+1) * -1;
312
313 }
314 if (pos == kvs.length) {
315 return -1;
316 }
317 return pos;
318 }
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333 protected int binarySearch(final Cell [] kvs,
334 final byte [] family, final int foffset, final int flength,
335 final byte [] qualifier, final int qoffset, final int qlength) {
336
337 double keyValueSize = (double)
338 KeyValue.getKeyValueDataStructureSize(kvs[0].getRowLength(), flength, qlength, 0);
339
340 byte[] buffer = localBuffer.get();
341 if (buffer == null || keyValueSize > buffer.length) {
342
343 buffer = new byte[(int) Math.ceil(keyValueSize / PAD_WIDTH) * PAD_WIDTH];
344 localBuffer.set(buffer);
345 }
346
347 Cell searchTerm = KeyValueUtil.createFirstOnRow(buffer, 0,
348 kvs[0].getRowArray(), kvs[0].getRowOffset(), kvs[0].getRowLength(),
349 family, foffset, flength,
350 qualifier, qoffset, qlength);
351
352
353 int pos = Arrays.binarySearch(kvs, searchTerm, KeyValue.COMPARATOR);
354
355 if (pos < 0) {
356 pos = (pos+1) * -1;
357
358 }
359 if (pos == kvs.length) {
360 return -1;
361 }
362 return pos;
363 }
364
365
366
367
368 @Deprecated
369 public KeyValue getColumnLatest(byte [] family, byte [] qualifier) {
370 return KeyValueUtil.ensureKeyValue(getColumnLatestCell(family, qualifier));
371 }
372
373
374
375
376
377
378
379
380
381
382 public Cell getColumnLatestCell(byte [] family, byte [] qualifier) {
383 Cell [] kvs = rawCells();
384 if (kvs == null || kvs.length == 0) {
385 return null;
386 }
387 int pos = binarySearch(kvs, family, qualifier);
388 if (pos == -1) {
389 return null;
390 }
391 if (CellUtil.matchingColumn(kvs[pos], family, qualifier)) {
392 return kvs[pos];
393 }
394 return null;
395 }
396
397
398
399
400 @Deprecated
401 public KeyValue getColumnLatest(byte [] family, int foffset, int flength,
402 byte [] qualifier, int qoffset, int qlength) {
403 return KeyValueUtil.ensureKeyValue(
404 getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength));
405 }
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420 public Cell getColumnLatestCell(byte [] family, int foffset, int flength,
421 byte [] qualifier, int qoffset, int qlength) {
422
423 Cell [] kvs = rawCells();
424 if (kvs == null || kvs.length == 0) {
425 return null;
426 }
427 int pos = binarySearch(kvs, family, foffset, flength, qualifier, qoffset, qlength);
428 if (pos == -1) {
429 return null;
430 }
431 if (CellUtil.matchingColumn(kvs[pos], family, foffset, flength, qualifier, qoffset, qlength)) {
432 return kvs[pos];
433 }
434 return null;
435 }
436
437
438
439
440
441
442
443
444
445
446 public byte[] getValue(byte [] family, byte [] qualifier) {
447 Cell kv = getColumnLatestCell(family, qualifier);
448 if (kv == null) {
449 return null;
450 }
451 return CellUtil.cloneValue(kv);
452 }
453
454
455
456
457
458
459
460
461
462 public ByteBuffer getValueAsByteBuffer(byte [] family, byte [] qualifier) {
463
464 Cell kv = getColumnLatestCell(family, 0, family.length, qualifier, 0, qualifier.length);
465
466 if (kv == null) {
467 return null;
468 }
469 return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()).
470 asReadOnlyBuffer();
471 }
472
473
474
475
476
477
478
479
480
481
482
483
484
485 public ByteBuffer getValueAsByteBuffer(byte [] family, int foffset, int flength,
486 byte [] qualifier, int qoffset, int qlength) {
487
488 Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
489
490 if (kv == null) {
491 return null;
492 }
493 return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()).
494 asReadOnlyBuffer();
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510 public boolean loadValue(byte [] family, byte [] qualifier, ByteBuffer dst)
511 throws BufferOverflowException {
512 return loadValue(family, 0, family.length, qualifier, 0, qualifier.length, dst);
513 }
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532 public boolean loadValue(byte [] family, int foffset, int flength,
533 byte [] qualifier, int qoffset, int qlength, ByteBuffer dst)
534 throws BufferOverflowException {
535 Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
536
537 if (kv == null) {
538 return false;
539 }
540 dst.put(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength());
541 return true;
542 }
543
544
545
546
547
548
549
550
551
552 public boolean containsNonEmptyColumn(byte [] family, byte [] qualifier) {
553
554 return containsNonEmptyColumn(family, 0, family.length, qualifier, 0, qualifier.length);
555 }
556
557
558
559
560
561
562
563
564
565
566
567
568
569 public boolean containsNonEmptyColumn(byte [] family, int foffset, int flength,
570 byte [] qualifier, int qoffset, int qlength) {
571
572 Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
573
574 return (kv != null) && (kv.getValueLength() > 0);
575 }
576
577
578
579
580
581
582
583
584
585 public boolean containsEmptyColumn(byte [] family, byte [] qualifier) {
586
587 return containsEmptyColumn(family, 0, family.length, qualifier, 0, qualifier.length);
588 }
589
590
591
592
593
594
595
596
597
598
599
600
601
602 public boolean containsEmptyColumn(byte [] family, int foffset, int flength,
603 byte [] qualifier, int qoffset, int qlength) {
604 Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
605
606 return (kv != null) && (kv.getValueLength() == 0);
607 }
608
609
610
611
612
613
614
615
616
617 public boolean containsColumn(byte [] family, byte [] qualifier) {
618 Cell kv = getColumnLatestCell(family, qualifier);
619 return kv != null;
620 }
621
622
623
624
625
626
627
628
629
630
631
632
633
634 public boolean containsColumn(byte [] family, int foffset, int flength,
635 byte [] qualifier, int qoffset, int qlength) {
636
637 return getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength) != null;
638 }
639
640
641
642
643
644
645
646
647
648
649 public NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> getMap() {
650 if (this.familyMap != null) {
651 return this.familyMap;
652 }
653 if(isEmpty()) {
654 return null;
655 }
656 this.familyMap = new TreeMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>(Bytes.BYTES_COMPARATOR);
657 for(Cell kv : this.cells) {
658 byte [] family = CellUtil.cloneFamily(kv);
659 NavigableMap<byte[], NavigableMap<Long, byte[]>> columnMap =
660 familyMap.get(family);
661 if(columnMap == null) {
662 columnMap = new TreeMap<byte[], NavigableMap<Long, byte[]>>
663 (Bytes.BYTES_COMPARATOR);
664 familyMap.put(family, columnMap);
665 }
666 byte [] qualifier = CellUtil.cloneQualifier(kv);
667 NavigableMap<Long, byte[]> versionMap = columnMap.get(qualifier);
668 if(versionMap == null) {
669 versionMap = new TreeMap<Long, byte[]>(new Comparator<Long>() {
670 @Override
671 public int compare(Long l1, Long l2) {
672 return l2.compareTo(l1);
673 }
674 });
675 columnMap.put(qualifier, versionMap);
676 }
677 Long timestamp = kv.getTimestamp();
678 byte [] value = CellUtil.cloneValue(kv);
679
680 versionMap.put(timestamp, value);
681 }
682 return this.familyMap;
683 }
684
685
686
687
688
689
690
691
692
693 public NavigableMap<byte[], NavigableMap<byte[], byte[]>> getNoVersionMap() {
694 if(this.familyMap == null) {
695 getMap();
696 }
697 if(isEmpty()) {
698 return null;
699 }
700 NavigableMap<byte[], NavigableMap<byte[], byte[]>> returnMap =
701 new TreeMap<byte[], NavigableMap<byte[], byte[]>>(Bytes.BYTES_COMPARATOR);
702 for(Map.Entry<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>
703 familyEntry : familyMap.entrySet()) {
704 NavigableMap<byte[], byte[]> qualifierMap =
705 new TreeMap<byte[], byte[]>(Bytes.BYTES_COMPARATOR);
706 for(Map.Entry<byte[], NavigableMap<Long, byte[]>> qualifierEntry :
707 familyEntry.getValue().entrySet()) {
708 byte [] value =
709 qualifierEntry.getValue().get(qualifierEntry.getValue().firstKey());
710 qualifierMap.put(qualifierEntry.getKey(), value);
711 }
712 returnMap.put(familyEntry.getKey(), qualifierMap);
713 }
714 return returnMap;
715 }
716
717
718
719
720
721
722
723
724 public NavigableMap<byte[], byte[]> getFamilyMap(byte [] family) {
725 if(this.familyMap == null) {
726 getMap();
727 }
728 if(isEmpty()) {
729 return null;
730 }
731 NavigableMap<byte[], byte[]> returnMap =
732 new TreeMap<byte[], byte[]>(Bytes.BYTES_COMPARATOR);
733 NavigableMap<byte[], NavigableMap<Long, byte[]>> qualifierMap =
734 familyMap.get(family);
735 if(qualifierMap == null) {
736 return returnMap;
737 }
738 for(Map.Entry<byte[], NavigableMap<Long, byte[]>> entry :
739 qualifierMap.entrySet()) {
740 byte [] value =
741 entry.getValue().get(entry.getValue().firstKey());
742 returnMap.put(entry.getKey(), value);
743 }
744 return returnMap;
745 }
746
747
748
749
750
751 public byte [] value() {
752 if (isEmpty()) {
753 return null;
754 }
755 return CellUtil.cloneValue(cells[0]);
756 }
757
758
759
760
761
762 public boolean isEmpty() {
763 return this.cells == null || this.cells.length == 0;
764 }
765
766
767
768
769 public int size() {
770 return this.cells == null? 0: this.cells.length;
771 }
772
773
774
775
776 @Override
777 public String toString() {
778 StringBuilder sb = new StringBuilder();
779 sb.append("keyvalues=");
780 if(isEmpty()) {
781 sb.append("NONE");
782 return sb.toString();
783 }
784 sb.append("{");
785 boolean moreThanOne = false;
786 for(Cell kv : this.cells) {
787 if(moreThanOne) {
788 sb.append(", ");
789 } else {
790 moreThanOne = true;
791 }
792 sb.append(kv.toString());
793 }
794 sb.append("}");
795 return sb.toString();
796 }
797
798
799
800
801
802
803
804 public static void compareResults(Result res1, Result res2)
805 throws Exception {
806 if (res2 == null) {
807 throw new Exception("There wasn't enough rows, we stopped at "
808 + Bytes.toStringBinary(res1.getRow()));
809 }
810 if (res1.size() != res2.size()) {
811 throw new Exception("This row doesn't have the same number of KVs: "
812 + res1.toString() + " compared to " + res2.toString());
813 }
814 Cell[] ourKVs = res1.rawCells();
815 Cell[] replicatedKVs = res2.rawCells();
816 for (int i = 0; i < res1.size(); i++) {
817 if (!ourKVs[i].equals(replicatedKVs[i]) ||
818 !Bytes.equals(CellUtil.cloneValue(ourKVs[i]), CellUtil.cloneValue(replicatedKVs[i]))) {
819 throw new Exception("This result was different: "
820 + res1.toString() + " compared to " + res2.toString());
821 }
822 }
823 }
824
825
826
827
828
829
830 public static long getTotalSizeOfCells(Result result) {
831 long size = 0;
832 for (Cell c : result.rawCells()) {
833 size += CellUtil.estimatedHeapSizeOf(c);
834 }
835 return size;
836 }
837
838
839
840
841
842 public void copyFrom(Result other) {
843 this.row = null;
844 this.familyMap = null;
845 this.cells = other.cells;
846 }
847
848 @Override
849 public CellScanner cellScanner() {
850
851 this.cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
852 return this;
853 }
854
855 @Override
856 public Cell current() {
857 if (cells == null) return null;
858 return (cellScannerIndex < 0)? null: this.cells[cellScannerIndex];
859 }
860
861 @Override
862 public boolean advance() {
863 if (cells == null) return false;
864 return ++cellScannerIndex < this.cells.length;
865 }
866
867 public Boolean getExists() {
868 return exists;
869 }
870
871 public void setExists(Boolean exists) {
872 this.exists = exists;
873 }
874
875
876
877
878
879
880 public boolean isStale() {
881 return stale;
882 }
883
884
885
886
887
888 public void addResults(ClientProtos.RegionLoadStats loadStats) {
889 this.stats = loadStats;
890 }
891
892
893
894
895
896 public ClientProtos.RegionLoadStats getStats() {
897 return stats;
898 }
899 }