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