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